blob: 84099dea1d2074a85d4ab3a164e6d85b096fc27c [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
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000040#include <stdio.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000041#include <stdlib.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000042
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000043#include "nasm.h"
44#include "nasmlib.h"
H. Peter Anvinb20bc732017-03-07 19:23:03 -080045#include "error.h"
H. Peter Anvin6244f4b2007-09-14 18:03:29 -070046#include "hashtbl.h"
H. Peter Anvinc6645832014-11-25 12:07:10 -080047#include "labels.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000048
49/*
H. Peter Anvin98578072018-06-01 18:02:54 -070050 * A dot-local label is one that begins with exactly one period. Things
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000051 * that begin with _two_ periods are NASM-specific things.
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +000052 *
53 * If TASM compatibility is enabled, a local label can also begin with
H. Peter Anvin98578072018-06-01 18:02:54 -070054 * @@.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000055 */
H. Peter Anvin98578072018-06-01 18:02:54 -070056static bool islocal(const char *l)
57{
58 if (tasm_compatible_mode) {
59 if (l[0] == '@' && l[1] == '@')
60 return true;
61 }
62
63 return (l[0] == '.' && l[1] != '.');
64}
65
66/*
67 * Return true if this falls into NASM's '..' namespace
68 */
69static bool ismagic(const char *l)
70{
71 return l[0] == '.' && l[1] == '.' && l[2] != '@';
72}
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000073
H. Peter Anvin, Intelbc77f9c2018-06-25 12:39:42 -070074/*
75 * Return true if we should update the local label base
76 * as a result of this symbol. We must exclude local labels
77 * as well as any kind of special labels, including ..@ ones.
78 */
79static bool set_prevlabel(const char *l)
80{
81 if (tasm_compatible_mode) {
82 if (l[0] == '@' && l[1] == '@')
83 return false;
84 }
85
86 return l[0] != '.';
87}
88
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +040089#define LABEL_BLOCK 128 /* no. of labels/block */
90#define LBLK_SIZE (LABEL_BLOCK * sizeof(union label))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000091
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +040092#define END_LIST -3 /* don't clash with NO_SEG! */
93#define END_BLOCK -2
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000094
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +040095#define PERMTS_SIZE 16384 /* size of text blocks */
H. Peter Anvin565be912009-07-05 22:15:57 -070096#if (PERMTS_SIZE < IDLEN_MAX)
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +040097 #error "IPERMTS_SIZE must be greater than or equal to IDLEN_MAX"
Ed Berosetc06f6df2003-09-08 00:30:40 +000098#endif
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000099
H. Peter Anvin98578072018-06-01 18:02:54 -0700100/* string values for enum label_type */
101static const char * const types[] =
102{"local", "global", "static", "extern", "common", "special",
103 "output format special"};
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000104
H. Peter Anvine2c80182005-01-15 22:15:51 +0000105union label { /* actual label structures */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000106 struct {
Charles Crayne4e8563d2007-11-05 17:19:32 -0800107 int32_t segment;
H. Peter Anvin29695c82018-06-14 17:04:32 -0700108 int32_t subsection; /* Available for ofmt->herelabel() */
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400109 int64_t offset;
H. Peter Anvin73482482018-06-11 14:54:14 -0700110 int64_t size;
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800111 int64_t defined; /* 0 if undefined, passn+1 for when defn seen */
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 Anvin98578072018-06-01 18:02:54 -0700162 case LBL_EXTERN:
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) {
178 case LBL_GLOBAL:
Cyrill Gorcunov70d42962018-07-01 01:59:07 +0300179 case LBL_EXTERN:
H. Peter Anvin98578072018-06-01 18:02:54 -0700180 backend_type = 1;
H. Peter Anvin73482482018-06-11 14:54:14 -0700181 backend_offset = lptr->defn.offset;
H. Peter Anvin98578072018-06-01 18:02:54 -0700182 break;
183 case LBL_COMMON:
184 backend_type = 2;
H. Peter Anvin73482482018-06-11 14:54:14 -0700185 backend_offset = lptr->defn.size;
H. Peter Anvin98578072018-06-01 18:02:54 -0700186 break;
187 default:
188 backend_type = 0;
H. Peter Anvin73482482018-06-11 14:54:14 -0700189 backend_offset = lptr->defn.offset;
H. Peter Anvin98578072018-06-01 18:02:54 -0700190 break;
191 }
192
193 /* Might be necessary for a backend symbol */
194 mangle_label_name(lptr);
195
196 ofmt->symdef(lptr->defn.mangled, lptr->defn.segment,
H. Peter Anvin73482482018-06-11 14:54:14 -0700197 backend_offset, backend_type,
H. Peter Anvin98578072018-06-01 18:02:54 -0700198 lptr->defn.special);
H. Peter Anvinfc0ff222016-03-07 21:46:04 -0800199
200 /*
201 * NASM special symbols are not passed to the debug format; none
202 * of the current backends want to see them.
203 */
H. Peter Anvin98578072018-06-01 18:02:54 -0700204 if (lptr->defn.type == LBL_SPECIAL || lptr->defn.type == LBL_BACKEND)
205 return;
206
207 dfmt->debug_deflabel(lptr->defn.mangled, lptr->defn.segment,
208 lptr->defn.offset, backend_type,
209 lptr->defn.special);
H. Peter Anvinfc0ff222016-03-07 21:46:04 -0800210}
211
212/*
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000213 * Internal routine: finds the `union label' corresponding to the
214 * given label name. Creates a new one, if it isn't found, and if
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700215 * `create' is true.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000216 */
H. Peter Anvin98578072018-06-01 18:02:54 -0700217static union label *find_label(const char *label, bool create, bool *created)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000218{
H. Peter Anvin97a23472007-09-16 17:57:25 -0700219 union label *lptr, **lpp;
H. Peter Anvin98578072018-06-01 18:02:54 -0700220 char *label_str = NULL;
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700221 struct hash_insert ip;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000222
Cyrill Gorcunov8e740c62018-10-13 17:18:05 +0300223 nasm_assert(label != NULL);
224
H. Peter Anvin98578072018-06-01 18:02:54 -0700225 if (islocal(label))
226 label = label_str = nasm_strcat(prevlabel, label);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000227
H. Peter Anvin166c2472008-05-28 12:28:58 -0700228 lpp = (union label **) hash_find(&ltab, label, &ip);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700229 lptr = lpp ? *lpp : NULL;
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700230
Cyrill Gorcunov5dfcab62016-07-18 11:49:47 +0300231 if (lptr || !create) {
232 if (created)
H. Peter Anvin98578072018-06-01 18:02:54 -0700233 *created = false;
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400234 return lptr;
Cyrill Gorcunov5dfcab62016-07-18 11:49:47 +0300235 }
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700236
237 /* Create a new label... */
238 if (lfree->admin.movingon == END_BLOCK) {
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400239 /*
240 * must allocate a new block
241 */
H. Peter Anvin3e555482017-04-23 17:02:46 -0700242 lfree->admin.next = nasm_malloc(LBLK_SIZE);
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400243 lfree = lfree->admin.next;
244 init_block(lfree);
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700245 }
H. Peter Anvin70653092007-10-19 14:42:29 -0700246
Cyrill Gorcunov5dfcab62016-07-18 11:49:47 +0300247 if (created)
H. Peter Anvin98578072018-06-01 18:02:54 -0700248 *created = true;
Cyrill Gorcunov5dfcab62016-07-18 11:49:47 +0300249
H. Peter Anvin98578072018-06-01 18:02:54 -0700250 nasm_zero(*lfree);
H. Peter Anvin98578072018-06-01 18:02:54 -0700251 lfree->defn.label = perm_copy(label);
H. Peter Anvin29695c82018-06-14 17:04:32 -0700252 lfree->defn.subsection = NO_SEG;
H. Peter Anvin98578072018-06-01 18:02:54 -0700253 if (label_str)
254 nasm_free(label_str);
H. Peter Anvin70653092007-10-19 14:42:29 -0700255
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700256 hash_add(&ip, lfree->defn.label, lfree);
257 return lfree++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000258}
259
H. Peter Anvin785ffb92017-03-14 18:41:25 -0700260bool lookup_label(const char *label, int32_t *segment, int64_t *offset)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000261{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000262 union label *lptr;
263
Keith Kaniosb7a89542007-04-12 02:40:54 +0000264 if (!initialized)
H. Peter Anvin70055962007-10-11 00:05:31 -0700265 return false;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000266
H. Peter Anvin98578072018-06-01 18:02:54 -0700267 lptr = find_label(label, false, NULL);
268 if (lptr && lptr->defn.defined) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000269 *segment = lptr->defn.segment;
270 *offset = lptr->defn.offset;
H. Peter Anvin70055962007-10-11 00:05:31 -0700271 return true;
Cyrill Gorcunovd7a64b72010-04-20 15:26:08 +0400272 }
273
274 return false;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000275}
276
H. Peter Anvin785ffb92017-03-14 18:41:25 -0700277bool is_extern(const char *label)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000278{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000279 union label *lptr;
280
Keith Kaniosb7a89542007-04-12 02:40:54 +0000281 if (!initialized)
H. Peter Anvin70055962007-10-11 00:05:31 -0700282 return false;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000283
H. Peter Anvin98578072018-06-01 18:02:54 -0700284 lptr = find_label(label, false, NULL);
285 return lptr && lptr->defn.type == LBL_EXTERN;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000286}
287
H. Peter Anvin98578072018-06-01 18:02:54 -0700288static const char *mangle_strings[] = {"", "", "", ""};
289static bool mangle_string_set[ARRAY_SIZE(mangle_strings)];
290
291/*
292 * Set a prefix or suffix
293 */
294void set_label_mangle(enum mangle_index which, const char *what)
295{
296 if (mangle_string_set[which])
297 return; /* Once set, do not change */
298
299 mangle_strings[which] = perm_copy(what);
300 mangle_string_set[which] = true;
301}
302
303/*
304 * Format a label name with appropriate prefixes and suffixes
305 */
306static const char *mangle_label_name(union label *lptr)
307{
308 const char *prefix;
309 const char *suffix;
310
311 if (likely(lptr->defn.mangled &&
312 lptr->defn.mangled_type == lptr->defn.type))
313 return lptr->defn.mangled; /* Already mangled */
314
315 switch (lptr->defn.type) {
316 case LBL_GLOBAL:
317 case LBL_STATIC:
318 case LBL_EXTERN:
319 prefix = mangle_strings[LM_GPREFIX];
320 suffix = mangle_strings[LM_GSUFFIX];
321 break;
322 case LBL_BACKEND:
323 case LBL_SPECIAL:
324 prefix = suffix = "";
325 break;
326 default:
327 prefix = mangle_strings[LM_LPREFIX];
328 suffix = mangle_strings[LM_LSUFFIX];
329 break;
330 }
331
332 lptr->defn.mangled_type = lptr->defn.type;
333
334 if (!(*prefix) && !(*suffix))
335 lptr->defn.mangled = lptr->defn.label;
336 else
337 lptr->defn.mangled = perm_copy3(prefix, lptr->defn.label, suffix);
338
339 return lptr->defn.mangled;
340}
341
342static void
H. Peter Anvin29695c82018-06-14 17:04:32 -0700343handle_herelabel(union label *lptr, int32_t *segment, int64_t *offset)
H. Peter Anvin892c4812018-05-30 14:43:46 -0700344{
345 int32_t oldseg;
346
347 if (likely(!ofmt->herelabel))
348 return;
349
350 if (unlikely(location.segment == NO_SEG))
351 return;
352
353 oldseg = *segment;
354
355 if (oldseg == location.segment && *offset == location.offset) {
356 /* This label is defined at this location */
357 int32_t newseg;
H. Peter Anvin (Intel)d6441192018-06-27 20:20:21 -0700358 bool copyoffset = false;
H. Peter Anvin892c4812018-05-30 14:43:46 -0700359
H. Peter Anvin98578072018-06-01 18:02:54 -0700360 nasm_assert(lptr->defn.mangled);
H. Peter Anvin29695c82018-06-14 17:04:32 -0700361 newseg = ofmt->herelabel(lptr->defn.mangled, lptr->defn.type,
H. Peter Anvin (Intel)d6441192018-06-27 20:20:21 -0700362 oldseg, &lptr->defn.subsection, &copyoffset);
H. Peter Anvin892c4812018-05-30 14:43:46 -0700363 if (likely(newseg == oldseg))
364 return;
365
366 *segment = newseg;
H. Peter Anvin (Intel)d6441192018-06-27 20:20:21 -0700367 if (copyoffset) {
368 /* Maintain the offset from the old to the new segment */
369 switch_segment(newseg);
370 location.offset = *offset;
371 } else {
372 /* Keep a separate offset for the new segment */
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800373 *offset = switch_segment(newseg);
H. Peter Anvin (Intel)d6441192018-06-27 20:20:21 -0700374 }
H. Peter Anvin892c4812018-05-30 14:43:46 -0700375 }
376}
377
H. Peter Anvin98578072018-06-01 18:02:54 -0700378static bool declare_label_lptr(union label *lptr,
379 enum label_type type, const char *special)
380{
H. Peter Anvin3cb90682018-06-01 21:05:45 -0700381 if (special && !special[0])
382 special = NULL;
383
H. Peter Anvin98578072018-06-01 18:02:54 -0700384 if (lptr->defn.type == type ||
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -0800385 (!pass_stable() && lptr->defn.type == LBL_LOCAL)) {
H. Peter Anvin98578072018-06-01 18:02:54 -0700386 lptr->defn.type = type;
387 if (special) {
388 if (!lptr->defn.special)
389 lptr->defn.special = perm_copy(special);
390 else if (nasm_stricmp(lptr->defn.special, special))
Cyrill Gorcunov46c37b32018-12-01 20:03:55 +0300391 nasm_nonfatal("symbol `%s' has inconsistent attributes `%s' and `%s'",
392 lptr->defn.label, lptr->defn.special, special);
H. Peter Anvin98578072018-06-01 18:02:54 -0700393 }
394 return true;
395 }
396
397 /* EXTERN can be replaced with GLOBAL or COMMON */
398 if (lptr->defn.type == LBL_EXTERN &&
399 (type == LBL_GLOBAL || type == LBL_COMMON)) {
400 lptr->defn.type = type;
401 /* Override special unconditionally */
402 if (special)
403 lptr->defn.special = perm_copy(special);
404 return true;
405 }
406
407 /* GLOBAL or COMMON ignore subsequent EXTERN */
408 if ((lptr->defn.type == LBL_GLOBAL || lptr->defn.type == LBL_COMMON) &&
409 type == LBL_EXTERN) {
410 if (!lptr->defn.special)
411 lptr->defn.special = perm_copy(special);
H. Peter Anvin, Intel4fb2acc2018-06-25 13:11:01 -0700412 return false; /* Don't call define_label() after this! */
H. Peter Anvin98578072018-06-01 18:02:54 -0700413 }
414
Cyrill Gorcunov46c37b32018-12-01 20:03:55 +0300415 nasm_nonfatal("symbol `%s' declared both as %s and %s",
416 lptr->defn.label, types[lptr->defn.type], types[type]);
H. Peter Anvin98578072018-06-01 18:02:54 -0700417
418 return false;
419}
420
421bool declare_label(const char *label, enum label_type type, const char *special)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000422{
Cyrill Gorcunova8e3d6a2018-06-30 20:02:24 +0300423 union label *lptr = find_label(label, true, NULL);
H. Peter Anvin98578072018-06-01 18:02:54 -0700424 return declare_label_lptr(lptr, type, special);
425}
426
427/*
428 * The "normal" argument decides if we should update the local segment
429 * base name or not.
430 */
431void define_label(const char *label, int32_t segment,
432 int64_t offset, bool normal)
433{
434 union label *lptr;
435 bool created, changed;
H. Peter Anvin73482482018-06-11 14:54:14 -0700436 int64_t size;
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -0800437 int64_t lpass, lastdef;
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800438
439 /*
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -0800440 * The backend may invoke this during initialization, at which
441 * pass_count() is zero, so add one so we never have a zero value
442 * for a defined variable.
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800443 */
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -0800444 lpass = pass_count() + 1;
H. Peter Anvin98578072018-06-01 18:02:54 -0700445
446 /*
447 * Phase errors here can be one of two types: a new label appears,
448 * or the offset changes. Increment global_offset_changed when that
449 * happens, to tell the assembler core to make another pass.
H. Peter Anvineba20a72002-04-30 20:53:55 +0000450 */
H. Peter Anvin98578072018-06-01 18:02:54 -0700451 lptr = find_label(label, true, &created);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000452
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800453 lastdef = lptr->defn.defined;
454
H. Peter Anvin, Intelc5e45f62018-06-25 13:16:53 -0700455 if (segment) {
456 /* We are actually defining this label */
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800457 if (lptr->defn.type == LBL_EXTERN) {
458 /* auto-promote EXTERN to GLOBAL */
H. Peter Anvin, Intelc5e45f62018-06-25 13:16:53 -0700459 lptr->defn.type = LBL_GLOBAL;
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800460 lastdef = 0; /* We are "re-creating" this label */
461 }
H. Peter Anvin, Intelc5e45f62018-06-25 13:16:53 -0700462 } else {
463 /* It's a pseudo-segment (extern, common) */
H. Peter Anvin46c839a2018-06-14 20:00:07 -0700464 segment = lptr->defn.segment ? lptr->defn.segment : seg_alloc();
H. Peter Anvin, Intelc5e45f62018-06-25 13:16:53 -0700465 }
H. Peter Anvinaf5f9182018-06-14 19:53:45 -0700466
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800467 if (lastdef || lptr->defn.type == LBL_BACKEND) {
468 /*
469 * We have seen this on at least one previous pass, or
470 * potentially earlier in this same pass (in which case we
471 * will probably error out further down.)
472 */
H. Peter Anvin98578072018-06-01 18:02:54 -0700473 mangle_label_name(lptr);
474 handle_herelabel(lptr, &segment, &offset);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000475 }
476
H. Peter Anvin98578072018-06-01 18:02:54 -0700477 if (ismagic(label) && lptr->defn.type == LBL_LOCAL)
478 lptr->defn.type = LBL_SPECIAL;
H. Peter Anvin73482482018-06-11 14:54:14 -0700479
H. Peter Anvin, Intelbc77f9c2018-06-25 12:39:42 -0700480 if (set_prevlabel(label) && normal)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000481 prevlabel = lptr->defn.label;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000482
H. Peter Anvin73482482018-06-11 14:54:14 -0700483 if (lptr->defn.type == LBL_COMMON) {
484 size = offset;
485 offset = 0;
486 } else {
487 size = 0; /* This is a hack... */
488 }
489
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800490 changed = created || !lastdef ||
H. Peter Anvin, Intelbc77f9c2018-06-25 12:39:42 -0700491 lptr->defn.segment != segment ||
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800492 lptr->defn.offset != offset ||
493 lptr->defn.size != size;
H. Peter Anvin98578072018-06-01 18:02:54 -0700494 global_offset_changed += changed;
495
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800496 if (lastdef == lpass) {
497 int32_t saved_line = 0;
498 const char *saved_fname = NULL;
499 int noteflags;
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800500
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800501 /*
502 * Defined elsewhere in the program, seen in this pass.
503 */
504 if (changed) {
H. Peter Anvin (Intel)8e08fb62018-12-12 18:05:52 -0800505 nasm_nonfatal("label `%s' inconsistently redefined", lptr->defn.label);
H. Peter Anvine2f5edb2018-12-11 00:06:29 -0800506 noteflags = ERR_NOTE|ERR_HERE;
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800507 } else {
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800508 /*!
509 *!label-redef [off] label redefined to an identical value
510 *! warns if a label is defined more than once, but the
511 *! value is identical. It is an unconditional error to
512 *! define the same label more than once to \e{different} values.
513 */
H. Peter Anvin (Intel)80c4f232018-12-14 13:33:24 -0800514 nasm_warn(WARN_LABEL_REDEF,
H. Peter Anvin (Intel)8e08fb62018-12-12 18:05:52 -0800515 "label `%s' redefined to an identical value", lptr->defn.label);
H. Peter Anvin (Intel)374312c2018-12-14 00:17:13 -0800516 noteflags = ERR_NOTE|ERR_HERE|WARN_LABEL_REDEF;
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800517 }
H. Peter Anvin98578072018-06-01 18:02:54 -0700518
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800519 src_get(&saved_line, &saved_fname);
520 src_set(lptr->defn.def_line, lptr->defn.def_file);
H. Peter Anvine2f5edb2018-12-11 00:06:29 -0800521 nasm_error(noteflags, "label `%s' originally defined",
522 lptr->defn.label);
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800523 src_set(saved_line, saved_fname);
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -0800524 } else if (changed && pass_final() && lptr->defn.type != LBL_SPECIAL) {
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800525 /*!
526 *!label-redef-late [err] label (re)defined during code generation
527 *! the value of a label changed during the final, code-generation
528 *! pass. This may be the result of strange use of the
529 *! preprocessor. This is very likely to produce incorrect code and
530 *! may end up being an unconditional error in a future
531 *! version of NASM.
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800532 *
H. Peter Anvin (Intel)0402a2d2018-12-14 13:01:39 -0800533 * WARN_LABEL_LATE defaults to an error, as this should never
534 * actually happen. Just in case this is a backwards
535 * compatibility problem, still make it a warning so that the
536 * user can suppress or demote it.
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800537 *
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800538 * Note: As a special case, LBL_SPECIAL symbols are allowed
539 * to be changed even during the last pass.
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800540 */
H. Peter Anvinbd280392018-12-27 11:37:22 -0800541 nasm_warn(WARN_LABEL_REDEF_LATE|ERR_UNDEAD,
H. Peter Anvin (Intel)950dee92018-12-12 16:49:07 -0800542 "label `%s' %s during code generation",
543 lptr->defn.label, created ? "defined" : "changed");
544 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000545 lptr->defn.segment = segment;
H. Peter Anvin98578072018-06-01 18:02:54 -0700546 lptr->defn.offset = offset;
H. Peter Anvin73482482018-06-11 14:54:14 -0700547 lptr->defn.size = size;
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800548 lptr->defn.defined = lpass;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000549
H. Peter Anvinb424ae32018-12-10 13:30:51 -0800550 if (changed || lastdef != lpass)
551 src_get(&lptr->defn.def_line, &lptr->defn.def_file);
552
553 if (lastdef != lpass)
554 out_symdef(lptr);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000555}
556
H. Peter Anvin98578072018-06-01 18:02:54 -0700557/*
558 * Define a special backend label
559 */
560void backend_label(const char *label, int32_t segment, int64_t offset)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000561{
H. Peter Anvin98578072018-06-01 18:02:54 -0700562 if (!declare_label(label, LBL_BACKEND, NULL))
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400563 return;
H. Peter Anvinaeb0e0e2009-06-27 16:30:00 -0700564
H. Peter Anvin98578072018-06-01 18:02:54 -0700565 define_label(label, segment, offset, false);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000566}
567
H. Peter Anvine2c80182005-01-15 22:15:51 +0000568int init_labels(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000569{
H. Peter Anvin3e555482017-04-23 17:02:46 -0700570 ldata = lfree = nasm_malloc(LBLK_SIZE);
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700571 init_block(lfree);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000572
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400573 perm_head = perm_tail =
H. Peter Anvin3e555482017-04-23 17:02:46 -0700574 nasm_malloc(sizeof(struct permts));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000575
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000576 perm_head->next = NULL;
577 perm_head->size = PERMTS_SIZE;
578 perm_head->usage = 0;
579
580 prevlabel = "";
581
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700582 initialized = true;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000583
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000584 return 0;
585}
586
H. Peter Anvine2c80182005-01-15 22:15:51 +0000587void cleanup_labels(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000588{
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700589 union label *lptr, *lhold;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000590
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700591 initialized = false;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000592
H. Peter Anvin166c2472008-05-28 12:28:58 -0700593 hash_free(&ltab);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000594
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700595 lptr = lhold = ldata;
596 while (lptr) {
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400597 lptr = &lptr[LABEL_BLOCK-1];
598 lptr = lptr->admin.next;
599 nasm_free(lhold);
600 lhold = lptr;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000601 }
602
603 while (perm_head) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000604 perm_tail = perm_head;
605 perm_head = perm_head->next;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000606 nasm_free(perm_tail);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000607 }
608}
609
H. Peter Anvine2c80182005-01-15 22:15:51 +0000610static void init_block(union label *blk)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000611{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000612 int j;
613
H. Peter Anvine2c80182005-01-15 22:15:51 +0000614 for (j = 0; j < LABEL_BLOCK - 1; j++)
615 blk[j].admin.movingon = END_LIST;
616 blk[LABEL_BLOCK - 1].admin.movingon = END_BLOCK;
617 blk[LABEL_BLOCK - 1].admin.next = NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000618}
619
H. Peter Anvin98578072018-06-01 18:02:54 -0700620static char * safe_alloc perm_alloc(size_t len)
621{
H. Peter Anvin3cb90682018-06-01 21:05:45 -0700622 char *p;
H. Peter Anvin73482482018-06-11 14:54:14 -0700623
H. Peter Anvin98578072018-06-01 18:02:54 -0700624 if (perm_tail->size - perm_tail->usage < len) {
625 size_t alloc_len = (len > PERMTS_SIZE) ? len : PERMTS_SIZE;
626 perm_tail->next = nasm_malloc(PERMTS_HEADER + alloc_len);
627 perm_tail = perm_tail->next;
628 perm_tail->next = NULL;
629 perm_tail->size = alloc_len;
630 perm_tail->usage = 0;
631 }
H. Peter Anvin3cb90682018-06-01 21:05:45 -0700632 p = perm_tail->data + perm_tail->usage;
H. Peter Anvin98578072018-06-01 18:02:54 -0700633 perm_tail->usage += len;
H. Peter Anvin3cb90682018-06-01 21:05:45 -0700634 return p;
H. Peter Anvin98578072018-06-01 18:02:54 -0700635}
636
H. Peter Anvind2fb7a62007-09-16 17:53:17 -0700637static char *perm_copy(const char *string)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000638{
H. Peter Anvind2fb7a62007-09-16 17:53:17 -0700639 char *p;
H. Peter Anvin98578072018-06-01 18:02:54 -0700640 size_t len;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000641
H. Peter Anvin98578072018-06-01 18:02:54 -0700642 if (!string)
643 return NULL;
H. Peter Anvin565be912009-07-05 22:15:57 -0700644
H. Peter Anvin98578072018-06-01 18:02:54 -0700645 len = strlen(string)+1; /* Include final NUL */
646
647 p = perm_alloc(len);
H. Peter Anvind2fb7a62007-09-16 17:53:17 -0700648 memcpy(p, string, len);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000649
650 return p;
651}
H. Peter Anvineba20a72002-04-30 20:53:55 +0000652
H. Peter Anvin3cb90682018-06-01 21:05:45 -0700653static char *
H. Peter Anvin98578072018-06-01 18:02:54 -0700654perm_copy3(const char *s1, const char *s2, const char *s3)
655{
656 char *p;
657 size_t l1 = strlen(s1);
658 size_t l2 = strlen(s2);
659 size_t l3 = strlen(s3)+1; /* Include final NUL */
H. Peter Anvin73482482018-06-11 14:54:14 -0700660
H. Peter Anvin98578072018-06-01 18:02:54 -0700661 p = perm_alloc(l1+l2+l3);
662 memcpy(p, s1, l1);
663 memcpy(p+l1, s2, l2);
664 memcpy(p+l1+l2, s3, l3);
665
666 return p;
667}
668
669const char *local_scope(const char *label)
Charles Crayned60059e2008-03-12 22:39:03 -0700670{
671 return islocal(label) ? prevlabel : "";
672}
673
H. Peter Anvineba20a72002-04-30 20:53:55 +0000674/*
675 * Notes regarding bug involving redefinition of external segments.
676 *
677 * Up to and including v0.97, the following code didn't work. From 0.97
678 * developers release 2 onwards, it will generate an error.
679 *
680 * EXTERN extlabel
681 * newlabel EQU extlabel + 1
682 *
683 * The results of allowing this code through are that two import records
684 * are generated, one for 'extlabel' and one for 'newlabel'.
685 *
686 * The reason for this is an inadequacy in the defined interface between
687 * the label manager and the output formats. The problem lies in how the
688 * output format driver tells that a label is an external label for which
689 * a label import record must be produced. Most (all except bin?) produce
690 * the record if the segment number of the label is not one of the internal
691 * segments that the output driver is producing.
692 *
693 * A simple fix to this would be to make the output formats keep track of
694 * which symbols they've produced import records for, and make them not
695 * produce import records for segments that are already defined.
696 *
697 * The best way, which is slightly harder but reduces duplication of code
698 * and should therefore make the entire system smaller and more stable is
699 * to change the interface between assembler, define_label(), and
700 * the output module. The changes that are needed are:
701 *
702 * The semantics of the 'isextern' flag passed to define_label() need
703 * examining. This information may or may not tell us what we need to
704 * know (ie should we be generating an import record at this point for this
705 * label). If these aren't the semantics, the semantics should be changed
706 * to this.
707 *
708 * The output module interface needs changing, so that the `isextern' flag
709 * is passed to the module, so that it can be easily tested for.
710 */