summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ldso/ldso/powerpc/elfinterp.c204
1 files changed, 87 insertions, 117 deletions
diff --git a/ldso/ldso/powerpc/elfinterp.c b/ldso/ldso/powerpc/elfinterp.c
index 635296142..c930f717b 100644
--- a/ldso/ldso/powerpc/elfinterp.c
+++ b/ldso/ldso/powerpc/elfinterp.c
@@ -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;
-
- /* Now parse the relocation information */
- 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);
-
- /* When the dynamic linker bootstrapped itself, it resolved some symbols.
- 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) /* R_PPC_COPY is handled later */
+ 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;/* Funny, this works too and appears to be much faster. */
+#endif
+ if (reloc_type == R_PPC_COPY) {
+ sym_scope = scope->next;
+ tpnt = NULL; /* To be or not to be ...*/
+ }
+ 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:
- /* This does not work yet, R_PPC_COPY is handled later, see if statemet above */
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;
}
-/* This is done as a separate step, because there are cases where
- 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;
+
+ /* Now parse the relocation information */
+ 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);
+
+ /* When the dynamic linker bootstrapped itself, it resolved some symbols.
+ 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);
}
+/* Should be a static inline instead, but that conflicts with ld_elf.h */
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);
+ /* Not used! */
+ return 0;
}
-