示例#1
0
static void
elf_locate_sections (bfd *ignore_abfd, asection *sectp, void *eip)
{
  register struct elfinfo *ei;

  ei = (struct elfinfo *) eip;
  if (STREQ (sectp->name, ".debug"))
    {
      ei->dboffset = sectp->filepos;
      ei->dbsize = bfd_get_section_size_before_reloc (sectp);
    }
  else if (STREQ (sectp->name, ".line"))
    {
      ei->lnoffset = sectp->filepos;
      ei->lnsize = bfd_get_section_size_before_reloc (sectp);
    }
  else if (STREQ (sectp->name, ".stab"))
    {
      ei->stabsect = sectp;
    }
  else if (STREQ (sectp->name, ".stab.index"))
    {
      ei->stabindexsect = sectp;
    }
  else if (STREQ (sectp->name, ".mdebug"))
    {
      ei->mdebugsect = sectp;
    }
}
示例#2
0
/** Find_Address_In_Section
 *
 * Localitza la direccio (pc) dins de la seccio ".text" del binari
 *
 * @param abfd
 * @param section
 * @param data
 *
 * @return No return value.
 */
static void BFDmanager_findAddressInSection (bfd * abfd, asection * section, PTR data)
{
#if HAVE_BFD_GET_SECTION_SIZE || HAVE_BFD_GET_SECTION_SIZE_BEFORE_RELOC
	bfd_size_type size;
#endif
	bfd_vma vma;
	BFDmanager_symbolInfo_t *symdata = (BFDmanager_symbolInfo_t*) data;

	if (symdata->found)
		return;

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

	vma = bfd_get_section_vma (abfd, section);;

	if (symdata->pc < vma)
		return;

#if HAVE_BFD_GET_SECTION_SIZE
	size = bfd_get_section_size (section);
	if (symdata->pc >= vma + size)
		return;
#elif HAVE_BFD_GET_SECTION_SIZE_BEFORE_RELOC
	size = bfd_get_section_size_before_reloc (section);
	if (symdata->pc >= vma + size)
		return;
#else
	/* Do nothing? */
#endif

	symdata->found = bfd_find_nearest_line (abfd, section, symdata->symbols,
	  symdata->pc - vma, &symdata->filename, &symdata->function,
	  &symdata->line);
}
示例#3
0
/**
 * Obtain data from the .bss section(s).
 * The section(s) are identified by having ALLOC flag but
 * not LOAD nor READONLY flags.
 * The return value is in the form [(address, value),...,...].
 * Note that the value elements will always be zeros.
 * FIXME: Use a reasonable data structure.
 */
