obj-coff.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,530 行 · 第 1/5 页
C
2,530 行
(void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr); ext_ptr++; }#endif } fix_ptr = fix_ptr->fx_next; }#ifdef TE_AUX /* Sort the reloc table */ qsort ((PTR) external_reloc_vec, nrelocs, sizeof (struct external_reloc), compare_external_relocs);#endif /* Write out the reloc table */ bfd_write ((PTR) external_reloc_vec, 1, external_reloc_size, abfd); free (external_reloc_vec); /* Fill in section header info. */ segment_info[idx].scnhdr.s_relptr = *file_cursor; *file_cursor += external_reloc_size; segment_info[idx].scnhdr.s_nreloc = nrelocs; } else { /* No relocs */ segment_info[idx].scnhdr.s_relptr = 0; } } } /* Set relocation_size field in file headers */ H_SET_RELOCATION_SIZE (h, *file_cursor - reloc_start, 0);}/* run through a frag chain and write out the data to go with it, fill in the scnhdrs with the info on the file postions*/static voidfill_section (abfd, h, file_cursor) bfd * abfd; object_headers *h ATTRIBUTE_UNUSED; unsigned long *file_cursor;{ unsigned int i; unsigned int paddr = 0; for (i = SEG_E0; i < SEG_UNKNOWN; i++) { unsigned int offset = 0; struct internal_scnhdr *s = &(segment_info[i].scnhdr); PROGRESS (1); if (s->s_name[0]) { fragS *frag = segment_info[i].frchainP->frch_root; char *buffer = NULL; if (s->s_size == 0) s->s_scnptr = 0; else { buffer = xmalloc (s->s_size); s->s_scnptr = *file_cursor; } know (s->s_paddr == paddr); if (strcmp (s->s_name, ".text") == 0) s->s_flags |= STYP_TEXT; else if (strcmp (s->s_name, ".data") == 0) s->s_flags |= STYP_DATA; else if (strcmp (s->s_name, ".bss") == 0) { s->s_scnptr = 0; s->s_flags |= STYP_BSS; /* @@ Should make the i386 and a29k coff targets define COFF_NOLOAD_PROBLEM, and have only one test here. */#ifndef TC_I386#ifndef TC_A29K#ifndef COFF_NOLOAD_PROBLEM /* Apparently the SVR3 linker (and exec syscall) and UDI mondfe progrem are confused by noload sections. */ s->s_flags |= STYP_NOLOAD;#endif#endif#endif } else if (strcmp (s->s_name, ".lit") == 0) s->s_flags = STYP_LIT | STYP_TEXT; else if (strcmp (s->s_name, ".init") == 0) s->s_flags |= STYP_TEXT; else if (strcmp (s->s_name, ".fini") == 0) s->s_flags |= STYP_TEXT; else if (strncmp (s->s_name, ".comment", 8) == 0) s->s_flags |= STYP_INFO; while (frag) { unsigned int fill_size; switch (frag->fr_type) { case rs_machine_dependent: if (frag->fr_fix) { memcpy (buffer + frag->fr_address, frag->fr_literal, (unsigned int) frag->fr_fix); offset += frag->fr_fix; } break; case rs_space: assert (frag->fr_symbol == 0); case rs_fill: case rs_align: case rs_align_code: case rs_align_test: case rs_org: if (frag->fr_fix) { memcpy (buffer + frag->fr_address, frag->fr_literal, (unsigned int) frag->fr_fix); offset += frag->fr_fix; } fill_size = frag->fr_var; if (fill_size && frag->fr_offset > 0) { unsigned int count; unsigned int off = frag->fr_fix; for (count = frag->fr_offset; count; count--) { if (fill_size + frag->fr_address + off <= s->s_size) { memcpy (buffer + frag->fr_address + off, frag->fr_literal + frag->fr_fix, fill_size); off += fill_size; offset += fill_size; } } } break; case rs_broken_word: break; default: abort (); } frag = frag->fr_next; } if (s->s_size != 0) { if (s->s_scnptr != 0) { bfd_write (buffer, s->s_size, 1, abfd); *file_cursor += s->s_size; } free (buffer); } paddr += s->s_size; } }}/* Coff file generation & utilities */static voidcoff_header_append (abfd, h) bfd * abfd; object_headers * h;{ unsigned int i; char buffer[1000]; char buffero[1000];#ifdef COFF_LONG_SECTION_NAMES unsigned long string_size = 4;#endif bfd_seek (abfd, 0, 0);#ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER H_SET_MAGIC_NUMBER (h, COFF_MAGIC); H_SET_VERSION_STAMP (h, 0); H_SET_ENTRY_POINT (h, 0); H_SET_TEXT_START (h, segment_info[SEG_E0].frchainP->frch_root->fr_address); H_SET_DATA_START (h, segment_info[SEG_E1].frchainP->frch_root->fr_address); H_SET_SIZEOF_OPTIONAL_HEADER (h, bfd_coff_swap_aouthdr_out(abfd, &h->aouthdr, buffero));#else /* defined (OBJ_COFF_OMIT_OPTIONAL_HEADER) */ H_SET_SIZEOF_OPTIONAL_HEADER (h, 0);#endif /* defined (OBJ_COFF_OMIT_OPTIONAL_HEADER) */ i = bfd_coff_swap_filehdr_out (abfd, &h->filehdr, buffer); bfd_write (buffer, i, 1, abfd); bfd_write (buffero, H_GET_SIZEOF_OPTIONAL_HEADER (h), 1, abfd); for (i = SEG_E0; i < SEG_LAST; i++) { if (segment_info[i].scnhdr.s_name[0]) { unsigned int size;#ifdef COFF_LONG_SECTION_NAMES /* Support long section names as found in PE. This code must coordinate with that in write_object_file and w_strings. */ if (strlen (segment_info[i].name) > SCNNMLEN) { memset (segment_info[i].scnhdr.s_name, 0, SCNNMLEN); sprintf (segment_info[i].scnhdr.s_name, "/%lu", string_size); string_size += strlen (segment_info[i].name) + 1; }#endif size = bfd_coff_swap_scnhdr_out (abfd, &(segment_info[i].scnhdr), buffer); if (size == 0) as_bad (_("bfd_coff_swap_scnhdr_out failed")); bfd_write (buffer, size, 1, abfd); } }}char *symbol_to_chars (abfd, where, symbolP) bfd * abfd; char *where; symbolS * symbolP;{ unsigned int numaux = symbolP->sy_symbol.ost_entry.n_numaux; unsigned int i; valueT val; /* Turn any symbols with register attributes into abs symbols */ if (S_GET_SEGMENT (symbolP) == reg_section) { S_SET_SEGMENT (symbolP, absolute_section); } /* At the same time, relocate all symbols to their output value */#ifndef TE_PE val = (segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_paddr + S_GET_VALUE (symbolP));#else val = S_GET_VALUE (symbolP);#endif S_SET_VALUE (symbolP, val); symbolP->sy_symbol.ost_entry.n_value = val; where += bfd_coff_swap_sym_out (abfd, &symbolP->sy_symbol.ost_entry, where); for (i = 0; i < numaux; i++) { where += bfd_coff_swap_aux_out (abfd, &symbolP->sy_symbol.ost_auxent[i], S_GET_DATA_TYPE (symbolP), S_GET_STORAGE_CLASS (symbolP), i, numaux, where); } return where;}voidcoff_obj_symbol_new_hook (symbolP) symbolS *symbolP;{ char underscore = 0; /* Symbol has leading _ */ /* Effective symbol */ /* Store the pointer in the offset. */ S_SET_ZEROES (symbolP, 0L); S_SET_DATA_TYPE (symbolP, T_NULL); S_SET_STORAGE_CLASS (symbolP, 0); S_SET_NUMBER_AUXILIARY (symbolP, 0); /* Additional information */ symbolP->sy_symbol.ost_flags = 0; /* Auxiliary entries */ memset ((char *) &symbolP->sy_symbol.ost_auxent[0], 0, AUXESZ); if (S_IS_STRING (symbolP)) SF_SET_STRING (symbolP); if (!underscore && S_IS_LOCAL (symbolP)) SF_SET_LOCAL (symbolP);}/* * Handle .ln directives. */static voidobj_coff_ln (appline) int appline;{ int l; if (! appline && def_symbol_in_progress != NULL) { as_warn (_(".ln pseudo-op inside .def/.endef: ignored.")); demand_empty_rest_of_line (); return; } /* wrong context */ l = get_absolute_expression (); c_line_new (0, frag_now_fix (), l, frag_now); if (appline) new_logical_line ((char *) NULL, l - 1);#ifndef NO_LISTING { extern int listing; if (listing) { if (! appline) l += line_base - 1; listing_source_line ((unsigned int) l); } }#endif demand_empty_rest_of_line ();}/* * def() * * Handle .def directives. * * One might ask : why can't we symbol_new if the symbol does not * already exist and fill it with debug information. Because of * the C_EFCN special symbol. It would clobber the value of the * function symbol before we have a chance to notice that it is * a C_EFCN. And a second reason is that the code is more clear this * way. (at least I think it is :-). * */#define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';')#define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \ *input_line_pointer == '\t') \ input_line_pointer++;static voidobj_coff_def (what) int what ATTRIBUTE_UNUSED;{ char name_end; /* Char after the end of name */ char *symbol_name; /* Name of the debug symbol */ char *symbol_name_copy; /* Temporary copy of the name */ unsigned int symbol_name_length; if (def_symbol_in_progress != NULL) { as_warn (_(".def pseudo-op used inside of .def/.endef: ignored.")); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ SKIP_WHITESPACES (); def_symbol_in_progress = (symbolS *) obstack_alloc (¬es, sizeof (*def_symbol_in_progress)); memset (def_symbol_in_progress, 0, sizeof (*def_symbol_in_progress)); symbol_name = input_line_pointer; name_end = get_symbol_end (); symbol_name_length = strlen (symbol_name); symbol_name_copy = xmalloc (symbol_name_length + 1); strcpy (symbol_name_copy, symbol_name);#ifdef tc_canonicalize_symbol_name symbol_name_copy = tc_canonicalize_symbol_name (symbol_name_copy);#endif /* Initialize the new symbol */#ifdef STRIP_UNDERSCORE S_SET_NAME (def_symbol_in_progress, (*symbol_name_copy == '_' ? symbol_name_copy + 1 : symbol_name_copy));#else /* STRIP_UNDERSCORE */ S_SET_NAME (def_symbol_in_progress, symbol_name_copy);#endif /* STRIP_UNDERSCORE */ /* free(symbol_name_copy); */ def_symbol_in_progress->sy_name_offset = (unsigned long) ~0; def_symbol_in_progress->sy_number = ~0; def_symbol_in_progress->sy_frag = &zero_address_frag; S_SET_VALUE (def_symbol_in_progress, 0); if (S_IS_STRING (def_symbol_in_progress)) SF_SET_STRING (def_symbol_in_progress); *input_line_pointer = name_end; demand_empty_rest_of_line ();}unsigned int dim_index;static voidobj_coff_endef (ignore) int ignore ATTRIBUTE_UNUSED;{ symbolS *symbolP = 0; /* DIM BUG FIX sac@cygnus.com */ dim_index = 0; if (def_symbol_in_progress == NULL) { as_warn (_(".endef pseudo-op used outside of .def/.endef: ignored.")); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ /* Set the section number according to storage class. */ switch (S_GET_STORAGE_CLASS (def_symbol_in_progress)) { case C_STRTAG: case C_ENTAG: case C_UNTAG: SF_SET_TAG (def_symbol_in_progress); /* intentional fallthrough */ case C_FILE: case C_TPDEF: SF_SET_DEBUG (def_symbol_in_progress); S_SET_SEGMENT (def_symbol_in_progress, SEG_DEBUG); break; case C_EFCN: SF_SET_LOCAL (def_symbol_in_progress); /* Do not emit this symbol. */ /* intentional fallthrough */ case C_BLOCK: SF_SET_PROCESS (def_symbol_in_progress); /* Will need processing before writing */ /* intentional fallthrough */ case C_FCN: S_SET_SEGMENT (def_symbol_in_progress, SEG_E0); if (strcmp (S_GET_NAME (def_symbol_in_progress), ".bf") == 0) { /* .bf */ if (function_lineoff < 0) { fprintf (stderr, _("`.bf' symbol without preceding function\n")); } /* missing function symbol */ SA_GET_SYM_LNNOPTR (last_line_symbol) = function_lineoff; SF_SET_PROCESS (last_line_symbol); SF_SET_ADJ_LNNOPTR (last_line_symbol); SF_SET_PROCESS (def_symbol_in_progress); function_lineoff = -1; } /* Value is always set to . */ def_symbol_in_progress->sy_frag = frag_now; S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ()); break;#ifdef C_AUTOARG case C_AUTOARG:#endif /* C_AUTOARG */ case C_AUTO: case C_REG: case C_MOS: case C_MOE: case C_MOU: case C_ARG: case C_REGPARM: case C_FIELD: case C_EOS: SF_SET_DEBUG (def_symbol_in_progress); S_SET_SEGMENT (def_symbol_in_progress, absolute_section); break; case C_EXT: case C_WEAKEXT:#ifdef TE_PE case C_NT_WEAK:#endif case C_STAT: case C_LABEL: /* Valid but set somewhere else (s_comm, s_lcomm, colon) */ break; case C_USTATIC: case C_EXTDEF: case C_ULABEL: as_warn (_("unexpected storage class %d"), S_GET_STORAGE_CLASS (def_symbol_in_progress)); break; } /* switch on storage class */ /* Now that we have built a debug symbol, try to find if we should merge with an existing symbol or not. If a symbol is C_EFCN or absolute_section or untagged SEG_DEBUG it never merges. We also don't merge labels, which are in a different namespace, nor symbols which have not yet been defined since they are typically unique, nor do we merge tags with non-tags. */ /* Two cases for functions. Either debug followed by definition or definition followed by debug. For definition first, we will
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?