mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-12-12 14:37:43 +00:00
Add experimental support for --gc-sections with COFF and PE based targets.
PR ld/11539 bfd * coffcode.h (coff_bfd_gc_sections): Define default to bfd_coff_gc_sections function. * cofflink.c (init_reloc_cookie): Copy and adjust coff related code about gc-sections from elflink.c to here. (fini_reloc_cookie): Likewise. (init_reloc_cookie_rels): Likewise. (fini_reloc_cookie_rels): Likewise. (init_reloc_cookie_for_section): Likewise. (fini_reloc_cookie_for_section): Likewise. (_bfd_coff_gc_mark_hook): Likewise. (_bfd_coff_gc_mark_rsec): Likewise. (_bfd_coff_gc_mark_reloc): Likewise. (_bfd_coff_gc_mark): Likewise. (_bfd_coff_gc_mark_extra_sections): Likewise. (coff_gc_sweep_symbol_info): Likewise. (coff_gc_sweep_symbol): Likewise. (gc_sweep_hook_fn): Likewise. (coff_gc_sweep): Likewise. (bfd_coff_gc_sections): Likewise. (_bfd_coff_gc_keep): Likewise. * libcoff.h (coff_reloc_cookie): New struct. (bfd_coff_gc_sections): New prototype. (coff_gc_mark_hook_fn): New type. ld * scripttempl/pep.sc: Mark .idata*, .CRT*, .tls*, .rsrc*, .init, .ctor*, .dtor*, .fini, .jcr, .eh_frame, .pdata. .xdata, and .gcc_except_table sections as KEEP. * scripttempl/pe.sc: Likewise.
This commit is contained in:
parent
b6b3dd8f31
commit
0f088b2a94
@ -1,3 +1,32 @@
|
||||
2015-07-03 Kai Tietz <ktietz@redhat.com>
|
||||
Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR ld/11539
|
||||
* coffcode.h (coff_bfd_gc_sections): Define default
|
||||
to bfd_coff_gc_sections function.
|
||||
(coff_gc_mark_hook_fn): New type.
|
||||
* coffgen.c (init_reloc_cookie): Copy and adjust coff
|
||||
related code about gc-sections from elflink.c to here.
|
||||
(fini_reloc_cookie): Likewise.
|
||||
(init_reloc_cookie_rels): Likewise.
|
||||
(fini_reloc_cookie_rels): Likewise.
|
||||
(init_reloc_cookie_for_section): Likewise.
|
||||
(fini_reloc_cookie_for_section): Likewise.
|
||||
(_bfd_coff_gc_mark_hook): Likewise.
|
||||
(_bfd_coff_gc_mark_rsec): Likewise.
|
||||
(_bfd_coff_gc_mark_reloc): Likewise.
|
||||
(_bfd_coff_gc_mark): Likewise.
|
||||
(_bfd_coff_gc_mark_extra_sections): Likewise.
|
||||
(coff_gc_sweep_symbol_info): Likewise.
|
||||
(coff_gc_sweep_symbol): Likewise.
|
||||
(gc_sweep_hook_fn): Likewise.
|
||||
(coff_gc_sweep): Likewise.
|
||||
(bfd_coff_gc_sections): Likewise.
|
||||
(_bfd_coff_gc_keep): Likewise.
|
||||
* libcoff-in.h (coff_reloc_cookie): New struct.
|
||||
(bfd_coff_gc_sections): New prototype.
|
||||
* libcoff.h: Regenerate.
|
||||
|
||||
2015-07-01 Sandra Loosemore <sandra@codesourcery.com>
|
||||
Cesar Philippidis <cesar@codesourcery.com>
|
||||
|
||||
|
@ -1352,6 +1352,10 @@ CODE_FRAGMENT
|
||||
. COFF_SYMBOL_PE_SECTION
|
||||
.};
|
||||
.
|
||||
.typedef asection * (*coff_gc_mark_hook_fn)
|
||||
. (asection *, struct bfd_link_info *, struct internal_reloc *,
|
||||
. struct coff_link_hash_entry *, struct internal_syment *);
|
||||
.
|
||||
Special entry points for gdb to swap in coff symbol table parts:
|
||||
.typedef struct
|
||||
.{
|
||||
@ -5993,7 +5997,7 @@ static bfd_coff_backend_data bigobj_swap_table =
|
||||
#endif
|
||||
|
||||
#ifndef coff_bfd_gc_sections
|
||||
#define coff_bfd_gc_sections bfd_generic_gc_sections
|
||||
#define coff_bfd_gc_sections bfd_coff_gc_sections
|
||||
#endif
|
||||
|
||||
#ifndef coff_bfd_lookup_section_flags
|
||||
|
428
bfd/coffgen.c
428
bfd/coffgen.c
@ -2626,3 +2626,431 @@ _bfd_coff_section_already_linked (bfd *abfd,
|
||||
info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Initialize COOKIE for input bfd ABFD. */
|
||||
|
||||
static bfd_boolean
|
||||
init_reloc_cookie (struct coff_reloc_cookie *cookie,
|
||||
struct bfd_link_info *info ATTRIBUTE_UNUSED,
|
||||
bfd *abfd)
|
||||
{
|
||||
/* Sometimes the symbol table does not yet have been loaded here. */
|
||||
bfd_coff_slurp_symbol_table (abfd);
|
||||
|
||||
cookie->abfd = abfd;
|
||||
cookie->sym_hashes = obj_coff_sym_hashes (abfd);
|
||||
|
||||
cookie->symbols = obj_symbols (abfd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Free the memory allocated by init_reloc_cookie, if appropriate. */
|
||||
|
||||
static void
|
||||
fini_reloc_cookie (struct coff_reloc_cookie *cookie ATTRIBUTE_UNUSED,
|
||||
bfd *abfd ATTRIBUTE_UNUSED)
|
||||
{
|
||||
/* Nothing to do. */
|
||||
}
|
||||
|
||||
/* Initialize the relocation information in COOKIE for input section SEC
|
||||
of input bfd ABFD. */
|
||||
|
||||
static bfd_boolean
|
||||
init_reloc_cookie_rels (struct coff_reloc_cookie *cookie,
|
||||
struct bfd_link_info *info ATTRIBUTE_UNUSED,
|
||||
bfd *abfd,
|
||||
asection *sec)
|
||||
{
|
||||
if (sec->reloc_count == 0)
|
||||
{
|
||||
cookie->rels = NULL;
|
||||
cookie->relend = NULL;
|
||||
cookie->rel = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cookie->rels = _bfd_coff_read_internal_relocs (abfd, sec, FALSE, NULL, 0, NULL);
|
||||
|
||||
if (cookie->rels == NULL)
|
||||
return FALSE;
|
||||
|
||||
cookie->rel = cookie->rels;
|
||||
cookie->relend = (cookie->rels + sec->reloc_count);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Free the memory allocated by init_reloc_cookie_rels,
|
||||
if appropriate. */
|
||||
|
||||
static void
|
||||
fini_reloc_cookie_rels (struct coff_reloc_cookie *cookie,
|
||||
asection *sec)
|
||||
{
|
||||
if (cookie->rels && coff_section_data (NULL, sec)->relocs != cookie->rels)
|
||||
free (cookie->rels);
|
||||
}
|
||||
|
||||
/* Initialize the whole of COOKIE for input section SEC. */
|
||||
|
||||
static bfd_boolean
|
||||
init_reloc_cookie_for_section (struct coff_reloc_cookie *cookie,
|
||||
struct bfd_link_info *info,
|
||||
asection *sec)
|
||||
{
|
||||
if (!init_reloc_cookie (cookie, info, sec->owner))
|
||||
return FALSE;
|
||||
|
||||
if (!init_reloc_cookie_rels (cookie, info, sec->owner, sec))
|
||||
{
|
||||
fini_reloc_cookie (cookie, sec->owner);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Free the memory allocated by init_reloc_cookie_for_section,
|
||||
if appropriate. */
|
||||
|
||||
static void
|
||||
fini_reloc_cookie_for_section (struct coff_reloc_cookie *cookie,
|
||||
asection *sec)
|
||||
{
|
||||
fini_reloc_cookie_rels (cookie, sec);
|
||||
fini_reloc_cookie (cookie, sec->owner);
|
||||
}
|
||||
|
||||
static asection *
|
||||
_bfd_coff_gc_mark_hook (asection *sec,
|
||||
struct bfd_link_info *info ATTRIBUTE_UNUSED,
|
||||
struct internal_reloc *rel ATTRIBUTE_UNUSED,
|
||||
struct coff_link_hash_entry *h,
|
||||
struct internal_syment *sym)
|
||||
{
|
||||
if (h != NULL)
|
||||
{
|
||||
switch (h->root.type)
|
||||
{
|
||||
case bfd_link_hash_defined:
|
||||
case bfd_link_hash_defweak:
|
||||
return h->root.u.def.section;
|
||||
|
||||
case bfd_link_hash_common:
|
||||
return h->root.u.c.p->section;
|
||||
|
||||
case bfd_link_hash_undefined:
|
||||
case bfd_link_hash_undefweak:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return coff_section_from_bfd_index (sec->owner, sym->n_scnum);
|
||||
}
|
||||
|
||||
/* COOKIE->rel describes a relocation against section SEC, which is
|
||||
a section we've decided to keep. Return the section that contains
|
||||
the relocation symbol, or NULL if no section contains it. */
|
||||
|
||||
static asection *
|
||||
_bfd_coff_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
|
||||
coff_gc_mark_hook_fn gc_mark_hook,
|
||||
struct coff_reloc_cookie *cookie)
|
||||
{
|
||||
struct coff_link_hash_entry *h;
|
||||
|
||||
h = cookie->sym_hashes[cookie->rel->r_symndx];
|
||||
if (h != NULL)
|
||||
{
|
||||
while (h->root.type == bfd_link_hash_indirect
|
||||
|| h->root.type == bfd_link_hash_warning)
|
||||
h = (struct coff_link_hash_entry *) h->root.u.i.link;
|
||||
|
||||
return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL);
|
||||
}
|
||||
|
||||
return (*gc_mark_hook) (sec, info, cookie->rel, NULL,
|
||||
&(cookie->symbols
|
||||
+ obj_convert (sec->owner)[cookie->rel->r_symndx])->native->u.syment);
|
||||
}
|
||||
|
||||
static bfd_boolean _bfd_coff_gc_mark
|
||||
(struct bfd_link_info *, asection *, coff_gc_mark_hook_fn);
|
||||
|
||||
/* 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. */
|
||||
|
||||
static bfd_boolean
|
||||
_bfd_coff_gc_mark_reloc (struct bfd_link_info *info,
|
||||
asection *sec,
|
||||
coff_gc_mark_hook_fn gc_mark_hook,
|
||||
struct coff_reloc_cookie *cookie)
|
||||
{
|
||||
asection *rsec;
|
||||
|
||||
rsec = _bfd_coff_gc_mark_rsec (info, sec, gc_mark_hook, cookie);
|
||||
if (rsec && !rsec->gc_mark)
|
||||
{
|
||||
if (bfd_get_flavour (rsec->owner) != bfd_target_coff_flavour)
|
||||
rsec->gc_mark = 1;
|
||||
else if (!_bfd_coff_gc_mark (info, rsec, gc_mark_hook))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* The mark phase of garbage collection. For a given section, mark
|
||||
it and any sections in this section's group, and all the sections
|
||||
which define symbols to which it refers. */
|
||||
|
||||
static bfd_boolean
|
||||
_bfd_coff_gc_mark (struct bfd_link_info *info,
|
||||
asection *sec,
|
||||
coff_gc_mark_hook_fn gc_mark_hook)
|
||||
{
|
||||
bfd_boolean ret = TRUE;
|
||||
|
||||
sec->gc_mark = 1;
|
||||
|
||||
/* Look through the section relocs. */
|
||||
if ((sec->flags & SEC_RELOC) != 0
|
||||
&& sec->reloc_count > 0)
|
||||
{
|
||||
struct coff_reloc_cookie cookie;
|
||||
|
||||
if (!init_reloc_cookie_for_section (&cookie, info, sec))
|
||||
ret = FALSE;
|
||||
else
|
||||
{
|
||||
for (; cookie.rel < cookie.relend; cookie.rel++)
|
||||
{
|
||||
if (!_bfd_coff_gc_mark_reloc (info, sec, gc_mark_hook, &cookie))
|
||||
{
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fini_reloc_cookie_for_section (&cookie, sec);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
_bfd_coff_gc_mark_extra_sections (struct bfd_link_info *info,
|
||||
coff_gc_mark_hook_fn mark_hook ATTRIBUTE_UNUSED)
|
||||
{
|
||||
bfd *ibfd;
|
||||
|
||||
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
|
||||
{
|
||||
asection *isec;
|
||||
bfd_boolean some_kept;
|
||||
|
||||
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
|
||||
continue;
|
||||
|
||||
/* Ensure all linker created sections are kept, and see whether
|
||||
any other section is already marked. */
|
||||
some_kept = FALSE;
|
||||
for (isec = ibfd->sections; isec != NULL; isec = isec->next)
|
||||
{
|
||||
if ((isec->flags & SEC_LINKER_CREATED) != 0)
|
||||
isec->gc_mark = 1;
|
||||
else if (isec->gc_mark)
|
||||
some_kept = TRUE;
|
||||
}
|
||||
|
||||
/* If no section in this file will be kept, then we can
|
||||
toss out debug sections. */
|
||||
if (!some_kept)
|
||||
continue;
|
||||
|
||||
/* Keep debug and special sections like .comment when they are
|
||||
not part of a group, or when we have single-member groups. */
|
||||
for (isec = ibfd->sections; isec != NULL; isec = isec->next)
|
||||
if ((isec->flags & SEC_DEBUGGING) != 0
|
||||
|| (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
|
||||
isec->gc_mark = 1;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Sweep symbols in swept sections. Called via coff_link_hash_traverse. */
|
||||
|
||||
static bfd_boolean
|
||||
coff_gc_sweep_symbol (struct coff_link_hash_entry *h,
|
||||
void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (h->root.type == bfd_link_hash_warning)
|
||||
h = (struct coff_link_hash_entry *) h->root.u.i.link;
|
||||
|
||||
if ((h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
&& !h->root.u.def.section->gc_mark
|
||||
&& !(h->root.u.def.section->owner->flags & DYNAMIC))
|
||||
{
|
||||
/* Do our best to hide the symbol. */
|
||||
h->root.u.def.section = bfd_und_section_ptr;
|
||||
h->symbol_class = C_HIDDEN;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* The sweep phase of garbage collection. Remove all garbage sections. */
|
||||
|
||||
typedef bfd_boolean (*gc_sweep_hook_fn)
|
||||
(bfd *, struct bfd_link_info *, asection *, const struct internal_reloc *);
|
||||
|
||||
static bfd_boolean
|
||||
coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
|
||||
{
|
||||
bfd *sub;
|
||||
|
||||
for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
|
||||
{
|
||||
asection *o;
|
||||
|
||||
if (bfd_get_flavour (sub) != bfd_target_coff_flavour)
|
||||
continue;
|
||||
|
||||
for (o = sub->sections; o != NULL; o = o->next)
|
||||
{
|
||||
/* Keep debug and special sections. */
|
||||
if ((o->flags & (SEC_DEBUGGING | SEC_LINKER_CREATED)) != 0
|
||||
|| (o->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
|
||||
o->gc_mark = 1;
|
||||
else if (CONST_STRNEQ (o->name, ".idata")
|
||||
|| CONST_STRNEQ (o->name, ".pdata")
|
||||
|| CONST_STRNEQ (o->name, ".xdata")
|
||||
|| CONST_STRNEQ (o->name, ".rsrc"))
|
||||
o->gc_mark = 1;
|
||||
|
||||
if (o->gc_mark)
|
||||
continue;
|
||||
|
||||
/* Skip sweeping sections already excluded. */
|
||||
if (o->flags & SEC_EXCLUDE)
|
||||
continue;
|
||||
|
||||
/* Since this is early in the link process, it is simple
|
||||
to remove a section from the output. */
|
||||
o->flags |= SEC_EXCLUDE;
|
||||
|
||||
if (info->print_gc_sections && o->size != 0)
|
||||
_bfd_error_handler (_("Removing unused section '%s' in file '%B'"), sub, o->name);
|
||||
|
||||
#if 0
|
||||
/* But we also have to update some of the relocation
|
||||
info we collected before. */
|
||||
if (gc_sweep_hook
|
||||
&& (o->flags & SEC_RELOC) != 0
|
||||
&& o->reloc_count > 0
|
||||
&& !bfd_is_abs_section (o->output_section))
|
||||
{
|
||||
struct internal_reloc *internal_relocs;
|
||||
bfd_boolean r;
|
||||
|
||||
internal_relocs
|
||||
= _bfd_coff_link_read_relocs (o->owner, o, NULL, NULL,
|
||||
info->keep_memory);
|
||||
if (internal_relocs == NULL)
|
||||
return FALSE;
|
||||
|
||||
r = (*gc_sweep_hook) (o->owner, info, o, internal_relocs);
|
||||
|
||||
if (coff_section_data (o)->relocs != internal_relocs)
|
||||
free (internal_relocs);
|
||||
|
||||
if (!r)
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove the symbols that were in the swept sections from the dynamic
|
||||
symbol table. */
|
||||
coff_link_hash_traverse (coff_hash_table (info), coff_gc_sweep_symbol,
|
||||
NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Keep all sections containing symbols undefined on the command-line,
|
||||
and the section containing the entry symbol. */
|
||||
|
||||
static void
|
||||
_bfd_coff_gc_keep (struct bfd_link_info *info)
|
||||
{
|
||||
struct bfd_sym_chain *sym;
|
||||
|
||||
for (sym = info->gc_sym_list; sym != NULL; sym = sym->next)
|
||||
{
|
||||
struct coff_link_hash_entry *h;
|
||||
|
||||
h = coff_link_hash_lookup (coff_hash_table (info), sym->name,
|
||||
FALSE, FALSE, FALSE);
|
||||
|
||||
if (h != NULL
|
||||
&& (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
&& !bfd_is_abs_section (h->root.u.def.section))
|
||||
h->root.u.def.section->flags |= SEC_KEEP;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do mark and sweep of unused sections. */
|
||||
|
||||
bfd_boolean
|
||||
bfd_coff_gc_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
|
||||
{
|
||||
bfd *sub;
|
||||
|
||||
/* FIXME: Should we implement this? */
|
||||
#if 0
|
||||
const bfd_coff_backend_data *bed = coff_backend_info (abfd);
|
||||
|
||||
if (!bed->can_gc_sections
|
||||
|| !is_coff_hash_table (info->hash))
|
||||
{
|
||||
(*_bfd_error_handler)(_("Warning: gc-sections option ignored"));
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
_bfd_coff_gc_keep (info);
|
||||
|
||||
/* Grovel through relocs to find out who stays ... */
|
||||
for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
|
||||
{
|
||||
asection *o;
|
||||
|
||||
if (bfd_get_flavour (sub) != bfd_target_coff_flavour)
|
||||
continue;
|
||||
|
||||
for (o = sub->sections; o != NULL; o = o->next)
|
||||
{
|
||||
if (((o->flags & (SEC_EXCLUDE | SEC_KEEP)) == SEC_KEEP
|
||||
|| CONST_STRNEQ (o->name, ".vectors")
|
||||
|| CONST_STRNEQ (o->name, ".ctors")
|
||||
|| CONST_STRNEQ (o->name, ".dtors"))
|
||||
&& !o->gc_mark)
|
||||
{
|
||||
if (!_bfd_coff_gc_mark (info, o, _bfd_coff_gc_mark_hook))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Allow the backend to mark additional target specific sections. */
|
||||
_bfd_coff_gc_mark_extra_sections (info, _bfd_coff_gc_mark_hook);
|
||||
|
||||
/* ... and mark SEC_EXCLUDE for those that go. */
|
||||
return coff_gc_sweep (abfd, info);
|
||||
}
|
||||
|
@ -265,6 +265,16 @@ struct coff_link_hash_table
|
||||
struct stab_info stab_info;
|
||||
};
|
||||
|
||||
struct coff_reloc_cookie
|
||||
{
|
||||
struct internal_reloc * rels;
|
||||
struct internal_reloc * rel;
|
||||
struct internal_reloc * relend;
|
||||
struct coff_symbol_struct * symbols; /* Symtab for input bfd. */
|
||||
bfd * abfd;
|
||||
struct coff_link_hash_entry ** sym_hashes;
|
||||
};
|
||||
|
||||
/* Look up an entry in a COFF linker hash table. */
|
||||
|
||||
#define coff_link_hash_lookup(table, string, create, copy, follow) \
|
||||
@ -562,6 +572,8 @@ extern bfd_boolean _bfd_coff_link_input_bfd
|
||||
extern bfd_boolean _bfd_coff_reloc_link_order
|
||||
(bfd *, struct coff_final_link_info *, asection *,
|
||||
struct bfd_link_order *);
|
||||
extern bfd_boolean bfd_coff_gc_sections
|
||||
(bfd *, struct bfd_link_info *);
|
||||
|
||||
|
||||
#define coff_get_section_contents_in_window \
|
||||
|
@ -269,6 +269,16 @@ struct coff_link_hash_table
|
||||
struct stab_info stab_info;
|
||||
};
|
||||
|
||||
struct coff_reloc_cookie
|
||||
{
|
||||
struct internal_reloc * rels;
|
||||
struct internal_reloc * rel;
|
||||
struct internal_reloc * relend;
|
||||
struct coff_symbol_struct * symbols; /* Symtab for input bfd. */
|
||||
bfd * abfd;
|
||||
struct coff_link_hash_entry ** sym_hashes;
|
||||
};
|
||||
|
||||
/* Look up an entry in a COFF linker hash table. */
|
||||
|
||||
#define coff_link_hash_lookup(table, string, create, copy, follow) \
|
||||
@ -566,6 +576,8 @@ extern bfd_boolean _bfd_coff_link_input_bfd
|
||||
extern bfd_boolean _bfd_coff_reloc_link_order
|
||||
(bfd *, struct coff_final_link_info *, asection *,
|
||||
struct bfd_link_order *);
|
||||
extern bfd_boolean bfd_coff_gc_sections
|
||||
(bfd *, struct bfd_link_info *);
|
||||
|
||||
|
||||
#define coff_get_section_contents_in_window \
|
||||
@ -673,6 +685,10 @@ enum coff_symbol_classification
|
||||
COFF_SYMBOL_PE_SECTION
|
||||
};
|
||||
|
||||
typedef asection * (*coff_gc_mark_hook_fn)
|
||||
(asection *, struct bfd_link_info *, struct internal_reloc *,
|
||||
struct coff_link_hash_entry *, struct internal_syment *);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (*_bfd_coff_swap_aux_in)
|
||||
|
12
ld/ChangeLog
12
ld/ChangeLog
@ -1,3 +1,15 @@
|
||||
2015-07-03 Kai Tietz <ktietz@redhat.com>
|
||||
|
||||
PR ld/11539
|
||||
* scripttempl/pep.sc: Mark .idata*, .CRT*, .tls*,
|
||||
.rsrc*, .init, .ctor*, .dtor*, .fini, .jcr,
|
||||
.eh_frame, .pdata. .xdata, and .gcc_except_table sections
|
||||
as KEEP.
|
||||
* scripttempl/pe.sc: Likewise.
|
||||
* ld.texinfo: Document that --gc-sections has experimental support
|
||||
for COFF and PE targets.
|
||||
* NEWS: Mention experimental support.
|
||||
|
||||
2015-07-03 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* Makefile.am (eelf32or1k.c, eelf32or1k_linux.c): Depend on ELF_DEPS.
|
||||
|
3
ld/NEWS
3
ld/NEWS
@ -1,5 +1,8 @@
|
||||
-*- text -*-
|
||||
|
||||
* Experimental support for linker garbage collection (--gc-sections)
|
||||
has been enabled for COFF and PE based targets.
|
||||
|
||||
* New command line option for ELF targets to compress DWARF debug
|
||||
sections, --compress-debug-sections=[none|zlib|zlib-gnu|zlib-gabi].
|
||||
|
||||
|
@ -1436,7 +1436,9 @@ it ends in a @code{.exe} suffix.
|
||||
Enable garbage collection of unused input sections. It is ignored on
|
||||
targets that do not support this option. The default behaviour (of not
|
||||
performing this garbage collection) can be restored by specifying
|
||||
@samp{--no-gc-sections} on the command line.
|
||||
@samp{--no-gc-sections} on the command line. Note that garbage
|
||||
collection for COFF and PE format targets is supported, but the
|
||||
implementation is currently considered to be experimental.
|
||||
|
||||
@samp{--gc-sections} decides which input sections are used by
|
||||
examining symbols and relocations. The section containing the entry
|
||||
|
@ -30,29 +30,29 @@ if test "${RELOCATING}"; then
|
||||
*(SORT(.rdata$*))'
|
||||
fi
|
||||
R_IDATA234='
|
||||
SORT(*)(.idata$2)
|
||||
SORT(*)(.idata$3)
|
||||
KEEP (SORT(*)(.idata$2))
|
||||
KEEP (SORT(*)(.idata$3))
|
||||
/* These zeroes mark the end of the import list. */
|
||||
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
|
||||
SORT(*)(.idata$4)'
|
||||
R_IDATA5='SORT(*)(.idata$5)'
|
||||
KEEP (SORT(*)(.idata$4))'
|
||||
R_IDATA5='KEEP (SORT(*)(.idata$5))'
|
||||
R_IDATA67='
|
||||
SORT(*)(.idata$6)
|
||||
SORT(*)(.idata$7)'
|
||||
R_CRT_XC='*(SORT(.CRT$XC*)) /* C initialization */'
|
||||
R_CRT_XI='*(SORT(.CRT$XI*)) /* C++ initialization */'
|
||||
R_CRT_XL='*(SORT(.CRT$XL*)) /* TLS callbacks */'
|
||||
R_CRT_XP='*(SORT(.CRT$XP*)) /* Pre-termination */'
|
||||
R_CRT_XT='*(SORT(.CRT$XT*)) /* Termination */'
|
||||
KEEP (SORT(*)(.idata$6))
|
||||
KEEP (SORT(*)(.idata$7))'
|
||||
R_CRT_XC='KEEP (*(SORT(.CRT$XC*))) /* C initialization */'
|
||||
R_CRT_XI='KEEP (*(SORT(.CRT$XI*))) /* C++ initialization */'
|
||||
R_CRT_XL='KEEP (*(SORT(.CRT$XL*))) /* TLS callbacks */'
|
||||
R_CRT_XP='KEEP (*(SORT(.CRT$XP*))) /* Pre-termination */'
|
||||
R_CRT_XT='KEEP (*(SORT(.CRT$XT*))) /* Termination */'
|
||||
R_TLS='
|
||||
*(.tls$AAA)
|
||||
*(.tls)
|
||||
*(.tls$)
|
||||
*(SORT(.tls$*))
|
||||
*(.tls$ZZZ)'
|
||||
KEEP (*(.tls$AAA))
|
||||
KEEP (*(.tls))
|
||||
KEEP (*(.tls$))
|
||||
KEEP (*(SORT(.tls$*)))
|
||||
KEEP (*(.tls$ZZZ))'
|
||||
R_RSRC='
|
||||
*(.rsrc)
|
||||
*(.rsrc$*)'
|
||||
KEEP (*(.rsrc))
|
||||
KEEP (*(.rsrc$*))'
|
||||
else
|
||||
R_TEXT=
|
||||
R_DATA=
|
||||
@ -85,7 +85,7 @@ SECTIONS
|
||||
${RELOCATING+. = ALIGN(__section_alignment__);}
|
||||
.text ${RELOCATING+ __image_base__ + ( __section_alignment__ < ${TARGET_PAGE_SIZE} ? . : __section_alignment__ )} :
|
||||
{
|
||||
${RELOCATING+ *(.init)}
|
||||
${RELOCATING+ KEEP(*(.init))}
|
||||
*(.text)
|
||||
${R_TEXT}
|
||||
${RELOCATING+ *(.text.*)}
|
||||
@ -116,7 +116,7 @@ SECTIONS
|
||||
*(.data)
|
||||
*(.data2)
|
||||
${R_DATA}
|
||||
*(.jcr)
|
||||
KEEP(*(.jcr))
|
||||
${RELOCATING+__data_end__ = . ;}
|
||||
${RELOCATING+*(.data_cygwin_nocopy)}
|
||||
}
|
||||
@ -136,12 +136,12 @@ SECTIONS
|
||||
|
||||
.eh_frame ${RELOCATING+BLOCK(__section_alignment__)} :
|
||||
{
|
||||
*(.eh_frame*)
|
||||
KEEP(*(.eh_frame*))
|
||||
}
|
||||
|
||||
.pdata ${RELOCATING+BLOCK(__section_alignment__)} :
|
||||
{
|
||||
*(.pdata)
|
||||
KEEP(*(.pdata))
|
||||
}
|
||||
|
||||
.bss ${RELOCATING+BLOCK(__section_alignment__)} :
|
||||
|
@ -30,29 +30,29 @@ if test "${RELOCATING}"; then
|
||||
*(SORT(.rdata$*))'
|
||||
fi
|
||||
R_IDATA234='
|
||||
SORT(*)(.idata$2)
|
||||
SORT(*)(.idata$3)
|
||||
KEEP (SORT(*)(.idata$2))
|
||||
KEEP (SORT(*)(.idata$3))
|
||||
/* These zeroes mark the end of the import list. */
|
||||
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
|
||||
SORT(*)(.idata$4)'
|
||||
KEEP (SORT(*)(.idata$4))'
|
||||
R_IDATA5='SORT(*)(.idata$5)'
|
||||
R_IDATA67='
|
||||
SORT(*)(.idata$6)
|
||||
SORT(*)(.idata$7)'
|
||||
R_CRT_XC='*(SORT(.CRT$XC*)) /* C initialization */'
|
||||
R_CRT_XI='*(SORT(.CRT$XI*)) /* C++ initialization */'
|
||||
R_CRT_XL='*(SORT(.CRT$XL*)) /* TLS callbacks */'
|
||||
R_CRT_XP='*(SORT(.CRT$XP*)) /* Pre-termination */'
|
||||
R_CRT_XT='*(SORT(.CRT$XT*)) /* Termination */'
|
||||
KEEP (SORT(*)(.idata$6))
|
||||
KEEP (SORT(*)(.idata$7))'
|
||||
R_CRT_XC='KEEP (*(SORT(.CRT$XC*))) /* C initialization */'
|
||||
R_CRT_XI='KEEP (*(SORT(.CRT$XI*))) /* C++ initialization */'
|
||||
R_CRT_XL='KEEP (*(SORT(.CRT$XL*))) /* TLS callbacks */'
|
||||
R_CRT_XP='KEEP (*(SORT(.CRT$XP*))) /* Pre-termination */'
|
||||
R_CRT_XT='KEEP (*(SORT(.CRT$XT*))) /* Termination */'
|
||||
R_TLS='
|
||||
*(.tls$AAA)
|
||||
*(.tls)
|
||||
*(.tls$)
|
||||
*(SORT(.tls$*))
|
||||
*(.tls$ZZZ)'
|
||||
KEEP (*(.tls$AAA))
|
||||
KEEP (*(.tls))
|
||||
KEEP (*(.tls$))
|
||||
KEEP (*(SORT(.tls$*)))
|
||||
KEEP (*(.tls$ZZZ))'
|
||||
R_RSRC='
|
||||
*(.rsrc)
|
||||
*(.rsrc$*)'
|
||||
KEEP (*(.rsrc))
|
||||
KEEP (*(.rsrc$*))'
|
||||
else
|
||||
R_TEXT=
|
||||
R_DATA=
|
||||
@ -85,7 +85,7 @@ SECTIONS
|
||||
${RELOCATING+. = ALIGN(__section_alignment__);}
|
||||
.text ${RELOCATING+ __image_base__ + ( __section_alignment__ < ${TARGET_PAGE_SIZE} ? . : __section_alignment__ )} :
|
||||
{
|
||||
${RELOCATING+ *(.init)}
|
||||
${RELOCATING+ KEEP(*(.init))}
|
||||
*(.text)
|
||||
${R_TEXT}
|
||||
${RELOCATING+ *(.text.*)}
|
||||
@ -94,14 +94,22 @@ SECTIONS
|
||||
*(.glue_7)
|
||||
${CONSTRUCTING+. = ALIGN(8);}
|
||||
${CONSTRUCTING+ ___CTOR_LIST__ = .; __CTOR_LIST__ = . ;
|
||||
LONG (-1); LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*)); LONG (0); LONG (0); }
|
||||
LONG (-1); LONG (-1);
|
||||
KEEP (*(.ctors));
|
||||
KEEP (*(.ctor));
|
||||
KEEP (*(SORT(.ctors.*)));
|
||||
LONG (0); LONG (0); }
|
||||
${CONSTRUCTING+ ___DTOR_LIST__ = .; __DTOR_LIST__ = . ;
|
||||
LONG (-1); LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*)); LONG (0); LONG (0); }
|
||||
${RELOCATING+ *(.fini)}
|
||||
LONG (-1); LONG (-1);
|
||||
KEEP (*(.dtors));
|
||||
KEEP (*(.dtor));
|
||||
KEEP (*(SORT(.dtors.*)));
|
||||
LONG (0); LONG (0); }
|
||||
${RELOCATING+ KEEP (*(.fini))}
|
||||
/* ??? Why is .gcc_exc here? */
|
||||
${RELOCATING+ *(.gcc_exc)}
|
||||
${RELOCATING+PROVIDE (etext = .);}
|
||||
${RELOCATING+ *(.gcc_except_table)}
|
||||
${RELOCATING+ KEEP (*(.gcc_except_table))}
|
||||
}
|
||||
|
||||
/* The Cygwin32 library uses a section to avoid copying certain data
|
||||
@ -116,7 +124,7 @@ SECTIONS
|
||||
*(.data)
|
||||
*(.data2)
|
||||
${R_DATA}
|
||||
*(.jcr)
|
||||
KEEP(*(.jcr))
|
||||
${RELOCATING+__data_end__ = . ;}
|
||||
${RELOCATING+*(.data_cygwin_nocopy)}
|
||||
}
|
||||
@ -136,17 +144,17 @@ SECTIONS
|
||||
|
||||
.eh_frame ${RELOCATING+BLOCK(__section_alignment__)} :
|
||||
{
|
||||
*(.eh_frame*)
|
||||
KEEP (*(.eh_frame*))
|
||||
}
|
||||
|
||||
.pdata ${RELOCATING+BLOCK(__section_alignment__)} :
|
||||
{
|
||||
*(.pdata*)
|
||||
KEEP(*(.pdata*))
|
||||
}
|
||||
|
||||
.xdata ${RELOCATING+BLOCK(__section_alignment__)} :
|
||||
{
|
||||
*(.xdata*)
|
||||
KEEP(*(.xdata*))
|
||||
}
|
||||
|
||||
.bss ${RELOCATING+BLOCK(__section_alignment__)} :
|
||||
|
@ -1,3 +1,10 @@
|
||||
2015-07-03 Kai Tietz <ktietz@redhat.com>
|
||||
Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR ld/11539
|
||||
* lib/ld-lib.exp (check_gc_sections_available): Do not
|
||||
automatically fail for cygwin and mingw targets.
|
||||
|
||||
2015-07-01 Sandra Loosemore <sandra@codesourcery.com>
|
||||
Cesar Philippidis <cesar@codesourcery.com>
|
||||
|
||||
|
@ -1610,9 +1610,7 @@ proc check_gc_sections_available { } {
|
||||
|| [istarget i860-*-*]
|
||||
|| [istarget ia64-*-*]
|
||||
|| [istarget mep-*-*]
|
||||
|| [istarget mn10200-*-*]
|
||||
|| [istarget *-*-cygwin]
|
||||
|| [istarget *-*-mingw*] } {
|
||||
|| [istarget mn10200-*-*] } {
|
||||
set gc_sections_available_saved 0
|
||||
return 0
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user