bfd/
* elf-bfd.h (eh_cie_fde): Add u.fde.next_for_section and u.cie.gc_mark. (bfd_elf_section_data): Add fde_list. (elf_fde_list): New macro. (elf_obj_tdata): Add eh_frame_section. (elf_eh_frame_section): New macro. (_bfd_elf_gc_mark_reloc): Remove last parameter. (_bfd_elf_gc_mark_fdes): Declare. * elf-eh-frame.c (_bfd_elf_get_eh_frame_sec_info): Chain the FDEs for each input section. (mark_entry, _bfd_elf_gc_mark_fdes): New functions. * elflink.c (_bfd_elf_gc_mark_reloc): Remove is_eh parameter. (_bfd_elf_gc_mark): Update call accordingly. Mark the relocations againts the section's FDEs. Don't mark the bfd's elf_eh_frame_section. (bfd_elf_gc_sections): Parse each input bfd's .eh_frame before marking any input sections. Remove the current EH handling. * section.c (bfd_section): Remove gc_mark_from_eh. * ecoff.c (bfd_debug_section): Update initializer accordingly.
This commit is contained in:
parent
ca92cecbbe
commit
9d0a14d3f3
6 changed files with 145 additions and 79 deletions
|
@ -1,3 +1,24 @@
|
|||
2007-12-15 Richard Sandiford <rsandifo@nildram.co.uk>
|
||||
|
||||
* elf-bfd.h (eh_cie_fde): Add u.fde.next_for_section and
|
||||
u.cie.gc_mark.
|
||||
(bfd_elf_section_data): Add fde_list.
|
||||
(elf_fde_list): New macro.
|
||||
(elf_obj_tdata): Add eh_frame_section.
|
||||
(elf_eh_frame_section): New macro.
|
||||
(_bfd_elf_gc_mark_reloc): Remove last parameter.
|
||||
(_bfd_elf_gc_mark_fdes): Declare.
|
||||
* elf-eh-frame.c (_bfd_elf_get_eh_frame_sec_info): Chain the FDEs
|
||||
for each input section.
|
||||
(mark_entry, _bfd_elf_gc_mark_fdes): New functions.
|
||||
* elflink.c (_bfd_elf_gc_mark_reloc): Remove is_eh parameter.
|
||||
(_bfd_elf_gc_mark): Update call accordingly. Mark the relocations
|
||||
againts the section's FDEs. Don't mark the bfd's elf_eh_frame_section.
|
||||
(bfd_elf_gc_sections): Parse each input bfd's .eh_frame before
|
||||
marking any input sections. Remove the current EH handling.
|
||||
* section.c (bfd_section): Remove gc_mark_from_eh.
|
||||
* ecoff.c (bfd_debug_section): Update initializer accordingly.
|
||||
|
||||
2007-12-15 Richard Sandiford <rsandifo@nildram.co.uk>
|
||||
|
||||
* elf-bfd.h (eh_cie_fde): Add u.cie. Document how u.fde.cie_inf
|
||||
|
|
|
@ -55,8 +55,8 @@ static asection bfd_debug_section =
|
|||
{
|
||||
/* name, id, index, next, prev, flags, user_set_vma, */
|
||||
"*DEBUG*", 0, 0, NULL, NULL, 0, 0,
|
||||
/* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh, */
|
||||
0, 0, 1, 0,
|
||||
/* linker_mark, linker_has_input, gc_mark, */
|
||||
0, 0, 1,
|
||||
/* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, */
|
||||
0, 0, 0, 0,
|
||||
/* has_gp_reloc, need_finalize_relax, reloc_done, */
|
||||
|
|
|
@ -273,6 +273,7 @@ struct eh_cie_fde
|
|||
the output FDE. The CIE's REMOVED field is also 0, but the CIE
|
||||
might belong to a different .eh_frame input section from the FDE. */
|
||||
struct eh_cie_fde *cie_inf;
|
||||
struct eh_cie_fde *next_for_section;
|
||||
} fde;
|
||||
struct {
|
||||
/* In general, equivalent CIEs are grouped together, with one CIE
|
||||
|
@ -281,6 +282,9 @@ struct eh_cie_fde
|
|||
following this pointer brings us "closer" to the CIE's group
|
||||
representative, and reapplying always gives the representative. */
|
||||
struct eh_cie_fde *merged;
|
||||
|
||||
/* True if we have marked relocations associated with this CIE. */
|
||||
unsigned int gc_mark : 1;
|
||||
} cie;
|
||||
} u;
|
||||
unsigned int reloc_index;
|
||||
|
@ -1243,6 +1247,10 @@ struct bfd_elf_section_data
|
|||
the linker. For the SHT_GROUP section, points at first member. */
|
||||
asection *next_in_group;
|
||||
|
||||
/* The FDEs associated with this section. The u.fde.next_in_section
|
||||
field acts as a chain pointer. */
|
||||
struct eh_cie_fde *fde_list;
|
||||
|
||||
/* A pointer used for various section optimizations. */
|
||||
void *sec_info;
|
||||
};
|
||||
|
@ -1254,6 +1262,7 @@ struct bfd_elf_section_data
|
|||
#define elf_group_name(sec) (elf_section_data(sec)->group.name)
|
||||
#define elf_group_id(sec) (elf_section_data(sec)->group.id)
|
||||
#define elf_next_in_group(sec) (elf_section_data(sec)->next_in_group)
|
||||
#define elf_fde_list(sec) (elf_section_data(sec)->fde_list)
|
||||
#define elf_sec_group(sec) (elf_section_data(sec)->sec_group)
|
||||
|
||||
#define xvec_get_elf_backend_data(xvec) \
|
||||
|
@ -1459,6 +1468,9 @@ struct elf_obj_tdata
|
|||
asection *elf_data_section;
|
||||
asection *elf_text_section;
|
||||
|
||||
/* A pointer to the .eh_frame section. */
|
||||
asection *eh_frame_section;
|
||||
|
||||
/* Whether a dyanmic object was specified normally on the linker
|
||||
command line, or was specified when --as-needed was in effect,
|
||||
or was found via a DT_NEEDED entry. */
|
||||
|
@ -1504,6 +1516,8 @@ struct elf_obj_tdata
|
|||
#define elf_dynversym(bfd) (elf_tdata(bfd) -> dynversym_section)
|
||||
#define elf_dynverdef(bfd) (elf_tdata(bfd) -> dynverdef_section)
|
||||
#define elf_dynverref(bfd) (elf_tdata(bfd) -> dynverref_section)
|
||||
#define elf_eh_frame_section(bfd) \
|
||||
(elf_tdata(bfd) -> eh_frame_section)
|
||||
#define elf_num_locals(bfd) (elf_tdata(bfd) -> num_locals)
|
||||
#define elf_num_globals(bfd) (elf_tdata(bfd) -> num_globals)
|
||||
#define elf_section_syms(bfd) (elf_tdata(bfd) -> section_syms)
|
||||
|
@ -2004,7 +2018,11 @@ extern asection *_bfd_elf_gc_mark_rsec
|
|||
|
||||
extern bfd_boolean _bfd_elf_gc_mark_reloc
|
||||
(struct bfd_link_info *, asection *, elf_gc_mark_hook_fn,
|
||||
struct elf_reloc_cookie *, bfd_boolean);
|
||||
struct elf_reloc_cookie *);
|
||||
|
||||
extern bfd_boolean _bfd_elf_gc_mark_fdes
|
||||
(struct bfd_link_info *, asection *, asection *, elf_gc_mark_hook_fn,
|
||||
struct elf_reloc_cookie *);
|
||||
|
||||
extern bfd_boolean _bfd_elf_gc_mark
|
||||
(struct bfd_link_info *, asection *, elf_gc_mark_hook_fn);
|
||||
|
|
|
@ -475,6 +475,7 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
|
|||
unsigned int ptr_size;
|
||||
unsigned int num_cies;
|
||||
unsigned int num_entries;
|
||||
elf_gc_mark_hook_fn gc_mark_hook;
|
||||
|
||||
htab = elf_hash_table (info);
|
||||
hdr_info = &htab->eh_info;
|
||||
|
@ -577,6 +578,7 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
|
|||
|
||||
buf = ehbuf;
|
||||
ecie_count = 0;
|
||||
gc_mark_hook = get_elf_backend_data (abfd)->gc_mark_hook;
|
||||
while ((bfd_size_type) (buf - ehbuf) != sec->size)
|
||||
{
|
||||
char *aug;
|
||||
|
@ -821,6 +823,8 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
|
|||
}
|
||||
else
|
||||
{
|
||||
asection *rsec;
|
||||
|
||||
/* Find the corresponding CIE. */
|
||||
unsigned int cie_offset = this_inf->offset + 4 - hdr_id;
|
||||
for (ecie = ecies; ecie < ecies + ecie_count; ++ecie)
|
||||
|
@ -836,6 +840,12 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
|
|||
ENSURE_NO_RELOCS (buf);
|
||||
REQUIRE (GET_RELOC (buf));
|
||||
|
||||
/* Chain together the FDEs for each section. */
|
||||
rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie);
|
||||
REQUIRE (rsec && rsec->owner == abfd);
|
||||
this_inf->u.fde.next_for_section = elf_fde_list (rsec);
|
||||
elf_fde_list (rsec) = this_inf;
|
||||
|
||||
/* Skip the initial location and address range. */
|
||||
start = buf;
|
||||
length = get_DW_EH_PE_width (cie->fde_encoding, ptr_size);
|
||||
|
@ -976,6 +986,55 @@ _bfd_elf_end_eh_frame_parsing (struct bfd_link_info *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. */
|
||||
|
||||
static bfd_boolean
|
||||
mark_entry (struct bfd_link_info *info, asection *sec,
|
||||
struct eh_cie_fde *ent, elf_gc_mark_hook_fn gc_mark_hook,
|
||||
struct elf_reloc_cookie *cookie)
|
||||
{
|
||||
for (cookie->rel = cookie->rels + ent->reloc_index;
|
||||
cookie->rel < cookie->relend
|
||||
&& cookie->rel->r_offset < ent->offset + ent->size;
|
||||
cookie->rel++)
|
||||
if (!_bfd_elf_gc_mark_reloc (info, sec, gc_mark_hook, cookie))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Mark all the relocations against FDEs that relate to code in input
|
||||
section SEC. The FDEs belong to .eh_frame section EH_FRAME, whose
|
||||
relocations are described by COOKIE. */
|
||||
|
||||
bfd_boolean
|
||||
_bfd_elf_gc_mark_fdes (struct bfd_link_info *info, asection *sec,
|
||||
asection *eh_frame, elf_gc_mark_hook_fn gc_mark_hook,
|
||||
struct elf_reloc_cookie *cookie)
|
||||
{
|
||||
struct eh_cie_fde *fde, *cie, *merged;
|
||||
|
||||
for (fde = elf_fde_list (sec); fde; fde = fde->u.fde.next_for_section)
|
||||
{
|
||||
if (!mark_entry (info, eh_frame, fde, gc_mark_hook, cookie))
|
||||
return FALSE;
|
||||
|
||||
/* At this stage, all cie_inf fields point to local CIEs, so we
|
||||
can use the same cookie to refer to them. */
|
||||
cie = fde->u.fde.cie_inf;
|
||||
merged = cie->u.cie.merged;
|
||||
if (!merged->u.cie.gc_mark)
|
||||
{
|
||||
merged->u.cie.gc_mark = 1;
|
||||
if (!mark_entry (info, eh_frame, cie, gc_mark_hook, cookie))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* This function is called for each input file before the .eh_frame
|
||||
section is relocated. It discards duplicate CIEs and FDEs for discarded
|
||||
functions. The function returns TRUE iff any entries have been
|
||||
|
|
117
bfd/elflink.c
117
bfd/elflink.c
|
@ -11137,15 +11137,13 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
|
|||
|
||||
/* COOKIE->rel describes a relocation against section SEC, which is
|
||||
a section we've decided to keep. Mark the section that contains
|
||||
the relocation symbol. IS_EH is true if the mark comes from
|
||||
.eh_frame. */
|
||||
the relocation symbol. */
|
||||
|
||||
bfd_boolean
|
||||
_bfd_elf_gc_mark_reloc (struct bfd_link_info *info,
|
||||
asection *sec,
|
||||
elf_gc_mark_hook_fn gc_mark_hook,
|
||||
struct elf_reloc_cookie *cookie,
|
||||
bfd_boolean is_eh)
|
||||
struct elf_reloc_cookie *cookie)
|
||||
{
|
||||
asection *rsec;
|
||||
|
||||
|
@ -11154,8 +11152,6 @@ _bfd_elf_gc_mark_reloc (struct bfd_link_info *info,
|
|||
{
|
||||
if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour)
|
||||
rsec->gc_mark = 1;
|
||||
else if (is_eh)
|
||||
rsec->gc_mark_from_eh = 1;
|
||||
else if (!_bfd_elf_gc_mark (info, rsec, gc_mark_hook))
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -11172,8 +11168,7 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
|
|||
elf_gc_mark_hook_fn gc_mark_hook)
|
||||
{
|
||||
bfd_boolean ret;
|
||||
bfd_boolean is_eh;
|
||||
asection *group_sec;
|
||||
asection *group_sec, *eh_frame;
|
||||
|
||||
sec->gc_mark = 1;
|
||||
|
||||
|
@ -11185,8 +11180,10 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
|
|||
|
||||
/* Look through the section relocs. */
|
||||
ret = TRUE;
|
||||
is_eh = strcmp (sec->name, ".eh_frame") == 0;
|
||||
if ((sec->flags & SEC_RELOC) != 0 && sec->reloc_count > 0)
|
||||
eh_frame = elf_eh_frame_section (sec->owner);
|
||||
if ((sec->flags & SEC_RELOC) != 0
|
||||
&& sec->reloc_count > 0
|
||||
&& sec != eh_frame)
|
||||
{
|
||||
struct elf_reloc_cookie cookie;
|
||||
|
||||
|
@ -11195,8 +11192,7 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
|
|||
else
|
||||
{
|
||||
for (; cookie.rel < cookie.relend; cookie.rel++)
|
||||
if (!_bfd_elf_gc_mark_reloc (info, sec, gc_mark_hook,
|
||||
&cookie, is_eh))
|
||||
if (!_bfd_elf_gc_mark_reloc (info, sec, gc_mark_hook, &cookie))
|
||||
{
|
||||
ret = FALSE;
|
||||
break;
|
||||
|
@ -11204,6 +11200,22 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
|
|||
fini_reloc_cookie_for_section (&cookie, sec);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret && eh_frame && elf_fde_list (sec))
|
||||
{
|
||||
struct elf_reloc_cookie cookie;
|
||||
|
||||
if (!init_reloc_cookie_for_section (&cookie, info, eh_frame))
|
||||
ret = FALSE;
|
||||
else
|
||||
{
|
||||
if (!_bfd_elf_gc_mark_fdes (info, sec, eh_frame,
|
||||
gc_mark_hook, &cookie))
|
||||
ret = FALSE;
|
||||
fini_reloc_cookie_for_section (&cookie, eh_frame);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -11469,6 +11481,25 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Try to parse each bfd's .eh_frame section. Point elf_eh_frame_section
|
||||
at the .eh_frame section if we can mark the FDEs individually. */
|
||||
_bfd_elf_begin_eh_frame_parsing (info);
|
||||
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
|
||||
{
|
||||
asection *sec;
|
||||
struct elf_reloc_cookie cookie;
|
||||
|
||||
sec = bfd_get_section_by_name (sub, ".eh_frame");
|
||||
if (sec && init_reloc_cookie_for_section (&cookie, info, sec))
|
||||
{
|
||||
_bfd_elf_parse_eh_frame (sub, info, sec, &cookie);
|
||||
if (elf_section_data (sec)->sec_info)
|
||||
elf_eh_frame_section (sub) = sec;
|
||||
fini_reloc_cookie_for_section (&cookie, sec);
|
||||
}
|
||||
}
|
||||
_bfd_elf_end_eh_frame_parsing (info);
|
||||
|
||||
/* Apply transitive closure to the vtable entry usage info. */
|
||||
elf_link_hash_traverse (elf_hash_table (info),
|
||||
elf_gc_propagate_vtable_entries_used,
|
||||
|
@ -11508,68 +11539,6 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
|
|||
if (bed->gc_mark_extra_sections)
|
||||
bed->gc_mark_extra_sections(info, gc_mark_hook);
|
||||
|
||||
/* ... again for sections marked from eh_frame. */
|
||||
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
|
||||
{
|
||||
asection *o;
|
||||
|
||||
if (bfd_get_flavour (sub) != bfd_target_elf_flavour)
|
||||
continue;
|
||||
|
||||
/* Keep .gcc_except_table.* if the associated .text.* (or the
|
||||
associated .gnu.linkonce.t.* if .text.* doesn't exist) is
|
||||
marked. This isn't very nice, but the proper solution,
|
||||
splitting .eh_frame up and using comdat doesn't pan out
|
||||
easily due to needing special relocs to handle the
|
||||
difference of two symbols in separate sections.
|
||||
Don't keep code sections referenced by .eh_frame. */
|
||||
#define TEXT_PREFIX ".text."
|
||||
#define TEXT_PREFIX2 ".gnu.linkonce.t."
|
||||
#define GCC_EXCEPT_TABLE_PREFIX ".gcc_except_table."
|
||||
for (o = sub->sections; o != NULL; o = o->next)
|
||||
if (!o->gc_mark && o->gc_mark_from_eh && (o->flags & SEC_CODE) == 0)
|
||||
{
|
||||
if (CONST_STRNEQ (o->name, GCC_EXCEPT_TABLE_PREFIX))
|
||||
{
|
||||
char *fn_name;
|
||||
const char *sec_name;
|
||||
asection *fn_text;
|
||||
unsigned o_name_prefix_len , fn_name_prefix_len, tmp;
|
||||
|
||||
o_name_prefix_len = strlen (GCC_EXCEPT_TABLE_PREFIX);
|
||||
sec_name = o->name + o_name_prefix_len;
|
||||
fn_name_prefix_len = strlen (TEXT_PREFIX);
|
||||
tmp = strlen (TEXT_PREFIX2);
|
||||
if (tmp > fn_name_prefix_len)
|
||||
fn_name_prefix_len = tmp;
|
||||
fn_name
|
||||
= bfd_malloc (fn_name_prefix_len + strlen (sec_name) + 1);
|
||||
if (fn_name == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* Try the first prefix. */
|
||||
sprintf (fn_name, "%s%s", TEXT_PREFIX, sec_name);
|
||||
fn_text = bfd_get_section_by_name (sub, fn_name);
|
||||
|
||||
/* Try the second prefix. */
|
||||
if (fn_text == NULL)
|
||||
{
|
||||
sprintf (fn_name, "%s%s", TEXT_PREFIX2, sec_name);
|
||||
fn_text = bfd_get_section_by_name (sub, fn_name);
|
||||
}
|
||||
|
||||
free (fn_name);
|
||||
if (fn_text == NULL || !fn_text->gc_mark)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If not using specially named exception table section,
|
||||
then keep whatever we are using. */
|
||||
if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* ... and mark SEC_EXCLUDE for those that go. */
|
||||
return elf_gc_sweep (abfd, info);
|
||||
}
|
||||
|
|
|
@ -357,9 +357,8 @@ CODE_FRAGMENT
|
|||
. output sections that have an input section. *}
|
||||
. unsigned int linker_has_input : 1;
|
||||
.
|
||||
. {* Mark flags used by some linker backends for garbage collection. *}
|
||||
. {* Mark flag used by some linker backends for garbage collection. *}
|
||||
. unsigned int gc_mark : 1;
|
||||
. unsigned int gc_mark_from_eh : 1;
|
||||
.
|
||||
. {* The following flags are used by the ELF linker. *}
|
||||
.
|
||||
|
|
Loading…
Reference in a new issue