0
0
mirror of https://github.com/netwide-assembler/nasm.git synced 2025-09-22 10:43:39 -04:00

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>
This commit is contained in:
H. Peter Anvin
2018-06-01 18:02:54 -07:00
parent 8413e8167a
commit 98578071b9
21 changed files with 508 additions and 530 deletions

View File

@@ -209,6 +209,7 @@ bool process_directives(char *directive)
struct tokenval tokval; struct tokenval tokval;
bool bad_param = false; bool bad_param = false;
int pass2 = passn > 1 ? 2 : 1; int pass2 = passn > 1 ? 2 : 1;
enum label_type type;
d = parse_directive_line(&directive, &value); d = parse_directive_line(&directive, &value);
@@ -292,140 +293,80 @@ bool process_directives(char *directive)
break; 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] */ case D_BITS: /* [BITS bits] */
globalbits = get_bits(value); globalbits = get_bits(value);
break; break;
case D_GLOBAL: /* [GLOBAL symbol:special] */ case D_GLOBAL: /* [GLOBAL|STATIC|EXTERN|COMMON symbol:special] */
if (*value == '$') type = LBL_GLOBAL;
value++; /* skip initial $ if present */ goto symdef;
if (pass0 == 2) { /* pass 2 */ case D_STATIC:
q = value; type = LBL_STATIC;
while (*q && *q != ':') goto symdef;
q++; case D_EXTERN:
if (*q == ':') { type = LBL_EXTERN;
*q++ = '\0'; goto symdef;
ofmt->symdef(value, 0L, 0L, 3, q); case D_COMMON:
} type = LBL_COMMON;
} else if (pass2 == 1) { /* pass == 1 */ goto symdef;
bool validid = true;
q = value; symdef:
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] */
{ {
int64_t size; bool validid = true;
bool rn_error; int64_t size = 0;
bool validid; char *sizestr;
bool rn_error;
if (*value == '$') q = value;
value++; /* skip initial $ if present */ if (!isidstart(*q))
p = value;
validid = true;
if (!isidstart(*p))
validid = false; validid = false;
while (*p && !nasm_isspace(*p)) { while (*q && *q != ':' && !nasm_isspace(*q)) {
if (!isidchar(*p)) if (!isidchar(*q))
validid = false; validid = false;
p++; q++;
} }
if (!validid) { if (!validid) {
nasm_error(ERR_NONFATAL, "identifier expected after COMMON");
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;
}
} else {
nasm_error(ERR_NONFATAL, nasm_error(ERR_NONFATAL,
"no size specified in" "identifier expected after %s", directive);
" COMMON declaration");
break; break;
} }
if (pass0 < 2) { if (nasm_isspace(*q)) {
define_common(value, seg_alloc(), size, special); sizestr = q = nasm_zap_spaces_fwd(q);
} else if (pass0 == 2) { q = strchr(q, ':');
if (special) } else {
ofmt->symdef(value, 0L, 0L, 3, special); sizestr = NULL;
} }
break;
if (*q == ':') {
*q++ = '\0';
special = q;
} else {
special = NULL;
}
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] */ case D_ABSOLUTE: /* [ABSOLUTE address] */

View File

@@ -66,6 +66,7 @@ default
extern extern
float float
global global
static
list list
section section
segment segment
@@ -85,6 +86,14 @@ osabi ; outelf
safeseh ; outcoff safeseh ; outcoff
uppercase ; outieee, outobj uppercase ; outieee, outobj
; --- Assembler pragmas
prefix
suffix
gprefix
gsuffix
lprefix
lsuffix
; --- Pragma operations ; --- Pragma operations
subsections_via_symbols ; macho subsections_via_symbols ; macho
no_dead_strip ; macho no_dead_strip ; macho

View File

