示例#1
0
_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;
}
示例#2
0
 __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;
}