main (int argc, char **argv) {
    bfd *ibfd, *obfd;
    asection *p;
    static asymbol **osympp, **delsympp;
    long symsize, symcount, delsymcount;
    int i;
    int c;
    int idx;
    struct add_reloc_struct *new_reloc;
    struct change_reloc_struct *new_change;
    struct delete_reloc_struct *new_delete;
    struct modify_byte_struct *new_modify;
    struct globalize_sym_struct *new_globalize;

    while ((c = getopt (argc, argv, "a:d:c:m:G:")) != -1) {
	switch (c) {
	    case 'a':
		/* check to see if we have two args: name and loc */
		if ((index(optarg, ',') == NULL) ||
		    (index(optarg, ',') != rindex(optarg, ','))) {
		    fprintf(stderr, "usage: -a argument should be <symbolname>,<location>, not \"%s\"\n", optarg);
		    exit(1);
		}
		/* record the add reloc command in the global array */
		new_reloc = (add_reloc_struct *)malloc(sizeof(add_reloc_struct));
		new_reloc->symbol_name = strndup(optarg, (index(optarg, ',') - optarg));
		new_reloc->loc = strtol(index(optarg, ',') + 1, NULL, 0);
		if (errno == EINVAL) {
		    fprintf(stderr, "the value %s is not a valid location for the add command\n", index(optarg, ',') + 1);
		    exit(1);
		}
		new_reloc->next = additional_relocs;
		additional_relocs = new_reloc;
		break;

	    case 'c':
		/* check to see if we have two args */
		if ((index(optarg, ',') == NULL) ||
		    (index(optarg, ',') != rindex(optarg, ','))) {
		    fprintf(stderr, "usage: -c argument should be <symbolname>,<symbolname>, not \"%s\"\n", optarg);
		    exit(1);
		}
		new_change = (change_reloc_struct *)malloc(sizeof(change_reloc_struct));
		new_change->old_symbol_name = strndup(optarg, strlen(optarg) - strlen(index(optarg, ',')));
		new_change->new_symbol_name = strdup(index(optarg, ',') + 1);
		new_change->next = change_relocs;
		change_relocs = new_change;
		break;

	    case 'd':
		new_delete = (delete_reloc_struct *)malloc(sizeof(delete_reloc_struct));
		new_delete->symbol_name = strdup(optarg);
		new_delete->next = delete_relocs;
		delete_relocs = new_delete;
		break;

	    case 'm':
		if ((index(optarg, '=') == NULL) ||
		    (index(optarg, '=') != rindex(optarg, '='))) {
		    fprintf(stderr, "usage: -m argument should be <location>=<value>, not \"%s\"\n", optarg);
		    exit(1);
		}
		new_modify = (modify_byte_struct *)malloc(sizeof(modify_byte_struct));
		new_modify->location = strtol(optarg, NULL, 0);
		new_modify->value = strtol(index(optarg, '=') + 1, NULL, 0);
		if (new_modify->value > 0xff) {
		    fprintf(stderr, "requested modify value %lx for location %lx exceeds 0xff\n",
			    new_modify->value, new_modify->location);
		    exit(1);
		}
		new_modify->next = modify_bytes;
		modify_bytes = new_modify;
		break;

	    case 'G':
		new_globalize = (globalize_sym_struct *)malloc(sizeof(globalize_sym_struct));
		new_globalize->symbol_name = strdup(optarg);
		new_globalize->next = globalize_syms;
		globalize_syms = new_globalize;
		break;

	    default:
		fprintf(stderr, "unrecognized argument character |%c|\n", c);
	}
    }

    if ((argc - optind) != 2) {
	fprintf(stderr, "usage: fixup_relocs [-a newsymbol,location] [-c oldsymbol,newsymbol] [-d symbol] infile.o outfile.o\n");
	exit(1);
    }

    ibfd = bfd_openr(argv[optind], NULL);
    if (ibfd == NULL) {
	bfd_perror("while opening input object file");
	exit(1);
    }

    /* if I don't do "check_format", there's no data in the bfd object.  wtf? */
    if (!bfd_check_format(ibfd, bfd_object)) {
	fprintf(stderr, "input file %s seems to NOT be an object file! exiting.\n", argv[optind]);
	exit(1);
    }

    obfd = bfd_openw(argv[optind+1], bfd_get_target(ibfd));
    if (obfd == NULL) {
	bfd_perror("while opening output object file");
	exit(1);
    }

    if (!bfd_set_format(obfd, bfd_get_format(ibfd))) {
	bfd_perror("while setting output object file format");
    }

    /* copy a bunch of necessary global stuff */
    bfd_set_start_address(obfd, bfd_get_start_address(ibfd));
    bfd_set_file_flags(obfd, bfd_get_file_flags(ibfd));
    bfd_set_arch_mach(obfd, bfd_get_arch(ibfd), bfd_get_mach(ibfd));
    /* BOZO objcopy sets format again at this point.  why? */

    bfd_map_over_sections (ibfd, setup_section, obfd);

    setup_bfd_headers (ibfd, obfd);

    /* Symbol filtering must happen after the output sections
       have been created, but before their contents are set.  */
    symsize = bfd_get_symtab_upper_bound (ibfd);
    if (symsize < 0) {
	fprintf(stderr, "problem processing %s\n", bfd_get_filename (ibfd));
	return FALSE;
    }

    /* count the added relocations so we can put extra space in the output symbol table for them */
    int reloc_add_cnt, reloc_delete_cnt;
    reloc_add_cnt = 0;
    reloc_delete_cnt = 0;
    for (new_reloc = additional_relocs; new_reloc != NULL; new_reloc = new_reloc->next) {
	reloc_add_cnt++;
    }
    /* the "change" symbols might also not be in the symbol table yet */
    for (new_change = change_relocs; new_change != NULL; new_change = new_change->next) {
	reloc_add_cnt++;
	/* the old symbol may be deleted, also */
	reloc_delete_cnt++;
    }
    for (new_delete = delete_relocs; new_delete != NULL; new_delete = new_delete->next) {
	reloc_delete_cnt++;
    }

    /* filter symbol table in two steps: */
    /* 1) move symbols bound for deletion to the end of the output symbol table array */
    /* 2) truncate the table at the first of those */
    /* this makes it possible to do the reloc processing with the symbol table intact, */
    /* and remove the deleted symbols afterwards, without corrupting the reloc data structures */
    isympp = malloc (symsize);
    osympp = malloc (symsize + reloc_add_cnt * sizeof(asymbol *));
    delsympp = malloc (reloc_delete_cnt * sizeof(asymbol *));
    symcount = bfd_canonicalize_symtab (ibfd, isympp);

    if (symcount < 0) {
	fprintf(stderr, "problem processing %s\n", bfd_get_filename (ibfd));
	return FALSE;
    }

    /* remove any undefined symbols whose relocation entries were deleted or changed */
    int osym_idx, delsym_idx;
    osym_idx = delsym_idx = 0;
    delsymcount = 0;
    for (i = 0; i < symcount; i++) {
	if ((is_delete_reloc(bfd_asymbol_name(isympp[i]), delete_relocs) ||
	     (find_change_reloc(bfd_asymbol_name(isympp[i]), change_relocs) != NULL)) &&
	    (isympp[i]->section != NULL) &&
	    (strcmp(isympp[i]->section->name, BFD_UND_SECTION_NAME) == 0)) {
	    delsympp[delsym_idx++] = isympp[i];
	}
	else {
	    if (is_globalize_sym(bfd_asymbol_name(isympp[i]), globalize_syms)) {
		isympp[i]->flags = BSF_GLOBAL;
	    }
	    osympp[osym_idx++] = isympp[i];
	}
    }
    symcount = osym_idx;
    delsymcount = delsym_idx;
    osympp[symcount] = NULL;

    /* add the symbols for additional relocs to the table */
    int added_symbol_cnt = 0;
    for (new_reloc = additional_relocs; new_reloc != NULL; new_reloc = new_reloc->next) {
	if (find_symbol(osympp, new_reloc->symbol_name) < 0) {
	    /* not yet present, so add it */
	    asymbol *new_sym;
	    new_sym = bfd_make_empty_symbol(obfd);
	    new_sym->name = strdup(new_reloc->symbol_name);
	    new_sym->section = bfd_get_section_by_name (obfd, ".text");
	    new_sym->value = new_reloc->loc;
	    new_sym->flags = BSF_GLOBAL;
	    osympp[symcount + added_symbol_cnt++] = new_sym;
	    osympp[symcount + added_symbol_cnt] = NULL;
	}
    }

    /* do the same for changed relocs */
    for (new_change = change_relocs; new_change != NULL; new_change = new_change->next) {
	if (find_symbol(osympp, new_change->new_symbol_name) < 0) {
	    /* not yet present, so add it */
	    /* since this is a name change, we will reuse the existing address (value field of reloc) */
	    int old_symbol_idx;
	    if ((old_symbol_idx = find_symbol(isympp, new_change->old_symbol_name)) < 0) {
		fprintf(stderr, "change command old symbol name %s not found in symbol table! Exiting.\n", new_change->old_symbol_name);
		exit(1);
	    }
	    asymbol *new_sym;
	    new_sym = bfd_make_empty_symbol(obfd);
	    new_sym->name = strdup(new_change->new_symbol_name);
	    new_sym->section = bfd_und_section_ptr;
	    new_sym->value = isympp[old_symbol_idx]->value;
	    new_sym->flags = BSF_GLOBAL;
	    fprintf(stderr, "adding new symbol %s for change reloc command\n", new_sym->name);
	    osympp[symcount + added_symbol_cnt++] = new_sym;
	    osympp[symcount + added_symbol_cnt] = NULL;
	}
    }

    /* append the soon-to-be deleted symbols to the end of the output symbol table */
    for (i = 0; i < delsymcount; i++) {
	osympp[symcount + added_symbol_cnt + i] = delsympp[i];
    }
    osympp[symcount + added_symbol_cnt + delsymcount] = NULL;

    bfd_set_symtab (obfd, osympp, symcount + added_symbol_cnt + delsymcount);

    /* This has to happen after the symbol table has been set.  */
    bfd_map_over_sections (ibfd, copy_section_relocs_edit, obfd);

    /* now truncate the symbol table to eliminate the deleted symbols */
    osympp[symcount + added_symbol_cnt] = NULL;

    bfd_set_symtab (obfd, osympp, symcount + added_symbol_cnt);
    
    /* now that we've set the relocs and cleaned the symtab, can call this */
    bfd_map_over_sections (ibfd, copy_section_data, obfd);

    bfd_close(obfd);
    bfd_close(ibfd);

    return 0;

}
Пример #2
0
static void
get_core_register_section (struct regcache *regcache,
			   const char *name,
			   int which,
			   const char *human_name,
			   int required)
{
  static char *section_name = NULL;
  struct bfd_section *section;
  bfd_size_type size;
  char *contents;

  xfree (section_name);

  if (ptid_get_lwp (inferior_ptid))
    section_name = xstrprintf ("%s/%ld", name,
			       ptid_get_lwp (inferior_ptid));
  else
    section_name = xstrdup (name);

  section = bfd_get_section_by_name (core_bfd, section_name);
  if (! section)
    {
      if (required)
	warning (_("Couldn't find %s registers in core file."),
		 human_name);
      return;
    }

  size = bfd_section_size (core_bfd, section);
  contents = alloca (size);
  if (! bfd_get_section_contents (core_bfd, section, contents,
				  (file_ptr) 0, size))
    {
      warning (_("Couldn't read %s registers from `%s' section in core file."),
	       human_name, name);
      return;
    }

  if (core_gdbarch && gdbarch_regset_from_core_section_p (core_gdbarch))
    {
      const struct regset *regset;

      regset = gdbarch_regset_from_core_section (core_gdbarch,
						 name, size);
      if (regset == NULL)
	{
	  if (required)
	    warning (_("Couldn't recognize %s registers in core file."),
		     human_name);
	  return;
	}

      regset->supply_regset (regset, regcache, -1, contents, size);
      return;
    }

  gdb_assert (core_vec);
  core_vec->core_read_registers (regcache, contents, size, which,
				 ((CORE_ADDR)
				  bfd_section_vma (core_bfd, section)));
}
Пример #3
0
static void
gldelf64btsmip_before_allocation (void)
{
  const char *rpath;
  asection *sinterp;

  /* If we are going to make any variable assignments, we need to let
     the ELF backend know about them in case the variables are
     referred to by dynamic objects.  */
  lang_for_each_statement (gldelf64btsmip_find_statement_assignment);

  /* Let the ELF backend work out the sizes of any sections required
     by dynamic linking.  */
  rpath = command_line.rpath;
  if (rpath == NULL)
    rpath = (const char *) getenv ("LD_RUN_PATH");
  if ((rpath) && (strlen (rpath) == 0))
      rpath = NULL;
  if (! (bfd_elf64_size_dynamic_sections
	 (output_bfd, command_line.soname, rpath,
	  command_line.filter_shlib,
	  (const char * const *) command_line.auxiliary_filters,
	  &link_info, &sinterp, lang_elf_version_info)))
    einfo ("%P%F: failed to set dynamic section sizes: %E\n");

  /* Let the user override the dynamic linker we are using.  */
  if (command_line.interpreter != NULL
      && sinterp != NULL)
    {
      sinterp->contents = (bfd_byte *) command_line.interpreter;
      sinterp->_raw_size = strlen (command_line.interpreter) + 1;
    }

  /* Look for any sections named .gnu.warning.  As a GNU extensions,
     we treat such sections as containing warning messages.  We print
     out the warning message, and then zero out the section size so
     that it does not get copied into the output file.  */

  {
    LANG_FOR_EACH_INPUT_STATEMENT (is)
      {
	asection *s;
	bfd_size_type sz;
	bfd_size_type prefix_len;
	char *msg;
	bfd_boolean ret;
	const char * gnu_warning_prefix = _("warning: ");

	if (is->just_syms_flag)
	  continue;

	s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning");
	if (s == NULL)
	  continue;

	sz = bfd_section_size (is->the_bfd, s);
	prefix_len = strlen (gnu_warning_prefix);
	msg = xmalloc ((size_t) (prefix_len + sz + 1));
	strcpy (msg, gnu_warning_prefix);
	if (! bfd_get_section_contents (is->the_bfd, s,	msg + prefix_len,
					(file_ptr) 0, sz))
	  einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
		 is->the_bfd);
	msg[prefix_len + sz] = '\0';
	ret = link_info.callbacks->warning (&link_info, msg,
					    (const char *) NULL,
					    is->the_bfd, (asection *) NULL,
					    (bfd_vma) 0);
	ASSERT (ret);
	free (msg);

	/* Clobber the section size, so that we don't waste copying the
	   warning into the output file.  */
	s->_raw_size = 0;
      }
  }
}
Пример #4
0
static int
enable_break2 (void)
{
  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
  int success = 0;
  char **bkpt_namep;
  asection *interp_sect;

  if (enable_break2_done)
    return 1;

  interp_text_sect_low = interp_text_sect_high = 0;
  interp_plt_sect_low = interp_plt_sect_high = 0;

  /* Find the .interp section; if not found, warn the user and drop
     into the old breakpoint at symbol code.  */
  interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
  if (interp_sect)
    {
      unsigned int interp_sect_size;
      gdb_byte *buf;
      bfd *tmp_bfd = NULL;
      int status;
      CORE_ADDR addr, interp_loadmap_addr;
      gdb_byte addr_buf[FRV_PTR_SIZE];
      struct int_elf32_fdpic_loadmap *ldm;
      volatile struct gdb_exception ex;

      /* Read the contents of the .interp section into a local buffer;
         the contents specify the dynamic linker this program uses.  */
      interp_sect_size = bfd_section_size (exec_bfd, interp_sect);
      buf = alloca (interp_sect_size);
      bfd_get_section_contents (exec_bfd, interp_sect,
				buf, 0, interp_sect_size);

      /* Now we need to figure out where the dynamic linker was
         loaded so that we can load its symbols and place a breakpoint
         in the dynamic linker itself.

         This address is stored on the stack.  However, I've been unable
         to find any magic formula to find it for Solaris (appears to
         be trivial on GNU/Linux).  Therefore, we have to try an alternate
         mechanism to find the dynamic linker's base address.  */

      TRY_CATCH (ex, RETURN_MASK_ALL)
        {
          tmp_bfd = solib_bfd_open (buf);
        }
      if (tmp_bfd == NULL)
	{
	  enable_break_failure_warning ();
	  return 0;
	}

      status = frv_fdpic_loadmap_addresses (target_gdbarch,
                                            &interp_loadmap_addr, 0);
      if (status < 0)
	{
	  warning (_("Unable to determine dynamic linker loadmap address."));
	  enable_break_failure_warning ();
	  bfd_close (tmp_bfd);
	  return 0;
	}

      if (solib_frv_debug)
	fprintf_unfiltered (gdb_stdlog,
	                    "enable_break: interp_loadmap_addr = %s\n",
			    hex_string_custom (interp_loadmap_addr, 8));

      ldm = fetch_loadmap (interp_loadmap_addr);
      if (ldm == NULL)
	{
	  warning (_("Unable to load dynamic linker loadmap at address %s."),
	           hex_string_custom (interp_loadmap_addr, 8));
	  enable_break_failure_warning ();
	  bfd_close (tmp_bfd);
	  return 0;
	}

      /* Record the relocated start and end address of the dynamic linker
         text and plt section for svr4_in_dynsym_resolve_code.  */
      interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
      if (interp_sect)
	{
	  interp_text_sect_low
	    = bfd_section_vma (tmp_bfd, interp_sect);
	  interp_text_sect_low
	    += displacement_from_map (ldm, interp_text_sect_low);
	  interp_text_sect_high
	    = interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect);
	}
      interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
      if (interp_sect)
	{
	  interp_plt_sect_low =
	    bfd_section_vma (tmp_bfd, interp_sect);
	  interp_plt_sect_low
	    += displacement_from_map (ldm, interp_plt_sect_low);
	  interp_plt_sect_high =
	    interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect);
	}

      addr = bfd_lookup_symbol (tmp_bfd, "_dl_debug_addr");
      if (addr == 0)
	{
	  warning (_("Could not find symbol _dl_debug_addr in dynamic linker"));
	  enable_break_failure_warning ();
	  bfd_close (tmp_bfd);
	  return 0;
	}

      if (solib_frv_debug)
	fprintf_unfiltered (gdb_stdlog,
	                    "enable_break: _dl_debug_addr (prior to relocation) = %s\n",
			    hex_string_custom (addr, 8));

      addr += displacement_from_map (ldm, addr);

      if (solib_frv_debug)
	fprintf_unfiltered (gdb_stdlog,
	                    "enable_break: _dl_debug_addr (after relocation) = %s\n",
			    hex_string_custom (addr, 8));

      /* Fetch the address of the r_debug struct.  */
      if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0)
	{
	  warning (_("Unable to fetch contents of _dl_debug_addr (at address %s) from dynamic linker"),
	           hex_string_custom (addr, 8));
	}
      addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);

      if (solib_frv_debug)
	fprintf_unfiltered (gdb_stdlog,
	                    "enable_break: _dl_debug_addr[0..3] = %s\n",
	                    hex_string_custom (addr, 8));

      /* If it's zero, then the ldso hasn't initialized yet, and so
         there are no shared libs yet loaded.  */
      if (addr == 0)
	{
	  if (solib_frv_debug)
	    fprintf_unfiltered (gdb_stdlog,
	                        "enable_break: ldso not yet initialized\n");
	  /* Do not warn, but mark to run again.  */
	  return 0;
	}

      /* Fetch the r_brk field.  It's 8 bytes from the start of
         _dl_debug_addr.  */
      if (target_read_memory (addr + 8, addr_buf, sizeof addr_buf) != 0)
	{
	  warning (_("Unable to fetch _dl_debug_addr->r_brk (at address %s) from dynamic linker"),
	           hex_string_custom (addr + 8, 8));
	  enable_break_failure_warning ();
	  bfd_close (tmp_bfd);
	  return 0;
	}
      addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);

      /* Now fetch the function entry point.  */
      if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0)
	{
	  warning (_("Unable to fetch _dl_debug_addr->.r_brk entry point (at address %s) from dynamic linker"),
	           hex_string_custom (addr, 8));
	  enable_break_failure_warning ();
	  bfd_close (tmp_bfd);
	  return 0;
	}
      addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);

      /* We're done with the temporary bfd.  */
      bfd_close (tmp_bfd);

      /* We're also done with the loadmap.  */
      xfree (ldm);

      /* Remove all the solib event breakpoints.  Their addresses
         may have changed since the last time we ran the program.  */
      remove_solib_event_breakpoints ();

      /* Now (finally!) create the solib breakpoint.  */
      create_solib_event_breakpoint (target_gdbarch, addr);

      enable_break2_done = 1;

      return 1;
    }
