ecofflink.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,153 行 · 第 1/5 页
C
2,153 行
/* Routines to link ECOFF debugging information. Copyright 1993, 1994, 1995, 1996, 1997, 2000 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>.This file is part of BFD, the Binary File Descriptor library.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "bfd.h"#include "sysdep.h"#include "bfdlink.h"#include "libbfd.h"#include "objalloc.h"#include "aout/stab_gnu.h"#include "coff/internal.h"#include "coff/sym.h"#include "coff/symconst.h"#include "coff/ecoff.h"#include "libcoff.h"#include "libecoff.h"static boolean ecoff_add_bytes PARAMS ((char **buf, char **bufend, size_t need));static struct bfd_hash_entry *string_hash_newfunc PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));static void ecoff_align_debug PARAMS ((bfd *abfd, struct ecoff_debug_info *debug, const struct ecoff_debug_swap *swap));static boolean ecoff_write_symhdr PARAMS ((bfd *, struct ecoff_debug_info *, const struct ecoff_debug_swap *, file_ptr where));static int cmp_fdrtab_entry PARAMS ((const PTR, const PTR));static boolean mk_fdrtab PARAMS ((bfd *, struct ecoff_debug_info * const, const struct ecoff_debug_swap * const, struct ecoff_find_line *));static long fdrtab_lookup PARAMS ((struct ecoff_find_line *, bfd_vma));static boolean lookup_line PARAMS ((bfd *, struct ecoff_debug_info * const, const struct ecoff_debug_swap * const, struct ecoff_find_line *));/* Routines to swap auxiliary information in and out. I am assuming that the auxiliary information format is always going to be target independent. *//* Swap in a type information record. BIGEND says whether AUX symbols are big-endian or little-endian; this info comes from the file header record (fh-fBigendian). */void_bfd_ecoff_swap_tir_in (bigend, ext_copy, intern) int bigend; const struct tir_ext *ext_copy; TIR *intern;{ struct tir_ext ext[1]; *ext = *ext_copy; /* Make it reasonable to do in-place. */ /* now the fun stuff... */ if (bigend) { intern->fBitfield = 0 != (ext->t_bits1[0] & TIR_BITS1_FBITFIELD_BIG); intern->continued = 0 != (ext->t_bits1[0] & TIR_BITS1_CONTINUED_BIG); intern->bt = (ext->t_bits1[0] & TIR_BITS1_BT_BIG) >> TIR_BITS1_BT_SH_BIG; intern->tq4 = (ext->t_tq45[0] & TIR_BITS_TQ4_BIG) >> TIR_BITS_TQ4_SH_BIG; intern->tq5 = (ext->t_tq45[0] & TIR_BITS_TQ5_BIG) >> TIR_BITS_TQ5_SH_BIG; intern->tq0 = (ext->t_tq01[0] & TIR_BITS_TQ0_BIG) >> TIR_BITS_TQ0_SH_BIG; intern->tq1 = (ext->t_tq01[0] & TIR_BITS_TQ1_BIG) >> TIR_BITS_TQ1_SH_BIG; intern->tq2 = (ext->t_tq23[0] & TIR_BITS_TQ2_BIG) >> TIR_BITS_TQ2_SH_BIG; intern->tq3 = (ext->t_tq23[0] & TIR_BITS_TQ3_BIG) >> TIR_BITS_TQ3_SH_BIG; } else { intern->fBitfield = 0 != (ext->t_bits1[0] & TIR_BITS1_FBITFIELD_LITTLE); intern->continued = 0 != (ext->t_bits1[0] & TIR_BITS1_CONTINUED_LITTLE); intern->bt = (ext->t_bits1[0] & TIR_BITS1_BT_LITTLE) >> TIR_BITS1_BT_SH_LITTLE; intern->tq4 = (ext->t_tq45[0] & TIR_BITS_TQ4_LITTLE) >> TIR_BITS_TQ4_SH_LITTLE; intern->tq5 = (ext->t_tq45[0] & TIR_BITS_TQ5_LITTLE) >> TIR_BITS_TQ5_SH_LITTLE; intern->tq0 = (ext->t_tq01[0] & TIR_BITS_TQ0_LITTLE) >> TIR_BITS_TQ0_SH_LITTLE; intern->tq1 = (ext->t_tq01[0] & TIR_BITS_TQ1_LITTLE) >> TIR_BITS_TQ1_SH_LITTLE; intern->tq2 = (ext->t_tq23[0] & TIR_BITS_TQ2_LITTLE) >> TIR_BITS_TQ2_SH_LITTLE; intern->tq3 = (ext->t_tq23[0] & TIR_BITS_TQ3_LITTLE) >> TIR_BITS_TQ3_SH_LITTLE; }#ifdef TEST if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0) abort ();#endif}/* Swap out a type information record. BIGEND says whether AUX symbols are big-endian or little-endian; this info comes from the file header record (fh-fBigendian). */void_bfd_ecoff_swap_tir_out (bigend, intern_copy, ext) int bigend; const TIR *intern_copy; struct tir_ext *ext;{ TIR intern[1]; *intern = *intern_copy; /* Make it reasonable to do in-place. */ /* now the fun stuff... */ if (bigend) { ext->t_bits1[0] = ((intern->fBitfield ? TIR_BITS1_FBITFIELD_BIG : 0) | (intern->continued ? TIR_BITS1_CONTINUED_BIG : 0) | ((intern->bt << TIR_BITS1_BT_SH_BIG) & TIR_BITS1_BT_BIG)); ext->t_tq45[0] = (((intern->tq4 << TIR_BITS_TQ4_SH_BIG) & TIR_BITS_TQ4_BIG) | ((intern->tq5 << TIR_BITS_TQ5_SH_BIG) & TIR_BITS_TQ5_BIG)); ext->t_tq01[0] = (((intern->tq0 << TIR_BITS_TQ0_SH_BIG) & TIR_BITS_TQ0_BIG) | ((intern->tq1 << TIR_BITS_TQ1_SH_BIG) & TIR_BITS_TQ1_BIG)); ext->t_tq23[0] = (((intern->tq2 << TIR_BITS_TQ2_SH_BIG) & TIR_BITS_TQ2_BIG) | ((intern->tq3 << TIR_BITS_TQ3_SH_BIG) & TIR_BITS_TQ3_BIG)); } else { ext->t_bits1[0] = ((intern->fBitfield ? TIR_BITS1_FBITFIELD_LITTLE : 0) | (intern->continued ? TIR_BITS1_CONTINUED_LITTLE : 0) | ((intern->bt << TIR_BITS1_BT_SH_LITTLE) & TIR_BITS1_BT_LITTLE)); ext->t_tq45[0] = (((intern->tq4 << TIR_BITS_TQ4_SH_LITTLE) & TIR_BITS_TQ4_LITTLE) | ((intern->tq5 << TIR_BITS_TQ5_SH_LITTLE) & TIR_BITS_TQ5_LITTLE)); ext->t_tq01[0] = (((intern->tq0 << TIR_BITS_TQ0_SH_LITTLE) & TIR_BITS_TQ0_LITTLE) | ((intern->tq1 << TIR_BITS_TQ1_SH_LITTLE) & TIR_BITS_TQ1_LITTLE)); ext->t_tq23[0] = (((intern->tq2 << TIR_BITS_TQ2_SH_LITTLE) & TIR_BITS_TQ2_LITTLE) | ((intern->tq3 << TIR_BITS_TQ3_SH_LITTLE) & TIR_BITS_TQ3_LITTLE)); }#ifdef TEST if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0) abort ();#endif}/* Swap in a relative symbol record. BIGEND says whether it is in big-endian or little-endian format.*/void_bfd_ecoff_swap_rndx_in (bigend, ext_copy, intern) int bigend; const struct rndx_ext *ext_copy; RNDXR *intern;{ struct rndx_ext ext[1]; *ext = *ext_copy; /* Make it reasonable to do in-place. */ /* now the fun stuff... */ if (bigend) { intern->rfd = (ext->r_bits[0] << RNDX_BITS0_RFD_SH_LEFT_BIG) | ((ext->r_bits[1] & RNDX_BITS1_RFD_BIG) >> RNDX_BITS1_RFD_SH_BIG); intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_BIG) << RNDX_BITS1_INDEX_SH_LEFT_BIG) | (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_BIG) | (ext->r_bits[3] << RNDX_BITS3_INDEX_SH_LEFT_BIG); } else { intern->rfd = (ext->r_bits[0] << RNDX_BITS0_RFD_SH_LEFT_LITTLE) | ((ext->r_bits[1] & RNDX_BITS1_RFD_LITTLE) << RNDX_BITS1_RFD_SH_LEFT_LITTLE); intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_LITTLE) >> RNDX_BITS1_INDEX_SH_LITTLE) | (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_LITTLE) | ((unsigned int) ext->r_bits[3] << RNDX_BITS3_INDEX_SH_LEFT_LITTLE); }#ifdef TEST if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0) abort ();#endif}/* Swap out a relative symbol record. BIGEND says whether it is in big-endian or little-endian format.*/void_bfd_ecoff_swap_rndx_out (bigend, intern_copy, ext) int bigend; const RNDXR *intern_copy; struct rndx_ext *ext;{ RNDXR intern[1]; *intern = *intern_copy; /* Make it reasonable to do in-place. */ /* now the fun stuff... */ if (bigend) { ext->r_bits[0] = intern->rfd >> RNDX_BITS0_RFD_SH_LEFT_BIG; ext->r_bits[1] = (((intern->rfd << RNDX_BITS1_RFD_SH_BIG) & RNDX_BITS1_RFD_BIG) | ((intern->index >> RNDX_BITS1_INDEX_SH_LEFT_BIG) & RNDX_BITS1_INDEX_BIG)); ext->r_bits[2] = intern->index >> RNDX_BITS2_INDEX_SH_LEFT_BIG; ext->r_bits[3] = intern->index >> RNDX_BITS3_INDEX_SH_LEFT_BIG; } else { ext->r_bits[0] = intern->rfd >> RNDX_BITS0_RFD_SH_LEFT_LITTLE; ext->r_bits[1] = (((intern->rfd >> RNDX_BITS1_RFD_SH_LEFT_LITTLE) & RNDX_BITS1_RFD_LITTLE) | ((intern->index << RNDX_BITS1_INDEX_SH_LITTLE) & RNDX_BITS1_INDEX_LITTLE)); ext->r_bits[2] = intern->index >> RNDX_BITS2_INDEX_SH_LEFT_LITTLE; ext->r_bits[3] = intern->index >> RNDX_BITS3_INDEX_SH_LEFT_LITTLE; }#ifdef TEST if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0) abort ();#endif}/* The minimum amount of data to allocate. */#define ALLOC_SIZE (4064)/* Add bytes to a buffer. Return success. */static booleanecoff_add_bytes (buf, bufend, need) char **buf; char **bufend; size_t need;{ size_t have; size_t want; char *newbuf; have = *bufend - *buf; if (have > need) want = ALLOC_SIZE; else { want = need - have; if (want < ALLOC_SIZE) want = ALLOC_SIZE; } newbuf = (char *) bfd_realloc (*buf, have + want); if (newbuf == NULL) return false; *buf = newbuf; *bufend = *buf + have + want; return true;}/* We keep a hash table which maps strings to numbers. We use it to map FDR names to indices in the output file, and to map local strings when combining stabs debugging information. */struct string_hash_entry{ struct bfd_hash_entry root; /* FDR index or string table offset. */ long val; /* Next entry in string table. */ struct string_hash_entry *next;};struct string_hash_table{ struct bfd_hash_table table;};/* Routine to create an entry in a string hash table. */static struct bfd_hash_entry *string_hash_newfunc (entry, table, string) struct bfd_hash_entry *entry; struct bfd_hash_table *table; const char *string;{ struct string_hash_entry *ret = (struct string_hash_entry *) entry; /* Allocate the structure if it has not already been allocated by a subclass. */ if (ret == (struct string_hash_entry *) NULL) ret = ((struct string_hash_entry *) bfd_hash_allocate (table, sizeof (struct string_hash_entry))); if (ret == (struct string_hash_entry *) NULL) return NULL; /* Call the allocation method of the superclass. */ ret = ((struct string_hash_entry *) bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); if (ret) { /* Initialize the local fields. */ ret->val = -1; ret->next = NULL; } return (struct bfd_hash_entry *) ret;}/* Look up an entry in an string hash table. */#define string_hash_lookup(t, string, create, copy) \ ((struct string_hash_entry *) \ bfd_hash_lookup (&(t)->table, (string), (create), (copy)))/* We can't afford to read in all the debugging information when we do a link. Instead, we build a list of these structures to show how different parts of the input file map to the output file. */struct shuffle{ /* The next entry in this linked list. */ struct shuffle *next; /* The length of the information. */ unsigned long size; /* Whether this information comes from a file or not. */ boolean filep; union { struct { /* The BFD the data comes from. */ bfd *input_bfd; /* The offset within input_bfd. */ file_ptr offset; } file; /* The data to be written out. */ PTR memory; } u;};/* This structure holds information across calls to bfd_ecoff_debug_accumulate. */struct accumulate{ /* The FDR hash table. */ struct string_hash_table fdr_hash; /* The strings hash table. */ struct string_hash_table str_hash; /* Linked lists describing how to shuffle the input debug information into the output file. We keep a pointer to both the head and the tail. */ struct shuffle *line; struct shuffle *line_end; struct shuffle *pdr; struct shuffle *pdr_end; struct shuffle *sym; struct shuffle *sym_end; struct shuffle *opt; struct shuffle *opt_end; struct shuffle *aux; struct shuffle *aux_end; struct shuffle *ss; struct shuffle *ss_end; struct string_hash_entry *ss_hash; struct string_hash_entry *ss_hash_end; struct shuffle *fdr; struct shuffle *fdr_end; struct shuffle *rfd; struct shuffle *rfd_end; /* The size of the largest file shuffle. */ unsigned long largest_file_shuffle; /* An objalloc for debugging information. */ struct objalloc *memory;};/* Add a file entry to a shuffle list. */static boolean add_file_shuffle PARAMS ((struct accumulate *, struct shuffle **, struct shuffle **, bfd *, file_ptr, unsigned long));static booleanadd_file_shuffle (ainfo, head, tail, input_bfd, offset, size) struct accumulate *ainfo; struct shuffle **head; struct shuffle **tail; bfd *input_bfd; file_ptr offset; unsigned long size;{ struct shuffle *n; if (*tail != (struct shuffle *) NULL && (*tail)->filep && (*tail)->u.file.input_bfd == input_bfd && (*tail)->u.file.offset + (*tail)->size == (unsigned long) offset) { /* Just merge this entry onto the existing one. */ (*tail)->size += size; if ((*tail)->size > ainfo->largest_file_shuffle) ainfo->largest_file_shuffle = (*tail)->size; return true; } n = (struct shuffle *) objalloc_alloc (ainfo->memory,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?