obj-coff.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,530 行 · 第 1/5 页
C
2,530 行
char name_end; if (def_symbol_in_progress == NULL) { as_warn (_(".tag pseudo-op used outside of .def/.endef ignored.")); demand_empty_rest_of_line (); return; } S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); symbol_name = input_line_pointer; name_end = get_symbol_end ();#ifdef tc_canonicalize_symbol_name symbol_name = tc_canonicalize_symbol_name (symbol_name);#endif /* Assume that the symbol referred to by .tag is always defined. This was a bad assumption. I've added find_or_make. xoxorich. */ SA_SET_SYM_TAGNDX (def_symbol_in_progress, tag_find_or_make (symbol_name)); if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L) { as_warn (_("tag not found for .tag %s"), symbol_name); } /* not defined */ SF_SET_TAGGED (def_symbol_in_progress); *input_line_pointer = name_end; demand_empty_rest_of_line ();}static voidobj_coff_type (ignore) int ignore ATTRIBUTE_UNUSED;{ if (def_symbol_in_progress == NULL) { as_warn (_(".type pseudo-op used outside of .def/.endef ignored.")); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ()); if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) && S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF) { SF_SET_FUNCTION (def_symbol_in_progress); } /* is a function */ demand_empty_rest_of_line ();}static voidobj_coff_val (ignore) int ignore ATTRIBUTE_UNUSED;{ if (def_symbol_in_progress == NULL) { as_warn (_(".val pseudo-op used outside of .def/.endef ignored.")); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ if (is_name_beginner (*input_line_pointer)) { char *symbol_name = input_line_pointer; char name_end = get_symbol_end ();#ifdef tc_canonicalize_symbol_name symbol_name = tc_canonicalize_symbol_name (symbol_name);#endif if (!strcmp (symbol_name, ".")) { symbol_set_frag (def_symbol_in_progress, frag_now); S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ()); /* If the .val is != from the .def (e.g. statics) */ } else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name)) { expressionS exp; exp.X_op = O_symbol; exp.X_add_symbol = symbol_find_or_make (symbol_name); exp.X_op_symbol = NULL; exp.X_add_number = 0; symbol_set_value_expression (def_symbol_in_progress, &exp); /* If the segment is undefined when the forward reference is resolved, then copy the segment id from the forward symbol. */ SF_SET_GET_SEGMENT (def_symbol_in_progress); /* FIXME: gcc can generate address expressions here in unusual cases (search for "obscure" in sdbout.c). We just ignore the offset here, thus generating incorrect debugging information. We ignore the rest of the line just below. */ } /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */ *input_line_pointer = name_end; } else { S_SET_VALUE (def_symbol_in_progress, get_absolute_expression ()); } /* if symbol based */ demand_empty_rest_of_line ();}voidcoff_obj_read_begin_hook (){ /* These had better be the same. Usually 18 bytes. */#ifndef BFD_HEADERS know (sizeof (SYMENT) == sizeof (AUXENT)); know (SYMESZ == AUXESZ);#endif tag_init ();}symbolS *coff_last_function;static symbolS *coff_last_bf;voidcoff_frob_symbol (symp, punt) symbolS *symp; int *punt;{ static symbolS *last_tagP; static stack *block_stack; static symbolS *set_end; symbolS *next_set_end = NULL; if (symp == &abs_symbol) { *punt = 1; return; } if (current_lineno_sym) coff_add_linesym ((symbolS *) 0); if (!block_stack) block_stack = stack_init (512, sizeof (symbolS*)); if (S_IS_WEAK (symp)) {#ifdef TE_PE S_SET_STORAGE_CLASS (symp, C_NT_WEAK);#else S_SET_STORAGE_CLASS (symp, C_WEAKEXT);#endif } if (!S_IS_DEFINED (symp) && !S_IS_WEAK (symp) && S_GET_STORAGE_CLASS (symp) != C_STAT) S_SET_STORAGE_CLASS (symp, C_EXT); if (!SF_GET_DEBUG (symp)) { symbolS *real; if (!SF_GET_LOCAL (symp) && !SF_GET_STATICS (symp) && S_GET_STORAGE_CLASS (symp) != C_LABEL && symbol_constant_p(symp) && (real = symbol_find_base (S_GET_NAME (symp), DO_NOT_STRIP)) && real != symp) { c_symbol_merge (symp, real); *punt = 1; return; } if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp)) { assert (S_GET_VALUE (symp) == 0); S_SET_EXTERNAL (symp); } else if (S_GET_STORAGE_CLASS (symp) == C_NULL) { if (S_GET_SEGMENT (symp) == text_section && symp != seg_info (text_section)->sym) S_SET_STORAGE_CLASS (symp, C_LABEL); else S_SET_STORAGE_CLASS (symp, C_STAT); } if (SF_GET_PROCESS (symp)) { if (S_GET_STORAGE_CLASS (symp) == C_BLOCK) { if (!strcmp (S_GET_NAME (symp), ".bb")) stack_push (block_stack, (char *) &symp); else { symbolS *begin; begin = *(symbolS **) stack_pop (block_stack); if (begin == 0) as_warn (_("mismatched .eb")); else next_set_end = begin; } } if (coff_last_function == 0 && SF_GET_FUNCTION (symp)) { union internal_auxent *auxp; coff_last_function = symp; if (S_GET_NUMBER_AUXILIARY (symp) < 1) S_SET_NUMBER_AUXILIARY (symp, 1); auxp = SYM_AUXENT (symp); memset (auxp->x_sym.x_fcnary.x_ary.x_dimen, 0, sizeof (auxp->x_sym.x_fcnary.x_ary.x_dimen)); } if (S_GET_STORAGE_CLASS (symp) == C_EFCN) { if (coff_last_function == 0) as_fatal (_("C_EFCN symbol out of scope")); SA_SET_SYM_FSIZE (coff_last_function, (long) (S_GET_VALUE (symp) - S_GET_VALUE (coff_last_function))); next_set_end = coff_last_function; coff_last_function = 0; } } if (S_IS_EXTERNAL (symp)) S_SET_STORAGE_CLASS (symp, C_EXT); else if (SF_GET_LOCAL (symp)) *punt = 1; if (SF_GET_FUNCTION (symp)) symbol_get_bfdsym (symp)->flags |= BSF_FUNCTION; /* more ... */ } /* Double check weak symbols. */ if (S_IS_WEAK (symp) && S_IS_COMMON (symp)) as_bad (_("Symbol `%s' can not be both weak and common"), S_GET_NAME (symp)); if (SF_GET_TAG (symp)) last_tagP = symp; else if (S_GET_STORAGE_CLASS (symp) == C_EOS) next_set_end = last_tagP;#ifdef OBJ_XCOFF /* This is pretty horrible, but we have to set *punt correctly in order to call SA_SET_SYM_ENDNDX correctly. */ if (! symbol_used_in_reloc_p (symp) && ((symbol_get_bfdsym (symp)->flags & BSF_SECTION_SYM) != 0 || (! S_IS_EXTERNAL (symp) && ! symbol_get_tc (symp)->output && S_GET_STORAGE_CLASS (symp) != C_FILE))) *punt = 1;#endif if (set_end != (symbolS *) NULL && ! *punt && ((symbol_get_bfdsym (symp)->flags & BSF_NOT_AT_END) != 0 || (S_IS_DEFINED (symp) && ! S_IS_COMMON (symp) && (! S_IS_EXTERNAL (symp) || SF_GET_FUNCTION (symp))))) { SA_SET_SYM_ENDNDX (set_end, symp); set_end = NULL; } if (next_set_end != NULL) { if (set_end != NULL) as_warn ("Warning: internal error: forgetting to set endndx of %s", S_GET_NAME (set_end)); set_end = next_set_end; } if (! *punt && S_GET_STORAGE_CLASS (symp) == C_FCN && strcmp (S_GET_NAME (symp), ".bf") == 0) { if (coff_last_bf != NULL) SA_SET_SYM_ENDNDX (coff_last_bf, symp); coff_last_bf = symp; } if (coffsymbol (symbol_get_bfdsym (symp))->lineno) { int i; struct line_no *lptr; alent *l; lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno; for (i = 0; lptr; lptr = lptr->next) i++; lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno; /* We need i entries for line numbers, plus 1 for the first entry which BFD will override, plus 1 for the last zero entry (a marker for BFD). */ l = (alent *) xmalloc ((i + 2) * sizeof (alent)); coffsymbol (symbol_get_bfdsym (symp))->lineno = l; l[i + 1].line_number = 0; l[i + 1].u.sym = NULL; for (; i > 0; i--) { if (lptr->frag) lptr->l.u.offset += lptr->frag->fr_address / OCTETS_PER_BYTE; l[i] = lptr->l; lptr = lptr->next; } }}voidcoff_adjust_section_syms (abfd, sec, x) bfd *abfd ATTRIBUTE_UNUSED; asection *sec; PTR x ATTRIBUTE_UNUSED;{ symbolS *secsym; segment_info_type *seginfo = seg_info (sec); int nlnno, nrelocs = 0; /* RS/6000 gas creates a .debug section manually in ppc_frob_file in tc-ppc.c. Do not get confused by it. */ if (seginfo == NULL) return; if (!strcmp (sec->name, ".text")) nlnno = coff_n_line_nos; else nlnno = 0; { /* @@ Hope that none of the fixups expand to more than one reloc entry... */ fixS *fixp = seginfo->fix_root; while (fixp) { if (! fixp->fx_done) nrelocs++; fixp = fixp->fx_next; } } if (bfd_get_section_size_before_reloc (sec) == 0 && nrelocs == 0 && nlnno == 0 && sec != text_section && sec != data_section && sec != bss_section) return; secsym = section_symbol (sec); /* This is an estimate; we'll plug in the real value using SET_SECTION_RELOCS later */ SA_SET_SCN_NRELOC (secsym, nrelocs); SA_SET_SCN_NLINNO (secsym, nlnno);}voidcoff_frob_file_after_relocs (){ bfd_map_over_sections (stdoutput, coff_adjust_section_syms, (char*) 0);}/* * implement the .section pseudo op: * .section name {, "flags"} * ^ ^ * | +--- optional flags: 'b' for bss * | 'i' for info * +-- section name 'l' for lib * 'n' for noload * 'o' for over * 'w' for data * 'd' (apparently m88k for data) * 'x' for text * 'r' for read-only data * 's' for shared data (PE) * But if the argument is not a quoted string, treat it as a * subsegment number. */voidobj_coff_section (ignore) int ignore ATTRIBUTE_UNUSED;{ /* Strip out the section name */ char *section_name; char c; char *name; unsigned int exp; flagword flags, oldflags; asection *sec; if (flag_mri) { char type; s_mri_sect (&type); return; } section_name = input_line_pointer; c = get_symbol_end (); name = xmalloc (input_line_pointer - section_name + 1); strcpy (name, section_name); *input_line_pointer = c; SKIP_WHITESPACE (); exp = 0; flags = SEC_NO_FLAGS; if (*input_line_pointer == ',') { ++input_line_pointer; SKIP_WHITESPACE (); if (*input_line_pointer != '"') exp = get_absolute_expression (); else { ++input_line_pointer; while (*input_line_pointer != '"' && ! is_end_of_line[(unsigned char) *input_line_pointer]) { switch (*input_line_pointer) { case 'b': flags |= SEC_ALLOC; flags &=~ SEC_LOAD; break; case 'n': flags &=~ SEC_LOAD; flags |= SEC_NEVER_LOAD; break; case 'd': flags |= SEC_DATA | SEC_LOAD; /* fall through */ case 'w': flags &=~ SEC_READONLY; break; case 'x': flags |= SEC_CODE | SEC_LOAD; break; case 'r': flags |= SEC_READONLY; break; case 's': flags |= SEC_SHARED; break; case 'i': /* STYP_INFO */ case 'l': /* STYP_LIB */ case 'o': /* STYP_OVER */ as_warn (_("unsupported section attribute '%c'"), *input_line_pointer); break; default: as_warn(_("unknown section attribute '%c'"), *input_line_pointer); break; } ++input_line_pointer; } if (*input_line_pointer == '"') ++input_line_pointer; } } sec = subseg_new (name, (subsegT) exp); oldflags = bfd_get_section_flags (stdoutput, sec); if (oldflags == SEC_NO_FLAGS) { /* Set section flags for a new section just created by subseg_new. Provide a default if no flags were parsed. */ if (flags == SEC_NO_FLAGS) flags = TC_COFF_SECTION_DEFAULT_ATTRIBUTES;#ifdef COFF_LONG_SECTION_NAMES /* Add SEC_LINK_ONCE and SEC_LINK_DUPLICATES_DISCARD to .gnu.linkonce sections so adjust_reloc_syms in write.c will correctly handle relocs which refer to non-local symbols in these sections. */ if (strncmp (name, ".gnu.linkonce", sizeof (".gnu.linkonce") - 1) == 0) flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;#endif if (! bfd_set_section_flags (stdoutput, sec, flags)) as_warn (_("error setting flags for \"%s\": %s"), bfd_section_name (stdoutput, sec), bfd_errmsg (bfd_get_error ())); } else if (flags != SEC_NO_FLAGS) { /* This section's attributes have already been set. Warn if the attributes don't match. */ flagword matchflags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA | SEC_SHARED | SEC_NEVER_LOAD); if ((flags ^ oldflags) & matchflags) as_warn (_("Ignoring changed section attributes for %s"), name); } demand_empty_rest_of_line ();}voidcoff_adjust_symtab (){ if (symbol_rootP == NULL || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE) c_dot_file_symbol ("fake");}voidcoff_frob_section (sec) segT sec;{ segT strsec; char *p;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?