Пример #5
0
static int
enable_break2 (void)
{
  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
  int success = 0;
  char **bkpt_namep;
  asection *interp_sect;
  struct dsbt_info *info = get_dsbt_info ();

  if (exec_bfd == NULL)
    return 0;

  if (!target_has_execution)
    return 0;

  if (info->enable_break2_done)
    return 1;

  info->interp_text_sect_low = 0;
  info->interp_text_sect_high = 0;
  info->interp_plt_sect_low = 0;
  info->interp_plt_sect_high = 0;

  /* Find the .interp section; if not found, warn the user and drop
     into the old breakpoint at symbol code.  */
  interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
  if (interp_sect)
    {
      unsigned int interp_sect_size;
      char *buf;
      bfd *tmp_bfd = NULL;
      CORE_ADDR addr;
      gdb_byte addr_buf[TIC6X_PTR_SIZE];
      struct int_elf32_dsbt_loadmap *ldm;
      volatile struct gdb_exception ex;

      /* Read the contents of the .interp section into a local buffer;
	 the contents specify the dynamic linker this program uses.  */
      interp_sect_size = bfd_section_size (exec_bfd, interp_sect);
      buf = alloca (interp_sect_size);
      bfd_get_section_contents (exec_bfd, interp_sect,
				buf, 0, interp_sect_size);

      /* Now we need to figure out where the dynamic linker was
	 loaded so that we can load its symbols and place a breakpoint
	 in the dynamic linker itself.  */

      TRY_CATCH (ex, RETURN_MASK_ALL)
	{
	  tmp_bfd = solib_bfd_open (buf);
	}
      if (tmp_bfd == NULL)
	{
	  enable_break_failure_warning ();
	  return 0;
	}

      dsbt_get_initial_loadmaps ();
      ldm = info->interp_loadmap;

      /* Record the relocated start and end address of the dynamic linker
	 text and plt section for dsbt_in_dynsym_resolve_code.  */
      interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
      if (interp_sect)
	{
	  info->interp_text_sect_low
	    = bfd_section_vma (tmp_bfd, interp_sect);
	  info->interp_text_sect_low
	    += displacement_from_map (ldm, info->interp_text_sect_low);
	  info->interp_text_sect_high
	    = info->interp_text_sect_low
	    + bfd_section_size (tmp_bfd, interp_sect);
	}
      interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
      if (interp_sect)
	{
	  info->interp_plt_sect_low =
	    bfd_section_vma (tmp_bfd, interp_sect);
	  info->interp_plt_sect_low
	    += displacement_from_map (ldm, info->interp_plt_sect_low);
	  info->interp_plt_sect_high =
	    info->interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect);
	}

      addr = gdb_bfd_lookup_symbol (tmp_bfd, cmp_name, "_dl_debug_addr");
      if (addr == 0)
	{
	  warning (_("Could not find symbol _dl_debug_addr in dynamic linker"));
	  enable_break_failure_warning ();
	  gdb_bfd_unref (tmp_bfd);
	  return 0;
	}

      if (solib_dsbt_debug)
	fprintf_unfiltered (gdb_stdlog,
			    "enable_break: _dl_debug_addr (prior to relocation) = %s\n",
			    hex_string_custom (addr, 8));

      addr += displacement_from_map (ldm, addr);

      if (solib_dsbt_debug)
	fprintf_unfiltered (gdb_stdlog,
			    "enable_break: _dl_debug_addr (after relocation) = %s\n",
			    hex_string_custom (addr, 8));

      /* Fetch the address of the r_debug struct.  */
      if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0)
	{
	  warning (_("Unable to fetch contents of _dl_debug_addr "
		     "(at address %s) from dynamic linker"),
		   hex_string_custom (addr, 8));
	}
      addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);

      if (solib_dsbt_debug)
	fprintf_unfiltered (gdb_stdlog,
			    "enable_break: _dl_debug_addr[0..3] = %s\n",
			    hex_string_custom (addr, 8));

      /* If it's zero, then the ldso hasn't initialized yet, and so
	 there are no shared libs yet loaded.  */
      if (addr == 0)
	{
	  if (solib_dsbt_debug)
	    fprintf_unfiltered (gdb_stdlog,
				"enable_break: ldso not yet initialized\n");
	  /* Do not warn, but mark to run again.  */
	  return 0;
	}

      /* Fetch the r_brk field.  It's 8 bytes from the start of
	 _dl_debug_addr.  */
      if (target_read_memory (addr + 8, addr_buf, sizeof addr_buf) != 0)
	{
	  warning (_("Unable to fetch _dl_debug_addr->r_brk "
		     "(at address %s) from dynamic linker"),
		   hex_string_custom (addr + 8, 8));
	  enable_break_failure_warning ();
	  gdb_bfd_unref (tmp_bfd);
	  return 0;
	}
      addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);

      /* We're done with the temporary bfd.  */
      gdb_bfd_unref (tmp_bfd);

      /* We're also done with the loadmap.  */
      xfree (ldm);

      /* Remove all the solib event breakpoints.  Their addresses
	 may have changed since the last time we ran the program.  */
      remove_solib_event_breakpoints ();

      /* Now (finally!) create the solib breakpoint.  */
      create_solib_event_breakpoint (target_gdbarch (), addr);

      info->enable_break2_done = 1;

      return 1;
    }
Пример #6
0
static bfd_boolean
pex64_bfd_print_pdata (bfd *abfd, void *vfile)
{
    FILE *file = (FILE *) vfile;
    bfd_byte *data = NULL;
    asection *section = bfd_get_section_by_name (abfd, ".pdata");
    bfd_size_type datasize = 0;
    bfd_size_type i;
    bfd_size_type start, stop;
    int onaline = PDATA_ROW_SIZE;

    if (section == NULL
            || coff_section_data (abfd, section) == NULL
            || pei_section_data (abfd, section) == NULL)
        return TRUE;

    stop = pei_section_data (abfd, section)->virt_size;
    if ((stop % onaline) != 0)
        fprintf (file,
                 _("warning: .pdata section size (%ld) is not a multiple of %d\n"),
                 (long) stop, onaline);

    fprintf (file,
             _("\nThe Function Table (interpreted .pdata section contents)\n"));

    fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t  UnwindData\n"));

    datasize = section->size;
    if (datasize == 0)
        return TRUE;

    if (!bfd_malloc_and_get_section (abfd, section, &data))
    {
        if (data != NULL)
            free (data);
        return FALSE;
    }

    start = 0;

    for (i = start; i < stop; i += onaline)
    {
        struct pex64_runtime_function rf;

        if (i + PDATA_ROW_SIZE > stop)
            break;
        pex64_get_runtime_function (abfd, &rf, &data[i]);

        if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
                && rf.rva_UnwindData == 0)
            /* We are probably into the padding of the section now.  */
            break;

        fputc (' ', file);
        fprintf_vma (file, i + section->vma);
        fprintf (file, ":\t");
        rf.rva_BeginAddress += pe_data (abfd)->pe_opthdr.ImageBase;
        fprintf_vma (file, rf.rva_BeginAddress);
        fputc (' ', file);
        rf.rva_EndAddress += pe_data (abfd)->pe_opthdr.ImageBase;
        fprintf_vma (file, rf.rva_EndAddress);
        fputc (' ', file);
        fprintf_vma (file, rf.rva_UnwindData);
        fprintf (file, "\n");

        if (rf.rva_UnwindData != 0)
        {
            if (rf.isChained)
            {
                fprintf (file, "\t shares information with pdata element at 0x");
                fprintf_vma (file, rf.rva_UnwindData + pe_data (abfd)->pe_opthdr.ImageBase);
                fprintf (file, ".\n");
            }
            else
                pex64_dump_xdata (file, abfd, rf.rva_UnwindData, rf.rva_BeginAddress);
        }
    }

    free (data);

    return TRUE;
}
/* Read in and initialize the SOM export list which is present
   for all executables and shared libraries.  The import list
   consists of the symbols that are referenced in OBJFILE but
   not defined there.  (Variables that are imported are dealt
   with as "loc_indirect" vars.)
   Return value = number of import symbols read in. */
