Beispiel #1
0
static int
do_sections64 (bfd *abfd, struct coreout *coreout)
{
  struct vmap64 vmap;
  char *secname;
  int i, val;

  for (i = 0; i < coreout->c_nvmap; i++)
    {
      val = bfd_bread ((PTR) &vmap, (bfd_size_type) sizeof vmap, abfd);
      if (val != sizeof vmap)
	break;

      switch (vmap.v_type)
	{
	case VDATA:
	  secname = ".data";
	  break;
	case VSTACK:
	  secname = ".stack";
	  break;
#ifdef VMAPFILE
	case VMAPFILE:
	  secname = ".mapfile";
	  break;
#endif
	default:
	  continue;
	}

      /* A file offset of zero means that the
	 section is not contained in the corefile.  */
      if (vmap.v_offset == 0)
	continue;

      if (!make_bfd_asection (abfd, secname,
			      SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
			      vmap.v_len, vmap.v_vaddr, vmap.v_offset))
	/* Fail.  */
	return 0;
    }

  return 1;
}
Beispiel #2
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 ((PTR) &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;
}
Beispiel #3
0
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;
}
Beispiel #4
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;
}
static const bfd_target *
hppabsd_core_core_file_p (bfd *abfd)
{
  int val;
  struct user u;
  struct hppabsd_core_struct *coredata;
  int clicksz;

  /* Try to read in the u-area.  We will need information from this
     to know how to grok the rest of the core structures.  */
  val = bfd_bread ((void *) &u, (bfd_size_type) sizeof u, abfd);
  if (val != sizeof u)
    {
      if (bfd_get_error () != bfd_error_system_call)
	bfd_set_error (bfd_error_wrong_format);
      return NULL;
    }

  /* Get the page size out of the u structure.  This will be different
     for PA 1.0 machines and PA 1.1 machines.   Yuk!  */
  clicksz = u.u_pcb.pcb_pgsz;

  /* clicksz must be a power of two >= 2k.  */
  if (clicksz < 0x800
      || clicksz != (clicksz & -clicksz))
    {
      bfd_set_error (bfd_error_wrong_format);
      return NULL;
    }

  /* Sanity checks.  Make sure the size of the core file matches the
     the size computed from information within the core itself.  */
  {
    struct stat statbuf;

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

    if (NBPG * (UPAGES + u.u_dsize + u.u_ssize) > statbuf.st_size)
      {
	bfd_set_error (bfd_error_file_truncated);
	return NULL;
      }
    if (clicksz * (UPAGES + u.u_dsize + u.u_ssize) < 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 NULL;
      }
  }

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

  coredata = (struct hppabsd_core_struct *)
    bfd_zalloc (abfd, (bfd_size_type) sizeof (struct hppabsd_core_struct));
  if (!coredata)
    return NULL;

  /* Make the core data and available via the tdata part of the BFD.  */
  abfd->tdata.hppabsd_core_data = coredata;

  /* Create the sections.  */
  core_stacksec (abfd) = make_bfd_asection (abfd, ".stack",
					   SEC_ALLOC + SEC_HAS_CONTENTS,
					   clicksz * u.u_ssize,
					   NBPG * (USIZE + KSTAKSIZE)
					     + clicksz * u.u_dsize, 2);
  if (core_stacksec (abfd) == NULL)
    goto fail;
  core_stacksec (abfd)->vma = USRSTACK;

  core_datasec (abfd) = make_bfd_asection (abfd, ".data",
					  SEC_ALLOC + SEC_LOAD
					    + SEC_HAS_CONTENTS,
					  clicksz * u.u_dsize,
					  NBPG * (USIZE + KSTAKSIZE), 2);
  if (core_datasec (abfd) == NULL)
    goto fail;
  core_datasec (abfd)->vma = UDATASEG;

  core_regsec (abfd) = make_bfd_asection (abfd, ".reg",
					 SEC_HAS_CONTENTS,
					 KSTAKSIZE * NBPG,
					 NBPG * USIZE, 2);
  if (core_regsec (abfd) == NULL)
    goto fail;
  core_regsec (abfd)->vma = 0;

  strncpy (core_command (abfd), u.u_comm, MAXCOMLEN + 1);
  core_signal (abfd) = u.u_code;
  return abfd->xvec;

 fail:
  bfd_release (abfd, abfd->tdata.any);
  abfd->tdata.any = NULL;
  bfd_section_list_clear (abfd);
  return NULL;
}
Beispiel #6
0
static const bfd_target *
osf_core_core_file_p (bfd *abfd)
{
    int val;
    int i;
    char *secname;
    struct core_filehdr core_header;
    bfd_size_type amt;

    amt = sizeof core_header;
    val = bfd_bread (& core_header, amt, abfd);
    if (val != sizeof core_header)
        return NULL;

    if (! CONST_STRNEQ (core_header.magic, "Core"))
        return NULL;

    core_hdr (abfd) = (struct osf_core_struct *)
                      bfd_zalloc (abfd, (bfd_size_type) sizeof (struct osf_core_struct));
    if (!core_hdr (abfd))
        return NULL;

    strncpy (core_command (abfd), core_header.name, MAXCOMLEN + 1);
    core_signal (abfd) = core_header.signo;

    for (i = 0; i < core_header.nscns; i++)
    {
        struct core_scnhdr core_scnhdr;
        flagword flags;

        amt = sizeof core_scnhdr;
        val = bfd_bread (& core_scnhdr, amt, abfd);
        if (val != sizeof core_scnhdr)
            break;

        /* Skip empty sections.  */
        if (core_scnhdr.size == 0 || core_scnhdr.scnptr == 0)
            continue;

        switch (core_scnhdr.scntype)
        {
        case SCNRGN:
            secname = ".data";
            flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
            break;
        case SCNSTACK:
            secname = ".stack";
            flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
            break;
        case SCNREGS:
            secname = ".reg";
            flags = SEC_HAS_CONTENTS;
            break;
        default:
            (*_bfd_error_handler) (_("Unhandled OSF/1 core file section type %d\n"),
                                   core_scnhdr.scntype);
            continue;
        }

        if (!make_bfd_asection (abfd, secname, flags,
                                (bfd_size_type) core_scnhdr.size,
                                (bfd_vma) core_scnhdr.vaddr,
                                (file_ptr) core_scnhdr.scnptr))
            goto fail;
    }

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

    return abfd->xvec;

fail:
    bfd_release (abfd, core_hdr (abfd));
    core_hdr (abfd) = NULL;
    bfd_section_list_clear (abfd);
    return NULL;
}
Beispiel #7
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;
}