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:
Tristan Gingold 2013-08-21 08:15:23 +00:00
parent 0ed1b36a6a
commit 2eea244095
3 changed files with 88 additions and 25 deletions

View file

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

View file

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

View file

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