diff --git a/asm/labels.c b/asm/labels.c index 94a57ac2..eec5a844 100644 --- a/asm/labels.c +++ b/asm/labels.c @@ -92,6 +92,7 @@ static const char * const types[] = union label { /* actual label structures */ struct { int32_t segment; + int32_t subsection; /* Available for ofmt->herelabel() */ int64_t offset; int64_t size; char *label, *mangled, *special; @@ -231,6 +232,7 @@ static union label *find_label(const char *label, bool create, bool *created) nasm_zero(*lfree); lfree->admin.movingon = BOGUS_VALUE; lfree->defn.label = perm_copy(label); + lfree->defn.subsection = NO_SEG; if (label_str) nasm_free(label_str); @@ -321,7 +323,7 @@ static const char *mangle_label_name(union label *lptr) } static void -handle_herelabel(const union label *lptr, int32_t *segment, int64_t *offset) +handle_herelabel(union label *lptr, int32_t *segment, int64_t *offset) { int32_t oldseg; @@ -338,7 +340,8 @@ handle_herelabel(const union label *lptr, int32_t *segment, int64_t *offset) int32_t newseg; nasm_assert(lptr->defn.mangled); - newseg = ofmt->herelabel(lptr->defn.mangled, lptr->defn.type, oldseg); + newseg = ofmt->herelabel(lptr->defn.mangled, lptr->defn.type, + oldseg, &lptr->defn.subsection); if (likely(newseg == oldseg)) return; diff --git a/asm/nasm.c b/asm/nasm.c index 4e922b4a..94bbc6b2 100644 --- a/asm/nasm.c +++ b/asm/nasm.c @@ -91,6 +91,7 @@ static const char *debug_format; # define ABORT_ON_PANIC 0 #endif static bool abort_on_panic = ABORT_ON_PANIC; +static bool keep_all; bool tasm_compatible_mode = false; int pass0, passn; @@ -540,7 +541,7 @@ int main(int argc, char **argv) preproc->cleanup(0); if (ofile) fclose(ofile); - if (ofile && terminate_after_phase) + if (ofile && terminate_after_phase && !keep_all) remove(outname); ofile = NULL; } @@ -576,7 +577,7 @@ int main(int argc, char **argv) if (ofile) { fclose(ofile); - if (terminate_after_phase) + if (terminate_after_phase && !keep_all) remove(outname); ofile = NULL; } @@ -786,7 +787,8 @@ enum text_options { OPT_INCLUDE, OPT_PRAGMA, OPT_BEFORE, - OPT_LIMIT + OPT_LIMIT, + OPT_KEEP_ALL }; struct textargs { const char *label; @@ -809,6 +811,7 @@ static const struct textargs textopts[] = { {"pragma", OPT_PRAGMA, true, 0}, {"before", OPT_BEFORE, true, 0}, {"limit-", OPT_LIMIT, true, 0}, + {"keep-all", OPT_KEEP_ALL, false, 0}, {NULL, OPT_BOGUS, false, 0} }; @@ -1155,6 +1158,9 @@ static bool process_arg(char *p, char *q, int pass) if (pass == 2) nasm_set_limit(p+olen, param); break; + case OPT_KEEP_ALL: + keep_all = true; + break; case OPT_HELP: help(0); exit(0); @@ -1400,7 +1406,7 @@ static void assemble_file(const char *fname, StrList **depend_ptr) cpu = cmd_cpu; if (pass0 == 2) { lfmt->init(listname); - } else if (passn == 1 && listname) { + } else if (passn == 1 && listname && !keep_all) { /* Remove the list file in case we die before the output pass */ remove(listname); } @@ -1859,7 +1865,8 @@ static void nasm_verror_common(int severity, const char *fmt, va_list args) case ERR_FATAL: if (ofile) { fclose(ofile); - remove(outname); + if (!keep_all) + remove(outname); ofile = NULL; } if (want_usage) @@ -1874,7 +1881,8 @@ static void nasm_verror_common(int severity, const char *fmt, va_list args) if (ofile) { fclose(ofile); - remove(outname); + if (!keep_all) + remove(outname); ofile = NULL; } exit(3); diff --git a/include/nasm.h b/include/nasm.h index c1ecf8a1..a801da46 100644 --- a/include/nasm.h +++ b/include/nasm.h @@ -915,8 +915,11 @@ struct ofmt { * This is *only* called if the symbol defined is at the * current offset, i.e. "foo:" or "foo equ $". * 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. */ - int32_t (*herelabel)(const char *name, enum label_type type, int32_t seg); + int32_t (*herelabel)(const char *name, enum label_type type, + int32_t seg, int32_t *subsection); /* * This procedure is called to modify section alignment, diff --git a/output/outdbg.c b/output/outdbg.c index 4d41d4db..84cccf73 100644 --- a/output/outdbg.c +++ b/output/outdbg.c @@ -136,15 +136,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 seg) + int32_t oldseg, int32_t *subsection) { - int32_t newseg = seg; - - if (subsections_via_symbols && type != LBL_LOCAL) - newseg += 0x10000; + int32_t newseg = oldseg; + if (subsections_via_symbols && type != LBL_LOCAL) { + newseg = *subsection; + if (newseg == NO_SEG) + newseg = *subsection = seg_alloc(); + } fprintf(ofile, "herelabel %s type %d (seg %08x) -> %08x\n", - name, type, seg, newseg); + name, type, oldseg, newseg); return newseg; } diff --git a/output/outmacho.c b/output/outmacho.c index ed1366b3..e4aa8000 100644 --- a/output/outmacho.c +++ b/output/outmacho.c @@ -1003,10 +1003,11 @@ 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 section, int32_t *subsection) { struct section *s; (void)name; + (void)subsection; if (!(head_flags & MH_SUBSECTIONS_VIA_SYMBOLS)) return section; @@ -1014,7 +1015,7 @@ static int32_t macho_herelabel(const char *name, enum label_type type, /* No subsection only for local labels */ if (type == LBL_LOCAL) return section; - + s = get_section_by_index(section); if (!s) return section;