示例#1
0
/* Set parameters about this a.out file that are machine-dependent.
   This routine is called from some_aout_object_p just before it returns.  */
static const bfd_target *
MY (callback) (bfd *abfd)
{
  struct internal_exec *execp = exec_hdr (abfd);

  /* Calculate the file positions of the parts of a newly read aout header */
  obj_textsec (abfd)->size = N_TXTSIZE (*execp);

  /* The virtual memory addresses of the sections */
  obj_textsec (abfd)->vma = N_TXTADDR (*execp);
  obj_datasec (abfd)->vma = N_DATADDR (*execp);
  obj_bsssec (abfd)->vma = N_BSSADDR (*execp);

  obj_textsec (abfd)->lma = obj_textsec (abfd)->vma;
  obj_datasec (abfd)->lma = obj_datasec (abfd)->vma;
  obj_bsssec (abfd)->lma = obj_bsssec (abfd)->vma;

  /* The file offsets of the sections */
  obj_textsec (abfd)->filepos = N_TXTOFF (*execp);
  obj_datasec (abfd)->filepos = N_DATOFF (*execp);

  /* The file offsets of the relocation info */
  obj_textsec (abfd)->rel_filepos = N_TRELOFF (*execp);
  obj_datasec (abfd)->rel_filepos = N_DRELOFF (*execp);

  /* The file offsets of the string table and symbol table.  */
  obj_sym_filepos (abfd) = N_SYMOFF (*execp);
  obj_str_filepos (abfd) = N_STROFF (*execp);

  /* Determine the architecture and machine type of the object file.  */
#ifdef SET_ARCH_MACH
  SET_ARCH_MACH (abfd, *execp);
#else
  bfd_default_set_arch_mach (abfd, DEFAULT_ARCH, 0);
#endif

  if (obj_aout_subformat (abfd) == gnu_encap_format)
    {
      /* The file offsets of the relocation info */
      obj_textsec (abfd)->rel_filepos = N_GNU_TRELOFF (*execp);
      obj_datasec (abfd)->rel_filepos = N_GNU_DRELOFF (*execp);

      /* The file offsets of the string table and symbol table.  */
      obj_sym_filepos (abfd) = N_GNU_SYMOFF (*execp);
      obj_str_filepos (abfd) = (obj_sym_filepos (abfd) + execp->a_syms);

      abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
      bfd_get_symcount (abfd) = execp->a_syms / 12;
      obj_symbol_entry_size (abfd) = 12;
      obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
    }

  return abfd->xvec;
}
示例#2
0
bfd_boolean
bfd_set_symtab (bfd *abfd, asymbol **location, unsigned int symcount)
{
  if (abfd->format != bfd_object || bfd_read_p (abfd))
    {
      bfd_set_error (bfd_error_invalid_operation);
      return FALSE;
    }

  bfd_get_outsymbols (abfd) = location;
  bfd_get_symcount (abfd) = symcount;
  return TRUE;
}
示例#3
0
static bfd_boolean
aout_adobe_write_object_contents (bfd *abfd)
{
  struct external_exec swapped_hdr;
  static struct external_segdesc sentinel[1];	/* Initialized to zero.  */
  asection *sect;
  bfd_size_type amt;

  exec_hdr (abfd)->a_info = ZMAGIC;

  /* Calculate text size as total of text sections, etc.  */
  exec_hdr (abfd)->a_text = 0;
  exec_hdr (abfd)->a_data = 0;
  exec_hdr (abfd)->a_bss  = 0;
  exec_hdr (abfd)->a_trsize = 0;
  exec_hdr (abfd)->a_drsize = 0;

  for (sect = abfd->sections; sect; sect = sect->next)
    {
      if (sect->flags & SEC_CODE)
	{
	  exec_hdr (abfd)->a_text += sect->size;
	  exec_hdr (abfd)->a_trsize += sect->reloc_count *
	    sizeof (struct reloc_std_external);
	}
      else if (sect->flags & SEC_DATA)
	{
	  exec_hdr (abfd)->a_data += sect->size;
	  exec_hdr (abfd)->a_drsize += sect->reloc_count *
	    sizeof (struct reloc_std_external);
	}
      else if (sect->flags & SEC_ALLOC && !(sect->flags & SEC_LOAD))
	exec_hdr (abfd)->a_bss += sect->size;
    }

  exec_hdr (abfd)->a_syms = bfd_get_symcount (abfd)
    * sizeof (struct external_nlist);
  exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);

  aout_adobe_swap_exec_header_out (abfd, exec_hdr (abfd), &swapped_hdr);

  amt = EXEC_BYTES_SIZE;
  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
      || bfd_bwrite (& swapped_hdr, amt, abfd) != amt)
    return FALSE;

  /* Now write out the section information.  Text first, data next, rest
     afterward.  */
  for (sect = abfd->sections; sect; sect = sect->next)
    if (sect->flags & SEC_CODE)
      aout_adobe_write_section (abfd, sect);

  for (sect = abfd->sections; sect; sect = sect->next)
    if (sect->flags & SEC_DATA)
      aout_adobe_write_section (abfd, sect);

  for (sect = abfd->sections; sect; sect = sect->next)
    if (!(sect->flags & (SEC_CODE | SEC_DATA)))
      aout_adobe_write_section (abfd, sect);

  /* Write final `sentinel` section header (with type of 0).  */
  amt = sizeof (*sentinel);
  if (bfd_bwrite (sentinel, amt, abfd) != amt)
    return FALSE;

  /* Now write out reloc info, followed by syms and strings.  */
  if (bfd_get_symcount (abfd) != 0)
    {
      if (bfd_seek (abfd, (file_ptr) (N_SYMOFF (*exec_hdr (abfd))), SEEK_SET)
	  != 0)
	return FALSE;

      if (! aout_32_write_syms (abfd))
	return FALSE;

      if (bfd_seek (abfd, (file_ptr) (N_TRELOFF (*exec_hdr (abfd))), SEEK_SET)
	  != 0)
	return FALSE;

      for (sect = abfd->sections; sect; sect = sect->next)
	if (sect->flags & SEC_CODE)
	  if (!aout_32_squirt_out_relocs (abfd, sect))
	    return FALSE;

      if (bfd_seek (abfd, (file_ptr) (N_DRELOFF (*exec_hdr (abfd))), SEEK_SET)
	  != 0)
	return FALSE;

      for (sect = abfd->sections; sect; sect = sect->next)
	if (sect->flags & SEC_DATA)
	  if (!aout_32_squirt_out_relocs (abfd, sect))
	    return FALSE;
    }

  return TRUE;
}
示例#4
0
static void
som_symtab_read (bfd *abfd, struct objfile *objfile,
		 struct section_offsets *section_offsets)
{
  struct cleanup *cleanup;
  struct gdbarch *gdbarch = get_objfile_arch (objfile);
  unsigned int number_of_symbols;
  int val, dynamic;
  char *stringtab;
  asection *shlib_info;
  struct som_external_symbol_dictionary_record *buf, *bufp, *endbufp;
  char *symname;
  CONST int symsize = sizeof (struct som_external_symbol_dictionary_record);


#define text_offset ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile))
#define data_offset ANOFFSET (section_offsets, SECT_OFF_DATA (objfile))

