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; } }
/** 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); }
/** * 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; }
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; }
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; } }
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!! */ }
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; }
/** * 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; }
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; }
// 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; }
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 */ } }
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); }