Beispiel #1
0
/* Create a dummy BFD.  */
bfd *
plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate)
{
  bfd *abfd;

  bfd_use_reserved_id = 1;
  abfd = bfd_create (concat (name, IRONLY_SUFFIX, (const char *) NULL),
		     srctemplate);
  if (abfd != NULL)
    {
      abfd->flags |= BFD_LINKER_CREATED | BFD_PLUGIN;
      bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
      bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate));
      if (bfd_make_writable (abfd)
	  && bfd_copy_private_bfd_data (srctemplate, abfd))
	{
	  flagword flags;

	  /* Create section to own the symbols.  */
	  flags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
		   | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE);
	  if (bfd_make_section_anyway_with_flags (abfd, ".text", flags))
	    return abfd;
	}
    }
  einfo (_("could not create dummy IR bfd: %F%E\n"));
  return NULL;
}
static asection *
make_bfd_asection (bfd *abfd, const char *name, flagword flags,
                   bfd_size_type size, bfd_vma vma,
                   unsigned int alignment_power)
{
  asection *asect;
  char *newname;

  newname = bfd_alloc (abfd, (bfd_size_type) strlen (name) + 1);
  if (!newname)
    return NULL;

  strcpy (newname, name);

  asect = bfd_make_section_anyway_with_flags (abfd, newname, flags);
  if (!asect)
    return NULL;

  asect->size = size;
  asect->vma = vma;
  asect->filepos = bfd_tell (abfd);
  asect->alignment_power = alignment_power;

  return asect;
}
Beispiel #3
0
static asection *
make_bfd_asection (bfd *abfd, const char *name, flagword flags,
		   bfd_size_type size, bfd_vma vma, file_ptr filepos)
{
  asection *asect;

  asect = bfd_make_section_anyway_with_flags (abfd, name, flags);
  if (!asect)
    return NULL;

  asect->size = size;
  asect->vma = vma;
  asect->filepos = filepos;
  asect->alignment_power = 8;

  return asect;
}
Beispiel #4
0
static void
write_gcore_file_1 (bfd *obfd)
{
  struct cleanup *cleanup;
  void *note_data = NULL;
  int note_size = 0;
  asection *note_sec = NULL;

  /* An external target method must build the notes section.  */
  /* FIXME: uweigand/2011-10-06: All architectures that support core file
     generation should be converted to gdbarch_make_corefile_notes; at that
     point, the target vector method can be removed.  */
  if (!gdbarch_make_corefile_notes_p (target_gdbarch ()))
    note_data = target_make_corefile_notes (obfd, &note_size);
  else
    note_data = gdbarch_make_corefile_notes (target_gdbarch (), obfd, &note_size);

  cleanup = make_cleanup (xfree, note_data);

  if (note_data == NULL || note_size == 0)
    error (_("Target does not support core file generation."));

  /* Create the note section.  */
  note_sec = bfd_make_section_anyway_with_flags (obfd, "note0",
						 SEC_HAS_CONTENTS
						 | SEC_READONLY
						 | SEC_ALLOC);
  if (note_sec == NULL)
    error (_("Failed to create 'note' section for corefile: %s"),
	   bfd_errmsg (bfd_get_error ()));

  bfd_set_section_vma (obfd, note_sec, 0);
  bfd_set_section_alignment (obfd, note_sec, 0);
  bfd_set_section_size (obfd, note_sec, note_size);

  /* Now create the memory/load sections.  */
  if (gcore_memory_sections (obfd) == 0)
    error (_("gcore: failed to get corefile memory sections from target."));

  /* Write out the contents of the note section.  */
  if (!bfd_set_section_contents (obfd, note_sec, note_data, 0, note_size))
    warning (_("writing note section (%s)"), bfd_errmsg (bfd_get_error ()));

  do_cleanups (cleanup);
}
Beispiel #5
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;
}
Beispiel #6
0
/* Helpers to convert between BFD and GOLD symbol formats.  */
static enum ld_plugin_status
asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym,
			    const struct ld_plugin_symbol *ldsym)
{
  flagword flags = BSF_NO_FLAGS;
  struct bfd_section *section;

  asym->the_bfd = abfd;
  asym->name = (ldsym->version
		? concat (ldsym->name, "@", ldsym->version, (const char *) NULL)
		: ldsym->name);
  asym->value = 0;
  switch (ldsym->def)
    {
    case LDPK_WEAKDEF:
      flags = BSF_WEAK;
      /* FALLTHRU */
    case LDPK_DEF:
      flags |= BSF_GLOBAL;
      if (ldsym->comdat_key)
	{
	  char *name = concat (".gnu.linkonce.t.", ldsym->comdat_key,
			       (const char *) NULL);
	  section = bfd_get_section_by_name (abfd, name);
	  if (section != NULL)
	    free (name);
	  else
	    {
	      flagword sflags;

	      sflags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
			| SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE
			| SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD);
	      section = bfd_make_section_anyway_with_flags (abfd, name, sflags);
	      if (section == NULL)
		return LDPS_ERR;
	    }
	}
      else
	section = bfd_get_section_by_name (abfd, ".text");
      break;

    case LDPK_WEAKUNDEF:
      flags = BSF_WEAK;
      /* FALLTHRU */
    case LDPK_UNDEF:
      section = bfd_und_section_ptr;
      break;

    case LDPK_COMMON:
      flags = BSF_GLOBAL;
      section = bfd_com_section_ptr;
      asym->value = ldsym->size;
      /* For ELF targets, set alignment of common symbol to 1.  */
      if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
	{
	  ((elf_symbol_type *) asym)->internal_elf_sym.st_shndx = SHN_COMMON;
	  ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1;
	}
      break;

    default:
      return LDPS_ERR;
    }
  asym->flags = flags;
  asym->section = section;

  /* Visibility only applies on ELF targets.  */
  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
    {
      elf_symbol_type *elfsym = elf_symbol_from (abfd, asym);
      unsigned char visibility;

      if (!elfsym)
	einfo (_("%P%F: %s: non-ELF symbol in ELF BFD!\n"), asym->name);
      switch (ldsym->visibility)
	{
	default:
	  einfo (_("%P%F: unknown ELF symbol visibility: %d!\n"),
		 ldsym->visibility);
	case LDPV_DEFAULT:
	  visibility = STV_DEFAULT;
	  break;
	case LDPV_PROTECTED:
	  visibility = STV_PROTECTED;
	  break;
	case LDPV_INTERNAL:
	  visibility = STV_INTERNAL;
	  break;
	case LDPV_HIDDEN:
	  visibility = STV_HIDDEN;
	  break;
	}
      elfsym->internal_elf_sym.st_other
	= (visibility | (elfsym->internal_elf_sym.st_other
			 & ~ELF_ST_VISIBILITY (-1)));
    }

  return LDPS_OK;
}
Beispiel #7
0
sec_ptr
bfd_make_section_anyway (bfd *abfd, const char *name)
{
  return bfd_make_section_anyway_with_flags (abfd, name, 0);
}
Beispiel #8
0
static void
gcore_command (char *args, int from_tty)
{
  struct cleanup *old_chain;
  char *corefilename, corefilename_buffer[40];
  asection *note_sec = NULL;
  bfd *obfd;
  void *note_data = NULL;
  int note_size = 0;

  /* No use generating a corefile without a target process.  */
  if (!target_has_execution)
    noprocess ();

  if (args && *args)
    corefilename = args;
  else
    {
      /* Default corefile name is "core.PID".  */
      sprintf (corefilename_buffer, "core.%d", PIDGET (inferior_ptid));
      corefilename = corefilename_buffer;
    }

  if (info_verbose)
    fprintf_filtered (gdb_stdout,
		      "Opening corefile '%s' for output.\n", corefilename);

  /* Open the output file.  */
  obfd = bfd_openw (corefilename, default_gcore_target ());
  if (!obfd)
    error (_("Failed to open '%s' for output."), corefilename);

  /* Need a cleanup that will close the file (FIXME: delete it?).  */
  old_chain = make_cleanup_bfd_close (obfd);

  bfd_set_format (obfd, bfd_core);
  bfd_set_arch_mach (obfd, default_gcore_arch (), default_gcore_mach ());

  /* An external target method must build the notes section.  */
  note_data = target_make_corefile_notes (obfd, &note_size);

  /* Create the note section.  */
  if (note_data != NULL && note_size != 0)
    {
      note_sec = bfd_make_section_anyway_with_flags (obfd, "note0",
						     SEC_HAS_CONTENTS
						     | SEC_READONLY
						     | SEC_ALLOC);
      if (note_sec == NULL)
	error (_("Failed to create 'note' section for corefile: %s"),
	       bfd_errmsg (bfd_get_error ()));

      bfd_set_section_vma (obfd, note_sec, 0);
      bfd_set_section_alignment (obfd, note_sec, 0);
      bfd_set_section_size (obfd, note_sec, note_size);
    }

  /* Now create the memory/load sections.  */
  if (gcore_memory_sections (obfd) == 0)
    error (_("gcore: failed to get corefile memory sections from target."));

  /* Write out the contents of the note section.  */
  if (note_data != NULL && note_size != 0)
    {
      if (!bfd_set_section_contents (obfd, note_sec, note_data, 0, note_size))
	warning (_("writing note section (%s)"), bfd_errmsg (bfd_get_error ()));
    }

  /* Succeeded.  */
  fprintf_filtered (gdb_stdout, "Saved corefile %s\n", corefilename);

  /* Clean-ups will close the output file and free malloc memory.  */
  do_cleanups (old_chain);
  return;
}
Beispiel #9
0
void replace_hello(const char *input_path, const char *output_path)
{
    bfd_init();

    bfd *ibfd = bfd_openr(input_path, NULL);

    if (ibfd == NULL)
        errx(1, bfd_errmsg(bfd_get_error()));

    if (!bfd_check_format(ibfd, bfd_object)) {
        bfd_close_all_done(ibfd);
        errx(1, "Input file is not a valid object file.");
    }

    bfd *obfd = bfd_openw(output_path, bfd_get_target(ibfd));

    if (obfd == NULL) {
        bfd_close_all_done(ibfd);
        errx(1, bfd_errmsg(bfd_get_error()));
    }

    if (!bfd_set_format(obfd, bfd_get_format(ibfd))) {
        bfd_close_all_done(ibfd);
        bfd_close_all_done(obfd);
        errx(1, "Setting obfd format failed: %s\n", bfd_errmsg(bfd_get_error()));
    }

    bfd_set_arch_info(obfd, bfd_get_arch_info(ibfd));

    // Create sections for .data
    asection *section = bfd_get_section_by_name(ibfd, ".data");
    while (section != NULL) {
        if (section->flags & SEC_HAS_CONTENTS) {
            char *section_contents = (char *)malloc(section->size);
            bfd_get_section_contents(ibfd, section, section_contents, 0, section->size);

            char *hello_pos = (char *)memmem(section_contents, section->size, "hello", 5);
            if (hello_pos != NULL) {
                if (bfd_make_section_anyway_with_flags(obfd, ".data", section->flags) == NULL) {
                    free(section_contents);
                    bfd_close_all_done(ibfd);
                    bfd_close_all_done(obfd);
                    errx(1, bfd_errmsg(bfd_get_error()));
                }
            }

            free(section_contents);
        }

        section = bfd_get_next_section_by_name(ibfd, section);
    }

    asection *comment_section = bfd_make_section_anyway_with_flags(obfd, ".comment.my_objcopy", SEC_HAS_CONTENTS);
    if (comment_section == NULL) {
        bfd_close_all_done(ibfd);
        bfd_close_all_done(obfd);
        errx(1, bfd_errmsg(bfd_get_error()));
    }

    if (!bfd_set_section_size(obfd, comment_section, 3)) {
        bfd_close_all_done(ibfd);
        bfd_close_all_done(obfd);
        errx(1, bfd_errmsg(bfd_get_error()));
    }

    if (!bfd_set_section_contents(obfd, comment_section, "moo", 0, 3)) {
        bfd_close_all_done(ibfd);
        bfd_close_all_done(obfd);
        errx(1, bfd_errmsg(bfd_get_error()));
    }

    // section = bfd_get_section_by_name(ibfd, ".data");
    // asection *osection = bfd_get_section_by_name(obfd, ".data");
    // if (osection == NULL) {
    // 	bfd_close_all_done(ibfd);
    // 	bfd_close_all_done(obfd);
    // 	errx(1, bfd_errmsg(bfd_get_error()));
    // }
    // while (section != NULL) {
    // 	if (section->flags & SEC_HAS_CONTENTS) {
    // 		char *section_contents = (char *)malloc(section->size);
    // 		bfd_get_section_contents(ibfd, section, section_contents, 0, section->size);
    //
    // 		char *hello_pos = (char *)memmem(section_contents, section->size, "hello", 5);
    // 		if (hello_pos != NULL) {
    // 			hello_pos[1] = 'o';
    // 			hello_pos[4] = 'a';
    // 			if (bfd_set_section_contents(obfd, osection, section_contents, 0, section->size)) {
    // 				free(section_contents);
    // 				bfd_close_all_done(ibfd);
    // 				bfd_close_all_done(obfd);
    // 				errx(1, bfd_errmsg(bfd_get_error()));
    // 			}
    // 		}
    //
    // 		free(section_contents);
    // 		osection = bfd_get_next_section_by_name(obfd, osection);
    // 	}
    //
    // 	section = bfd_get_next_section_by_name(ibfd, section);
    // }

    if (!bfd_close(obfd))
        errx(1, "Closing obfd failed: %s\n", bfd_errmsg(bfd_get_error()));

    if (!bfd_close(ibfd))
        errx(1, "Closing ibfd failed: %s\n", bfd_errmsg(bfd_get_error()));
}
Beispiel #10
0
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;
}
Beispiel #11
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;
}
bfd_boolean
_bfd_link_section_stabs (bfd *abfd,
			 struct stab_info *sinfo,
			 asection *stabsec,
			 asection *stabstrsec,
			 void * *psecinfo,
			 bfd_size_type *pstring_offset)
{
  bfd_boolean first;
  bfd_size_type count, amt;
  struct stab_section_info *secinfo;
  bfd_byte *stabbuf = NULL;
  bfd_byte *stabstrbuf = NULL;
  bfd_byte *sym, *symend;
  bfd_size_type stroff, next_stroff, skip;
  bfd_size_type *pstridx;

  if (stabsec->size == 0
      || stabstrsec->size == 0)
    /* This file does not contain stabs debugging information.  */
    return TRUE;

  if (stabsec->size % STABSIZE != 0)
    /* Something is wrong with the format of these stab symbols.
       Don't try to optimize them.  */
    return TRUE;

  if ((stabstrsec->flags & SEC_RELOC) != 0)
    /* We shouldn't see relocations in the strings, and we aren't
       prepared to handle them.  */
    return TRUE;

  if (bfd_is_abs_section (stabsec->output_section)
      || bfd_is_abs_section (stabstrsec->output_section))
    /* At least one of the sections is being discarded from the
       link, so we should just ignore them.  */
    return TRUE;

  first = FALSE;

  if (sinfo->stabstr == NULL)
    {
      flagword flags;

      /* Initialize the stabs information we need to keep track of.  */
      first = TRUE;
      sinfo->strings = _bfd_stringtab_init ();
      if (sinfo->strings == NULL)
	goto error_return;
      /* Make sure the first byte is zero.  */
      (void) _bfd_stringtab_add (sinfo->strings, "", TRUE, TRUE);
      if (! bfd_hash_table_init (&sinfo->includes,
				 stab_link_includes_newfunc,
				 sizeof (struct stab_link_includes_entry)))
	goto error_return;
      flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING
	       | SEC_LINKER_CREATED);
      sinfo->stabstr = bfd_make_section_anyway_with_flags (abfd, ".stabstr",
							   flags);
      if (sinfo->stabstr == NULL)
	goto error_return;
    }

  /* Initialize the information we are going to store for this .stab
     section.  */
  count = stabsec->size / STABSIZE;

  amt = sizeof (struct stab_section_info);
  amt += (count - 1) * sizeof (bfd_size_type);
  *psecinfo = bfd_alloc (abfd, amt);
  if (*psecinfo == NULL)
    goto error_return;

  secinfo = (struct stab_section_info *) *psecinfo;
  secinfo->excls = NULL;
  stabsec->rawsize = stabsec->size;
  secinfo->cumulative_skips = NULL;
  memset (secinfo->stridxs, 0, (size_t) count * sizeof (bfd_size_type));

  /* Read the stabs information from abfd.  */
  if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf)
      || !bfd_malloc_and_get_section (abfd, stabstrsec, &stabstrbuf))
    goto error_return;

  /* Look through the stabs symbols, work out the new string indices,
     and identify N_BINCL symbols which can be eliminated.  */
  stroff = 0;
  /* The stabs sections can be split when
     -split-by-reloc/-split-by-file is used.  We must keep track of
     each stab section's place in the single concatenated string
     table.  */
  next_stroff = pstring_offset ? *pstring_offset : 0;
  skip = 0;

  symend = stabbuf + stabsec->size;
  for (sym = stabbuf, pstridx = secinfo->stridxs;
       sym < symend;
       sym += STABSIZE, ++pstridx)
    {
      bfd_size_type symstroff;
      int type;
      const char *string;

      if (*pstridx != 0)
	/* This symbol has already been handled by an N_BINCL pass.  */
	continue;

      type = sym[TYPEOFF];

      if (type == 0)
	{
	  /* Special type 0 stabs indicate the offset to the next
	     string table.  We only copy the very first one.  */
	  stroff = next_stroff;
	  next_stroff += bfd_get_32 (abfd, sym + 8);
	  if (pstring_offset)
	    *pstring_offset = next_stroff;
	  if (! first)
	    {
	      *pstridx = (bfd_size_type) -1;
	      ++skip;
	      continue;
	    }
	  first = FALSE;
	}

      /* Store the string in the hash table, and record the index.  */
      symstroff = stroff + bfd_get_32 (abfd, sym + STRDXOFF);
      if (symstroff >= stabstrsec->size)
	{
	  _bfd_error_handler
	    /* xgettext:c-format */
	    (_("%B(%A+0x%lx): Stabs entry has invalid string index."),
	     abfd, stabsec, (long) (sym - stabbuf));
	  bfd_set_error (bfd_error_bad_value);
	  goto error_return;
	}
      string = (char *) stabstrbuf + symstroff;
      *pstridx = _bfd_stringtab_add (sinfo->strings, string, TRUE, TRUE);

      /* An N_BINCL symbol indicates the start of the stabs entries
	 for a header file.  We need to scan ahead to the next N_EINCL
	 symbol, ignoring nesting, adding up all the characters in the
	 symbol names, not including the file numbers in types (the
	 first number after an open parenthesis).  */
      if (type == (int) N_BINCL)
	{
	  bfd_vma sum_chars;
	  bfd_vma num_chars;
	  bfd_vma buf_len = 0;
	  char * symb;
	  char * symb_rover;
	  int nest;
	  bfd_byte * incl_sym;
	  struct stab_link_includes_entry * incl_entry;
	  struct stab_link_includes_totals * t;
	  struct stab_excl_list * ne;

	  symb = symb_rover = NULL;
	  sum_chars = num_chars = 0;
	  nest = 0;

	  for (incl_sym = sym + STABSIZE;
	       incl_sym < symend;
	       incl_sym += STABSIZE)
	    {
	      int incl_type;

	      incl_type = incl_sym[TYPEOFF];
	      if (incl_type == 0)
		break;
	      else if (incl_type == (int) N_EXCL)
		continue;
	      else if (incl_type == (int) N_EINCL)
		{
		  if (nest == 0)
		    break;
		  --nest;
		}
	      else if (incl_type == (int) N_BINCL)
		++nest;
	      else if (nest == 0)
		{
		  const char *str;

		  str = ((char *) stabstrbuf
			 + stroff
			 + bfd_get_32 (abfd, incl_sym + STRDXOFF));
		  for (; *str != '\0'; str++)
		    {
		      if (num_chars >= buf_len)
			{
			  buf_len += 32 * 1024;
			  symb = (char *) bfd_realloc_or_free (symb, buf_len);
			  if (symb == NULL)
			    goto error_return;
			  symb_rover = symb + num_chars;
			}
		      * symb_rover ++ = * str;
		      sum_chars += *str;
		      num_chars ++;
		      if (*str == '(')
			{
			  /* Skip the file number.  */
			  ++str;
			  while (ISDIGIT (*str))
			    ++str;
			  --str;
			}
		    }
		}
	    }

	  BFD_ASSERT (num_chars == (bfd_vma) (symb_rover - symb));

	  /* If we have already included a header file with the same
	     value, then replaced this one with an N_EXCL symbol.  */
	  incl_entry = (struct stab_link_includes_entry * )
	    bfd_hash_lookup (&sinfo->includes, string, TRUE, TRUE);
	  if (incl_entry == NULL)
	    goto error_return;

	  for (t = incl_entry->totals; t != NULL; t = t->next)
	    if (t->sum_chars == sum_chars
		&& t->num_chars == num_chars
		&& memcmp (t->symb, symb, num_chars) == 0)
	      break;

	  /* Record this symbol, so that we can set the value
	     correctly.  */
	  amt = sizeof *ne;
	  ne = (struct stab_excl_list *) bfd_alloc (abfd, amt);
	  if (ne == NULL)
	    goto error_return;
	  ne->offset = sym - stabbuf;
	  ne->val = sum_chars;
	  ne->type = (int) N_BINCL;
	  ne->next = secinfo->excls;
	  secinfo->excls = ne;

	  if (t == NULL)
	    {
	      /* This is the first time we have seen this header file
		 with this set of stabs strings.  */
	      t = (struct stab_link_includes_totals *)
                  bfd_hash_allocate (&sinfo->includes, sizeof *t);
	      if (t == NULL)
		goto error_return;
	      t->sum_chars = sum_chars;
	      t->num_chars = num_chars;
              /* Trim data down.  */
	      t->symb = symb = (char *) bfd_realloc_or_free (symb, num_chars);
	      t->next = incl_entry->totals;
	      incl_entry->totals = t;
	    }
	  else
	    {
	      bfd_size_type *incl_pstridx;

	      /* We have seen this header file before.  Tell the final
		 pass to change the type to N_EXCL.  */
	      ne->type = (int) N_EXCL;

	      /* Free off superfluous symbols.  */
	      free (symb);

	      /* Mark the skipped symbols.  */

	      nest = 0;
	      for (incl_sym = sym + STABSIZE, incl_pstridx = pstridx + 1;
		   incl_sym < symend;
		   incl_sym += STABSIZE, ++incl_pstridx)
		{
		  int incl_type;

		  incl_type = incl_sym[TYPEOFF];

		  if (incl_type == (int) N_EINCL)
		    {
		      if (nest == 0)
			{
			  *incl_pstridx = (bfd_size_type) -1;
			  ++skip;
			  break;
			}
		      --nest;
		    }
		  else if (incl_type == (int) N_BINCL)
		    ++nest;
		  else if (incl_type == (int) N_EXCL)
		    /* Keep existing exclusion marks.  */
		    continue;
		  else if (nest == 0)
		    {
		      *incl_pstridx = (bfd_size_type) -1;
		      ++skip;
		    }
		}
	    }
	}
    }

  free (stabbuf);
  stabbuf = NULL;
  free (stabstrbuf);
  stabstrbuf = NULL;

  /* We need to set the section sizes such that the linker will
     compute the output section sizes correctly.  We set the .stab
     size to not include the entries we don't want.  We set
     SEC_EXCLUDE for the .stabstr section, so that it will be dropped
     from the link.  We record the size of the strtab in the first
     .stabstr section we saw, and make sure we don't set SEC_EXCLUDE
     for that section.  */
  stabsec->size = (count - skip) * STABSIZE;
  if (stabsec->size == 0)
    stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
  stabstrsec->flags |= SEC_EXCLUDE | SEC_KEEP;
  sinfo->stabstr->size = _bfd_stringtab_size (sinfo->strings);

  /* Calculate the `cumulative_skips' array now that stabs have been
     deleted for this section.  */

  if (skip != 0)
    {
      bfd_size_type i, offset;
      bfd_size_type *pskips;

      amt = count * sizeof (bfd_size_type);
      secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt);
      if (secinfo->cumulative_skips == NULL)
	goto error_return;

      pskips = secinfo->cumulative_skips;
      pstridx = secinfo->stridxs;
      offset = 0;

      for (i = 0; i < count; i++, pskips++, pstridx++)
	{
	  *pskips = offset;
	  if (*pstridx == (bfd_size_type) -1)
	    offset += STABSIZE;
	}

      BFD_ASSERT (offset != 0);
    }

  return TRUE;

 error_return:
  if (stabbuf != NULL)
    free (stabbuf);
  if (stabstrbuf != NULL)
    free (stabstrbuf);
  return FALSE;
}
Beispiel #13
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;
}
Beispiel #14
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;
}