summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2016-02-11 20:24:53 -0800
committerH. Peter Anvin <hpa@linux.intel.com>2016-02-11 20:24:53 -0800
commit5507ad585fa98ff81e84350eb3d94183714580c6 (patch)
treed595a41abc715aa33c83a309540e112eaab1dfc3
parent1c10ad65feabeb08a9f1bb16f28128c02dfe557e (diff)
parentf30d96d1c025d1a9c9453ed225f78d6b156da5f9 (diff)
downloadnasm-5507ad585fa98ff81e84350eb3d94183714580c6.tar.gz
Merge branch 'machofix'
This fixes the macho64 output. However, macho32 has the same problems and the code either needs to be backported or, better yet, unified. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--listing.c2
-rw-r--r--nasmlib.h2
-rw-r--r--output/codeview.c4
-rw-r--r--output/outaout.c2
-rw-r--r--output/outas86.c2
-rw-r--r--output/outbin.c2
-rw-r--r--output/outcoff.c4
-rw-r--r--output/outelf32.c2
-rw-r--r--output/outelf64.c2
-rw-r--r--output/outelfx32.c2
-rw-r--r--output/outieee.c2
-rw-r--r--output/outmac32.c2
-rw-r--r--output/outmac64.c107
-rw-r--r--output/outobj.c2
-rw-r--r--output/outrdf2.c2
15 files changed, 78 insertions, 61 deletions
diff --git a/listing.c b/listing.c
index 18e949b4..49f5e15d 100644
--- a/listing.c
+++ b/listing.c
@@ -216,7 +216,7 @@ static void list_output(int32_t offset, const void *data,
break;
}
case OUT_ADDRESS:
- list_address(offset, "[]", *(int64_t *)data, abs(size));
+ list_address(offset, "[]", *(int64_t *)data, abs((int)size));
break;
case OUT_REL1ADR:
list_address(offset, "()", *(int64_t *)data, 1);
diff --git a/nasmlib.h b/nasmlib.h
index 47e9a0ae..86766e37 100644
--- a/nasmlib.h
+++ b/nasmlib.h
@@ -260,6 +260,8 @@ void standard_extension(char *inname, char *outname, char *extension);
/*
* Power of 2 align helpers
*/
+#undef ALIGN_MASK /* Some BSD flavors define these in system headers */
+#undef ALIGN
#define ALIGN_MASK(v, mask) (((v) + (mask)) & ~(mask))
#define ALIGN(v, a) ALIGN_MASK(v, (a) - 1)
#define IS_ALIGNED(v, a) (((v) & ((a) - 1)) == 0)
diff --git a/output/codeview.c b/output/codeview.c
index 4256e8dd..2f5bb690 100644
--- a/output/codeview.c
+++ b/output/codeview.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2010 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.
*
@@ -402,7 +402,7 @@ static void register_reloc(struct coff_Section *const sect,
for (uint32_t i = 0; i < coff_nsyms; i++) {
struct coff_Symbol *s = saa_rstruct(coff_syms);
r->symbol++;
- if (s->strpos == -1 && s->name && !strcmp(sym, s->name)) {
+ if (s->strpos == -1 && !strcmp(sym, s->name)) {
return;
} else if (s->strpos != -1) {
int res;
diff --git a/output/outaout.c b/output/outaout.c
index 575089c6..1b2b2191 100644
--- a/output/outaout.c
+++ b/output/outaout.c
@@ -634,7 +634,7 @@ static void aout_out(int32_t segto, const void *data,
nasm_error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
aout_sect_write(s, data, size);
} else if (type == OUT_ADDRESS) {
- int asize = abs(size);
+ int asize = abs((int)size);
addr = *(int64_t *)data;
if (segment != NO_SEG) {
if (segment % 2) {
diff --git a/output/outas86.c b/output/outas86.c
index a800e90f..892362b6 100644
--- a/output/outas86.c
+++ b/output/outas86.c
@@ -347,7 +347,7 @@ static void as86_out(int32_t segto, const void *data,
as86_sect_write(s, data, size);
as86_add_piece(s, 0, 0L, 0L, size, 0);
} else if (type == OUT_ADDRESS) {
- int asize = abs(size);
+ int asize = abs((int)size);
if (segment != NO_SEG) {
if (segment % 2) {
nasm_error(ERR_NONFATAL, "as86 format does not support"
diff --git a/output/outbin.c b/output/outbin.c
index 77a9778f..c64daaaf 100644
--- a/output/outbin.c
+++ b/output/outbin.c
@@ -765,7 +765,7 @@ static void bin_out(int32_t segto, const void *data,
switch (type) {
case OUT_ADDRESS:
{
- int asize = abs(size);
+ int asize = abs((int)size);
if (segment != NO_SEG && !find_section_by_index(segment)) {
if (segment % 2)
diff --git a/output/outcoff.c b/output/outcoff.c
index b45e4f16..73ba13e3 100644
--- a/output/outcoff.c
+++ b/output/outcoff.c
@@ -611,7 +611,7 @@ static void coff_out(int32_t segto, const void *data,
dinfo.section = s;
if (type == OUT_ADDRESS)
- dinfo.size = abs(size);
+ dinfo.size = abs((int)size);
else
dinfo.size = realsize(type, size);
@@ -630,7 +630,7 @@ static void coff_out(int32_t segto, const void *data,
nasm_error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
coff_sect_write(s, data, size);
} else if (type == OUT_ADDRESS) {
- int asize = abs(size);
+ int asize = abs((int)size);
if (!win64) {
if (asize != 4 && (segment != NO_SEG || wrt != NO_SEG)) {
nasm_error(ERR_NONFATAL, "COFF format does not support non-32-bit"
diff --git a/output/outelf32.c b/output/outelf32.c
index 4489d401..7ac78050 100644
--- a/output/outelf32.c
+++ b/output/outelf32.c
@@ -730,7 +730,7 @@ static void elf_out(int32_t segto, const void *data,
case OUT_ADDRESS:
{
bool gnu16 = false;
- int asize = abs(size);
+ int asize = abs((int)size);
addr = *(int64_t *)data;
if (segment != NO_SEG) {
if (segment % 2) {
diff --git a/output/outelf64.c b/output/outelf64.c
index 41243b1e..3c3e921a 100644
--- a/output/outelf64.c
+++ b/output/outelf64.c
@@ -746,7 +746,7 @@ static void elf_out(int32_t segto, const void *data,
case OUT_ADDRESS:
{
int isize = (int)size;
- int asize = abs(size);
+ int asize = abs((int)size);
addr = *(int64_t *)data;
if (segment == NO_SEG) {
diff --git a/output/outelfx32.c b/output/outelfx32.c
index 3eeb224f..33972b41 100644
--- a/output/outelfx32.c
+++ b/output/outelfx32.c
@@ -745,7 +745,7 @@ static void elf_out(int32_t segto, const void *data,
case OUT_ADDRESS:
{
int isize = (int)size;
- int asize = abs(size);
+ int asize = abs((int)size);
addr = *(int64_t *)data;
if (segment == NO_SEG) {
diff --git a/output/outieee.c b/output/outieee.c
index 56060db1..d42a6fd8 100644
--- a/output/outieee.c
+++ b/output/outieee.c
@@ -438,7 +438,7 @@ static void ieee_out(int32_t segto, const void *data,
} else if (type == OUT_ADDRESS || type == OUT_REL2ADR ||
type == OUT_REL4ADR) {
if (type == OUT_ADDRESS)
- size = abs(size);
+ size = abs((int)size);
else if (segment == NO_SEG)
nasm_error(ERR_NONFATAL, "relative call to absolute address not"
" supported by IEEE format");
diff --git a/output/outmac32.c b/output/outmac32.c
index 0ed88c99..873ed7e1 100644
--- a/output/outmac32.c
+++ b/output/outmac32.c
@@ -434,7 +434,7 @@ static void macho_output(int32_t secto, const void *data,
case OUT_ADDRESS:
{
- int asize = abs(size);
+ int asize = abs((int)size);
addr = *(int64_t *)data;
diff --git a/output/outmac64.c b/output/outmac64.c
index b4a46d84..5c8a0dc6 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.
*
@@ -59,10 +59,11 @@
/* Mach-O in-file header structure sizes */
#define MACHO_HEADER64_SIZE (32)
#define MACHO_SEGCMD64_SIZE (72)
-#define MACHO_SECTCMD64_SIZE (80)
+#define MACHO_SECTCMD64_SIZE (80)
#define MACHO_SYMCMD_SIZE (24)
#define MACHO_NLIST64_SIZE (16)
-#define MACHO_RELINFO64_SIZE (8)
+#define MACHO_RELINFO64_SIZE (8)
+#define MACHO_DATA_IN_CODE_CMD_SIZE (16)
/* Mach-O file header values */
#define MH_MAGIC_64 (0xfeedfacf)
@@ -72,6 +73,7 @@
#define LC_SEGMENT_64 (0x19) /* segment load command */
#define LC_SYMTAB (0x2) /* symbol table load command */
+#define LC_DATA_IN_CODE (0x29) /* data in code command */
#define VM_PROT_NONE (0x00)
#define VM_PROT_READ (0x01)
@@ -94,9 +96,11 @@ 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 */
+ uint64_t offset; /* in-file offset */
+ 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 */
@@ -178,7 +182,7 @@ struct symbol {
#define NO_SECT 0 /* no section, invalid */
#define MAX_SECT 255 /* maximum number of sections */
-static struct section *sects, **sectstail;
+static struct section *sects, **sectstail, **sectstab;
static struct symbol *syms, **symstail;
static uint32_t nsyms;
@@ -437,7 +441,7 @@ static int32_t add_reloc(struct section *sect, int32_t section,
/* inter-section */
} else {
- r->type = 2; // X86_64_RELOC_BRANCH
+ r->type = 1; // X86_64_RELOC_SIGNED
fi = get_section_fileindex_by_index(section);
/* external */
@@ -535,7 +539,7 @@ static void macho_output(int32_t secto, const void *data,
case OUT_ADDRESS:
{
- int asize = abs(size);
+ int asize = abs((int)size);
addr = *(int64_t *)data;
if (section != NO_SEG) {
@@ -667,6 +671,8 @@ static int32_t macho_section(char *name, int pass, int *bits)
s->index = seg_alloc();
s->relocs = NULL;
s->align = -1;
+ s->pad = -1;
+ s->offset = -1;
xstrncpy(s->segname, sm->segname);
xstrncpy(s->sectname, sm->sectname);
@@ -963,27 +969,36 @@ static void macho_layout_symbols (uint32_t *numsyms,
static void macho_calculate_sizes (void)
{
struct section *s;
+ int fi;
/* 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;
+ s->offset = seg_filesize64 + s->pad;
+ seg_filesize64 += s->size + s->pad;
+ }
+
++seg_nsects64;
}
@@ -999,6 +1014,12 @@ static void macho_calculate_sizes (void)
++head_ncmds64;
head_sizeofcmds64 += MACHO_SYMCMD_SIZE;
}
+
+ /* Create a table of sections by file index to avoid linear search */
+ sectstab = nasm_malloc((seg_nsects64 + 1) * sizeof(*sectstab));
+ sectstab[0] = NULL;
+ for (s = sects, fi = 1; s != NULL; s = s->next, fi++)
+ sectstab[fi] = s;
}
/* Write out the header information for the file. */
@@ -1026,8 +1047,9 @@ static uint32_t macho_write_segment (uint64_t offset)
fwriteint32_t(LC_SEGMENT_64, ofile); /* cmd == LC_SEGMENT_64 */
/* size of load command including section load commands */
- fwriteint32_t(MACHO_SEGCMD64_SIZE + seg_nsects64 *
- MACHO_SECTCMD64_SIZE, ofile);
+ fwriteint32_t(MACHO_SEGCMD64_SIZE +
+ seg_nsects64 * MACHO_SECTCMD64_SIZE,
+ ofile);
/* in an MH_OBJECT file all sections are in one unnamed (name
** all zeros) segment */
@@ -1050,7 +1072,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 +1086,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 +1101,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 +1146,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 +1206,7 @@ static void macho_write_section (void)
}
/* dump the section data to file */
+ fwritezero(s->pad, ofile);
saa_fpwrite(s->data, ofile);
}
@@ -1200,8 +1223,6 @@ static void macho_write_section (void)
static void macho_write_symtab (void)
{
struct symbol *sym;
- struct section *s;
- int64_t fi;
uint64_t i;
/* we don't need to pad here since MACHO_RELINFO_SIZE == 8 */
@@ -1216,12 +1237,8 @@ static void macho_write_symtab (void)
/* Fix up the symbol value now that we know the final section
sizes. */
if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
- for (s = sects, fi = 1; s != NULL; s = s->next, fi++) {
- if (fi == sym->sect) {
- sym->value += s->addr;
- break;
- }
- }
+ nasm_assert(sym->sect <= seg_nsects64);
+ sym->value += sectstab[sym->sect]->addr;
}
fwriteint64_t(sym->value, ofile); /* value (i.e. offset) */
@@ -1238,9 +1255,8 @@ static void macho_write_symtab (void)
/* Fix up the symbol value now that we know the final section
sizes. */
if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
- for (s = sects, fi = 1;
- s != NULL && fi < sym->sect; s = s->next, ++fi)
- sym->value += s->size;
+ nasm_assert(sym->sect <= seg_nsects64);
+ sym->value += sectstab[sym->sect]->addr;
}
fwriteint64_t(sym->value, ofile); /* value (i.e. offset) */
@@ -1255,9 +1271,8 @@ static void macho_write_symtab (void)
// Fix up the symbol value now that we know the final section sizes.
if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
- for (s = sects, fi = 1;
- s != NULL && fi < sym->sect; s = s->next, ++fi)
- sym->value += s->size;
+ nasm_assert(sym->sect <= seg_nsects64);
+ sym->value += sectstab[sym->sect]->addr;
}
fwriteint64_t(sym->value, ofile); // value (i.e. offset)
@@ -1381,7 +1396,6 @@ static void macho_write (void)
fwriteint32_t(offset, ofile); /* symbol table offset */
fwriteint32_t(nsyms, ofile); /* number of symbol
** table entries */
-
offset += nsyms * MACHO_NLIST64_SIZE;
fwriteint32_t(offset, ofile); /* string table offset */
fwriteint32_t(strslen, ofile); /* string table size */
@@ -1442,14 +1456,15 @@ static void macho_cleanup(int debuginfo)
saa_free(strs);
raa_free(extsyms);
- if (syms) {
- while (syms->next) {
+ while (syms) {
sym = syms;
syms = syms->next;
-
nasm_free (sym);
}
-}
+
+ nasm_free(extdefsyms);
+ nasm_free(undefsyms);
+ nasm_free(sectstab);
}
/* Debugging routines. */
diff --git a/output/outobj.c b/output/outobj.c
index 6b173eb9..c9f40094 100644
--- a/output/outobj.c
+++ b/output/outobj.c
@@ -1087,7 +1087,7 @@ static void obj_out(int32_t segto, const void *data,
int rsize;
if (type == OUT_ADDRESS)
- size = abs(size);
+ size = abs((int)size);
if (segment == NO_SEG && type != OUT_ADDRESS)
nasm_error(ERR_NONFATAL, "relative call to absolute address not"
diff --git a/output/outrdf2.c b/output/outrdf2.c
index fdac5ee3..884cdf44 100644
--- a/output/outrdf2.c
+++ b/output/outrdf2.c
@@ -583,7 +583,7 @@ static void rdf2_out(int32_t segto, const void *data,
membufwrite(segto, data, size);
} else if (type == OUT_ADDRESS) {
- int asize = abs(size);
+ int asize = abs((int)size);
/* if segment == NO_SEG then we are writing an address of an
object within the same segment - do not produce reloc rec. */