_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry) { ELF_RELOC *this_reloc; char *strtab; ElfW(Sym) *symtab; int symtab_index; char *rel_addr; struct elf_resolve *new_tpnt; char *new_addr; struct funcdesc_value funcval; struct funcdesc_value volatile *got_entry; char *symname; rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); symtab_index = ELF_R_SYM(this_reloc->r_info); symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB]; strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; symname= strtab + symtab[symtab_index].st_name; /* Address of GOT entry fix up */ got_entry = (struct funcdesc_value *) DL_RELOC_ADDR(tpnt->loadaddr, this_reloc->r_offset); /* Get the address to be used to fill in the GOT entry. */ new_addr = _dl_lookup_hash(symname, tpnt->symbol_scope, NULL, 0, &new_tpnt); if (!new_addr) { new_addr = _dl_lookup_hash(symname, NULL, NULL, 0, &new_tpnt); if (!new_addr) { _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); _dl_exit(1); } } funcval.entry_point = new_addr; funcval.got_value = new_tpnt->loadaddr.got_value; #if defined (__SUPPORT_LD_DEBUG__) if (_dl_debug_bindings) { _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); if (_dl_debug_detail) _dl_dprintf(_dl_debug_file, "\n\tpatched (%x,%x) ==> (%x,%x) @ %x\n", got_entry->entry_point, got_entry->got_value, funcval.entry_point, funcval.got_value, got_entry); } if (1 || !_dl_debug_nofixups) { *got_entry = funcval; } #else *got_entry = funcval; #endif return got_entry; }
__attribute__((__visibility__("hidden"))) struct funcdesc_value volatile * _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry) { int reloc_type; ELF_RELOC *this_reloc; char *strtab; ElfW(Sym) *symtab; int symtab_index; char *rel_addr; struct elf_resolve *new_tpnt; char *new_addr; struct funcdesc_value funcval; struct funcdesc_value volatile *got_entry; char *symname; rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); reloc_type = ELF_R_TYPE(this_reloc->r_info); symtab_index = ELF_R_SYM(this_reloc->r_info); symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB]; strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; symname= strtab + symtab[symtab_index].st_name; if (reloc_type != R_UBICOM32_FUNCDESC_VALUE) { _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", _dl_progname); _dl_exit(1); } /* Address of GOT entry fix up */ got_entry = (struct funcdesc_value *) DL_RELOC_ADDR(tpnt->loadaddr, this_reloc->r_offset); /* Get the address to be used to fill in the GOT entry. */ new_addr = _dl_lookup_hash(symname, tpnt->symbol_scope, NULL, 0, &new_tpnt); if (!new_addr) { new_addr = _dl_lookup_hash(symname, NULL, NULL, 0, &new_tpnt); if (!new_addr) { _dl_dprintf(2, "_dl_linux_resolver: %s: can't resolve symbol '%s'\n", _dl_progname, symname); _dl_exit(1); } } funcval.entry_point = new_addr; funcval.got_value = new_tpnt->loadaddr.got_value; #if defined (__SUPPORT_LD_DEBUG__) if (_dl_debug_bindings) { _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); if (_dl_debug_detail) _dl_dprintf(_dl_debug_file, "\n\tpatched (%x,%x) ==> (%x,%x) @ %x\n", got_entry->entry_point, got_entry->got_value, funcval.entry_point, funcval.got_value, got_entry); } if (1 || !_dl_debug_nofixups) { got_entry->entry_point = ((void *)&_dl_ubicom32_resolve_pending); got_entry->got_value = funcval.got_value; got_entry->entry_point = funcval.entry_point; } #else /* * initially set the entry point to resolve pending before starting * the update. This has the effect of putting all other requests in a * holding pattern until the resolution is completed. */ got_entry->entry_point = ((void*)&_dl_ubicom32_resolve_pending); got_entry->got_value = funcval.got_value; got_entry->entry_point = funcval.entry_point; #endif return got_entry; }