aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog9
-rw-r--r--bfd/elf-bfd.h4
-rw-r--r--bfd/elf.c78
-rw-r--r--bfd/elflink.c18
-rw-r--r--ld/ChangeLog7
-rw-r--r--ld/emultempl/genelf.em10
-rw-r--r--ld/ldlang.c37
-rw-r--r--ld/testsuite/ChangeLog5
-rw-r--r--ld/testsuite/ld-elf/group.ld2
-rw-r--r--ld/testsuite/ld-elf/group10.d11
-rw-r--r--ld/testsuite/ld-elf/group10.s14
11 files changed, 159 insertions, 36 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 8e0e2dd..a09058a 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 6d4b8dd..74348d3 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -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
diff --git a/bfd/elf.c b/bfd/elf.c
index 85ece8b..20b82a7 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -6137,58 +6137,92 @@ _bfd_elf_copy_private_section_data (bfd *ibfd,
NULL);
}
-/* Copy private header information. */
+/* 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_copy_private_header_data (bfd *ibfd, bfd *obfd)
+_bfd_elf_fixup_group_sections (bfd *ibfd, asection *discarded)
{
asection *isec;
- if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return TRUE;
-
- /* Copy over private BFD data if it has not already been copied.
- This must be done here, rather than in the copy_private_bfd_data
- entry point, because the latter is called after the section
- contents have been set, which means that the program headers have
- already been worked out. */
- if (elf_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL)
- {
- if (! copy_private_bfd_data (ibfd, 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;
+ 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 != NULL
- && isec->output_section == NULL)
+ 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 == NULL
- && isec->output_section != NULL)
- isec->output_section->size -= 4;
+ 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)
+{
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+ || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return TRUE;
+
+ /* Copy over private BFD data if it has not already been copied.
+ This must be done here, rather than in the copy_private_bfd_data
+ entry point, because the latter is called after the section
+ contents have been set, which means that the program headers have
+ already been worked out. */
+ if (elf_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL)
+ {
+ if (! copy_private_bfd_data (ibfd, obfd))
+ return FALSE;
+ }
+
+ return _bfd_elf_fixup_group_sections (ibfd, NULL);
+}
+
/* Copy private symbol information. If this symbol is in a section
which we did not map into a BFD section, try to map the section
index correctly. We use special macro definitions for the mapped
diff --git a/bfd/elflink.c b/bfd/elflink.c
index a325c00..9fb347b 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -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
diff --git a/ld/ChangeLog b/ld/ChangeLog
index cc2b5e6..ce42f17 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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.
diff --git a/ld/emultempl/genelf.em b/ld/emultempl/genelf.em
index 1a6c539..62af4de 100644
--- a/ld/emultempl/genelf.em
+++ b/ld/emultempl/genelf.em
@@ -48,6 +48,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)
{
gld${EMULATION_NAME}_map_segments (FALSE);
@@ -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
diff --git a/ld/ldlang.c b/ld/ldlang.c
index fd75a5b..ce5a11c 100644
--- a/ld/ldlang.c
+++ b/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))
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 8e075ed..e170dfc 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -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.
diff --git a/ld/testsuite/ld-elf/group.ld b/ld/testsuite/ld-elf/group.ld
index 58d78da..123ab26 100644
--- a/ld/testsuite/ld-elf/group.ld
+++ b/ld/testsuite/ld-elf/group.ld
@@ -2,5 +2,5 @@ SECTIONS
{
. = 0x1000;
.text : { *(.text) *(.rodata.brlt) }
- /DISCARD/ : { *(.reginfo) }
+ /DISCARD/ : { *(.dropme) *(.reginfo) }
}
diff --git a/ld/testsuite/ld-elf/group10.d b/ld/testsuite/ld-elf/group10.d
new file mode 100644
index 0000000..d22a70a
--- /dev/null
+++ b/ld/testsuite/ld-elf/group10.d
@@ -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.*
diff --git a/ld/testsuite/ld-elf/group10.s b/ld/testsuite/ld-elf/group10.s
new file mode 100644
index 0000000..57704b4
--- /dev/null
+++ b/ld/testsuite/ld-elf/group10.s
@@ -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