diff options
author | Alan Modra <amodra@gmail.com> | 2004-05-25 06:33:51 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2004-05-25 06:33:51 +0000 |
commit | 57ceae9483c03910f7ee7ac66f3cb118c9d7d657 (patch) | |
tree | a5653edf9e28f48685a159531cb5d8dc82fedda5 /bfd | |
parent | 81bb3443544bff4a3cc386acc5d4f1a6339967da (diff) | |
download | binutils-57ceae9483c03910f7ee7ac66f3cb118c9d7d657.zip binutils-57ceae9483c03910f7ee7ac66f3cb118c9d7d657.tar.gz binutils-57ceae9483c03910f7ee7ac66f3cb118c9d7d657.tar.bz2 |
bfd/
* elflink.c (elf_link_add_object_symbols): Don't set up merge
section data here..
* elf.c (_bfd_elf_merge_sections): .. Do it here instead.
* merge.c: Formatting. Remove unnecessary casts. Expand
bfd_get_section_alignment macro.
(struct sec_merge_sec_info): Rename "first" to "first_str". Update
use throughout file.
(_bfd_add_merge_section): Rename from _bfd_merge_section. Update
comment. Abort on dynamic or non-SEC_MERGE input. Don't test
section name to determine sinfo group, instead test output section
and alignment.
(_bfd_merge_sections): Add struct bfd_link_info param. Call
_bfd_strip_section_from_output rather than just twiddling flags.
* libbfd-in.h (_bfd_add_merge_section): Rename, update comment.
(_bfd_merge_sections): Update prototype.
* libbfd.h: Regenerate.
ld/
* ldlang.c (lang_process): Call bfd_merge_sections later, and
only when not a relocatable link.
(print_input_section): Handle SEC_EXCLUDE sections.
(size_input_section): Don't update dot on SEC_EXCLUDE sections.
(lang_do_assignments_1): Likewise.
* ldwrite.c (build_link_order): Ignore SEC_EXCLUDE input sections.
* emultempl/armelf.em (arm_elf_set_bfd_for_interworking): Likewise.
* emultempl/hppaelf.em (build_section_lists): Likewise.
* emultempl/ppc64elf.em (build_toc_list): Likewise.
(build_section_lists): Likewise.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 19 | ||||
-rw-r--r-- | bfd/elf.c | 25 | ||||
-rw-r--r-- | bfd/elflink.c | 22 | ||||
-rw-r--r-- | bfd/libbfd-in.h | 6 | ||||
-rw-r--r-- | bfd/libbfd.h | 6 | ||||
-rw-r--r-- | bfd/merge.c | 105 |
6 files changed, 99 insertions, 84 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index dab90b4..93ae1f6 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,22 @@ +2004-05-25 Alan Modra <amodra@bigpond.net.au> + + * elflink.c (elf_link_add_object_symbols): Don't set up merge + section data here.. + * elf.c (_bfd_elf_merge_sections): .. Do it here instead. + * merge.c: Formatting. Remove unnecessary casts. Expand + bfd_get_section_alignment macro. + (struct sec_merge_sec_info): Rename "first" to "first_str". Update + use throughout file. + (_bfd_add_merge_section): Rename from _bfd_merge_section. Update + comment. Abort on dynamic or non-SEC_MERGE input. Don't test + section name to determine sinfo group, instead test output section + and alignment. + (_bfd_merge_sections): Add struct bfd_link_info param. Call + _bfd_strip_section_from_output rather than just twiddling flags. + * libbfd-in.h (_bfd_add_merge_section): Rename, update comment. + (_bfd_merge_sections): Update prototype. + * libbfd.h: Regenerate. + 2004-05-24 Mark Kettenis <kettenis@gnu.org> * netbsd-core.c: Correctly indent section that sets architecture @@ -901,10 +901,31 @@ merge_sections_remove_hook (bfd *abfd ATTRIBUTE_UNUSED, bfd_boolean _bfd_elf_merge_sections (bfd *abfd, struct bfd_link_info *info) { + bfd *ibfd; + asection *sec; + if (!is_elf_hash_table (info->hash)) return FALSE; - if (elf_hash_table (info)->merge_info) - _bfd_merge_sections (abfd, elf_hash_table (info)->merge_info, + + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + if ((ibfd->flags & DYNAMIC) == 0) + for (sec = ibfd->sections; sec != NULL; sec = sec->next) + if ((sec->flags & SEC_MERGE) != 0 + && !bfd_is_abs_section (sec->output_section)) + { + struct bfd_elf_section_data *secdata; + + secdata = elf_section_data (sec); + if (! _bfd_add_merge_section (abfd, + &elf_hash_table (info)->merge_info, + sec, &secdata->sec_info)) + return FALSE; + else if (secdata->sec_info) + sec->sec_info_type = ELF_INFO_TYPE_MERGE; + } + + if (elf_hash_table (info)->merge_info != NULL) + _bfd_merge_sections (abfd, info, elf_hash_table (info)->merge_info, merge_sections_remove_hook); return TRUE; } diff --git a/bfd/elflink.c b/bfd/elflink.c index 37540aa..436ff84 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -4127,28 +4127,6 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) } } - if (! info->relocatable - && ! dynamic - && is_elf_hash_table (hash_table)) - { - asection *s; - - for (s = abfd->sections; s != NULL; s = s->next) - if ((s->flags & SEC_MERGE) != 0 - && !bfd_is_abs_section (s->output_section)) - { - struct bfd_elf_section_data *secdata; - - secdata = elf_section_data (s); - if (! _bfd_merge_section (abfd, - & hash_table->merge_info, - s, &secdata->sec_info)) - goto error_return; - else if (secdata->sec_info) - s->sec_info_type = ELF_INFO_TYPE_MERGE; - } - } - if (is_elf_hash_table (hash_table)) { /* Add this bfd to the loaded list. */ diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h index 956727d..fd7f296 100644 --- a/bfd/libbfd-in.h +++ b/bfd/libbfd-in.h @@ -520,15 +520,15 @@ extern bfd_boolean _bfd_write_stab_strings extern bfd_vma _bfd_stab_section_offset (bfd *, void **, asection *, void **, bfd_vma); -/* Attempt to merge a SEC_MERGE section. */ +/* Register a SEC_MERGE section as a candidate for merging. */ -extern bfd_boolean _bfd_merge_section +extern bfd_boolean _bfd_add_merge_section (bfd *, void **, asection *, void **); /* Attempt to merge SEC_MERGE sections. */ extern bfd_boolean _bfd_merge_sections - (bfd *, void *, void (*) (bfd *, asection *)); + (bfd *, struct bfd_link_info *, void *, void (*) (bfd *, asection *)); /* Write out a merged section. */ diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 96776ca..30890bc 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -525,15 +525,15 @@ extern bfd_boolean _bfd_write_stab_strings extern bfd_vma _bfd_stab_section_offset (bfd *, void **, asection *, void **, bfd_vma); -/* Attempt to merge a SEC_MERGE section. */ +/* Register a SEC_MERGE section as a candidate for merging. */ -extern bfd_boolean _bfd_merge_section +extern bfd_boolean _bfd_add_merge_section (bfd *, void **, asection *, void **); /* Attempt to merge SEC_MERGE sections. */ extern bfd_boolean _bfd_merge_sections - (bfd *, void *, void (*) (bfd *, asection *)); + (bfd *, struct bfd_link_info *, void *, void (*) (bfd *, asection *)); /* Write out a merged section. */ diff --git a/bfd/merge.c b/bfd/merge.c index 3811523..6b367b5 100644 --- a/bfd/merge.c +++ b/bfd/merge.c @@ -90,7 +90,7 @@ struct sec_merge_sec_info /* A hash table used to hold section content. */ struct sec_merge_hash *htab; /* First string in this section. */ - struct sec_merge_hash_entry *first; + struct sec_merge_hash_entry *first_str; /* Original section content. */ unsigned char contents[1]; }; @@ -102,30 +102,28 @@ static struct bfd_hash_entry * sec_merge_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table, const char *string) { - struct sec_merge_hash_entry *ret = (struct sec_merge_hash_entry *) entry; - /* Allocate the structure if it has not already been allocated by a subclass. */ - if (ret == (struct sec_merge_hash_entry *) NULL) - ret = ((struct sec_merge_hash_entry *) - bfd_hash_allocate (table, sizeof (struct sec_merge_hash_entry))); - if (ret == (struct sec_merge_hash_entry *) NULL) + if (entry == NULL) + entry = bfd_hash_allocate (table, sizeof (struct sec_merge_hash_entry)); + if (entry == NULL) return NULL; /* Call the allocation method of the superclass. */ - ret = ((struct sec_merge_hash_entry *) - bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); + entry = bfd_hash_newfunc (entry, table, string); - if (ret) + if (entry != NULL) { /* Initialize the local fields. */ + struct sec_merge_hash_entry *ret = (struct sec_merge_hash_entry *) entry; + ret->u.suffix = NULL; ret->alignment = 0; ret->secinfo = NULL; ret->next = NULL; } - return (struct bfd_hash_entry *) ret; + return entry; } /* Look up an entry in a section merge hash table. */ @@ -192,7 +190,7 @@ sec_merge_hash_lookup (struct sec_merge_hash *table, const char *string, index = hash % table->table.size; for (hashp = (struct sec_merge_hash_entry *) table->table.table[index]; - hashp != (struct sec_merge_hash_entry *) NULL; + hashp != NULL; hashp = (struct sec_merge_hash_entry *) hashp->root.next) { if (hashp->root.hash == hash @@ -216,13 +214,12 @@ sec_merge_hash_lookup (struct sec_merge_hash *table, const char *string, } if (! create) - return (struct sec_merge_hash_entry *) NULL; + return NULL; - hashp = (struct sec_merge_hash_entry *) - sec_merge_hash_newfunc ((struct bfd_hash_entry *) NULL, - (struct bfd_hash_table *) table, string); - if (hashp == (struct sec_merge_hash_entry *) NULL) - return (struct sec_merge_hash_entry *) NULL; + hashp = ((struct sec_merge_hash_entry *) + sec_merge_hash_newfunc (NULL, &table->table, string)); + if (hashp == NULL) + return NULL; hashp->root.string = string; hashp->root.hash = hash; hashp->len = len; @@ -239,9 +236,8 @@ static struct sec_merge_hash * sec_merge_init (unsigned int entsize, bfd_boolean strings) { struct sec_merge_hash *table; - bfd_size_type amt = sizeof (struct sec_merge_hash); - table = (struct sec_merge_hash *) bfd_malloc (amt); + table = bfd_malloc (sizeof (struct sec_merge_hash)); if (table == NULL) return NULL; @@ -294,7 +290,7 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry) asection *sec = secinfo->sec; char *pad = ""; bfd_size_type off = 0; - int alignment_power = bfd_get_section_alignment (abfd, sec->output_section); + int alignment_power = sec->output_section->alignment_power; if (alignment_power) pad = bfd_zmalloc ((bfd_size_type) 1 << alignment_power); @@ -308,7 +304,7 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry) if (len) { len = entry->alignment - len; - if (bfd_bwrite (pad, (bfd_size_type) len, abfd) != len) + if (bfd_bwrite (pad, len, abfd) != len) break; off += len; } @@ -316,7 +312,7 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry) str = entry->root.string; len = entry->len; - if (bfd_bwrite (str, (bfd_size_type) len, abfd) != len) + if (bfd_bwrite (str, len, abfd) != len) break; off += len; @@ -328,20 +324,24 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry) return entry == NULL || entry->secinfo != secinfo; } -/* This function is called for each input file from the add_symbols - pass of the linker. */ +/* Register a SEC_MERGE section as a candidate for merging. + This function is called for all non-dynamic SEC_MERGE input sections. */ bfd_boolean -_bfd_merge_section (bfd *abfd, void **psinfo, asection *sec, void **psecinfo) +_bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec, + void **psecinfo) { struct sec_merge_info *sinfo; struct sec_merge_sec_info *secinfo; unsigned int align; bfd_size_type amt; + if ((abfd->flags & DYNAMIC) != 0 + || (sec->flags & SEC_MERGE) == 0) + abort (); + if (sec->_raw_size == 0 - || (sec->flags & SEC_EXCLUDE) - || (sec->flags & SEC_MERGE) == 0 + || (sec->flags & SEC_EXCLUDE) != 0 || sec->entsize == 0) return TRUE; @@ -351,12 +351,12 @@ _bfd_merge_section (bfd *abfd, void **psinfo, asection *sec, void **psecinfo) return TRUE; } - align = bfd_get_section_alignment (sec->owner, sec); - if ((sec->entsize < (unsigned int)(1 << align) + align = sec->alignment_power; + if ((sec->entsize < (unsigned) 1 << align && ((sec->entsize & (sec->entsize - 1)) || !(sec->flags & SEC_STRINGS))) - || (sec->entsize > (unsigned int)(1 << align) - && (sec->entsize & ((1 << align) - 1)))) + || (sec->entsize > (unsigned) 1 << align + && (sec->entsize & (((unsigned) 1 << align) - 1)))) { /* Sanity check. If string character size is smaller than alignment, then we require character size to be a power @@ -371,14 +371,14 @@ _bfd_merge_section (bfd *abfd, void **psinfo, asection *sec, void **psecinfo) if ((secinfo = sinfo->chain) && ! ((secinfo->sec->flags ^ sec->flags) & (SEC_MERGE | SEC_STRINGS)) && secinfo->sec->entsize == sec->entsize - && ! strcmp (secinfo->sec->name, sec->name)) + && secinfo->sec->alignment_power == sec->alignment_power + && secinfo->sec->output_section == sec->output_section) break; if (sinfo == NULL) { /* Initialize the information we need to keep track of. */ - amt = sizeof (struct sec_merge_info); - sinfo = (struct sec_merge_info *) bfd_alloc (abfd, amt); + sinfo = bfd_alloc (abfd, sizeof (struct sec_merge_info)); if (sinfo == NULL) goto error_return; sinfo->next = (struct sec_merge_info *) *psinfo; @@ -396,7 +396,7 @@ _bfd_merge_section (bfd *abfd, void **psinfo, asection *sec, void **psecinfo) if (*psecinfo == NULL) goto error_return; - secinfo = (struct sec_merge_sec_info *)*psecinfo; + secinfo = (struct sec_merge_sec_info *) *psecinfo; if (sinfo->chain) { secinfo->next = sinfo->chain->next; @@ -408,10 +408,10 @@ _bfd_merge_section (bfd *abfd, void **psinfo, asection *sec, void **psecinfo) secinfo->sec = sec; secinfo->psecinfo = psecinfo; secinfo->htab = sinfo->htab; - secinfo->first = NULL; + secinfo->first_str = NULL; if (! bfd_get_section_contents (sec->owner, sec, secinfo->contents, - (bfd_vma) 0, sec->_raw_size)) + 0, sec->_raw_size)) goto error_return; return TRUE; @@ -433,7 +433,7 @@ record_section (struct sec_merge_info *sinfo, bfd_vma mask, eltalign; unsigned int align, i; - align = bfd_get_section_alignment (sec->owner, sec); + align = sec->alignment_power; end = secinfo->contents + sec->_raw_size; nul = FALSE; mask = ((bfd_vma) 1 << align) - 1; @@ -580,7 +580,7 @@ merge_strings (struct sec_merge_info *sinfo) /* Now sort the strings */ amt = sinfo->htab->size * sizeof (struct sec_merge_hash_entry *); - array = (struct sec_merge_hash_entry **) bfd_malloc (amt); + array = bfd_malloc (amt); if (array == NULL) goto alloc_failure; @@ -643,9 +643,9 @@ alloc_failure: } if (e->alignment) { - if (e->secinfo->first == NULL) + if (e->secinfo->first_str == NULL) { - e->secinfo->first = e; + e->secinfo->first_str = e; size = 0; } size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1); @@ -676,8 +676,8 @@ alloc_failure: with _bfd_merge_section. */ bfd_boolean -_bfd_merge_sections (bfd *abfd ATTRIBUTE_UNUSED, void *xsinfo, - void (*remove_hook) (bfd *, asection *)) +_bfd_merge_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info, + void *xsinfo, void (*remove_hook) (bfd *, asection *)) { struct sec_merge_info *sinfo; @@ -722,11 +722,11 @@ _bfd_merge_sections (bfd *abfd ATTRIBUTE_UNUSED, void *xsinfo, secinfo = NULL; for (e = sinfo->htab->first; e; e = e->next) { - if (e->secinfo->first == NULL) + if (e->secinfo->first_str == NULL) { if (secinfo) secinfo->sec->_cooked_size = size; - e->secinfo->first = e; + e->secinfo->first_str = e; size = 0; } size = (size + e->alignment - 1) @@ -741,11 +741,8 @@ _bfd_merge_sections (bfd *abfd ATTRIBUTE_UNUSED, void *xsinfo, /* Finally remove all input sections which have not made it into the hash table at all. */ for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next) - if (secinfo->first == NULL) - { - secinfo->sec->_cooked_size = 0; - secinfo->sec->flags |= SEC_EXCLUDE; - } + if (secinfo->first_str == NULL) + _bfd_strip_section_from_output (info, secinfo->sec); } return TRUE; @@ -761,14 +758,14 @@ _bfd_write_merged_section (bfd *output_bfd, asection *sec, void *psecinfo) secinfo = (struct sec_merge_sec_info *) psecinfo; - if (!secinfo->first) + if (secinfo->first_str == NULL) return TRUE; pos = sec->output_section->filepos + sec->output_offset; if (bfd_seek (output_bfd, pos, SEEK_SET) != 0) return FALSE; - if (! sec_merge_emit (output_bfd, secinfo->first)) + if (! sec_merge_emit (output_bfd, secinfo->first_str)) return FALSE; return TRUE; @@ -797,7 +794,7 @@ _bfd_merged_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, asection **psec, (_("%s: access beyond end of merged section (%ld)"), bfd_get_filename (sec->owner), (long) offset); } - return (secinfo->first ? sec->_cooked_size : 0); + return (secinfo->first_str ? sec->_cooked_size : 0); } if (secinfo->htab->strings) |