int
init_export_symbols (struct objfile *objfile)
{
  unsigned int export_list;
  unsigned int export_list_size;
  unsigned int string_table;
  unsigned int string_table_size;
  char *string_buffer;
  int i;
  int j;
  int k;
  asection *text_section;	/* section handle */
  unsigned int dl_header[12];	/* SOM executable header */

  /* A struct for an entry in the SOM export list */
  typedef struct
    {
      int next;			/* for hash table use -- we don't use this */
      int name;			/* index into string table */
      int value;		/* offset or plabel */
      int dont_care1;		/* not used */
      unsigned char type;	/* 0 = NULL, 2 = Data, 3 = Code, 7 = Storage, 13 = Plabel */
      char dont_care2;		/* not used */
      short dont_care3;		/* not used */
    }
  SomExportEntry;

  /* We read 100 entries in at a time from the disk file. */
#define SOM_READ_EXPORTS_NUM         100
#define SOM_READ_EXPORTS_CHUNK_SIZE  (sizeof (SomExportEntry) * SOM_READ_EXPORTS_NUM)
  SomExportEntry buffer[SOM_READ_EXPORTS_NUM];

  /* Initialize in case we error out */
  objfile->export_list = NULL;
  objfile->export_list_size = 0;

  /* It doesn't work, for some reason, to read in space $TEXT$;
     the subspace $SHLIB_INFO$ has to be used.  Some BFD quirk? pai/1997-08-05 */
  text_section = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
  if (!text_section)
    return 0;
  /* Get the SOM executable header */
  bfd_get_section_contents (objfile->obfd, text_section, dl_header, 0, 12 * sizeof (int));

  /* Check header version number for 10.x HP-UX */
  /* Currently we deal only with 10.x systems; on 9.x the version # is 89060912.
     FIXME: Change for future HP-UX releases and mods to the SOM executable format */
  if (dl_header[0] != 93092112)
    return 0;

  export_list = dl_header[8];
  export_list_size = dl_header[9];
  if (!export_list_size)
    return 0;
  string_table = dl_header[10];
  string_table_size = dl_header[11];
  if (!string_table_size)
    return 0;

  /* Suck in SOM string table */
  string_buffer = (char *) xmalloc (string_table_size);
  bfd_get_section_contents (objfile->obfd, text_section, string_buffer,
			    string_table, string_table_size);

  /* Allocate export list in the psymbol obstack; this has nothing
     to do with psymbols, just a matter of convenience.  We want the
     export list to be freed when the objfile is deallocated */
  objfile->export_list
    = (ExportEntry *) obstack_alloc (&objfile->objfile_obstack,
				   export_list_size * sizeof (ExportEntry));

  /* Read in the export entries, a bunch at a time */
  for (j = 0, k = 0;
       j < (export_list_size / SOM_READ_EXPORTS_NUM);
       j++)
    {
      bfd_get_section_contents (objfile->obfd, text_section, buffer,
			      export_list + j * SOM_READ_EXPORTS_CHUNK_SIZE,
				SOM_READ_EXPORTS_CHUNK_SIZE);
      for (i = 0; i < SOM_READ_EXPORTS_NUM; i++, k++)
	{
	  if (buffer[i].type != (unsigned char) 0)
	    {
	      objfile->export_list[k].name
		= (char *) obstack_alloc (&objfile->objfile_obstack, strlen (string_buffer + buffer[i].name) + 1);
	      strcpy (objfile->export_list[k].name, string_buffer + buffer[i].name);
	      objfile->export_list[k].address = buffer[i].value;
	      /* Some day we might want to record the type and other information too */
	    }
	  else
	    /* null type */
	    {
	      objfile->export_list[k].name = NULL;
	      objfile->export_list[k].address = 0;
	    }
	}
    }

  /* Get the leftovers */
  if (k < export_list_size)
    bfd_get_section_contents (objfile->obfd, text_section, buffer,
			      export_list + k * sizeof (SomExportEntry),
			  (export_list_size - k) * sizeof (SomExportEntry));
  for (i = 0; k < export_list_size; i++, k++)
    {
      if (buffer[i].type != (unsigned char) 0)
	{
	  objfile->export_list[k].name
	    = (char *) obstack_alloc (&objfile->objfile_obstack, strlen (string_buffer + buffer[i].name) + 1);
	  strcpy (objfile->export_list[k].name, string_buffer + buffer[i].name);
	  /* Some day we might want to record the type and other information too */
	  objfile->export_list[k].address = buffer[i].value;
	}
      else
	{
	  objfile->export_list[k].name = NULL;
	  objfile->export_list[k].address = 0;
	}
    }

  objfile->export_list_size = export_list_size;
  xfree (string_buffer);
  return export_list_size;
}
Пример #8
0
char *symbol_lookup(struct kvm *kvm, unsigned long addr, char *sym, size_t size)
{
	const char *filename;
	bfd_vma sym_offset;
	bfd_vma sym_start;
	asection *section;
	unsigned int line;
	const char *func;
	long symtab_size;
	asymbol *symbol;
	asymbol **syms;
	int nr_syms, ret;

	ret = -ENOENT;
	if (!abfd)
		goto not_found;

	if (!bfd_check_format(abfd, bfd_object))
		goto not_found;

	symtab_size = bfd_get_symtab_upper_bound(abfd);
	if (!symtab_size)
		goto not_found;

	ret = -ENOMEM;
	syms = malloc(symtab_size);
	if (!syms)
		goto not_found;

	nr_syms = bfd_canonicalize_symtab(abfd, syms);

	ret = -ENOENT;
	section = bfd_get_section_by_name(abfd, ".debug_aranges");
	if (!section)
		goto not_found;

	if (!bfd_find_nearest_line(abfd, section, NULL, addr, &filename, &func, &line))
		goto not_found;

	if (!func)
		goto not_found;

	symbol = lookup(syms, nr_syms, func);
	if (IS_ERR(symbol))
		goto not_found;

	sym_start = bfd_asymbol_value(symbol);

	sym_offset = addr - sym_start;

	snprintf(sym, size, "%s+%llx (%s:%i)", func, (long long) sym_offset, filename, line);

	sym[size - 1] = '\0';

	free(syms);

	return sym;

not_found:
	return ERR_PTR(ret);
}
int main(int argc, char ** argv)
{
  bfd *fd;
  asection *sec;
  file_ptr offset;
  long st_size;
  asymbol ** symbol_table;
  long sym_count, i;

  if (argc != 2) {
    fprintf(stderr, "Usage: objinfo_helper <dynamic library>\n");
    return 2;
  }

  fd = bfd_openr(argv[1], "default");
  if (!fd) {
    fprintf(stderr, "Error opening file %s\n", argv[1]);
    return 2;
  }
  if (! bfd_check_format (fd, bfd_object)) {
    fprintf(stderr, "Error: wrong format\n");
    bfd_close(fd);
    return 2;
  }

  sec = bfd_get_section_by_name(fd, ".data");
  if (! sec) {
    fprintf(stderr, "Error: section .data not found\n");
    bfd_close(fd);
    return 2;
  }

  offset = sec->filepos;
  st_size = bfd_get_dynamic_symtab_upper_bound (fd);
  if (st_size <= 0) {
    fprintf(stderr, "Error: size of section .data unknown\n");
    bfd_close(fd);
    return 2;
  }

  symbol_table = malloc(st_size);
  if (! symbol_table) {
    fprintf(stderr, "Error: out of memory\n");
    bfd_close(fd);
    return 2;
  }

  sym_count = bfd_canonicalize_dynamic_symtab (fd, symbol_table);

  for (i = 0; i < sym_count; i++) {
    if (strcmp(symbol_table[i]->name, "caml_plugin_header") == 0) {
      printf("%ld\n", (long) (offset + symbol_table[i]->value));
      bfd_close(fd);
      return 0;
    }
  }

  fprintf(stderr, "Error: missing symbol caml_plugin_header\n");
  bfd_close(fd);
  return 2;
}
Пример #10
0
void
xcoff_relocate_core (struct target_ops *target)
{
  struct bfd_section *ldinfo_sec;
  int offset = 0;
  LdInfo *ldi;
  struct vmap *vp;
  int arch64 = ARCH64 ();

  /* Size of a struct ld_info except for the variable-length filename. */
  int nonfilesz = (int)LDI_FILENAME ((LdInfo *)0, arch64);

  /* Allocated size of buffer.  */
  int buffer_size = nonfilesz;
  char *buffer = xmalloc (buffer_size);
  struct cleanup *old = make_cleanup (free_current_contents, &buffer);

  ldinfo_sec = bfd_get_section_by_name (core_bfd, ".ldinfo");
  if (ldinfo_sec == NULL)
    {
    bfd_err:
      fprintf_filtered (gdb_stderr, "Couldn't get ldinfo from core file: %s\n",
			bfd_errmsg (bfd_get_error ()));
      do_cleanups (old);
      return;
    }
  do
    {
      int i;
      int names_found = 0;

      /* Read in everything but the name.  */
      if (bfd_get_section_contents (core_bfd, ldinfo_sec, buffer,
				    offset, nonfilesz) == 0)
	goto bfd_err;

      /* Now the name.  */
      i = nonfilesz;
      do
	{
	  if (i == buffer_size)
	    {
	      buffer_size *= 2;
	      buffer = xrealloc (buffer, buffer_size);
	    }
	  if (bfd_get_section_contents (core_bfd, ldinfo_sec, &buffer[i],
					offset + i, 1) == 0)
	    goto bfd_err;
	  if (buffer[i++] == '\0')
	    ++names_found;
	}
      while (names_found < 2);

      ldi = (LdInfo *) buffer;

      /* Can't use a file descriptor from the core file; need to open it.  */
      if (arch64)
	ldi->l64.ldinfo_fd = -1;
      else
	ldi->l32.ldinfo_fd = -1;

      /* The first ldinfo is for the exec file, allocated elsewhere.  */
      if (offset == 0 && vmap != NULL)
	vp = vmap;
      else
	vp = add_vmap (ldi);

      /* Process next shared library upon error. */
      offset += LDI_NEXT (ldi, arch64);
      if (vp == NULL)
	continue;

      vmap_secs (vp, ldi, arch64);

      /* Unless this is the exec file,
         add our sections to the section table for the core target.  */
      if (vp != vmap)
	{
	  struct section_table *stp;

	  target_resize_to_sections (target, 2);
	  stp = target->to_sections_end - 2;

	  stp->bfd = vp->bfd;
	  stp->the_bfd_section = bfd_get_section_by_name (stp->bfd, ".text");
	  stp->addr = vp->tstart;
	  stp->endaddr = vp->tend;
	  stp++;

	  stp->bfd = vp->bfd;
	  stp->the_bfd_section = bfd_get_section_by_name (stp->bfd, ".data");
	  stp->addr = vp->dstart;
	  stp->endaddr = vp->dend;
	}

      vmap_symtab (vp);

      if (deprecated_target_new_objfile_hook && vp != vmap && vp->objfile)
	deprecated_target_new_objfile_hook (vp->objfile);
    }
  while (LDI_NEXT (ldi, arch64) != 0);
  vmap_exec ();
  breakpoint_re_set ();
  do_cleanups (old);
}
Пример #11
0
bool show_exe_function(void *addr, struct string *str)
{
	bool ret;
	const char *function_name;
	bfd_vma symbol_offset;
	bfd_vma symbol_start;
	const char *filename;
	asection *sections;
	unsigned int line;
	asymbol **symbols;
	asymbol *symbol;
	int nr_symbols;
	bfd *abfd;
	int size;

	symbols = NULL;

	bfd_init();

	abfd = bfd_openr("/proc/self/exe", NULL);
	if (!abfd)
		goto failed;

	if (!bfd_check_format(abfd, bfd_object))
		goto failed;

	size = bfd_get_symtab_upper_bound(abfd);
	if (!size)
		goto failed;

	symbols = malloc(size);
	if (!symbols)
		goto failed;

	nr_symbols = bfd_canonicalize_symtab(abfd, symbols);

	sections = bfd_get_section_by_name(abfd, ".debug_info");
	if (!sections)
		goto failed;

	if (!bfd_find_nearest_line
	    (abfd, sections, symbols, (unsigned long) addr, &filename,
	     &function_name, &line))
		goto failed;

	if (!function_name)
		goto failed;

	symbol = lookup_symbol(symbols, nr_symbols, function_name);
	if (!symbol)
		goto failed;

	symbol_start = bfd_asymbol_value(symbol);
	symbol_offset = (unsigned long) addr - symbol_start;

	str_append(str, "%s+%llx (%s:%i)\n",
		   function_name, (long long) symbol_offset, filename, line);
	ret = true;

out:
	free(symbols);

	if (abfd)
		bfd_close(abfd);
	return ret;

failed:
	/*
	 * If above steps failed then try to obtain the symbol description with
	 * backtrace_symbols().
	 */
	ret = show_backtrace_function(addr, str);
	goto out;
}
Пример #12
0
int main(int argc, char *argv[])
{
        bfd *tmp_bfd = NULL;
	bfd_byte *p;
        uint32_t *call;
        uint32_t *rcv;
        uint32_t *snd;
        uint8_t rcvCount;
        uint8_t sndCount;
        uint32_t *scan;
        MessageMap msgs;

	if (argc < 2) {
		printf("Specify filename\n");
		exit(1);
	}
        tmp_bfd = bfd_openr (argv[1], NULL);
        if (tmp_bfd == NULL) {
                printf ("Error openning file");
                exit(1);
        }
        //check if the file is in format
        if (!bfd_check_format (tmp_bfd, bfd_object)) {
                if (bfd_get_error () != bfd_error_file_ambiguously_recognized) {
                        printf("Incompatible format\n");
                        exit(1);
                }
        }

	secText.sec = bfd_get_section_by_name(tmp_bfd, ".text");
	bfd_malloc_and_get_section(tmp_bfd, secText.sec, &secText.data);

	secRdata.sec = bfd_get_section_by_name(tmp_bfd, ".rdata");
        if (!secRdata.sec) {
                printf("Failed to get section\n");
                exit(10);
        }
	if (!bfd_malloc_and_get_section(tmp_bfd, secRdata.sec, &secRdata.data)) {
                printf("Alloc error\n");
                exit(10);
        }


	secData.sec = bfd_get_section_by_name(tmp_bfd, ".data");
        if (!secData.sec) {
                printf("Failed to get section\n");
                exit(10);
        }
	if (!bfd_malloc_and_get_section(tmp_bfd, secData.sec, &secData.data)) {
                printf("Alloc error\n");
                exit(10);
        }
		

/*
  406060:       68 40 6f 0e 01          push   $0x10e6f40
  406065:       6a 06                   push   $0x6
  406067:       68 38 6f 0e 01          push   $0x10e6f38
  40606c:       6a 02                   push   $0x2
  40606e:       33 d2                   xor    %edx,%edx
  406070:       33 c9                   xor    %ecx,%ecx
  406072:       e8 e9 16 5e 00          call   0x9e7760
*/
	for(p= secText.data; p < secText.data+bfd_section_size(tmp_bfd, secText.sec); p++) {

		if ( p< secText.data+bfd_section_size(tmp_bfd, secText.sec)-22 &&
                     isMsgRegister(p, &rcv, &rcvCount, &snd, &sndCount, &call)
                        )
                {
                        uint8_t i;

                        bfd_vma dest;

                        scan= NULL;
                        if (rcvCount) {
                                if (inSection(&secRdata, (bfd_vma)rcv))
                                        rcv= (uint32_t *)f2v(&secRdata, (uint32_t)rcv);
                                else
                                        rcv= (uint32_t *)f2v(&secData, (uint32_t)rcv);
                                scan= rcv;
                        }
                        if (sndCount) {
                                if (inSection(&secRdata, (bfd_vma)snd))
                                        snd= (uint32_t *)f2v(&secRdata, (uint32_t)snd);
                                else
                                        snd= (uint32_t *)f2v(&secData, (uint32_t)snd);
                                scan= snd;
                        }

                        char *text= NULL;
                        char *clitext= NULL;
                        if (scan) {
                                for(uint32_t *cp = scan-0x200; cp < scan; cp++) {
                                        char *p;
                                        if ((p=strstr((char *)cp, ".cpp")) == NULL)
                                                continue;

                                        while(*p != '\\')
                                                p--;

                                        text= &p[1];
					if (strstr(text, "Cli"))
						clitext= text;
                                }
                                if (!text) {
                                        printf("Name missing\n");
                                        exit(1);
                                }

                        }
#if 0
			if (clitext)
				text= clitext;
#endif

                        if (rcvCount) {
                                rcvCount *= 2;

                                for(i=0; i< rcvCount; i++) {

                                        if ( !(i%2) &&
                                             !inSection(&secData, rcv[i]) &&
                                             !inSection(&secRdata, rcv[i])) {
                                                //printf("Not in (r)data section\n");
                                                goto next;
                                        }

                                        if ( (i%2) &&
                                             !inSection(&secText, rcv[i])) {
                                                //printf("Not in text section 0x%p\n", rcv[i]);
                                                goto next;
                                        }

                                }
                                for(i=0; i< rcvCount; i+=2) {

                                        struct netField *nf= (struct netField *)
                                                f2v(&secData, rcv[i]);

                                        msgs.insert( MessageEntry(call, Message(text,nf, true) ));
                                }
                        }

                        if (sndCount) {
                                for(i=0; i< sndCount; i++) {
                                        if ( !inSection(&secData, snd[i]))
                                                goto next;

                                }
                                for(i=0; i< sndCount; i++) {
                                        struct netField *nf= (struct netField *)
                                                f2v(&secData, snd[i]);

                                        msgs.insert( MessageEntry(call, Message(text,nf, false) ));
                                }
                        }


		}
        next:;
	}

        std::cout << "#ifndef PACKETS_H\n"
                  << "#define PACKETS_H\n"
                  << "#include \"netfield.hpp\"\n"
                  << std::endl;

        for(MessageMap::iterator m = msgs.begin();
            m != msgs.end();
            ++m) {
                Message msg = m->second;

                msg.display();
        }

        // Server Messages
        uint32_t *oldcall= NULL;
        for(MessageMap::iterator m = msgs.begin();
            m != msgs.end();
            ++m) {
                uint32_t *call = m->first;
                Message msg = m->second;

                if (!msg.isServer)
                        continue;

                if (oldcall != call) {
                        if (oldcall)
                                std::cout << "\tNULL"
                                        << "};\n\n";
                        std::cout << "struct netFieldI *serverMsgPack_"
                                  << msg.getBasicName() << "[] = {" << std::endl;
                        oldcall = call;
                }
                std::cout << "\t" << msg.getName() << "," << std::endl;
        }
        std::cout << "\tNULL\n"
                  <<"};\n\n" << std::endl;

        // Client Messages
        oldcall= NULL;
        for(MessageMap::iterator m = msgs.begin();
            m != msgs.end();
            ++m) {
                uint32_t *call = m->first;
                Message msg = m->second;

                if (msg.isServer)
                        continue;

                if (oldcall != call) {
                        if (oldcall)
                                std::cout << "\tNULL"
                                        << "};\n\n";
                        std::cout << "struct netFieldI *clientMsgPack_"
                                  << msg.getBasicName() << "[] = {" << std::endl;
                        oldcall = call;
                }
                std::cout << "\t" << msg.getName() << "," << std::endl;
        }
        std::cout << "\tNULL\n"
                  <<"};\n\n"
                  << "#endif" << std::endl;

        return 0;
}
Пример #13
0
int
dicos_load_module_p (bfd *abfd, int header_size)
{
  long storage_needed;
  int ret = 0;
  asymbol **symbol_table = NULL;
  const char *symname = "Dicos_loadModuleInfo";
  asection *section;

  /* DICOS files don't have a .note.ABI-tag marker or something
     similar.  We do know there's always a "header" section of
     HEADER_SIZE bytes (size depends on architecture), and there's
     always a "Dicos_loadModuleInfo" symbol defined.  Look for the
     section first, as that should be cheaper.  */

  section = bfd_get_section_by_name (abfd, "header");
  if (!section)
    return 0;

  if (bfd_section_size (abfd, section) != header_size)
    return 0;

  /* Dicos LMs always have a "Dicos_loadModuleInfo" symbol
     defined.  Look for it.  */

  storage_needed = bfd_get_symtab_upper_bound (abfd);
  if (storage_needed < 0)
    {
      warning (_("Can't read elf symbols from %s: %s"),
	       bfd_get_filename (abfd),
	       bfd_errmsg (bfd_get_error ()));
      return 0;
    }

  if (storage_needed > 0)
    {
      long i, symcount;

      symbol_table = xmalloc (storage_needed);
      symcount = bfd_canonicalize_symtab (abfd, symbol_table);

      if (symcount < 0)
	warning (_("Can't read elf symbols from %s: %s"),
		 bfd_get_filename (abfd),
		 bfd_errmsg (bfd_get_error ()));
      else
	{
	  for (i = 0; i < symcount; i++)
	    {
	      asymbol *sym = symbol_table[i];
	      if (sym->name != NULL
		  && symname[0] == sym->name[0]
		  && strcmp (symname + 1, sym->name + 1) == 0)
		{
		  ret = 1;
		  break;
		}
	    }
	}
    }

  xfree (symbol_table);
  return ret;
}
Пример #14
0
    void resolve(const address_type&   addr,
                 const char *   binfile,
                 const char **  source_file_name,
                 const char **  func_name,
                 unsigned int * line_number)
    {
        if (!binfile || !*binfile) {
            return;
        }

        *source_file_name = nullptr;
        *line_number      = 0;
        *func_name        = nullptr;

        boost::mutex::scoped_lock lock(_lib_mutex);

        _init();
        if (!_init_called)
        {
            return;
        }

        sym_map_type::iterator itBfd = _syms.find(binfile);
        if (itBfd == _syms.end()) {
            sym_tab_type fbfd;

            fbfd.base = _compute_maps_base(binfile);

            //FIXME: char *find_separate_debug_file (bfd *abfd);
            fbfd.abfd.reset(bfd_openr(binfile, 0), bfd_close_wrapper());
            if (!fbfd.abfd) {
                return;
            }
#ifdef BFD_DECOMPRESS // Old libbfd?
            fbfd.abfd->flags |= BFD_DECOMPRESS;
#endif

            // Required
            bfd_check_format(fbfd.abfd.get(), bfd_object);

            fbfd.text = bfd_get_section_by_name(fbfd.abfd.get(), ".text");

            fbfd.storage_needed = bfd_get_symtab_upper_bound(fbfd.abfd.get());
            if (0 == fbfd.storage_needed) {
                fbfd.dynamic = true;
                fbfd.storage_needed = bfd_get_dynamic_symtab_upper_bound(fbfd.abfd.get());
            }

            fbfd.syms.reset(static_cast<asymbol**>(::malloc(fbfd.storage_needed)),
                            free_wrapper<asymbol*>());

            if (fbfd.dynamic) {
                fbfd.cSymbols = bfd_canonicalize_dynamic_symtab(fbfd.abfd.get(), fbfd.syms.get());
            }
            else {
                fbfd.cSymbols = bfd_canonicalize_symtab(fbfd.abfd.get(), fbfd.syms.get());
            }
            BOOST_ASSERT(fbfd.cSymbols >= 0);

            _syms[binfile] = fbfd;
            itBfd = _syms.find(binfile);
        }

        if (itBfd != _syms.end()) {
            const sym_tab_type &stab = itBfd->second;

            bfd_vma vma = bfd_get_section_vma(stab.abfd.get(), stab.text);

            long offset = ((long)addr) - stab.base - vma; //stab.text->vma;
            if (offset > 0) {
                if ( !bfd_find_nearest_line(stab.abfd.get(),
                                            stab.text,
                                            stab.syms.get(),
                                            offset,
                                            source_file_name,
                                            func_name,
                                            line_number)
                    ) {
                    //std::cerr << "libbfd: could not find " << std::hex << addr;
                    *source_file_name = nullptr;
                    *line_number      = 0;
                    *func_name        = nullptr;
                }
                //trace it
            }
        }
    }
