|
@@ -3,6 +3,7 @@
|
|
|
*
|
|
|
* Copyright (C) 2001-2002 David A. Schleef
|
|
|
* Copyright (C) 2003-2004 Erik Andersen
|
|
|
+ * Copyright (C) 2004 Joakim Tjernlund
|
|
|
*
|
|
|
* All rights reserved.
|
|
|
*
|
|
@@ -251,72 +252,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
|
|
|
return finaladdr;
|
|
|
}
|
|
|
|
|
|
-static int
|
|
|
-_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
|
|
|
- unsigned long rel_addr, unsigned long rel_size,
|
|
|
- int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
|
|
|
- ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
|
|
|
-{
|
|
|
- unsigned int i;
|
|
|
- char *strtab;
|
|
|
- Elf32_Sym *symtab;
|
|
|
- ELF_RELOC *rpnt;
|
|
|
- int symtab_index;
|
|
|
-
|
|
|
-
|
|
|
- rpnt = (ELF_RELOC *)(intptr_t) (rel_addr + tpnt->loadaddr);
|
|
|
- rel_size = rel_size / sizeof(ELF_RELOC);
|
|
|
-
|
|
|
- symtab = (Elf32_Sym *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
|
|
|
- strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
|
|
|
-
|
|
|
- for (i = 0; i < rel_size; i++, rpnt++) {
|
|
|
- int res;
|
|
|
-
|
|
|
- symtab_index = ELF32_R_SYM(rpnt->r_info);
|
|
|
-
|
|
|
-
|
|
|
- Make sure we do not do them again */
|
|
|
- if (!symtab_index && tpnt->libtype == program_interpreter)
|
|
|
- continue;
|
|
|
- if (symtab_index && tpnt->libtype == program_interpreter &&
|
|
|
- _dl_symbol(strtab + symtab[symtab_index].st_name))
|
|
|
- continue;
|
|
|
-
|
|
|
-#if defined (__SUPPORT_LD_DEBUG__)
|
|
|
- debug_sym(symtab,strtab,symtab_index);
|
|
|
- debug_reloc(symtab,strtab,rpnt);
|
|
|
-#endif
|
|
|
-
|
|
|
- res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
|
|
|
-
|
|
|
- if (res==0) continue;
|
|
|
-
|
|
|
- _dl_dprintf(2, "\n%s: ",_dl_progname);
|
|
|
-
|
|
|
- if (symtab_index)
|
|
|
- _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
|
|
|
-
|
|
|
- if (res <0)
|
|
|
- {
|
|
|
- int reloc_type = ELF32_R_TYPE(rpnt->r_info);
|
|
|
-#if defined (__SUPPORT_LD_DEBUG__)
|
|
|
- _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
|
|
|
-#else
|
|
|
- _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
|
|
|
-#endif
|
|
|
- _dl_exit(-res);
|
|
|
- }
|
|
|
- else if (res >0)
|
|
|
- {
|
|
|
- _dl_dprintf(2, "can't resolve symbol\n");
|
|
|
- return res;
|
|
|
- }
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
+static inline int
|
|
|
_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
|
|
|
ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
|
|
|
{
|
|
@@ -325,6 +261,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
|
|
|
char *symname;
|
|
|
Elf32_Addr *reloc_addr;
|
|
|
Elf32_Addr finaladdr;
|
|
|
+ struct dyn_elf *sym_scope;
|
|
|
|
|
|
unsigned long symbol_addr;
|
|
|
#if defined (__SUPPORT_LD_DEBUG__)
|
|
@@ -336,13 +273,22 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
|
|
|
*reloc_addr = tpnt->loadaddr + rpnt->r_addend;
|
|
|
return 0;
|
|
|
}
|
|
|
- if (reloc_type == R_PPC_NONE || reloc_type == R_PPC_COPY)
|
|
|
+ if (reloc_type == R_PPC_NONE)
|
|
|
return 0;
|
|
|
symtab_index = ELF32_R_SYM(rpnt->r_info);
|
|
|
symname = strtab + symtab[symtab_index].st_name;
|
|
|
-
|
|
|
- symbol_addr = (unsigned long) _dl_find_hash(symname, scope,
|
|
|
- (reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL), symbolrel);
|
|
|
+#if 0
|
|
|
+ sym_scope = scope->dyn->symbol_scope;
|
|
|
+#else
|
|
|
+ sym_scope = scope;
|
|
|
+#endif
|
|
|
+ if (reloc_type == R_PPC_COPY) {
|
|
|
+ sym_scope = scope->next;
|
|
|
+ tpnt = NULL;
|
|
|
+ }
|
|
|
+ symbol_addr = (unsigned long) _dl_find_hash(symname, sym_scope,
|
|
|
+ (reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL),
|
|
|
+ (reloc_type == R_PPC_COPY ? copyrel : symbolrel));
|
|
|
|
|
|
* We want to allow undefined references to weak symbols - this might
|
|
|
* have been intentional. We should not be linking local symbols
|
|
@@ -398,7 +344,6 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
|
|
|
break;
|
|
|
}
|
|
|
case R_PPC_COPY:
|
|
|
-
|
|
|
if (symbol_addr) {
|
|
|
#if defined (__SUPPORT_LD_DEBUG__)
|
|
|
if(_dl_debug_move)
|
|
@@ -423,7 +368,8 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
|
|
|
{
|
|
|
Elf32_Sword delta = finaladdr - (Elf32_Word)reloc_addr;
|
|
|
if(delta<<6>>6 != delta){
|
|
|
- _dl_dprintf(2, "%s: symbol '%s' R_PPC_REL24 is out of range.\n\tCompile shared libraries with -fPIC!\n",
|
|
|
+ _dl_dprintf(2, "%s: symbol '%s' R_PPC_REL24 is out of range.\n\t"
|
|
|
+ "Compile shared libraries with -fPIC!\n",
|
|
|
_dl_progname, symname);
|
|
|
_dl_exit(1);
|
|
|
}
|
|
@@ -452,48 +398,6 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- information is first copied and later initialized. This results in
|
|
|
- the wrong information being copied. Someone at Sun was complaining about
|
|
|
- a bug in the handling of _COPY by SVr4, and this may in fact be what he
|
|
|
- was talking about. Sigh. */
|
|
|
-static int
|
|
|
-_dl_do_copy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
|
|
|
- ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
|
|
|
-{
|
|
|
- int reloc_type;
|
|
|
- int symtab_index;
|
|
|
- unsigned long *reloc_addr;
|
|
|
- unsigned long symbol_addr;
|
|
|
- int goof = 0;
|
|
|
- char *symname;
|
|
|
-
|
|
|
- reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
|
|
|
- reloc_type = ELF32_R_TYPE(rpnt->r_info);
|
|
|
- if (reloc_type != R_PPC_COPY)
|
|
|
- return 0;
|
|
|
- symtab_index = ELF32_R_SYM(rpnt->r_info);
|
|
|
- symbol_addr = 0;
|
|
|
- symname = strtab + symtab[symtab_index].st_name;
|
|
|
-
|
|
|
- if (symtab_index) {
|
|
|
- symbol_addr = (unsigned long) _dl_find_hash(symname, scope, NULL, copyrel);
|
|
|
- if (!symbol_addr) goof++;
|
|
|
- }
|
|
|
- if (!goof) {
|
|
|
-#if defined (__SUPPORT_LD_DEBUG__)
|
|
|
- if(_dl_debug_move)
|
|
|
- _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x",
|
|
|
- symname, symtab[symtab_index].st_size,
|
|
|
- symbol_addr, symtab[symtab_index].st_value);
|
|
|
-#endif
|
|
|
- _dl_memcpy((char *) reloc_addr,
|
|
|
- (char *) (symbol_addr + (unsigned long)rpnt->r_addend), symtab[symtab_index].st_size);
|
|
|
- }
|
|
|
-
|
|
|
- return goof;
|
|
|
-}
|
|
|
-
|
|
|
void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
|
|
|
unsigned long rel_addr, unsigned long rel_size, int type)
|
|
|
{
|
|
@@ -538,16 +442,82 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
|
|
|
PPC_ISYNC;
|
|
|
}
|
|
|
|
|
|
+static inline int
|
|
|
+_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
|
|
|
+ unsigned long rel_addr, unsigned long rel_size,
|
|
|
+ int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
|
|
|
+ ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
|
|
|
+{
|
|
|
+ unsigned int i;
|
|
|
+ char *strtab;
|
|
|
+ Elf32_Sym *symtab;
|
|
|
+ ELF_RELOC *rpnt;
|
|
|
+ int symtab_index;
|
|
|
+
|
|
|
+
|
|
|
+ rpnt = (ELF_RELOC *)(intptr_t) (rel_addr + tpnt->loadaddr);
|
|
|
+ rel_size = rel_size / sizeof(ELF_RELOC);
|
|
|
+
|
|
|
+ symtab = (Elf32_Sym *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
|
|
|
+ strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
|
|
|
+
|
|
|
+ for (i = 0; i < rel_size; i++, rpnt++) {
|
|
|
+ int res;
|
|
|
+
|
|
|
+ symtab_index = ELF32_R_SYM(rpnt->r_info);
|
|
|
+
|
|
|
+
|
|
|
+ Make sure we do not do them again */
|
|
|
+ if (!symtab_index && tpnt->libtype == program_interpreter)
|
|
|
+ continue;
|
|
|
+ if (symtab_index && tpnt->libtype == program_interpreter &&
|
|
|
+ _dl_symbol(strtab + symtab[symtab_index].st_name))
|
|
|
+ continue;
|
|
|
+
|
|
|
+#if defined (__SUPPORT_LD_DEBUG__)
|
|
|
+ debug_sym(symtab,strtab,symtab_index);
|
|
|
+ debug_reloc(symtab,strtab,rpnt);
|
|
|
+#endif
|
|
|
+
|
|
|
+ res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
|
|
|
+
|
|
|
+ if (res==0) continue;
|
|
|
+
|
|
|
+ _dl_dprintf(2, "\n%s: ",_dl_progname);
|
|
|
+
|
|
|
+ if (symtab_index)
|
|
|
+ _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
|
|
|
+
|
|
|
+ if (res <0)
|
|
|
+ {
|
|
|
+ int reloc_type = ELF32_R_TYPE(rpnt->r_info);
|
|
|
+#if defined (__SUPPORT_LD_DEBUG__)
|
|
|
+ _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
|
|
|
+#else
|
|
|
+ _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
|
|
|
+#endif
|
|
|
+ _dl_exit(-res);
|
|
|
+ }
|
|
|
+ else if (res >0)
|
|
|
+ {
|
|
|
+ _dl_dprintf(2, "can't resolve symbol\n");
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
int _dl_parse_relocation_information(struct dyn_elf *rpnt,
|
|
|
unsigned long rel_addr, unsigned long rel_size, int type)
|
|
|
{
|
|
|
- return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
|
|
|
+ return _dl_parse(rpnt->dyn, rpnt, rel_addr, rel_size, _dl_do_reloc);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
int _dl_parse_copy_information(struct dyn_elf *rpnt,
|
|
|
unsigned long rel_addr, unsigned long rel_size, int type)
|
|
|
{
|
|
|
- return _dl_parse(rpnt->dyn, rpnt->next, rel_addr, rel_size, _dl_do_copy_reloc);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-
|