|
|
1.1 ! root 1: /* symbols.c -symbol table- ! 2: Copyright (C) 1987 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GAS, the GNU Assembler. ! 5: ! 6: GAS is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 1, or (at your option) ! 9: any later version. ! 10: ! 11: GAS is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GAS; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: #include <stdlib.h> ! 21: #include <string.h> ! 22: #include "as.h" ! 23: #include "hash.h" ! 24: #include "obstack.h" /* For "symbols.h" */ ! 25: #include "struc-symbol.h" ! 26: #include "symbols.h" ! 27: #include "frags.h" ! 28: #include "expr.h" ! 29: #include "sections.h" ! 30: #include "read.h" ! 31: #include "xmalloc.h" ! 32: #include "messages.h" ! 33: #include "fixes.h" ! 34: #include "input-scrub.h" ! 35: ! 36: /* symbol-name => struct symbol pointer */ ! 37: struct hash_control *sy_hash = NULL; ! 38: ! 39: /* FixS & symbols live here */ ! 40: struct obstack notes = { 0 }; ! 41: ! 42: /* all the symbol nodes */ ! 43: symbolS *symbol_rootP = NULL; ! 44: /* last struct symbol we made, or NULL */ ! 45: symbolS *symbol_lastP = NULL; ! 46: ! 47: symbolS abs_symbol = { 0 }; ! 48: ! 49: /* ! 50: * Un*x idea of local labels. They are made by "n:" where n ! 51: * is any decimal digit. Refer to them with ! 52: * "nb" for previous (backward) n: ! 53: * or "nf" for next (forward) n:. ! 54: * ! 55: * Like Un*x AS, we have one set of local label counters for entire assembly, ! 56: * not one set per (sub)segment like in most assemblers. This implies that ! 57: * one can refer to a label in another segment, and indeed some crufty ! 58: * compilers have done just that. ! 59: * ! 60: * I document the symbol names here to save duplicating words elsewhere. ! 61: * The mth occurence of label n: is turned into the symbol "Ln^Am" where ! 62: * n is a digit and m is a decimal number. "L" makes it a label discarded ! 63: * unless debugging and "^A"('\1') ensures no ordinary symbol SHOULD get the ! 64: * same name as a local label symbol. The first "4:" is "L4^A1" - the m ! 65: * numbers begin at 1. ! 66: */ ! 67: ! 68: typedef short unsigned int local_label_countT; ! 69: ! 70: static local_label_countT local_label_counter[10]; ! 71: ! 72: static /* Returned to caller, then copied. */ ! 73: char symbol_name_build[12]; /* used for created names ("4f") */ ! 74: ! 75: static void make_stab_for_symbol( ! 76: symbolS *symbolP); ! 77: ! 78: ! 79: void ! 80: symbol_begin( ! 81: void) ! 82: { ! 83: symbol_lastP = NULL; ! 84: symbol_rootP = NULL; /* In case we have 0 symbols (!!) */ ! 85: sy_hash = hash_new(); ! 86: memset((char *)(&abs_symbol), '\0', sizeof(abs_symbol)); ! 87: abs_symbol.sy_type = N_ABS; /* Can't initialise a union. Sigh. */ ! 88: memset((char *)(local_label_counter), '\0', sizeof(local_label_counter) ); ! 89: } ! 90: ! 91: /* ! 92: * local_label_name() ! 93: * ! 94: * Caller must copy returned name: we re-use the area for the next name. ! 95: */ ! 96: char * /* Return local label name. */ ! 97: local_label_name( ! 98: int n, /* we just saw "n:", "nf" or "nb" : n a digit */ ! 99: int augend) /* 0 for nb, 1 for n:, nf */ ! 100: { ! 101: register char * p; ! 102: register char * q; ! 103: char symbol_name_temporary[10]; /* build up a number, BACKWARDS */ ! 104: ! 105: know( n >= 0 ); ! 106: know( augend == 0 || augend == 1 ); ! 107: p = symbol_name_build; ! 108: * p ++ = 'L'; ! 109: * p ++ = n + '0'; /* Make into ASCII */ ! 110: * p ++ = 1; /* ^A */ ! 111: n = local_label_counter [ n ] + augend; ! 112: /* version number of this local label */ ! 113: /* ! 114: * Next code just does sprintf( {}, "%d", n); ! 115: * It is more elegant to do the next part recursively, but a procedure ! 116: * call for each digit emitted is considered too costly. ! 117: */ ! 118: q = symbol_name_temporary; ! 119: for (*q++=0; n; q++) /* emits NOTHING if n starts as 0 */ ! 120: { ! 121: know(n>0); /* We expect n > 0 always */ ! 122: *q = n % 10 + '0'; ! 123: n /= 10; ! 124: } ! 125: while (( * p ++ = * -- q )) ! 126: { ! 127: } ! 128: /* The label, as a '\0' ended string, starts at symbol_name_build. */ ! 129: return (symbol_name_build); ! 130: } ! 131: ! 132: void ! 133: local_colon( ! 134: int n) /* just saw "n:" */ ! 135: { ! 136: local_label_counter [n] ++; ! 137: colon (local_label_name (n, 0)); ! 138: } ! 139: ! 140: /* ! 141: * symbol_new() ! 142: * ! 143: * Return a pointer to a new symbol. ! 144: * Die if we can't make a new symbol. ! 145: * Fill in the symbol's values. ! 146: * Add symbol to end of symbol chain. ! 147: * ! 148: * ! 149: * Please always call this to create a new symbol. ! 150: * ! 151: * Changes since 1985: Symbol names may not contain '\0'. Sigh. ! 152: */ ! 153: symbolS * ! 154: symbol_new( ! 155: char *name, /* We copy this: OK to alter your copy. */ ! 156: unsigned char type, /* As in <nlist.h>. */ ! 157: char other, /* As in <nlist.h>. */ ! 158: short desc, /* As in <nlist.h>. */ ! 159: valueT value, /* As in <nlist.h>, often an address. */ ! 160: /* Often used as offset from frag address. */ ! 161: struct frag *frag) /* For sy_frag. */ ! 162: { ! 163: register symbolS * symbolP; ! 164: register char * preserved_copy_of_name; ! 165: register unsigned int name_length; ! 166: char * p; ! 167: ! 168: name_length = strlen(name) + 1; ! 169: obstack_grow(¬es,name,name_length); ! 170: p=obstack_finish(¬es); ! 171: /* obstack_1done( ¬es, name, name_length, &p ); */ ! 172: preserved_copy_of_name = p; ! 173: p=obstack_alloc(¬es,sizeof(struct symbol)); ! 174: /* obstack_1blank( ¬es, sizeof(struct symbol), &p ); */ ! 175: symbolP = (symbolS *) p; ! 176: symbolP -> sy_name = preserved_copy_of_name; ! 177: symbolP -> sy_type = type; ! 178: symbolP -> sy_other = other; ! 179: symbolP -> sy_desc = desc; ! 180: symbolP -> sy_value = value; ! 181: symbolP -> sy_frag = frag; ! 182: symbolP -> sy_next = NULL; /* End of chain. */ ! 183: symbolP -> sy_forward = NULL; /* JF */ ! 184: #ifdef SUSPECT ! 185: symbolP -> sy_name_offset = ~ 0; /* Impossible offset catches errors. */ ! 186: symbolP -> sy_number = ~ 0; /* Ditto. */ ! 187: #endif ! 188: /* ! 189: * Link to end of symbol chain. ! 190: */ ! 191: if (symbol_lastP) ! 192: { ! 193: symbol_lastP -> sy_next = symbolP; ! 194: } ! 195: else ! 196: { ! 197: symbol_rootP = symbolP; ! 198: } ! 199: symbol_lastP = symbolP; ! 200: ! 201: return (symbolP); ! 202: } ! 203: ! 204: /* ! 205: * colon() ! 206: * ! 207: * We have just seen "<name>:". ! 208: * Creates a struct symbol unless it already exists. ! 209: * ! 210: * Gripes if we are redefining a symbol incompatibly (and ignores it). ! 211: * ! 212: */ ! 213: void ! 214: colon( /* just seen "x:" - rattle symbols & frags */ ! 215: char *sym_name) /* symbol name, as a cannonical string */ ! 216: /* We copy this string: OK to alter later. */ ! 217: { ! 218: register struct symbol * symbolP; /* symbol we are working with */ ! 219: ! 220: if (frchain_now == NULL) ! 221: { ! 222: know(flagseen['n']); ! 223: as_fatal("with -n a section directive must be seen before assembly " ! 224: "can begin"); ! 225: } ! 226: if ((symbolP = symbol_table_lookup( sym_name ))) ! 227: { ! 228: /* ! 229: * Now check for undefined symbols ! 230: */ ! 231: if ((symbolP -> sy_type & N_TYPE) == N_UNDF) ! 232: { ! 233: if( symbolP -> sy_other == 0 ! 234: /* -O causes this not to work */ ! 235: && ((symbolP->sy_desc) & (~REFERENCE_TYPE)) == 0 ! 236: && symbolP -> sy_value == 0) ! 237: { ! 238: symbolP -> sy_frag = frag_now; ! 239: symbolP -> sy_value = obstack_next_free(& frags) - frag_now -> fr_literal; ! 240: know( N_UNDF == 0 ); ! 241: symbolP -> sy_type |= N_SECT; /* keep N_EXT bit */ ! 242: symbolP -> sy_other = frchain_now->frch_nsect; ! 243: symbolP -> sy_desc &= ~REFERENCE_TYPE; ! 244: #ifdef NeXT /* generate stabs for debugging assembly code */ ! 245: if(flagseen['g']) ! 246: make_stab_for_symbol(symbolP); ! 247: #endif ! 248: } ! 249: else ! 250: { ! 251: as_fatal( "Symbol \"%s\" is already defined as \"%s\"/%d.%d.%ld.", ! 252: sym_name, ! 253: seg_name [(int) N_TYPE_seg [symbolP -> sy_type & N_TYPE]], ! 254: symbolP -> sy_other, symbolP -> sy_desc, ! 255: symbolP -> sy_value); ! 256: } ! 257: } ! 258: else ! 259: { ! 260: as_fatal("Symbol %s already defined.",sym_name); ! 261: } ! 262: } ! 263: else ! 264: { ! 265: symbolP = symbol_new (sym_name, ! 266: N_SECT, ! 267: frchain_now->frch_nsect, ! 268: 0, ! 269: (valueT)(obstack_next_free(&frags)-frag_now->fr_literal), ! 270: frag_now); ! 271: symbol_table_insert (symbolP); ! 272: #ifdef NeXT /* generate stabs for debugging assembly code */ ! 273: if(flagseen['g']) ! 274: make_stab_for_symbol(symbolP); ! 275: #endif ! 276: } ! 277: } ! 278: ! 279: ! 280: /* ! 281: * symbol_table_insert() ! 282: * ! 283: * Die if we can't insert the symbol. ! 284: * ! 285: */ ! 286: void ! 287: symbol_table_insert( ! 288: struct symbol *symbolP) ! 289: { ! 290: register char * error_string; ! 291: ! 292: know( symbolP ); ! 293: know( symbolP -> sy_name ); ! 294: if ( * (error_string = hash_jam (sy_hash, symbolP -> sy_name, (char *)symbolP))) ! 295: { ! 296: as_fatal( "Inserting \"%s\" into symbol table failed: %s", ! 297: symbolP -> sy_name, error_string); ! 298: } ! 299: } ! 300: ! 301: /* ! 302: * symbol_find_or_make() ! 303: * ! 304: * If a symbol name does not exist, create it as undefined, and insert ! 305: * it into the symbol table. Return a pointer to it. ! 306: */ ! 307: symbolS * ! 308: symbol_find_or_make( ! 309: char *name) ! 310: { ! 311: register symbolS * symbolP; ! 312: ! 313: symbolP = symbol_table_lookup (name); ! 314: if (symbolP == NULL) ! 315: { ! 316: symbolP = symbol_new (name, N_UNDF, 0, 0, 0, & zero_address_frag); ! 317: symbol_table_insert (symbolP); ! 318: } ! 319: return (symbolP); ! 320: } ! 321: ! 322: /* ! 323: * symbol_find() ! 324: * ! 325: * Implement symbol table lookup. ! 326: * In: A symbol's name as a string: '\0' can't be part of a symbol name. ! 327: * Out: NULL if the name was not in the symbol table, else the address ! 328: * of a struct symbol associated with that name. ! 329: */ ! 330: symbolS * ! 331: symbol_find( ! 332: char *name) ! 333: { ! 334: return ( (symbolS *) hash_find( sy_hash, name )); ! 335: } ! 336: ! 337: #ifdef NeXT /* generate stabs for debugging assembly code */ ! 338: /* ! 339: * make_stab_for_symbol() is called when -g is present for a label that is ! 340: * being defined. If the label is a text label and in the (__TEXT,__text) ! 341: * section and not a local label create a stab for it. ! 342: * ! 343: * See the detailed comments about stabs in read_a_source_file() for a ! 344: * description of what is going on here. ! 345: */ ! 346: static ! 347: void ! 348: make_stab_for_symbol( ! 349: symbolS *symbolP) ! 350: { ! 351: symbolS *stab; ! 352: int stabnamelen; ! 353: char *stabname; ! 354: ! 355: if(symbolP->sy_name[0] == 'L') ! 356: return; ! 357: if((symbolP->sy_type & N_TYPE) != N_SECT) ! 358: return; ! 359: if(symbolP->sy_other != text_nsect) ! 360: return; ! 361: ! 362: stabnamelen = strlen(symbolP->sy_name) + sizeof(":f3"); ! 363: stabname = xmalloc(stabnamelen); ! 364: strcpy(stabname, symbolP->sy_name); ! 365: if(symbolP->sy_type & N_EXT) ! 366: strcat(stabname, ":F3"); ! 367: else ! 368: strcat(stabname, ":f3"); ! 369: ! 370: stab = symbol_new( ! 371: stabname, ! 372: 36, /* N_FUN */ ! 373: text_nsect, /* n_sect */ ! 374: logical_input_line, /* n_desc, line number */ ! 375: symbolP->sy_value, ! 376: symbolP->sy_frag); ! 377: free(stabname); ! 378: } ! 379: #endif /* NeXT generate stabs for debugging assembly code */ ! 380: ! 381: /* ! 382: * indirect_symbol_new() ! 383: * ! 384: * Return a pointer to a new indirect_symbol. ! 385: * Die if we can't make a new indirect_symbol. ! 386: * Fill in the indirect_symbol's values. ! 387: * Add symbol to end of section's indirect symbol chain. ! 388: */ ! 389: isymbolS * ! 390: indirect_symbol_new( ! 391: char *name, /* We copy this: OK to alter your copy. */ ! 392: struct frag *frag, /* For sy_frag. */ ! 393: unsigned long offset) /* Offset from frag address. */ ! 394: { ! 395: isymbolS *isymbolP; ! 396: char *preserved_copy_of_name; ! 397: unsigned long name_length; ! 398: char *p; ! 399: struct frag *fr_next; ! 400: #ifdef CHECK_INDIRECTS ! 401: unsigned long stride, fr_fix; ! 402: #endif ! 403: ! 404: /* ! 405: * First see if the last frag recorded for an indirect symbol turned ! 406: * out to be zero sized then changed that recorded frag to the next ! 407: * non-zero frag in the list. I think this happens because we record ! 408: * the frag before we fill it and if we run out of space that frag gets ! 409: * a zero size and a new one is created. ! 410: */ ! 411: if(frchain_now->frch_isym_last != NULL && ! 412: frchain_now->frch_isym_last->isy_frag->fr_fix == 0){ ! 413: if(frchain_now->frch_isym_last->isy_frag->fr_next != NULL){ ! 414: fr_next = frchain_now->frch_isym_last->isy_frag->fr_next; ! 415: while(fr_next->fr_fix == 0 && ! 416: fr_next->fr_type == rs_fill && ! 417: fr_next->fr_next != NULL) ! 418: fr_next = fr_next->fr_next; ! 419: frchain_now->frch_isym_last->isy_frag = fr_next; ! 420: } ! 421: } ! 422: ! 423: name_length = strlen(name) + 1; ! 424: obstack_grow(¬es, name, name_length); ! 425: p = obstack_finish(¬es); ! 426: preserved_copy_of_name = p; ! 427: p = obstack_alloc(¬es, sizeof(struct indirect_symbol)); ! 428: isymbolP = (isymbolS *)p; ! 429: isymbolP->isy_name = preserved_copy_of_name; ! 430: isymbolP->isy_offset = offset; ! 431: isymbolP->isy_frag = frag; ! 432: isymbolP->isy_next = NULL; /* End of chain. */ ! 433: isymbolP->isy_symbol = NULL; ! 434: ! 435: /* ! 436: * Link to end of indirect symbol chain and check for missing indirect ! 437: * symbols. ! 438: */ ! 439: if(frchain_now->frch_isym_root == NULL){ ! 440: #ifdef CHECK_INDIRECTS ! 441: if(offset != 0) ! 442: as_warn("missing or bad indirect symbol for section (%s,%s)", ! 443: frchain_now->frch_section.segname, ! 444: frchain_now->frch_section.sectname); ! 445: #endif ! 446: frchain_now->frch_isym_root = isymbolP; ! 447: frchain_now->frch_isym_last = isymbolP; ! 448: } ! 449: else{ ! 450: #ifdef CHECK_INDIRECTS ! 451: if((frchain_now->frch_section.flags & SECTION_TYPE) == ! 452: S_SYMBOL_STUBS) ! 453: stride = frchain_now->frch_section.reserved2; ! 454: else ! 455: stride = sizeof(unsigned long); ! 456: if(frag == frchain_now->frch_isym_last->isy_frag){ ! 457: if(offset - frchain_now->frch_isym_last->isy_offset != stride) ! 458: as_warn("missing or bad indirect symbol for section " ! 459: "(%s,%s)", frchain_now->frch_section.segname, ! 460: frchain_now->frch_section.sectname); ! 461: } ! 462: else{ ! 463: if(frchain_now->frch_isym_last->isy_frag->fr_fix < stride){ ! 464: fr_fix = 0; ! 465: fr_next = frchain_now->frch_isym_last->isy_frag; ! 466: while(fr_fix + fr_next->fr_fix < stride && ! 467: fr_next->fr_type == rs_fill && ! 468: fr_next->fr_next != NULL){ ! 469: fr_fix += fr_next->fr_fix; ! 470: fr_next = fr_next->fr_next; ! 471: } ! 472: if(frag != fr_next->fr_next || ! 473: fr_fix + fr_next->fr_fix != stride || ! 474: offset != 0) ! 475: as_warn("missing or bad indirect symbol for section " ! 476: "(%s,%s)", frchain_now->frch_section.segname, ! 477: frchain_now->frch_section.sectname); ! 478: } ! 479: else{ ! 480: fr_next = frchain_now->frch_isym_last->isy_frag->fr_next; ! 481: /* ! 482: * Because of section changes there maybe some zero length ! 483: * frags after the last one that passed through here. So ! 484: * skip them and get to the last real one. ! 485: */ ! 486: while(fr_next->fr_fix == 0 && ! 487: fr_next->fr_type == rs_fill && ! 488: fr_next->fr_next != NULL) ! 489: fr_next = fr_next->fr_next; ! 490: if(frag != fr_next || offset != 0) ! 491: as_warn("missing or bad indirect symbol for section " ! 492: "(%s,%s)", frchain_now->frch_section.segname, ! 493: frchain_now->frch_section.sectname); ! 494: } ! 495: } ! 496: #endif ! 497: frchain_now->frch_isym_last->isy_next = isymbolP; ! 498: frchain_now->frch_isym_last = isymbolP; ! 499: } ! 500: return(isymbolP); ! 501: } ! 502: ! 503: /* end: symbols.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.