blob: 2275bdb73e4c2418ad6e850fbe5b3f5707f29a49 [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>
41#include <string.h>
42#include <stdlib.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000043
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000044#include "nasm.h"
45#include "nasmlib.h"
H. Peter Anvinb20bc732017-03-07 19:23:03 -080046#include "error.h"
H. Peter Anvin6244f4b2007-09-14 18:03:29 -070047#include "hashtbl.h"
H. Peter Anvinc6645832014-11-25 12:07:10 -080048#include "labels.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000049
50/*
H. Peter Anvin98578072018-06-01 18:02:54 -070051 * A dot-local label is one that begins with exactly one period. Things
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000052 * that begin with _two_ periods are NASM-specific things.
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +000053 *
54 * If TASM compatibility is enabled, a local label can also begin with
H. Peter Anvin98578072018-06-01 18:02:54 -070055 * @@.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000056 */
H. Peter Anvin98578072018-06-01 18:02:54 -070057static bool islocal(const char *l)
58{
59 if (tasm_compatible_mode) {
60 if (l[0] == '@' && l[1] == '@')
61 return true;
62 }
63
64 return (l[0] == '.' && l[1] != '.');
65}
66
67/*
68 * Return true if this falls into NASM's '..' namespace
69 */
70static bool ismagic(const char *l)
71{
72 return l[0] == '.' && l[1] == '.' && l[2] != '@';
73}
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000074
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +040075#define LABEL_BLOCK 128 /* no. of labels/block */
76#define LBLK_SIZE (LABEL_BLOCK * sizeof(union label))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000077
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +040078#define END_LIST -3 /* don't clash with NO_SEG! */
79#define END_BLOCK -2
80#define BOGUS_VALUE -4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000081
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +040082#define PERMTS_SIZE 16384 /* size of text blocks */
H. Peter Anvin565be912009-07-05 22:15:57 -070083#if (PERMTS_SIZE < IDLEN_MAX)
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +040084 #error "IPERMTS_SIZE must be greater than or equal to IDLEN_MAX"
Ed Berosetc06f6df2003-09-08 00:30:40 +000085#endif
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000086
H. Peter Anvin98578072018-06-01 18:02:54 -070087/* string values for enum label_type */
88static const char * const types[] =
89{"local", "global", "static", "extern", "common", "special",
90 "output format special"};
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000091
H. Peter Anvine2c80182005-01-15 22:15:51 +000092union label { /* actual label structures */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000093 struct {
Charles Crayne4e8563d2007-11-05 17:19:32 -080094 int32_t segment;
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +040095 int64_t offset;
H. Peter Anvin98578072018-06-01 18:02:54 -070096 char *label, *mangled, *special;
97 enum label_type type, mangled_type;
98 bool defined;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000099 } defn;
100 struct {
Charles Crayne4e8563d2007-11-05 17:19:32 -0800101 int32_t movingon;
102 int64_t dummy;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000103 union label *next;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000104 } admin;
105};
106
H. Peter Anvine2c80182005-01-15 22:15:51 +0000107struct permts { /* permanent text storage */
108 struct permts *next; /* for the linked list */
H. Peter Anvin98578072018-06-01 18:02:54 -0700109 unsigned int size, usage; /* size and used space in ... */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000110 char data[PERMTS_SIZE]; /* ... the data block itself */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000111};
H. Peter Anvin98578072018-06-01 18:02:54 -0700112#define PERMTS_HEADER offsetof(struct permts, data)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000113
H. Peter Anvin9c595b62017-03-07 19:44:21 -0800114uint64_t global_offset_changed; /* counter for global offset changes */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000115
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400116static struct hash_table ltab; /* labels hash table */
117static union label *ldata; /* all label data blocks */
118static union label *lfree; /* labels free block */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000119static struct permts *perm_head; /* start of perm. text storage */
120static struct permts *perm_tail; /* end of perm. text storage */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000121
H. Peter Anvine2c80182005-01-15 22:15:51 +0000122static void init_block(union label *blk);
H. Peter Anvin98578072018-06-01 18:02:54 -0700123static char *perm_alloc(size_t len);
H. Peter Anvind2fb7a62007-09-16 17:53:17 -0700124static char *perm_copy(const char *string);
H. Peter Anvin98578072018-06-01 18:02:54 -0700125static char *perm_copy3(const char *s1, const char *s2, const char *s3);
126static const char *mangle_label_name(union label *lptr);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000127
H. Peter Anvin98578072018-06-01 18:02:54 -0700128static const char *prevlabel;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000129
H. Peter Anvin70055962007-10-11 00:05:31 -0700130static bool initialized = false;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000131
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000132/*
H. Peter Anvinfc0ff222016-03-07 21:46:04 -0800133 * Emit a symdef to the output and the debug format backends.
134 */
H. Peter Anvin98578072018-06-01 18:02:54 -0700135static void out_symdef(union label *lptr)
H. Peter Anvinfc0ff222016-03-07 21:46:04 -0800136{
H. Peter Anvin98578072018-06-01 18:02:54 -0700137 int backend_type;
138
139 /* Backend-defined special segments are passed to symdef immediately */
140 if (pass0 == 2) {
141 /* Emit special fixups for globals and commons */
142 switch (lptr->defn.type) {
143 case LBL_GLOBAL:
144 case LBL_COMMON:
145 case LBL_EXTERN:
146 if (lptr->defn.special)
147 ofmt->symdef(lptr->defn.label, 0, 0, 3, lptr->defn.special);
148 break;
149 default:
150 break;
151 }
152 return;
153 }
154
155 if (pass0 != 1 && lptr->defn.type != LBL_BACKEND)
156 return;
157
158 /* Clean up this hack... */
159 switch(lptr->defn.type) {
160 case LBL_GLOBAL:
161 backend_type = 1;
162 break;
163 case LBL_COMMON:
164 backend_type = 2;
165 break;
166 default:
167 backend_type = 0;
168 break;
169 }
170
171 /* Might be necessary for a backend symbol */
172 mangle_label_name(lptr);
173
174 ofmt->symdef(lptr->defn.mangled, lptr->defn.segment,
175 lptr->defn.offset, backend_type,
176 lptr->defn.special);
H. Peter Anvinfc0ff222016-03-07 21:46:04 -0800177
178 /*
179 * NASM special symbols are not passed to the debug format; none
180 * of the current backends want to see them.
181 */
H. Peter Anvin98578072018-06-01 18:02:54 -0700182 if (lptr->defn.type == LBL_SPECIAL || lptr->defn.type == LBL_BACKEND)
183 return;
184
185 dfmt->debug_deflabel(lptr->defn.mangled, lptr->defn.segment,
186 lptr->defn.offset, backend_type,
187 lptr->defn.special);
H. Peter Anvinfc0ff222016-03-07 21:46:04 -0800188}
189
190/*
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000191 * Internal routine: finds the `union label' corresponding to the
192 * given label name. Creates a new one, if it isn't found, and if
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700193 * `create' is true.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000194 */
H. Peter Anvin98578072018-06-01 18:02:54 -0700195static union label *find_label(const char *label, bool create, bool *created)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000196{
H. Peter Anvin97a23472007-09-16 17:57:25 -0700197 union label *lptr, **lpp;
H. Peter Anvin98578072018-06-01 18:02:54 -0700198 char *label_str = NULL;
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700199 struct hash_insert ip;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000200
H. Peter Anvin98578072018-06-01 18:02:54 -0700201 if (islocal(label))
202 label = label_str = nasm_strcat(prevlabel, label);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000203
H. Peter Anvin166c2472008-05-28 12:28:58 -0700204 lpp = (union label **) hash_find(&ltab, label, &ip);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700205 lptr = lpp ? *lpp : NULL;
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700206
Cyrill Gorcunov5dfcab62016-07-18 11:49:47 +0300207 if (lptr || !create) {
208 if (created)
H. Peter Anvin98578072018-06-01 18:02:54 -0700209 *created = false;
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400210 return lptr;
Cyrill Gorcunov5dfcab62016-07-18 11:49:47 +0300211 }
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700212
213 /* Create a new label... */
214 if (lfree->admin.movingon == END_BLOCK) {
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400215 /*
216 * must allocate a new block
217 */
H. Peter Anvin3e555482017-04-23 17:02:46 -0700218 lfree->admin.next = nasm_malloc(LBLK_SIZE);
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400219 lfree = lfree->admin.next;
220 init_block(lfree);
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700221 }
H. Peter Anvin70653092007-10-19 14:42:29 -0700222
Cyrill Gorcunov5dfcab62016-07-18 11:49:47 +0300223 if (created)
H. Peter Anvin98578072018-06-01 18:02:54 -0700224 *created = true;
Cyrill Gorcunov5dfcab62016-07-18 11:49:47 +0300225
H. Peter Anvin98578072018-06-01 18:02:54 -0700226 nasm_zero(*lfree);
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700227 lfree->admin.movingon = BOGUS_VALUE;
H. Peter Anvin98578072018-06-01 18:02:54 -0700228 lfree->defn.label = perm_copy(label);
229 if (label_str)
230 nasm_free(label_str);
H. Peter Anvin70653092007-10-19 14:42:29 -0700231
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700232 hash_add(&ip, lfree->defn.label, lfree);
233 return lfree++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000234}
235
H. Peter Anvin785ffb92017-03-14 18:41:25 -0700236bool lookup_label(const char *label, int32_t *segment, int64_t *offset)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000237{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000238 union label *lptr;
239
Keith Kaniosb7a89542007-04-12 02:40:54 +0000240 if (!initialized)
H. Peter Anvin70055962007-10-11 00:05:31 -0700241 return false;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000242
H. Peter Anvin98578072018-06-01 18:02:54 -0700243 lptr = find_label(label, false, NULL);
244 if (lptr && lptr->defn.defined) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000245 *segment = lptr->defn.segment;
246 *offset = lptr->defn.offset;
H. Peter Anvin70055962007-10-11 00:05:31 -0700247 return true;
Cyrill Gorcunovd7a64b72010-04-20 15:26:08 +0400248 }
249
250 return false;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000251}
252
H. Peter Anvin785ffb92017-03-14 18:41:25 -0700253bool is_extern(const char *label)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000254{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000255 union label *lptr;
256
Keith Kaniosb7a89542007-04-12 02:40:54 +0000257 if (!initialized)
H. Peter Anvin70055962007-10-11 00:05:31 -0700258 return false;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000259
H. Peter Anvin98578072018-06-01 18:02:54 -0700260 lptr = find_label(label, false, NULL);
261 return lptr && lptr->defn.type == LBL_EXTERN;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000262}
263
H. Peter Anvin98578072018-06-01 18:02:54 -0700264static const char *mangle_strings[] = {"", "", "", ""};
265static bool mangle_string_set[ARRAY_SIZE(mangle_strings)];
266
267/*
268 * Set a prefix or suffix
269 */
270void set_label_mangle(enum mangle_index which, const char *what)
271{
272 if (mangle_string_set[which])
273 return; /* Once set, do not change */
274
275 mangle_strings[which] = perm_copy(what);
276 mangle_string_set[which] = true;
277}
278
279/*
280 * Format a label name with appropriate prefixes and suffixes
281 */
282static const char *mangle_label_name(union label *lptr)
283{
284 const char *prefix;
285 const char *suffix;
286
287 if (likely(lptr->defn.mangled &&
288 lptr->defn.mangled_type == lptr->defn.type))
289 return lptr->defn.mangled; /* Already mangled */
290
291 switch (lptr->defn.type) {
292 case LBL_GLOBAL:
293 case LBL_STATIC:
294 case LBL_EXTERN:
295 prefix = mangle_strings[LM_GPREFIX];
296 suffix = mangle_strings[LM_GSUFFIX];
297 break;
298 case LBL_BACKEND:
299 case LBL_SPECIAL:
300 prefix = suffix = "";
301 break;
302 default:
303 prefix = mangle_strings[LM_LPREFIX];
304 suffix = mangle_strings[LM_LSUFFIX];
305 break;
306 }
307
308 lptr->defn.mangled_type = lptr->defn.type;
309
310 if (!(*prefix) && !(*suffix))
311 lptr->defn.mangled = lptr->defn.label;
312 else
313 lptr->defn.mangled = perm_copy3(prefix, lptr->defn.label, suffix);
314
315 return lptr->defn.mangled;
316}
317
318static void
319handle_herelabel(const union label *lptr, int32_t *segment, int64_t *offset)
H. Peter Anvin892c4812018-05-30 14:43:46 -0700320{
321 int32_t oldseg;
322
323 if (likely(!ofmt->herelabel))
324 return;
325
326 if (unlikely(location.segment == NO_SEG))
327 return;
328
329 oldseg = *segment;
330
331 if (oldseg == location.segment && *offset == location.offset) {
332 /* This label is defined at this location */
333 int32_t newseg;
334
H. Peter Anvin98578072018-06-01 18:02:54 -0700335 nasm_assert(lptr->defn.mangled);
336 newseg = ofmt->herelabel(lptr->defn.mangled, lptr->defn.type, oldseg);
H. Peter Anvin892c4812018-05-30 14:43:46 -0700337 if (likely(newseg == oldseg))
338 return;
339
340 *segment = newseg;
341 *offset = switch_segment(newseg);
342 }
343}
344
H. Peter Anvin98578072018-06-01 18:02:54 -0700345static bool declare_label_lptr(union label *lptr,
346 enum label_type type, const char *special)
347{
H. Peter Anvin3cb90682018-06-01 21:05:45 -0700348 if (special && !special[0])
349 special = NULL;
350
351 printf("declare_label %s type %d special %s\n",
352 lptr->defn.label, lptr->defn.type, lptr->defn.special);
353
H. Peter Anvin98578072018-06-01 18:02:54 -0700354 if (lptr->defn.type == type ||
355 (pass0 == 0 && lptr->defn.type == LBL_LOCAL)) {
356 lptr->defn.type = type;
357 if (special) {
358 if (!lptr->defn.special)
359 lptr->defn.special = perm_copy(special);
360 else if (nasm_stricmp(lptr->defn.special, special))
361 nasm_error(ERR_NONFATAL,
362 "symbol `%s' has inconsistent attributes `%s' and `%s'",
363 lptr->defn.label, lptr->defn.special, special);
364 }
365 return true;
366 }
367
368 /* EXTERN can be replaced with GLOBAL or COMMON */
369 if (lptr->defn.type == LBL_EXTERN &&
370 (type == LBL_GLOBAL || type == LBL_COMMON)) {
371 lptr->defn.type = type;
372 /* Override special unconditionally */
373 if (special)
374 lptr->defn.special = perm_copy(special);
375 return true;
376 }
377
378 /* GLOBAL or COMMON ignore subsequent EXTERN */
379 if ((lptr->defn.type == LBL_GLOBAL || lptr->defn.type == LBL_COMMON) &&
380 type == LBL_EXTERN) {
381 if (!lptr->defn.special)
382 lptr->defn.special = perm_copy(special);
383 return true;
384 }
385
386 nasm_error(ERR_NONFATAL, "symbol `%s' declared both as %s and %s",
387 lptr->defn.label, types[lptr->defn.type], types[type]);
388
389 return false;
390}
391
392bool declare_label(const char *label, enum label_type type, const char *special)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000393{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000394 union label *lptr;
H. Peter Anvin98578072018-06-01 18:02:54 -0700395 bool created;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000396
H. Peter Anvin98578072018-06-01 18:02:54 -0700397 lptr = find_label(label, true, &created);
398 return declare_label_lptr(lptr, type, special);
399}
400
401/*
402 * The "normal" argument decides if we should update the local segment
403 * base name or not.
404 */
405void define_label(const char *label, int32_t segment,
406 int64_t offset, bool normal)
407{
408 union label *lptr;
409 bool created, changed;
410
411 /*
412 * Phase errors here can be one of two types: a new label appears,
413 * or the offset changes. Increment global_offset_changed when that
414 * happens, to tell the assembler core to make another pass.
H. Peter Anvineba20a72002-04-30 20:53:55 +0000415 */
H. Peter Anvin98578072018-06-01 18:02:54 -0700416 lptr = find_label(label, true, &created);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000417
H. Peter Anvin98578072018-06-01 18:02:54 -0700418 if (pass0 > 1) {
419 if (created)
Cyrill Gorcunov5dfcab62016-07-18 11:49:47 +0300420 nasm_error(ERR_WARNING, "label `%s' defined on pass two", label);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000421 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000422
H. Peter Anvin98578072018-06-01 18:02:54 -0700423 if (lptr->defn.defined || lptr->defn.type == LBL_BACKEND) {
424 /* We have seen this on at least one previous pass */
425 mangle_label_name(lptr);
426 handle_herelabel(lptr, &segment, &offset);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000427 }
428
H. Peter Anvin98578072018-06-01 18:02:54 -0700429 if (ismagic(label) && lptr->defn.type == LBL_LOCAL)
430 lptr->defn.type = LBL_SPECIAL;
431
432 if (!islocal(label) && normal) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000433 prevlabel = lptr->defn.label;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000434 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000435
H. Peter Anvin98578072018-06-01 18:02:54 -0700436 changed = !lptr->defn.defined || lptr->defn.segment != segment ||
437 lptr->defn.offset != offset;
438 global_offset_changed += changed;
439
440 /*
441 * This probably should be ERR_NONFATAL, but not quite yet. As a
442 * special case, LBL_SPECIAL symbols are allowed to be changed
443 * even during the last pass.
444 */
445 if (changed && pass0 == 2 && lptr->defn.type != LBL_SPECIAL)
446 nasm_error(ERR_WARNING, "label `%s' changed during code generation",
447 lptr->defn.label);
448
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000449 lptr->defn.segment = segment;
H. Peter Anvin98578072018-06-01 18:02:54 -0700450 lptr->defn.offset = offset;
451 lptr->defn.defined = true;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000452
H. Peter Anvin98578072018-06-01 18:02:54 -0700453 out_symdef(lptr);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000454}
455
H. Peter Anvin98578072018-06-01 18:02:54 -0700456/*
457 * Define a special backend label
458 */
459void backend_label(const char *label, int32_t segment, int64_t offset)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000460{
H. Peter Anvin98578072018-06-01 18:02:54 -0700461 if (!declare_label(label, LBL_BACKEND, NULL))
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400462 return;
H. Peter Anvinaeb0e0e2009-06-27 16:30:00 -0700463
H. Peter Anvin98578072018-06-01 18:02:54 -0700464 define_label(label, segment, offset, false);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000465}
466
H. Peter Anvine2c80182005-01-15 22:15:51 +0000467int init_labels(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000468{
H. Peter Anvin166c2472008-05-28 12:28:58 -0700469 hash_init(&ltab, HASH_LARGE);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000470
H. Peter Anvin3e555482017-04-23 17:02:46 -0700471 ldata = lfree = nasm_malloc(LBLK_SIZE);
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700472 init_block(lfree);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000473
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400474 perm_head = perm_tail =
H. Peter Anvin3e555482017-04-23 17:02:46 -0700475 nasm_malloc(sizeof(struct permts));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000476
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000477 perm_head->next = NULL;
478 perm_head->size = PERMTS_SIZE;
479 perm_head->usage = 0;
480
481 prevlabel = "";
482
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700483 initialized = true;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000484
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000485 return 0;
486}
487
H. Peter Anvine2c80182005-01-15 22:15:51 +0000488void cleanup_labels(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000489{
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700490 union label *lptr, *lhold;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000491
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700492 initialized = false;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000493
H. Peter Anvin166c2472008-05-28 12:28:58 -0700494 hash_free(&ltab);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000495
H. Peter Anvin6244f4b2007-09-14 18:03:29 -0700496 lptr = lhold = ldata;
497 while (lptr) {
Cyrill Gorcunovd143f4f2010-07-28 10:18:48 +0400498 lptr = &lptr[LABEL_BLOCK-1];
499 lptr = lptr->admin.next;
500 nasm_free(lhold);
501 lhold = lptr;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000502 }
503
504 while (perm_head) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000505 perm_tail = perm_head;
506 perm_head = perm_head->next;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000507 nasm_free(perm_tail);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000508 }
509}
510
H. Peter Anvine2c80182005-01-15 22:15:51 +0000511static void init_block(union label *blk)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000512{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000513 int j;
514
H. Peter Anvine2c80182005-01-15 22:15:51 +0000515 for (j = 0; j < LABEL_BLOCK - 1; j++)
516 blk[j].admin.movingon = END_LIST;
517 blk[LABEL_BLOCK - 1].admin.movingon = END_BLOCK;
518 blk[LABEL_BLOCK - 1].admin.next = NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000519}
520
H. Peter Anvin98578072018-06-01 18:02:54 -0700521static char * safe_alloc perm_alloc(size_t len)
522{
H. Peter Anvin3cb90682018-06-01 21:05:45 -0700523 char *p;
524
H. Peter Anvin98578072018-06-01 18:02:54 -0700525 if (perm_tail->size - perm_tail->usage < len) {
526 size_t alloc_len = (len > PERMTS_SIZE) ? len : PERMTS_SIZE;
527 perm_tail->next = nasm_malloc(PERMTS_HEADER + alloc_len);
528 perm_tail = perm_tail->next;
529 perm_tail->next = NULL;
530 perm_tail->size = alloc_len;
531 perm_tail->usage = 0;
532 }
H. Peter Anvin3cb90682018-06-01 21:05:45 -0700533 p = perm_tail->data + perm_tail->usage;
H. Peter Anvin98578072018-06-01 18:02:54 -0700534 perm_tail->usage += len;
H. Peter Anvin3cb90682018-06-01 21:05:45 -0700535 return p;
H. Peter Anvin98578072018-06-01 18:02:54 -0700536}
537
H. Peter Anvind2fb7a62007-09-16 17:53:17 -0700538static char *perm_copy(const char *string)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000539{
H. Peter Anvind2fb7a62007-09-16 17:53:17 -0700540 char *p;
H. Peter Anvin98578072018-06-01 18:02:54 -0700541 size_t len;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000542
H. Peter Anvin98578072018-06-01 18:02:54 -0700543 if (!string)
544 return NULL;
H. Peter Anvin565be912009-07-05 22:15:57 -0700545
H. Peter Anvin98578072018-06-01 18:02:54 -0700546 len = strlen(string)+1; /* Include final NUL */
547
548 p = perm_alloc(len);
H. Peter Anvind2fb7a62007-09-16 17:53:17 -0700549 memcpy(p, string, len);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000550
551 return p;
552}
H. Peter Anvineba20a72002-04-30 20:53:55 +0000553
H. Peter Anvin3cb90682018-06-01 21:05:45 -0700554static char *
H. Peter Anvin98578072018-06-01 18:02:54 -0700555perm_copy3(const char *s1, const char *s2, const char *s3)
556{
557 char *p;
558 size_t l1 = strlen(s1);
559 size_t l2 = strlen(s2);
560 size_t l3 = strlen(s3)+1; /* Include final NUL */
561
562 p = perm_alloc(l1+l2+l3);
563 memcpy(p, s1, l1);
564 memcpy(p+l1, s2, l2);
565 memcpy(p+l1+l2, s3, l3);
566
567 return p;
568}
569
570const char *local_scope(const char *label)
Charles Crayned60059e2008-03-12 22:39:03 -0700571{
572 return islocal(label) ? prevlabel : "";
573}
574
H. Peter Anvineba20a72002-04-30 20:53:55 +0000575/*
576 * Notes regarding bug involving redefinition of external segments.
577 *
578 * Up to and including v0.97, the following code didn't work. From 0.97
579 * developers release 2 onwards, it will generate an error.
580 *
581 * EXTERN extlabel
582 * newlabel EQU extlabel + 1
583 *
584 * The results of allowing this code through are that two import records
585 * are generated, one for 'extlabel' and one for 'newlabel'.
586 *
587 * The reason for this is an inadequacy in the defined interface between
588 * the label manager and the output formats. The problem lies in how the
589 * output format driver tells that a label is an external label for which
590 * a label import record must be produced. Most (all except bin?) produce
591 * the record if the segment number of the label is not one of the internal
592 * segments that the output driver is producing.
593 *
594 * A simple fix to this would be to make the output formats keep track of
595 * which symbols they've produced import records for, and make them not
596 * produce import records for segments that are already defined.
597 *
598 * The best way, which is slightly harder but reduces duplication of code
599 * and should therefore make the entire system smaller and more stable is
600 * to change the interface between assembler, define_label(), and
601 * the output module. The changes that are needed are:
602 *
603 * The semantics of the 'isextern' flag passed to define_label() need
604 * examining. This information may or may not tell us what we need to
605 * know (ie should we be generating an import record at this point for this
606 * label). If these aren't the semantics, the semantics should be changed
607 * to this.
608 *
609 * The output module interface needs changing, so that the `isextern' flag
610 * is passed to the module, so that it can be easily tested for.
611 */