Пример #15
0
static bfd_boolean
read_section_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount,
				   void *dhandle, bfd_boolean *pfound)
{
  static struct
    {
      const char *secname;
      const char *strsecname;
    }
  names[] =
    {
      { ".stab", ".stabstr" },
      { "LC_SYMTAB.stabs", "LC_SYMTAB.stabstr" },
      { "$GDB_SYMBOLS$", "$GDB_STRINGS$" }
    };
  unsigned int i;
  void *shandle;

  *pfound = FALSE;
  shandle = NULL;

  for (i = 0; i < sizeof names / sizeof names[0]; i++)
    {
      asection *sec, *strsec;

      sec = bfd_get_section_by_name (abfd, names[i].secname);
      strsec = bfd_get_section_by_name (abfd, names[i].strsecname);
      if (sec != NULL && strsec != NULL)
	{
	  bfd_size_type stabsize, strsize;
	  bfd_byte *stabs, *strings;
	  bfd_byte *stab;
	  bfd_size_type stroff, next_stroff;

	  stabsize = bfd_section_size (abfd, sec);
	  stabs = (bfd_byte *) xmalloc (stabsize);
	  if (! bfd_get_section_contents (abfd, sec, stabs, 0, stabsize))
	    {
	      fprintf (stderr, "%s: %s: %s\n",
		       bfd_get_filename (abfd), names[i].secname,
		       bfd_errmsg (bfd_get_error ()));
	      return FALSE;
	    }

	  strsize = bfd_section_size (abfd, strsec);
	  strings = (bfd_byte *) xmalloc (strsize);
	  if (! bfd_get_section_contents (abfd, strsec, strings, 0, strsize))
	    {
	      fprintf (stderr, "%s: %s: %s\n",
		       bfd_get_filename (abfd), names[i].strsecname,
		       bfd_errmsg (bfd_get_error ()));
	      return FALSE;
	    }

	  if (shandle == NULL)
	    {
	      shandle = start_stab (dhandle, abfd, TRUE, syms, symcount);
	      if (shandle == NULL)
		return FALSE;
	    }

	  *pfound = TRUE;

	  stroff = 0;
	  next_stroff = 0;
	  for (stab = stabs; stab < stabs + stabsize; stab += 12)
	    {
	      unsigned int strx;
	      int type;
	      int other;
	      int desc;
	      bfd_vma value;

	      /* This code presumes 32 bit values.  */

	      strx = bfd_get_32 (abfd, stab);
	      type = bfd_get_8 (abfd, stab + 4);
	      other = bfd_get_8 (abfd, stab + 5);
	      desc = bfd_get_16 (abfd, stab + 6);
	      value = bfd_get_32 (abfd, stab + 8);

	      if (type == 0)
		{
		  /* Special type 0 stabs indicate the offset to the
		     next string table.  */
		  stroff = next_stroff;
		  next_stroff += value;
		}
	      else
		{
		  char *f, *s;

		  f = NULL;

		  if (stroff + strx > strsize)
		    {
		      fprintf (stderr, "%s: %s: stab entry %ld is corrupt, strx = 0x%x, type = %d\n",
			       bfd_get_filename (abfd), names[i].secname,
			       (long) (stab - stabs) / 12, strx, type);
		      continue;
		    }

		  s = (char *) strings + stroff + strx;

		  while (s[strlen (s) - 1] == '\\'
			 && stab + 12 < stabs + stabsize)
		    {
		      char *p;

		      stab += 12;
		      p = s + strlen (s) - 1;
		      *p = '\0';
		      s = concat (s,
				  ((char *) strings
				   + stroff
				   + bfd_get_32 (abfd, stab)),
				  (const char *) NULL);

		      /* We have to restore the backslash, because, if
			 the linker is hashing stabs strings, we may
			 see the same string more than once.  */
		      *p = '\\';

		      if (f != NULL)
			free (f);
		      f = s;
		    }

		  save_stab (type, desc, value, s);

		  if (! parse_stab (dhandle, shandle, type, desc, value, s))
		    {
		      stab_context ();
		      free_saved_stabs ();
		      return FALSE;
		    }

		  /* Don't free f, since I think the stabs code
		     expects strings to hang around.  This should be
		     straightened out.  FIXME.  */
		}
	    }

	  free_saved_stabs ();
	  free (stabs);

	  /* Don't free strings, since I think the stabs code expects
	     the strings to hang around.  This should be straightened
	     out.  FIXME.  */
	}
    }

  if (shandle != NULL)
    {
      if (! finish_stab (dhandle, shandle))
	return FALSE;
    }

  return TRUE;
}
/* 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;
}
Пример #17
0
void
core_init (const char * aout_name)
{
  int core_sym_bytes;
  asymbol *synthsyms;
  long synth_count;

  core_bfd = bfd_openr (aout_name, 0);

  if (!core_bfd)
    {
      perror (aout_name);
      done (1);
    }

  if (!bfd_check_format (core_bfd, bfd_object))
    {
      fprintf (stderr, _("%s: %s: not in executable format\n"), whoami, aout_name);
      done (1);
    }

  /* Get core's text section.  */
  core_text_sect = bfd_get_section_by_name (core_bfd, ".text");
  if (!core_text_sect)
    {
      core_text_sect = bfd_get_section_by_name (core_bfd, "$CODE$");
      if (!core_text_sect)
	{
	  fprintf (stderr, _("%s: can't find .text section in %s\n"),
		   whoami, aout_name);
	  done (1);
	}
    }

  /* Read core's symbol table.  */

  /* This will probably give us more than we need, but that's ok.  */
  core_sym_bytes = bfd_get_symtab_upper_bound (core_bfd);
  if (core_sym_bytes < 0)
    {
      fprintf (stderr, "%s: %s: %s\n", whoami, aout_name,
	       bfd_errmsg (bfd_get_error ()));
      done (1);
    }

  core_syms = (asymbol **) xmalloc (core_sym_bytes);
  core_num_syms = bfd_canonicalize_symtab (core_bfd, core_syms);

  if (core_num_syms < 0)
    {
      fprintf (stderr, "%s: %s: %s\n", whoami, aout_name,
	       bfd_errmsg (bfd_get_error ()));
      done (1);
    }

  synth_count = bfd_get_synthetic_symtab (core_bfd, core_num_syms, core_syms,
					  0, NULL, &synthsyms);
  if (synth_count > 0)
    {
      asymbol **symp;
      long new_size;
      long i;

      new_size = (core_num_syms + synth_count + 1) * sizeof (*core_syms);
      core_syms = (asymbol **) xrealloc (core_syms, new_size);
      symp = core_syms + core_num_syms;
      core_num_syms += synth_count;
      for (i = 0; i < synth_count; i++)
	*symp++ = synthsyms + i;
      *symp = 0;
    }

  min_insn_size = 1;
  offset_to_code = 0;

  switch (bfd_get_arch (core_bfd))
    {
    case bfd_arch_vax:
    case bfd_arch_tahoe:
      offset_to_code = 2;
      break;

    case bfd_arch_alpha:
      min_insn_size = 4;
      break;

    default:
      break;
    }

  if (function_mapping_file)
    read_function_mappings (function_mapping_file);
}
Пример #18
0
static void report_fault(int signo, siginfo_t* siginf, void* arg)
{
	(void)siginf;
	(void)arg;

	fprintf(stderr, "fault signal %d (%s)\n", signo, strsignal(signo));

#ifndef DISABLE_CLIENT
	int nptrs;
	int i;
	void *trace[48];
	char **strings;
	Dl_info info;
	char linkname[PATH_MAX];
	bfd* abfd = 0;
	asymbol **syms = 0;
	asection *text = 0;
	int l;

	l = readlink("/proc/self/exe", linkname, sizeof(linkname));
	if (l == -1) {
		perror("failed to find executable\n");
		return;
	}
	linkname[l] = 0;

	bfd_init();

	abfd = bfd_openr(linkname, 0);
	if (!abfd) {
		perror("bfd_openr failed: ");
		return;
	}

	/* oddly, this is required for it to work... */
	bfd_check_format(abfd,bfd_object);

	unsigned storage_needed = bfd_get_symtab_upper_bound(abfd);
	syms = (asymbol **) malloc(storage_needed);

	bfd_canonicalize_symtab(abfd, syms);

	text = bfd_get_section_by_name(abfd, ".text");

	nptrs = backtrace(trace, ARRAY_SIZE(trace));

	strings = backtrace_symbols(trace, nptrs);
	if (!strings) {
		perror("backtrace_symbols");
		_exit(EXIT_FAILURE);
	}

	for (i = 0; i < nptrs; ++i) {
		unsigned long offset;

		fprintf(stderr, "%d:%s", i, strings[i]);

		offset = ((long)trace[i]) - text->vma;

		if (offset < text->size) {
			const char *file;
			const char *func;
			unsigned line;

			if (bfd_find_nearest_line(abfd, text, syms, offset, &file, &func, &line) && file) {
				fprintf(stderr, ": %s()", func);
				if (*file)
					fprintf(stderr, ":%s@%u", file, line);
				goto skip;
			}
		}

		if (dladdr(trace[i], &info)) {
			if (info.dli_sname)
				fprintf(stderr, ": %s", info.dli_sname);
		}
skip:
		fprintf(stderr, "\n");
	}

	free(strings);
#endif

	fflush(stderr);

	_exit(EXIT_FAILURE);
}
Пример #19
0
void
dwarf2_finish (void)
{
  segT line_seg;
  struct line_seg *s;
  segT info_seg;
  int emit_other_sections = 0;

  info_seg = bfd_get_section_by_name (stdoutput, ".debug_info");
  emit_other_sections = info_seg == NULL || !seg_not_empty_p (info_seg);

  if (!all_segs && emit_other_sections)
    /* There is no line information and no non-empty .debug_info
       section.  */
    return;

  /* Calculate the size of an address for the target machine.  */
  sizeof_address = DWARF2_ADDR_SIZE (stdoutput);

  /* Create and switch to the line number section.  */
  line_seg = subseg_new (".debug_line", 0);
  bfd_set_section_flags (stdoutput, line_seg, SEC_READONLY | SEC_DEBUGGING);

  /* For each subsection, chain the debug entries together.  */
  for (s = all_segs; s; s = s->next)
    {
      struct line_subseg *ss = s->head;
      struct line_entry **ptail = ss->ptail;

      while ((ss = ss->next) != NULL)
	{
	  *ptail = ss->head;
	  ptail = ss->ptail;
	}
    }

  out_debug_line (line_seg);

  /* If this is assembler generated line info, and there is no
     debug_info already, we need .debug_info and .debug_abbrev
     sections as well.  */
  if (emit_other_sections)
    {
      segT abbrev_seg;
      segT aranges_seg;
      segT ranges_seg;

      assert (all_segs);
      
      info_seg = subseg_new (".debug_info", 0);
      abbrev_seg = subseg_new (".debug_abbrev", 0);
      aranges_seg = subseg_new (".debug_aranges", 0);

      bfd_set_section_flags (stdoutput, info_seg,
			     SEC_READONLY | SEC_DEBUGGING);
      bfd_set_section_flags (stdoutput, abbrev_seg,
			     SEC_READONLY | SEC_DEBUGGING);
      bfd_set_section_flags (stdoutput, aranges_seg,
			     SEC_READONLY | SEC_DEBUGGING);

      record_alignment (aranges_seg, ffs (2 * sizeof_address) - 1);

      if (all_segs->next == NULL)
	ranges_seg = NULL;
      else
	{
	  ranges_seg = subseg_new (".debug_ranges", 0);
	  bfd_set_section_flags (stdoutput, ranges_seg, 
				 SEC_READONLY | SEC_DEBUGGING);
	  record_alignment (ranges_seg, ffs (2 * sizeof_address) - 1);
	  out_debug_ranges (ranges_seg);
	}

      out_debug_aranges (aranges_seg, info_seg);
      out_debug_abbrev (abbrev_seg);
      out_debug_info (info_seg, abbrev_seg, line_seg, ranges_seg);
    }
}
Пример #20
0
static struct mdebug_extra_func_info *
non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr)
{
    CORE_ADDR startaddr;
    struct mdebug_extra_func_info *proc_desc;
    struct block *b = block_for_pc (pc);
    struct symbol *sym;
    struct obj_section *sec;
    struct mips_objfile_private *priv;

    find_pc_partial_function (pc, NULL, &startaddr, NULL);
    if (addrptr)
        *addrptr = startaddr;

    priv = NULL;

    sec = find_pc_section (pc);
    if (sec != NULL)
    {
        priv = (struct mips_objfile_private *) objfile_data (sec->objfile, mips_pdr_data);

        /* Search the ".pdr" section generated by GAS.  This includes most of
           the information normally found in ECOFF PDRs.  */

        the_bfd = sec->objfile->obfd;
        if (priv == NULL
                && (the_bfd->format == bfd_object
                    && bfd_get_flavour (the_bfd) == bfd_target_elf_flavour
                    && elf_elfheader (the_bfd)->e_ident[EI_CLASS] == ELFCLASS64))
        {
            /* Right now GAS only outputs the address as a four-byte sequence.
               This means that we should not bother with this method on 64-bit
               targets (until that is fixed).  */

            priv = obstack_alloc (&sec->objfile->objfile_obstack,
                                  sizeof (struct mips_objfile_private));
            priv->size = 0;
            set_objfile_data (sec->objfile, mips_pdr_data, priv);
        }
        else if (priv == NULL)
        {
            asection *bfdsec;

            priv = obstack_alloc (&sec->objfile->objfile_obstack,
                                  sizeof (struct mips_objfile_private));

            bfdsec = bfd_get_section_by_name (sec->objfile->obfd, ".pdr");
            if (bfdsec != NULL)
            {
                priv->size = bfd_section_size (sec->objfile->obfd, bfdsec);
                priv->contents = obstack_alloc (&sec->objfile->objfile_obstack,
                                                priv->size);
                bfd_get_section_contents (sec->objfile->obfd, bfdsec,
                                          priv->contents, 0, priv->size);

                /* In general, the .pdr section is sorted.  However, in the
                   presence of multiple code sections (and other corner cases)
                   it can become unsorted.  Sort it so that we can use a faster
                   binary search.  */
                qsort (priv->contents, priv->size / 32, 32,
                       compare_pdr_entries);
            }
            else
                priv->size = 0;

            set_objfile_data (sec->objfile, mips_pdr_data, priv);
        }
        the_bfd = NULL;

        if (priv->size != 0)
        {
            int low, mid, high;
            char *ptr;
            CORE_ADDR pdr_pc;

            low = 0;
            high = priv->size / 32;

            /* We've found a .pdr section describing this objfile.  We want to
               find the entry which describes this code address.  The .pdr
               information is not very descriptive; we have only a function
               start address.  We have to look for the closest entry, because
               the local symbol at the beginning of this function may have
               been stripped - so if we ask the symbol table for the start
               address we may get a preceding global function.  */

            /* First, find the last .pdr entry starting at or before PC.  */
            do
            {
                mid = (low + high) / 2;

                ptr = priv->contents + mid * 32;
                pdr_pc = bfd_get_signed_32 (sec->objfile->obfd, ptr);
                pdr_pc += ANOFFSET (sec->objfile->section_offsets,
                                    SECT_OFF_TEXT (sec->objfile));

                if (pdr_pc > pc)
                    high = mid;
                else
                    low = mid + 1;
            }
            while (low != high);

            /* Both low and high point one past the PDR of interest.  If
               both are zero, that means this PC is before any region
               covered by a PDR, i.e. pdr_pc for the first PDR entry is
               greater than PC.  */
            if (low > 0)
            {
                ptr = priv->contents + (low - 1) * 32;
                pdr_pc = bfd_get_signed_32 (sec->objfile->obfd, ptr);
                pdr_pc += ANOFFSET (sec->objfile->section_offsets,
                                    SECT_OFF_TEXT (sec->objfile));
            }

            /* We don't have a range, so we have no way to know for sure
               whether we're in the correct PDR or a PDR for a preceding
               function and the current function was a stripped local
               symbol.  But if the PDR's PC is at least as great as the
               best guess from the symbol table, assume that it does cover
               the right area; if a .pdr section is present at all then
               nearly every function will have an entry.  The biggest exception
               will be the dynamic linker stubs; conveniently these are
               placed before .text instead of after.  */

            if (pc >= pdr_pc && pdr_pc >= startaddr)
            {
                struct symbol *sym = find_pc_function (pc);

                if (addrptr)
                    *addrptr = pdr_pc;

                /* Fill in what we need of the proc_desc.  */
                proc_desc = (struct mdebug_extra_func_info *)
                            obstack_alloc (&sec->objfile->objfile_obstack,
                                           sizeof (struct mdebug_extra_func_info));
                PROC_LOW_ADDR (proc_desc) = pdr_pc;

                PROC_FRAME_OFFSET (proc_desc)
                    = bfd_get_signed_32 (sec->objfile->obfd, ptr + 20);
                PROC_FRAME_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd,
                                             ptr + 24);
                PROC_REG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd,
                                                        ptr + 4);
                PROC_FREG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd,
                                             ptr + 12);
                PROC_REG_OFFSET (proc_desc)
                    = bfd_get_signed_32 (sec->objfile->obfd, ptr + 8);
                PROC_FREG_OFFSET (proc_desc)
                    = bfd_get_signed_32 (sec->objfile->obfd, ptr + 16);
                PROC_PC_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd,
                                                      ptr + 28);
                proc_desc->pdr.isym = (long) sym;

                return proc_desc;
            }
        }
    }

    if (b == NULL)
        return NULL;

    if (startaddr > BLOCK_START (b))
    {
        /* This is the "pathological" case referred to in a comment in
           print_frame_info.  It might be better to move this check into
           symbol reading.  */
        return NULL;
    }

    sym = lookup_symbol (MDEBUG_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0);

    /* If we never found a PDR for this function in symbol reading, then
       examine prologues to find the information.  */
    if (sym)
    {
        proc_desc = (struct mdebug_extra_func_info *) SYMBOL_VALUE (sym);
        if (PROC_FRAME_REG (proc_desc) == -1)
            return NULL;
        else
            return proc_desc;
    }
    else
        return NULL;
}
Пример #21
0
void
dwarf2_finish (void)
{
  segT line_seg;
  struct line_seg *s;

  /* We don't need to do anything unless:
     - Some debug information was recorded via .file/.loc
     - or, we are generating DWARF2 information ourself (--gdwarf2)
     - or, there is a user-provided .debug_info section which could
       reference the file table in the .debug_line section we generate
       below.  */
  if (all_segs == NULL
      && debug_type != DEBUG_DWARF2
      && bfd_get_section_by_name (stdoutput, ".debug_info") == NULL)
    return;

  /* Calculate the size of an address for the target machine.  */
  sizeof_address = DWARF2_ADDR_SIZE (stdoutput);

  /* Create and switch to the line number section.  */
  line_seg = subseg_new (".debug_line", 0);
  bfd_set_section_flags (stdoutput, line_seg, SEC_READONLY);

  /* For each subsection, chain the debug entries together.  */
  for (s = all_segs; s; s = s->next)
    {
      struct line_subseg *ss = s->head;
      struct line_entry **ptail = ss->ptail;

      while ((ss = ss->next) != NULL)
	{
	  *ptail = ss->head;
	  ptail = ss->ptail;
	}
    }

  out_debug_line (line_seg);

  /* If this is assembler generated line info, we need .debug_info
     and .debug_abbrev sections as well.  */
  if (all_segs != NULL && debug_type == DEBUG_DWARF2)
    {
      segT abbrev_seg;
      segT info_seg;
      segT aranges_seg;

      info_seg = subseg_new (".debug_info", 0);
      abbrev_seg = subseg_new (".debug_abbrev", 0);
      aranges_seg = subseg_new (".debug_aranges", 0);

      bfd_set_section_flags (stdoutput, info_seg, SEC_READONLY);
      bfd_set_section_flags (stdoutput, abbrev_seg, SEC_READONLY);
      bfd_set_section_flags (stdoutput, aranges_seg, SEC_READONLY);

      record_alignment (aranges_seg, ffs (2 * sizeof_address) - 1);

      out_debug_aranges (aranges_seg, info_seg);
      out_debug_abbrev (abbrev_seg);
      out_debug_info (info_seg, abbrev_seg, line_seg);
    }
}
Пример #22
0
static int
enable_break (void)
{
  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
  asection *interp_sect;
  struct dsbt_info *info;

  if (exec_bfd == NULL)
    return 0;

  if (!target_has_execution)
    return 0;

  info = get_dsbt_info ();

  info->interp_text_sect_low = 0;
  info->interp_text_sect_high = 0;
  info->interp_plt_sect_low = 0;
  info->interp_plt_sect_high = 0;

  /* Find the .interp section; if not found, warn the user and drop
     into the old breakpoint at symbol code.  */
  interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
  if (interp_sect)
    {
      unsigned int interp_sect_size;
      char *buf;
      bfd *tmp_bfd = NULL;
      CORE_ADDR addr;
      gdb_byte addr_buf[TIC6X_PTR_SIZE];
      struct int_elf32_dsbt_loadmap *ldm;
      volatile struct gdb_exception ex;
      int ret;

      /* Read the contents of the .interp section into a local buffer;
	 the contents specify the dynamic linker this program uses.  */
      interp_sect_size = bfd_section_size (exec_bfd, interp_sect);
      buf = alloca (interp_sect_size);
      bfd_get_section_contents (exec_bfd, interp_sect,
				buf, 0, interp_sect_size);

      /* Now we need to figure out where the dynamic linker was
	 loaded so that we can load its symbols and place a breakpoint
	 in the dynamic linker itself.  */

      TRY_CATCH (ex, RETURN_MASK_ALL)
	{
	  tmp_bfd = solib_bfd_open (buf);
	}
      if (tmp_bfd == NULL)
	{
	  enable_break_failure_warning ();
	  return 0;
	}

      dsbt_get_initial_loadmaps ();
      ldm = info->interp_loadmap;

      /* Record the relocated start and end address of the dynamic linker
	 text and plt section for dsbt_in_dynsym_resolve_code.  */
      interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
      if (interp_sect)
	{
	  info->interp_text_sect_low
	    = bfd_section_vma (tmp_bfd, interp_sect);
	  info->interp_text_sect_low
	    += displacement_from_map (ldm, info->interp_text_sect_low);
	  info->interp_text_sect_high
	    = info->interp_text_sect_low
	    + bfd_section_size (tmp_bfd, interp_sect);
	}
      interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
      if (interp_sect)
	{
	  info->interp_plt_sect_low =
	    bfd_section_vma (tmp_bfd, interp_sect);
	  info->interp_plt_sect_low
	    += displacement_from_map (ldm, info->interp_plt_sect_low);
	  info->interp_plt_sect_high =
	    info->interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect);
	}

      addr = gdb_bfd_lookup_symbol (tmp_bfd, cmp_name, "_dl_debug_state");
      if (addr != 0)
	{
	  if (solib_dsbt_debug)
	    fprintf_unfiltered (gdb_stdlog,
				"enable_break: _dl_debug_state (prior to relocation) = %s\n",
				hex_string_custom (addr, 8));
	  addr += displacement_from_map (ldm, addr);

	  if (solib_dsbt_debug)
	    fprintf_unfiltered (gdb_stdlog,
				"enable_break: _dl_debug_state (after relocation) = %s\n",
				hex_string_custom (addr, 8));

	  /* Now (finally!) create the solib breakpoint.  */
	  create_solib_event_breakpoint (target_gdbarch (), addr);

	  ret = 1;
	}
      else
	{
	  if (solib_dsbt_debug)
	    fprintf_unfiltered (gdb_stdlog,
				"enable_break: _dl_debug_state is not found\n");
	  ret = 0;
	}

      /* We're done with the temporary bfd.  */
      gdb_bfd_unref (tmp_bfd);

      /* We're also done with the loadmap.  */
      xfree (ldm);

      return ret;
    }
