2013-08-21 Tristan Gingold <gingold@adacore.com>
* coff-rs6000.c (_bfd_xcoff_sizeof_headers): Also count .ovrflo sections. * coffcode.h (coff_compute_section_file_positions): Force match between file offset and vma offset.
This commit is contained in:
parent
0ed1b36a6a
commit
2eea244095
3 changed files with 88 additions and 25 deletions
|
@ -1,3 +1,10 @@
|
|||
2013-08-21 Tristan Gingold <gingold@adacore.com>
|
||||
|
||||
* coff-rs6000.c (_bfd_xcoff_sizeof_headers): Also count
|
||||
.ovrflo sections.
|
||||
* coffcode.h (coff_compute_section_file_positions): Force
|
||||
match between file offset and vma offset.
|
||||
|
||||
2013-08-21 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elflink.c (_bfd_elf_merge_symbol): Set *poldbfd, *poldweak,
|
||||
|
|
|
@ -2570,6 +2570,60 @@ _bfd_xcoff_sizeof_headers (bfd *abfd,
|
|||
else
|
||||
size += SMALL_AOUTSZ;
|
||||
size += abfd->section_count * SCNHSZ;
|
||||
|
||||
if (info->strip != strip_all)
|
||||
{
|
||||
/* There can be additional sections just for dealing with overflow in
|
||||
reloc and lineno counts. But the numbers of relocs and lineno aren't
|
||||
known when bfd_sizeof_headers is called, so we compute them by
|
||||
summing the numbers from input sections. */
|
||||
struct nbr_reloc_lineno
|
||||
{
|
||||
unsigned int reloc_count;
|
||||
unsigned int lineno_count;
|
||||
};
|
||||
struct nbr_reloc_lineno *n_rl;
|
||||
bfd *sub;
|
||||
int max_index;
|
||||
asection *s;
|
||||
|
||||
/* Although the number of sections is known, the maximum value of
|
||||
section->index isn't (because some sections may have been removed).
|
||||
Don't try to renumber sections, just compute the upper bound. */
|
||||
max_index = 0;
|
||||
for (s = abfd->sections; s != NULL; s = s->next)
|
||||
if (s->index > max_index)
|
||||
max_index = s->index;
|
||||
|
||||
/* Allocate the per section counters. It could be possible to use a
|
||||
preallocated array as the number of sections is limited on XCOFF,
|
||||
but this creates a maintainance issue. */
|
||||
n_rl = bfd_zmalloc ((max_index + 1) * sizeof (*n_rl));
|
||||
if (n_rl == NULL)
|
||||
return -1;
|
||||
|
||||
/* Sum. */
|
||||
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
|
||||
for (s = sub->sections; s != NULL; s = s->next)
|
||||
{
|
||||
struct nbr_reloc_lineno *e = &n_rl[s->output_section->index];
|
||||
e->reloc_count += s->reloc_count;
|
||||
e->lineno_count += s->lineno_count;
|
||||
}
|
||||
|
||||
/* Add the size of a section for each section with an overflow. */
|
||||
for (s = abfd->sections; s != NULL; s = s->next)
|
||||
{
|
||||
struct nbr_reloc_lineno *e = &n_rl[s->index];
|
||||
|
||||
if (e->reloc_count >= 0xffff
|
||||
|| (e->lineno_count >= 0xffff && info->strip != strip_debugger))
|
||||
size += SCNHSZ;
|
||||
}
|
||||
|
||||
free (n_rl);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
|
|
@ -3363,36 +3363,38 @@ coff_compute_section_file_positions (bfd * abfd)
|
|||
padding the previous section up if necessary. */
|
||||
old_sofar = sofar;
|
||||
|
||||
sofar = BFD_ALIGN (sofar, 1 << current->alignment_power);
|
||||
|
||||
#ifdef RS6000COFF_C
|
||||
/* AIX loader checks the text section alignment of (vma - filepos)
|
||||
So even though the filepos may be aligned wrt the o_algntext, for
|
||||
AIX executables, this check fails. This shows up when a native
|
||||
AIX executable is stripped with gnu strip because the default vma
|
||||
of native is 0x10000150 but default for gnu is 0x10000140. Gnu
|
||||
stripped gnu excutable passes this check because the filepos is
|
||||
0x0140. This problem also show up with 64 bit shared objects. The
|
||||
data section must also be aligned. */
|
||||
/* Make sure the file offset and the vma of .text/.data are at the
|
||||
same page offset, so that the file can be mmap'ed without being
|
||||
relocated. Failing that, AIX is able to load and execute the
|
||||
program, but it will be silently relocated (possible as
|
||||
executables are PIE). But the relocation is slightly costly and
|
||||
complexify the use of addr2line or gdb. So better to avoid it,
|
||||
like does the native linker. Usually gnu ld makes sure that
|
||||
the vma of .text is the file offset so this issue shouldn't
|
||||
appear unless you are stripping such an executable.
|
||||
|
||||
AIX loader checks the text section alignment of (vma - filepos),
|
||||
and the native linker doesn't try to align the text sections.
|
||||
For example:
|
||||
|
||||
0 .text 000054cc 10000128 10000128 00000128 2**5
|
||||
CONTENTS, ALLOC, LOAD, CODE
|
||||
*/
|
||||
|
||||
if (!strcmp (current->name, _TEXT)
|
||||
|| !strcmp (current->name, _DATA))
|
||||
{
|
||||
bfd_vma pad;
|
||||
bfd_vma align;
|
||||
bfd_vma align = 4096;
|
||||
bfd_vma sofar_off = sofar % align;
|
||||
bfd_vma vma_off = current->vma % align;
|
||||
|
||||
sofar = BFD_ALIGN (sofar, 1 << current->alignment_power);
|
||||
|
||||
align = 1 << current->alignment_power;
|
||||
pad = abs (current->vma - sofar) % align;
|
||||
|
||||
if (pad)
|
||||
{
|
||||
pad = align - pad;
|
||||
sofar += pad;
|
||||
}
|
||||
}
|
||||
else
|
||||
#else
|
||||
{
|
||||
sofar = BFD_ALIGN (sofar, 1 << current->alignment_power);
|
||||
if (vma_off > sofar_off)
|
||||
sofar += vma_off - sofar_off;
|
||||
else if (vma_off < sofar_off)
|
||||
sofar += align + vma_off - sofar_off;
|
||||
}
|
||||
#endif
|
||||
if (previous != NULL)
|
||||
|
|
Loading…
Reference in a new issue