diff options
Diffstat (limited to 'trunk/src/conflict.c')
-rw-r--r-- | trunk/src/conflict.c | 163 |
1 files changed, 82 insertions, 81 deletions
diff --git a/trunk/src/conflict.c b/trunk/src/conflict.c index 82e07db..38d0830 100644 --- a/trunk/src/conflict.c +++ b/trunk/src/conflict.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2002, 2003, 2004, 2007 Red Hat, Inc. +/* Copyright (C) 2001, 2002, 2003, 2004, 2007, 2009 Red Hat, Inc. Written by Jakub Jelinek <jakub@redhat.com>, 2001. This program is free software; you can redistribute it and/or modify @@ -276,7 +276,7 @@ conflict_rela_cmp (const void *A, const void *B) int get_relocated_mem (struct prelink_info *info, DSO *dso, GElf_Addr addr, - char *buf, GElf_Word size) + char *buf, GElf_Word size, GElf_Addr dest_addr) { int sec = addr_to_sec (dso, addr), j; Elf_Scn *scn; @@ -321,7 +321,7 @@ get_relocated_mem (struct prelink_info *info, DSO *dso, GElf_Addr addr, reloc offset. */ for (j = 0; j < info->conflict_rela_size; ++j) { - int reloc_type, reloc_size; + int reloc_type, reloc_size, ret; off_t off; if (info->conflict_rela[j].r_offset >= addr + size) @@ -343,8 +343,12 @@ get_relocated_mem (struct prelink_info *info, DSO *dso, GElf_Addr addr, return 2; /* Note that apply_conflict_rela shouldn't rely on R_SYM field of conflict to be 0. */ - dso->arch->apply_conflict_rela (info, info->conflict_rela + j, - buf + off); + ret + = dso->arch->apply_conflict_rela (info, info->conflict_rela + j, + buf + off, + dest_addr ? dest_addr + off : 0); + if (ret) + return ret; } } else @@ -467,15 +471,17 @@ prelink_build_conflicts (struct prelink_info *info) } } - for (i = 1; i < ndeps; ++i) + for (i = 0; i < ndeps; ++i) { + int j, sec, first_conflict, maxidx; + struct prelink_conflict *conflict; + dso = info->dsos[i]; - ent = info->ent->depends[i - 1]; + ent = i ? info->ent->depends[i - 1] : info->ent; /* Verify .gnu.liblist sections of all dependent libraries. */ - if (ent->ndepends > 0) + if (i && ent->ndepends > 0) { - int j; const char *name; int nliblist; Elf32_Lib *liblist; @@ -539,85 +545,78 @@ prelink_build_conflicts (struct prelink_info *info) } } - if (info->conflicts[i].count || info->tls[i].modid) + info->curconflicts = &info->conflicts[i]; + info->curtls = info->tls[i].modid ? info->tls + i : NULL; + first_conflict = info->conflict_rela_size; + sec = addr_to_sec (dso, dso->info[DT_SYMTAB]); + /* DT_SYMTAB should be found and should point to + start of .dynsym section. */ + if (sec == -1 || dso->info[DT_SYMTAB] != dso->shdr[sec].sh_addr) { - int j, sec, first_conflict, maxidx; - struct prelink_conflict *conflict; - - info->curconflicts = &info->conflicts[i]; - info->curtls = info->tls[i].modid ? info->tls + i : NULL; - first_conflict = info->conflict_rela_size; - sec = addr_to_sec (dso, dso->info[DT_SYMTAB]); - /* DT_SYMTAB should be found and should point to - start of .dynsym section. */ - if (sec == -1 - || dso->info[DT_SYMTAB] != dso->shdr[sec].sh_addr) + error (0, 0, "Bad symtab"); + goto error_out; + } + info->symtab_start = dso->shdr[sec].sh_addr - dso->base; + info->symtab_end = info->symtab_start + dso->shdr[sec].sh_size; + for (j = 0; j < dso->ehdr.e_shnum; ++j) + { + if (! (dso->shdr[j].sh_flags & SHF_ALLOC)) + continue; + switch (dso->shdr[j].sh_type) { - error (0, 0, "Bad symtab"); - goto error_out; + case SHT_REL: + if (prelink_conflict_rel (dso, j, info)) + goto error_out; + break; + case SHT_RELA: + if (prelink_conflict_rela (dso, j, info)) + goto error_out; + break; } - info->symtab_start = dso->shdr[sec].sh_addr - dso->base; - info->symtab_end = info->symtab_start + dso->shdr[sec].sh_size; - for (j = 0; j < dso->ehdr.e_shnum; ++j) + } + + if (dso->arch->arch_prelink_conflict + && dso->arch->arch_prelink_conflict (dso, info)) + goto error_out; + + maxidx = 1; + if (info->curconflicts->hash != &info->curconflicts->first) + maxidx = 251; + for (j = 0; j < maxidx; j++) + for (conflict = info->curconflicts->hash[j]; conflict; + conflict = conflict->next) + if (! conflict->used && (i || conflict->ifunc)) { - if (! (dso->shdr[j].sh_flags & SHF_ALLOC)) - continue; - switch (dso->shdr[j].sh_type) - { - case SHT_REL: - if (prelink_conflict_rel (dso, j, info)) - goto error_out; - break; - case SHT_RELA: - if (prelink_conflict_rela (dso, j, info)) - goto error_out; - break; - } + error (0, 0, "%s: Conflict %08llx not found in any relocation", + dso->filename, (unsigned long long) conflict->symoff); + ret = 1; } - if (dso->arch->arch_prelink_conflict - && dso->arch->arch_prelink_conflict (dso, info)) - goto error_out; + /* Record library's position in search scope into R_SYM field. */ + for (j = first_conflict; j < info->conflict_rela_size; ++j) + info->conflict_rela[j].r_info + = GELF_R_INFO (i, GELF_R_TYPE (info->conflict_rela[j].r_info)); - maxidx = 1; - if (info->curconflicts->hash != &info->curconflicts->first) - maxidx = 251; - for (j = 0; j < maxidx; j++) - for (conflict = info->curconflicts->hash[j]; conflict; - conflict = conflict->next) - if (! conflict->used) - { - error (0, 0, "%s: Conflict %08llx not found in any relocation", - dso->filename, (unsigned long long) conflict->symoff); - ret = 1; - } + if (dynamic_info_is_set (dso, DT_TEXTREL) + && info->conflict_rela_size > first_conflict) + { + /* We allow prelinking against non-PIC libraries, as long as + no conflict is against read-only segment. */ + int k; - /* Record library's position in search scope into R_SYM field. */ for (j = first_conflict; j < info->conflict_rela_size; ++j) - info->conflict_rela[j].r_info - = GELF_R_INFO (i, GELF_R_TYPE (info->conflict_rela[j].r_info)); - - if (dynamic_info_is_set (dso, DT_TEXTREL) - && info->conflict_rela_size > first_conflict) - { - /* We allow prelinking against non-PIC libraries, as long as - no conflict is against read-only segment. */ - int k; - - for (j = first_conflict; j < info->conflict_rela_size; ++j) - for (k = 0; k < dso->ehdr.e_phnum; ++k) - if (dso->phdr[k].p_type == PT_LOAD - && (dso->phdr[k].p_flags & PF_W) == 0 - && dso->phdr[k].p_vaddr - <= info->conflict_rela[j].r_offset - && dso->phdr[k].p_vaddr + dso->phdr[k].p_memsz - > info->conflict_rela[j].r_offset) - { - error (0, 0, "%s: Cannot prelink against non-PIC shared library %s", - info->dso->filename, dso->filename); - goto error_out; - } - } + for (k = 0; k < dso->ehdr.e_phnum; ++k) + if (dso->phdr[k].p_type == PT_LOAD + && (dso->phdr[k].p_flags & PF_W) == 0 + && dso->phdr[k].p_vaddr + <= info->conflict_rela[j].r_offset + && dso->phdr[k].p_vaddr + dso->phdr[k].p_memsz + > info->conflict_rela[j].r_offset) + { + error (0, 0, "%s: Cannot prelink against non-PIC shared library %s", + info->dso->filename, dso->filename); + goto error_out; + } } } @@ -755,11 +754,13 @@ prelink_build_conflicts (struct prelink_info *info) if (i < firstbss2) j = get_relocated_mem (info, ndso, s->u.ent->base + s->value, info->sdynbss + cr.rela[i].r_offset - - info->sdynbss_base, cr.rela[i].r_addend); + - info->sdynbss_base, cr.rela[i].r_addend, + cr.rela[i].r_offset); else j = get_relocated_mem (info, ndso, s->u.ent->base + s->value, info->dynbss + cr.rela[i].r_offset - - info->dynbss_base, cr.rela[i].r_addend); + - info->dynbss_base, cr.rela[i].r_addend, + cr.rela[i].r_offset); switch (j) { |