Esempio n. 1
0
const bfd_target *
rs6000coff_core_p (bfd *abfd)
{
  CoreHdr core;
  struct stat statbuf;
  bfd_size_type size;
  char *tmpptr;

  /* Values from new and old core structures.  */
  int c_flag;
  file_ptr c_stack, c_regoff, c_loader;
  bfd_size_type c_size, c_regsize, c_lsize;
  bfd_vma c_stackend;
  void *c_regptr;
  int proc64;

  if (!read_hdr (abfd, &core))
    {
      if (bfd_get_error () != bfd_error_system_call)
	bfd_set_error (bfd_error_wrong_format);
      return NULL;
    }

  /* This isn't the right handler for 64-bit core files on AIX 5.x.  */
  if (CORE_NEW (core) && CNEW_IS_CORE_DUMPXX (core))
    {
      bfd_set_error (bfd_error_wrong_format);
      return NULL;
    }

  /* Copy fields from new or old core structure.  */
  if (CORE_NEW (core))
    {
      c_flag = core.new_dump.c_flag;
      c_stack = (file_ptr) core.new_dump.c_stack;
      c_size = core.new_dump.c_size;
      c_stackend = CNEW_STACKORG (core.new_dump) + c_size;
      c_lsize = CNEW_LSIZE (core.new_dump);
      c_loader = CNEW_LOADER (core.new_dump);
#ifndef BFD64
      proc64 = CNEW_PROC64 (core.new_dump);
    }
  else
    {
      c_flag = core.old.c_flag;
      c_stack = (file_ptr) (ptr_to_uint) core.old.c_stack;
      c_size = core.old.c_size;
      c_stackend = COLD_STACKEND;
      c_lsize = 0x7ffffff;
      c_loader = (file_ptr) (ptr_to_uint) COLD_LOADER (core.old);
#endif
      proc64 = 0;
    }

  if (proc64)
    {
      c_regsize = sizeof (CNEW_CONTEXT64 (core.new_dump));
      c_regptr = &CNEW_CONTEXT64 (core.new_dump);
    }
  else if (CORE_NEW (core))
    {
      c_regsize = sizeof (CNEW_MSTSAVE (core.new_dump));
      c_regptr = &CNEW_MSTSAVE (core.new_dump);
    }
#ifndef BFD64
  else
    {
      c_regsize = sizeof (COLD_MSTSAVE (core.old));
      c_regptr = &COLD_MSTSAVE (core.old);
    }
#endif
  c_regoff = (char *) c_regptr - (char *) &core;

  if (bfd_stat (abfd, &statbuf) < 0)
    {
      bfd_set_error (bfd_error_system_call);
      return NULL;
    }

  /* If the core file ulimit is too small, the system will first
     omit the data segment, then omit the stack, then decline to
     dump core altogether (as far as I know UBLOCK_VALID and LE_VALID
     are always set) (this is based on experimentation on AIX 3.2).
     Now, the thing is that GDB users will be surprised
     if segments just silently don't appear (well, maybe they would
     think to check "info files", I don't know).

     For the data segment, we have no choice but to keep going if it's
     not there, since the default behavior is not to dump it (regardless
     of the ulimit, it's based on SA_FULLDUMP).  But for the stack segment,
     if it's not there, we refuse to have anything to do with this core
     file.  The usefulness of a core dump without a stack segment is pretty
     limited anyway.  */

  if (!(c_flag & UBLOCK_VALID)
      || !(c_flag & LE_VALID))
    {
      bfd_set_error (bfd_error_wrong_format);
      return NULL;
    }

  if (!(c_flag & USTACK_VALID))
    {
      bfd_set_error (bfd_error_file_truncated);
      return NULL;
    }

  /* Don't check the core file size for a full core, AIX 4.1 includes
     additional shared library sections in a full core.  */
  if (!(c_flag & (FULL_CORE | CORE_TRUNC)))
    {
      /* If the size is wrong, it means we're misinterpreting something.  */
      if (c_stack + (file_ptr) c_size != statbuf.st_size)
	{
	  bfd_set_error (bfd_error_wrong_format);
	  return NULL;
	}
    }

  /* Sanity check on the c_tab field.  */
  if (!CORE_NEW (core)
      && (
#ifndef BFD64
	  c_loader < (file_ptr) sizeof core.old
#else
	  c_loader < (file_ptr) sizeof core.new_dump
#endif
	  || c_loader >= statbuf.st_size
	  || c_loader >= c_stack))
    {
      bfd_set_error (bfd_error_wrong_format);
      return NULL;
    }

  /* Issue warning if the core file was truncated during writing.  */
  if (c_flag & CORE_TRUNC)
    _bfd_error_handler (_("%s: warning core file truncated"),
			bfd_get_filename (abfd));

  /* Allocate core file header.  */
#ifndef BFD64
  size = CORE_NEW (core) ? sizeof (core.new_dump) : sizeof (core.old);
#else
  size =  sizeof (core.new_dump);
#endif
  tmpptr = (char *) bfd_zalloc (abfd, (bfd_size_type) size);
  if (!tmpptr)
    return NULL;

  /* Copy core file header.  */
  memcpy (tmpptr, &core, size);
  set_tdata (abfd, tmpptr);

  /* Set architecture.  */
  if (CORE_NEW (core))
    {
      enum bfd_architecture arch;
      unsigned long mach;

      switch (CNEW_IMPL (core.new_dump))
	{
	case POWER_RS1:
	case POWER_RSC:
	case POWER_RS2:
	  arch = bfd_arch_rs6000;
	  mach = bfd_mach_rs6k;
	  break;
	default:
	  arch = bfd_arch_powerpc;
	  mach = bfd_mach_ppc;
	  break;
	}
      bfd_default_set_arch_mach (abfd, arch, mach);
    }

  /* .stack section.  */
  if (!make_bfd_asection (abfd, ".stack",
			  SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
			  c_size, c_stackend - c_size, c_stack))
    goto fail;

  /* .reg section for all registers.  */
  if (!make_bfd_asection (abfd, ".reg",
			  SEC_HAS_CONTENTS,
			  c_regsize, (bfd_vma) 0, c_regoff))
    goto fail;

  /* .ldinfo section.
     To actually find out how long this section is in this particular
     core dump would require going down the whole list of struct ld_info's.
     See if we can just fake it.  */
  if (!make_bfd_asection (abfd, ".ldinfo",
			  SEC_HAS_CONTENTS,
			  c_lsize, (bfd_vma) 0, c_loader))
    goto fail;

#ifndef CORE_VERSION_1
  /* .data section if present.
     AIX 3 dumps the complete data section and sets FULL_CORE if the
     ulimit is large enough, otherwise the data section is omitted.
     AIX 4 sets FULL_CORE even if the core file is truncated, we have
     to examine core.c_datasize below to find out the actual size of
     the .data section.  */
  if (c_flag & FULL_CORE)
    {
      if (!make_bfd_asection (abfd, ".data",
			      SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
			      (bfd_size_type) core.old.c_u.u_dsize,
			      (bfd_vma)
				CDATA_ADDR (core.old.c_u.u_dsize),
			      c_stack + c_size))
	goto fail;
    }
#endif

#ifdef CORE_VERSION_1
  /* AIX 4 adds data sections from loaded objects to the core file,
     which can be found by examining ldinfo, and anonymously mmapped
     regions.  */
  {
    LdInfo ldinfo;
    bfd_size_type ldi_datasize;
    file_ptr ldi_core;
    uint ldi_next;
    bfd_vma ldi_dataorg;
    bfd_vma core_dataorg;

    /* Fields from new and old core structures.  */
    bfd_size_type c_datasize, c_vmregions;
    file_ptr c_data, c_vmm;

    if (CORE_NEW (core))
      {
	c_datasize = CNEW_DATASIZE (core.new_dump);
	c_data = (file_ptr) core.new_dump.c_data;
	c_vmregions = core.new_dump.c_vmregions;
	c_vmm = (file_ptr) core.new_dump.c_vmm;
      }
#ifndef BFD64
    else
      {
	c_datasize = core.old.c_datasize;
	c_data = (file_ptr) (ptr_to_uint) core.old.c_data;
	c_vmregions = core.old.c_vmregions;
	c_vmm = (file_ptr) (ptr_to_uint) core.old.c_vmm;
      }
#endif

    /* .data section from executable.  */
    if (c_datasize)
      {
	/* If Large Memory Model is used, then the .data segment should start from
	   BDATAORG which has been defined in the system header files. */

        if (c_flag & CORE_BIGDATA)
          core_dataorg = BDATAORG;
        else
          core_dataorg = CDATA_ADDR (c_datasize);

	if (!make_bfd_asection (abfd, ".data",
				SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
				c_datasize,
				(bfd_vma) core_dataorg,
				c_data))
	  goto fail;
      }

    /* .data sections from loaded objects.  */
    if (proc64)
      size = (unsigned long) ((LdInfo *) 0)->l64.ldinfo_filename;
    else
      size = (unsigned long) ((LdInfo *) 0)->l32.ldinfo_filename;

    while (1)
      {
	if (bfd_seek (abfd, c_loader, SEEK_SET) != 0)
	  goto fail;
	if (bfd_bread (&ldinfo, size, abfd) != size)
	  goto fail;

	if (proc64)
	  {
	    ldi_core = ldinfo.l64.ldinfo_core;
	    ldi_datasize = ldinfo.l64.ldinfo_datasize;
	    ldi_dataorg = (bfd_vma) ldinfo.l64.ldinfo_dataorg;
	    ldi_next = ldinfo.l64.ldinfo_next;
	  }
	else
	  {
	    ldi_core = ldinfo.l32.ldinfo_core;
	    ldi_datasize = ldinfo.l32.ldinfo_datasize;
	    ldi_dataorg = (bfd_vma) (ptr_to_uint) ldinfo.l32.ldinfo_dataorg;
	    ldi_next = ldinfo.l32.ldinfo_next;
	  }

	if (ldi_core)
	  if (!make_bfd_asection (abfd, ".data",
				  SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
				  ldi_datasize, ldi_dataorg, ldi_core))
	    goto fail;

	if (ldi_next == 0)
	  break;
	c_loader += ldi_next;
      }

    /* .vmdata sections from anonymously mmapped regions.  */
    if (c_vmregions)
      {
	bfd_size_type i;

	if (bfd_seek (abfd, c_vmm, SEEK_SET) != 0)
	  goto fail;

	for (i = 0; i < c_vmregions; i++)
	  {
	    VmInfo vminfo;
	    bfd_size_type vminfo_size;
	    file_ptr vminfo_offset;
	    bfd_vma vminfo_addr;

#ifndef BFD64
	    size = CORE_NEW (core) ? sizeof (vminfo.new_dump) : sizeof (vminfo.old);
#else
            size = sizeof (vminfo.new_dump);
#endif
	    if (bfd_bread (&vminfo, size, abfd) != size)
	      goto fail;

	    if (CORE_NEW (core))
	      {
		vminfo_addr = (bfd_vma) vminfo.new_dump.vminfo_addr;
		vminfo_size = vminfo.new_dump.vminfo_size;
		vminfo_offset = vminfo.new_dump.vminfo_offset;
	      }
#ifndef BFD64
	    else
	      {
		vminfo_addr = (bfd_vma) (ptr_to_uint) vminfo.old.vminfo_addr;
		vminfo_size = vminfo.old.vminfo_size;
		vminfo_offset = vminfo.old.vminfo_offset;
	      }
#endif

	    if (vminfo_offset)
	      if (!make_bfd_asection (abfd, ".vmdata",
				      SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
				      vminfo_size, vminfo_addr,
				      vminfo_offset))
		goto fail;
	  }
      }
  }
#endif

  return abfd->xvec;		/* This is garbage for now.  */

 fail:
  bfd_release (abfd, abfd->tdata.any);
  abfd->tdata.any = NULL;
  bfd_section_list_clear (abfd);
  return NULL;
}
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);
    }
}
Esempio n. 3
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);
}
Esempio n. 4
0
static const bfd_target *
netbsd_core_file_p (bfd *abfd)
{
  int val;
  unsigned i;
  file_ptr offset;
  asection *asect;
  struct core core;
  struct coreseg coreseg;
  bfd_size_type amt = sizeof core;

  val = bfd_bread (&core, amt, abfd);
  if (val != sizeof core)
    {
      /* Too small to be a core file.  */
      bfd_set_error (bfd_error_wrong_format);
      return 0;
    }

  if (CORE_GETMAGIC (core) != COREMAGIC)
    {
      bfd_set_error (bfd_error_wrong_format);
      return 0;
    }

  amt = sizeof (struct netbsd_core_struct);
  rawptr = (struct netbsd_core_struct *) bfd_zalloc (abfd, amt);
  if (rawptr == NULL)
    return 0;

  rawptr->core = core;
  abfd->tdata.netbsd_core_data = rawptr;

  offset = core.c_hdrsize;
  for (i = 0; i < core.c_nseg; i++)
    {
      const char *sname;
      flagword flags;

      if (bfd_seek (abfd, offset, SEEK_SET) != 0)
	goto punt;

      val = bfd_bread (&coreseg, sizeof coreseg, abfd);
      if (val != sizeof coreseg)
	{
	  bfd_set_error (bfd_error_file_truncated);
	  goto punt;
	}
      if (CORE_GETMAGIC (coreseg) != CORESEGMAGIC)
	{
	  bfd_set_error (bfd_error_wrong_format);
	  goto punt;
	}

      offset += core.c_seghdrsize;

      switch (CORE_GETFLAG (coreseg))
	{
	case CORE_CPU:
	  sname = ".reg";
	  flags = SEC_ALLOC + SEC_HAS_CONTENTS;
	  break;
	case CORE_DATA:
	  sname = ".data";
	  flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
	  break;
	case CORE_STACK:
	  sname = ".stack";
	  flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
	  break;
	default:
	  sname = ".unknown";
	  flags = SEC_ALLOC + SEC_HAS_CONTENTS;
	  break;
	}
      asect = bfd_make_section_anyway_with_flags (abfd, sname, flags);
      if (asect == NULL)
	goto punt;

      asect->size = coreseg.c_size;
      asect->vma = coreseg.c_addr;
      asect->filepos = offset;
      asect->alignment_power = 2;

      if (CORE_GETFLAG (coreseg) == CORE_CPU)
	{
	  bfd_size_type wcookie_offset;

	  switch (CORE_GETMID (core))
	    {
	    case M_SPARC_NETBSD:
	      wcookie_offset = SPARC_WCOOKIE_OFFSET;
	      break;
	    case M_SPARC64_OPENBSD:
	      wcookie_offset = SPARC64_WCOOKIE_OFFSET;
	      break;
	    default:
	      wcookie_offset = 0;
	      break;
	    }

	  if (wcookie_offset > 0 && coreseg.c_size > wcookie_offset)
	    {
	      /* Truncate the .reg section.  */
	      asect->size = wcookie_offset;

	      /* And create the .wcookie section.  */
	      flags = SEC_ALLOC + SEC_HAS_CONTENTS;
	      asect = bfd_make_section_anyway_with_flags (abfd, ".wcookie",
							  flags);
	      if (asect == NULL)
		goto punt;

	      asect->size = coreseg.c_size - wcookie_offset;
	      asect->vma = 0;
	      asect->filepos = offset + wcookie_offset;
	      asect->alignment_power = 2;
	    }
	}

      offset += coreseg.c_size;
    }

  /* Set architecture from machine ID.  */
  switch (CORE_GETMID (core))
    {
    case M_ALPHA_NETBSD:
      bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0);
      break;

    case M_ARM6_NETBSD:
      bfd_default_set_arch_mach (abfd, bfd_arch_arm, bfd_mach_arm_3);
      break;

    case M_X86_64_NETBSD:
      bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x86_64);
      break;

    case M_386_NETBSD:
      bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_i386_i386);
      break;

    case M_68K_NETBSD:
    case M_68K4K_NETBSD:
      bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);
      break;

    case M_88K_OPENBSD:
      bfd_default_set_arch_mach (abfd, bfd_arch_m88k, 0);
      break;

    case M_HPPA_OPENBSD:
      bfd_default_set_arch_mach (abfd, bfd_arch_hppa, bfd_mach_hppa11);
      break;

    case M_POWERPC_NETBSD:
      bfd_default_set_arch_mach (abfd, bfd_arch_powerpc, bfd_mach_ppc);
      break;

    case M_SPARC_NETBSD:
      bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc);
      break;

    case M_SPARC64_NETBSD:
    case M_SPARC64_OPENBSD:
      bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc_v9);
      break;

    case M_VAX_NETBSD:
    case M_VAX4K_NETBSD:
      bfd_default_set_arch_mach (abfd, bfd_arch_vax, 0);
      break;
    }

  /* OK, we believe you.  You're a core file (sure, sure).  */
  return abfd->xvec;

 punt:
  bfd_release (abfd, abfd->tdata.any);
  abfd->tdata.any = NULL;
  bfd_section_list_clear (abfd);
  return 0;
}
Esempio n. 5
0
bfd_boolean
bfd_elf64_archive_slurp_armap (bfd *abfd)
{
  struct artdata *ardata = bfd_ardata (abfd);
  char nextname[17];
  bfd_size_type i, parsed_size, nsymz, stringsize, carsym_size, ptrsize;
  struct areltdata *mapdata;
  bfd_byte int_buf[8];
  char *stringbase;
  char *stringend;
  bfd_byte *raw_armap = NULL;
  carsym *carsyms;
  bfd_size_type amt;

  ardata->symdefs = NULL;

  /* Get the name of the first element.  */
  i = bfd_bread (nextname, 16, abfd);
  if (i == 0)
    return TRUE;
  if (i != 16)
    return FALSE;

  if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0)
    return FALSE;

  /* Archives with traditional armaps are still permitted.  */
  if (CONST_STRNEQ (nextname, "/               "))
    return bfd_slurp_armap (abfd);

  if (! CONST_STRNEQ (nextname, "/SYM64/         "))
    {
      bfd_has_map (abfd) = FALSE;
      return TRUE;
    }

  mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
  if (mapdata == NULL)
    return FALSE;
  parsed_size = mapdata->parsed_size;
  free (mapdata);

  if (bfd_bread (int_buf, 8, abfd) != 8)
    {
      if (bfd_get_error () != bfd_error_system_call)
	bfd_set_error (bfd_error_malformed_archive);
      return FALSE;
    }

  nsymz = bfd_getb64 (int_buf);
  stringsize = parsed_size - 8 * nsymz - 8;

  carsym_size = nsymz * sizeof (carsym);
  ptrsize = 8 * nsymz;

  amt = carsym_size + stringsize + 1;
  if (carsym_size < nsymz || ptrsize < nsymz || amt < nsymz)
    {
      bfd_set_error (bfd_error_malformed_archive);
      return FALSE;
    }
  ardata->symdefs = (struct carsym *) bfd_zalloc (abfd, amt);
  if (ardata->symdefs == NULL)
    return FALSE;
  carsyms = ardata->symdefs;
  stringbase = ((char *) ardata->symdefs) + carsym_size;
  stringbase[stringsize] = 0;
  stringend = stringbase + stringsize;

  raw_armap = (bfd_byte *) bfd_alloc (abfd, ptrsize);
  if (raw_armap == NULL)
    goto release_symdefs;

  if (bfd_bread (raw_armap, ptrsize, abfd) != ptrsize
      || bfd_bread (stringbase, stringsize, abfd) != stringsize)
    {
      if (bfd_get_error () != bfd_error_system_call)
	bfd_set_error (bfd_error_malformed_archive);
      goto release_raw_armap;
    }

  for (i = 0; i < nsymz; i++)
    {
      carsyms->file_offset = bfd_getb64 (raw_armap + i * 8);
      carsyms->name = stringbase;
      if (stringbase < stringend)
	stringbase += strlen (stringbase) + 1;
      ++carsyms;
    }
  *stringbase = '\0';

  ardata->symdef_count = nsymz;
  ardata->first_file_filepos = bfd_tell (abfd);
  /* Pad to an even boundary if you have to.  */
  ardata->first_file_filepos += (ardata->first_file_filepos) % 2;

  bfd_has_map (abfd) = TRUE;
  bfd_release (abfd, raw_armap);

  return TRUE;

