ecofflink.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,153 行 · 第 1/5 页
C
2,153 行
sizeof (struct shuffle)); if (!n) { bfd_set_error (bfd_error_no_memory); return false; } n->next = NULL; n->size = size; n->filep = true; n->u.file.input_bfd = input_bfd; n->u.file.offset = offset; if (*head == (struct shuffle *) NULL) *head = n; if (*tail != (struct shuffle *) NULL) (*tail)->next = n; *tail = n; if (size > ainfo->largest_file_shuffle) ainfo->largest_file_shuffle = size; return true;}/* Add a memory entry to a shuffle list. */static boolean add_memory_shuffle PARAMS ((struct accumulate *, struct shuffle **head, struct shuffle **tail, bfd_byte *data, unsigned long size));static booleanadd_memory_shuffle (ainfo, head, tail, data, size) struct accumulate *ainfo; struct shuffle **head; struct shuffle **tail; bfd_byte *data; unsigned long size;{ struct shuffle *n; n = (struct shuffle *) objalloc_alloc (ainfo->memory, sizeof (struct shuffle)); if (!n) { bfd_set_error (bfd_error_no_memory); return false; } n->next = NULL; n->size = size; n->filep = false; n->u.memory = (PTR) data; if (*head == (struct shuffle *) NULL) *head = n; if (*tail != (struct shuffle *) NULL) (*tail)->next = n; *tail = n; return true;}/* Initialize the FDR hash table. This returns a handle which is then passed in to bfd_ecoff_debug_accumulate, et. al. */PTRbfd_ecoff_debug_init (output_bfd, output_debug, output_swap, info) bfd *output_bfd ATTRIBUTE_UNUSED; struct ecoff_debug_info *output_debug; const struct ecoff_debug_swap *output_swap ATTRIBUTE_UNUSED; struct bfd_link_info *info;{ struct accumulate *ainfo; ainfo = (struct accumulate *) bfd_malloc (sizeof (struct accumulate)); if (!ainfo) return NULL; if (! bfd_hash_table_init_n (&ainfo->fdr_hash.table, string_hash_newfunc, 1021)) return NULL; ainfo->line = NULL; ainfo->line_end = NULL; ainfo->pdr = NULL; ainfo->pdr_end = NULL; ainfo->sym = NULL; ainfo->sym_end = NULL; ainfo->opt = NULL; ainfo->opt_end = NULL; ainfo->aux = NULL; ainfo->aux_end = NULL; ainfo->ss = NULL; ainfo->ss_end = NULL; ainfo->ss_hash = NULL; ainfo->ss_hash_end = NULL; ainfo->fdr = NULL; ainfo->fdr_end = NULL; ainfo->rfd = NULL; ainfo->rfd_end = NULL; ainfo->largest_file_shuffle = 0; if (! info->relocateable) { if (! bfd_hash_table_init (&ainfo->str_hash.table, string_hash_newfunc)) return NULL; /* The first entry in the string table is the empty string. */ output_debug->symbolic_header.issMax = 1; } ainfo->memory = objalloc_create (); if (ainfo->memory == NULL) { bfd_set_error (bfd_error_no_memory); return NULL; } return (PTR) ainfo;}/* Free the accumulated debugging information. */voidbfd_ecoff_debug_free (handle, output_bfd, output_debug, output_swap, info) PTR handle; bfd *output_bfd ATTRIBUTE_UNUSED; struct ecoff_debug_info *output_debug ATTRIBUTE_UNUSED; const struct ecoff_debug_swap *output_swap ATTRIBUTE_UNUSED; struct bfd_link_info *info;{ struct accumulate *ainfo = (struct accumulate *) handle; bfd_hash_table_free (&ainfo->fdr_hash.table); if (! info->relocateable) bfd_hash_table_free (&ainfo->str_hash.table); objalloc_free (ainfo->memory); free (ainfo);}/* Accumulate the debugging information from INPUT_BFD into OUTPUT_BFD. The INPUT_DEBUG argument points to some ECOFF debugging information which we want to link into the information pointed to by the OUTPUT_DEBUG argument. OUTPUT_SWAP and INPUT_SWAP point to the swapping information needed. INFO is the linker information structure. HANDLE is returned by bfd_ecoff_debug_init. */booleanbfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap, input_bfd, input_debug, input_swap, info) PTR handle; bfd *output_bfd; struct ecoff_debug_info *output_debug; const struct ecoff_debug_swap *output_swap; bfd *input_bfd; struct ecoff_debug_info *input_debug; const struct ecoff_debug_swap *input_swap; struct bfd_link_info *info;{ struct accumulate *ainfo = (struct accumulate *) handle; void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)) = input_swap->swap_sym_in; void (* const swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *)) = input_swap->swap_rfd_in; void (* const swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR)) = output_swap->swap_sym_out; void (* const swap_fdr_out) PARAMS ((bfd *, const FDR *, PTR)) = output_swap->swap_fdr_out; void (* const swap_rfd_out) PARAMS ((bfd *, const RFDT *, PTR)) = output_swap->swap_rfd_out; bfd_size_type external_pdr_size = output_swap->external_pdr_size; bfd_size_type external_sym_size = output_swap->external_sym_size; bfd_size_type external_opt_size = output_swap->external_opt_size; bfd_size_type external_fdr_size = output_swap->external_fdr_size; bfd_size_type external_rfd_size = output_swap->external_rfd_size; HDRR * const output_symhdr = &output_debug->symbolic_header; HDRR * const input_symhdr = &input_debug->symbolic_header; bfd_vma section_adjust[scMax]; asection *sec; bfd_byte *fdr_start; bfd_byte *fdr_ptr; bfd_byte *fdr_end; bfd_size_type fdr_add; unsigned int copied; RFDT i; unsigned long sz; bfd_byte *rfd_out; bfd_byte *rfd_in; bfd_byte *rfd_end; long newrfdbase = 0; long oldrfdbase = 0; bfd_byte *fdr_out; /* Use section_adjust to hold the value to add to a symbol in a particular section. */ memset ((PTR) section_adjust, 0, sizeof section_adjust);#define SET(name, indx) \ sec = bfd_get_section_by_name (input_bfd, name); \ if (sec != NULL) \ section_adjust[indx] = (sec->output_section->vma \ + sec->output_offset \ - sec->vma); SET (".text", scText); SET (".data", scData); SET (".bss", scBss); SET (".sdata", scSData); SET (".sbss", scSBss); /* scRdata section may be either .rdata or .rodata. */ SET (".rdata", scRData); SET (".rodata", scRData); SET (".init", scInit); SET (".fini", scFini); SET (".rconst", scRConst);#undef SET /* Find all the debugging information based on the FDR's. We need to handle them whether they are swapped or not. */ if (input_debug->fdr != (FDR *) NULL) { fdr_start = (bfd_byte *) input_debug->fdr; fdr_add = sizeof (FDR); } else { fdr_start = (bfd_byte *) input_debug->external_fdr; fdr_add = input_swap->external_fdr_size; } fdr_end = fdr_start + input_symhdr->ifdMax * fdr_add; input_debug->ifdmap = (RFDT *) bfd_alloc (input_bfd, (input_symhdr->ifdMax * sizeof (RFDT))); sz = (input_symhdr->crfd + input_symhdr->ifdMax) * external_rfd_size; rfd_out = (bfd_byte *) objalloc_alloc (ainfo->memory, sz); if (!input_debug->ifdmap || !rfd_out) { bfd_set_error (bfd_error_no_memory); return false; } if (!add_memory_shuffle (ainfo, &ainfo->rfd, &ainfo->rfd_end, rfd_out, sz)) return false; copied = 0; /* Look through the FDR's to see which ones we are going to include in the final output. We do not want duplicate FDR information for header files, because ECOFF debugging is often very large. When we find an FDR with no line information which can be merged, we look it up in a hash table to ensure that we only include it once. We keep a table mapping FDR numbers to the final number they get with the BFD, so that we can refer to it when we write out the external symbols. */ for (fdr_ptr = fdr_start, i = 0; fdr_ptr < fdr_end; fdr_ptr += fdr_add, i++, rfd_out += external_rfd_size) { FDR fdr; if (input_debug->fdr != (FDR *) NULL) fdr = *(FDR *) fdr_ptr; else (*input_swap->swap_fdr_in) (input_bfd, (PTR) fdr_ptr, &fdr); /* See if this FDR can be merged with an existing one. */ if (fdr.cbLine == 0 && fdr.rss != -1 && fdr.fMerge) { const char *name; char *lookup; struct string_hash_entry *fh; /* We look up a string formed from the file name and the number of symbols and aux entries. Sometimes an include file will conditionally define a typedef or something based on the order of include files. Using the number of symbols and aux entries as a hash reduces the chance that we will merge symbol information that should not be merged. */ name = input_debug->ss + fdr.issBase + fdr.rss; lookup = (char *) bfd_malloc (strlen (name) + 20); if (lookup == NULL) return false; sprintf (lookup, "%s %lx %lx", name, fdr.csym, fdr.caux); fh = string_hash_lookup (&ainfo->fdr_hash, lookup, true, true); free (lookup); if (fh == (struct string_hash_entry *) NULL) return false; if (fh->val != -1) { input_debug->ifdmap[i] = fh->val; (*swap_rfd_out) (output_bfd, input_debug->ifdmap + i, (PTR) rfd_out); /* Don't copy this FDR. */ continue; } fh->val = output_symhdr->ifdMax + copied; } input_debug->ifdmap[i] = output_symhdr->ifdMax + copied; (*swap_rfd_out) (output_bfd, input_debug->ifdmap + i, (PTR) rfd_out); ++copied; } newrfdbase = output_symhdr->crfd; output_symhdr->crfd += input_symhdr->ifdMax; /* Copy over any existing RFD's. RFD's are only created by the linker, so this will only happen for input files which are the result of a partial link. */ rfd_in = (bfd_byte *) input_debug->external_rfd; rfd_end = rfd_in + input_symhdr->crfd * input_swap->external_rfd_size; for (; rfd_in < rfd_end; rfd_in += input_swap->external_rfd_size) { RFDT rfd; (*swap_rfd_in) (input_bfd, (PTR) rfd_in, &rfd); BFD_ASSERT (rfd >= 0 && rfd < input_symhdr->ifdMax); rfd = input_debug->ifdmap[rfd]; (*swap_rfd_out) (output_bfd, &rfd, (PTR) rfd_out); rfd_out += external_rfd_size; } oldrfdbase = output_symhdr->crfd; output_symhdr->crfd += input_symhdr->crfd; /* Look through the FDR's and copy over all associated debugging information. */ sz = copied * external_fdr_size; fdr_out = (bfd_byte *) objalloc_alloc (ainfo->memory, sz); if (!fdr_out) { bfd_set_error (bfd_error_no_memory); return false; } if (!add_memory_shuffle (ainfo, &ainfo->fdr, &ainfo->fdr_end, fdr_out, sz)) return false; for (fdr_ptr = fdr_start, i = 0; fdr_ptr < fdr_end; fdr_ptr += fdr_add, i++) { FDR fdr; bfd_vma fdr_adr; bfd_byte *sym_out; bfd_byte *lraw_src; bfd_byte *lraw_end; boolean fgotfilename; if (input_debug->ifdmap[i] < output_symhdr->ifdMax) { /* We are not copying this FDR. */ continue; } if (input_debug->fdr != (FDR *) NULL) fdr = *(FDR *) fdr_ptr; else (*input_swap->swap_fdr_in) (input_bfd, (PTR) fdr_ptr, &fdr); fdr_adr = fdr.adr; /* Adjust the FDR address for any changes that may have been made by relaxing. */ if (input_debug->adjust != (struct ecoff_value_adjust *) NULL) { struct ecoff_value_adjust *adjust; for (adjust = input_debug->adjust; adjust != (struct ecoff_value_adjust *) NULL; adjust = adjust->next) if (fdr_adr >= adjust->start && fdr_adr < adjust->end) fdr.adr += adjust->adjust; } /* FIXME: It is conceivable that this FDR points to the .init or .fini section, in which case this will not do the right thing. */ fdr.adr += section_adjust[scText]; /* Swap in the local symbols, adjust their values, and swap them out again. */ fgotfilename = false; sz = fdr.csym * external_sym_size; sym_out = (bfd_byte *) objalloc_alloc (ainfo->memory, sz); if (!sym_out) { bfd_set_error (bfd_error_no_memory); return false; } if (!add_memory_shuffle (ainfo, &ainfo->sym, &ainfo->sym_end, sym_out, sz)) return false; lraw_src = ((bfd_byte *) input_debug->external_sym + fdr.isymBase * input_swap->external_sym_size); lraw_end = lraw_src + fdr.csym * input_swap->external_sym_size; for (; lraw_src < lraw_end; lraw_src += input_swap->external_sym_size) { SYMR internal_sym; (*swap_sym_in) (input_bfd, (PTR) lraw_src, &internal_sym); BFD_ASSERT (internal_sym.sc != scCommon && internal_sym.sc != scSCommon); /* Adjust the symbol value if appropriate. */ switch (internal_sym.st) { case stNil: if (ECOFF_IS_STAB (&internal_sym)) break; /* Fall through. */ case stGlobal: case stStatic: case stLabel: case stProc: case stStaticProc: if (input_debug->adjust != (struct ecoff_value_adjust *) NULL) { bfd_vma value; struct ecoff_value_adjust *adjust;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?