* 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.
This commit is contained in:
Alan Modra 2004-05-25 06:33:51 +00:00
parent 81bb344354
commit 57ceae9483
12 changed files with 174 additions and 131 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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. */

View File

@ -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. */

View File

@ -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. */

View File

@ -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)

View File

@ -1,3 +1,16 @@
2004-05-25 Alan Modra <amodra@bigpond.net.au>
* 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.
2004-05-23 Andreas Schwab <schwab@suse.de>
* ld.texinfo (Options): Fix typo in last change.

View File

@ -67,7 +67,8 @@ static void
arm_elf_set_bfd_for_interworking (lang_statement_union_type *statement)
{
if (statement->header.type == lang_input_section_enum
&& !statement->input_section.ifile->just_syms_flag)
&& !statement->input_section.ifile->just_syms_flag
&& (statement->input_section.section->flags & SEC_EXCLUDE) == 0)
{
asection *i = statement->input_section.section;
asection *output_section = i->output_section;

View File

@ -239,6 +239,7 @@ build_section_lists (lang_statement_union_type *statement)
{
if (statement->header.type == lang_input_section_enum
&& !statement->input_section.ifile->just_syms_flag
&& (statement->input_section.section->flags & SEC_EXCLUDE) == 0
&& statement->input_section.section->output_section != NULL
&& statement->input_section.section->output_section->owner == output_bfd)
{

View File

@ -288,6 +288,7 @@ build_toc_list (lang_statement_union_type *statement)
{
if (statement->header.type == lang_input_section_enum
&& !statement->input_section.ifile->just_syms_flag
&& (statement->input_section.section->flags & SEC_EXCLUDE) == 0
&& statement->input_section.section->output_section == toc_section)
ppc64_elf_next_toc_section (&link_info, statement->input_section.section);
}
@ -298,6 +299,7 @@ build_section_lists (lang_statement_union_type *statement)
{
if (statement->header.type == lang_input_section_enum
&& !statement->input_section.ifile->just_syms_flag
&& (statement->input_section.section->flags & SEC_EXCLUDE) == 0
&& statement->input_section.section->output_section != NULL
&& statement->input_section.section->output_section->owner == output_bfd)
{

View File

@ -2472,54 +2472,59 @@ print_input_section (lang_input_section_type *in)
init_opb ();
if (size != 0)
{
print_space ();
int len;
bfd_vma addr;
print_space ();
minfo ("%s", i->name);
if (i->output_section != NULL)
len = 1 + strlen (i->name);
if (len >= SECTION_NAME_MAP_LENGTH - 1)
{
int len;
print_nl ();
len = 0;
}
while (len < SECTION_NAME_MAP_LENGTH)
{
print_space ();
++len;
}
len = 1 + strlen (i->name);
if (len >= SECTION_NAME_MAP_LENGTH - 1)
{
print_nl ();
len = 0;
}
while (len < SECTION_NAME_MAP_LENGTH)
if (i->output_section != NULL && (i->flags & SEC_EXCLUDE) == 0)
addr = i->output_section->vma + i->output_offset;
else
{
addr = print_dot;
size = 0;
}
minfo ("0x%V %W %B\n", addr, TO_ADDR (size), i->owner);
if (size != i->_raw_size)
{
len = SECTION_NAME_MAP_LENGTH + 3;
#ifdef BFD64
len += 16;
#else
len += 8;
#endif
while (len > 0)
{
print_space ();
++len;
--len;
}
minfo ("0x%V %W %B\n",
i->output_section->vma + i->output_offset, TO_ADDR (size),
i->owner);
if (i->_cooked_size != 0 && i->_cooked_size != i->_raw_size)
{
len = SECTION_NAME_MAP_LENGTH + 3;
#ifdef BFD64
len += 16;
#else
len += 8;
#endif
while (len > 0)
{
print_space ();
--len;
}
minfo (_("%W (size before relaxing)\n"), i->_raw_size);
}
minfo (_("%W (size before relaxing)\n"), i->_raw_size);
}
if (i->output_section != NULL && (i->flags & SEC_EXCLUDE) == 0)
{
if (command_line.reduce_memory_overheads)
bfd_link_hash_traverse (link_info.hash, print_one_symbol, i);
else
print_all_symbols (i);
print_dot = (i->output_section->vma + i->output_offset
+ TO_ADDR (size));
print_dot = addr + TO_ADDR (size);
}
}
}
@ -2892,7 +2897,7 @@ size_input_section (lang_statement_union_type **this_ptr,
lang_input_section_type *is = &((*this_ptr)->input_section);
asection *i = is->section;
if (!is->ifile->just_syms_flag)
if (!is->ifile->just_syms_flag && (i->flags & SEC_EXCLUDE) == 0)
{
unsigned int alignment_needed;
asection *o;
@ -3622,10 +3627,13 @@ lang_do_assignments_1
{
asection *in = s->input_section.section;
if (in->_cooked_size != 0)
dot += TO_ADDR (in->_cooked_size);
else
dot += TO_ADDR (in->_raw_size);
if ((in->flags & SEC_EXCLUDE) == 0)
{
if (in->_cooked_size != 0)
dot += TO_ADDR (in->_cooked_size);
else
dot += TO_ADDR (in->_raw_size);
}
}
break;
@ -4384,12 +4392,6 @@ lang_process (void)
if (command_line.gc_sections)
lang_gc_sections ();
/* If there were any SEC_MERGE sections, finish their merging, so that
section sizes can be computed. This has to be done after GC of sections,
so that GCed sections are not merged, but before assigning output
sections, since removing whole input sections is hard then. */
bfd_merge_sections (output_bfd, &link_info);
/* Size up the common data. */
lang_common ();
@ -4402,8 +4404,16 @@ lang_process (void)
if (! link_info.relocatable)
{
asection *found;
/* Merge SEC_MERGE sections. This has to be done after GC of
sections, so that GCed sections are not merged, but before
assigning dynamic symbols, since removing whole input sections
is hard then. */
bfd_merge_sections (output_bfd, &link_info);
/* Look for a text section and set the readonly attribute in it. */
asection *found = bfd_get_section_by_name (output_bfd, ".text");
found = bfd_get_section_by_name (output_bfd, ".text");
if (found != NULL)
{

View File

@ -220,7 +220,8 @@ build_link_order (lang_statement_union_type *statement)
case lang_input_section_enum:
/* Create a new link_order in the output section with this
attached */
if (!statement->input_section.ifile->just_syms_flag)
if (!statement->input_section.ifile->just_syms_flag
&& (statement->input_section.section->flags & SEC_EXCLUDE) == 0)
{
asection *i = statement->input_section.section;
asection *output_section = i->output_section;