elf2ecoff.c revision 1.10
1/* $NetBSD: elf2ecoff.c,v 1.10 1998/08/10 03:11:07 perry 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#include <sys/types.h> 41#include <fcntl.h> 42#include <unistd.h> 43#include <sys/exec.h> 44#include <sys/exec_elf.h> 45#include <sys/exec_aout.h> 46#include <stdio.h> 47#include <sys/exec_ecoff.h> 48#include <sys/errno.h> 49#include <stdlib.h> 50#include <string.h> 51#include <limits.h> 52 53 54/* Elf Program segment permissions, in program header flags field */ 55 56#define PF_X (1 << 0)/* Segment is executable */ 57#define PF_W (1 << 1)/* Segment is writable */ 58#define PF_R (1 << 2)/* Segment is readable */ 59#define PF_MASKPROC 0xF0000000 /* Processor-specific reserved bits */ 60 61 62#define ISLAST(p) (p->n_un.n_name == 0 || p->n_un.n_name[0] == 0) 63 64struct sect { 65 unsigned long vaddr; 66 unsigned long len; 67}; 68 69struct elf_syms { 70 int nsymbols; 71 Elf32_Sym *elf_syms; 72 off_t stringsize; 73 char *stringtab; 74}; 75 76struct ecoff_syms { 77 int nsymbols; 78 struct ecoff_extsym *ecoff_syms; 79 off_t stringsize; 80 char *stringtab; 81}; 82 83int debug = 0; 84 85int phcmp(Elf32_Phdr * h1, Elf32_Phdr * h2); 86 87 88char *saveRead(int file, off_t offset, off_t len, char *name); 89void safewrite(int outfile, void *buf, off_t len, const char *msg); 90void copy(int, int, off_t, off_t); 91void combine(struct sect * base, struct sect * new, int paddable); 92void translate_syms(struct elf_syms *, struct ecoff_syms *); 93void 94elf_symbol_table_to_ecoff(int out, int in, 95 struct ecoff_exechdr * ep, 96 off_t symoff, off_t symsize, 97 off_t stroff, off_t strsize); 98 99 100int 101make_ecoff_section_hdrs(struct ecoff_exechdr * ep, 102 struct ecoff_scnhdr * esecs); 103 104void 105write_ecoff_symhdr(int outfile, struct ecoff_exechdr * ep, 106 struct ecoff_symhdr * symhdrp, 107 long nesyms, long extsymoff, long extstroff, 108 long strsize); 109 110void pad16(int fd, int size, const char *msg); 111 112extern int errno; 113int *symTypeTable; 114 115 116 117 118void 119elf_read_syms(struct elf_syms * elfsymsp, int infile, 120 off_t symoff, off_t symsize, off_t stroff, off_t strsize); 121 122 123int 124main(int argc, char **argv, char **envp) 125{ 126 Elf32_Ehdr ex; 127 Elf32_Phdr *ph; 128 Elf32_Shdr *sh; 129 char *shstrtab; 130 int strtabix, symtabix; 131 int i, pad; 132 struct sect text, data, bss; /* a.out-compatible sections */ 133 struct sect rdata, sdata, sbss; /* ECOFF-only sections */ 134 135 struct ecoff_exechdr ep; 136 struct ecoff_scnhdr esecs[6]; 137 struct ecoff_symhdr symhdr; 138 139 int infile, outfile; 140 unsigned long cur_vma = ULONG_MAX; 141 int symflag = 0; 142 int nsecs = 0; 143 144 text.len = data.len = bss.len = 0; 145 text.vaddr = data.vaddr = bss.vaddr = 0; 146 147 rdata.len = sdata.len = sbss.len = 0; 148 rdata.vaddr = sdata.vaddr = sbss.vaddr = 0; 149 150 /* Check args... */ 151 if (argc < 3 || argc > 4) { 152usage: 153 fprintf(stderr, 154 "usage: elf2ecoff <elf executable> <ECOFF executable> [-s]\n"); 155 exit(1); 156 } 157 if (argc == 4) { 158 if (strcmp(argv[3], "-s")) 159 goto usage; 160 symflag = 1; 161 } 162 /* Try the input file... */ 163 if ((infile = open(argv[1], O_RDONLY)) < 0) { 164 fprintf(stderr, "Can't open %s for read: %s\n", 165 argv[1], strerror(errno)); 166 exit(1); 167 } 168 /* Read the header, which is at the beginning of the file... */ 169 i = read(infile, &ex, sizeof ex); 170 if (i != sizeof ex) { 171 fprintf(stderr, "ex: %s: %s.\n", 172 argv[1], i ? strerror(errno) : "End of file reached"); 173 exit(1); 174 } 175 /* Read the program headers... */ 176 ph = (Elf32_Phdr *) saveRead(infile, ex.e_phoff, 177 ex.e_phnum * sizeof(Elf32_Phdr), "ph"); 178 /* Read the section headers... */ 179 sh = (Elf32_Shdr *) saveRead(infile, ex.e_shoff, 180 ex.e_shnum * sizeof(Elf32_Shdr), "sh"); 181 /* Read in the section string table. */ 182 shstrtab = saveRead(infile, sh[ex.e_shstrndx].sh_offset, 183 sh[ex.e_shstrndx].sh_size, "shstrtab"); 184 /* Read in the section string table. */ 185 shstrtab = saveRead(infile, sh[ex.e_shstrndx].sh_offset, 186 sh[ex.e_shstrndx].sh_size, "shstrtab"); 187 188 189 /* Look for the symbol table and string table... Also map section 190 * indices to symbol types for a.out */ 191 symtabix = 0; 192 strtabix = 0; 193 for (i = 0; i < ex.e_shnum; i++) { 194 char *name = shstrtab + sh[i].sh_name; 195 if (!strcmp(name, ".symtab")) 196 symtabix = i; 197 else 198 if (!strcmp(name, ".strtab")) 199 strtabix = i; 200 201 } 202 203 /* Figure out if we can cram the program header into an ECOFF 204 * header... Basically, we can't handle anything but loadable 205 * segments, but we can ignore some kinds of segments. We can't 206 * handle holes in the address space. Segments may be out of order, 207 * so we sort them first. */ 208 209 qsort(ph, ex.e_phnum, sizeof(Elf32_Phdr), 210 (int (*) (const void *, const void *)) phcmp); 211 212 for (i = 0; i < ex.e_phnum; i++) { 213 /* Section types we can ignore... */ 214 if (ph[i].p_type == Elf_pt_null || ph[i].p_type == Elf_pt_note || 215 ph[i].p_type == Elf_pt_phdr || 216 ph[i].p_type == Elf_pt_mips_reginfo) { 217 218 if (debug) { 219 fprintf(stderr, " skipping PH %d type %d flags 0x%x\n", 220 i, ph[i].p_type, ph[i].p_flags); 221 } 222 continue; 223 } 224 /* Section types we can't handle... */ 225 else 226 if (ph[i].p_type != Elf_pt_load) { 227 fprintf(stderr, "Program header %d type %d can't be converted.\n", 228 i, ph[i].p_type); 229 exit(1); 230 } 231 /* Writable (data) segment? */ 232 if (ph[i].p_flags & PF_W) { 233 struct sect ndata, nbss; 234 235 ndata.vaddr = ph[i].p_vaddr; 236 ndata.len = ph[i].p_filesz; 237 nbss.vaddr = ph[i].p_vaddr + ph[i].p_filesz; 238 nbss.len = ph[i].p_memsz - ph[i].p_filesz; 239 240 if (debug) { 241 fprintf(stderr, 242 " combinining PH %d 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); 243 } 244 combine(&data, &ndata, 0); 245 combine(&bss, &nbss, 1); 246 } else { 247 struct sect ntxt; 248 249 ntxt.vaddr = ph[i].p_vaddr; 250 ntxt.len = ph[i].p_filesz; 251 if (debug) { 252 253 fprintf(stderr, 254 " combinining PH %d type %d flags 0x%x with text, len = %ld\n", 255 i, ph[i].p_type, ph[i].p_flags, ntxt.len); 256 } 257 combine(&text, &ntxt, 0); 258 } 259 /* Remember the lowest segment start address. */ 260 if (ph[i].p_vaddr < cur_vma) 261 cur_vma = ph[i].p_vaddr; 262 } 263 264 /* Sections must be in order to be converted... */ 265 if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr || 266 text.vaddr + text.len > data.vaddr || data.vaddr + data.len > bss.vaddr) { 267 fprintf(stderr, "Sections ordering prevents a.out conversion.\n"); 268 exit(1); 269 } 270 /* If there's a data section but no text section, then the loader 271 * combined everything into one section. That needs to be the text 272 * section, so just make the data section zero length following text. */ 273 if (data.len && !text.len) { 274 text = data; 275 data.vaddr = text.vaddr + text.len; 276 data.len = 0; 277 } 278 /* If there is a gap between text and data, we'll fill it when we copy 279 * the data, so update the length of the text segment as represented 280 * in a.out to reflect that, since a.out doesn't allow gaps in the 281 * program address space. */ 282 if (text.vaddr + text.len < data.vaddr) 283 text.len = data.vaddr - text.vaddr; 284 285 /* We now have enough information to cons up an a.out header... */ 286 ep.a.magic = ECOFF_OMAGIC; 287 ep.a.vstamp = 2 * 256 + 10; /* compatible with version 2.10 */ 288 ep.a.tsize = text.len; 289 ep.a.dsize = data.len; 290 ep.a.bsize = bss.len; 291 ep.a.entry = ex.e_entry; 292 ep.a.text_start = text.vaddr; 293 ep.a.data_start = data.vaddr; 294 ep.a.bss_start = bss.vaddr; 295 ep.a.gprmask = 0xf3fffffe; 296 memset(&ep.a.cprmask, 0, sizeof ep.a.cprmask); 297 ep.a.gp_value = 0; /* unused. */ 298 299 ep.f.f_magic = ECOFF_MAGIC_MIPSEL; 300 ep.f.f_nscns = 6; 301 ep.f.f_timdat = 0; /* bogus */ 302 ep.f.f_symptr = 0; 303 ep.f.f_nsyms = sizeof(struct ecoff_symhdr); 304 ep.f.f_opthdr = sizeof ep.a; 305 ep.f.f_flags = 0x100f; /* Stripped, not sharable. */ 306 307 memset(esecs, 0, sizeof(esecs)); 308 309 /* Make ECOFF section headers, with empty stubs for 310 * .rdata/.sdata/.sbss. */ 311 make_ecoff_section_hdrs(&ep, esecs); 312 313 nsecs = ep.f.f_nscns; 314 315 /* Make the output file... */ 316 if ((outfile = open(argv[2], O_WRONLY | O_CREAT, 0777)) < 0) { 317 fprintf(stderr, "Unable to create %s: %s\n", argv[2], strerror(errno)); 318 exit(1); 319 } 320 /* Write the headers... */ 321 safewrite(outfile, &ep.f, sizeof(ep.f), "ep.f: write: %s\n"); 322 fprintf(stderr, "wrote %d byte file header.\n", sizeof(ep.f)); 323 324 safewrite(outfile, &ep.a, sizeof(ep.a), "ep.a: write: %s\n"); 325 fprintf(stderr, "wrote %d byte a.out header.\n", sizeof(ep.a)); 326 327 safewrite(outfile, &esecs, sizeof(esecs[0]) * nsecs, 328 "esecs: write: %s\n"); 329 fprintf(stderr, "wrote %d bytes of section headers.\n", 330 sizeof(esecs[0]) * nsecs); 331 332 333 pad = ((sizeof ep.f + sizeof ep.a + sizeof esecs) & 15); 334 if (pad) { 335 pad = 16 - pad; 336 pad16(outfile, pad, "ipad: write: %s\n"); 337 fprintf(stderr, "wrote %d byte pad.\n", pad); 338 } 339 /* Copy the loadable sections. Zero-fill any gaps less than 64k; 340 * complain about any zero-filling, and die if we're asked to 341 * zero-fill more than 64k. */ 342 for (i = 0; i < ex.e_phnum; i++) { 343 /* Unprocessable sections were handled above, so just verify 344 * that the section can be loaded before copying. */ 345 if (ph[i].p_type == Elf_pt_load && ph[i].p_filesz) { 346 if (cur_vma != ph[i].p_vaddr) { 347 unsigned long gap = ph[i].p_vaddr - cur_vma; 348 char obuf[1024]; 349 if (gap > 65536) { 350 fprintf(stderr, "Intersegment gap (%ld bytes) too large.\n", 351 gap); 352 exit(1); 353 } 354 fprintf(stderr, "Warning: %ld byte intersegment gap.\n", gap); 355 memset(obuf, 0, sizeof obuf); 356 while (gap) { 357 int count = write(outfile, obuf, (gap > sizeof obuf 358 ? sizeof obuf : gap)); 359 if (count < 0) { 360 fprintf(stderr, "Error writing gap: %s\n", 361 strerror(errno)); 362 exit(1); 363 } 364 gap -= count; 365 } 366 } 367 fprintf(stderr, "writing %d bytes...\n", ph[i].p_filesz); 368 copy(outfile, infile, ph[i].p_offset, ph[i].p_filesz); 369 cur_vma = ph[i].p_vaddr + ph[i].p_filesz; 370 } 371 } 372 373 374 if (debug) 375 fprintf(stderr, "writing syms at offset 0x%lx\n", 376 (u_long) ep.f.f_symptr + sizeof(symhdr)); 377 378 /* Copy and translate the symbol table... */ 379 elf_symbol_table_to_ecoff(outfile, infile, &ep, 380 sh[symtabix].sh_offset, sh[symtabix].sh_size, 381 sh[strtabix].sh_offset, sh[strtabix].sh_size); 382 383 /* 384 * Write a page of padding for boot PROMS that read entire pages. 385 * Without this, they may attempt to read past the end of the 386 * data section, incur an error, and refuse to boot. 387 */ 388 { 389 char obuf[4096]; 390 memset(obuf, 0, sizeof obuf); 391 if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf)) { 392 fprintf(stderr, "Error writing PROM padding: %s\n", 393 strerror(errno)); 394 exit(1); 395 } 396 } 397 398 /* Looks like we won... */ 399 exit(0); 400} 401 402void 403copy(out, in, offset, size) 404 int out, in; 405 off_t offset, size; 406{ 407 char ibuf[4096]; 408 int remaining, cur, count; 409 410 /* Go the the start of the ELF symbol table... */ 411 if (lseek(in, offset, SEEK_SET) < 0) { 412 perror("copy: lseek"); 413 exit(1); 414 } 415 remaining = size; 416 while (remaining) { 417 cur = remaining; 418 if (cur > sizeof ibuf) 419 cur = sizeof ibuf; 420 remaining -= cur; 421 if ((count = read(in, ibuf, cur)) != cur) { 422 fprintf(stderr, "copy: read: %s\n", 423 count ? strerror(errno) : "premature end of file"); 424 exit(1); 425 } 426 safewrite(out, ibuf, cur, "copy: write: %s\n"); 427 } 428} 429/* Combine two segments, which must be contiguous. If pad is true, it's 430 okay for there to be padding between. */ 431void 432combine(base, new, pad) 433 struct sect *base, *new; 434 int pad; 435{ 436 if (!base->len) 437 *base = *new; 438 else 439 if (new->len) { 440 if (base->vaddr + base->len != new->vaddr) { 441 if (pad) 442 base->len = new->vaddr - base->vaddr; 443 else { 444 fprintf(stderr, 445 "Non-contiguous data can't be converted.\n"); 446 exit(1); 447 } 448 } 449 base->len += new->len; 450 } 451} 452 453int 454phcmp(h1, h2) 455 Elf32_Phdr *h1, *h2; 456{ 457 if (h1->p_vaddr > h2->p_vaddr) 458 return 1; 459 else 460 if (h1->p_vaddr < h2->p_vaddr) 461 return -1; 462 else 463 return 0; 464} 465 466char 467 * 468saveRead(int file, off_t offset, off_t len, char *name) 469{ 470 char *tmp; 471 int count; 472 off_t off; 473 if ((off = lseek(file, offset, SEEK_SET)) < 0) { 474 fprintf(stderr, "%s: fseek: %s\n", name, strerror(errno)); 475 exit(1); 476 } 477 if (!(tmp = (char *) malloc(len))) { 478 fprintf(stderr, "%s: Can't allocate %ld bytes.\n", name, (long) len); 479 exit(1); 480 } 481 count = read(file, tmp, len); 482 if (count != len) { 483 fprintf(stderr, "%s: read: %s.\n", 484 name, count ? strerror(errno) : "End of file reached"); 485 exit(1); 486 } 487 return tmp; 488} 489 490void 491safewrite(int outfile, void *buf, off_t len, const char *msg) 492{ 493 int written; 494 written = write(outfile, (char *) buf, len); 495 if (written != len) { 496 fprintf(stderr, msg, strerror(errno)); 497 exit(1); 498 } 499} 500 501 502/* 503 * Output only three ECOFF sections, corresponding to ELF psecs 504 * for text, data, and bss. 505 */ 506int 507make_ecoff_section_hdrs(ep, esecs) 508 struct ecoff_exechdr *ep; 509 struct ecoff_scnhdr *esecs; 510 511{ 512 ep->f.f_nscns = 6; /* XXX */ 513 514 strcpy(esecs[0].s_name, ".text"); 515 strcpy(esecs[1].s_name, ".data"); 516 strcpy(esecs[2].s_name, ".bss"); 517 518 esecs[0].s_paddr = esecs[0].s_vaddr = ep->a.text_start; 519 esecs[1].s_paddr = esecs[1].s_vaddr = ep->a.data_start; 520 esecs[2].s_paddr = esecs[2].s_vaddr = ep->a.bss_start; 521 esecs[0].s_size = ep->a.tsize; 522 esecs[1].s_size = ep->a.dsize; 523 esecs[2].s_size = ep->a.bsize; 524 525 esecs[0].s_scnptr = ECOFF_TXTOFF(ep); 526 esecs[1].s_scnptr = ECOFF_DATOFF(ep); 527#if 0 528 esecs[2].s_scnptr = esecs[1].s_scnptr + 529 ECOFF_ROUND(esecs[1].s_size, ECOFF_SEGMENT_ALIGNMENT(ep)); 530#endif 531 532 esecs[0].s_relptr = esecs[1].s_relptr = esecs[2].s_relptr = 0; 533 esecs[0].s_lnnoptr = esecs[1].s_lnnoptr = esecs[2].s_lnnoptr = 0; 534 esecs[0].s_nreloc = esecs[1].s_nreloc = esecs[2].s_nreloc = 0; 535 esecs[0].s_nlnno = esecs[1].s_nlnno = esecs[2].s_nlnno = 0; 536 537 esecs[1].s_flags = 0x100; /* ECOFF rdata */ 538 esecs[3].s_flags = 0x200; /* ECOFF sdata */ 539 esecs[4].s_flags = 0x400; /* ECOFF sbss */ 540 541 /* 542 * Set the symbol-table offset to point at the end of any 543 * sections we loaded above, so later code can use it to write 544 * symbol table info.. 545 */ 546 ep->f.f_symptr = esecs[1].s_scnptr + esecs[1].s_size; 547 return (ep->f.f_nscns); 548} 549 550 551/* 552 * Write the ECOFF symbol header. 553 * Guess at how big the symbol table will be. 554 * Mark all symbols as EXTERN (for now). 555 */ 556void 557write_ecoff_symhdr(out, ep, symhdrp, nesyms, extsymoff, extstroff, strsize) 558 int out; 559 struct ecoff_exechdr *ep; 560 struct ecoff_symhdr *symhdrp; 561 long nesyms, extsymoff, extstroff, strsize; 562{ 563 if (debug) 564 fprintf(stderr, "writing symhdr for %ld entries at offset 0x%lx\n", 565 nesyms, (u_long) ep->f.f_symptr); 566 567 ep->f.f_nsyms = sizeof(struct ecoff_symhdr); 568 569 memset(symhdrp, 0, sizeof(*symhdrp)); 570 symhdrp->esymMax = nesyms; 571 symhdrp->magic = 0x7009;/* XXX */ 572 symhdrp->cbExtOffset = extsymoff; 573 symhdrp->cbSsExtOffset = extstroff; 574 575 symhdrp->issExtMax = strsize; 576 if (debug) 577 fprintf(stderr, 578 "ECOFF symhdr: symhdr %x, strsize %lx, symsize %lx\n", 579 sizeof(*symhdrp), strsize, 580 (nesyms * sizeof(struct ecoff_extsym))); 581 582 safewrite(out, symhdrp, sizeof(*symhdrp), 583 "writing symbol header: %s\n"); 584} 585 586 587void 588elf_read_syms(elfsymsp, in, symoff, symsize, stroff, strsize) 589 struct elf_syms *elfsymsp; 590 int in; 591 off_t symoff, symsize; 592 off_t stroff, strsize; 593{ 594 register int nsyms; 595 nsyms = symsize / sizeof(Elf32_Sym); 596 597 /* Suck in the ELF symbol list... */ 598 elfsymsp->elf_syms = (Elf32_Sym *) 599 saveRead(in, symoff, nsyms * sizeof(Elf32_Sym), 600 "ELF symboltable"); 601 elfsymsp->nsymbols = nsyms; 602 603 /* Suck in the ELF string table... */ 604 elfsymsp->stringtab = (char *) 605 saveRead(in, stroff, strsize, "ELF string table"); 606 elfsymsp->stringsize = strsize; 607} 608 609 610/* 611 * 612 */ 613void 614elf_symbol_table_to_ecoff(out, in, ep, symoff, symsize, stroff, strsize) 615 int out, in; 616 struct ecoff_exechdr *ep; 617 off_t symoff, symsize; 618 off_t stroff, strsize; 619{ 620 621 struct elf_syms elfsymtab; 622 struct ecoff_syms ecoffsymtab; 623 register u_long ecoff_symhdr_off, symtaboff, stringtaboff; 624 register u_long nextoff, symtabsize, ecoff_strsize; 625 int nsyms; 626 struct ecoff_symhdr symhdr; 627 int padding; 628 629 /* Read in the ELF symbols. */ 630 elf_read_syms(&elfsymtab, in, symoff, symsize, stroff, strsize); 631 632 /* Approximate translation to ECOFF. */ 633 translate_syms(&elfsymtab, &ecoffsymtab); 634 nsyms = ecoffsymtab.nsymbols; 635 636 /* Compute output ECOFF symbol- and string-table offsets. */ 637 ecoff_symhdr_off = ep->f.f_symptr; 638 639 nextoff = ecoff_symhdr_off + sizeof(struct ecoff_symhdr); 640 stringtaboff = nextoff; 641 ecoff_strsize = ECOFF_ROUND(ecoffsymtab.stringsize, 642 (ECOFF_SEGMENT_ALIGNMENT(ep))); 643 644 645 nextoff = stringtaboff + ecoff_strsize; 646 symtaboff = nextoff; 647 symtabsize = nsyms * sizeof(struct ecoff_extsym); 648 symtabsize = ECOFF_ROUND(symtabsize, ECOFF_SEGMENT_ALIGNMENT(ep)); 649 650 /* Write out the symbol header ... */ 651 write_ecoff_symhdr(out, ep, &symhdr, nsyms, symtaboff, 652 stringtaboff, ecoffsymtab.stringsize); 653 654 /* Write out the string table... */ 655 padding = ecoff_strsize - ecoffsymtab.stringsize; 656 safewrite(out, ecoffsymtab.stringtab, ecoffsymtab.stringsize, 657 "string table: write: %s\n"); 658 if (padding) 659 pad16(out, padding, "string table: padding: %s\n"); 660 661 662 /* Write out the symbol table... */ 663 padding = symtabsize - (nsyms * sizeof(struct ecoff_extsym)); 664 safewrite(out, ecoffsymtab.ecoff_syms, 665 nsyms * sizeof(struct ecoff_extsym), 666 "symbol table: write: %s\n"); 667 if (padding) 668 pad16(out, padding, "symbols: padding: %s\n"); 669} 670 671 672 673/* 674 * In-memory translation of ELF symbosl to ECOFF. 675 */ 676void 677translate_syms(elfp, ecoffp) 678 struct elf_syms *elfp; 679 struct ecoff_syms *ecoffp; 680{ 681 682 int i; 683 char *oldstringbase; 684 char *newstrings, *nsp; 685 686 int nsyms, idx; 687 688 nsyms = elfp->nsymbols; 689 oldstringbase = elfp->stringtab; 690 691 /* Allocate space for corresponding ECOFF symbols. */ 692 memset(ecoffp, 0, sizeof(*ecoffp)); 693 694 ecoffp->nsymbols = 0; 695 ecoffp->ecoff_syms = malloc(sizeof(struct ecoff_extsym) * nsyms); 696 697 /* we are going to be no bigger than the ELF symbol table. */ 698 ecoffp->stringsize = elfp->stringsize; 699 ecoffp->stringtab = malloc(elfp->stringsize); 700 701 newstrings = (char *) ecoffp->stringtab; 702 nsp = (char *) ecoffp->stringtab; 703 if (!newstrings) { 704 fprintf(stderr, "No memory for new string table!\n"); 705 exit(1); 706 } 707 /* Copy and translate symbols... */ 708 idx = 0; 709 for (i = 0; i < nsyms; i++) { 710 int binding, type; 711 712 binding = ELF_SYM_BIND((elfp->elf_syms[i].st_info)); 713 type = ELF_SYM_TYPE((elfp->elf_syms[i].st_info)); 714 715 /* skip strange symbols */ 716 if (binding == 0) { 717 continue; 718 } 719 /* Copy the symbol into the new table */ 720 strcpy(nsp, oldstringbase + elfp->elf_syms[i].st_name); 721 ecoffp->ecoff_syms[idx].es_strindex = nsp - newstrings; 722 nsp += strlen(nsp) + 1; 723 724 /* translate symbol types to ECOFF XXX */ 725 ecoffp->ecoff_syms[idx].es_type = 1; 726 ecoffp->ecoff_syms[idx].es_class = 5; 727 728 /* Symbol values in executables should be compatible. */ 729 ecoffp->ecoff_syms[idx].es_value = elfp->elf_syms[i].st_value; 730 ecoffp->ecoff_syms[idx].es_symauxindex = 0xfffff; 731 732 idx++; 733 } 734 735 ecoffp->nsymbols = idx; 736 ecoffp->stringsize = nsp - newstrings; 737} 738/* 739 * pad to a 16-byte boundary 740 */ 741void 742pad16(int fd, int size, const char *msg) 743{ 744 safewrite(fd, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", size, msg); 745} 746