  number_of_symbols = bfd_get_symcount (abfd);

  /* Allocate a buffer to read in the debug info.
     We avoid using alloca because the memory size could be so large
     that we could hit the stack size limit.  */
  buf = xmalloc (symsize * number_of_symbols);
  cleanup = make_cleanup (xfree, buf);
  bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET);
  val = bfd_bread (buf, symsize * number_of_symbols, abfd);
  if (val != symsize * number_of_symbols)
    error (_("Couldn't read symbol dictionary!"));

  /* Allocate a buffer to read in the som stringtab section of
     the debugging info.  Again, we avoid using alloca because
     the data could be so large that we could potentially hit
     the stack size limitat.  */
  stringtab = xmalloc (obj_som_stringtab_size (abfd));
  make_cleanup (xfree, stringtab);
  bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET);
  val = bfd_bread (stringtab, obj_som_stringtab_size (abfd), abfd);
  if (val != obj_som_stringtab_size (abfd))
    error (_("Can't read in HP string table."));

  /* We need to determine if objfile is a dynamic executable (so we
     can do the right thing for ST_ENTRY vs ST_CODE symbols).

     There's nothing in the header which easily allows us to do
     this.

     This code used to rely upon the existence of a $SHLIB_INFO$
     section to make this determination.  HP claims that it is
     more accurate to check for a nonzero text offset, but they
     have not provided any information about why that test is
     more accurate.  */
  dynamic = (text_offset != 0);

  endbufp = buf + number_of_symbols;
  for (bufp = buf; bufp < endbufp; ++bufp)
    {
      enum minimal_symbol_type ms_type;
      unsigned int flags = bfd_getb32 (bufp->flags);
      unsigned int symbol_type
	= (flags >> SOM_SYMBOL_TYPE_SH) & SOM_SYMBOL_TYPE_MASK;
      unsigned int symbol_scope
	= (flags >> SOM_SYMBOL_SCOPE_SH) & SOM_SYMBOL_SCOPE_MASK;
      CORE_ADDR symbol_value = bfd_getb32 (bufp->symbol_value);
      asection *section = NULL;

      QUIT;

      /* Compute the section.  */
      switch (symbol_scope)
	{
	case SS_EXTERNAL:
	  if (symbol_type != ST_STORAGE)
	    section = bfd_und_section_ptr;
	  else
	    section = bfd_com_section_ptr;
	  break;

	case SS_UNSAT:
	  if (symbol_type != ST_STORAGE)
	    section = bfd_und_section_ptr;
	  else
	    section = bfd_com_section_ptr;
	  break;

	case SS_UNIVERSAL:
	  section = bfd_section_from_som_symbol (abfd, bufp);
	  break;

	case SS_LOCAL:
	  section = bfd_section_from_som_symbol (abfd, bufp);
	  break;
	}

      switch (symbol_scope)
	{
	case SS_UNIVERSAL:
	case SS_EXTERNAL:
	  switch (symbol_type)
	    {
	    case ST_SYM_EXT:
	    case ST_ARG_EXT:
	      continue;

	    case ST_CODE:
	    case ST_PRI_PROG:
	    case ST_SEC_PROG:
	    case ST_MILLICODE:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      ms_type = mst_text;
	      symbol_value += text_offset;
	      symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value);
	      break;

	    case ST_ENTRY:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      /* For a dynamic executable, ST_ENTRY symbols are
	         the stubs, while the ST_CODE symbol is the real
	         function.  */
	      if (dynamic)
		ms_type = mst_solib_trampoline;
	      else
		ms_type = mst_text;
	      symbol_value += text_offset;
	      symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value);
	      break;

	    case ST_STUB:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      ms_type = mst_solib_trampoline;
	      symbol_value += text_offset;
	      symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value);
	      break;

	    case ST_DATA:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      symbol_value += data_offset;
	      ms_type = mst_data;
	      break;
	    default:
	      continue;
	    }
	  break;

