[PATCH]mips: ldso: dlopen with flag RTLD_NOW should look up the symbols

xiaoyur347 at gmail.com xiaoyur347 at gmail.com
Fri Feb 20 03:26:36 UTC 2015


Reason:
MIPS ELF strategy is so different from other architectures like x86 and arm. When fPIC enabled in x86 and arm, ".rel.plt" section is generated after ".rel.dyn" section, and the dependency of the library (like the function and object) . But MIPS only generates ".rel.dyn" section for the library when fPIC, and ".rel.dyn" section can only be generated in non-PIC executable.
This leads to a bug which other architectures will not have.

Description:
If you dlopen a library, uclibc only check the symbols defined in ".rel.dyn" section. And ".rel.dyn" section has no outer dependency, most flags have the type "R_MIPS_REL32". Only ".rel.plt" section generates call to R_MIPS_JUMP_SLOT and R_MIPS_COPY.
In my environment, I almost see the cplusplus virtual functions in ".rel.dyn".

Bug Demo:
use mipsel-linux-readelf -aW libxx.so to view the dependency.

Patch:
MIPS: Scan the symtab for the dependency of the library to avoid runtime empty function pointer. 
The dependency = SHN_UNDEF && STB_GLOBAL && (STT_FUNC || STT_OBJECT)
Signed-off-by: Jean Lee <xiaoyur347 at gmail.com>
---
ldso/ldso/mips/elfinterp.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)

diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c
index dfe37c5..00b136a 100644
--- a/ldso/ldso/mips/elfinterp.c
+++ b/ldso/ldso/mips/elfinterp.c
@@ -162,6 +162,8 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
#endif
struct symbol_ref sym_ref;
+ unsigned long symtab_size = 0;
+ ElfW(Sym) *psym = NULL;
/* Now parse the relocation information */
rel_size = rel_size / sizeof(ElfW(Rel));
rpnt = (ELF_RELOC *) rel_addr;
@@ -170,6 +172,32 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
got = (unsigned long *) tpnt->dynamic_info[DT_PLTGOT];
+ /* strtab always layout after symtab */
+ symtab_size = ((unsigned long)strtab - (unsigned long)symtab)
+ / tpnt->dynamic_info[DT_SYMENT];
+ for (i = 0, psym = symtab; i < symtab_size; ++i, ++psym) {
+ if (psym->st_name == 0) {
+ continue;
+ }
+
+ if (psym->st_shndx != SHN_UNDEF
+ || ELF_ST_BIND(psym->st_info) != STB_GLOBAL
+ || (ELF_ST_TYPE(psym->st_info) != STT_FUNC
+ && ELF_ST_TYPE(psym->st_info) != STT_OBJECT)) {
+ continue;
+ }
+ symname = strtab + psym->st_name;
+ 
+ sym_ref.tpnt = NULL;
+ sym_ref.sym = psym;
+ symbol_addr = (unsigned long)_dl_find_hash(symname,
+ scope,
+ tpnt,
+ ELF_RTYPE_CLASS_PLT, &sym_ref);
+ if (symbol_addr == 0) {
+ return 1;
+ }
+ }
for (i = 0; i < rel_size; i++, rpnt++) {
reloc_addr = (unsigned long *) (tpnt->loadaddr +




xiaoyur347 at gmail.com


More information about the uClibc mailing list