summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2016-02-02 17:15:03 -0800
committerH. Peter Anvin <hpa@linux.intel.com>2016-02-05 11:19:29 -0800
commitdef81d5c71838aa1510340540c2efb4501180d0a (patch)
tree5e3a4d529c908d04cef3db6221502f30acfdf40e
parentf0d92fd19ad01b99a93a766f482d2ecaa3ca91a8 (diff)
downloadnasm-def81d5c71838aa1510340540c2efb4501180d0a.tar.gz
outmac64: Fix the handling of section data alignment
Fix a number of places which failed to account for padding to alignment of section data. Also, fix confusion between aligning section data in the linkable object code and final address alignment; LLVM/Xcode always align section data to 4 bytes (with a comment saying that it probably should be 8 bytes for 64-bit output) independent of the section alignment. This will need to be ported to the macho32 backend, as well; ideally the two should be merged as they are really very similar and we don't want to have these kinds of cross-porting problems. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--output/outmac64.c50
1 files changed, 30 insertions, 20 deletions
diff --git a/output/outmac64.c b/output/outmac64.c
index b4a46d84..d1a0a5c0 100644
--- a/output/outmac64.c
+++ b/output/outmac64.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2013 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2016 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -94,9 +94,10 @@ struct section {
char segname[16]; /* segment this section will be in */
uint64_t addr; /* in-memory address (subject to alignment) */
uint64_t size; /* in-memory and -file size */
+ uint32_t pad; /* padding bytes before section */
uint32_t nreloc; /* relocation entry count */
uint32_t flags; /* type and attributes (masked) */
- uint32_t extreloc; /* external relocations */
+ uint32_t extreloc; /* external relocations */
};
#define SECTION_TYPE 0x000000ff /* section type mask */
@@ -667,6 +668,7 @@ static int32_t macho_section(char *name, int pass, int *bits)
s->index = seg_alloc();
s->relocs = NULL;
s->align = -1;
+ s->pad = -1;
xstrncpy(s->segname, sm->segname);
xstrncpy(s->sectname, sm->sectname);
@@ -966,24 +968,31 @@ static void macho_calculate_sizes (void)
/* count sections and calculate in-memory and in-file offsets */
for (s = sects; s != NULL; s = s->next) {
- uint64_t pad = 0;
-
- /* zerofill sections aren't actually written to the file */
- if ((s->flags & SECTION_TYPE) != S_ZEROFILL)
- seg_filesize64 += s->size;
+ uint64_t newaddr;
/* recalculate segment address based on alignment and vm size */
s->addr = seg_vmsize64;
+
/* we need section alignment to calculate final section address */
if (s->align == -1)
s->align = DEFAULT_SECTION_ALIGNMENT;
- if(s->align) {
- uint64_t newaddr = ALIGN(s->addr, 1 << s->align);
- pad = newaddr - s->addr;
- s->addr = newaddr;
- }
- seg_vmsize64 += s->size + pad;
+ newaddr = ALIGN(s->addr, 1 << s->align);
+ s->addr = newaddr;
+
+ seg_vmsize64 = newaddr + s->size;
+
+ /* zerofill sections aren't actually written to the file */
+ if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
+ /*
+ * LLVM/Xcode as always aligns the section data to 4
+ * bytes; there is a comment in the LLVM source code that
+ * perhaps aligning to pointer size would be better.
+ */
+ s->pad = ALIGN(seg_filesize64, 4) - seg_filesize64;
+ seg_filesize64 += s->size + s->pad;
+ }
+
++seg_nsects64;
}
@@ -1050,7 +1059,10 @@ static uint32_t macho_write_segment (uint64_t offset)
/* dummy data for zerofill sections or proper values */
if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
+ nasm_assert(s->pad != (uint32_t)-1);
+ offset += s->pad;
fwriteint32_t(offset, ofile);
+ offset += s->size;
/* Write out section alignment, as a power of two.
e.g. 32-bit word alignment would be 2 (2^2 = 4). */
if (s->align == -1)
@@ -1061,11 +1073,10 @@ static uint32_t macho_write_segment (uint64_t offset)
fwriteint32_t(s->nreloc ? rel_base + s_reloff : 0, ofile);
fwriteint32_t(s->nreloc, ofile);
- offset += s->size;
s_reloff += s->nreloc * MACHO_RELINFO64_SIZE;
} else {
fwriteint32_t(0, ofile);
- fwriteint32_t(0, ofile);
+ fwriteint32_t(0, ofile); /* No alignment?! */
fwriteint32_t(0, ofile);
fwriteint32_t(0, ofile);
}
@@ -1077,10 +1088,10 @@ static uint32_t macho_write_segment (uint64_t offset)
}
fwriteint32_t(s->flags, ofile); /* flags */
- fwriteint32_t(0, ofile); /* reserved */
- fwriteint32_t(0, ofile); /* reserved */
+ fwriteint32_t(0, ofile); /* reserved */
+ fwriteint32_t(0, ofile); /* reserved */
- fwriteint32_t(0, ofile); /* align */
+ fwriteint32_t(0, ofile); /* align */
}
rel_padcnt64 = rel_base - offset;
@@ -1122,8 +1133,6 @@ static void macho_write_section (void)
if ((s->flags & SECTION_TYPE) == S_ZEROFILL)
continue;
- /* no padding needs to be done to the sections */
-
/* Like a.out Mach-O references things in the data or bss
* sections by addresses which are actually relative to the
* start of the _text_ section, in the _file_. See outaout.c
@@ -1184,6 +1193,7 @@ static void macho_write_section (void)
}
/* dump the section data to file */
+ fwritezero(s->pad, ofile);
saa_fpwrite(s->data, ofile);
}