Beispiel #1
0
static int
derive_heap_segment (bfd *abfd, bfd_vma *bottom, bfd_vma *top)
{
  bfd_vma top_of_data_memory = 0;
  bfd_vma top_of_heap = 0;
  bfd_size_type sec_size;
  bfd_vma sec_vaddr;
  asection *sec;

  gdb_assert (bottom);
  gdb_assert (top);

  /* This function depends on being able to call a function in the
     inferior.  */
  if (!target_has_execution)
    return 0;

  /* The following code assumes that the link map is arranged as
     follows (low to high addresses):

     ---------------------------------
     | text sections                 |
     ---------------------------------
     | data sections (including bss) |
     ---------------------------------
     | heap                          |
     --------------------------------- */

  for (sec = abfd->sections; sec; sec = sec->next)
    {
      if (bfd_get_section_flags (abfd, sec) & SEC_DATA
	  || strcmp (".bss", bfd_section_name (abfd, sec)) == 0)
	{
	  sec_vaddr = bfd_get_section_vma (abfd, sec);
	  sec_size = bfd_get_section_size (sec);
	  if (sec_vaddr + sec_size > top_of_data_memory)
	    top_of_data_memory = sec_vaddr + sec_size;
	}
    }

  top_of_heap = call_target_sbrk (0);
  if (top_of_heap == (bfd_vma) 0)
    return 0;

  /* Return results.  */
  if (top_of_heap > top_of_data_memory)
    {
      *bottom = top_of_data_memory;
      *top = top_of_heap;
      return 1;
    }

  /* No additional heap space needs to be saved.  */
  return 0;
}
Beispiel #2
0
static int
sim_prepare_for_program (SIM_DESC sd, bfd* abfd)
{
  sim_cpu *cpu;
  int elf_flags = 0;

  cpu = STATE_CPU (sd, 0);

  if (abfd != NULL)
    {
      asection *s;

      if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
        elf_flags = elf_elfheader (abfd)->e_flags;

      cpu->cpu_elf_start = bfd_get_start_address (abfd);
      /* See if any section sets the reset address */
      cpu->cpu_use_elf_start = 1;
      for (s = abfd->sections; s && cpu->cpu_use_elf_start; s = s->next) 
        {
          if (s->flags & SEC_LOAD)
            {
              bfd_size_type size;

              size = bfd_get_section_size (s);
              if (size > 0)
                {
                  bfd_vma lma;

                  if (STATE_LOAD_AT_LMA_P (sd))
                    lma = bfd_section_lma (abfd, s);
                  else
                    lma = bfd_section_vma (abfd, s);

                  if (lma <= 0xFFFE && lma+size >= 0x10000)
                    cpu->cpu_use_elf_start = 0;
                }
            }
        }

      if (elf_flags & E_M68HC12_BANKS)
        {
          if (sim_get_bank_parameters (sd) != 0)
            sim_io_eprintf (sd, "Memory bank parameters are not initialized\n");
        }
    }

  if (!sim_hw_configure (sd))
    return SIM_RC_FAIL;

  /* reset all state information */
  sim_board_reset (sd);

  return SIM_RC_OK;
}
Beispiel #3
0
void
add_target_sections_of_objfile (struct objfile *objfile)
{
  struct target_section_table *table = current_target_sections;
  struct obj_section *osect;
  int space;
  unsigned count = 0;
  struct target_section *ts;

  if (objfile == NULL)
    return;

  /* Compute the number of sections to add.  */
  ALL_OBJFILE_OSECTIONS (objfile, osect)
    {
      if (bfd_get_section_size (osect->the_bfd_section) == 0)
	continue;
      count++;
    }

  if (count == 0)
    return;

  space = resize_section_table (table, count);

  ts = table->sections + space;

  ALL_OBJFILE_OSECTIONS (objfile, osect)
    {
      if (bfd_get_section_size (osect->the_bfd_section) == 0)
	continue;

      gdb_assert (ts < table->sections + space + count);

      ts->addr = obj_section_addr (osect);
      ts->endaddr = obj_section_endaddr (osect);
      ts->the_bfd_section = osect->the_bfd_section;
      ts->owner = (void *) objfile;

      ts++;
    }
}
Beispiel #4
0
static CORE_ADDR
bss_data_overlap (struct objfile *objfile)
{
  struct obj_section *osect;
  struct bfd_section *data = NULL;
  struct bfd_section *bss = NULL;

  /* First, find the .data and .bss sections.  */
  ALL_OBJFILE_OSECTIONS (objfile, osect)
    {
      if (strcmp (bfd_section_name (objfile->obfd,
				    osect->the_bfd_section),
		  ".data") == 0)
	data = osect->the_bfd_section;
      else if (strcmp (bfd_section_name (objfile->obfd,
					 osect->the_bfd_section),
		       ".bss") == 0)
	bss = osect->the_bfd_section;
    }

  /* If either section is not defined, there can be no overlap.  */
  if (data == NULL || bss == NULL)
    return 0;

  /* Assume the problem only occurs with linkers that place the .bss
     section after the .data section (the problem has only been
     observed when using the GNU linker, and the default linker
     script always places the .data and .bss sections in that order).  */
  if (bfd_section_vma (objfile->obfd, bss)
      < bfd_section_vma (objfile->obfd, data))
    return 0;

  if (bfd_section_vma (objfile->obfd, bss)
      < bfd_section_vma (objfile->obfd, data) + bfd_get_section_size (data))
    return ((bfd_section_vma (objfile->obfd, data)
	     + bfd_get_section_size (data))
	    - bfd_section_vma (objfile->obfd, bss));

  return 0;
}
Beispiel #5
0
static void *
lzma_open (struct bfd *nbfd, void *open_closure)
{
    asection *section = open_closure;
    bfd_size_type size, offset;
    lzma_stream_flags options;
    gdb_byte footer[LZMA_STREAM_HEADER_SIZE];
    gdb_byte *indexdata;
    lzma_index *index;
    int ret;
    uint64_t memlimit = UINT64_MAX;
    struct lzma_stream *lstream;
    size_t pos;

    size = bfd_get_section_size (section);
    offset = section->filepos + size - LZMA_STREAM_HEADER_SIZE;
    if (size < LZMA_STREAM_HEADER_SIZE
            || bfd_seek (section->owner, offset, SEEK_SET) != 0
            || bfd_bread (footer, LZMA_STREAM_HEADER_SIZE, section->owner)
            != LZMA_STREAM_HEADER_SIZE
            || lzma_stream_footer_decode (&options, footer) != LZMA_OK
            || offset < options.backward_size)
    {
        bfd_set_error (bfd_error_wrong_format);
        return NULL;
    }

    offset -= options.backward_size;
    indexdata = xmalloc (options.backward_size);
    index = NULL;
    pos = 0;
    if (bfd_seek (section->owner, offset, SEEK_SET) != 0
            || bfd_bread (indexdata, options.backward_size, section->owner)
            != options.backward_size
            || lzma_index_buffer_decode (&index, &memlimit, &gdb_lzma_allocator,
                                         indexdata, &pos, options.backward_size)
            != LZMA_OK
            || lzma_index_size (index) != options.backward_size)
    {
        xfree (indexdata);
        bfd_set_error (bfd_error_wrong_format);
        return NULL;
    }
    xfree (indexdata);

    lstream = xzalloc (sizeof (struct lzma_stream));
    lstream->section = section;
    lstream->index = index;

    return lstream;
}
Beispiel #6
0
void
core_get_text_space (bfd *cbfd)
{
  core_text_space = malloc (bfd_get_section_size (core_text_sect));

  if (!core_text_space)
    {
      fprintf (stderr, _("%s: ran out room for %lu bytes of text space\n"),
	       whoami, (unsigned long) bfd_get_section_size (core_text_sect));
      done (1);
    }

  if (!bfd_get_section_contents (cbfd, core_text_sect, core_text_space,
				 0, bfd_get_section_size (core_text_sect)))
    {
      bfd_perror ("bfd_get_section_contents");
      free (core_text_space);
      core_text_space = 0;
    }

  if (!core_text_space)
    fprintf (stderr, _("%s: can't do -c\n"), whoami);
}
Beispiel #7
0
// Look for an address in a section.  This is called via  bfd_map_over_sections.
static void find_address_in_section (bfd *abfd, asection *section, PTR data)
{
	struct find_handle *info = (struct find_handle *) data;
	bfd_vma vma;
	bfd_size_type size;

	if (info->found)
		return;

	if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0)
		return;

	vma = bfd_get_section_vma (abfd, section);
	size = bfd_get_section_size (section);

	if (info->pc < (vma = bfd_get_section_vma (abfd, section)))
		return;

	if (info->pc >= vma + (size = bfd_get_section_size (section)))
		return;

	info->found = bfd_find_nearest_line (abfd, section, info->syms, info->pc - vma, &info->filename, &info->functionname, &info->line);
}
bfd_boolean
_bfd_elf_convert_gnu_properties (bfd *ibfd, asection *isec,
				 bfd *obfd, bfd_byte **ptr,
				 bfd_size_type *ptr_size)
{
  unsigned int size;
  bfd_byte *contents;
  unsigned int align_shift;
  const struct elf_backend_data *bed;
  elf_property_list *list = elf_properties (ibfd);

  bed = get_elf_backend_data (obfd);
  align_shift = bed->s->elfclass == ELFCLASS64 ? 3 : 2;

  /* Get the output .note.gnu.property section size.  */
  size = bfd_get_section_size (isec->output_section);

  /* Update the output .note.gnu.property section alignment.  */
  bfd_set_section_alignment (obfd, isec->output_section, align_shift);

  if (size > bfd_get_section_size (isec))
    {
      contents = (bfd_byte *) bfd_malloc (size);
      free (*ptr);
      *ptr = contents;
    }
  else
    contents = *ptr;

  *ptr_size = size;

  /* Generate the output .note.gnu.property section.  */
  elf_write_gnu_properties (ibfd, contents, list, size, 1 << align_shift);

  return TRUE;
}
Beispiel #9
0
static void
do_sections_p1 (struct coff_ofile *head)
{
  asection *section;
  int idx;
  struct coff_section *all = (struct coff_section *) (xcalloc (abfd->section_count + 1,
					     sizeof (struct coff_section)));
  head->nsections = abfd->section_count + 1;
  head->sections = all;

  for (idx = 0, section = abfd->sections; section; section = section->next, idx++)
    {
      long relsize;
      int i = section->target_index;
      arelent **relpp;
      long relcount;

      relsize = bfd_get_reloc_upper_bound (abfd, section);
      if (relsize < 0)
	bfd_fatal (bfd_get_filename (abfd));
      if (relsize == 0)
	continue;
      relpp = (arelent **) xmalloc (relsize);
      relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms);
      if (relcount < 0)
	bfd_fatal (bfd_get_filename (abfd));

      head->sections[i].name = (char *) (section->name);
      head->sections[i].code = section->flags & SEC_CODE;
      head->sections[i].data = section->flags & SEC_DATA;
      if (strcmp (section->name, ".bss") == 0)
	head->sections[i].data = 1;
      head->sections[i].address = section->lma;
      head->sections[i].size = bfd_get_section_size (section);
      head->sections[i].number = idx;
      head->sections[i].nrelocs = section->reloc_count;
      head->sections[i].relocs =
	(struct coff_reloc *) (xcalloc (section->reloc_count,
					sizeof (struct coff_reloc)));
      head->sections[i].bfd_section = section;
    }
  head->sections[0].name = "ABSOLUTE";
  head->sections[0].code = 0;
  head->sections[0].data = 0;
  head->sections[0].address = 0;
  head->sections[0].size = 0;
  head->sections[0].number = 0;
}
void lookup_section(bfd * abfd, asection * sec, void * opaque_data)
{
	find_info * data = (find_info*)opaque_data;

	if (data->func)
		return;

	if (!(bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
		return;

	bfd_vma vma = bfd_get_section_vma(abfd, sec);
	if (data->counter < vma || vma + bfd_get_section_size(sec) <= data->counter)
		return;

	bfd_find_nearest_line(abfd, sec, data->symbol, data->counter - vma, &(data->file), &(data->func), &(data->line));
}
Beispiel #11
0
void traceback::Bfd::Context::lookup_section(bfd* abfd, asection* sec, void* opaque_data)
{
	Bfd::Info* data = static_cast<Bfd::Info*>(opaque_data);

	if (data->func)
		return;

	if (!(bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
		return;

	bfd_vma vma = bfd_get_section_vma(abfd, sec);
	if (data->counter < vma || vma + bfd_get_section_size(sec) <= data->counter)
		return;

	data->displacement = data->counter - vma;
	bfd_find_nearest_line(abfd, sec, data->symbol, data->displacement, &(data->file), &(data->func), &(data->line));
}
Beispiel #12
0
static void add_bfd_section(bfd *Bfd, asection *Sect, bfd_info_t *BfdInfo) {
	if (strcmp(Sect->name, ".symbols") == 0) {
		Sect->userdata = new_symbols_section(Sect, Bfd);
	} else if (strcmp(Sect->name, ".methods") == 0) {
		method_section_t *Section = new_method_section();
		bfd_section_t *Block = new_bfd_section(Sect, Bfd, BfdInfo);
		Block->Next = Section->Blocks;
		Section->Blocks = Block;
		Sect->userdata = Block;
	} else if (Sect->flags & SEC_THREAD_LOCAL) {
		printf("Thread local storage not supported yet!\n");
		exit(1);
	} else if (Sect->flags & SEC_LOAD) {
		Sect->userdata = new_bfd_section(Sect, Bfd, BfdInfo);
	} else if (Sect->flags & SEC_ALLOC) {
		Sect->userdata = new_bss_section(bfd_get_section_size(Sect));
	};
};
Beispiel #13
0
/**
 * Lookup callback.
 */
static void
bfd_util_lookup_section(bfd *b, asection *sec, void *data)
{
	struct symbol_ctx *sc = data;
	bfd_vma vma;

	if (sc->location.function != NULL)
		return;		/* Already found */

	if (0 == (bfd_get_section_flags(b, sec) & SEC_ALLOC))
		return;

	vma = bfd_get_section_vma(b, sec);
	if (sc->addr < vma || sc->addr >= bfd_get_section_size(sec) + vma)
		return;

	bfd_find_nearest_line(b, sec, sc->symbols, sc->addr - vma,
		&sc->location.file, &sc->location.function, &sc->location.line);
}
Beispiel #14
0
static void find_address_in_section(bfd *abfd, asection *section, void *data) {
  addr2line_data *adata = reinterpret_cast<addr2line_data*>(data);

  bfd_vma vma;
  bfd_size_type size;

  if (adata->found) {
    return;
  }

  if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0) {
    return;
  }

  vma = bfd_get_section_vma(abfd, section);
  if (adata->pc < vma) {
    return;
  }

  size = bfd_get_section_size(section);
  if (adata->pc >= vma + size) {
    return;
  }

  // libdwarf allocates its own unaligned memory so it doesn't play well with
  // valgrind
#ifndef VALGRIND
  adata->found = bfd_find_nearest_line(abfd, section, adata->syms,
                                       adata->pc - vma, &adata->filename,
                                       &adata->functionname, &adata->line);
#endif

  if (adata->found) {
    const char *file = adata->filename;
    unsigned int line = adata->line;
    bfd_boolean found = TRUE;
    while (found) {
      found = bfd_find_inliner_info(abfd, &file, &adata->functionname, &line);
    }
  }
}
Beispiel #15
0
    static void find_address_in_section (bfd *abfd, asection *section, void *data)
    {
        GetFileLineContext* ctx = static_cast<GetFileLineContext*>(data);

        if (ctx->found) return;

        uint64_t pc = ctx->address;
        
        if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0)
            return;

        bfd_vma vma = bfd_get_section_vma (abfd, section);
        if (pc < vma)
            return;

        bfd_size_type size = bfd_get_section_size (section);
        if (pc >= vma + size)
            return;

        ctx->found = bfd_find_nearest_line (abfd, section, ctx->syms, pc - vma, &ctx->filename, &ctx->functionname, &ctx->line);
    }
Beispiel #16
0
static void find_address_in_section(bfd *abfd, asection *section, void *data)
{
	bfd_vma pc, vma;
	bfd_size_type size;
	struct a2l_data *a2l = data;

	if (a2l->found)
		return;

	if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0)
		return;

	pc = a2l->addr;
	vma = bfd_get_section_vma(abfd, section);
	size = bfd_get_section_size(section);

	if (pc < vma || pc >= vma + size)
		return;

	a2l->found = bfd_find_nearest_line(abfd, section, a2l->syms, pc - vma,
					   &a2l->filename, &a2l->funcname,
					   &a2l->line);
}
Beispiel #17
0
/* initialize section data */
void initialize_section(bincode_t *bin)
{
    asection *section;
    //const char *section_name;
    //flagword section_flags; // unsigned int
    bfd *abfd = bin->abfd;
    section_t *nextsec = NULL;

    for (section=abfd->sections;section!=NULL;section=section->next) {
        section_t *sec;
        bfd_byte *data;
        bfd_size_type datasize = bfd_get_section_size(section);

        if (datasize == 0) continue;

        if((data = malloc(datasize)) == NULL) {
            bs_errmsg("  (!) malloc(): data\n");
            exit(EXIT_FAILURE);
        }
        bfd_get_section_contents(abfd, section, data, 0 ,datasize);
        if((sec = malloc(sizeof(section_t))) == NULL) {
            bs_errmsg("  (!) malloc(): section\n");
            exit(EXIT_FAILURE);
        }
        sec->name = strdup(bfd_section_name(abfd, section));
        sec->data = data;
        sec->datasize = datasize;
        sec->vma = section->vma;
        sec->section = section;
        sec->is_code = section->flags & SEC_CODE;

        sec->next = nextsec;
        nextsec = sec;
    }
    bin->sec = nextsec;
}
Beispiel #18
0
struct parsed_option_list *iterate_short_opts(bfd *binary_bfd, const bfd_vma shortopts) {
	asection *shortopt_section = find_vma_section(binary_bfd, shortopts);

	// Prepare a list of options for this call
	struct parsed_option_list *options_found = NULL;

	size_t sec_size = bfd_get_section_size(shortopt_section);
	bfd_byte *section_data = (bfd_byte *) xmalloc (sec_size);
	bfd_get_section_contents(binary_bfd, shortopt_section, section_data, 0, sec_size);
	debug("Loading the contents of section %s (%ld bytes)\n", shortopt_section->name, sec_size);

	size_t shortopt_offset = (shortopts - shortopt_section->vma);
	info("shortopts live in section %s at offset %ld\n", shortopt_section->name, shortopt_offset);


	bfd_byte *optstring = &section_data[shortopt_offset];
	info("Short opts %s\n", optstring);

	unsigned int opt_idx = 0;
	while (0x0 != optstring[opt_idx]) {

		char opt_char[2] = {optstring[opt_idx], 0x0};

		bool has_arg = false;
		// Does this option require an argument?
		if (':' == optstring[opt_idx+1]) {
			has_arg = false;
			opt_idx++;
		}
		options_found = append_option(options_found, opt_char, has_arg, ONE_DASH);
		opt_idx++;
	}

	free(section_data);
	return options_found;
}
Beispiel #19
0
static void find_address_in_section(bfd *abfd, asection *section, void *data) {
  addr2line_data *adata = reinterpret_cast<addr2line_data*>(data);

  bfd_vma vma;
  bfd_size_type size;

  if (adata->found) {
    return;
  }

  if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0) {
    return;
  }

  vma = bfd_get_section_vma(abfd, section);
  if (adata->pc < vma) {
    return;
  }

  size = bfd_get_section_size(section);
  if (adata->pc >= vma + size) {
    return;
  }

  adata->found = bfd_find_nearest_line(abfd, section, adata->syms,
                                       adata->pc - vma, &adata->filename,
                                       &adata->functionname, &adata->line);
  if (adata->found) {
    const char *file = adata->filename;
    unsigned int line = adata->line;
    bfd_boolean found = TRUE;
    while (found) {
      found = bfd_find_inliner_info(abfd, &file, &adata->functionname, &line);
    }
  }
}
Beispiel #20
0
void
mini_dump_get_debug_info_about_address(MiniDump *self, guint64 address, gchar *module_name, const gchar **source_file_name, const gchar **function_name,guint *line_number)
{
  gchar *filename = g_build_filename(self->bin_dir,module_name, NULL);
  bfd *abfd = bfd_openr(filename,NULL);
  asection *section;
  long storage;
  long symcount;
  bfd_boolean dynamic = FALSE;
  asymbol **syms;  
  if (abfd == NULL)
    return;
  if (!bfd_check_format (abfd, bfd_object))
    {
      bfd_close(abfd);
      return; 
    }
  if ((bfd_get_file_flags (abfd) & HAS_SYMS) == 0)
    {
      bfd_close(abfd);
      return;
    }
  storage = bfd_get_symtab_upper_bound (abfd);
  if (storage == 0)
    {
      storage = bfd_get_dynamic_symtab_upper_bound (abfd);
      dynamic = TRUE;
    }
  if (storage < 0)
    {
      bfd_close(abfd);
      return;
    }
  syms = (asymbol **) g_malloc0(storage);
  if (dynamic)
    symcount = bfd_canonicalize_dynamic_symtab (abfd, syms);
  else
    symcount = bfd_canonicalize_symtab (abfd, syms);
  if (symcount < 0)
    {
      bfd_close(abfd);
      g_free(syms);
      return;
    }
  section = abfd->sections;
  long i = 0;
  gchar *temp = g_strdup_printf("%s_symbols",filename);
  FILE *sym_file = fopen(temp,"wb");
  for (i = 0; i < symcount; i++)
    {
      fprintf(sym_file,"%s\t%08X\t%08X\t%p\n",syms[i]->name,syms[i]->value,syms[i]->flags,syms[i]->udata.p);
    }
  g_free(temp);
  fclose(sym_file);
  while(section)
    {
      bfd_vma vma;
      bfd_vma pc = address;
      bfd_size_type size;
      if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0)
        {
          goto next_iteration;
        }
      vma = bfd_get_section_vma (abfd, section);
      if (pc < vma)
        {
          goto next_iteration;
        }
      size = bfd_get_section_size (section);
      if (pc >= vma + size)
        {
          goto next_iteration;
        }
      if (bfd_find_nearest_line (abfd, section, syms, pc - vma, source_file_name, function_name, line_number))
        {
          break;
        }
next_iteration:
      section = section->next;
    } 
}
static void
setup_sections (bfd *abfd, asection *sect, void *data_voidp)
{
  struct setup_sections_data *data = data_voidp;
  CORE_ADDR alignment;
  unsigned prot;

  if (sect != NULL)
    {
      /* It is required by later bfd_get_relocated_section_contents.  */
      if (sect->output_section == NULL)
	sect->output_section = sect;

      if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0)
	return;

      /* Make the memory always readable.  */
      prot = GDB_MMAP_PROT_READ;
      if ((bfd_get_section_flags (abfd, sect) & SEC_READONLY) == 0)
	prot |= GDB_MMAP_PROT_WRITE;
      if ((bfd_get_section_flags (abfd, sect) & SEC_CODE) != 0)
	prot |= GDB_MMAP_PROT_EXEC;

      if (compile_debug)
	fprintf_unfiltered (gdb_stdlog,
			    "module \"%s\" section \"%s\" size %s prot %u\n",
			    bfd_get_filename (abfd),
			    bfd_get_section_name (abfd, sect),
			    paddress (target_gdbarch (),
				      bfd_get_section_size (sect)),
			    prot);
    }
  else
    prot = -1;

  if (sect == NULL
      || (data->last_prot != prot && bfd_get_section_size (sect) != 0))
    {
      CORE_ADDR addr;
      asection *sect_iter;

      if (data->last_size != 0)
	{
	  addr = gdbarch_infcall_mmap (target_gdbarch (), data->last_size,
				       data->last_prot);
	  munmap_list_add (data->munmap_list_headp, addr, data->last_size);
	  if (compile_debug)
	    fprintf_unfiltered (gdb_stdlog,
				"allocated %s bytes at %s prot %u\n",
				paddress (target_gdbarch (), data->last_size),
				paddress (target_gdbarch (), addr),
				data->last_prot);
	}
      else
	addr = 0;

      if ((addr & (data->last_max_alignment - 1)) != 0)
	error (_("Inferior compiled module address %s "
		 "is not aligned to BFD required %s."),
	       paddress (target_gdbarch (), addr),
	       paddress (target_gdbarch (), data->last_max_alignment));

      for (sect_iter = data->last_section_first; sect_iter != sect;
	   sect_iter = sect_iter->next)
	if ((bfd_get_section_flags (abfd, sect_iter) & SEC_ALLOC) != 0)
	  bfd_set_section_vma (abfd, sect_iter,
			       addr + bfd_get_section_vma (abfd, sect_iter));

      data->last_size = 0;
      data->last_section_first = sect;
      data->last_prot = prot;
      data->last_max_alignment = 1;
    }

  if (sect == NULL)
    return;

  alignment = ((CORE_ADDR) 1) << bfd_get_section_alignment (abfd, sect);
  data->last_max_alignment = max (data->last_max_alignment, alignment);

  data->last_size = (data->last_size + alignment - 1) & -alignment;

  bfd_set_section_vma (abfd, sect, data->last_size);

  data->last_size += bfd_get_section_size (sect);
  data->last_size = (data->last_size + alignment - 1) & -alignment;
}
void
m32c_load (bfd * prog)
{
  asection *s;
  unsigned long mach = bfd_get_mach (prog);
  unsigned long highest_addr_loaded = 0;

  if (mach == 0 && default_machine != 0)
    mach = default_machine;

  m32c_set_mach (mach);

  for (s = prog->sections; s; s = s->next)
    {
#if 0
      /* This was a good idea until we started storing the RAM data in
         ROM, at which point everything was all messed up.  The code
         remains as a reminder.  */
      if ((s->flags & SEC_ALLOC) && !(s->flags & SEC_READONLY))
	{
	  if (strcmp (bfd_get_section_name (prog, s), ".stack"))
	    {
	      int secend =
		bfd_get_section_size (s) + bfd_section_lma (prog, s);
	      if (heaptop < secend && bfd_section_lma (prog, s) < 0x10000)
		{
		  heaptop = heapbottom = secend;
		}
	    }
	}
#endif
      if (s->flags & SEC_LOAD)
	{
	  char *buf;
	  bfd_size_type size;

	  size = bfd_get_section_size (s);
	  if (size <= 0)
	    continue;

	  bfd_vma base = bfd_section_lma (prog, s);
	  if (verbose)
	    fprintf (stderr, "[load a=%08x s=%08x %s]\n",
		     (int) base, (int) size, bfd_get_section_name (prog, s));
	  buf = (char *) malloc (size);
	  bfd_get_section_contents (prog, s, buf, 0, size);
	  mem_put_blk (base, buf, size);
	  free (buf);
	  if (highest_addr_loaded < base + size - 1 && size >= 4)
	    highest_addr_loaded = base + size - 1;
	}
    }

  if (strcmp (bfd_get_target (prog), "srec") == 0)
    {
      heaptop = heapbottom = 0;
      switch (mach)
	{
	case bfd_mach_m16c:
	  if (highest_addr_loaded > 0x10000)
	    regs.r_pc = mem_get_si (0x000ffffc) & membus_mask;
	  else
	    regs.r_pc = mem_get_si (0x000fffc) & membus_mask;
	  break;
	case bfd_mach_m32c:
	  regs.r_pc = mem_get_si (0x00fffffc) & membus_mask;
	  break;
	}
    }
  else
    regs.r_pc = prog->start_address;
  if (verbose)
    fprintf (stderr, "[start pc=%08x]\n", (unsigned int) regs.r_pc);
}
Beispiel #23
0
struct parsed_option_list *iterate_long_opts(bfd *binary_bfd, const bfd_vma longopts) {

