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 + -
显示快捷键?