memory_data_t *
get_bssdata(asm_program_t *prog) {
    vector<memory_cell_data_t *> *bssdata = new vector<memory_cell_data_t *>();

    bfd *abfd = prog->abfd;

    unsigned int opb = bfd_octets_per_byte(abfd);
    assert(opb == 1);

    for(asection *section = abfd->sections;
        section != (asection *)  NULL; section = section->next){

        if(!(!(section->flags & SEC_READONLY) &&
             (section->flags & SEC_ALLOC) &&
             !(section->flags & SEC_LOAD))
            ) continue;
        bfd_vma datasize = bfd_get_section_size_before_reloc(section);
        if(datasize == 0) continue;
        bfd_vma start_addr = section->vma;
        bfd_vma end_addr = start_addr + datasize/opb;
        for (bfd_vma itr = start_addr; itr < end_addr; itr++) {
            memory_cell_data_t *mcd = (memory_cell_data_t *)
                xalloc((size_t) 1, (size_t) sizeof(memory_cell_data_t));
            mcd->address = itr;
            mcd->value = 0;
            bssdata->push_back(mcd);
        }
    }
    return bssdata;
}
示例#4
0
map<address_t, asm_function_t *>
get_stripped_binary_functions(bfd *abfd)
{
  // For a stripped binary, we  treat an executable section as a
  // function. 
  unsigned int opb = bfd_octets_per_byte(abfd);
  print_debug("warning", "no symbol table. disassembling each section");
  map<address_t, asm_function_t *> ret;
  for(asection *section = abfd->sections; section != (asection *) NULL; 
      section = section->next){
    if(!(section->flags & SEC_CODE)) continue;
    bfd_size_type datasize = 0;
    datasize = bfd_get_section_size_before_reloc (section);
    if (datasize == 0)
      continue;      
    asm_function_t *f = new asm_function_t;
    f->start_addr =  section->vma;
    f->end_addr = section->vma + datasize / opb;
    ostringstream os;
    os << "section_" << hex << section->vma;
    f->name = os.str();
    ret.insert(pair<address_t, asm_function_t *>(f->start_addr, f));
  }
  return ret;
}
示例#5
0
static void
initialize_sections(asm_program_t *prog, bfd_vma base)
{
  bfd_vma offset = 0;
  struct disassemble_info *disasm_info = &prog->disasm_info;
  assert(prog);
  bfd *abfd = prog->abfd;
  unsigned int opb = bfd_octets_per_byte(abfd);
  disasm_info->octets_per_byte = opb;
  init_disasm_info(prog);
  section_t **nextseg = &prog->segs;
  asection *section;

  /* Set to NULL in case there are zero segments. */
  *nextseg = NULL;

  /* Look for the section loaded into the lowest memory address */
  if (base != -1) {

    offset = base - asmir_get_base_address(prog);
    //fprintf(stderr, "Adjusting by %Lx\n", offset);
  }

  for(section = abfd->sections; section; section = section->next) {
    section_t *seg;
    bfd_byte *data;
    bfd_vma datasize = bfd_get_section_size_before_reloc(section);

    if(datasize == 0) continue;

    section->vma += offset;
    data = bfd_alloc2(abfd, datasize, sizeof(bfd_byte));
    bfd_get_section_contents(abfd, section, data, 0, datasize);
    seg = bfd_alloc(abfd, sizeof(section_t));
    seg->data = data;
    seg->datasize = datasize;
    seg->start_addr = section->vma;
    seg->end_addr = section->vma + datasize/opb;
    seg->section = section;
    seg->is_code = !!(section->flags & SEC_CODE);


    seg->next = NULL;
    *nextseg = seg;
    nextseg = &seg->next;
  }

}
示例#6
0
static void
mygeneric_load (bfd *loadfile_bfd)
{
  asection *s;

  for (s = loadfile_bfd->sections; s; s = s->next)
    {
      if (s->flags & SEC_LOAD)
	{
	  bfd_size_type size;

	  size = bfd_get_section_size_before_reloc (s);
	  if (size > 0)
	    {
	      char *buffer;
	      bfd_vma lma;	/* use load address, not virtual address */

	      buffer = xmalloc (size);
	      lma = s->lma;

	      /* Is this really necessary? I guess it gives the user something
	       * to look at during a long download.
		   */
	      printf ("Loading section %s, size 0x%lx lma 0x%lx\n",
		      bfd_get_section_name (loadfile_bfd, s),
		      (unsigned long) size,
		      (unsigned long) lma);	/* chops high 32 bits.  FIXME!! */

	      bfd_get_section_contents (loadfile_bfd, s, buffer, 0, size);

	      write_inferior_memory (lma, buffer, size);
	      free (buffer);
	    }
	}
    }

  printf ("Start address 0x%lx\n",
	  (unsigned long) loadfile_bfd->start_address);

  /* We were doing this in remote-mips.c, I suspect it is right
   * for other targets too.
   */
  /* write_pc (loadfile_bfd->start_address); *//* FIXME!! */
}
示例#7
0
address_t get_last_segment_address(const char *filename, 
				   address_t addr)
{
  bfd *abfd = initialize_bfd(filename);
  unsigned int opb = bfd_octets_per_byte(abfd);

  address_t ret = addr;
  for(asection *section = abfd->sections; 
      section != (asection *)  NULL; section = section->next){

    bfd_vma datasize = bfd_get_section_size_before_reloc(section);
    if(datasize == 0) continue;

    address_t start = section->vma;
    address_t end = section->vma + datasize/opb;
    if(addr >= start && addr <= end)
      return end;
  }
  return ret;
}
示例#8
0
/**
 * Obtain data from the section with readonly flags.
 * I.e. ALLOC, READONLY, and LOAD flags are set.
 * FIXME: Use a reasonable data structure.
 */