	asection *longopt_section = find_vma_section(binary_bfd, longopts);

	// Prepare a list of options for this call
	struct parsed_option_list *options_found = NULL;

	size_t sec_size = bfd_get_section_size(longopt_section);
	bfd_byte *section_data = (bfd_byte *) xmalloc (sec_size);
	bfd_get_section_contents(binary_bfd, longopt_section, section_data, 0, sec_size);
	debug("Loading the contents of section %s (%ld bytes)\n", longopt_section->name, sec_size);

	size_t longopt_offset = (longopts - longopt_section->vma);
	info("longopts live in section %s at offset %ld\n", longopt_section->name, longopt_offset);

	char *all_zeroes = alloca(sizeof(struct option));
	memset(all_zeroes, 0x0, sizeof(struct option));

	while (longopt_offset) {

		/* As per the man page for getopt_long(3), the last element in
		 * the array of struct option elements has to be all zeroes
		 */
		if (0==memcmp(&section_data[longopt_offset], all_zeroes, sizeof(struct option)))
			break;

		struct option *long_option = (struct option*) &section_data[longopt_offset];

		if (NULL==long_option->name)
			break;


		debug("struct option @ section offset %ld\t loaded into %016" PRIXPTR "\n", longopt_offset, (uintptr_t) long_option);

		// FIXME We're assuming that pointers hardcoded into the binary can
		// safely be cast into bfd_vma, which is unsafe

		// We can't assume member 'name' of the struct option will point to an
		// area in the same section of the ELF binary as the struct option
		// itself
		bfd_byte *option_name_section_data = NULL;
		asection *option_name_section = find_vma_section(binary_bfd, (bfd_vma) long_option->name);
		if (!option_name_section)
			break;
		debug("option name lives in section %s\n", option_name_section->name);
		if (option_name_section==longopt_section) {
			option_name_section_data = section_data;
		} else {
			size_t option_name_sec_size = bfd_get_section_size(option_name_section);
			option_name_section_data = (bfd_byte *) xmalloc (option_name_sec_size);
			bfd_get_section_contents(binary_bfd, option_name_section, option_name_section_data, 0, option_name_sec_size);
		}

		size_t name_offset = ( (bfd_vma)long_option->name - option_name_section->vma);

		debug("option name @ %016" PRIXPTR ": %s\n", (uintptr_t) long_option->name, &option_name_section_data[name_offset]);

		options_found = append_option(options_found, 
			(const char*) &option_name_section_data[name_offset], 
			(bool) (1==long_option->has_arg), TWO_DASH);

		if (option_name_section != longopt_section)
			free(option_name_section_data);

		longopt_offset += sizeof(struct option);
	}

