blob: f6b940fcaaa70bb502c9f91e17c0668ecd43eebf [file] [log] [blame]
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07001/* ----------------------------------------------------------------------- *
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +04002 *
H. Peter Anvin892c4812018-05-30 14:43:46 -07003 * Copyright 1996-2018 The NASM Authors - All Rights Reserved
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07004 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00006 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07007 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +040017 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -070018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * ----------------------------------------------------------------------- */
33
34/*
35 * labels.c label handling for the Netwide Assembler
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000036 */
37
H. Peter Anvinfe501952007-10-02 21:53:51 -070038#include "compiler.h"
39
Keith Kaniosb7a89542007-04-12 02:40:54 +000040
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000041#include "nasm.h"
42#include "nasmlib.h"
H. Peter Anvinb20bc732017-03-07 19:23:03 -080043#include "error.h"
H. Peter Anvin6244f4b2007-09-14 18:03:29 -070044#include "hashtbl.h"
H. Peter Anvinc6645832014-11-25 12:07:10 -080045#include "labels.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000046
47/*
H. Peter Anvin98578072018-06-01 18:02:54 -070048 * A dot-local label is one that begins with exactly one period. Things
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000049 * that begin with _two_ periods are NASM-specific things.
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +000050 *
51 * If TASM compatibility is enabled, a local label can also begin with
H. Peter Anvin98578072018-06-01 18:02:54 -070052 * @@.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000053 */
H. Peter Anvin98578072018-06-01 18:02:54 -070054static bool islocal(const char *l)
55{
56 if (tasm_compatible_mode) {
57 if (l[0] == '@' && l[1] == '@')
58 return true;
59 }
60
61 return (l[0] == '.' && l[1] != '.');
62}
63
64/*
65 * Return true if this falls into NASM's '..' namespace
66 */
67static bool ismagic(const char *l)
68{
69 return l[0] == '.' && l[1] == '.' && l[2] != '@';
70}
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000071
H. Peter Anvin, Intelbc77f9c2018-06-25 12:39:42 -070072/*
73 * Return true if we should update the local label base
74 * as a result of this symbol. We must exclude local labels
75 * as well as any kind of special labels, including ..@ ones.
76 */
77static bool set_prevlabel(const char *l)
78{
79 if (tasm_compatible_mode) {
80 if (l[0] == '@' && l[1] == '@')
81 return false;
82 }
83
84 return l[0] != '.';
85}
86
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +040087#define LABEL_BLOCK 128 /* no. of labels/block */
88#define LBLK_SIZE (LABEL_BLOCK * sizeof(union label))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000089
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +040090#define END_LIST -3 /* don't clash with NO_SEG! */
91#define END_BLOCK -2
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000092
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +040093#define PERMTS_SIZE 16384 /* size of text blocks */
H. Peter Anvin565be912009-07-05 22:15:57 -070094#if (PERMTS_SIZE < IDLEN_MAX)
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +040095 #error "IPERMTS_SIZE must be greater than or equal to IDLEN_MAX"
Ed Berosetc06f6df2003-09-08 00:30:40 +000096#endif
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000097
H. Peter Anvin98578072018-06-01 18:02:54 -070098/* string values for enum label_type */
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -040099static const char * const types[] = {
100 "local", "static", "global", "extern", "required", "common",
101 "special", "output format special"
102};
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000103
H. Peter Anvine2c80182005-01-15 22:15:51 +0000104union label { /* actual label structures */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000105 struct {
Charles Crayne4e8563d2007-11-05 17:19:32 -0800106 int32_t segment;
H. Peter Anvin29695c82018-06-14 17:04:32 -0700107 int32_t subsection; /* Available for ofmt->herelabel() */
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400108 int64_t offset;
H. Peter Anvin73482482018-06-11 14:54:14 -0700109 int64_t size;
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800110 int64_t defined; /* 0 if undefined, passn+1 for when defn seen */
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400111 int64_t lastref; /* Last pass where we saw a reference */
H. Peter Anvin98578072018-06-01 18:02:54 -0700112 char *label, *mangled, *special;
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800113 const char *def_file; /* Where defined */
114 int32_t def_line;
H. Peter Anvin98578072018-06-01 18:02:54 -0700115 enum label_type type, mangled_type;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000116 } defn;
117 struct {
Charles Crayne4e8563d2007-11-05 17:19:32 -0800118 int32_t movingon;
119 int64_t dummy;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000120 union label *next;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000121 } admin;
122};
123
H. Peter Anvine2c80182005-01-15 22:15:51 +0000124struct permts { /* permanent text storage */
125 struct permts *next; /* for the linked list */
H. Peter Anvin98578072018-06-01 18:02:54 -0700126 unsigned int size, usage; /* size and used space in ... */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000127 char data[PERMTS_SIZE]; /* ... the data block itself */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000128};
H. Peter Anvin98578072018-06-01 18:02:54 -0700129#define PERMTS_HEADER offsetof(struct permts, data)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000130
H. Peter Anvin9c595b62017-03-07 19:44:21 -0800131uint64_t global_offset_changed; /* counter for global offset changes */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000132
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400133static struct hash_table ltab; /* labels hash table */
134static union label *ldata; /* all label data blocks */
135static union label *lfree; /* labels free block */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000136static struct permts *perm_head; /* start of perm. text storage */
137static struct permts *perm_tail; /* end of perm. text storage */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000138
H. Peter Anvine2c80182005-01-15 22:15:51 +0000139static void init_block(union label *blk);
H. Peter Anvin98578072018-06-01 18:02:54 -0700140static char *perm_alloc(size_t len);
H. Peter Anvind2fb7a62007-09-16 17:53:17 -0700141static char *perm_copy(const char *string);
H. Peter Anvin98578072018-06-01 18:02:54 -0700142static char *perm_copy3(const char *s1, const char *s2, const char *s3);
143static const char *mangle_label_name(union label *lptr);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000144
H. Peter Anvin98578072018-06-01 18:02:54 -0700145static const char *prevlabel;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000146
H. Peter Anvin70055962007-10-11 00:05:31 -0700147static bool initialized = false;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000148
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000149/*
H. Peter Anvinfc0ff222016-03-07 21:46:04 -0800150 * Emit a symdef to the output and the debug format backends.
151 */
H. Peter Anvin98578072018-06-01 18:02:54 -0700152static void out_symdef(union label *lptr)
H. Peter Anvinfc0ff222016-03-07 21:46:04 -0800153{
H. Peter Anvin98578072018-06-01 18:02:54 -0700154 int backend_type;
H. Peter Anvin73482482018-06-11 14:54:14 -0700155 int64_t backend_offset;
H. Peter Anvin98578072018-06-01 18:02:54 -0700156
157 /* Backend-defined special segments are passed to symdef immediately */
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -0800158 if (pass_final()) {
H. Peter Anvin98578072018-06-01 18:02:54 -0700159 /* Emit special fixups for globals and commons */
160 switch (lptr->defn.type) {
161 case LBL_GLOBAL:
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400162 case LBL_REQUIRED:
H. Peter Anvin73482482018-06-11 14:54:14 -0700163 case LBL_COMMON:
H. Peter Anvin98578072018-06-01 18:02:54 -0700164 if (lptr->defn.special)
H. Peter Anvina7c8e392018-06-18 14:17:26 -0700165 ofmt->symdef(lptr->defn.mangled, 0, 0, 3, lptr->defn.special);
H. Peter Anvin98578072018-06-01 18:02:54 -0700166 break;
167 default:
168 break;
169 }
170 return;
171 }
172
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -0800173 if (pass_type() != PASS_STAB && lptr->defn.type != LBL_BACKEND)
H. Peter Anvin98578072018-06-01 18:02:54 -0700174 return;
175
176 /* Clean up this hack... */
177 switch(lptr->defn.type) {
Cyrill Gorcunov70d42962018-07-01 01:59:07 +0300178 case LBL_EXTERN:
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400179 /* If not seen in the previous or this pass, drop it */
180 if (lptr->defn.lastref < pass_count())
181 return;
182
183 /* Otherwise, promote to LBL_REQUIRED at this time */
184 lptr->defn.type = LBL_REQUIRED;
185
186 /* fall through */
187 case LBL_GLOBAL:
188 case LBL_REQUIRED:
H. Peter Anvin98578072018-06-01 18:02:54 -0700189 backend_type = 1;
H. Peter Anvin73482482018-06-11 14:54:14 -0700190 backend_offset = lptr->defn.offset;
H. Peter Anvin98578072018-06-01 18:02:54 -0700191 break;
192 case LBL_COMMON:
193 backend_type = 2;
H. Peter Anvin73482482018-06-11 14:54:14 -0700194 backend_offset = lptr->defn.size;
H. Peter Anvin98578072018-06-01 18:02:54 -0700195 break;
196 default:
197 backend_type = 0;
H. Peter Anvin73482482018-06-11 14:54:14 -0700198 backend_offset = lptr->defn.offset;
H. Peter Anvin98578072018-06-01 18:02:54 -0700199 break;
200 }
201
202 /* Might be necessary for a backend symbol */
203 mangle_label_name(lptr);
204
205 ofmt->symdef(lptr->defn.mangled, lptr->defn.segment,
H. Peter Anvin73482482018-06-11 14:54:14 -0700206 backend_offset, backend_type,
H. Peter Anvin98578072018-06-01 18:02:54 -0700207 lptr->defn.special);
H. Peter Anvinfc0ff222016-03-07 21:46:04 -0800208
209 /*
210 * NASM special symbols are not passed to the debug format; none
211 * of the current backends want to see them.
212 */
H. Peter Anvin98578072018-06-01 18:02:54 -0700213 if (lptr->defn.type == LBL_SPECIAL || lptr->defn.type == LBL_BACKEND)
214 return;
215
216 dfmt->debug_deflabel(lptr->defn.mangled, lptr->defn.segment,
217 lptr->defn.offset, backend_type,
218 lptr->defn.special);
H. Peter Anvinfc0ff222016-03-07 21:46:04 -0800219}
220
221/*
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000222 * Internal routine: finds the `union label' corresponding to the
223 * given label name. Creates a new one, if it isn't found, and if
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700224 * `create' is true.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000225 */
H. Peter Anvin98578072018-06-01 18:02:54 -0700226static union label *find_label(const char *label, bool create, bool *created)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000227{
H. Peter Anvin97a23472007-09-16 17:57:25 -0700228 union label *lptr, **lpp;
H. Peter Anvin98578072018-06-01 18:02:54 -0700229 char *label_str = NULL;
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700230 struct hash_insert ip;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000231
Cyrill Gorcunov8e740c62018-10-13 17:18:05 +0300232 nasm_assert(label != NULL);
233
H. Peter Anvin98578072018-06-01 18:02:54 -0700234 if (islocal(label))
235 label = label_str = nasm_strcat(prevlabel, label);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000236
H. Peter Anvin166c2472008-05-28 12:28:58 -0700237 lpp = (union label **) hash_find(&ltab, label, &ip);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700238 lptr = lpp ? *lpp : NULL;
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700239
Cyrill Gorcunov5dfcab62016-07-18 11:49:47 +0300240 if (lptr || !create) {
241 if (created)
H. Peter Anvin98578072018-06-01 18:02:54 -0700242 *created = false;
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400243 return lptr;
Cyrill Gorcunov5dfcab62016-07-18 11:49:47 +0300244 }
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700245
246 /* Create a new label... */
247 if (lfree->admin.movingon == END_BLOCK) {
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400248 /*
249 * must allocate a new block
250 */
H. Peter Anvin3e555482017-04-23 17:02:46 -0700251 lfree->admin.next = nasm_malloc(LBLK_SIZE);
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400252 lfree = lfree->admin.next;
253 init_block(lfree);
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700254 }
H. Peter Anvin70653092007-10-19 14:42:29 -0700255
Cyrill Gorcunov5dfcab62016-07-18 11:49:47 +0300256 if (created)
H. Peter Anvin98578072018-06-01 18:02:54 -0700257 *created = true;
Cyrill Gorcunov5dfcab62016-07-18 11:49:47 +0300258
H. Peter Anvin98578072018-06-01 18:02:54 -0700259 nasm_zero(*lfree);
H. Peter Anvin98578072018-06-01 18:02:54 -0700260 lfree->defn.label = perm_copy(label);
H. Peter Anvin29695c82018-06-14 17:04:32 -0700261 lfree->defn.subsection = NO_SEG;
H. Peter Anvin98578072018-06-01 18:02:54 -0700262 if (label_str)
263 nasm_free(label_str);
H. Peter Anvin70653092007-10-19 14:42:29 -0700264
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700265 hash_add(&ip, lfree->defn.label, lfree);
266 return lfree++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000267}
268
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400269enum label_type lookup_label(const char *label,
270 int32_t *segment, int64_t *offset)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000271{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000272 union label *lptr;
273
Keith Kaniosb7a89542007-04-12 02:40:54 +0000274 if (!initialized)
H. Peter Anvin7ad25b22019-09-12 20:26:23 -0400275 return LBL_none;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000276
H. Peter Anvin98578072018-06-01 18:02:54 -0700277 lptr = find_label(label, false, NULL);
278 if (lptr && lptr->defn.defined) {
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400279 int64_t lpass = pass_count() + 1;
280
281 lptr->defn.lastref = lpass;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000282 *segment = lptr->defn.segment;
283 *offset = lptr->defn.offset;
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400284 return lptr->defn.type;
Cyrill Gorcunovd7a64b72010-04-20 15:26:08 +0400285 }
286
H. Peter Anvin7ad25b22019-09-12 20:26:23 -0400287 return LBL_none;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000288}
289
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400290static inline bool is_global(enum label_type type)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000291{
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400292 return type == LBL_GLOBAL || type == LBL_COMMON;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000293}
294
H. Peter Anvin98578072018-06-01 18:02:54 -0700295static const char *mangle_strings[] = {"", "", "", ""};
296static bool mangle_string_set[ARRAY_SIZE(mangle_strings)];
297
298/*
299 * Set a prefix or suffix
300 */
301void set_label_mangle(enum mangle_index which, const char *what)
302{
303 if (mangle_string_set[which])
304 return; /* Once set, do not change */
305
306 mangle_strings[which] = perm_copy(what);
307 mangle_string_set[which] = true;
308}
309
310/*
311 * Format a label name with appropriate prefixes and suffixes
312 */
313static const char *mangle_label_name(union label *lptr)
314{
315 const char *prefix;
316 const char *suffix;
317
318 if (likely(lptr->defn.mangled &&
319 lptr->defn.mangled_type == lptr->defn.type))
320 return lptr->defn.mangled; /* Already mangled */
321
322 switch (lptr->defn.type) {
323 case LBL_GLOBAL:
324 case LBL_STATIC:
325 case LBL_EXTERN:
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400326 case LBL_REQUIRED:
H. Peter Anvin98578072018-06-01 18:02:54 -0700327 prefix = mangle_strings[LM_GPREFIX];
328 suffix = mangle_strings[LM_GSUFFIX];
329 break;
330 case LBL_BACKEND:
331 case LBL_SPECIAL:
332 prefix = suffix = "";
333 break;
334 default:
335 prefix = mangle_strings[LM_LPREFIX];
336 suffix = mangle_strings[LM_LSUFFIX];
337 break;
338 }
339
340 lptr->defn.mangled_type = lptr->defn.type;
341
342 if (!(*prefix) && !(*suffix))
343 lptr->defn.mangled = lptr->defn.label;
344 else
345 lptr->defn.mangled = perm_copy3(prefix, lptr->defn.label, suffix);
346
347 return lptr->defn.mangled;
348}
349
350static void
H. Peter Anvin29695c82018-06-14 17:04:32 -0700351handle_herelabel(union label *lptr, int32_t *segment, int64_t *offset)
H. Peter Anvin892c4812018-05-30 14:43:46 -0700352{
353 int32_t oldseg;
354
355 if (likely(!ofmt->herelabel))
356 return;
357
358 if (unlikely(location.segment == NO_SEG))
359 return;
360
361 oldseg = *segment;
362
363 if (oldseg == location.segment && *offset == location.offset) {
364 /* This label is defined at this location */
365 int32_t newseg;
H. Peter Anvin (Intel)d6441192018-06-27 20:20:21 -0700366 bool copyoffset = false;
H. Peter Anvin892c4812018-05-30 14:43:46 -0700367
H. Peter Anvin98578072018-06-01 18:02:54 -0700368 nasm_assert(lptr->defn.mangled);
H. Peter Anvin29695c82018-06-14 17:04:32 -0700369 newseg = ofmt->herelabel(lptr->defn.mangled, lptr->defn.type,
H. Peter Anvin (Intel)d6441192018-06-27 20:20:21 -0700370 oldseg, &lptr->defn.subsection, &copyoffset);
H. Peter Anvin892c4812018-05-30 14:43:46 -0700371 if (likely(newseg == oldseg))
372 return;
373
374 *segment = newseg;
H. Peter Anvin (Intel)d6441192018-06-27 20:20:21 -0700375 if (copyoffset) {
376 /* Maintain the offset from the old to the new segment */
377 switch_segment(newseg);
378 location.offset = *offset;
379 } else {
380 /* Keep a separate offset for the new segment */
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800381 *offset = switch_segment(newseg);
H. Peter Anvin (Intel)d6441192018-06-27 20:20:21 -0700382 }
H. Peter Anvin892c4812018-05-30 14:43:46 -0700383 }
384}
385
H. Peter Anvin98578072018-06-01 18:02:54 -0700386static bool declare_label_lptr(union label *lptr,
387 enum label_type type, const char *special)
388{
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400389 enum label_type oldtype = lptr->defn.type;
390
H. Peter Anvin3cb90682018-06-01 21:05:45 -0700391 if (special && !special[0])
392 special = NULL;
393
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400394 if (oldtype == type || (!pass_stable() && oldtype == LBL_LOCAL) ||
395 (oldtype == LBL_EXTERN && type == LBL_REQUIRED)) {
H. Peter Anvin98578072018-06-01 18:02:54 -0700396 lptr->defn.type = type;
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400397
H. Peter Anvin98578072018-06-01 18:02:54 -0700398 if (special) {
399 if (!lptr->defn.special)
400 lptr->defn.special = perm_copy(special);
401 else if (nasm_stricmp(lptr->defn.special, special))
Cyrill Gorcunov46c37b32018-12-01 20:03:55 +0300402 nasm_nonfatal("symbol `%s' has inconsistent attributes `%s' and `%s'",
403 lptr->defn.label, lptr->defn.special, special);
H. Peter Anvin98578072018-06-01 18:02:54 -0700404 }
405 return true;
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400406 } else if (is_extern(oldtype) && is_global(type)) {
407 /* EXTERN or REQUIRED can be replaced with GLOBAL or COMMON */
H. Peter Anvin98578072018-06-01 18:02:54 -0700408 lptr->defn.type = type;
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400409
H. Peter Anvin98578072018-06-01 18:02:54 -0700410 /* Override special unconditionally */
411 if (special)
412 lptr->defn.special = perm_copy(special);
413 return true;
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400414 } else if (is_extern(type) && (is_global(oldtype) || is_extern(oldtype))) {
415 /*
416 * GLOBAL or COMMON ignore subsequent EXTERN or REQUIRED;
417 * REQUIRED ignores subsequent EXTERN.
418 */
H. Peter Anvin98578072018-06-01 18:02:54 -0700419
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400420 /* Ignore special unless we don't already have one */
H. Peter Anvin98578072018-06-01 18:02:54 -0700421 if (!lptr->defn.special)
422 lptr->defn.special = perm_copy(special);
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400423
424 return false; /* Don't call define_label() after this! */
H. Peter Anvin98578072018-06-01 18:02:54 -0700425 }
426
Cyrill Gorcunov46c37b32018-12-01 20:03:55 +0300427 nasm_nonfatal("symbol `%s' declared both as %s and %s",
428 lptr->defn.label, types[lptr->defn.type], types[type]);
H. Peter Anvin98578072018-06-01 18:02:54 -0700429 return false;
430}
431
432bool declare_label(const char *label, enum label_type type, const char *special)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000433{
Cyrill Gorcunova8e3d6a2018-06-30 20:02:24 +0300434 union label *lptr = find_label(label, true, NULL);
H. Peter Anvin98578072018-06-01 18:02:54 -0700435 return declare_label_lptr(lptr, type, special);
436}
437
438/*
439 * The "normal" argument decides if we should update the local segment
440 * base name or not.
441 */
442void define_label(const char *label, int32_t segment,
443 int64_t offset, bool normal)
444{
445 union label *lptr;
446 bool created, changed;
H. Peter Anvin73482482018-06-11 14:54:14 -0700447 int64_t size;
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -0800448 int64_t lpass, lastdef;
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800449
450 /*
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -0800451 * The backend may invoke this during initialization, at which
452 * pass_count() is zero, so add one so we never have a zero value
453 * for a defined variable.
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800454 */
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -0800455 lpass = pass_count() + 1;
H. Peter Anvin98578072018-06-01 18:02:54 -0700456
457 /*
458 * Phase errors here can be one of two types: a new label appears,
459 * or the offset changes. Increment global_offset_changed when that
460 * happens, to tell the assembler core to make another pass.
H. Peter Anvineba20a72002-04-30 20:53:55 +0000461 */
H. Peter Anvin98578072018-06-01 18:02:54 -0700462 lptr = find_label(label, true, &created);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000463
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800464 lastdef = lptr->defn.defined;
465
H. Peter Anvin, Intelc5e45f62018-06-25 13:16:53 -0700466 if (segment) {
467 /* We are actually defining this label */
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400468 if (is_extern(lptr->defn.type)) {
469 /* auto-promote EXTERN/REQUIRED to GLOBAL */
H. Peter Anvin, Intelc5e45f62018-06-25 13:16:53 -0700470 lptr->defn.type = LBL_GLOBAL;
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800471 lastdef = 0; /* We are "re-creating" this label */
472 }
H. Peter Anvin, Intelc5e45f62018-06-25 13:16:53 -0700473 } else {
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400474 /* It's a pseudo-segment (extern, required, common) */
H. Peter Anvin46c839a2018-06-14 20:00:07 -0700475 segment = lptr->defn.segment ? lptr->defn.segment : seg_alloc();
H. Peter Anvin, Intelc5e45f62018-06-25 13:16:53 -0700476 }
H. Peter Anvinaf5f9182018-06-14 19:53:45 -0700477
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800478 if (lastdef || lptr->defn.type == LBL_BACKEND) {
479 /*
480 * We have seen this on at least one previous pass, or
481 * potentially earlier in this same pass (in which case we
482 * will probably error out further down.)
483 */
H. Peter Anvin98578072018-06-01 18:02:54 -0700484 mangle_label_name(lptr);
485 handle_herelabel(lptr, &segment, &offset);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000486 }
487
H. Peter Anvin98578072018-06-01 18:02:54 -0700488 if (ismagic(label) && lptr->defn.type == LBL_LOCAL)
489 lptr->defn.type = LBL_SPECIAL;
H. Peter Anvin73482482018-06-11 14:54:14 -0700490
H. Peter Anvin, Intelbc77f9c2018-06-25 12:39:42 -0700491 if (set_prevlabel(label) && normal)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000492 prevlabel = lptr->defn.label;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000493
H. Peter Anvin73482482018-06-11 14:54:14 -0700494 if (lptr->defn.type == LBL_COMMON) {
495 size = offset;
496 offset = 0;
497 } else {
498 size = 0; /* This is a hack... */
499 }
500
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800501 changed = created || !lastdef ||
H. Peter Anvin, Intelbc77f9c2018-06-25 12:39:42 -0700502 lptr->defn.segment != segment ||
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800503 lptr->defn.offset != offset ||
504 lptr->defn.size != size;
H. Peter Anvin98578072018-06-01 18:02:54 -0700505 global_offset_changed += changed;
506
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800507 if (lastdef == lpass) {
508 int32_t saved_line = 0;
509 const char *saved_fname = NULL;
510 int noteflags;
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800511
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800512 /*
513 * Defined elsewhere in the program, seen in this pass.
514 */
515 if (changed) {
H. Peter Anvin (Intel)8e08fb62018-12-12 18:05:52 -0800516 nasm_nonfatal("label `%s' inconsistently redefined", lptr->defn.label);
H. Peter Anvin (Intel)52491832019-08-09 03:55:29 -0700517 noteflags = ERR_NONFATAL|ERR_HERE|ERR_NO_SEVERITY;
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800518 } else {
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800519 /*!
520 *!label-redef [off] label redefined to an identical value
521 *! warns if a label is defined more than once, but the
522 *! value is identical. It is an unconditional error to
523 *! define the same label more than once to \e{different} values.
524 */
H. Peter Anvin (Intel)80c4f232018-12-14 13:33:24 -0800525 nasm_warn(WARN_LABEL_REDEF,
H. Peter Anvin (Intel)52491832019-08-09 03:55:29 -0700526 "info: label `%s' redefined to an identical value", lptr->defn.label);
527 noteflags = ERR_WARNING|ERR_HERE|ERR_NO_SEVERITY|WARN_LABEL_REDEF;
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800528 }
H. Peter Anvin98578072018-06-01 18:02:54 -0700529
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800530 src_get(&saved_line, &saved_fname);
531 src_set(lptr->defn.def_line, lptr->defn.def_file);
H. Peter Anvin (Intel)52491832019-08-09 03:55:29 -0700532 nasm_error(noteflags, "info: label `%s' originally defined", lptr->defn.label);
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800533 src_set(saved_line, saved_fname);
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -0800534 } else if (changed && pass_final() && lptr->defn.type != LBL_SPECIAL) {
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800535 /*!
536 *!label-redef-late [err] label (re)defined during code generation
537 *! the value of a label changed during the final, code-generation
538 *! pass. This may be the result of strange use of the
539 *! preprocessor. This is very likely to produce incorrect code and
540 *! may end up being an unconditional error in a future
541 *! version of NASM.
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800542 *
H. Peter Anvin (Intel)0402a2d2018-12-14 13:01:39 -0800543 * WARN_LABEL_LATE defaults to an error, as this should never
544 * actually happen. Just in case this is a backwards
545 * compatibility problem, still make it a warning so that the
546 * user can suppress or demote it.
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800547 *
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800548 * Note: As a special case, LBL_SPECIAL symbols are allowed
549 * to be changed even during the last pass.
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800550 */
H. Peter Anvinbd280392018-12-27 11:37:22 -0800551 nasm_warn(WARN_LABEL_REDEF_LATE|ERR_UNDEAD,
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800552 "label `%s' %s during code generation",
553 lptr->defn.label, created ? "defined" : "changed");
554 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000555 lptr->defn.segment = segment;
H. Peter Anvin98578072018-06-01 18:02:54 -0700556 lptr->defn.offset = offset;
H. Peter Anvin73482482018-06-11 14:54:14 -0700557 lptr->defn.size = size;
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800558 lptr->defn.defined = lpass;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000559
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800560 if (changed || lastdef != lpass)
561 src_get(&lptr->defn.def_line, &lptr->defn.def_file);
562
563 if (lastdef != lpass)
564 out_symdef(lptr);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000565}
566
H. Peter Anvin98578072018-06-01 18:02:54 -0700567/*
568 * Define a special backend label
569 */
570void backend_label(const char *label, int32_t segment, int64_t offset)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000571{
H. Peter Anvin98578072018-06-01 18:02:54 -0700572 if (!declare_label(label, LBL_BACKEND, NULL))
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400573 return;
H. Peter Anvinaeb0e0e2009-06-27 16:30:00 -0700574
H. Peter Anvin98578072018-06-01 18:02:54 -0700575 define_label(label, segment, offset, false);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000576}
577
H. Peter Anvine2c80182005-01-15 22:15:51 +0000578int init_labels(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000579{
H. Peter Anvin3e555482017-04-23 17:02:46 -0700580 ldata = lfree = nasm_malloc(LBLK_SIZE);
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700581 init_block(lfree);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000582
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400583 perm_head = perm_tail =
H. Peter Anvin3e555482017-04-23 17:02:46 -0700584 nasm_malloc(sizeof(struct permts));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000585
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000586 perm_head->next = NULL;
587 perm_head->size = PERMTS_SIZE;
588 perm_head->usage = 0;
589
590 prevlabel = "";
591
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700592 initialized = true;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000593
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000594 return 0;
595}
596
H. Peter Anvine2c80182005-01-15 22:15:51 +0000597void cleanup_labels(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000598{
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700599 union label *lptr, *lhold;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000600
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700601 initialized = false;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000602
H. Peter Anvin166c2472008-05-28 12:28:58 -0700603 hash_free(&ltab);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000604
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700605 lptr = lhold = ldata;
606 while (lptr) {
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400607 lptr = &lptr[LABEL_BLOCK-1];
608 lptr = lptr->admin.next;
609 nasm_free(lhold);
610 lhold = lptr;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000611 }
612
613 while (perm_head) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000614 perm_tail = perm_head;
615 perm_head = perm_head->next;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000616 nasm_free(perm_tail);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000617 }
618}
619
H. Peter Anvine2c80182005-01-15 22:15:51 +0000620static void init_block(union label *blk)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000621{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000622 int j;
623
H. Peter Anvine2c80182005-01-15 22:15:51 +0000624 for (j = 0; j < LABEL_BLOCK - 1; j++)
625 blk[j].admin.movingon = END_LIST;
626 blk[LABEL_BLOCK - 1].admin.movingon = END_BLOCK;
627 blk[LABEL_BLOCK - 1].admin.next = NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000628}
629
H. Peter Anvin98578072018-06-01 18:02:54 -0700630static char * safe_alloc perm_alloc(size_t len)
631{
H. Peter Anvin3cb90682018-06-01 21:05:45 -0700632 char *p;
H. Peter Anvin73482482018-06-11 14:54:14 -0700633
H. Peter Anvin98578072018-06-01 18:02:54 -0700634 if (perm_tail->size - perm_tail->usage < len) {
635 size_t alloc_len = (len > PERMTS_SIZE) ? len : PERMTS_SIZE;
636 perm_tail->next = nasm_malloc(PERMTS_HEADER + alloc_len);
637 perm_tail = perm_tail->next;
638 perm_tail->next = NULL;
639 perm_tail->size = alloc_len;
640 perm_tail->usage = 0;
641 }
H. Peter Anvin3cb90682018-06-01 21:05:45 -0700642 p = perm_tail->data + perm_tail->usage;
H. Peter Anvin98578072018-06-01 18:02:54 -0700643 perm_tail->usage += len;
H. Peter Anvin3cb90682018-06-01 21:05:45 -0700644 return p;
H. Peter Anvin98578072018-06-01 18:02:54 -0700645}
646
H. Peter Anvind2fb7a62007-09-16 17:53:17 -0700647static char *perm_copy(const char *string)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000648{
H. Peter Anvind2fb7a62007-09-16 17:53:17 -0700649 char *p;
H. Peter Anvin98578072018-06-01 18:02:54 -0700650 size_t len;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000651
H. Peter Anvin98578072018-06-01 18:02:54 -0700652 if (!string)
653 return NULL;
H. Peter Anvin565be912009-07-05 22:15:57 -0700654
H. Peter Anvin98578072018-06-01 18:02:54 -0700655 len = strlen(string)+1; /* Include final NUL */
656
657 p = perm_alloc(len);
H. Peter Anvind2fb7a62007-09-16 17:53:17 -0700658 memcpy(p, string, len);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000659
660 return p;
661}
H. Peter Anvineba20a72002-04-30 20:53:55 +0000662
H. Peter Anvin3cb90682018-06-01 21:05:45 -0700663static char *
H. Peter Anvin98578072018-06-01 18:02:54 -0700664perm_copy3(const char *s1, const char *s2, const char *s3)
665{
666 char *p;
667 size_t l1 = strlen(s1);
668 size_t l2 = strlen(s2);
669 size_t l3 = strlen(s3)+1; /* Include final NUL */
H. Peter Anvin73482482018-06-11 14:54:14 -0700670
H. Peter Anvin98578072018-06-01 18:02:54 -0700671 p = perm_alloc(l1+l2+l3);
672 memcpy(p, s1, l1);
673 memcpy(p+l1, s2, l2);
674 memcpy(p+l1+l2, s3, l3);
675
676 return p;
677}
678
679const char *local_scope(const char *label)
Charles Crayned60059e2008-03-12 22:39:03 -0700680{
681 return islocal(label) ? prevlabel : "";
682}
683
H. Peter Anvineba20a72002-04-30 20:53:55 +0000684/*
685 * Notes regarding bug involving redefinition of external segments.
686 *
687 * Up to and including v0.97, the following code didn't work. From 0.97
688 * developers release 2 onwards, it will generate an error.
689 *
690 * EXTERN extlabel
691 * newlabel EQU extlabel + 1
692 *
693 * The results of allowing this code through are that two import records
694 * are generated, one for 'extlabel' and one for 'newlabel'.
695 *
696 * The reason for this is an inadequacy in the defined interface between
697 * the label manager and the output formats. The problem lies in how the
698 * output format driver tells that a label is an external label for which
699 * a label import record must be produced. Most (all except bin?) produce
700 * the record if the segment number of the label is not one of the internal
701 * segments that the output driver is producing.
702 *
703 * A simple fix to this would be to make the output formats keep track of
704 * which symbols they've produced import records for, and make them not
705 * produce import records for segments that are already defined.
706 *
707 * The best way, which is slightly harder but reduces duplication of code
708 * and should therefore make the entire system smaller and more stable is
709 * to change the interface between assembler, define_label(), and
710 * the output module. The changes that are needed are:
711 *
712 * The semantics of the 'isextern' flag passed to define_label() need
713 * examining. This information may or may not tell us what we need to
714 * know (ie should we be generating an import record at this point for this
715 * label). If these aren't the semantics, the semantics should be changed
716 * to this.
717 *
718 * The output module interface needs changing, so that the `isextern' flag
719 * is passed to the module, so that it can be easily tested for.
720 */