Пример #23
0
static int
scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr)
{
  int arch_size, step, sect_size;
  long dyn_tag;
  CORE_ADDR dyn_ptr, dyn_addr;
  gdb_byte *bufend, *bufstart, *buf;
  Elf32_External_Dyn *x_dynp_32;
  Elf64_External_Dyn *x_dynp_64;
  struct bfd_section *sect;
  struct target_section *target_section;

  if (abfd == NULL)
    return 0;

  if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
    return 0;

  arch_size = bfd_get_arch_size (abfd);
  if (arch_size == -1)
    return 0;

  /* Find the start address of the .dynamic section.  */
  sect = bfd_get_section_by_name (abfd, ".dynamic");
  if (sect == NULL)
    return 0;

  for (target_section = current_target_sections->sections;
       target_section < current_target_sections->sections_end;
       target_section++)
    if (sect == target_section->the_bfd_section)
      break;
  if (target_section < current_target_sections->sections_end)
    dyn_addr = target_section->addr;
  else
    {
      /* ABFD may come from OBJFILE acting only as a symbol file without being
	 loaded into the target (see add_symbol_file_command).  This case is
	 such fallback to the file VMA address without the possibility of
	 having the section relocated to its actual in-memory address.  */

      dyn_addr = bfd_section_vma (abfd, sect);
    }

  /* Read in .dynamic from the BFD.  We will get the actual value
     from memory later.  */
  sect_size = bfd_section_size (abfd, sect);
  buf = bufstart = alloca (sect_size);
  if (!bfd_get_section_contents (abfd, sect,
				 buf, 0, sect_size))
    return 0;

  /* Iterate over BUF and scan for DYNTAG.  If found, set PTR and return.  */
  step = (arch_size == 32) ? sizeof (Elf32_External_Dyn)
			   : sizeof (Elf64_External_Dyn);
  for (bufend = buf + sect_size;
       buf < bufend;
       buf += step)
  {
    if (arch_size == 32)
      {
	x_dynp_32 = (Elf32_External_Dyn *) buf;
	dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_tag);
	dyn_ptr = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_un.d_ptr);
      }
    else
      {
	x_dynp_64 = (Elf64_External_Dyn *) buf;
	dyn_tag = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_tag);
	dyn_ptr = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_un.d_ptr);
      }
     if (dyn_tag == DT_NULL)
       return 0;
     if (dyn_tag == dyntag)
       {
	 /* If requested, try to read the runtime value of this .dynamic
	    entry.  */
	 if (ptr)
	   {
	     struct type *ptr_type;
	     gdb_byte ptr_buf[8];
	     CORE_ADDR ptr_addr;

	     ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
	     ptr_addr = dyn_addr + (buf - bufstart) + arch_size / 8;
	     if (target_read_memory (ptr_addr, ptr_buf, arch_size / 8) == 0)
	       dyn_ptr = extract_typed_address (ptr_buf, ptr_type);
	     *ptr = dyn_ptr;
	   }
	 return 1;
       }
  }

  return 0;
}
Пример #24
0
static bfd_boolean
parse_line_table (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
{
  bfd_byte *xptr;

  /* Load the ".line" section from the bfd if we haven't already.  */
  if (stash->line_section == 0)
    {
      asection *msec;
      bfd_size_type size;

      msec = bfd_get_section_by_name (stash->abfd, ".line");
      if (! msec)
	return FALSE;

      size = msec->rawsize ? msec->rawsize : msec->size;
      stash->line_section
	= bfd_simple_get_relocated_section_contents
	(stash->abfd, msec, NULL, stash->syms);

      if (! stash->line_section)
	return FALSE;

      stash->line_section_end = stash->line_section + size;
    }

  xptr = stash->line_section + aUnit->stmt_list_offset;
  if (xptr < stash->line_section_end)
    {
      unsigned long eachLine;
      bfd_byte *tblend;
      unsigned long base;
      bfd_size_type amt;

      /* First comes the length.  */
      tblend = bfd_get_32 (stash->abfd, (bfd_byte *) xptr) + xptr;
      xptr += 4;

      /* Then the base address for each address in the table.  */
      base = bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
      xptr += 4;

      /* How many line entrys?
	 10 = 4 (line number) + 2 (pos in line) + 4 (address in line).  */
      aUnit->line_count = (tblend - xptr) / 10;

      /* Allocate an array for the entries.  */
      amt = sizeof (struct linenumber) * aUnit->line_count;
      aUnit->linenumber_table = bfd_alloc (stash->abfd, amt);
      if (!aUnit->linenumber_table)
	return FALSE;

      for (eachLine = 0; eachLine < aUnit->line_count; eachLine++)
	{
	  /* A line number.  */
	  aUnit->linenumber_table[eachLine].linenumber
	    = bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
	  xptr += 4;

	  /* Skip the position within the line.  */
	  xptr += 2;

	  /* And finally the address.  */
	  aUnit->linenumber_table[eachLine].addr
	    = base + bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
	  xptr += 4;
	}
    }

  return TRUE;
}
Пример #25
0
static void
core_open (char *filename, int from_tty)
{
  const char *p;
  int siggy;
  struct cleanup *old_chain;
  char *temp;
  bfd *temp_bfd;
  int scratch_chan;
  int flags;
  volatile struct gdb_exception except;

  target_preopen (from_tty);
  if (!filename)
    {
      if (core_bfd)
	error (_("No core file specified.  (Use `detach' "
		 "to stop debugging a core file.)"));
      else
	error (_("No core file specified."));
    }

  filename = tilde_expand (filename);
  if (!IS_ABSOLUTE_PATH (filename))
    {
      temp = concat (current_directory, "/",
		     filename, (char *) NULL);
      xfree (filename);
      filename = temp;
    }

  old_chain = make_cleanup (xfree, filename);

  flags = O_BINARY | O_LARGEFILE;
  if (write_files)
    flags |= O_RDWR;
  else
    flags |= O_RDONLY;
  scratch_chan = open (filename, flags, 0);
  if (scratch_chan < 0)
    perror_with_name (filename);

  temp_bfd = gdb_bfd_fopen (filename, gnutarget, 
			    write_files ? FOPEN_RUB : FOPEN_RB,
			    scratch_chan);
  if (temp_bfd == NULL)
    perror_with_name (filename);

  if (!bfd_check_format (temp_bfd, bfd_core)
      && !gdb_check_format (temp_bfd))
    {
      /* Do it after the err msg */
      /* FIXME: should be checking for errors from bfd_close (for one
         thing, on error it does not free all the storage associated
         with the bfd).  */
      make_cleanup_bfd_unref (temp_bfd);
      error (_("\"%s\" is not a core dump: %s"),
	     filename, bfd_errmsg (bfd_get_error ()));
    }

  /* Looks semi-reasonable.  Toss the old core file and work on the
     new.  */

  do_cleanups (old_chain);
  unpush_target (&core_ops);
  core_bfd = temp_bfd;
  old_chain = make_cleanup (core_close_cleanup, 0 /*ignore*/);

  /* FIXME: kettenis/20031023: This is very dangerous.  The
     CORE_GDBARCH that results from this call may very well be
     different from CURRENT_GDBARCH.  However, its methods may only
     work if it is selected as the current architecture, because they
     rely on swapped data (see gdbarch.c).  We should get rid of that
     swapped data.  */
  core_gdbarch = gdbarch_from_bfd (core_bfd);

  /* Find a suitable core file handler to munch on core_bfd */
  core_vec = sniff_core_bfd (core_bfd);

  validate_files ();

  core_data = XZALLOC (struct target_section_table);

  /* Find the data section */
  if (build_section_table (core_bfd,
			   &core_data->sections,
			   &core_data->sections_end))
    error (_("\"%s\": Can't find sections: %s"),
	   bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ()));

  /* If we have no exec file, try to set the architecture from the
     core file.  We don't do this unconditionally since an exec file
     typically contains more information that helps us determine the
     architecture than a core file.  */
  if (!exec_bfd)
    set_gdbarch_from_file (core_bfd);

  push_target (&core_ops);
  discard_cleanups (old_chain);

  /* Do this before acknowledging the inferior, so if
     post_create_inferior throws (can happen easilly if you're loading
     a core file with the wrong exec), we aren't left with threads
     from the previous inferior.  */
  init_thread_list ();

  inferior_ptid = null_ptid;

  /* Need to flush the register cache (and the frame cache) from a
     previous debug session.  If inferior_ptid ends up the same as the
     last debug session --- e.g., b foo; run; gcore core1; step; gcore
     core2; core core1; core core2 --- then there's potential for
     get_current_regcache to return the cached regcache of the
     previous session, and the frame cache being stale.  */
  registers_changed ();

  /* Build up thread list from BFD sections, and possibly set the
     current thread to the .reg/NN section matching the .reg
     section.  */
  bfd_map_over_sections (core_bfd, add_to_thread_list,
			 bfd_get_section_by_name (core_bfd, ".reg"));

  if (ptid_equal (inferior_ptid, null_ptid))
    {
      /* Either we found no .reg/NN section, and hence we have a
	 non-threaded core (single-threaded, from gdb's perspective),
	 or for some reason add_to_thread_list couldn't determine
	 which was the "main" thread.  The latter case shouldn't
	 usually happen, but we're dealing with input here, which can
	 always be broken in different ways.  */
      struct thread_info *thread = first_thread_of_process (-1);

      if (thread == NULL)
	{
	  inferior_appeared (current_inferior (), CORELOW_PID);
	  inferior_ptid = pid_to_ptid (CORELOW_PID);
	  add_thread_silent (inferior_ptid);
	}
      else
	switch_to_thread (thread->ptid);
    }

  post_create_inferior (&core_ops, from_tty);

  /* Now go through the target stack looking for threads since there
     may be a thread_stratum target loaded on top of target core by
     now.  The layer above should claim threads found in the BFD
     sections.  */
  TRY_CATCH (except, RETURN_MASK_ERROR)
    {
      target_find_new_threads ();
    }

  if (except.reason < 0)
    exception_print (gdb_stderr, except);

  p = bfd_core_file_failing_command (core_bfd);
  if (p)
    printf_filtered (_("Core was generated by `%s'.\n"), p);

  siggy = bfd_core_file_failing_signal (core_bfd);
  if (siggy > 0)
    {
      /* If we don't have a CORE_GDBARCH to work with, assume a native
	 core (map gdb_signal from host signals).  If we do have
	 CORE_GDBARCH to work with, but no gdb_signal_from_target
	 implementation for that gdbarch, as a fallback measure,
	 assume the host signal mapping.  It'll be correct for native
	 cores, but most likely incorrect for cross-cores.  */
      enum gdb_signal sig = (core_gdbarch != NULL
			     && gdbarch_gdb_signal_from_target_p (core_gdbarch)
			     ? gdbarch_gdb_signal_from_target (core_gdbarch,
							       siggy)
			     : gdb_signal_from_host (siggy));

      printf_filtered (_("Program terminated with signal %d, %s.\n"),
		       siggy, gdb_signal_to_string (sig));
    }

  /* Fetch all registers from core file.  */
  target_fetch_registers (get_current_regcache (), -1);

  /* Now, set up the frame cache, and print the top of stack.  */
  reinit_frame_cache ();
  print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
}
Пример #26
0
bfd_boolean
_bfd_dwarf1_find_nearest_line (bfd *abfd,
			       asection *section,
			       asymbol **symbols,
			       bfd_vma offset,
			       const char **filename_ptr,
			       const char **functionname_ptr,
			       unsigned int *linenumber_ptr)
{
  struct dwarf1_debug *stash = elf_tdata (abfd)->dwarf1_find_line_info;

  struct dwarf1_unit* eachUnit;

  /* What address are we looking for? */
  unsigned long addr = (unsigned long)(offset + section->vma);

  *filename_ptr = NULL;
  *functionname_ptr = NULL;
  *linenumber_ptr = 0;

  if (! stash)
    {
      asection *msec;
      bfd_size_type size = sizeof (struct dwarf1_debug);

      stash = elf_tdata (abfd)->dwarf1_find_line_info
	= bfd_zalloc (abfd, size);

      if (! stash)
	return FALSE;

      msec = bfd_get_section_by_name (abfd, ".debug");
      if (! msec)
	/* No dwarf1 info.  Note that at this point the stash
	   has been allocated, but contains zeros, this lets
	   future calls to this function fail quicker.  */
	return FALSE;

      size = msec->rawsize ? msec->rawsize : msec->size;
      stash->debug_section
	= bfd_simple_get_relocated_section_contents (abfd, msec, NULL,
						     symbols);

      if (! stash->debug_section)
	return FALSE;

      stash->debug_section_end = stash->debug_section + size;
      stash->currentDie = stash->debug_section;
      stash->abfd = abfd;
      stash->syms = symbols;
    }

  /* A null debug_section indicates that there was no dwarf1 info
     or that an error occured while setting up the stash.  */

  if (! stash->debug_section)
    return FALSE;

  /* Look at the previously parsed units to see if any contain
     the addr.  */
  for (eachUnit = stash->lastUnit; eachUnit; eachUnit = eachUnit->prev)
    if (eachUnit->low_pc <= addr && addr < eachUnit->high_pc)
      return dwarf1_unit_find_nearest_line (stash, eachUnit, addr,
					    filename_ptr,
					    functionname_ptr,
					    linenumber_ptr);

  while (stash->currentDie < stash->debug_section_end)
    {
      struct die_info aDieInfo;

      if (! parse_die (stash->abfd, &aDieInfo, stash->currentDie,
		       stash->debug_section_end))
	return FALSE;

      if (aDieInfo.tag == TAG_compile_unit)
	{
	  struct dwarf1_unit* aUnit
	    = alloc_dwarf1_unit (stash);
	  if (!aUnit)
	    return FALSE;

	  aUnit->name = aDieInfo.name;
	  aUnit->low_pc = aDieInfo.low_pc;
	  aUnit->high_pc = aDieInfo.high_pc;
	  aUnit->has_stmt_list = aDieInfo.has_stmt_list;
	  aUnit->stmt_list_offset = aDieInfo.stmt_list_offset;

	  /* A die has a child if it's followed by a die that is
	     not it's sibling.  */
	  if (aDieInfo.sibling
	      && stash->currentDie + aDieInfo.length
                    < stash->debug_section_end
	      && stash->currentDie + aDieInfo.length
	            != stash->debug_section + aDieInfo.sibling)
	    aUnit->first_child = stash->currentDie + aDieInfo.length;
	  else
	    aUnit->first_child = 0;

	  if (aUnit->low_pc <= addr && addr < aUnit->high_pc)
	    return dwarf1_unit_find_nearest_line (stash, aUnit, addr,
						  filename_ptr,
						  functionname_ptr,
						  linenumber_ptr);
	}

      if (aDieInfo.sibling != 0)
	stash->currentDie = stash->debug_section + aDieInfo.sibling;
      else
	stash->currentDie += aDieInfo.length;
    }

  return FALSE;
}
Пример #27
0
static LONGEST
core_xfer_partial (struct target_ops *ops, enum target_object object,
		   const char *annex, gdb_byte *readbuf,
		   const gdb_byte *writebuf, ULONGEST offset,
		   LONGEST len)
{
  switch (object)
    {
    case TARGET_OBJECT_MEMORY:
      return section_table_xfer_memory_partial (readbuf, writebuf,
						offset, len,
						core_data->sections,
						core_data->sections_end,
						NULL);

    case TARGET_OBJECT_AUXV:
      if (readbuf)
	{
	  /* When the aux vector is stored in core file, BFD
	     represents this with a fake section called ".auxv".  */

	  struct bfd_section *section;
	  bfd_size_type size;

	  section = bfd_get_section_by_name (core_bfd, ".auxv");
	  if (section == NULL)
	    return -1;

	  size = bfd_section_size (core_bfd, section);
	  if (offset >= size)
	    return 0;
	  size -= offset;
	  if (size > len)
	    size = len;
	  if (size > 0
	      && !bfd_get_section_contents (core_bfd, section, readbuf,
					    (file_ptr) offset, size))
	    {
	      warning (_("Couldn't read NT_AUXV note in core file."));
	      return -1;
	    }

	  return size;
	}
      return -1;

    case TARGET_OBJECT_WCOOKIE:
      if (readbuf)
	{
	  /* When the StackGhost cookie is stored in core file, BFD
	     represents this with a fake section called
	     ".wcookie".  */

	  struct bfd_section *section;
	  bfd_size_type size;

	  section = bfd_get_section_by_name (core_bfd, ".wcookie");
	  if (section == NULL)
	    return -1;

	  size = bfd_section_size (core_bfd, section);
	  if (offset >= size)
	    return 0;
	  size -= offset;
	  if (size > len)
	    size = len;
	  if (size > 0
	      && !bfd_get_section_contents (core_bfd, section, readbuf,
					    (file_ptr) offset, size))
	    {
	      warning (_("Couldn't read StackGhost cookie in core file."));
	      return -1;
	    }

	  return size;
	}
      return -1;

    case TARGET_OBJECT_LIBRARIES:
      if (core_gdbarch
	  && gdbarch_core_xfer_shared_libraries_p (core_gdbarch))
	{
	  if (writebuf)
	    return -1;
	  return
	    gdbarch_core_xfer_shared_libraries (core_gdbarch,
						readbuf, offset, len);
	}
      /* FALL THROUGH */

    case TARGET_OBJECT_SPU:
      if (readbuf && annex)
	{
	  /* When the SPU contexts are stored in a core file, BFD
	     represents this with a fake section called
	     "SPU/<annex>".  */

	  struct bfd_section *section;
	  bfd_size_type size;
	  char sectionstr[100];

	  xsnprintf (sectionstr, sizeof sectionstr, "SPU/%s", annex);

	  section = bfd_get_section_by_name (core_bfd, sectionstr);
	  if (section == NULL)
	    return -1;

	  size = bfd_section_size (core_bfd, section);
	  if (offset >= size)
	    return 0;
	  size -= offset;
	  if (size > len)
	    size = len;
	  if (size > 0
	      && !bfd_get_section_contents (core_bfd, section, readbuf,
					    (file_ptr) offset, size))
	    {
	      warning (_("Couldn't read SPU section in core file."));
	      return -1;
	    }

	  return size;
	}
      else if (readbuf)
	{
	  /* NULL annex requests list of all present spuids.  */
	  struct spuid_list list;

	  list.buf = readbuf;
	  list.offset = offset;
	  list.len = len;
	  list.pos = 0;
	  list.written = 0;
	  bfd_map_over_sections (core_bfd, add_to_spuid_list, &list);
	  return list.written;
	}
      return -1;

    default:
      if (ops->beneath != NULL)
	return ops->beneath->to_xfer_partial (ops->beneath, object,
					      annex, readbuf,
					      writebuf, offset, len);
      return -1;
    }
}
Пример #28
0
struct sr_disasm_state *
sr_disasm_init(const char *file_name,
               char **error_message)
{
#if HAVE_LIBOPCODES
    struct sr_disasm_state *state =
        sr_malloc(sizeof(struct sr_disasm_state));

    state->bfd_file = bfd_openr(file_name, NULL);
    if (!state->bfd_file)
    {
        *error_message = sr_asprintf("Failed to open file %s: %s",
                                     file_name,
                                     bfd_errmsg(bfd_get_error()));
        free(state);
        return NULL;
    }

    if (!bfd_check_format(state->bfd_file, bfd_object))
    {
        *error_message = sr_asprintf("Invalid file format of %s: %s",
                                     file_name,
                                     bfd_errmsg(bfd_get_error()));
        bfd_close(state->bfd_file);
        free(state);
        return NULL;
    }

    asection *section =
        bfd_get_section_by_name(state->bfd_file, ".text");

    if (!section)
    {
        *error_message = sr_asprintf(
            "Failed to find .text section in %s: %s",
            file_name,
            bfd_errmsg(bfd_get_error()));

        bfd_close(state->bfd_file);
        free(state);
        return NULL;
    }

    state->disassembler = disassembler(state->bfd_file);
    if (!state->disassembler)
    {
        *error_message = sr_asprintf(
            "Unable to find disassembler for %s",
            file_name);

        bfd_close(state->bfd_file);
        free(state);
        return NULL;
    }

    init_disassemble_info(&state->info, NULL, buffer_printf);
    state->info.arch = bfd_get_arch(state->bfd_file);
    state->info.mach = bfd_get_mach(state->bfd_file);
    state->info.buffer_vma = section->vma;
    state->info.buffer_length = section->size;
    state->info.section = section;
    /* TODO: memory error func */
    bfd_malloc_and_get_section(state->bfd_file, section,
                               &state->info.buffer);

    disassemble_init_for_target(&state->info);
    return state;
#else // HAVE_LIBOPCODES
    *error_message = sr_asprintf("satyr compiled without libopcodes");
    return NULL;
#endif // HAVE_LIBOPCODES
}
Пример #29
0
static bfd_boolean
gldelf64btsmip_place_orphan (lang_input_statement_type *file, asection *s)
{
  static struct orphan_save hold_text;
  static struct orphan_save hold_rodata;
  static struct orphan_save hold_data;
  static struct orphan_save hold_bss;
  static struct orphan_save hold_rel;
  static struct orphan_save hold_interp;
  static struct orphan_save hold_sdata;
  static int count = 1;
  struct orphan_save *place;
  lang_statement_list_type *old;
  lang_statement_list_type add;
  etree_type *address;
  const char *secname;
  const char *ps = NULL;
  lang_output_section_statement_type *os;
  lang_statement_union_type **os_tail;
  etree_type *load_base;
  int isdyn = 0;

  secname = bfd_get_section_name (s->owner, s);
  if (! link_info.relocatable
      && link_info.combreloc
      && (s->flags & SEC_ALLOC)
      && strncmp (secname, ".rel", 4) == 0)
    {
      if (secname[4] == 'a')
	secname = ".rela.dyn";
      else
	secname = ".rel.dyn";
      isdyn = 1;
    }

  if (isdyn || (!config.unique_orphan_sections && !unique_section_p (secname)))
    {
      /* Look through the script to see where to place this section.  */
      os = lang_output_section_find (secname);

      if (os != NULL
	  && (os->bfd_section == NULL
	      || ((s->flags ^ os->bfd_section->flags)
		  & (SEC_LOAD | SEC_ALLOC)) == 0))
	{
	  /* We already have an output section statement with this
	     name, and its bfd section, if any, has compatible flags.  */
	  lang_add_section (&os->children, s, os, file);
	  return TRUE;
	}
    }

  if (hold_text.os == NULL)
    hold_text.os = lang_output_section_find (".text");

  /* If this is a final link, then always put .gnu.warning.SYMBOL
     sections into the .text section to get them out of the way.  */
  if (link_info.executable
      && ! link_info.relocatable
      && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
      && hold_text.os != NULL)
    {
      lang_add_section (&hold_text.os->children, s, hold_text.os, file);
      return TRUE;
    }

  /* Decide which segment the section should go in based on the
     section name and section flags.  We put loadable .note sections
     right after the .interp section, so that the PT_NOTE segment is
     stored right after the program headers where the OS can read it
     in the first page.  */
#define HAVE_SECTION(hold, name) (hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)

  if ((s->flags & SEC_EXCLUDE) != 0 && !link_info.relocatable)
    {
      if (s->output_section == NULL)
	s->output_section = bfd_abs_section_ptr;
      return TRUE;
    }

  place = NULL;
  if ((s->flags & SEC_ALLOC) == 0)
    ;
  else if ((s->flags & SEC_LOAD) != 0
	   && strncmp (secname, ".note", 5) == 0
	   && HAVE_SECTION (hold_interp, ".interp"))
    place = &hold_interp;
  else if ((s->flags & SEC_HAS_CONTENTS) == 0
	   && HAVE_SECTION (hold_bss, ".bss"))
    place = &hold_bss;
  else if ((s->flags & SEC_SMALL_DATA) != 0
	   && HAVE_SECTION (hold_sdata, ".sdata"))
    place = &hold_sdata;
  else if ((s->flags & SEC_READONLY) == 0
	   && HAVE_SECTION (hold_data, ".data"))
    place = &hold_data;
  else if (strncmp (secname, ".rel", 4) == 0
	   && (s->flags & SEC_LOAD) != 0
	   && (hold_rel.os != NULL
	       || (hold_rel.os = output_rel_find (s, isdyn)) != NULL))
    place = &hold_rel;
  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
	   && HAVE_SECTION (hold_rodata, ".rodata"))
    place = &hold_rodata;
  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == (SEC_CODE | SEC_READONLY)
	   && hold_text.os != NULL)
    place = &hold_text;