#if 0
	  /* SS_GLOBAL and SS_LOCAL are two names for the same thing (!).  */
	case SS_GLOBAL:
#endif
	case SS_LOCAL:
	  switch (symbol_type)
	    {
	    case ST_SYM_EXT:
	    case ST_ARG_EXT:
	      continue;

	    case ST_CODE:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      ms_type = mst_file_text;
	      symbol_value += text_offset;
	      symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value);

	    check_strange_names:
	      /* Utah GCC 2.5, FSF GCC 2.6 and later generate correct local
	         label prefixes for stabs, constant data, etc.  So we need
	         only filter out L$ symbols which are left in due to
	         limitations in how GAS generates SOM relocations.

	         When linking in the HPUX C-library the HP linker has
	         the nasty habit of placing section symbols from the literal
	         subspaces in the middle of the program's text.  Filter
	         those out as best we can.  Check for first and last character
	         being '$'.

	         And finally, the newer HP compilers emit crud like $PIC_foo$N
	         in some circumstance (PIC code I guess).  It's also claimed
	         that they emit D$ symbols too.  What stupidity.  */
	      if ((symname[0] == 'L' && symname[1] == '$')
	      || (symname[0] == '$' && symname[strlen (symname) - 1] == '$')
		  || (symname[0] == 'D' && symname[1] == '$')
		  || (strncmp (symname, "L0\001", 3) == 0)
		  || (strncmp (symname, "$PIC", 4) == 0))
		continue;
	      break;

	    case ST_PRI_PROG:
	    case ST_SEC_PROG:
	    case ST_MILLICODE:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      ms_type = mst_file_text;
	      symbol_value += text_offset;
	      symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value);
	      break;

	    case ST_ENTRY:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      /* SS_LOCAL symbols in a shared library do not have
		 export stubs, so we do not have to worry about
		 using mst_file_text vs mst_solib_trampoline here like
		 we do for SS_UNIVERSAL and SS_EXTERNAL symbols above.  */
	      ms_type = mst_file_text;
	      symbol_value += text_offset;
	      symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value);
	      break;

	    case ST_STUB:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      ms_type = mst_solib_trampoline;
	      symbol_value += text_offset;
	      symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value);
	      break;


	    case ST_DATA:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      symbol_value += data_offset;
	      ms_type = mst_file_data;
	      goto check_strange_names;

	    default:
	      continue;
	    }
	  break;

	  /* This can happen for common symbols when -E is passed to the
	     final link.  No idea _why_ that would make the linker force
	     common symbols to have an SS_UNSAT scope, but it does.

	     This also happens for weak symbols, but their type is
	     ST_DATA.  */
	case SS_UNSAT:
	  switch (symbol_type)
	    {
	    case ST_STORAGE:
	    case ST_DATA:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      symbol_value += data_offset;
	      ms_type = mst_data;
	      break;

	    default:
	      continue;
	    }
	  break;

	default:
	  continue;
	}

      if (bfd_getb32 (bufp->name) > obj_som_stringtab_size (abfd))
	error (_("Invalid symbol data; bad HP string table offset: %s"),
	       plongest (bfd_getb32 (bufp->name)));

      if (bfd_is_const_section (section))
	{
	  struct obj_section *iter;

	  ALL_OBJFILE_OSECTIONS (objfile, iter)
	    {
	      if (bfd_is_const_section (iter->the_bfd_section))
		continue;

	      if (obj_section_addr (iter) <= symbol_value
		  && symbol_value < obj_section_endaddr (iter))
		{
		  section = iter->the_bfd_section;
		  break;
		}
	    }
	}

      prim_record_minimal_symbol_and_info (symname, symbol_value, ms_type,
					   gdb_bfd_section_index (objfile->obfd,
								  section),
					   objfile);
    }

  do_cleanups (cleanup);
}
static void
som_symtab_read (bfd *abfd, struct objfile *objfile,
		 struct section_offsets *section_offsets)
{
  unsigned int number_of_symbols;
  int val, dynamic;
  char *stringtab;
  asection *shlib_info;
  struct symbol_dictionary_record *buf, *bufp, *endbufp;
  char *symname;
  CONST int symsize = sizeof (struct symbol_dictionary_record);
  CORE_ADDR text_offset, data_offset;


  text_offset = ANOFFSET (section_offsets, 0);
  data_offset = ANOFFSET (section_offsets, 1);

  number_of_symbols = bfd_get_symcount (abfd);