release_raw_armap:
  bfd_release (abfd, raw_armap);
release_symdefs:
  bfd_release (abfd, ardata->symdefs);
  return FALSE;
}
Esempio n. 6
0
static bool
bfin_fdpic_load (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd, bu32 *sp,
		 bu32 *elf_addrs, char **ldso_path)
{
  bool ret;
  int i;

  Elf_Internal_Ehdr *iehdr;
  Elf32_External_Ehdr ehdr;
  Elf_Internal_Phdr *phdrs;
  unsigned char *data;
  long phdr_size;
  int phdrc;
  bu32 nsegs;

  bu32 max_load_addr;

  unsigned char null[4] = { 0, 0, 0, 0 };

  ret = false;
  *ldso_path = NULL;

  /* See if this an FDPIC ELF.  */
  phdrs = NULL;
  if (!abfd)
    goto skip_fdpic_init;
  if (bfd_seek (abfd, 0, SEEK_SET) != 0)
    goto skip_fdpic_init;
  if (bfd_bread (&ehdr, sizeof (ehdr), abfd) != sizeof (ehdr))
    goto skip_fdpic_init;
  iehdr = elf_elfheader (abfd);
  if (!(iehdr->e_flags & EF_BFIN_FDPIC))
    goto skip_fdpic_init;

  if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
    sim_io_printf (sd, "Loading FDPIC ELF %s\n Load base: %#x\n ELF entry: %#x\n",
		   bfd_get_filename (abfd), fdpic_load_offset, elf_addrs[0]);

  /* Grab the Program Headers to set up the loadsegs on the stack.  */
  phdr_size = bfd_get_elf_phdr_upper_bound (abfd);
  if (phdr_size == -1)
    goto skip_fdpic_init;
  phdrs = xmalloc (phdr_size);
  phdrc = bfd_get_elf_phdrs (abfd, phdrs);
  if (phdrc == -1)
    goto skip_fdpic_init;

  /* Push the Ehdr onto the stack.  */
  *sp -= sizeof (ehdr);
  elf_addrs[3] = *sp;
  sim_write (sd, *sp, (void *)&ehdr, sizeof (ehdr));
  if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
    sim_io_printf (sd, " Elf_Ehdr: %#x\n", *sp);

  /* Since we're relocating things ourselves, we need to relocate
     the start address as well.  */
  elf_addrs[0] = bfd_get_start_address (abfd) + fdpic_load_offset;

  /* And the Exec's Phdrs onto the stack.  */
  if (STATE_PROG_BFD (sd) == abfd)
    {
      elf_addrs[4] = elf_addrs[0];

      phdr_size = iehdr->e_phentsize * iehdr->e_phnum;
      if (bfd_seek (abfd, iehdr->e_phoff, SEEK_SET) != 0)
	goto skip_fdpic_init;
      data = xmalloc (phdr_size);
      if (bfd_bread (data, phdr_size, abfd) != phdr_size)
	goto skip_fdpic_init;
      *sp -= phdr_size;
      elf_addrs[1] = *sp;
      elf_addrs[2] = phdrc;
      sim_write (sd, *sp, data, phdr_size);
      free (data);
      if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
	sim_io_printf (sd, " Elf_Phdrs: %#x\n", *sp);
    }

  /* Now push all the loadsegs.  */
  nsegs = 0;
  max_load_addr = 0;
  for (i = phdrc; i >= 0; --i)
    if (phdrs[i].p_type == PT_LOAD)
      {
	Elf_Internal_Phdr *p = &phdrs[i];
	bu32 paddr, vaddr, memsz, filesz;

	paddr = p->p_paddr + fdpic_load_offset;
	vaddr = p->p_vaddr;
	memsz = p->p_memsz;
	filesz = p->p_filesz;

	if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
	  sim_io_printf (sd, " PHDR %i: vma %#x lma %#x filesz %#x memsz %#x\n",
			 i, vaddr, paddr, filesz, memsz);

	data = xmalloc (memsz);
	if (memsz != filesz)
	  memset (data + filesz, 0, memsz - filesz);

	if (bfd_seek (abfd, p->p_offset, SEEK_SET) == 0
	    && bfd_bread (data, filesz, abfd) == filesz)
	  sim_write (sd, paddr, data, memsz);

	free (data);

	max_load_addr = MAX (paddr + memsz, max_load_addr);

	*sp -= 12;
	sim_write (sd, *sp+0, (void *)&paddr, 4); /* loadseg.addr  */
	sim_write (sd, *sp+4, (void *)&vaddr, 4); /* loadseg.p_vaddr  */
	sim_write (sd, *sp+8, (void *)&memsz, 4); /* loadseg.p_memsz  */
	++nsegs;
      }
    else if (phdrs[i].p_type == PT_DYNAMIC)
      {
	elf_addrs[5] = phdrs[i].p_paddr + fdpic_load_offset;
	if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
	  sim_io_printf (sd, " PT_DYNAMIC: %#x\n", elf_addrs[5]);
      }
    else if (phdrs[i].p_type == PT_INTERP)
      {
	uint32_t off = phdrs[i].p_offset;
	uint32_t len = phdrs[i].p_filesz;

	*ldso_path = xmalloc (len);
	if (bfd_seek (abfd, off, SEEK_SET) != 0
	    || bfd_bread (*ldso_path, len, abfd) != len)
	  {
	    free (*ldso_path);
	    *ldso_path = NULL;
	  }
	else if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
	  sim_io_printf (sd, " PT_INTERP: %s\n", *ldso_path);
      }

  /* Update the load offset with a few extra pages.  */
  fdpic_load_offset = ALIGN (MAX (max_load_addr, fdpic_load_offset), 0x10000);
  fdpic_load_offset += 0x10000;

  /* Push the summary loadmap info onto the stack last.  */
  *sp -= 4;
  sim_write (sd, *sp+0, null, 2); /* loadmap.version  */
  sim_write (sd, *sp+2, (void *)&nsegs, 2); /* loadmap.nsegs  */

  ret = true;
 skip_fdpic_init:
  free (phdrs);

  return ret;
}
Esempio n. 7
0
static const bfd_target *
oasys_archive_p (bfd *abfd)
{
  oasys_archive_header_type header;
  oasys_extarchive_header_type header_ext;
  unsigned int i;
  file_ptr filepos;
  bfd_size_type amt;

  amt = sizeof (header_ext);
  if (bfd_seek (abfd, (file_ptr) 0, 0) != 0
      || bfd_bread ((void *) &header_ext, amt, abfd) != amt)
    {
      if (bfd_get_error () != bfd_error_system_call)
	bfd_set_error (bfd_error_wrong_format);
      return NULL;
    }

  header.version = H_GET_32 (abfd, header_ext.version);
  header.mod_count = H_GET_32 (abfd, header_ext.mod_count);
  header.mod_tbl_offset = H_GET_32 (abfd, header_ext.mod_tbl_offset);
  header.sym_tbl_size = H_GET_32 (abfd, header_ext.sym_tbl_size);
  header.sym_count = H_GET_32 (abfd, header_ext.sym_count);
  header.sym_tbl_offset = H_GET_32 (abfd, header_ext.sym_tbl_offset);
  header.xref_count = H_GET_32 (abfd, header_ext.xref_count);
  header.xref_lst_offset = H_GET_32 (abfd, header_ext.xref_lst_offset);

  /* There isn't a magic number in an Oasys archive, so the best we
     can do to verify reasonableness is to make sure that the values in
     the header are too weird.  */

  if (header.version > 10000
      || header.mod_count > 10000
      || header.sym_count > 100000
      || header.xref_count > 100000)
    return NULL;

  /* That all worked, let's buy the space for the header and read in
     the headers.  */
  {
    oasys_ar_data_type *ar;
    oasys_module_info_type *module;
    oasys_module_table_type record;

    amt = sizeof (oasys_ar_data_type);
    ar = bfd_alloc (abfd, amt);

    amt = header.mod_count;
    amt *= sizeof (oasys_module_info_type);
    module = bfd_alloc (abfd, amt);

    if (!ar || !module)
      return NULL;

    abfd->tdata.oasys_ar_data = ar;
    ar->module = module;
    ar->module_count = header.mod_count;

    filepos = header.mod_tbl_offset;
    for (i = 0; i < header.mod_count; i++)
      {
	if (bfd_seek (abfd, filepos, SEEK_SET) != 0)
	  return NULL;

	/* There are two ways of specifying the archive header.  */
	  {
	    oasys_extmodule_table_type_b_type record_ext;

	    amt = sizeof (record_ext);
	    if (bfd_bread ((void *) &record_ext, amt, abfd) != amt)
	      return NULL;

	    record.mod_size = H_GET_32 (abfd, record_ext.mod_size);
	    record.file_offset = H_GET_32 (abfd, record_ext.file_offset);

	    record.dep_count = H_GET_32 (abfd, record_ext.dep_count);
	    record.depee_count = H_GET_32 (abfd, record_ext.depee_count);
	    record.sect_count = H_GET_32 (abfd, record_ext.sect_count);
	    record.module_name_size = H_GET_32 (abfd,
						record_ext.mod_name_length);

	    amt = record.module_name_size;
	    module[i].name = bfd_alloc (abfd, amt + 1);
	    if (!module[i].name)
	      return NULL;
	    if (bfd_bread ((void *) module[i].name, amt, abfd) != amt)
	      return NULL;
	    module[i].name[record.module_name_size] = 0;
	    filepos += (sizeof (record_ext)
			+ record.dep_count * 4
			+ record.module_name_size + 1);
	  }

	module[i].size = record.mod_size;
	module[i].pos = record.file_offset;
	module[i].abfd = 0;
      }
  }
  return abfd->xvec;
}
Esempio n. 8
0
bfd_boolean
xcoff64_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
{
  struct core_dumpxx core;
  char *path, *s;
  size_t alloc;
  const char *str1, *str2;
  bfd_boolean return_value = FALSE;

  /* Get the header.  */
  if (bfd_seek (core_bfd, 0, SEEK_SET) != 0)
    return return_value;

  if (sizeof (struct core_dumpxx) !=
      bfd_bread (&core, sizeof (struct core_dumpxx), core_bfd))
    return return_value;

  if (bfd_seek (core_bfd, core.c_loader, SEEK_SET) != 0)
    return return_value;

  alloc = 100;
  path = bfd_malloc (alloc);
  if (path == NULL)
    return return_value;

  s = path;

  while (1)
    {
      if (bfd_bread (s, 1, core_bfd) != 1)
	goto xcoff64_core_file_matches_executable_p_end_1;

      if (*s == '\0')
	break;
      ++s;
      if (s == path + alloc)
	{
	  char *n;

	  alloc *= 2;
	  n = bfd_realloc (path, alloc);
	  if (n == NULL)
	    goto xcoff64_core_file_matches_executable_p_end_1;

	  s = n + (path - s);
	  path = n;
	}
    }

  str1 = strrchr (path, '/');
  str2 = strrchr (exec_bfd->filename, '/');

  /* Step over character '/'.  */
  str1 = str1 != NULL ? str1 + 1 : path;
  str2 = str2 != NULL ? str2 + 1 : exec_bfd->filename;

  if (strcmp (str1, str2) == 0)
    return_value = TRUE;

 xcoff64_core_file_matches_executable_p_end_1:
  free (path);
  return return_value;
}
Esempio n. 9
0
static file_ptr
lzma_pread (struct bfd *nbfd, void *stream, void *buf, file_ptr nbytes,
	    file_ptr offset)
{
  struct lzma_stream *lstream = stream;
  bfd_size_type chunk_size;
  lzma_index_iter iter;
  gdb_byte *compressed, *uncompressed;
  file_ptr block_offset;
  lzma_filter filters[LZMA_FILTERS_MAX + 1];
  lzma_block block;
  size_t compressed_pos, uncompressed_pos;
  file_ptr res;

  res = 0;
  while (nbytes > 0)
    {
      if (lstream->data == NULL
	  || lstream->data_start > offset || offset >= lstream->data_end)
	{
	  asection *section = lstream->section;

	  lzma_index_iter_init (&iter, lstream->index);
	  if (lzma_index_iter_locate (&iter, offset))
	    break;

	  compressed = xmalloc (iter.block.total_size);
	  block_offset = section->filepos + iter.block.compressed_file_offset;
	  if (bfd_seek (section->owner, block_offset, SEEK_SET) != 0
	      || bfd_bread (compressed, iter.block.total_size, section->owner)
		 != iter.block.total_size)
	    {
	      xfree (compressed);
	      break;
	    }

	  uncompressed = xmalloc (iter.block.uncompressed_size);

	  memset (&block, 0, sizeof (block));
	  block.filters = filters;
	  block.header_size = lzma_block_header_size_decode (compressed[0]);
	  if (lzma_block_header_decode (&block, &gdb_lzma_allocator, compressed)
	      != LZMA_OK)
	    {
	      xfree (compressed);
	      xfree (uncompressed);
	      break;
	    }

	  compressed_pos = block.header_size;
	  uncompressed_pos = 0;
	  if (lzma_block_buffer_decode (&block, &gdb_lzma_allocator,
					compressed, &compressed_pos,
					iter.block.total_size,
					uncompressed, &uncompressed_pos,
					iter.block.uncompressed_size)
	      != LZMA_OK)
	    {
	      xfree (compressed);
	      xfree (uncompressed);
	      break;
	    }

	  xfree (compressed);

	  xfree (lstream->data);
	  lstream->data = uncompressed;
	  lstream->data_start = iter.block.uncompressed_file_offset;
	  lstream->data_end = (iter.block.uncompressed_file_offset
			       + iter.block.uncompressed_size);
	}

      chunk_size = min (nbytes, lstream->data_end - offset);
      memcpy (buf, lstream->data + offset - lstream->data_start, chunk_size);
      buf = (gdb_byte *) buf + chunk_size;
      offset += chunk_size;
      nbytes -= chunk_size;
      res += chunk_size;
    }

  return res;
}
Esempio n. 10
0
static const bfd_target *
cisco_core_file_validate (bfd *abfd, int crash_info_loc)
{
  char buf[4];
  unsigned int crashinfo_offset;
  crashinfo_external crashinfo;
  bfd_size_type nread;
  unsigned int magic;
  unsigned int version;
  unsigned int rambase;
  sec_ptr asect;
  struct stat statbuf;
  bfd_size_type amt;
  flagword flags;

  if (bfd_seek (abfd, (file_ptr) crash_info_loc, SEEK_SET) != 0)
    return NULL;

  nread = bfd_bread (buf, (bfd_size_type) 4, abfd);
  if (nread != 4)
    {
      if (bfd_get_error () != bfd_error_system_call)
	bfd_set_error (bfd_error_wrong_format);
      return NULL;
    }
  crashinfo_offset = MASK_ADDR (bfd_get_32 (abfd, buf));

  if (bfd_seek (abfd, (file_ptr) crashinfo_offset, SEEK_SET) != 0)
    {
      /* Most likely we failed because of a bogus (huge) offset */
      bfd_set_error (bfd_error_wrong_format);
      return NULL;
    }

  nread = bfd_bread (&crashinfo, (bfd_size_type) sizeof (crashinfo), abfd);
  if (nread != sizeof (crashinfo))
    {
      if (bfd_get_error () != bfd_error_system_call)
	bfd_set_error (bfd_error_wrong_format);
      return NULL;
    }

  if (bfd_stat (abfd, &statbuf) < 0)
    {
      bfd_set_error (bfd_error_system_call);
      return NULL;
    }

  magic = bfd_get_32 (abfd, crashinfo.magic);
  if (magic != CRASH_MAGIC)
    {
      bfd_set_error (bfd_error_wrong_format);
      return NULL;
    }

  version = bfd_get_32 (abfd, crashinfo.version);
  if (version == 0)
    {
      bfd_set_error (bfd_error_wrong_format);
      return NULL;
    }
  else if (version == 1)
    {
      /* V1 core dumps don't specify the dump base, assume 0 */
      rambase = 0;
    }
  else
    {
      rambase = bfd_get_32 (abfd, crashinfo.rambase);
    }

  /* OK, we believe you.  You're a core file.  */

  amt = sizeof (struct cisco_core_struct);
  abfd->tdata.cisco_core_data = (struct cisco_core_struct *) bfd_zmalloc (amt);
  if (abfd->tdata.cisco_core_data == NULL)
    return NULL;

  switch ((crashreason) bfd_get_32 (abfd, crashinfo.reason))
    {
    case CRASH_REASON_NOTCRASHED:
      /* Crash file probably came from write core.  */
      abfd->tdata.cisco_core_data->sig = 0;
      break;
    case CRASH_REASON_CORRUPT:
      /* The crash context area was corrupt -- proceed with caution.
	 We have no way of passing this information back to the caller.  */
      abfd->tdata.cisco_core_data->sig = 0;
      break;
    case CRASH_REASON_EXCEPTION:
      /* Crash occured due to CPU exception.  */

      /* This is 68k-specific; for MIPS we'll need to interpret
	 cpu_vector differently based on the target configuration
	 (since CISCO core files don't seem to have the processor
	 encoded in them).  */

      switch (bfd_get_32 (abfd, crashinfo.cpu_vector))
	{
	   /* bus error           */
	case 2 : abfd->tdata.cisco_core_data->sig = SIGBUS; break;
	   /* address error       */
	case 3 : abfd->tdata.cisco_core_data->sig = SIGBUS; break;
	   /* illegal instruction */
	case 4 : abfd->tdata.cisco_core_data->sig = SIGILL;  break;
	   /* zero divide         */
	case 5 : abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
	   /* chk instruction     */
	case 6 : abfd->tdata.cisco_core_data->sig = SIGFPE; break;
	   /* trapv instruction   */
	case 7 : abfd->tdata.cisco_core_data->sig = SIGFPE; break;
	   /* privilege violation */
	case 8 : abfd->tdata.cisco_core_data->sig = SIGSEGV; break;
	   /* trace trap          */
	case 9 : abfd->tdata.cisco_core_data->sig = SIGTRAP;  break;
	   /* line 1010 emulator  */
	case 10: abfd->tdata.cisco_core_data->sig = SIGILL;  break;
	   /* line 1111 emulator  */
	case 11: abfd->tdata.cisco_core_data->sig = SIGILL;  break;

	  /* Coprocessor protocol violation.  Using a standard MMU or FPU
	     this cannot be triggered by software.  Call it a SIGBUS.  */
	case 13: abfd->tdata.cisco_core_data->sig = SIGBUS;  break;

	  /* interrupt           */
	case 31: abfd->tdata.cisco_core_data->sig = SIGINT;  break;
	  /* breakpoint          */
	case 33: abfd->tdata.cisco_core_data->sig = SIGTRAP;  break;

	  /* floating point err  */
	case 48: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
	  /* floating point err  */
	case 49: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
	  /* zero divide         */
	case 50: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
	  /* underflow           */
	case 51: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
	  /* operand error       */
	case 52: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
	   /* overflow            */
	case 53: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
	  /* NAN                 */
	case 54: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
	default:
#ifndef SIGEMT
#define SIGEMT SIGTRAP
#endif
	  /* "software generated"*/
	  abfd->tdata.cisco_core_data->sig = SIGEMT;
	}
      break;
    default:
      /* Unknown crash reason.  */
      abfd->tdata.cisco_core_data->sig = 0;
      break;
    }

  /* Create a ".data" section that maps the entire file, which is
     essentially a dump of the target system's RAM.  */

  flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
  asect = bfd_make_section_anyway_with_flags (abfd, ".data", flags);
  if (asect == NULL)
    goto error_return;
  /* The size of memory is the size of the core file itself.  */
  asect->size = statbuf.st_size;
  asect->vma = rambase;
  asect->filepos = 0;

  /* Create a ".crash" section to allow access to the saved
     crash information.  */

  flags = SEC_HAS_CONTENTS;
  asect = bfd_make_section_anyway_with_flags (abfd, ".crash", flags);
  if (asect == NULL)
    goto error_return;
  asect->vma = 0;
  asect->filepos = crashinfo_offset;
  asect->size = sizeof (crashinfo);

  /* Create a ".reg" section to allow access to the saved
     registers.  */

  asect = bfd_make_section_anyway_with_flags (abfd, ".reg", flags);
  if (asect == NULL)
    goto error_return;
  asect->vma = 0;
  asect->filepos = bfd_get_32 (abfd, crashinfo.registers) - rambase;
  /* Since we don't know the exact size of the saved register info,
     choose a register section size that is either the remaining part
     of the file, or 1024, whichever is smaller.  */
  nread = statbuf.st_size - asect->filepos;
  asect->size = (nread < 1024) ? nread : 1024;

  return abfd->xvec;

  /* Get here if we have already started filling out the BFD
     and there is an error of some kind.  */

 error_return:
  bfd_release (abfd, abfd->tdata.any);
  abfd->tdata.any = NULL;
  bfd_section_list_clear (abfd);
  return NULL;
}
Esempio n. 11
0
static const bfd_target *
irix_core_core_file_p (bfd *abfd)
{
  int val;
  struct coreout coreout;
  struct idesc *idg, *idf, *ids;
  bfd_size_type amt;

  val = bfd_bread (&coreout, (bfd_size_type) sizeof coreout, abfd);
  if (val != sizeof coreout)
    {
      if (bfd_get_error () != bfd_error_system_call)
	bfd_set_error (bfd_error_wrong_format);
      return 0;
    }

  if (coreout.c_version != CORE_VERSION1)
    return 0;

  /* Have we got a corefile?  */
  switch (coreout.c_magic)
    {
    case CORE_MAGIC:	break;
#ifdef CORE_MAGIC64
    case CORE_MAGIC64:	break;
#endif
#ifdef CORE_MAGICN32
    case CORE_MAGICN32:	break;
#endif
    default:		return 0;	/* Un-identifiable or not corefile.  */
    }

  amt = sizeof (struct sgi_core_struct);
  core_hdr (abfd) = (struct sgi_core_struct *) bfd_zalloc (abfd, amt);
  if (!core_hdr (abfd))
    return NULL;

  strncpy (core_command (abfd), coreout.c_name, CORE_NAMESIZE);
  core_signal (abfd) = coreout.c_sigcause;

  if (bfd_seek (abfd, coreout.c_vmapoffset, SEEK_SET) != 0)
    goto fail;

  /* Process corefile sections.  */
#ifdef CORE_MAGIC64
  if (coreout.c_magic == (int) CORE_MAGIC64)
    {
      if (! do_sections64 (abfd, & coreout))
	goto fail;
    }
  else
#endif
    if (! do_sections (abfd, & coreout))
      goto fail;

  /* Make sure that the regs are contiguous within the core file.  */

  idg = &coreout.c_idesc[I_GPREGS];
  idf = &coreout.c_idesc[I_FPREGS];
  ids = &coreout.c_idesc[I_SPECREGS];

  if (idg->i_offset + idg->i_len != idf->i_offset
      || idf->i_offset + idf->i_len != ids->i_offset)
    goto fail;			/* Can't deal with non-contig regs */

  if (bfd_seek (abfd, idg->i_offset, SEEK_SET) != 0)
    goto fail;

  if (!make_bfd_asection (abfd, ".reg",
			  SEC_HAS_CONTENTS,
			  idg->i_len + idf->i_len + ids->i_len,
			  0,
			  idg->i_offset))
    goto fail;

  /* OK, we believe you.  You're a core file (sure, sure).  */
  bfd_default_set_arch_mach (abfd, bfd_arch_mips, 0);

  return abfd->xvec;

 fail:
  bfd_release (abfd, core_hdr (abfd));
  core_hdr (abfd) = NULL;
  bfd_section_list_clear (abfd);
  return NULL;
}
Esempio n. 12
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;
}
Esempio n. 13
0
bfd_boolean
rs6000coff_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
{
  CoreHdr core;
  bfd_size_type size;
  char *path, *s;
  size_t alloc;
  const char *str1, *str2;
  bfd_boolean ret;
  file_ptr c_loader;

  if (!read_hdr (core_bfd, &core))
    return FALSE;

  if (CORE_NEW (core))
    c_loader = CNEW_LOADER (core.new_dump);
#ifndef BFD64
  else
    c_loader = (file_ptr) (ptr_to_uint) COLD_LOADER (core.old);
#endif

  if (CORE_NEW (core) && CNEW_PROC64 (core.new_dump))
    size = (int) ((LdInfo *) 0)->l64.ldinfo_filename;
  else
    size = (int) ((LdInfo *) 0)->l32.ldinfo_filename;

  if (bfd_seek (core_bfd, c_loader + size, SEEK_SET) != 0)
    return FALSE;

  alloc = 100;
  path = bfd_malloc ((bfd_size_type) alloc);
  if (path == NULL)
    return FALSE;
  s = path;

  while (1)
    {
      if (bfd_bread (s, (bfd_size_type) 1, core_bfd) != 1)
	{
	  free (path);
	  return FALSE;
	}
      if (*s == '\0')
	break;
      ++s;
      if (s == path + alloc)
	{
	  char *n;

	  alloc *= 2;
	  n = bfd_realloc (path, (bfd_size_type) alloc);
	  if (n == NULL)
	    {
	      free (path);
	      return FALSE;
	    }
	  s = n + (path - s);
	  path = n;
	}
    }

  str1 = strrchr (path, '/');
  str2 = strrchr (exec_bfd->filename, '/');

  /* step over character '/' */
  str1 = str1 != NULL ? str1 + 1 : path;
  str2 = str2 != NULL ? str2 + 1 : exec_bfd->filename;

  if (strcmp (str1, str2) == 0)
    ret = TRUE;
  else
    ret = FALSE;

  free (path);

  return ret;
}
Esempio n. 14
0
File: sco5-core.c Progetto: 5kg/gdb
const bfd_target *
sco5_core_file_p (bfd *abfd)
{
  int coffset_siz, val, nsecs, cheadoffs;
  int coresize;
  struct user *u;
  struct coreoffsets coffsets;
  struct coresecthead chead;
  char *secname;
  flagword flags;

  /* Read coreoffsets region at end of core (see core(FP)).  */

  {
    struct stat statbuf;

    if (bfd_stat (abfd, &statbuf) < 0)
      return NULL;

    coresize = statbuf.st_size;
  }
  /* Last long in core is sizeof struct coreoffsets, read it */
  if ((bfd_seek (abfd, (file_ptr) (coresize - sizeof coffset_siz),
		 SEEK_SET) != 0)
      || bfd_bread ((void *) &coffset_siz, (bfd_size_type) sizeof coffset_siz,
		   abfd) != sizeof coffset_siz)
    {
      bfd_set_error (bfd_error_wrong_format);
      return NULL;
    }

  /* Use it to seek start of coreoffsets region, read it and determine
     validity */
  if ((bfd_seek (abfd, (file_ptr) (coresize - coffset_siz), SEEK_SET) != 0)
      || (bfd_bread ((void *) &coffsets, (bfd_size_type) sizeof coffsets, abfd)
	  != sizeof coffsets)
      || ((coffsets.u_info != 1) && (coffsets.u_info != C_VERSION)))
    {
      bfd_set_error (bfd_error_wrong_format);
      return NULL;
    }

  if (coffsets.u_info == 1)
    {
      /* Old version, no section heads, read info from user struct */

      u = read_uarea (abfd, coffsets.u_user);
      if (! u)
	goto fail;

      if (!make_bfd_asection (abfd, ".reg", SEC_HAS_CONTENTS,
			      (bfd_size_type) coffsets.u_usize,
			      0 - (bfd_vma) u->u_ar0,
			      (file_ptr) coffsets.u_user))
	goto fail;

      if (!make_bfd_asection (abfd, ".data",
			      SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
			      ((bfd_size_type) u->u_exdata.ux_dsize
			       + u->u_exdata.ux_bsize),
			      (bfd_vma) u->u_exdata.ux_datorg,
			      (file_ptr) coffsets.u_data))
	goto fail;

      if (!make_bfd_asection (abfd, ".stack",
			      SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
			      (bfd_size_type) u->u_ssize * NBPC,
			      (bfd_vma) u->u_sub,
			      (file_ptr) coffsets.u_stack))
	goto fail;

      return abfd->xvec;		/* Done for version 1 */
    }

  /* Immediately before coreoffsets region is a long with offset in core
     to first coresecthead (CORES_OFFSETS), the long before this is the
     number of section heads in the list. Read both longs and read the
     coresecthead and check its validity */

  if ((bfd_seek (abfd,
		 (file_ptr) (coresize - coffset_siz - 2 * sizeof coffset_siz),
		 SEEK_SET) != 0)
      || (bfd_bread ((void *) &nsecs, (bfd_size_type) sizeof nsecs, abfd)
	  != sizeof nsecs)
      || (bfd_bread ((void *) &cheadoffs, (bfd_size_type) sizeof cheadoffs,
		    abfd) != sizeof cheadoffs)
      || (bfd_seek (abfd, (file_ptr) cheadoffs, SEEK_SET) != 0)
      || (bfd_bread ((void *) &chead, (bfd_size_type) sizeof chead, abfd)
	  != sizeof chead)
      || (chead.cs_stype != CORES_OFFSETS)
      || (chead.cs_x.csx_magic != COREMAGIC_NUMBER))
    {
      bfd_set_error (bfd_error_wrong_format);
      goto fail;
    }

  /* OK, we believe you.  You're a core file (sure, sure).  */

  /* Now loop over all regions and map them */
  nsecs--;				/* We've seen CORES_OFFSETS already */
  for (; nsecs; nsecs--)
    {
      if ((bfd_seek (abfd, (file_ptr) chead.cs_hseek, SEEK_SET) != 0)
	  || (bfd_bread ((void *) &chead, (bfd_size_type) sizeof chead, abfd)
	      != sizeof chead))
	{
	  bfd_set_error (bfd_error_wrong_format);
	  goto fail;
	}

      switch (chead.cs_stype)
	{
	case CORES_MAGIC:			/* Core header, check magic */
	  if (chead.cs_x.csx_magic != COREMAGIC_NUMBER)
	    {
	      bfd_set_error (bfd_error_wrong_format);
	      goto fail;
	    }
	  secname = NULL;
	  nsecs++;				/* MAGIC not in section cnt!*/
	  break;
	case CORES_UAREA:			/* U-area, read in tdata */
	  u = read_uarea (abfd, chead.cs_sseek);
	  if (! u)
	    goto fail;

	  /* This is tricky.  As the "register section", we give them
	     the entire upage and stack.  u.u_ar0 points to where
	     "register 0" is stored.  There are two tricks with this,
	     though.  One is that the rest of the registers might be
	     at positive or negative (or both) displacements from
	     *u_ar0.  The other is that u_ar0 is sometimes an absolute
	     address in kernel memory, and on other systems it is an
	     offset from the beginning of the `struct user'.

	     As a practical matter, we don't know where the registers
	     actually are, so we have to pass the whole area to GDB.
	     We encode the value of u_ar0 by setting the .regs section
	     up so that its virtual memory address 0 is at the place
	     pointed to by u_ar0 (by setting the vma of the start of
	     the section to -u_ar0).  GDB uses this info to locate the
	     regs, using minor trickery to get around the
	     offset-or-absolute-addr problem.  */

	  chead.cs_vaddr = 0 - (bfd_vma) u->u_ar0;

	  secname = ".reg";
	  flags = SEC_HAS_CONTENTS;

	  break;
	case CORES_PREGION:			/* A program region, map it */
	  switch (chead.cs_x.csx_preg.csxp_rtyp)
	    {
	    case PT_DATA:
	      secname = ".data";	/* Data region.		 */
	      break;
	    case PT_STACK:
	      secname = ".stack";	/* Stack region.	 */
	      break;
	    case PT_SHMEM:
	      secname = ".shmem";	/* Shared memory	 */
	      break;
	    case PT_LIBDAT:
	      secname = ".libdat";	/* Shared library data	 */
	      break;
	    case PT_V86:
	      secname = ".virt86";	/* Virtual 8086 mode	 */
	      break;
	    case PT_SHFIL:
	      secname = ".mmfile";	/* Memory mapped file	 */
	      break;
	    case PT_XDATA0:
	      secname = ".Xdat0";	/* XENIX data region, virtual 0 */
	      break;
	    default:
	      secname = "";
	    }
	  flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
	  break;
	case CORES_PROC:			/* struct proc */
	case CORES_ITIMER:			/* interval timers */
	case CORES_SCOUTSNAME:			/* struct scoutsname */
	  secname = NULL;	/* Ignore these */
	  break;
	default:
	  (*_bfd_error_handler) ("Unhandled SCO core file section type %d\n",
				 chead.cs_stype);
	  continue;
	}

      if (secname
	  && !make_bfd_asection (abfd, secname, flags,
				 (bfd_size_type) chead.cs_vsize,
				 (bfd_vma) chead.cs_vaddr,
				 (file_ptr) chead.cs_sseek))
	goto fail;

    }

  return abfd->xvec;

 fail:
  if (abfd->tdata.any)
    {
      bfd_release (abfd, abfd->tdata.any);
      abfd->tdata.any = NULL;
    }
  bfd_section_list_clear (abfd);
  return NULL;
}
Esempio n. 15
0
static bfd_boolean
oasys_slurp_section_data (bfd *const abfd)
{
  oasys_record_union_type record;
  oasys_data_type *data = OASYS_DATA (abfd);
  bfd_boolean loop = TRUE;
  oasys_per_section_type *per;
  asection *s;
  bfd_size_type amt;

  /* See if the data has been slurped already.  */
  for (s = abfd->sections; s != NULL; s = s->next)
    {
      per = oasys_per_section (s);
      if (per->initialized)
	return TRUE;
    }

  if (data->first_data_record == 0)
    return TRUE;

  if (bfd_seek (abfd, data->first_data_record, SEEK_SET) != 0)
    return FALSE;

  while (loop)
    {
      if (! oasys_read_record (abfd, &record))
	return FALSE;

      switch (record.header.type)
	{
	case oasys_record_is_header_enum:
	  break;
	case oasys_record_is_data_enum:
	  {
	    bfd_byte *src = record.data.data;
	    bfd_byte *end_src = ((bfd_byte *) & record) + record.header.length;
	    bfd_byte *dst_ptr;
	    bfd_byte *dst_base_ptr;
	    unsigned int relbit;
	    unsigned int count;
	    asection *section =
	    data->sections[record.data.relb & RELOCATION_SECT_BITS];
	    bfd_vma dst_offset;

	    per = oasys_per_section (section);

	    if (! per->initialized)
	      {
		arelent **relpp;

		per->data = bfd_zalloc (abfd, section->size);
		if (!per->data)
		  return FALSE;
		relpp = &section->relocation;
		per->reloc_tail_ptr = (oasys_reloc_type **) relpp;
		per->had_vma = FALSE;
		per->initialized = TRUE;
		section->reloc_count = 0;
		section->flags = SEC_ALLOC;
	      }

	    dst_offset = H_GET_32 (abfd, record.data.addr);
	    if (! per->had_vma)
	      {
		/* Take the first vma we see as the base.  */
		section->vma = dst_offset;
		per->had_vma = TRUE;
	      }

	    dst_offset -= section->vma;

	    dst_base_ptr = oasys_per_section (section)->data;
	    dst_ptr = oasys_per_section (section)->data +
	      dst_offset;

	    if (src < end_src)
	      section->flags |= SEC_LOAD | SEC_HAS_CONTENTS;

	    while (src < end_src)
	      {
		unsigned char mod_byte = *src++;
		size_t gap = end_src - src;

		count = 8;
		if (mod_byte == 0 && gap >= 8)
		  {
		    dst_ptr[0] = src[0];
		    dst_ptr[1] = src[1];
		    dst_ptr[2] = src[2];
		    dst_ptr[3] = src[3];
		    dst_ptr[4] = src[4];
		    dst_ptr[5] = src[5];
		    dst_ptr[6] = src[6];
		    dst_ptr[7] = src[7];
		    dst_ptr += 8;
		    src += 8;
		  }
		else
		  {
		    for (relbit = 1; count-- != 0 && src < end_src; relbit <<= 1)
		      {
			if (relbit & mod_byte)
			  {
			    unsigned char reloc = *src;
			    /* This item needs to be relocated.  */
			    switch (reloc & RELOCATION_TYPE_BITS)
			      {
			      case RELOCATION_TYPE_ABS:
				break;

			      case RELOCATION_TYPE_REL:
				{
				  /* Relocate the item relative to the section.  */
				  oasys_reloc_type *r;

				  amt = sizeof (oasys_reloc_type);
				  r = bfd_alloc (abfd, amt);
				  if (!r)
				    return FALSE;
				  *(per->reloc_tail_ptr) = r;
				  per->reloc_tail_ptr = &r->next;
				  r->next = NULL;
				  /* Reference to undefined symbol.  */
				  src++;
				  /* There is no symbol.  */
				  r->symbol = 0;
				  /* Work out the howto.  */
				  abort ();
				  r->relent.address = dst_ptr - dst_base_ptr;
				  r->relent.howto = &howto_table[reloc >> 6];
				  r->relent.sym_ptr_ptr = NULL;
				  section->reloc_count++;

				  /* Fake up the data to look like
				     it's got the -ve pc in it, this
				     makes it much easier to convert
				     into other formats.  This is done
				     by hitting the addend.  */
				  if (r->relent.howto->pc_relative)
				    r->relent.addend -= dst_ptr - dst_base_ptr;
				}
				break;

			      case RELOCATION_TYPE_UND:
				{
				  oasys_reloc_type *r;

				  amt = sizeof (oasys_reloc_type);
				  r = bfd_alloc (abfd, amt);
				  if (!r)
				    return FALSE;
				  *(per->reloc_tail_ptr) = r;
				  per->reloc_tail_ptr = &r->next;
				  r->next = NULL;
				  /* Reference to undefined symbol.  */
				  src++;
				  /* Get symbol number.  */
				  r->symbol = (src[0] << 8) | src[1];
				  /* Work out the howto.  */
				  abort ();

				  r->relent.addend = 0;
				  r->relent.address = dst_ptr - dst_base_ptr;
				  r->relent.howto = &howto_table[reloc >> 6];
				  r->relent.sym_ptr_ptr = NULL;
				  section->reloc_count++;

				  src += 2;
				  /* Fake up the data to look like
				     it's got the -ve pc in it, this
				     makes it much easier to convert
				     into other formats.  This is done
				     by hitting the addend.  */
				  if (r->relent.howto->pc_relative)
				    r->relent.addend -= dst_ptr - dst_base_ptr;
				}
				break;
			      case RELOCATION_TYPE_COM:
				BFD_FAIL ();
			      }
			  }
			*dst_ptr++ = *src++;
		      }
		  }
	      }
	  }
	  break;
	case oasys_record_is_local_enum:
	case oasys_record_is_symbol_enum:
	case oasys_record_is_section_enum:
	  break;
	default:
	  loop = FALSE;
	}
    }
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;
}
Esempio n. 17
0
static bfd_boolean
oasys_slurp_symbol_table (bfd *const abfd)
{
  oasys_record_union_type record;
  oasys_data_type *data = OASYS_DATA (abfd);
  bfd_boolean loop = TRUE;
  asymbol *dest_defined;
  asymbol *dest;
  char *string_ptr;
  bfd_size_type amt;

  if (data->symbols != NULL)
    return TRUE;

  /* Buy enough memory for all the symbols and all the names.  */
  amt = abfd->symcount;
  amt *= sizeof (asymbol);
  data->symbols = bfd_alloc (abfd, amt);

  amt = data->symbol_string_length;
#ifdef UNDERSCORE_HACK
  /* Buy 1 more char for each symbol to keep the underscore in.  */
  amt += abfd->symcount;
#endif
  data->strings = bfd_alloc (abfd, amt);

  if (!data->symbols || !data->strings)
    return FALSE;

  dest_defined = data->symbols + abfd->symcount - 1;

  string_ptr = data->strings;
  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
    return FALSE;
  while (loop)
    {
      if (! oasys_read_record (abfd, &record))
	return FALSE;

      switch (record.header.type)
	{
	case oasys_record_is_header_enum:
	  break;
	case oasys_record_is_local_enum:
	case oasys_record_is_symbol_enum:
	  {
	    int flag = record.header.type == (int) oasys_record_is_local_enum ?
	    (BSF_LOCAL) : (BSF_GLOBAL | BSF_EXPORT);

	    size_t length = oasys_string_length (&record);
	    switch (record.symbol.relb & RELOCATION_TYPE_BITS)
	      {
	      case RELOCATION_TYPE_ABS:
		dest = dest_defined--;
		dest->section = bfd_abs_section_ptr;
		dest->flags = 0;

		break;
	      case RELOCATION_TYPE_REL:
		dest = dest_defined--;
		dest->section =
		  OASYS_DATA (abfd)->sections[record.symbol.relb &
					      RELOCATION_SECT_BITS];
		if (record.header.type == (int) oasys_record_is_local_enum)
		  {
		    dest->flags = BSF_LOCAL;
		    if (dest->section == (asection *) (~0))
		      {
			/* It seems that sometimes internal symbols are tied up, but
		       still get output, even though there is no
		       section */
			dest->section = 0;
		      }
		  }
		else
		  dest->flags = flag;
		break;
	      case RELOCATION_TYPE_UND:
		dest = data->symbols + H_GET_16 (abfd, record.symbol.refno);
		dest->section = bfd_und_section_ptr;
		break;
	      case RELOCATION_TYPE_COM:
		dest = dest_defined--;
		dest->name = string_ptr;
		dest->the_bfd = abfd;
		dest->section = bfd_com_section_ptr;
		break;
	      default:
		dest = dest_defined--;
		BFD_ASSERT (FALSE);
		break;
	      }
	    dest->name = string_ptr;
	    dest->the_bfd = abfd;
	    dest->udata.p = NULL;
	    dest->value = H_GET_32 (abfd, record.symbol.value);

#ifdef UNDERSCORE_HACK
	    if (record.symbol.name[0] != '_')
	      {
		string_ptr[0] = '_';
		string_ptr++;
	      }
#endif
	    memcpy (string_ptr, record.symbol.name, length);

	    string_ptr[length] = 0;
	    string_ptr += length + 1;
	  }
	  break;
	default:
	  loop = FALSE;
	}
    }
  return TRUE;
}
Esempio n. 18
0
const bfd_target *
xcoff64_core_p (bfd *abfd)
{
  enum bfd_architecture arch;
  unsigned long mach;
  struct core_dumpxx core, *new_core_hdr;
  struct stat statbuf;
  asection *sec;
  struct __ld_info64 ldinfo;
  bfd_vma ld_offset;
  bfd_size_type i;
  struct vm_infox vminfo;
  const bfd_target *return_value = NULL;
  flagword flags;

  /* Get the header.  */
  if (bfd_seek (abfd, 0, SEEK_SET) != 0)
    goto xcoff64_core_p_error;

  if (sizeof (struct core_dumpxx)
      != bfd_bread (&core, sizeof (struct core_dumpxx), abfd))
    goto xcoff64_core_p_error;

  if (bfd_stat (abfd, &statbuf) < 0)
    goto xcoff64_core_p_error;

  /* Sanity checks
     c_flag has CORE_VERSION_1, Aix 4+
     c_entries = 0 for Aix 4.3+
     IS_PROC64 is a macro defined in procinfo.h, test for 64 bit process.

     We will still be confused if a Aix 4.3 64 bit core file is
     copied over to a Aix 5 machine.

     Check file header offsets

     See rs6000-core.c for comment on size of core
     If there isn't enough of a real core file, bail.  */

  if ((CORE_VERSION_1 != (core.c_flag & CORE_VERSION_1))
      || (0 != core.c_entries)
      || (! (IS_PROC64 (&core.c_u.U_proc)))
      || ((CHECK_FILE_OFFSET (statbuf, core.c_fdsinfox)))
      || ((CHECK_FILE_OFFSET (statbuf, core.c_loader)))
      || ((CHECK_FILE_OFFSET (statbuf, core.c_loader + core.c_lsize)))
      || ((CHECK_FILE_OFFSET (statbuf, core.c_thr)))
      || ((CHECK_FILE_OFFSET (statbuf, core.c_segregion)))
      || ((CHECK_FILE_OFFSET (statbuf, core.c_stack)))
      || ((CHECK_FILE_OFFSET (statbuf, core.c_stack + core.c_size)))
      || ((CHECK_FILE_OFFSET (statbuf, core.c_data)))
      || ((CHECK_FILE_OFFSET (statbuf, core.c_data + core.c_datasize)))
      || (! (core.c_flag & UBLOCK_VALID))
      || (! (core.c_flag & LE_VALID)))
    goto xcoff64_core_p_error;

  /* Check for truncated stack or general truncating.  */
  if ((! (core.c_flag & USTACK_VALID))
      || (core.c_flag & CORE_TRUNC))
    {
      bfd_set_error (bfd_error_file_truncated);

      return return_value;
    }

  new_core_hdr = bfd_zalloc (abfd, sizeof (struct core_dumpxx));
  if (NULL == new_core_hdr)
    return return_value;

  memcpy (new_core_hdr, &core, sizeof (struct core_dumpxx));
  /* The core_hdr() macro is no longer used here because it would
     expand to code relying on gcc's cast-as-lvalue extension,
     which was removed in gcc 4.0.  */
  abfd->tdata.any = new_core_hdr;

  /* .stack section.  */
  flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
  sec = bfd_make_section_anyway_with_flags (abfd, ".stack", flags);
  if (NULL == sec)
    return return_value;

  sec->size = core.c_size;
  sec->vma = core.c_stackorg;
  sec->filepos = core.c_stack;

  /* .reg section for all registers.  */
  flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY;
  sec = bfd_make_section_anyway_with_flags (abfd, ".reg", flags);
  if (NULL == sec)
    return return_value;

  sec->size = sizeof (struct __context64);
  sec->vma = 0;
  sec->filepos = 0;
  sec->contents = (bfd_byte *)&new_core_hdr->c_flt.r64;

  /* .ldinfo section.
     To actually find out how long this section is in this particular
     core dump would require going down the whole list of struct
     ld_info's.   See if we can just fake it.  */
  flags = SEC_HAS_CONTENTS;
  sec = bfd_make_section_anyway_with_flags (abfd, ".ldinfo", flags);
  if (NULL == sec)
    return return_value;

  sec->size = core.c_lsize;
  sec->vma = 0;
  sec->filepos = core.c_loader;

  /* AIX 4 adds data sections from loaded objects to the core file,
     which can be found by examining ldinfo, and anonymously mmapped
     regions.  */

  /* .data section from executable.  */
  flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
  sec = bfd_make_section_anyway_with_flags (abfd, ".data", flags);
  if (NULL == sec)
    return return_value;

  sec->size = core.c_datasize;
  sec->vma = core.c_dataorg;
  sec->filepos = core.c_data;

  /* .data sections from loaded objects.  */
  ld_offset = core.c_loader;

  while (1)
    {
      if (bfd_seek (abfd, ld_offset, SEEK_SET) != 0)
	return return_value;

      if (sizeof (struct __ld_info64) !=
	  bfd_bread (&ldinfo, sizeof (struct __ld_info64), abfd))
	return return_value;

      if (ldinfo.ldinfo_core)
	{
	  flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
	  sec = bfd_make_section_anyway_with_flags (abfd, ".data", flags);
	  if (NULL == sec)
	    return return_value;

	  sec->size = ldinfo.ldinfo_datasize;
	  sec->vma = ldinfo.ldinfo_dataorg;
	  sec->filepos = ldinfo.ldinfo_core;
	}

      if (0 == ldinfo.ldinfo_next)
	break;
      ld_offset += ldinfo.ldinfo_next;
    }

  /* .vmdata sections from anonymously mmapped regions.  */
  if (core.c_vmregions)
    {
      if (bfd_seek (abfd, core.c_vmm, SEEK_SET) != 0)
	return return_value;

      for (i = 0; i < core.c_vmregions; i++)
	if (sizeof (struct vm_infox) !=
	    bfd_bread (&vminfo, sizeof (struct vm_infox), abfd))
	  return return_value;

      if (vminfo.vminfo_offset)
	{
	  flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
	  sec = bfd_make_section_anyway_with_flags (abfd, ".vmdata", flags);
	  if (NULL == sec)
	    return return_value;

	  sec->size = vminfo.vminfo_size;
	  sec->vma = vminfo.vminfo_addr;
	  sec->filepos = vminfo.vminfo_offset;
	}
    }

  /* Set the architecture and machine.  */
  arch = DEFAULT_ARCHITECTURE;
  mach = DEFAULT_MACHINE;
  bfd_default_set_arch_mach (abfd, arch, mach);

  return_value = (bfd_target *) abfd->xvec;	/* This is garbage for now.  */

 xcoff64_core_p_error:
  if (bfd_get_error () != bfd_error_system_call)
    bfd_set_error (bfd_error_wrong_format);

  return return_value;
}
Esempio n. 19
0
const bfd_target *
lynx_core_file_p (bfd *abfd)
{
  int secnum;
  struct pssentry pss;
  bfd_size_type tcontext_size;
  core_st_t *threadp;
  int pagesize;
  asection *newsect;
  bfd_size_type amt;

  pagesize = getpagesize ();	/* Serious cross-target issue here...  This
				   really needs to come from a system-specific
				   header file.  */

  /* Get the pss entry from the core file */

  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
    return NULL;

  amt = sizeof pss;
  if (bfd_bread ((void *) &pss, amt, abfd) != amt)
    {
      /* Too small to be a core file */
      if (bfd_get_error () != bfd_error_system_call)
	bfd_set_error (bfd_error_wrong_format);
      return NULL;
    }

  amt = sizeof (struct lynx_core_struct);
  core_hdr (abfd) = (struct lynx_core_struct *) bfd_zalloc (abfd, amt);

  if (!core_hdr (abfd))
    return NULL;

  strncpy (core_command (abfd), pss.pname, PNMLEN + 1);

  /* Compute the size of the thread contexts */

  tcontext_size = pss.threadcnt * sizeof (core_st_t);

  /* Allocate space for the thread contexts */

  threadp = (core_st_t *) bfd_alloc (abfd, tcontext_size);
  if (!threadp)
    goto fail;

  /* Save thread contexts */

  if (bfd_seek (abfd, (file_ptr) pagesize, SEEK_SET) != 0)
    goto fail;

  if (bfd_bread ((void *) threadp, tcontext_size, abfd) != tcontext_size)
    {
      /* Probably too small to be a core file */
      if (bfd_get_error () != bfd_error_system_call)
	bfd_set_error (bfd_error_wrong_format);
      goto fail;
    }

  core_signal (abfd) = threadp->currsig;

  newsect = make_bfd_asection (abfd, ".stack",
			       SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
			       pss.ssize,
			       pss.slimit,
			       pagesize + tcontext_size);
  if (!newsect)
    goto fail;

  newsect = make_bfd_asection (abfd, ".data",
			       SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
			       pss.data_len + pss.bss_len,
			       pss.data_start,
			       pagesize + tcontext_size + pss.ssize
#if defined (SPARC) || defined (__SPARC__)
			       /* SPARC Lynx seems to start dumping
				  the .data section at a page
				  boundary.  It's OK to check a
				  #define like SPARC here because this
				  file can only be compiled on a Lynx
				  host.  */
			       + pss.data_start % pagesize
#endif
			       );
  if (!newsect)
    goto fail;

/* And, now for the .reg/XXX pseudo sections.  Each thread has it's own
   .reg/XXX section, where XXX is the thread id (without leading zeros).  The
   currently running thread (at the time of the core dump) also has an alias
   called `.reg' (just to keep GDB happy).  Note that we use `.reg/XXX' as
   opposed to `.regXXX' because GDB expects that .reg2 will be the floating-
   point registers.  */

  newsect = make_bfd_asection (abfd, ".reg",
			       SEC_HAS_CONTENTS,
			       sizeof (core_st_t),
			       0,
			       pagesize);
  if (!newsect)
    goto fail;

  for (secnum = 0; secnum < pss.threadcnt; secnum++)
    {
      char secname[100];

      sprintf (secname, ".reg/%d", BUILDPID (0, threadp[secnum].tid));
      newsect = make_bfd_asection (abfd, secname,
				   SEC_HAS_CONTENTS,
				   sizeof (core_st_t),
				   0,
				   pagesize + secnum * sizeof (core_st_t));
      if (!newsect)
	goto fail;
    }

  return abfd->xvec;

 fail:
  bfd_release (abfd, core_hdr (abfd));
  core_hdr (abfd) = NULL;
  bfd_section_list_clear (abfd);
  return NULL;
}
Esempio n. 20
0
File: trad-core.c Progetto: 5kg/gdb
static const bfd_target *
trad_unix_core_file_p (bfd *abfd)
{
  int val;
  struct user u;
  struct trad_core_struct *rawptr;
  bfd_size_type amt;
  flagword flags;

#ifdef TRAD_CORE_USER_OFFSET
  /* If defined, this macro is the file position of the user struct.  */
  if (bfd_seek (abfd, (file_ptr) TRAD_CORE_USER_OFFSET, SEEK_SET) != 0)
    return 0;
#endif

  val = bfd_bread ((void *) &u, (bfd_size_type) sizeof u, abfd);
  if (val != sizeof u)
    {
      /* Too small to be a core file */
      bfd_set_error (bfd_error_wrong_format);
      return 0;
    }

  /* Sanity check perhaps??? */
  if (u.u_dsize > 0x1000000)	/* Remember, it's in pages...  */
    {
      bfd_set_error (bfd_error_wrong_format);
      return 0;
    }
  if (u.u_ssize > 0x1000000)
    {
      bfd_set_error (bfd_error_wrong_format);
      return 0;
    }

  /* Check that the size claimed is no greater than the file size.  */
  {
    struct stat statbuf;

    if (bfd_stat (abfd, &statbuf) < 0)
      return 0;

    if ((ufile_ptr) NBPG * (UPAGES + u.u_dsize
#ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE
			    - u.u_tsize
#endif
			    + u.u_ssize)
	> (ufile_ptr) statbuf.st_size)
      {
	bfd_set_error (bfd_error_wrong_format);
	return 0;
      }
#ifndef TRAD_CORE_ALLOW_ANY_EXTRA_SIZE
    if (((ufile_ptr) NBPG * (UPAGES + u.u_dsize + u.u_ssize)
#ifdef TRAD_CORE_EXTRA_SIZE_ALLOWED
	/* Some systems write the file too big.  */
	 + TRAD_CORE_EXTRA_SIZE_ALLOWED
#endif
	 )
	< (ufile_ptr) statbuf.st_size)
      {
	/* The file is too big.  Maybe it's not a core file
	   or we otherwise have bad values for u_dsize and u_ssize).  */
	bfd_set_error (bfd_error_wrong_format);
	return 0;
      }
#endif
  }

  /* OK, we believe you.  You're a core file (sure, sure).  */

  /* Allocate both the upage and the struct core_data at once, so
     a single free() will free them both.  */
  amt = sizeof (struct trad_core_struct);
  rawptr = (struct trad_core_struct *) bfd_zmalloc (amt);
  if (rawptr == NULL)
    return 0;

  abfd->tdata.trad_core_data = rawptr;

  rawptr->u = u; /*Copy the uarea into the tdata part of the bfd */

  /* Create the sections.  */

  flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
  core_stacksec(abfd) = bfd_make_section_anyway_with_flags (abfd, ".stack",
							    flags);
  if (core_stacksec (abfd) == NULL)
    goto fail;
  core_datasec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".data",
							    flags);
  if (core_datasec (abfd) == NULL)
    goto fail;
  core_regsec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".reg",
							   SEC_HAS_CONTENTS);
  if (core_regsec (abfd) == NULL)
    goto fail;

  core_datasec (abfd)->size =  NBPG * u.u_dsize
#ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE
    - NBPG * u.u_tsize
#endif
      ;
  core_stacksec (abfd)->size = NBPG * u.u_ssize;
  core_regsec (abfd)->size = NBPG * UPAGES; /* Larger than sizeof struct u */

  /* What a hack... we'd like to steal it from the exec file,
     since the upage does not seem to provide it.  FIXME.  */
#ifdef HOST_DATA_START_ADDR
  core_datasec (abfd)->vma = HOST_DATA_START_ADDR;
#else
  core_datasec (abfd)->vma = HOST_TEXT_START_ADDR + (NBPG * u.u_tsize);
#endif

#ifdef HOST_STACK_START_ADDR
  core_stacksec (abfd)->vma = HOST_STACK_START_ADDR;
#else
  core_stacksec (abfd)->vma = HOST_STACK_END_ADDR - (NBPG * u.u_ssize);
#endif

  /* This is tricky.  As the "register section", we give them the entire
     upage and stack.  u.u_ar0 points to where "register 0" is stored.
     There are two tricks with this, though.  One is that the rest of the
     registers might be at positive or negative (or both) displacements
     from *u_ar0.  The other is that u_ar0 is sometimes an absolute address
     in kernel memory, and on other systems it is an offset from the beginning
     of the `struct user'.

     As a practical matter, we don't know where the registers actually are,
     so we have to pass the whole area to GDB.  We encode the value of u_ar0
     by setting the .regs section up so that its virtual memory address
     0 is at the place pointed to by u_ar0 (by setting the vma of the start
     of the section to -u_ar0).  GDB uses this info to locate the regs,
     using minor trickery to get around the offset-or-absolute-addr problem.  */
  core_regsec (abfd)->vma = - (bfd_vma) (unsigned long) u.u_ar0;

  core_datasec (abfd)->filepos = NBPG * UPAGES;
  core_stacksec (abfd)->filepos = (NBPG * UPAGES) + NBPG * u.u_dsize
#ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE
    - NBPG * u.u_tsize
#endif
      ;
  core_regsec (abfd)->filepos = 0; /* Register segment is the upage */

  /* Align to word at least */
  core_stacksec (abfd)->alignment_power = 2;
  core_datasec (abfd)->alignment_power = 2;
  core_regsec (abfd)->alignment_power = 2;

  return abfd->xvec;

 fail:
  bfd_release (abfd, abfd->tdata.any);
  abfd->tdata.any = NULL;
  bfd_section_list_clear (abfd);
  return NULL;
}
Esempio n. 21
0
static bfd_boolean
_bfd_get_file_window_mmap(bfd *abfd, ufile_ptr offset, bfd_size_type size,
                          bfd_window *windowp, bfd_window_internal *i,
                          bfd_boolean writable)
{
  static size_t pagesize;
  bfd_size_type size_to_alloc = size;

  if (debug_windows)
    fprintf(stderr,
            "bfd_get_file_window (%p, %6ld, %6ld, %p<%p,%lx,%p>, %d)",
            (void *)abfd, (long)offset, (long)size, (void *)windowp,
            windowp->data, (unsigned long)windowp->size,
            (void *)windowp->i, writable);

  /* Make sure we know the page size, so we can be friendly to mmap: */
  if (pagesize == 0)
    pagesize = (size_t)getpagesize();
  if (pagesize == 0)
    abort();

# ifdef HAVE_MMAP
  if (ok_to_map
      && ((i->data == 0) || (i->mapped == 1))
      && ((abfd->flags & BFD_IN_MEMORY) == 0))
    {
      file_ptr file_offset, offset2;
      size_t real_size;
      int fd;
      FILE *f;

      /* Find the real file and the real offset into it: */
      while (abfd->my_archive != NULL)
	{
	  offset += abfd->origin;
	  abfd = abfd->my_archive;
	}
      f = bfd_cache_lookup(abfd);
      fd = fileno(f);

      /* Compute offsets and size for mmap and for the user's data: */
      offset2 = (file_ptr)(offset % pagesize);
      if (offset2 < 0)
	abort();
      file_offset = ((file_ptr)offset - offset2);
      real_size = (size_t)(offset + size - (unsigned long)file_offset);
      real_size = (real_size + pagesize - 1UL);
      real_size -= (real_size % pagesize);

      /* If we are re-using a memory region, make sure it is big enough: */
      if (i->data && (i->size < size))
	{
	  munmap(i->data, (size_t)i->size);
	  i->data = 0;
	}
      i->data = mmap(i->data, real_size,
                     (writable ? (PROT_WRITE | PROT_READ) : PROT_READ),
                     (writable
                      ? (MAP_FILE | MAP_PRIVATE)
                      : (MAP_FILE | MAP_SHARED)),
                     fd, (off_t)file_offset);
      if (i->data == (void *)-1)
	{
	  /* An error happened.  Report it, or try using malloc, or
	   * something: */
	  bfd_set_error(bfd_error_system_call);
	  i->data = 0;
	  windowp->data = 0;
	  if (debug_windows)
	    fprintf(stderr, "\t\tmmap failed!\n");
	  return FALSE;
	}
      if (debug_windows)
	fprintf(stderr, "\n\tmapped %ld at %p, offset is %ld\n",
                (long)real_size, i->data, (long)offset2);
      i->size = real_size;
      windowp->data = ((bfd_byte *)i->data + offset2);
      windowp->size = size;
      i->mapped = 1;
      return TRUE;
    }
  else if (debug_windows)
    {
      if (ok_to_map)
	fprintf(stderr, _("not mapping: data=%lx mapped=%d\n"),
                (unsigned long)i->data, (int)i->mapped);
      else
	fprintf(stderr, _("not mapping: env var not set\n"));
    }
# else
  ok_to_map = 0;
# endif /* HAVE_MMAP */

# ifdef HAVE_MPROTECT
  if (!writable)
    {
      size_to_alloc += (pagesize - 1);
      size_to_alloc -= (size_to_alloc % pagesize);
    }
# endif /* HAVE_MPROTECT */
  if (debug_windows)
    fprintf(stderr, "\n\t%s(%6ld)",
            (i->data ? "realloc" : " malloc"), (long)size_to_alloc);
  i->data = bfd_realloc(i->data, size_to_alloc);
  if (debug_windows)
    fprintf(stderr, "\t-> %p\n", i->data);
  i->refcount = 1;
  if (i->data == NULL)
    {
      if (size_to_alloc == 0)
	return TRUE;
      return FALSE;
    }
  if (bfd_seek(abfd, (file_ptr)offset, SEEK_SET) != 0)
    return FALSE;
  i->size = bfd_bread(i->data, size, abfd);
  if (i->size != size)
    return FALSE;
  i->mapped = 0;
# ifdef HAVE_MPROTECT
  if (!writable)
    {
      if (debug_windows)
	fprintf(stderr, "\tmprotect (%p, %ld, PROT_READ)\n", i->data,
                (long)i->size);
      mprotect(i->data, i->size, PROT_READ);
    }
# endif /* HAVE_MPROTECT */
  windowp->data = i->data;
  windowp->size = i->size;
  return TRUE;
}
Esempio n. 22
0
void
read_pe_exported_syms (struct objfile *objfile)
{
  bfd *dll = objfile->obfd;
  unsigned long nbnormal, nbforward;
  unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
  unsigned long export_opthdrrva, export_opthdrsize;
  unsigned long export_rva, export_size, nsections, secptr, expptr;
  unsigned long exp_funcbase;
  unsigned char *expdata, *erva;
  unsigned long name_rvas, ordinals, nexp, ordbase;
  char *dll_name = (char *) dll->filename;
  int otherix = PE_SECTION_TABLE_SIZE;
  int is_pe64 = 0;
  int is_pe32 = 0;

  /* Array elements are for text, data and bss in that order
     Initialization with RVA_START > RVA_END guarantees that
     unused sections won't be matched.  */
  struct read_pe_section_data *section_data;
  struct pe_sections_info pe_sections_info;

  struct cleanup *back_to = make_cleanup (null_cleanup, 0);

  char const *target = bfd_get_target (objfile->obfd);

  section_data = xzalloc (PE_SECTION_TABLE_SIZE
			 * sizeof (struct read_pe_section_data));

  make_cleanup (free_current_contents, &section_data);

  for (i=0; i < PE_SECTION_TABLE_SIZE; i++)
    {
      section_data[i].vma_offset = 0;
      section_data[i].rva_start = 1;
      section_data[i].rva_end = 0;
    };
  section_data[PE_SECTION_INDEX_TEXT].ms_type = mst_text;
  section_data[PE_SECTION_INDEX_TEXT].section_name = ".text";
  section_data[PE_SECTION_INDEX_DATA].ms_type = mst_data;
  section_data[PE_SECTION_INDEX_DATA].section_name = ".data";
  section_data[PE_SECTION_INDEX_BSS].ms_type = mst_bss;
  section_data[PE_SECTION_INDEX_BSS].section_name = ".bss";

  is_pe64 = (strcmp (target, "pe-x86-64") == 0
	     || strcmp (target, "pei-x86-64") == 0);
  is_pe32 = (strcmp (target, "pe-i386") == 0
	     || strcmp (target, "pei-i386") == 0
	     || strcmp (target, "pe-arm-wince-little") == 0
	     || strcmp (target, "pei-arm-wince-little") == 0);
  if (!is_pe32 && !is_pe64)
    {
      /* This is not a recognized PE format file.  Abort now, because
	 the code is untested on anything else.  *FIXME* test on
	 further architectures and loosen or remove this test.  */
      do_cleanups (back_to);
      return;
    }

  /* Get pe_header, optional header and numbers of export entries.  */
  pe_header_offset = pe_get32 (dll, 0x3c);
  opthdr_ofs = pe_header_offset + 4 + 20;
  if (is_pe64)
    num_entries = pe_get32 (dll, opthdr_ofs + 108);
  else
    num_entries = pe_get32 (dll, opthdr_ofs + 92);

  if (num_entries < 1)		/* No exports.  */
    {
      do_cleanups (back_to);
      return;
    }
  if (is_pe64)
    {
      export_opthdrrva = pe_get32 (dll, opthdr_ofs + 112);
      export_opthdrsize = pe_get32 (dll, opthdr_ofs + 116);
    }
  else
    {
      export_opthdrrva = pe_get32 (dll, opthdr_ofs + 96);
      export_opthdrsize = pe_get32 (dll, opthdr_ofs + 100);
    }
  nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
  secptr = (pe_header_offset + 4 + 20 +
	    pe_get16 (dll, pe_header_offset + 4 + 16));
  expptr = 0;
  export_size = 0;

  /* Get the rva and size of the export section.  */
  for (i = 0; i < nsections; i++)
    {
      char sname[8];
      unsigned long secptr1 = secptr + 40 * i;
      unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
      unsigned long vsize = pe_get32 (dll, secptr1 + 16);
      unsigned long fptr = pe_get32 (dll, secptr1 + 20);

      bfd_seek (dll, (file_ptr) secptr1, SEEK_SET);
      bfd_bread (sname, (bfd_size_type) sizeof (sname), dll);

      if ((strcmp (sname, ".edata") == 0)
	  || (vaddr <= export_opthdrrva && export_opthdrrva < vaddr + vsize))
	{
	  if (strcmp (sname, ".edata") != 0)
	    {
	      if (debug_coff_pe_read)
		fprintf_unfiltered (gdb_stdlog, _("Export RVA for dll "
				    "\"%s\" is in section \"%s\"\n"),
				    dll_name, sname);
	    }
	  else if (export_opthdrrva != vaddr && debug_coff_pe_read)
	    fprintf_unfiltered (gdb_stdlog, _("Wrong value of export RVA"
				" for dll \"%s\": 0x%lx instead of 0x%lx\n"),
				dll_name, export_opthdrrva, vaddr);
	  expptr = fptr + (export_opthdrrva - vaddr);
	  break;
	}
    }

  export_rva = export_opthdrrva;
  export_size = export_opthdrsize;

  if (export_size == 0)
    {
      /* Empty export table.  */
      do_cleanups (back_to);
      return;
    }

  /* Scan sections and store the base and size of the relevant
     sections.  */
  for (i = 0; i < nsections; i++)
    {
      unsigned long secptr1 = secptr + 40 * i;
      unsigned long vsize = pe_get32 (dll, secptr1 + 8);
      unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
      unsigned long characteristics = pe_get32 (dll, secptr1 + 36);
      char sec_name[SCNNMLEN + 1];
      int sectix;

      bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET);
      bfd_bread (sec_name, (bfd_size_type) SCNNMLEN, dll);
      sec_name[SCNNMLEN] = '\0';

      sectix = read_pe_section_index (sec_name);

      if (sectix != PE_SECTION_INDEX_INVALID)
	{
	  section_data[sectix].rva_start = vaddr;
	  section_data[sectix].rva_end = vaddr + vsize;
	}
      else
	{
	  char *name;

	  section_data = xrealloc (section_data, (otherix + 1)
				   * sizeof (struct read_pe_section_data));
	  name = xstrdup (sec_name);
	  section_data[otherix].section_name = name;
	  make_cleanup (xfree, name);
	  section_data[otherix].rva_start = vaddr;
	  section_data[otherix].rva_end = vaddr + vsize;
	  section_data[otherix].vma_offset = 0;
	  if (characteristics & IMAGE_SCN_CNT_CODE)
	    section_data[otherix].ms_type = mst_text;
	  else if (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
	    section_data[otherix].ms_type = mst_data;
	  else if (characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
	    section_data[otherix].ms_type = mst_bss;
	  else
	    section_data[otherix].ms_type = mst_unknown;
	  otherix++;
	}
    }

  expdata = (unsigned char *) xmalloc (export_size);
  make_cleanup (xfree, expdata);

  bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
  bfd_bread (expdata, (bfd_size_type) export_size, dll);
  erva = expdata - export_rva;

  nexp = pe_as32 (expdata + 24);
  name_rvas = pe_as32 (expdata + 32);
  ordinals = pe_as32 (expdata + 36);
  ordbase = pe_as32 (expdata + 16);
  exp_funcbase = pe_as32 (expdata + 28);

  /* Use internal dll name instead of full pathname.  */
  dll_name = pe_as32 (expdata + 12) + erva;

  pe_sections_info.nb_sections = otherix;
  pe_sections_info.sections = section_data;

  bfd_map_over_sections (dll, get_section_vmas, &pe_sections_info);

  /* Adjust the vma_offsets in case this PE got relocated. This
     assumes that *all* sections share the same relocation offset
     as the text section.  */
  for (i = 0; i < otherix; i++)
    {
      section_data[i].vma_offset
	+= ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
    }

  /* Truncate name at first dot. Should maybe also convert to all
     lower case for convenience on Windows.  */
  read_pe_truncate_name (dll_name);

  if (debug_coff_pe_read)
    fprintf_unfiltered (gdb_stdlog, _("DLL \"%s\" has %ld export entries,"
			" base=%ld\n"), dll_name, nexp, ordbase);
  nbforward = 0;
  nbnormal = 0;
  /* Iterate through the list of symbols.  */
  for (i = 0; i < nexp; i++)
    {
      /* Pointer to the names vector.  */
      unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4);
      /* Retrieve ordinal value.  */

      unsigned long ordinal = pe_as16 (erva + ordinals + i * 2);


      /* Pointer to the function address vector.  */
      /* This is relatived to ordinal value. */
      unsigned long func_rva = pe_as32 (erva + exp_funcbase +
                                        ordinal * 4);

      /* Find this symbol's section in our own array.  */
      int sectix = 0;
      int section_found = 0;

      /* First handle forward cases.  */
      if (func_rva >= export_rva && func_rva < export_rva + export_size)
	{
	  char *forward_name = (char *) (erva + func_rva);
	  char *funcname = (char *) (erva + name_rva);
	  char *forward_dll_name = forward_name;
	  char *forward_func_name = forward_name;
	  char *sep = strrchr (forward_name, '.');

	  if (sep)
	    {
	      int len = (int) (sep - forward_name);

	      forward_dll_name = alloca (len + 1);
	      strncpy (forward_dll_name, forward_name, len);
	      forward_dll_name[len] = '\0';
	      forward_func_name = ++sep;
	    }
	  if (add_pe_forwarded_sym (funcname, forward_dll_name,
				    forward_func_name, ordinal,
				    dll_name, objfile) != 0)
	    ++nbforward;
	  continue;
	}

      for (sectix = 0; sectix < otherix; ++sectix)
	{
	  if ((func_rva >= section_data[sectix].rva_start)
	      && (func_rva < section_data[sectix].rva_end))
	    {
	      section_found = 1;
	      add_pe_exported_sym (erva + name_rva,
				   func_rva, ordinal,
				   section_data + sectix, dll_name, objfile);
	      ++nbnormal;
	      break;
	    }
	}
      if (!section_found)
	{
	  char *funcname = (char *) (erva + name_rva);

	  if (name_rva == 0)
	    {
	      add_pe_exported_sym (NULL, func_rva, ordinal,
				   section_data, dll_name, objfile);
	      ++nbnormal;
	    }
	  else if (debug_coff_pe_read)
	    fprintf_unfiltered (gdb_stdlog, _("Export name \"%s\" ord. %lu,"
				" RVA 0x%lx in dll \"%s\" not handled\n"),
				funcname, ordinal, func_rva, dll_name);
	}
    }

  if (debug_coff_pe_read)
    fprintf_unfiltered (gdb_stdlog, _("Finished reading \"%s\", exports %ld,"
			" forwards %ld, total %ld/%ld.\n"), dll_name, nbnormal,
			nbforward, nbnormal + nbforward, nexp);
  /* Discard expdata and section_data.  */
  do_cleanups (back_to);
}
Esempio n. 23
0
void
read_pe_exported_syms (struct objfile *objfile)
{
  bfd *dll = objfile->obfd;
  unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
  unsigned long export_rva, export_size, nsections, secptr, expptr;
  unsigned long exp_funcbase;
  unsigned char *expdata, *erva;
  unsigned long name_rvas, ordinals, nexp, ordbase;
  char *dll_name;

  /* Array elements are for text, data and bss in that order
     Initialization with start_rva > end_rva guarantees that
     unused sections won't be matched. */
  struct read_pe_section_data section_data[PE_SECTION_TABLE_SIZE]
    = { {0, 1, 0, mst_text},
  {0, 1, 0, mst_data},
  {0, 1, 0, mst_bss}
  };

  struct cleanup *back_to = 0;

  char const *target = bfd_get_target (objfile->obfd);

  if ((strcmp (target, "pe-i386") != 0) && (strcmp (target, "pei-i386") != 0))
    {
      /* This is not an i386 format file. Abort now, because the code
         is untested on anything else. *FIXME* test on further
         architectures and loosen or remove this test. */
      return;
    }

  /* Get pe_header, optional header and numbers of export entries.  */
  pe_header_offset = pe_get32 (dll, 0x3c);
  opthdr_ofs = pe_header_offset + 4 + 20;
  num_entries = pe_get32 (dll, opthdr_ofs + 92);

  if (num_entries < 1)		/* No exports.  */
    {
      return;
    }

  export_rva = pe_get32 (dll, opthdr_ofs + 96);
  export_size = pe_get32 (dll, opthdr_ofs + 100);
  nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
  secptr = (pe_header_offset + 4 + 20 +
	    pe_get16 (dll, pe_header_offset + 4 + 16));
  expptr = 0;

  /* Get the rva and size of the export section.  */
  for (i = 0; i < nsections; i++)
    {
      char sname[8];
      unsigned long secptr1 = secptr + 40 * i;
      unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
      unsigned long vsize = pe_get32 (dll, secptr1 + 16);
      unsigned long fptr = pe_get32 (dll, secptr1 + 20);

      bfd_seek (dll, (file_ptr) secptr1, SEEK_SET);
      bfd_bread (sname, (bfd_size_type) 8, dll);

      if (vaddr <= export_rva && vaddr + vsize > export_rva)
	{
	  expptr = fptr + (export_rva - vaddr);
	  if (export_rva + export_size > vaddr + vsize)
	    export_size = vsize - (export_rva - vaddr);
	  break;
	}
    }

  if (export_size == 0)
    {
      /* Empty export table. */
      return;
    }

  /* Scan sections and store the base and size of the relevant sections. */
  for (i = 0; i < nsections; i++)
    {
      unsigned long secptr1 = secptr + 40 * i;
      unsigned long vsize = pe_get32 (dll, secptr1 + 8);
      unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
      unsigned long flags = pe_get32 (dll, secptr1 + 36);
      char sec_name[9];
      int sectix;

      sec_name[8] = '\0';
      bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET);
      bfd_bread (sec_name, (bfd_size_type) 8, dll);

      sectix = read_pe_section_index (sec_name);

      if (sectix != PE_SECTION_INDEX_INVALID)
	{
	  section_data[sectix].rva_start = vaddr;
	  section_data[sectix].rva_end = vaddr + vsize;
	}
    }

  expdata = (unsigned char *) xmalloc (export_size);
  back_to = make_cleanup (xfree, expdata);

  bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
  bfd_bread (expdata, (bfd_size_type) export_size, dll);
  erva = expdata - export_rva;

  nexp = pe_as32 (expdata + 24);
  name_rvas = pe_as32 (expdata + 32);
  ordinals = pe_as32 (expdata + 36);
  ordbase = pe_as32 (expdata + 16);
  exp_funcbase = pe_as32 (expdata + 28);

  /* Use internal dll name instead of full pathname. */
  dll_name = pe_as32 (expdata + 12) + erva;

  bfd_map_over_sections (dll, get_section_vmas, section_data);

  /* Adjust the vma_offsets in case this PE got relocated. This
     assumes that *all* sections share the same relocation offset
     as the text section. */
  for (i = 0; i < PE_SECTION_TABLE_SIZE; i++)
    {
      section_data[i].vma_offset
	+= ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
    }

  printf_filtered ("Minimal symbols from %s...", dll_name);
  wrap_here ("");

  /* Truncate name at first dot. Should maybe also convert to all
     lower case for convenience on Windows. */
  read_pe_truncate_name (dll_name);

  /* Iterate through the list of symbols.  */
  for (i = 0; i < nexp; i++)
    {
      /* Pointer to the names vector.  */
      unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4);

      /* Pointer to the function address vector.  */
      unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4);

      /* Find this symbol's section in our own array. */
      int sectix = 0;

      for (sectix = 0; sectix < PE_SECTION_TABLE_SIZE; ++sectix)
	{
	  if ((func_rva >= section_data[sectix].rva_start)
	      && (func_rva < section_data[sectix].rva_end))
	    {
	      add_pe_exported_sym (erva + name_rva,
				   func_rva,
				   section_data + sectix, dll_name, objfile);
	      break;
	    }
	}
    }

  /* discard expdata. */
  do_cleanups (back_to);
}
Esempio n. 24
0
bfd_boolean
bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
{
  extern const bfd_target binary_vec;
  const bfd_target * const *target;
  const bfd_target **matching_vector = NULL;
  const bfd_target *save_targ, *right_targ, *ar_right_targ;
  int match_count;
  int ar_match_index;

  if (!bfd_read_p (abfd)
      || (unsigned int) abfd->format >= (unsigned int) bfd_type_end)
    {
      bfd_set_error (bfd_error_invalid_operation);
      return FALSE;
    }

  if (abfd->format != bfd_unknown)
    return abfd->format == format;

  /* Since the target type was defaulted, check them
     all in the hope that one will be uniquely recognized.  */
  save_targ = abfd->xvec;
  match_count = 0;
  ar_match_index = _bfd_target_vector_entries;

  if (matching)
    {
      bfd_size_type amt;

      *matching = NULL;
      amt = sizeof (*matching_vector) * 2 * _bfd_target_vector_entries;
      matching_vector = bfd_malloc (amt);
      if (!matching_vector)
	return FALSE;
    }

  right_targ = 0;
  ar_right_targ = 0;

  /* Presume the answer is yes.  */
  abfd->format = format;

  /* If the target type was explicitly specified, just check that target.  */
  if (!abfd->target_defaulted)
    {
      if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)	/* rewind! */
	{
	  if (matching)
	    free (matching_vector);
	  return FALSE;
	}

      right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));

      if (right_targ)
	{
	  abfd->xvec = right_targ;	/* Set the target as returned.  */

	  if (matching)
	    free (matching_vector);

	  /* If the file was opened for update, then `output_has_begun'
	     some time ago when the file was created.  Do not recompute
	     sections sizes or alignments in _bfd_set_section_contents.
	     We can not set this flag until after checking the format,
	     because it will interfere with creation of BFD sections.  */
	  if (abfd->direction == both_direction)
	    abfd->output_has_begun = TRUE;

	  return TRUE;			/* File position has moved, BTW.  */
	}

      /* For a long time the code has dropped through to check all
	 targets if the specified target was wrong.  I don't know why,
	 and I'm reluctant to change it.  However, in the case of an
	 archive, it can cause problems.  If the specified target does
	 not permit archives (e.g., the binary target), then we should
	 not allow some other target to recognize it as an archive, but
	 should instead allow the specified target to recognize it as an
	 object.  When I first made this change, it broke the PE target,
	 because the specified pei-i386 target did not recognize the
	 actual pe-i386 archive.  Since there may be other problems of
	 this sort, I changed this test to check only for the binary
	 target.  */
      if (format == bfd_archive && save_targ == &binary_vec)
	{
	  abfd->xvec = save_targ;
	  abfd->format = bfd_unknown;

	  if (matching)
	    free (matching_vector);

	  bfd_set_error (bfd_error_file_not_recognized);

	  return FALSE;
	}
    }

  for (target = bfd_target_vector; *target != NULL; target++)
    {
      const bfd_target *temp;
      bfd_error_type err;

      if (*target == &binary_vec)
	continue;

      abfd->xvec = *target;	/* Change BFD's target temporarily.  */

      if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
	{
	  if (matching)
	    free (matching_vector);
	  return FALSE;
	}

      /* If _bfd_check_format neglects to set bfd_error, assume
	 bfd_error_wrong_format.  We didn't used to even pay any
	 attention to bfd_error, so I suspect that some
	 _bfd_check_format might have this problem.  */
      bfd_set_error (bfd_error_wrong_format);

      temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));

      if (temp)
	{
	  /* This format checks out as ok!  */
	  right_targ = temp;

	  /* If this is the default target, accept it, even if other
	     targets might match.  People who want those other targets
	     have to set the GNUTARGET variable.  */
	  if (temp == bfd_default_vector[0])
	    {
	      match_count = 1;
	      break;
	    }

	  if (matching)
	    matching_vector[match_count] = temp;

	  match_count++;
	}
      else if ((err = bfd_get_error ()) == bfd_error_wrong_object_format
	       || err == bfd_error_file_ambiguously_recognized)
	{
	  /* An archive with objects of the wrong type, or an
	     ambiguous match.  We want this target to match if we get
	     no better matches.  */
	  if (ar_right_targ != bfd_default_vector[0])
	    ar_right_targ = *target;
	  if (matching)
	    matching_vector[ar_match_index] = *target;
	  ar_match_index++;
	}
      else if (err != bfd_error_wrong_format)
	{
	  abfd->xvec = save_targ;
	  abfd->format = bfd_unknown;

	  if (matching)
	    free (matching_vector);

	  return FALSE;
	}
    }

  if (match_count == 0)
    {
      /* Try partial matches.  */
      right_targ = ar_right_targ;

      if (right_targ == bfd_default_vector[0])
	{
	  match_count = 1;
	}
      else
	{
	  match_count = ar_match_index - _bfd_target_vector_entries;

	  if (matching && match_count > 1)
	    memcpy (matching_vector,
		    matching_vector + _bfd_target_vector_entries,
		    sizeof (*matching_vector) * match_count);
	}
    }

  if (match_count > 1
      && bfd_associated_vector != NULL
      && matching)
    {
      const bfd_target * const *assoc = bfd_associated_vector;

      while ((right_targ = *assoc++) != NULL)
	{
	  int i = match_count;

	  while (--i >= 0)
	    if (matching_vector[i] == right_targ)
	      break;

	  if (i >= 0)
	    {
	      match_count = 1;
	      break;
	    }
	}
    }

  if (match_count == 1)
    {
      abfd->xvec = right_targ;		/* Change BFD's target permanently.  */

      if (matching)
	free (matching_vector);

      /* If the file was opened for update, then `output_has_begun'
	 some time ago when the file was created.  Do not recompute
	 sections sizes or alignments in _bfd_set_section_contents.
	 We can not set this flag until after checking the format,
	 because it will interfere with creation of BFD sections.  */
      if (abfd->direction == both_direction)
	abfd->output_has_begun = TRUE;

      return TRUE;			/* File position has moved, BTW.  */
    }

  abfd->xvec = save_targ;		/* Restore original target type.  */
  abfd->format = bfd_unknown;		/* Restore original format.  */

  if (match_count == 0)
    {
      bfd_set_error (bfd_error_file_not_recognized);

      if (matching)
	free (matching_vector);
    }
  else
    {
      bfd_set_error (bfd_error_file_ambiguously_recognized);

      if (matching)
	{
	  *matching = (char **) matching_vector;
	  matching_vector[match_count] = NULL;
	  /* Return target names.  This is a little nasty.  Maybe we
	     should do another bfd_malloc?  */
	  while (--match_count >= 0)
	    {
	      const char *name = matching_vector[match_count]->name;
	      *(const char **) &matching_vector[match_count] = name;
	    }
	}
    }

  return FALSE;
}
Esempio n. 25
0
bfd_boolean
bfd_get_file_window (bfd *abfd,
		     file_ptr offset,
		     bfd_size_type size,
		     bfd_window *windowp,
		     bfd_boolean writable)
{
  static size_t pagesize;
  bfd_window_internal *i = windowp->i;
  bfd_size_type size_to_alloc = size;

  if (debug_windows)
    fprintf (stderr, "bfd_get_file_window (%p, %6ld, %6ld, %p<%p,%lx,%p>, %d)",
	     abfd, (long) offset, (long) size,
	     windowp, windowp->data, (unsigned long) windowp->size,
	     windowp->i, writable);

  /* Make sure we know the page size, so we can be friendly to mmap.  */
  if (pagesize == 0)
    pagesize = getpagesize ();
  if (pagesize == 0)
    abort ();

  if (i == NULL)
    {
      i = bfd_zmalloc (sizeof (bfd_window_internal));
      if (i == NULL)
	return FALSE;
      i->data = NULL;
    }
#ifdef HAVE_MMAP
  if (ok_to_map
      && (i->data == NULL || i->mapped == 1)
      && (abfd->flags & BFD_IN_MEMORY) == 0)
    {
      file_ptr file_offset, offset2;
      size_t real_size;
      int fd;

      /* Find the real file and the real offset into it.  */
      while (abfd->my_archive != NULL
	     && !bfd_is_thin_archive (abfd->my_archive))
	{
	  offset += abfd->origin;
	  abfd = abfd->my_archive;
	}

      /* Seek into the file, to ensure it is open if cacheable.  */
      if (abfd->iostream == NULL
	  && (abfd->iovec == NULL
	      || abfd->iovec->bseek (abfd, offset, SEEK_SET) != 0))
	goto free_and_fail;

      fd = fileno ((FILE *) abfd->iostream);
      /* Compute offsets and size for mmap and for the user's data.  */
      offset2 = offset % pagesize;
      if (offset2 < 0)
	abort ();
      file_offset = offset - offset2;
      real_size = offset + size - file_offset;
      real_size = real_size + pagesize - 1;
      real_size -= real_size % pagesize;

      /* If we're re-using a memory region, make sure it's big enough.  */
      if (i->data != NULL && i->size < size)
	{
	  munmap (i->data, i->size);
	  i->data = NULL;
	}
      i->data = mmap (i->data, real_size,
		      writable ? PROT_WRITE | PROT_READ : PROT_READ,
		      (writable
		       ? MAP_FILE | MAP_PRIVATE
		       : MAP_FILE | MAP_SHARED),
		      fd, file_offset);
      if (i->data == (void *) -1)
	{
	  /* An error happened.  Report it, or try using malloc, or
	     something.  */
	  bfd_set_error (bfd_error_system_call);
	  windowp->data = 0;
	  if (debug_windows)
	    fprintf (stderr, "\t\tmmap failed!\n");
	  goto free_and_fail;
	}
      if (debug_windows)
	fprintf (stderr, "\n\tmapped %ld at %p, offset is %ld\n",
		 (long) real_size, i->data, (long) offset2);
      i->size = real_size;
      windowp->data = (bfd_byte *) i->data + offset2;
      windowp->size = size;
      i->mapped = 1;
      i->refcount = 1;
      windowp->i = i;
      return TRUE;
    }
  else if (debug_windows)
    {
      if (ok_to_map)
	fprintf (stderr, _("not mapping: data=%lx mapped=%d\n"),
		 (unsigned long) i->data, (int) i->mapped);
      else
	fprintf (stderr, _("not mapping: env var not set\n"));
    }
#else
  ok_to_map = 0;
#endif

#ifdef HAVE_MPROTECT
  if (!writable)
    {
      size_to_alloc += pagesize - 1;
      size_to_alloc -= size_to_alloc % pagesize;
    }
#endif
  if (debug_windows)
    fprintf (stderr, "\n\t%s(%6ld)",
	     i->data ? "realloc" : " malloc", (long) size_to_alloc);
  i->data = bfd_realloc_or_free (i->data, size_to_alloc);
  if (debug_windows)
    fprintf (stderr, "\t-> %p\n", i->data);
  if (i->data == NULL)
    {
      if (size_to_alloc == 0)
	{
	  windowp->i = i;
	  return TRUE;
	}
      goto free_and_fail;
    }
  i->refcount = 1;
  if (bfd_seek (abfd, offset, SEEK_SET) != 0)
    goto free_and_fail;
  i->size = bfd_bread (i->data, size, abfd);
  if (i->size != size)
    goto free_and_fail;
  i->mapped = 0;
#ifdef HAVE_MPROTECT
  if (!writable)
    {
      if (debug_windows)
	fprintf (stderr, "\tmprotect (%p, %ld, PROT_READ)\n", i->data,
		 (long) i->size);
      mprotect (i->data, i->size, PROT_READ);
    }
#endif
  windowp->data = i->data;
  windowp->size = i->size;
  windowp->i = i;
  return TRUE;

 free_and_fail:
  /* We have a bfd_window_internal, but an error occurred.  Free it. */
  free (i);
  return FALSE;
}
Esempio n. 26
0
static const struct bfd_target *
vms_object_p (bfd * abfd)
{
  int err = 0;
  int prev_type;
  const struct bfd_target *target_vector = NULL;
  const bfd_arch_info_type *arch = NULL;
  void * tdata_save = abfd->tdata.any;
  bfd_vma saddr_save = bfd_get_start_address (abfd);

#if defined(VMS_DEBUG) && VMS_DEBUG
  vms_debug (1, "vms_object_p (%p)\n", abfd);
#endif

  if (!vms_initialize (abfd))
    goto error_ret;

  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET))
    goto err_wrong_format;

  prev_type = -1;

  do
    {
#if defined(VMS_DEBUG) && VMS_DEBUG
      vms_debug (7, "reading at %08lx\n", bfd_tell (abfd));
#endif
      if (_bfd_vms_next_record (abfd) < 0)
	{
#if defined(VMS_DEBUG) && VMS_DEBUG
	  vms_debug (2, "next_record failed\n");
#endif
	  goto err_wrong_format;
	}

      if ((prev_type == EOBJ_S_C_EGSD)
	   && (PRIV (rec_type) != EOBJ_S_C_EGSD))
	{
	  if (! vms_fixup_sections (abfd))
	    {
#if defined(VMS_DEBUG) && VMS_DEBUG
	      vms_debug (2, "vms_fixup_sections failed\n");
#endif
	      goto err_wrong_format;
	    }
	}

      prev_type = PRIV (rec_type);

      if (target_vector == NULL)
	{
	  if (prev_type <= OBJ_S_C_MAXRECTYP)
	    target_vector = & vms_vax_vec;
	  else
	    target_vector = & vms_alpha_vec;
	}

      switch (prev_type)
	{
	  case OBJ_S_C_HDR:
	  case EOBJ_S_C_EMH:
	    err = _bfd_vms_slurp_hdr (abfd, prev_type);
	    break;
	  case OBJ_S_C_EOM:
	  case OBJ_S_C_EOMW:
	  case EOBJ_S_C_EEOM:
	    err = _bfd_vms_slurp_eom (abfd, prev_type);
	    break;
	  case OBJ_S_C_GSD:
	  case EOBJ_S_C_EGSD:
	    err = _bfd_vms_slurp_gsd (abfd, prev_type);
	    break;
	  case OBJ_S_C_TIR:
	  case EOBJ_S_C_ETIR:
	    err = _bfd_vms_slurp_tir (abfd, prev_type);
	    break;
	  case OBJ_S_C_DBG:
	  case EOBJ_S_C_EDBG:
	    err = _bfd_vms_slurp_dbg (abfd, prev_type);
	    break;
	  case OBJ_S_C_TBT:
	  case EOBJ_S_C_ETBT:
	    err = _bfd_vms_slurp_tbt (abfd, prev_type);
	    break;
	  case OBJ_S_C_LNK:
	    err = _bfd_vms_slurp_lnk (abfd, prev_type);
	    break;
	  default:
	    err = -1;
	}
      if (err != 0)
	{
#if defined(VMS_DEBUG) && VMS_DEBUG
	  vms_debug (2, "slurp type %d failed with %d\n", prev_type, err);
#endif
	  goto err_wrong_format;
	}
    }
  while ((prev_type != EOBJ_S_C_EEOM) && (prev_type != OBJ_S_C_EOM) && (prev_type != OBJ_S_C_EOMW));

  if (target_vector == & vms_vax_vec)
    {
      if (! vms_fixup_sections (abfd))
	{
#if defined(VMS_DEBUG) && VMS_DEBUG
	  vms_debug (2, "vms_fixup_sections failed\n");
#endif
	  goto err_wrong_format;
	}

      /* Set arch_info to vax.  */

      arch = bfd_scan_arch ("vax");
      PRIV (is_vax) = TRUE;
#if defined(VMS_DEBUG) && VMS_DEBUG
      vms_debug (2, "arch is vax\n");
#endif
    }
  else if (target_vector == & vms_alpha_vec)
    {
      /* Set arch_info to alpha.   */

      arch = bfd_scan_arch ("alpha");
      PRIV (is_vax) = FALSE;
#if defined(VMS_DEBUG) && VMS_DEBUG
      vms_debug (2, "arch is alpha\n");
#endif
    }

  if (arch == NULL)
    {
#if defined(VMS_DEBUG) && VMS_DEBUG
      vms_debug (2, "arch not found\n");
#endif
      goto err_wrong_format;
    }
  abfd->arch_info = arch;

  return target_vector;

 err_wrong_format:
  bfd_set_error (bfd_error_wrong_format);
 error_ret:
  if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
    bfd_release (abfd, abfd->tdata.any);
  abfd->tdata.any = tdata_save;
  bfd_set_start_address (abfd, saddr_save);
  return NULL;
}
Esempio n. 27
0
static bfd_boolean
wasm_scan (bfd *abfd)
{
  bfd_boolean error = FALSE;
  /* Fake VMAs for now. Choose 0x80000000 as base to avoid clashes
     with actual data addresses.  */
  bfd_vma vma = 0x80000000;
  int section_code;
  unsigned int bytes_read;
  char *name = NULL;
  asection *bfdsec;

  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
    goto error_return;

  if (! wasm_read_header (abfd, &error))
    goto error_return;

  while ((section_code = wasm_read_byte (abfd, &error)) != EOF)
    {
      if (section_code != 0)
	{
	  const char *sname = wasm_section_code_to_name (section_code);

	  if (! sname)
	    goto error_return;

	  name = strdup (sname);
	  bfdsec = bfd_make_section_anyway_with_flags (abfd, name, SEC_HAS_CONTENTS);
	  if (bfdsec == NULL)
	    goto error_return;
	  name = NULL;

	  bfdsec->vma = vma;
	  bfdsec->lma = vma;
	  bfdsec->size = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE);
	  if (error)
	    goto error_return;
	  bfdsec->filepos = bfd_tell (abfd);
	  bfdsec->alignment_power = 0;
	}
      else
	{
	  bfd_vma payload_len;
	  file_ptr section_start;
	  bfd_vma namelen;
	  char *prefix = WASM_SECTION_PREFIX;
	  char *p;
	  int ret;

	  payload_len = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE);
	  if (error)
	    goto error_return;
	  section_start = bfd_tell (abfd);
	  namelen = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE);
	  if (error || namelen > payload_len)
	    goto error_return;
	  name = bfd_zmalloc (namelen + strlen (prefix) + 1);
	  if (! name)
	    goto error_return;
	  p = name;
	  ret = sprintf (p, "%s", prefix);
	  if (ret < 0 || (bfd_vma) ret != strlen (prefix))
	    goto error_return;
	  p += ret;
	  if (bfd_bread (p, namelen, abfd) != namelen)
	    goto error_return;

	  bfdsec = bfd_make_section_anyway_with_flags (abfd, name, SEC_HAS_CONTENTS);
	  if (bfdsec == NULL)
	    goto error_return;
	  name = NULL;

	  bfdsec->vma = vma;
	  bfdsec->lma = vma;
	  bfdsec->filepos = bfd_tell (abfd);
	  bfdsec->size = section_start + payload_len - bfdsec->filepos;
	  bfdsec->alignment_power = 0;
	}

      if (bfdsec->size != 0)
	{
	  bfdsec->contents = bfd_zalloc (abfd, bfdsec->size);
	  if (! bfdsec->contents)
	    goto error_return;

	  if (bfd_bread (bfdsec->contents, bfdsec->size, abfd) != bfdsec->size)
	    goto error_return;
	}

      vma += bfdsec->size;
    }

  /* Make sure we're at actual EOF.  There's no indication in the
     WebAssembly format of how long the file is supposed to be.  */
  if (error)
    goto error_return;

  return TRUE;

 error_return:
  if (name)
    free (name);

  for (bfdsec = abfd->sections; bfdsec; bfdsec = bfdsec->next)
    free ((void *) bfdsec->name);

  return FALSE;
}