diff options
author | H. Peter Anvin (Intel) <hpa@zytor.com> | 2018-06-27 20:20:21 -0700 |
---|---|---|
committer | H. Peter Anvin (Intel) <hpa@zytor.com> | 2018-06-27 20:20:21 -0700 |
commit | d644119ded5aa963e334ec035f782c0b244d855c (patch) | |
tree | bbcc106c989f81ce40ff8ddb75d4ab83ce966ef6 | |
parent | 12810fac9294cd205f3d7a4a1ce9fab480e42f89 (diff) | |
download | nasm-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.c | 12 | ||||
-rw-r--r-- | include/nasm.h | 7 | ||||
-rw-r--r-- | output/outdbg.c | 7 | ||||
-rw-r--r-- | output/outmacho.c | 8 |
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, ©offset); 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) { |