  /* FIXME (alloca): could be quite large. */
  buf = alloca (symsize * number_of_symbols);
  bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET);
  val = bfd_bread (buf, symsize * number_of_symbols, abfd);
  if (val != symsize * number_of_symbols)
    error ("Couldn't read symbol dictionary!");

  /* FIXME (alloca): could be quite large. */
  stringtab = alloca (obj_som_stringtab_size (abfd));
  bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET);
  val = bfd_bread (stringtab, obj_som_stringtab_size (abfd), abfd);
  if (val != obj_som_stringtab_size (abfd))
    error ("Can't read in HP string table.");

  /* We need to determine if objfile is a dynamic executable (so we
     can do the right thing for ST_ENTRY vs ST_CODE symbols).

     There's nothing in the header which easily allows us to do
     this.

     This code used to rely upon the existence of a $SHLIB_INFO$
     section to make this determination.  HP claims that it is
     more accurate to check for a nonzero text offset, but they
     have not provided any information about why that test is
     more accurate.  */
  dynamic = (text_offset != 0);

  endbufp = buf + number_of_symbols;
  for (bufp = buf; bufp < endbufp; ++bufp)
    {
      enum minimal_symbol_type ms_type;

      QUIT;

      switch (bufp->symbol_scope)
	{
	case SS_UNIVERSAL:
	case SS_EXTERNAL:
	  switch (bufp->symbol_type)
	    {
	    case ST_SYM_EXT:
	    case ST_ARG_EXT:
	      continue;

	    case ST_CODE:
	    case ST_PRI_PROG:
	    case ST_SEC_PROG:
	    case ST_MILLICODE:
	      symname = bufp->name.n_strx + stringtab;
	      ms_type = mst_text;
	      bufp->symbol_value += text_offset;
	      bufp->symbol_value = SMASH_TEXT_ADDRESS (bufp->symbol_value);
	      break;

	    case ST_ENTRY:
	      symname = bufp->name.n_strx + stringtab;
	      /* For a dynamic executable, ST_ENTRY symbols are
	         the stubs, while the ST_CODE symbol is the real
	         function.  */
	      if (dynamic)
		ms_type = mst_solib_trampoline;
	      else
		ms_type = mst_text;
	      bufp->symbol_value += text_offset;
	      bufp->symbol_value = SMASH_TEXT_ADDRESS (bufp->symbol_value);
	      break;

	    case ST_STUB:
	      symname = bufp->name.n_strx + stringtab;
	      ms_type = mst_solib_trampoline;
	      bufp->symbol_value += text_offset;
	      bufp->symbol_value = SMASH_TEXT_ADDRESS (bufp->symbol_value);
	      break;

	    case ST_DATA:
	      symname = bufp->name.n_strx + stringtab;
	      bufp->symbol_value += data_offset;
	      ms_type = mst_data;
	      break;
	    default:
	      continue;
	    }
	  break;

#if 0
	  /* SS_GLOBAL and SS_LOCAL are two names for the same thing (!).  */
	case SS_GLOBAL:
#endif
	case SS_LOCAL:
	  switch (bufp->symbol_type)
	    {
	    case ST_SYM_EXT:
	    case ST_ARG_EXT:
	      continue;

	    case ST_CODE:
	      symname = bufp->name.n_strx + stringtab;
	      ms_type = mst_file_text;
	      bufp->symbol_value += text_offset;
	      bufp->symbol_value = SMASH_TEXT_ADDRESS (bufp->symbol_value);

	    check_strange_names:
	      /* Utah GCC 2.5, FSF GCC 2.6 and later generate correct local
	         label prefixes for stabs, constant data, etc.  So we need
	         only filter out L$ symbols which are left in due to
	         limitations in how GAS generates SOM relocations.

	         When linking in the HPUX C-library the HP linker has
	         the nasty habit of placing section symbols from the literal
	         subspaces in the middle of the program's text.  Filter
	         those out as best we can.  Check for first and last character
	         being '$'. 

	         And finally, the newer HP compilers emit crud like $PIC_foo$N
	         in some circumstance (PIC code I guess).  It's also claimed
	         that they emit D$ symbols too.  What stupidity.  */
	      if ((symname[0] == 'L' && symname[1] == '$')
	      || (symname[0] == '$' && symname[strlen (symname) - 1] == '$')
		  || (symname[0] == 'D' && symname[1] == '$')
		  || (strncmp (symname, "L0\001", 3) == 0)
		  || (strncmp (symname, "$PIC", 4) == 0))
		continue;
	      break;

	    case ST_PRI_PROG:
	    case ST_SEC_PROG:
	    case ST_MILLICODE:
	      symname = bufp->name.n_strx + stringtab;
	      ms_type = mst_file_text;
	      bufp->symbol_value += text_offset;
	      bufp->symbol_value = SMASH_TEXT_ADDRESS (bufp->symbol_value);
	      break;

	    case ST_ENTRY:
	      symname = bufp->name.n_strx + stringtab;
	      /* SS_LOCAL symbols in a shared library do not have
		 export stubs, so we do not have to worry about
		 using mst_file_text vs mst_solib_trampoline here like
		 we do for SS_UNIVERSAL and SS_EXTERNAL symbols above.  */
	      ms_type = mst_file_text;
	      bufp->symbol_value += text_offset;
	      bufp->symbol_value = SMASH_TEXT_ADDRESS (bufp->symbol_value);
	      break;

	    case ST_STUB:
	      symname = bufp->name.n_strx + stringtab;
	      ms_type = mst_solib_trampoline;
	      bufp->symbol_value += text_offset;
	      bufp->symbol_value = SMASH_TEXT_ADDRESS (bufp->symbol_value);
	      break;


	    case ST_DATA:
	      symname = bufp->name.n_strx + stringtab;
	      bufp->symbol_value += data_offset;
	      ms_type = mst_file_data;
	      goto check_strange_names;

	    default:
	      continue;
	    }
	  break;

	  /* This can happen for common symbols when -E is passed to the
	     final link.  No idea _why_ that would make the linker force
	     common symbols to have an SS_UNSAT scope, but it does.

	     This also happens for weak symbols, but their type is
	     ST_DATA.  */
	case SS_UNSAT:
	  switch (bufp->symbol_type)
	    {
	    case ST_STORAGE:
	    case ST_DATA:
	      symname = bufp->name.n_strx + stringtab;
	      bufp->symbol_value += data_offset;
	      ms_type = mst_data;
	      break;

	    default:
	      continue;
	    }
	  break;

	default:
	  continue;
	}

      if (bufp->name.n_strx > obj_som_stringtab_size (abfd))
	error ("Invalid symbol data; bad HP string table offset: %d",
	       bufp->name.n_strx);

      prim_record_minimal_symbol (symname, bufp->symbol_value, ms_type,
				  objfile);
    }
}
static void
read_alphacoff_dynamic_symtab (minimal_symbol_reader &reader,
			       struct section_offsets *section_offsets,
			       struct objfile *objfile)
{
  bfd *abfd = objfile->obfd;
  struct alphacoff_dynsecinfo si;
  char *sym_secptr;
  char *str_secptr;
  char *dyninfo_secptr;
  char *got_secptr;
  bfd_size_type sym_secsize;
  bfd_size_type str_secsize;
  bfd_size_type dyninfo_secsize;
  bfd_size_type got_secsize;
  int sym_count;
  int i;
  int stripped;
  Elfalpha_External_Sym *x_symp;
  char *dyninfo_p;
  char *dyninfo_end;
  int got_entry_size = 8;
  int dt_mips_local_gotno = -1;
  int dt_mips_gotsym = -1;
  struct cleanup *cleanups;

