summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2016-02-16 12:56:27 -0800
committerH. Peter Anvin <hpa@linux.intel.com>2016-02-16 12:56:27 -0800
commit6fc2b123afaaf57577581a7680aa41fe101fd86b (patch)
treebfce6df922d9a71bcecbe707c5c2eccb7a99c476
parentd1da074b837cd8f56f2eca3e622cdfe2de20dbec (diff)
downloadnasm-6fc2b123afaaf57577581a7680aa41fe101fd86b.tar.gz
outmacho: if .rodata contains no relocations, change it to __TEXT,__const
If we specify .rodata as opposed to the explicit __DATA,__const, and we end up with no relocations, change it to __TEXT,__const per the Mach-O ABI. However, it is generally better for the programmer to explicitly specify the items that should go into __TEXT,__const as otherwise a single relocatable item will force the whole thing into __DATA. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--output/outmacho.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/output/outmacho.c b/output/outmacho.c
index e39d655f..6872a7bf 100644
--- a/output/outmacho.c
+++ b/output/outmacho.c
@@ -114,6 +114,7 @@ struct section {
int32_t index;
struct reloc *relocs;
int align;
+ bool by_name; /* This section was specified by full MachO name */
/* data that goes into the file */
char sectname[16]; /* what this section is called */
@@ -248,7 +249,6 @@ static uint64_t seg_vmsize = 0;
static uint32_t seg_nsects = 0;
static uint64_t rel_padcnt = 0;
-
#define xstrncpy(xdst, xsrc) \
memset(xdst, '\0', sizeof(xdst)); /* zero out whole buffer */ \
strncpy(xdst, xsrc, sizeof(xdst)); /* copy over string */ \
@@ -632,14 +632,14 @@ static int32_t macho_section(char *name, int pass, int *bits)
len = strlen(segment);
if (len == 0) {
nasm_error(ERR_NONFATAL, "empty segment name\n");
- } else if (len > 16) {
+ } else if (len >= 16) {
nasm_error(ERR_NONFATAL, "segment name %s too long\n", segment);
}
len = strlen(section);
if (len == 0) {
nasm_error(ERR_NONFATAL, "empty section name\n");
- } else if (len > 16) {
+ } else if (len >= 16) {
nasm_error(ERR_NONFATAL, "section name %s too long\n", section);
}
@@ -682,6 +682,7 @@ static int32_t macho_section(char *name, int pass, int *bits)
s->align = -1;
s->pad = -1;
s->offset = -1;
+ s->by_name = false;
xstrncpy(s->segname, segment);
xstrncpy(s->sectname, section);
@@ -697,6 +698,8 @@ static int32_t macho_section(char *name, int pass, int *bits)
if (comma)
*comma = ','; /* Restore comma */
+ s->by_name = s->by_name || comma; /* Was specified by name */
+
flags = (uint32_t)-1;
while ((NULL != sectionAttributes)
@@ -1114,6 +1117,17 @@ static uint32_t macho_write_segment (uint64_t offset)
s->flags |= S_ATTR_LOC_RELOC;
if (s->extreloc)
s->flags |= S_ATTR_EXT_RELOC;
+ } else if (!strcmp(s->segname, "__DATA") &&
+ !strcmp(s->sectname, "__const") &&
+ !s->by_name &&
+ !get_section_by_name("__TEXT", "__const")) {
+ /*
+ * The MachO equivalent to .rodata can be either
+ * __DATA,__const or __TEXT,__const; the latter only if
+ * there are no relocations. However, when mixed it is
+ * better to specify the segments explicitly.
+ */
+ xstrncpy(s->segname, "__TEXT");
}
fwriteint32_t(s->flags, ofile); /* flags */