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:
177
asm/directiv.c
177
asm/directiv.c
@@ -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] */
|
||||||
|
@@ -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
|
||||||
|
@@ -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 '-':
|
||||||
|
533
asm/labels.c
533
asm/labels.c
@@ -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(<ab, label, &ip);
|
lpp = (union label **) hash_find(<ab, 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 : "";
|
||||||
}
|
}
|
||||||
|
126
asm/nasm.c
126
asm/nasm.c
@@ -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;
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
31
asm/pragma.c
31
asm/pragma.c
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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,
|
||||||
|
@@ -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]
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
|
@@ -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 = {
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user