* elf-eh-frame.c (struct cie): Add "local_personality".  Make
	"personality" a union.
	(cie_eq): Compare local_personality too.  Adjust personality
	comparison.
	(_bfd_elf_discard_section_eh_frame): Check binding on personality
	reloc sym to allow for bad symtab.  Use stashed local syms rather
	than reading personality local sym.  Handle discarded sections.
This commit is contained in:
Alan Modra 2007-05-12 14:27:34 +00:00
parent 4f4416b5f9
commit f137a54e7a
2 changed files with 39 additions and 26 deletions

View File

@ -1,3 +1,14 @@
2007-05-12 Alan Modra <amodra@bigpond.net.au>
PR 4497
* elf-eh-frame.c (struct cie): Add "local_personality". Make
"personality" a union.
(cie_eq): Compare local_personality too. Adjust personality
comparison.
(_bfd_elf_discard_section_eh_frame): Check binding on personality
reloc sym to allow for bad symtab. Use stashed local syms rather
than reading personality local sym. Handle discarded sections.
2007-05-12 Alan Modra <amodra@bigpond.net.au> 2007-05-12 Alan Modra <amodra@bigpond.net.au>
* elf32-spu.c (elf_howto_table): Add howto for R_SPU_ADDR16X. * elf32-spu.c (elf_howto_table): Add howto for R_SPU_ADDR16X.

View File

@ -32,12 +32,16 @@ struct cie
unsigned int length; unsigned int length;
unsigned int hash; unsigned int hash;
unsigned char version; unsigned char version;
unsigned char local_personality;
char augmentation[20]; char augmentation[20];
bfd_vma code_align; bfd_vma code_align;
bfd_signed_vma data_align; bfd_signed_vma data_align;
bfd_vma ra_column; bfd_vma ra_column;
bfd_vma augmentation_size; bfd_vma augmentation_size;
bfd_vma personality; union {
struct elf_link_hash_entry *h;
bfd_vma val;
} personality;
asection *output_sec; asection *output_sec;
struct eh_cie_fde *cie_inf; struct eh_cie_fde *cie_inf;
unsigned char per_encoding; unsigned char per_encoding;
@ -216,13 +220,15 @@ cie_eq (const void *e1, const void *e2)
if (c1->hash == c2->hash if (c1->hash == c2->hash
&& c1->length == c2->length && c1->length == c2->length
&& c1->version == c2->version && c1->version == c2->version
&& c1->local_personality == c2->local_personality
&& strcmp (c1->augmentation, c2->augmentation) == 0 && strcmp (c1->augmentation, c2->augmentation) == 0
&& strcmp (c1->augmentation, "eh") != 0 && strcmp (c1->augmentation, "eh") != 0
&& c1->code_align == c2->code_align && c1->code_align == c2->code_align
&& c1->data_align == c2->data_align && c1->data_align == c2->data_align
&& c1->ra_column == c2->ra_column && c1->ra_column == c2->ra_column
&& c1->augmentation_size == c2->augmentation_size && c1->augmentation_size == c2->augmentation_size
&& c1->personality == c2->personality && memcmp (&c1->personality, &c2->personality,
sizeof (c1->personality)) == 0
&& c1->output_sec == c2->output_sec && c1->output_sec == c2->output_sec
&& c1->per_encoding == c2->per_encoding && c1->per_encoding == c2->per_encoding
&& c1->lsda_encoding == c2->lsda_encoding && c1->lsda_encoding == c2->lsda_encoding
@ -670,12 +676,10 @@ _bfd_elf_discard_section_eh_frame
REQUIRE (skip_bytes (&buf, end, length)); REQUIRE (skip_bytes (&buf, end, length));
} }
ENSURE_NO_RELOCS (buf); ENSURE_NO_RELOCS (buf);
/* Ensure we have a reloc here, against /* Ensure we have a reloc here. */
a global symbol. */
if (GET_RELOC (buf) != NULL) if (GET_RELOC (buf) != NULL)
{ {
unsigned long r_symndx; unsigned long r_symndx;
asection *sym_sec = NULL;
#ifdef BFD64 #ifdef BFD64
if (ptr_size == 8) if (ptr_size == 8)
@ -683,7 +687,9 @@ _bfd_elf_discard_section_eh_frame
else else
#endif #endif
r_symndx = ELF32_R_SYM (cookie->rel->r_info); r_symndx = ELF32_R_SYM (cookie->rel->r_info);
if (r_symndx >= cookie->locsymcount) if (r_symndx >= cookie->locsymcount
|| ELF_ST_BIND (cookie->locsyms[r_symndx]
.st_info) != STB_LOCAL)
{ {
struct elf_link_hash_entry *h; struct elf_link_hash_entry *h;
@ -695,33 +701,29 @@ _bfd_elf_discard_section_eh_frame
h = (struct elf_link_hash_entry *) h = (struct elf_link_hash_entry *)
h->root.u.i.link; h->root.u.i.link;
if (h->root.type == bfd_link_hash_defined cie->personality.h = h;
|| h->root.type == bfd_link_hash_defweak)
{
cie->personality = h->root.u.def.value;
sym_sec = h->root.u.def.section;
}
} }
else else
{ {
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Sym *sym; Elf_Internal_Sym *sym;
asection *sym_sec;
bfd_vma val;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym = &cookie->locsyms[r_symndx];
sym = bfd_elf_get_elf_syms (abfd, symtab_hdr, sym_sec = (bfd_section_from_elf_index
1, r_symndx, (abfd, sym->st_shndx));
NULL, NULL, NULL); if (sym_sec->kept_section != NULL)
if (sym != NULL) sym_sec = sym_sec->kept_section;
if (sym_sec != NULL
&& sym_sec->output_section != NULL)
{ {
cie->personality = sym->st_value; val = (sym->st_value
sym_sec = (bfd_section_from_elf_index + sym_sec->output_offset
(abfd, sym->st_shndx)); + sym_sec->output_section->vma);
free (sym); cie->personality.val = val;
cie->local_personality = 1;
} }
} }
if (sym_sec != NULL)
cie->personality += (sym_sec->output_section->vma
+ sym_sec->output_offset);
/* Cope with MIPS-style composite relocations. */ /* Cope with MIPS-style composite relocations. */
do do
@ -729,7 +731,7 @@ _bfd_elf_discard_section_eh_frame
while (GET_RELOC (buf) != NULL); while (GET_RELOC (buf) != NULL);
} }
REQUIRE (skip_bytes (&buf, end, per_width)); REQUIRE (skip_bytes (&buf, end, per_width));
REQUIRE (cie->personality); REQUIRE (cie->local_personality || cie->personality.h);
} }
break; break;
default: default: