ecofflink.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,153 行 · 第 1/5 页
C
2,153 行
value = internal_sym.value; for (adjust = input_debug->adjust; adjust != (struct ecoff_value_adjust *) NULL; adjust = adjust->next) if (value >= adjust->start && value < adjust->end) internal_sym.value += adjust->adjust; } internal_sym.value += section_adjust[internal_sym.sc]; break; default: break; } /* If we are doing a final link, we hash all the strings in the local symbol table together. This reduces the amount of space required by debugging information. We don't do this when performing a relocateable link because it would prevent us from easily merging different FDR's. */ if (! info->relocateable) { boolean ffilename; const char *name; if (! fgotfilename && internal_sym.iss == fdr.rss) ffilename = true; else ffilename = false; /* Hash the name into the string table. */ name = input_debug->ss + fdr.issBase + internal_sym.iss; if (*name == '\0') internal_sym.iss = 0; else { struct string_hash_entry *sh; sh = string_hash_lookup (&ainfo->str_hash, name, true, true); if (sh == (struct string_hash_entry *) NULL) return false; if (sh->val == -1) { sh->val = output_symhdr->issMax; output_symhdr->issMax += strlen (name) + 1; if (ainfo->ss_hash == (struct string_hash_entry *) NULL) ainfo->ss_hash = sh; if (ainfo->ss_hash_end != (struct string_hash_entry *) NULL) ainfo->ss_hash_end->next = sh; ainfo->ss_hash_end = sh; } internal_sym.iss = sh->val; } if (ffilename) { fdr.rss = internal_sym.iss; fgotfilename = true; } } (*swap_sym_out) (output_bfd, &internal_sym, sym_out); sym_out += external_sym_size; } fdr.isymBase = output_symhdr->isymMax; output_symhdr->isymMax += fdr.csym; /* Copy the information that does not need swapping. */ /* FIXME: If we are relaxing, we need to adjust the line numbers. Frankly, forget it. Anybody using stabs debugging information will not use this line number information, and stabs are adjusted correctly. */ if (fdr.cbLine > 0) { if (!add_file_shuffle (ainfo, &ainfo->line, &ainfo->line_end, input_bfd, input_symhdr->cbLineOffset + fdr.cbLineOffset, fdr.cbLine)) return false; fdr.ilineBase = output_symhdr->ilineMax; fdr.cbLineOffset = output_symhdr->cbLine; output_symhdr->ilineMax += fdr.cline; output_symhdr->cbLine += fdr.cbLine; } if (fdr.caux > 0) { if (!add_file_shuffle (ainfo, &ainfo->aux, &ainfo->aux_end, input_bfd, (input_symhdr->cbAuxOffset + fdr.iauxBase * sizeof (union aux_ext)), fdr.caux * sizeof (union aux_ext))) return false; fdr.iauxBase = output_symhdr->iauxMax; output_symhdr->iauxMax += fdr.caux; } if (! info->relocateable) { /* When are are hashing strings, we lie about the number of strings attached to each FDR. We need to set cbSs because some versions of dbx apparently use it to decide how much of the string table to read in. */ fdr.issBase = 0; fdr.cbSs = output_symhdr->issMax; } else if (fdr.cbSs > 0) { if (!add_file_shuffle (ainfo, &ainfo->ss, &ainfo->ss_end, input_bfd, input_symhdr->cbSsOffset + fdr.issBase, fdr.cbSs)) return false; fdr.issBase = output_symhdr->issMax; output_symhdr->issMax += fdr.cbSs; } if ((output_bfd->xvec->header_byteorder == input_bfd->xvec->header_byteorder) && input_debug->adjust == (struct ecoff_value_adjust *) NULL) { /* The two BFD's have the same endianness, and we don't have to adjust the PDR addresses, so simply copying the information will suffice. */ BFD_ASSERT (external_pdr_size == input_swap->external_pdr_size); if (fdr.cpd > 0) { if (!add_file_shuffle (ainfo, &ainfo->pdr, &ainfo->pdr_end, input_bfd, (input_symhdr->cbPdOffset + fdr.ipdFirst * external_pdr_size), fdr.cpd * external_pdr_size)) return false; } BFD_ASSERT (external_opt_size == input_swap->external_opt_size); if (fdr.copt > 0) { if (!add_file_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end, input_bfd, (input_symhdr->cbOptOffset + fdr.ioptBase * external_opt_size), fdr.copt * external_opt_size)) return false; } } else { bfd_size_type outsz, insz; bfd_byte *in; bfd_byte *end; bfd_byte *out; /* The two BFD's have different endianness, so we must swap everything in and out. This code would always work, but it would be unnecessarily slow in the normal case. */ outsz = external_pdr_size; insz = input_swap->external_pdr_size; in = ((bfd_byte *) input_debug->external_pdr + fdr.ipdFirst * insz); end = in + fdr.cpd * insz; sz = fdr.cpd * outsz; out = (bfd_byte *) objalloc_alloc (ainfo->memory, sz); if (!out) { bfd_set_error (bfd_error_no_memory); return false; } if (!add_memory_shuffle (ainfo, &ainfo->pdr, &ainfo->pdr_end, out, sz)) return false; for (; in < end; in += insz, out += outsz) { PDR pdr; (*input_swap->swap_pdr_in) (input_bfd, (PTR) in, &pdr); /* If we have been relaxing, we may have to adjust the address. */ if (input_debug->adjust != (struct ecoff_value_adjust *) NULL) { bfd_vma adr; struct ecoff_value_adjust *adjust; adr = fdr_adr + pdr.adr; for (adjust = input_debug->adjust; adjust != (struct ecoff_value_adjust *) NULL; adjust = adjust->next) if (adr >= adjust->start && adr < adjust->end) pdr.adr += adjust->adjust; } (*output_swap->swap_pdr_out) (output_bfd, &pdr, (PTR) out); } /* Swap over the optimization information. */ outsz = external_opt_size; insz = input_swap->external_opt_size; in = ((bfd_byte *) input_debug->external_opt + fdr.ioptBase * insz); end = in + fdr.copt * insz; sz = fdr.copt * outsz; out = (bfd_byte *) objalloc_alloc (ainfo->memory, sz); if (!out) { bfd_set_error (bfd_error_no_memory); return false; } if (!add_memory_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end, out, sz)) return false; for (; in < end; in += insz, out += outsz) { OPTR opt; (*input_swap->swap_opt_in) (input_bfd, (PTR) in, &opt); (*output_swap->swap_opt_out) (output_bfd, &opt, (PTR) out); } } fdr.ipdFirst = output_symhdr->ipdMax; output_symhdr->ipdMax += fdr.cpd; fdr.ioptBase = output_symhdr->ioptMax; output_symhdr->ioptMax += fdr.copt; if (fdr.crfd <= 0) { /* Point this FDR at the table of RFD's we created. */ fdr.rfdBase = newrfdbase; fdr.crfd = input_symhdr->ifdMax; } else { /* Point this FDR at the remapped RFD's. */ fdr.rfdBase += oldrfdbase; } (*swap_fdr_out) (output_bfd, &fdr, fdr_out); fdr_out += external_fdr_size; ++output_symhdr->ifdMax; } return true;}/* Add a string to the debugging information we are accumulating. Return the offset from the fdr string base. */static long ecoff_add_string PARAMS ((struct accumulate *, struct bfd_link_info *, struct ecoff_debug_info *, FDR *fdr, const char *string));static longecoff_add_string (ainfo, info, debug, fdr, string) struct accumulate *ainfo; struct bfd_link_info *info; struct ecoff_debug_info *debug; FDR *fdr; const char *string;{ HDRR *symhdr; size_t len; bfd_size_type ret; symhdr = &debug->symbolic_header; len = strlen (string); if (info->relocateable) { if (!add_memory_shuffle (ainfo, &ainfo->ss, &ainfo->ss_end, (PTR) string, len + 1)) return -1; ret = symhdr->issMax; symhdr->issMax += len + 1; fdr->cbSs += len + 1; } else { struct string_hash_entry *sh; sh = string_hash_lookup (&ainfo->str_hash, string, true, true); if (sh == (struct string_hash_entry *) NULL) return -1; if (sh->val == -1) { sh->val = symhdr->issMax; symhdr->issMax += len + 1; if (ainfo->ss_hash == (struct string_hash_entry *) NULL) ainfo->ss_hash = sh; if (ainfo->ss_hash_end != (struct string_hash_entry *) NULL) ainfo->ss_hash_end->next = sh; ainfo->ss_hash_end = sh; } ret = sh->val; } return ret;}/* Add debugging information from a non-ECOFF file. */booleanbfd_ecoff_debug_accumulate_other (handle, output_bfd, output_debug, output_swap, input_bfd, info) PTR handle; bfd *output_bfd; struct ecoff_debug_info *output_debug; const struct ecoff_debug_swap *output_swap; bfd *input_bfd; struct bfd_link_info *info;{ struct accumulate *ainfo = (struct accumulate *) handle; void (* const swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR)) = output_swap->swap_sym_out; HDRR *output_symhdr = &output_debug->symbolic_header; FDR fdr; asection *sec; asymbol **symbols; asymbol **sym_ptr; asymbol **sym_end; long symsize; long symcount; PTR external_fdr; memset ((PTR) &fdr, 0, sizeof fdr); sec = bfd_get_section_by_name (input_bfd, ".text"); if (sec != NULL) fdr.adr = sec->output_section->vma + sec->output_offset; else { /* FIXME: What about .init or .fini? */ fdr.adr = 0; } fdr.issBase = output_symhdr->issMax; fdr.cbSs = 0; fdr.rss = ecoff_add_string (ainfo, info, output_debug, &fdr, bfd_get_filename (input_bfd)); if (fdr.rss == -1) return false; fdr.isymBase = output_symhdr->isymMax; /* Get the local symbols from the input BFD. */ symsize = bfd_get_symtab_upper_bound (input_bfd); if (symsize < 0) return false; symbols = (asymbol **) bfd_alloc (output_bfd, symsize); if (symbols == (asymbol **) NULL) return false; symcount = bfd_canonicalize_symtab (input_bfd, symbols); if (symcount < 0) return false; sym_end = symbols + symcount; /* Handle the local symbols. Any external symbols are handled separately. */ fdr.csym = 0; for (sym_ptr = symbols; sym_ptr != sym_end; sym_ptr++) { SYMR internal_sym; PTR external_sym; if (((*sym_ptr)->flags & BSF_EXPORT) != 0) continue; memset ((PTR) &internal_sym, 0, sizeof internal_sym); internal_sym.iss = ecoff_add_string (ainfo, info, output_debug, &fdr, (*sym_ptr)->name); if (internal_sym.iss == -1) return false; if (bfd_is_com_section ((*sym_ptr)->section) || bfd_is_und_section ((*sym_ptr)->section)) internal_sym.value = (*sym_ptr)->value; else internal_sym.value = ((*sym_ptr)->value + (*sym_ptr)->section->output_offset + (*sym_ptr)->section->output_section->vma); internal_sym.st = stNil; internal_sym.sc = scUndefined; internal_sym.index = indexNil; external_sym = (PTR) objalloc_alloc (ainfo->memory, output_swap->external_sym_size); if (!external_sym) { bfd_set_error (bfd_error_no_memory); return false; } (*swap_sym_out) (output_bfd, &internal_sym, external_sym); add_memory_shuffle (ainfo, &ainfo->sym, &ainfo->sym_end, external_sym, output_swap->external_sym_size); ++fdr.csym; ++output_symhdr->isymMax; } bfd_release (output_bfd, (PTR) symbols); /* Leave everything else in the FDR zeroed out. This will cause the lang field to be langC. The fBigendian field will indicate little endian format, but it doesn't matter because it only applies to aux fields and there are none. */ external_fdr = (PTR) objalloc_alloc (ainfo->memory, output_swap->external_fdr_size); if (!external_fdr) { bfd_set_error (bfd_error_no_memory); return false; } (*output_swap->swap_fdr_out) (output_bfd, &fdr, external_fdr); add_memory_shuffle (ainfo, &ainfo->fdr, &ainfo->fdr_end, external_fdr, output_swap->external_fdr_size); ++output_symhdr->ifdMax; return true;}/* Set up ECOFF debugging information for the external symbols. FIXME: This is done using a memory buffer, but it should be probably be changed to use a shuffle structure. The assembler uses this interface, so that must be changed to do something else. */booleanbfd_ecoff_debug_externals (abfd, debug, swap, relocateable, get_extr, set_index) bfd *abfd; struct ecoff_debug_info *debug;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?