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 +
[email protected]
_______________________________________________
uClibc mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/uclibc