symbols.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,503 行 · 第 1/4 页
C
2,503 行
{ if (islower (c)) c = toupper (c); *copy++ = c; } *copy = '\0'; }#ifdef BFD_ASSEMBLER { struct local_symbol *locsym; locsym = (struct local_symbol *) hash_find (local_hash, name); if (locsym != NULL) return (symbolS *) locsym; }#endif return ((symbolS *) hash_find (sy_hash, name));}/* Once upon a time, symbols were kept in a singly linked list. At least coff needs to be able to rearrange them from time to time, for which a doubly linked list is much more convenient. Loic did these as macros which seemed dangerous to me so they're now functions. xoxorich. *//* Link symbol ADDME after symbol TARGET in the chain. */voidsymbol_append (addme, target, rootPP, lastPP) symbolS *addme; symbolS *target; symbolS **rootPP; symbolS **lastPP;{ if (LOCAL_SYMBOL_CHECK (addme)) abort (); if (target != NULL && LOCAL_SYMBOL_CHECK (target)) abort (); if (target == NULL) { know (*rootPP == NULL); know (*lastPP == NULL); addme->sy_next = NULL;#ifdef SYMBOLS_NEED_BACKPOINTERS addme->sy_previous = NULL;#endif *rootPP = addme; *lastPP = addme; return; } /* if the list is empty */ if (target->sy_next != NULL) {#ifdef SYMBOLS_NEED_BACKPOINTERS target->sy_next->sy_previous = addme;#endif /* SYMBOLS_NEED_BACKPOINTERS */ } else { know (*lastPP == target); *lastPP = addme; } /* if we have a next */ addme->sy_next = target->sy_next; target->sy_next = addme;#ifdef SYMBOLS_NEED_BACKPOINTERS addme->sy_previous = target;#endif /* SYMBOLS_NEED_BACKPOINTERS */ debug_verify_symchain (symbol_rootP, symbol_lastP);}/* Set the chain pointers of SYMBOL to null. */voidsymbol_clear_list_pointers (symbolP) symbolS *symbolP;{ if (LOCAL_SYMBOL_CHECK (symbolP)) abort (); symbolP->sy_next = NULL;#ifdef SYMBOLS_NEED_BACKPOINTERS symbolP->sy_previous = NULL;#endif}#ifdef SYMBOLS_NEED_BACKPOINTERS/* Remove SYMBOLP from the list. */voidsymbol_remove (symbolP, rootPP, lastPP) symbolS *symbolP; symbolS **rootPP; symbolS **lastPP;{ if (LOCAL_SYMBOL_CHECK (symbolP)) abort (); if (symbolP == *rootPP) { *rootPP = symbolP->sy_next; } /* if it was the root */ if (symbolP == *lastPP) { *lastPP = symbolP->sy_previous; } /* if it was the tail */ if (symbolP->sy_next != NULL) { symbolP->sy_next->sy_previous = symbolP->sy_previous; } /* if not last */ if (symbolP->sy_previous != NULL) { symbolP->sy_previous->sy_next = symbolP->sy_next; } /* if not first */ debug_verify_symchain (*rootPP, *lastPP);}/* Link symbol ADDME before symbol TARGET in the chain. */voidsymbol_insert (addme, target, rootPP, lastPP) symbolS *addme; symbolS *target; symbolS **rootPP; symbolS **lastPP ATTRIBUTE_UNUSED;{ if (LOCAL_SYMBOL_CHECK (addme)) abort (); if (LOCAL_SYMBOL_CHECK (target)) abort (); if (target->sy_previous != NULL) { target->sy_previous->sy_next = addme; } else { know (*rootPP == target); *rootPP = addme; } /* if not first */ addme->sy_previous = target->sy_previous; target->sy_previous = addme; addme->sy_next = target; debug_verify_symchain (*rootPP, *lastPP);}#endif /* SYMBOLS_NEED_BACKPOINTERS */voidverify_symbol_chain (rootP, lastP) symbolS *rootP; symbolS *lastP;{ symbolS *symbolP = rootP; if (symbolP == NULL) return; for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP)) {#ifdef BFD_ASSEMBLER assert (symbolP->bsym != NULL);#endif#ifdef SYMBOLS_NEED_BACKPOINTERS assert (symbolP->sy_next->sy_previous == symbolP);#else /* Walk the list anyways, to make sure pointers are still good. */ ;#endif /* SYMBOLS_NEED_BACKPOINTERS */ } assert (lastP == symbolP);}voidverify_symbol_chain_2 (sym) symbolS *sym;{ symbolS *p = sym, *n = sym;#ifdef SYMBOLS_NEED_BACKPOINTERS while (symbol_previous (p)) p = symbol_previous (p);#endif while (symbol_next (n)) n = symbol_next (n); verify_symbol_chain (p, n);}/* Resolve the value of a symbol. This is called during the final pass over the symbol table to resolve any symbols with complex values. */valueTresolve_symbol_value (symp, finalize) symbolS *symp; int finalize;{ int resolved; valueT final_val; segT final_seg;#ifdef BFD_ASSEMBLER if (LOCAL_SYMBOL_CHECK (symp)) { struct local_symbol *locsym = (struct local_symbol *) symp; if (local_symbol_resolved_p (locsym)) return locsym->lsy_offset / bfd_octets_per_byte (stdoutput); final_val = (local_symbol_get_frag (locsym)->fr_address + locsym->lsy_offset) / bfd_octets_per_byte (stdoutput); if (finalize) { locsym->lsy_offset = final_val; local_symbol_mark_resolved (locsym); } return final_val; }#endif if (symp->sy_resolved) { if (symp->sy_value.X_op == O_constant) return (valueT) symp->sy_value.X_add_number; else return 0; } resolved = 0; final_seg = S_GET_SEGMENT (symp); if (symp->sy_resolving) { if (finalize) as_bad (_("Symbol definition loop encountered at %s"), S_GET_NAME (symp)); final_val = 0; resolved = 1; } else { symbolS *add_symbol, *op_symbol; offsetT left, right; segT seg_left, seg_right; operatorT op; symp->sy_resolving = 1; /* Help out with CSE. */ add_symbol = symp->sy_value.X_add_symbol; op_symbol = symp->sy_value.X_op_symbol; final_val = symp->sy_value.X_add_number; op = symp->sy_value.X_op; switch (op) { default: BAD_CASE (op); break; case O_absent: final_val = 0; /* Fall through. */ case O_constant: final_val += symp->sy_frag->fr_address / OCTETS_PER_BYTE; if (final_seg == expr_section) final_seg = absolute_section; resolved = 1; break; case O_symbol: case O_symbol_rva: left = resolve_symbol_value (add_symbol, finalize); do_symbol: if (symp->sy_mri_common) { /* This is a symbol inside an MRI common section. The relocation routines are going to handle it specially. Don't change the value. */ resolved = symbol_resolved_p (add_symbol); break; } if (finalize && final_val == 0) { if (LOCAL_SYMBOL_CHECK (add_symbol)) add_symbol = local_symbol_convert ((struct local_symbol *) add_symbol); copy_symbol_attributes (symp, add_symbol); } /* If we have equated this symbol to an undefined symbol, we keep X_op set to O_symbol, and we don't change X_add_number. This permits the routine which writes out relocation to detect this case, and convert the relocation to be against the symbol to which this symbol is equated. */ if (! S_IS_DEFINED (add_symbol) || S_IS_COMMON (add_symbol)) { if (finalize) { S_SET_SEGMENT (symp, S_GET_SEGMENT (add_symbol)); symp->sy_value.X_op = O_symbol; symp->sy_value.X_add_symbol = add_symbol; symp->sy_value.X_add_number = final_val; } final_val = 0; resolved = symbol_resolved_p (add_symbol); goto exit_dont_set_value; } else { final_val += symp->sy_frag->fr_address + left; if (final_seg == expr_section || final_seg == undefined_section) final_seg = S_GET_SEGMENT (add_symbol); } resolved = symbol_resolved_p (add_symbol); break; case O_uminus: case O_bit_not: case O_logical_not: left = resolve_symbol_value (add_symbol, finalize); if (op == O_uminus) left = -left; else if (op == O_logical_not) left = !left; else left = ~left; final_val += left + symp->sy_frag->fr_address; if (final_seg == expr_section || final_seg == undefined_section) final_seg = absolute_section; resolved = symbol_resolved_p (add_symbol); break; case O_multiply: case O_divide: case O_modulus: case O_left_shift: case O_right_shift: case O_bit_inclusive_or: case O_bit_or_not: case O_bit_exclusive_or: case O_bit_and: case O_add: case O_subtract: case O_eq: case O_ne: case O_lt: case O_le: case O_ge: case O_gt: case O_logical_and: case O_logical_or: left = resolve_symbol_value (add_symbol, finalize); right = resolve_symbol_value (op_symbol, finalize); seg_left = S_GET_SEGMENT (add_symbol); seg_right = S_GET_SEGMENT (op_symbol); /* Simplify addition or subtraction of a constant by folding the constant into X_add_number. */ if (op == O_add || op == O_subtract) { if (seg_right == absolute_section) { if (op == O_add) final_val += right; else final_val -= right; op = O_symbol; op_symbol = NULL; goto do_symbol; } else if (seg_left == absolute_section && op == O_add) { op = O_symbol; final_val += left; add_symbol = op_symbol; left = right; op_symbol = NULL; goto do_symbol; } } /* Subtraction is permitted if both operands are in the same section. Otherwise, both operands must be absolute. We already handled the case of addition or subtraction of a constant above. This will probably need to be changed for an object file format which supports arbitrary expressions, such as IEEE-695. */ /* Don't emit messages unless we're finalizing the symbol value, otherwise we may get the same message multiple times. */ if ((seg_left != absolute_section || seg_right != absolute_section) && (op != O_subtract || seg_left != seg_right || seg_left == undefined_section) && finalize) { char *file; unsigned int line; if (expr_symbol_where (symp, &file, &line)) { if (seg_left == undefined_section) as_bad_where (file, line, _("undefined symbol %s in operation"), S_GET_NAME (symp->sy_value.X_add_symbol)); if (seg_right == undefined_section) as_bad_where (file, line, _("undefined symbol %s in operation"), S_GET_NAME (symp->sy_value.X_op_symbol)); if (seg_left != undefined_section && seg_right != undefined_section) as_bad_where (file, line, _("invalid section for operation")); } else { if (seg_left == undefined_section) as_bad (_("undefined symbol %s in operation setting %s"), S_GET_NAME (symp->sy_value.X_add_symbol), S_GET_NAME (symp)); if (seg_right == undefined_section) as_bad (_("undefined symbol %s in operation setting %s"), S_GET_NAME (symp->sy_value.X_op_symbol), S_GET_NAME (symp)); if (seg_left != undefined_section && seg_right != undefined_section) as_bad (_("invalid section for operation setting %s"), S_GET_NAME (symp)); } } /* Check for division by zero. */ if ((op == O_divide || op == O_modulus) && right == 0) { /* If seg_right is not absolute_section, then we've already issued a warning about using a bad symbol. */ if (seg_right == absolute_section && finalize) { char *file; unsigned int line; if (expr_symbol_where (symp, &file, &line)) as_bad_where (file, line, _("division by zero")); else as_bad (_("division by zero when setting %s"), S_GET_NAME (symp)); } right = 1; } switch (symp->sy_value.X_op) { case O_multiply: left *= right; break; case O_divide: left /= right; break; case O_modulus: left %= right; break; case O_left_shift: left <<= right; break; case O_right_shift: left >>= right; break; case O_bit_inclusive_or: left |= right; break; case O_bit_or_not: left |= ~right; break; case O_bit_exclusive_or: left ^= right; break; case O_bit_and: left &= right; break; case O_add: left += right; break; case O_subtract: left -= right; break; case O_eq: left = left == right ? ~ (offsetT) 0 : 0; break; case O_ne: left = left != right ? ~ (offsetT) 0 : 0; break; case O_lt: left = left < right ? ~ (offsetT) 0 : 0; break; case O_le: left = left <= right ? ~ (offsetT) 0 : 0; break; case O_ge: left = left >= right ? ~ (offsetT) 0 : 0; break; case O_gt: left = left > right ? ~ (offsetT) 0 : 0; break; case O_logical_and: left = left && right; break; case O_logical_or: left = left || right; break; default: abort (); } final_val += symp->sy_frag->fr_address + left; if (final_seg == expr_section || final_seg == undefined_section) final_seg = absolute_section; resolved = (symbol_resolved_p (add_symbol) && symbol_resolved_p (op_symbol)); break; case O_register: case O_big: case O_illegal: /* Give an error (below) if not in expr_section. We don't want to worry about expr_section symbols, because they are fictional (they are created as part of expression resolution), and any problems may not actually mean anything. */ break; } symp->sy_resolving = 0; } if (finalize) { S_SET_VALUE (symp, final_val);#if defined (OBJ_AOUT) && ! defined (BFD_ASSEMBLER) /* The old a.out backend does not handle S_SET_SEGMENT correctly for a stab symbol, so we use this bad hack. */ if (final_seg != S_GET_SEGMENT (symp))#endif S_SET_SEGMENT (symp, final_seg); }exit_dont_set_value: /* Don't worry if we can't resolve an expr_section symbol. */ if (finalize) { if (resolved) symp->sy_resolved = 1; else if (S_GET_SEGMENT (symp) != expr_section) { as_bad (_("can't resolve value for symbol \"%s\""), S_GET_NAME (symp)); symp->sy_resolved = 1; } } return final_val;}#ifdef BFD_ASSEMBLERstatic void resolve_local_symbol PARAMS ((const char *, PTR));/* A static function passed to hash_traverse. */static voidresolve_local_symbol (key, value) const char *key ATTRIBUTE_UNUSED; PTR value;{ if (value != NULL) resolve_symbol_value (value, 1);}#endif/* Resolve all local symbols. */voidresolve_local_symbol_values (){#ifdef BFD_ASSEMBLER hash_traverse (local_hash, resolve_local_symbol);#endif}/* Dollar labels look like a number followed by a dollar sign. Eg, "42$". They are *really* local. That is, they go out of scope whenever we see a label that isn't local. Also, like fb labels, there can be multiple instances of a dollar label. Therefor, we name encode each instance with the instance number, keep a list of defined symbols separate from the real symbol table, and we treat these buggers as a sparse array. */static long *dollar_labels;static long *dollar_label_instances;static char *dollar_label_defines;static unsigned long dollar_label_count;static unsigned long dollar_label_max;intdollar_label_defined (label) long label;{ long *i; know ((dollar_labels != NULL) || (dollar_label_count == 0)); for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i) if (*i == label) return dollar_label_defines[i - dollar_labels]; /* If we get here, label isn't defined. */ return 0;}static longdollar_label_instance (label) long label;{ long *i; know ((dollar_labels != NULL) || (dollar_label_count == 0)); for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i) if (*i == label) return (dollar_label_instances[i - dollar_labels]); /* If we get here, we haven't seen the label before. Therefore its instance count is zero. */ return 0;}voiddollar_label_clear (){ memset (dollar_label_defines, '\0', (unsigned int) dollar_label_count);}#define DOLLAR_LABEL_BUMP_BY 10
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?