Page MenuHomeFreeBSD

D32878.id99649.diff
No OneTemporary

D32878.id99649.diff

diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -912,7 +912,7 @@
linker_file_t lf;
TAILQ_FOREACH(lf, &linker_files, link) {
- if (LINKER_LOOKUP_SYMBOL(lf, symstr, sym) == 0)
+ if (LINKER_LOOKUP_DEBUG_SYMBOL(lf, symstr, sym) == 0)
return (0);
}
return (ENOENT);
@@ -956,7 +956,7 @@
linker_file_t lf;
TAILQ_FOREACH(lf, &linker_files, link) {
- if (LINKER_SYMBOL_VALUES(lf, sym, symval) == 0)
+ if (LINKER_DEBUG_SYMBOL_VALUES(lf, sym, symval) == 0)
return (0);
}
return (ENOENT);
diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c
--- a/sys/kern/link_elf.c
+++ b/sys/kern/link_elf.c
@@ -144,8 +144,12 @@
linker_file_t *);
static int link_elf_lookup_symbol(linker_file_t, const char *,
c_linker_sym_t *);
+static int link_elf_lookup_debug_symbol(linker_file_t, const char *,
+ c_linker_sym_t *);
static int link_elf_symbol_values(linker_file_t, c_linker_sym_t,
linker_symval_t *);
+static int link_elf_debug_symbol_values(linker_file_t, c_linker_sym_t,
+ linker_symval_t*);
static int link_elf_search_symbol(linker_file_t, caddr_t,
c_linker_sym_t *, long *);
@@ -164,7 +168,9 @@
static kobj_method_t link_elf_methods[] = {
KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol),
+ KOBJMETHOD(linker_lookup_debug_symbol, link_elf_lookup_debug_symbol),
KOBJMETHOD(linker_symbol_values, link_elf_symbol_values),
+ KOBJMETHOD(linker_debug_symbol_values, link_elf_debug_symbol_values),
KOBJMETHOD(linker_search_symbol, link_elf_search_symbol),
KOBJMETHOD(linker_unload, link_elf_unload_file),
KOBJMETHOD(linker_load_file, link_elf_load_file),
@@ -188,6 +194,11 @@
link_elf_methods, sizeof(struct elf_file)
};
+static bool link_elf_leak_locals = true;
+SYSCTL_BOOL(_debug, OID_AUTO, link_elf_leak_locals,
+ CTLFLAG_RWTUN, &link_elf_leak_locals, 0,
+ "Allow local symbols to participate in global module symbol resolution");
+
typedef int (*elf_reloc_fn)(linker_file_t lf, Elf_Addr relocbase,
const void *data, int type, elf_lookup_fn lookup);
@@ -1490,14 +1501,14 @@
}
static int
-link_elf_lookup_symbol(linker_file_t lf, const char *name, c_linker_sym_t *sym)
+link_elf_lookup_symbol1(linker_file_t lf, const char *name, c_linker_sym_t *sym,
+ bool see_local)
{
elf_file_t ef = (elf_file_t) lf;
unsigned long symnum;
const Elf_Sym* symp;
const char *strp;
unsigned long hash;
- int i;
/* If we don't have a hash, bail. */
if (ef->buckets == NULL || ef->nbuckets == 0) {
@@ -1528,8 +1539,11 @@
(symp->st_value != 0 &&
(ELF_ST_TYPE(symp->st_info) == STT_FUNC ||
ELF_ST_TYPE(symp->st_info) == STT_GNU_IFUNC))) {
- *sym = (c_linker_sym_t) symp;
- return (0);
+ if (see_local ||
+ ELF_ST_BIND(symp->st_info) != STB_LOCAL) {
+ *sym = (c_linker_sym_t) symp;
+ return (0);
+ }
}
return (ENOENT);
}
@@ -1537,11 +1551,29 @@
symnum = ef->chains[symnum];
}
- /* If we have not found it, look at the full table (if loaded) */
- if (ef->symtab == ef->ddbsymtab)
- return (ENOENT);
+ return (ENOENT);
+}
+
+static int
+link_elf_lookup_symbol(linker_file_t lf, const char *name, c_linker_sym_t *sym)
+{
+ if (link_elf_leak_locals)
+ return (link_elf_lookup_debug_symbol(lf, name, sym));
+ return (link_elf_lookup_symbol1(lf, name, sym, false));
+}
+
+static int
+link_elf_lookup_debug_symbol(linker_file_t lf, const char *name,
+ c_linker_sym_t *sym)
+{
+ elf_file_t ef = (elf_file_t)lf;
+ const Elf_Sym* symp;
+ const char *strp;
+ int i;
+
+ if (link_elf_lookup_symbol1(lf, name, sym, true) == 0)
+ return (0);
- /* Exhaustive search */
for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
strp = ef->ddbstrtab + symp->st_name;
if (strcmp(name, strp) == 0) {
@@ -1560,8 +1592,8 @@
}
static int
-link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym,
- linker_symval_t *symval)
+link_elf_symbol_values1(linker_file_t lf, c_linker_sym_t sym,
+ linker_symval_t *symval, bool see_local)
{
elf_file_t ef;
const Elf_Sym *es;
@@ -1569,7 +1601,9 @@
ef = (elf_file_t)lf;
es = (const Elf_Sym *)sym;
- if (es >= ef->symtab && es < (ef->symtab + ef->nchains)) {
+ if (es >= ef->symtab && es < ef->symtab + ef->nchains) {
+ if (!see_local && ELF_ST_BIND(es->st_info) == STB_LOCAL)
+ return (ENOENT);
symval->name = ef->strtab + es->st_name;
val = (caddr_t)ef->address + es->st_value;
if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC)
@@ -1578,8 +1612,31 @@
symval->size = es->st_size;
return (0);
}
+ return (ENOENT);
+}
+
+static int
+link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym,
+ linker_symval_t *symval)
+{
+ if (link_elf_leak_locals)
+ return (link_elf_debug_symbol_values(lf, sym, symval));
+ return (link_elf_symbol_values1(lf, sym, symval, false));
+}
+
+static int
+link_elf_debug_symbol_values(linker_file_t lf, c_linker_sym_t sym,
+ linker_symval_t *symval)
+{
+ elf_file_t ef = (elf_file_t)lf;
+ const Elf_Sym *es = (const Elf_Sym *)sym;
+ caddr_t val;
+
+ if (link_elf_symbol_values1(lf, sym, symval, true) == 0)
+ return (0);
if (ef->symtab == ef->ddbsymtab)
return (ENOENT);
+
if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) {
symval->name = ef->ddbstrtab + es->st_name;
val = (caddr_t)ef->address + es->st_value;
@@ -1597,7 +1654,7 @@
c_linker_sym_t *sym, long *diffp)
{
elf_file_t ef = (elf_file_t)lf;
- u_long off = (uintptr_t) (void *)value;
+ u_long off = (uintptr_t)(void *)value;
u_long diff = off;
u_long st_value;
const Elf_Sym *es;
diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
--- a/sys/kern/link_elf_obj.c
+++ b/sys/kern/link_elf_obj.c
@@ -44,6 +44,7 @@
#include <sys/namei.h>
#include <sys/proc.h>
#include <sys/rwlock.h>
+#include <sys/sysctl.h>
#include <sys/vnode.h>
#include <machine/elf.h>
@@ -131,8 +132,12 @@
static int link_elf_load_file(linker_class_t, const char *, linker_file_t *);
static int link_elf_lookup_symbol(linker_file_t, const char *,
c_linker_sym_t *);
+static int link_elf_lookup_debug_symbol(linker_file_t, const char *,
+ c_linker_sym_t *);
static int link_elf_symbol_values(linker_file_t, c_linker_sym_t,
linker_symval_t *);
+static int link_elf_debug_symbol_values(linker_file_t, c_linker_sym_t,
+ linker_symval_t *);
static int link_elf_search_symbol(linker_file_t, caddr_t value,
c_linker_sym_t *sym, long *diffp);
@@ -153,7 +158,9 @@
static kobj_method_t link_elf_methods[] = {
KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol),
+ KOBJMETHOD(linker_lookup_debug_symbol, link_elf_lookup_debug_symbol),
KOBJMETHOD(linker_symbol_values, link_elf_symbol_values),
+ KOBJMETHOD(linker_debug_symbol_values, link_elf_debug_symbol_values),
KOBJMETHOD(linker_search_symbol, link_elf_search_symbol),
KOBJMETHOD(linker_unload, link_elf_unload_file),
KOBJMETHOD(linker_load_file, link_elf_load_file),
@@ -177,6 +184,11 @@
link_elf_methods, sizeof(struct elf_file)
};
+static bool link_elf_obj_leak_locals = true;
+SYSCTL_BOOL(_debug, OID_AUTO, link_elf_obj_leak_locals,
+ CTLFLAG_RWTUN, &link_elf_obj_leak_locals, 0,
+ "Allow local symbols to participate in global module symbol resolution");
+
static int relocate_file(elf_file_t ef);
static void elf_obj_cleanup_globals_cache(elf_file_t);
@@ -1424,9 +1436,10 @@
}
static int
-link_elf_lookup_symbol(linker_file_t lf, const char *name, c_linker_sym_t *sym)
+link_elf_lookup_symbol1(linker_file_t lf, const char *name, c_linker_sym_t *sym,
+ bool see_local)
{
- elf_file_t ef = (elf_file_t) lf;
+ elf_file_t ef = (elf_file_t)lf;
const Elf_Sym *symp;
const char *strp;
int i;
@@ -1434,16 +1447,34 @@
for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
strp = ef->ddbstrtab + symp->st_name;
if (symp->st_shndx != SHN_UNDEF && strcmp(name, strp) == 0) {
- *sym = (c_linker_sym_t) symp;
- return 0;
+ if (see_local ||
+ ELF_ST_BIND(symp->st_info) == STB_GLOBAL) {
+ *sym = (c_linker_sym_t) symp;
+ return (0);
+ }
+ return (ENOENT);
}
}
return (ENOENT);
}
static int
-link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym,
- linker_symval_t *symval)
+link_elf_lookup_symbol(linker_file_t lf, const char *name, c_linker_sym_t *sym)
+{
+ return (link_elf_lookup_symbol1(lf, name, sym,
+ link_elf_obj_leak_locals));
+}
+
+static int
+link_elf_lookup_debug_symbol(linker_file_t lf, const char *name,
+ c_linker_sym_t *sym)
+{
+ return (link_elf_lookup_symbol1(lf, name, sym, true));
+}
+
+static int
+link_elf_symbol_values1(linker_file_t lf, c_linker_sym_t sym,
+ linker_symval_t *symval, bool see_local)
{
elf_file_t ef;
const Elf_Sym *es;
@@ -1453,6 +1484,8 @@
es = (const Elf_Sym*) sym;
val = (caddr_t)es->st_value;
if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) {
+ if (!see_local && ELF_ST_BIND(es->st_info) == STB_LOCAL)
+ return (ENOENT);
symval->name = ef->ddbstrtab + es->st_name;
val = (caddr_t)es->st_value;
if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC)
@@ -1464,6 +1497,21 @@
return (ENOENT);
}
+static int
+link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym,
+ linker_symval_t *symval)
+{
+ return (link_elf_symbol_values1(lf, sym, symval,
+ link_elf_obj_leak_locals));
+}
+
+static int
+link_elf_debug_symbol_values(linker_file_t lf, c_linker_sym_t sym,
+ linker_symval_t *symval)
+{
+ return (link_elf_symbol_values1(lf, sym, symval, true));
+}
+
static int
link_elf_search_symbol(linker_file_t lf, caddr_t value,
c_linker_sym_t *sym, long *diffp)
diff --git a/sys/kern/linker_if.m b/sys/kern/linker_if.m
--- a/sys/kern/linker_if.m
+++ b/sys/kern/linker_if.m
@@ -40,12 +40,24 @@
c_linker_sym_t* symp;
};
+METHOD int lookup_debug_symbol {
+ linker_file_t file;
+ const char* name;
+ c_linker_sym_t* symp;
+};
+
METHOD int symbol_values {
linker_file_t file;
c_linker_sym_t sym;
linker_symval_t* valp;
};
+METHOD int debug_symbol_values {
+ linker_file_t file;
+ c_linker_sym_t sym;
+ linker_symval_t* valp;
+};
+
METHOD int search_symbol {
linker_file_t file;
caddr_t value;

File Metadata

Mime Type
text/plain
Expires
Fri, Oct 24, 4:35 AM (8 h, 23 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24119411
Default Alt Text
D32878.id99649.diff (10 KB)

Event Timeline