summaryrefslogtreecommitdiffstats
path: root/sys/kern/link_elf.c
diff options
context:
space:
mode:
authorjb <jb@FreeBSD.org>2008-05-23 00:49:39 +0000
committerjb <jb@FreeBSD.org>2008-05-23 00:49:39 +0000
commit090fe643c2a0482ad0454a18acf9e5b54df003fc (patch)
tree60128931d1442975820875bbdc7c20456ce9f38e /sys/kern/link_elf.c
parent8c4eed9aad5a7911341733c7a8d074c9fd9e11f1 (diff)
downloadFreeBSD-src-090fe643c2a0482ad0454a18acf9e5b54df003fc.zip
FreeBSD-src-090fe643c2a0482ad0454a18acf9e5b54df003fc.tar.gz
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.
Diffstat (limited to 'sys/kern/link_elf.c')
-rw-r--r--sys/kern/link_elf.c47
1 files changed, 47 insertions, 0 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
OpenPOWER on IntegriCloud