Add hooks for the Compact C Type Format (CTF) data to be attached to

the elf files. This is complicated by the fact that the actual CTF
parsing has to be done in CDDL'd code, so the BSD licensed code only
knows about the opaque data which it must be able to free.
This commit is contained in:
John Birrell 2008-05-23 00:49:39 +00:00
parent 91dd776cd2
commit a2024a3edf
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=179223
3 changed files with 117 additions and 3 deletions

View File

@ -27,6 +27,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include "opt_gdb.h"
#include "opt_mac.h"
@ -62,6 +63,10 @@ __FBSDID("$FreeBSD$");
#include <sys/link_elf.h>
#ifdef DDB_CTF
#include <net/zlib.h>
#endif
#include "linker_if.h"
#define MAXSEGS 4
@ -98,11 +103,18 @@ typedef struct elf_file {
long ddbstrcnt; /* number of bytes in string table */
caddr_t symbase; /* malloc'ed symbold base */
caddr_t strbase; /* malloc'ed string base */
caddr_t ctftab; /* CTF table */
long ctfcnt; /* number of bytes in CTF table */
caddr_t ctfoff; /* CTF offset table */
caddr_t typoff; /* Type offset table */
long typlen; /* Number of type entries. */
#ifdef GDB
struct link_map gdb; /* hooks for gdb */
#endif
} *elf_file_t;
#include <kern/kern_ctf.c>
static int link_elf_link_common_finish(linker_file_t);
static int link_elf_link_preload(linker_class_t cls,
const char*, linker_file_t*);
@ -121,6 +133,9 @@ static int link_elf_lookup_set(linker_file_t, const char *,
static int link_elf_each_function_name(linker_file_t,
int (*)(const char *, void *),
void *);
static int link_elf_each_function_nameval(linker_file_t,
linker_function_nameval_callback_t,
void *);
static void link_elf_reloc_local(linker_file_t);
static Elf_Addr elf_lookup(linker_file_t lf, Elf_Size symidx, int deps);
@ -134,6 +149,8 @@ static kobj_method_t link_elf_methods[] = {
KOBJMETHOD(linker_link_preload_finish, link_elf_link_preload_finish),
KOBJMETHOD(linker_lookup_set, link_elf_lookup_set),
KOBJMETHOD(linker_each_function_name, link_elf_each_function_name),
KOBJMETHOD(linker_each_function_nameval, link_elf_each_function_nameval),
KOBJMETHOD(linker_ctf_get, link_elf_ctf_get),
{ 0, 0 }
};
@ -910,6 +927,12 @@ link_elf_unload_file(linker_file_t file)
free(ef->symbase, M_LINKER);
if (ef->strbase)
free(ef->strbase, M_LINKER);
if (ef->ctftab)
free(ef->ctftab, M_LINKER);
if (ef->ctfoff)
free(ef->ctfoff, M_LINKER);
if (ef->typoff)
free(ef->typoff, M_LINKER);
}
static void
@ -1227,6 +1250,30 @@ link_elf_each_function_name(linker_file_t file,
return (0);
}
static int
link_elf_each_function_nameval(linker_file_t file,
linker_function_nameval_callback_t callback, void *opaque)
{
linker_symval_t symval;
elf_file_t ef = (elf_file_t)file;
const Elf_Sym* symp;
int i, error;
/* Exhaustive search */
for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
if (symp->st_value != 0 &&
ELF_ST_TYPE(symp->st_info) == STT_FUNC) {
error = link_elf_symbol_values(file, (c_linker_sym_t) symp, &symval);
if (error)
return (error);
error = callback(file, i, &symval, opaque);
if (error)
return (error);
}
}
return (0);
}
#ifdef __ia64__
/*
* Each KLD has its own GP. The GP value for each load module is given by

View File

@ -58,6 +58,10 @@ __FBSDID("$FreeBSD$");
#include <sys/link_elf.h>
#ifdef DDB_CTF
#include <net/zlib.h>
#endif
#include "linker_if.h"
typedef struct {
@ -106,8 +110,16 @@ typedef struct elf_file {
caddr_t shstrtab; /* Section name string table */
long shstrcnt; /* number of bytes in string table */
caddr_t ctftab; /* CTF table */
long ctfcnt; /* number of bytes in CTF table */
caddr_t ctfoff; /* CTF offset table */
caddr_t typoff; /* Type offset table */
long typlen; /* Number of type entries. */
} *elf_file_t;
#include <kern/kern_ctf.c>
static int link_elf_link_preload(linker_class_t cls,
const char *, linker_file_t *);
static int link_elf_link_preload_finish(linker_file_t);
@ -124,6 +136,9 @@ static int link_elf_lookup_set(linker_file_t, const char *,
void ***, void ***, int *);
static int link_elf_each_function_name(linker_file_t,
int (*)(const char *, void *), void *);
static int link_elf_each_function_nameval(linker_file_t,
linker_function_nameval_callback_t,
void *);
static void link_elf_reloc_local(linker_file_t);
static Elf_Addr elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps);
@ -138,6 +153,8 @@ static kobj_method_t link_elf_methods[] = {
KOBJMETHOD(linker_link_preload_finish, link_elf_link_preload_finish),
KOBJMETHOD(linker_lookup_set, link_elf_lookup_set),
KOBJMETHOD(linker_each_function_name, link_elf_each_function_name),
KOBJMETHOD(linker_each_function_nameval, link_elf_each_function_nameval),
KOBJMETHOD(linker_ctf_get, link_elf_ctf_get),
{ 0, 0 }
};
@ -815,6 +832,12 @@ link_elf_unload_file(linker_file_t file)
free(ef->relatab, M_LINKER);
if (ef->progtab)
free(ef->progtab, M_LINKER);
if (ef->ctftab)
free(ef->ctftab, M_LINKER);
if (ef->ctfoff)
free(ef->ctfoff, M_LINKER);
if (ef->typoff)
free(ef->typoff, M_LINKER);
if (file->filename != NULL)
preload_delete_name(file->filename);
/* XXX reclaim module memory? */
@ -847,6 +870,12 @@ link_elf_unload_file(linker_file_t file)
free(ef->ddbstrtab, M_LINKER);
if (ef->shstrtab)
free(ef->shstrtab, M_LINKER);
if (ef->ctftab)
free(ef->ctftab, M_LINKER);
if (ef->ctfoff)
free(ef->ctfoff, M_LINKER);
if (ef->typoff)
free(ef->typoff, M_LINKER);
}
static const char *
@ -1068,6 +1097,30 @@ link_elf_each_function_name(linker_file_t file,
return (0);
}
static int
link_elf_each_function_nameval(linker_file_t file,
linker_function_nameval_callback_t callback, void *opaque)
{
linker_symval_t symval;
elf_file_t ef = (elf_file_t)file;
const Elf_Sym* symp;
int i, error;
/* Exhaustive search */
for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
if (symp->st_value != 0 &&
ELF_ST_TYPE(symp->st_info) == STT_FUNC) {
error = link_elf_symbol_values(file, (c_linker_sym_t) symp, &symval);
if (error)
return (error);
error = callback(file, i, &symval, opaque);
if (error)
return (error);
}
}
return (0);
}
/*
* Symbol lookup function that can be used when the symbol index is known (ie
* in relocations). It uses the symbol index instead of doing a fully fledged

View File

@ -59,7 +59,7 @@ typedef struct linker_symval {
size_t size;
} linker_symval_t;
typedef int (*linker_function_nameval_callback_t)(linker_file_t, linker_symval_t *, void *);
typedef int (*linker_function_nameval_callback_t)(linker_file_t, int, linker_symval_t *, void *);
struct common_symbol {
STAILQ_ENTRY(common_symbol) link;
@ -158,8 +158,8 @@ int linker_file_lookup_set(linker_file_t _file, const char *_name,
/*
* List all functions in a file.
*/
int linker_file_function_listall(linker_file_t, int (*)(linker_file_t,
linker_symval_t *, void *), void *);
int linker_file_function_listall(linker_file_t,
linker_function_nameval_callback_t, void *);
/*
* Functions soley for use by the linker class handlers.
@ -267,6 +267,20 @@ int elf_reloc_local(linker_file_t _lf, Elf_Addr base, const void *_rel, int _typ
const Elf_Sym *elf_get_sym(linker_file_t _lf, Elf_Size _symidx);
const char *elf_get_symname(linker_file_t _lf, Elf_Size _symidx);
typedef struct linker_ctf {
const uint8_t *ctftab; /* Decompressed CTF data. */
int ctfcnt; /* Number of CTF data bytes. */
const Elf_Sym *symtab; /* Ptr to the symbol table. */
int nsym; /* Number of symbols. */
const char *strtab; /* Ptr to the string table. */
int strcnt; /* Number of string bytes. */
uint32_t **ctfoffp; /* Ptr to array of obj/fnc offsets. */
uint32_t **typoffp; /* Ptr to array of type offsets. */
long *typlenp; /* Ptr to number of type data entries. */
} linker_ctf_t;
int linker_ctf_get(linker_file_t, linker_ctf_t *);
int elf_cpu_load_file(linker_file_t);
int elf_cpu_unload_file(linker_file_t);