| 1 |
147 |
khays |
/* symbols.c -symbol table-
|
| 2 |
|
|
Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
| 3 |
|
|
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
| 4 |
|
|
2011 Free Software Foundation, Inc.
|
| 5 |
|
|
|
| 6 |
|
|
This file is part of GAS, the GNU Assembler.
|
| 7 |
|
|
|
| 8 |
|
|
GAS is free software; you can redistribute it and/or modify
|
| 9 |
|
|
it under the terms of the GNU General Public License as published by
|
| 10 |
|
|
the Free Software Foundation; either version 3, or (at your option)
|
| 11 |
|
|
any later version.
|
| 12 |
|
|
|
| 13 |
|
|
GAS is distributed in the hope that it will be useful,
|
| 14 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 15 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 16 |
|
|
GNU General Public License for more details.
|
| 17 |
|
|
|
| 18 |
|
|
You should have received a copy of the GNU General Public License
|
| 19 |
|
|
along with GAS; see the file COPYING. If not, write to the Free
|
| 20 |
|
|
Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
|
| 21 |
|
|
02110-1301, USA. */
|
| 22 |
|
|
|
| 23 |
|
|
/* #define DEBUG_SYMS / * to debug symbol list maintenance. */
|
| 24 |
|
|
|
| 25 |
|
|
#include "as.h"
|
| 26 |
|
|
#include "safe-ctype.h"
|
| 27 |
|
|
#include "obstack.h" /* For "symbols.h" */
|
| 28 |
|
|
#include "subsegs.h"
|
| 29 |
|
|
#include "struc-symbol.h"
|
| 30 |
|
|
|
| 31 |
|
|
/* This is non-zero if symbols are case sensitive, which is the
|
| 32 |
|
|
default. */
|
| 33 |
|
|
int symbols_case_sensitive = 1;
|
| 34 |
|
|
|
| 35 |
|
|
#ifndef WORKING_DOT_WORD
|
| 36 |
|
|
extern int new_broken_words;
|
| 37 |
|
|
#endif
|
| 38 |
|
|
|
| 39 |
|
|
/* symbol-name => struct symbol pointer */
|
| 40 |
|
|
static struct hash_control *sy_hash;
|
| 41 |
|
|
|
| 42 |
|
|
/* Table of local symbols. */
|
| 43 |
|
|
static struct hash_control *local_hash;
|
| 44 |
|
|
|
| 45 |
|
|
/* Below are commented in "symbols.h". */
|
| 46 |
|
|
symbolS *symbol_rootP;
|
| 47 |
|
|
symbolS *symbol_lastP;
|
| 48 |
|
|
symbolS abs_symbol;
|
| 49 |
|
|
symbolS dot_symbol;
|
| 50 |
|
|
|
| 51 |
|
|
#ifdef DEBUG_SYMS
|
| 52 |
|
|
#define debug_verify_symchain verify_symbol_chain
|
| 53 |
|
|
#else
|
| 54 |
|
|
#define debug_verify_symchain(root, last) ((void) 0)
|
| 55 |
|
|
#endif
|
| 56 |
|
|
|
| 57 |
|
|
#define DOLLAR_LABEL_CHAR '\001'
|
| 58 |
|
|
#define LOCAL_LABEL_CHAR '\002'
|
| 59 |
|
|
|
| 60 |
160 |
khays |
#ifndef TC_LABEL_IS_LOCAL
|
| 61 |
|
|
#define TC_LABEL_IS_LOCAL(name) 0
|
| 62 |
|
|
#endif
|
| 63 |
|
|
|
| 64 |
147 |
khays |
struct obstack notes;
|
| 65 |
|
|
#ifdef TE_PE
|
| 66 |
|
|
/* The name of an external symbol which is
|
| 67 |
|
|
used to make weak PE symbol names unique. */
|
| 68 |
|
|
const char * an_external_name;
|
| 69 |
|
|
#endif
|
| 70 |
|
|
|
| 71 |
|
|
static char *save_symbol_name (const char *);
|
| 72 |
|
|
static void fb_label_init (void);
|
| 73 |
|
|
static long dollar_label_instance (long);
|
| 74 |
|
|
static long fb_label_instance (long);
|
| 75 |
|
|
|
| 76 |
|
|
static void print_binary (FILE *, const char *, expressionS *);
|
| 77 |
|
|
|
| 78 |
|
|
/* Return a pointer to a new symbol. Die if we can't make a new
|
| 79 |
|
|
symbol. Fill in the symbol's values. Add symbol to end of symbol
|
| 80 |
|
|
chain.
|
| 81 |
|
|
|
| 82 |
|
|
This function should be called in the general case of creating a
|
| 83 |
|
|
symbol. However, if the output file symbol table has already been
|
| 84 |
|
|
set, and you are certain that this symbol won't be wanted in the
|
| 85 |
|
|
output file, you can call symbol_create. */
|
| 86 |
|
|
|
| 87 |
|
|
symbolS *
|
| 88 |
|
|
symbol_new (const char *name, segT segment, valueT valu, fragS *frag)
|
| 89 |
|
|
{
|
| 90 |
|
|
symbolS *symbolP = symbol_create (name, segment, valu, frag);
|
| 91 |
|
|
|
| 92 |
|
|
/* Link to end of symbol chain. */
|
| 93 |
|
|
{
|
| 94 |
|
|
extern int symbol_table_frozen;
|
| 95 |
|
|
if (symbol_table_frozen)
|
| 96 |
|
|
abort ();
|
| 97 |
|
|
}
|
| 98 |
|
|
symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);
|
| 99 |
|
|
|
| 100 |
|
|
return symbolP;
|
| 101 |
|
|
}
|
| 102 |
|
|
|
| 103 |
|
|
/* Save a symbol name on a permanent obstack, and convert it according
|
| 104 |
|
|
to the object file format. */
|
| 105 |
|
|
|
| 106 |
|
|
static char *
|
| 107 |
|
|
save_symbol_name (const char *name)
|
| 108 |
|
|
{
|
| 109 |
|
|
unsigned int name_length;
|
| 110 |
|
|
char *ret;
|
| 111 |
|
|
|
| 112 |
|
|
name_length = strlen (name) + 1; /* +1 for \0. */
|
| 113 |
|
|
obstack_grow (¬es, name, name_length);
|
| 114 |
|
|
ret = (char *) obstack_finish (¬es);
|
| 115 |
|
|
|
| 116 |
|
|
#ifdef tc_canonicalize_symbol_name
|
| 117 |
|
|
ret = tc_canonicalize_symbol_name (ret);
|
| 118 |
|
|
#endif
|
| 119 |
|
|
|
| 120 |
|
|
if (! symbols_case_sensitive)
|
| 121 |
|
|
{
|
| 122 |
|
|
char *s;
|
| 123 |
|
|
|
| 124 |
|
|
for (s = ret; *s != '\0'; s++)
|
| 125 |
|
|
*s = TOUPPER (*s);
|
| 126 |
|
|
}
|
| 127 |
|
|
|
| 128 |
|
|
return ret;
|
| 129 |
|
|
}
|
| 130 |
|
|
|
| 131 |
|
|
symbolS *
|
| 132 |
|
|
symbol_create (const char *name, /* It is copied, the caller can destroy/modify. */
|
| 133 |
|
|
segT segment, /* Segment identifier (SEG_<something>). */
|
| 134 |
|
|
valueT valu, /* Symbol value. */
|
| 135 |
|
|
fragS *frag /* Associated fragment. */)
|
| 136 |
|
|
{
|
| 137 |
|
|
char *preserved_copy_of_name;
|
| 138 |
|
|
symbolS *symbolP;
|
| 139 |
|
|
|
| 140 |
|
|
preserved_copy_of_name = save_symbol_name (name);
|
| 141 |
|
|
|
| 142 |
|
|
symbolP = (symbolS *) obstack_alloc (¬es, sizeof (symbolS));
|
| 143 |
|
|
|
| 144 |
|
|
/* symbol must be born in some fixed state. This seems as good as any. */
|
| 145 |
|
|
memset (symbolP, 0, sizeof (symbolS));
|
| 146 |
|
|
|
| 147 |
|
|
symbolP->bsym = bfd_make_empty_symbol (stdoutput);
|
| 148 |
|
|
if (symbolP->bsym == NULL)
|
| 149 |
|
|
as_fatal ("bfd_make_empty_symbol: %s", bfd_errmsg (bfd_get_error ()));
|
| 150 |
|
|
S_SET_NAME (symbolP, preserved_copy_of_name);
|
| 151 |
|
|
|
| 152 |
|
|
S_SET_SEGMENT (symbolP, segment);
|
| 153 |
|
|
S_SET_VALUE (symbolP, valu);
|
| 154 |
|
|
symbol_clear_list_pointers (symbolP);
|
| 155 |
|
|
|
| 156 |
|
|
symbolP->sy_frag = frag;
|
| 157 |
|
|
|
| 158 |
|
|
obj_symbol_new_hook (symbolP);
|
| 159 |
|
|
|
| 160 |
|
|
#ifdef tc_symbol_new_hook
|
| 161 |
|
|
tc_symbol_new_hook (symbolP);
|
| 162 |
|
|
#endif
|
| 163 |
|
|
|
| 164 |
|
|
return symbolP;
|
| 165 |
|
|
}
|
| 166 |
|
|
|
| 167 |
|
|
|
| 168 |
|
|
/* Local symbol support. If we can get away with it, we keep only a
|
| 169 |
|
|
small amount of information for local symbols. */
|
| 170 |
|
|
|
| 171 |
|
|
static symbolS *local_symbol_convert (struct local_symbol *);
|
| 172 |
|
|
|
| 173 |
|
|
/* Used for statistics. */
|
| 174 |
|
|
|
| 175 |
|
|
static unsigned long local_symbol_count;
|
| 176 |
|
|
static unsigned long local_symbol_conversion_count;
|
| 177 |
|
|
|
| 178 |
|
|
/* This macro is called with a symbol argument passed by reference.
|
| 179 |
|
|
It returns whether this is a local symbol. If necessary, it
|
| 180 |
|
|
changes its argument to the real symbol. */
|
| 181 |
|
|
|
| 182 |
|
|
#define LOCAL_SYMBOL_CHECK(s) \
|
| 183 |
|
|
(s->bsym == NULL \
|
| 184 |
|
|
? (local_symbol_converted_p ((struct local_symbol *) s) \
|
| 185 |
|
|
? (s = local_symbol_get_real_symbol ((struct local_symbol *) s), \
|
| 186 |
|
|
0) \
|
| 187 |
|
|
: 1) \
|
| 188 |
|
|
: 0)
|
| 189 |
|
|
|
| 190 |
|
|
/* Create a local symbol and insert it into the local hash table. */
|
| 191 |
|
|
|
| 192 |
163 |
khays |
struct local_symbol *
|
| 193 |
147 |
khays |
local_symbol_make (const char *name, segT section, valueT val, fragS *frag)
|
| 194 |
|
|
{
|
| 195 |
|
|
char *name_copy;
|
| 196 |
|
|
struct local_symbol *ret;
|
| 197 |
|
|
|
| 198 |
|
|
++local_symbol_count;
|
| 199 |
|
|
|
| 200 |
|
|
name_copy = save_symbol_name (name);
|
| 201 |
|
|
|
| 202 |
|
|
ret = (struct local_symbol *) obstack_alloc (¬es, sizeof *ret);
|
| 203 |
|
|
ret->lsy_marker = NULL;
|
| 204 |
|
|
ret->lsy_name = name_copy;
|
| 205 |
|
|
ret->lsy_section = section;
|
| 206 |
|
|
local_symbol_set_frag (ret, frag);
|
| 207 |
|
|
ret->lsy_value = val;
|
| 208 |
|
|
|
| 209 |
|
|
hash_jam (local_hash, name_copy, (void *) ret);
|
| 210 |
|
|
|
| 211 |
|
|
return ret;
|
| 212 |
|
|
}
|
| 213 |
|
|
|
| 214 |
|
|
/* Convert a local symbol into a real symbol. Note that we do not
|
| 215 |
|
|
reclaim the space used by the local symbol. */
|
| 216 |
|
|
|
| 217 |
|
|
static symbolS *
|
| 218 |
|
|
local_symbol_convert (struct local_symbol *locsym)
|
| 219 |
|
|
{
|
| 220 |
|
|
symbolS *ret;
|
| 221 |
|
|
|
| 222 |
|
|
gas_assert (locsym->lsy_marker == NULL);
|
| 223 |
|
|
if (local_symbol_converted_p (locsym))
|
| 224 |
|
|
return local_symbol_get_real_symbol (locsym);
|
| 225 |
|
|
|
| 226 |
|
|
++local_symbol_conversion_count;
|
| 227 |
|
|
|
| 228 |
|
|
ret = symbol_new (locsym->lsy_name, locsym->lsy_section, locsym->lsy_value,
|
| 229 |
|
|
local_symbol_get_frag (locsym));
|
| 230 |
|
|
|
| 231 |
|
|
if (local_symbol_resolved_p (locsym))
|
| 232 |
|
|
ret->sy_resolved = 1;
|
| 233 |
|
|
|
| 234 |
|
|
/* Local symbols are always either defined or used. */
|
| 235 |
|
|
ret->sy_used = 1;
|
| 236 |
|
|
|
| 237 |
|
|
#ifdef TC_LOCAL_SYMFIELD_CONVERT
|
| 238 |
|
|
TC_LOCAL_SYMFIELD_CONVERT (locsym, ret);
|
| 239 |
|
|
#endif
|
| 240 |
|
|
|
| 241 |
|
|
symbol_table_insert (ret);
|
| 242 |
|
|
|
| 243 |
|
|
local_symbol_mark_converted (locsym);
|
| 244 |
|
|
local_symbol_set_real_symbol (locsym, ret);
|
| 245 |
|
|
|
| 246 |
|
|
hash_jam (local_hash, locsym->lsy_name, NULL);
|
| 247 |
|
|
|
| 248 |
|
|
return ret;
|
| 249 |
|
|
}
|
| 250 |
|
|
|
| 251 |
|
|
static void
|
| 252 |
|
|
define_sym_at_dot (symbolS *symbolP)
|
| 253 |
|
|
{
|
| 254 |
|
|
symbolP->sy_frag = frag_now;
|
| 255 |
|
|
S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
|
| 256 |
|
|
S_SET_SEGMENT (symbolP, now_seg);
|
| 257 |
|
|
}
|
| 258 |
|
|
|
| 259 |
|
|
/* We have just seen "<name>:".
|
| 260 |
|
|
Creates a struct symbol unless it already exists.
|
| 261 |
|
|
|
| 262 |
|
|
Gripes if we are redefining a symbol incompatibly (and ignores it). */
|
| 263 |
|
|
|
| 264 |
|
|
symbolS *
|
| 265 |
|
|
colon (/* Just seen "x:" - rattle symbols & frags. */
|
| 266 |
|
|
const char *sym_name /* Symbol name, as a cannonical string. */
|
| 267 |
|
|
/* We copy this string: OK to alter later. */)
|
| 268 |
|
|
{
|
| 269 |
|
|
register symbolS *symbolP; /* Symbol we are working with. */
|
| 270 |
|
|
|
| 271 |
|
|
/* Sun local labels go out of scope whenever a non-local symbol is
|
| 272 |
|
|
defined. */
|
| 273 |
|
|
if (LOCAL_LABELS_DOLLAR
|
| 274 |
|
|
&& !bfd_is_local_label_name (stdoutput, sym_name))
|
| 275 |
|
|
dollar_label_clear ();
|
| 276 |
|
|
|
| 277 |
|
|
#ifndef WORKING_DOT_WORD
|
| 278 |
|
|
if (new_broken_words)
|
| 279 |
|
|
{
|
| 280 |
|
|
struct broken_word *a;
|
| 281 |
|
|
int possible_bytes;
|
| 282 |
|
|
fragS *frag_tmp;
|
| 283 |
|
|
char *frag_opcode;
|
| 284 |
|
|
|
| 285 |
|
|
if (now_seg == absolute_section)
|
| 286 |
|
|
{
|
| 287 |
|
|
as_bad (_("cannot define symbol `%s' in absolute section"), sym_name);
|
| 288 |
|
|
return NULL;
|
| 289 |
|
|
}
|
| 290 |
|
|
|
| 291 |
|
|
possible_bytes = (md_short_jump_size
|
| 292 |
|
|
+ new_broken_words * md_long_jump_size);
|
| 293 |
|
|
|
| 294 |
|
|
frag_tmp = frag_now;
|
| 295 |
|
|
frag_opcode = frag_var (rs_broken_word,
|
| 296 |
|
|
possible_bytes,
|
| 297 |
|
|
possible_bytes,
|
| 298 |
|
|
(relax_substateT) 0,
|
| 299 |
|
|
(symbolS *) broken_words,
|
| 300 |
|
|
(offsetT) 0,
|
| 301 |
|
|
NULL);
|
| 302 |
|
|
|
| 303 |
|
|
/* We want to store the pointer to where to insert the jump
|
| 304 |
|
|
table in the fr_opcode of the rs_broken_word frag. This
|
| 305 |
|
|
requires a little hackery. */
|
| 306 |
|
|
while (frag_tmp
|
| 307 |
|
|
&& (frag_tmp->fr_type != rs_broken_word
|
| 308 |
|
|
|| frag_tmp->fr_opcode))
|
| 309 |
|
|
frag_tmp = frag_tmp->fr_next;
|
| 310 |
|
|
know (frag_tmp);
|
| 311 |
|
|
frag_tmp->fr_opcode = frag_opcode;
|
| 312 |
|
|
new_broken_words = 0;
|
| 313 |
|
|
|
| 314 |
|
|
for (a = broken_words; a && a->dispfrag == 0; a = a->next_broken_word)
|
| 315 |
|
|
a->dispfrag = frag_tmp;
|
| 316 |
|
|
}
|
| 317 |
|
|
#endif /* WORKING_DOT_WORD */
|
| 318 |
|
|
|
| 319 |
|
|
if ((symbolP = symbol_find (sym_name)) != 0)
|
| 320 |
|
|
{
|
| 321 |
|
|
S_CLEAR_WEAKREFR (symbolP);
|
| 322 |
|
|
#ifdef RESOLVE_SYMBOL_REDEFINITION
|
| 323 |
|
|
if (RESOLVE_SYMBOL_REDEFINITION (symbolP))
|
| 324 |
|
|
return symbolP;
|
| 325 |
|
|
#endif
|
| 326 |
|
|
/* Now check for undefined symbols. */
|
| 327 |
|
|
if (LOCAL_SYMBOL_CHECK (symbolP))
|
| 328 |
|
|
{
|
| 329 |
|
|
struct local_symbol *locsym = (struct local_symbol *) symbolP;
|
| 330 |
|
|
|
| 331 |
|
|
if (locsym->lsy_section != undefined_section
|
| 332 |
|
|
&& (local_symbol_get_frag (locsym) != frag_now
|
| 333 |
|
|
|| locsym->lsy_section != now_seg
|
| 334 |
|
|
|| locsym->lsy_value != frag_now_fix ()))
|
| 335 |
|
|
{
|
| 336 |
|
|
as_bad (_("symbol `%s' is already defined"), sym_name);
|
| 337 |
|
|
return symbolP;
|
| 338 |
|
|
}
|
| 339 |
|
|
|
| 340 |
|
|
locsym->lsy_section = now_seg;
|
| 341 |
|
|
local_symbol_set_frag (locsym, frag_now);
|
| 342 |
|
|
locsym->lsy_value = frag_now_fix ();
|
| 343 |
|
|
}
|
| 344 |
|
|
else if (!(S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP))
|
| 345 |
|
|
|| S_IS_COMMON (symbolP)
|
| 346 |
|
|
|| S_IS_VOLATILE (symbolP))
|
| 347 |
|
|
{
|
| 348 |
|
|
if (S_IS_VOLATILE (symbolP))
|
| 349 |
|
|
{
|
| 350 |
|
|
symbolP = symbol_clone (symbolP, 1);
|
| 351 |
|
|
S_SET_VALUE (symbolP, 0);
|
| 352 |
|
|
S_CLEAR_VOLATILE (symbolP);
|
| 353 |
|
|
}
|
| 354 |
|
|
if (S_GET_VALUE (symbolP) == 0)
|
| 355 |
|
|
{
|
| 356 |
|
|
define_sym_at_dot (symbolP);
|
| 357 |
|
|
#ifdef N_UNDF
|
| 358 |
|
|
know (N_UNDF == 0);
|
| 359 |
|
|
#endif /* if we have one, it better be zero. */
|
| 360 |
|
|
|
| 361 |
|
|
}
|
| 362 |
|
|
else
|
| 363 |
|
|
{
|
| 364 |
|
|
/* There are still several cases to check:
|
| 365 |
|
|
|
| 366 |
|
|
A .comm/.lcomm symbol being redefined as initialized
|
| 367 |
|
|
data is OK
|
| 368 |
|
|
|
| 369 |
|
|
A .comm/.lcomm symbol being redefined with a larger
|
| 370 |
|
|
size is also OK
|
| 371 |
|
|
|
| 372 |
|
|
This only used to be allowed on VMS gas, but Sun cc
|
| 373 |
|
|
on the sparc also depends on it. */
|
| 374 |
|
|
|
| 375 |
|
|
if (((!S_IS_DEBUG (symbolP)
|
| 376 |
|
|
&& (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
|
| 377 |
|
|
&& S_IS_EXTERNAL (symbolP))
|
| 378 |
|
|
|| S_GET_SEGMENT (symbolP) == bss_section)
|
| 379 |
|
|
&& (now_seg == data_section
|
| 380 |
|
|
|| now_seg == bss_section
|
| 381 |
|
|
|| now_seg == S_GET_SEGMENT (symbolP)))
|
| 382 |
|
|
{
|
| 383 |
|
|
/* Select which of the 2 cases this is. */
|
| 384 |
|
|
if (now_seg != data_section)
|
| 385 |
|
|
{
|
| 386 |
|
|
/* New .comm for prev .comm symbol.
|
| 387 |
|
|
|
| 388 |
|
|
If the new size is larger we just change its
|
| 389 |
|
|
value. If the new size is smaller, we ignore
|
| 390 |
|
|
this symbol. */
|
| 391 |
|
|
if (S_GET_VALUE (symbolP)
|
| 392 |
|
|
< ((unsigned) frag_now_fix ()))
|
| 393 |
|
|
{
|
| 394 |
|
|
S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
|
| 395 |
|
|
}
|
| 396 |
|
|
}
|
| 397 |
|
|
else
|
| 398 |
|
|
{
|
| 399 |
|
|
/* It is a .comm/.lcomm being converted to initialized
|
| 400 |
|
|
data. */
|
| 401 |
|
|
define_sym_at_dot (symbolP);
|
| 402 |
|
|
}
|
| 403 |
|
|
}
|
| 404 |
|
|
else
|
| 405 |
|
|
{
|
| 406 |
|
|
#if (!defined (OBJ_AOUT) && !defined (OBJ_MAYBE_AOUT) \
|
| 407 |
|
|
&& !defined (OBJ_BOUT) && !defined (OBJ_MAYBE_BOUT))
|
| 408 |
|
|
static const char *od_buf = "";
|
| 409 |
|
|
#else
|
| 410 |
|
|
char od_buf[100];
|
| 411 |
|
|
od_buf[0] = '\0';
|
| 412 |
|
|
if (OUTPUT_FLAVOR == bfd_target_aout_flavour)
|
| 413 |
|
|
sprintf (od_buf, "%d.%d.",
|
| 414 |
|
|
S_GET_OTHER (symbolP),
|
| 415 |
|
|
S_GET_DESC (symbolP));
|
| 416 |
|
|
#endif
|
| 417 |
|
|
as_bad (_("symbol `%s' is already defined as \"%s\"/%s%ld"),
|
| 418 |
|
|
sym_name,
|
| 419 |
|
|
segment_name (S_GET_SEGMENT (symbolP)),
|
| 420 |
|
|
od_buf,
|
| 421 |
|
|
(long) S_GET_VALUE (symbolP));
|
| 422 |
|
|
}
|
| 423 |
|
|
} /* if the undefined symbol has no value */
|
| 424 |
|
|
}
|
| 425 |
|
|
else
|
| 426 |
|
|
{
|
| 427 |
|
|
/* Don't blow up if the definition is the same. */
|
| 428 |
|
|
if (!(frag_now == symbolP->sy_frag
|
| 429 |
|
|
&& S_GET_VALUE (symbolP) == frag_now_fix ()
|
| 430 |
|
|
&& S_GET_SEGMENT (symbolP) == now_seg))
|
| 431 |
|
|
{
|
| 432 |
|
|
as_bad (_("symbol `%s' is already defined"), sym_name);
|
| 433 |
|
|
symbolP = symbol_clone (symbolP, 0);
|
| 434 |
|
|
define_sym_at_dot (symbolP);
|
| 435 |
|
|
}
|
| 436 |
|
|
}
|
| 437 |
|
|
|
| 438 |
|
|
}
|
| 439 |
|
|
else if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, sym_name))
|
| 440 |
|
|
{
|
| 441 |
|
|
symbolP = (symbolS *) local_symbol_make (sym_name, now_seg,
|
| 442 |
|
|
(valueT) frag_now_fix (),
|
| 443 |
|
|
frag_now);
|
| 444 |
|
|
}
|
| 445 |
|
|
else
|
| 446 |
|
|
{
|
| 447 |
|
|
symbolP = symbol_new (sym_name, now_seg, (valueT) frag_now_fix (),
|
| 448 |
|
|
frag_now);
|
| 449 |
|
|
|
| 450 |
|
|
symbol_table_insert (symbolP);
|
| 451 |
|
|
}
|
| 452 |
|
|
|
| 453 |
|
|
if (mri_common_symbol != NULL)
|
| 454 |
|
|
{
|
| 455 |
|
|
/* This symbol is actually being defined within an MRI common
|
| 456 |
|
|
section. This requires special handling. */
|
| 457 |
|
|
if (LOCAL_SYMBOL_CHECK (symbolP))
|
| 458 |
|
|
symbolP = local_symbol_convert ((struct local_symbol *) symbolP);
|
| 459 |
|
|
symbolP->sy_value.X_op = O_symbol;
|
| 460 |
|
|
symbolP->sy_value.X_add_symbol = mri_common_symbol;
|
| 461 |
|
|
symbolP->sy_value.X_add_number = S_GET_VALUE (mri_common_symbol);
|
| 462 |
|
|
symbolP->sy_frag = &zero_address_frag;
|
| 463 |
|
|
S_SET_SEGMENT (symbolP, expr_section);
|
| 464 |
|
|
symbolP->sy_mri_common = 1;
|
| 465 |
|
|
}
|
| 466 |
|
|
|
| 467 |
|
|
#ifdef tc_frob_label
|
| 468 |
|
|
tc_frob_label (symbolP);
|
| 469 |
|
|
#endif
|
| 470 |
|
|
#ifdef obj_frob_label
|
| 471 |
|
|
obj_frob_label (symbolP);
|
| 472 |
|
|
#endif
|
| 473 |
|
|
|
| 474 |
|
|
return symbolP;
|
| 475 |
|
|
}
|
| 476 |
|
|
|
| 477 |
|
|
/* Die if we can't insert the symbol. */
|
| 478 |
|
|
|
| 479 |
|
|
void
|
| 480 |
|
|
symbol_table_insert (symbolS *symbolP)
|
| 481 |
|
|
{
|
| 482 |
|
|
register const char *error_string;
|
| 483 |
|
|
|
| 484 |
|
|
know (symbolP);
|
| 485 |
|
|
know (S_GET_NAME (symbolP));
|
| 486 |
|
|
|
| 487 |
|
|
if (LOCAL_SYMBOL_CHECK (symbolP))
|
| 488 |
|
|
{
|
| 489 |
|
|
error_string = hash_jam (local_hash, S_GET_NAME (symbolP),
|
| 490 |
|
|
(void *) symbolP);
|
| 491 |
|
|
if (error_string != NULL)
|
| 492 |
|
|
as_fatal (_("inserting \"%s\" into symbol table failed: %s"),
|
| 493 |
|
|
S_GET_NAME (symbolP), error_string);
|
| 494 |
|
|
return;
|
| 495 |
|
|
}
|
| 496 |
|
|
|
| 497 |
|
|
if ((error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (void *) symbolP)))
|
| 498 |
|
|
{
|
| 499 |
|
|
as_fatal (_("inserting \"%s\" into symbol table failed: %s"),
|
| 500 |
|
|
S_GET_NAME (symbolP), error_string);
|
| 501 |
|
|
} /* on error */
|
| 502 |
|
|
}
|
| 503 |
|
|
|
| 504 |
|
|
/* If a symbol name does not exist, create it as undefined, and insert
|
| 505 |
|
|
it into the symbol table. Return a pointer to it. */
|
| 506 |
|
|
|
| 507 |
|
|
symbolS *
|
| 508 |
|
|
symbol_find_or_make (const char *name)
|
| 509 |
|
|
{
|
| 510 |
|
|
register symbolS *symbolP;
|
| 511 |
|
|
|
| 512 |
|
|
symbolP = symbol_find (name);
|
| 513 |
|
|
|
| 514 |
|
|
if (symbolP == NULL)
|
| 515 |
|
|
{
|
| 516 |
|
|
if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, name))
|
| 517 |
|
|
{
|
| 518 |
|
|
symbolP = md_undefined_symbol ((char *) name);
|
| 519 |
|
|
if (symbolP != NULL)
|
| 520 |
|
|
return symbolP;
|
| 521 |
|
|
|
| 522 |
|
|
symbolP = (symbolS *) local_symbol_make (name, undefined_section,
|
| 523 |
|
|
(valueT) 0,
|
| 524 |
|
|
&zero_address_frag);
|
| 525 |
|
|
return symbolP;
|
| 526 |
|
|
}
|
| 527 |
|
|
|
| 528 |
|
|
symbolP = symbol_make (name);
|
| 529 |
|
|
|
| 530 |
|
|
symbol_table_insert (symbolP);
|
| 531 |
|
|
} /* if symbol wasn't found */
|
| 532 |
|
|
|
| 533 |
|
|
return (symbolP);
|
| 534 |
|
|
}
|
| 535 |
|
|
|
| 536 |
|
|
symbolS *
|
| 537 |
|
|
symbol_make (const char *name)
|
| 538 |
|
|
{
|
| 539 |
|
|
symbolS *symbolP;
|
| 540 |
|
|
|
| 541 |
|
|
/* Let the machine description default it, e.g. for register names. */
|
| 542 |
|
|
symbolP = md_undefined_symbol ((char *) name);
|
| 543 |
|
|
|
| 544 |
|
|
if (!symbolP)
|
| 545 |
|
|
symbolP = symbol_new (name, undefined_section, (valueT) 0, &zero_address_frag);
|
| 546 |
|
|
|
| 547 |
|
|
return (symbolP);
|
| 548 |
|
|
}
|
| 549 |
|
|
|
| 550 |
|
|
symbolS *
|
| 551 |
|
|
symbol_clone (symbolS *orgsymP, int replace)
|
| 552 |
|
|
{
|
| 553 |
|
|
symbolS *newsymP;
|
| 554 |
|
|
asymbol *bsymorg, *bsymnew;
|
| 555 |
|
|
|
| 556 |
|
|
/* Make sure we never clone the dot special symbol. */
|
| 557 |
|
|
gas_assert (orgsymP != &dot_symbol);
|
| 558 |
|
|
|
| 559 |
|
|
/* Running local_symbol_convert on a clone that's not the one currently
|
| 560 |
|
|
in local_hash would incorrectly replace the hash entry. Thus the
|
| 561 |
|
|
symbol must be converted here. Note that the rest of the function
|
| 562 |
|
|
depends on not encountering an unconverted symbol. */
|
| 563 |
|
|
if (LOCAL_SYMBOL_CHECK (orgsymP))
|
| 564 |
|
|
orgsymP = local_symbol_convert ((struct local_symbol *) orgsymP);
|
| 565 |
|
|
bsymorg = orgsymP->bsym;
|
| 566 |
|
|
|
| 567 |
|
|
newsymP = (symbolS *) obstack_alloc (¬es, sizeof (*newsymP));
|
| 568 |
|
|
*newsymP = *orgsymP;
|
| 569 |
|
|
bsymnew = bfd_make_empty_symbol (bfd_asymbol_bfd (bsymorg));
|
| 570 |
|
|
if (bsymnew == NULL)
|
| 571 |
|
|
as_fatal ("bfd_make_empty_symbol: %s", bfd_errmsg (bfd_get_error ()));
|
| 572 |
|
|
newsymP->bsym = bsymnew;
|
| 573 |
|
|
bsymnew->name = bsymorg->name;
|
| 574 |
|
|
bsymnew->flags = bsymorg->flags & ~BSF_SECTION_SYM;
|
| 575 |
|
|
bsymnew->section = bsymorg->section;
|
| 576 |
|
|
bfd_copy_private_symbol_data (bfd_asymbol_bfd (bsymorg), bsymorg,
|
| 577 |
|
|
bfd_asymbol_bfd (bsymnew), bsymnew);
|
| 578 |
|
|
|
| 579 |
|
|
#ifdef obj_symbol_clone_hook
|
| 580 |
|
|
obj_symbol_clone_hook (newsymP, orgsymP);
|
| 581 |
|
|
#endif
|
| 582 |
|
|
|
| 583 |
|
|
#ifdef tc_symbol_clone_hook
|
| 584 |
|
|
tc_symbol_clone_hook (newsymP, orgsymP);
|
| 585 |
|
|
#endif
|
| 586 |
|
|
|
| 587 |
|
|
if (replace)
|
| 588 |
|
|
{
|
| 589 |
|
|
if (symbol_rootP == orgsymP)
|
| 590 |
|
|
symbol_rootP = newsymP;
|
| 591 |
|
|
else if (orgsymP->sy_previous)
|
| 592 |
|
|
{
|
| 593 |
|
|
orgsymP->sy_previous->sy_next = newsymP;
|
| 594 |
|
|
orgsymP->sy_previous = NULL;
|
| 595 |
|
|
}
|
| 596 |
|
|
if (symbol_lastP == orgsymP)
|
| 597 |
|
|
symbol_lastP = newsymP;
|
| 598 |
|
|
else if (orgsymP->sy_next)
|
| 599 |
|
|
orgsymP->sy_next->sy_previous = newsymP;
|
| 600 |
|
|
|
| 601 |
|
|
/* Symbols that won't be output can't be external. */
|
| 602 |
|
|
S_CLEAR_EXTERNAL (orgsymP);
|
| 603 |
|
|
orgsymP->sy_previous = orgsymP->sy_next = orgsymP;
|
| 604 |
|
|
debug_verify_symchain (symbol_rootP, symbol_lastP);
|
| 605 |
|
|
|
| 606 |
|
|
symbol_table_insert (newsymP);
|
| 607 |
|
|
}
|
| 608 |
|
|
else
|
| 609 |
|
|
{
|
| 610 |
|
|
/* Symbols that won't be output can't be external. */
|
| 611 |
|
|
S_CLEAR_EXTERNAL (newsymP);
|
| 612 |
|
|
newsymP->sy_previous = newsymP->sy_next = newsymP;
|
| 613 |
|
|
}
|
| 614 |
|
|
|
| 615 |
|
|
return newsymP;
|
| 616 |
|
|
}
|
| 617 |
|
|
|
| 618 |
|
|
/* Referenced symbols, if they are forward references, need to be cloned
|
| 619 |
|
|
(without replacing the original) so that the value of the referenced
|
| 620 |
|
|
symbols at the point of use . */
|
| 621 |
|
|
|
| 622 |
|
|
#undef symbol_clone_if_forward_ref
|
| 623 |
|
|
symbolS *
|
| 624 |
|
|
symbol_clone_if_forward_ref (symbolS *symbolP, int is_forward)
|
| 625 |
|
|
{
|
| 626 |
|
|
if (symbolP && !LOCAL_SYMBOL_CHECK (symbolP))
|
| 627 |
|
|
{
|
| 628 |
|
|
symbolS *add_symbol = symbolP->sy_value.X_add_symbol;
|
| 629 |
|
|
symbolS *op_symbol = symbolP->sy_value.X_op_symbol;
|
| 630 |
|
|
|
| 631 |
|
|
if (symbolP->sy_forward_ref)
|
| 632 |
|
|
is_forward = 1;
|
| 633 |
|
|
|
| 634 |
|
|
if (is_forward)
|
| 635 |
|
|
{
|
| 636 |
|
|
/* assign_symbol() clones volatile symbols; pre-existing expressions
|
| 637 |
|
|
hold references to the original instance, but want the current
|
| 638 |
|
|
value. Just repeat the lookup. */
|
| 639 |
|
|
if (add_symbol && S_IS_VOLATILE (add_symbol))
|
| 640 |
|
|
add_symbol = symbol_find_exact (S_GET_NAME (add_symbol));
|
| 641 |
|
|
if (op_symbol && S_IS_VOLATILE (op_symbol))
|
| 642 |
|
|
op_symbol = symbol_find_exact (S_GET_NAME (op_symbol));
|
| 643 |
|
|
}
|
| 644 |
|
|
|
| 645 |
|
|
/* Re-using sy_resolving here, as this routine cannot get called from
|
| 646 |
|
|
symbol resolution code. */
|
| 647 |
|
|
if ((symbolP->bsym->section == expr_section || symbolP->sy_forward_ref)
|
| 648 |
|
|
&& !symbolP->sy_resolving)
|
| 649 |
|
|
{
|
| 650 |
|
|
symbolP->sy_resolving = 1;
|
| 651 |
|
|
add_symbol = symbol_clone_if_forward_ref (add_symbol, is_forward);
|
| 652 |
|
|
op_symbol = symbol_clone_if_forward_ref (op_symbol, is_forward);
|
| 653 |
|
|
symbolP->sy_resolving = 0;
|
| 654 |
|
|
}
|
| 655 |
|
|
|
| 656 |
|
|
if (symbolP->sy_forward_ref
|
| 657 |
|
|
|| add_symbol != symbolP->sy_value.X_add_symbol
|
| 658 |
|
|
|| op_symbol != symbolP->sy_value.X_op_symbol)
|
| 659 |
|
|
{
|
| 660 |
|
|
if (symbolP != &dot_symbol)
|
| 661 |
|
|
{
|
| 662 |
|
|
symbolP = symbol_clone (symbolP, 0);
|
| 663 |
|
|
symbolP->sy_resolving = 0;
|
| 664 |
|
|
}
|
| 665 |
|
|
else
|
| 666 |
|
|
{
|
| 667 |
|
|
symbolP = symbol_temp_new_now ();
|
| 668 |
|
|
#ifdef tc_new_dot_label
|
| 669 |
|
|
tc_new_dot_label (symbolP);
|
| 670 |
|
|
#endif
|
| 671 |
|
|
}
|
| 672 |
|
|
}
|
| 673 |
|
|
|
| 674 |
|
|
symbolP->sy_value.X_add_symbol = add_symbol;
|
| 675 |
|
|
symbolP->sy_value.X_op_symbol = op_symbol;
|
| 676 |
|
|
}
|
| 677 |
|
|
|
| 678 |
|
|
return symbolP;
|
| 679 |
|
|
}
|
| 680 |
|
|
|
| 681 |
|
|
symbolS *
|
| 682 |
|
|
symbol_temp_new (segT seg, valueT ofs, fragS *frag)
|
| 683 |
|
|
{
|
| 684 |
|
|
return symbol_new (FAKE_LABEL_NAME, seg, ofs, frag);
|
| 685 |
|
|
}
|
| 686 |
|
|
|
| 687 |
|
|
symbolS *
|
| 688 |
|
|
symbol_temp_new_now (void)
|
| 689 |
|
|
{
|
| 690 |
|
|
return symbol_temp_new (now_seg, frag_now_fix (), frag_now);
|
| 691 |
|
|
}
|
| 692 |
|
|
|
| 693 |
|
|
symbolS *
|
| 694 |
|
|
symbol_temp_make (void)
|
| 695 |
|
|
{
|
| 696 |
|
|
return symbol_make (FAKE_LABEL_NAME);
|
| 697 |
|
|
}
|
| 698 |
|
|
|
| 699 |
|
|
/* Implement symbol table lookup.
|
| 700 |
|
|
In: A symbol's name as a string: '\0' can't be part of a symbol name.
|
| 701 |
|
|
Out: NULL if the name was not in the symbol table, else the address
|
| 702 |
|
|
of a struct symbol associated with that name. */
|
| 703 |
|
|
|
| 704 |
|
|
symbolS *
|
| 705 |
|
|
symbol_find_exact (const char *name)
|
| 706 |
|
|
{
|
| 707 |
|
|
return symbol_find_exact_noref (name, 0);
|
| 708 |
|
|
}
|
| 709 |
|
|
|
| 710 |
|
|
symbolS *
|
| 711 |
|
|
symbol_find_exact_noref (const char *name, int noref)
|
| 712 |
|
|
{
|
| 713 |
|
|
struct local_symbol *locsym;
|
| 714 |
|
|
symbolS* sym;
|
| 715 |
|
|
|
| 716 |
|
|
locsym = (struct local_symbol *) hash_find (local_hash, name);
|
| 717 |
|
|
if (locsym != NULL)
|
| 718 |
|
|
return (symbolS *) locsym;
|
| 719 |
|
|
|
| 720 |
|
|
sym = ((symbolS *) hash_find (sy_hash, name));
|
| 721 |
|
|
|
| 722 |
|
|
/* Any references to the symbol, except for the reference in
|
| 723 |
|
|
.weakref, must clear this flag, such that the symbol does not
|
| 724 |
|
|
turn into a weak symbol. Note that we don't have to handle the
|
| 725 |
|
|
local_symbol case, since a weakrefd is always promoted out of the
|
| 726 |
|
|
local_symbol table when it is turned into a weak symbol. */
|
| 727 |
|
|
if (sym && ! noref)
|
| 728 |
|
|
S_CLEAR_WEAKREFD (sym);
|
| 729 |
|
|
|
| 730 |
|
|
return sym;
|
| 731 |
|
|
}
|
| 732 |
|
|
|
| 733 |
|
|
symbolS *
|
| 734 |
|
|
symbol_find (const char *name)
|
| 735 |
|
|
{
|
| 736 |
|
|
return symbol_find_noref (name, 0);
|
| 737 |
|
|
}
|
| 738 |
|
|
|
| 739 |
|
|
symbolS *
|
| 740 |
|
|
symbol_find_noref (const char *name, int noref)
|
| 741 |
|
|
{
|
| 742 |
|
|
#ifdef tc_canonicalize_symbol_name
|
| 743 |
|
|
{
|
| 744 |
|
|
char *copy;
|
| 745 |
|
|
size_t len = strlen (name) + 1;
|
| 746 |
|
|
|
| 747 |
|
|
copy = (char *) alloca (len);
|
| 748 |
|
|
memcpy (copy, name, len);
|
| 749 |
|
|
name = tc_canonicalize_symbol_name (copy);
|
| 750 |
|
|
}
|
| 751 |
|
|
#endif
|
| 752 |
|
|
|
| 753 |
|
|
if (! symbols_case_sensitive)
|
| 754 |
|
|
{
|
| 755 |
|
|
char *copy;
|
| 756 |
|
|
const char *orig;
|
| 757 |
|
|
unsigned char c;
|
| 758 |
|
|
|
| 759 |
|
|
orig = name;
|
| 760 |
|
|
name = copy = (char *) alloca (strlen (name) + 1);
|
| 761 |
|
|
|
| 762 |
|
|
while ((c = *orig++) != '\0')
|
| 763 |
|
|
{
|
| 764 |
|
|
*copy++ = TOUPPER (c);
|
| 765 |
|
|
}
|
| 766 |
|
|
*copy = '\0';
|
| 767 |
|
|
}
|
| 768 |
|
|
|
| 769 |
|
|
return symbol_find_exact_noref (name, noref);
|
| 770 |
|
|
}
|
| 771 |
|
|
|
| 772 |
|
|
/* Once upon a time, symbols were kept in a singly linked list. At
|
| 773 |
|
|
least coff needs to be able to rearrange them from time to time, for
|
| 774 |
|
|
which a doubly linked list is much more convenient. Loic did these
|
| 775 |
|
|
as macros which seemed dangerous to me so they're now functions.
|
| 776 |
|
|
xoxorich. */
|
| 777 |
|
|
|
| 778 |
|
|
/* Link symbol ADDME after symbol TARGET in the chain. */
|
| 779 |
|
|
|
| 780 |
|
|
void
|
| 781 |
|
|
symbol_append (symbolS *addme, symbolS *target,
|
| 782 |
|
|
symbolS **rootPP, symbolS **lastPP)
|
| 783 |
|
|
{
|
| 784 |
|
|
if (LOCAL_SYMBOL_CHECK (addme))
|
| 785 |
|
|
abort ();
|
| 786 |
|
|
if (target != NULL && LOCAL_SYMBOL_CHECK (target))
|
| 787 |
|
|
abort ();
|
| 788 |
|
|
|
| 789 |
|
|
if (target == NULL)
|
| 790 |
|
|
{
|
| 791 |
|
|
know (*rootPP == NULL);
|
| 792 |
|
|
know (*lastPP == NULL);
|
| 793 |
|
|
addme->sy_next = NULL;
|
| 794 |
|
|
addme->sy_previous = NULL;
|
| 795 |
|
|
*rootPP = addme;
|
| 796 |
|
|
*lastPP = addme;
|
| 797 |
|
|
return;
|
| 798 |
|
|
} /* if the list is empty */
|
| 799 |
|
|
|
| 800 |
|
|
if (target->sy_next != NULL)
|
| 801 |
|
|
{
|
| 802 |
|
|
target->sy_next->sy_previous = addme;
|
| 803 |
|
|
}
|
| 804 |
|
|
else
|
| 805 |
|
|
{
|
| 806 |
|
|
know (*lastPP == target);
|
| 807 |
|
|
*lastPP = addme;
|
| 808 |
|
|
} /* if we have a next */
|
| 809 |
|
|
|
| 810 |
|
|
addme->sy_next = target->sy_next;
|
| 811 |
|
|
target->sy_next = addme;
|
| 812 |
|
|
addme->sy_previous = target;
|
| 813 |
|
|
|
| 814 |
|
|
debug_verify_symchain (symbol_rootP, symbol_lastP);
|
| 815 |
|
|
}
|
| 816 |
|
|
|
| 817 |
|
|
/* Set the chain pointers of SYMBOL to null. */
|
| 818 |
|
|
|
| 819 |
|
|
void
|
| 820 |
|
|
symbol_clear_list_pointers (symbolS *symbolP)
|
| 821 |
|
|
{
|
| 822 |
|
|
if (LOCAL_SYMBOL_CHECK (symbolP))
|
| 823 |
|
|
abort ();
|
| 824 |
|
|
symbolP->sy_next = NULL;
|
| 825 |
|
|
symbolP->sy_previous = NULL;
|
| 826 |
|
|
}
|
| 827 |
|
|
|
| 828 |
|
|
/* Remove SYMBOLP from the list. */
|
| 829 |
|
|
|
| 830 |
|
|
void
|
| 831 |
|
|
symbol_remove (symbolS *symbolP, symbolS **rootPP, symbolS **lastPP)
|
| 832 |
|
|
{
|
| 833 |
|
|
if (LOCAL_SYMBOL_CHECK (symbolP))
|
| 834 |
|
|
abort ();
|
| 835 |
|
|
|
| 836 |
|
|
if (symbolP == *rootPP)
|
| 837 |
|
|
{
|
| 838 |
|
|
*rootPP = symbolP->sy_next;
|
| 839 |
|
|
} /* if it was the root */
|
| 840 |
|
|
|
| 841 |
|
|
if (symbolP == *lastPP)
|
| 842 |
|
|
{
|
| 843 |
|
|
*lastPP = symbolP->sy_previous;
|
| 844 |
|
|
} /* if it was the tail */
|
| 845 |
|
|
|
| 846 |
|
|
if (symbolP->sy_next != NULL)
|
| 847 |
|
|
{
|
| 848 |
|
|
symbolP->sy_next->sy_previous = symbolP->sy_previous;
|
| 849 |
|
|
} /* if not last */
|
| 850 |
|
|
|
| 851 |
|
|
if (symbolP->sy_previous != NULL)
|
| 852 |
|
|
{
|
| 853 |
|
|
symbolP->sy_previous->sy_next = symbolP->sy_next;
|
| 854 |
|
|
} /* if not first */
|
| 855 |
|
|
|
| 856 |
|
|
debug_verify_symchain (*rootPP, *lastPP);
|
| 857 |
|
|
}
|
| 858 |
|
|
|
| 859 |
|
|
/* Link symbol ADDME before symbol TARGET in the chain. */
|
| 860 |
|
|
|
| 861 |
|
|
void
|
| 862 |
|
|
symbol_insert (symbolS *addme, symbolS *target,
|
| 863 |
|
|
symbolS **rootPP, symbolS **lastPP ATTRIBUTE_UNUSED)
|
| 864 |
|
|
{
|
| 865 |
|
|
if (LOCAL_SYMBOL_CHECK (addme))
|
| 866 |
|
|
abort ();
|
| 867 |
|
|
if (LOCAL_SYMBOL_CHECK (target))
|
| 868 |
|
|
abort ();
|
| 869 |
|
|
|
| 870 |
|
|
if (target->sy_previous != NULL)
|
| 871 |
|
|
{
|
| 872 |
|
|
target->sy_previous->sy_next = addme;
|
| 873 |
|
|
}
|
| 874 |
|
|
else
|
| 875 |
|
|
{
|
| 876 |
|
|
know (*rootPP == target);
|
| 877 |
|
|
*rootPP = addme;
|
| 878 |
|
|
} /* if not first */
|
| 879 |
|
|
|
| 880 |
|
|
addme->sy_previous = target->sy_previous;
|
| 881 |
|
|
target->sy_previous = addme;
|
| 882 |
|
|
addme->sy_next = target;
|
| 883 |
|
|
|
| 884 |
|
|
debug_verify_symchain (*rootPP, *lastPP);
|
| 885 |
|
|
}
|
| 886 |
|
|
|
| 887 |
|
|
void
|
| 888 |
|
|
verify_symbol_chain (symbolS *rootP, symbolS *lastP)
|
| 889 |
|
|
{
|
| 890 |
|
|
symbolS *symbolP = rootP;
|
| 891 |
|
|
|
| 892 |
|
|
if (symbolP == NULL)
|
| 893 |
|
|
return;
|
| 894 |
|
|
|
| 895 |
|
|
for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP))
|
| 896 |
|
|
{
|
| 897 |
|
|
gas_assert (symbolP->bsym != NULL);
|
| 898 |
|
|
gas_assert (symbolP->sy_next->sy_previous == symbolP);
|
| 899 |
|
|
}
|
| 900 |
|
|
|
| 901 |
|
|
gas_assert (lastP == symbolP);
|
| 902 |
|
|
}
|
| 903 |
|
|
|
| 904 |
|
|
#ifdef OBJ_COMPLEX_RELC
|
| 905 |
|
|
|
| 906 |
|
|
static int
|
| 907 |
|
|
use_complex_relocs_for (symbolS * symp)
|
| 908 |
|
|
{
|
| 909 |
|
|
switch (symp->sy_value.X_op)
|
| 910 |
|
|
{
|
| 911 |
|
|
case O_constant:
|
| 912 |
|
|
return 0;
|
| 913 |
|
|
|
| 914 |
|
|
case O_symbol:
|
| 915 |
|
|
case O_symbol_rva:
|
| 916 |
|
|
case O_uminus:
|
| 917 |
|
|
case O_bit_not:
|
| 918 |
|
|
case O_logical_not:
|
| 919 |
|
|
if ( (S_IS_COMMON (symp->sy_value.X_add_symbol)
|
| 920 |
|
|
|| S_IS_LOCAL (symp->sy_value.X_add_symbol))
|
| 921 |
|
|
&&
|
| 922 |
|
|
(S_IS_DEFINED (symp->sy_value.X_add_symbol)
|
| 923 |
|
|
&& S_GET_SEGMENT (symp->sy_value.X_add_symbol) != expr_section))
|
| 924 |
|
|
return 0;
|
| 925 |
|
|
break;
|
| 926 |
|
|
|
| 927 |
|
|
case O_multiply:
|
| 928 |
|
|
case O_divide:
|
| 929 |
|
|
case O_modulus:
|
| 930 |
|
|
case O_left_shift:
|
| 931 |
|
|
case O_right_shift:
|
| 932 |
|
|
case O_bit_inclusive_or:
|
| 933 |
|
|
case O_bit_or_not:
|
| 934 |
|
|
case O_bit_exclusive_or:
|
| 935 |
|
|
case O_bit_and:
|
| 936 |
|
|
case O_add:
|
| 937 |
|
|
case O_subtract:
|
| 938 |
|
|
case O_eq:
|
| 939 |
|
|
case O_ne:
|
| 940 |
|
|
case O_lt:
|
| 941 |
|
|
case O_le:
|
| 942 |
|
|
case O_ge:
|
| 943 |
|
|
case O_gt:
|
| 944 |
|
|
case O_logical_and:
|
| 945 |
|
|
case O_logical_or:
|
| 946 |
|
|
|
| 947 |
|
|
if ( (S_IS_COMMON (symp->sy_value.X_add_symbol)
|
| 948 |
|
|
|| S_IS_LOCAL (symp->sy_value.X_add_symbol))
|
| 949 |
|
|
&&
|
| 950 |
|
|
(S_IS_COMMON (symp->sy_value.X_op_symbol)
|
| 951 |
|
|
|| S_IS_LOCAL (symp->sy_value.X_op_symbol))
|
| 952 |
|
|
|
| 953 |
|
|
&& S_IS_DEFINED (symp->sy_value.X_add_symbol)
|
| 954 |
|
|
&& S_IS_DEFINED (symp->sy_value.X_op_symbol)
|
| 955 |
|
|
&& S_GET_SEGMENT (symp->sy_value.X_add_symbol) != expr_section
|
| 956 |
|
|
&& S_GET_SEGMENT (symp->sy_value.X_op_symbol) != expr_section)
|
| 957 |
|
|
return 0;
|
| 958 |
|
|
break;
|
| 959 |
|
|
|
| 960 |
|
|
default:
|
| 961 |
|
|
break;
|
| 962 |
|
|
}
|
| 963 |
|
|
return 1;
|
| 964 |
|
|
}
|
| 965 |
|
|
#endif
|
| 966 |
|
|
|
| 967 |
|
|
static void
|
| 968 |
|
|
report_op_error (symbolS *symp, symbolS *left, operatorT op, symbolS *right)
|
| 969 |
|
|
{
|
| 970 |
|
|
char *file;
|
| 971 |
|
|
unsigned int line;
|
| 972 |
|
|
segT seg_left = left ? S_GET_SEGMENT (left) : 0;
|
| 973 |
|
|
segT seg_right = S_GET_SEGMENT (right);
|
| 974 |
|
|
const char *opname;
|
| 975 |
|
|
|
| 976 |
|
|
switch (op)
|
| 977 |
|
|
{
|
| 978 |
|
|
default:
|
| 979 |
|
|
abort ();
|
| 980 |
|
|
return;
|
| 981 |
|
|
|
| 982 |
|
|
case O_uminus: opname = "-"; break;
|
| 983 |
|
|
case O_bit_not: opname = "~"; break;
|
| 984 |
|
|
case O_logical_not: opname = "!"; break;
|
| 985 |
|
|
case O_multiply: opname = "*"; break;
|
| 986 |
|
|
case O_divide: opname = "/"; break;
|
| 987 |
|
|
case O_modulus: opname = "%"; break;
|
| 988 |
|
|
case O_left_shift: opname = "<<"; break;
|
| 989 |
|
|
case O_right_shift: opname = ">>"; break;
|
| 990 |
|
|
case O_bit_inclusive_or: opname = "|"; break;
|
| 991 |
|
|
case O_bit_or_not: opname = "|~"; break;
|
| 992 |
|
|
case O_bit_exclusive_or: opname = "^"; break;
|
| 993 |
|
|
case O_bit_and: opname = "&"; break;
|
| 994 |
|
|
case O_add: opname = "+"; break;
|
| 995 |
|
|
case O_subtract: opname = "-"; break;
|
| 996 |
|
|
case O_eq: opname = "=="; break;
|
| 997 |
|
|
case O_ne: opname = "!="; break;
|
| 998 |
|
|
case O_lt: opname = "<"; break;
|
| 999 |
|
|
case O_le: opname = "<="; break;
|
| 1000 |
|
|
case O_ge: opname = ">="; break;
|
| 1001 |
|
|
case O_gt: opname = ">"; break;
|
| 1002 |
|
|
case O_logical_and: opname = "&&"; break;
|
| 1003 |
|
|
case O_logical_or: opname = "||"; break;
|
| 1004 |
|
|
}
|
| 1005 |
|
|
|
| 1006 |
|
|
if (expr_symbol_where (symp, &file, &line))
|
| 1007 |
|
|
{
|
| 1008 |
|
|
if (left)
|
| 1009 |
|
|
as_bad_where (file, line,
|
| 1010 |
|
|
_("invalid operands (%s and %s sections) for `%s'"),
|
| 1011 |
|
|
seg_left->name, seg_right->name, opname);
|
| 1012 |
|
|
else
|
| 1013 |
|
|
as_bad_where (file, line,
|
| 1014 |
|
|
_("invalid operand (%s section) for `%s'"),
|
| 1015 |
|
|
seg_right->name, opname);
|
| 1016 |
|
|
}
|
| 1017 |
|
|
else
|
| 1018 |
|
|
{
|
| 1019 |
|
|
const char *sname = S_GET_NAME (symp);
|
| 1020 |
|
|
|
| 1021 |
|
|
if (left)
|
| 1022 |
|
|
as_bad (_("invalid operands (%s and %s sections) for `%s' when setting `%s'"),
|
| 1023 |
|
|
seg_left->name, seg_right->name, opname, sname);
|
| 1024 |
|
|
else
|
| 1025 |
|
|
as_bad (_("invalid operand (%s section) for `%s' when setting `%s'"),
|
| 1026 |
|
|
seg_right->name, opname, sname);
|
| 1027 |
|
|
}
|
| 1028 |
|
|
}
|
| 1029 |
|
|
|
| 1030 |
|
|
/* Resolve the value of a symbol. This is called during the final
|
| 1031 |
|
|
pass over the symbol table to resolve any symbols with complex
|
| 1032 |
|
|
values. */
|
| 1033 |
|
|
|
| 1034 |
|
|
valueT
|
| 1035 |
|
|
resolve_symbol_value (symbolS *symp)
|
| 1036 |
|
|
{
|
| 1037 |
|
|
int resolved;
|
| 1038 |
|
|
valueT final_val = 0;
|
| 1039 |
|
|
segT final_seg;
|
| 1040 |
|
|
|
| 1041 |
|
|
if (LOCAL_SYMBOL_CHECK (symp))
|
| 1042 |
|
|
{
|
| 1043 |
|
|
struct local_symbol *locsym = (struct local_symbol *) symp;
|
| 1044 |
|
|
|
| 1045 |
|
|
final_val = locsym->lsy_value;
|
| 1046 |
|
|
if (local_symbol_resolved_p (locsym))
|
| 1047 |
|
|
return final_val;
|
| 1048 |
|
|
|
| 1049 |
|
|
final_val += local_symbol_get_frag (locsym)->fr_address / OCTETS_PER_BYTE;
|
| 1050 |
|
|
|
| 1051 |
|
|
if (finalize_syms)
|
| 1052 |
|
|
{
|
| 1053 |
|
|
locsym->lsy_value = final_val;
|
| 1054 |
|
|
local_symbol_mark_resolved (locsym);
|
| 1055 |
|
|
}
|
| 1056 |
|
|
|
| 1057 |
|
|
return final_val;
|
| 1058 |
|
|
}
|
| 1059 |
|
|
|
| 1060 |
|
|
if (symp->sy_resolved)
|
| 1061 |
|
|
{
|
| 1062 |
|
|
if (symp->sy_value.X_op == O_constant)
|
| 1063 |
|
|
return (valueT) symp->sy_value.X_add_number;
|
| 1064 |
|
|
else
|
| 1065 |
|
|
return 0;
|
| 1066 |
|
|
}
|
| 1067 |
|
|
|
| 1068 |
|
|
resolved = 0;
|
| 1069 |
|
|
final_seg = S_GET_SEGMENT (symp);
|
| 1070 |
|
|
|
| 1071 |
|
|
if (symp->sy_resolving)
|
| 1072 |
|
|
{
|
| 1073 |
|
|
if (finalize_syms)
|
| 1074 |
|
|
as_bad (_("symbol definition loop encountered at `%s'"),
|
| 1075 |
|
|
S_GET_NAME (symp));
|
| 1076 |
|
|
final_val = 0;
|
| 1077 |
|
|
resolved = 1;
|
| 1078 |
|
|
}
|
| 1079 |
|
|
#ifdef OBJ_COMPLEX_RELC
|
| 1080 |
|
|
else if (final_seg == expr_section
|
| 1081 |
|
|
&& use_complex_relocs_for (symp))
|
| 1082 |
|
|
{
|
| 1083 |
|
|
symbolS * relc_symbol = NULL;
|
| 1084 |
|
|
char * relc_symbol_name = NULL;
|
| 1085 |
|
|
|
| 1086 |
|
|
relc_symbol_name = symbol_relc_make_expr (& symp->sy_value);
|
| 1087 |
|
|
|
| 1088 |
|
|
/* For debugging, print out conversion input & output. */
|
| 1089 |
|
|
#ifdef DEBUG_SYMS
|
| 1090 |
|
|
print_expr (& symp->sy_value);
|
| 1091 |
|
|
if (relc_symbol_name)
|
| 1092 |
|
|
fprintf (stderr, "-> relc symbol: %s\n", relc_symbol_name);
|
| 1093 |
|
|
#endif
|
| 1094 |
|
|
|
| 1095 |
|
|
if (relc_symbol_name != NULL)
|
| 1096 |
|
|
relc_symbol = symbol_new (relc_symbol_name, undefined_section,
|
| 1097 |
|
|
0, & zero_address_frag);
|
| 1098 |
|
|
|
| 1099 |
|
|
if (relc_symbol == NULL)
|
| 1100 |
|
|
{
|
| 1101 |
|
|
as_bad (_("cannot convert expression symbol %s to complex relocation"),
|
| 1102 |
|
|
S_GET_NAME (symp));
|
| 1103 |
|
|
resolved = 0;
|
| 1104 |
|
|
}
|
| 1105 |
|
|
else
|
| 1106 |
|
|
{
|
| 1107 |
|
|
symbol_table_insert (relc_symbol);
|
| 1108 |
|
|
|
| 1109 |
|
|
/* S_CLEAR_EXTERNAL (relc_symbol); */
|
| 1110 |
|
|
if (symp->bsym->flags & BSF_SRELC)
|
| 1111 |
|
|
relc_symbol->bsym->flags |= BSF_SRELC;
|
| 1112 |
|
|
else
|
| 1113 |
|
|
relc_symbol->bsym->flags |= BSF_RELC;
|
| 1114 |
|
|
/* symp->bsym->flags |= BSF_RELC; */
|
| 1115 |
|
|
copy_symbol_attributes (symp, relc_symbol);
|
| 1116 |
|
|
symp->sy_value.X_op = O_symbol;
|
| 1117 |
|
|
symp->sy_value.X_add_symbol = relc_symbol;
|
| 1118 |
|
|
symp->sy_value.X_add_number = 0;
|
| 1119 |
|
|
resolved = 1;
|
| 1120 |
|
|
}
|
| 1121 |
|
|
|
| 1122 |
|
|
final_seg = undefined_section;
|
| 1123 |
|
|
goto exit_dont_set_value;
|
| 1124 |
|
|
}
|
| 1125 |
|
|
#endif
|
| 1126 |
|
|
else
|
| 1127 |
|
|
{
|
| 1128 |
|
|
symbolS *add_symbol, *op_symbol;
|
| 1129 |
|
|
offsetT left, right;
|
| 1130 |
|
|
segT seg_left, seg_right;
|
| 1131 |
|
|
operatorT op;
|
| 1132 |
|
|
int move_seg_ok;
|
| 1133 |
|
|
|
| 1134 |
|
|
symp->sy_resolving = 1;
|
| 1135 |
|
|
|
| 1136 |
|
|
/* Help out with CSE. */
|
| 1137 |
|
|
add_symbol = symp->sy_value.X_add_symbol;
|
| 1138 |
|
|
op_symbol = symp->sy_value.X_op_symbol;
|
| 1139 |
|
|
final_val = symp->sy_value.X_add_number;
|
| 1140 |
|
|
op = symp->sy_value.X_op;
|
| 1141 |
|
|
|
| 1142 |
|
|
switch (op)
|
| 1143 |
|
|
{
|
| 1144 |
|
|
default:
|
| 1145 |
|
|
BAD_CASE (op);
|
| 1146 |
|
|
break;
|
| 1147 |
|
|
|
| 1148 |
|
|
case O_absent:
|
| 1149 |
|
|
final_val = 0;
|
| 1150 |
|
|
/* Fall through. */
|
| 1151 |
|
|
|
| 1152 |
|
|
case O_constant:
|
| 1153 |
|
|
final_val += symp->sy_frag->fr_address / OCTETS_PER_BYTE;
|
| 1154 |
|
|
if (final_seg == expr_section)
|
| 1155 |
|
|
final_seg = absolute_section;
|
| 1156 |
|
|
/* Fall through. */
|
| 1157 |
|
|
|
| 1158 |
|
|
case O_register:
|
| 1159 |
|
|
resolved = 1;
|
| 1160 |
|
|
break;
|
| 1161 |
|
|
|
| 1162 |
|
|
case O_symbol:
|
| 1163 |
|
|
case O_symbol_rva:
|
| 1164 |
|
|
left = resolve_symbol_value (add_symbol);
|
| 1165 |
|
|
seg_left = S_GET_SEGMENT (add_symbol);
|
| 1166 |
|
|
if (finalize_syms)
|
| 1167 |
|
|
symp->sy_value.X_op_symbol = NULL;
|
| 1168 |
|
|
|
| 1169 |
|
|
do_symbol:
|
| 1170 |
|
|
if (S_IS_WEAKREFR (symp))
|
| 1171 |
|
|
{
|
| 1172 |
|
|
gas_assert (final_val == 0);
|
| 1173 |
|
|
if (S_IS_WEAKREFR (add_symbol))
|
| 1174 |
|
|
{
|
| 1175 |
|
|
gas_assert (add_symbol->sy_value.X_op == O_symbol
|
| 1176 |
|
|
&& add_symbol->sy_value.X_add_number == 0);
|
| 1177 |
|
|
add_symbol = add_symbol->sy_value.X_add_symbol;
|
| 1178 |
|
|
gas_assert (! S_IS_WEAKREFR (add_symbol));
|
| 1179 |
|
|
symp->sy_value.X_add_symbol = add_symbol;
|
| 1180 |
|
|
}
|
| 1181 |
|
|
}
|
| 1182 |
|
|
|
| 1183 |
|
|
if (symp->sy_mri_common)
|
| 1184 |
|
|
{
|
| 1185 |
|
|
/* This is a symbol inside an MRI common section. The
|
| 1186 |
|
|
relocation routines are going to handle it specially.
|
| 1187 |
|
|
Don't change the value. */
|
| 1188 |
|
|
resolved = symbol_resolved_p (add_symbol);
|
| 1189 |
|
|
break;
|
| 1190 |
|
|
}
|
| 1191 |
|
|
|
| 1192 |
|
|
if (finalize_syms && final_val == 0)
|
| 1193 |
|
|
{
|
| 1194 |
|
|
if (LOCAL_SYMBOL_CHECK (add_symbol))
|
| 1195 |
|
|
add_symbol = local_symbol_convert ((struct local_symbol *)
|
| 1196 |
|
|
add_symbol);
|
| 1197 |
|
|
copy_symbol_attributes (symp, add_symbol);
|
| 1198 |
|
|
}
|
| 1199 |
|
|
|
| 1200 |
|
|
/* If we have equated this symbol to an undefined or common
|
| 1201 |
|
|
symbol, keep X_op set to O_symbol, and don't change
|
| 1202 |
|
|
X_add_number. This permits the routine which writes out
|
| 1203 |
|
|
relocation to detect this case, and convert the
|
| 1204 |
|
|
relocation to be against the symbol to which this symbol
|
| 1205 |
|
|
is equated. */
|
| 1206 |
|
|
if (! S_IS_DEFINED (add_symbol)
|
| 1207 |
|
|
#if defined (OBJ_COFF) && defined (TE_PE)
|
| 1208 |
|
|
|| S_IS_WEAK (add_symbol)
|
| 1209 |
|
|
#endif
|
| 1210 |
|
|
|| S_IS_COMMON (add_symbol))
|
| 1211 |
|
|
{
|
| 1212 |
|
|
if (finalize_syms)
|
| 1213 |
|
|
{
|
| 1214 |
|
|
symp->sy_value.X_op = O_symbol;
|
| 1215 |
|
|
symp->sy_value.X_add_symbol = add_symbol;
|
| 1216 |
|
|
symp->sy_value.X_add_number = final_val;
|
| 1217 |
|
|
/* Use X_op_symbol as a flag. */
|
| 1218 |
|
|
symp->sy_value.X_op_symbol = add_symbol;
|
| 1219 |
|
|
}
|
| 1220 |
|
|
final_seg = seg_left;
|
| 1221 |
|
|
final_val = 0;
|
| 1222 |
|
|
resolved = symbol_resolved_p (add_symbol);
|
| 1223 |
|
|
symp->sy_resolving = 0;
|
| 1224 |
|
|
goto exit_dont_set_value;
|
| 1225 |
|
|
}
|
| 1226 |
|
|
else if (finalize_syms
|
| 1227 |
|
|
&& ((final_seg == expr_section && seg_left != expr_section)
|
| 1228 |
|
|
|| symbol_shadow_p (symp)))
|
| 1229 |
|
|
{
|
| 1230 |
|
|
/* If the symbol is an expression symbol, do similarly
|
| 1231 |
|
|
as for undefined and common syms above. Handles
|
| 1232 |
|
|
"sym +/- expr" where "expr" cannot be evaluated
|
| 1233 |
|
|
immediately, and we want relocations to be against
|
| 1234 |
|
|
"sym", eg. because it is weak. */
|
| 1235 |
|
|
symp->sy_value.X_op = O_symbol;
|
| 1236 |
|
|
symp->sy_value.X_add_symbol = add_symbol;
|
| 1237 |
|
|
symp->sy_value.X_add_number = final_val;
|
| 1238 |
|
|
symp->sy_value.X_op_symbol = add_symbol;
|
| 1239 |
|
|
final_seg = seg_left;
|
| 1240 |
|
|
final_val += symp->sy_frag->fr_address + left;
|
| 1241 |
|
|
resolved = symbol_resolved_p (add_symbol);
|
| 1242 |
|
|
symp->sy_resolving = 0;
|
| 1243 |
|
|
goto exit_dont_set_value;
|
| 1244 |
|
|
}
|
| 1245 |
|
|
else
|
| 1246 |
|
|
{
|
| 1247 |
|
|
final_val += symp->sy_frag->fr_address + left;
|
| 1248 |
|
|
if (final_seg == expr_section || final_seg == undefined_section)
|
| 1249 |
|
|
final_seg = seg_left;
|
| 1250 |
|
|
}
|
| 1251 |
|
|
|
| 1252 |
|
|
resolved = symbol_resolved_p (add_symbol);
|
| 1253 |
|
|
if (S_IS_WEAKREFR (symp))
|
| 1254 |
|
|
goto exit_dont_set_value;
|
| 1255 |
|
|
break;
|
| 1256 |
|
|
|
| 1257 |
|
|
case O_uminus:
|
| 1258 |
|
|
case O_bit_not:
|
| 1259 |
|
|
case O_logical_not:
|
| 1260 |
|
|
left = resolve_symbol_value (add_symbol);
|
| 1261 |
|
|
seg_left = S_GET_SEGMENT (add_symbol);
|
| 1262 |
|
|
|
| 1263 |
|
|
/* By reducing these to the relevant dyadic operator, we get
|
| 1264 |
|
|
!S -> S == 0 permitted on anything,
|
| 1265 |
|
|
-S -> 0 - S only permitted on absolute
|
| 1266 |
|
|
~S -> S ^ ~0 only permitted on absolute */
|
| 1267 |
|
|
if (op != O_logical_not && seg_left != absolute_section
|
| 1268 |
|
|
&& finalize_syms)
|
| 1269 |
|
|
report_op_error (symp, NULL, op, add_symbol);
|
| 1270 |
|
|
|
| 1271 |
|
|
if (final_seg == expr_section || final_seg == undefined_section)
|
| 1272 |
|
|
final_seg = absolute_section;
|
| 1273 |
|
|
|
| 1274 |
|
|
if (op == O_uminus)
|
| 1275 |
|
|
left = -left;
|
| 1276 |
|
|
else if (op == O_logical_not)
|
| 1277 |
|
|
left = !left;
|
| 1278 |
|
|
else
|
| 1279 |
|
|
left = ~left;
|
| 1280 |
|
|
|
| 1281 |
|
|
final_val += left + symp->sy_frag->fr_address;
|
| 1282 |
|
|
|
| 1283 |
|
|
resolved = symbol_resolved_p (add_symbol);
|
| 1284 |
|
|
break;
|
| 1285 |
|
|
|
| 1286 |
|
|
case O_multiply:
|
| 1287 |
|
|
case O_divide:
|
| 1288 |
|
|
case O_modulus:
|
| 1289 |
|
|
case O_left_shift:
|
| 1290 |
|
|
case O_right_shift:
|
| 1291 |
|
|
case O_bit_inclusive_or:
|
| 1292 |
|
|
case O_bit_or_not:
|
| 1293 |
|
|
case O_bit_exclusive_or:
|
| 1294 |
|
|
case O_bit_and:
|
| 1295 |
|
|
case O_add:
|
| 1296 |
|
|
case O_subtract:
|
| 1297 |
|
|
case O_eq:
|
| 1298 |
|
|
case O_ne:
|
| 1299 |
|
|
case O_lt:
|
| 1300 |
|
|
case O_le:
|
| 1301 |
|
|
case O_ge:
|
| 1302 |
|
|
case O_gt:
|
| 1303 |
|
|
case O_logical_and:
|
| 1304 |
|
|
case O_logical_or:
|
| 1305 |
|
|
left = resolve_symbol_value (add_symbol);
|
| 1306 |
|
|
right = resolve_symbol_value (op_symbol);
|
| 1307 |
|
|
seg_left = S_GET_SEGMENT (add_symbol);
|
| 1308 |
|
|
seg_right = S_GET_SEGMENT (op_symbol);
|
| 1309 |
|
|
|
| 1310 |
|
|
/* Simplify addition or subtraction of a constant by folding the
|
| 1311 |
|
|
constant into X_add_number. */
|
| 1312 |
|
|
if (op == O_add)
|
| 1313 |
|
|
{
|
| 1314 |
|
|
if (seg_right == absolute_section)
|
| 1315 |
|
|
{
|
| 1316 |
|
|
final_val += right;
|
| 1317 |
|
|
goto do_symbol;
|
| 1318 |
|
|
}
|
| 1319 |
|
|
else if (seg_left == absolute_section)
|
| 1320 |
|
|
{
|
| 1321 |
|
|
final_val += left;
|
| 1322 |
|
|
add_symbol = op_symbol;
|
| 1323 |
|
|
left = right;
|
| 1324 |
|
|
seg_left = seg_right;
|
| 1325 |
|
|
goto do_symbol;
|
| 1326 |
|
|
}
|
| 1327 |
|
|
}
|
| 1328 |
|
|
else if (op == O_subtract)
|
| 1329 |
|
|
{
|
| 1330 |
|
|
if (seg_right == absolute_section)
|
| 1331 |
|
|
{
|
| 1332 |
|
|
final_val -= right;
|
| 1333 |
|
|
goto do_symbol;
|
| 1334 |
|
|
}
|
| 1335 |
|
|
}
|
| 1336 |
|
|
|
| 1337 |
|
|
move_seg_ok = 1;
|
| 1338 |
|
|
/* Equality and non-equality tests are permitted on anything.
|
| 1339 |
|
|
Subtraction, and other comparison operators are permitted if
|
| 1340 |
|
|
both operands are in the same section. Otherwise, both
|
| 1341 |
|
|
operands must be absolute. We already handled the case of
|
| 1342 |
|
|
addition or subtraction of a constant above. This will
|
| 1343 |
|
|
probably need to be changed for an object file format which
|
| 1344 |
|
|
supports arbitrary expressions, such as IEEE-695. */
|
| 1345 |
|
|
if (!(seg_left == absolute_section
|
| 1346 |
|
|
&& seg_right == absolute_section)
|
| 1347 |
|
|
&& !(op == O_eq || op == O_ne)
|
| 1348 |
|
|
&& !((op == O_subtract
|
| 1349 |
|
|
|| op == O_lt || op == O_le || op == O_ge || op == O_gt)
|
| 1350 |
|
|
&& seg_left == seg_right
|
| 1351 |
|
|
&& (seg_left != undefined_section
|
| 1352 |
|
|
|| add_symbol == op_symbol)))
|
| 1353 |
|
|
{
|
| 1354 |
|
|
/* Don't emit messages unless we're finalizing the symbol value,
|
| 1355 |
|
|
otherwise we may get the same message multiple times. */
|
| 1356 |
|
|
if (finalize_syms)
|
| 1357 |
|
|
report_op_error (symp, add_symbol, op, op_symbol);
|
| 1358 |
|
|
/* However do not move the symbol into the absolute section
|
| 1359 |
|
|
if it cannot currently be resolved - this would confuse
|
| 1360 |
|
|
other parts of the assembler into believing that the
|
| 1361 |
|
|
expression had been evaluated to zero. */
|
| 1362 |
|
|
else
|
| 1363 |
|
|
move_seg_ok = 0;
|
| 1364 |
|
|
}
|
| 1365 |
|
|
|
| 1366 |
|
|
if (move_seg_ok
|
| 1367 |
|
|
&& (final_seg == expr_section || final_seg == undefined_section))
|
| 1368 |
|
|
final_seg = absolute_section;
|
| 1369 |
|
|
|
| 1370 |
|
|
/* Check for division by zero. */
|
| 1371 |
|
|
if ((op == O_divide || op == O_modulus) && right == 0)
|
| 1372 |
|
|
{
|
| 1373 |
|
|
/* If seg_right is not absolute_section, then we've
|
| 1374 |
|
|
already issued a warning about using a bad symbol. */
|
| 1375 |
|
|
if (seg_right == absolute_section && finalize_syms)
|
| 1376 |
|
|
{
|
| 1377 |
|
|
char *file;
|
| 1378 |
|
|
unsigned int line;
|
| 1379 |
|
|
|
| 1380 |
|
|
if (expr_symbol_where (symp, &file, &line))
|
| 1381 |
|
|
as_bad_where (file, line, _("division by zero"));
|
| 1382 |
|
|
else
|
| 1383 |
|
|
as_bad (_("division by zero when setting `%s'"),
|
| 1384 |
|
|
S_GET_NAME (symp));
|
| 1385 |
|
|
}
|
| 1386 |
|
|
|
| 1387 |
|
|
right = 1;
|
| 1388 |
|
|
}
|
| 1389 |
|
|
|
| 1390 |
|
|
switch (symp->sy_value.X_op)
|
| 1391 |
|
|
{
|
| 1392 |
|
|
case O_multiply: left *= right; break;
|
| 1393 |
|
|
case O_divide: left /= right; break;
|
| 1394 |
|
|
case O_modulus: left %= right; break;
|
| 1395 |
|
|
case O_left_shift: left <<= right; break;
|
| 1396 |
|
|
case O_right_shift: left >>= right; break;
|
| 1397 |
|
|
case O_bit_inclusive_or: left |= right; break;
|
| 1398 |
|
|
case O_bit_or_not: left |= ~right; break;
|
| 1399 |
|
|
case O_bit_exclusive_or: left ^= right; break;
|
| 1400 |
|
|
case O_bit_and: left &= right; break;
|
| 1401 |
|
|
case O_add: left += right; break;
|
| 1402 |
|
|
case O_subtract: left -= right; break;
|
| 1403 |
|
|
case O_eq:
|
| 1404 |
|
|
case O_ne:
|
| 1405 |
|
|
left = (left == right && seg_left == seg_right
|
| 1406 |
|
|
&& (seg_left != undefined_section
|
| 1407 |
|
|
|| add_symbol == op_symbol)
|
| 1408 |
|
|
? ~ (offsetT) 0 : 0);
|
| 1409 |
|
|
if (symp->sy_value.X_op == O_ne)
|
| 1410 |
|
|
left = ~left;
|
| 1411 |
|
|
break;
|
| 1412 |
|
|
case O_lt: left = left < right ? ~ (offsetT) 0 : 0; break;
|
| 1413 |
|
|
case O_le: left = left <= right ? ~ (offsetT) 0 : 0; break;
|
| 1414 |
|
|
case O_ge: left = left >= right ? ~ (offsetT) 0 : 0; break;
|
| 1415 |
|
|
case O_gt: left = left > right ? ~ (offsetT) 0 : 0; break;
|
| 1416 |
|
|
case O_logical_and: left = left && right; break;
|
| 1417 |
|
|
case O_logical_or: left = left || right; break;
|
| 1418 |
|
|
default: abort ();
|
| 1419 |
|
|
}
|
| 1420 |
|
|
|
| 1421 |
|
|
final_val += symp->sy_frag->fr_address + left;
|
| 1422 |
|
|
if (final_seg == expr_section || final_seg == undefined_section)
|
| 1423 |
|
|
{
|
| 1424 |
|
|
if (seg_left == undefined_section
|
| 1425 |
|
|
|| seg_right == undefined_section)
|
| 1426 |
|
|
final_seg = undefined_section;
|
| 1427 |
|
|
else if (seg_left == absolute_section)
|
| 1428 |
|
|
final_seg = seg_right;
|
| 1429 |
|
|
else
|
| 1430 |
|
|
final_seg = seg_left;
|
| 1431 |
|
|
}
|
| 1432 |
|
|
resolved = (symbol_resolved_p (add_symbol)
|
| 1433 |
|
|
&& symbol_resolved_p (op_symbol));
|
| 1434 |
|
|
break;
|
| 1435 |
|
|
|
| 1436 |
|
|
case O_big:
|
| 1437 |
|
|
case O_illegal:
|
| 1438 |
|
|
/* Give an error (below) if not in expr_section. We don't
|
| 1439 |
|
|
want to worry about expr_section symbols, because they
|
| 1440 |
|
|
are fictional (they are created as part of expression
|
| 1441 |
|
|
resolution), and any problems may not actually mean
|
| 1442 |
|
|
anything. */
|
| 1443 |
|
|
break;
|
| 1444 |
|
|
}
|
| 1445 |
|
|
|
| 1446 |
|
|
symp->sy_resolving = 0;
|
| 1447 |
|
|
}
|
| 1448 |
|
|
|
| 1449 |
|
|
if (finalize_syms)
|
| 1450 |
|
|
S_SET_VALUE (symp, final_val);
|
| 1451 |
|
|
|
| 1452 |
|
|
exit_dont_set_value:
|
| 1453 |
|
|
/* Always set the segment, even if not finalizing the value.
|
| 1454 |
|
|
The segment is used to determine whether a symbol is defined. */
|
| 1455 |
|
|
S_SET_SEGMENT (symp, final_seg);
|
| 1456 |
|
|
|
| 1457 |
|
|
/* Don't worry if we can't resolve an expr_section symbol. */
|
| 1458 |
|
|
if (finalize_syms)
|
| 1459 |
|
|
{
|
| 1460 |
|
|
if (resolved)
|
| 1461 |
|
|
symp->sy_resolved = 1;
|
| 1462 |
|
|
else if (S_GET_SEGMENT (symp) != expr_section)
|
| 1463 |
|
|
{
|
| 1464 |
|
|
as_bad (_("can't resolve value for symbol `%s'"),
|
| 1465 |
|
|
S_GET_NAME (symp));
|
| 1466 |
|
|
symp->sy_resolved = 1;
|
| 1467 |
|
|
}
|
| 1468 |
|
|
}
|
| 1469 |
|
|
|
| 1470 |
|
|
return final_val;
|
| 1471 |
|
|
}
|
| 1472 |
|
|
|
| 1473 |
|
|
static void resolve_local_symbol (const char *, void *);
|
| 1474 |
|
|
|
| 1475 |
|
|
/* A static function passed to hash_traverse. */
|
| 1476 |
|
|
|
| 1477 |
|
|
static void
|
| 1478 |
|
|
resolve_local_symbol (const char *key ATTRIBUTE_UNUSED, void *value)
|
| 1479 |
|
|
{
|
| 1480 |
|
|
if (value != NULL)
|
| 1481 |
|
|
resolve_symbol_value ((symbolS *) value);
|
| 1482 |
|
|
}
|
| 1483 |
|
|
|
| 1484 |
|
|
/* Resolve all local symbols. */
|
| 1485 |
|
|
|
| 1486 |
|
|
void
|
| 1487 |
|
|
resolve_local_symbol_values (void)
|
| 1488 |
|
|
{
|
| 1489 |
|
|
hash_traverse (local_hash, resolve_local_symbol);
|
| 1490 |
|
|
}
|
| 1491 |
|
|
|
| 1492 |
|
|
/* Obtain the current value of a symbol without changing any
|
| 1493 |
|
|
sub-expressions used. */
|
| 1494 |
|
|
|
| 1495 |
|
|
int
|
| 1496 |
|
|
snapshot_symbol (symbolS **symbolPP, valueT *valueP, segT *segP, fragS **fragPP)
|
| 1497 |
|
|
{
|
| 1498 |
|
|
symbolS *symbolP = *symbolPP;
|
| 1499 |
|
|
|
| 1500 |
|
|
if (LOCAL_SYMBOL_CHECK (symbolP))
|
| 1501 |
|
|
{
|
| 1502 |
|
|
struct local_symbol *locsym = (struct local_symbol *) symbolP;
|
| 1503 |
|
|
|
| 1504 |
|
|
*valueP = locsym->lsy_value;
|
| 1505 |
|
|
*segP = locsym->lsy_section;
|
| 1506 |
|
|
*fragPP = local_symbol_get_frag (locsym);
|
| 1507 |
|
|
}
|
| 1508 |
|
|
else
|
| 1509 |
|
|
{
|
| 1510 |
|
|
expressionS exp = symbolP->sy_value;
|
| 1511 |
|
|
|
| 1512 |
|
|
if (!symbolP->sy_resolved && exp.X_op != O_illegal)
|
| 1513 |
|
|
{
|
| 1514 |
|
|
int resolved;
|
| 1515 |
|
|
|
| 1516 |
|
|
if (symbolP->sy_resolving)
|
| 1517 |
|
|
return 0;
|
| 1518 |
|
|
symbolP->sy_resolving = 1;
|
| 1519 |
|
|
resolved = resolve_expression (&exp);
|
| 1520 |
|
|
symbolP->sy_resolving = 0;
|
| 1521 |
|
|
if (!resolved)
|
| 1522 |
|
|
return 0;
|
| 1523 |
|
|
|
| 1524 |
|
|
switch (exp.X_op)
|
| 1525 |
|
|
{
|
| 1526 |
|
|
case O_constant:
|
| 1527 |
|
|
case O_register:
|
| 1528 |
|
|
if (!symbol_equated_p (symbolP))
|
| 1529 |
|
|
break;
|
| 1530 |
|
|
/* Fall thru. */
|
| 1531 |
|
|
case O_symbol:
|
| 1532 |
|
|
case O_symbol_rva:
|
| 1533 |
|
|
symbolP = exp.X_add_symbol;
|
| 1534 |
|
|
break;
|
| 1535 |
|
|
default:
|
| 1536 |
|
|
return 0;
|
| 1537 |
|
|
}
|
| 1538 |
|
|
}
|
| 1539 |
|
|
|
| 1540 |
|
|
*symbolPP = symbolP;
|
| 1541 |
|
|
*valueP = exp.X_add_number;
|
| 1542 |
|
|
*segP = symbolP->bsym->section;
|
| 1543 |
|
|
*fragPP = symbolP->sy_frag;
|
| 1544 |
|
|
|
| 1545 |
|
|
if (*segP == expr_section)
|
| 1546 |
|
|
switch (exp.X_op)
|
| 1547 |
|
|
{
|
| 1548 |
|
|
case O_constant: *segP = absolute_section; break;
|
| 1549 |
|
|
case O_register: *segP = reg_section; break;
|
| 1550 |
|
|
default: break;
|
| 1551 |
|
|
}
|
| 1552 |
|
|
}
|
| 1553 |
|
|
|
| 1554 |
|
|
return 1;
|
| 1555 |
|
|
}
|
| 1556 |
|
|
|
| 1557 |
|
|
/* Dollar labels look like a number followed by a dollar sign. Eg, "42$".
|
| 1558 |
|
|
They are *really* local. That is, they go out of scope whenever we see a
|
| 1559 |
|
|
label that isn't local. Also, like fb labels, there can be multiple
|
| 1560 |
|
|
instances of a dollar label. Therefor, we name encode each instance with
|
| 1561 |
|
|
the instance number, keep a list of defined symbols separate from the real
|
| 1562 |
|
|
symbol table, and we treat these buggers as a sparse array. */
|
| 1563 |
|
|
|
| 1564 |
|
|
static long *dollar_labels;
|
| 1565 |
|
|
static long *dollar_label_instances;
|
| 1566 |
|
|
static char *dollar_label_defines;
|
| 1567 |
|
|
static unsigned long dollar_label_count;
|
| 1568 |
|
|
static unsigned long dollar_label_max;
|
| 1569 |
|
|
|
| 1570 |
|
|
int
|
| 1571 |
|
|
dollar_label_defined (long label)
|
| 1572 |
|
|
{
|
| 1573 |
|
|
long *i;
|
| 1574 |
|
|
|
| 1575 |
|
|
know ((dollar_labels != NULL) || (dollar_label_count == 0));
|
| 1576 |
|
|
|
| 1577 |
|
|
for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
|
| 1578 |
|
|
if (*i == label)
|
| 1579 |
|
|
return dollar_label_defines[i - dollar_labels];
|
| 1580 |
|
|
|
| 1581 |
|
|
/* If we get here, label isn't defined. */
|
| 1582 |
|
|
return 0;
|
| 1583 |
|
|
}
|
| 1584 |
|
|
|
| 1585 |
|
|
static long
|
| 1586 |
|
|
dollar_label_instance (long label)
|
| 1587 |
|
|
{
|
| 1588 |
|
|
long *i;
|
| 1589 |
|
|
|
| 1590 |
|
|
know ((dollar_labels != NULL) || (dollar_label_count == 0));
|
| 1591 |
|
|
|
| 1592 |
|
|
for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
|
| 1593 |
|
|
if (*i == label)
|
| 1594 |
|
|
return (dollar_label_instances[i - dollar_labels]);
|
| 1595 |
|
|
|
| 1596 |
|
|
/* If we get here, we haven't seen the label before.
|
| 1597 |
|
|
Therefore its instance count is zero. */
|
| 1598 |
|
|
return 0;
|
| 1599 |
|
|
}
|
| 1600 |
|
|
|
| 1601 |
|
|
void
|
| 1602 |
|
|
dollar_label_clear (void)
|
| 1603 |
|
|
{
|
| 1604 |
|
|
memset (dollar_label_defines, '\0', (unsigned int) dollar_label_count);
|
| 1605 |
|
|
}
|
| 1606 |
|
|
|
| 1607 |
|
|
#define DOLLAR_LABEL_BUMP_BY 10
|
| 1608 |
|
|
|
| 1609 |
|
|
void
|
| 1610 |
|
|
define_dollar_label (long label)
|
| 1611 |
|
|
{
|
| 1612 |
|
|
long *i;
|
| 1613 |
|
|
|
| 1614 |
|
|
for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
|
| 1615 |
|
|
if (*i == label)
|
| 1616 |
|
|
{
|
| 1617 |
|
|
++dollar_label_instances[i - dollar_labels];
|
| 1618 |
|
|
dollar_label_defines[i - dollar_labels] = 1;
|
| 1619 |
|
|
return;
|
| 1620 |
|
|
}
|
| 1621 |
|
|
|
| 1622 |
|
|
/* If we get to here, we don't have label listed yet. */
|
| 1623 |
|
|
|
| 1624 |
|
|
if (dollar_labels == NULL)
|
| 1625 |
|
|
{
|
| 1626 |
|
|
dollar_labels = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
|
| 1627 |
|
|
dollar_label_instances = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
|
| 1628 |
|
|
dollar_label_defines = (char *) xmalloc (DOLLAR_LABEL_BUMP_BY);
|
| 1629 |
|
|
dollar_label_max = DOLLAR_LABEL_BUMP_BY;
|
| 1630 |
|
|
dollar_label_count = 0;
|
| 1631 |
|
|
}
|
| 1632 |
|
|
else if (dollar_label_count == dollar_label_max)
|
| 1633 |
|
|
{
|
| 1634 |
|
|
dollar_label_max += DOLLAR_LABEL_BUMP_BY;
|
| 1635 |
|
|
dollar_labels = (long *) xrealloc ((char *) dollar_labels,
|
| 1636 |
|
|
dollar_label_max * sizeof (long));
|
| 1637 |
|
|
dollar_label_instances = (long *) xrealloc ((char *) dollar_label_instances,
|
| 1638 |
|
|
dollar_label_max * sizeof (long));
|
| 1639 |
|
|
dollar_label_defines = (char *) xrealloc (dollar_label_defines, dollar_label_max);
|
| 1640 |
|
|
} /* if we needed to grow */
|
| 1641 |
|
|
|
| 1642 |
|
|
dollar_labels[dollar_label_count] = label;
|
| 1643 |
|
|
dollar_label_instances[dollar_label_count] = 1;
|
| 1644 |
|
|
dollar_label_defines[dollar_label_count] = 1;
|
| 1645 |
|
|
++dollar_label_count;
|
| 1646 |
|
|
}
|
| 1647 |
|
|
|
| 1648 |
|
|
/* Caller must copy returned name: we re-use the area for the next name.
|
| 1649 |
|
|
|
| 1650 |
|
|
The mth occurence of label n: is turned into the symbol "Ln^Am"
|
| 1651 |
|
|
where n is the label number and m is the instance number. "L" makes
|
| 1652 |
|
|
it a label discarded unless debugging and "^A"('\1') ensures no
|
| 1653 |
|
|
ordinary symbol SHOULD get the same name as a local label
|
| 1654 |
|
|
symbol. The first "4:" is "L4^A1" - the m numbers begin at 1.
|
| 1655 |
|
|
|
| 1656 |
|
|
fb labels get the same treatment, except that ^B is used in place
|
| 1657 |
|
|
of ^A. */
|
| 1658 |
|
|
|
| 1659 |
|
|
char * /* Return local label name. */
|
| 1660 |
|
|
dollar_label_name (register long n, /* we just saw "n$:" : n a number. */
|
| 1661 |
|
|
register int augend /* 0 for current instance, 1 for new instance. */)
|
| 1662 |
|
|
{
|
| 1663 |
|
|
long i;
|
| 1664 |
|
|
/* Returned to caller, then copied. Used for created names ("4f"). */
|
| 1665 |
|
|
static char symbol_name_build[24];
|
| 1666 |
|
|
register char *p;
|
| 1667 |
|
|
register char *q;
|
| 1668 |
|
|
char symbol_name_temporary[20]; /* Build up a number, BACKWARDS. */
|
| 1669 |
|
|
|
| 1670 |
|
|
know (n >= 0);
|
| 1671 |
|
|
know (augend == 0 || augend == 1);
|
| 1672 |
|
|
p = symbol_name_build;
|
| 1673 |
|
|
#ifdef LOCAL_LABEL_PREFIX
|
| 1674 |
|
|
*p++ = LOCAL_LABEL_PREFIX;
|
| 1675 |
|
|
#endif
|
| 1676 |
|
|
*p++ = 'L';
|
| 1677 |
|
|
|
| 1678 |
|
|
/* Next code just does sprintf( {}, "%d", n); */
|
| 1679 |
|
|
/* Label number. */
|
| 1680 |
|
|
q = symbol_name_temporary;
|
| 1681 |
|
|
for (*q++ = 0, i = n; i; ++q)
|
| 1682 |
|
|
{
|
| 1683 |
|
|
*q = i % 10 + '0';
|
| 1684 |
|
|
i /= 10;
|
| 1685 |
|
|
}
|
| 1686 |
|
|
while ((*p = *--q) != '\0')
|
| 1687 |
|
|
++p;
|
| 1688 |
|
|
|
| 1689 |
|
|
*p++ = DOLLAR_LABEL_CHAR; /* ^A */
|
| 1690 |
|
|
|
| 1691 |
|
|
/* Instance number. */
|
| 1692 |
|
|
q = symbol_name_temporary;
|
| 1693 |
|
|
for (*q++ = 0, i = dollar_label_instance (n) + augend; i; ++q)
|
| 1694 |
|
|
{
|
| 1695 |
|
|
*q = i % 10 + '0';
|
| 1696 |
|
|
i /= 10;
|
| 1697 |
|
|
}
|
| 1698 |
|
|
while ((*p++ = *--q) != '\0');;
|
| 1699 |
|
|
|
| 1700 |
|
|
/* The label, as a '\0' ended string, starts at symbol_name_build. */
|
| 1701 |
|
|
return symbol_name_build;
|
| 1702 |
|
|
}
|
| 1703 |
|
|
|
| 1704 |
|
|
/* Somebody else's idea of local labels. They are made by "n:" where n
|
| 1705 |
|
|
is any decimal digit. Refer to them with
|
| 1706 |
|
|
"nb" for previous (backward) n:
|
| 1707 |
|
|
or "nf" for next (forward) n:.
|
| 1708 |
|
|
|
| 1709 |
|
|
We do a little better and let n be any number, not just a single digit, but
|
| 1710 |
|
|
since the other guy's assembler only does ten, we treat the first ten
|
| 1711 |
|
|
specially.
|
| 1712 |
|
|
|
| 1713 |
|
|
Like someone else's assembler, we have one set of local label counters for
|
| 1714 |
|
|
entire assembly, not one set per (sub)segment like in most assemblers. This
|
| 1715 |
|
|
implies that one can refer to a label in another segment, and indeed some
|
| 1716 |
|
|
crufty compilers have done just that.
|
| 1717 |
|
|
|
| 1718 |
|
|
Since there could be a LOT of these things, treat them as a sparse
|
| 1719 |
|
|
array. */
|
| 1720 |
|
|
|
| 1721 |
|
|
#define FB_LABEL_SPECIAL (10)
|
| 1722 |
|
|
|
| 1723 |
|
|
static long fb_low_counter[FB_LABEL_SPECIAL];
|
| 1724 |
|
|
static long *fb_labels;
|
| 1725 |
|
|
static long *fb_label_instances;
|
| 1726 |
|
|
static long fb_label_count;
|
| 1727 |
|
|
static long fb_label_max;
|
| 1728 |
|
|
|
| 1729 |
|
|
/* This must be more than FB_LABEL_SPECIAL. */
|
| 1730 |
|
|
#define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6)
|
| 1731 |
|
|
|
| 1732 |
|
|
static void
|
| 1733 |
|
|
fb_label_init (void)
|
| 1734 |
|
|
{
|
| 1735 |
|
|
memset ((void *) fb_low_counter, '\0', sizeof (fb_low_counter));
|
| 1736 |
|
|
}
|
| 1737 |
|
|
|
| 1738 |
|
|
/* Add one to the instance number of this fb label. */
|
| 1739 |
|
|
|
| 1740 |
|
|
void
|
| 1741 |
|
|
fb_label_instance_inc (long label)
|
| 1742 |
|
|
{
|
| 1743 |
|
|
long *i;
|
| 1744 |
|
|
|
| 1745 |
|
|
if (label < FB_LABEL_SPECIAL)
|
| 1746 |
|
|
{
|
| 1747 |
|
|
++fb_low_counter[label];
|
| 1748 |
|
|
return;
|
| 1749 |
|
|
}
|
| 1750 |
|
|
|
| 1751 |
|
|
if (fb_labels != NULL)
|
| 1752 |
|
|
{
|
| 1753 |
|
|
for (i = fb_labels + FB_LABEL_SPECIAL;
|
| 1754 |
|
|
i < fb_labels + fb_label_count; ++i)
|
| 1755 |
|
|
{
|
| 1756 |
|
|
if (*i == label)
|
| 1757 |
|
|
{
|
| 1758 |
|
|
++fb_label_instances[i - fb_labels];
|
| 1759 |
|
|
return;
|
| 1760 |
|
|
} /* if we find it */
|
| 1761 |
|
|
} /* for each existing label */
|
| 1762 |
|
|
}
|
| 1763 |
|
|
|
| 1764 |
|
|
/* If we get to here, we don't have label listed yet. */
|
| 1765 |
|
|
|
| 1766 |
|
|
if (fb_labels == NULL)
|
| 1767 |
|
|
{
|
| 1768 |
|
|
fb_labels = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
|
| 1769 |
|
|
fb_label_instances = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
|
| 1770 |
|
|
fb_label_max = FB_LABEL_BUMP_BY;
|
| 1771 |
|
|
fb_label_count = FB_LABEL_SPECIAL;
|
| 1772 |
|
|
|
| 1773 |
|
|
}
|
| 1774 |
|
|
else if (fb_label_count == fb_label_max)
|
| 1775 |
|
|
{
|
| 1776 |
|
|
fb_label_max += FB_LABEL_BUMP_BY;
|
| 1777 |
|
|
fb_labels = (long *) xrealloc ((char *) fb_labels,
|
| 1778 |
|
|
fb_label_max * sizeof (long));
|
| 1779 |
|
|
fb_label_instances = (long *) xrealloc ((char *) fb_label_instances,
|
| 1780 |
|
|
fb_label_max * sizeof (long));
|
| 1781 |
|
|
} /* if we needed to grow */
|
| 1782 |
|
|
|
| 1783 |
|
|
fb_labels[fb_label_count] = label;
|
| 1784 |
|
|
fb_label_instances[fb_label_count] = 1;
|
| 1785 |
|
|
++fb_label_count;
|
| 1786 |
|
|
}
|
| 1787 |
|
|
|
| 1788 |
|
|
static long
|
| 1789 |
|
|
fb_label_instance (long label)
|
| 1790 |
|
|
{
|
| 1791 |
|
|
long *i;
|
| 1792 |
|
|
|
| 1793 |
|
|
if (label < FB_LABEL_SPECIAL)
|
| 1794 |
|
|
{
|
| 1795 |
|
|
return (fb_low_counter[label]);
|
| 1796 |
|
|
}
|
| 1797 |
|
|
|
| 1798 |
|
|
if (fb_labels != NULL)
|
| 1799 |
|
|
{
|
| 1800 |
|
|
for (i = fb_labels + FB_LABEL_SPECIAL;
|
| 1801 |
|
|
i < fb_labels + fb_label_count; ++i)
|
| 1802 |
|
|
{
|
| 1803 |
|
|
if (*i == label)
|
| 1804 |
|
|
{
|
| 1805 |
|
|
return (fb_label_instances[i - fb_labels]);
|
| 1806 |
|
|
} /* if we find it */
|
| 1807 |
|
|
} /* for each existing label */
|
| 1808 |
|
|
}
|
| 1809 |
|
|
|
| 1810 |
|
|
/* We didn't find the label, so this must be a reference to the
|
| 1811 |
|
|
first instance. */
|
| 1812 |
|
|
return 0;
|
| 1813 |
|
|
}
|
| 1814 |
|
|
|
| 1815 |
|
|
/* Caller must copy returned name: we re-use the area for the next name.
|
| 1816 |
|
|
|
| 1817 |
|
|
The mth occurence of label n: is turned into the symbol "Ln^Bm"
|
| 1818 |
|
|
where n is the label number and m is the instance number. "L" makes
|
| 1819 |
|
|
it a label discarded unless debugging and "^B"('\2') ensures no
|
| 1820 |
|
|
ordinary symbol SHOULD get the same name as a local label
|
| 1821 |
|
|
symbol. The first "4:" is "L4^B1" - the m numbers begin at 1.
|
| 1822 |
|
|
|
| 1823 |
|
|
dollar labels get the same treatment, except that ^A is used in
|
| 1824 |
|
|
place of ^B. */
|
| 1825 |
|
|
|
| 1826 |
|
|
char * /* Return local label name. */
|
| 1827 |
|
|
fb_label_name (long n, /* We just saw "n:", "nf" or "nb" : n a number. */
|
| 1828 |
|
|
long augend /* 0 for nb, 1 for n:, nf. */)
|
| 1829 |
|
|
{
|
| 1830 |
|
|
long i;
|
| 1831 |
|
|
/* Returned to caller, then copied. Used for created names ("4f"). */
|
| 1832 |
|
|
static char symbol_name_build[24];
|
| 1833 |
|
|
register char *p;
|
| 1834 |
|
|
register char *q;
|
| 1835 |
|
|
char symbol_name_temporary[20]; /* Build up a number, BACKWARDS. */
|
| 1836 |
|
|
|
| 1837 |
|
|
know (n >= 0);
|
| 1838 |
|
|
#ifdef TC_MMIX
|
| 1839 |
|
|
know ((unsigned long) augend <= 2 /* See mmix_fb_label. */);
|
| 1840 |
|
|
#else
|
| 1841 |
|
|
know ((unsigned long) augend <= 1);
|
| 1842 |
|
|
#endif
|
| 1843 |
|
|
p = symbol_name_build;
|
| 1844 |
|
|
#ifdef LOCAL_LABEL_PREFIX
|
| 1845 |
|
|
*p++ = LOCAL_LABEL_PREFIX;
|
| 1846 |
|
|
#endif
|
| 1847 |
|
|
*p++ = 'L';
|
| 1848 |
|
|
|
| 1849 |
|
|
/* Next code just does sprintf( {}, "%d", n); */
|
| 1850 |
|
|
/* Label number. */
|
| 1851 |
|
|
q = symbol_name_temporary;
|
| 1852 |
|
|
for (*q++ = 0, i = n; i; ++q)
|
| 1853 |
|
|
{
|
| 1854 |
|
|
*q = i % 10 + '0';
|
| 1855 |
|
|
i /= 10;
|
| 1856 |
|
|
}
|
| 1857 |
|
|
while ((*p = *--q) != '\0')
|
| 1858 |
|
|
++p;
|
| 1859 |
|
|
|
| 1860 |
|
|
*p++ = LOCAL_LABEL_CHAR; /* ^B */
|
| 1861 |
|
|
|
| 1862 |
|
|
/* Instance number. */
|
| 1863 |
|
|
q = symbol_name_temporary;
|
| 1864 |
|
|
for (*q++ = 0, i = fb_label_instance (n) + augend; i; ++q)
|
| 1865 |
|
|
{
|
| 1866 |
|
|
*q = i % 10 + '0';
|
| 1867 |
|
|
i /= 10;
|
| 1868 |
|
|
}
|
| 1869 |
|
|
while ((*p++ = *--q) != '\0');;
|
| 1870 |
|
|
|
| 1871 |
|
|
/* The label, as a '\0' ended string, starts at symbol_name_build. */
|
| 1872 |
|
|
return (symbol_name_build);
|
| 1873 |
|
|
}
|
| 1874 |
|
|
|
| 1875 |
|
|
/* Decode name that may have been generated by foo_label_name() above.
|
| 1876 |
|
|
If the name wasn't generated by foo_label_name(), then return it
|
| 1877 |
|
|
unaltered. This is used for error messages. */
|
| 1878 |
|
|
|
| 1879 |
|
|
char *
|
| 1880 |
|
|
decode_local_label_name (char *s)
|
| 1881 |
|
|
{
|
| 1882 |
|
|
char *p;
|
| 1883 |
|
|
char *symbol_decode;
|
| 1884 |
|
|
int label_number;
|
| 1885 |
|
|
int instance_number;
|
| 1886 |
|
|
char *type;
|
| 1887 |
|
|
const char *message_format;
|
| 1888 |
|
|
int lindex = 0;
|
| 1889 |
|
|
|
| 1890 |
|
|
#ifdef LOCAL_LABEL_PREFIX
|
| 1891 |
|
|
if (s[lindex] == LOCAL_LABEL_PREFIX)
|
| 1892 |
|
|
++lindex;
|
| 1893 |
|
|
#endif
|
| 1894 |
|
|
|
| 1895 |
|
|
if (s[lindex] != 'L')
|
| 1896 |
|
|
return s;
|
| 1897 |
|
|
|
| 1898 |
|
|
for (label_number = 0, p = s + lindex + 1; ISDIGIT (*p); ++p)
|
| 1899 |
|
|
label_number = (10 * label_number) + *p - '0';
|
| 1900 |
|
|
|
| 1901 |
|
|
if (*p == DOLLAR_LABEL_CHAR)
|
| 1902 |
|
|
type = "dollar";
|
| 1903 |
|
|
else if (*p == LOCAL_LABEL_CHAR)
|
| 1904 |
|
|
type = "fb";
|
| 1905 |
|
|
else
|
| 1906 |
|
|
return s;
|
| 1907 |
|
|
|
| 1908 |
|
|
for (instance_number = 0, p++; ISDIGIT (*p); ++p)
|
| 1909 |
|
|
instance_number = (10 * instance_number) + *p - '0';
|
| 1910 |
|
|
|
| 1911 |
|
|
message_format = _("\"%d\" (instance number %d of a %s label)");
|
| 1912 |
|
|
symbol_decode = (char *) obstack_alloc (¬es, strlen (message_format) + 30);
|
| 1913 |
|
|
sprintf (symbol_decode, message_format, label_number, instance_number, type);
|
| 1914 |
|
|
|
| 1915 |
|
|
return symbol_decode;
|
| 1916 |
|
|
}
|
| 1917 |
|
|
|
| 1918 |
|
|
/* Get the value of a symbol. */
|
| 1919 |
|
|
|
| 1920 |
|
|
valueT
|
| 1921 |
|
|
S_GET_VALUE (symbolS *s)
|
| 1922 |
|
|
{
|
| 1923 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 1924 |
|
|
return resolve_symbol_value (s);
|
| 1925 |
|
|
|
| 1926 |
|
|
if (!s->sy_resolved)
|
| 1927 |
|
|
{
|
| 1928 |
|
|
valueT val = resolve_symbol_value (s);
|
| 1929 |
|
|
if (!finalize_syms)
|
| 1930 |
|
|
return val;
|
| 1931 |
|
|
}
|
| 1932 |
|
|
if (S_IS_WEAKREFR (s))
|
| 1933 |
|
|
return S_GET_VALUE (s->sy_value.X_add_symbol);
|
| 1934 |
|
|
|
| 1935 |
|
|
if (s->sy_value.X_op != O_constant)
|
| 1936 |
|
|
{
|
| 1937 |
|
|
if (! s->sy_resolved
|
| 1938 |
|
|
|| s->sy_value.X_op != O_symbol
|
| 1939 |
|
|
|| (S_IS_DEFINED (s) && ! S_IS_COMMON (s)))
|
| 1940 |
|
|
as_bad (_("attempt to get value of unresolved symbol `%s'"),
|
| 1941 |
|
|
S_GET_NAME (s));
|
| 1942 |
|
|
}
|
| 1943 |
|
|
return (valueT) s->sy_value.X_add_number;
|
| 1944 |
|
|
}
|
| 1945 |
|
|
|
| 1946 |
|
|
/* Set the value of a symbol. */
|
| 1947 |
|
|
|
| 1948 |
|
|
void
|
| 1949 |
|
|
S_SET_VALUE (symbolS *s, valueT val)
|
| 1950 |
|
|
{
|
| 1951 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 1952 |
|
|
{
|
| 1953 |
|
|
((struct local_symbol *) s)->lsy_value = val;
|
| 1954 |
|
|
return;
|
| 1955 |
|
|
}
|
| 1956 |
|
|
|
| 1957 |
|
|
s->sy_value.X_op = O_constant;
|
| 1958 |
|
|
s->sy_value.X_add_number = (offsetT) val;
|
| 1959 |
|
|
s->sy_value.X_unsigned = 0;
|
| 1960 |
|
|
S_CLEAR_WEAKREFR (s);
|
| 1961 |
|
|
}
|
| 1962 |
|
|
|
| 1963 |
|
|
void
|
| 1964 |
|
|
copy_symbol_attributes (symbolS *dest, symbolS *src)
|
| 1965 |
|
|
{
|
| 1966 |
|
|
if (LOCAL_SYMBOL_CHECK (dest))
|
| 1967 |
|
|
dest = local_symbol_convert ((struct local_symbol *) dest);
|
| 1968 |
|
|
if (LOCAL_SYMBOL_CHECK (src))
|
| 1969 |
|
|
src = local_symbol_convert ((struct local_symbol *) src);
|
| 1970 |
|
|
|
| 1971 |
|
|
/* In an expression, transfer the settings of these flags.
|
| 1972 |
|
|
The user can override later, of course. */
|
| 1973 |
|
|
#define COPIED_SYMFLAGS (BSF_FUNCTION | BSF_OBJECT \
|
| 1974 |
|
|
| BSF_GNU_INDIRECT_FUNCTION)
|
| 1975 |
|
|
dest->bsym->flags |= src->bsym->flags & COPIED_SYMFLAGS;
|
| 1976 |
|
|
|
| 1977 |
|
|
#ifdef OBJ_COPY_SYMBOL_ATTRIBUTES
|
| 1978 |
|
|
OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src);
|
| 1979 |
|
|
#endif
|
| 1980 |
|
|
|
| 1981 |
|
|
#ifdef TC_COPY_SYMBOL_ATTRIBUTES
|
| 1982 |
|
|
TC_COPY_SYMBOL_ATTRIBUTES (dest, src);
|
| 1983 |
|
|
#endif
|
| 1984 |
|
|
}
|
| 1985 |
|
|
|
| 1986 |
|
|
int
|
| 1987 |
|
|
S_IS_FUNCTION (symbolS *s)
|
| 1988 |
|
|
{
|
| 1989 |
|
|
flagword flags;
|
| 1990 |
|
|
|
| 1991 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 1992 |
|
|
return 0;
|
| 1993 |
|
|
|
| 1994 |
|
|
flags = s->bsym->flags;
|
| 1995 |
|
|
|
| 1996 |
|
|
return (flags & BSF_FUNCTION) != 0;
|
| 1997 |
|
|
}
|
| 1998 |
|
|
|
| 1999 |
|
|
int
|
| 2000 |
|
|
S_IS_EXTERNAL (symbolS *s)
|
| 2001 |
|
|
{
|
| 2002 |
|
|
flagword flags;
|
| 2003 |
|
|
|
| 2004 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2005 |
|
|
return 0;
|
| 2006 |
|
|
|
| 2007 |
|
|
flags = s->bsym->flags;
|
| 2008 |
|
|
|
| 2009 |
|
|
/* Sanity check. */
|
| 2010 |
|
|
if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
|
| 2011 |
|
|
abort ();
|
| 2012 |
|
|
|
| 2013 |
|
|
return (flags & BSF_GLOBAL) != 0;
|
| 2014 |
|
|
}
|
| 2015 |
|
|
|
| 2016 |
|
|
int
|
| 2017 |
|
|
S_IS_WEAK (symbolS *s)
|
| 2018 |
|
|
{
|
| 2019 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2020 |
|
|
return 0;
|
| 2021 |
|
|
/* Conceptually, a weakrefr is weak if the referenced symbol is. We
|
| 2022 |
|
|
could probably handle a WEAKREFR as always weak though. E.g., if
|
| 2023 |
|
|
the referenced symbol has lost its weak status, there's no reason
|
| 2024 |
|
|
to keep handling the weakrefr as if it was weak. */
|
| 2025 |
|
|
if (S_IS_WEAKREFR (s))
|
| 2026 |
|
|
return S_IS_WEAK (s->sy_value.X_add_symbol);
|
| 2027 |
|
|
return (s->bsym->flags & BSF_WEAK) != 0;
|
| 2028 |
|
|
}
|
| 2029 |
|
|
|
| 2030 |
|
|
int
|
| 2031 |
|
|
S_IS_WEAKREFR (symbolS *s)
|
| 2032 |
|
|
{
|
| 2033 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2034 |
|
|
return 0;
|
| 2035 |
|
|
return s->sy_weakrefr != 0;
|
| 2036 |
|
|
}
|
| 2037 |
|
|
|
| 2038 |
|
|
int
|
| 2039 |
|
|
S_IS_WEAKREFD (symbolS *s)
|
| 2040 |
|
|
{
|
| 2041 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2042 |
|
|
return 0;
|
| 2043 |
|
|
return s->sy_weakrefd != 0;
|
| 2044 |
|
|
}
|
| 2045 |
|
|
|
| 2046 |
|
|
int
|
| 2047 |
|
|
S_IS_COMMON (symbolS *s)
|
| 2048 |
|
|
{
|
| 2049 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2050 |
|
|
return 0;
|
| 2051 |
|
|
return bfd_is_com_section (s->bsym->section);
|
| 2052 |
|
|
}
|
| 2053 |
|
|
|
| 2054 |
|
|
int
|
| 2055 |
|
|
S_IS_DEFINED (symbolS *s)
|
| 2056 |
|
|
{
|
| 2057 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2058 |
|
|
return ((struct local_symbol *) s)->lsy_section != undefined_section;
|
| 2059 |
|
|
return s->bsym->section != undefined_section;
|
| 2060 |
|
|
}
|
| 2061 |
|
|
|
| 2062 |
|
|
|
| 2063 |
|
|
#ifndef EXTERN_FORCE_RELOC
|
| 2064 |
|
|
#define EXTERN_FORCE_RELOC IS_ELF
|
| 2065 |
|
|
#endif
|
| 2066 |
|
|
|
| 2067 |
|
|
/* Return true for symbols that should not be reduced to section
|
| 2068 |
|
|
symbols or eliminated from expressions, because they may be
|
| 2069 |
|
|
overridden by the linker. */
|
| 2070 |
|
|
int
|
| 2071 |
|
|
S_FORCE_RELOC (symbolS *s, int strict)
|
| 2072 |
|
|
{
|
| 2073 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2074 |
|
|
return ((struct local_symbol *) s)->lsy_section == undefined_section;
|
| 2075 |
|
|
|
| 2076 |
|
|
return ((strict
|
| 2077 |
|
|
&& ((s->bsym->flags & BSF_WEAK) != 0
|
| 2078 |
|
|
|| (EXTERN_FORCE_RELOC
|
| 2079 |
|
|
&& (s->bsym->flags & BSF_GLOBAL) != 0)))
|
| 2080 |
|
|
|| (s->bsym->flags & BSF_GNU_INDIRECT_FUNCTION) != 0
|
| 2081 |
|
|
|| s->bsym->section == undefined_section
|
| 2082 |
|
|
|| bfd_is_com_section (s->bsym->section));
|
| 2083 |
|
|
}
|
| 2084 |
|
|
|
| 2085 |
|
|
int
|
| 2086 |
|
|
S_IS_DEBUG (symbolS *s)
|
| 2087 |
|
|
{
|
| 2088 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2089 |
|
|
return 0;
|
| 2090 |
|
|
if (s->bsym->flags & BSF_DEBUGGING)
|
| 2091 |
|
|
return 1;
|
| 2092 |
|
|
return 0;
|
| 2093 |
|
|
}
|
| 2094 |
|
|
|
| 2095 |
|
|
int
|
| 2096 |
|
|
S_IS_LOCAL (symbolS *s)
|
| 2097 |
|
|
{
|
| 2098 |
|
|
flagword flags;
|
| 2099 |
|
|
const char *name;
|
| 2100 |
|
|
|
| 2101 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2102 |
|
|
return 1;
|
| 2103 |
|
|
|
| 2104 |
|
|
flags = s->bsym->flags;
|
| 2105 |
|
|
|
| 2106 |
|
|
/* Sanity check. */
|
| 2107 |
|
|
if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
|
| 2108 |
|
|
abort ();
|
| 2109 |
|
|
|
| 2110 |
|
|
if (bfd_get_section (s->bsym) == reg_section)
|
| 2111 |
|
|
return 1;
|
| 2112 |
|
|
|
| 2113 |
|
|
if (flag_strip_local_absolute
|
| 2114 |
|
|
/* Keep BSF_FILE symbols in order to allow debuggers to identify
|
| 2115 |
|
|
the source file even when the object file is stripped. */
|
| 2116 |
|
|
&& (flags & (BSF_GLOBAL | BSF_FILE)) == 0
|
| 2117 |
|
|
&& bfd_get_section (s->bsym) == absolute_section)
|
| 2118 |
|
|
return 1;
|
| 2119 |
|
|
|
| 2120 |
|
|
name = S_GET_NAME (s);
|
| 2121 |
|
|
return (name != NULL
|
| 2122 |
|
|
&& ! S_IS_DEBUG (s)
|
| 2123 |
|
|
&& (strchr (name, DOLLAR_LABEL_CHAR)
|
| 2124 |
|
|
|| strchr (name, LOCAL_LABEL_CHAR)
|
| 2125 |
160 |
khays |
|| TC_LABEL_IS_LOCAL (name)
|
| 2126 |
147 |
khays |
|| (! flag_keep_locals
|
| 2127 |
|
|
&& (bfd_is_local_label (stdoutput, s->bsym)
|
| 2128 |
|
|
|| (flag_mri
|
| 2129 |
|
|
&& name[0] == '?'
|
| 2130 |
|
|
&& name[1] == '?')))));
|
| 2131 |
|
|
}
|
| 2132 |
|
|
|
| 2133 |
|
|
int
|
| 2134 |
|
|
S_IS_STABD (symbolS *s)
|
| 2135 |
|
|
{
|
| 2136 |
|
|
return S_GET_NAME (s) == 0;
|
| 2137 |
|
|
}
|
| 2138 |
|
|
|
| 2139 |
|
|
int
|
| 2140 |
163 |
khays |
S_CAN_BE_REDEFINED (const symbolS *s)
|
| 2141 |
|
|
{
|
| 2142 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2143 |
|
|
return (local_symbol_get_frag ((struct local_symbol *) s)
|
| 2144 |
|
|
== &predefined_address_frag);
|
| 2145 |
|
|
/* Permit register names to be redefined. */
|
| 2146 |
|
|
return s->bsym->section == reg_section;
|
| 2147 |
|
|
}
|
| 2148 |
|
|
|
| 2149 |
|
|
int
|
| 2150 |
147 |
khays |
S_IS_VOLATILE (const symbolS *s)
|
| 2151 |
|
|
{
|
| 2152 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2153 |
|
|
return 0;
|
| 2154 |
|
|
return s->sy_volatile;
|
| 2155 |
|
|
}
|
| 2156 |
|
|
|
| 2157 |
|
|
int
|
| 2158 |
|
|
S_IS_FORWARD_REF (const symbolS *s)
|
| 2159 |
|
|
{
|
| 2160 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2161 |
|
|
return 0;
|
| 2162 |
|
|
return s->sy_forward_ref;
|
| 2163 |
|
|
}
|
| 2164 |
|
|
|
| 2165 |
|
|
const char *
|
| 2166 |
|
|
S_GET_NAME (symbolS *s)
|
| 2167 |
|
|
{
|
| 2168 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2169 |
|
|
return ((struct local_symbol *) s)->lsy_name;
|
| 2170 |
|
|
return s->bsym->name;
|
| 2171 |
|
|
}
|
| 2172 |
|
|
|
| 2173 |
|
|
segT
|
| 2174 |
|
|
S_GET_SEGMENT (symbolS *s)
|
| 2175 |
|
|
{
|
| 2176 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2177 |
|
|
return ((struct local_symbol *) s)->lsy_section;
|
| 2178 |
|
|
return s->bsym->section;
|
| 2179 |
|
|
}
|
| 2180 |
|
|
|
| 2181 |
|
|
void
|
| 2182 |
|
|
S_SET_SEGMENT (symbolS *s, segT seg)
|
| 2183 |
|
|
{
|
| 2184 |
|
|
/* Don't reassign section symbols. The direct reason is to prevent seg
|
| 2185 |
|
|
faults assigning back to const global symbols such as *ABS*, but it
|
| 2186 |
|
|
shouldn't happen anyway. */
|
| 2187 |
|
|
|
| 2188 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2189 |
|
|
{
|
| 2190 |
|
|
if (seg == reg_section)
|
| 2191 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2192 |
|
|
else
|
| 2193 |
|
|
{
|
| 2194 |
|
|
((struct local_symbol *) s)->lsy_section = seg;
|
| 2195 |
|
|
return;
|
| 2196 |
|
|
}
|
| 2197 |
|
|
}
|
| 2198 |
|
|
|
| 2199 |
|
|
if (s->bsym->flags & BSF_SECTION_SYM)
|
| 2200 |
|
|
{
|
| 2201 |
|
|
if (s->bsym->section != seg)
|
| 2202 |
|
|
abort ();
|
| 2203 |
|
|
}
|
| 2204 |
|
|
else
|
| 2205 |
|
|
s->bsym->section = seg;
|
| 2206 |
|
|
}
|
| 2207 |
|
|
|
| 2208 |
|
|
void
|
| 2209 |
|
|
S_SET_EXTERNAL (symbolS *s)
|
| 2210 |
|
|
{
|
| 2211 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2212 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2213 |
|
|
if ((s->bsym->flags & BSF_WEAK) != 0)
|
| 2214 |
|
|
{
|
| 2215 |
|
|
/* Let .weak override .global. */
|
| 2216 |
|
|
return;
|
| 2217 |
|
|
}
|
| 2218 |
|
|
if (s->bsym->flags & BSF_SECTION_SYM)
|
| 2219 |
|
|
{
|
| 2220 |
|
|
char * file;
|
| 2221 |
|
|
unsigned int line;
|
| 2222 |
|
|
|
| 2223 |
|
|
/* Do not reassign section symbols. */
|
| 2224 |
|
|
as_where (& file, & line);
|
| 2225 |
|
|
as_warn_where (file, line,
|
| 2226 |
|
|
_("section symbols are already global"));
|
| 2227 |
|
|
return;
|
| 2228 |
|
|
}
|
| 2229 |
|
|
#ifndef TC_GLOBAL_REGISTER_SYMBOL_OK
|
| 2230 |
|
|
if (S_GET_SEGMENT (s) == reg_section)
|
| 2231 |
|
|
{
|
| 2232 |
|
|
as_bad ("can't make register symbol `%s' global",
|
| 2233 |
|
|
S_GET_NAME (s));
|
| 2234 |
|
|
return;
|
| 2235 |
|
|
}
|
| 2236 |
|
|
#endif
|
| 2237 |
|
|
s->bsym->flags |= BSF_GLOBAL;
|
| 2238 |
|
|
s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK);
|
| 2239 |
|
|
|
| 2240 |
|
|
#ifdef TE_PE
|
| 2241 |
|
|
if (! an_external_name && S_GET_NAME(s)[0] != '.')
|
| 2242 |
|
|
an_external_name = S_GET_NAME (s);
|
| 2243 |
|
|
#endif
|
| 2244 |
|
|
}
|
| 2245 |
|
|
|
| 2246 |
|
|
void
|
| 2247 |
|
|
S_CLEAR_EXTERNAL (symbolS *s)
|
| 2248 |
|
|
{
|
| 2249 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2250 |
|
|
return;
|
| 2251 |
|
|
if ((s->bsym->flags & BSF_WEAK) != 0)
|
| 2252 |
|
|
{
|
| 2253 |
|
|
/* Let .weak override. */
|
| 2254 |
|
|
return;
|
| 2255 |
|
|
}
|
| 2256 |
|
|
s->bsym->flags |= BSF_LOCAL;
|
| 2257 |
|
|
s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK);
|
| 2258 |
|
|
}
|
| 2259 |
|
|
|
| 2260 |
|
|
void
|
| 2261 |
|
|
S_SET_WEAK (symbolS *s)
|
| 2262 |
|
|
{
|
| 2263 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2264 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2265 |
|
|
#ifdef obj_set_weak_hook
|
| 2266 |
|
|
obj_set_weak_hook (s);
|
| 2267 |
|
|
#endif
|
| 2268 |
|
|
s->bsym->flags |= BSF_WEAK;
|
| 2269 |
|
|
s->bsym->flags &= ~(BSF_GLOBAL | BSF_LOCAL);
|
| 2270 |
|
|
}
|
| 2271 |
|
|
|
| 2272 |
|
|
void
|
| 2273 |
|
|
S_SET_WEAKREFR (symbolS *s)
|
| 2274 |
|
|
{
|
| 2275 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2276 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2277 |
|
|
s->sy_weakrefr = 1;
|
| 2278 |
|
|
/* If the alias was already used, make sure we mark the target as
|
| 2279 |
|
|
used as well, otherwise it might be dropped from the symbol
|
| 2280 |
|
|
table. This may have unintended side effects if the alias is
|
| 2281 |
|
|
later redirected to another symbol, such as keeping the unused
|
| 2282 |
|
|
previous target in the symbol table. Since it will be weak, it's
|
| 2283 |
|
|
not a big deal. */
|
| 2284 |
|
|
if (s->sy_used)
|
| 2285 |
|
|
symbol_mark_used (s->sy_value.X_add_symbol);
|
| 2286 |
|
|
}
|
| 2287 |
|
|
|
| 2288 |
|
|
void
|
| 2289 |
|
|
S_CLEAR_WEAKREFR (symbolS *s)
|
| 2290 |
|
|
{
|
| 2291 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2292 |
|
|
return;
|
| 2293 |
|
|
s->sy_weakrefr = 0;
|
| 2294 |
|
|
}
|
| 2295 |
|
|
|
| 2296 |
|
|
void
|
| 2297 |
|
|
S_SET_WEAKREFD (symbolS *s)
|
| 2298 |
|
|
{
|
| 2299 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2300 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2301 |
|
|
s->sy_weakrefd = 1;
|
| 2302 |
|
|
S_SET_WEAK (s);
|
| 2303 |
|
|
}
|
| 2304 |
|
|
|
| 2305 |
|
|
void
|
| 2306 |
|
|
S_CLEAR_WEAKREFD (symbolS *s)
|
| 2307 |
|
|
{
|
| 2308 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2309 |
|
|
return;
|
| 2310 |
|
|
if (s->sy_weakrefd)
|
| 2311 |
|
|
{
|
| 2312 |
|
|
s->sy_weakrefd = 0;
|
| 2313 |
|
|
/* If a weakref target symbol is weak, then it was never
|
| 2314 |
|
|
referenced directly before, not even in a .global directive,
|
| 2315 |
|
|
so decay it to local. If it remains undefined, it will be
|
| 2316 |
|
|
later turned into a global, like any other undefined
|
| 2317 |
|
|
symbol. */
|
| 2318 |
|
|
if (s->bsym->flags & BSF_WEAK)
|
| 2319 |
|
|
{
|
| 2320 |
|
|
#ifdef obj_clear_weak_hook
|
| 2321 |
|
|
obj_clear_weak_hook (s);
|
| 2322 |
|
|
#endif
|
| 2323 |
|
|
s->bsym->flags &= ~BSF_WEAK;
|
| 2324 |
|
|
s->bsym->flags |= BSF_LOCAL;
|
| 2325 |
|
|
}
|
| 2326 |
|
|
}
|
| 2327 |
|
|
}
|
| 2328 |
|
|
|
| 2329 |
|
|
void
|
| 2330 |
|
|
S_SET_THREAD_LOCAL (symbolS *s)
|
| 2331 |
|
|
{
|
| 2332 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2333 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2334 |
|
|
if (bfd_is_com_section (s->bsym->section)
|
| 2335 |
|
|
&& (s->bsym->flags & BSF_THREAD_LOCAL) != 0)
|
| 2336 |
|
|
return;
|
| 2337 |
|
|
s->bsym->flags |= BSF_THREAD_LOCAL;
|
| 2338 |
|
|
if ((s->bsym->flags & BSF_FUNCTION) != 0)
|
| 2339 |
|
|
as_bad (_("Accessing function `%s' as thread-local object"),
|
| 2340 |
|
|
S_GET_NAME (s));
|
| 2341 |
|
|
else if (! bfd_is_und_section (s->bsym->section)
|
| 2342 |
|
|
&& (s->bsym->section->flags & SEC_THREAD_LOCAL) == 0)
|
| 2343 |
|
|
as_bad (_("Accessing `%s' as thread-local object"),
|
| 2344 |
|
|
S_GET_NAME (s));
|
| 2345 |
|
|
}
|
| 2346 |
|
|
|
| 2347 |
|
|
void
|
| 2348 |
|
|
S_SET_NAME (symbolS *s, const char *name)
|
| 2349 |
|
|
{
|
| 2350 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2351 |
|
|
{
|
| 2352 |
|
|
((struct local_symbol *) s)->lsy_name = name;
|
| 2353 |
|
|
return;
|
| 2354 |
|
|
}
|
| 2355 |
|
|
s->bsym->name = name;
|
| 2356 |
|
|
}
|
| 2357 |
|
|
|
| 2358 |
|
|
void
|
| 2359 |
|
|
S_SET_VOLATILE (symbolS *s)
|
| 2360 |
|
|
{
|
| 2361 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2362 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2363 |
|
|
s->sy_volatile = 1;
|
| 2364 |
|
|
}
|
| 2365 |
|
|
|
| 2366 |
|
|
void
|
| 2367 |
|
|
S_CLEAR_VOLATILE (symbolS *s)
|
| 2368 |
|
|
{
|
| 2369 |
|
|
if (!LOCAL_SYMBOL_CHECK (s))
|
| 2370 |
|
|
s->sy_volatile = 0;
|
| 2371 |
|
|
}
|
| 2372 |
|
|
|
| 2373 |
|
|
void
|
| 2374 |
|
|
S_SET_FORWARD_REF (symbolS *s)
|
| 2375 |
|
|
{
|
| 2376 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2377 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2378 |
|
|
s->sy_forward_ref = 1;
|
| 2379 |
|
|
}
|
| 2380 |
|
|
|
| 2381 |
|
|
/* Return the previous symbol in a chain. */
|
| 2382 |
|
|
|
| 2383 |
|
|
symbolS *
|
| 2384 |
|
|
symbol_previous (symbolS *s)
|
| 2385 |
|
|
{
|
| 2386 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2387 |
|
|
abort ();
|
| 2388 |
|
|
return s->sy_previous;
|
| 2389 |
|
|
}
|
| 2390 |
|
|
|
| 2391 |
|
|
/* Return the next symbol in a chain. */
|
| 2392 |
|
|
|
| 2393 |
|
|
symbolS *
|
| 2394 |
|
|
symbol_next (symbolS *s)
|
| 2395 |
|
|
{
|
| 2396 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2397 |
|
|
abort ();
|
| 2398 |
|
|
return s->sy_next;
|
| 2399 |
|
|
}
|
| 2400 |
|
|
|
| 2401 |
|
|
/* Return a pointer to the value of a symbol as an expression. */
|
| 2402 |
|
|
|
| 2403 |
|
|
expressionS *
|
| 2404 |
|
|
symbol_get_value_expression (symbolS *s)
|
| 2405 |
|
|
{
|
| 2406 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2407 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2408 |
|
|
return &s->sy_value;
|
| 2409 |
|
|
}
|
| 2410 |
|
|
|
| 2411 |
|
|
/* Set the value of a symbol to an expression. */
|
| 2412 |
|
|
|
| 2413 |
|
|
void
|
| 2414 |
|
|
symbol_set_value_expression (symbolS *s, const expressionS *exp)
|
| 2415 |
|
|
{
|
| 2416 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2417 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2418 |
|
|
s->sy_value = *exp;
|
| 2419 |
|
|
S_CLEAR_WEAKREFR (s);
|
| 2420 |
|
|
}
|
| 2421 |
|
|
|
| 2422 |
|
|
/* Return whether 2 symbols are the same. */
|
| 2423 |
|
|
|
| 2424 |
|
|
int
|
| 2425 |
|
|
symbol_same_p (symbolS *s1, symbolS *s2)
|
| 2426 |
|
|
{
|
| 2427 |
|
|
if (s1->bsym == NULL
|
| 2428 |
|
|
&& local_symbol_converted_p ((struct local_symbol *) s1))
|
| 2429 |
|
|
s1 = local_symbol_get_real_symbol ((struct local_symbol *) s1);
|
| 2430 |
|
|
if (s2->bsym == NULL
|
| 2431 |
|
|
&& local_symbol_converted_p ((struct local_symbol *) s2))
|
| 2432 |
|
|
s2 = local_symbol_get_real_symbol ((struct local_symbol *) s2);
|
| 2433 |
|
|
return s1 == s2;
|
| 2434 |
|
|
}
|
| 2435 |
|
|
|
| 2436 |
|
|
/* Return a pointer to the X_add_number component of a symbol. */
|
| 2437 |
|
|
|
| 2438 |
|
|
offsetT *
|
| 2439 |
|
|
symbol_X_add_number (symbolS *s)
|
| 2440 |
|
|
{
|
| 2441 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2442 |
|
|
return (offsetT *) &((struct local_symbol *) s)->lsy_value;
|
| 2443 |
|
|
|
| 2444 |
|
|
return &s->sy_value.X_add_number;
|
| 2445 |
|
|
}
|
| 2446 |
|
|
|
| 2447 |
|
|
/* Set the value of SYM to the current position in the current segment. */
|
| 2448 |
|
|
|
| 2449 |
|
|
void
|
| 2450 |
|
|
symbol_set_value_now (symbolS *sym)
|
| 2451 |
|
|
{
|
| 2452 |
|
|
S_SET_SEGMENT (sym, now_seg);
|
| 2453 |
|
|
S_SET_VALUE (sym, frag_now_fix ());
|
| 2454 |
|
|
symbol_set_frag (sym, frag_now);
|
| 2455 |
|
|
}
|
| 2456 |
|
|
|
| 2457 |
|
|
/* Set the frag of a symbol. */
|
| 2458 |
|
|
|
| 2459 |
|
|
void
|
| 2460 |
|
|
symbol_set_frag (symbolS *s, fragS *f)
|
| 2461 |
|
|
{
|
| 2462 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2463 |
|
|
{
|
| 2464 |
|
|
local_symbol_set_frag ((struct local_symbol *) s, f);
|
| 2465 |
|
|
return;
|
| 2466 |
|
|
}
|
| 2467 |
|
|
s->sy_frag = f;
|
| 2468 |
|
|
S_CLEAR_WEAKREFR (s);
|
| 2469 |
|
|
}
|
| 2470 |
|
|
|
| 2471 |
|
|
/* Return the frag of a symbol. */
|
| 2472 |
|
|
|
| 2473 |
|
|
fragS *
|
| 2474 |
|
|
symbol_get_frag (symbolS *s)
|
| 2475 |
|
|
{
|
| 2476 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2477 |
|
|
return local_symbol_get_frag ((struct local_symbol *) s);
|
| 2478 |
|
|
return s->sy_frag;
|
| 2479 |
|
|
}
|
| 2480 |
|
|
|
| 2481 |
|
|
/* Mark a symbol as having been used. */
|
| 2482 |
|
|
|
| 2483 |
|
|
void
|
| 2484 |
|
|
symbol_mark_used (symbolS *s)
|
| 2485 |
|
|
{
|
| 2486 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2487 |
|
|
return;
|
| 2488 |
|
|
s->sy_used = 1;
|
| 2489 |
|
|
if (S_IS_WEAKREFR (s))
|
| 2490 |
|
|
symbol_mark_used (s->sy_value.X_add_symbol);
|
| 2491 |
|
|
}
|
| 2492 |
|
|
|
| 2493 |
|
|
/* Clear the mark of whether a symbol has been used. */
|
| 2494 |
|
|
|
| 2495 |
|
|
void
|
| 2496 |
|
|
symbol_clear_used (symbolS *s)
|
| 2497 |
|
|
{
|
| 2498 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2499 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2500 |
|
|
s->sy_used = 0;
|
| 2501 |
|
|
}
|
| 2502 |
|
|
|
| 2503 |
|
|
/* Return whether a symbol has been used. */
|
| 2504 |
|
|
|
| 2505 |
|
|
int
|
| 2506 |
|
|
symbol_used_p (symbolS *s)
|
| 2507 |
|
|
{
|
| 2508 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2509 |
|
|
return 1;
|
| 2510 |
|
|
return s->sy_used;
|
| 2511 |
|
|
}
|
| 2512 |
|
|
|
| 2513 |
|
|
/* Mark a symbol as having been used in a reloc. */
|
| 2514 |
|
|
|
| 2515 |
|
|
void
|
| 2516 |
|
|
symbol_mark_used_in_reloc (symbolS *s)
|
| 2517 |
|
|
{
|
| 2518 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2519 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2520 |
|
|
s->sy_used_in_reloc = 1;
|
| 2521 |
|
|
}
|
| 2522 |
|
|
|
| 2523 |
|
|
/* Clear the mark of whether a symbol has been used in a reloc. */
|
| 2524 |
|
|
|
| 2525 |
|
|
void
|
| 2526 |
|
|
symbol_clear_used_in_reloc (symbolS *s)
|
| 2527 |
|
|
{
|
| 2528 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2529 |
|
|
return;
|
| 2530 |
|
|
s->sy_used_in_reloc = 0;
|
| 2531 |
|
|
}
|
| 2532 |
|
|
|
| 2533 |
|
|
/* Return whether a symbol has been used in a reloc. */
|
| 2534 |
|
|
|
| 2535 |
|
|
int
|
| 2536 |
|
|
symbol_used_in_reloc_p (symbolS *s)
|
| 2537 |
|
|
{
|
| 2538 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2539 |
|
|
return 0;
|
| 2540 |
|
|
return s->sy_used_in_reloc;
|
| 2541 |
|
|
}
|
| 2542 |
|
|
|
| 2543 |
|
|
/* Mark a symbol as an MRI common symbol. */
|
| 2544 |
|
|
|
| 2545 |
|
|
void
|
| 2546 |
|
|
symbol_mark_mri_common (symbolS *s)
|
| 2547 |
|
|
{
|
| 2548 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2549 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2550 |
|
|
s->sy_mri_common = 1;
|
| 2551 |
|
|
}
|
| 2552 |
|
|
|
| 2553 |
|
|
/* Clear the mark of whether a symbol is an MRI common symbol. */
|
| 2554 |
|
|
|
| 2555 |
|
|
void
|
| 2556 |
|
|
symbol_clear_mri_common (symbolS *s)
|
| 2557 |
|
|
{
|
| 2558 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2559 |
|
|
return;
|
| 2560 |
|
|
s->sy_mri_common = 0;
|
| 2561 |
|
|
}
|
| 2562 |
|
|
|
| 2563 |
|
|
/* Return whether a symbol is an MRI common symbol. */
|
| 2564 |
|
|
|
| 2565 |
|
|
int
|
| 2566 |
|
|
symbol_mri_common_p (symbolS *s)
|
| 2567 |
|
|
{
|
| 2568 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2569 |
|
|
return 0;
|
| 2570 |
|
|
return s->sy_mri_common;
|
| 2571 |
|
|
}
|
| 2572 |
|
|
|
| 2573 |
|
|
/* Mark a symbol as having been written. */
|
| 2574 |
|
|
|
| 2575 |
|
|
void
|
| 2576 |
|
|
symbol_mark_written (symbolS *s)
|
| 2577 |
|
|
{
|
| 2578 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2579 |
|
|
return;
|
| 2580 |
|
|
s->written = 1;
|
| 2581 |
|
|
}
|
| 2582 |
|
|
|
| 2583 |
|
|
/* Clear the mark of whether a symbol has been written. */
|
| 2584 |
|
|
|
| 2585 |
|
|
void
|
| 2586 |
|
|
symbol_clear_written (symbolS *s)
|
| 2587 |
|
|
{
|
| 2588 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2589 |
|
|
return;
|
| 2590 |
|
|
s->written = 0;
|
| 2591 |
|
|
}
|
| 2592 |
|
|
|
| 2593 |
|
|
/* Return whether a symbol has been written. */
|
| 2594 |
|
|
|
| 2595 |
|
|
int
|
| 2596 |
|
|
symbol_written_p (symbolS *s)
|
| 2597 |
|
|
{
|
| 2598 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2599 |
|
|
return 0;
|
| 2600 |
|
|
return s->written;
|
| 2601 |
|
|
}
|
| 2602 |
|
|
|
| 2603 |
|
|
/* Mark a symbol has having been resolved. */
|
| 2604 |
|
|
|
| 2605 |
|
|
void
|
| 2606 |
|
|
symbol_mark_resolved (symbolS *s)
|
| 2607 |
|
|
{
|
| 2608 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2609 |
|
|
{
|
| 2610 |
|
|
local_symbol_mark_resolved ((struct local_symbol *) s);
|
| 2611 |
|
|
return;
|
| 2612 |
|
|
}
|
| 2613 |
|
|
s->sy_resolved = 1;
|
| 2614 |
|
|
}
|
| 2615 |
|
|
|
| 2616 |
|
|
/* Return whether a symbol has been resolved. */
|
| 2617 |
|
|
|
| 2618 |
|
|
int
|
| 2619 |
|
|
symbol_resolved_p (symbolS *s)
|
| 2620 |
|
|
{
|
| 2621 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2622 |
|
|
return local_symbol_resolved_p ((struct local_symbol *) s);
|
| 2623 |
|
|
return s->sy_resolved;
|
| 2624 |
|
|
}
|
| 2625 |
|
|
|
| 2626 |
|
|
/* Return whether a symbol is a section symbol. */
|
| 2627 |
|
|
|
| 2628 |
|
|
int
|
| 2629 |
|
|
symbol_section_p (symbolS *s ATTRIBUTE_UNUSED)
|
| 2630 |
|
|
{
|
| 2631 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2632 |
|
|
return 0;
|
| 2633 |
|
|
return (s->bsym->flags & BSF_SECTION_SYM) != 0;
|
| 2634 |
|
|
}
|
| 2635 |
|
|
|
| 2636 |
|
|
/* Return whether a symbol is equated to another symbol. */
|
| 2637 |
|
|
|
| 2638 |
|
|
int
|
| 2639 |
|
|
symbol_equated_p (symbolS *s)
|
| 2640 |
|
|
{
|
| 2641 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2642 |
|
|
return 0;
|
| 2643 |
|
|
return s->sy_value.X_op == O_symbol;
|
| 2644 |
|
|
}
|
| 2645 |
|
|
|
| 2646 |
|
|
/* Return whether a symbol is equated to another symbol, and should be
|
| 2647 |
|
|
treated specially when writing out relocs. */
|
| 2648 |
|
|
|
| 2649 |
|
|
int
|
| 2650 |
|
|
symbol_equated_reloc_p (symbolS *s)
|
| 2651 |
|
|
{
|
| 2652 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2653 |
|
|
return 0;
|
| 2654 |
|
|
/* X_op_symbol, normally not used for O_symbol, is set by
|
| 2655 |
|
|
resolve_symbol_value to flag expression syms that have been
|
| 2656 |
|
|
equated. */
|
| 2657 |
|
|
return (s->sy_value.X_op == O_symbol
|
| 2658 |
|
|
#if defined (OBJ_COFF) && defined (TE_PE)
|
| 2659 |
|
|
&& ! S_IS_WEAK (s)
|
| 2660 |
|
|
#endif
|
| 2661 |
|
|
&& ((s->sy_resolved && s->sy_value.X_op_symbol != NULL)
|
| 2662 |
|
|
|| ! S_IS_DEFINED (s)
|
| 2663 |
|
|
|| S_IS_COMMON (s)));
|
| 2664 |
|
|
}
|
| 2665 |
|
|
|
| 2666 |
|
|
/* Return whether a symbol has a constant value. */
|
| 2667 |
|
|
|
| 2668 |
|
|
int
|
| 2669 |
|
|
symbol_constant_p (symbolS *s)
|
| 2670 |
|
|
{
|
| 2671 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2672 |
|
|
return 1;
|
| 2673 |
|
|
return s->sy_value.X_op == O_constant;
|
| 2674 |
|
|
}
|
| 2675 |
|
|
|
| 2676 |
|
|
/* Return whether a symbol was cloned and thus removed from the global
|
| 2677 |
|
|
symbol list. */
|
| 2678 |
|
|
|
| 2679 |
|
|
int
|
| 2680 |
|
|
symbol_shadow_p (symbolS *s)
|
| 2681 |
|
|
{
|
| 2682 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2683 |
|
|
return 0;
|
| 2684 |
|
|
return s->sy_next == s;
|
| 2685 |
|
|
}
|
| 2686 |
|
|
|
| 2687 |
|
|
/* Return the BFD symbol for a symbol. */
|
| 2688 |
|
|
|
| 2689 |
|
|
asymbol *
|
| 2690 |
|
|
symbol_get_bfdsym (symbolS *s)
|
| 2691 |
|
|
{
|
| 2692 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2693 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2694 |
|
|
return s->bsym;
|
| 2695 |
|
|
}
|
| 2696 |
|
|
|
| 2697 |
|
|
/* Set the BFD symbol for a symbol. */
|
| 2698 |
|
|
|
| 2699 |
|
|
void
|
| 2700 |
|
|
symbol_set_bfdsym (symbolS *s, asymbol *bsym)
|
| 2701 |
|
|
{
|
| 2702 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2703 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2704 |
|
|
/* Usually, it is harmless to reset a symbol to a BFD section
|
| 2705 |
|
|
symbol. For example, obj_elf_change_section sets the BFD symbol
|
| 2706 |
|
|
of an old symbol with the newly created section symbol. But when
|
| 2707 |
|
|
we have multiple sections with the same name, the newly created
|
| 2708 |
|
|
section may have the same name as an old section. We check if the
|
| 2709 |
|
|
old symbol has been already marked as a section symbol before
|
| 2710 |
|
|
resetting it. */
|
| 2711 |
|
|
if ((s->bsym->flags & BSF_SECTION_SYM) == 0)
|
| 2712 |
|
|
s->bsym = bsym;
|
| 2713 |
|
|
/* else XXX - What do we do now ? */
|
| 2714 |
|
|
}
|
| 2715 |
|
|
|
| 2716 |
|
|
#ifdef OBJ_SYMFIELD_TYPE
|
| 2717 |
|
|
|
| 2718 |
|
|
/* Get a pointer to the object format information for a symbol. */
|
| 2719 |
|
|
|
| 2720 |
|
|
OBJ_SYMFIELD_TYPE *
|
| 2721 |
|
|
symbol_get_obj (symbolS *s)
|
| 2722 |
|
|
{
|
| 2723 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2724 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2725 |
|
|
return &s->sy_obj;
|
| 2726 |
|
|
}
|
| 2727 |
|
|
|
| 2728 |
|
|
/* Set the object format information for a symbol. */
|
| 2729 |
|
|
|
| 2730 |
|
|
void
|
| 2731 |
|
|
symbol_set_obj (symbolS *s, OBJ_SYMFIELD_TYPE *o)
|
| 2732 |
|
|
{
|
| 2733 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2734 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2735 |
|
|
s->sy_obj = *o;
|
| 2736 |
|
|
}
|
| 2737 |
|
|
|
| 2738 |
|
|
#endif /* OBJ_SYMFIELD_TYPE */
|
| 2739 |
|
|
|
| 2740 |
|
|
#ifdef TC_SYMFIELD_TYPE
|
| 2741 |
|
|
|
| 2742 |
|
|
/* Get a pointer to the processor information for a symbol. */
|
| 2743 |
|
|
|
| 2744 |
|
|
TC_SYMFIELD_TYPE *
|
| 2745 |
|
|
symbol_get_tc (symbolS *s)
|
| 2746 |
|
|
{
|
| 2747 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2748 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2749 |
|
|
return &s->sy_tc;
|
| 2750 |
|
|
}
|
| 2751 |
|
|
|
| 2752 |
|
|
/* Set the processor information for a symbol. */
|
| 2753 |
|
|
|
| 2754 |
|
|
void
|
| 2755 |
|
|
symbol_set_tc (symbolS *s, TC_SYMFIELD_TYPE *o)
|
| 2756 |
|
|
{
|
| 2757 |
|
|
if (LOCAL_SYMBOL_CHECK (s))
|
| 2758 |
|
|
s = local_symbol_convert ((struct local_symbol *) s);
|
| 2759 |
|
|
s->sy_tc = *o;
|
| 2760 |
|
|
}
|
| 2761 |
|
|
|
| 2762 |
|
|
#endif /* TC_SYMFIELD_TYPE */
|
| 2763 |
|
|
|
| 2764 |
|
|
void
|
| 2765 |
|
|
symbol_begin (void)
|
| 2766 |
|
|
{
|
| 2767 |
|
|
symbol_lastP = NULL;
|
| 2768 |
|
|
symbol_rootP = NULL; /* In case we have 0 symbols (!!) */
|
| 2769 |
|
|
sy_hash = hash_new ();
|
| 2770 |
|
|
local_hash = hash_new ();
|
| 2771 |
|
|
|
| 2772 |
|
|
memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol));
|
| 2773 |
|
|
#if defined (EMIT_SECTION_SYMBOLS) || !defined (RELOC_REQUIRES_SYMBOL)
|
| 2774 |
|
|
abs_symbol.bsym = bfd_abs_section.symbol;
|
| 2775 |
|
|
#endif
|
| 2776 |
|
|
abs_symbol.sy_value.X_op = O_constant;
|
| 2777 |
|
|
abs_symbol.sy_frag = &zero_address_frag;
|
| 2778 |
|
|
|
| 2779 |
|
|
if (LOCAL_LABELS_FB)
|
| 2780 |
|
|
fb_label_init ();
|
| 2781 |
|
|
}
|
| 2782 |
|
|
|
| 2783 |
|
|
void
|
| 2784 |
|
|
dot_symbol_init (void)
|
| 2785 |
|
|
{
|
| 2786 |
|
|
dot_symbol.bsym = bfd_make_empty_symbol (stdoutput);
|
| 2787 |
|
|
if (dot_symbol.bsym == NULL)
|
| 2788 |
|
|
as_fatal ("bfd_make_empty_symbol: %s", bfd_errmsg (bfd_get_error ()));
|
| 2789 |
|
|
dot_symbol.bsym->name = ".";
|
| 2790 |
|
|
dot_symbol.sy_forward_ref = 1;
|
| 2791 |
|
|
dot_symbol.sy_value.X_op = O_constant;
|
| 2792 |
|
|
}
|
| 2793 |
|
|
|
| 2794 |
|
|
int indent_level;
|
| 2795 |
|
|
|
| 2796 |
|
|
/* Maximum indent level.
|
| 2797 |
|
|
Available for modification inside a gdb session. */
|
| 2798 |
|
|
static int max_indent_level = 8;
|
| 2799 |
|
|
|
| 2800 |
|
|
void
|
| 2801 |
|
|
print_symbol_value_1 (FILE *file, symbolS *sym)
|
| 2802 |
|
|
{
|
| 2803 |
|
|
const char *name = S_GET_NAME (sym);
|
| 2804 |
|
|
if (!name || !name[0])
|
| 2805 |
|
|
name = "(unnamed)";
|
| 2806 |
|
|
fprintf (file, "sym ");
|
| 2807 |
|
|
fprintf_vma (file, (bfd_vma) ((bfd_hostptr_t) sym));
|
| 2808 |
|
|
fprintf (file, " %s", name);
|
| 2809 |
|
|
|
| 2810 |
|
|
if (LOCAL_SYMBOL_CHECK (sym))
|
| 2811 |
|
|
{
|
| 2812 |
|
|
struct local_symbol *locsym = (struct local_symbol *) sym;
|
| 2813 |
|
|
|
| 2814 |
|
|
if (local_symbol_get_frag (locsym) != & zero_address_frag
|
| 2815 |
|
|
&& local_symbol_get_frag (locsym) != NULL)
|
| 2816 |
|
|
{
|
| 2817 |
|
|
fprintf (file, " frag ");
|
| 2818 |
|
|
fprintf_vma (file, (bfd_vma) ((bfd_hostptr_t) local_symbol_get_frag (locsym)));
|
| 2819 |
|
|
}
|
| 2820 |
|
|
if (local_symbol_resolved_p (locsym))
|
| 2821 |
|
|
fprintf (file, " resolved");
|
| 2822 |
|
|
fprintf (file, " local");
|
| 2823 |
|
|
}
|
| 2824 |
|
|
else
|
| 2825 |
|
|
{
|
| 2826 |
|
|
if (sym->sy_frag != &zero_address_frag)
|
| 2827 |
|
|
{
|
| 2828 |
|
|
fprintf (file, " frag ");
|
| 2829 |
|
|
fprintf_vma (file, (bfd_vma) ((bfd_hostptr_t) sym->sy_frag));
|
| 2830 |
|
|
}
|
| 2831 |
|
|
if (sym->written)
|
| 2832 |
|
|
fprintf (file, " written");
|
| 2833 |
|
|
if (sym->sy_resolved)
|
| 2834 |
|
|
fprintf (file, " resolved");
|
| 2835 |
|
|
else if (sym->sy_resolving)
|
| 2836 |
|
|
fprintf (file, " resolving");
|
| 2837 |
|
|
if (sym->sy_used_in_reloc)
|
| 2838 |
|
|
fprintf (file, " used-in-reloc");
|
| 2839 |
|
|
if (sym->sy_used)
|
| 2840 |
|
|
fprintf (file, " used");
|
| 2841 |
|
|
if (S_IS_LOCAL (sym))
|
| 2842 |
|
|
fprintf (file, " local");
|
| 2843 |
|
|
if (S_IS_EXTERNAL (sym))
|
| 2844 |
|
|
fprintf (file, " extern");
|
| 2845 |
|
|
if (S_IS_WEAK (sym))
|
| 2846 |
|
|
fprintf (file, " weak");
|
| 2847 |
|
|
if (S_IS_DEBUG (sym))
|
| 2848 |
|
|
fprintf (file, " debug");
|
| 2849 |
|
|
if (S_IS_DEFINED (sym))
|
| 2850 |
|
|
fprintf (file, " defined");
|
| 2851 |
|
|
}
|
| 2852 |
|
|
if (S_IS_WEAKREFR (sym))
|
| 2853 |
|
|
fprintf (file, " weakrefr");
|
| 2854 |
|
|
if (S_IS_WEAKREFD (sym))
|
| 2855 |
|
|
fprintf (file, " weakrefd");
|
| 2856 |
|
|
fprintf (file, " %s", segment_name (S_GET_SEGMENT (sym)));
|
| 2857 |
|
|
if (symbol_resolved_p (sym))
|
| 2858 |
|
|
{
|
| 2859 |
|
|
segT s = S_GET_SEGMENT (sym);
|
| 2860 |
|
|
|
| 2861 |
|
|
if (s != undefined_section
|
| 2862 |
|
|
&& s != expr_section)
|
| 2863 |
|
|
fprintf (file, " %lx", (unsigned long) S_GET_VALUE (sym));
|
| 2864 |
|
|
}
|
| 2865 |
|
|
else if (indent_level < max_indent_level
|
| 2866 |
|
|
&& S_GET_SEGMENT (sym) != undefined_section)
|
| 2867 |
|
|
{
|
| 2868 |
|
|
indent_level++;
|
| 2869 |
|
|
fprintf (file, "\n%*s<", indent_level * 4, "");
|
| 2870 |
|
|
if (LOCAL_SYMBOL_CHECK (sym))
|
| 2871 |
|
|
fprintf (file, "constant %lx",
|
| 2872 |
|
|
(unsigned long) ((struct local_symbol *) sym)->lsy_value);
|
| 2873 |
|
|
else
|
| 2874 |
|
|
print_expr_1 (file, &sym->sy_value);
|
| 2875 |
|
|
fprintf (file, ">");
|
| 2876 |
|
|
indent_level--;
|
| 2877 |
|
|
}
|
| 2878 |
|
|
fflush (file);
|
| 2879 |
|
|
}
|
| 2880 |
|
|
|
| 2881 |
|
|
void
|
| 2882 |
|
|
print_symbol_value (symbolS *sym)
|
| 2883 |
|
|
{
|
| 2884 |
|
|
indent_level = 0;
|
| 2885 |
|
|
print_symbol_value_1 (stderr, sym);
|
| 2886 |
|
|
fprintf (stderr, "\n");
|
| 2887 |
|
|
}
|
| 2888 |
|
|
|
| 2889 |
|
|
static void
|
| 2890 |
|
|
print_binary (FILE *file, const char *name, expressionS *exp)
|
| 2891 |
|
|
{
|
| 2892 |
|
|
indent_level++;
|
| 2893 |
|
|
fprintf (file, "%s\n%*s<", name, indent_level * 4, "");
|
| 2894 |
|
|
print_symbol_value_1 (file, exp->X_add_symbol);
|
| 2895 |
|
|
fprintf (file, ">\n%*s<", indent_level * 4, "");
|
| 2896 |
|
|
print_symbol_value_1 (file, exp->X_op_symbol);
|
| 2897 |
|
|
fprintf (file, ">");
|
| 2898 |
|
|
indent_level--;
|
| 2899 |
|
|
}
|
| 2900 |
|
|
|
| 2901 |
|
|
void
|
| 2902 |
|
|
print_expr_1 (FILE *file, expressionS *exp)
|
| 2903 |
|
|
{
|
| 2904 |
|
|
fprintf (file, "expr ");
|
| 2905 |
|
|
fprintf_vma (file, (bfd_vma) ((bfd_hostptr_t) exp));
|
| 2906 |
|
|
fprintf (file, " ");
|
| 2907 |
|
|
switch (exp->X_op)
|
| 2908 |
|
|
{
|
| 2909 |
|
|
case O_illegal:
|
| 2910 |
|
|
fprintf (file, "illegal");
|
| 2911 |
|
|
break;
|
| 2912 |
|
|
case O_absent:
|
| 2913 |
|
|
fprintf (file, "absent");
|
| 2914 |
|
|
break;
|
| 2915 |
|
|
case O_constant:
|
| 2916 |
|
|
fprintf (file, "constant %lx", (unsigned long) exp->X_add_number);
|
| 2917 |
|
|
break;
|
| 2918 |
|
|
case O_symbol:
|
| 2919 |
|
|
indent_level++;
|
| 2920 |
|
|
fprintf (file, "symbol\n%*s<", indent_level * 4, "");
|
| 2921 |
|
|
print_symbol_value_1 (file, exp->X_add_symbol);
|
| 2922 |
|
|
fprintf (file, ">");
|
| 2923 |
|
|
maybe_print_addnum:
|
| 2924 |
|
|
if (exp->X_add_number)
|
| 2925 |
|
|
fprintf (file, "\n%*s%lx", indent_level * 4, "",
|
| 2926 |
|
|
(unsigned long) exp->X_add_number);
|
| 2927 |
|
|
indent_level--;
|
| 2928 |
|
|
break;
|
| 2929 |
|
|
case O_register:
|
| 2930 |
|
|
fprintf (file, "register #%d", (int) exp->X_add_number);
|
| 2931 |
|
|
break;
|
| 2932 |
|
|
case O_big:
|
| 2933 |
|
|
fprintf (file, "big");
|
| 2934 |
|
|
break;
|
| 2935 |
|
|
case O_uminus:
|
| 2936 |
|
|
fprintf (file, "uminus -<");
|
| 2937 |
|
|
indent_level++;
|
| 2938 |
|
|
print_symbol_value_1 (file, exp->X_add_symbol);
|
| 2939 |
|
|
fprintf (file, ">");
|
| 2940 |
|
|
goto maybe_print_addnum;
|
| 2941 |
|
|
case O_bit_not:
|
| 2942 |
|
|
fprintf (file, "bit_not");
|
| 2943 |
|
|
break;
|
| 2944 |
|
|
case O_multiply:
|
| 2945 |
|
|
print_binary (file, "multiply", exp);
|
| 2946 |
|
|
break;
|
| 2947 |
|
|
case O_divide:
|
| 2948 |
|
|
print_binary (file, "divide", exp);
|
| 2949 |
|
|
break;
|
| 2950 |
|
|
case O_modulus:
|
| 2951 |
|
|
print_binary (file, "modulus", exp);
|
| 2952 |
|
|
break;
|
| 2953 |
|
|
case O_left_shift:
|
| 2954 |
|
|
print_binary (file, "lshift", exp);
|
| 2955 |
|
|
break;
|
| 2956 |
|
|
case O_right_shift:
|
| 2957 |
|
|
print_binary (file, "rshift", exp);
|
| 2958 |
|
|
break;
|
| 2959 |
|
|
case O_bit_inclusive_or:
|
| 2960 |
|
|
print_binary (file, "bit_ior", exp);
|
| 2961 |
|
|
break;
|
| 2962 |
|
|
case O_bit_exclusive_or:
|
| 2963 |
|
|
print_binary (file, "bit_xor", exp);
|
| 2964 |
|
|
break;
|
| 2965 |
|
|
case O_bit_and:
|
| 2966 |
|
|
print_binary (file, "bit_and", exp);
|
| 2967 |
|
|
break;
|
| 2968 |
|
|
case O_eq:
|
| 2969 |
|
|
print_binary (file, "eq", exp);
|
| 2970 |
|
|
break;
|
| 2971 |
|
|
case O_ne:
|
| 2972 |
|
|
print_binary (file, "ne", exp);
|
| 2973 |
|
|
break;
|
| 2974 |
|
|
case O_lt:
|
| 2975 |
|
|
print_binary (file, "lt", exp);
|
| 2976 |
|
|
break;
|
| 2977 |
|
|
case O_le:
|
| 2978 |
|
|
print_binary (file, "le", exp);
|
| 2979 |
|
|
break;
|
| 2980 |
|
|
case O_ge:
|
| 2981 |
|
|
print_binary (file, "ge", exp);
|
| 2982 |
|
|
break;
|
| 2983 |
|
|
case O_gt:
|
| 2984 |
|
|
print_binary (file, "gt", exp);
|
| 2985 |
|
|
break;
|
| 2986 |
|
|
case O_logical_and:
|
| 2987 |
|
|
print_binary (file, "logical_and", exp);
|
| 2988 |
|
|
break;
|
| 2989 |
|
|
case O_logical_or:
|
| 2990 |
|
|
print_binary (file, "logical_or", exp);
|
| 2991 |
|
|
break;
|
| 2992 |
|
|
case O_add:
|
| 2993 |
|
|
indent_level++;
|
| 2994 |
|
|
fprintf (file, "add\n%*s<", indent_level * 4, "");
|
| 2995 |
|
|
print_symbol_value_1 (file, exp->X_add_symbol);
|
| 2996 |
|
|
fprintf (file, ">\n%*s<", indent_level * 4, "");
|
| 2997 |
|
|
print_symbol_value_1 (file, exp->X_op_symbol);
|
| 2998 |
|
|
fprintf (file, ">");
|
| 2999 |
|
|
goto maybe_print_addnum;
|
| 3000 |
|
|
case O_subtract:
|
| 3001 |
|
|
indent_level++;
|
| 3002 |
|
|
fprintf (file, "subtract\n%*s<", indent_level * 4, "");
|
| 3003 |
|
|
print_symbol_value_1 (file, exp->X_add_symbol);
|
| 3004 |
|
|
fprintf (file, ">\n%*s<", indent_level * 4, "");
|
| 3005 |
|
|
print_symbol_value_1 (file, exp->X_op_symbol);
|
| 3006 |
|
|
fprintf (file, ">");
|
| 3007 |
|
|
goto maybe_print_addnum;
|
| 3008 |
|
|
default:
|
| 3009 |
|
|
fprintf (file, "{unknown opcode %d}", (int) exp->X_op);
|
| 3010 |
|
|
break;
|
| 3011 |
|
|
}
|
| 3012 |
|
|
fflush (stdout);
|
| 3013 |
|
|
}
|
| 3014 |
|
|
|
| 3015 |
|
|
void
|
| 3016 |
|
|
print_expr (expressionS *exp)
|
| 3017 |
|
|
{
|
| 3018 |
|
|
print_expr_1 (stderr, exp);
|
| 3019 |
|
|
fprintf (stderr, "\n");
|
| 3020 |
|
|
}
|
| 3021 |
|
|
|
| 3022 |
|
|
void
|
| 3023 |
|
|
symbol_print_statistics (FILE *file)
|
| 3024 |
|
|
{
|
| 3025 |
|
|
hash_print_statistics (file, "symbol table", sy_hash);
|
| 3026 |
|
|
hash_print_statistics (file, "mini local symbol table", local_hash);
|
| 3027 |
|
|
fprintf (file, "%lu mini local symbols created, %lu converted\n",
|
| 3028 |
|
|
local_symbol_count, local_symbol_conversion_count);
|
| 3029 |
|
|
}
|
| 3030 |
|
|
|
| 3031 |
|
|
#ifdef OBJ_COMPLEX_RELC
|
| 3032 |
|
|
|
| 3033 |
|
|
/* Convert given symbol to a new complex-relocation symbol name. This
|
| 3034 |
|
|
may be a recursive function, since it might be called for non-leaf
|
| 3035 |
|
|
nodes (plain symbols) in the expression tree. The caller owns the
|
| 3036 |
|
|
returning string, so should free it eventually. Errors are
|
| 3037 |
|
|
indicated via as_bad and a NULL return value. The given symbol
|
| 3038 |
|
|
is marked with sy_used_in_reloc. */
|
| 3039 |
|
|
|
| 3040 |
|
|
char *
|
| 3041 |
|
|
symbol_relc_make_sym (symbolS * sym)
|
| 3042 |
|
|
{
|
| 3043 |
|
|
char * terminal = NULL;
|
| 3044 |
|
|
const char * sname;
|
| 3045 |
|
|
char typetag;
|
| 3046 |
|
|
int sname_len;
|
| 3047 |
|
|
|
| 3048 |
|
|
gas_assert (sym != NULL);
|
| 3049 |
|
|
|
| 3050 |
|
|
/* Recurse to symbol_relc_make_expr if this symbol
|
| 3051 |
|
|
is defined as an expression or a plain value. */
|
| 3052 |
|
|
if ( S_GET_SEGMENT (sym) == expr_section
|
| 3053 |
|
|
|| S_GET_SEGMENT (sym) == absolute_section)
|
| 3054 |
|
|
return symbol_relc_make_expr (& sym->sy_value);
|
| 3055 |
|
|
|
| 3056 |
|
|
/* This may be a "fake symbol" L0\001, referring to ".".
|
| 3057 |
|
|
Write out a special null symbol to refer to this position. */
|
| 3058 |
|
|
if (! strcmp (S_GET_NAME (sym), FAKE_LABEL_NAME))
|
| 3059 |
|
|
return xstrdup (".");
|
| 3060 |
|
|
|
| 3061 |
|
|
/* We hope this is a plain leaf symbol. Construct the encoding
|
| 3062 |
|
|
as {S,s}II...:CCCCCCC....
|
| 3063 |
|
|
where 'S'/'s' means section symbol / plain symbol
|
| 3064 |
|
|
III is decimal for the symbol name length
|
| 3065 |
|
|
CCC is the symbol name itself. */
|
| 3066 |
|
|
symbol_mark_used_in_reloc (sym);
|
| 3067 |
|
|
|
| 3068 |
|
|
sname = S_GET_NAME (sym);
|
| 3069 |
|
|
sname_len = strlen (sname);
|
| 3070 |
|
|
typetag = symbol_section_p (sym) ? 'S' : 's';
|
| 3071 |
|
|
|
| 3072 |
|
|
terminal = xmalloc (1 /* S or s */
|
| 3073 |
|
|
+ 8 /* sname_len in decimal */
|
| 3074 |
|
|
+ 1 /* _ spacer */
|
| 3075 |
|
|
+ sname_len /* name itself */
|
| 3076 |
|
|
+ 1 /* \0 */ );
|
| 3077 |
|
|
|
| 3078 |
|
|
sprintf (terminal, "%c%d:%s", typetag, sname_len, sname);
|
| 3079 |
|
|
return terminal;
|
| 3080 |
|
|
}
|
| 3081 |
|
|
|
| 3082 |
|
|
/* Convert given value to a new complex-relocation symbol name. This
|
| 3083 |
|
|
is a non-recursive function, since it is be called for leaf nodes
|
| 3084 |
|
|
(plain values) in the expression tree. The caller owns the
|
| 3085 |
|
|
returning string, so should free() it eventually. No errors. */
|
| 3086 |
|
|
|
| 3087 |
|
|
char *
|
| 3088 |
|
|
symbol_relc_make_value (offsetT val)
|
| 3089 |
|
|
{
|
| 3090 |
|
|
char * terminal = xmalloc (28); /* Enough for long long. */
|
| 3091 |
|
|
|
| 3092 |
|
|
terminal[0] = '#';
|
| 3093 |
|
|
bfd_sprintf_vma (stdoutput, terminal + 1, val);
|
| 3094 |
|
|
return terminal;
|
| 3095 |
|
|
}
|
| 3096 |
|
|
|
| 3097 |
|
|
/* Convert given expression to a new complex-relocation symbol name.
|
| 3098 |
|
|
This is a recursive function, since it traverses the entire given
|
| 3099 |
|
|
expression tree. The caller owns the returning string, so should
|
| 3100 |
|
|
free() it eventually. Errors are indicated via as_bad() and a NULL
|
| 3101 |
|
|
return value. */
|
| 3102 |
|
|
|
| 3103 |
|
|
char *
|
| 3104 |
|
|
symbol_relc_make_expr (expressionS * exp)
|
| 3105 |
|
|
{
|
| 3106 |
|
|
char * opstr = NULL; /* Operator prefix string. */
|
| 3107 |
|
|
int arity = 0; /* Arity of this operator. */
|
| 3108 |
|
|
char * operands[3]; /* Up to three operands. */
|
| 3109 |
|
|
char * concat_string = NULL;
|
| 3110 |
|
|
|
| 3111 |
|
|
operands[0] = operands[1] = operands[2] = NULL;
|
| 3112 |
|
|
|
| 3113 |
|
|
gas_assert (exp != NULL);
|
| 3114 |
|
|
|
| 3115 |
|
|
/* Match known operators -> fill in opstr, arity, operands[] and fall
|
| 3116 |
|
|
through to construct subexpression fragments; may instead return
|
| 3117 |
|
|
string directly for leaf nodes. */
|
| 3118 |
|
|
|
| 3119 |
|
|
/* See expr.h for the meaning of all these enums. Many operators
|
| 3120 |
|
|
have an unnatural arity (X_add_number implicitly added). The
|
| 3121 |
|
|
conversion logic expands them to explicit "+" subexpressions. */
|
| 3122 |
|
|
|
| 3123 |
|
|
switch (exp->X_op)
|
| 3124 |
|
|
{
|
| 3125 |
|
|
default:
|
| 3126 |
|
|
as_bad ("Unknown expression operator (enum %d)", exp->X_op);
|
| 3127 |
|
|
break;
|
| 3128 |
|
|
|
| 3129 |
|
|
/* Leaf nodes. */
|
| 3130 |
|
|
case O_constant:
|
| 3131 |
|
|
return symbol_relc_make_value (exp->X_add_number);
|
| 3132 |
|
|
|
| 3133 |
|
|
case O_symbol:
|
| 3134 |
|
|
if (exp->X_add_number)
|
| 3135 |
|
|
{
|
| 3136 |
|
|
arity = 2;
|
| 3137 |
|
|
opstr = "+";
|
| 3138 |
|
|
operands[0] = symbol_relc_make_sym (exp->X_add_symbol);
|
| 3139 |
|
|
operands[1] = symbol_relc_make_value (exp->X_add_number);
|
| 3140 |
|
|
break;
|
| 3141 |
|
|
}
|
| 3142 |
|
|
else
|
| 3143 |
|
|
return symbol_relc_make_sym (exp->X_add_symbol);
|
| 3144 |
|
|
|
| 3145 |
|
|
/* Helper macros for nesting nodes. */
|
| 3146 |
|
|
|
| 3147 |
|
|
#define HANDLE_XADD_OPT1(str_) \
|
| 3148 |
|
|
if (exp->X_add_number) \
|
| 3149 |
|
|
{ \
|
| 3150 |
|
|
arity = 2; \
|
| 3151 |
|
|
opstr = "+:" str_; \
|
| 3152 |
|
|
operands[0] = symbol_relc_make_sym (exp->X_add_symbol); \
|
| 3153 |
|
|
operands[1] = symbol_relc_make_value (exp->X_add_number); \
|
| 3154 |
|
|
break; \
|
| 3155 |
|
|
} \
|
| 3156 |
|
|
else \
|
| 3157 |
|
|
{ \
|
| 3158 |
|
|
arity = 1; \
|
| 3159 |
|
|
opstr = str_; \
|
| 3160 |
|
|
operands[0] = symbol_relc_make_sym (exp->X_add_symbol); \
|
| 3161 |
|
|
} \
|
| 3162 |
|
|
break
|
| 3163 |
|
|
|
| 3164 |
|
|
#define HANDLE_XADD_OPT2(str_) \
|
| 3165 |
|
|
if (exp->X_add_number) \
|
| 3166 |
|
|
{ \
|
| 3167 |
|
|
arity = 3; \
|
| 3168 |
|
|
opstr = "+:" str_; \
|
| 3169 |
|
|
operands[0] = symbol_relc_make_sym (exp->X_add_symbol); \
|
| 3170 |
|
|
operands[1] = symbol_relc_make_sym (exp->X_op_symbol); \
|
| 3171 |
|
|
operands[2] = symbol_relc_make_value (exp->X_add_number); \
|
| 3172 |
|
|
} \
|
| 3173 |
|
|
else \
|
| 3174 |
|
|
{ \
|
| 3175 |
|
|
arity = 2; \
|
| 3176 |
|
|
opstr = str_; \
|
| 3177 |
|
|
operands[0] = symbol_relc_make_sym (exp->X_add_symbol); \
|
| 3178 |
|
|
operands[1] = symbol_relc_make_sym (exp->X_op_symbol); \
|
| 3179 |
|
|
} \
|
| 3180 |
|
|
break
|
| 3181 |
|
|
|
| 3182 |
|
|
/* Nesting nodes. */
|
| 3183 |
|
|
|
| 3184 |
|
|
case O_uminus: HANDLE_XADD_OPT1 ("0-");
|
| 3185 |
|
|
case O_bit_not: HANDLE_XADD_OPT1 ("~");
|
| 3186 |
|
|
case O_logical_not: HANDLE_XADD_OPT1 ("!");
|
| 3187 |
|
|
case O_multiply: HANDLE_XADD_OPT2 ("*");
|
| 3188 |
|
|
case O_divide: HANDLE_XADD_OPT2 ("/");
|
| 3189 |
|
|
case O_modulus: HANDLE_XADD_OPT2 ("%");
|
| 3190 |
|
|
case O_left_shift: HANDLE_XADD_OPT2 ("<<");
|
| 3191 |
|
|
case O_right_shift: HANDLE_XADD_OPT2 (">>");
|
| 3192 |
|
|
case O_bit_inclusive_or: HANDLE_XADD_OPT2 ("|");
|
| 3193 |
|
|
case O_bit_exclusive_or: HANDLE_XADD_OPT2 ("^");
|
| 3194 |
|
|
case O_bit_and: HANDLE_XADD_OPT2 ("&");
|
| 3195 |
|
|
case O_add: HANDLE_XADD_OPT2 ("+");
|
| 3196 |
|
|
case O_subtract: HANDLE_XADD_OPT2 ("-");
|
| 3197 |
|
|
case O_eq: HANDLE_XADD_OPT2 ("==");
|
| 3198 |
|
|
case O_ne: HANDLE_XADD_OPT2 ("!=");
|
| 3199 |
|
|
case O_lt: HANDLE_XADD_OPT2 ("<");
|
| 3200 |
|
|
case O_le: HANDLE_XADD_OPT2 ("<=");
|
| 3201 |
|
|
case O_ge: HANDLE_XADD_OPT2 (">=");
|
| 3202 |
|
|
case O_gt: HANDLE_XADD_OPT2 (">");
|
| 3203 |
|
|
case O_logical_and: HANDLE_XADD_OPT2 ("&&");
|
| 3204 |
|
|
case O_logical_or: HANDLE_XADD_OPT2 ("||");
|
| 3205 |
|
|
}
|
| 3206 |
|
|
|
| 3207 |
|
|
/* Validate & reject early. */
|
| 3208 |
|
|
if (arity >= 1 && ((operands[0] == NULL) || (strlen (operands[0]) == 0)))
|
| 3209 |
|
|
opstr = NULL;
|
| 3210 |
|
|
if (arity >= 2 && ((operands[1] == NULL) || (strlen (operands[1]) == 0)))
|
| 3211 |
|
|
opstr = NULL;
|
| 3212 |
|
|
if (arity >= 3 && ((operands[2] == NULL) || (strlen (operands[2]) == 0)))
|
| 3213 |
|
|
opstr = NULL;
|
| 3214 |
|
|
|
| 3215 |
|
|
if (opstr == NULL)
|
| 3216 |
|
|
concat_string = NULL;
|
| 3217 |
|
|
else
|
| 3218 |
|
|
{
|
| 3219 |
|
|
/* Allocate new string; include inter-operand padding gaps etc. */
|
| 3220 |
|
|
concat_string = xmalloc (strlen (opstr)
|
| 3221 |
|
|
+ 1
|
| 3222 |
|
|
+ (arity >= 1 ? (strlen (operands[0]) + 1 ) : 0)
|
| 3223 |
|
|
+ (arity >= 2 ? (strlen (operands[1]) + 1 ) : 0)
|
| 3224 |
|
|
+ (arity >= 3 ? (strlen (operands[2]) + 0 ) : 0)
|
| 3225 |
|
|
+ 1);
|
| 3226 |
|
|
gas_assert (concat_string != NULL);
|
| 3227 |
|
|
|
| 3228 |
|
|
/* Format the thing. */
|
| 3229 |
|
|
sprintf (concat_string,
|
| 3230 |
|
|
(arity == 0 ? "%s" :
|
| 3231 |
|
|
arity == 1 ? "%s:%s" :
|
| 3232 |
|
|
arity == 2 ? "%s:%s:%s" :
|
| 3233 |
|
|
/* arity == 3 */ "%s:%s:%s:%s"),
|
| 3234 |
|
|
opstr, operands[0], operands[1], operands[2]);
|
| 3235 |
|
|
}
|
| 3236 |
|
|
|
| 3237 |
|
|
/* Free operand strings (not opstr). */
|
| 3238 |
|
|
if (arity >= 1) xfree (operands[0]);
|
| 3239 |
|
|
if (arity >= 2) xfree (operands[1]);
|
| 3240 |
|
|
if (arity >= 3) xfree (operands[2]);
|
| 3241 |
|
|
|
| 3242 |
|
|
return concat_string;
|
| 3243 |
|
|
}
|
| 3244 |
|
|
|
| 3245 |
|
|
#endif
|