1 /* $NetBSD: elf2ecoff.c,v 1.26 2009/12/19 10:27:13 tsutsui Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Jonathan Stone 5 * All rights reserved. 6 * Copyright (c) 1995 7 * Ted Lemon (hereinafter referred to as the author) 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* elf2ecoff.c 34 35 This program converts an elf executable to an ECOFF executable. 36 No symbol table is retained. This is useful primarily in building 37 net-bootable kernels for machines (e.g., DECstation and Alpha) which 38 only support the ECOFF object file format. */ 39 40 #if HAVE_NBTOOL_CONFIG_H 41 #include "nbtool_config.h" 42 #endif 43 44 #include <sys/types.h> 45 #include <err.h> 46 #include <errno.h> 47 #include <fcntl.h> 48 #include <unistd.h> 49 #include <sys/exec_elf.h> 50 #include <stdio.h> 51 #include <sys/exec_ecoff.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <limits.h> 55 56 #define ISLAST(p) (p->n_un.n_name == 0 || p->n_un.n_name[0] == 0) 57 58 struct sect { 59 unsigned long vaddr; 60 unsigned long len; 61 }; 62 63 struct elf_syms { 64 int nsymbols; 65 Elf32_Sym *elf_syms; 66 off_t stringsize; 67 char *stringtab; 68 }; 69 70 struct ecoff_syms { 71 int nsymbols; 72 struct ecoff_extsym *ecoff_syms; 73 off_t stringsize; 74 char *stringtab; 75 }; 76 77 int debug = 0; 78 79 int phcmp(Elf32_Phdr * h1, Elf32_Phdr * h2); 80 81 82 char *saveRead(int file, off_t offset, off_t len, const char *name); 83 void safewrite(int outfile, const void *buf, off_t len, const char *msg); 84 void copy(int, int, off_t, off_t); 85 void combine(struct sect * base, struct sect * new, int paddable); 86 void translate_syms(struct elf_syms *, struct ecoff_syms *); 87 void 88 elf_symbol_table_to_ecoff(int out, int in, 89 struct ecoff_exechdr * ep, 90 off_t symoff, off_t symsize, 91 off_t stroff, off_t strsize); 92 93 94 int 95 make_ecoff_section_hdrs(struct ecoff_exechdr * ep, 96 struct ecoff_scnhdr * esecs); 97 98 void 99 write_ecoff_symhdr(int outfile, struct ecoff_exechdr * ep, 100 struct ecoff_symhdr * symhdrp, 101 long nesyms, long extsymoff, long extstroff, 102 long strsize); 103 104 void pad16(int fd, int size, const char *msg); 105 void bswap32_region(int32_t* , int); 106 107 int *symTypeTable; 108 int needswap; 109 110 111 112 113 void 114 elf_read_syms(struct elf_syms * elfsymsp, int infile, 115 off_t symoff, off_t symsize, off_t stroff, off_t strsize); 116 117 118 int 119 main(int argc, char **argv, char **envp) 120 { 121 Elf32_Ehdr ex; 122 Elf32_Phdr *ph; 123 Elf32_Shdr *sh; 124 char *shstrtab; 125 int strtabix, symtabix; 126 size_t i; 127 int pad; 128 struct sect text, data, bss; /* a.out-compatible sections */ 129 struct sect rdata, sdata, sbss; /* ECOFF-only sections */ 130 131 struct ecoff_exechdr ep; 132 struct ecoff_scnhdr esecs[6]; 133 struct ecoff_symhdr symhdr; 134 135 int infile, outfile; 136 unsigned long cur_vma = ULONG_MAX; 137 int symflag = 0; 138 int nsecs = 0; 139 int mipsel; 140 141 142 text.len = data.len = bss.len = 0; 143 text.vaddr = data.vaddr = bss.vaddr = 0; 144 145 rdata.len = sdata.len = sbss.len = 0; 146 rdata.vaddr = sdata.vaddr = sbss.vaddr = 0; 147 148 /* Check args... */ 149 if (argc < 3 || argc > 4) { 150 usage: 151 fprintf(stderr, 152 "usage: elf2ecoff <elf executable> <ECOFF executable> [-s]\n"); 153 exit(1); 154 } 155 if (argc == 4) { 156 if (strcmp(argv[3], "-s")) 157 goto usage; 158 symflag = 1; 159 } 160 /* Try the input file... */ 161 if ((infile = open(argv[1], O_RDONLY)) < 0) { 162 fprintf(stderr, "Can't open %s for read: %s\n", 163 argv[1], strerror(errno)); 164 exit(1); 165 } 166 /* Read the header, which is at the beginning of the file... */ 167 i = read(infile, &ex, sizeof ex); 168 if (i != sizeof ex) { 169 fprintf(stderr, "ex: %s: %s.\n", 170 argv[1], i ? strerror(errno) : "End of file reached"); 171 exit(1); 172 } 173 if (ex.e_ident[EI_DATA] == ELFDATA2LSB) 174 mipsel = 1; 175 else if (ex.e_ident[EI_DATA] == ELFDATA2MSB) 176 mipsel = 0; 177 else { 178 fprintf(stderr, "invalid ELF byte order %d\n", 179 ex.e_ident[EI_DATA]); 180 exit(1); 181 } 182 #if BYTE_ORDER == BIG_ENDIAN 183 if (mipsel) 184 needswap = 1; 185 else 186 needswap = 0; 187 #elif BYTE_ORDER == LITTLE_ENDIAN 188 if (mipsel) 189 needswap = 0; 190 else 191 needswap = 1; 192 #else 193 #error "unknown endian" 194 #endif 195 196 if (needswap) { 197 ex.e_type = bswap16(ex.e_type); 198 ex.e_machine = bswap16(ex.e_machine); 199 ex.e_version = bswap32(ex.e_version); 200 ex.e_entry = bswap32(ex.e_entry); 201 ex.e_phoff = bswap32(ex.e_phoff); 202 ex.e_shoff = bswap32(ex.e_shoff); 203 ex.e_flags = bswap32(ex.e_flags); 204 ex.e_ehsize = bswap16(ex.e_ehsize); 205 ex.e_phentsize = bswap16(ex.e_phentsize); 206 ex.e_phnum = bswap16(ex.e_phnum); 207 ex.e_shentsize = bswap16(ex.e_shentsize); 208 ex.e_shnum = bswap16(ex.e_shnum); 209 ex.e_shstrndx = bswap16(ex.e_shstrndx); 210 } 211 212 /* Read the program headers... */ 213 ph = (Elf32_Phdr *) saveRead(infile, ex.e_phoff, 214 ex.e_phnum * sizeof(Elf32_Phdr), "ph"); 215 if (needswap) 216 bswap32_region((int32_t*)ph, sizeof(Elf32_Phdr) * ex.e_phnum); 217 /* Read the section headers... */ 218 sh = (Elf32_Shdr *) saveRead(infile, ex.e_shoff, 219 ex.e_shnum * sizeof(Elf32_Shdr), "sh"); 220 if (needswap) 221 bswap32_region((int32_t*)sh, sizeof(Elf32_Shdr) * ex.e_shnum); 222 223 /* Read in the section string table. */ 224 shstrtab = saveRead(infile, sh[ex.e_shstrndx].sh_offset, 225 sh[ex.e_shstrndx].sh_size, "shstrtab"); 226 227 228 /* Look for the symbol table and string table... Also map section 229 * indices to symbol types for a.out */ 230 symtabix = 0; 231 strtabix = 0; 232 for (i = 0; i < ex.e_shnum; i++) { 233 char *name = shstrtab + sh[i].sh_name; 234 if (!strcmp(name, ".symtab")) 235 symtabix = i; 236 else 237 if (!strcmp(name, ".strtab")) 238 strtabix = i; 239 240 } 241 242 /* Figure out if we can cram the program header into an ECOFF 243 * header... Basically, we can't handle anything but loadable 244 * segments, but we can ignore some kinds of segments. We can't 245 * handle holes in the address space. Segments may be out of order, 246 * so we sort them first. */ 247 248 qsort(ph, ex.e_phnum, sizeof(Elf32_Phdr), 249 (int (*) (const void *, const void *)) phcmp); 250 251 for (i = 0; i < ex.e_phnum; i++) { 252 /* Section types we can ignore... */ 253 if (ph[i].p_type == PT_NULL || ph[i].p_type == PT_NOTE || 254 ph[i].p_type == PT_PHDR || 255 ph[i].p_type == PT_MIPS_REGINFO) { 256 257 if (debug) { 258 fprintf(stderr, " skipping PH %zu type %d flags 0x%x\n", 259 i, ph[i].p_type, ph[i].p_flags); 260 } 261 continue; 262 } 263 /* Section types we can't handle... */ 264 else 265 if (ph[i].p_type != PT_LOAD) { 266 fprintf(stderr, "Program header %zu type %d can't be converted.\n", 267 i, ph[i].p_type); 268 exit(1); 269 } 270 /* Writable (data) segment? */ 271 if (ph[i].p_flags & PF_W) { 272 struct sect ndata, nbss; 273 274 ndata.vaddr = ph[i].p_vaddr; 275 ndata.len = ph[i].p_filesz; 276 nbss.vaddr = ph[i].p_vaddr + ph[i].p_filesz; 277 nbss.len = ph[i].p_memsz - ph[i].p_filesz; 278 279 if (debug) { 280 fprintf(stderr, 281 " combinining PH %zu type %d flags 0x%x with data, ndata = %ld, nbss =%ld\n", i, ph[i].p_type, ph[i].p_flags, ndata.len, nbss.len); 282 } 283 combine(&data, &ndata, 0); 284 combine(&bss, &nbss, 1); 285 } else { 286 struct sect ntxt; 287 288 ntxt.vaddr = ph[i].p_vaddr; 289 ntxt.len = ph[i].p_filesz; 290 if (debug) { 291 292 fprintf(stderr, 293 " combinining PH %zu type %d flags 0x%x with text, len = %ld\n", 294 i, ph[i].p_type, ph[i].p_flags, ntxt.len); 295 } 296 combine(&text, &ntxt, 0); 297 } 298 /* Remember the lowest segment start address. */ 299 if (ph[i].p_vaddr < cur_vma) 300 cur_vma = ph[i].p_vaddr; 301 } 302 303 /* Sections must be in order to be converted... */ 304 if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr || 305 text.vaddr + text.len > data.vaddr || data.vaddr + data.len > bss.vaddr) { 306 fprintf(stderr, "Sections ordering prevents a.out conversion.\n"); 307 exit(1); 308 } 309 /* If there's a data section but no text section, then the loader 310 * combined everything into one section. That needs to be the text 311 * section, so just make the data section zero length following text. */ 312 if (data.len && !text.len) { 313 text = data; 314 data.vaddr = text.vaddr + text.len; 315 data.len = 0; 316 } 317 /* If there is a gap between text and data, we'll fill it when we copy 318 * the data, so update the length of the text segment as represented 319 * in a.out to reflect that, since a.out doesn't allow gaps in the 320 * program address space. */ 321 if (text.vaddr + text.len < data.vaddr) 322 text.len = data.vaddr - text.vaddr; 323 324 /* We now have enough information to cons up an a.out header... */ 325 ep.a.magic = ECOFF_OMAGIC; 326 ep.a.vstamp = 2 * 256 + 10; /* compatible with version 2.10 */ 327 ep.a.tsize = text.len; 328 ep.a.dsize = data.len; 329 ep.a.bsize = bss.len; 330 ep.a.entry = ex.e_entry; 331 ep.a.text_start = text.vaddr; 332 ep.a.data_start = data.vaddr; 333 ep.a.bss_start = bss.vaddr; 334 ep.a.gprmask = 0xf3fffffe; 335 memset(&ep.a.cprmask, 0, sizeof ep.a.cprmask); 336 ep.a.gp_value = 0; /* unused. */ 337 338 if (mipsel) 339 ep.f.f_magic = ECOFF_MAGIC_MIPSEL; 340 else 341 ep.f.f_magic = ECOFF_MAGIC_MIPSEB; 342 343 ep.f.f_nscns = 6; 344 ep.f.f_timdat = 0; /* bogus */ 345 ep.f.f_symptr = 0; 346 ep.f.f_nsyms = sizeof(struct ecoff_symhdr); 347 ep.f.f_opthdr = sizeof ep.a; 348 ep.f.f_flags = 0x100f; /* Stripped, not sharable. */ 349 350 memset(esecs, 0, sizeof(esecs)); 351 352 /* Make ECOFF section headers, with empty stubs for 353 * .rdata/.sdata/.sbss. */ 354 make_ecoff_section_hdrs(&ep, esecs); 355 356 nsecs = ep.f.f_nscns; 357 358 if (needswap) { 359 ep.f.f_magic = bswap16(ep.f.f_magic); 360 ep.f.f_nscns = bswap16(ep.f.f_nscns); 361 ep.f.f_timdat = bswap32(ep.f.f_timdat); 362 ep.f.f_symptr = bswap32(ep.f.f_symptr); 363 ep.f.f_nsyms = bswap32(ep.f.f_nsyms); 364 ep.f.f_opthdr = bswap16(ep.f.f_opthdr); 365 ep.f.f_flags = bswap16(ep.f.f_flags); 366 ep.a.magic = bswap16(ep.a.magic); 367 ep.a.vstamp = bswap16(ep.a.vstamp); 368 ep.a.tsize = bswap32(ep.a.tsize); 369 ep.a.dsize = bswap32(ep.a.dsize); 370 ep.a.bsize = bswap32(ep.a.bsize); 371 ep.a.entry = bswap32(ep.a.entry); 372 ep.a.text_start = bswap32(ep.a.text_start); 373 ep.a.data_start = bswap32(ep.a.data_start); 374 ep.a.bss_start = bswap32(ep.a.bss_start); 375 ep.a.gprmask = bswap32(ep.a.gprmask); 376 bswap32_region((int32_t*)ep.a.cprmask, sizeof(ep.a.cprmask)); 377 ep.a.gp_value = bswap32(ep.a.gp_value); 378 for (i = 0; i < sizeof(esecs) / sizeof(esecs[0]); i++) { 379 esecs[i].s_paddr = bswap32(esecs[i].s_paddr); 380 esecs[i].s_vaddr = bswap32(esecs[i].s_vaddr); 381 esecs[i].s_size = bswap32(esecs[i].s_size); 382 esecs[i].s_scnptr = bswap32(esecs[i].s_scnptr); 383 esecs[i].s_relptr = bswap32(esecs[i].s_relptr); 384 esecs[i].s_lnnoptr = bswap32(esecs[i].s_lnnoptr); 385 esecs[i].s_nreloc = bswap16(esecs[i].s_nreloc); 386 esecs[i].s_nlnno = bswap16(esecs[i].s_nlnno); 387 esecs[i].s_flags = bswap32(esecs[i].s_flags); 388 } 389 } 390 391 /* Make the output file... */ 392 if ((outfile = open(argv[2], O_WRONLY | O_CREAT, 0777)) < 0) { 393 fprintf(stderr, "Unable to create %s: %s\n", argv[2], strerror(errno)); 394 exit(1); 395 } 396 /* Truncate file... */ 397 if (ftruncate(outfile, 0)) { 398 warn("ftruncate %s", argv[2]); 399 } 400 /* Write the headers... */ 401 safewrite(outfile, &ep.f, sizeof(ep.f), "ep.f: write: %s\n"); 402 if (debug) 403 fprintf(stderr, "wrote %zu byte file header.\n", sizeof(ep.f)); 404 405 safewrite(outfile, &ep.a, sizeof(ep.a), "ep.a: write: %s\n"); 406 if (debug) 407 fprintf(stderr, "wrote %zu byte a.out header.\n", sizeof(ep.a)); 408 409 safewrite(outfile, &esecs, sizeof(esecs[0]) * nsecs, 410 "esecs: write: %s\n"); 411 if (debug) 412 fprintf(stderr, "wrote %zu bytes of section headers.\n", 413 sizeof(esecs[0]) * nsecs); 414 415 416 pad = ((sizeof ep.f + sizeof ep.a + sizeof esecs) & 15); 417 if (pad) { 418 pad = 16 - pad; 419 pad16(outfile, pad, "ipad: write: %s\n"); 420 if (debug) 421 fprintf(stderr, "wrote %d byte pad.\n", pad); 422 } 423 /* Copy the loadable sections. Zero-fill any gaps less than 64k; 424 * complain about any zero-filling, and die if we're asked to 425 * zero-fill more than 64k. */ 426 for (i = 0; i < ex.e_phnum; i++) { 427 /* Unprocessable sections were handled above, so just verify 428 * that the section can be loaded before copying. */ 429 if (ph[i].p_type == PT_LOAD && ph[i].p_filesz) { 430 if (cur_vma != ph[i].p_vaddr) { 431 unsigned long gap = ph[i].p_vaddr - cur_vma; 432 char obuf[1024]; 433 if (gap > 65536) { 434 fprintf(stderr, "Intersegment gap (%ld bytes) too large.\n", 435 gap); 436 exit(1); 437 } 438 if (debug) 439 fprintf(stderr, "Warning: %ld byte intersegment gap.\n", gap); 440 memset(obuf, 0, sizeof obuf); 441 while (gap) { 442 int count = write(outfile, obuf, (gap > sizeof obuf 443 ? sizeof obuf : gap)); 444 if (count < 0) { 445 fprintf(stderr, "Error writing gap: %s\n", 446 strerror(errno)); 447 exit(1); 448 } 449 gap -= count; 450 } 451 } 452 if (debug) 453 fprintf(stderr, "writing %d bytes...\n", ph[i].p_filesz); 454 copy(outfile, infile, ph[i].p_offset, ph[i].p_filesz); 455 cur_vma = ph[i].p_vaddr + ph[i].p_filesz; 456 } 457 } 458 459 460 if (debug) 461 fprintf(stderr, "writing syms at offset 0x%lx\n", 462 (u_long) ep.f.f_symptr + sizeof(symhdr)); 463 464 /* Copy and translate the symbol table... */ 465 elf_symbol_table_to_ecoff(outfile, infile, &ep, 466 sh[symtabix].sh_offset, sh[symtabix].sh_size, 467 sh[strtabix].sh_offset, sh[strtabix].sh_size); 468 469 /* 470 * Write a page of padding for boot PROMS that read entire pages. 471 * Without this, they may attempt to read past the end of the 472 * data section, incur an error, and refuse to boot. 473 */ 474 { 475 char obuf[4096]; 476 memset(obuf, 0, sizeof obuf); 477 if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf)) { 478 fprintf(stderr, "Error writing PROM padding: %s\n", 479 strerror(errno)); 480 exit(1); 481 } 482 } 483 484 /* Looks like we won... */ 485 exit(0); 486 } 487 488 void 489 copy(out, in, offset, size) 490 int out, in; 491 off_t offset, size; 492 { 493 char ibuf[4096]; 494 size_t remaining, cur, count; 495 496 /* Go to the start of the ELF symbol table... */ 497 if (lseek(in, offset, SEEK_SET) < 0) { 498 perror("copy: lseek"); 499 exit(1); 500 } 501 remaining = size; 502 while (remaining) { 503 cur = remaining; 504 if (cur > sizeof ibuf) 505 cur = sizeof ibuf; 506 remaining -= cur; 507 if ((count = read(in, ibuf, cur)) != cur) { 508 fprintf(stderr, "copy: read: %s\n", 509 count ? strerror(errno) : "premature end of file"); 510 exit(1); 511 } 512 safewrite(out, ibuf, cur, "copy: write: %s\n"); 513 } 514 } 515 /* Combine two segments, which must be contiguous. If pad is true, it's 516 okay for there to be padding between. */ 517 void 518 combine(base, new, pad) 519 struct sect *base, *new; 520 int pad; 521 { 522 if (!base->len) 523 *base = *new; 524 else 525 if (new->len) { 526 if (base->vaddr + base->len != new->vaddr) { 527 if (pad) 528 base->len = new->vaddr - base->vaddr; 529 else { 530 fprintf(stderr, 531 "Non-contiguous data can't be converted.\n"); 532 exit(1); 533 } 534 } 535 base->len += new->len; 536 } 537 } 538 539 int 540 phcmp(h1, h2) 541 Elf32_Phdr *h1, *h2; 542 { 543 if (h1->p_vaddr > h2->p_vaddr) 544 return 1; 545 else 546 if (h1->p_vaddr < h2->p_vaddr) 547 return -1; 548 else 549 return 0; 550 } 551 552 char 553 * 554 saveRead(int file, off_t offset, off_t len, const char *name) 555 { 556 char *tmp; 557 int count; 558 off_t off; 559 if ((off = lseek(file, offset, SEEK_SET)) < 0) { 560 fprintf(stderr, "%s: fseek: %s\n", name, strerror(errno)); 561 exit(1); 562 } 563 if (!(tmp = (char *) malloc(len))) { 564 fprintf(stderr, "%s: Can't allocate %ld bytes.\n", name, (long) len); 565 exit(1); 566 } 567 count = read(file, tmp, len); 568 if (count != len) { 569 fprintf(stderr, "%s: read: %s.\n", 570 name, count ? strerror(errno) : "End of file reached"); 571 exit(1); 572 } 573 return tmp; 574 } 575 576 void 577 safewrite(int outfile, const void *buf, off_t len, const char *msg) 578 { 579 int written; 580 written = write(outfile, buf, len); 581 if (written != len) { 582 fprintf(stderr, msg, strerror(errno)); 583 exit(1); 584 } 585 } 586 587 588 /* 589 * Output only three ECOFF sections, corresponding to ELF psecs 590 * for text, data, and bss. 591 */ 592 int 593 make_ecoff_section_hdrs(ep, esecs) 594 struct ecoff_exechdr *ep; 595 struct ecoff_scnhdr *esecs; 596 597 { 598 ep->f.f_nscns = 6; /* XXX */ 599 600 strcpy(esecs[0].s_name, ".text"); 601 strcpy(esecs[1].s_name, ".data"); 602 strcpy(esecs[2].s_name, ".bss"); 603 604 esecs[0].s_paddr = esecs[0].s_vaddr = ep->a.text_start; 605 esecs[1].s_paddr = esecs[1].s_vaddr = ep->a.data_start; 606 esecs[2].s_paddr = esecs[2].s_vaddr = ep->a.bss_start; 607 esecs[0].s_size = ep->a.tsize; 608 esecs[1].s_size = ep->a.dsize; 609 esecs[2].s_size = ep->a.bsize; 610 611 esecs[0].s_scnptr = ECOFF_TXTOFF(ep); 612 esecs[1].s_scnptr = ECOFF_DATOFF(ep); 613 #if 0 614 esecs[2].s_scnptr = esecs[1].s_scnptr + 615 ECOFF_ROUND(esecs[1].s_size, ECOFF_SEGMENT_ALIGNMENT(ep)); 616 #endif 617 618 esecs[0].s_relptr = esecs[1].s_relptr = esecs[2].s_relptr = 0; 619 esecs[0].s_lnnoptr = esecs[1].s_lnnoptr = esecs[2].s_lnnoptr = 0; 620 esecs[0].s_nreloc = esecs[1].s_nreloc = esecs[2].s_nreloc = 0; 621 esecs[0].s_nlnno = esecs[1].s_nlnno = esecs[2].s_nlnno = 0; 622 623 esecs[1].s_flags = 0x100; /* ECOFF rdata */ 624 esecs[3].s_flags = 0x200; /* ECOFF sdata */ 625 esecs[4].s_flags = 0x400; /* ECOFF sbss */ 626 627 /* 628 * Set the symbol-table offset to point at the end of any 629 * sections we loaded above, so later code can use it to write 630 * symbol table info.. 631 */ 632 ep->f.f_symptr = esecs[1].s_scnptr + esecs[1].s_size; 633 return (ep->f.f_nscns); 634 } 635 636 637 /* 638 * Write the ECOFF symbol header. 639 * Guess at how big the symbol table will be. 640 * Mark all symbols as EXTERN (for now). 641 */ 642 void 643 write_ecoff_symhdr(out, ep, symhdrp, nesyms, extsymoff, extstroff, strsize) 644 int out; 645 struct ecoff_exechdr *ep; 646 struct ecoff_symhdr *symhdrp; 647 long nesyms, extsymoff, extstroff, strsize; 648 { 649 if (debug) 650 fprintf(stderr, "writing symhdr for %ld entries at offset 0x%lx\n", 651 nesyms, (u_long) ep->f.f_symptr); 652 653 ep->f.f_nsyms = sizeof(struct ecoff_symhdr); 654 655 memset(symhdrp, 0, sizeof(*symhdrp)); 656 symhdrp->esymMax = nesyms; 657 symhdrp->magic = 0x7009;/* XXX */ 658 symhdrp->cbExtOffset = extsymoff; 659 symhdrp->cbSsExtOffset = extstroff; 660 661 symhdrp->issExtMax = strsize; 662 if (debug) 663 fprintf(stderr, 664 "ECOFF symhdr: symhdr %zx, strsize %lx, symsize %lx\n", 665 sizeof(*symhdrp), strsize, 666 (nesyms * sizeof(struct ecoff_extsym))); 667 668 if (needswap) { 669 bswap32_region(&symhdrp->ilineMax, 670 sizeof(*symhdrp) - sizeof(symhdrp->magic) - 671 sizeof(symhdrp->ilineMax)); 672 symhdrp->magic = bswap16(symhdrp->magic); 673 symhdrp->ilineMax = bswap16(symhdrp->ilineMax); 674 } 675 676 safewrite(out, symhdrp, sizeof(*symhdrp), 677 "writing symbol header: %s\n"); 678 } 679 680 681 void 682 elf_read_syms(elfsymsp, in, symoff, symsize, stroff, strsize) 683 struct elf_syms *elfsymsp; 684 int in; 685 off_t symoff, symsize; 686 off_t stroff, strsize; 687 { 688 register int nsyms; 689 int i; 690 nsyms = symsize / sizeof(Elf32_Sym); 691 692 /* Suck in the ELF symbol list... */ 693 elfsymsp->elf_syms = (Elf32_Sym *) 694 saveRead(in, symoff, nsyms * sizeof(Elf32_Sym), 695 "ELF symboltable"); 696 elfsymsp->nsymbols = nsyms; 697 if (needswap) { 698 for (i = 0; i < nsyms; i++) { 699 Elf32_Sym *s = &elfsymsp->elf_syms[i]; 700 s->st_name = bswap32(s->st_name); 701 s->st_value = bswap32(s->st_value); 702 s->st_size = bswap32(s->st_size); 703 s->st_shndx = bswap16(s->st_shndx); 704 } 705 } 706 707 /* Suck in the ELF string table... */ 708 elfsymsp->stringtab = (char *) 709 saveRead(in, stroff, strsize, "ELF string table"); 710 elfsymsp->stringsize = strsize; 711 } 712 713 714 /* 715 * 716 */ 717 void 718 elf_symbol_table_to_ecoff(out, in, ep, symoff, symsize, stroff, strsize) 719 int out, in; 720 struct ecoff_exechdr *ep; 721 off_t symoff, symsize; 722 off_t stroff, strsize; 723 { 724 725 struct elf_syms elfsymtab; 726 struct ecoff_syms ecoffsymtab; 727 register u_long ecoff_symhdr_off, symtaboff, stringtaboff; 728 register u_long nextoff, symtabsize, ecoff_strsize; 729 int nsyms, i; 730 struct ecoff_symhdr symhdr; 731 int padding; 732 733 /* Read in the ELF symbols. */ 734 elf_read_syms(&elfsymtab, in, symoff, symsize, stroff, strsize); 735 736 /* Approximate translation to ECOFF. */ 737 translate_syms(&elfsymtab, &ecoffsymtab); 738 nsyms = ecoffsymtab.nsymbols; 739 740 /* Compute output ECOFF symbol- and string-table offsets. */ 741 ecoff_symhdr_off = ep->f.f_symptr; 742 743 nextoff = ecoff_symhdr_off + sizeof(struct ecoff_symhdr); 744 stringtaboff = nextoff; 745 ecoff_strsize = ECOFF_ROUND(ecoffsymtab.stringsize, 746 (ECOFF_SEGMENT_ALIGNMENT(ep))); 747 748 749 nextoff = stringtaboff + ecoff_strsize; 750 symtaboff = nextoff; 751 symtabsize = nsyms * sizeof(struct ecoff_extsym); 752 symtabsize = ECOFF_ROUND(symtabsize, ECOFF_SEGMENT_ALIGNMENT(ep)); 753 754 /* Write out the symbol header ... */ 755 write_ecoff_symhdr(out, ep, &symhdr, nsyms, symtaboff, 756 stringtaboff, ecoffsymtab.stringsize); 757 758 /* Write out the string table... */ 759 padding = ecoff_strsize - ecoffsymtab.stringsize; 760 safewrite(out, ecoffsymtab.stringtab, ecoffsymtab.stringsize, 761 "string table: write: %s\n"); 762 if (padding) 763 pad16(out, padding, "string table: padding: %s\n"); 764 765 766 /* Write out the symbol table... */ 767 padding = symtabsize - (nsyms * sizeof(struct ecoff_extsym)); 768 769 for (i = 0; i < nsyms; i++) { 770 struct ecoff_extsym *es = &ecoffsymtab.ecoff_syms[i]; 771 es->es_flags = bswap16(es->es_flags); 772 es->es_ifd = bswap16(es->es_ifd); 773 bswap32_region(&es->es_strindex, 774 sizeof(*es) - sizeof(es->es_flags) - sizeof(es->es_ifd)); 775 } 776 safewrite(out, ecoffsymtab.ecoff_syms, 777 nsyms * sizeof(struct ecoff_extsym), 778 "symbol table: write: %s\n"); 779 if (padding) 780 pad16(out, padding, "symbols: padding: %s\n"); 781 } 782 783 784 785 /* 786 * In-memory translation of ELF symbosl to ECOFF. 787 */ 788 void 789 translate_syms(elfp, ecoffp) 790 struct elf_syms *elfp; 791 struct ecoff_syms *ecoffp; 792 { 793 794 int i; 795 char *oldstringbase; 796 char *newstrings, *nsp; 797 798 int nsyms, idx; 799 800 nsyms = elfp->nsymbols; 801 oldstringbase = elfp->stringtab; 802 803 /* Allocate space for corresponding ECOFF symbols. */ 804 memset(ecoffp, 0, sizeof(*ecoffp)); 805 806 ecoffp->nsymbols = 0; 807 ecoffp->ecoff_syms = malloc(sizeof(struct ecoff_extsym) * nsyms); 808 809 /* we are going to be no bigger than the ELF symbol table. */ 810 ecoffp->stringsize = elfp->stringsize; 811 ecoffp->stringtab = malloc(elfp->stringsize); 812 813 newstrings = (char *) ecoffp->stringtab; 814 nsp = (char *) ecoffp->stringtab; 815 if (!newstrings) { 816 fprintf(stderr, "No memory for new string table!\n"); 817 exit(1); 818 } 819 /* Copy and translate symbols... */ 820 idx = 0; 821 for (i = 0; i < nsyms; i++) { 822 int binding, type; 823 824 binding = ELF32_ST_BIND((elfp->elf_syms[i].st_info)); 825 type = ELF32_ST_TYPE((elfp->elf_syms[i].st_info)); 826 827 /* skip strange symbols */ 828 if (binding == 0) { 829 continue; 830 } 831 /* Copy the symbol into the new table */ 832 strcpy(nsp, oldstringbase + elfp->elf_syms[i].st_name); 833 ecoffp->ecoff_syms[idx].es_strindex = nsp - newstrings; 834 nsp += strlen(nsp) + 1; 835 836 /* translate symbol types to ECOFF XXX */ 837 ecoffp->ecoff_syms[idx].es_type = 1; 838 ecoffp->ecoff_syms[idx].es_class = 5; 839 840 /* Symbol values in executables should be compatible. */ 841 ecoffp->ecoff_syms[idx].es_value = elfp->elf_syms[i].st_value; 842 ecoffp->ecoff_syms[idx].es_symauxindex = 0xfffff; 843 844 idx++; 845 } 846 847 ecoffp->nsymbols = idx; 848 ecoffp->stringsize = nsp - newstrings; 849 } 850 /* 851 * pad to a 16-byte boundary 852 */ 853 void 854 pad16(int fd, int size, const char *msg) 855 { 856 safewrite(fd, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", size, msg); 857 } 858 859 /* swap a 32bit region */ 860 void 861 bswap32_region(int32_t* p, int len) 862 { 863 size_t i; 864 865 for (i = 0; i < len / sizeof(int32_t); i++, p++) 866 *p = bswap32(*p); 867 } 868