Page MenuHomeFreeBSD

D50683.id157603.diff
No OneTemporary

D50683.id157603.diff

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
@@ -1628,6 +1628,41 @@
return (i < ef->ddbsymcnt ? link_elf_ctf_get_ddb(lf, lc) : ENOENT);
}
+static void
+link_elf_ifunc_symbol_value(linker_file_t lf, caddr_t *valp, size_t *sizep)
+{
+ c_linker_sym_t sym;
+ elf_file_t ef;
+ const Elf_Sym *es;
+ caddr_t val;
+ long off;
+ int error;
+
+ val = *valp;
+ ef = (elf_file_t)lf;
+
+ /* Provide the value and size of the resolvee's symbol, if available. */
+ val = ((caddr_t (*)(void))val)();
+ error = link_elf_search_symbol(lf, val, &sym, &off);
+ if (error != 0) {
+ /* The resolvee might live in a different linker file. */
+ for (int i = 0; i < lf->ndeps; i++) {
+ error = link_elf_search_symbol(lf->deps[i], val, &sym,
+ &off);
+ if (error == 0)
+ break;
+ }
+ }
+ if (error == 0 && off == 0) {
+ es = (const Elf_Sym *)sym;
+ *valp = (caddr_t)ef->address + es->st_value;
+ *sizep = es->st_size;
+ } else {
+ *valp = val;
+ *sizep = 0;
+ }
+}
+
static int
link_elf_symbol_values1(linker_file_t lf, c_linker_sym_t sym,
linker_symval_t *symval, bool see_local)
@@ -1635,6 +1670,7 @@
elf_file_t ef;
const Elf_Sym *es;
caddr_t val;
+ size_t size;
ef = (elf_file_t)lf;
es = (const Elf_Sym *)sym;
@@ -1644,9 +1680,11 @@
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)
- val = ((caddr_t (*)(void))val)();
+ link_elf_ifunc_symbol_value(lf, &val, &size);
+ else
+ size = es->st_size;
symval->value = val;
- symval->size = es->st_size;
+ symval->size = size;
return (0);
}
return (ENOENT);
@@ -1668,6 +1706,7 @@
elf_file_t ef = (elf_file_t)lf;
const Elf_Sym *es = (const Elf_Sym *)sym;
caddr_t val;
+ size_t size;
if (link_elf_symbol_values1(lf, sym, symval, true) == 0)
return (0);
@@ -1678,9 +1717,11 @@
symval->name = ef->ddbstrtab + es->st_name;
val = (caddr_t)ef->address + es->st_value;
if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC)
- val = ((caddr_t (*)(void))val)();
+ link_elf_ifunc_symbol_value(lf, &val, &size);
+ else
+ size = es->st_size;
symval->value = val;
- symval->size = es->st_size;
+ symval->size = size;
return (0);
}
return (ENOENT);
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
@@ -1510,6 +1510,41 @@
return (link_elf_ctf_get_ddb(lf, lc));
}
+static void
+link_elf_ifunc_symbol_value(linker_file_t lf, caddr_t *valp, size_t *sizep)
+{
+ c_linker_sym_t sym;
+ elf_file_t ef;
+ const Elf_Sym *es;
+ caddr_t val;
+ long off;
+ int error;
+
+ val = *valp;
+ ef = (elf_file_t)lf;
+
+ /* Provide the value and size of the resolvee's symbol, if available. */
+ val = ((caddr_t (*)(void))val)();
+ error = link_elf_search_symbol(lf, val, &sym, &off);
+ if (error != 0) {
+ /* The resolvee might live in a different linker file. */
+ for (int i = 0; i < lf->ndeps; i++) {
+ error = link_elf_search_symbol(lf->deps[i], val, &sym,
+ &off);
+ if (error == 0)
+ break;
+ }
+ }
+ if (error == 0 && off == 0) {
+ es = (const Elf_Sym *)sym;
+ *valp = (caddr_t)ef->address + es->st_value;
+ *sizep = es->st_size;
+ } else {
+ *valp = val;
+ *sizep = 0;
+ }
+}
+
static int
link_elf_symbol_values1(linker_file_t lf, c_linker_sym_t sym,
linker_symval_t *symval, bool see_local)
@@ -1517,6 +1552,7 @@
elf_file_t ef;
const Elf_Sym *es;
caddr_t val;
+ size_t size;
ef = (elf_file_t) lf;
es = (const Elf_Sym*) sym;
@@ -1527,9 +1563,11 @@
symval->name = ef->ddbstrtab + es->st_name;
val = (caddr_t)es->st_value;
if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC)
- val = ((caddr_t (*)(void))val)();
+ link_elf_ifunc_symbol_value(lf, &val, &size);
+ else
+ size = es->st_size;
symval->value = val;
- symval->size = es->st_size;
+ symval->size = size;
return (0);
}
return (ENOENT);

File Metadata

Mime Type
text/plain
Expires
Tue, Apr 7, 11:46 PM (8 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31056356
Default Alt Text
D50683.id157603.diff (3 KB)

Event Timeline