aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2007-05-12 14:27:34 +0000
committerAlan Modra <amodra@gmail.com>2007-05-12 14:27:34 +0000
commitf137a54e7af023b5a81c138f1ff7b0619883e807 (patch)
tree3f374af435a5bdd33ccea9f76b46bfd6aada8cfc /bfd
parent4f4416b5f935edad0191d7e60952db517bb2671c (diff)
downloadbinutils-f137a54e7af023b5a81c138f1ff7b0619883e807.zip
binutils-f137a54e7af023b5a81c138f1ff7b0619883e807.tar.gz
binutils-f137a54e7af023b5a81c138f1ff7b0619883e807.tar.bz2
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.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog11
-rw-r--r--bfd/elf-eh-frame.c56
2 files changed, 40 insertions, 27 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 102fd08..81848c0 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,16 @@
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>
+
* elf32-spu.c (elf_howto_table): Add howto for R_SPU_ADDR16X.
2007-05-11 Alan Modra <amodra@bigpond.net.au>
diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
index ae07f37..c7cb1d7 100644
--- a/bfd/elf-eh-frame.c
+++ b/bfd/elf-eh-frame.c
@@ -32,12 +32,16 @@ struct cie
unsigned int length;
unsigned int hash;
unsigned char version;
+ unsigned char local_personality;
char augmentation[20];
bfd_vma code_align;
bfd_signed_vma data_align;
bfd_vma ra_column;
bfd_vma augmentation_size;
- bfd_vma personality;
+ union {
+ struct elf_link_hash_entry *h;
+ bfd_vma val;
+ } personality;
asection *output_sec;
struct eh_cie_fde *cie_inf;
unsigned char per_encoding;
@@ -216,13 +220,15 @@ cie_eq (const void *e1, const void *e2)
if (c1->hash == c2->hash
&& c1->length == c2->length
&& c1->version == c2->version
+ && c1->local_personality == c2->local_personality
&& strcmp (c1->augmentation, c2->augmentation) == 0
&& strcmp (c1->augmentation, "eh") != 0
&& c1->code_align == c2->code_align
&& c1->data_align == c2->data_align
&& c1->ra_column == c2->ra_column
&& 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->per_encoding == c2->per_encoding
&& c1->lsda_encoding == c2->lsda_encoding
@@ -670,12 +676,10 @@ _bfd_elf_discard_section_eh_frame
REQUIRE (skip_bytes (&buf, end, length));
}
ENSURE_NO_RELOCS (buf);
- /* Ensure we have a reloc here, against
- a global symbol. */
+ /* Ensure we have a reloc here. */
if (GET_RELOC (buf) != NULL)
{
unsigned long r_symndx;
- asection *sym_sec = NULL;
#ifdef BFD64
if (ptr_size == 8)
@@ -683,7 +687,9 @@ _bfd_elf_discard_section_eh_frame
else
#endif
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;
@@ -695,33 +701,29 @@ _bfd_elf_discard_section_eh_frame
h = (struct elf_link_hash_entry *)
h->root.u.i.link;
- if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- {
- cie->personality = h->root.u.def.value;
- sym_sec = h->root.u.def.section;
- }
+ cie->personality.h = h;
}
else
{
- Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Sym *sym;
-
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- sym = bfd_elf_get_elf_syms (abfd, symtab_hdr,
- 1, r_symndx,
- NULL, NULL, NULL);
- if (sym != NULL)
+ asection *sym_sec;
+ bfd_vma val;
+
+ sym = &cookie->locsyms[r_symndx];
+ sym_sec = (bfd_section_from_elf_index
+ (abfd, sym->st_shndx));
+ if (sym_sec->kept_section != NULL)
+ sym_sec = sym_sec->kept_section;
+ if (sym_sec != NULL
+ && sym_sec->output_section != NULL)
{
- cie->personality = sym->st_value;
- sym_sec = (bfd_section_from_elf_index
- (abfd, sym->st_shndx));
- free (sym);
+ val = (sym->st_value
+ + sym_sec->output_offset
+ + sym_sec->output_section->vma);
+ 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. */
do
@@ -729,7 +731,7 @@ _bfd_elf_discard_section_eh_frame
while (GET_RELOC (buf) != NULL);
}
REQUIRE (skip_bytes (&buf, end, per_width));
- REQUIRE (cie->personality);
+ REQUIRE (cie->local_personality || cie->personality.h);
}
break;
default: