* merge.c (struct sec_merge_hash_entry): Add u.entsize and u.suffix

fields, change sec into secinfo.
	(struct sec_merge_info): Add chain, remove last fields.
	(struct sec_merge_sec_info): Add next, sec, psecinfo fields.
	(sec_merge_hash_lookup): If lookup could not use a string only
	because it has bad alignment, mark the old string for deletion.
	(sec_merge_add): Add secinfo argument. Don't compute entry's
	position, instead record the section.
	(sec_merge_emit): Update for the sec into secinfo change in
	struct sec_merge_hash_entry.
	(_bfd_merge_section): Only record the section for merging, defer
	putting strings into the hash table.
	(cmplengthentry, last4_eq, last_eq, record_section, merge_strings,
	_bfd_merge_sections): New functions.
	(_bfd_merged_section_offset): Update for the sec_merge_hash_entry
	changes.
	* libbfd-in.h (_bfd_merge_sections): Add prototype.
	(_bfd_nolink_bfd_merge_sections): Define.
	* libbfd.h: Likewise.
	(bfd_generic_merge_sections): Add prototype.
	* targets.c (BFD_JUMP_TABLE_LINK): Add _bfd_merge_sections.
	(struct bfd_target): Likewise.
	* bfd.c (bfd_merge_sections): Define.
	* bfd-in2.h: Rebuilt.
	* elf.c (_bfd_elf_merge_sections): New function.
	* elf-bfd.h (_bfd_elf_merge_sections): Add prototype.
	* elfxx-target.h (bfd_elfNN_bfd_merge_sections): Define.
	* reloc.c (bfd_generic_merge_sections): New function.
	* vms.c (vms_bfd_merge_sections): New function.
	* aout-adobe.c (aout_32_bfd_merge_sections): Define.
	* aout-target.h (MY_bfd_merge_sections): Define.
	* aout-tic30.c (MY_bfd_merge_sections): Define.
	* binary.c (binary_bfd_merge_sections): Define.
	* bout.c (b_out_bfd_merge_sections): Define.
	* coff-alpha.c (_bfd_ecoff_bfd_merge_sections): Define.
	* coffcode.c (coff_bfd_merge_sections): Define.
	* coff-mips.c (_bfd_ecoff_bfd_merge_sections): Define.
	* i386msdos.c (msdos_bfd_merge_sections): Define.
	* i386os9k.c (os9k_bfd_merge_sections): Define.
	* ieee.c (ieee_bfd_merge_sections): Define.
	* ihex.c (ihex_bfd_merge_sections): Define.
	* nlm-target.h (nlm_bfd_merge_sections): Define.
	* oasys.c (oasys_bfd_merge_sections): Define.
	* ppcboot.c (ppcboot_bfd_merge_sections): Define.
	* som.c (som_bfd_merge_sections): Define.
	* srec.c (srec_bfd_merge_sections): Define.
	* tekhex.c (tekhex_bfd_merge_sections): Define.
	* versados.c (versados_bfd_merge_sections): Define.
	* xcoff-target.h (_bfd_xcoff_bfd_merge_sections): Define.

	* ldlang.c (lang_process): Call bfd_merge_sections.
This commit is contained in:
Jakub Jelinek 2001-05-11 12:23:48 +00:00
parent 15f65ae412
commit 8550eb6e64
34 changed files with 576 additions and 78 deletions

View File

@ -1,3 +1,55 @@
2001-05-11 Jakub Jelinek <jakub@redhat.com>
* merge.c (struct sec_merge_hash_entry): Add u.entsize and u.suffix
fields, change sec into secinfo.
(struct sec_merge_info): Add chain, remove last fields.
(struct sec_merge_sec_info): Add next, sec, psecinfo fields.
(sec_merge_hash_lookup): If lookup could not use a string only
because it has bad alignment, mark the old string for deletion.
(sec_merge_add): Add secinfo argument. Don't compute entry's
position, instead record the section.
(sec_merge_emit): Update for the sec into secinfo change in
struct sec_merge_hash_entry.
(_bfd_merge_section): Only record the section for merging, defer
putting strings into the hash table.
(cmplengthentry, last4_eq, last_eq, record_section, merge_strings,
_bfd_merge_sections): New functions.
(_bfd_merged_section_offset): Update for the sec_merge_hash_entry
changes.
* libbfd-in.h (_bfd_merge_sections): Add prototype.
(_bfd_nolink_bfd_merge_sections): Define.
* libbfd.h: Likewise.
(bfd_generic_merge_sections): Add prototype.
* targets.c (BFD_JUMP_TABLE_LINK): Add _bfd_merge_sections.
(struct bfd_target): Likewise.
* bfd.c (bfd_merge_sections): Define.
* bfd-in2.h: Rebuilt.
* elf.c (_bfd_elf_merge_sections): New function.
* elf-bfd.h (_bfd_elf_merge_sections): Add prototype.
* elfxx-target.h (bfd_elfNN_bfd_merge_sections): Define.
* reloc.c (bfd_generic_merge_sections): New function.
* vms.c (vms_bfd_merge_sections): New function.
* aout-adobe.c (aout_32_bfd_merge_sections): Define.
* aout-target.h (MY_bfd_merge_sections): Define.
* aout-tic30.c (MY_bfd_merge_sections): Define.
* binary.c (binary_bfd_merge_sections): Define.
* bout.c (b_out_bfd_merge_sections): Define.
* coff-alpha.c (_bfd_ecoff_bfd_merge_sections): Define.
* coffcode.c (coff_bfd_merge_sections): Define.
* coff-mips.c (_bfd_ecoff_bfd_merge_sections): Define.
* i386msdos.c (msdos_bfd_merge_sections): Define.
* i386os9k.c (os9k_bfd_merge_sections): Define.
* ieee.c (ieee_bfd_merge_sections): Define.
* ihex.c (ihex_bfd_merge_sections): Define.
* nlm-target.h (nlm_bfd_merge_sections): Define.
* oasys.c (oasys_bfd_merge_sections): Define.
* ppcboot.c (ppcboot_bfd_merge_sections): Define.
* som.c (som_bfd_merge_sections): Define.
* srec.c (srec_bfd_merge_sections): Define.
* tekhex.c (tekhex_bfd_merge_sections): Define.
* versados.c (versados_bfd_merge_sections): Define.
* xcoff-target.h (_bfd_xcoff_bfd_merge_sections): Define.
2001-05-11 Nick Clifton <nickc@cambridge.redhat.com>
* dwarf1.c (_bfd_dwarf1_find_nearest_line): Change type of 'addr'

View File

@ -513,6 +513,7 @@ aout_adobe_sizeof_headers (ignore_abfd, ignore)
#define aout_32_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
#define aout_32_bfd_relax_section bfd_generic_relax_section
#define aout_32_bfd_gc_sections bfd_generic_gc_sections
#define aout_32_bfd_merge_sections bfd_generic_merge_sections
#define aout_32_bfd_link_hash_table_create \
_bfd_generic_link_hash_table_create
#define aout_32_bfd_link_add_symbols _bfd_generic_link_add_symbols

View File

@ -507,6 +507,9 @@ MY_bfd_final_link (abfd, info)
#ifndef MY_bfd_gc_sections
#define MY_bfd_gc_sections bfd_generic_gc_sections
#endif
#ifndef MY_bfd_merge_sections
#define MY_bfd_merge_sections bfd_generic_merge_sections
#endif
#ifndef MY_bfd_reloc_type_lookup
#define MY_bfd_reloc_type_lookup NAME(aout,reloc_type_lookup)
#endif

View File

@ -940,6 +940,9 @@ tic30_aout_set_arch_mach (abfd, arch, machine)
#ifndef MY_bfd_gc_sections
#define MY_bfd_gc_sections bfd_generic_gc_sections
#endif
#ifndef MY_bfd_merge_sections
#define MY_bfd_merge_sections bfd_generic_merge_sections
#endif
#ifndef MY_bfd_reloc_type_lookup
#define MY_bfd_reloc_type_lookup tic30_aout_reloc_type_lookup
#endif

View File

@ -3229,6 +3229,9 @@ bfd_set_private_flags PARAMS ((bfd *abfd, flagword flags));
#define bfd_gc_sections(abfd, link_info) \
BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info))
#define bfd_merge_sections(abfd, link_info) \
BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info))
#define bfd_link_hash_table_create(abfd) \
BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
@ -3525,7 +3528,8 @@ CAT(NAME,_bfd_link_hash_table_create),\
CAT(NAME,_bfd_link_add_symbols),\
CAT(NAME,_bfd_final_link),\
CAT(NAME,_bfd_link_split_section),\
CAT(NAME,_bfd_gc_sections)
CAT(NAME,_bfd_gc_sections),\
CAT(NAME,_bfd_merge_sections)
int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean));
bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *,
struct bfd_link_info *, struct bfd_link_order *,
@ -3552,6 +3556,9 @@ CAT(NAME,_bfd_gc_sections)
/* Remove sections that are not referenced from the output. */
boolean (*_bfd_gc_sections) PARAMS ((bfd *, struct bfd_link_info *));
/* Attempt to merge SEC_MERGE sections. */
boolean (*_bfd_merge_sections) PARAMS ((bfd *, struct bfd_link_info *));
/* Routines to handle dynamic symbols and relocs. */
#define BFD_JUMP_TABLE_DYNAMIC(NAME)\
CAT(NAME,_get_dynamic_symtab_upper_bound),\

View File

@ -1126,6 +1126,9 @@ DESCRIPTION
.#define bfd_gc_sections(abfd, link_info) \
. BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info))
.
.#define bfd_merge_sections(abfd, link_info) \
. BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info))
.
.#define bfd_link_hash_table_create(abfd) \
. BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
.

View File

@ -345,6 +345,7 @@ binary_sizeof_headers (abfd, exec)
bfd_generic_get_relocated_section_contents
#define binary_bfd_relax_section bfd_generic_relax_section
#define binary_bfd_gc_sections bfd_generic_gc_sections
#define binary_bfd_merge_sections bfd_generic_merge_sections
#define binary_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define binary_bfd_link_add_symbols _bfd_generic_link_add_symbols
#define binary_bfd_final_link _bfd_generic_final_link

View File

@ -1436,6 +1436,7 @@ b_out_bfd_get_relocated_section_contents (output_bfd, link_info, link_order,
#define b_out_bfd_final_link _bfd_generic_final_link
#define b_out_bfd_link_split_section _bfd_generic_link_split_section
#define b_out_bfd_gc_sections bfd_generic_gc_sections
#define b_out_bfd_merge_sections bfd_generic_merge_sections
#define aout_32_get_section_contents_in_window \
_bfd_generic_get_section_contents_in_window

View File

@ -2359,6 +2359,7 @@ static const struct ecoff_backend_data alpha_ecoff_backend_data =
/* Relaxing sections is generic. */
#define _bfd_ecoff_bfd_relax_section bfd_generic_relax_section
#define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections
#define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections
const bfd_target ecoffalpha_little_vec =
{

View File

@ -2600,6 +2600,9 @@ static const struct ecoff_backend_data mips_ecoff_backend_data =
/* GC of sections is not done. */
#define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections
/* Merging of sections is not done. */
#define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections
extern const bfd_target ecoff_big_vec;
const bfd_target ecoff_little_vec =

View File

@ -5258,6 +5258,10 @@ static const bfd_coff_backend_data bfd_coff_std_swap_table =
#define coff_bfd_gc_sections bfd_generic_gc_sections
#endif
#ifndef coff_bfd_merge_sections
#define coff_bfd_merge_sections bfd_generic_merge_sections
#endif
#define CREATE_BIG_COFF_TARGET_VEC(VAR, NAME, EXTRA_O_FLAGS, EXTRA_S_FLAGS, UNDER, ALTERNATIVE) \
const bfd_target VAR = \
{ \

View File

@ -1006,6 +1006,9 @@ extern boolean _bfd_elf_link_hash_table_init
const char *)));
extern boolean _bfd_elf_slurp_version_tables PARAMS ((bfd *));
extern boolean _bfd_elf_merge_sections
PARAMS ((bfd *, struct bfd_link_info *));
extern boolean _bfd_elf_copy_private_symbol_data
PARAMS ((bfd *, asymbol *, bfd *, asymbol *));
extern boolean _bfd_elf_copy_private_section_data

View File

