set vma on mach-o sections.

gas:

	* config/obj-macho.c (obj_mach_o_set_vma_data): New type.
	(obj_mach_o_set_section_vma): New.
	(obj_mach_o_post_relax_hook): New.
	* config/obj-macho.h (md_post_relax_hook): Define.
	(obj_mach_o_post_relax_hook): Declare.

gas/testsuite:

	* gas/mach-o/dysymtab-2.d: Update to include the set VMA.
	* gas/mach-o/symbols-1-64.d: Likewise.
	* gas/mach-o/symbols-1.d: Likewise.
	* gas/mach-o/symbols-6.d: Likewise.
	* gas/mach-o/zerofill-1.d: Likewise.
	* gas/mach-o/zerofill-2.d: Likewise.
This commit is contained in:
Iain Sandoe
2012-01-13 11:55:02 +00:00
parent ee5106fede
commit c3402d2056
10 changed files with 378 additions and 271 deletions

View File

@@ -45,6 +45,8 @@
#include "mach-o/loader.h"
#include "obj-macho.h"
#include <string.h>
/* Forward decls. */
static segT obj_mach_o_segT_from_bfd_name (const char *, int);
@@ -1471,6 +1473,89 @@ obj_macho_frob_symbol (struct symbol *sp)
return 0;
}
/* Zerofill and GB Zerofill sections must be sorted to follow all other
sections in their segments.
The native 'as' leaves the sections physically in the order they appear in
the source, and adjusts the section VMAs to meet the constraint.
We follow this for now - if nothing else, it makes comparison easier.
An alternative implementation would be to sort the sections as ld requires.
It might be advantageous to implement such a scheme in the future (or even
to make the style of section ordering user-selectable). */
typedef struct obj_mach_o_set_vma_data
{
bfd_vma vma;
unsigned vma_pass;
unsigned zerofill_seen;
unsigned gb_zerofill_seen;
} obj_mach_o_set_vma_data;
/* We do (possibly) three passes through to set the vma, so that:
zerofill sections get VMAs after all others in their segment
GB zerofill get VMAs last.
As we go, we notice if we see any Zerofill or GB Zerofill sections, so that
we can skip the additional passes if there's nothing to do. */
static void
obj_mach_o_set_section_vma (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *v_p)
{
bfd_mach_o_section *ms = bfd_mach_o_get_mach_o_section (sec);
unsigned bfd_align = bfd_get_section_alignment (abfd, sec);
obj_mach_o_set_vma_data *p = (struct obj_mach_o_set_vma_data *)v_p;
unsigned sectype = (ms->flags & BFD_MACH_O_SECTION_TYPE_MASK);
unsigned zf;
zf = 0;
if (sectype == BFD_MACH_O_S_ZEROFILL)
{
zf = 1;
p->zerofill_seen = zf;
}
else if (sectype == BFD_MACH_O_S_GB_ZEROFILL)
{
zf = 2;
p->gb_zerofill_seen = zf;
}
if (p->vma_pass != zf)
return;
/* We know the section size now - so make a vma for the section just
based on order. */
ms->size = bfd_get_section_size (sec);
/* Make sure that the align agrees, and set to the largest value chosen. */
ms->align = ms->align > bfd_align ? ms->align : bfd_align;
bfd_set_section_alignment (abfd, sec, ms->align);
p->vma += (1 << ms->align) - 1;
p->vma &= ~((1 << ms->align) - 1);
ms->addr = p->vma;
bfd_set_section_vma (abfd, sec, p->vma);
p->vma += ms->size;
}
/* (potentially) three passes over the sections, setting VMA. We skip the
{gb}zerofill passes if we didn't see any of the relevant sections. */
void obj_mach_o_post_relax_hook (void)
{
obj_mach_o_set_vma_data d;
memset (&d, 0, sizeof (d));
bfd_map_over_sections (stdoutput, obj_mach_o_set_section_vma, (char *) &d);
if ((d.vma_pass = d.zerofill_seen) != 0)
bfd_map_over_sections (stdoutput, obj_mach_o_set_section_vma, (char *) &d);
if ((d.vma_pass = d.gb_zerofill_seen) != 0)
bfd_map_over_sections (stdoutput, obj_mach_o_set_section_vma, (char *) &d);
}
static void
obj_mach_o_set_indirect_symbols (bfd *abfd, asection *sec,
void *xxx ATTRIBUTE_UNUSED)