@@ -767,7 +767,7 @@ static expr *expr6(int critical)
int64_t label_ofs; int64_t label_ofs;
int64_t tmpval; int64_t tmpval;
bool rn_warn; bool rn_warn;
char *scope; const char *scope;
switch (i) { switch (i) {
case '-': case '-':

View File

@@ -48,21 +48,29 @@
#include "labels.h" #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. * that begin with _two_ periods are NASM-specific things.
* *
* If TASM compatibility is enabled, a local label can also begin with * 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) \ static bool islocal(const char *l)
(tasm_compatible_mode ? \ {
(((l)[0] == '.' || (l)[0] == '@') && (l)[1] != '.') : \ if (tasm_compatible_mode) {
((l)[0] == '.' && (l)[1] != '.')) if (l[0] == '@' && l[1] == '@')
#define islocalchar(c) \ return true;
(tasm_compatible_mode ? \ }
((c) == '.' || (c) == '@') : \
((c) == '.')) 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 LABEL_BLOCK 128 /* no. of labels/block */
#define LBLK_SIZE (LABEL_BLOCK * sizeof(union label)) #define LBLK_SIZE (LABEL_BLOCK * sizeof(union label))
@@ -76,24 +84,18 @@
#error "IPERMTS_SIZE must be greater than or equal to IDLEN_MAX" #error "IPERMTS_SIZE must be greater than or equal to IDLEN_MAX"
#endif #endif
/* values for label.defn.is_global */ /* string values for enum label_type */
#define DEFINED_BIT 1 static const char * const types[] =
#define GLOBAL_BIT 2 {"local", "global", "static", "extern", "common", "special",
#define EXTERN_BIT 4 "output format special"};
#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)
union label { /* actual label structures */ union label { /* actual label structures */
struct { struct {
int32_t segment; int32_t segment;
int64_t offset; int64_t offset;
char *label, *special; char *label, *mangled, *special;
int is_global, is_norm; enum label_type type, mangled_type;
bool defined;
} defn; } defn;
struct { struct {
int32_t movingon; int32_t movingon;
@@ -104,9 +106,10 @@ union label { /* actual label structures */
struct permts { /* permanent text storage */ struct permts { /* permanent text storage */
struct permts *next; /* for the linked list */ 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 */ 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 */ 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 struct permts *perm_tail; /* end of perm. text storage */
static void init_block(union label *blk); static void init_block(union label *blk);
static char *perm_alloc(size_t len);
static char *perm_copy(const char *string); 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; 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. * Emit a symdef to the output and the debug format backends.
*/ */
static void out_symdef(char *name, int32_t segment, int64_t offset, static void out_symdef(union label *lptr)
int is_global, char *special)
{ {
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 * NASM special symbols are not passed to the debug format; none
* of the current backends want to see them. * of the current backends want to see them.
*/ */
if (!(name[0] == '.' && name[1] == '.' && name[2] != '@')) if (lptr->defn.type == LBL_SPECIAL || lptr->defn.type == LBL_BACKEND)
dfmt->debug_deflabel(name, segment, offset, is_global, special); 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 * given label name. Creates a new one, if it isn't found, and if
* `create' is true. * `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; union label *lptr, **lpp;
char label_str[IDLEN_MAX]; char *label_str = NULL;
struct hash_insert ip; struct hash_insert ip;
if (islocal(label)) { if (islocal(label))
prev = prevlabel; label = label_str = nasm_strcat(prevlabel, label);
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;
}
lpp = (union label **) hash_find(&ltab, label, &ip); lpp = (union label **) hash_find(&ltab, label, &ip);
lptr = lpp ? *lpp : NULL; lptr = lpp ? *lpp : NULL;
if (lptr || !create) { if (lptr || !create) {
if (created) if (created)
*created = 0; *created = false;
return lptr; return lptr;
} }
@@ -192,12 +221,13 @@ static union label *find_label(const char *label, int create, int *created)
} }
if (created) if (created)
*created = 1; *created = true;
nasm_zero(*lfree);
lfree->admin.movingon = BOGUS_VALUE; lfree->admin.movingon = BOGUS_VALUE;
lfree->defn.label = perm_copy(label); lfree->defn.label = perm_copy(label);
lfree->defn.special = NULL; if (label_str)
lfree->defn.is_global = NOT_DEFINED_YET; nasm_free(label_str);
hash_add(&ip, lfree->defn.label, lfree); hash_add(&ip, lfree->defn.label, lfree);
return lfree++; return lfree++;
@@ -210,8 +240,8 @@ bool lookup_label(const char *label, int32_t *segment, int64_t *offset)
if (!initialized) if (!initialized)
return false; return false;
lptr = find_label(label, 0, NULL); lptr = find_label(label, false, NULL);
if (lptr && (lptr->defn.is_global & DEFINED_BIT)) { if (lptr && lptr->defn.defined) {
*segment = lptr->defn.segment; *segment = lptr->defn.segment;
*offset = lptr->defn.offset; *offset = lptr->defn.offset;
return true; return true;
@@ -227,12 +257,66 @@ bool is_extern(const char *label)
if (!initialized) if (!initialized)
return false; return false;
lptr = find_label(label, 0, NULL); lptr = find_label(label, false, NULL);
return (lptr && (lptr->defn.is_global & EXTERN_BIT)); return lptr && lptr->defn.type == LBL_EXTERN;
} }
static void handle_herelabel(const char *label, static const char *mangle_strings[] = {"", "", "", ""};
int32_t *segment, int64_t *offset) 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; int32_t oldseg;
@@ -248,7 +332,8 @@ static void handle_herelabel(const char *label,
/* This label is defined at this location */ /* This label is defined at this location */
int32_t newseg; 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)) if (likely(newseg == oldseg))
return; 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, static bool declare_label_lptr(union label *lptr,
bool is_norm, bool isextrn) enum label_type type, const char *special)
{
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;
}
/* 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;
}
/* 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;
}
nasm_error(ERR_NONFATAL, "symbol `%s' declared both as %s and %s",
lptr->defn.label, types[lptr->defn.type], types[type]);
return false;
}
bool declare_label(const char *label, enum label_type type, const char *special)
{ {
union label *lptr; union label *lptr;
int exi, created; bool created;
/* This routine possibly ought to check for phase errors. Most assemblers lptr = find_label(label, true, &created);
* check for phase errors at this point. I don't know whether phase errors return declare_label_lptr(lptr, type, special);
* are even possible, nor whether they are checked somewhere else }
/*
* 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;
/*
* 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);
(void)special; /* Don't warn that this parameter is unused */ if (pass0 > 1) {
(void)is_norm; /* Don't warn that this parameter is unused */ if (created)
(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); nasm_error(ERR_WARNING, "label `%s' defined on pass two", label);
if (!islocal(label)) {
if (!islocalchar(*label) && lptr->defn.is_norm)
prevlabel = lptr->defn.label;
} }
if (lptr->defn.offset != offset) if (lptr->defn.defined || lptr->defn.type == LBL_BACKEND) {
global_offset_changed++; /* We have seen this on at least one previous pass */
mangle_label_name(lptr);
lptr->defn.offset = offset; handle_herelabel(lptr, &segment, &offset);
lptr->defn.segment = segment;
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) */
}
void define_label(char *label, int32_t segment, int64_t offset, char *special,
bool is_norm, bool isextrn)
{
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
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) { if (ismagic(label) && lptr->defn.type == LBL_LOCAL)
/* not local, but not special either */ lptr->defn.type = LBL_SPECIAL;
if (!islocal(label) && normal) {
prevlabel = lptr->defn.label; prevlabel = lptr->defn.label;
} else if (islocal(label) && !*prevlabel) {
nasm_error(ERR_NONFATAL, "attempt to define a local label before any"
" non-local labels");
} }
changed = !lptr->defn.defined || lptr->defn.segment != segment ||
lptr->defn.offset != offset;
global_offset_changed += changed;
/*
* 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.segment = segment;
lptr->defn.offset = offset; lptr->defn.offset = offset;
lptr->defn.is_norm = (!islocalchar(label[0]) && is_norm); lptr->defn.defined = true;
if (pass0 == 1 || (!is_norm && !isextrn && (segment > 0) && (segment & 1))) { out_symdef(lptr);
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) */
} }
void define_common(char *label, int32_t segment, int32_t size, char *special) /*
* Define a special backend label
*/
void backend_label(const char *label, int32_t segment, int64_t offset)
{ {
union label *lptr; if (!declare_label(label, LBL_BACKEND, NULL))
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;
}
lptr->defn.is_global |= DEFINED_BIT|COMMON_BIT;
if (!islocalchar(label[0])) {
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;
if (pass0 == 0)
return; return;
out_symdef(lptr->defn.label, segment, size, 2, define_label(label, segment, offset, false);
special ? special : lptr->defn.special);
}
void declare_as_global(char *label, char *special)
{
union label *lptr;
if (islocal(label)) {
nasm_error(ERR_NONFATAL, "attempt to declare local symbol `%s' as"
" global", label);
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;
}
} }
int init_labels(void) int init_labels(void)
@@ -505,29 +512,53 @@ static void init_block(union label *blk)
blk[LABEL_BLOCK - 1].admin.next = NULL; blk[LABEL_BLOCK - 1].admin.next = NULL;
} }
static char * safe_alloc perm_alloc(size_t len)
{
if (perm_tail->size - perm_tail->usage < len) {
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 = alloc_len;
perm_tail->usage = 0;
}
perm_tail->usage += len;
return perm_tail->data + perm_tail->usage;
}
static char *perm_copy(const char *string) static char *perm_copy(const char *string)
{ {
char *p; char *p;
int len = strlen(string)+1; size_t len;
nasm_assert(len <= PERMTS_SIZE); if (!string)
return NULL;
if (perm_tail->size - perm_tail->usage < len) { len = strlen(string)+1; /* Include final NUL */
perm_tail->next =
nasm_malloc(sizeof(struct permts)); p = perm_alloc(len);
perm_tail = perm_tail->next;
perm_tail->next = NULL;
perm_tail->size = PERMTS_SIZE;
perm_tail->usage = 0;
}
p = perm_tail->data + perm_tail->usage;
memcpy(p, string, len); memcpy(p, string, len);
perm_tail->usage += len;
return p; return p;
} }
char *local_scope(char *label) 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;
}
const char *local_scope(const char *label)
{ {
return islocal(label) ? prevlabel : ""; return islocal(label) ? prevlabel : "";
} }

View File

@@ -718,21 +718,25 @@ enum text_options {
OPT_BOGUS, OPT_BOGUS,
OPT_VERSION, OPT_VERSION,
OPT_ABORT_ON_PANIC, OPT_ABORT_ON_PANIC,
OPT_PREFIX, OPT_MANGLE
OPT_POSTFIX
}; };
struct textargs { struct textargs {
const char *label; const char *label;
enum text_options opt; enum text_options opt;
bool need_arg; bool need_arg;
int pvt;
}; };
static const struct textargs textopts[] = { static const struct textargs textopts[] = {
{"v", OPT_VERSION, false}, {"v", OPT_VERSION, false, 0},
{"version", OPT_VERSION, false}, {"version", OPT_VERSION, false, 0},
{"abort-on-panic", OPT_ABORT_ON_PANIC, false}, {"abort-on-panic", OPT_ABORT_ON_PANIC, false, 0},
{"prefix", OPT_PREFIX, true}, {"prefix", OPT_MANGLE, true, LM_GPREFIX},
{"postfix", OPT_POSTFIX, true}, {"postfix", OPT_MANGLE, true, LM_GSUFFIX},
{NULL, OPT_BOGUS, false} {"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) 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" " -h show invocation summary and exit\n\n"
"--prefix,--postfix\n" "--prefix,--postfix\n"
" these options prepend or append the given string\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" "\n"
"Response files should contain command line parameters,\n" "Response files should contain command line parameters,\n"
"one per line.\n" "one per line.\n"
@@ -1081,13 +1088,9 @@ static bool process_arg(char *p, char *q, int pass)
case OPT_ABORT_ON_PANIC: case OPT_ABORT_ON_PANIC:
abort_on_panic = true; abort_on_panic = true;
break; break;
case OPT_PREFIX: case OPT_MANGLE:
if (pass == 2) if (pass == 2)
strlcpy(lprefix, q, PREFIX_MAX); set_label_mangle(tx->pvt, q);
break;
case OPT_POSTFIX:
if (pass == 2)
strlcpy(lpostfix, q, POSTFIX_MAX);
break; break;
case OPT_BOGUS: case OPT_BOGUS:
nasm_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE, 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 */ pass_max = prev_offset_changed = (INT_MAX >> 1) + 2; /* Almost unlimited */
for (passn = 1; pass0 <= 2; passn++) { for (passn = 1; pass0 <= 2; passn++) {
ldfunc def_label;
pass1 = pass0 == 2 ? 2 : 1; /* 1, 1, 1, ..., 1, 2 */ pass1 = pass0 == 2 ? 2 : 1; /* 1, 1, 1, ..., 1, 2 */
pass2 = passn > 1 ? 2 : 1; /* 1, 2, 2, ..., 2, 2 */ pass2 = passn > 1 ? 2 : 1; /* 1, 2, 2, ..., 2, 2 */
/* pass0 0, 0, 0, ..., 1, 2 */ /* pass0 0, 0, 0, ..., 1, 2 */
def_label = passn > 1 ? redefine_label : define_label;
globalbits = cmd_sb; /* set 'bits' to command line default */ globalbits = cmd_sb; /* set 'bits' to command line default */
cpu = cmd_cpu; cpu = cmd_cpu;
if (pass0 == 2) { 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 */ goto end_of_line; /* Just do final cleanup */
/* Not a directive, or even something that starts with [ */ /* Not a directive, or even something that starts with [ */
parse_line(pass1, line, &output_ins);
parse_line(pass1, line, &output_ins, def_label);
if (optimizing > 0) { if (optimizing > 0) {
if (forwref != NULL && globallineno == forwref->lineno) { if (forwref != NULL && globallineno == forwref->lineno) {
@@ -1405,71 +1403,29 @@ static void assemble_file(const char *fname, StrList **depend_ptr)
/* forw_ref */ /* forw_ref */
if (output_ins.opcode == I_EQU) { if (output_ins.opcode == I_EQU) {
if (pass1 == 1) { if (!output_ins.label)
/* nasm_error(ERR_NONFATAL,
* Special `..' EQUs get processed in pass two, "EQU not preceded by label");
* except `..@' macro-processor EQUs which are done
* in the normal place. if (output_ins.operands == 1 &&
*/ (output_ins.oprs[0].type & IMMEDIATE) &&
if (!output_ins.label) output_ins.oprs[0].wrt == NO_SEG) {
nasm_error(ERR_NONFATAL, define_label(output_ins.label,
"EQU not preceded by label"); output_ins.oprs[0].segment,
output_ins.oprs[0].offset, false);
else if (output_ins.label[0] != '.' || } else if (output_ins.operands == 2
output_ins.label[1] != '.' || && (output_ins.oprs[0].type & IMMEDIATE)
output_ins.label[2] == '@') { && (output_ins.oprs[0].type & COLON)
if (output_ins.operands == 1 && && output_ins.oprs[0].segment == NO_SEG
(output_ins.oprs[0].type & IMMEDIATE) && && output_ins.oprs[0].wrt == NO_SEG
output_ins.oprs[0].wrt == NO_SEG) { && (output_ins.oprs[1].type & IMMEDIATE)
bool isext = !!(output_ins.oprs[0].opflags & OPFLAG_EXTERN); && output_ins.oprs[1].segment == NO_SEG
def_label(output_ins.label, && output_ins.oprs[1].wrt == NO_SEG) {
output_ins.oprs[0].segment, define_label(output_ins.label,
output_ins.oprs[0].offset, NULL, output_ins.oprs[0].offset | SEG_ABS,
false, isext); output_ins.oprs[1].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) {
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");
}
} else { } else {
/* nasm_error(ERR_NONFATAL, "bad syntax for EQU");
* 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");
}
} }
} else { /* instruction isn't an EQU */ } else { /* instruction isn't an EQU */
int32_t n; int32_t n;

View File

@@ -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 * See the file AUTHORS included with the NASM distribution for
* the specific copyright holders. * the specific copyright holders.
* *
@@ -426,7 +426,7 @@ static int value_to_extop(expr * vect, extop *eop, int32_t myseg)
return 0; 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; bool insn_is_label = false;
struct eval_hints hints; struct eval_hints hints;
@@ -485,8 +485,8 @@ restart_parse:
* Generally fix things. I think this is right as it is, but * Generally fix things. I think this is right as it is, but
* am still not certain. * am still not certain.
*/ */
ldef(result->label, in_absolute ? absolute.segment : location.segment, define_label(result->label, location.segment,
location.offset, NULL, true, false); location.offset, true);
} }
} }

View File

@@ -39,7 +39,7 @@
#ifndef NASM_PARSER_H #ifndef NASM_PARSER_H
#define 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); void cleanup_insn(insn *instruction);
#endif #endif

View File

@@ -49,6 +49,8 @@
#include "assemble.h" #include "assemble.h"
#include "error.h" #include "error.h"
static enum directive_result asm_pragma(const struct pragma *pragma);
/* /*
* Handle [pragma] directives. [pragma] is generally produced by * Handle [pragma] directives. [pragma] is generally produced by
* the %pragma preprocessor directive, which simply passes on any * the %pragma preprocessor directive, which simply passes on any
@@ -83,7 +85,7 @@
*/ */
static struct pragma_facility global_pragmas[] = static struct pragma_facility global_pragmas[] =
{ {
{ "asm", NULL }, { "asm", asm_pragma },
{ "list", NULL }, { "list", NULL },
{ "file", NULL }, { "file", NULL },
{ "input", NULL }, { "input", NULL },
@@ -202,7 +204,7 @@ void process_pragma(char *str)
else else
pragma.opcode = directive_find(pragma.opname); pragma.opcode = directive_find(pragma.opname);
pragma.tail = nasm_skip_spaces(p); pragma.tail = nasm_trim_spaces(p);
/* Look for a global pragma namespace */ /* Look for a global pragma namespace */
if (search_pragma_list(global_pragmas, NULL, &pragma)) if (search_pragma_list(global_pragmas, NULL, &pragma))
@@ -227,3 +229,28 @@ void process_pragma(char *str)
* already defined for future compatibility. * 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;
}
}

View File

@@ -40,10 +40,10 @@
#include "nasmlib.h" #include "nasmlib.h"
#include "insns.h" #include "insns.h"
static int32_t next_seg = 0; static int32_t next_seg = 2;
void seg_alloc_reset(void) void seg_alloc_reset(void)
{ {
next_seg = 0; next_seg = 2;
} }
int32_t seg_alloc(void) int32_t seg_alloc(void)
@@ -51,6 +51,5 @@ int32_t seg_alloc(void)
int32_t this_seg = next_seg; int32_t this_seg = next_seg;
next_seg += 2; next_seg += 2;
return this_seg; return this_seg;
} }

View File

@@ -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 * See the file AUTHORS included with the NASM distribution for
* the specific copyright holders. * the specific copyright holders.
* *
@@ -40,20 +40,34 @@
#include "compiler.h" #include "compiler.h"
extern char lprefix[PREFIX_MAX]; enum mangle_index {
extern char lpostfix[PREFIX_MAX]; 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 lookup_label(const char *label, int32_t *segment, int64_t *offset);
bool is_extern(const char *label); bool is_extern(const char *label);
void define_label(char *label, int32_t segment, int64_t offset, char *special, void define_label(const char *label, int32_t segment, int64_t offset,
bool is_norm, bool isextrn); bool normal);
void redefine_label(char *label, int32_t segment, int64_t offset, char *special, void backend_label(const char *label, int32_t segment, int64_t offset);
bool is_norm, bool isextrn); bool declare_label(const char *label, enum label_type type,
void define_common(char *label, int32_t segment, int32_t size, char *special); const char *special);
void declare_as_global(char *label, char *special); void set_label_mangle(enum mangle_index which, const char *what);
int init_labels(void); int init_labels(void);
void cleanup_labels(void); void cleanup_labels(void);
char *local_scope(char *label); const char *local_scope(const char *label);
extern uint64_t global_offset_changed; extern uint64_t global_offset_changed;

View File

@@ -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 * See the file AUTHORS included with the NASM distribution for
* the specific copyright holders. * the specific copyright holders.
* *
@@ -48,6 +48,7 @@
#include "preproc.h" #include "preproc.h"
#include "insnsi.h" /* For enum opcode */ #include "insnsi.h" /* For enum opcode */
#include "directiv.h" /* For enum directive */ #include "directiv.h" /* For enum directive */
#include "labels.h" /* For enum mangle_index, enum label_type */
#include "opflags.h" #include "opflags.h"
#include "regs.h" #include "regs.h"
@@ -61,7 +62,7 @@ struct compile_time {
}; };
extern struct compile_time official_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 */ #define SEG_ABS 0x40000000L /* mask for far-absolute segments */
#ifndef PREFIX_MAX #ifndef PREFIX_MAX
@@ -141,11 +142,6 @@ struct out_data {
int64_t relbase; /* Relative base for OUT_RELADDR */ 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 * And a label-definition function. The boolean parameter
* `is_norm' states whether the label is a `normal' label (which * `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. * an EQU or a segment-base symbol, which shouldn't.
*/ */
typedef void (*ldfunc)(char *label, int32_t segment, int64_t offset, typedef void (*ldfunc)(char *label, int32_t segment, int64_t offset,
char *special, bool is_norm, bool isextrn); char *special, bool is_norm);
void define_label(char *label, int32_t segment, int64_t offset,
char *special, bool is_norm, bool isextrn);
/* /*
* Token types returned by the scanner, in addition to ordinary * Token types returned by the scanner, in addition to ordinary
@@ -904,7 +897,7 @@ struct ofmt {
* current offset, i.e. "foo:" or "foo equ $". * current offset, i.e. "foo:" or "foo equ $".
* The offset isn't passed; and may not be stable at this point. * 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, * This procedure is called to modify section alignment,

View File

@@ -130,13 +130,6 @@ STD: nasm
%endif %endif
%endmacro %endmacro
%imacro extern 1-*.nolist
%rep %0
[extern %1]
%rotate 1
%endrep
%endmacro
%imacro bits 1+.nolist %imacro bits 1+.nolist
[bits %1] [bits %1]
%endmacro %endmacro
@@ -153,6 +146,20 @@ STD: nasm
[bits 64] [bits 64]
%endmacro %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 %imacro global 1-*.nolist
%rep %0 %rep %0
[global %1] [global %1]

View File

@@ -198,15 +198,15 @@ static void aoutb_init(void)
is_pic = 0x00; /* may become 0x40 */ is_pic = 0x00; /* may become 0x40 */
aout_gotpc_sect = seg_alloc(); 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(); 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(); 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(); 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(); 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 #endif

View File

@@ -1217,11 +1217,11 @@ static void bin_define_section_labels(void)
/* section.<name>.start */ /* section.<name>.start */
strcpy(label_name + base_len, ".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 */ /* section.<name>.vstart */
strcpy(label_name + base_len, ".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); nasm_free(label_name);
} }

View File

@@ -198,7 +198,7 @@ static void coff_win64_init(void)
win64 = true; win64 = true;
coff_gen_init(); coff_gen_init();
imagebase_sect = seg_alloc()+1; 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) static void coff_std_init(void)

View File

@@ -124,7 +124,7 @@ static int32_t dbg_add_section(char *name, int pass, int *bits,
whatwecallit, name, tail, pass, seg); whatwecallit, name, tail, pass, seg);
if (section_labels) if (section_labels)
define_label(s->name, s->number + 1, 0, NULL, false, false); backend_label(s->name, s->number + 1, 0);
} }
} }
return seg; 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"); 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; int32_t newseg = seg;
if (subsections_via_symbols && name[0] != 'L') if (subsections_via_symbols && type != LBL_LOCAL)
newseg += 0x10000; newseg += 0x10000;
fprintf(ofile, "herelabel %s (seg %08x) -> %08x\n", fprintf(ofile, "herelabel %s type %d (seg %08x) -> %08x\n",
name, seg, newseg); name, type, seg, newseg);
return newseg; return newseg;
} }

View File

@@ -337,19 +337,19 @@ static void elf_init(void)
*/ */
elf_gotpc_sect = seg_alloc(); 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(); 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(); 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(); 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(); 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(); 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(); 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(); def_seg = seg_alloc();
} }

