1 /* $NetBSD: elf2aout.c,v 1.25 2024/11/01 00:35:53 gutteridge Exp $ */ 2 3 /* 4 * Copyright (c) 1995 5 * Ted Lemon (hereinafter referred to as the author) 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 /* elf2aout.c 32 33 This program converts an elf executable to a NetBSD a.out executable. 34 The minimal symbol table is copied, but the debugging symbols and 35 other informational sections are not. */ 36 37 #if HAVE_NBTOOL_CONFIG_H 38 #include "nbtool_config.h" 39 #endif 40 41 #ifndef TARGET_BYTE_ORDER 42 #define TARGET_BYTE_ORDER BYTE_ORDER 43 #endif 44 45 #include <sys/types.h> 46 #include <sys/endian.h> 47 #include <sys/exec_aout.h> 48 #include <sys/exec_elf.h> 49 50 #include <a.out.h> 51 #include <err.h> 52 #include <errno.h> 53 #include <fcntl.h> 54 #include <limits.h> 55 #include <stdio.h> 56 #include <stdlib.h> 57 #include <string.h> 58 #include <unistd.h> 59 60 61 struct sect { 62 /* should be unsigned long, but assume no a.out binaries on LP64 */ 63 uint32_t vaddr; 64 uint32_t len; 65 }; 66 67 static void combine(struct sect *, struct sect *, int); 68 static int phcmp(const void *, const void *); 69 static void *saveRead(int file, off_t offset, size_t len, const char *name); 70 static void copy(int, int, off_t, off_t); 71 static void translate_syms(int, int, off_t, off_t, off_t, off_t); 72 73 #if TARGET_BYTE_ORDER != BYTE_ORDER 74 static void bswap32_region(int32_t* , int); 75 #endif 76 77 static int *symTypeTable; 78 static int debug; 79 80 static __dead void 81 usage(void) 82 { 83 fprintf(stderr, "Usage: %s [-Os] <elf executable> <a.out executable>\n", 84 getprogname()); 85 exit(EXIT_FAILURE); 86 } 87 88 static const struct { 89 const char *n; 90 int v; 91 } nv[] = { 92 { ".text", N_TEXT }, 93 { ".rodata", N_TEXT }, 94 { ".data", N_DATA }, 95 { ".sdata", N_DATA }, 96 { ".lit4", N_DATA }, 97 { ".lit8", N_DATA }, 98 { ".bss", N_BSS }, 99 { ".sbss", N_BSS }, 100 }; 101 102 static int 103 get_symtab_type(const char *name) 104 { 105 size_t i; 106 for (i = 0; i < __arraycount(nv); i++) { 107 if (strcmp(name, nv[i].n) == 0) 108 return nv[i].v; 109 } 110 if (debug) 111 warnx("section `%s' is not handled\n", name); 112 return 0; 113 } 114 115 static uint32_t 116 get_mid(const Elf32_Ehdr *ex) 117 { 118 switch (ex->e_machine) { 119 #ifdef notyet 120 case EM_AARCH64: 121 return MID_AARCH64; 122 case EM_ALPHA: 123 return MID_ALPHA; 124 #endif 125 case EM_ARM: 126 return MID_ARM6; 127 #ifdef notyet 128 case EM_PARISC: 129 return MID_HPPA; 130 #endif 131 case EM_386: 132 return MID_I386; 133 case EM_68K: 134 return MID_M68K; 135 case EM_OR1K: 136 return MID_OR1K; 137 case EM_MIPS: 138 if (ex->e_ident[EI_DATA] == ELFDATA2LSB) 139 return MID_PMAX; 140 else 141 return MID_MIPS; 142 case EM_PPC: 143 return MID_POWERPC; 144 #ifdef notyet 145 case EM_PPC64: 146 return MID_POWERPC64; 147 break; 148 #endif 149 case EM_RISCV: 150 return MID_RISCV; 151 case EM_SH: 152 return MID_SH3; 153 case EM_SPARC: 154 case EM_SPARC32PLUS: 155 case EM_SPARCV9: 156 if (ex->e_ident[EI_CLASS] == ELFCLASS32) 157 return MID_SPARC; 158 #ifdef notyet 159 return MID_SPARC64; 160 case EM_X86_64: 161 return MID_X86_64; 162 #else 163 break; 164 #endif 165 case EM_VAX: 166 return MID_VAX; 167 case EM_NONE: 168 return MID_ZERO; 169 default: 170 break; 171 } 172 if (debug) 173 warnx("Unsupported machine `%d'", ex->e_machine); 174 return MID_ZERO; 175 } 176 177 static unsigned char 178 get_type(Elf32_Half shndx) 179 { 180 switch (shndx) { 181 case SHN_UNDEF: 182 return N_UNDF; 183 case SHN_ABS: 184 return N_ABS; 185 case SHN_COMMON: 186 case SHN_MIPS_ACOMMON: 187 return N_COMM; 188 default: 189 return (unsigned char)symTypeTable[shndx]; 190 } 191 } 192 193 int 194 main(int argc, char **argv) 195 { 196 Elf32_Ehdr ex; 197 Elf32_Phdr *ph; 198 Elf32_Shdr *sh; 199 char *shstrtab; 200 ssize_t i, strtabix, symtabix; 201 struct sect text, data, bss; 202 struct exec aex; 203 int infile, outfile; 204 uint32_t cur_vma = UINT32_MAX; 205 uint32_t mid; 206 int symflag = 0, c; 207 unsigned long magic = ZMAGIC; 208 209 strtabix = symtabix = 0; 210 text.len = data.len = bss.len = 0; 211 text.vaddr = data.vaddr = bss.vaddr = 0; 212 213 while ((c = getopt(argc, argv, "dOs")) != -1) { 214 switch (c) { 215 case 'd': 216 debug++; 217 break; 218 case 's': 219 symflag = 1; 220 break; 221 case 'O': 222 magic = OMAGIC; 223 break; 224 case '?': 225 default: 226 usage: 227 usage(); 228 } 229 } 230 231 argc -= optind; 232 argv += optind; 233 234 /* Check args... */ 235 if (argc != 2) 236 goto usage; 237 238 239 /* Try the input file... */ 240 if ((infile = open(argv[0], O_RDONLY)) < 0) 241 err(EXIT_FAILURE, "Can't open `%s' for read", argv[0]); 242 243 /* Read the header, which is at the beginning of the file... */ 244 i = read(infile, &ex, sizeof ex); 245 if (i != sizeof ex) { 246 if (i == -1) 247 err(EXIT_FAILURE, "Error reading `%s'", argv[1]); 248 else 249 errx(EXIT_FAILURE, "End of file reading `%s'", argv[1]); 250 } 251 #if TARGET_BYTE_ORDER != BYTE_ORDER 252 ex.e_type = bswap16(ex.e_type); 253 ex.e_machine = bswap16(ex.e_machine); 254 ex.e_version = bswap32(ex.e_version); 255 ex.e_entry = bswap32(ex.e_entry); 256 ex.e_phoff = bswap32(ex.e_phoff); 257 ex.e_shoff = bswap32(ex.e_shoff); 258 ex.e_flags = bswap32(ex.e_flags); 259 ex.e_ehsize = bswap16(ex.e_ehsize); 260 ex.e_phentsize = bswap16(ex.e_phentsize); 261 ex.e_phnum = bswap16(ex.e_phnum); 262 ex.e_shentsize = bswap16(ex.e_shentsize); 263 ex.e_shnum = bswap16(ex.e_shnum); 264 ex.e_shstrndx = bswap16(ex.e_shstrndx); 265 #endif 266 // Not yet 267 if (ex.e_ident[EI_CLASS] == ELFCLASS64) 268 errx(EXIT_FAILURE, "Only 32 bit is supported"); 269 270 /* Read the program headers... */ 271 ph = saveRead(infile, ex.e_phoff, 272 (size_t)ex.e_phnum * sizeof(Elf32_Phdr), "ph"); 273 #if TARGET_BYTE_ORDER != BYTE_ORDER 274 bswap32_region((int32_t*)ph, sizeof(Elf32_Phdr) * ex.e_phnum); 275 #endif 276 /* Read the section headers... */ 277 sh = saveRead(infile, ex.e_shoff, 278 (size_t)ex.e_shnum * sizeof(Elf32_Shdr), "sh"); 279 #if TARGET_BYTE_ORDER != BYTE_ORDER 280 bswap32_region((int32_t*)sh, sizeof(Elf32_Shdr) * ex.e_shnum); 281 #endif 282 /* Read in the section string table. */ 283 shstrtab = saveRead(infile, sh[ex.e_shstrndx].sh_offset, 284 (size_t)sh[ex.e_shstrndx].sh_size, "shstrtab"); 285 286 /* Find space for a table matching ELF section indices to a.out symbol 287 * types. */ 288 symTypeTable = malloc(ex.e_shnum * sizeof(int)); 289 if (symTypeTable == NULL) 290 err(EXIT_FAILURE, "symTypeTable: can't allocate"); 291 memset(symTypeTable, 0, ex.e_shnum * sizeof(int)); 292 293 /* Look for the symbol table and string table... Also map section 294 * indices to symbol types for a.out */ 295 for (i = 0; i < ex.e_shnum; i++) { 296 char *name = shstrtab + sh[i].sh_name; 297 if (!strcmp(name, ".symtab")) 298 symtabix = i; 299 else if (!strcmp(name, ".strtab")) 300 strtabix = i; 301 else 302 symTypeTable[i] = get_symtab_type(name); 303 } 304 305 /* Figure out if we can cram the program header into an a.out 306 * header... Basically, we can't handle anything but loadable 307 * segments, but we can ignore some kinds of segments. We can't 308 * handle holes in the address space, and we handle start addresses 309 * other than 0x1000 by hoping that the loader will know where to load 310 * - a.out doesn't have an explicit load address. Segments may be 311 * out of order, so we sort them first. */ 312 qsort(ph, ex.e_phnum, sizeof(Elf32_Phdr), phcmp); 313 for (i = 0; i < ex.e_phnum; i++) { 314 /* Section types we can ignore... */ 315 if (ph[i].p_type == PT_NULL || ph[i].p_type == PT_NOTE || 316 ph[i].p_type == PT_PHDR || ph[i].p_type == PT_MIPS_REGINFO) 317 continue; 318 /* Section types we can't handle... */ 319 if (ph[i].p_type == PT_TLS) { 320 if (debug) 321 warnx("Can't handle TLS section"); 322 continue; 323 } 324 if (ph[i].p_type != PT_LOAD) 325 errx(EXIT_FAILURE, "Program header %zd " 326 "type %d can't be converted.", i, ph[i].p_type); 327 /* Writable (data) segment? */ 328 if (ph[i].p_flags & PF_W) { 329 struct sect ndata, nbss; 330 331 ndata.vaddr = ph[i].p_vaddr; 332 ndata.len = ph[i].p_filesz; 333 nbss.vaddr = ph[i].p_vaddr + ph[i].p_filesz; 334 nbss.len = ph[i].p_memsz - ph[i].p_filesz; 335 336 combine(&data, &ndata, 0); 337 combine(&bss, &nbss, 1); 338 } else { 339 struct sect ntxt; 340 341 ntxt.vaddr = ph[i].p_vaddr; 342 ntxt.len = ph[i].p_filesz; 343 344 combine(&text, &ntxt, 0); 345 } 346 /* Remember the lowest segment start address. */ 347 if (ph[i].p_vaddr < cur_vma) 348 cur_vma = ph[i].p_vaddr; 349 } 350 351 /* Sections must be in order to be converted... */ 352 if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr || 353 text.vaddr + text.len > data.vaddr || 354 data.vaddr + data.len > bss.vaddr) 355 errx(EXIT_FAILURE, "Sections ordering prevents a.out " 356 "conversion."); 357 /* If there's a data section but no text section, then the loader 358 * combined everything into one section. That needs to be the text 359 * section, so just make the data section zero length following text. */ 360 if (data.len && text.len == 0) { 361 text = data; 362 data.vaddr = text.vaddr + text.len; 363 data.len = 0; 364 } 365 /* If there is a gap between text and data, we'll fill it when we copy 366 * the data, so update the length of the text segment as represented 367 * in a.out to reflect that, since a.out doesn't allow gaps in the 368 * program address space. */ 369 if (text.vaddr + text.len < data.vaddr) 370 text.len = data.vaddr - text.vaddr; 371 372 /* We now have enough information to cons up an a.out header... */ 373 mid = get_mid(&ex); 374 aex.a_midmag = (u_long)htobe32(((u_long)symflag << 26) 375 | ((u_long)mid << 16) | magic); 376 377 aex.a_text = text.len; 378 aex.a_data = data.len; 379 aex.a_bss = bss.len; 380 aex.a_entry = ex.e_entry; 381 aex.a_syms = (sizeof(struct nlist) * 382 (symtabix != -1 ? sh[symtabix].sh_size / sizeof(Elf32_Sym) : 0)); 383 aex.a_trsize = 0; 384 aex.a_drsize = 0; 385 #if TARGET_BYTE_ORDER != BYTE_ORDER 386 aex.a_text = bswap32(aex.a_text); 387 aex.a_data = bswap32(aex.a_data); 388 aex.a_bss = bswap32(aex.a_bss); 389 aex.a_entry = bswap32(aex.a_entry); 390 aex.a_syms = bswap32(aex.a_syms); 391 aex.a_trsize = bswap32(aex.a_trsize); 392 aex.a_drsize = bswap32(aex.a_drsize); 393 #endif 394 395 /* Make the output file... */ 396 if ((outfile = open(argv[1], O_WRONLY | O_CREAT, 0777)) < 0) 397 err(EXIT_FAILURE, "Unable to create `%s'", argv[1]); 398 /* Truncate file... */ 399 if (ftruncate(outfile, 0)) { 400 warn("ftruncate %s", argv[1]); 401 } 402 /* Write the header... */ 403 i = write(outfile, &aex, sizeof aex); 404 if (i != sizeof aex) 405 err(EXIT_FAILURE, "Can't write `%s'", argv[1]); 406 /* Copy the loadable sections. Zero-fill any gaps less than 64k; 407 * complain about any zero-filling, and die if we're asked to 408 * zero-fill more than 64k. */ 409 for (i = 0; i < ex.e_phnum; i++) { 410 /* Unprocessable sections were handled above, so just verify 411 * that the section can be loaded before copying. */ 412 if (ph[i].p_type == PT_LOAD && ph[i].p_filesz) { 413 if (cur_vma != ph[i].p_vaddr) { 414 uint32_t gap = ph[i].p_vaddr - cur_vma; 415 char obuf[1024]; 416 if (gap > 65536) 417 errx(EXIT_FAILURE, 418 "Intersegment gap (%u bytes) too large", gap); 419 if (debug) 420 warnx("%u byte intersegment gap", gap); 421 memset(obuf, 0, sizeof obuf); 422 while (gap) { 423 ssize_t count = write(outfile, obuf, 424 (gap > sizeof obuf 425 ? sizeof obuf : gap)); 426 if (count < 0) 427 err(EXIT_FAILURE, 428 "Error writing gap"); 429 gap -= (uint32_t)count; 430 } 431 } 432 copy(outfile, infile, ph[i].p_offset, ph[i].p_filesz); 433 cur_vma = ph[i].p_vaddr + ph[i].p_filesz; 434 } 435 } 436 437 /* Copy and translate the symbol table... */ 438 translate_syms(outfile, infile, 439 sh[symtabix].sh_offset, sh[symtabix].sh_size, 440 sh[strtabix].sh_offset, sh[strtabix].sh_size); 441 442 free(ph); 443 free(sh); 444 free(shstrtab); 445 free(symTypeTable); 446 /* Looks like we won... */ 447 return EXIT_SUCCESS; 448 } 449 /* translate_syms (out, in, offset, size) 450 451 Read the ELF symbol table from in at offset; translate it into a.out 452 nlist format and write it to out. */ 453 454 void 455 translate_syms(int out, int in, off_t symoff, off_t symsize, 456 off_t stroff, off_t strsize) 457 { 458 #define SYMS_PER_PASS 64 459 Elf32_Sym inbuf[64]; 460 struct nlist outbuf[64]; 461 ssize_t i, remaining, cur; 462 char *oldstrings; 463 char *newstrings, *nsp; 464 size_t newstringsize; 465 uint32_t stringsizebuf; 466 467 /* Zero the unused fields in the output buffer.. */ 468 memset(outbuf, 0, sizeof outbuf); 469 470 /* Find number of symbols to process... */ 471 remaining = (ssize_t)(symsize / (off_t)sizeof(Elf32_Sym)); 472 473 /* Suck in the old string table... */ 474 oldstrings = saveRead(in, stroff, (size_t)strsize, "string table"); 475 476 /* 477 * Allocate space for the new one. We will increase the space if 478 * this is too small 479 */ 480 newstringsize = (size_t)(strsize + remaining); 481 newstrings = malloc(newstringsize); 482 if (newstrings == NULL) 483 err(EXIT_FAILURE, "No memory for new string table!"); 484 /* Initialize the table pointer... */ 485 nsp = newstrings; 486 487 /* Go the start of the ELF symbol table... */ 488 if (lseek(in, symoff, SEEK_SET) < 0) 489 err(EXIT_FAILURE, "Can't seek"); 490 /* Translate and copy symbols... */ 491 for (; remaining; remaining -= cur) { 492 cur = remaining; 493 if (cur > SYMS_PER_PASS) 494 cur = SYMS_PER_PASS; 495 if ((i = read(in, inbuf, (size_t)cur * sizeof(Elf32_Sym))) 496 != cur * (ssize_t)sizeof(Elf32_Sym)) { 497 if (i < 0) 498 err(EXIT_FAILURE, "%s: read error", __func__); 499 else 500 errx(EXIT_FAILURE, "%s: premature end of file", 501 __func__); 502 } 503 /* Do the translation... */ 504 for (i = 0; i < cur; i++) { 505 int binding, type; 506 size_t off, len; 507 508 #if TARGET_BYTE_ORDER != BYTE_ORDER 509 inbuf[i].st_name = bswap32(inbuf[i].st_name); 510 inbuf[i].st_value = bswap32(inbuf[i].st_value); 511 inbuf[i].st_size = bswap32(inbuf[i].st_size); 512 inbuf[i].st_shndx = bswap16(inbuf[i].st_shndx); 513 #endif 514 off = (size_t)(nsp - newstrings); 515 516 /* length of this symbol with leading '_' and trailing '\0' */ 517 len = strlen(oldstrings + inbuf[i].st_name) + 1 + 1; 518 519 /* Does it fit? If not make more space */ 520 if (newstringsize - off < len) { 521 char *nns; 522 523 newstringsize += (size_t)(remaining) * len; 524 nns = realloc(newstrings, newstringsize); 525 if (nns == NULL) 526 err(EXIT_FAILURE, "No memory for new string table!"); 527 newstrings = nns; 528 nsp = newstrings + off; 529 } 530 /* Copy the symbol into the new table, but prepend an 531 * underscore. */ 532 *nsp = '_'; 533 strcpy(nsp + 1, oldstrings + inbuf[i].st_name); 534 outbuf[i].n_un.n_strx = nsp - newstrings + 4; 535 nsp += len; 536 537 type = ELF32_ST_TYPE(inbuf[i].st_info); 538 binding = ELF32_ST_BIND(inbuf[i].st_info); 539 540 /* Convert ELF symbol type/section/etc info into a.out 541 * type info. */ 542 if (type == STT_FILE) 543 outbuf[i].n_type = N_FN; 544 else 545 outbuf[i].n_type = get_type(inbuf[i].st_shndx); 546 if (binding == STB_GLOBAL) 547 outbuf[i].n_type |= N_EXT; 548 /* Symbol values in executables should be compatible. */ 549 outbuf[i].n_value = inbuf[i].st_value; 550 #if TARGET_BYTE_ORDER != BYTE_ORDER 551 outbuf[i].n_un.n_strx = bswap32(outbuf[i].n_un.n_strx); 552 outbuf[i].n_desc = bswap16(outbuf[i].n_desc); 553 outbuf[i].n_value = bswap32(outbuf[i].n_value); 554 #endif 555 } 556 /* Write out the symbols... */ 557 if ((i = write(out, outbuf, (size_t)cur * sizeof(struct nlist))) 558 != cur * (ssize_t)sizeof(struct nlist)) 559 err(EXIT_FAILURE, "%s: write failed", __func__); 560 } 561 /* Write out the string table length... */ 562 stringsizebuf = (uint32_t)newstringsize; 563 #if TARGET_BYTE_ORDER != BYTE_ORDER 564 stringsizebuf = bswap32(stringsizebuf); 565 #endif 566 if (write(out, &stringsizebuf, sizeof stringsizebuf) 567 != sizeof stringsizebuf) 568 err(EXIT_FAILURE, "%s: newstringsize: write failed", __func__); 569 /* Write out the string table... */ 570 if (write(out, newstrings, newstringsize) != (ssize_t)newstringsize) 571 err(EXIT_FAILURE, "%s: newstrings: write failed", __func__); 572 free(newstrings); 573 free(oldstrings); 574 } 575 576 static void 577 copy(int out, int in, off_t offset, off_t size) 578 { 579 char ibuf[4096]; 580 ssize_t remaining, cur, count; 581 582 /* Go to the start of the segment... */ 583 if (lseek(in, offset, SEEK_SET) < 0) 584 err(EXIT_FAILURE, "%s: lseek failed", __func__); 585 if (size > SSIZE_MAX) 586 err(EXIT_FAILURE, "%s: can not copy this much", __func__); 587 remaining = (ssize_t)size; 588 while (remaining) { 589 cur = remaining; 590 if (cur > (int)sizeof ibuf) 591 cur = sizeof ibuf; 592 remaining -= cur; 593 if ((count = read(in, ibuf, (size_t)cur)) != cur) { 594 if (count < 0) 595 err(EXIT_FAILURE, "%s: read error", __func__); 596 else 597 errx(EXIT_FAILURE, "%s: premature end of file", 598 __func__); 599 } 600 if ((count = write(out, ibuf, (size_t)cur)) != cur) 601 err(EXIT_FAILURE, "%s: write failed", __func__); 602 } 603 } 604 605 /* Combine two segments, which must be contiguous. If pad is true, it's 606 okay for there to be padding between. */ 607 static void 608 combine(struct sect *base, struct sect *new, int pad) 609 { 610 611 if (base->len == 0) 612 *base = *new; 613 else 614 if (new->len) { 615 if (base->vaddr + base->len != new->vaddr) { 616 if (pad) 617 base->len = new->vaddr - base->vaddr; 618 else 619 errx(EXIT_FAILURE, "Non-contiguous " 620 "data can't be converted"); 621 } 622 base->len += new->len; 623 } 624 } 625 626 static int 627 phcmp(const void *vh1, const void *vh2) 628 { 629 const Elf32_Phdr *h1, *h2; 630 631 h1 = (const Elf32_Phdr *)vh1; 632 h2 = (const Elf32_Phdr *)vh2; 633 634 if (h1->p_vaddr > h2->p_vaddr) 635 return 1; 636 else 637 if (h1->p_vaddr < h2->p_vaddr) 638 return -1; 639 else 640 return 0; 641 } 642 643 static void * 644 saveRead(int file, off_t offset, size_t len, const char *name) 645 { 646 char *tmp; 647 ssize_t count; 648 off_t off; 649 650 if ((off = lseek(file, offset, SEEK_SET)) < 0) 651 errx(EXIT_FAILURE, "%s: seek failed", name); 652 if ((tmp = malloc(len)) == NULL) 653 errx(EXIT_FAILURE, 654 "%s: Can't allocate %jd bytes.", name, (intmax_t)len); 655 count = read(file, tmp, len); 656 if ((size_t)count != len) { 657 if (count < 0) 658 err(EXIT_FAILURE, "%s: read error", name); 659 else 660 errx(EXIT_FAILURE, "%s: premature end of file", 661 name); 662 } 663 return tmp; 664 } 665 666 #if TARGET_BYTE_ORDER != BYTE_ORDER 667 /* swap a 32bit region */ 668 static void 669 bswap32_region(int32_t* p, int len) 670 { 671 size_t i; 672 673 for (i = 0; i < len / sizeof(int32_t); i++, p++) 674 *p = bswap32(*p); 675 } 676 #endif 677