memory_data_t *
get_rodata(asm_program_t *prog) {
    vector<memory_cell_data_t *> *rodata = new vector<memory_cell_data_t *>();

    bfd *abfd = prog->abfd;

    unsigned int opb = bfd_octets_per_byte(abfd);
    assert(opb == 1);

    for(asection *section = abfd->sections;
        section != (asection *)  NULL; section = section->next){

        if(!((section->flags & SEC_READONLY) &&
             (section->flags & SEC_ALLOC) &&
             (section->flags & SEC_LOAD))
            ) continue;
        bfd_byte *data = NULL;
        bfd_vma datasize = bfd_get_section_size_before_reloc(section);
        if(datasize == 0) continue;
        data = (bfd_byte *) xalloc((size_t) datasize, (size_t)
                                   sizeof(bfd_byte));
        bfd_get_section_contents(abfd, section, data, 0, datasize);
        bfd_vma start_addr = section->vma;
        bfd_vma end_addr = start_addr + datasize/opb;
        for (bfd_vma itr = start_addr; itr < end_addr; itr++) {
            memory_cell_data_t *mcd = (memory_cell_data_t *)
                xalloc((size_t) 1, (size_t) sizeof(memory_cell_data_t));
            mcd->address = itr;
            mcd->value = data[itr-start_addr];
            rodata->push_back(mcd);
        }
        free(data);
    }
    /* FIXMEO: close the BFD */
    return rodata;
}
示例#9
0
文件: ldwrite.c 项目: janfj/dd-wrt
static void
build_link_order (lang_statement_union_type *statement)
{
    switch (statement->header.type)
    {
    case lang_data_statement_enum:
    {
        asection *output_section;
        struct bfd_link_order *link_order;
        bfd_vma value;
        bfd_boolean big_endian = FALSE;

        output_section = statement->data_statement.output_section;
        ASSERT (output_section->owner == output_bfd);

        link_order = bfd_new_link_order (output_bfd, output_section);
        if (link_order == NULL)
            einfo (_("%P%F: bfd_new_link_order failed\n"));

        link_order->type = bfd_data_link_order;
        link_order->offset = statement->data_statement.output_vma;
        link_order->u.data.contents = xmalloc (QUAD_SIZE);

        value = statement->data_statement.value;

        /* If the endianness of the output BFD is not known, then we
           base the endianness of the data on the first input file.
           By convention, the bfd_put routines for an unknown
           endianness are big endian, so we must swap here if the
           input file is little endian.  */
        if (bfd_big_endian (output_bfd))
            big_endian = TRUE;
        else if (bfd_little_endian (output_bfd))
            big_endian = FALSE;
        else
        {
            bfd_boolean swap;

            swap = FALSE;
            if (command_line.endian == ENDIAN_BIG)
                big_endian = TRUE;
            else if (command_line.endian == ENDIAN_LITTLE)
            {
                big_endian = FALSE;
                swap = TRUE;
            }
            else if (command_line.endian == ENDIAN_UNSET)
            {
                big_endian = TRUE;
                {
                    LANG_FOR_EACH_INPUT_STATEMENT (s)
                    {
                        if (s->the_bfd != NULL)
                        {
                            if (bfd_little_endian (s->the_bfd))
                            {
                                big_endian = FALSE;
                                swap = TRUE;
                            }
                            break;
                        }
                    }
                }
            }

            if (swap)
            {
                bfd_byte buffer[8];

                switch (statement->data_statement.type)
                {
                case QUAD:
                case SQUAD:
                    if (sizeof (bfd_vma) >= QUAD_SIZE)
                    {
                        bfd_putl64 (value, buffer);
                        value = bfd_getb64 (buffer);
                        break;
                    }
                /* Fall through.  */
                case LONG:
                    bfd_putl32 (value, buffer);
                    value = bfd_getb32 (buffer);
                    break;
                case SHORT:
                    bfd_putl16 (value, buffer);
                    value = bfd_getb16 (buffer);
                    break;
                case BYTE:
                    break;
                default:
                    abort ();
                }
            }
        }

        ASSERT (output_section->owner == output_bfd);
        switch (statement->data_statement.type)
        {
        case QUAD:
        case SQUAD:
            if (sizeof (bfd_vma) >= QUAD_SIZE)
                bfd_put_64 (output_bfd, value, link_order->u.data.contents);
            else
            {
                bfd_vma high;

                if (statement->data_statement.type == QUAD)
                    high = 0;
                else if ((value & 0x80000000) == 0)
                    high = 0;
                else
                    high = (bfd_vma) -1;
                bfd_put_32 (output_bfd, high,
                            (link_order->u.data.contents
                             + (big_endian ? 0 : 4)));
                bfd_put_32 (output_bfd, value,
                            (link_order->u.data.contents
                             + (big_endian ? 4 : 0)));
            }
            link_order->size = QUAD_SIZE;
            break;
        case LONG:
            bfd_put_32 (output_bfd, value, link_order->u.data.contents);
            link_order->size = LONG_SIZE;
            break;
        case SHORT:
            bfd_put_16 (output_bfd, value, link_order->u.data.contents);
            link_order->size = SHORT_SIZE;
            break;
        case BYTE:
            bfd_put_8 (output_bfd, value, link_order->u.data.contents);
            link_order->size = BYTE_SIZE;
            break;
        default:
            abort ();
        }
    }
    break;

    case lang_reloc_statement_enum:
    {
        lang_reloc_statement_type *rs;
        asection *output_section;
        struct bfd_link_order *link_order;

        rs = &statement->reloc_statement;

        output_section = rs->output_section;
        ASSERT (output_section->owner == output_bfd);

        link_order = bfd_new_link_order (output_bfd, output_section);
        if (link_order == NULL)
            einfo (_("%P%F: bfd_new_link_order failed\n"));

        link_order->offset = rs->output_vma;
        link_order->size = bfd_get_reloc_size (rs->howto);

        link_order->u.reloc.p = xmalloc (sizeof (struct bfd_link_order_reloc));

        link_order->u.reloc.p->reloc = rs->reloc;
        link_order->u.reloc.p->addend = rs->addend_value;

        if (rs->name == NULL)
        {
            link_order->type = bfd_section_reloc_link_order;
            if (rs->section->owner == output_bfd)
                link_order->u.reloc.p->u.section = rs->section;
            else
            {
                link_order->u.reloc.p->u.section = rs->section->output_section;
                link_order->u.reloc.p->addend += rs->section->output_offset;
            }
        }
        else
        {
            link_order->type = bfd_symbol_reloc_link_order;
            link_order->u.reloc.p->u.name = rs->name;
        }
    }
    break;

    case lang_input_section_enum:
        /* Create a new link_order in the output section with this
        attached */
        if (!statement->input_section.ifile->just_syms_flag)
        {
            asection *i = statement->input_section.section;
            asection *output_section = i->output_section;

            ASSERT (output_section->owner == output_bfd);

            if ((output_section->flags & SEC_HAS_CONTENTS) != 0
                    || ((output_section->flags & SEC_LOAD) != 0
                        && (output_section->flags & SEC_THREAD_LOCAL)))
            {
                struct bfd_link_order *link_order;

                link_order = bfd_new_link_order (output_bfd, output_section);

                if (i->flags & SEC_NEVER_LOAD)
                {
                    /* We've got a never load section inside one which
                       is going to be output, we'll change it into a
                       fill.  */
                    link_order->type = bfd_data_link_order;
                    link_order->u.data.contents = "";
                    link_order->u.data.size = 1;
                }
                else
                {
                    link_order->type = bfd_indirect_link_order;
                    link_order->u.indirect.section = i;
                    ASSERT (i->output_section == output_section);
                }
                if (i->_cooked_size)
                    link_order->size = i->_cooked_size;
                else
                    link_order->size = bfd_get_section_size_before_reloc (i);
                link_order->offset = i->output_offset;
            }
        }
        break;

    case lang_padding_statement_enum:
        /* Make a new link_order with the right filler */
    {
        asection *output_section;
        struct bfd_link_order *link_order;

        output_section = statement->padding_statement.output_section;
        ASSERT (statement->padding_statement.output_section->owner
                == output_bfd);
        if ((output_section->flags & SEC_HAS_CONTENTS) != 0)
        {
            link_order = bfd_new_link_order (output_bfd, output_section);
            link_order->type = bfd_data_link_order;
            link_order->size = statement->padding_statement.size;
            link_order->offset = statement->padding_statement.output_offset;
            link_order->u.data.contents = statement->padding_statement.fill->data;
            link_order->u.data.size = statement->padding_statement.fill->size;
        }
    }
    break;

    default:
        /* All the other ones fall through */
        break;
    }
示例#10
0
// FIXME: the memory that gets allocated here is never freed.
void
initialize_sections(bfd *abfd, asm_program_t *prog)
{
  struct disassemble_info *disasm_info = &prog->disasm_info;
  unsigned int opb = bfd_octets_per_byte(abfd);
  disasm_info->octets_per_byte = opb;
  init_disasm_info(prog);
  Segment *segs = NULL;

  for(asection *section = abfd->sections; 
      section != (asection *)  NULL; section = section->next){
    Segment *seg, *ts;

    int is_code = 0;
    bfd_byte *data = NULL;

    bfd_vma datasize = bfd_get_section_size_before_reloc(section);
    if(datasize == 0) continue;

    data = (bfd_byte *) xalloc((size_t) datasize, (size_t)
			       sizeof(bfd_byte));
    bfd_get_section_contents(abfd, section, data, 0, datasize);
    seg = (Segment *) xalloc(1, sizeof(Segment));
    seg->data = data;
    seg->datasize = datasize;
    seg->start_addr = section->vma;
    seg->end_addr = section->vma + datasize/opb;
    seg->section = section;
    if(section->flags & SEC_CODE == 0)
      is_code = 0;
    else
      is_code = 1;
    seg->is_code = is_code;
    if(is_code){
      /*seg->status = (unsigned char *)
	xalloc((seg->end_addr - seg->start_addr), sizeof(char)); */
      /*
      seg->insts = (Instruction **) xalloc((seg->end_addr - 
					    seg->start_addr),
					   sizeof(Instruction *));
       //init_disasm_info(&disasm_info, seg);
      for(bfd_vma pc = seg->start_addr; pc < seg->end_addr; ++pc){
	Instruction *inst = get_inst_of(prog, pc, seg);
	// DJB: Hack for stmxcsr and ldmxcsr instrs as found
	// in atphttpd instr 806a36e
	//if(inst->opcode[0] == 0xae && inst->opcode[1] == 0xf)
	//  inst->length++;
	seg->insts[pc - seg->start_addr] = inst;
      }
      */
      seg->next = NULL;
      if(segs == NULL)
	segs = seg;
      else{
	ts = segs;
	while(ts->next != NULL)
	  ts = ts->next;
	ts->next = seg;
      }
    }
    prog->sections[seg->start_addr] = seg;
  }
  prog->segs = segs;
}
示例#11
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_before_reloc(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");
    zfree(section_init); /* only free if load */
  }
}
示例#12
0
static void
download (char *target_name, char *args, int from_tty,
	  void (*write_routine) (bfd *from_bfd, asection *from_sec,
				 file_ptr from_addr, bfd_vma to_addr, int len),
	  void (*start_routine) (bfd_vma entry))
{
  struct cleanup *old_chain;
  asection *section;
  bfd *pbfd;
  bfd_vma entry;
  int i;
#define WRITESIZE 1024
  char *filename;
  int quiet;
  int nostart;

  quiet = 0;
  nostart = 0;
  filename = NULL;

  while (*args != '\000')
    {
      char *arg;

      while (isspace (*args))
	args++;

      arg = args;

      while ((*args != '\000') && !isspace (*args))
	args++;

      if (*args != '\000')
	*args++ = '\000';

      if (*arg != '-')
	filename = arg;
      else if (strncmp (arg, "-quiet", strlen (arg)) == 0)
	quiet = 1;
      else if (strncmp (arg, "-nostart", strlen (arg)) == 0)
	nostart = 1;
      else
	error ("unknown option `%s'", arg);
    }

  if (!filename)
    filename = get_exec_file (1);

  pbfd = bfd_openr (filename, gnutarget);
  if (pbfd == NULL)
    {
      perror_with_name (filename);
      return;
    }
  old_chain = make_cleanup_bfd_close (pbfd);

  if (!bfd_check_format (pbfd, bfd_object))
    error ("\"%s\" is not an object file: %s", filename,
	   bfd_errmsg (bfd_get_error ()));

  for (section = pbfd->sections; section; section = section->next)
    {
      if (bfd_get_section_flags (pbfd, section) & SEC_LOAD)
	{
	  bfd_vma section_address;
	  bfd_size_type section_size;
	  file_ptr fptr;
	  const char *section_name;

	  section_name = bfd_get_section_name (pbfd, section);

	  section_address = bfd_get_section_vma (pbfd, section);

	  /* Adjust sections from a.out files, since they don't
	     carry their addresses with.  */
	  if (bfd_get_flavour (pbfd) == bfd_target_aout_flavour)
	    {
	      if (strcmp (section_name, ".text") == 0)
		section_address = bfd_get_start_address (pbfd);
	      else if (strcmp (section_name, ".data") == 0)
		{
		  /* Read the first 8 bytes of the data section.
		     There should be the string 'DaTa' followed by
		     a word containing the actual section address. */
		  struct data_marker
		    {
		      char signature[4];	/* 'DaTa' */
		      unsigned char sdata[4];	/* &sdata */
		    }
		  marker;
		  bfd_get_section_contents (pbfd, section, &marker, 0,
					    sizeof (marker));
		  if (strncmp (marker.signature, "DaTa", 4) == 0)
		    {
		      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
			section_address = bfd_getb32 (marker.sdata);
		      else
			section_address = bfd_getl32 (marker.sdata);
		    }
		}
	    }

	  section_size = bfd_get_section_size_before_reloc (section);

	  if (!quiet)
	    printf_filtered ("[Loading section %s at 0x%x (%d bytes)]\n",
			     bfd_get_section_name (pbfd, section),
			     section_address,
			     section_size);

	  fptr = 0;
	  while (section_size > 0)
	    {
	      int count;
	      static char inds[] = "|/-\\";
	      static int k = 0;

	      QUIT;

	      count = min (section_size, WRITESIZE);

	      write_routine (pbfd, section, fptr, section_address, count);

	      if (!quiet)
		{
		  printf_unfiltered ("\r%c", inds[k++ % 4]);
		  gdb_flush (gdb_stdout);
		}

	      section_address += count;
	      fptr += count;
	      section_size -= count;
	    }
	}
    }

  if (!nostart)
    {
      entry = bfd_get_start_address (pbfd);

      if (!quiet)
	printf_unfiltered ("[Starting %s at 0x%x]\n", filename, entry);

      start_routine (entry);
    }

  do_cleanups (old_chain);
}