aboutsummaryrefslogtreecommitdiff
path: root/gas/config/obj-macho.c
diff options
context:
space:
mode:
authorIain Sandoe <iain@codesourcery.com>2012-01-13 11:55:02 +0000
committerIain Sandoe <iain@codesourcery.com>2012-01-13 11:55:02 +0000
commitc3402d205655e74dda81fd58387a2d5fac870dea (patch)
treeb9ce4a2fc0a8c5fb2484fb16f5d3e918fc1ab561 /gas/config/obj-macho.c
parentee5106fedefc3b2378641dbfaac0b4c5a919584e (diff)
downloadgdb-c3402d205655e74dda81fd58387a2d5fac870dea.zip
gdb-c3402d205655e74dda81fd58387a2d5fac870dea.tar.gz
gdb-c3402d205655e74dda81fd58387a2d5fac870dea.tar.bz2
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.
Diffstat (limited to 'gas/config/obj-macho.c')
-rw-r--r--gas/config/obj-macho.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/gas/config/obj-macho.c b/gas/config/obj-macho.c
index 61e6771..988b098 100644
--- a/gas/config/obj-macho.c
+++ b/gas/config/obj-macho.c
@@ -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)