diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c index 89a8971e7983..bdaa63633920 100644 --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -27,6 +27,7 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_ddb.h" #include "opt_gdb.h" #include "opt_mac.h" @@ -62,6 +63,10 @@ __FBSDID("$FreeBSD$"); #include +#ifdef DDB_CTF +#include +#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 + 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 diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c index 95966c7334cd..7df776b6374e 100644 --- a/sys/kern/link_elf_obj.c +++ b/sys/kern/link_elf_obj.c @@ -58,6 +58,10 @@ __FBSDID("$FreeBSD$"); #include +#ifdef DDB_CTF +#include +#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 + 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 diff --git a/sys/sys/linker.h b/sys/sys/linker.h index 6655d46e4c3f..4ba7a40072ac 100644 --- a/sys/sys/linker.h +++ b/sys/sys/linker.h @@ -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);