#undef HAVE_SECTION

  /* Choose a unique name for the section.  This will be needed if the
     same section name appears in the input file with different
     loadable or allocatable characteristics.  */
  if (bfd_get_section_by_name (output_bfd, secname) != NULL)
    {
      secname = bfd_get_unique_section_name (output_bfd, secname, &count);
      if (secname == NULL)
	einfo ("%F%P: place_orphan failed: %E\n");
    }

  /* Start building a list of statements for this section.
     First save the current statement pointer.  */
  old = stat_ptr;

  /* If we have found an appropriate place for the output section
     statements for this orphan, add them to our own private list,
     inserting them later into the global statement list.  */
  if (place != NULL)
    {
      stat_ptr = &add;
      lang_list_init (stat_ptr);
    }

  if (config.build_constructors)
    {
      /* If the name of the section is representable in C, then create
	 symbols to mark the start and the end of the section.  */
      for (ps = secname; *ps != '\0'; ps++)
	if (! ISALNUM (*ps) && *ps != '_')
	  break;
      if (*ps == '\0')
	{
	  char *symname;
	  etree_type *e_align;

	  symname = (char *) xmalloc (ps - secname + sizeof "__start_");
	  sprintf (symname, "__start_%s", secname);
	  e_align = exp_unop (ALIGN_K,
			      exp_intop ((bfd_vma) 1 << s->alignment_power));
	  lang_add_assignment (exp_assop ('=', symname, e_align));
	}
    }

  address = NULL;
  if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
    address = exp_intop ((bfd_vma) 0);

  load_base = NULL;
  if (place != NULL && place->os->load_base != NULL)
    {
      etree_type *lma_from_vma;
      lma_from_vma = exp_binop ('-', place->os->load_base,
				exp_nameop (ADDR, place->os->name));
      load_base = exp_binop ('+', lma_from_vma,
			     exp_nameop (ADDR, secname));
    }

  os_tail = lang_output_section_statement.tail;
  os = lang_enter_output_section_statement (secname, address, 0,
					    (bfd_vma) 0,
					    (etree_type *) NULL,
					    (etree_type *) NULL,
					    load_base);

  lang_add_section (&os->children, s, os, file);

  lang_leave_output_section_statement
    ((bfd_vma) 0, "*default*",
     (struct lang_output_section_phdr_list *) NULL, NULL);

  if (config.build_constructors && *ps == '\0')
    {
      char *symname;

      /* lang_leave_ouput_section_statement resets stat_ptr.  Put
	 stat_ptr back where we want it.  */
      if (place != NULL)
	stat_ptr = &add;

      symname = (char *) xmalloc (ps - secname + sizeof "__stop_");
      sprintf (symname, "__stop_%s", secname);
      lang_add_assignment (exp_assop ('=', symname,
				      exp_nameop (NAME, ".")));
    }

  /* Restore the global list pointer.  */
  stat_ptr = old;

  if (place != NULL && os->bfd_section != NULL)
    {
      asection *snew, **pps;

      snew = os->bfd_section;

      /* Shuffle the bfd section list to make the output file look
	 neater.  This is really only cosmetic.  */
      if (place->section == NULL)
	{
	  asection *bfd_section = place->os->bfd_section;

	  /* If the output statement hasn't been used to place
	     any input sections (and thus doesn't have an output
	     bfd_section), look for the closest prior output statement
	     having an output section.  */
	  if (bfd_section == NULL)
	    bfd_section = output_prev_sec_find (place->os);

	  if (bfd_section != NULL && bfd_section != snew)
	    place->section = &bfd_section->next;
	}

      if (place->section != NULL)
	{
	  /* Unlink the section.  */
	  for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
	    ;
	  bfd_section_list_remove (output_bfd, pps);

	  /* Now tack it on to the "place->os" section list.  */
	  bfd_section_list_insert (output_bfd, place->section, snew);
	}

      /* Save the end of this list.  Further ophans of this type will
	 follow the one we've just added.  */
      place->section = &snew->next;

      /* The following is non-cosmetic.  We try to put the output
	 statements in some sort of reasonable order here, because
	 they determine the final load addresses of the orphan
	 sections.  In addition, placing output statements in the
	 wrong order may require extra segments.  For instance,
	 given a typical situation of all read-only sections placed
	 in one segment and following that a segment containing all
	 the read-write sections, we wouldn't want to place an orphan
	 read/write section before or amongst the read-only ones.  */
      if (add.head != NULL)
	{
	  lang_statement_union_type *newly_added_os;

	  if (place->stmt == NULL)
	    {
	      /* Put the new statement list right at the head.  */
	      *add.tail = place->os->header.next;
	      place->os->header.next = add.head;

	      place->os_tail = &place->os->next;
	    }
	  else
	    {
	      /* Put it after the last orphan statement we added.  */
	      *add.tail = *place->stmt;
	      *place->stmt = add.head;
	    }

	  /* Fix the global list pointer if we happened to tack our
	     new list at the tail.  */
	  if (*old->tail == add.head)
	    old->tail = add.tail;

	  /* Save the end of this list.  */
	  place->stmt = add.tail;

	  /* Do the same for the list of output section statements.  */
	  newly_added_os = *os_tail;
	  *os_tail = NULL;
	  newly_added_os->output_section_statement.next = *place->os_tail;
	  *place->os_tail = newly_added_os;
	  place->os_tail = &newly_added_os->output_section_statement.next;

	  /* Fixing the global list pointer here is a little different.
	     We added to the list in lang_enter_output_section_statement,
	     trimmed off the new output_section_statment above when
	     assigning *os_tail = NULL, but possibly added it back in
	     the same place when assigning *place->os_tail.  */
	  if (*os_tail == NULL)
	    lang_output_section_statement.tail = os_tail;
	}
    }

  return TRUE;
}
Пример #30
0
static void
elf_symfile_read (struct objfile *objfile, int mainline)
{
  bfd *abfd = objfile->obfd;
  struct elfinfo ei;
  struct cleanup *back_to;
  CORE_ADDR offset;

  init_minimal_symbol_collection ();
  back_to = make_cleanup_discard_minimal_symbols ();

  memset ((char *) &ei, 0, sizeof (ei));

  /* Allocate struct to keep track of the symfile */
  objfile->sym_stab_info = (struct dbx_symfile_info *)
    xmmalloc (objfile->md, sizeof (struct dbx_symfile_info));
  memset ((char *) objfile->sym_stab_info, 0, sizeof (struct dbx_symfile_info));
  make_cleanup (free_elfinfo, (void *) objfile);

  /* Process the normal ELF symbol table first.  This may write some 
     chain of info into the dbx_symfile_info in objfile->sym_stab_info,
     which can later be used by elfstab_offset_sections.  */

  elf_symtab_read (objfile, 0);

  /* Add the dynamic symbols.  */

  elf_symtab_read (objfile, 1);

  /* Now process debugging information, which is contained in
     special ELF sections. */

  /* If we are reinitializing, or if we have never loaded syms yet,
     set table to empty.  MAINLINE is cleared so that *_read_psymtab
     functions do not all also re-initialize the psymbol table. */
  if (mainline)
    {
      init_psymbol_list (objfile, 0);
      mainline = 0;
    }

  /* We first have to find them... */
  bfd_map_over_sections (abfd, elf_locate_sections, (void *) & ei);

  /* ELF debugging information is inserted into the psymtab in the
     order of least informative first - most informative last.  Since
     the psymtab table is searched `most recent insertion first' this
     increases the probability that more detailed debug information
     for a section is found.

     For instance, an object file might contain both .mdebug (XCOFF)
     and .debug_info (DWARF2) sections then .mdebug is inserted first
     (searched last) and DWARF2 is inserted last (searched first).  If
     we don't do this then the XCOFF info is found first - for code in
     an included file XCOFF info is useless. */

  if (ei.mdebugsect)
    {
      const struct ecoff_debug_swap *swap;

      /* .mdebug section, presumably holding ECOFF debugging
         information.  */
      swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
      if (swap)
	elfmdebug_build_psymtabs (objfile, swap, ei.mdebugsect);
    }
  if (ei.stabsect)
    {
      asection *str_sect;

      /* Stab sections have an associated string table that looks like
         a separate section.  */
      str_sect = bfd_get_section_by_name (abfd, ".stabstr");

      /* FIXME should probably warn about a stab section without a stabstr.  */
      if (str_sect)
	elfstab_build_psymtabs (objfile,
				mainline,
				ei.stabsect->filepos,
				bfd_section_size (abfd, ei.stabsect),
				str_sect->filepos,
				bfd_section_size (abfd, str_sect));
    }
  if (dwarf2_has_info (abfd))
    {
      /* DWARF 2 sections */
      dwarf2_build_psymtabs (objfile, mainline);
    }
  else if (ei.dboffset && ei.lnoffset)
    {
      /* DWARF sections */
      dwarf_build_psymtabs (objfile,
			    mainline,
			    ei.dboffset, ei.dbsize,
			    ei.lnoffset, ei.lnsize);
    }

  if (DWARF2_BUILD_FRAME_INFO_P ())
    DWARF2_BUILD_FRAME_INFO(objfile);

  /* Install any minimal symbols that have been collected as the current
     minimal symbols for this objfile. */

  install_minimal_symbols (objfile);

  do_cleanups (back_to);
}