	debug("Last struct option in array at offset %ld vma %016" PRIXPTR "\n", longopt_offset, longopt_section->vma+longopt_offset);
	free(section_data);

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

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

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

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

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

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

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

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

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

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

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

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

	  ms_type = mst_solib_trampoline;

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

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

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

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

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

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

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

  do_cleanups (cleanups);
}
/* the finishing piece for each section */
static void copy_section_data (bfd *ibfd, sec_ptr isection, void *obfdarg)
{
    bfd *obfd = obfdarg;
    sec_ptr osection;
    bfd_size_type size;
    struct add_reloc_struct *new_reloc;

    size = bfd_get_section_size (isection);

    osection = isection->output_section;

    if (size == 0 || osection == 0)
	return;

    if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS
	&& bfd_get_section_flags (obfd, osection) & SEC_HAS_CONTENTS) {

	void *memhunk;

	mcheck_check_all();

	memhunk = malloc (size);

	if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size))
	    return;

	if (strcmp(bfd_get_section_name(ibfd, isection), ".text") == 0) {

	    /* make the data modifications, if requested */
	    modify_byte_struct *mbyte_ptr = modify_bytes;
	    while (mbyte_ptr != NULL) {
		((unsigned char *)memhunk)[mbyte_ptr->location] = (char)(mbyte_ptr->value & 0xff);
		mbyte_ptr = mbyte_ptr->next;
	    }

	    /* make sure additional relocs have proper data present */
	    /* kernel implements relocs relative to what's already there in the data! */
	    /* so if we're overriding a call, we need to set the old PC-relative data back to 0xfffffffc */
	    for (new_reloc = additional_relocs; new_reloc != NULL; new_reloc = new_reloc->next) {
		((unsigned char *)memhunk)[new_reloc->loc]   = (unsigned char)0xfc;
		((unsigned char *)memhunk)[new_reloc->loc+1] = (unsigned char)0xff;
		((unsigned char *)memhunk)[new_reloc->loc+2] = (unsigned char)0xff;
		((unsigned char *)memhunk)[new_reloc->loc+3] = (unsigned char)0xff;
	    }
	}

	if (!bfd_set_section_contents (obfd, osection, memhunk, 0, size))
	    return;

	/* note that bfd_set_section_contents will render the symbol table noncanonical */
	/* (the array will not be NULL terminated) */

	free (memhunk);
    }
    else if (!(bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS)) {
	fprintf(stderr, "not copying input section %s because flags %x do not indicate contents (%x)\n",
	       isection->name,
	       bfd_get_section_flags (ibfd, isection),
	       SEC_HAS_CONTENTS);
    }
    else {
	fprintf(stderr, "not copying output section %s because flags %x do not indicate contents (%x)\n",
	       osection->name,
	       bfd_get_section_flags (obfd, osection),
	       SEC_HAS_CONTENTS);
    }
}
Beispiel #26
0
static int
derive_heap_segment (bfd *abfd, bfd_vma *bottom, bfd_vma *top)
{
  bfd_vma top_of_data_memory = 0;
  bfd_vma top_of_heap = 0;
  bfd_size_type sec_size;
  struct value *zero, *sbrk;
  bfd_vma sec_vaddr;
  asection *sec;

  gdb_assert (bottom);
  gdb_assert (top);

  /* This function depends on being able to call a function in the
     inferior.  */
  if (!target_has_execution)
    return 0;

  /* The following code assumes that the link map is arranged as
     follows (low to high addresses):

     ---------------------------------
     | text sections                 |
     ---------------------------------
     | data sections (including bss) |
     ---------------------------------
     | heap                          |
     --------------------------------- */

  for (sec = abfd->sections; sec; sec = sec->next)
    {
      if (bfd_get_section_flags (abfd, sec) & SEC_DATA
	  || strcmp (".bss", bfd_section_name (abfd, sec)) == 0)
	{
	  sec_vaddr = bfd_get_section_vma (abfd, sec);
	  sec_size = bfd_get_section_size (sec);
	  if (sec_vaddr + sec_size > top_of_data_memory)
	    top_of_data_memory = sec_vaddr + sec_size;
	}
    }

  /* Now get the top-of-heap by calling sbrk in the inferior.  */
  if (lookup_minimal_symbol ("sbrk", NULL, NULL) != NULL)
    {
      sbrk = find_function_in_inferior ("sbrk");
      if (sbrk == NULL)
	return 0;
    }
  else if (lookup_minimal_symbol ("_sbrk", NULL, NULL) != NULL)
    {
      sbrk = find_function_in_inferior ("_sbrk");
      if (sbrk == NULL)
	return 0;
    }
  else
    return 0;

  zero = value_from_longest (builtin_type_int, 0);
  gdb_assert (zero);
  sbrk = call_function_by_hand (sbrk, 1, &zero);
  if (sbrk == NULL)
    return 0;
  top_of_heap = value_as_long (sbrk);

  /* Return results.  */
  if (top_of_heap > top_of_data_memory)
    {
      *bottom = top_of_data_memory;
      *top = top_of_heap;
      return 1;
    }

  /* No additional heap space needs to be saved.  */
  return 0;
}
Beispiel #27
0
static void
update_for_binary_section(bfd *abfd,
			  asection *the_section,
			  PTR obj)
{
  unsigned_word section_vma;
  unsigned_word section_size;
  access_type access;
  device *me = (device*)obj;

  /* skip the section if no memory to allocate */
  if (! (bfd_get_section_flags(abfd, the_section) & SEC_ALLOC))
    return;

  /* check/ignore any sections of size zero */
  section_size = bfd_get_section_size (the_section);
  if (section_size == 0)
    return;

  /* find where it is to go */
  section_vma = bfd_get_section_vma(abfd, the_section);

  DTRACE(binary,
	 ("name=%-7s, vma=0x%.8lx, size=%6ld, flags=%3lx(%s%s%s%s%s )\n",
	  bfd_get_section_name(abfd, the_section),
	  (long)section_vma,
	  (long)section_size,
	  (long)bfd_get_section_flags(abfd, the_section),
	  bfd_get_section_flags(abfd, the_section) & SEC_LOAD ? " LOAD" : "",
	  bfd_get_section_flags(abfd, the_section) & SEC_CODE ? " CODE" : "",
	  bfd_get_section_flags(abfd, the_section) & SEC_DATA ? " DATA" : "",
	  bfd_get_section_flags(abfd, the_section) & SEC_ALLOC ? " ALLOC" : "",
	  bfd_get_section_flags(abfd, the_section) & SEC_READONLY ? " READONLY" : ""
	  ));

  /* If there is an .interp section, it means it needs a shared library interpreter.  */
  if (strcmp(".interp", bfd_get_section_name(abfd, the_section)) == 0)
    error("Shared libraries are not yet supported.\n");

  /* determine the devices access */
  access = access_read;
  if (bfd_get_section_flags(abfd, the_section) & SEC_CODE)
    access |= access_exec;
  if (!(bfd_get_section_flags(abfd, the_section) & SEC_READONLY))
    access |= access_write;

  /* if claim specified, allocate region from the memory device */
  if (device_find_property(me, "claim") != NULL) {
    device_instance *memory = tree_find_ihandle_property(me, "/chosen/memory");
    unsigned_cell mem_in[3];
    unsigned_cell mem_out[1];
    mem_in[0] = 0; /*alignment - top-of-stack*/
    mem_in[1] = section_size;
    mem_in[2] = section_vma;
    if (device_instance_call_method(memory, "claim", 3, mem_in, 1, mem_out) < 0)
      device_error(me, "failed to claim memory for section at 0x%lx (0x%lx",
		   section_vma,
		   section_size);
    if (mem_out[0] != section_vma)
      device_error(me, "section address not as requested");
  }

  /* if a map, pass up a request to create the memory in core */
  if (strncmp(device_name(me), "map-binary", strlen("map-binary")) == 0)
    device_attach_address(device_parent(me),
			  attach_raw_memory,
			  0 /*address space*/,
			  section_vma,
			  section_size,
			  access,
			  me);

  /* if a load dma in the required data */
  if (bfd_get_section_flags(abfd, the_section) & SEC_LOAD) {
    void *section_init = zalloc(section_size);
    if (!bfd_get_section_contents(abfd,
				  the_section,
				  section_init, 0,
				  section_size)) {
      bfd_perror("binary");
      device_error(me, "load of data failed");
      return;
    }
    if (device_dma_write_buffer(device_parent(me),
				section_init,
				0 /*space*/,
				section_vma,
				section_size,
				1 /*violate_read_only*/)
	!= section_size)
      device_error(me, "broken transfer\n");
    free(section_init); /* only free if load */
  }
}
Beispiel #28
0
// --------------------------------------------------------------------------
void* ctkBinaryFileDescriptorPrivate::resolve(const char * symbol)
{
  if (!this->BFD)
    {
    return 0;
    }

  void *addr = 0;
  
  // Get the symbol table
  long storageNeeded = bfd_get_symtab_upper_bound(this->BFD);
  asymbol ** symbolTable = (asymbol **) malloc(storageNeeded);
  
  long numberOfSymbols = bfd_canonicalize_symtab(this->BFD, symbolTable);
    
  // Run through the symbol table, looking for the requested symbol
  for (int i = 0; i < numberOfSymbols; i++) 
    {
    if (strcmp(symbol, symbolTable[i]->name) == 0)
      { 
      // Found the symbol, get the section pointer
      asection *p = bfd_get_section(symbolTable[i]);
          
      // Do we have this section already?
      MemorySectionContainer::iterator sit;
      for (sit = this->Sections.begin(); sit != this->Sections.end(); ++sit)
        {
        if ((*sit).first == p)
          {
          break;
          }  
        }
            
      PTR mem;
      if (sit == this->Sections.end())
        {
        // Get the contents of the section
        bfd_size_type sz = bfd_get_section_size (p);
        mem = malloc (sz);
        if (bfd_get_section_contents(this->BFD, p, mem, (file_ptr) 0,sz))
          {
          this->Sections.push_back( MemorySectionType(p, mem) );
          }
        else
          {
          // Error reading section
          free(mem);
          break;
          }
        }
      else
        {
        // pull the start of the section block from the cache
        mem = const_cast<void*>((*sit).second);
        }
            
      // determine the address of this section
      addr = (char *)mem + (bfd_asymbol_value(symbolTable[i]) - bfd_asymbol_base(symbolTable[i]));
      break;
      }
    }

  // cleanup. just delete the outer vector for the symbol table
  free(symbolTable);
  
  return addr;
}
Beispiel #29
0
void
core_create_line_syms (void)
{
  char *prev_name, *prev_filename;
  unsigned int prev_name_len, prev_filename_len;
  bfd_vma vma, min_vma = ~(bfd_vma) 0, max_vma = 0;
  Sym *prev, dummy, *sym;
  const char *filename;
  int prev_line_num;
  Sym_Table ltab;
  bfd_vma vma_high;

  /* Create symbols for functions as usual.  This is necessary in
     cases where parts of a program were not compiled with -g.  For
     those parts we still want to get info at the function level.  */
  core_create_function_syms ();

  /* Pass 1: count the number of symbols.  */

  /* To find all line information, walk through all possible
     text-space addresses (one by one!) and get the debugging
     info for each address.  When the debugging info changes,
     it is time to create a new symbol.

     Of course, this is rather slow and it would be better if
     BFD would provide an iterator for enumerating all line infos.  */
  prev_name_len = PATH_MAX;
  prev_filename_len = PATH_MAX;
  prev_name = (char *) xmalloc (prev_name_len);
  prev_filename = (char *) xmalloc (prev_filename_len);
  ltab.len = 0;
  prev_line_num = 0;

  vma_high = core_text_sect->vma + bfd_get_section_size (core_text_sect);
  for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size)
    {
      unsigned int len;

      if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num)
	  || (prev_line_num == dummy.line_num
	      && prev_name != NULL
	      && strcmp (prev_name, dummy.name) == 0
	      && filename_cmp (prev_filename, filename) == 0))
	continue;

      ++ltab.len;
      prev_line_num = dummy.line_num;

      len = strlen (dummy.name);
      if (len >= prev_name_len)
	{
	  prev_name_len = len + 1024;
	  free (prev_name);
	  prev_name = (char *) xmalloc (prev_name_len);
	}

      strcpy (prev_name, dummy.name);
      len = strlen (filename);

      if (len >= prev_filename_len)
	{
	  prev_filename_len = len + 1024;
	  free (prev_filename);
	  prev_filename = (char *) xmalloc (prev_filename_len);
	}

      strcpy (prev_filename, filename);

      min_vma = MIN (vma, min_vma);
      max_vma = MAX (vma, max_vma);
    }

  free (prev_name);
  free (prev_filename);

  /* Make room for function symbols, too.  */
  ltab.len += symtab.len;
  ltab.base = (Sym *) xmalloc (ltab.len * sizeof (Sym));
  ltab.limit = ltab.base;

  /* Pass 2 - create symbols.  */

  /* We now set is_static as we go along, rather than by running
     through the symbol table at the end.

     The old way called symtab_finalize before the is_static pass,
     causing a problem since symtab_finalize uses is_static as part of
     its address conflict resolution algorithm.  Since global symbols
     were prefered over static symbols, and all line symbols were
     global at that point, static function names that conflicted with
     their own line numbers (static, but labeled as global) were
     rejected in favor of the line num.

     This was not the desired functionality.  We always want to keep
     our function symbols and discard any conflicting line symbols.
     Perhaps symtab_finalize should be modified to make this
     distinction as well, but the current fix works and the code is a
     lot cleaner now.  */
  prev = 0;

  for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size)
    {
      sym_init (ltab.limit);

      if (!get_src_info (vma, &filename, &ltab.limit->name, &ltab.limit->line_num)
	  || (prev && prev->line_num == ltab.limit->line_num
	      && strcmp (prev->name, ltab.limit->name) == 0
	      && filename_cmp (prev->file->name, filename) == 0))
	continue;

      /* Make name pointer a malloc'ed string.  */
      ltab.limit->name = xstrdup (ltab.limit->name);
      ltab.limit->file = source_file_lookup_path (filename);

      ltab.limit->addr = vma;

      /* Set is_static based on the enclosing function, using either:
	 1) the previous symbol, if it's from the same function, or
	 2) a symtab lookup.  */
      if (prev && ltab.limit->file == prev->file &&
	  strcmp (ltab.limit->name, prev->name) == 0)
	{
	  ltab.limit->is_static = prev->is_static;
	}
      else
	{
	  sym = sym_lookup(&symtab, ltab.limit->addr);
          if (sym)
	    ltab.limit->is_static = sym->is_static;
	}

      prev = ltab.limit;

      DBG (AOUTDEBUG, printf ("[core_create_line_syms] %lu %s 0x%lx\n",
			      (unsigned long) (ltab.limit - ltab.base),
			      ltab.limit->name,
			      (unsigned long) ltab.limit->addr));
      ++ltab.limit;
    }

  /* Copy in function symbols.  */
  memcpy (ltab.limit, symtab.base, symtab.len * sizeof (Sym));
  ltab.limit += symtab.len;

  if ((unsigned int) (ltab.limit - ltab.base) != ltab.len)
    {
      fprintf (stderr,
	       _("%s: somebody miscounted: ltab.len=%d instead of %ld\n"),
	       whoami, ltab.len, (long) (ltab.limit - ltab.base));
      done (1);
    }

  /* Finalize ltab and make it symbol table.  */
  symtab_finalize (&ltab);
  free (symtab.base);
  symtab = ltab;
}
static void
copy_sections (bfd *abfd, asection *sect, void *data)
{
  asymbol **symbol_table = data;
  bfd_byte *sect_data, *sect_data_got;
  struct cleanup *cleanups;
  struct bfd_link_info link_info;
  struct bfd_link_order link_order;
  CORE_ADDR inferior_addr;
  struct link_hash_table_cleanup_data cleanup_data;

  if ((bfd_get_section_flags (abfd, sect) & (SEC_ALLOC | SEC_LOAD))
      != (SEC_ALLOC | SEC_LOAD))
    return;

  if (bfd_get_section_size (sect) == 0)
    return;

  /* Mostly a copy of bfd_simple_get_relocated_section_contents which GDB
     cannot use as it does not report relocations to undefined symbols.  */
  memset (&link_info, 0, sizeof (link_info));
  link_info.output_bfd = abfd;
  link_info.input_bfds = abfd;
  link_info.input_bfds_tail = &abfd->link.next;

  cleanup_data.abfd = abfd;
  cleanup_data.link_next = abfd->link.next;

  abfd->link.next = NULL;
  link_info.hash = bfd_link_hash_table_create (abfd);

  cleanups = make_cleanup (link_hash_table_free, &cleanup_data);
  link_info.callbacks = &link_callbacks;

  memset (&link_order, 0, sizeof (link_order));
  link_order.next = NULL;
  link_order.type = bfd_indirect_link_order;
  link_order.offset = 0;
  link_order.size = bfd_get_section_size (sect);
  link_order.u.indirect.section = sect;

  sect_data = xmalloc (bfd_get_section_size (sect));
  make_cleanup (xfree, sect_data);

  sect_data_got = bfd_get_relocated_section_contents (abfd, &link_info,
						      &link_order, sect_data,
						      FALSE, symbol_table);

  if (sect_data_got == NULL)
    error (_("Cannot map compiled module \"%s\" section \"%s\": %s"),
	   bfd_get_filename (abfd), bfd_get_section_name (abfd, sect),
	   bfd_errmsg (bfd_get_error ()));
  gdb_assert (sect_data_got == sect_data);

  inferior_addr = bfd_get_section_vma (abfd, sect);
  if (0 != target_write_memory (inferior_addr, sect_data,
				bfd_get_section_size (sect)))
    error (_("Cannot write compiled module \"%s\" section \"%s\" "
	     "to inferior memory range %s-%s."),
	   bfd_get_filename (abfd), bfd_get_section_name (abfd, sect),
	   paddress (target_gdbarch (), inferior_addr),
	   paddress (target_gdbarch (),
		     inferior_addr + bfd_get_section_size (sect)));

  do_cleanups (cleanups);
}