summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/link_elf.c47
-rw-r--r--sys/kern/link_elf_obj.c53
-rw-r--r--sys/sys/linker.h20
3 files changed, 117 insertions, 3 deletions
diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c
index 89a8971..bdaa636 100644
--- a/sys/kern/link_elf.c
+++ b/sys/kern/link_elf.c
@@ -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
diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
index 95966c7..7df776b 100644
--- a/sys/kern/link_elf_obj.c
+++ b/sys/kern/link_elf_obj.c
@@ -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
diff --git a/sys/sys/linker.h b/sys/sys/linker.h
index 6655d46..4ba7a40 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);
OpenPOWER on IntegriCloud