ecoff.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,282 行 · 第 1/5 页

C
2,282
字号
  PTR raw = NULL;  HDRR *internal_symhdr;  /* See if we've already read it in.  */  if (ecoff_data (abfd)->debug_info.symbolic_header.magic ==      backend->debug_swap.sym_magic)    return true;  /* See whether there is a symbolic header.  */  if (ecoff_data (abfd)->sym_filepos == 0)    {      bfd_get_symcount (abfd) = 0;      return true;    }  /* At this point bfd_get_symcount (abfd) holds the number of symbols     as read from the file header, but on ECOFF this is always the     size of the symbolic information header.  It would be cleaner to     handle this when we first read the file in coffgen.c.  */  external_hdr_size = backend->debug_swap.external_hdr_size;  if (bfd_get_symcount (abfd) != external_hdr_size)    {      bfd_set_error (bfd_error_bad_value);      return false;    }  /* Read the symbolic information header.  */  raw = (PTR) bfd_malloc ((size_t) external_hdr_size);  if (raw == NULL)    goto error_return;  if (bfd_seek (abfd, ecoff_data (abfd)->sym_filepos, SEEK_SET) == -1      || (bfd_read (raw, external_hdr_size, 1, abfd)	  != external_hdr_size))    goto error_return;  internal_symhdr = &ecoff_data (abfd)->debug_info.symbolic_header;  (*backend->debug_swap.swap_hdr_in) (abfd, raw, internal_symhdr);  if (internal_symhdr->magic != backend->debug_swap.sym_magic)    {      bfd_set_error (bfd_error_bad_value);      goto error_return;    }  /* Now we can get the correct number of symbols.  */  bfd_get_symcount (abfd) = (internal_symhdr->isymMax			     + internal_symhdr->iextMax);  if (raw != NULL)    free (raw);  return true; error_return:  if (raw != NULL)    free (raw);  return false;}/* Read in and swap the important symbolic information for an ECOFF   object file.  This is called by gdb via the read_debug_info entry   point in the backend structure.  */boolean_bfd_ecoff_slurp_symbolic_info (abfd, ignore, debug)     bfd *abfd;     asection *ignore ATTRIBUTE_UNUSED;     struct ecoff_debug_info *debug;{  const struct ecoff_backend_data * const backend = ecoff_backend (abfd);  HDRR *internal_symhdr;  bfd_size_type raw_base;  bfd_size_type raw_size;  PTR raw;  bfd_size_type external_fdr_size;  char *fraw_src;  char *fraw_end;  struct fdr *fdr_ptr;  bfd_size_type raw_end;  bfd_size_type cb_end;  BFD_ASSERT (debug == &ecoff_data (abfd)->debug_info);  /* Check whether we've already gotten it, and whether there's any to     get.  */  if (ecoff_data (abfd)->raw_syments != (PTR) NULL)    return true;  if (ecoff_data (abfd)->sym_filepos == 0)    {      bfd_get_symcount (abfd) = 0;      return true;    }  if (! ecoff_slurp_symbolic_header (abfd))    return false;  internal_symhdr = &debug->symbolic_header;  /* Read all the symbolic information at once.  */  raw_base = (ecoff_data (abfd)->sym_filepos	      + backend->debug_swap.external_hdr_size);  /* Alpha ecoff makes the determination of raw_size difficult. It has     an undocumented debug data section between the symhdr and the first     documented section. And the ordering of the sections varies between     statically and dynamically linked executables.     If bfd supports SEEK_END someday, this code could be simplified.  */  raw_end = 0;#define UPDATE_RAW_END(start, count, size) \  cb_end = internal_symhdr->start + internal_symhdr->count * (size); \  if (cb_end > raw_end) \    raw_end = cb_end  UPDATE_RAW_END (cbLineOffset, cbLine, sizeof (unsigned char));  UPDATE_RAW_END (cbDnOffset, idnMax, backend->debug_swap.external_dnr_size);  UPDATE_RAW_END (cbPdOffset, ipdMax, backend->debug_swap.external_pdr_size);  UPDATE_RAW_END (cbSymOffset, isymMax, backend->debug_swap.external_sym_size);  UPDATE_RAW_END (cbOptOffset, ioptMax, backend->debug_swap.external_opt_size);  UPDATE_RAW_END (cbAuxOffset, iauxMax, sizeof (union aux_ext));  UPDATE_RAW_END (cbSsOffset, issMax, sizeof (char));  UPDATE_RAW_END (cbSsExtOffset, issExtMax, sizeof (char));  UPDATE_RAW_END (cbFdOffset, ifdMax, backend->debug_swap.external_fdr_size);  UPDATE_RAW_END (cbRfdOffset, crfd, backend->debug_swap.external_rfd_size);  UPDATE_RAW_END (cbExtOffset, iextMax, backend->debug_swap.external_ext_size);#undef UPDATE_RAW_END  raw_size = raw_end - raw_base;  if (raw_size == 0)    {      ecoff_data (abfd)->sym_filepos = 0;      return true;    }  raw = (PTR) bfd_alloc (abfd, raw_size);  if (raw == NULL)    return false;  if (bfd_seek (abfd,		(ecoff_data (abfd)->sym_filepos		 + backend->debug_swap.external_hdr_size),		SEEK_SET) != 0      || bfd_read (raw, raw_size, 1, abfd) != raw_size)    {      bfd_release (abfd, raw);      return false;    }  ecoff_data (abfd)->raw_syments = raw;  /* Get pointers for the numeric offsets in the HDRR structure.  */#define FIX(off1, off2, type) \  if (internal_symhdr->off1 == 0) \    debug->off2 = (type) NULL; \  else \    debug->off2 = (type) ((char *) raw \			  + (internal_symhdr->off1 \			     - raw_base))  FIX (cbLineOffset, line, unsigned char *);  FIX (cbDnOffset, external_dnr, PTR);  FIX (cbPdOffset, external_pdr, PTR);  FIX (cbSymOffset, external_sym, PTR);  FIX (cbOptOffset, external_opt, PTR);  FIX (cbAuxOffset, external_aux, union aux_ext *);  FIX (cbSsOffset, ss, char *);  FIX (cbSsExtOffset, ssext, char *);  FIX (cbFdOffset, external_fdr, PTR);  FIX (cbRfdOffset, external_rfd, PTR);  FIX (cbExtOffset, external_ext, PTR);#undef FIX  /* I don't want to always swap all the data, because it will just     waste time and most programs will never look at it.  The only     time the linker needs most of the debugging information swapped     is when linking big-endian and little-endian MIPS object files     together, which is not a common occurrence.     We need to look at the fdr to deal with a lot of information in     the symbols, so we swap them here.  */  debug->fdr = (struct fdr *) bfd_alloc (abfd,					 (internal_symhdr->ifdMax *					  sizeof (struct fdr)));  if (debug->fdr == NULL)    return false;  external_fdr_size = backend->debug_swap.external_fdr_size;  fdr_ptr = debug->fdr;  fraw_src = (char *) debug->external_fdr;  fraw_end = fraw_src + internal_symhdr->ifdMax * external_fdr_size;  for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)    (*backend->debug_swap.swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr);  return true;}/* ECOFF symbol table routines.  The ECOFF symbol table is described   in gcc/mips-tfile.c.  *//* ECOFF uses two common sections.  One is the usual one, and the   other is for small objects.  All the small objects are kept   together, and then referenced via the gp pointer, which yields   faster assembler code.  This is what we use for the small common   section.  */static asection ecoff_scom_section;static asymbol ecoff_scom_symbol;static asymbol *ecoff_scom_symbol_ptr;/* Create an empty symbol.  */asymbol *_bfd_ecoff_make_empty_symbol (abfd)     bfd *abfd;{  ecoff_symbol_type *new;  new = (ecoff_symbol_type *) bfd_alloc (abfd, sizeof (ecoff_symbol_type));  if (new == (ecoff_symbol_type *) NULL)    return (asymbol *) NULL;  memset ((PTR) new, 0, sizeof *new);  new->symbol.section = (asection *) NULL;  new->fdr = (FDR *) NULL;  new->local = false;  new->native = NULL;  new->symbol.the_bfd = abfd;  return &new->symbol;}/* Set the BFD flags and section for an ECOFF symbol.  */static booleanecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, weak)     bfd *abfd;     SYMR *ecoff_sym;     asymbol *asym;     int ext;     int weak;{  asym->the_bfd = abfd;  asym->value = ecoff_sym->value;  asym->section = &bfd_debug_section;  asym->udata.i = 0;  /* Most symbol types are just for debugging.  */  switch (ecoff_sym->st)    {    case stGlobal:    case stStatic:    case stLabel:    case stProc:    case stStaticProc:      break;    case stNil:      if (ECOFF_IS_STAB (ecoff_sym))	{	  asym->flags = BSF_DEBUGGING;	  return true;	}      break;    default:      asym->flags = BSF_DEBUGGING;      return true;    }  if (weak)    asym->flags = BSF_EXPORT | BSF_WEAK;  else if (ext)    asym->flags = BSF_EXPORT | BSF_GLOBAL;  else    {      asym->flags = BSF_LOCAL;      /* Normally, a local stProc symbol will have a corresponding         external symbol.  We mark the local symbol as a debugging         symbol, in order to prevent nm from printing both out.         Similarly, we mark stLabel and stabs symbols as debugging         symbols.  In both cases, we do want to set the value         correctly based on the symbol class.  */      if (ecoff_sym->st == stProc	  || ecoff_sym->st == stLabel	  || ECOFF_IS_STAB (ecoff_sym))	asym->flags |= BSF_DEBUGGING;    }  switch (ecoff_sym->sc)    {    case scNil:      /* Used for compiler generated labels.  Leave them in the	 debugging section, and mark them as local.  If BSF_DEBUGGING	 is set, then nm does not display them for some reason.  If no	 flags are set then the linker whines about them.  */      asym->flags = BSF_LOCAL;      break;    case scText:      asym->section = bfd_make_section_old_way (abfd, ".text");      asym->value -= asym->section->vma;      break;    case scData:      asym->section = bfd_make_section_old_way (abfd, ".data");      asym->value -= asym->section->vma;      break;    case scBss:      asym->section = bfd_make_section_old_way (abfd, ".bss");      asym->value -= asym->section->vma;      break;    case scRegister:      asym->flags = BSF_DEBUGGING;      break;    case scAbs:      asym->section = bfd_abs_section_ptr;      break;    case scUndefined:      asym->section = bfd_und_section_ptr;      asym->flags = 0;      asym->value = 0;      break;    case scCdbLocal:    case scBits:    case scCdbSystem:    case scRegImage:    case scInfo:    case scUserStruct:      asym->flags = BSF_DEBUGGING;      break;    case scSData:      asym->section = bfd_make_section_old_way (abfd, ".sdata");      asym->value -= asym->section->vma;      break;    case scSBss:      asym->section = bfd_make_section_old_way (abfd, ".sbss");      asym->value -= asym->section->vma;      break;    case scRData:      asym->section = bfd_make_section_old_way (abfd, ".rdata");      asym->value -= asym->section->vma;      break;    case scVar:      asym->flags = BSF_DEBUGGING;      break;    case scCommon:      if (asym->value > ecoff_data (abfd)->gp_size)	{	  asym->section = bfd_com_section_ptr;	  asym->flags = 0;	  break;	}      /* Fall through.  */    case scSCommon:      if (ecoff_scom_section.name == NULL)	{	  /* Initialize the small common section.  */	  ecoff_scom_section.name = SCOMMON;	  ecoff_scom_section.flags = SEC_IS_COMMON;	  ecoff_scom_section.output_section = &ecoff_scom_section;	  ecoff_scom_section.symbol = &ecoff_scom_symbol;	  ecoff_scom_section.symbol_ptr_ptr = &ecoff_scom_symbol_ptr;	  ecoff_scom_symbol.name = SCOMMON;	  ecoff_scom_symbol.flags = BSF_SECTION_SYM;	  ecoff_scom_symbol.section = &ecoff_scom_section;	  ecoff_scom_symbol_ptr = &ecoff_scom_symbol;	}      asym->section = &ecoff_scom_section;      asym->flags = 0;      break;    case scVarRegister:    case scVariant:      asym->flags = BSF_DEBUGGING;      break;    case scSUndefined:      asym->section = bfd_und_section_ptr;      asym->flags = 0;      asym->value = 0;      break;    case scInit:      asym->section = bfd_make_section_old_way (abfd, ".init");      asym->value -= asym->section->vma;      break;    case scBasedVar:    case scXData:    case scPData:      asym->flags = BSF_DEBUGGING;      break;    case scFini:      asym->section = bfd_make_section_old_way (abfd, ".fini");      asym->value -= asym->section->vma;      break;    case scRConst:      asym->section = bfd_make_section_old_way (abfd, ".rconst");      asym->value -= asym->section->vma;      break;    default:      break;    }  /* Look for special constructors symbols and make relocation entries     in a special construction section.  These are produced by the     -fgnu-linker argument to g++.  */  if (ECOFF_IS_STAB (ecoff_sym))    {      switch (ECOFF_UNMARK_STAB (ecoff_sym->index))	{	default:	  break;	case N_SETA:	case N_SETT:	case N_SETD:	case N_SETB:	  {	    /* This code is no longer needed.  It used to be used to	       make the linker handle set symbols, but they are now	       handled in the add_symbols routine instead.  */#if 0	    const char *name;	    asection *section;	    arelent_chain *reloc_chain;	    unsigned int bitsize;	    /* Get a section with the same name as the symbol (usually	       __CTOR_LIST__ or __DTOR_LIST__).  FIXME: gcc uses the	       name ___CTOR_LIST (three underscores).  We need	       __CTOR_LIST (two underscores), since ECOFF doesn't use	       a leading underscore.  This should be handled by gcc,	       but instead we do it here.  Actually, this should all	       be done differently anyhow.  */	    name = bfd_asymbol_name (asym);	    if (name[0] == '_' && name[1] == '_' && name[2] == '_')	      {		++name;		asym->name = name;	      }	    section = bfd_get_section_by_name (abfd, name);	    if (section == (asection *) NULL)	      {		char *copy;		copy = (char *) bfd_alloc (abfd, strlen (name) + 1);		if (!copy)		  return false;		strcpy (copy, name);		section = bfd_make_section (abfd, copy);	      }	    /* Build a reloc pointing to this constructor.  */	    reloc_chain =	      (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain));	    if (!reloc_chain)	      return false;	    reloc_chain->relent.sym_ptr_ptr =	      bfd_get_section (asym)->symbol_ptr_ptr;	    reloc_chain->relent.address = section->_raw_size;	    reloc_chain->relent.addend = asym->value;	    reloc_chain->relent.howto =	      ecoff_backend (abfd)->constructor_reloc;	    /* Set up the constructor section to hold the reloc.  */	    section->flags = SEC_CONSTRUCTOR;	    ++section->reloc_count;	    /* Constructor sections must be rounded to a boundary	       based on the bitsize.  These are not real sections--	       they are handled specially by the linker--so the ECOFF	       16 byte alignment restriction does not apply.  */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?