+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
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;
}
}
}
- 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. */
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. */
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. */
/* 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];
};
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. */
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
}
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;
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;
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);
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;
}
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;
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;
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
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;
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;
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;
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;
/* 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;
}
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);
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;
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)
/* 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;
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;
(_("%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)
+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.
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;
{
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)
{
{
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);
}
{
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)
{
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)
+ {
+ print_nl ();
+ len = 0;
+ }
+ while (len < SECTION_NAME_MAP_LENGTH)
{
- int len;
+ 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)
- {
- print_space ();
- ++len;
- }
+ 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",
- i->output_section->vma + i->output_offset, TO_ADDR (size),
- i->owner);
+ minfo ("0x%V %W %B\n", addr, TO_ADDR (size), i->owner);
- if (i->_cooked_size != 0 && i->_cooked_size != i->_raw_size)
- {
- len = SECTION_NAME_MAP_LENGTH + 3;
+ if (size != i->_raw_size)
+ {
+ len = SECTION_NAME_MAP_LENGTH + 3;
#ifdef BFD64
- len += 16;
+ len += 16;
#else
- len += 8;
+ len += 8;
#endif
- while (len > 0)
- {
- print_space ();
- --len;
- }
-
- minfo (_("%W (size before relaxing)\n"), i->_raw_size);
+ while (len > 0)
+ {
+ print_space ();
+ --len;
}
+ 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);
}
}
}
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;
{
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;
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 ();
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)
{
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;