labels: add a subsection field available for backend use

Allow the subsection to store a subsection value directly in the
label, rather than having to do strange encoding hacks.

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
This commit is contained in:
H. Peter Anvin 2018-06-14 17:04:32 -07:00
parent 13587802fe
commit 29695c85fb
5 changed files with 34 additions and 17 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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,

View file

@ -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;
}

View file

@ -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;