  /* We currently only know how to handle alpha dynamic symbols.  */
  if (bfd_get_arch (abfd) != bfd_arch_alpha)
    return;

  /* Locate the dynamic symbols sections and read them in.  */
  memset ((char *) &si, 0, sizeof (si));
  bfd_map_over_sections (abfd, alphacoff_locate_sections, (void *) & si);
  if (si.sym_sect == NULL || si.str_sect == NULL
      || si.dyninfo_sect == NULL || si.got_sect == NULL)
    return;

  sym_secsize = bfd_get_section_size (si.sym_sect);
  str_secsize = bfd_get_section_size (si.str_sect);
  dyninfo_secsize = bfd_get_section_size (si.dyninfo_sect);
  got_secsize = bfd_get_section_size (si.got_sect);
  sym_secptr = (char *) xmalloc (sym_secsize);
  cleanups = make_cleanup (xfree, sym_secptr);
  str_secptr = (char *) xmalloc (str_secsize);
  make_cleanup (xfree, str_secptr);
  dyninfo_secptr = (char *) xmalloc (dyninfo_secsize);
  make_cleanup (xfree, dyninfo_secptr);
  got_secptr = (char *) xmalloc (got_secsize);
  make_cleanup (xfree, got_secptr);

  if (!bfd_get_section_contents (abfd, si.sym_sect, sym_secptr,
				 (file_ptr) 0, sym_secsize))
    {
      do_cleanups (cleanups);
      return;
    }
  if (!bfd_get_section_contents (abfd, si.str_sect, str_secptr,
				 (file_ptr) 0, str_secsize))
    {
      do_cleanups (cleanups);
      return;
    }
  if (!bfd_get_section_contents (abfd, si.dyninfo_sect, dyninfo_secptr,
				 (file_ptr) 0, dyninfo_secsize))
    {
      do_cleanups (cleanups);
      return;
    }
  if (!bfd_get_section_contents (abfd, si.got_sect, got_secptr,
				 (file_ptr) 0, got_secsize))
    {
      do_cleanups (cleanups);
      return;
    }

