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; }
/******************************************************* Function: extract_archive_member Given an archive of WHIRL objects, extract the one specified and put it into a separate file. *******************************************************/ static int extract_archive_member (bfd *abfd, string path) { int fd = -1; int mode = 0666; pointer addr = (pointer)-1; struct areltdata *p_areltdata = (struct areltdata *)abfd->arelt_data; struct ar_hdr *p_hdr = arch_hdr(abfd); if ((fd = OPEN (path, O_RDWR|O_CREAT|O_TRUNC, mode)) != -1) addr = (pointer) MMAP ( 0, p_hdr->ar_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (fd == -1 || addr == (pointer)-1 || FCHMOD (fd, mode) != 0 ) { perror("cannot create intermediate file"); return -1; } CLOSE (fd); MEMCPY (addr, bfd_tell(abfd), p_hdr->ar_size); MUNMAP (addr, p_hdr->ar_size); return 0; } /* extract_archive_member */
static const struct bfd_target * vms_object_p (bfd * abfd) { int err = 0; int prev_type; const struct bfd_target *target_vector = NULL; const bfd_arch_info_type *arch = NULL; void * tdata_save = abfd->tdata.any; bfd_vma saddr_save = bfd_get_start_address (abfd); #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug(1, "vms_object_p (%p)\n", (void *)abfd); #endif if (!vms_initialize (abfd)) goto error_ret; if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET)) goto err_wrong_format; prev_type = -1; do { #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug(7, "reading at %08lx\n", (unsigned long)bfd_tell(abfd)); #endif if (_bfd_vms_next_record (abfd) < 0) { #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (2, "next_record failed\n"); #endif goto err_wrong_format; } if ((prev_type == EOBJ_S_C_EGSD) && (PRIV (rec_type) != EOBJ_S_C_EGSD)) { if (! vms_fixup_sections (abfd)) { #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (2, "vms_fixup_sections failed\n"); #endif goto err_wrong_format; } } prev_type = PRIV (rec_type); if (target_vector == NULL) { if (prev_type <= OBJ_S_C_MAXRECTYP) target_vector = &vms_vax_vec; else target_vector = &vms_alpha_vec; } switch (prev_type) { case OBJ_S_C_HDR: case EOBJ_S_C_EMH: err = _bfd_vms_slurp_hdr (abfd, prev_type); break; case OBJ_S_C_EOM: case OBJ_S_C_EOMW: case EOBJ_S_C_EEOM: err = _bfd_vms_slurp_eom (abfd, prev_type); break; case OBJ_S_C_GSD: case EOBJ_S_C_EGSD: err = _bfd_vms_slurp_gsd (abfd, prev_type); break; case OBJ_S_C_TIR: case EOBJ_S_C_ETIR: err = _bfd_vms_slurp_tir (abfd, prev_type); break; case OBJ_S_C_DBG: case EOBJ_S_C_EDBG: err = _bfd_vms_slurp_dbg (abfd, prev_type); break; case OBJ_S_C_TBT: case EOBJ_S_C_ETBT: err = _bfd_vms_slurp_tbt (abfd, prev_type); break; case OBJ_S_C_LNK: err = _bfd_vms_slurp_lnk (abfd, prev_type); break; default: err = -1; } if (err != 0) { #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (2, "slurp type %d failed with %d\n", prev_type, err); #endif goto err_wrong_format; } } while ((prev_type != EOBJ_S_C_EEOM) && (prev_type != OBJ_S_C_EOM) && (prev_type != OBJ_S_C_EOMW)); if (target_vector == & vms_vax_vec) { if (! vms_fixup_sections (abfd)) { #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (2, "vms_fixup_sections failed\n"); #endif goto err_wrong_format; } /* Set arch_info to vax. */ arch = bfd_scan_arch ("vax"); PRIV (is_vax) = TRUE; #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (2, "arch is vax\n"); #endif } else if (target_vector == &vms_alpha_vec) { /* Set arch_info to alpha: */ const char *alphastr = "alpha"; arch = bfd_scan_arch(alphastr); PRIV (is_vax) = FALSE; #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug(2, "arch is %s\n", alphastr); #endif /* VMS_DEBUG */ } if (arch == NULL) { #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (2, "arch not found\n"); #endif goto err_wrong_format; } abfd->arch_info = arch; return target_vector; err_wrong_format: bfd_set_error (bfd_error_wrong_format); error_ret: if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL) bfd_release (abfd, abfd->tdata.any); abfd->tdata.any = tdata_save; bfd_set_start_address (abfd, saddr_save); return NULL; }
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; }
int bfd_seek (bfd *abfd, file_ptr position, int direction) { int result; file_ptr file_position; /* For the time being, a BFD may not seek to it's end. The problem is that we don't easily have a way to recognize the end of an element in an archive. */ BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR); if (direction == SEEK_CUR && position == 0) return 0; if ((abfd->flags & BFD_IN_MEMORY) != 0) { struct bfd_in_memory *bim; bim = abfd->iostream; if (direction == SEEK_SET) abfd->where = position; else abfd->where += position; if (abfd->where > bim->size) { if ((abfd->direction == write_direction) || (abfd->direction == both_direction)) { bfd_size_type newsize, oldsize; oldsize = (bim->size + 127) & ~(bfd_size_type) 127; bim->size = abfd->where; /* Round up to cut down on memory fragmentation */ newsize = (bim->size + 127) & ~(bfd_size_type) 127; if (newsize > oldsize) { bim->buffer = bfd_realloc_or_free (bim->buffer, newsize); if (bim->buffer == NULL) { bim->size = 0; return -1; } } } else { abfd->where = bim->size; bfd_set_error (bfd_error_file_truncated); return -1; } } return 0; } if (abfd->format != bfd_archive && abfd->my_archive == 0) { if (direction == SEEK_SET && (bfd_vma) position == abfd->where) return 0; } else { /* We need something smarter to optimize access to archives. Currently, anything inside an archive is read via the file handle for the archive. Which means that a bfd_seek on one component affects the `current position' in the archive, as well as in any other component. It might be sufficient to put a spike through the cache abstraction, and look to the archive for the file position, but I think we should try for something cleaner. In the meantime, no optimization for archives. */ } file_position = position; if (direction == SEEK_SET && abfd->my_archive != NULL) file_position += abfd->origin; if (abfd->iovec) result = abfd->iovec->bseek (abfd, file_position, direction); else result = -1; if (result != 0) { int hold_errno = errno; /* Force redetermination of `where' field. */ bfd_tell (abfd); /* An EINVAL error probably means that the file offset was absurd. */ if (hold_errno == EINVAL) bfd_set_error (bfd_error_file_truncated); else { bfd_set_error (bfd_error_system_call); errno = hold_errno; } } else { /* Adjust `where' field. */ if (direction == SEEK_SET) abfd->where = position; else abfd->where += position; } return result; }
int bfd_seek (bfd *abfd, file_ptr position, int direction) { int result; file_ptr file_position; /* For the time being, a BFD may not seek to it's end. The problem is that we don't easily have a way to recognize the end of an element in an archive. */ BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR); if (direction == SEEK_CUR && position == 0) return 0; if (abfd->format != bfd_archive && abfd->my_archive == 0) { if (direction == SEEK_SET && (bfd_vma) position == abfd->where) return 0; } else { /* We need something smarter to optimize access to archives. Currently, anything inside an archive is read via the file handle for the archive. Which means that a bfd_seek on one component affects the `current position' in the archive, as well as in any other component. It might be sufficient to put a spike through the cache abstraction, and look to the archive for the file position, but I think we should try for something cleaner. In the meantime, no optimization for archives. */ } file_position = position; if (direction == SEEK_SET) { bfd *parent_bfd = abfd; while (parent_bfd->my_archive != NULL) { file_position += parent_bfd->origin; parent_bfd = parent_bfd->my_archive; } } if (abfd->iovec) result = abfd->iovec->bseek (abfd, file_position, direction); else result = -1; if (result != 0) { int hold_errno = errno; /* Force redetermination of `where' field. */ bfd_tell (abfd); /* An EINVAL error probably means that the file offset was absurd. */ if (hold_errno == EINVAL) bfd_set_error (bfd_error_file_truncated); else { bfd_set_error (bfd_error_system_call); errno = hold_errno; } } else { /* Adjust `where' field. */ if (direction == SEEK_SET) abfd->where = position; else abfd->where += position; } return result; }
static bfd_boolean wasm_scan (bfd *abfd) { bfd_boolean error = FALSE; /* Fake VMAs for now. Choose 0x80000000 as base to avoid clashes with actual data addresses. */ bfd_vma vma = 0x80000000; int section_code; unsigned int bytes_read; char *name = NULL; asection *bfdsec; if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) goto error_return; if (! wasm_read_header (abfd, &error)) goto error_return; while ((section_code = wasm_read_byte (abfd, &error)) != EOF) { if (section_code != 0) { const char *sname = wasm_section_code_to_name (section_code); if (! sname) goto error_return; name = strdup (sname); bfdsec = bfd_make_section_anyway_with_flags (abfd, name, SEC_HAS_CONTENTS); if (bfdsec == NULL) goto error_return; name = NULL; bfdsec->vma = vma; bfdsec->lma = vma; bfdsec->size = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE); if (error) goto error_return; bfdsec->filepos = bfd_tell (abfd); bfdsec->alignment_power = 0; } else { bfd_vma payload_len; file_ptr section_start; bfd_vma namelen; char *prefix = WASM_SECTION_PREFIX; char *p; int ret; payload_len = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE); if (error) goto error_return; section_start = bfd_tell (abfd); namelen = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE); if (error || namelen > payload_len) goto error_return; name = bfd_zmalloc (namelen + strlen (prefix) + 1); if (! name) goto error_return; p = name; ret = sprintf (p, "%s", prefix); if (ret < 0 || (bfd_vma) ret != strlen (prefix)) goto error_return; p += ret; if (bfd_bread (p, namelen, abfd) != namelen) goto error_return; bfdsec = bfd_make_section_anyway_with_flags (abfd, name, SEC_HAS_CONTENTS); if (bfdsec == NULL) goto error_return; name = NULL; bfdsec->vma = vma; bfdsec->lma = vma; bfdsec->filepos = bfd_tell (abfd); bfdsec->size = section_start + payload_len - bfdsec->filepos; bfdsec->alignment_power = 0; } if (bfdsec->size != 0) { bfdsec->contents = bfd_zalloc (abfd, bfdsec->size); if (! bfdsec->contents) goto error_return; if (bfd_bread (bfdsec->contents, bfdsec->size, abfd) != bfdsec->size) goto error_return; } vma += bfdsec->size; } /* Make sure we're at actual EOF. There's no indication in the WebAssembly format of how long the file is supposed to be. */ if (error) goto error_return; return TRUE; error_return: if (name) free (name); for (bfdsec = abfd->sections; bfdsec; bfdsec = bfdsec->next) free ((void *) bfdsec->name); return FALSE; }