summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin (Intel) <hpa@zytor.com>2018-06-27 20:20:21 -0700
committerH. Peter Anvin (Intel) <hpa@zytor.com>2018-06-27 20:20:21 -0700
commitd644119ded5aa963e334ec035f782c0b244d855c (patch)
treebbcc106c989f81ce40ff8ddb75d4ab83ce966ef6
parent12810fac9294cd205f3d7a4a1ce9fab480e42f89 (diff)
downloadnasm-d644119ded5aa963e334ec035f782c0b244d855c.tar.gz
subsections: don't lose the offset in the parent section
We don't want to lose the offset into the parent section when we create a subsection, at least not for the MachO backend which is currently the only user of subsections. Allow ofmt->herelabel() to set a flag to copy the section offset from the previous section. Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
-rw-r--r--asm/labels.c12
-rw-r--r--include/nasm.h7
-rw-r--r--output/outdbg.c7
-rw-r--r--output/outmacho.c8
4 files changed, 26 insertions, 8 deletions
diff --git a/asm/labels.c b/asm/labels.c
index 93a687ea..fbc4396b 100644
--- a/asm/labels.c
+++ b/asm/labels.c
@@ -351,15 +351,23 @@ handle_herelabel(union label *lptr, int32_t *segment, int64_t *offset)
if (oldseg == location.segment && *offset == location.offset) {
/* This label is defined at this location */
int32_t newseg;
+ bool copyoffset = false;
nasm_assert(lptr->defn.mangled);
newseg = ofmt->herelabel(lptr->defn.mangled, lptr->defn.type,
- oldseg, &lptr->defn.subsection);
+ oldseg, &lptr->defn.subsection, &copyoffset);
if (likely(newseg == oldseg))
return;
*segment = newseg;
- *offset = switch_segment(newseg);
+ if (copyoffset) {
+ /* Maintain the offset from the old to the new segment */
+ switch_segment(newseg);
+ location.offset = *offset;
+ } else {
+ /* Keep a separate offset for the new segment */
+ *offset = switch_segment(newseg);
+ }
}
}
diff --git a/include/nasm.h b/include/nasm.h
index 9eae9b8b..b9f730c8 100644
--- a/include/nasm.h
+++ b/include/nasm.h
@@ -911,9 +911,14 @@ struct ofmt {
* The offset isn't passed; and may not be stable at this point.
* The subsection number is a field available for use by the
* backend. It is initialized to NO_SEG.
+ *
+ * If "copyoffset" is set by the backend then the offset is
+ * copied from the previous segment, otherwise the new segment
+ * is treated as a new segment the normal way.
*/
int32_t (*herelabel)(const char *name, enum label_type type,
- int32_t seg, int32_t *subsection);
+ int32_t seg, int32_t *subsection,
+ bool *copyoffset);
/*
* This procedure is called to modify section alignment,
diff --git a/output/outdbg.c b/output/outdbg.c
index a28e85f7..debe30f7 100644
--- a/output/outdbg.c
+++ b/output/outdbg.c
@@ -137,14 +137,17 @@ static int32_t dbg_section_names(char *name, int pass, int *bits)
}
static int32_t dbg_herelabel(const char *name, enum label_type type,
- int32_t oldseg, int32_t *subsection)
+ int32_t oldseg, int32_t *subsection,
+ bool *copyoffset)
{
int32_t newseg = oldseg;
if (subsections_via_symbols && type != LBL_LOCAL) {
newseg = *subsection;
- if (newseg == NO_SEG)
+ if (newseg == NO_SEG) {
newseg = *subsection = seg_alloc();
+ *copyoffset = true; /* Minic MachO for now */
+ }
}
fprintf(ofile, "herelabel %s type %d (seg %08x) -> %08x\n",
name, type, oldseg, newseg);
diff --git a/output/outmacho.c b/output/outmacho.c
index 75650b47..93b4768e 100644
--- a/output/outmacho.c
+++ b/output/outmacho.c
@@ -1018,7 +1018,8 @@ static int32_t macho_section(char *name, int pass, int *bits)
}
static int32_t macho_herelabel(const char *name, enum label_type type,
- int32_t section, int32_t *subsection)
+ int32_t section, int32_t *subsection,
+ bool *copyoffset)
{
struct section *s;
int32_t subsec;
@@ -1043,6 +1044,7 @@ static int32_t macho_herelabel(const char *name, enum label_type type,
}
s->subsection = subsec;
+ *copyoffset = true; /* Maintain previous offset */
return subsec;
}
@@ -1055,8 +1057,8 @@ static void macho_symdef(char *name, int32_t section, int64_t offset,
#if defined(DEBUG) && DEBUG>2
nasm_error(ERR_DEBUG,
- " macho_symdef: %s, sec=%"PRIx32", off=%"PRIx64", is_global=%d, %s\n",
- name, section, offset, is_global, special);
+ " macho_symdef: %s, pass0=%d, passn=%"PRId64", sec=%"PRIx32", off=%"PRIx64", is_global=%d, %s\n",
+ name, pass0, passn, section, offset, is_global, special);
#endif
if (is_global == 3) {