cofflink.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,243 行 · 第 1/5 页
C
2,243 行
FIXME: I don't think this will work in the case where there are two object files which use the constants as a literal and two object files which use it as a data initializer. One or the other of the second object files is going to wind up with an inappropriate reference. */ if (obj_pe (abfd) && (classification == COFF_SYMBOL_GLOBAL || classification == COFF_SYMBOL_PE_SECTION) && section->comdat != NULL && strncmp (name, "??_", 3) == 0 && strcmp (name, section->comdat->name) == 0) { if (*sym_hash == NULL) *sym_hash = coff_link_hash_lookup (coff_hash_table (info), name, false, copy, false); if (*sym_hash != NULL && (*sym_hash)->root.type == bfd_link_hash_defined && (*sym_hash)->root.u.def.section->comdat != NULL && strcmp ((*sym_hash)->root.u.def.section->comdat->name, section->comdat->name) == 0) addit = false; } if (addit) { if (! (bfd_coff_link_add_one_symbol (info, abfd, name, flags, section, value, (const char *) NULL, copy, false, (struct bfd_link_hash_entry **) sym_hash))) goto error_return; } if (obj_pe (abfd) && (flags & BSF_SECTION_SYM) != 0) (*sym_hash)->coff_link_hash_flags |= COFF_LINK_HASH_PE_SECTION_SYMBOL; /* Limit the alignment of a common symbol to the possible alignment of a section. There is no point to permitting a higher alignment for a common symbol: we can not guarantee it, and it may cause us to allocate extra space in the common section. */ if (section == bfd_com_section_ptr && (*sym_hash)->root.type == bfd_link_hash_common && ((*sym_hash)->root.u.c.p->alignment_power > bfd_coff_default_section_alignment_power (abfd))) (*sym_hash)->root.u.c.p->alignment_power = bfd_coff_default_section_alignment_power (abfd); if (info->hash->creator->flavour == bfd_get_flavour (abfd)) { /* If we don't have any symbol information currently in the hash table, or if we are looking at a symbol definition, then update the symbol class and type in the hash table. */ if (((*sym_hash)->class == C_NULL && (*sym_hash)->type == T_NULL) || sym.n_scnum != 0 || (sym.n_value != 0 && (*sym_hash)->root.type != bfd_link_hash_defined && (*sym_hash)->root.type != bfd_link_hash_defweak)) { (*sym_hash)->class = sym.n_sclass; if (sym.n_type != T_NULL) { /* We want to warn if the type changed, but not if it changed from an unspecified type. Testing the whole type byte may work, but the change from (e.g.) a function of unspecified type to function of known type also wants to skip the warning. */ if ((*sym_hash)->type != T_NULL && (*sym_hash)->type != sym.n_type && !(DTYPE ((*sym_hash)->type) == DTYPE (sym.n_type) && (BTYPE ((*sym_hash)->type) == T_NULL || BTYPE (sym.n_type) == T_NULL))) (*_bfd_error_handler) (_("Warning: type of symbol `%s' changed from %d to %d in %s"), name, (*sym_hash)->type, sym.n_type, bfd_get_filename (abfd)); /* We don't want to change from a meaningful base type to a null one, but if we know nothing, take what little we might now know. */ if (BTYPE (sym.n_type) != T_NULL || (*sym_hash)->type == T_NULL) (*sym_hash)->type = sym.n_type; } (*sym_hash)->auxbfd = abfd; if (sym.n_numaux != 0) { union internal_auxent *alloc; unsigned int i; bfd_byte *eaux; union internal_auxent *iaux; (*sym_hash)->numaux = sym.n_numaux; alloc = ((union internal_auxent *) bfd_hash_allocate (&info->hash->table, (sym.n_numaux * sizeof (*alloc)))); if (alloc == NULL) goto error_return; for (i = 0, eaux = esym + symesz, iaux = alloc; i < sym.n_numaux; i++, eaux += symesz, iaux++) bfd_coff_swap_aux_in (abfd, (PTR) eaux, sym.n_type, sym.n_sclass, i, sym.n_numaux, (PTR) iaux); (*sym_hash)->aux = alloc; } } } if (classification == COFF_SYMBOL_PE_SECTION && (*sym_hash)->numaux != 0) { /* Some PE sections (such as .bss) have a zero size in the section header, but a non-zero size in the AUX record. Correct that here. FIXME: This is not at all the right place to do this. For example, it won't help objdump. This needs to be done when we swap in the section header. */ BFD_ASSERT ((*sym_hash)->numaux == 1); if (section->_raw_size == 0) section->_raw_size = (*sym_hash)->aux[0].x_scn.x_scnlen; /* FIXME: We could test whether the section sizes matches the size in the aux entry, but apparently that sometimes fails unexpectedly. */ } } esym += (sym.n_numaux + 1) * symesz; sym_hash += sym.n_numaux + 1; } /* If this is a non-traditional, non-relocateable link, try to optimize the handling of any .stab/.stabstr sections. */ if (! info->relocateable && ! info->traditional_format && info->hash->creator->flavour == bfd_get_flavour (abfd) && (info->strip != strip_all && info->strip != strip_debugger)) { asection *stab, *stabstr; stab = bfd_get_section_by_name (abfd, ".stab"); if (stab != NULL) { stabstr = bfd_get_section_by_name (abfd, ".stabstr"); if (stabstr != NULL) { struct coff_link_hash_table *table; struct coff_section_tdata *secdata; secdata = coff_section_data (abfd, stab); if (secdata == NULL) { stab->used_by_bfd = (PTR) bfd_zalloc (abfd, sizeof (struct coff_section_tdata)); if (stab->used_by_bfd == NULL) goto error_return; secdata = coff_section_data (abfd, stab); } table = coff_hash_table (info); if (! _bfd_link_section_stabs (abfd, &table->stab_info, stab, stabstr, &secdata->stab_info)) goto error_return; } } } obj_coff_keep_syms (abfd) = keep_syms; return true; error_return: obj_coff_keep_syms (abfd) = keep_syms; return false;}/* Do the final link step. */boolean_bfd_coff_final_link (abfd, info) bfd *abfd; struct bfd_link_info *info;{ bfd_size_type symesz; struct coff_final_link_info finfo; boolean debug_merge_allocated; boolean long_section_names; asection *o; struct bfd_link_order *p; size_t max_sym_count; size_t max_lineno_count; size_t max_reloc_count; size_t max_output_reloc_count; size_t max_contents_size; file_ptr rel_filepos; unsigned int relsz; file_ptr line_filepos; unsigned int linesz; bfd *sub; bfd_byte *external_relocs = NULL; char strbuf[STRING_SIZE_SIZE]; symesz = bfd_coff_symesz (abfd); finfo.info = info; finfo.output_bfd = abfd; finfo.strtab = NULL; finfo.section_info = NULL; finfo.last_file_index = -1; finfo.last_bf_index = -1; finfo.internal_syms = NULL; finfo.sec_ptrs = NULL; finfo.sym_indices = NULL; finfo.outsyms = NULL; finfo.linenos = NULL; finfo.contents = NULL; finfo.external_relocs = NULL; finfo.internal_relocs = NULL; finfo.global_to_static = false; debug_merge_allocated = false; coff_data (abfd)->link_info = info; finfo.strtab = _bfd_stringtab_init (); if (finfo.strtab == NULL) goto error_return; if (! coff_debug_merge_hash_table_init (&finfo.debug_merge)) goto error_return; debug_merge_allocated = true; /* Compute the file positions for all the sections. */ if (! abfd->output_has_begun) { if (! bfd_coff_compute_section_file_positions (abfd)) goto error_return; } /* Count the line numbers and relocation entries required for the output file. Set the file positions for the relocs. */ rel_filepos = obj_relocbase (abfd); relsz = bfd_coff_relsz (abfd); max_contents_size = 0; max_lineno_count = 0; max_reloc_count = 0; long_section_names = false; for (o = abfd->sections; o != NULL; o = o->next) { o->reloc_count = 0; o->lineno_count = 0; for (p = o->link_order_head; p != NULL; p = p->next) { if (p->type == bfd_indirect_link_order) { asection *sec; sec = p->u.indirect.section; /* Mark all sections which are to be included in the link. This will normally be every section. We need to do this so that we can identify any sections which the linker has decided to not include. */ sec->linker_mark = true; if (info->strip == strip_none || info->strip == strip_some) o->lineno_count += sec->lineno_count; if (info->relocateable) o->reloc_count += sec->reloc_count; if (sec->_raw_size > max_contents_size) max_contents_size = sec->_raw_size; if (sec->lineno_count > max_lineno_count) max_lineno_count = sec->lineno_count; if (sec->reloc_count > max_reloc_count) max_reloc_count = sec->reloc_count; } else if (info->relocateable && (p->type == bfd_section_reloc_link_order || p->type == bfd_symbol_reloc_link_order)) ++o->reloc_count; } if (o->reloc_count == 0) o->rel_filepos = 0; else { o->flags |= SEC_RELOC; o->rel_filepos = rel_filepos; rel_filepos += o->reloc_count * relsz; } if (bfd_coff_long_section_names (abfd) && strlen (o->name) > SCNNMLEN) { /* This section has a long name which must go in the string table. This must correspond to the code in coff_write_object_contents which puts the string index into the s_name field of the section header. That is why we pass hash as false. */ if (_bfd_stringtab_add (finfo.strtab, o->name, false, false) == (bfd_size_type) -1) goto error_return; long_section_names = true; } } /* If doing a relocateable link, allocate space for the pointers we need to keep. */ if (info->relocateable) { unsigned int i; /* We use section_count + 1, rather than section_count, because the target_index fields are 1 based. */ finfo.section_info = ((struct coff_link_section_info *) bfd_malloc ((abfd->section_count + 1) * sizeof (struct coff_link_section_info))); if (finfo.section_info == NULL) goto error_return; for (i = 0; i <= abfd->section_count; i++) { finfo.section_info[i].relocs = NULL; finfo.section_info[i].rel_hashes = NULL; } } /* We now know the size of the relocs, so we can determine the file positions of the line numbers. */ line_filepos = rel_filepos; linesz = bfd_coff_linesz (abfd); max_output_reloc_count = 0; for (o = abfd->sections; o != NULL; o = o->next) { if (o->lineno_count == 0) o->line_filepos = 0; else { o->line_filepos = line_filepos; line_filepos += o->lineno_count * linesz; } if (o->reloc_count != 0) { /* We don't know the indices of global symbols until we have written out all the local symbols. For each section in the output file, we keep an array of pointers to hash table entries. Each entry in the array corresponds to a reloc. When we find a reloc against a global symbol, we set the corresponding entry in this array so that we can fix up the symbol index after we have written out all the local symbols. Because of this problem, we also keep the relocs in memory until the end of the link. This wastes memory, but only when doing a relocateable link, which is not the common case. */ BFD_ASSERT (info->relocateable); finfo.section_info[o->target_index].relocs = ((struct internal_reloc *) bfd_malloc (o->reloc_count * sizeof (struct internal_reloc))); finfo.section_info[o->target_index].rel_hashes = ((struct coff_link_hash_entry **) bfd_malloc (o->reloc_count * sizeof (struct coff_link_hash_entry *))); if (finfo.section_info[o->target_index].relocs == NULL || finfo.section_info[o->target_index].rel_hashes == NULL) goto error_return; if (o->reloc_count > max_output_reloc_count) max_output_reloc_count = o->reloc_count; } /* Reset the reloc and lineno counts, so that we can use them to count the number of entries we have output so far. */ o->reloc_count = 0; o->lineno_count = 0; } obj_sym_filepos (abfd) = line_filepos; /* Figure out the largest number of symbols in an input BFD. Take the opportunity to clear the output_has_begun fields of all the input BFD's. */ max_sym_count = 0; for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) { size_t sz; sub->output_has_begun = false; sz = obj_raw_syment_count (sub); if (sz > max_sym_count) max_sym_count = sz; } /* Allocate some buffers used while linking. */ finfo.internal_syms = ((struct internal_syment *) bfd_malloc (max_sym_count * sizeof (struct internal_syment))); finfo.sec_ptrs = (asection **) bfd_malloc (max_sym_count * sizeof (asection *)); finfo.sym_indices = (long *) bfd_malloc (max_sym_count * sizeof (long)); finfo.outsyms = ((bfd_byte *) bfd_malloc ((size_t) ((max_sym_count + 1) * symesz))); finfo.linenos = (bfd_byte *) bfd_malloc (max_lineno_count * bfd_coff_linesz (abfd)); finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size); finfo.external_relocs = (bfd_byte *) bfd_malloc (max_reloc_count * relsz); if (! info->relocateable) finfo.internal_relocs = ((struct internal_reloc *) bfd_malloc (max_reloc_count * sizeof (struct internal_reloc))); if ((finfo.internal_syms == NULL && max_sym_count > 0) || (finfo.sec_ptrs == NULL && max_sym_count > 0) || (finfo.sym_indices == NULL && max_sym_count > 0) || finfo.outsyms == NULL || (finfo.linenos == NULL && max_lineno_count > 0) || (finfo.contents == NULL && max_contents_size > 0) || (finfo.external_relocs == NULL && max_reloc_count > 0) || (! info->relocateable && finfo.internal_relocs == NULL && max_reloc_count > 0)) goto error_return; /* We now know the position of everything in the file, except that we don't know the size of the symbol table and therefore we don't know where the string table starts. We just build the string table in memory as we go along. We process all the relocations for a single input file at once. */ obj_raw_syment_count (abfd) = 0; if (coff_backend_info (abfd)->_bfd_coff_start_final_link) { if (! bfd_coff_start_final_link (abfd, info)) goto error_return;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?