/* .eh_frame section optimization.
- Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
- 2012 Free Software Foundation, Inc.
+ Copyright (C) 2001-2014 Free Software Foundation, Inc.
Written by Jakub Jelinek <jakub@redhat.com>.
This file is part of BFD, the Binary File Descriptor library.
bfd_vma augmentation_size;
union {
struct elf_link_hash_entry *h;
- bfd_vma val;
+ struct {
+ unsigned int bfd_id;
+ unsigned int index;
+ } sym;
unsigned int reloc_index;
} personality;
- asection *output_sec;
struct eh_cie_fde *cie_inf;
unsigned char per_encoding;
unsigned char lsda_encoding;
&& c1->augmentation_size == c2->augmentation_size
&& memcmp (&c1->personality, &c2->personality,
sizeof (c1->personality)) == 0
- && c1->output_sec == c2->output_sec
+ && (c1->cie_inf->u.cie.u.sec->output_section
+ == c2->cie_inf->u.cie.u.sec->output_section)
&& c1->per_encoding == c2->per_encoding
&& c1->lsda_encoding == c2->lsda_encoding
&& c1->fde_encoding == c2->fde_encoding
&& c1->initial_insn_length == c2->initial_insn_length
+ && c1->initial_insn_length <= sizeof (c1->initial_instructions)
&& memcmp (c1->initial_instructions,
c2->initial_instructions,
c1->initial_insn_length) == 0)
cie_compute_hash (struct cie *c)
{
hashval_t h = 0;
+ size_t len;
h = iterative_hash_object (c->length, h);
h = iterative_hash_object (c->version, h);
h = iterative_hash (c->augmentation, strlen (c->augmentation) + 1, h);
h = iterative_hash_object (c->ra_column, h);
h = iterative_hash_object (c->augmentation_size, h);
h = iterative_hash_object (c->personality, h);
- h = iterative_hash_object (c->output_sec, h);
+ h = iterative_hash_object (c->cie_inf->u.cie.u.sec->output_section, h);
h = iterative_hash_object (c->per_encoding, h);
h = iterative_hash_object (c->lsda_encoding, h);
h = iterative_hash_object (c->fde_encoding, h);
h = iterative_hash_object (c->initial_insn_length, h);
- h = iterative_hash (c->initial_instructions, c->initial_insn_length, h);
+ len = c->initial_insn_length;
+ if (len > sizeof (c->initial_instructions))
+ len = sizeof (c->initial_instructions);
+ h = iterative_hash (c->initial_instructions, len, h);
c->hash = h;
return h;
}
return encoding | DW_EH_PE_pcrel;
}
-/* Called before calling _bfd_elf_parse_eh_frame on every input bfd's
- .eh_frame section. */
-
-void
-_bfd_elf_begin_eh_frame_parsing (struct bfd_link_info *info)
-{
- struct eh_frame_hdr_info *hdr_info;
-
- hdr_info = &elf_hash_table (info)->eh_info;
- hdr_info->merge_cies = !info->relocatable;
-}
-
/* Try to parse .eh_frame section SEC, which belongs to ABFD. Store the
information in the section's sec_info field on success. COOKIE
describes the relocations in SEC. */
htab = elf_hash_table (info);
hdr_info = &htab->eh_info;
- if (hdr_info->parsed_eh_frames)
- return;
if (sec->size == 0
|| sec->sec_info_type != SEC_INFO_TYPE_NONE)
cie->cie_inf = this_inf;
cie->length = hdr_length;
- cie->output_sec = sec->output_section;
start = buf;
REQUIRE (read_byte (&buf, end, &cie->version));
cie->fde_encoding = DW_EH_PE_absptr;
initial_insn_length = end - buf;
- if (initial_insn_length <= sizeof (cie->initial_instructions))
- {
- cie->initial_insn_length = initial_insn_length;
- memcpy (cie->initial_instructions, buf, initial_insn_length);
- }
+ cie->initial_insn_length = initial_insn_length;
+ memcpy (cie->initial_instructions, buf,
+ initial_insn_length <= sizeof (cie->initial_instructions)
+ ? initial_insn_length : sizeof (cie->initial_instructions));
insns = buf;
buf += initial_insn_length;
ENSURE_NO_RELOCS (buf);
- if (hdr_info->merge_cies)
+ if (!info->relocatable)
+ /* Keep info for merging cies. */
this_inf->u.cie.u.full_cie = cie;
this_inf->u.cie.per_encoding_relative
= (cie->per_encoding & 0x70) == DW_EH_PE_pcrel;
elf_section_data (sec)->sec_info = sec_info;
sec->sec_info_type = SEC_INFO_TYPE_EH_FRAME;
- if (hdr_info->merge_cies)
+ if (!info->relocatable)
{
+ /* Keep info for merging cies. */
sec_info->cies = local_cies;
local_cies = NULL;
}
#undef REQUIRE
}
-/* Finish a pass over all .eh_frame sections. */
-
-void
-_bfd_elf_end_eh_frame_parsing (struct bfd_link_info *info)
-{
- struct eh_frame_hdr_info *hdr_info;
-
- hdr_info = &elf_hash_table (info)->eh_info;
- hdr_info->parsed_eh_frames = TRUE;
-}
-
/* Mark all relocations against CIE or FDE ENT, which occurs in
.eh_frame section SEC. COOKIE describes the relocations in SEC;
its "rel" field can be changed freely. */
{
bfd_boolean per_binds_local;
- /* Work out the address of personality routine, either as an absolute
- value or as a symbol. */
+ /* Work out the address of personality routine, or at least
+ enough info that we could calculate the address had we made a
+ final section layout. The symbol on the reloc is enough,
+ either the hash for a global, or (bfd id, index) pair for a
+ local. The assumption here is that no one uses addends on
+ the reloc. */
rel = cookie->rels + cie->personality.reloc_index;
memset (&cie->personality, 0, sizeof (cie->personality));
#ifdef BFD64
return cie_inf;
cie->local_personality = 1;
- cie->personality.val = (sym->st_value
- + sym_sec->output_offset
- + sym_sec->output_section->vma);
+ cie->personality.sym.bfd_id = abfd->id;
+ cie->personality.sym.index = r_symndx;
per_binds_local = TRUE;
}
}
/* See if we can merge this CIE with an earlier one. */
- cie->output_sec = sec->output_section;
cie_compute_hash (cie);
if (hdr_info->cies == NULL)
{
if (hdr_info->table)
sec->size += 4 + hdr_info->fde_count * 8;
- elf_tdata (abfd)->eh_frame_hdr = sec;
+ elf_eh_frame_hdr (abfd) = sec;
return TRUE;
}