coffgen.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,343 行 · 第 1/5 页
C
2,343 行
if (free_external != NULL) { free (free_external); free_external = NULL; } if (cache && free_internal != NULL) { if (coff_section_data (abfd, sec) == NULL) { sec->used_by_bfd = (PTR) bfd_zalloc (abfd, sizeof (struct coff_section_tdata)); if (sec->used_by_bfd == NULL) goto error_return; coff_section_data (abfd, sec)->contents = NULL; } coff_section_data (abfd, sec)->relocs = free_internal; } return internal_relocs; error_return: if (free_external != NULL) free (free_external); if (free_internal != NULL) free (free_internal); return NULL;}/* Set lineno_count for the output sections of a COFF file. */intcoff_count_linenumbers (abfd) bfd *abfd;{ unsigned int limit = bfd_get_symcount (abfd); unsigned int i; int total = 0; asymbol **p; asection *s; if (limit == 0) { /* This may be from the backend linker, in which case the lineno_count in the sections is correct. */ for (s = abfd->sections; s != NULL; s = s->next) total += s->lineno_count; return total; } for (s = abfd->sections; s != NULL; s = s->next) BFD_ASSERT (s->lineno_count == 0); for (p = abfd->outsymbols, i = 0; i < limit; i++, p++) { asymbol *q_maybe = *p; if (bfd_family_coff (bfd_asymbol_bfd (q_maybe))) { coff_symbol_type *q = coffsymbol (q_maybe); /* The AIX 4.1 compiler can sometimes generate line numbers attached to debugging symbols. We try to simply ignore those here. */ if (q->lineno != NULL && q->symbol.section->owner != NULL) { /* This symbol has line numbers. Increment the owning section's linenumber count. */ alent *l = q->lineno; ++q->symbol.section->output_section->lineno_count; ++total; ++l; while (l->line_number != 0) { ++total; ++q->symbol.section->output_section->lineno_count; ++l; } } } } return total;}/* Takes a bfd and a symbol, returns a pointer to the coff specific area of the symbol if there is one. */coff_symbol_type *coff_symbol_from (ignore_abfd, symbol) bfd *ignore_abfd ATTRIBUTE_UNUSED; asymbol *symbol;{ if (!bfd_family_coff (bfd_asymbol_bfd (symbol))) return (coff_symbol_type *) NULL; if (bfd_asymbol_bfd (symbol)->tdata.coff_obj_data == (coff_data_type *) NULL) return (coff_symbol_type *) NULL; return (coff_symbol_type *) symbol;}static voidfixup_symbol_value (abfd, coff_symbol_ptr, syment) bfd *abfd; coff_symbol_type *coff_symbol_ptr; struct internal_syment *syment;{ /* Normalize the symbol flags */ if (bfd_is_com_section (coff_symbol_ptr->symbol.section)) { /* a common symbol is undefined with a value */ syment->n_scnum = N_UNDEF; syment->n_value = coff_symbol_ptr->symbol.value; } else if ((coff_symbol_ptr->symbol.flags & BSF_DEBUGGING) != 0 && (coff_symbol_ptr->symbol.flags & BSF_DEBUGGING_RELOC) == 0) { syment->n_value = coff_symbol_ptr->symbol.value; } else if (bfd_is_und_section (coff_symbol_ptr->symbol.section)) { syment->n_scnum = N_UNDEF; syment->n_value = 0; } /* FIXME: Do we need to handle the absolute section here? */ else { if (coff_symbol_ptr->symbol.section) { syment->n_scnum = coff_symbol_ptr->symbol.section->output_section->target_index; syment->n_value = (coff_symbol_ptr->symbol.value + coff_symbol_ptr->symbol.section->output_offset); if (! obj_pe (abfd)) { syment->n_value += (syment->n_sclass == C_STATLAB) ? coff_symbol_ptr->symbol.section->output_section->lma : coff_symbol_ptr->symbol.section->output_section->vma; } } else { BFD_ASSERT (0); /* This can happen, but I don't know why yet (steve@cygnus.com) */ syment->n_scnum = N_ABS; syment->n_value = coff_symbol_ptr->symbol.value; } }}/* Run through all the symbols in the symbol table and work out what their indexes into the symbol table will be when output. Coff requires that each C_FILE symbol points to the next one in the chain, and that the last one points to the first external symbol. We do that here too. */booleancoff_renumber_symbols (bfd_ptr, first_undef) bfd *bfd_ptr; int *first_undef;{ unsigned int symbol_count = bfd_get_symcount (bfd_ptr); asymbol **symbol_ptr_ptr = bfd_ptr->outsymbols; unsigned int native_index = 0; struct internal_syment *last_file = (struct internal_syment *) NULL; unsigned int symbol_index; /* COFF demands that undefined symbols come after all other symbols. Since we don't need to impose this extra knowledge on all our client programs, deal with that here. Sort the symbol table; just move the undefined symbols to the end, leaving the rest alone. The O'Reilly book says that defined global symbols come at the end before the undefined symbols, so we do that here as well. */ /* @@ Do we have some condition we could test for, so we don't always have to do this? I don't think relocatability is quite right, but I'm not certain. [raeburn:19920508.1711EST] */ { asymbol **newsyms; unsigned int i; newsyms = (asymbol **) bfd_alloc (bfd_ptr, sizeof (asymbol *) * (symbol_count + 1)); if (!newsyms) return false; bfd_ptr->outsymbols = newsyms; for (i = 0; i < symbol_count; i++) if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) != 0 || (!bfd_is_und_section (symbol_ptr_ptr[i]->section) && !bfd_is_com_section (symbol_ptr_ptr[i]->section) && ((symbol_ptr_ptr[i]->flags & BSF_FUNCTION) != 0 || ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL | BSF_WEAK)) == 0)))) *newsyms++ = symbol_ptr_ptr[i]; for (i = 0; i < symbol_count; i++) if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) == 0 && !bfd_is_und_section (symbol_ptr_ptr[i]->section) && (bfd_is_com_section (symbol_ptr_ptr[i]->section) || ((symbol_ptr_ptr[i]->flags & BSF_FUNCTION) == 0 && ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL | BSF_WEAK)) != 0)))) *newsyms++ = symbol_ptr_ptr[i]; *first_undef = newsyms - bfd_ptr->outsymbols; for (i = 0; i < symbol_count; i++) if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) == 0 && bfd_is_und_section (symbol_ptr_ptr[i]->section)) *newsyms++ = symbol_ptr_ptr[i]; *newsyms = (asymbol *) NULL; symbol_ptr_ptr = bfd_ptr->outsymbols; } for (symbol_index = 0; symbol_index < symbol_count; symbol_index++) { coff_symbol_type *coff_symbol_ptr = coff_symbol_from (bfd_ptr, symbol_ptr_ptr[symbol_index]); symbol_ptr_ptr[symbol_index]->udata.i = symbol_index; if (coff_symbol_ptr && coff_symbol_ptr->native) { combined_entry_type *s = coff_symbol_ptr->native; int i; if (s->u.syment.n_sclass == C_FILE) { if (last_file != (struct internal_syment *) NULL) last_file->n_value = native_index; last_file = &(s->u.syment); } else { /* Modify the symbol values according to their section and type */ fixup_symbol_value (bfd_ptr, coff_symbol_ptr, &(s->u.syment)); } for (i = 0; i < s->u.syment.n_numaux + 1; i++) s[i].offset = native_index++; } else { native_index++; } } obj_conv_table_size (bfd_ptr) = native_index; return true;}/* Run thorough the symbol table again, and fix it so that all pointers to entries are changed to the entries' index in the output symbol table. */voidcoff_mangle_symbols (bfd_ptr) bfd *bfd_ptr;{ unsigned int symbol_count = bfd_get_symcount (bfd_ptr); asymbol **symbol_ptr_ptr = bfd_ptr->outsymbols; unsigned int symbol_index; for (symbol_index = 0; symbol_index < symbol_count; symbol_index++) { coff_symbol_type *coff_symbol_ptr = coff_symbol_from (bfd_ptr, symbol_ptr_ptr[symbol_index]); if (coff_symbol_ptr && coff_symbol_ptr->native) { int i; combined_entry_type *s = coff_symbol_ptr->native; if (s->fix_value) { /* FIXME: We should use a union here. */ s->u.syment.n_value = ((combined_entry_type *) s->u.syment.n_value)->offset; s->fix_value = 0; } if (s->fix_line) { /* The value is the offset into the line number entries for the symbol's section. On output, the symbol's section should be N_DEBUG. */ s->u.syment.n_value = (coff_symbol_ptr->symbol.section->output_section->line_filepos + s->u.syment.n_value * bfd_coff_linesz (bfd_ptr)); coff_symbol_ptr->symbol.section = coff_section_from_bfd_index (bfd_ptr, N_DEBUG); BFD_ASSERT (coff_symbol_ptr->symbol.flags & BSF_DEBUGGING); } for (i = 0; i < s->u.syment.n_numaux; i++) { combined_entry_type *a = s + i + 1; if (a->fix_tag) { a->u.auxent.x_sym.x_tagndx.l = a->u.auxent.x_sym.x_tagndx.p->offset; a->fix_tag = 0; } if (a->fix_end) { a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l = a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p->offset; a->fix_end = 0; } if (a->fix_scnlen) { a->u.auxent.x_csect.x_scnlen.l = a->u.auxent.x_csect.x_scnlen.p->offset; a->fix_scnlen = 0; } } } }}static voidcoff_fix_symbol_name (abfd, symbol, native, string_size_p, debug_string_section_p, debug_string_size_p) bfd *abfd; asymbol *symbol; combined_entry_type *native; bfd_size_type *string_size_p; asection **debug_string_section_p; bfd_size_type *debug_string_size_p;{ unsigned int name_length; union internal_auxent *auxent; char *name = (char *) (symbol->name); if (name == (char *) NULL) { /* coff symbols always have names, so we'll make one up */ symbol->name = "strange"; name = (char *) symbol->name; } name_length = strlen (name); if (native->u.syment.n_sclass == C_FILE && native->u.syment.n_numaux > 0) { unsigned int filnmlen; if (bfd_coff_force_symnames_in_strings (abfd)) { native->u.syment._n._n_n._n_offset = (*string_size_p + STRING_SIZE_SIZE); native->u.syment._n._n_n._n_zeroes = 0; *string_size_p += 6; /* strlen(".file") + 1 */ } else strncpy (native->u.syment._n._n_name, ".file", SYMNMLEN); auxent = &(native + 1)->u.auxent; filnmlen = bfd_coff_filnmlen (abfd); if (bfd_coff_long_filenames (abfd)) { if (name_length <= filnmlen) { strncpy (auxent->x_file.x_fname, name, filnmlen); } else { auxent->x_file.x_n.x_offset = *string_size_p + STRING_SIZE_SIZE; auxent->x_file.x_n.x_zeroes = 0; *string_size_p += name_length + 1; } } else { strncpy (auxent->x_file.x_fname, name, filnmlen); if (name_length > filnmlen) name[filnmlen] = '\0'; } } else { if (name_length <= SYMNMLEN && !bfd_coff_force_symnames_in_strings (abfd)) { /* This name will fit into the symbol neatly */ strncpy (native->u.syment._n._n_name, symbol->name, SYMNMLEN); } else if (!bfd_coff_symname_in_debug (abfd, &native->u.syment)) { native->u.syment._n._n_n._n_offset = (*string_size_p + STRING_SIZE_SIZE); native->u.syment._n._n_n._n_zeroes = 0; *string_size_p += name_length + 1; } else { long filepos; bfd_byte buf[4]; int prefix_len = bfd_coff_debug_string_prefix_length (abfd); /* This name should be written into the .debug section. For some reason each name is preceded by a two byte length and also followed by a null byte. FIXME: We assume that the .debug section has already been created, and that it is large enough. */ if (*debug_string_section_p == (asection *) NULL) *debug_string_section_p = bfd_get_section_by_name (abfd, ".debug"); filepos = bfd_tell (abfd); if (prefix_len == 4) bfd_put_32 (abfd, name_length + 1, buf); else bfd_put_16 (abfd, name_length + 1, buf); if (!bfd_set_section_contents (abfd, *debug_string_section_p, (PTR) buf, (file_ptr) *debug_string_size_p, (bfd_size_type) prefix_len) || !bfd_set_section_contents (abfd, *debug_string_section_p, (PTR) symbol->name, ((file_ptr) *debug_string_size_p + prefix_len), (bfd_size_type) name_length + 1)) abort (); if (bfd_seek (abfd, filepos, SEEK_SET) != 0) abort (); native->u.syment._n._n_n._n_offset = *debug_string_size_p + prefix_len; native->u.syment._n._n_n._n_zeroes = 0; *debug_string_size_p += name_length + 1 + prefix_len; } }}/* We need to keep track of the symbol index so that when we write out the relocs we can get the index for a symbol. This method is a hack. FIXME. */#define set_index(symbol, idx) ((symbol)->udata.i = (idx))/* Write a symbol out to a COFF file. */static booleancoff_write_symbol (abfd, symbol, native, written, string_size_p, debug_string_section_p, debug_string_size_p) bfd *abfd; asymbol *symbol; combined_entry_type *native; unsigned int *written; bfd_size_type *string_size_p; asection **debug_string_section_p; bfd_size_type *debug_string_size_p;{ unsigned int numaux = native->u.syment.n_numaux; int type = native->u.syment.n_type; int class = native->u.syment.n_sclass; PTR buf; bfd_size_type symesz; if (native->u.syment.n_sclass == C_FILE) symbol->flags |= BSF_DEBUGGING; if (symbol->flags & BSF_DEBUGGING
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?