From 98578071b9d71ecaa2344dd9c185237c1765041e Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 1 Jun 2018 18:02:54 -0700 Subject: 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 --- asm/directiv.c | 177 ++++++------------ asm/directiv.dat | 9 + asm/eval.c | 2 +- asm/labels.c | 517 ++++++++++++++++++++++++++++------------------------ asm/nasm.c | 126 +++++-------- asm/parser.c | 8 +- asm/parser.h | 2 +- asm/pragma.c | 31 +++- asm/segalloc.c | 5 +- include/labels.h | 34 +++- include/nasm.h | 17 +- macros/standard.mac | 21 ++- output/outaout.c | 10 +- output/outbin.c | 4 +- output/outcoff.c | 2 +- output/outdbg.c | 11 +- output/outelf.c | 14 +- output/outieee.c | 5 +- output/outmacho.c | 12 +- output/outobj.c | 8 +- test/subsection.asm | 7 +- 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(<ab, 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 @@ -141,11 +142,6 @@ struct out_data { int64_t relbase; /* Relative base for OUT_RELADDR */ }; -/* - * 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 @@ -153,10 +149,7 @@ typedef bool (*lfunc)(char *label, int32_t *segment, int64_t *offset); * 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..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..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 -- cgit v1.2.1