View File

@@ -808,10 +808,9 @@ static int32_t ieee_segment(char *name, int pass, int *bits)
ieee_seg_needs_update = seg; ieee_seg_needs_update = seg;
if (seg->align >= SEG_ABS) if (seg->align >= SEG_ABS)
define_label(name, NO_SEG, seg->align - SEG_ABS, define_label(name, NO_SEG, seg->align - SEG_ABS, false);
NULL, false, false);
else else
define_label(name, seg->index + 1, 0L, NULL, false, false); define_label(name, seg->index + 1, 0L, false);
ieee_seg_needs_update = NULL; ieee_seg_needs_update = NULL;
if (seg->use32) if (seg->use32)

View File

@@ -411,7 +411,7 @@ static void macho_init(void)
/* add special symbol for TLVP */ /* add special symbol for TLVP */
macho_tlvp_sect = seg_alloc() + 1; 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); 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; struct section *s;
(void)name;
if (!(head_flags & MH_SUBSECTIONS_VIA_SYMBOLS)) if (!(head_flags & MH_SUBSECTIONS_VIA_SYMBOLS))
return section; return section;
/* If it starts with L, it doesn't start a new subsection */ /* No subsection only for local labels */
if (name[0] == 'L') if (type == LBL_LOCAL)
return section; return section;
s = get_section_by_index(section); s = get_section_by_index(section);
@@ -2398,7 +2400,7 @@ static void macho64_init(void)
/* add special symbol for ..gotpcrel */ /* add special symbol for ..gotpcrel */
macho_gotpcrel_sect = seg_alloc() + 1; 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 = { static const struct dfmt macho64_df_dwarf = {

View File

@@ -1540,11 +1540,9 @@ static int32_t obj_segment(char *name, int pass, int *bits)
obj_seg_needs_update = seg; obj_seg_needs_update = seg;
if (seg->align >= SEG_ABS) if (seg->align >= SEG_ABS)
define_label(name, NO_SEG, seg->align - SEG_ABS, define_label(name, NO_SEG, seg->align - SEG_ABS, false);
NULL, false, false);
else else
define_label(name, seg->index + 1, 0L, define_label(name, seg->index + 1, 0L, false);
NULL, false, false);
obj_seg_needs_update = NULL; obj_seg_needs_update = NULL;
/* /*
@@ -1647,7 +1645,7 @@ obj_directive(enum directive directive, char *value, int pass)
grp->name = NULL; grp->name = NULL;
obj_grp_needs_update = grp; 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; obj_grp_needs_update = NULL;
while (*q) { while (*q) {

View File

@@ -5,12 +5,13 @@
; ;
%pragma output subsections_via_symbols %pragma output subsections_via_symbols
%pragma asm gprefix _
%pragma asm lprefix L_
bits 32 bits 32
global foo, bar, quux global foo, bar
static quux
%define baz Lbaz
foo: foo:
jmp foo jmp foo