am 7cab2188: am ad180738: Merge "linker: Fix ARM_R_COPY relocations"

* commit '7cab21885ac039375264a45b2c774106415be664':
  linker: Fix ARM_R_COPY relocations
This commit is contained in:
Nick Kralevich 2012-08-28 13:04:46 -07:00 committed by Android Git Automerger
commit d7440f3725

View File

@ -434,26 +434,28 @@ static unsigned elfhash(const char *_name)
static Elf32_Sym * static Elf32_Sym *
soinfo_do_lookup(soinfo *si, const char *name, Elf32_Addr *offset, soinfo_do_lookup(soinfo *si, const char *name, Elf32_Addr *offset,
soinfo *needed[]) soinfo *needed[], bool ignore_local)
{ {
unsigned elf_hash = elfhash(name); unsigned elf_hash = elfhash(name);
Elf32_Sym *s; Elf32_Sym *s = NULL;
soinfo *lsi = si; soinfo *lsi = si;
int i; int i;
/* Look for symbols in the local scope (the object who is if (!ignore_local) {
* searching). This happens with C++ templates on i386 for some /* Look for symbols in the local scope (the object who is
* reason. * searching). This happens with C++ templates on i386 for some
* * reason.
* Notes on weak symbols: *
* The ELF specs are ambiguous about treatment of weak definitions in * Notes on weak symbols:
* dynamic linking. Some systems return the first definition found * The ELF specs are ambiguous about treatment of weak definitions in
* and some the first non-weak definition. This is system dependent. * dynamic linking. Some systems return the first definition found
* Here we return the first definition found for simplicity. */ * and some the first non-weak definition. This is system dependent.
* Here we return the first definition found for simplicity. */
s = soinfo_elf_lookup(si, elf_hash, name); s = soinfo_elf_lookup(si, elf_hash, name);
if(s != NULL) if(s != NULL)
goto done; goto done;
}
/* Next, look for it in the preloads list */ /* Next, look for it in the preloads list */
for(i = 0; preloads[i] != NULL; i++) { for(i = 0; preloads[i] != NULL; i++) {
@ -684,6 +686,7 @@ verify_elf_header(const Elf32_Ehdr* hdr)
if (hdr->e_ident[EI_MAG1] != ELFMAG1) return -1; if (hdr->e_ident[EI_MAG1] != ELFMAG1) return -1;
if (hdr->e_ident[EI_MAG2] != ELFMAG2) return -1; if (hdr->e_ident[EI_MAG2] != ELFMAG2) return -1;
if (hdr->e_ident[EI_MAG3] != ELFMAG3) return -1; if (hdr->e_ident[EI_MAG3] != ELFMAG3) return -1;
if (hdr->e_type != ET_DYN) return -1;
/* TODO: Should we verify anything else in the header? */ /* TODO: Should we verify anything else in the header? */
#ifdef ANDROID_ARM_LINKER #ifdef ANDROID_ARM_LINKER
@ -959,7 +962,11 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count,
} }
if(sym != 0) { if(sym != 0) {
sym_name = (char *)(strtab + symtab[sym].st_name); sym_name = (char *)(strtab + symtab[sym].st_name);
s = soinfo_do_lookup(si, sym_name, &offset, needed); bool ignore_local = false;
#if defined(ANDROID_ARM_LINKER)
ignore_local = (type == R_ARM_COPY);
#endif
s = soinfo_do_lookup(si, sym_name, &offset, needed, ignore_local);
if(s == NULL) { if(s == NULL) {
/* We only allow an undefined symbol if this is a weak /* We only allow an undefined symbol if this is a weak
reference.. */ reference.. */
@ -1139,10 +1146,29 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count,
#ifdef ANDROID_ARM_LINKER #ifdef ANDROID_ARM_LINKER
case R_ARM_COPY: case R_ARM_COPY:
if ((si->flags & FLAG_EXE) == 0) {
/*
* http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
*
* Section 4.7.1.10 "Dynamic relocations"
* R_ARM_COPY may only appear in executable objects where e_type is
* set to ET_EXEC.
*
* TODO: FLAG_EXE is set for both ET_DYN and ET_EXEC executables.
* We should explicitly disallow ET_DYN executables from having
* R_ARM_COPY relocations.
*/
DL_ERR("%s R_ARM_COPY relocations only supported for ET_EXEC", si->name);
return -1;
}
count_relocation(kRelocCopy); count_relocation(kRelocCopy);
MARK(rel->r_offset); MARK(rel->r_offset);
TRACE_TYPE(RELO, "%5d RELO %08x <- %d @ %08x %s\n", pid, TRACE_TYPE(RELO, "%5d RELO %08x <- %d @ %08x %s\n", pid,
reloc, s->st_size, sym_addr, sym_name); reloc, s->st_size, sym_addr, sym_name);
if (reloc == sym_addr) {
DL_ERR("Internal linker error detected. reloc == symaddr");
return -1;
}
memcpy((void*)reloc, (void*)sym_addr, s->st_size); memcpy((void*)reloc, (void*)sym_addr, s->st_size);
break; break;
#endif /* ANDROID_ARM_LINKER */ #endif /* ANDROID_ARM_LINKER */
@ -1201,7 +1227,7 @@ static int mips_relocate_got(soinfo* si, soinfo* needed[]) {
/* This is an undefined reference... try to locate it */ /* This is an undefined reference... try to locate it */
sym_name = si->strtab + sym->st_name; sym_name = si->strtab + sym->st_name;
s = soinfo_do_lookup(si, sym_name, &base, needed); s = soinfo_do_lookup(si, sym_name, &base, needed, false);
if (s == NULL) { if (s == NULL) {
/* We only allow an undefined symbol if this is a weak /* We only allow an undefined symbol if this is a weak
reference.. */ reference.. */
@ -1804,7 +1830,7 @@ sanitize:
exit(-1); exit(-1);
} }
/* bootstrap the link map, the main exe always needs to be first */ /* bootstrap the link map, the main exe always needs to be first */
si->flags |= FLAG_EXE; si->flags |= FLAG_EXE;
link_map* map = &(si->linkmap); link_map* map = &(si->linkmap);
@ -1839,7 +1865,7 @@ sanitize:
&linker_soinfo.dynamic, NULL); &linker_soinfo.dynamic, NULL);
insert_soinfo_into_debug_map(&linker_soinfo); insert_soinfo_into_debug_map(&linker_soinfo);
/* extract information passed from the kernel */ /* extract information passed from the kernel */
while(vecs[0] != 0){ while(vecs[0] != 0){
switch(vecs[0]){ switch(vecs[0]){
case AT_PHDR: case AT_PHDR: