mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-03-19 13:51:44 +08:00
* merge.c (struct sec_merge_hash_entry): Add alignment field.
(struct sec_merge_hash): Remove alignment_power. (sec_merge_hash_newfunc): Clear alignment. (sec_merge_hash_lookup): Pass alignment as argument. Use hashp->root.next, not hashp->next to walk the hash chain. If a string already in the hashtable does not have required alignment, create a new hashtable entry. (sec_merge_init): Remove alignment_power argument. (sec_merge_add): Add alignment argument. (sec_merge_emit): Alignment is now a per-entity thing, not per section. (_bfd_merge_section): Sanity check even non-SEC_STRINGS sections for proper alignment. Pass alignment information to sec_merge_add.
This commit is contained in:
parent
851c18e0e9
commit
a531bbd206
@ -1,3 +1,20 @@
|
||||
2001-04-24 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* merge.c (struct sec_merge_hash_entry): Add alignment field.
|
||||
(struct sec_merge_hash): Remove alignment_power.
|
||||
(sec_merge_hash_newfunc): Clear alignment.
|
||||
(sec_merge_hash_lookup): Pass alignment as argument.
|
||||
Use hashp->root.next, not hashp->next to walk the hash chain.
|
||||
If a string already in the hashtable does not have required
|
||||
alignment, create a new hashtable entry.
|
||||
(sec_merge_init): Remove alignment_power argument.
|
||||
(sec_merge_add): Add alignment argument.
|
||||
(sec_merge_emit): Alignment is now a per-entity thing, not per
|
||||
section.
|
||||
(_bfd_merge_section): Sanity check even non-SEC_STRINGS sections
|
||||
for proper alignment.
|
||||
Pass alignment information to sec_merge_add.
|
||||
|
||||
2001-04-24 Christian Groessler <cpg@aladdin.de>
|
||||
|
||||
* coff-z8k.c (extra_case): added handler for R_DISP7, R_CALLR
|
||||
|
112
bfd/merge.c
112
bfd/merge.c
@ -34,6 +34,9 @@ struct sec_merge_hash_entry
|
||||
struct bfd_hash_entry root;
|
||||
/* Length of this entry. */
|
||||
unsigned int len;
|
||||
/* 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;
|
||||
/* Which section is it in. */
|
||||
@ -55,9 +58,6 @@ struct sec_merge_hash
|
||||
struct sec_merge_hash_entry *last;
|
||||
/* Entity size. */
|
||||
unsigned int entsize;
|
||||
/* Start of each string needs to be aligned to 1 << alignment_power
|
||||
octets. */
|
||||
unsigned int alignment_power;
|
||||
/* Are entries fixed size or zero terminated strings? */
|
||||
boolean strings;
|
||||
};
|
||||
@ -85,13 +85,13 @@ struct sec_merge_sec_info
|
||||
static struct bfd_hash_entry *sec_merge_hash_newfunc
|
||||
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
|
||||
static struct sec_merge_hash_entry *sec_merge_hash_lookup
|
||||
PARAMS ((struct sec_merge_hash *, const char *, boolean));
|
||||
PARAMS ((struct sec_merge_hash *, const char *, unsigned int, boolean));
|
||||
static struct sec_merge_hash *sec_merge_init
|
||||
PARAMS ((unsigned int, unsigned int, boolean));
|
||||
PARAMS ((unsigned int, boolean));
|
||||
static struct sec_merge_hash_entry *sec_merge_add
|
||||
PARAMS ((struct sec_merge_hash *, const char *));
|
||||
PARAMS ((struct sec_merge_hash *, const char *, unsigned int));
|
||||
static boolean sec_merge_emit
|
||||
PARAMS ((bfd *, struct sec_merge_hash *, struct sec_merge_hash_entry *));
|
||||
PARAMS ((bfd *, struct sec_merge_hash_entry *));
|
||||
|
||||
/* Routine to create an entry in a section merge hashtab. */
|
||||
|
||||
@ -119,6 +119,7 @@ sec_merge_hash_newfunc (entry, table, string)
|
||||
{
|
||||
/* Initialize the local fields. */
|
||||
ret->index = (bfd_size_type) -1;
|
||||
ret->alignment = 0;
|
||||
ret->sec = NULL;
|
||||
ret->next = NULL;
|
||||
}
|
||||
@ -129,9 +130,10 @@ sec_merge_hash_newfunc (entry, table, string)
|
||||
/* Look up an entry in a section merge hash table. */
|
||||
|
||||
static struct sec_merge_hash_entry *
|
||||
sec_merge_hash_lookup (table, string, create)
|
||||
sec_merge_hash_lookup (table, string, alignment, create)
|
||||
struct sec_merge_hash *table;
|
||||
const char *string;
|
||||
unsigned int alignment;
|
||||
boolean create;
|
||||
{
|
||||
register const unsigned char *s;
|
||||
@ -193,12 +195,20 @@ sec_merge_hash_lookup (table, string, create)
|
||||
index = hash % table->table.size;
|
||||
for (hashp = (struct sec_merge_hash_entry *) table->table.table[index];
|
||||
hashp != (struct sec_merge_hash_entry *) NULL;
|
||||
hashp = (struct sec_merge_hash_entry *) hashp->next)
|
||||
hashp = (struct sec_merge_hash_entry *) hashp->root.next)
|
||||
{
|
||||
if (hashp->root.hash == hash
|
||||
&& len == hashp->len
|
||||
&& memcmp (hashp->root.string, string, len) == 0)
|
||||
return hashp;
|
||||
{
|
||||
/* 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). */
|
||||
if (hashp->alignment < alignment)
|
||||
break;
|
||||
return hashp;
|
||||
}
|
||||
}
|
||||
|
||||
if (! create)
|
||||
@ -212,6 +222,7 @@ sec_merge_hash_lookup (table, string, create)
|
||||
hashp->root.string = string;
|
||||
hashp->root.hash = hash;
|
||||
hashp->len = len;
|
||||
hashp->alignment = alignment;
|
||||
hashp->root.next = table->table.table[index];
|
||||
table->table.table[index] = (struct bfd_hash_entry *) hashp;
|
||||
|
||||
@ -221,8 +232,8 @@ sec_merge_hash_lookup (table, string, create)
|
||||
/* Create a new hash table. */
|
||||
|
||||
static struct sec_merge_hash *
|
||||
sec_merge_init (alignment_power, entsize, strings)
|
||||
unsigned int alignment_power, entsize;
|
||||
sec_merge_init (entsize, strings)
|
||||
unsigned int entsize;
|
||||
boolean strings;
|
||||
{
|
||||
struct sec_merge_hash *table;
|
||||
@ -241,7 +252,6 @@ sec_merge_init (alignment_power, entsize, strings)
|
||||
table->size = 0;
|
||||
table->first = NULL;
|
||||
table->last = NULL;
|
||||
table->alignment_power = alignment_power;
|
||||
table->entsize = entsize;
|
||||
table->strings = strings;
|
||||
|
||||
@ -252,21 +262,22 @@ sec_merge_init (alignment_power, entsize, strings)
|
||||
already present. */
|
||||
|
||||
static struct sec_merge_hash_entry *
|
||||
sec_merge_add (tab, str)
|
||||
sec_merge_add (tab, str, alignment)
|
||||
struct sec_merge_hash *tab;
|
||||
const char *str;
|
||||
unsigned int alignment;
|
||||
{
|
||||
register struct sec_merge_hash_entry *entry;
|
||||
|
||||
entry = sec_merge_hash_lookup (tab, str, true);
|
||||
entry = sec_merge_hash_lookup (tab, str, alignment, true);
|
||||
if (entry == NULL)
|
||||
return NULL;
|
||||
|
||||
if (entry->index == (bfd_size_type) -1)
|
||||
{
|
||||
tab->size = (tab->size + alignment - 1) & ~((bfd_vma) alignment - 1);
|
||||
entry->index = tab->size;
|
||||
tab->size += entry->len;
|
||||
tab->size = align_power (tab->size, tab->alignment_power);
|
||||
if (tab->first == NULL)
|
||||
tab->first = entry;
|
||||
else
|
||||
@ -278,39 +289,42 @@ sec_merge_add (tab, str)
|
||||
}
|
||||
|
||||
static boolean
|
||||
sec_merge_emit (abfd, tab, entry)
|
||||
sec_merge_emit (abfd, entry)
|
||||
register bfd *abfd;
|
||||
struct sec_merge_hash *tab;
|
||||
struct sec_merge_hash_entry *entry;
|
||||
{
|
||||
asection *sec = entry->sec;
|
||||
char *pad = "";
|
||||
bfd_size_type off = 0;
|
||||
int alignment_power = bfd_get_section_alignment (abfd, sec->output_section);
|
||||
|
||||
if (tab->alignment_power)
|
||||
pad = bfd_zmalloc (1 << tab->alignment_power);
|
||||
if (alignment_power)
|
||||
pad = bfd_zmalloc (1 << alignment_power);
|
||||
|
||||
for (; entry != NULL && entry->sec == sec; entry = entry->next)
|
||||
{
|
||||
register const char *str;
|
||||
register size_t len;
|
||||
|
||||
len = off & (entry->alignment - 1);
|
||||
if (len)
|
||||
{
|
||||
len = entry->alignment - len;
|
||||
if (bfd_write ((PTR) pad, 1, len, abfd) != len)
|
||||
break;
|
||||
off += len;
|
||||
}
|
||||
|
||||
str = entry->root.string;
|
||||
len = entry->len;
|
||||
|
||||
if (bfd_write ((PTR) str, 1, len, abfd) != len)
|
||||
break;
|
||||
|
||||
if (tab->alignment_power)
|
||||
{
|
||||
len &= (1 << tab->alignment_power) - 1;
|
||||
if (len && bfd_write ((PTR) pad, 1,
|
||||
(1 << tab->alignment_power) - len,
|
||||
abfd) != (1 << tab->alignment_power) - len)
|
||||
break;
|
||||
}
|
||||
off += len;
|
||||
}
|
||||
|
||||
if (tab->alignment_power)
|
||||
if (alignment_power)
|
||||
free (pad);
|
||||
|
||||
return entry == NULL || entry->sec != sec;
|
||||
@ -330,7 +344,7 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
|
||||
struct sec_merge_info *sinfo;
|
||||
struct sec_merge_sec_info *secinfo;
|
||||
unsigned char *p, *end;
|
||||
bfd_vma mask;
|
||||
bfd_vma mask, eltalign;
|
||||
unsigned int align;
|
||||
unsigned int i;
|
||||
|
||||
@ -354,16 +368,18 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
|
||||
}
|
||||
|
||||
align = bfd_get_section_alignment (abfd, sec);
|
||||
if ((sec->flags & SEC_STRINGS)
|
||||
&& ((sec->entsize < (unsigned int)(1 << align)
|
||||
&& (sec->entsize & (sec->entsize - 1)))
|
||||
|| (sec->entsize > (unsigned int)(1 << align)
|
||||
&& (sec->entsize & ((1 << align) - 1)))))
|
||||
if ((sec->entsize < (unsigned int)(1 << align)
|
||||
&& ((sec->entsize & (sec->entsize - 1))
|
||||
|| !(sec->flags & SEC_STRINGS)))
|
||||
|| (sec->entsize > (unsigned int)(1 << align)
|
||||
&& (sec->entsize & ((1 << align) - 1))))
|
||||
{
|
||||
/* Sanity check. If string character size is smaller than
|
||||
alignment, then we require character size to be a power
|
||||
of 2, otherwise character size must be integer multiple
|
||||
of alignment. */
|
||||
of alignment. For non-string constants, alignment must
|
||||
be smaller than or equal to entity size and entity size
|
||||
must be integer multiple of alignment. */
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -372,8 +388,7 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
|
||||
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)
|
||||
&& bfd_get_section_alignment (abfd, sinfo->last) == align)
|
||||
&& ! strcmp (sinfo->last->name, sec->name))
|
||||
break;
|
||||
|
||||
if (sinfo == NULL)
|
||||
@ -387,8 +402,7 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
|
||||
sinfo->next = (struct sec_merge_info *) *psinfo;
|
||||
*psinfo = (PTR) sinfo;
|
||||
sinfo->htab =
|
||||
sec_merge_init ((sec->flags & SEC_STRINGS) ? align : 0,
|
||||
sec->entsize, (sec->flags & SEC_STRINGS));
|
||||
sec_merge_init (sec->entsize, (sec->flags & SEC_STRINGS));
|
||||
if (sinfo->htab == NULL)
|
||||
goto error_return;
|
||||
}
|
||||
@ -411,14 +425,18 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
|
||||
|
||||
end = secinfo->contents + sec->_raw_size;
|
||||
nul = false;
|
||||
mask = ((bfd_vma)1 << sinfo->htab->alignment_power) - 1;
|
||||
mask = ((bfd_vma)1 << align) - 1;
|
||||
if (sec->flags & SEC_STRINGS)
|
||||
{
|
||||
for (p = secinfo->contents; p < end;)
|
||||
{
|
||||
struct sec_merge_hash_entry *entry;
|
||||
|
||||
entry = sec_merge_add (sinfo->htab, p);
|
||||
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)
|
||||
@ -433,7 +451,7 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
|
||||
if (!nul && !((p - secinfo->contents) & mask))
|
||||
{
|
||||
nul = true;
|
||||
entry = sec_merge_add (sinfo->htab, "");
|
||||
entry = sec_merge_add (sinfo->htab, "", mask + 1);
|
||||
if (entry->sec == NULL)
|
||||
{
|
||||
if (secinfo->first == NULL)
|
||||
@ -456,7 +474,7 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
|
||||
if (!nul && !((p - secinfo->contents) & mask))
|
||||
{
|
||||
nul = true;
|
||||
entry = sec_merge_add (sinfo->htab, p);
|
||||
entry = sec_merge_add (sinfo->htab, p, mask + 1);
|
||||
if (entry->sec == NULL)
|
||||
{
|
||||
if (secinfo->first == NULL)
|
||||
@ -475,7 +493,7 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
|
||||
{
|
||||
struct sec_merge_hash_entry *entry;
|
||||
|
||||
entry = sec_merge_add (sinfo->htab, p);
|
||||
entry = sec_merge_add (sinfo->htab, p, 1);
|
||||
if (entry->sec == NULL)
|
||||
{
|
||||
if (secinfo->first == NULL)
|
||||
@ -518,7 +536,7 @@ _bfd_write_merged_section (output_bfd, sec, psecinfo)
|
||||
SEEK_SET) != 0)
|
||||
return false;
|
||||
|
||||
if (! sec_merge_emit (output_bfd, secinfo->htab, secinfo->first))
|
||||
if (! sec_merge_emit (output_bfd, secinfo->first))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -584,7 +602,7 @@ _bfd_merged_section_offset (output_bfd, psec, psecinfo, offset, addend)
|
||||
p = secinfo->contents
|
||||
+ ((offset + addend) / sec->entsize) * sec->entsize;
|
||||
}
|
||||
entry = sec_merge_hash_lookup (secinfo->htab, p, false);
|
||||
entry = sec_merge_hash_lookup (secinfo->htab, p, 0, false);
|
||||
if (!entry)
|
||||
{
|
||||
if (! secinfo->htab->strings)
|
||||
|
Loading…
x
Reference in New Issue
Block a user