@ -558,6 +558,18 @@ bfd_elf_generic_reloc (abfd,
return bfd_reloc_continue;
}
/* Finish SHF_MERGE section merging. */
boolean
_bfd_elf_merge_sections (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
{
if (elf_hash_table (info)->merge_info)
_bfd_merge_sections (abfd, elf_hash_table (info)->merge_info);
return true;
}
/* Print out the program headers. */
boolean

View File

@ -111,6 +111,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define bfd_elfNN_bfd_gc_sections _bfd_elfNN_gc_sections
#endif
#ifndef bfd_elfNN_bfd_merge_sections
#define bfd_elfNN_bfd_merge_sections \
_bfd_elf_merge_sections
#endif
#define bfd_elfNN_bfd_make_debug_symbol \
((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)

View File

@ -170,6 +170,7 @@ msdos_set_section_contents (abfd, section, location, offset, count)
bfd_generic_get_relocated_section_contents
#define msdos_bfd_relax_section bfd_generic_relax_section
#define msdos_bfd_gc_sections bfd_generic_gc_sections
#define msdos_bfd_merge_sections bfd_generic_merge_sections
#define msdos_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define msdos_bfd_link_add_symbols _bfd_generic_link_add_symbols
#define msdos_bfd_final_link _bfd_generic_final_link

View File

@ -328,6 +328,7 @@ os9k_sizeof_headers (ignore_abfd, ignore)
bfd_generic_get_relocated_section_contents
#define os9k_bfd_relax_section bfd_generic_relax_section
#define os9k_bfd_gc_sections bfd_generic_gc_sections
#define os9k_bfd_merge_sections bfd_generic_merge_sections
#define os9k_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define os9k_bfd_link_add_symbols _bfd_generic_link_add_symbols
#define os9k_bfd_final_link _bfd_generic_final_link

View File

@ -3926,6 +3926,7 @@ ieee_bfd_debug_info_accumulate (abfd, section)
bfd_generic_get_relocated_section_contents
#define ieee_bfd_relax_section bfd_generic_relax_section
#define ieee_bfd_gc_sections bfd_generic_gc_sections
#define ieee_bfd_merge_sections bfd_generic_merge_sections
#define ieee_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define ieee_bfd_link_add_symbols _bfd_generic_link_add_symbols
#define ieee_bfd_final_link _bfd_generic_final_link

View File

@ -983,6 +983,7 @@ ihex_sizeof_headers (abfd, exec)
bfd_generic_get_relocated_section_contents
#define ihex_bfd_relax_section bfd_generic_relax_section
#define ihex_bfd_gc_sections bfd_generic_gc_sections
#define ihex_bfd_merge_sections bfd_generic_merge_sections
#define ihex_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define ihex_bfd_link_add_symbols _bfd_generic_link_add_symbols
#define ihex_bfd_final_link _bfd_generic_final_link

View File

@ -323,6 +323,10 @@ extern boolean _bfd_generic_set_section_contents
((boolean (*) \
PARAMS ((bfd *, struct bfd_link_info *))) \
bfd_false)
#define _bfd_nolink_bfd_merge_sections \
((boolean (*) \
PARAMS ((bfd *, struct bfd_link_info *))) \
bfd_false)
#define _bfd_nolink_bfd_link_hash_table_create \
((struct bfd_link_hash_table *(*) PARAMS ((bfd *))) bfd_nullvoidptr)
#define _bfd_nolink_bfd_link_add_symbols \
@ -467,6 +471,11 @@ extern bfd_vma _bfd_stab_section_offset
extern boolean _bfd_merge_section
PARAMS ((bfd *, PTR *, asection *, PTR *));
/* Attempt to merge SEC_MERGE sections. */
extern boolean _bfd_merge_sections
PARAMS ((bfd *, PTR));
/* Write out a merged section. */
extern boolean _bfd_write_merged_section

View File

@ -323,6 +323,10 @@ extern boolean _bfd_generic_set_section_contents
((boolean (*) \
PARAMS ((bfd *, struct bfd_link_info *))) \
bfd_false)
#define _bfd_nolink_bfd_merge_sections \
((boolean (*) \
PARAMS ((bfd *, struct bfd_link_info *))) \
bfd_false)
#define _bfd_nolink_bfd_link_hash_table_create \
((struct bfd_link_hash_table *(*) PARAMS ((bfd *))) bfd_nullvoidptr)
#define _bfd_nolink_bfd_link_add_symbols \
@ -467,6 +471,11 @@ extern bfd_vma _bfd_stab_section_offset
extern boolean _bfd_merge_section
PARAMS ((bfd *, PTR *, asection *, PTR *));
/* Attempt to merge SEC_MERGE sections. */
extern boolean _bfd_merge_sections
PARAMS ((bfd *, PTR));
/* Write out a merged section. */
extern boolean _bfd_write_merged_section
@ -1080,6 +1089,9 @@ bfd_generic_relax_section PARAMS ((bfd *abfd,
boolean
bfd_generic_gc_sections PARAMS ((bfd *, struct bfd_link_info *));
boolean
bfd_generic_merge_sections PARAMS ((bfd *, struct bfd_link_info *));
bfd_byte *
bfd_generic_get_relocated_section_contents PARAMS ((bfd *abfd,
struct bfd_link_info *link_info,

View File

@ -24,9 +24,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
#include "hashtab.h"
#include <ctype.h>
struct sec_merge_sec_info;
/* An entry in the section merge hash table. */
struct sec_merge_hash_entry
@ -37,10 +40,16 @@ struct sec_merge_hash_entry
/* Start of this string needs to be aligned to
alignment octets (not 1 << align). */
unsigned int alignment;
/* Index within the merged section. */
bfd_size_type index;
union {
/* Index within the merged section. */
bfd_size_type index;
/* Entity size (if present in suffix hash tables). */
unsigned int entsize;
/* Entry this is a suffix of (if alignment is 0). */
struct sec_merge_hash_entry *suffix;
} u;
/* Which section is it in. */
asection *sec;
struct sec_merge_sec_info *secinfo;
/* Next entity in the hash table. */
struct sec_merge_hash_entry *next;
};
@ -66,14 +75,20 @@ struct sec_merge_info
{
/* Chain of sec_merge_infos. */
struct sec_merge_info *next;
/* Chain of sec_merge_sec_infos. */
struct sec_merge_sec_info *chain;
/* A hash table used to hold section content. */
struct sec_merge_hash *htab;
/* The last section attempted for merge. */
asection *last;
};
struct sec_merge_sec_info
{
/* Chain of sec_merge_sec_infos. */
struct sec_merge_sec_info *next;
/* The corresponding section. */
asection *sec;
/* Pointer to merge_info pointing to us. */
PTR *psecinfo;
/* A hash table used to hold section content. */
struct sec_merge_hash *htab;
/* First string in this section. */
@ -89,7 +104,8 @@ static struct sec_merge_hash_entry *sec_merge_hash_lookup
static struct sec_merge_hash *sec_merge_init
PARAMS ((unsigned int, boolean));
static struct sec_merge_hash_entry *sec_merge_add
PARAMS ((struct sec_merge_hash *, const char *, unsigned int));
PARAMS ((struct sec_merge_hash *, const char *, unsigned int,
struct sec_merge_sec_info *));
static boolean sec_merge_emit
PARAMS ((bfd *, struct sec_merge_hash_entry *));
@ -118,9 +134,9 @@ sec_merge_hash_newfunc (entry, table, string)
if (ret)
{
/* Initialize the local fields. */
ret->index = (bfd_size_type) -1;
ret->u.suffix = NULL;
ret->alignment = 0;
ret->sec = NULL;
ret->secinfo = NULL;
ret->next = NULL;
}
@ -202,11 +218,14 @@ sec_merge_hash_lookup (table, string, alignment, create)
&& memcmp (hashp->root.string, string, len) == 0)
{
/* If the string we found does not have at least the required
alignment, we need to insert another copy.
FIXME: The old copy could be removed and the space allocated
for it filled by some new string (similarly with padding). */
alignment, we need to insert another copy. */
if (hashp->alignment < alignment)
break;
{
/* Mark the less aligned copy as deleted. */
hashp->len = 0;
hashp->alignment = 0;
break;
}
return hashp;
}
}
@ -262,10 +281,11 @@ sec_merge_init (entsize, strings)
already present. */
static struct sec_merge_hash_entry *
sec_merge_add (tab, str, alignment)
sec_merge_add (tab, str, alignment, secinfo)
struct sec_merge_hash *tab;
const char *str;
unsigned int alignment;
struct sec_merge_sec_info *secinfo;
{
register struct sec_merge_hash_entry *entry;
@ -273,11 +293,10 @@ sec_merge_add (tab, str, alignment)
if (entry == NULL)
return NULL;
if (entry->index == (bfd_size_type) -1)
if (entry->secinfo == NULL)
{
tab->size = (tab->size + alignment - 1) & ~((bfd_vma) alignment - 1);
entry->index = tab->size;
tab->size += entry->len;
tab->size++;
entry->secinfo = secinfo;
if (tab->first == NULL)
tab->first = entry;
else
@ -293,7 +312,8 @@ sec_merge_emit (abfd, entry)
register bfd *abfd;
struct sec_merge_hash_entry *entry;
{
asection *sec = entry->sec;
struct sec_merge_sec_info *secinfo = entry->secinfo;
asection *sec = secinfo->sec;
char *pad = "";
bfd_size_type off = 0;
int alignment_power = bfd_get_section_alignment (abfd, sec->output_section);
@ -301,7 +321,7 @@ sec_merge_emit (abfd, entry)
if (alignment_power)
pad = bfd_zmalloc (1 << alignment_power);
for (; entry != NULL && entry->sec == sec; entry = entry->next)
for (; entry != NULL && entry->secinfo == secinfo; entry = entry->next)
{
register const char *str;
register size_t len;
@ -327,7 +347,7 @@ sec_merge_emit (abfd, entry)
if (alignment_power)
free (pad);
return entry == NULL || entry->sec != sec;
return entry == NULL || entry->secinfo != secinfo;
}
/* This function is called for each input file from the add_symbols
@ -340,15 +360,12 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
asection *sec;
PTR *psecinfo;
{
boolean first, nul;
struct sec_merge_info *sinfo;
struct sec_merge_sec_info *secinfo;
unsigned char *p, *end;
bfd_vma mask, eltalign;
unsigned int align;
unsigned int i;
if (sec->_raw_size == 0
|| (sec->flags & SEC_EXCLUDE)
|| (sec->flags & SEC_MERGE) == 0
|| sec->entsize == 0)
return true;
@ -367,7 +384,7 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
return true;
}
align = bfd_get_section_alignment (abfd, sec);
align = bfd_get_section_alignment (sec->owner, sec);
if ((sec->entsize < (unsigned int)(1 << align)
&& ((sec->entsize & (sec->entsize - 1))
|| !(sec->flags & SEC_STRINGS)))
@ -383,23 +400,22 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
return true;
}
first = false;
for (sinfo = (struct sec_merge_info *) *psinfo; sinfo; sinfo = sinfo->next)
if (! ((sinfo->last->flags ^ sec->flags) & (SEC_MERGE | SEC_STRINGS))
&& sinfo->last->entsize == sec->entsize
&& ! strcmp (sinfo->last->name, sec->name))
if ((secinfo = sinfo->chain)
&& ! ((secinfo->sec->flags ^ sec->flags) & (SEC_MERGE | SEC_STRINGS))
&& secinfo->sec->entsize == sec->entsize
&& ! strcmp (secinfo->sec->name, sec->name))
break;
if (sinfo == NULL)
{
/* Initialize the information we need to keep track of. */
first = true;
sinfo = (struct sec_merge_info *)
bfd_alloc (abfd, sizeof (struct sec_merge_info));
if (sinfo == NULL)
goto error_return;
sinfo->next = (struct sec_merge_info *) *psinfo;
sinfo->chain = NULL;
*psinfo = (PTR) sinfo;
sinfo->htab =
sec_merge_init (sec->entsize, (sec->flags & SEC_STRINGS));
@ -415,14 +431,121 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
goto error_return;
secinfo = (struct sec_merge_sec_info *)*psecinfo;
if (sinfo->chain)
{
secinfo->next = sinfo->chain->next;
sinfo->chain->next = secinfo;
}
else
secinfo->next = secinfo;
sinfo->chain = secinfo;
secinfo->sec = sec;
secinfo->psecinfo = psecinfo;
secinfo->htab = sinfo->htab;
sinfo->htab->size = 0;
secinfo->first = NULL;
if (! bfd_get_section_contents (abfd, sec, secinfo->contents, 0,
if (! bfd_get_section_contents (sec->owner, sec, secinfo->contents, 0,
sec->_raw_size))
goto error_return;
return true;
error_return:
*psecinfo = NULL;
return false;
}
/* Compare two sec_merge_hash_entry structures. This is called via qsort. */
static int
cmplengthentry (a, b)
const PTR a;
const PTR b;
{
struct sec_merge_hash_entry * A = *(struct sec_merge_hash_entry **) a;
struct sec_merge_hash_entry * B = *(struct sec_merge_hash_entry **) b;
if (A->len < B->len)
return 1;
else if (A->len > B->len)
return -1;
return memcmp (A->root.string, B->root.string, A->len);
}
static int
last4_eq (a, b)
const void *a, *b;
{
struct sec_merge_hash_entry * A = (struct sec_merge_hash_entry *) a;
struct sec_merge_hash_entry * B = (struct sec_merge_hash_entry *) b;
if (memcmp (A->root.string + A->len - 5 * A->u.entsize,
B->root.string + B->len - 5 * A->u.entsize,
4 * A->u.entsize) != 0)
/* This was a hashtable collision. */
return 0;
if (A->len <= B->len)
/* B cannot be a suffix of A unless A is equal to B, which is guaranteed
not to be equal by the hash table. */
return 0;
if (A->alignment < B->alignment
|| ((A->len - B->len) & (B->alignment - 1)))
/* The suffix is not sufficiently aligned. */
return 0;
return memcmp (A->root.string + (A->len - B->len),
B->root.string, B->len - 5 * A->u.entsize) == 0;
}
static int
last_eq (a, b)
const void *a, *b;
{
struct sec_merge_hash_entry * A = (struct sec_merge_hash_entry *) a;
struct sec_merge_hash_entry * B = (struct sec_merge_hash_entry *) b;
if (B->len >= 5 * A->u.entsize)
/* Longer strings are just pushed into the hash table,
they'll be used when looking up for very short strings. */
return 0;
if (memcmp (A->root.string + A->len - 2 * A->u.entsize,
B->root.string + B->len - 2 * A->u.entsize,
A->u.entsize) != 0)
/* This was a hashtable collision. */
return 0;
if (A->len <= B->len)
/* B cannot be a suffix of A unless A is equal to B, which is guaranteed
not to be equal by the hash table. */
return 0;
if (A->alignment < B->alignment
|| ((A->len - B->len) & (B->alignment - 1)))
/* The suffix is not sufficiently aligned. */
return 0;
return memcmp (A->root.string + (A->len - B->len),
B->root.string, B->len - 2 * A->u.entsize) == 0;
}
/* Record one section into the hash table. */
static boolean
record_section (sinfo, secinfo)
struct sec_merge_info *sinfo;
struct sec_merge_sec_info *secinfo;
{
asection *sec = secinfo->sec;
struct sec_merge_hash_entry *entry;
boolean nul;
unsigned char *p, *end;
bfd_vma mask, eltalign;
unsigned int align, i;
align = bfd_get_section_alignment (sec->owner, sec);
end = secinfo->contents + sec->_raw_size;
nul = false;
mask = ((bfd_vma)1 << align) - 1;
@ -430,19 +553,13 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
{
for (p = secinfo->contents; p < end;)
{
struct sec_merge_hash_entry *entry;
eltalign = p - secinfo->contents;
eltalign = ((eltalign ^ (eltalign - 1)) + 1) >> 1;
if (!eltalign || eltalign > mask)
eltalign = mask + 1;
entry = sec_merge_add (sinfo->htab, p, eltalign);
if (entry->sec == NULL)
{
if (secinfo->first == NULL)
secinfo->first = entry;
entry->sec = sec;
}
entry = sec_merge_add (sinfo->htab, p, eltalign, secinfo);
if (! entry)
goto error_return;
p += entry->len;
if (sec->entsize == 1)
{
@ -451,13 +568,10 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
if (!nul && !((p - secinfo->contents) & mask))
{
nul = true;
entry = sec_merge_add (sinfo->htab, "", mask + 1);
if (entry->sec == NULL)
{
if (secinfo->first == NULL)
secinfo->first = entry;
entry->sec = sec;
}
entry = sec_merge_add (sinfo->htab, "", mask + 1,
secinfo);
if (! entry)
goto error_return;
}
p++;
}
@ -474,13 +588,10 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
if (!nul && !((p - secinfo->contents) & mask))
{
nul = true;
entry = sec_merge_add (sinfo->htab, p, mask + 1);
if (entry->sec == NULL)
{
if (secinfo->first == NULL)
secinfo->first = entry;
entry->sec = sec;
}
entry = sec_merge_add (sinfo->htab, p, mask + 1,
secinfo);
if (! entry)
goto error_return;
}
p += sec->entsize;
}
@ -491,31 +602,237 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
{
for (p = secinfo->contents; p < end; p += sec->entsize)
{
struct sec_merge_hash_entry *entry;
entry = sec_merge_add (sinfo->htab, p, 1);
if (entry->sec == NULL)
{
if (secinfo->first == NULL)
secinfo->first = entry;
entry->sec = sec;
}
entry = sec_merge_add (sinfo->htab, p, 1, secinfo);
if (! entry)
goto error_return;
}
}
sec->_cooked_size = sinfo->htab->size;
if (!sec->_cooked_size)
sec->flags |= SEC_EXCLUDE;
sinfo->last = sec;
return true;
error_return:
if (*psecinfo != NULL)
free (*psecinfo);
*psecinfo = NULL;
error_return:
for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
*secinfo->psecinfo = NULL;
return false;
}
/* This is a helper function for _bfd_merge_sections. It attempts to
merge strings matching suffixes of longer strings. */
static void
merge_strings (sinfo)
struct sec_merge_info *sinfo;
{
struct sec_merge_hash_entry **array, **a, **end, *e;
struct sec_merge_sec_info *secinfo;
htab_t lasttab = NULL, last4tab = NULL;
bfd_size_type size;
/* Now sort the strings by length, longest first. */
array = (struct sec_merge_hash_entry **)
malloc (sinfo->htab->size
* sizeof (struct sec_merge_hash_entry *));
if (array == NULL)
goto alloc_failure;
for (e = sinfo->htab->first, a = array; e; e = e->next)
if (e->alignment)
*a++ = e;
sinfo->htab->size = a - array;
qsort (array, sinfo->htab->size, sizeof (struct sec_merge_hash_entry *),
cmplengthentry);
last4tab = htab_create (sinfo->htab->size * 4, NULL, last4_eq, NULL);
lasttab = htab_create (sinfo->htab->size * 4, NULL, last_eq, NULL);
if (lasttab == NULL || last4tab == NULL)
goto alloc_failure;
/* Now insert the strings into hash tables (strings with last 4 characters
and strings with last character equal), look for longer strings which
we're suffix of. */
for (a = array, end = array + sinfo->htab->size; a < end; a++)
{
register hashval_t hash;
unsigned int c;
unsigned int i;
const unsigned char *s;
PTR *p;
e = *a;
e->u.entsize = sinfo->htab->entsize;
if (e->len <= e->u.entsize)
break;
if (e->len > 4 * e->u.entsize)
{
s = e->root.string + e->len - e->u.entsize;
hash = 0;
for (i = 0; i < 4 * e->u.entsize; i++)
{
c = *--s;
hash += c + (c << 17);
hash ^= hash >> 2;
}
p = htab_find_slot_with_hash (last4tab, e, hash, INSERT);
if (p == NULL)
goto alloc_failure;
if (*p)
{
struct sec_merge_hash_entry *ent;
ent = (struct sec_merge_hash_entry *) *p;
e->u.suffix = ent;
e->alignment = 0;
continue;
}
else
*p = (PTR) e;
}
s = e->root.string + e->len - e->u.entsize;
hash = 0;
for (i = 0; i < e->u.entsize; i++)
{
c = *--s;
hash += c + (c << 17);
hash ^= hash >> 2;
}
p = htab_find_slot_with_hash (lasttab, e, hash, INSERT);
if (p == NULL)
goto alloc_failure;
if (*p)
{
struct sec_merge_hash_entry *ent;
ent = (struct sec_merge_hash_entry *) *p;
e->u.suffix = ent;
e->alignment = 0;
}
else
*p = (PTR) e;
}
alloc_failure:
if (array)
free (array);
if (lasttab)
htab_delete (lasttab);
if (last4tab)
htab_delete (last4tab);
/* Now assign positions to the strings we want to keep. */
size = 0;
secinfo = sinfo->htab->first->secinfo;
for (e = sinfo->htab->first; e; e = e->next)
{
if (e->secinfo != secinfo)
{
secinfo->sec->_cooked_size = size;
secinfo = e->secinfo;
}
if (e->alignment)
{
if (e->secinfo->first == NULL)
{
e->secinfo->first = e;
size = 0;
}
size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1);
e->u.index = size;
size += e->len;
}
}
secinfo->sec->_cooked_size = size;
/* And now adjust the rest, removing them from the chain (but not hashtable)
at the same time. */
for (a = &sinfo->htab->first, e = *a; e; e = e->next)
if (e->alignment)
a = &e->next;
else
{
*a = e->next;
if (e->len)
{
e->secinfo = e->u.suffix->secinfo;
e->alignment = e->u.suffix->alignment;
e->u.index = e->u.suffix->u.index + (e->u.suffix->len - e->len);
}
}
}
/* This function is called once after all SEC_MERGE sections are registered
with _bfd_merge_section. */
boolean
_bfd_merge_sections (abfd, xsinfo)
bfd *abfd ATTRIBUTE_UNUSED;
PTR xsinfo;
{
struct sec_merge_info *sinfo;
for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
{
struct sec_merge_sec_info * secinfo;
if (! sinfo->chain)
continue;
/* Move sinfo->chain to head of the chain, terminate it. */
secinfo = sinfo->chain;
sinfo->chain = secinfo->next;
secinfo->next = NULL;
/* Record the sections into the hash table. */
for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
if (secinfo->sec->flags & SEC_EXCLUDE)
*secinfo->psecinfo = NULL;
else if (! record_section (sinfo, secinfo))
break;
if (secinfo)
continue;
if (sinfo->htab->strings)
merge_strings (sinfo);
else
{
struct sec_merge_hash_entry *e;
bfd_size_type size = 0;
/* Things are much simpler for non-strings.
Just assign them slots in the section. */
secinfo = NULL;
for (e = sinfo->htab->first; e; e = e->next)
{
if (e->secinfo->first == NULL)
{
if (secinfo)
secinfo->sec->_cooked_size = size;
e->secinfo->first = e;
size = 0;
}
size = (size + e->alignment - 1)
& ~((bfd_vma) e->alignment - 1);
e->u.index = size;
size += e->len;
secinfo = e->secinfo;
}
secinfo->sec->_cooked_size = size;
}
/* Finally shrink 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;
}
}
return true;
}
/* Write out the merged section. */
boolean
@ -619,6 +936,6 @@ _bfd_merged_section_offset (output_bfd, psec, psecinfo, offset, addend)
- entry->len;
}
*psec = entry->sec;
return entry->index + (secinfo->contents + offset - p);
*psec = entry->secinfo->sec;
return entry->u.index + (secinfo->contents + offset - p);
}

View File

@ -1,5 +1,5 @@
/* Target definitions for 32/64-bit NLM (NetWare Loadable Module)
Copyright 1993, 1994, 1998, 1999, 2000 Free Software Foundation, Inc.
Copyright 1993, 1994, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@ -42,6 +42,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
bfd_generic_get_relocated_section_contents
#define nlm_bfd_relax_section bfd_generic_relax_section
#define nlm_bfd_gc_sections bfd_generic_gc_sections
#define nlm_bfd_merge_sections bfd_generic_merge_sections
#define nlm_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define nlm_bfd_link_add_symbols _bfd_generic_link_add_symbols
#define nlm_bfd_final_link _bfd_generic_final_link

View File

@ -1476,6 +1476,7 @@ oasys_sizeof_headers (abfd, exec)
bfd_generic_get_relocated_section_contents
#define oasys_bfd_relax_section bfd_generic_relax_section
#define oasys_bfd_gc_sections bfd_generic_gc_sections
#define oasys_bfd_merge_sections bfd_generic_merge_sections
#define oasys_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define oasys_bfd_link_add_symbols _bfd_generic_link_add_symbols
#define oasys_bfd_final_link _bfd_generic_final_link

View File

@ -475,6 +475,7 @@ ppcboot_bfd_print_private_bfd_data (abfd, farg)
bfd_generic_get_relocated_section_contents
#define ppcboot_bfd_relax_section bfd_generic_relax_section
#define ppcboot_bfd_gc_sections bfd_generic_gc_sections
#define ppcboot_bfd_merge_sections bfd_generic_merge_sections
#define ppcboot_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define ppcboot_bfd_link_add_symbols _bfd_generic_link_add_symbols
#define ppcboot_bfd_final_link _bfd_generic_final_link

View File

@ -3252,6 +3252,28 @@ bfd_generic_gc_sections (abfd, link_info)
return true;
}
/*
INTERNAL_FUNCTION
bfd_generic_merge_sections
SYNOPSIS
boolean bfd_generic_merge_sections
(bfd *, struct bfd_link_info *);
DESCRIPTION
Provides default handling for SEC_MERGE section merging for back ends
which don't have SEC_MERGE support -- i.e., does nothing.
*/
/*ARGSUSED*/
boolean
bfd_generic_merge_sections (abfd, link_info)
bfd *abfd ATTRIBUTE_UNUSED;
struct bfd_link_info *link_info ATTRIBUTE_UNUSED;
{
return true;
}
/*
INTERNAL_FUNCTION
bfd_generic_get_relocated_section_contents

View File

@ -6286,6 +6286,7 @@ som_bfd_link_split_section (abfd, sec)
#define som_bfd_final_link _bfd_generic_final_link
#define som_bfd_gc_sections bfd_generic_gc_sections
#define som_bfd_merge_sections bfd_generic_merge_sections
const bfd_target som_vec = {
"som", /* name */

View File

@ -1262,6 +1262,7 @@ srec_print_symbol (ignore_abfd, afile, symbol, how)
bfd_generic_get_relocated_section_contents
#define srec_bfd_relax_section bfd_generic_relax_section
#define srec_bfd_gc_sections bfd_generic_gc_sections
#define srec_bfd_merge_sections bfd_generic_merge_sections
#define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols
#define srec_bfd_final_link _bfd_generic_final_link

View File

@ -416,7 +416,8 @@ BFD_JUMP_TABLE macros.
.CAT(NAME,_bfd_link_add_symbols),\
.CAT(NAME,_bfd_final_link),\
.CAT(NAME,_bfd_link_split_section),\
.CAT(NAME,_bfd_gc_sections)
.CAT(NAME,_bfd_gc_sections),\
.CAT(NAME,_bfd_merge_sections)
. int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean));
. bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *,
. struct bfd_link_info *, struct bfd_link_order *,
@ -443,6 +444,9 @@ BFD_JUMP_TABLE macros.
. {* Remove sections that are not referenced from the output. *}
. boolean (*_bfd_gc_sections) PARAMS ((bfd *, struct bfd_link_info *));
.
. {* Attempt to merge SEC_MERGE sections. *}
. boolean (*_bfd_merge_sections) PARAMS ((bfd *, struct bfd_link_info *));
.
. {* Routines to handle dynamic symbols and relocs. *}
.#define BFD_JUMP_TABLE_DYNAMIC(NAME)\
.CAT(NAME,_get_dynamic_symtab_upper_bound),\

View File

@ -1001,6 +1001,7 @@ tekhex_print_symbol (ignore_abfd, filep, symbol, how)
bfd_generic_get_relocated_section_contents
#define tekhex_bfd_relax_section bfd_generic_relax_section
#define tekhex_bfd_gc_sections bfd_generic_gc_sections
#define tekhex_bfd_merge_sections bfd_generic_merge_sections
#define tekhex_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define tekhex_bfd_link_add_symbols _bfd_generic_link_add_symbols
#define tekhex_bfd_final_link _bfd_generic_final_link

View File

@ -840,6 +840,7 @@ versados_canonicalize_reloc (abfd, section, relptr, symbols)
bfd_generic_get_relocated_section_contents
#define versados_bfd_relax_section bfd_generic_relax_section
#define versados_bfd_gc_sections bfd_generic_gc_sections
#define versados_bfd_merge_sections bfd_generic_merge_sections
#define versados_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define versados_bfd_link_add_symbols _bfd_generic_link_add_symbols
#define versados_bfd_final_link _bfd_generic_final_link

View File

@ -110,6 +110,8 @@ static boolean vms_bfd_relax_section
boolean *again));
static boolean vms_bfd_gc_sections
PARAMS ((bfd *abfd, struct bfd_link_info *link_info));
static boolean vms_bfd_merge_sections
PARAMS ((bfd *abfd, struct bfd_link_info *link_info));
static struct bfd_link_hash_table *vms_bfd_link_hash_table_create
PARAMS ((bfd *abfd));
static boolean vms_bfd_link_add_symbols
@ -1784,6 +1786,17 @@ vms_bfd_gc_sections (abfd, link_info)
return true;
}
static boolean
vms_bfd_merge_sections (abfd, link_info)
bfd *abfd ATTRIBUTE_UNUSED;
struct bfd_link_info *link_info ATTRIBUTE_UNUSED;
{
#if VMS_DEBUG
vms_debug (1, "vms_bfd_merge_sections(%p, %p)\n", abfd, link_info);
#endif
return true;
}
/* Create a hash table for the linker. Different backends store
different information in this table. */

View File

@ -97,6 +97,7 @@ extern int lynx_core_file_failing_signal PARAMS ((bfd *abfd));
coff_bfd_get_relocated_section_contents
#define _bfd_xcoff_bfd_relax_section coff_bfd_relax_section
#define _bfd_xcoff_bfd_gc_sections coff_bfd_gc_sections
#define _bfd_xcoff_bfd_merge_sections coff_bfd_merge_sections
#define _bfd_xcoff_bfd_link_split_section coff_bfd_link_split_section
/* XCOFF archives do not have anything which corresponds to an

View File

@ -1,3 +1,7 @@
2001-05-11 Jakub Jelinek <jakub@redhat.com>
* ldlang.c (lang_process): Call bfd_merge_sections.
2001-05-07 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
* ldgram.y: Fix typo.

View File

@ -4130,6 +4130,12 @@ lang_process ()
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 ();