&& (!(TFROM) || (TFROM)->loadaddr < (TPNT)->loadaddr))
#endif
+/* On some platforms, computing a pointer to function is more
+ expensive than calling a function at a given address, so this
+ alternative is provided. The function signature must be given
+ within parentheses, as in a type cast. */
+#ifndef DL_ADDR_TO_FUNC_PTR
+# define DL_ADDR_TO_FUNC_PTR(ADDR, LOADADDR) (ADDR)
+#endif
+#ifndef DL_CALL_FUNC_AT_ADDR
+# define DL_CALL_FUNC_AT_ADDR(ADDR, LOADADDR, SIGNATURE, ...) \
+ ((*SIGNATURE DL_ADDR_TO_FUNC_PTR ((ADDR), (LOADADDR)))(__VA_ARGS__))
+#endif
+
#endif /* _LD_DEFS_H */
struct elf_resolve {
/* These entries must be in this order to be compatible with the interface used
by gdb to obtain the list of symbols. */
- DL_LOADADDR_TYPE loadaddr; /* Base address shared object is loaded at. */
+ DL_LOADADDR_TYPE loadaddr; /* Base address shared object is loaded at. */
char *libname; /* Absolute file name object was found in. */
ElfW(Dyn) *dynamic_addr; /* Dynamic section of the shared object. */
struct elf_resolve * next;
void
_dl_protect_relro (struct elf_resolve *l)
{
- ElfW(Addr) start = (DL_RELOC_ADDR(l->loadaddr, l->relro_addr)
- & ~(_dl_pagesize - 1));
- ElfW(Addr) end = ((DL_RELOC_ADDR(l->loadaddr, l->relro_addr) + l->relro_size)
- & ~(_dl_pagesize - 1));
+ ElfW(Addr) base = (ElfW(Addr)) DL_RELOC_ADDR(l->loadaddr, l->relro_addr);
+ ElfW(Addr) start = (base & ~(_dl_pagesize - 1));
+ ElfW(Addr) end = ((base + l->relro_size) & ~(_dl_pagesize - 1));
_dl_if_debug_dprint("RELRO protecting %s: start:%x, end:%x\n", l->libname, start, end);
if (start != end &&
_dl_mprotect ((void *) start, end - start, PROT_READ) < 0) {
}
_dl_if_debug_dprint("\n\tfile='%s'; generating link map\n", libname);
- _dl_if_debug_dprint("\t\tdynamic: %x base: %x\n", dynamic_addr, DL_LOADADDR_BASE(libaddr));
+ _dl_if_debug_dprint("\t\tdynamic: %x base: %x\n", dynamic_addr, DL_LOADADDR_BASE(lib_loadaddr));
_dl_if_debug_dprint("\t\t entry: %x phdr: %x phnum: %x\n\n",
DL_RELOC_ADDR(lib_loadaddr, epnt->e_entry), tpnt->ppnt, tpnt->n_phent);
int ret = 0;
for (l = _dl_loaded_modules; l != NULL; l = l->next) {
- info.dlpi_addr = DL_LOADADDR_BASE(l->loadaddr);
+ info.dlpi_addr = l->loadaddr;
info.dlpi_name = l->libname;
info.dlpi_phdr = l->ppnt;
info.dlpi_phnum = l->n_phent;
rel_addr += relative_count * sizeof(ELF_RELOC);
}
- rpnt = (ELF_RELOC *) DL_RELOC_ADDR(load_addr, rel_addr);
+ rpnt = (ELF_RELOC *) rel_addr;
for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) {
reloc_addr = (unsigned long *) DL_RELOC_ADDR(load_addr, (unsigned long)rpnt->r_offset);
symtab_index = ELF_R_SYM(rpnt->r_info);
for (j = 0; j < jm; ++j) {
void (*dl_elf_func) (void);
dl_elf_func = (void (*)(void)) (intptr_t) addrs[j];
- (*dl_elf_func) ();
+ DL_CALL_FUNC_AT_ADDR (dl_elf_func, loadaddr, (void (*)(void)));
}
}
}
while (i-- > 0) {
void (*dl_elf_func) (void);
dl_elf_func = (void (*)(void)) (intptr_t) array[i];
- (*dl_elf_func) ();
+ DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void (*)(void)));
}
}
}
dl_elf_func = (void (*)(void)) (intptr_t) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI]);
_dl_if_debug_dprint("\ncalling FINI: %s\n\n", tpnt->libname);
- (*dl_elf_func) ();
+ DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
}
}
}
_dl_if_debug_dprint("calling INIT: %s\n\n", tpnt->libname);
- (*dl_elf_func) ();
+ DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
}
_dl_run_init_array(tpnt);
if (tpnt->dynamic_info[DT_INIT]) {
void (*dl_elf_func) (void);
dl_elf_func = (void (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_INIT]);
- if (dl_elf_func && *dl_elf_func != NULL) {
+ if (dl_elf_func) {
_dl_if_debug_print("running ctors for library %s at '%p'\n",
tpnt->libname, dl_elf_func);
- (*dl_elf_func) ();
+ DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
}
}
dl_elf_fini = (int (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI]);
_dl_if_debug_print("running dtors for library %s at '%p'\n",
tpnt->libname, dl_elf_fini);
- (*dl_elf_fini) ();
+ DL_CALL_FUNC_AT_ADDR (dl_elf_fini, tpnt->loadaddr, (int (*)(void)));
}
}
_dl_if_debug_print("Module \"%s\" at %p\n",
tpnt->libname, DL_LOADADDR_BASE(tpnt->loadaddr));
- if (DL_ADDR_IN_LOADADDR((ElfW(Addr)) __address, tpnt, pelf))
+ if (DL_ADDR_IN_LOADADDR((ElfW(Addr)) __address, tpnt, pelf))
pelf = tpnt;
}