  /* Find the number of local GOT entries and the index for the
     first dynamic symbol in the GOT.  */
  for (dyninfo_p = dyninfo_secptr, dyninfo_end = dyninfo_p + dyninfo_secsize;
       dyninfo_p < dyninfo_end;
       dyninfo_p += sizeof (Elfalpha_External_Dyn))
    {
      Elfalpha_External_Dyn *x_dynp = (Elfalpha_External_Dyn *) dyninfo_p;
      long dyn_tag;

      dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_tag);
      if (dyn_tag == DT_NULL)
	break;
      else if (dyn_tag == DT_MIPS_LOCAL_GOTNO)
	{
	  if (dt_mips_local_gotno < 0)
	    dt_mips_local_gotno
	      = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
	}
      else if (dyn_tag == DT_MIPS_GOTSYM)
	{
	  if (dt_mips_gotsym < 0)
	    dt_mips_gotsym
	      = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
	}
    }
  if (dt_mips_local_gotno < 0 || dt_mips_gotsym < 0)
    {
      do_cleanups (cleanups);
      return;
    }

  /* Scan all dynamic symbols and enter them into the minimal symbol
     table if appropriate.  */
  sym_count = sym_secsize / sizeof (Elfalpha_External_Sym);
  stripped = (bfd_get_symcount (abfd) == 0);

  /* Skip first symbol, which is a null dummy.  */
  for (i = 1, x_symp = (Elfalpha_External_Sym *) sym_secptr + 1;
       i < sym_count;
       i++, x_symp++)
    {
      unsigned long strx;
      char *name;
      bfd_vma sym_value;
      unsigned char sym_info;
      unsigned int sym_shndx;
      int isglobal;
      enum minimal_symbol_type ms_type;

      strx = bfd_h_get_32 (abfd, (bfd_byte *) x_symp->st_name);
      if (strx >= str_secsize)
	continue;
      name = str_secptr + strx;
      if (*name == '\0' || *name == '.')
	continue;

      sym_value = bfd_h_get_64 (abfd, (bfd_byte *) x_symp->st_value);
      sym_info = bfd_h_get_8 (abfd, (bfd_byte *) x_symp->st_info);
      sym_shndx = bfd_h_get_16 (abfd, (bfd_byte *) x_symp->st_shndx);
      if (sym_shndx >= (SHN_LORESERVE & 0xffff))
	sym_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff);
      isglobal = (ELF_ST_BIND (sym_info) == STB_GLOBAL);

      if (sym_shndx == SHN_UNDEF)
	{
	  /* Handle undefined functions which are defined in a shared
	     library.  */
	  if (ELF_ST_TYPE (sym_info) != STT_FUNC
	      || ELF_ST_BIND (sym_info) != STB_GLOBAL)
	    continue;

	  ms_type = mst_solib_trampoline;

	  /* If sym_value is nonzero, it points to the shared library
	     trampoline entry, which is what we are looking for.

	     If sym_value is zero, then we have to get the GOT entry
	     for the symbol.

	     If the GOT entry is nonzero, it represents the quickstart
	     address of the function and we use that as the symbol
	     value.

	     If the GOT entry is zero, the function address has to be
	     resolved by the runtime loader before the executable is
	     started.  We are unable to find any meaningful address
	     for these functions in the executable file, so we skip
	     them.  */
	  if (sym_value == 0)
	    {
	      int got_entry_offset =
		(i - dt_mips_gotsym + dt_mips_local_gotno) * got_entry_size;

	      if (got_entry_offset < 0 || got_entry_offset >= got_secsize)
		continue;
	      sym_value =
		bfd_h_get_64 (abfd,
			      (bfd_byte *) (got_secptr + got_entry_offset));
	      if (sym_value == 0)
		continue;
	    }
	}
      else
	{
	  /* Symbols defined in the executable itself.  We only care
	     about them if this is a stripped executable, otherwise
	     they have been retrieved from the normal symbol table
	     already.  */
	  if (!stripped)
	    continue;

	  if (sym_shndx == SHN_MIPS_TEXT)
	    {
	      if (isglobal)
		ms_type = mst_text;
	      else
		ms_type = mst_file_text;
	    }
	  else if (sym_shndx == SHN_MIPS_DATA)
	    {
	      if (isglobal)
		ms_type = mst_data;
	      else
		ms_type = mst_file_data;
	    }
	  else if (sym_shndx == SHN_MIPS_ACOMMON)
	    {
	      if (isglobal)
		ms_type = mst_bss;
	      else
		ms_type = mst_file_bss;
	    }
	  else if (sym_shndx == SHN_ABS)
	    {
	      ms_type = mst_abs;
	    }
	  else
	    {
	      continue;
	    }
	}

      reader.record (name, sym_value, ms_type);
    }

  do_cleanups (cleanups);
}
示例#7
0
static void
elf_symtab_read (struct objfile *objfile, int dynamic)
{
  long storage_needed;
  asymbol *sym;
  asymbol **symbol_table;
  long number_of_symbols;
  long i;
  int index;
  struct cleanup *back_to;
  CORE_ADDR symaddr;
  CORE_ADDR offset;
  enum minimal_symbol_type ms_type;
  /* If sectinfo is nonNULL, it contains section info that should end up
     filed in the objfile.  */
  struct stab_section_info *sectinfo = NULL;
  /* If filesym is nonzero, it points to a file symbol, but we haven't
     seen any section info for it yet.  */
  asymbol *filesym = 0;
#ifdef SOFUN_ADDRESS_MAYBE_MISSING
  /* Name of filesym, as saved on the symbol_obstack.  */
  char *filesymname = obsavestring ("", 0, &objfile->symbol_obstack);
#endif
  struct dbx_symfile_info *dbx = objfile->sym_stab_info;
  unsigned long size;
  int stripped = (bfd_get_symcount (objfile->obfd) == 0);

  if (dynamic)
    {
      storage_needed = bfd_get_dynamic_symtab_upper_bound (objfile->obfd);

      /* Nothing to be done if there is no dynamic symtab.  */
      if (storage_needed < 0)
	return;
    }
  else
    {
      storage_needed = bfd_get_symtab_upper_bound (objfile->obfd);
      if (storage_needed < 0)
	error ("Can't read symbols from %s: %s", bfd_get_filename (objfile->obfd),
	       bfd_errmsg (bfd_get_error ()));
    }
  if (storage_needed > 0)
    {
      symbol_table = (asymbol **) xmalloc (storage_needed);
      back_to = make_cleanup (xfree, symbol_table);
      if (dynamic)
	number_of_symbols = bfd_canonicalize_dynamic_symtab (objfile->obfd,
							     symbol_table);
      else
	number_of_symbols = bfd_canonicalize_symtab (objfile->obfd, symbol_table);
      if (number_of_symbols < 0)
	error ("Can't read symbols from %s: %s", bfd_get_filename (objfile->obfd),
	       bfd_errmsg (bfd_get_error ()));

      for (i = 0; i < number_of_symbols; i++)
	{
	  sym = symbol_table[i];
	  if (sym->name == NULL || *sym->name == '\0')
	    {
	      /* Skip names that don't exist (shouldn't happen), or names
	         that are null strings (may happen). */
	      continue;
	    }

          offset = ANOFFSET (objfile->section_offsets, sym->section->index);
	  if (dynamic
	      && sym->section == &bfd_und_section
	      && (sym->flags & BSF_FUNCTION))
	    {
	      struct minimal_symbol *msym;

	      /* Symbol is a reference to a function defined in
	         a shared library.
	         If its value is non zero then it is usually the address
	         of the corresponding entry in the procedure linkage table,
	         plus the desired section offset.
	         If its value is zero then the dynamic linker has to resolve
	         the symbol. We are unable to find any meaningful address
	         for this symbol in the executable file, so we skip it.  */
	      symaddr = sym->value;
	      if (symaddr == 0)
		continue;
	      symaddr += offset;
	      msym = record_minimal_symbol_and_info
		((char *) sym->name, symaddr,
		 mst_solib_trampoline, NULL, sym->section, objfile);
#ifdef SOFUN_ADDRESS_MAYBE_MISSING
	      if (msym != NULL)
		msym->filename = filesymname;
#endif
	      continue;
	    }

	  /* If it is a nonstripped executable, do not enter dynamic
	     symbols, as the dynamic symbol table is usually a subset
	     of the main symbol table.  */
	  if (dynamic && !stripped)
	    continue;
	  if (sym->flags & BSF_FILE)
	    {
	      /* STT_FILE debugging symbol that helps stabs-in-elf debugging.
	         Chain any old one onto the objfile; remember new sym.  */
	      if (sectinfo != NULL)
		{
		  sectinfo->next = dbx->stab_section_info;
		  dbx->stab_section_info = sectinfo;
		  sectinfo = NULL;
		}
	      filesym = sym;
#ifdef SOFUN_ADDRESS_MAYBE_MISSING
	      filesymname =
		obsavestring ((char *) filesym->name, strlen (filesym->name),
			      &objfile->symbol_obstack);
#endif
	    }
	  else if (sym->flags & (BSF_GLOBAL | BSF_LOCAL | BSF_WEAK))
	    {
	      struct minimal_symbol *msym;

	      /* Select global/local/weak symbols.  Note that bfd puts abs
	         symbols in their own section, so all symbols we are
	         interested in will have a section. */
	      /* Bfd symbols are section relative. */
	      symaddr = sym->value + sym->section->vma;
	      /* Relocate all non-absolute symbols by the section offset.  */
	      if (sym->section != &bfd_abs_section)
		{
		  symaddr += offset;
		}
	      /* For non-absolute symbols, use the type of the section
	         they are relative to, to intuit text/data.  Bfd provides
	         no way of figuring this out for absolute symbols. */
	      if (sym->section == &bfd_abs_section)
		{
		  /* This is a hack to get the minimal symbol type
		     right for Irix 5, which has absolute addresses
		     with special section indices for dynamic symbols. */
		  unsigned short shndx =
		  ((elf_symbol_type *) sym)->internal_elf_sym.st_shndx;

		  switch (shndx)
		    {
		    case SHN_MIPS_TEXT:
		      ms_type = mst_text;
		      break;
		    case SHN_MIPS_DATA:
		      ms_type = mst_data;
		      break;
		    case SHN_MIPS_ACOMMON:
		      ms_type = mst_bss;
		      break;
		    default:
		      ms_type = mst_abs;
		    }

		  /* If it is an Irix dynamic symbol, skip section name
		     symbols, relocate all others by section offset. */
		  if (ms_type != mst_abs)
		    {
		      if (sym->name[0] == '.')
			continue;
		      symaddr += offset;
		    }
		}
	      else if (sym->section->flags & SEC_CODE)
		{
		  if (sym->flags & BSF_GLOBAL)
		    {
		      ms_type = mst_text;
		    }
		  else if ((sym->name[0] == '.' && sym->name[1] == 'L')
			   || ((sym->flags & BSF_LOCAL)
			       && sym->name[0] == '$'
			       && sym->name[1] == 'L'))
		    /* Looks like a compiler-generated label.  Skip
		       it.  The assembler should be skipping these (to
		       keep executables small), but apparently with
		       gcc on the (OBSOLETE) delta m88k SVR4, it
		       loses.  So to have us check too should be
		       harmless (but I encourage people to fix this in
		       the assembler instead of adding checks here).  */
		    continue;
		  else
		    {
		      ms_type = mst_file_text;
		    }
		}
	      else if (sym->section->flags & SEC_ALLOC)
		{
		  if (sym->flags & (BSF_GLOBAL | BSF_WEAK))
		    {
		      if (sym->section->flags & SEC_LOAD)
			{
			  ms_type = mst_data;
			}
		      else
			{
			  ms_type = mst_bss;
			}
		    }
		  else if (sym->flags & BSF_LOCAL)
		    {
		      /* Named Local variable in a Data section.  Check its
		         name for stabs-in-elf.  The STREQ macro checks the
		         first character inline, so we only actually do a
		         strcmp function call on names that start with 'B'
		         or 'D' */
		      index = SECT_OFF_MAX;
		      if (STREQ ("Bbss.bss", sym->name))
			{
			  index = SECT_OFF_BSS (objfile);
			}
		      else if (STREQ ("Ddata.data", sym->name))
			{
			  index = SECT_OFF_DATA (objfile);
			}
		      else if (STREQ ("Drodata.rodata", sym->name))
			{
			  index = SECT_OFF_RODATA (objfile);
			}
		      if (index != SECT_OFF_MAX)
			{
			  /* Found a special local symbol.  Allocate a
			     sectinfo, if needed, and fill it in.  */
			  if (sectinfo == NULL)
			    {
			      sectinfo = (struct stab_section_info *)
				xmmalloc (objfile->md, sizeof (*sectinfo));
			      memset (sectinfo, 0,
				      sizeof (*sectinfo));
			      if (filesym == NULL)
				{
				  complain (&section_info_complaint,
					    sym->name);
				}
			      else
				{
				  sectinfo->filename =
				    (char *) filesym->name;
				}
			    }
			  if (index != -1)
			    { 
			      if (sectinfo->sections[index] != 0)
				{
				  complain (&section_info_dup_complaint,
					    sectinfo->filename);
				}
			    }
			  else
			    internal_error (__FILE__, __LINE__,
					    "Section index uninitialized.");
			  /* Bfd symbols are section relative. */
			  symaddr = sym->value + sym->section->vma;
			  /* Relocate non-absolute symbols by the section offset. */
			  if (sym->section != &bfd_abs_section)
			    {
			      symaddr += offset;
			    }
			  if (index != -1)
			    sectinfo->sections[index] = symaddr;
			  else
			    internal_error (__FILE__, __LINE__,
					    "Section index uninitialized.");
			  /* The special local symbols don't go in the
			     minimal symbol table, so ignore this one. */
			  continue;
			}
		      /* Not a special stabs-in-elf symbol, do regular
		         symbol processing. */
		      if (sym->section->flags & SEC_LOAD)
			{
			  ms_type = mst_file_data;
			}
		      else
			{
			  ms_type = mst_file_bss;
			}
		    }
		  else
		    {
		      ms_type = mst_unknown;
		    }
		}
	      else
		{
		  /* FIXME:  Solaris2 shared libraries include lots of
		     odd "absolute" and "undefined" symbols, that play 
		     hob with actions like finding what function the PC
		     is in.  Ignore them if they aren't text, data, or bss.  */
		  /* ms_type = mst_unknown; */
		  continue;	/* Skip this symbol. */
		}
	      /* Pass symbol size field in via BFD.  FIXME!!!  */
	      size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
	      msym = record_minimal_symbol_and_info
		((char *) sym->name, symaddr,
		 ms_type, (void *) size, sym->section, objfile);
#ifdef SOFUN_ADDRESS_MAYBE_MISSING
	      if (msym != NULL)
		msym->filename = filesymname;
#endif
	      ELF_MAKE_MSYMBOL_SPECIAL (sym, msym);
	    }
	}
      do_cleanups (back_to);
    }
}
示例#8
0
static bfd_boolean
MY (write_object_contents) (bfd * abfd)
{
  struct external_exec exec_bytes;
  struct internal_exec *execp = exec_hdr (abfd);
  bfd_size_type text_size;	/* dummy vars */
  file_ptr text_end;

  memset (&exec_bytes, 0, sizeof (exec_bytes));

  obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;

  if (adata (abfd).magic == undecided_magic)
    NAME (aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end);
  execp->a_syms = 0;

  execp->a_entry = bfd_get_start_address (abfd);

  execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *
		     obj_reloc_entry_size (abfd));
  execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *
		     obj_reloc_entry_size (abfd));

  N_SET_MACHTYPE (*execp, 0xc);
  N_SET_FLAGS (*execp, aout_backend_info (abfd)->exec_hdr_flags);

  NAME (aout,swap_exec_header_out) (abfd, execp, &exec_bytes);

  /* update fields not covered by default swap_exec_header_out */

  /* this is really the sym table size but we store it in drelocs */
  H_PUT_32 (abfd, (bfd_get_symcount (abfd) * 12), exec_bytes.e_drelocs);

  if (bfd_seek (abfd, (file_ptr) 0, FALSE) != 0
      || (bfd_bwrite (&exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, abfd)
	  != EXEC_BYTES_SIZE))
    return FALSE;

  /* Write out the symbols, and then the relocs.  We must write out
       the symbols first so that we know the symbol indices.  */

  if (bfd_get_symcount (abfd) != 0)
    {
      /* Skip the relocs to where we want to put the symbols.  */
      if (bfd_seek (abfd, (file_ptr) (N_DRELOFF (*execp) + execp->a_drsize),
		    SEEK_SET) != 0)
	return FALSE;
    }

  if (!MY (write_syms) (abfd))
    return FALSE;

  if (bfd_get_symcount (abfd) != 0)
    {
      if (bfd_seek (abfd, (file_ptr) N_TRELOFF (*execp), SEEK_CUR) != 0)
	return FALSE;
      if (!NAME (aout,squirt_out_relocs) (abfd, obj_textsec (abfd)))
	return FALSE;
      if (bfd_seek (abfd, (file_ptr) N_DRELOFF (*execp), SEEK_CUR) != 0)
	return FALSE;
      if (!NAME (aout,squirt_out_relocs) (abfd, obj_datasec (abfd)))
	return FALSE;
    }

  return TRUE;
}