bfd/
* elf.c (_bfd_elf_fixup_group_sections): New function, split out from.. (_bfd_elf_copy_private_header_data): ..here. * elflink.c (_bfd_elf_size_group_sections): New function. (bfd_elf_size_dynamic_sections): Call it. * elf-bfd.h (_bfd_elf_size_group_sections): Declare. (_bfd_elf_fixup_group_sections): Declare. ld/ * ldlang.c (unique_section_p): Add os param. Allow group sections to match /DISCARD/. Update all callers. * emultempl/genelf.em (gld${EMULATION_NAME}_before_allocation): New. (LDEMUL_BEFORE_ALLOCATION): Define. ld/testsuite/ * ld-elf/group.ld: Discard .dropme sections. * ld-elf/group10.d, * ld-elf/group10.s: New test.
This commit is contained in:
parent
220453ec97
commit
d0bf826b37
11 changed files with 167 additions and 44 deletions
|
@ -1,3 +1,12 @@
|
|||
2010-02-19 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf.c (_bfd_elf_fixup_group_sections): New function, split out from..
|
||||
(_bfd_elf_copy_private_header_data): ..here.
|
||||
* elflink.c (_bfd_elf_size_group_sections): New function.
|
||||
(bfd_elf_size_dynamic_sections): Call it.
|
||||
* elf-bfd.h (_bfd_elf_size_group_sections): Declare.
|
||||
(_bfd_elf_fixup_group_sections): Declare.
|
||||
|
||||
2010-02-18 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
|
||||
|
||||
* elf32-arm.c (elf32_arm_merge_eabi_attributes): Add support for
|
||||
|
|
|
@ -1773,6 +1773,10 @@ extern void _bfd_elf_link_just_syms
|
|||
(asection *, struct bfd_link_info *);
|
||||
extern void _bfd_elf_copy_link_hash_symbol_type
|
||||
(bfd *, struct bfd_link_hash_entry *, struct bfd_link_hash_entry *);
|
||||
extern bfd_boolean _bfd_elf_size_group_sections
|
||||
(struct bfd_link_info *);
|
||||
extern bfd_boolean _bfd_elf_fixup_group_sections
|
||||
(bfd *, asection *);
|
||||
extern bfd_boolean _bfd_elf_copy_private_header_data
|
||||
(bfd *, bfd *);
|
||||
extern bfd_boolean _bfd_elf_copy_private_symbol_data
|
||||
|
|
94
bfd/elf.c
94
bfd/elf.c
|
@ -6137,13 +6137,74 @@ _bfd_elf_copy_private_section_data (bfd *ibfd,
|
|||
NULL);
|
||||
}
|
||||
|
||||
/* Look at all the SHT_GROUP sections in IBFD, making any adjustments
|
||||
necessary if we are removing either the SHT_GROUP section or any of
|
||||
the group member sections. DISCARDED is the value that a section's
|
||||
output_section has if the section will be discarded, NULL when this
|
||||
function is called from objcopy, bfd_abs_section_ptr when called
|
||||
from the linker. */
|
||||
|
||||
bfd_boolean
|
||||
_bfd_elf_fixup_group_sections (bfd *ibfd, asection *discarded)
|
||||
{
|
||||
asection *isec;
|
||||
|
||||
for (isec = ibfd->sections; isec != NULL; isec = isec->next)
|
||||
if (elf_section_type (isec) == SHT_GROUP)
|
||||
{
|
||||
asection *first = elf_next_in_group (isec);
|
||||
asection *s = first;
|
||||
bfd_size_type removed = 0;
|
||||
|
||||
while (s != NULL)
|
||||
{
|
||||
/* If this member section is being output but the
|
||||
SHT_GROUP section is not, then clear the group info
|
||||
set up by _bfd_elf_copy_private_section_data. */
|
||||
if (s->output_section != discarded
|
||||
&& isec->output_section == discarded)
|
||||
{
|
||||
elf_section_flags (s->output_section) &= ~SHF_GROUP;
|
||||
elf_group_name (s->output_section) = NULL;
|
||||
}
|
||||
/* Conversely, if the member section is not being output
|
||||
but the SHT_GROUP section is, then adjust its size. */
|
||||
else if (s->output_section == discarded
|
||||
&& isec->output_section != discarded)
|
||||
removed += 4;
|
||||
s = elf_next_in_group (s);
|
||||
if (s == first)
|
||||
break;
|
||||
}
|
||||
if (removed != 0)
|
||||
{
|
||||
if (discarded != NULL)
|
||||
{
|
||||
/* If we've been called for ld -r, then we need to
|
||||
adjust the input section size. This function may
|
||||
be called multiple times, so save the original
|
||||
size. */
|
||||
if (isec->rawsize == 0)
|
||||
isec->rawsize = isec->size;
|
||||
isec->size = isec->rawsize - removed;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Adjust the output section size when called from
|
||||
objcopy. */
|
||||
isec->output_section->size -= removed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Copy private header information. */
|
||||
|
||||
bfd_boolean
|
||||
_bfd_elf_copy_private_header_data (bfd *ibfd, bfd *obfd)
|
||||
{
|
||||
asection *isec;
|
||||
|
||||
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|
||||
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
|
||||
return TRUE;
|
||||
|
@ -6159,34 +6220,7 @@ _bfd_elf_copy_private_header_data (bfd *ibfd, bfd *obfd)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
for (isec = ibfd->sections; isec != NULL; isec = isec->next)
|
||||
if (elf_section_type (isec) == SHT_GROUP)
|
||||
{
|
||||
asection *first = elf_next_in_group (isec);
|
||||
asection *s = first;
|
||||
while (s != NULL)
|
||||
{
|
||||
/* If this member section is being output but the
|
||||
SHT_GROUP section is not, then clear the group info
|
||||
set up by _bfd_elf_copy_private_section_data. */
|
||||
if (s->output_section != NULL
|
||||
&& isec->output_section == NULL)
|
||||
{
|
||||
elf_section_flags (s->output_section) &= ~SHF_GROUP;
|
||||
elf_group_name (s->output_section) = NULL;
|
||||
}
|
||||
/* Conversely, if the member section is not being output
|
||||
but the SHT_GROUP section is, then adjust its size. */
|
||||
else if (s->output_section == NULL
|
||||
&& isec->output_section != NULL)
|
||||
isec->output_section->size -= 4;
|
||||
s = elf_next_in_group (s);
|
||||
if (s == first)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return _bfd_elf_fixup_group_sections (ibfd, NULL);
|
||||
}
|
||||
|
||||
/* Copy private symbol information. If this symbol is in a section
|
||||
|
|
|
@ -5481,6 +5481,20 @@ compute_bucket_count (struct bfd_link_info *info,
|
|||
return best_size;
|
||||
}
|
||||
|
||||
/* Size any SHT_GROUP section for ld -r. */
|
||||
|
||||
bfd_boolean
|
||||
_bfd_elf_size_group_sections (struct bfd_link_info *info)
|
||||
{
|
||||
bfd *ibfd;
|
||||
|
||||
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
|
||||
if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour
|
||||
&& !_bfd_elf_fixup_group_sections (ibfd, bfd_abs_section_ptr))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Set up the sizes and contents of the ELF dynamic sections. This is
|
||||
called by the ELF linker emulation before_allocation routine. We
|
||||
must set the sizes of the sections before the linker sets the
|
||||
|
@ -5555,6 +5569,10 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
|
|||
elf_hash_table (info)->init_plt_refcount
|
||||
= elf_hash_table (info)->init_plt_offset;
|
||||
|
||||
if (info->relocatable
|
||||
&& !_bfd_elf_size_group_sections (info))
|
||||
return FALSE;
|
||||
|
||||
/* The backend may have to create some sections regardless of whether
|
||||
we're dynamic or not. */
|
||||
if (bed->elf_backend_always_size_sections
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2010-02-19 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* ldlang.c (unique_section_p): Add os param. Allow group
|
||||
sections to match /DISCARD/. Update all callers.
|
||||
* emultempl/genelf.em (gld${EMULATION_NAME}_before_allocation): New.
|
||||
(LDEMUL_BEFORE_ALLOCATION): Define.
|
||||
|
||||
2010-02-15 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* po/vi.po: Updated Vietnamese translation.
|
||||
|
|
|
@ -47,6 +47,15 @@ gld${EMULATION_NAME}_after_open (void)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gld${EMULATION_NAME}_before_allocation (void)
|
||||
{
|
||||
if (link_info.relocatable
|
||||
&& !_bfd_elf_size_group_sections (&link_info))
|
||||
einfo ("%X%P: can not size group sections: %E\n");
|
||||
before_allocation_default ();
|
||||
}
|
||||
|
||||
static void
|
||||
gld${EMULATION_NAME}_after_allocation (void)
|
||||
{
|
||||
|
@ -56,4 +65,5 @@ EOF
|
|||
# Put these extra routines in ld_${EMULATION_NAME}_emulation
|
||||
#
|
||||
LDEMUL_AFTER_OPEN=gld${EMULATION_NAME}_after_open
|
||||
LDEMUL_BEFORE_ALLOCATION=gld${EMULATION_NAME}_before_allocation
|
||||
LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
|
||||
|
|
37
ld/ldlang.c
37
ld/ldlang.c
|
@ -195,7 +195,8 @@ input_statement_is_archive_path (const char *file_spec, char *sep,
|
|||
}
|
||||
|
||||
static bfd_boolean
|
||||
unique_section_p (const asection *sec)
|
||||
unique_section_p (const asection *sec,
|
||||
const lang_output_section_statement_type *os)
|
||||
{
|
||||
struct unique_sections *unam;
|
||||
const char *secnam;
|
||||
|
@ -203,7 +204,8 @@ unique_section_p (const asection *sec)
|
|||
if (link_info.relocatable
|
||||
&& sec->owner != NULL
|
||||
&& bfd_is_group_section (sec->owner, sec))
|
||||
return TRUE;
|
||||
return !(os != NULL
|
||||
&& strcmp (os->name, DISCARD_SECTION_NAME) == 0);
|
||||
|
||||
secnam = sec->name;
|
||||
for (unam = unique_section_list; unam; unam = unam->next)
|
||||
|
@ -445,12 +447,15 @@ output_section_callback_fast (lang_wild_statement_type *ptr,
|
|||
struct wildcard_list *sec,
|
||||
asection *section,
|
||||
lang_input_statement_type *file,
|
||||
void *output ATTRIBUTE_UNUSED)
|
||||
void *output)
|
||||
{
|
||||
lang_section_bst_type *node;
|
||||
lang_section_bst_type **tree;
|
||||
lang_output_section_statement_type *os;
|
||||
|
||||
if (unique_section_p (section))
|
||||
os = (lang_output_section_statement_type *) output;
|
||||
|
||||
if (unique_section_p (section, os))
|
||||
return;
|
||||
|
||||
node = (lang_section_bst_type *) xmalloc (sizeof (lang_section_bst_type));
|
||||
|
@ -2415,9 +2420,12 @@ output_section_callback (lang_wild_statement_type *ptr,
|
|||
void *output)
|
||||
{
|
||||
lang_statement_union_type *before;
|
||||
lang_output_section_statement_type *os;
|
||||
|
||||
os = (lang_output_section_statement_type *) output;
|
||||
|
||||
/* Exclude sections that match UNIQUE_SECTION_LIST. */
|
||||
if (unique_section_p (section))
|
||||
if (unique_section_p (section, os))
|
||||
return;
|
||||
|
||||
before = wild_sort (ptr, sec, file, section);
|
||||
|
@ -2428,16 +2436,14 @@ output_section_callback (lang_wild_statement_type *ptr,
|
|||
of the current list. */
|
||||
|
||||
if (before == NULL)
|
||||
lang_add_section (&ptr->children, section,
|
||||
(lang_output_section_statement_type *) output);
|
||||
lang_add_section (&ptr->children, section, os);
|
||||
else
|
||||
{
|
||||
lang_statement_list_type list;
|
||||
lang_statement_union_type **pp;
|
||||
|
||||
lang_list_init (&list);
|
||||
lang_add_section (&list, section,
|
||||
(lang_output_section_statement_type *) output);
|
||||
lang_add_section (&list, section, os);
|
||||
|
||||
/* If we are discarding the section, LIST.HEAD will
|
||||
be NULL. */
|
||||
|
@ -2464,14 +2470,18 @@ check_section_callback (lang_wild_statement_type *ptr ATTRIBUTE_UNUSED,
|
|||
struct wildcard_list *sec ATTRIBUTE_UNUSED,
|
||||
asection *section,
|
||||
lang_input_statement_type *file ATTRIBUTE_UNUSED,
|
||||
void *data)
|
||||
void *output)
|
||||
{
|
||||
lang_output_section_statement_type *os;
|
||||
|
||||
os = (lang_output_section_statement_type *) output;
|
||||
|
||||
/* Exclude sections that match UNIQUE_SECTION_LIST. */
|
||||
if (unique_section_p (section))
|
||||
if (unique_section_p (section, os))
|
||||
return;
|
||||
|
||||
if (section->output_section == NULL && (section->flags & SEC_READONLY) == 0)
|
||||
((lang_output_section_statement_type *) data)->all_input_readonly = FALSE;
|
||||
os->all_input_readonly = FALSE;
|
||||
}
|
||||
|
||||
/* This is passed a file name which must have been seen already and
|
||||
|
@ -5848,7 +5858,8 @@ lang_place_orphans (void)
|
|||
const char *name = s->name;
|
||||
int constraint = 0;
|
||||
|
||||
if (config.unique_orphan_sections || unique_section_p (s))
|
||||
if (config.unique_orphan_sections
|
||||
|| unique_section_p (s, NULL))
|
||||
constraint = SPECIAL;
|
||||
|
||||
if (!ldemul_place_orphan (s, name, constraint))
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2010-02-19 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* ld-elf/group.ld: Discard .dropme sections.
|
||||
* ld-elf/group10.d, * ld-elf/group10.s: New test.
|
||||
|
||||
2010-02-18 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
|
||||
|
||||
* ld-arm/attr-merge-6.attr: Add new test. Missed off last commit.
|
||||
|
|
|
@ -2,5 +2,5 @@ SECTIONS
|
|||
{
|
||||
. = 0x1000;
|
||||
.text : { *(.text) *(.rodata.brlt) }
|
||||
/DISCARD/ : { *(.reginfo) }
|
||||
/DISCARD/ : { *(.dropme) *(.reginfo) }
|
||||
}
|
||||
|
|
11
ld/testsuite/ld-elf/group10.d
Normal file
11
ld/testsuite/ld-elf/group10.d
Normal file
|
@ -0,0 +1,11 @@
|
|||
#source: group10.s
|
||||
#ld: -r -T group.ld
|
||||
#readelf: -Sg --wide
|
||||
|
||||
#...
|
||||
group section \[[ 0-9]+\] `foo_group' \[foo_group\] contains 4 sections:
|
||||
\[Index\] Name
|
||||
\[[ 0-9]+\] \.text.*
|
||||
\[[ 0-9]+\] \.rodata\.str.*
|
||||
\[[ 0-9]+\] \.data.*
|
||||
\[[ 0-9]+\] \.keepme.*
|
14
ld/testsuite/ld-elf/group10.s
Normal file
14
ld/testsuite/ld-elf/group10.s
Normal file
|
@ -0,0 +1,14 @@
|
|||
.section .text.foo,"axG",%progbits,foo_group
|
||||
.word 0
|
||||
|
||||
.section .rodata.str.1,"aMSG",%progbits,1,foo_group
|
||||
.asciz "abc"
|
||||
|
||||
.section .data.foo,"waG",%progbits,foo_group
|
||||
.word 1
|
||||
|
||||
.section .dropme,"G",%progbits,foo_group
|
||||
.word 2
|
||||
|
||||
.section .keepme,"G",%progbits,foo_group
|
||||
.word 3
|
Loading…
Reference in a new issue