1 /* simple-object-coff.c -- routines to manipulate COFF object files. 2 Copyright 2010 Free Software Foundation, Inc. 3 Written by Ian Lance Taylor, Google. 4 5 This program is free software; you can redistribute it and/or modify it 6 under the terms of the GNU General Public License as published by the 7 Free Software Foundation; either version 2, or (at your option) any 8 later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, 51 Franklin Street - Fifth Floor, 18 Boston, MA 02110-1301, USA. */ 19 20 #include "config.h" 21 #include "libiberty.h" 22 #include "simple-object.h" 23 24 #include <errno.h> 25 #include <stddef.h> 26 27 #ifdef HAVE_STDLIB_H 28 #include <stdlib.h> 29 #endif 30 31 #ifdef HAVE_STDINT_H 32 #include <stdint.h> 33 #endif 34 35 #ifdef HAVE_STRING_H 36 #include <string.h> 37 #endif 38 39 #ifdef HAVE_INTTYPES_H 40 #include <inttypes.h> 41 #endif 42 43 #include "simple-object-common.h" 44 45 /* COFF structures and constants. */ 46 47 /* COFF file header. */ 48 49 struct external_filehdr 50 { 51 unsigned char f_magic[2]; /* magic number */ 52 unsigned char f_nscns[2]; /* number of sections */ 53 unsigned char f_timdat[4]; /* time & date stamp */ 54 unsigned char f_symptr[4]; /* file pointer to symtab */ 55 unsigned char f_nsyms[4]; /* number of symtab entries */ 56 unsigned char f_opthdr[2]; /* sizeof(optional hdr) */ 57 unsigned char f_flags[2]; /* flags */ 58 }; 59 60 /* Bits for filehdr f_flags field. */ 61 62 #define F_EXEC (0x0002) 63 #define IMAGE_FILE_SYSTEM (0x1000) 64 #define IMAGE_FILE_DLL (0x2000) 65 66 /* COFF section header. */ 67 68 struct external_scnhdr 69 { 70 unsigned char s_name[8]; /* section name */ 71 unsigned char s_paddr[4]; /* physical address, aliased s_nlib */ 72 unsigned char s_vaddr[4]; /* virtual address */ 73 unsigned char s_size[4]; /* section size */ 74 unsigned char s_scnptr[4]; /* file ptr to raw data for section */ 75 unsigned char s_relptr[4]; /* file ptr to relocation */ 76 unsigned char s_lnnoptr[4]; /* file ptr to line numbers */ 77 unsigned char s_nreloc[2]; /* number of relocation entries */ 78 unsigned char s_nlnno[2]; /* number of line number entries */ 79 unsigned char s_flags[4]; /* flags */ 80 }; 81 82 /* The length of the s_name field in struct external_scnhdr. */ 83 84 #define SCNNMLEN (8) 85 86 /* Bits for scnhdr s_flags field. This includes some bits defined 87 only for PE. This may need to be moved into coff_magic. */ 88 89 #define STYP_DATA (1 << 6) 90 #define IMAGE_SCN_MEM_DISCARDABLE (1 << 25) 91 #define IMAGE_SCN_MEM_SHARED (1 << 28) 92 #define IMAGE_SCN_MEM_READ (1 << 30) 93 94 #define IMAGE_SCN_ALIGN_POWER_BIT_POS 20 95 #define IMAGE_SCN_ALIGN_POWER_CONST(val) \ 96 (((val) + 1) << IMAGE_SCN_ALIGN_POWER_BIT_POS) 97 98 /* COFF symbol table entry. */ 99 100 #define E_SYMNMLEN 8 /* # characters in a symbol name */ 101 102 struct external_syment 103 { 104 union 105 { 106 unsigned char e_name[E_SYMNMLEN]; 107 108 struct 109 { 110 unsigned char e_zeroes[4]; 111 unsigned char e_offset[4]; 112 } e; 113 } e; 114 115 unsigned char e_value[4]; 116 unsigned char e_scnum[2]; 117 unsigned char e_type[2]; 118 unsigned char e_sclass[1]; 119 unsigned char e_numaux[1]; 120 }; 121 122 /* Length allowed for filename in aux sym format 4. */ 123 124 #define E_FILNMLEN 18 125 126 /* Omits x_sym and other unused variants. */ 127 128 union external_auxent 129 { 130 /* Aux sym format 4: file. */ 131 union 132 { 133 char x_fname[E_FILNMLEN]; 134 struct 135 { 136 unsigned char x_zeroes[4]; 137 unsigned char x_offset[4]; 138 } x_n; 139 } x_file; 140 /* Aux sym format 5: section. */ 141 struct 142 { 143 unsigned char x_scnlen[4]; /* section length */ 144 unsigned char x_nreloc[2]; /* # relocation entries */ 145 unsigned char x_nlinno[2]; /* # line numbers */ 146 unsigned char x_checksum[4]; /* section COMDAT checksum */ 147 unsigned char x_associated[2]; /* COMDAT assoc section index */ 148 unsigned char x_comdat[1]; /* COMDAT selection number */ 149 } x_scn; 150 }; 151 152 /* Symbol-related constants. */ 153 154 #define IMAGE_SYM_DEBUG (-2) 155 #define IMAGE_SYM_TYPE_NULL (0) 156 #define IMAGE_SYM_DTYPE_NULL (0) 157 #define IMAGE_SYM_CLASS_STATIC (3) 158 #define IMAGE_SYM_CLASS_FILE (103) 159 160 #define IMAGE_SYM_TYPE \ 161 ((IMAGE_SYM_DTYPE_NULL << 4) | IMAGE_SYM_TYPE_NULL) 162 163 /* Private data for an simple_object_read. */ 164 165 struct simple_object_coff_read 166 { 167 /* Magic number. */ 168 unsigned short magic; 169 /* Whether the file is big-endian. */ 170 unsigned char is_big_endian; 171 /* Number of sections. */ 172 unsigned short nscns; 173 /* File offset of symbol table. */ 174 off_t symptr; 175 /* Number of symbol table entries. */ 176 unsigned int nsyms; 177 /* Flags. */ 178 unsigned short flags; 179 /* Offset of section headers in file. */ 180 off_t scnhdr_offset; 181 }; 182 183 /* Private data for an simple_object_attributes. */ 184 185 struct simple_object_coff_attributes 186 { 187 /* Magic number. */ 188 unsigned short magic; 189 /* Whether the file is big-endian. */ 190 unsigned char is_big_endian; 191 /* Flags. */ 192 unsigned short flags; 193 }; 194 195 /* There is no magic number which indicates a COFF file as opposed to 196 any other sort of file. Instead, each COFF file starts with a 197 two-byte magic number which also indicates the type of the target. 198 This struct holds a magic number as well as characteristics of that 199 COFF format. */ 200 201 struct coff_magic_struct 202 { 203 /* Magic number. */ 204 unsigned short magic; 205 /* Whether this magic number is for a big-endian file. */ 206 unsigned char is_big_endian; 207 /* Flag bits, in the f_flags fields, which indicates that this file 208 is not a relocatable object file. There is no flag which 209 specifically indicates a relocatable object file, it is only 210 implied by the absence of these flags. */ 211 unsigned short non_object_flags; 212 }; 213 214 /* This is a list of the COFF magic numbers which we recognize, namely 215 the ones used on Windows. More can be added as needed. */ 216 217 static const struct coff_magic_struct coff_magic[] = 218 { 219 /* i386. */ 220 { 0x14c, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL }, 221 /* x86_64. */ 222 { 0x8664, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL } 223 }; 224 225 /* See if we have a COFF file. */ 226 227 static void * 228 simple_object_coff_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN], 229 int descriptor, off_t offset, 230 const char *segment_name ATTRIBUTE_UNUSED, 231 const char **errmsg, int *err) 232 { 233 size_t c; 234 unsigned short magic_big; 235 unsigned short magic_little; 236 unsigned short magic; 237 size_t i; 238 int is_big_endian; 239 unsigned short (*fetch_16) (const unsigned char *); 240 unsigned int (*fetch_32) (const unsigned char *); 241 unsigned char hdrbuf[sizeof (struct external_filehdr)]; 242 unsigned short flags; 243 struct simple_object_coff_read *ocr; 244 245 c = sizeof (coff_magic) / sizeof (coff_magic[0]); 246 magic_big = simple_object_fetch_big_16 (header); 247 magic_little = simple_object_fetch_little_16 (header); 248 for (i = 0; i < c; ++i) 249 { 250 if (coff_magic[i].is_big_endian 251 ? coff_magic[i].magic == magic_big 252 : coff_magic[i].magic == magic_little) 253 break; 254 } 255 if (i >= c) 256 { 257 *errmsg = NULL; 258 *err = 0; 259 return NULL; 260 } 261 is_big_endian = coff_magic[i].is_big_endian; 262 263 magic = is_big_endian ? magic_big : magic_little; 264 fetch_16 = (is_big_endian 265 ? simple_object_fetch_big_16 266 : simple_object_fetch_little_16); 267 fetch_32 = (is_big_endian 268 ? simple_object_fetch_big_32 269 : simple_object_fetch_little_32); 270 271 if (!simple_object_internal_read (descriptor, offset, hdrbuf, sizeof hdrbuf, 272 errmsg, err)) 273 return NULL; 274 275 flags = fetch_16 (hdrbuf + offsetof (struct external_filehdr, f_flags)); 276 if ((flags & coff_magic[i].non_object_flags) != 0) 277 { 278 *errmsg = "not relocatable object file"; 279 *err = 0; 280 return NULL; 281 } 282 283 ocr = XNEW (struct simple_object_coff_read); 284 ocr->magic = magic; 285 ocr->is_big_endian = is_big_endian; 286 ocr->nscns = fetch_16 (hdrbuf + offsetof (struct external_filehdr, f_nscns)); 287 ocr->symptr = fetch_32 (hdrbuf 288 + offsetof (struct external_filehdr, f_symptr)); 289 ocr->nsyms = fetch_32 (hdrbuf + offsetof (struct external_filehdr, f_nsyms)); 290 ocr->flags = flags; 291 ocr->scnhdr_offset = (sizeof (struct external_filehdr) 292 + fetch_16 (hdrbuf + offsetof (struct external_filehdr, 293 f_opthdr))); 294 295 return (void *) ocr; 296 } 297 298 /* Read the string table in a COFF file. */ 299 300 static char * 301 simple_object_coff_read_strtab (simple_object_read *sobj, size_t *strtab_size, 302 const char **errmsg, int *err) 303 { 304 struct simple_object_coff_read *ocr = 305 (struct simple_object_coff_read *) sobj->data; 306 off_t strtab_offset; 307 unsigned char strsizebuf[4]; 308 size_t strsize; 309 char *strtab; 310 311 strtab_offset = sobj->offset + ocr->symptr 312 + ocr->nsyms * sizeof (struct external_syment); 313 if (!simple_object_internal_read (sobj->descriptor, strtab_offset, 314 strsizebuf, 4, errmsg, err)) 315 return NULL; 316 strsize = (ocr->is_big_endian 317 ? simple_object_fetch_big_32 (strsizebuf) 318 : simple_object_fetch_little_32 (strsizebuf)); 319 strtab = XNEWVEC (char, strsize); 320 if (!simple_object_internal_read (sobj->descriptor, strtab_offset, 321 (unsigned char *) strtab, strsize, errmsg, 322 err)) 323 { 324 XDELETEVEC (strtab); 325 return NULL; 326 } 327 *strtab_size = strsize; 328 return strtab; 329 } 330 331 /* Find all sections in a COFF file. */ 332 333 static const char * 334 simple_object_coff_find_sections (simple_object_read *sobj, 335 int (*pfn) (void *, const char *, 336 off_t offset, off_t length), 337 void *data, 338 int *err) 339 { 340 struct simple_object_coff_read *ocr = 341 (struct simple_object_coff_read *) sobj->data; 342 size_t scnhdr_size; 343 unsigned char *scnbuf; 344 const char *errmsg; 345 unsigned int (*fetch_32) (const unsigned char *); 346 unsigned int nscns; 347 char *strtab; 348 size_t strtab_size; 349 unsigned int i; 350 351 scnhdr_size = sizeof (struct external_scnhdr); 352 scnbuf = XNEWVEC (unsigned char, scnhdr_size * ocr->nscns); 353 if (!simple_object_internal_read (sobj->descriptor, 354 sobj->offset + ocr->scnhdr_offset, 355 scnbuf, scnhdr_size * ocr->nscns, &errmsg, 356 err)) 357 { 358 XDELETEVEC (scnbuf); 359 return errmsg; 360 } 361 362 fetch_32 = (ocr->is_big_endian 363 ? simple_object_fetch_big_32 364 : simple_object_fetch_little_32); 365 366 nscns = ocr->nscns; 367 strtab = NULL; 368 strtab_size = 0; 369 for (i = 0; i < nscns; ++i) 370 { 371 unsigned char *scnhdr; 372 unsigned char *scnname; 373 char namebuf[SCNNMLEN + 1]; 374 char *name; 375 off_t scnptr; 376 unsigned int size; 377 378 scnhdr = scnbuf + i * scnhdr_size; 379 scnname = scnhdr + offsetof (struct external_scnhdr, s_name); 380 memcpy (namebuf, scnname, SCNNMLEN); 381 namebuf[SCNNMLEN] = '\0'; 382 name = &namebuf[0]; 383 if (namebuf[0] == '/') 384 { 385 size_t strindex; 386 char *end; 387 388 strindex = strtol (namebuf + 1, &end, 10); 389 if (*end == '\0') 390 { 391 /* The real section name is found in the string 392 table. */ 393 if (strtab == NULL) 394 { 395 strtab = simple_object_coff_read_strtab (sobj, 396 &strtab_size, 397 &errmsg, err); 398 if (strtab == NULL) 399 { 400 XDELETEVEC (scnbuf); 401 return errmsg; 402 } 403 } 404 405 if (strindex < 4 || strindex >= strtab_size) 406 { 407 XDELETEVEC (strtab); 408 XDELETEVEC (scnbuf); 409 *err = 0; 410 return "section string index out of range"; 411 } 412 413 name = strtab + strindex; 414 } 415 } 416 417 scnptr = fetch_32 (scnhdr + offsetof (struct external_scnhdr, s_scnptr)); 418 size = fetch_32 (scnhdr + offsetof (struct external_scnhdr, s_size)); 419 420 if (!(*pfn) (data, name, scnptr, size)) 421 break; 422 } 423 424 if (strtab != NULL) 425 XDELETEVEC (strtab); 426 XDELETEVEC (scnbuf); 427 428 return NULL; 429 } 430 431 /* Fetch the attributes for an simple_object_read. */ 432 433 static void * 434 simple_object_coff_fetch_attributes (simple_object_read *sobj, 435 const char **errmsg ATTRIBUTE_UNUSED, 436 int *err ATTRIBUTE_UNUSED) 437 { 438 struct simple_object_coff_read *ocr = 439 (struct simple_object_coff_read *) sobj->data; 440 struct simple_object_coff_attributes *ret; 441 442 ret = XNEW (struct simple_object_coff_attributes); 443 ret->magic = ocr->magic; 444 ret->is_big_endian = ocr->is_big_endian; 445 ret->flags = ocr->flags; 446 return ret; 447 } 448 449 /* Release the private data for an simple_object_read. */ 450 451 static void 452 simple_object_coff_release_read (void *data) 453 { 454 XDELETE (data); 455 } 456 457 /* Compare two attributes structures. */ 458 459 static const char * 460 simple_object_coff_attributes_merge (void *todata, void *fromdata, int *err) 461 { 462 struct simple_object_coff_attributes *to = 463 (struct simple_object_coff_attributes *) todata; 464 struct simple_object_coff_attributes *from = 465 (struct simple_object_coff_attributes *) fromdata; 466 467 if (to->magic != from->magic || to->is_big_endian != from->is_big_endian) 468 { 469 *err = 0; 470 return "COFF object format mismatch"; 471 } 472 return NULL; 473 } 474 475 /* Release the private data for an attributes structure. */ 476 477 static void 478 simple_object_coff_release_attributes (void *data) 479 { 480 XDELETE (data); 481 } 482 483 /* Prepare to write out a file. */ 484 485 static void * 486 simple_object_coff_start_write (void *attributes_data, 487 const char **errmsg ATTRIBUTE_UNUSED, 488 int *err ATTRIBUTE_UNUSED) 489 { 490 struct simple_object_coff_attributes *attrs = 491 (struct simple_object_coff_attributes *) attributes_data; 492 struct simple_object_coff_attributes *ret; 493 494 /* We're just going to record the attributes, but we need to make a 495 copy because the user may delete them. */ 496 ret = XNEW (struct simple_object_coff_attributes); 497 *ret = *attrs; 498 return ret; 499 } 500 501 /* Write out a COFF filehdr. */ 502 503 static int 504 simple_object_coff_write_filehdr (simple_object_write *sobj, int descriptor, 505 unsigned int nscns, size_t symtab_offset, 506 unsigned int nsyms, const char **errmsg, 507 int *err) 508 { 509 struct simple_object_coff_attributes *attrs = 510 (struct simple_object_coff_attributes *) sobj->data; 511 unsigned char hdrbuf[sizeof (struct external_filehdr)]; 512 unsigned char *hdr; 513 void (*set_16) (unsigned char *, unsigned short); 514 void (*set_32) (unsigned char *, unsigned int); 515 516 hdr = &hdrbuf[0]; 517 518 set_16 = (attrs->is_big_endian 519 ? simple_object_set_big_16 520 : simple_object_set_little_16); 521 set_32 = (attrs->is_big_endian 522 ? simple_object_set_big_32 523 : simple_object_set_little_32); 524 525 memset (hdr, 0, sizeof (struct external_filehdr)); 526 527 set_16 (hdr + offsetof (struct external_filehdr, f_magic), attrs->magic); 528 set_16 (hdr + offsetof (struct external_filehdr, f_nscns), nscns); 529 /* f_timdat left as zero. */ 530 set_32 (hdr + offsetof (struct external_filehdr, f_symptr), symtab_offset); 531 set_32 (hdr + offsetof (struct external_filehdr, f_nsyms), nsyms); 532 /* f_opthdr left as zero. */ 533 set_16 (hdr + offsetof (struct external_filehdr, f_flags), attrs->flags); 534 535 return simple_object_internal_write (descriptor, 0, hdrbuf, 536 sizeof (struct external_filehdr), 537 errmsg, err); 538 } 539 540 /* Write out a COFF section header. */ 541 542 static int 543 simple_object_coff_write_scnhdr (simple_object_write *sobj, int descriptor, 544 const char *name, size_t *name_offset, 545 off_t scnhdr_offset, size_t scnsize, 546 off_t offset, unsigned int align, 547 const char **errmsg, int *err) 548 { 549 struct simple_object_coff_attributes *attrs = 550 (struct simple_object_coff_attributes *) sobj->data; 551 void (*set_32) (unsigned char *, unsigned int); 552 unsigned char hdrbuf[sizeof (struct external_scnhdr)]; 553 unsigned char *hdr; 554 size_t namelen; 555 unsigned int flags; 556 557 set_32 = (attrs->is_big_endian 558 ? simple_object_set_big_32 559 : simple_object_set_little_32); 560 561 memset (hdrbuf, 0, sizeof hdrbuf); 562 hdr = &hdrbuf[0]; 563 564 namelen = strlen (name); 565 if (namelen <= SCNNMLEN) 566 strncpy ((char *) hdr + offsetof (struct external_scnhdr, s_name), name, 567 SCNNMLEN); 568 else 569 { 570 snprintf ((char *) hdr + offsetof (struct external_scnhdr, s_name), 571 SCNNMLEN, "/%lu", (unsigned long) *name_offset); 572 *name_offset += namelen + 1; 573 } 574 575 /* s_paddr left as zero. */ 576 /* s_vaddr left as zero. */ 577 set_32 (hdr + offsetof (struct external_scnhdr, s_size), scnsize); 578 set_32 (hdr + offsetof (struct external_scnhdr, s_scnptr), offset); 579 /* s_relptr left as zero. */ 580 /* s_lnnoptr left as zero. */ 581 /* s_nreloc left as zero. */ 582 /* s_nlnno left as zero. */ 583 flags = (STYP_DATA | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_MEM_SHARED 584 | IMAGE_SCN_MEM_READ); 585 /* PE can represent alignment up to 13. */ 586 if (align > 13) 587 align = 13; 588 flags |= IMAGE_SCN_ALIGN_POWER_CONST(align); 589 set_32 (hdr + offsetof (struct external_scnhdr, s_flags), flags); 590 591 return simple_object_internal_write (descriptor, scnhdr_offset, hdrbuf, 592 sizeof (struct external_scnhdr), 593 errmsg, err); 594 } 595 596 /* Write out a complete COFF file. */ 597 598 static const char * 599 simple_object_coff_write_to_file (simple_object_write *sobj, int descriptor, 600 int *err) 601 { 602 struct simple_object_coff_attributes *attrs = 603 (struct simple_object_coff_attributes *) sobj->data; 604 unsigned int nscns, secnum; 605 simple_object_write_section *section; 606 off_t scnhdr_offset; 607 size_t symtab_offset; 608 off_t secsym_offset; 609 unsigned int nsyms; 610 size_t offset; 611 size_t name_offset; 612 const char *errmsg; 613 unsigned char strsizebuf[4]; 614 /* The interface doesn't give us access to the name of the input file 615 yet. We want to use its basename for the FILE symbol. This is 616 what 'gas' uses when told to assemble from stdin. */ 617 const char *source_filename = "fake"; 618 size_t sflen; 619 union 620 { 621 struct external_syment sym; 622 union external_auxent aux; 623 } syms[2]; 624 void (*set_16) (unsigned char *, unsigned short); 625 void (*set_32) (unsigned char *, unsigned int); 626 627 set_16 = (attrs->is_big_endian 628 ? simple_object_set_big_16 629 : simple_object_set_little_16); 630 set_32 = (attrs->is_big_endian 631 ? simple_object_set_big_32 632 : simple_object_set_little_32); 633 634 nscns = 0; 635 for (section = sobj->sections; section != NULL; section = section->next) 636 ++nscns; 637 638 scnhdr_offset = sizeof (struct external_filehdr); 639 offset = scnhdr_offset + nscns * sizeof (struct external_scnhdr); 640 name_offset = 4; 641 for (section = sobj->sections; section != NULL; section = section->next) 642 { 643 size_t mask; 644 size_t new_offset; 645 size_t scnsize; 646 struct simple_object_write_section_buffer *buffer; 647 648 mask = (1U << section->align) - 1; 649 new_offset = offset & mask; 650 new_offset &= ~ mask; 651 while (new_offset > offset) 652 { 653 unsigned char zeroes[16]; 654 size_t write; 655 656 memset (zeroes, 0, sizeof zeroes); 657 write = new_offset - offset; 658 if (write > sizeof zeroes) 659 write = sizeof zeroes; 660 if (!simple_object_internal_write (descriptor, offset, zeroes, write, 661 &errmsg, err)) 662 return errmsg; 663 } 664 665 scnsize = 0; 666 for (buffer = section->buffers; buffer != NULL; buffer = buffer->next) 667 { 668 if (!simple_object_internal_write (descriptor, offset + scnsize, 669 ((const unsigned char *) 670 buffer->buffer), 671 buffer->size, &errmsg, err)) 672 return errmsg; 673 scnsize += buffer->size; 674 } 675 676 if (!simple_object_coff_write_scnhdr (sobj, descriptor, section->name, 677 &name_offset, scnhdr_offset, 678 scnsize, offset, section->align, 679 &errmsg, err)) 680 return errmsg; 681 682 scnhdr_offset += sizeof (struct external_scnhdr); 683 offset += scnsize; 684 } 685 686 /* Symbol table is always half-word aligned. */ 687 offset += (offset & 1); 688 /* There is a file symbol and a section symbol per section, 689 and each of these has a single auxiliary symbol following. */ 690 nsyms = 2 * (nscns + 1); 691 symtab_offset = offset; 692 /* Advance across space reserved for symbol table to locate 693 start of string table. */ 694 offset += nsyms * sizeof (struct external_syment); 695 696 /* Write out file symbol. */ 697 memset (&syms[0], 0, sizeof (syms)); 698 strcpy ((char *)&syms[0].sym.e.e_name[0], ".file"); 699 set_16 (&syms[0].sym.e_scnum[0], IMAGE_SYM_DEBUG); 700 set_16 (&syms[0].sym.e_type[0], IMAGE_SYM_TYPE); 701 syms[0].sym.e_sclass[0] = IMAGE_SYM_CLASS_FILE; 702 syms[0].sym.e_numaux[0] = 1; 703 /* The name need not be nul-terminated if it fits into the x_fname field 704 directly, but must be if it has to be placed into the string table. */ 705 sflen = strlen (source_filename); 706 if (sflen <= E_FILNMLEN) 707 memcpy (&syms[1].aux.x_file.x_fname[0], source_filename, sflen); 708 else 709 { 710 set_32 (&syms[1].aux.x_file.x_n.x_offset[0], name_offset); 711 if (!simple_object_internal_write (descriptor, offset + name_offset, 712 ((const unsigned char *) 713 source_filename), 714 sflen + 1, &errmsg, err)) 715 return errmsg; 716 name_offset += strlen (source_filename) + 1; 717 } 718 if (!simple_object_internal_write (descriptor, symtab_offset, 719 (const unsigned char *) &syms[0], 720 sizeof (syms), &errmsg, err)) 721 return errmsg; 722 723 /* Write the string table length, followed by the strings and section 724 symbols in step with each other. */ 725 set_32 (strsizebuf, name_offset); 726 if (!simple_object_internal_write (descriptor, offset, strsizebuf, 4, 727 &errmsg, err)) 728 return errmsg; 729 730 name_offset = 4; 731 secsym_offset = symtab_offset + sizeof (syms); 732 memset (&syms[0], 0, sizeof (syms)); 733 set_16 (&syms[0].sym.e_type[0], IMAGE_SYM_TYPE); 734 syms[0].sym.e_sclass[0] = IMAGE_SYM_CLASS_STATIC; 735 syms[0].sym.e_numaux[0] = 1; 736 secnum = 1; 737 738 for (section = sobj->sections; section != NULL; section = section->next) 739 { 740 size_t namelen; 741 size_t scnsize; 742 struct simple_object_write_section_buffer *buffer; 743 744 namelen = strlen (section->name); 745 set_16 (&syms[0].sym.e_scnum[0], secnum++); 746 scnsize = 0; 747 for (buffer = section->buffers; buffer != NULL; buffer = buffer->next) 748 scnsize += buffer->size; 749 set_32 (&syms[1].aux.x_scn.x_scnlen[0], scnsize); 750 if (namelen > SCNNMLEN) 751 { 752 set_32 (&syms[0].sym.e.e.e_zeroes[0], 0); 753 set_32 (&syms[0].sym.e.e.e_offset[0], name_offset); 754 if (!simple_object_internal_write (descriptor, offset + name_offset, 755 ((const unsigned char *) 756 section->name), 757 namelen + 1, &errmsg, err)) 758 return errmsg; 759 name_offset += namelen + 1; 760 } 761 else 762 { 763 memcpy (&syms[0].sym.e.e_name[0], section->name, 764 strlen (section->name)); 765 memset (&syms[0].sym.e.e_name[strlen (section->name)], 0, 766 E_SYMNMLEN - strlen (section->name)); 767 } 768 769 if (!simple_object_internal_write (descriptor, secsym_offset, 770 (const unsigned char *) &syms[0], 771 sizeof (syms), &errmsg, err)) 772 return errmsg; 773 secsym_offset += sizeof (syms); 774 } 775 776 if (!simple_object_coff_write_filehdr (sobj, descriptor, nscns, 777 symtab_offset, nsyms, &errmsg, err)) 778 return errmsg; 779 780 return NULL; 781 } 782 783 /* Release the private data for an simple_object_write structure. */ 784 785 static void 786 simple_object_coff_release_write (void *data) 787 { 788 XDELETE (data); 789 } 790 791 /* The COFF functions. */ 792 793 const struct simple_object_functions simple_object_coff_functions = 794 { 795 simple_object_coff_match, 796 simple_object_coff_find_sections, 797 simple_object_coff_fetch_attributes, 798 simple_object_coff_release_read, 799 simple_object_coff_attributes_merge, 800 simple_object_coff_release_attributes, 801 simple_object_coff_start_write, 802 simple_object_coff_write_to_file, 803 simple_object_coff_release_write 804 }; 805