diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2016-02-02 17:15:03 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2016-02-05 11:19:29 -0800 |
commit | def81d5c71838aa1510340540c2efb4501180d0a (patch) | |
tree | 5e3a4d529c908d04cef3db6221502f30acfdf40e | |
parent | f0d92fd19ad01b99a93a766f482d2ecaa3ca91a8 (diff) | |
download | nasm-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.c | 50 |
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); } |