asm_program_t* byte_insn_to_asmp(bfd_architecture arch, address_t addr, unsigned char *bb_bytes, unsigned int len) { asm_program_t *prog = asmir_new_asmp_for_arch(arch); unsigned char *bytes = (unsigned char*)bfd_alloc(prog->abfd, len); assert(bytes); // copy the string, because the old one is freed when we return memcpy(bytes, bb_bytes, len); section_t *sec = (section_t*)bfd_alloc(prog->abfd, sizeof(section_t)); assert(sec); sec->start_addr = addr; sec->datasize = len; sec->end_addr = addr+len; sec->data = bytes; sec->is_code = 1; sec->next = NULL; prog->segs = sec; struct disassemble_info *disasm_info = &prog->disasm_info; disasm_info->buffer = bytes; disasm_info->buffer_vma = addr; disasm_info->buffer_length = len; disasm_info->section = NULL; return prog; }
asm_program_t* byte_insn_to_asmp(bfd_architecture arch, address_t addr, unsigned char *bb_bytes, unsigned int len) { asm_program_t *prog = fake_prog_for_arch(arch); unsigned char *bytes = (unsigned char*)bfd_alloc(prog->abfd, len); // copy the string, because the old one is freed when we return memcpy(bytes, bb_bytes, len); Instruction *inst = new Instruction; inst->address = addr; inst->length = len; inst->bytes = bytes; struct disassemble_info *disasm_info = &prog->disasm_info; disasm_info->buffer = bytes; disasm_info->buffer_vma = addr; disasm_info->buffer_length = len; disasm_info->section = NULL; asm_function_t *asmf = new asm_function_t; asmf->name = ""; asmf->start_addr = addr; asmf->end_addr = addr+len; asmf->instmap[addr] = inst; prog->functions[addr] = asmf; return prog; }
static asection * make_bfd_asection (bfd *abfd, const char *name, flagword flags, bfd_size_type size, bfd_vma vma, unsigned int alignment_power) { asection *asect; char *newname; newname = bfd_alloc (abfd, (bfd_size_type) strlen (name) + 1); if (!newname) return NULL; strcpy (newname, name); asect = bfd_make_section_anyway_with_flags (abfd, newname, flags); if (!asect) return NULL; asect->size = size; asect->vma = vma; asect->filepos = bfd_tell (abfd); asect->alignment_power = alignment_power; return asect; }
static bfd_boolean oasys_mkobject (bfd *abfd) { bfd_size_type amt = sizeof (oasys_data_type); abfd->tdata.oasys_obj_data = bfd_alloc (abfd, amt); return abfd->tdata.oasys_obj_data != NULL; }
/* Duplicate an object attribute string value. */ char * _bfd_elf_attr_strdup (bfd *abfd, const char * s) { char * p; int len; len = strlen (s) + 1; p = (char *) bfd_alloc (abfd, len); return (char *) memcpy (p, s, len); }
bfd_vma asmir_get_base_address(asm_program_t *prog) { #if SIZEOF_BFD_VMA == 4 bfd_vma lowest = LONG_MAX; #else bfd_vma lowest = LLONG_MAX; #endif assert(prog); bfd *abfd = prog->abfd; asection *section; if (bfd_get_flavour(abfd) == bfd_target_elf_flavour) { /* BFD has some issues with ELF files. ELF files have both sections and segments ("program headers"). We really care about the lowest address of program segments, but BFD only shows sections when an ELF file contains both. So, we need to use ELF-specific functions to learn the segment address, which is typically different than the section address. */ int i, is_nice; size_t ubound = bfd_get_elf_phdr_upper_bound(abfd); Elf_Internal_Phdr *phdrs = bfd_alloc(abfd, ubound); if (phdrs == NULL) { bfd_perror(NULL); assert(0); } int n = bfd_get_elf_phdrs(abfd, phdrs); if (n == -1) { bfd_perror(NULL); assert(0); } for (i = 0; i < n; i++) { /* fprintf(stderr, "VA: %#" BFD_VMA_FMT "x Align: %#" BFD_VMA_FMT "x Aligned: %#" BFD_VMA_FMT "x p_flags: %#" BFD_VMA_FMT "x p_type: %#"BFD_VMA_FMT "x\n", phdrs[i].p_vaddr, phdrs[i].p_align, phdrs[i].p_vaddr & (~(phdrs[i].p_align)), phdrs[i].p_flags, phdrs[i].p_type); */ bfd_vma aligned = phdrs[i].p_vaddr & (~(phdrs[i].p_align)); /* STACK segment has vaddr=paddr=0. If we don't ignore it, imagebase=0*/ is_nice = (phdrs[i].p_flags & SHT_PROGBITS) && (phdrs[i].p_type != PT_GNU_STACK); if (is_nice && aligned < lowest) { lowest = aligned; } } } else { /* Non-ELF files */ for (section = abfd->sections; section; section = section->next) { /* fprintf(stderr, "Section %s, vma %Lx\n", section->name, section->vma); */ if ((section->vma < lowest) && (section->flags & SEC_LOAD)) { lowest = section->vma; } } } //fprintf(stderr, "Lowest section is %#" BFD_VMA_FMT "x\n", lowest); //fprintf(stderr, "Adjusting by %Lx\n", offset); return lowest; }
void gdb_bfd_stash_filename (struct bfd *abfd) { char *name = bfd_get_filename (abfd); char *data; data = bfd_alloc (abfd, strlen (name) + 1); strcpy (data, name); /* Unwarranted chumminess with BFD. */ abfd->filename = data; }
static char * plugin_strdup (bfd *abfd, const char *str) { size_t strlength; char *copy; strlength = strlen (str) + 1; copy = bfd_alloc (abfd, strlength); if (copy == NULL) einfo (_("%P%F: plugin_strdup failed to allocate memory: %s\n"), bfd_get_error ()); memcpy (copy, str, strlength); return copy; }
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 bfd_boolean bfd_preserve_save (bfd *abfd, struct bfd_preserve *preserve) { preserve->tdata = abfd->tdata.any; preserve->arch_info = abfd->arch_info; preserve->flags = abfd->flags; preserve->sections = abfd->sections; preserve->section_last = abfd->section_last; preserve->section_count = abfd->section_count; preserve->section_htab = abfd->section_htab; preserve->marker = bfd_alloc (abfd, 1); if (preserve->marker == NULL) return FALSE; return bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc, sizeof (struct section_hash_entry)); }
static bfd_boolean versados_mkobject (bfd *abfd) { if (abfd->tdata.versados_data == NULL) { bfd_size_type amt = sizeof (tdata_type); tdata_type *tdata = bfd_alloc (abfd, amt); if (tdata == NULL) return FALSE; abfd->tdata.versados_data = tdata; tdata->symbols = NULL; VDATA (abfd)->alert = 0x12345678; } bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0); return TRUE; }
static enum ld_plugin_status add_symbols (void * handle, int nsyms, const struct ld_plugin_symbol * syms) { bfd *abfd = handle; struct plugin_data_struct *plugin_data = bfd_alloc (abfd, sizeof (plugin_data_struct));; plugin_data->nsyms = nsyms; plugin_data->syms = syms; if (nsyms != 0) abfd->flags |= HAS_SYMS; abfd->tdata.plugin_data = plugin_data; return LDPS_OK; }
elf_property * _bfd_elf_get_property (bfd *abfd, unsigned int type, unsigned int datasz) { elf_property_list *p, **lastp; if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) { /* Never should happen. */ abort (); } /* Keep the property list in order of type. */ lastp = &elf_properties (abfd); for (p = *lastp; p; p = p->next) { /* Reuse the existing entry. */ if (type == p->property.pr_type) { if (datasz > p->property.pr_datasz) { /* This can happen when mixing 32-bit and 64-bit objects. */ p->property.pr_datasz = datasz; } return &p->property; } else if (type < p->property.pr_type) break; lastp = &p->next; } p = (elf_property_list *) bfd_alloc (abfd, sizeof (*p)); if (p == NULL) { _bfd_error_handler (_("%pB: out of memory in _bfd_elf_get_property"), abfd); _exit (EXIT_FAILURE); } memset (p, 0, sizeof (*p)); p->property.pr_type = type; p->property.pr_datasz = datasz; p->next = *lastp; *lastp = p; return &p->property; }
asection * _bfd_elf_create_ifunc_dyn_reloc (bfd *abfd, struct bfd_link_info *info, asection *sec, asection *sreloc, struct elf_dyn_relocs **head) { struct elf_dyn_relocs *p; struct elf_link_hash_table *htab = elf_hash_table (info); if (sreloc == NULL) { const struct elf_backend_data *bed = get_elf_backend_data (abfd); if (htab->dynobj == NULL) htab->dynobj = abfd; sreloc = _bfd_elf_make_dynamic_reloc_section (sec, htab->dynobj, bed->s->log_file_align, abfd, bed->rela_plts_and_copies_p); if (sreloc == NULL) return NULL; } p = *head; if (p == NULL || p->sec != sec) { bfd_size_type amt = sizeof *p; p = ((struct elf_dyn_relocs *) bfd_alloc (htab->dynobj, amt)); if (p == NULL) return NULL; p->next = *head; *head = p; p->sec = sec; p->count = 0; p->pc_count = 0; } p->count += 1; return sreloc; }
static struct bfd_link_hash_table * linux_link_hash_table_create (bfd *abfd) { struct linux_link_hash_table *ret; bfd_size_type amt = sizeof (struct linux_link_hash_table); ret = (struct linux_link_hash_table *) bfd_alloc (abfd, amt); if (ret == (struct linux_link_hash_table *) NULL) return (struct bfd_link_hash_table *) NULL; if (!NAME(aout,link_hash_table_init) (&ret->root, abfd, linux_link_hash_newfunc, sizeof (struct linux_link_hash_entry))) { free (ret); return (struct bfd_link_hash_table *) NULL; } ret->dynobj = NULL; ret->fixup_count = 0; ret->local_builtins = 0; ret->fixup_list = NULL; return &ret->root.root; }
/* Allocate/find an object attribute. */ static obj_attribute * elf_new_obj_attr (bfd *abfd, int vendor, int tag) { obj_attribute *attr; obj_attribute_list *list; obj_attribute_list *p; obj_attribute_list **lastp; if (tag < NUM_KNOWN_OBJ_ATTRIBUTES) { /* Known tags are preallocated. */ attr = &elf_known_obj_attributes (abfd)[vendor][tag]; } else { /* Create a new tag. */ list = (obj_attribute_list *) bfd_alloc (abfd, sizeof (obj_attribute_list)); memset (list, 0, sizeof (obj_attribute_list)); list->tag = tag; /* Keep the tag list in order. */ lastp = &elf_other_obj_attributes (abfd)[vendor]; for (p = *lastp; p; p = p->next) { if (tag < p->tag) break; lastp = &p->next; } list->next = *lastp; *lastp = list; attr = &list->attr; } return attr; }
/* We permute the segment_map to get BFD to do the file layout we want: The first non-executable PT_LOAD segment appears first in the file and contains the ELF file header and phdrs. */ bfd_boolean nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info) { const struct elf_backend_data *const bed = get_elf_backend_data (abfd); struct elf_segment_map **m = &elf_seg_map (abfd); struct elf_segment_map **first_load = NULL; struct elf_segment_map **last_load = NULL; bfd_boolean moved_headers = FALSE; int sizeof_headers; if (info != NULL && info->user_phdrs) /* The linker script used PHDRS explicitly, so don't change what the user asked for. */ return TRUE; if (info != NULL) /* We're doing linking, so evalute SIZEOF_HEADERS as in a linker script. */ sizeof_headers = bfd_sizeof_headers (abfd, info); else { /* We're not doing linking, so this is objcopy or suchlike. We just need to collect the size of the existing headers. */ struct elf_segment_map *seg; sizeof_headers = bed->s->sizeof_ehdr; for (seg = *m; seg != NULL; seg = seg->next) sizeof_headers += bed->s->sizeof_phdr; } while (*m != NULL) { struct elf_segment_map *seg = *m; if (seg->p_type == PT_LOAD) { bfd_boolean executable = segment_executable (seg); if (executable && seg->count > 0 && seg->sections[0]->vma % bed->minpagesize == 0) { asection *lastsec = seg->sections[seg->count - 1]; bfd_vma end = lastsec->vma + lastsec->size; if (end % bed->minpagesize != 0) { /* This is an executable segment that starts on a page boundary but does not end on a page boundary. Fill it out to a whole page with code fill (the tail of the segment will not be within any section). Thus the entire code segment can be mapped from the file as whole pages and that mapping will contain only valid instructions. To accomplish this, we must fake out the code in assign_file_positions_for_load_sections (elf.c) so that it advances past the rest of the final page, rather than trying to put the next (unaligned, or unallocated) section. We do this by appending a dummy section record to this element in the segment map. No such output section ever actually exists, but this gets the layout logic to advance the file positions past this partial page. Since we are lying to BFD like this, nothing will ever know to write the section contents. So we do that by hand after the fact, in nacl_final_write_processing, below. */ struct elf_segment_map *newseg; asection *sec; struct bfd_elf_section_data *secdata; BFD_ASSERT (!seg->p_size_valid); secdata = bfd_zalloc (abfd, sizeof *secdata); if (secdata == NULL) return FALSE; sec = bfd_zalloc (abfd, sizeof *sec); if (sec == NULL) return FALSE; /* Fill in only the fields that actually affect the logic in assign_file_positions_for_load_sections. */ sec->vma = end; sec->lma = lastsec->lma + lastsec->size; sec->size = bed->minpagesize - (end % bed->minpagesize); sec->flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_LINKER_CREATED); sec->used_by_bfd = secdata; secdata->this_hdr.sh_type = SHT_PROGBITS; secdata->this_hdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR; secdata->this_hdr.sh_addr = sec->vma; secdata->this_hdr.sh_size = sec->size; newseg = bfd_alloc (abfd, sizeof *newseg + ((seg->count + 1) * sizeof (asection *))); if (newseg == NULL) return FALSE; memcpy (newseg, seg, sizeof *newseg + (seg->count * sizeof (asection *))); newseg->sections[newseg->count++] = sec; *m = seg = newseg; } } /* First, we're just finding the earliest PT_LOAD. By the normal rules, this will be the lowest-addressed one. We only have anything interesting to do if it's executable. */ last_load = m; if (first_load == NULL) { if (!executable) goto next; first_load = m; } /* Now that we've noted the first PT_LOAD, we're looking for the first non-executable PT_LOAD with a nonempty p_filesz. */ else if (!moved_headers && segment_eligible_for_headers (seg, bed->minpagesize, sizeof_headers)) { /* This is the one we were looking for! First, clear the flags on previous segments that say they include the file header and phdrs. */ struct elf_segment_map *prevseg; for (prevseg = *first_load; prevseg != seg; prevseg = prevseg->next) if (prevseg->p_type == PT_LOAD) { prevseg->includes_filehdr = 0; prevseg->includes_phdrs = 0; } /* This segment will include those headers instead. */ seg->includes_filehdr = 1; seg->includes_phdrs = 1; moved_headers = TRUE; } } next: m = &seg->next; } if (first_load != last_load && moved_headers) { /* Now swap the first and last PT_LOAD segments' positions in segment_map. */ struct elf_segment_map *first = *first_load; struct elf_segment_map *last = *last_load; *first_load = first->next; first->next = last->next; last->next = first; } return TRUE; }
bfd_boolean _bfd_discard_section_stabs (bfd *abfd, asection *stabsec, void * psecinfo, bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *), void * cookie) { bfd_size_type count, amt; struct stab_section_info *secinfo; bfd_byte *stabbuf = NULL; bfd_byte *sym, *symend; bfd_size_type skip; bfd_size_type *pstridx; int deleting; if (stabsec->size == 0) /* This file does not contain stabs debugging information. */ return FALSE; if (stabsec->size % STABSIZE != 0) /* Something is wrong with the format of these stab symbols. Don't try to optimize them. */ return FALSE; if ((stabsec->output_section != NULL && bfd_is_abs_section (stabsec->output_section))) /* At least one of the sections is being discarded from the link, so we should just ignore them. */ return FALSE; /* We should have initialized our data in _bfd_link_section_stabs. If there was some bizarre error reading the string sections, though, we might not have. Bail rather than asserting. */ if (psecinfo == NULL) return FALSE; count = stabsec->rawsize / STABSIZE; secinfo = (struct stab_section_info *) psecinfo; /* Read the stabs information from abfd. */ if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf)) goto error_return; /* Look through the stabs symbols and discard any information for discarded functions. */ skip = 0; deleting = -1; symend = stabbuf + stabsec->rawsize; for (sym = stabbuf, pstridx = secinfo->stridxs; sym < symend; sym += STABSIZE, ++pstridx) { int type; if (*pstridx == (bfd_size_type) -1) /* This stab was deleted in a previous pass. */ continue; type = sym[TYPEOFF]; if (type == (int) N_FUN) { int strx = bfd_get_32 (abfd, sym + STRDXOFF); if (strx == 0) { if (deleting) { skip++; *pstridx = -1; } deleting = -1; continue; } deleting = 0; if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie)) deleting = 1; } if (deleting == 1) { *pstridx = -1; skip++; } else if (deleting == -1) { /* Outside of a function. Check for deleted variables. */ if (type == (int) N_STSYM || type == (int) N_LCSYM) if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie)) { *pstridx = -1; skip ++; } /* We should also check for N_GSYM entries which reference a deleted global, but those are less harmful to debuggers and would require parsing the stab strings. */ } } free (stabbuf); stabbuf = NULL; /* Shrink the stabsec as needed. */ stabsec->size -= skip * STABSIZE; if (stabsec->size == 0) stabsec->flags |= SEC_EXCLUDE | SEC_KEEP; /* Recalculate the `cumulative_skips' array now that stabs have been deleted for this section. */ if (skip != 0) { bfd_size_type i, offset; bfd_size_type *pskips; if (secinfo->cumulative_skips == NULL) { amt = count * sizeof (bfd_size_type); secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt); if (secinfo->cumulative_skips == NULL) goto error_return; } pskips = secinfo->cumulative_skips; pstridx = secinfo->stridxs; offset = 0; for (i = 0; i < count; i++, pskips++, pstridx++) { *pskips = offset; if (*pstridx == (bfd_size_type) -1) offset += STABSIZE; } BFD_ASSERT (offset != 0); } return skip > 0; error_return: if (stabbuf != NULL) free (stabbuf); return FALSE; }
static int bfd_pef_parse_traceback_table (bfd *abfd, asection *section, unsigned char *buf, size_t len, size_t pos, asymbol *sym, FILE *file) { struct traceback_table table; size_t offset; const char *s; asymbol tmpsymbol; if (sym == NULL) sym = & tmpsymbol; sym->name = NULL; sym->value = 0; sym->the_bfd = abfd; sym->section = section; sym->flags = 0; sym->udata.i = 0; /* memcpy is fine since all fields are unsigned char. */ if ((pos + 8) > len) return -1; memcpy (&table, buf + pos, 8); /* Calling code relies on returned symbols having a name and correct offset. */ if ((table.lang != TB_C) && (table.lang != TB_CPLUSPLUS)) return -1; if (! (table.flags2 & TB_NAME_PRESENT)) return -1; if (! (table.flags1 & TB_HAS_TBOFF)) return -1; offset = 8; if ((table.flags5 & TB_FLOATPARAMS) || (table.fixedparams)) offset += 4; if (table.flags1 & TB_HAS_TBOFF) { struct traceback_table_tboff off; if ((pos + offset + 4) > len) return -1; off.tb_offset = bfd_getb32 (buf + pos + offset); offset += 4; /* Need to subtract 4 because the offset includes the 0x0L preceding the table. */ if (file != NULL) fprintf (file, " [offset = 0x%lx]", off.tb_offset); if ((file == NULL) && ((off.tb_offset + 4) > (pos + offset))) return -1; sym->value = pos - off.tb_offset - 4; } if (table.flags2 & TB_INT_HNDL) offset += 4; if (table.flags1 & TB_HAS_CTL) { struct traceback_table_anchors anchors; if ((pos + offset + 4) > len) return -1; anchors.ctl_info = bfd_getb32 (buf + pos + offset); offset += 4; if (anchors.ctl_info > 1024) return -1; offset += anchors.ctl_info * 4; } if (table.flags2 & TB_NAME_PRESENT) { struct traceback_table_routine name; char *namebuf; if ((pos + offset + 2) > len) return -1; name.name_len = bfd_getb16 (buf + pos + offset); offset += 2; if (name.name_len > 4096) return -1; if ((pos + offset + name.name_len) > len) return -1; namebuf = bfd_alloc (abfd, name.name_len + 1); if (namebuf == NULL) return -1; memcpy (namebuf, buf + pos + offset, name.name_len); namebuf[name.name_len] = '\0'; /* Strip leading period inserted by compiler. */ if (namebuf[0] == '.') memmove (namebuf, namebuf + 1, name.name_len + 1); sym->name = namebuf; for (s = sym->name; (*s != '\0'); s++) if (! ISPRINT (*s)) return -1; offset += name.name_len; } if (table.flags2 & TB_USES_ALLOCA) offset += 4; if (table.flags4 & TB_HAS_VEC_INFO) offset += 4; if (file != NULL) fprintf (file, " [length = 0x%lx]", (unsigned long) offset); return offset; }
/* Get view of the input file. */ static enum ld_plugin_status get_view (const void *handle, const void **viewp) { plugin_input_file_t *input = (plugin_input_file_t *) handle; char *buffer; size_t size = input->filesize; off_t offset = input->offset; #if HAVE_MMAP && HAVE_GETPAGESIZE off_t bias; #endif ASSERT (called_plugin); /* FIXME: einfo should support %lld. */ if ((off_t) size != input->filesize) einfo (_("%P%F: unsupported input file size: %s (%ld bytes)\n"), input->name, (long) input->filesize); /* Check the cached view buffer. */ if (input->view_buffer.addr != NULL && input->view_buffer.filesize == size && input->view_buffer.offset == offset) { *viewp = input->view_buffer.addr; return LDPS_OK; } input->view_buffer.filesize = size; input->view_buffer.offset = offset; #if HAVE_MMAP # if HAVE_GETPAGESIZE bias = offset % plugin_pagesize; offset -= bias; size += bias; # endif buffer = mmap (NULL, size, PROT_READ, MAP_PRIVATE, input->fd, offset); if (buffer != MAP_FAILED) { input->use_mmap = TRUE; # if HAVE_GETPAGESIZE buffer += bias; # endif } else #endif { char *p; input->use_mmap = FALSE; if (lseek (input->fd, offset, SEEK_SET) < 0) return LDPS_ERR; buffer = bfd_alloc (input->abfd, size); if (buffer == NULL) return LDPS_ERR; p = buffer; do { ssize_t got = read (input->fd, p, size); if (got == 0) break; else if (got > 0) { p += got; size -= got; } else if (errno != EINTR) return LDPS_ERR; } while (size > 0); } input->view_buffer.addr = buffer; *viewp = buffer; return LDPS_OK; }
static bfd_size_type bfd_compress_section_contents (bfd *abfd, sec_ptr sec, bfd_byte *uncompressed_buffer, bfd_size_type uncompressed_size) { uLong compressed_size; bfd_byte *buffer; bfd_size_type buffer_size; bfd_boolean decompress; #if defined(__GNUC__) && GCC_VERSION < 4007 /* Work around a GCC uninitialized warning bug fixed in GCC 4.7. */ int zlib_size = 0; #else int zlib_size; #endif int orig_compression_header_size; int compression_header_size = bfd_get_compression_header_size (abfd, NULL); bfd_boolean compressed = bfd_is_section_compressed_with_header (abfd, sec, &orig_compression_header_size); if (compressed) { /* We shouldn't decompress unsupported compressed section. */ if (orig_compression_header_size < 0) abort (); /* Different compression schemes. Just move the compressed section contents to the right position. */ if (orig_compression_header_size == 0) { /* Convert it from .zdebug* section. Get the uncompressed size first. */ zlib_size = uncompressed_size; compressed_size = zlib_size + compression_header_size; uncompressed_size = bfd_getb64 (uncompressed_buffer + 4); } else { /* Convert it to .zdebug* section. */ zlib_size = uncompressed_size - orig_compression_header_size; compressed_size = zlib_size; } } else compressed_size = compressBound (uncompressed_size) + 12; /* When converting from .zdebug* section, uncompress if it leads to smaller size. */ if (compressed && orig_compression_header_size == 0 && compressed_size > uncompressed_size) { decompress = TRUE; buffer_size = uncompressed_size; } else { decompress = FALSE; buffer_size = compressed_size + compression_header_size; } buffer = (bfd_byte *) bfd_alloc (abfd, buffer_size); if (buffer == NULL) return 0; if (compressed) { sec->size = uncompressed_size; if (decompress) { if (!decompress_contents (uncompressed_buffer, zlib_size, buffer, uncompressed_size)) { bfd_set_error (bfd_error_bad_value); bfd_release (abfd, buffer); return 0; } free (uncompressed_buffer); sec->contents = buffer; sec->compress_status = COMPRESS_SECTION_DONE; return uncompressed_size; } else { bfd_update_compression_header (abfd, buffer, sec); memmove (buffer + compression_header_size, uncompressed_buffer + orig_compression_header_size, zlib_size); } } else { bfd_size_type size = uncompressed_size; int header_size = 12 + compression_header_size; if (compress ((Bytef*) buffer + header_size, &compressed_size, (const Bytef*) uncompressed_buffer, uncompressed_size) != Z_OK) { bfd_release (abfd, buffer); bfd_set_error (bfd_error_bad_value); return 0; } compressed_size += header_size; /* PR binutils/18087: If compression didn't make the section smaller, just keep it uncompressed. */ if (compressed_size < uncompressed_size) { bfd_update_compression_header (abfd, buffer, sec); /* Write the zlib header. In this case, it should be "ZLIB" followed by the uncompressed section size, 8 bytes in big-endian order. */ memcpy (buffer + compression_header_size, "ZLIB", 4); bfd_putb64 (size, buffer + compression_header_size + 4); } else { /* NOTE: There is a small memory leak here since uncompressed_buffer is malloced and won't be freed. */ bfd_release (abfd, buffer); sec->contents = uncompressed_buffer; sec->compress_status = COMPRESS_SECTION_NONE; return uncompressed_size; } } free (uncompressed_buffer); sec->contents = buffer; sec->size = compressed_size; sec->compress_status = COMPRESS_SECTION_DONE; return uncompressed_size; }
static bfd_boolean oasys_slurp_symbol_table (bfd *const abfd) { oasys_record_union_type record; oasys_data_type *data = OASYS_DATA (abfd); bfd_boolean loop = TRUE; asymbol *dest_defined; asymbol *dest; char *string_ptr; bfd_size_type amt; if (data->symbols != NULL) return TRUE; /* Buy enough memory for all the symbols and all the names. */ amt = abfd->symcount; amt *= sizeof (asymbol); data->symbols = bfd_alloc (abfd, amt); amt = data->symbol_string_length; #ifdef UNDERSCORE_HACK /* Buy 1 more char for each symbol to keep the underscore in. */ amt += abfd->symcount; #endif data->strings = bfd_alloc (abfd, amt); if (!data->symbols || !data->strings) return FALSE; dest_defined = data->symbols + abfd->symcount - 1; string_ptr = data->strings; if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) return FALSE; while (loop) { if (! oasys_read_record (abfd, &record)) return FALSE; switch (record.header.type) { case oasys_record_is_header_enum: break; case oasys_record_is_local_enum: case oasys_record_is_symbol_enum: { int flag = record.header.type == (int) oasys_record_is_local_enum ? (BSF_LOCAL) : (BSF_GLOBAL | BSF_EXPORT); size_t length = oasys_string_length (&record); switch (record.symbol.relb & RELOCATION_TYPE_BITS) { case RELOCATION_TYPE_ABS: dest = dest_defined--; dest->section = bfd_abs_section_ptr; dest->flags = 0; break; case RELOCATION_TYPE_REL: dest = dest_defined--; dest->section = OASYS_DATA (abfd)->sections[record.symbol.relb & RELOCATION_SECT_BITS]; if (record.header.type == (int) oasys_record_is_local_enum) { dest->flags = BSF_LOCAL; if (dest->section == (asection *) (~0)) { /* It seems that sometimes internal symbols are tied up, but still get output, even though there is no section */ dest->section = 0; } } else dest->flags = flag; break; case RELOCATION_TYPE_UND: dest = data->symbols + H_GET_16 (abfd, record.symbol.refno); dest->section = bfd_und_section_ptr; break; case RELOCATION_TYPE_COM: dest = dest_defined--; dest->name = string_ptr; dest->the_bfd = abfd; dest->section = bfd_com_section_ptr; break; default: dest = dest_defined--; BFD_ASSERT (FALSE); break; } dest->name = string_ptr; dest->the_bfd = abfd; dest->udata.p = NULL; dest->value = H_GET_32 (abfd, record.symbol.value); #ifdef UNDERSCORE_HACK if (record.symbol.name[0] != '_') { string_ptr[0] = '_'; string_ptr++; } #endif memcpy (string_ptr, record.symbol.name, length); string_ptr[length] = 0; string_ptr += length + 1; } break; default: loop = FALSE; } } return TRUE; }
static const bfd_target * plugin_object_p (bfd *ibfd) { int claimed; plugin_input_file_t *input; struct ld_plugin_input_file file; bfd *abfd; /* Don't try the dummy object file. */ if ((ibfd->flags & BFD_PLUGIN) != 0) return NULL; if (ibfd->plugin_format != bfd_plugin_unknown) { if (ibfd->plugin_format == bfd_plugin_yes) return ibfd->plugin_dummy_bfd->xvec; else return NULL; } /* We create a dummy BFD, initially empty, to house whatever symbols the plugin may want to add. */ abfd = plugin_get_ir_dummy_bfd (ibfd->filename, ibfd); input = bfd_alloc (abfd, sizeof (*input)); if (input == NULL) einfo (_("%P%F: plugin failed to allocate memory for input: %s\n"), bfd_get_error ()); if (!bfd_plugin_open_input (ibfd, &file)) return NULL; if (file.name == ibfd->filename) { /* We must copy filename attached to ibfd if it is not an archive member since it may be freed by bfd_close below. */ file.name = plugin_strdup (abfd, file.name); } file.handle = input; /* The plugin API expects that the file descriptor won't be closed and reused as done by the bfd file cache. So dup one. */ file.fd = dup (file.fd); if (file.fd < 0) return NULL; input->abfd = abfd; input->view_buffer.addr = NULL; input->view_buffer.filesize = 0; input->view_buffer.offset = 0; input->fd = file.fd; input->use_mmap = FALSE; input->offset = file.offset; input->filesize = file.filesize; input->name = plugin_strdup (abfd, ibfd->filename); claimed = 0; if (plugin_call_claim_file (&file, &claimed)) einfo (_("%P%F: %s: plugin reported error claiming file\n"), plugin_error_plugin ()); if (input->fd != -1 && !bfd_plugin_target_p (ibfd->xvec)) { /* FIXME: fd belongs to us, not the plugin. GCC plugin, which doesn't need fd after plugin_call_claim_file, doesn't use BFD plugin target vector. Since GCC plugin doesn't call release_input_file, we close it here. LLVM plugin, which needs fd after plugin_call_claim_file and calls release_input_file after it is done, uses BFD plugin target vector. This scheme doesn't work when a plugin needs fd and doesn't use BFD plugin target vector neither. */ close (input->fd); input->fd = -1; } if (claimed) { ibfd->plugin_format = bfd_plugin_yes; ibfd->plugin_dummy_bfd = abfd; bfd_make_readable (abfd); return abfd->xvec; } else { #if HAVE_MMAP if (input->use_mmap) { /* If plugin didn't claim the file, unmap the buffer. */ char *addr = input->view_buffer.addr; off_t size = input->view_buffer.filesize; # if HAVE_GETPAGESIZE off_t bias = input->view_buffer.offset % plugin_pagesize; size += bias; addr -= bias; # endif munmap (addr, size); } #endif /* If plugin didn't claim the file, we don't need the dummy bfd. Can't avoid speculatively creating it, alas. */ ibfd->plugin_format = bfd_plugin_no; bfd_close_all_done (abfd); return NULL; } }
bfd_boolean _bfd_link_section_stabs (bfd *abfd, struct stab_info *sinfo, asection *stabsec, asection *stabstrsec, void * *psecinfo, bfd_size_type *pstring_offset) { bfd_boolean first; bfd_size_type count, amt; struct stab_section_info *secinfo; bfd_byte *stabbuf = NULL; bfd_byte *stabstrbuf = NULL; bfd_byte *sym, *symend; bfd_size_type stroff, next_stroff, skip; bfd_size_type *pstridx; if (stabsec->size == 0 || stabstrsec->size == 0) /* This file does not contain stabs debugging information. */ return TRUE; if (stabsec->size % STABSIZE != 0) /* Something is wrong with the format of these stab symbols. Don't try to optimize them. */ return TRUE; if ((stabstrsec->flags & SEC_RELOC) != 0) /* We shouldn't see relocations in the strings, and we aren't prepared to handle them. */ return TRUE; if (bfd_is_abs_section (stabsec->output_section) || bfd_is_abs_section (stabstrsec->output_section)) /* At least one of the sections is being discarded from the link, so we should just ignore them. */ return TRUE; first = FALSE; if (sinfo->stabstr == NULL) { flagword flags; /* Initialize the stabs information we need to keep track of. */ first = TRUE; sinfo->strings = _bfd_stringtab_init (); if (sinfo->strings == NULL) goto error_return; /* Make sure the first byte is zero. */ (void) _bfd_stringtab_add (sinfo->strings, "", TRUE, TRUE); if (! bfd_hash_table_init (&sinfo->includes, stab_link_includes_newfunc, sizeof (struct stab_link_includes_entry))) goto error_return; flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING | SEC_LINKER_CREATED); sinfo->stabstr = bfd_make_section_anyway_with_flags (abfd, ".stabstr", flags); if (sinfo->stabstr == NULL) goto error_return; } /* Initialize the information we are going to store for this .stab section. */ count = stabsec->size / STABSIZE; amt = sizeof (struct stab_section_info); amt += (count - 1) * sizeof (bfd_size_type); *psecinfo = bfd_alloc (abfd, amt); if (*psecinfo == NULL) goto error_return; secinfo = (struct stab_section_info *) *psecinfo; secinfo->excls = NULL; stabsec->rawsize = stabsec->size; secinfo->cumulative_skips = NULL; memset (secinfo->stridxs, 0, (size_t) count * sizeof (bfd_size_type)); /* Read the stabs information from abfd. */ if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf) || !bfd_malloc_and_get_section (abfd, stabstrsec, &stabstrbuf)) goto error_return; /* Look through the stabs symbols, work out the new string indices, and identify N_BINCL symbols which can be eliminated. */ stroff = 0; /* The stabs sections can be split when -split-by-reloc/-split-by-file is used. We must keep track of each stab section's place in the single concatenated string table. */ next_stroff = pstring_offset ? *pstring_offset : 0; skip = 0; symend = stabbuf + stabsec->size; for (sym = stabbuf, pstridx = secinfo->stridxs; sym < symend; sym += STABSIZE, ++pstridx) { bfd_size_type symstroff; int type; const char *string; if (*pstridx != 0) /* This symbol has already been handled by an N_BINCL pass. */ continue; type = sym[TYPEOFF]; if (type == 0) { /* Special type 0 stabs indicate the offset to the next string table. We only copy the very first one. */ stroff = next_stroff; next_stroff += bfd_get_32 (abfd, sym + 8); if (pstring_offset) *pstring_offset = next_stroff; if (! first) { *pstridx = (bfd_size_type) -1; ++skip; continue; } first = FALSE; } /* Store the string in the hash table, and record the index. */ symstroff = stroff + bfd_get_32 (abfd, sym + STRDXOFF); if (symstroff >= stabstrsec->size) { _bfd_error_handler /* xgettext:c-format */ (_("%B(%A+0x%lx): Stabs entry has invalid string index."), abfd, stabsec, (long) (sym - stabbuf)); bfd_set_error (bfd_error_bad_value); goto error_return; } string = (char *) stabstrbuf + symstroff; *pstridx = _bfd_stringtab_add (sinfo->strings, string, TRUE, TRUE); /* An N_BINCL symbol indicates the start of the stabs entries for a header file. We need to scan ahead to the next N_EINCL symbol, ignoring nesting, adding up all the characters in the symbol names, not including the file numbers in types (the first number after an open parenthesis). */ if (type == (int) N_BINCL) { bfd_vma sum_chars; bfd_vma num_chars; bfd_vma buf_len = 0; char * symb; char * symb_rover; int nest; bfd_byte * incl_sym; struct stab_link_includes_entry * incl_entry; struct stab_link_includes_totals * t; struct stab_excl_list * ne; symb = symb_rover = NULL; sum_chars = num_chars = 0; nest = 0; for (incl_sym = sym + STABSIZE; incl_sym < symend; incl_sym += STABSIZE) { int incl_type; incl_type = incl_sym[TYPEOFF]; if (incl_type == 0) break; else if (incl_type == (int) N_EXCL) continue; else if (incl_type == (int) N_EINCL) { if (nest == 0) break; --nest; } else if (incl_type == (int) N_BINCL) ++nest; else if (nest == 0) { const char *str; str = ((char *) stabstrbuf + stroff + bfd_get_32 (abfd, incl_sym + STRDXOFF)); for (; *str != '\0'; str++) { if (num_chars >= buf_len) { buf_len += 32 * 1024; symb = (char *) bfd_realloc_or_free (symb, buf_len); if (symb == NULL) goto error_return; symb_rover = symb + num_chars; } * symb_rover ++ = * str; sum_chars += *str; num_chars ++; if (*str == '(') { /* Skip the file number. */ ++str; while (ISDIGIT (*str)) ++str; --str; } } } } BFD_ASSERT (num_chars == (bfd_vma) (symb_rover - symb)); /* If we have already included a header file with the same value, then replaced this one with an N_EXCL symbol. */ incl_entry = (struct stab_link_includes_entry * ) bfd_hash_lookup (&sinfo->includes, string, TRUE, TRUE); if (incl_entry == NULL) goto error_return; for (t = incl_entry->totals; t != NULL; t = t->next) if (t->sum_chars == sum_chars && t->num_chars == num_chars && memcmp (t->symb, symb, num_chars) == 0) break; /* Record this symbol, so that we can set the value correctly. */ amt = sizeof *ne; ne = (struct stab_excl_list *) bfd_alloc (abfd, amt); if (ne == NULL) goto error_return; ne->offset = sym - stabbuf; ne->val = sum_chars; ne->type = (int) N_BINCL; ne->next = secinfo->excls; secinfo->excls = ne; if (t == NULL) { /* This is the first time we have seen this header file with this set of stabs strings. */ t = (struct stab_link_includes_totals *) bfd_hash_allocate (&sinfo->includes, sizeof *t); if (t == NULL) goto error_return; t->sum_chars = sum_chars; t->num_chars = num_chars; /* Trim data down. */ t->symb = symb = (char *) bfd_realloc_or_free (symb, num_chars); t->next = incl_entry->totals; incl_entry->totals = t; } else { bfd_size_type *incl_pstridx; /* We have seen this header file before. Tell the final pass to change the type to N_EXCL. */ ne->type = (int) N_EXCL; /* Free off superfluous symbols. */ free (symb); /* Mark the skipped symbols. */ nest = 0; for (incl_sym = sym + STABSIZE, incl_pstridx = pstridx + 1; incl_sym < symend; incl_sym += STABSIZE, ++incl_pstridx) { int incl_type; incl_type = incl_sym[TYPEOFF]; if (incl_type == (int) N_EINCL) { if (nest == 0) { *incl_pstridx = (bfd_size_type) -1; ++skip; break; } --nest; } else if (incl_type == (int) N_BINCL) ++nest; else if (incl_type == (int) N_EXCL) /* Keep existing exclusion marks. */ continue; else if (nest == 0) { *incl_pstridx = (bfd_size_type) -1; ++skip; } } } } } free (stabbuf); stabbuf = NULL; free (stabstrbuf); stabstrbuf = NULL; /* We need to set the section sizes such that the linker will compute the output section sizes correctly. We set the .stab size to not include the entries we don't want. We set SEC_EXCLUDE for the .stabstr section, so that it will be dropped from the link. We record the size of the strtab in the first .stabstr section we saw, and make sure we don't set SEC_EXCLUDE for that section. */ stabsec->size = (count - skip) * STABSIZE; if (stabsec->size == 0) stabsec->flags |= SEC_EXCLUDE | SEC_KEEP; stabstrsec->flags |= SEC_EXCLUDE | SEC_KEEP; sinfo->stabstr->size = _bfd_stringtab_size (sinfo->strings); /* Calculate the `cumulative_skips' array now that stabs have been deleted for this section. */ if (skip != 0) { bfd_size_type i, offset; bfd_size_type *pskips; amt = count * sizeof (bfd_size_type); secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt); if (secinfo->cumulative_skips == NULL) goto error_return; pskips = secinfo->cumulative_skips; pstridx = secinfo->stridxs; offset = 0; for (i = 0; i < count; i++, pskips++, pstridx++) { *pskips = offset; if (*pstridx == (bfd_size_type) -1) offset += STABSIZE; } BFD_ASSERT (offset != 0); } return TRUE; error_return: if (stabbuf != NULL) free (stabbuf); if (stabstrbuf != NULL) free (stabstrbuf); return FALSE; }
static bfd_boolean vms_initialize (bfd * abfd) { int i; bfd_size_type amt; bfd_set_start_address(abfd, (bfd_vma)-1); amt = sizeof(struct vms_private_data_struct); abfd->tdata.any = bfd_alloc(abfd, amt); if (abfd->tdata.any == NULL) { return FALSE; } #ifdef __ALPHA PRIV(is_vax) = FALSE; #else PRIV(is_vax) = TRUE; #endif /* __ALPHA */ PRIV(vms_buf) = NULL; PRIV(buf_size) = 0; PRIV(rec_length) = 0; PRIV(file_format) = FF_UNKNOWN; PRIV(fixup_done) = FALSE; PRIV(sections) = NULL; amt = (sizeof(struct stack_struct) * STACKSIZE); PRIV(stack) = (struct stack_struct *)bfd_alloc(abfd, amt); if (PRIV(stack) == NULL) { goto error_ret1; } PRIV(stackptr) = 0; amt = sizeof(struct bfd_hash_table); PRIV(vms_symbol_table) = (struct bfd_hash_table *)bfd_alloc(abfd, amt); if (PRIV (vms_symbol_table) == NULL) goto error_ret1; if (!bfd_hash_table_init (PRIV (vms_symbol_table), _bfd_vms_hash_newfunc)) goto error_ret1; amt = sizeof(struct location_struct) * LOCATION_SAVE_SIZE; PRIV(location_stack) = (struct location_struct *)bfd_alloc(abfd, amt); if (PRIV(location_stack) == NULL) { goto error_ret2; } for ((i = 0); (i < VMS_SECTION_COUNT); i++) { PRIV(vms_section_table)[i] = NULL; } amt = MAX_OUTREC_SIZE; PRIV(output_buf) = (unsigned char *)bfd_alloc(abfd, amt); if (PRIV(output_buf) == NULL) { goto error_ret2; } PRIV (push_level) = 0; PRIV (pushed_size) = 0; PRIV (length_pos) = 2; PRIV (output_size) = 0; PRIV (output_alignment) = 1; return TRUE; error_ret2: bfd_hash_table_free (PRIV (vms_symbol_table)); error_ret1: bfd_release (abfd, abfd->tdata.any); abfd->tdata.any = NULL; return FALSE; }
bfd_boolean bfd_elf64_archive_slurp_armap (bfd *abfd) { struct artdata *ardata = bfd_ardata (abfd); char nextname[17]; bfd_size_type i, parsed_size, nsymz, stringsize, carsym_size, ptrsize; struct areltdata *mapdata; bfd_byte int_buf[8]; char *stringbase; char *stringend; bfd_byte *raw_armap = NULL; carsym *carsyms; bfd_size_type amt; ardata->symdefs = NULL; /* Get the name of the first element. */ i = bfd_bread (nextname, 16, abfd); if (i == 0) return TRUE; if (i != 16) return FALSE; if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0) return FALSE; /* Archives with traditional armaps are still permitted. */ if (CONST_STRNEQ (nextname, "/ ")) return bfd_slurp_armap (abfd); if (! CONST_STRNEQ (nextname, "/SYM64/ ")) { bfd_has_map (abfd) = FALSE; return TRUE; } mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd); if (mapdata == NULL) return FALSE; parsed_size = mapdata->parsed_size; free (mapdata); if (bfd_bread (int_buf, 8, abfd) != 8) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_malformed_archive); return FALSE; } nsymz = bfd_getb64 (int_buf); stringsize = parsed_size - 8 * nsymz - 8; carsym_size = nsymz * sizeof (carsym); ptrsize = 8 * nsymz; amt = carsym_size + stringsize + 1; if (carsym_size < nsymz || ptrsize < nsymz || amt < nsymz) { bfd_set_error (bfd_error_malformed_archive); return FALSE; } ardata->symdefs = (struct carsym *) bfd_zalloc (abfd, amt); if (ardata->symdefs == NULL) return FALSE; carsyms = ardata->symdefs; stringbase = ((char *) ardata->symdefs) + carsym_size; stringbase[stringsize] = 0; stringend = stringbase + stringsize; raw_armap = (bfd_byte *) bfd_alloc (abfd, ptrsize); if (raw_armap == NULL) goto release_symdefs; if (bfd_bread (raw_armap, ptrsize, abfd) != ptrsize || bfd_bread (stringbase, stringsize, abfd) != stringsize) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_malformed_archive); goto release_raw_armap; } for (i = 0; i < nsymz; i++) { carsyms->file_offset = bfd_getb64 (raw_armap + i * 8); carsyms->name = stringbase; if (stringbase < stringend) stringbase += strlen (stringbase) + 1; ++carsyms; } *stringbase = '\0'; ardata->symdef_count = nsymz; ardata->first_file_filepos = bfd_tell (abfd); /* Pad to an even boundary if you have to. */ ardata->first_file_filepos += (ardata->first_file_filepos) % 2; bfd_has_map (abfd) = TRUE; bfd_release (abfd, raw_armap); return TRUE; release_raw_armap: bfd_release (abfd, raw_armap); release_symdefs: bfd_release (abfd, ardata->symdefs); return FALSE; }
static const bfd_target * plugin_object_p (bfd *ibfd) { int claimed; plugin_input_file_t *input; off_t offset, filesize; struct ld_plugin_input_file file; bfd *abfd; bfd_boolean inarchive; const char *name; int fd; /* Don't try the dummy object file. */ if ((ibfd->flags & BFD_PLUGIN) != 0) return NULL; if (ibfd->plugin_format != bfd_plugin_uknown) { if (ibfd->plugin_format == bfd_plugin_yes) return ibfd->plugin_dummy_bfd->xvec; else return NULL; } inarchive = bfd_my_archive (ibfd) != NULL; name = inarchive ? bfd_my_archive (ibfd)->filename : ibfd->filename; fd = open (name, O_RDONLY | O_BINARY); if (fd < 0) return NULL; /* We create a dummy BFD, initially empty, to house whatever symbols the plugin may want to add. */ abfd = plugin_get_ir_dummy_bfd (ibfd->filename, ibfd); input = bfd_alloc (abfd, sizeof (*input)); if (input == NULL) einfo (_("%P%F: plugin failed to allocate memory for input: %s\n"), bfd_get_error ()); if (inarchive) { /* Offset and filesize must refer to the individual archive member, not the whole file, and must exclude the header. Fortunately for us, that is how the data is stored in the origin field of the bfd and in the arelt_data. */ offset = ibfd->origin; filesize = arelt_size (ibfd); } else { offset = 0; filesize = lseek (fd, 0, SEEK_END); /* We must copy filename attached to ibfd if it is not an archive member since it may be freed by bfd_close below. */ name = plugin_strdup (abfd, name); } file.name = name; file.offset = offset; file.filesize = filesize; file.fd = fd; file.handle = input; input->abfd = abfd; input->view_buffer.addr = NULL; input->view_buffer.filesize = 0; input->view_buffer.offset = 0; input->fd = fd; input->use_mmap = FALSE; input->offset = offset; input->filesize = filesize; input->name = plugin_strdup (abfd, ibfd->filename); claimed = 0; if (plugin_call_claim_file (&file, &claimed)) einfo (_("%P%F: %s: plugin reported error claiming file\n"), plugin_error_plugin ()); if (input->fd != -1 && ! bfd_plugin_target_p (ibfd->xvec)) { /* FIXME: fd belongs to us, not the plugin. GCC plugin, which doesn't need fd after plugin_call_claim_file, doesn't use BFD plugin target vector. Since GCC plugin doesn't call release_input_file, we close it here. LLVM plugin, which needs fd after plugin_call_claim_file and calls release_input_file after it is done, uses BFD plugin target vector. This scheme doesn't work when a plugin needs fd and doesn't use BFD plugin target vector neither. */ close (fd); input->fd = -1; } if (claimed) { ibfd->plugin_format = bfd_plugin_yes; ibfd->plugin_dummy_bfd = abfd; bfd_make_readable (abfd); return abfd->xvec; } else { #if HAVE_MMAP if (input->use_mmap) { /* If plugin didn't claim the file, unmap the buffer. */ char *addr = input->view_buffer.addr; off_t size = input->view_buffer.filesize; # if HAVE_GETPAGESIZE off_t bias = input->view_buffer.offset % plugin_pagesize; size += bias; addr -= bias; # endif munmap (addr, size); } #endif /* If plugin didn't claim the file, we don't need the dummy bfd. Can't avoid speculatively creating it, alas. */ ibfd->plugin_format = bfd_plugin_no; bfd_close_all_done (abfd); return NULL; } }
static bfd_boolean parse_line_table (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit) { bfd_byte *xptr; /* Load the ".line" section from the bfd if we haven't already. */ if (stash->line_section == 0) { asection *msec; bfd_size_type size; msec = bfd_get_section_by_name (stash->abfd, ".line"); if (! msec) return FALSE; size = msec->rawsize ? msec->rawsize : msec->size; stash->line_section = bfd_simple_get_relocated_section_contents (stash->abfd, msec, NULL, stash->syms); if (! stash->line_section) return FALSE; stash->line_section_end = stash->line_section + size; } xptr = stash->line_section + aUnit->stmt_list_offset; if (xptr < stash->line_section_end) { unsigned long eachLine; bfd_byte *tblend; unsigned long base; bfd_size_type amt; /* First comes the length. */ tblend = bfd_get_32 (stash->abfd, (bfd_byte *) xptr) + xptr; xptr += 4; /* Then the base address for each address in the table. */ base = bfd_get_32 (stash->abfd, (bfd_byte *) xptr); xptr += 4; /* How many line entrys? 10 = 4 (line number) + 2 (pos in line) + 4 (address in line). */ aUnit->line_count = (tblend - xptr) / 10; /* Allocate an array for the entries. */ amt = sizeof (struct linenumber) * aUnit->line_count; aUnit->linenumber_table = (struct linenumber *) bfd_alloc (stash->abfd, amt); if (!aUnit->linenumber_table) return FALSE; for (eachLine = 0; eachLine < aUnit->line_count; eachLine++) { /* A line number. */ aUnit->linenumber_table[eachLine].linenumber = bfd_get_32 (stash->abfd, (bfd_byte *) xptr); xptr += 4; /* Skip the position within the line. */ xptr += 2; /* And finally the address. */ aUnit->linenumber_table[eachLine].addr = base + bfd_get_32 (stash->abfd, (bfd_byte *) xptr); xptr += 4; } } return TRUE; }
static bfd_boolean oasys_slurp_section_data (bfd *const abfd) { oasys_record_union_type record; oasys_data_type *data = OASYS_DATA (abfd); bfd_boolean loop = TRUE; oasys_per_section_type *per; asection *s; bfd_size_type amt; /* See if the data has been slurped already. */ for (s = abfd->sections; s != NULL; s = s->next) { per = oasys_per_section (s); if (per->initialized) return TRUE; } if (data->first_data_record == 0) return TRUE; if (bfd_seek (abfd, data->first_data_record, SEEK_SET) != 0) return FALSE; while (loop) { if (! oasys_read_record (abfd, &record)) return FALSE; switch (record.header.type) { case oasys_record_is_header_enum: break; case oasys_record_is_data_enum: { bfd_byte *src = record.data.data; bfd_byte *end_src = ((bfd_byte *) & record) + record.header.length; bfd_byte *dst_ptr; bfd_byte *dst_base_ptr; unsigned int relbit; unsigned int count; asection *section = data->sections[record.data.relb & RELOCATION_SECT_BITS]; bfd_vma dst_offset; per = oasys_per_section (section); if (! per->initialized) { arelent **relpp; per->data = bfd_zalloc (abfd, section->size); if (!per->data) return FALSE; relpp = §ion->relocation; per->reloc_tail_ptr = (oasys_reloc_type **) relpp; per->had_vma = FALSE; per->initialized = TRUE; section->reloc_count = 0; section->flags = SEC_ALLOC; } dst_offset = H_GET_32 (abfd, record.data.addr); if (! per->had_vma) { /* Take the first vma we see as the base. */ section->vma = dst_offset; per->had_vma = TRUE; } dst_offset -= section->vma; dst_base_ptr = oasys_per_section (section)->data; dst_ptr = oasys_per_section (section)->data + dst_offset; if (src < end_src) section->flags |= SEC_LOAD | SEC_HAS_CONTENTS; while (src < end_src) { unsigned char mod_byte = *src++; size_t gap = end_src - src; count = 8; if (mod_byte == 0 && gap >= 8) { dst_ptr[0] = src[0]; dst_ptr[1] = src[1]; dst_ptr[2] = src[2]; dst_ptr[3] = src[3]; dst_ptr[4] = src[4]; dst_ptr[5] = src[5]; dst_ptr[6] = src[6]; dst_ptr[7] = src[7]; dst_ptr += 8; src += 8; } else { for (relbit = 1; count-- != 0 && src < end_src; relbit <<= 1) { if (relbit & mod_byte) { unsigned char reloc = *src; /* This item needs to be relocated. */ switch (reloc & RELOCATION_TYPE_BITS) { case RELOCATION_TYPE_ABS: break; case RELOCATION_TYPE_REL: { /* Relocate the item relative to the section. */ oasys_reloc_type *r; amt = sizeof (oasys_reloc_type); r = bfd_alloc (abfd, amt); if (!r) return FALSE; *(per->reloc_tail_ptr) = r; per->reloc_tail_ptr = &r->next; r->next = NULL; /* Reference to undefined symbol. */ src++; /* There is no symbol. */ r->symbol = 0; /* Work out the howto. */ abort (); r->relent.address = dst_ptr - dst_base_ptr; r->relent.howto = &howto_table[reloc >> 6]; r->relent.sym_ptr_ptr = NULL; section->reloc_count++; /* Fake up the data to look like it's got the -ve pc in it, this makes it much easier to convert into other formats. This is done by hitting the addend. */ if (r->relent.howto->pc_relative) r->relent.addend -= dst_ptr - dst_base_ptr; } break; case RELOCATION_TYPE_UND: { oasys_reloc_type *r; amt = sizeof (oasys_reloc_type); r = bfd_alloc (abfd, amt); if (!r) return FALSE; *(per->reloc_tail_ptr) = r; per->reloc_tail_ptr = &r->next; r->next = NULL; /* Reference to undefined symbol. */ src++; /* Get symbol number. */ r->symbol = (src[0] << 8) | src[1]; /* Work out the howto. */ abort (); r->relent.addend = 0; r->relent.address = dst_ptr - dst_base_ptr; r->relent.howto = &howto_table[reloc >> 6]; r->relent.sym_ptr_ptr = NULL; section->reloc_count++; src += 2; /* Fake up the data to look like it's got the -ve pc in it, this makes it much easier to convert into other formats. This is done by hitting the addend. */ if (r->relent.howto->pc_relative) r->relent.addend -= dst_ptr - dst_base_ptr; } break; case RELOCATION_TYPE_COM: BFD_FAIL (); } } *dst_ptr++ = *src++; } } } } break; case oasys_record_is_local_enum: case oasys_record_is_symbol_enum: case oasys_record_is_section_enum: break; default: loop = FALSE; } }
const bfd_target * lynx_core_file_p (bfd *abfd) { int secnum; struct pssentry pss; bfd_size_type tcontext_size; core_st_t *threadp; int pagesize; asection *newsect; bfd_size_type amt; pagesize = getpagesize (); /* Serious cross-target issue here... This really needs to come from a system-specific header file. */ /* Get the pss entry from the core file */ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) return NULL; amt = sizeof pss; if (bfd_bread ((void *) &pss, amt, abfd) != amt) { /* Too small to be a core file */ if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_wrong_format); return NULL; } amt = sizeof (struct lynx_core_struct); core_hdr (abfd) = (struct lynx_core_struct *) bfd_zalloc (abfd, amt); if (!core_hdr (abfd)) return NULL; strncpy (core_command (abfd), pss.pname, PNMLEN + 1); /* Compute the size of the thread contexts */ tcontext_size = pss.threadcnt * sizeof (core_st_t); /* Allocate space for the thread contexts */ threadp = (core_st_t *) bfd_alloc (abfd, tcontext_size); if (!threadp) goto fail; /* Save thread contexts */ if (bfd_seek (abfd, (file_ptr) pagesize, SEEK_SET) != 0) goto fail; if (bfd_bread ((void *) threadp, tcontext_size, abfd) != tcontext_size) { /* Probably too small to be a core file */ if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_wrong_format); goto fail; } core_signal (abfd) = threadp->currsig; newsect = make_bfd_asection (abfd, ".stack", SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS, pss.ssize, pss.slimit, pagesize + tcontext_size); if (!newsect) goto fail; newsect = make_bfd_asection (abfd, ".data", SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS, pss.data_len + pss.bss_len, pss.data_start, pagesize + tcontext_size + pss.ssize #if defined (SPARC) || defined (__SPARC__) /* SPARC Lynx seems to start dumping the .data section at a page boundary. It's OK to check a #define like SPARC here because this file can only be compiled on a Lynx host. */ + pss.data_start % pagesize #endif ); if (!newsect) goto fail; /* And, now for the .reg/XXX pseudo sections. Each thread has it's own .reg/XXX section, where XXX is the thread id (without leading zeros). The currently running thread (at the time of the core dump) also has an alias called `.reg' (just to keep GDB happy). Note that we use `.reg/XXX' as opposed to `.regXXX' because GDB expects that .reg2 will be the floating- point registers. */ newsect = make_bfd_asection (abfd, ".reg", SEC_HAS_CONTENTS, sizeof (core_st_t), 0, pagesize); if (!newsect) goto fail; for (secnum = 0; secnum < pss.threadcnt; secnum++) { char secname[100]; sprintf (secname, ".reg/%d", BUILDPID (0, threadp[secnum].tid)); newsect = make_bfd_asection (abfd, secname, SEC_HAS_CONTENTS, sizeof (core_st_t), 0, pagesize + secnum * sizeof (core_st_t)); if (!newsect) goto fail; } return abfd->xvec; fail: bfd_release (abfd, core_hdr (abfd)); core_hdr (abfd) = NULL; bfd_section_list_clear (abfd); return NULL; }