summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2018-06-01 18:02:54 -0700
committerH. Peter Anvin <hpa@linux.intel.com>2018-06-01 18:06:25 -0700
commit98578071b9d71ecaa2344dd9c185237c1765041e (patch)
tree74dfdf8b0f587364f34ae804dc7ce0cd7d81ba7e
parent8413e8167a21a922bbf99660165bb091e71bf1c0 (diff)
downloadnasm-98578071b9d71ecaa2344dd9c185237c1765041e.tar.gz
Cleanup of label renaming infrastructure, add subsection support
In order to support Mach-O better, add support for subsections, as used by Mach-O "subsections_via_symbols". We also want to add infrastructure to support this by downcalling to the backend to indicate if a new subsection is needed. Currently this supports a maximum of 2^14 subsections per section for Mach-O; this can be addressed by adding a level of indirection (or cleaning up the handling of sections so we have an actual data structure.) Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--asm/directiv.c177
-rw-r--r--asm/directiv.dat9
-rw-r--r--asm/eval.c2
-rw-r--r--asm/labels.c517
-rw-r--r--asm/nasm.c126
-rw-r--r--asm/parser.c8
-rw-r--r--asm/parser.h2
-rw-r--r--asm/pragma.c31
-rw-r--r--asm/segalloc.c5
-rw-r--r--include/labels.h34
-rw-r--r--include/nasm.h17
-rw-r--r--macros/standard.mac21
-rw-r--r--output/outaout.c10
-rw-r--r--output/outbin.c4
-rw-r--r--output/outcoff.c2
-rw-r--r--output/outdbg.c11
-rw-r--r--output/outelf.c14
-rw-r--r--output/outieee.c5
-rw-r--r--output/outmacho.c12
-rw-r--r--output/outobj.c8
-rw-r--r--test/subsection.asm7
21 files changed, 500 insertions, 522 deletions
diff --git a/asm/directiv.c b/asm/directiv.c
index 2f887647..b7c919d2 100644
--- a/asm/directiv.c
+++ b/asm/directiv.c
@@ -209,6 +209,7 @@ bool process_directives(char *directive)
struct tokenval tokval;
bool bad_param = false;
int pass2 = passn > 1 ? 2 : 1;
+ enum label_type type;
d = parse_directive_line(&directive, &value);
@@ -292,140 +293,80 @@ bool process_directives(char *directive)
break;
}
- case D_EXTERN: /* [EXTERN label:special] */
- if (*value == '$')
- value++; /* skip initial $ if present */
- if (pass0 == 2) {
- q = value;
- while (*q && *q != ':')
- q++;
- if (*q == ':') {
- *q++ = '\0';
- ofmt->symdef(value, 0L, 0L, 3, q);
- }
- } else if (passn == 1) {
- bool validid = true;
- q = value;
- if (!isidstart(*q))
- validid = false;
- while (*q && *q != ':') {
- if (!isidchar(*q))
- validid = false;
- q++;
- }
- if (!validid) {
- nasm_error(ERR_NONFATAL, "identifier expected after EXTERN");
- break;
- }
- if (*q == ':') {
- *q++ = '\0';
- special = q;
- } else
- special = NULL;
- if (!is_extern(value)) { /* allow re-EXTERN to be ignored */
- int temp = pass0;
- pass0 = 1; /* fake pass 1 in labels.c */
- declare_as_global(value, special);
- define_label(value, seg_alloc(), 0L, NULL,
- false, true);
- pass0 = temp;
- }
- } /* else pass0 == 1 */
- break;
-
case D_BITS: /* [BITS bits] */
globalbits = get_bits(value);
break;
- case D_GLOBAL: /* [GLOBAL symbol:special] */
- if (*value == '$')
- value++; /* skip initial $ if present */
- if (pass0 == 2) { /* pass 2 */
- q = value;
- while (*q && *q != ':')
- q++;
- if (*q == ':') {
- *q++ = '\0';
- ofmt->symdef(value, 0L, 0L, 3, q);
- }
- } else if (pass2 == 1) { /* pass == 1 */
- bool validid = true;
-
- q = value;
- if (!isidstart(*q))
- validid = false;
- while (*q && *q != ':') {
- if (!isidchar(*q))
- validid = false;
- q++;
- }
- if (!validid) {
- nasm_error(ERR_NONFATAL,
- "identifier expected after GLOBAL");
- break;
- }
- if (*q == ':') {
- *q++ = '\0';
- special = q;
- } else
- special = NULL;
- declare_as_global(value, special);
- } /* pass == 1 */
- break;
-
- case D_COMMON: /* [COMMON symbol size:special] */
+ case D_GLOBAL: /* [GLOBAL|STATIC|EXTERN|COMMON symbol:special] */
+ type = LBL_GLOBAL;
+ goto symdef;
+ case D_STATIC:
+ type = LBL_STATIC;
+ goto symdef;
+ case D_EXTERN:
+ type = LBL_EXTERN;
+ goto symdef;
+ case D_COMMON:
+ type = LBL_COMMON;
+ goto symdef;
+
+ symdef:
{
- int64_t size;
- bool rn_error;
- bool validid;
+ bool validid = true;
+ int64_t size = 0;
+ char *sizestr;
+ bool rn_error;
- if (*value == '$')
- value++; /* skip initial $ if present */
- p = value;
- validid = true;
- if (!isidstart(*p))
+ q = value;
+ if (!isidstart(*q))
validid = false;
- while (*p && !nasm_isspace(*p)) {
- if (!isidchar(*p))
+ while (*q && *q != ':' && !nasm_isspace(*q)) {
+ if (!isidchar(*q))
validid = false;
- p++;
+ q++;
}
if (!validid) {
- nasm_error(ERR_NONFATAL, "identifier expected after COMMON");
+ nasm_error(ERR_NONFATAL,
+ "identifier expected after %s", directive);
break;
}
- if (*p) {
- p = nasm_zap_spaces_fwd(p);
- q = p;
- while (*q && *q != ':')
- q++;
- if (*q == ':') {
- *q++ = '\0';
- special = q;
- } else {
- special = NULL;
- }
- size = readnum(p, &rn_error);
- if (rn_error) {
- nasm_error(ERR_NONFATAL,
- "invalid size specified"
- " in COMMON declaration");
- break;
- }
+
+ if (nasm_isspace(*q)) {
+ sizestr = q = nasm_zap_spaces_fwd(q);
+ q = strchr(q, ':');
} else {
- nasm_error(ERR_NONFATAL,
- "no size specified in"
- " COMMON declaration");
- break;
+ sizestr = NULL;
}
- if (pass0 < 2) {
- define_common(value, seg_alloc(), size, special);
- } else if (pass0 == 2) {
- if (special)
- ofmt->symdef(value, 0L, 0L, 3, special);
+ if (*q == ':') {
+ *q++ = '\0';
+ special = q;
+ } else {
+ special = NULL;
}
- break;
+
+ if (type == LBL_COMMON) {
+ if (sizestr)
+ size = readnum(sizestr, &rn_error);
+ if (!sizestr || rn_error)
+ nasm_error(ERR_NONFATAL,
+ "%s size specified in common declaration",
+ sizestr ? "invalid" : "no");
+ } else if (sizestr) {
+ nasm_error(ERR_NONFATAL, "invalid syntax in %s declaration",
+ directive);
+ }
+
+ if (*value == '$')
+ value++; /* skip initial $ if present */
+
+ if (!declare_label(value, type, special))
+ break;
+
+ if (type == LBL_COMMON || type == LBL_EXTERN)
+ define_label(value, 0, size, false);
+
+ break;
}
case D_ABSOLUTE: /* [ABSOLUTE address] */
diff --git a/asm/directiv.dat b/asm/directiv.dat
index ebf66148..96649488 100644
--- a/asm/directiv.dat
+++ b/asm/directiv.dat
@@ -66,6 +66,7 @@ default
extern
float
global
+static
list
section
segment
@@ -85,6 +86,14 @@ osabi ; outelf
safeseh ; outcoff
uppercase ; outieee, outobj
+; --- Assembler pragmas
+prefix
+suffix
+gprefix
+gsuffix
+lprefix
+lsuffix
+
; --- Pragma operations
subsections_via_symbols ; macho
no_dead_strip ; macho
diff --git a/asm/eval.c b/asm/eval.c
index 4ce60cec..72d6a0e2 100644
--- a/asm/eval.c
+++ b/asm/eval.c
@@ -767,7 +767,7 @@ static expr *expr6(int critical)
int64_t label_ofs;
int64_t tmpval;
bool rn_warn;
- char *scope;
+ const char *scope;
switch (i) {
case '-':
diff --git a/asm/labels.c b/asm/labels.c
index ce0df180..cde518d0 100644
--- a/asm/labels.c
+++ b/asm/labels.c
@@ -48,21 +48,29 @@
#include "labels.h"
/*
- * A local label is one that begins with exactly one period. Things
+ * A dot-local label is one that begins with exactly one period. Things
* that begin with _two_ periods are NASM-specific things.
*
* If TASM compatibility is enabled, a local label can also begin with
- * @@, so @@local is a TASM compatible local label. Note that we only
- * check for the first @ symbol, although TASM requires both.
+ * @@.
*/
-#define islocal(l) \
- (tasm_compatible_mode ? \
- (((l)[0] == '.' || (l)[0] == '@') && (l)[1] != '.') : \
- ((l)[0] == '.' && (l)[1] != '.'))
-#define islocalchar(c) \
- (tasm_compatible_mode ? \
- ((c) == '.' || (c) == '@') : \
- ((c) == '.'))
+static bool islocal(const char *l)
+{
+ if (tasm_compatible_mode) {
+ if (l[0] == '@' && l[1] == '@')
+ return true;
+ }
+
+ return (l[0] == '.' && l[1] != '.');
+}
+
+/*
+ * Return true if this falls into NASM's '..' namespace
+ */
+static bool ismagic(const char *l)
+{
+ return l[0] == '.' && l[1] == '.' && l[2] != '@';
+}
#define LABEL_BLOCK 128 /* no. of labels/block */
#define LBLK_SIZE (LABEL_BLOCK * sizeof(union label))
@@ -76,24 +84,18 @@
#error "IPERMTS_SIZE must be greater than or equal to IDLEN_MAX"
#endif
-/* values for label.defn.is_global */
-#define DEFINED_BIT 1
-#define GLOBAL_BIT 2
-#define EXTERN_BIT 4
-#define COMMON_BIT 8
-
-#define NOT_DEFINED_YET 0
-#define TYPE_MASK 3
-#define LOCAL_SYMBOL (DEFINED_BIT)
-#define GLOBAL_PLACEHOLDER (GLOBAL_BIT)
-#define GLOBAL_SYMBOL (DEFINED_BIT | GLOBAL_BIT)
+/* string values for enum label_type */
+static const char * const types[] =
+{"local", "global", "static", "extern", "common", "special",
+ "output format special"};
union label { /* actual label structures */
struct {
int32_t segment;
int64_t offset;
- char *label, *special;
- int is_global, is_norm;
+ char *label, *mangled, *special;
+ enum label_type type, mangled_type;
+ bool defined;
} defn;
struct {
int32_t movingon;
@@ -104,9 +106,10 @@ union label { /* actual label structures */
struct permts { /* permanent text storage */
struct permts *next; /* for the linked list */
- int size, usage; /* size and used space in ... */
+ unsigned int size, usage; /* size and used space in ... */
char data[PERMTS_SIZE]; /* ... the data block itself */
};
+#define PERMTS_HEADER offsetof(struct permts, data)
uint64_t global_offset_changed; /* counter for global offset changes */
@@ -117,29 +120,71 @@ static struct permts *perm_head; /* start of perm. text storage */
static struct permts *perm_tail; /* end of perm. text storage */
static void init_block(union label *blk);
+static char *perm_alloc(size_t len);
static char *perm_copy(const char *string);
+static char *perm_copy3(const char *s1, const char *s2, const char *s3);
+static const char *mangle_label_name(union label *lptr);
-static char *prevlabel;
+static const char *prevlabel;
static bool initialized = false;
-char lprefix[PREFIX_MAX] = { 0 };
-char lpostfix[PREFIX_MAX] = { 0 };
-
/*
* Emit a symdef to the output and the debug format backends.
*/
-static void out_symdef(char *name, int32_t segment, int64_t offset,
- int is_global, char *special)
+static void out_symdef(union label *lptr)
{
- ofmt->symdef(name, segment, offset, is_global, special);
+ int backend_type;
+
+ /* Backend-defined special segments are passed to symdef immediately */
+ if (pass0 == 2) {
+ /* Emit special fixups for globals and commons */
+ switch (lptr->defn.type) {
+ case LBL_GLOBAL:
+ case LBL_COMMON:
+ case LBL_EXTERN:
+ if (lptr->defn.special)
+ ofmt->symdef(lptr->defn.label, 0, 0, 3, lptr->defn.special);
+ break;
+ default:
+ break;
+ }
+ return;
+ }
+
+ if (pass0 != 1 && lptr->defn.type != LBL_BACKEND)
+ return;
+
+ /* Clean up this hack... */
+ switch(lptr->defn.type) {
+ case LBL_GLOBAL:
+ backend_type = 1;
+ break;
+ case LBL_COMMON:
+ backend_type = 2;
+ break;
+ default:
+ backend_type = 0;
+ break;
+ }
+
+ /* Might be necessary for a backend symbol */
+ mangle_label_name(lptr);
+
+ ofmt->symdef(lptr->defn.mangled, lptr->defn.segment,
+ lptr->defn.offset, backend_type,
+ lptr->defn.special);
/*
* NASM special symbols are not passed to the debug format; none
* of the current backends want to see them.
*/
- if (!(name[0] == '.' && name[1] == '.' && name[2] != '@'))
- dfmt->debug_deflabel(name, segment, offset, is_global, special);
+ if (lptr->defn.type == LBL_SPECIAL || lptr->defn.type == LBL_BACKEND)
+ return;
+
+ dfmt->debug_deflabel(lptr->defn.mangled, lptr->defn.segment,
+ lptr->defn.offset, backend_type,
+ lptr->defn.special);
}
/*
@@ -147,37 +192,21 @@ static void out_symdef(char *name, int32_t segment, int64_t offset,
* given label name. Creates a new one, if it isn't found, and if
* `create' is true.
*/
-static union label *find_label(const char *label, int create, int *created)
+static union label *find_label(const char *label, bool create, bool *created)
{
- char *prev;
- int prevlen, len;
union label *lptr, **lpp;
- char label_str[IDLEN_MAX];
+ char *label_str = NULL;
struct hash_insert ip;
- if (islocal(label)) {
- prev = prevlabel;
- prevlen = strlen(prev);
- len = strlen(label);
- if (prevlen + len >= IDLEN_MAX) {
- nasm_error(ERR_NONFATAL, "identifier length exceed %i bytes",
- IDLEN_MAX);
- return NULL;
- }
- memcpy(label_str, prev, prevlen);
- memcpy(label_str+prevlen, label, len+1);
- label = label_str;
- } else {
- prev = "";
- prevlen = 0;
- }
+ if (islocal(label))
+ label = label_str = nasm_strcat(prevlabel, label);
lpp = (union label **) hash_find(&ltab, label, &ip);
lptr = lpp ? *lpp : NULL;
if (lptr || !create) {
if (created)
- *created = 0;
+ *created = false;
return lptr;
}
@@ -192,12 +221,13 @@ static union label *find_label(const char *label, int create, int *created)
}
if (created)
- *created = 1;
+ *created = true;
+ nasm_zero(*lfree);
lfree->admin.movingon = BOGUS_VALUE;
- lfree->defn.label = perm_copy(label);
- lfree->defn.special = NULL;
- lfree->defn.is_global = NOT_DEFINED_YET;
+ lfree->defn.label = perm_copy(label);
+ if (label_str)
+ nasm_free(label_str);
hash_add(&ip, lfree->defn.label, lfree);
return lfree++;
@@ -210,8 +240,8 @@ bool lookup_label(const char *label, int32_t *segment, int64_t *offset)
if (!initialized)
return false;
- lptr = find_label(label, 0, NULL);
- if (lptr && (lptr->defn.is_global & DEFINED_BIT)) {
+ lptr = find_label(label, false, NULL);
+ if (lptr && lptr->defn.defined) {
*segment = lptr->defn.segment;
*offset = lptr->defn.offset;
return true;
@@ -227,12 +257,66 @@ bool is_extern(const char *label)
if (!initialized)
return false;
- lptr = find_label(label, 0, NULL);
- return (lptr && (lptr->defn.is_global & EXTERN_BIT));
+ lptr = find_label(label, false, NULL);
+ return lptr && lptr->defn.type == LBL_EXTERN;
}
-static void handle_herelabel(const char *label,
- int32_t *segment, int64_t *offset)
+static const char *mangle_strings[] = {"", "", "", ""};
+static bool mangle_string_set[ARRAY_SIZE(mangle_strings)];
+
+/*
+ * Set a prefix or suffix
+ */
+void set_label_mangle(enum mangle_index which, const char *what)
+{
+ if (mangle_string_set[which])
+ return; /* Once set, do not change */
+
+ mangle_strings[which] = perm_copy(what);
+ mangle_string_set[which] = true;
+}
+
+/*
+ * Format a label name with appropriate prefixes and suffixes
+ */
+static const char *mangle_label_name(union label *lptr)
+{
+ const char *prefix;
+ const char *suffix;
+
+ if (likely(lptr->defn.mangled &&
+ lptr->defn.mangled_type == lptr->defn.type))
+ return lptr->defn.mangled; /* Already mangled */
+
+ switch (lptr->defn.type) {
+ case LBL_GLOBAL:
+ case LBL_STATIC:
+ case LBL_EXTERN:
+ prefix = mangle_strings[LM_GPREFIX];
+ suffix = mangle_strings[LM_GSUFFIX];
+ break;
+ case LBL_BACKEND:
+ case LBL_SPECIAL:
+ prefix = suffix = "";
+ break;
+ default:
+ prefix = mangle_strings[LM_LPREFIX];
+ suffix = mangle_strings[LM_LSUFFIX];
+ break;
+ }
+
+ lptr->defn.mangled_type = lptr->defn.type;
+
+ if (!(*prefix) && !(*suffix))
+ lptr->defn.mangled = lptr->defn.label;
+ else
+ lptr->defn.mangled = perm_copy3(prefix, lptr->defn.label, suffix);
+
+ return lptr->defn.mangled;
+}
+
+static void
+handle_herelabel(const union label *lptr, int32_t *segment, int64_t *offset)
{
int32_t oldseg;
@@ -248,7 +332,8 @@ static void handle_herelabel(const char *label,
/* This label is defined at this location */
int32_t newseg;
- newseg = ofmt->herelabel(label, oldseg);
+ nasm_assert(lptr->defn.mangled);
+ newseg = ofmt->herelabel(lptr->defn.mangled, lptr->defn.type, oldseg);
if (likely(newseg == oldseg))
return;
@@ -257,198 +342,120 @@ static void handle_herelabel(const char *label,
}
}
-void redefine_label(char *label, int32_t segment, int64_t offset, char *special,
- bool is_norm, bool isextrn)
+static bool declare_label_lptr(union label *lptr,
+ enum label_type type, const char *special)
{
- union label *lptr;
- int exi, created;
-
- /* This routine possibly ought to check for phase errors. Most assemblers
- * check for phase errors at this point. I don't know whether phase errors
- * are even possible, nor whether they are checked somewhere else
- */
-
- (void)special; /* Don't warn that this parameter is unused */
- (void)is_norm; /* Don't warn that this parameter is unused */
- (void)isextrn; /* Don't warn that this parameter is unused */
-
-#ifdef DEBUG
-#if DEBUG < 3
- if (!strncmp(label, "debugdump", 9))
-#endif
- nasm_error(ERR_DEBUG, "redefine_label (%s, %"PRIx32", %"PRIx64", %s, %d, %d)",
- label, segment, offset, special, is_norm, isextrn);
-#endif
-
- handle_herelabel(label, &segment, &offset);
-
- lptr = find_label(label, 1, &created);
- if (!lptr)
- nasm_panic(0, "can't find label `%s' on pass two", label);
-
- if (created)
- nasm_error(ERR_WARNING, "label `%s' defined on pass two", label);
+ if (lptr->defn.type == type ||
+ (pass0 == 0 && lptr->defn.type == LBL_LOCAL)) {
+ lptr->defn.type = type;
+ if (special) {
+ if (!lptr->defn.special)
+ lptr->defn.special = perm_copy(special);
+ else if (nasm_stricmp(lptr->defn.special, special))
+ nasm_error(ERR_NONFATAL,
+ "symbol `%s' has inconsistent attributes `%s' and `%s'",
+ lptr->defn.label, lptr->defn.special, special);
+ }
+ return true;
+ }
- if (!islocal(label)) {
- if (!islocalchar(*label) && lptr->defn.is_norm)
- prevlabel = lptr->defn.label;
+ /* EXTERN can be replaced with GLOBAL or COMMON */
+ if (lptr->defn.type == LBL_EXTERN &&
+ (type == LBL_GLOBAL || type == LBL_COMMON)) {
+ lptr->defn.type = type;
+ /* Override special unconditionally */
+ if (special)
+ lptr->defn.special = perm_copy(special);
+ return true;
}
- if (lptr->defn.offset != offset)
- global_offset_changed++;
+ /* GLOBAL or COMMON ignore subsequent EXTERN */
+ if ((lptr->defn.type == LBL_GLOBAL || lptr->defn.type == LBL_COMMON) &&
+ type == LBL_EXTERN) {
+ if (!lptr->defn.special)
+ lptr->defn.special = perm_copy(special);
+ return true;
+ }
- lptr->defn.offset = offset;
- lptr->defn.segment = segment;
+ nasm_error(ERR_NONFATAL, "symbol `%s' declared both as %s and %s",
+ lptr->defn.label, types[lptr->defn.type], types[type]);
- if (pass0 == 1) {
- exi = !!(lptr->defn.is_global & GLOBAL_BIT);
- if (exi) {
- char *xsymbol;
- int slen;
- slen = strlen(lprefix);
- slen += strlen(lptr->defn.label);
- slen += strlen(lpostfix);
- slen++; /* room for that null char */
- xsymbol = nasm_malloc(slen);
- snprintf(xsymbol, slen, "%s%s%s", lprefix, lptr->defn.label,
- lpostfix);
-
- out_symdef(xsymbol, segment, offset, exi,
- special ? special : lptr->defn.special);
- /** nasm_free(xsymbol); ! outobj.c stores the pointer; ouch!!! **/
- } else {
- if ((lptr->defn.is_global & (GLOBAL_BIT | EXTERN_BIT)) != EXTERN_BIT) {
- out_symdef(lptr->defn.label, segment, offset, exi,
- special ? special : lptr->defn.special);
- }
- }
- } /* if (pass0 == 1) */
+ return false;
}
-void define_label(char *label, int32_t segment, int64_t offset, char *special,
- bool is_norm, bool isextrn)
+bool declare_label(const char *label, enum label_type type, const char *special)
{
union label *lptr;
- int exi;
-
-#ifdef DEBUG
-#if DEBUG<3
- if (!strncmp(label, "debugdump", 9))
-#endif
- nasm_error(ERR_DEBUG, "define_label (%s, %"PRIx32", %"PRIx64", %s, %d, %d)",
- label, segment, offset, special, is_norm, isextrn);
-#endif
+ bool created;
- handle_herelabel(label, &segment, &offset);
-
- lptr = find_label(label, 1, NULL);
- if (!lptr)
- return;
- if (lptr->defn.is_global & DEFINED_BIT) {
- nasm_error(ERR_NONFATAL, "symbol `%s' redefined", label);
- return;
- }
- lptr->defn.is_global |= DEFINED_BIT;
- if (isextrn)
- lptr->defn.is_global |= EXTERN_BIT;
-
- if (!islocalchar(label[0]) && is_norm) {
- /* not local, but not special either */
- prevlabel = lptr->defn.label;
- } else if (islocal(label) && !*prevlabel) {
- nasm_error(ERR_NONFATAL, "attempt to define a local label before any"
- " non-local labels");
- }
-
- lptr->defn.segment = segment;
- lptr->defn.offset = offset;
- lptr->defn.is_norm = (!islocalchar(label[0]) && is_norm);
-
- if (pass0 == 1 || (!is_norm && !isextrn && (segment > 0) && (segment & 1))) {
- exi = !!(lptr->defn.is_global & GLOBAL_BIT);
- if (exi) {
- char *xsymbol;
- int slen;
- slen = strlen(lprefix);
- slen += strlen(lptr->defn.label);
- slen += strlen(lpostfix);
- slen++; /* room for that null char */
- xsymbol = nasm_malloc(slen);
- snprintf(xsymbol, slen, "%s%s%s", lprefix, lptr->defn.label,
- lpostfix);
-
- out_symdef(xsymbol, segment, offset, exi,
- special ? special : lptr->defn.special);
- /** nasm_free(xsymbol); ! outobj.c stores the pointer; ouch!!! **/
- } else {
- if ((lptr->defn.is_global & (GLOBAL_BIT | EXTERN_BIT)) != EXTERN_BIT) {
- out_symdef(lptr->defn.label, segment, offset, exi,
- special ? special : lptr->defn.special);
- }
- }
- } /* if (pass0 == 1) */
+ lptr = find_label(label, true, &created);
+ return declare_label_lptr(lptr, type, special);
}
-void define_common(char *label, int32_t segment, int32_t size, char *special)
+/*
+ * The "normal" argument decides if we should update the local segment
+ * base name or not.
+ */
+void define_label(const char *label, int32_t segment,
+ int64_t offset, bool normal)
{
union label *lptr;
+ bool created, changed;
- lptr = find_label(label, 1, NULL);
- if (!lptr)
- return;
- if ((lptr->defn.is_global & DEFINED_BIT) &&
- (passn == 1 || !(lptr->defn.is_global & COMMON_BIT))) {
- nasm_error(ERR_NONFATAL, "symbol `%s' redefined", label);
- return;
+ /*
+ * Phase errors here can be one of two types: a new label appears,
+ * or the offset changes. Increment global_offset_changed when that
+ * happens, to tell the assembler core to make another pass.
+ */
+ lptr = find_label(label, true, &created);
+
+ if (pass0 > 1) {
+ if (created)
+ nasm_error(ERR_WARNING, "label `%s' defined on pass two", label);
+ }
+
+ if (lptr->defn.defined || lptr->defn.type == LBL_BACKEND) {
+ /* We have seen this on at least one previous pass */
+ mangle_label_name(lptr);
+ handle_herelabel(lptr, &segment, &offset);
}
- lptr->defn.is_global |= DEFINED_BIT|COMMON_BIT;
- if (!islocalchar(label[0])) {
+ if (ismagic(label) && lptr->defn.type == LBL_LOCAL)
+ lptr->defn.type = LBL_SPECIAL;
+
+ if (!islocal(label) && normal) {
prevlabel = lptr->defn.label;
- } else {
- nasm_error(ERR_NONFATAL, "attempt to define a local label as a "
- "common variable");
- return;
}
- lptr->defn.segment = segment;
- lptr->defn.offset = 0;
+ changed = !lptr->defn.defined || lptr->defn.segment != segment ||
+ lptr->defn.offset != offset;
+ global_offset_changed += changed;
- if (pass0 == 0)
- return;
+ /*
+ * This probably should be ERR_NONFATAL, but not quite yet. As a
+ * special case, LBL_SPECIAL symbols are allowed to be changed
+ * even during the last pass.
+ */
+ if (changed && pass0 == 2 && lptr->defn.type != LBL_SPECIAL)
+ nasm_error(ERR_WARNING, "label `%s' changed during code generation",
+ lptr->defn.label);
+
+ lptr->defn.segment = segment;
+ lptr->defn.offset = offset;
+ lptr->defn.defined = true;
- out_symdef(lptr->defn.label, segment, size, 2,
- special ? special : lptr->defn.special);
+ out_symdef(lptr);
}
-void declare_as_global(char *label, char *special)
+/*
+ * Define a special backend label
+ */
+void backend_label(const char *label, int32_t segment, int64_t offset)
{
- union label *lptr;
-
- if (islocal(label)) {
- nasm_error(ERR_NONFATAL, "attempt to declare local symbol `%s' as"
- " global", label);
+ if (!declare_label(label, LBL_BACKEND, NULL))
return;
- }
- lptr = find_label(label, 1, NULL);
- if (!lptr)
- return;
- switch (lptr->defn.is_global & TYPE_MASK) {
- case NOT_DEFINED_YET:
- lptr->defn.is_global = GLOBAL_PLACEHOLDER;
- lptr->defn.special = special ? perm_copy(special) : NULL;
- break;
- case GLOBAL_PLACEHOLDER: /* already done: silently ignore */
- case GLOBAL_SYMBOL:
- break;
- case LOCAL_SYMBOL:
- if (!(lptr->defn.is_global & EXTERN_BIT)) {
- nasm_error(ERR_WARNING, "symbol `%s': GLOBAL directive "
- "after symbol definition is an experimental feature", label);
- lptr->defn.is_global = GLOBAL_SYMBOL;
- }
- break;
- }
+
+ define_label(label, segment, offset, false);
}
int init_labels(void)
@@ -505,29 +512,53 @@ static void init_block(union label *blk)
blk[LABEL_BLOCK - 1].admin.next = NULL;
}
-static char *perm_copy(const char *string)
+static char * safe_alloc perm_alloc(size_t len)
{
- char *p;
- int len = strlen(string)+1;
-
- nasm_assert(len <= PERMTS_SIZE);
-
if (perm_tail->size - perm_tail->usage < len) {
- perm_tail->next =
- nasm_malloc(sizeof(struct permts));
+ size_t alloc_len = (len > PERMTS_SIZE) ? len : PERMTS_SIZE;
+ perm_tail->next = nasm_malloc(PERMTS_HEADER + alloc_len);
perm_tail = perm_tail->next;
perm_tail->next = NULL;
- perm_tail->size = PERMTS_SIZE;
+ perm_tail->size = alloc_len;
perm_tail->usage = 0;
}
- p = perm_tail->data + perm_tail->usage;
- memcpy(p, string, len);
perm_tail->usage += len;
+ return perm_tail->data + perm_tail->usage;
+}
+
+static char *perm_copy(const char *string)
+{
+ char *p;
+ size_t len;
+
+ if (!string)
+ return NULL;
+
+ len = strlen(string)+1; /* Include final NUL */
+
+ p = perm_alloc(len);
+ memcpy(p, string, len);
+
+ return p;
+}
+
+static char * safe_alloc
+perm_copy3(const char *s1, const char *s2, const char *s3)
+{
+ char *p;
+ size_t l1 = strlen(s1);
+ size_t l2 = strlen(s2);
+ size_t l3 = strlen(s3)+1; /* Include final NUL */
+
+ p = perm_alloc(l1+l2+l3);
+ memcpy(p, s1, l1);
+ memcpy(p+l1, s2, l2);
+ memcpy(p+l1+l2, s3, l3);
return p;
}
-char *local_scope(char *label)
+const char *local_scope(const char *label)
{
return islocal(label) ? prevlabel : "";
}
diff --git a/asm/nasm.c b/asm/nasm.c
index 8e405466..a5b8f763 100644
--- a/asm/nasm.c
+++ b/asm/nasm.c
@@ -718,21 +718,25 @@ enum text_options {
OPT_BOGUS,
OPT_VERSION,
OPT_ABORT_ON_PANIC,
- OPT_PREFIX,
- OPT_POSTFIX
+ OPT_MANGLE
};
struct textargs {
const char *label;
enum text_options opt;
bool need_arg;
+ int pvt;
};
static const struct textargs textopts[] = {
- {"v", OPT_VERSION, false},
- {"version", OPT_VERSION, false},
- {"abort-on-panic", OPT_ABORT_ON_PANIC, false},
- {"prefix", OPT_PREFIX, true},
- {"postfix", OPT_POSTFIX, true},
- {NULL, OPT_BOGUS, false}
+ {"v", OPT_VERSION, false, 0},
+ {"version", OPT_VERSION, false, 0},
+ {"abort-on-panic", OPT_ABORT_ON_PANIC, false, 0},
+ {"prefix", OPT_MANGLE, true, LM_GPREFIX},
+ {"postfix", OPT_MANGLE, true, LM_GSUFFIX},
+ {"gprefix", OPT_MANGLE, true, LM_GPREFIX},
+ {"gpostfix", OPT_MANGLE, true, LM_GSUFFIX},
+ {"lprefix", OPT_MANGLE, true, LM_LPREFIX},
+ {"lpostfix", OPT_MANGLE, true, LM_LSUFFIX},
+ {NULL, OPT_BOGUS, false, 0}
};
static void show_version(void)
@@ -930,7 +934,10 @@ static bool process_arg(char *p, char *q, int pass)
" -h show invocation summary and exit\n\n"
"--prefix,--postfix\n"
" these options prepend or append the given string\n"
- " to all extern and global variables\n"
+ " to all extern, common and global symbols\n"
+ "--lprefix,--lportfix\n"
+ " these options prepend or append the given string\n"
+ " to all other symbols\n"
"\n"
"Response files should contain command line parameters,\n"
"one per line.\n"
@@ -1081,13 +1088,9 @@ static bool process_arg(char *p, char *q, int pass)
case OPT_ABORT_ON_PANIC:
abort_on_panic = true;
break;
- case OPT_PREFIX:
- if (pass == 2)
- strlcpy(lprefix, q, PREFIX_MAX);
- break;
- case OPT_POSTFIX:
+ case OPT_MANGLE:
if (pass == 2)
- strlcpy(lpostfix, q, POSTFIX_MAX);
+ set_label_mangle(tx->pvt, q);
break;
case OPT_BOGUS:
nasm_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
@@ -1324,14 +1327,10 @@ static void assemble_file(const char *fname, StrList **depend_ptr)
pass_max = prev_offset_changed = (INT_MAX >> 1) + 2; /* Almost unlimited */
for (passn = 1; pass0 <= 2; passn++) {
- ldfunc def_label;
-
pass1 = pass0 == 2 ? 2 : 1; /* 1, 1, 1, ..., 1, 2 */
pass2 = passn > 1 ? 2 : 1; /* 1, 2, 2, ..., 2, 2 */
/* pass0 0, 0, 0, ..., 1, 2 */
- def_label = passn > 1 ? redefine_label : define_label;
-
globalbits = cmd_sb; /* set 'bits' to command line default */
cpu = cmd_cpu;
if (pass0 == 2) {
@@ -1376,8 +1375,7 @@ static void assemble_file(const char *fname, StrList **depend_ptr)
goto end_of_line; /* Just do final cleanup */
/* Not a directive, or even something that starts with [ */
-
- parse_line(pass1, line, &output_ins, def_label);
+ parse_line(pass1, line, &output_ins);
if (optimizing > 0) {
if (forwref != NULL && globallineno == forwref->lineno) {
@@ -1405,71 +1403,29 @@ static void assemble_file(const char *fname, StrList **depend_ptr)
/* forw_ref */
if (output_ins.opcode == I_EQU) {
- if (pass1 == 1) {
- /*
- * Special `..' EQUs get processed in pass two,
- * except `..@' macro-processor EQUs which are done
- * in the normal place.
- */
- if (!output_ins.label)
- nasm_error(ERR_NONFATAL,
- "EQU not preceded by label");
-
- else if (output_ins.label[0] != '.' ||
- output_ins.label[1] != '.' ||
- output_ins.label[2] == '@') {
- if (output_ins.operands == 1 &&
- (output_ins.oprs[0].type & IMMEDIATE) &&
- output_ins.oprs[0].wrt == NO_SEG) {
- bool isext = !!(output_ins.oprs[0].opflags & OPFLAG_EXTERN);
- def_label(output_ins.label,
- output_ins.oprs[0].segment,
- output_ins.oprs[0].offset, NULL,
- false, isext);
- } else if (output_ins.operands == 2
- && (output_ins.oprs[0].type & IMMEDIATE)
- && (output_ins.oprs[0].type & COLON)
- && output_ins.oprs[0].segment == NO_SEG
- && output_ins.oprs[0].wrt == NO_SEG
- && (output_ins.oprs[1].type & IMMEDIATE)
- && output_ins.oprs[1].segment == NO_SEG
- && output_ins.oprs[1].wrt == NO_SEG) {
- def_label(output_ins.label,
- output_ins.oprs[0].offset | SEG_ABS,
- output_ins.oprs[1].offset,
- NULL, false, false);
- } else
- nasm_error(ERR_NONFATAL,
- "bad syntax for EQU");
- }
+ if (!output_ins.label)
+ nasm_error(ERR_NONFATAL,
+ "EQU not preceded by label");
+
+ if (output_ins.operands == 1 &&
+ (output_ins.oprs[0].type & IMMEDIATE) &&
+ output_ins.oprs[0].wrt == NO_SEG) {
+ define_label(output_ins.label,
+ output_ins.oprs[0].segment,
+ output_ins.oprs[0].offset, false);
+ } else if (output_ins.operands == 2
+ && (output_ins.oprs[0].type & IMMEDIATE)
+ && (output_ins.oprs[0].type & COLON)
+ && output_ins.oprs[0].segment == NO_SEG
+ && output_ins.oprs[0].wrt == NO_SEG
+ && (output_ins.oprs[1].type & IMMEDIATE)
+ && output_ins.oprs[1].segment == NO_SEG
+ && output_ins.oprs[1].wrt == NO_SEG) {
+ define_label(output_ins.label,
+ output_ins.oprs[0].offset | SEG_ABS,
+ output_ins.oprs[1].offset, false);
} else {
- /*
- * Special `..' EQUs get processed here, except
- * `..@' macro processor EQUs which are done above.
- */
- if (output_ins.label[0] == '.' &&
- output_ins.label[1] == '.' &&
- output_ins.label[2] != '@') {
- if (output_ins.operands == 1 &&
- (output_ins.oprs[0].type & IMMEDIATE)) {
- define_label(output_ins.label,
- output_ins.oprs[0].segment,
- output_ins.oprs[0].offset,
- NULL, false, false);
- } else if (output_ins.operands == 2
- && (output_ins.oprs[0].type & IMMEDIATE)
- && (output_ins.oprs[0].type & COLON)
- && output_ins.oprs[0].segment == NO_SEG
- && (output_ins.oprs[1].type & IMMEDIATE)
- && output_ins.oprs[1].segment == NO_SEG) {
- define_label(output_ins.label,
- output_ins.oprs[0].offset | SEG_ABS,
- output_ins.oprs[1].offset,
- NULL, false, false);
- } else
- nasm_error(ERR_NONFATAL,
- "bad syntax for EQU");
- }
+ nasm_error(ERR_NONFATAL, "bad syntax for EQU");
}
} else { /* instruction isn't an EQU */
int32_t n;
diff --git a/asm/parser.c b/asm/parser.c
index 2ad37ceb..622259c8 100644
--- a/asm/parser.c
+++ b/asm/parser.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2017 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2018 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -426,7 +426,7 @@ static int value_to_extop(expr * vect, extop *eop, int32_t myseg)
return 0;
}
-insn *parse_line(int pass, char *buffer, insn *result, ldfunc ldef)
+insn *parse_line(int pass, char *buffer, insn *result)
{
bool insn_is_label = false;
struct eval_hints hints;
@@ -485,8 +485,8 @@ restart_parse:
* Generally fix things. I think this is right as it is, but
* am still not certain.
*/
- ldef(result->label, in_absolute ? absolute.segment : location.segment,
- location.offset, NULL, true, false);
+ define_label(result->label, location.segment,
+ location.offset, true);
}
}
diff --git a/asm/parser.h b/asm/parser.h
index e148c7fa..cd2d1362 100644
--- a/asm/parser.h
+++ b/asm/parser.h
@@ -39,7 +39,7 @@
#ifndef NASM_PARSER_H
#define NASM_PARSER_H
-insn *parse_line(int pass, char *buffer, insn *result, ldfunc ldef);
+insn *parse_line(int pass, char *buffer, insn *result);
void cleanup_insn(insn *instruction);
#endif
diff --git a/asm/pragma.c b/asm/pragma.c
index cbe0cc7b..e7dba760 100644
--- a/asm/pragma.c
+++ b/asm/pragma.c
@@ -49,6 +49,8 @@
#include "assemble.h"
#include "error.h"
+static enum directive_result asm_pragma(const struct pragma *pragma);
+
/*
* Handle [pragma] directives. [pragma] is generally produced by
* the %pragma preprocessor directive, which simply passes on any
@@ -83,7 +85,7 @@
*/
static struct pragma_facility global_pragmas[] =
{
- { "asm", NULL },
+ { "asm", asm_pragma },
{ "list", NULL },
{ "file", NULL },
{ "input", NULL },
@@ -202,7 +204,7 @@ void process_pragma(char *str)
else
pragma.opcode = directive_find(pragma.opname);
- pragma.tail = nasm_skip_spaces(p);
+ pragma.tail = nasm_trim_spaces(p);
/* Look for a global pragma namespace */
if (search_pragma_list(global_pragmas, NULL, &pragma))
@@ -227,3 +229,28 @@ void process_pragma(char *str)
* already defined for future compatibility.
*/
}
+
+/*
+ * Pragmas for the assembler proper
+ */
+static enum directive_result asm_pragma(const struct pragma *pragma)
+{
+ switch (pragma->opcode) {
+ case D_PREFIX:
+ case D_GPREFIX:
+ set_label_mangle(LM_GPREFIX, pragma->tail);
+ return DIRR_OK;
+ case D_SUFFIX:
+ case D_GSUFFIX:
+ set_label_mangle(LM_GSUFFIX, pragma->tail);
+ return DIRR_OK;
+ case D_LPREFIX:
+ set_label_mangle(LM_LPREFIX, pragma->tail);
+ return DIRR_OK;
+ case D_LSUFFIX:
+ set_label_mangle(LM_LSUFFIX, pragma->tail);
+ return DIRR_OK;
+ default:
+ return DIRR_UNKNOWN;
+ }
+}
diff --git a/asm/segalloc.c b/asm/segalloc.c
index e81f919d..5b4ea4bb 100644
--- a/asm/segalloc.c
+++ b/asm/segalloc.c
@@ -40,10 +40,10 @@
#include "nasmlib.h"
#include "insns.h"
-static int32_t next_seg = 0;
+static int32_t next_seg = 2;
void seg_alloc_reset(void)
{
- next_seg = 0;
+ next_seg = 2;
}
int32_t seg_alloc(void)
@@ -51,6 +51,5 @@ int32_t seg_alloc(void)
int32_t this_seg = next_seg;
next_seg += 2;
-
return this_seg;
}
diff --git a/include/labels.h b/include/labels.h
index 3e8ac3ed..9cf57c1b 100644
--- a/include/labels.h
+++ b/include/labels.h
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2017 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2018 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -40,20 +40,34 @@
#include "compiler.h"
-extern char lprefix[PREFIX_MAX];
-extern char lpostfix[PREFIX_MAX];
+enum mangle_index {
+ LM_LPREFIX, /* Local variable prefix */
+ LM_LSUFFIX, /* Local variable suffix */
+ LM_GPREFIX, /* Global variable prefix */
+ LM_GSUFFIX /* GLobal variable suffix */
+};
+
+enum label_type {
+ LBL_LOCAL, /* Must be zero */
+ LBL_GLOBAL,
+ LBL_STATIC,
+ LBL_EXTERN,
+ LBL_COMMON,
+ LBL_SPECIAL, /* Magic symbols like ..start */
+ LBL_BACKEND /* Backend-defined symbols like ..got */
+};
bool lookup_label(const char *label, int32_t *segment, int64_t *offset);
bool is_extern(const char *label);
-void define_label(char *label, int32_t segment, int64_t offset, char *special,
- bool is_norm, bool isextrn);
-void redefine_label(char *label, int32_t segment, int64_t offset, char *special,
- bool is_norm, bool isextrn);
-void define_common(char *label, int32_t segment, int32_t size, char *special);
-void declare_as_global(char *label, char *special);
+void define_label(const char *label, int32_t segment, int64_t offset,
+ bool normal);
+void backend_label(const char *label, int32_t segment, int64_t offset);
+bool declare_label(const char *label, enum label_type type,
+ const char *special);
+void set_label_mangle(enum mangle_index which, const char *what);
int init_labels(void);
void cleanup_labels(void);
-char *local_scope(char *label);
+const char *local_scope(const char *label);
extern uint64_t global_offset_changed;
diff --git a/include/nasm.h b/include/nasm.h
index eb3691f7..9b639852 100644
--- a/include/nasm.h
+++ b/include/nasm.h
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2017 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2018 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -48,6 +48,7 @@
#include "preproc.h"
#include "insnsi.h" /* For enum opcode */
#include "directiv.h" /* For enum directive */
+#include "labels.h" /* For enum mangle_index, enum label_type */
#include "opflags.h"
#include "regs.h"
@@ -61,7 +62,7 @@ struct compile_time {
};
extern struct compile_time official_compile_time;
-#define NO_SEG -1L /* null segment value */
+#define NO_SEG INT32_C(-1) /* null segment value */
#define SEG_ABS 0x40000000L /* mask for far-absolute segments */
#ifndef PREFIX_MAX
@@ -142,21 +143,13 @@ struct out_data {
};
/*
- * A label-lookup function.
- */
-typedef bool (*lfunc)(char *label, int32_t *segment, int64_t *offset);
-
-/*
* And a label-definition function. The boolean parameter
* `is_norm' states whether the label is a `normal' label (which
* should affect the local-label system), or something odder like
* an EQU or a segment-base symbol, which shouldn't.
*/
typedef void (*ldfunc)(char *label, int32_t segment, int64_t offset,
- char *special, bool is_norm, bool isextrn);
-
-void define_label(char *label, int32_t segment, int64_t offset,
- char *special, bool is_norm, bool isextrn);
+ char *special, bool is_norm);
/*
* Token types returned by the scanner, in addition to ordinary
@@ -904,7 +897,7 @@ struct ofmt {
* current offset, i.e. "foo:" or "foo equ $".
* The offset isn't passed; and may not be stable at this point.
*/
- int32_t (*herelabel)(const char *name, int32_t seg);
+ int32_t (*herelabel)(const char *name, enum label_type type, int32_t seg);
/*
* This procedure is called to modify section alignment,
diff --git a/macros/standard.mac b/macros/standard.mac
index 5fe9eb6c..a6c50b68 100644
--- a/macros/standard.mac
+++ b/macros/standard.mac
@@ -130,13 +130,6 @@ STD: nasm
%endif
%endmacro
-%imacro extern 1-*.nolist
- %rep %0
- [extern %1]
- %rotate 1
- %endrep
-%endmacro
-
%imacro bits 1+.nolist
[bits %1]
%endmacro
@@ -153,6 +146,20 @@ STD: nasm
[bits 64]
%endmacro
+%imacro extern 1-*.nolist
+ %rep %0
+ [extern %1]
+ %rotate 1
+ %endrep
+%endmacro
+
+%imacro static 1-*.nolist
+ %rep %0
+ [static %1]
+ %rotate 1
+ %endrep
+%endmacro
+
%imacro global 1-*.nolist
%rep %0
[global %1]
diff --git a/output/outaout.c b/output/outaout.c
index 184684a9..ba2dbd5e 100644
--- a/output/outaout.c
+++ b/output/outaout.c
@@ -198,15 +198,15 @@ static void aoutb_init(void)
is_pic = 0x00; /* may become 0x40 */
aout_gotpc_sect = seg_alloc();
- define_label("..gotpc", aout_gotpc_sect + 1, 0L, NULL, false, false);
+ backend_label("..gotpc", aout_gotpc_sect + 1, 0L);
aout_gotoff_sect = seg_alloc();
- define_label("..gotoff", aout_gotoff_sect + 1, 0L, NULL, false, false);
+ backend_label("..gotoff", aout_gotoff_sect + 1, 0L);
aout_got_sect = seg_alloc();
- define_label("..got", aout_got_sect + 1, 0L, NULL, false, false);
+ backend_label("..got", aout_got_sect + 1, 0L);
aout_plt_sect = seg_alloc();
- define_label("..plt", aout_plt_sect + 1, 0L, NULL, false, false);
+ backend_label("..plt", aout_plt_sect + 1, 0L);
aout_sym_sect = seg_alloc();
- define_label("..sym", aout_sym_sect + 1, 0L, NULL, false, false);
+ backend_label("..sym", aout_sym_sect + 1, 0L);
}
#endif
diff --git a/output/outbin.c b/output/outbin.c
index 8a71a503..28535f99 100644
--- a/output/outbin.c
+++ b/output/outbin.c
@@ -1217,11 +1217,11 @@ static void bin_define_section_labels(void)
/* section.<name>.start */
strcpy(label_name + base_len, ".start");
- define_label(label_name, sec->start_index, 0L, NULL, 0, 0);
+ define_label(label_name, sec->start_index, 0L, false);
/* section.<name>.vstart */
strcpy(label_name + base_len, ".vstart");
- define_label(label_name, sec->vstart_index, 0L, NULL, 0, 0);
+ define_label(label_name, sec->vstart_index, 0L, false);
nasm_free(label_name);
}
diff --git a/output/outcoff.c b/output/outcoff.c
index f7b62b80..a2fd302c 100644
--- a/output/outcoff.c
+++ b/output/outcoff.c
@@ -198,7 +198,7 @@ static void coff_win64_init(void)
win64 = true;
coff_gen_init();
imagebase_sect = seg_alloc()+1;
- define_label(WRT_IMAGEBASE, imagebase_sect, 0, NULL, false, false);
+ backend_label(WRT_IMAGEBASE, imagebase_sect, 0);
}
static void coff_std_init(void)
diff --git a/output/outdbg.c b/output/outdbg.c
index 87119cbd..4d41d4db 100644
--- a/output/outdbg.c
+++ b/output/outdbg.c
@@ -124,7 +124,7 @@ static int32_t dbg_add_section(char *name, int pass, int *bits,
whatwecallit, name, tail, pass, seg);
if (section_labels)
- define_label(s->name, s->number + 1, 0, NULL, false, false);
+ backend_label(s->name, s->number + 1, 0);
}
}
return seg;
@@ -135,15 +135,16 @@ static int32_t dbg_section_names(char *name, int pass, int *bits)
return dbg_add_section(name, pass, bits, "section_names");
}
-static int32_t dbg_herelabel(const char *name, int32_t seg)
+static int32_t dbg_herelabel(const char *name, enum label_type type,
+ int32_t seg)
{
int32_t newseg = seg;
- if (subsections_via_symbols && name[0] != 'L')
+ if (subsections_via_symbols && type != LBL_LOCAL)
newseg += 0x10000;
- fprintf(ofile, "herelabel %s (seg %08x) -> %08x\n",
- name, seg, newseg);
+ fprintf(ofile, "herelabel %s type %d (seg %08x) -> %08x\n",
+ name, type, seg, newseg);
return newseg;
}
diff --git a/output/outelf.c b/output/outelf.c
index 7cdf9a34..a32e1335 100644
--- a/output/outelf.c
+++ b/output/outelf.c
@@ -337,19 +337,19 @@ static void elf_init(void)
*/
elf_gotpc_sect = seg_alloc();
- define_label("..gotpc", elf_gotpc_sect + 1, 0L, NULL, false, false);
+ backend_label("..gotpc", elf_gotpc_sect + 1, 0L);
elf_gotoff_sect = seg_alloc();
- define_label("..gotoff", elf_gotoff_sect + 1, 0L, NULL, false, false);
+ backend_label("..gotoff", elf_gotoff_sect + 1, 0L);
elf_got_sect = seg_alloc();
- define_label("..got", elf_got_sect + 1, 0L, NULL, false, false);
+ backend_label("..got", elf_got_sect + 1, 0L);
elf_plt_sect = seg_alloc();
- define_label("..plt", elf_plt_sect + 1, 0L, NULL, false, false);
+ backend_label("..plt", elf_plt_sect + 1, 0L);
elf_sym_sect = seg_alloc();
- define_label("..sym", elf_sym_sect + 1, 0L, NULL, false, false);
+ backend_label("..sym", elf_sym_sect + 1, 0L);
elf_gottpoff_sect = seg_alloc();
- define_label("..gottpoff", elf_gottpoff_sect + 1, 0L, NULL, false, false);
+ backend_label("..gottpoff", elf_gottpoff_sect + 1, 0L);
elf_tlsie_sect = seg_alloc();
- define_label("..tlsie", elf_tlsie_sect + 1, 0L, NULL, false, false);
+ backend_label("..tlsie", elf_tlsie_sect + 1, 0L);
def_seg = seg_alloc();
}
diff --git a/output/outieee.c b/output/outieee.c
index 6e7360d1..3a28942d 100644
--- a/output/outieee.c
+++ b/output/outieee.c
@@ -808,10 +808,9 @@ static int32_t ieee_segment(char *name, int pass, int *bits)
ieee_seg_needs_update = seg;
if (seg->align >= SEG_ABS)
- define_label(name, NO_SEG, seg->align - SEG_ABS,
- NULL, false, false);
+ define_label(name, NO_SEG, seg->align - SEG_ABS, false);
else
- define_label(name, seg->index + 1, 0L, NULL, false, false);
+ define_label(name, seg->index + 1, 0L, false);
ieee_seg_needs_update = NULL;
if (seg->use32)
diff --git a/output/outmacho.c b/output/outmacho.c
index 38ead489..e2c3e5eb 100644
--- a/output/outmacho.c
+++ b/output/outmacho.c
@@ -411,7 +411,7 @@ static void macho_init(void)
/* add special symbol for TLVP */
macho_tlvp_sect = seg_alloc() + 1;
- define_label("..tlvp", macho_tlvp_sect, 0L, NULL, false, false);
+ backend_label("..tlvp", macho_tlvp_sect, 0L);
}
@@ -1002,15 +1002,17 @@ static int32_t macho_section(char *name, int pass, int *bits)
return s->index | (s->subsection << 16);
}
-static int32_t macho_herelabel(const char *name, int32_t section)
+static int32_t macho_herelabel(const char *name, enum label_type type,
+ int32_t section)
{
struct section *s;
+ (void)name;
if (!(head_flags & MH_SUBSECTIONS_VIA_SYMBOLS))
return section;
- /* If it starts with L, it doesn't start a new subsection */
- if (name[0] == 'L')
+ /* No subsection only for local labels */
+ if (type == LBL_LOCAL)
return section;
s = get_section_by_index(section);
@@ -2398,7 +2400,7 @@ static void macho64_init(void)
/* add special symbol for ..gotpcrel */
macho_gotpcrel_sect = seg_alloc() + 1;
- define_label("..gotpcrel", macho_gotpcrel_sect, 0L, NULL, false, false);
+ backend_label("..gotpcrel", macho_gotpcrel_sect, 0L);
}
static const struct dfmt macho64_df_dwarf = {
diff --git a/output/outobj.c b/output/outobj.c
index 5c4da9eb..a223c60a 100644
--- a/output/outobj.c
+++ b/output/outobj.c
@@ -1540,11 +1540,9 @@ static int32_t obj_segment(char *name, int pass, int *bits)
obj_seg_needs_update = seg;
if (seg->align >= SEG_ABS)
- define_label(name, NO_SEG, seg->align - SEG_ABS,
- NULL, false, false);
+ define_label(name, NO_SEG, seg->align - SEG_ABS, false);
else
- define_label(name, seg->index + 1, 0L,
- NULL, false, false);
+ define_label(name, seg->index + 1, 0L, false);
obj_seg_needs_update = NULL;
/*
@@ -1647,7 +1645,7 @@ obj_directive(enum directive directive, char *value, int pass)
grp->name = NULL;
obj_grp_needs_update = grp;
- define_label(v, grp->index + 1, 0L, NULL, false, false);
+ backend_label(v, grp->index + 1, 0L);
obj_grp_needs_update = NULL;
while (*q) {
diff --git a/test/subsection.asm b/test/subsection.asm
index f0a1fa03..ce8ed4aa 100644
--- a/test/subsection.asm
+++ b/test/subsection.asm
@@ -5,12 +5,13 @@
;
%pragma output subsections_via_symbols
+%pragma asm gprefix _
+%pragma asm lprefix L_
bits 32
- global foo, bar, quux
-
-%define baz Lbaz
+ global foo, bar
+ static quux
foo:
jmp foo