1 /* BFD back-end for WebAssembly modules. 2 Copyright (C) 2017-2020 Free Software Foundation, Inc. 3 4 Based on srec.c, mmo.c, and binary.c 5 6 This file is part of BFD, the Binary File Descriptor library. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21 MA 02110-1301, USA. */ 22 23 /* The WebAssembly module format is a simple object file format 24 including up to 11 numbered sections, plus any number of named 25 "custom" sections. It is described at: 26 https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md. */ 27 28 #include "sysdep.h" 29 #include "alloca-conf.h" 30 #include "bfd.h" 31 #include <limits.h> 32 #include "libiberty.h" 33 #include "libbfd.h" 34 #include "wasm-module.h" 35 36 typedef struct 37 { 38 asymbol * symbols; 39 bfd_size_type symcount; 40 } tdata_type; 41 42 static const char * const wasm_numbered_sections[] = 43 { 44 NULL, /* Custom section, different layout. */ 45 WASM_SECTION ( 1, "type"), 46 WASM_SECTION ( 2, "import"), 47 WASM_SECTION ( 3, "function"), 48 WASM_SECTION ( 4, "table"), 49 WASM_SECTION ( 5, "memory"), 50 WASM_SECTION ( 6, "global"), 51 WASM_SECTION ( 7, "export"), 52 WASM_SECTION ( 8, "start"), 53 WASM_SECTION ( 9, "element"), 54 WASM_SECTION (10, "code"), 55 WASM_SECTION (11, "data"), 56 }; 57 58 #define WASM_NUMBERED_SECTIONS ARRAY_SIZE (wasm_numbered_sections) 59 60 /* Resolve SECTION_CODE to a section name if there is one, NULL 61 otherwise. */ 62 63 static const char * 64 wasm_section_code_to_name (bfd_byte section_code) 65 { 66 if (section_code < WASM_NUMBERED_SECTIONS) 67 return wasm_numbered_sections[section_code]; 68 69 return NULL; 70 } 71 72 /* Translate section name NAME to a section code, or 0 if it's a 73 custom name. */ 74 75 static unsigned int 76 wasm_section_name_to_code (const char *name) 77 { 78 unsigned i; 79 80 for (i = 1; i < WASM_NUMBERED_SECTIONS; i++) 81 if (strcmp (name, wasm_numbered_sections[i]) == 0) 82 return i; 83 84 return 0; 85 } 86 87 /* WebAssembly LEB128 integers are sufficiently like DWARF LEB128 88 integers that we use _bfd_safe_read_leb128, but there are two 89 points of difference: 90 91 - WebAssembly requires a 32-bit value to be encoded in at most 5 92 bytes, etc. 93 - _bfd_safe_read_leb128 accepts incomplete LEB128 encodings at the 94 end of the buffer, while these are invalid in WebAssembly. 95 96 Those differences mean that we will accept some files that are 97 invalid WebAssembly. */ 98 99 /* Read an LEB128-encoded integer from ABFD's I/O stream, reading one 100 byte at a time. Set ERROR_RETURN if no complete integer could be 101 read, LENGTH_RETURN to the number of bytes read (including bytes in 102 incomplete numbers). SIGN means interpret the number as SLEB128. */ 103 104 static bfd_vma 105 wasm_read_leb128 (bfd * abfd, 106 bfd_boolean * error_return, 107 unsigned int * length_return, 108 bfd_boolean sign) 109 { 110 bfd_vma result = 0; 111 unsigned int num_read = 0; 112 unsigned int shift = 0; 113 unsigned char byte = 0; 114 int status = 1; 115 116 while (bfd_bread (&byte, 1, abfd) == 1) 117 { 118 num_read++; 119 120 if (shift < sizeof (result) * 8) 121 { 122 result |= ((bfd_vma) (byte & 0x7f)) << shift; 123 if ((result >> shift) != (byte & 0x7f)) 124 /* Overflow. */ 125 status |= 2; 126 shift += 7; 127 } 128 else if ((byte & 0x7f) != 0) 129 status |= 2; 130 131 if ((byte & 0x80) == 0) 132 { 133 status &= ~1; 134 if (sign && (shift < 8 * sizeof (result)) && (byte & 0x40)) 135 result |= -((bfd_vma) 1 << shift); 136 break; 137 } 138 } 139 140 if (length_return != NULL) 141 *length_return = num_read; 142 if (error_return != NULL) 143 *error_return = status != 0; 144 145 return result; 146 } 147 148 /* Encode an integer V as LEB128 and write it to ABFD, return TRUE on 149 success. */ 150 151 static bfd_boolean 152 wasm_write_uleb128 (bfd *abfd, bfd_vma v) 153 { 154 do 155 { 156 bfd_byte c = v & 0x7f; 157 v >>= 7; 158 159 if (v) 160 c |= 0x80; 161 162 if (bfd_bwrite (&c, 1, abfd) != 1) 163 return FALSE; 164 } 165 while (v); 166 167 return TRUE; 168 } 169 170 /* Read the LEB128 integer at P, saving it to X; at end of buffer, 171 jump to error_return. */ 172 #define READ_LEB128(x, p, end) \ 173 do \ 174 { \ 175 unsigned int length_read; \ 176 (x) = _bfd_safe_read_leb128 (abfd, (p), &length_read, \ 177 FALSE, (end)); \ 178 (p) += length_read; \ 179 if (length_read == 0) \ 180 goto error_return; \ 181 } \ 182 while (0) 183 184 /* Verify the magic number at the beginning of a WebAssembly module 185 ABFD, setting ERRORPTR if there's a mismatch. */ 186 187 static bfd_boolean 188 wasm_read_magic (bfd *abfd, bfd_boolean *errorptr) 189 { 190 bfd_byte magic_const[SIZEOF_WASM_MAGIC] = WASM_MAGIC; 191 bfd_byte magic[SIZEOF_WASM_MAGIC]; 192 193 if (bfd_bread (magic, sizeof (magic), abfd) == sizeof (magic) 194 && memcmp (magic, magic_const, sizeof (magic)) == 0) 195 return TRUE; 196 197 *errorptr = TRUE; 198 return FALSE; 199 } 200 201 /* Read the version number from ABFD, returning TRUE if it's a supported 202 version. Set ERRORPTR otherwise. */ 203 204 static bfd_boolean 205 wasm_read_version (bfd *abfd, bfd_boolean *errorptr) 206 { 207 bfd_byte vers_const[SIZEOF_WASM_VERSION] = WASM_VERSION; 208 bfd_byte vers[SIZEOF_WASM_VERSION]; 209 210 if (bfd_bread (vers, sizeof (vers), abfd) == sizeof (vers) 211 /* Don't attempt to parse newer versions, which are likely to 212 require code changes. */ 213 && memcmp (vers, vers_const, sizeof (vers)) == 0) 214 return TRUE; 215 216 *errorptr = TRUE; 217 return FALSE; 218 } 219 220 /* Read the WebAssembly header (magic number plus version number) from 221 ABFD, setting ERRORPTR to TRUE if there is a mismatch. */ 222 223 static bfd_boolean 224 wasm_read_header (bfd *abfd, bfd_boolean *errorptr) 225 { 226 if (! wasm_read_magic (abfd, errorptr)) 227 return FALSE; 228 229 if (! wasm_read_version (abfd, errorptr)) 230 return FALSE; 231 232 return TRUE; 233 } 234 235 /* Scan the "function" subsection of the "name" section ASECT in the 236 wasm module ABFD. Create symbols. Return TRUE on success. */ 237 238 static bfd_boolean 239 wasm_scan_name_function_section (bfd *abfd, sec_ptr asect) 240 { 241 bfd_byte *p; 242 bfd_byte *end; 243 bfd_vma payload_size; 244 bfd_vma symcount = 0; 245 tdata_type *tdata = abfd->tdata.any; 246 asymbol *symbols = NULL; 247 sec_ptr space_function_index; 248 size_t amt; 249 250 p = asect->contents; 251 end = asect->contents + asect->size; 252 253 if (!p) 254 return FALSE; 255 256 while (p < end) 257 { 258 bfd_byte subsection_code = *p++; 259 if (subsection_code == WASM_FUNCTION_SUBSECTION) 260 break; 261 262 /* subsection_code is documented to be a varuint7, meaning that 263 it has to be a single byte in the 0 - 127 range. If it isn't, 264 the spec must have changed underneath us, so give up. */ 265 if (subsection_code & 0x80) 266 return FALSE; 267 268 READ_LEB128 (payload_size, p, end); 269 270 if (payload_size > (size_t) (end - p)) 271 return FALSE; 272 273 p += payload_size; 274 } 275 276 if (p >= end) 277 return FALSE; 278 279 READ_LEB128 (payload_size, p, end); 280 281 if (payload_size > (size_t) (end - p)) 282 return FALSE; 283 284 end = p + payload_size; 285 286 READ_LEB128 (symcount, p, end); 287 288 /* Sanity check: each symbol has at least two bytes. */ 289 if (symcount > payload_size / 2) 290 return FALSE; 291 292 tdata->symcount = symcount; 293 294 space_function_index 295 = bfd_make_section_with_flags (abfd, WASM_SECTION_FUNCTION_INDEX, 296 SEC_READONLY | SEC_CODE); 297 298 if (!space_function_index) 299 space_function_index 300 = bfd_get_section_by_name (abfd, WASM_SECTION_FUNCTION_INDEX); 301 302 if (!space_function_index) 303 return FALSE; 304 305 if (_bfd_mul_overflow (tdata->symcount, sizeof (asymbol), &amt)) 306 { 307 bfd_set_error (bfd_error_file_too_big); 308 return FALSE; 309 } 310 symbols = bfd_alloc (abfd, amt); 311 if (!symbols) 312 return FALSE; 313 314 for (symcount = 0; p < end && symcount < tdata->symcount; symcount++) 315 { 316 bfd_vma idx; 317 bfd_vma len; 318 char *name; 319 asymbol *sym; 320 321 READ_LEB128 (idx, p, end); 322 READ_LEB128 (len, p, end); 323 324 if (len > (size_t) (end - p)) 325 goto error_return; 326 327 name = bfd_alloc (abfd, len + 1); 328 if (!name) 329 goto error_return; 330 331 memcpy (name, p, len); 332 name[len] = 0; 333 p += len; 334 335 sym = &symbols[symcount]; 336 sym->the_bfd = abfd; 337 sym->name = name; 338 sym->value = idx; 339 sym->flags = BSF_GLOBAL | BSF_FUNCTION; 340 sym->section = space_function_index; 341 sym->udata.p = NULL; 342 } 343 344 if (symcount < tdata->symcount) 345 goto error_return; 346 347 tdata->symbols = symbols; 348 abfd->symcount = symcount; 349 350 return TRUE; 351 352 error_return: 353 bfd_release (abfd, symbols); 354 return FALSE; 355 } 356 357 /* Read a byte from ABFD and return it, or EOF for EOF or error. 358 Set ERRORPTR on non-EOF error. */ 359 360 static int 361 wasm_read_byte (bfd *abfd, bfd_boolean *errorptr) 362 { 363 bfd_byte byte; 364 365 if (bfd_bread (&byte, (bfd_size_type) 1, abfd) != 1) 366 { 367 if (bfd_get_error () != bfd_error_file_truncated) 368 *errorptr = TRUE; 369 return EOF; 370 } 371 372 return byte; 373 } 374 375 /* Scan the wasm module ABFD, creating sections and symbols. 376 Return TRUE on success. */ 377 378 static bfd_boolean 379 wasm_scan (bfd *abfd) 380 { 381 bfd_boolean error = FALSE; 382 /* Fake VMAs for now. Choose 0x80000000 as base to avoid clashes 383 with actual data addresses. */ 384 bfd_vma vma = 0x80000000; 385 int section_code; 386 unsigned int bytes_read; 387 asection *bfdsec; 388 389 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) 390 goto error_return; 391 392 if (!wasm_read_header (abfd, &error)) 393 goto error_return; 394 395 while ((section_code = wasm_read_byte (abfd, &error)) != EOF) 396 { 397 if (section_code != 0) 398 { 399 const char *sname = wasm_section_code_to_name (section_code); 400 401 if (!sname) 402 goto error_return; 403 404 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, 405 SEC_HAS_CONTENTS); 406 if (bfdsec == NULL) 407 goto error_return; 408 409 bfdsec->size = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE); 410 if (error) 411 goto error_return; 412 } 413 else 414 { 415 bfd_vma payload_len; 416 bfd_vma namelen; 417 char *name; 418 char *prefix = WASM_SECTION_PREFIX; 419 size_t prefixlen = strlen (prefix); 420 ufile_ptr filesize; 421 422 payload_len = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE); 423 if (error) 424 goto error_return; 425 namelen = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE); 426 if (error || bytes_read > payload_len 427 || namelen > payload_len - bytes_read) 428 goto error_return; 429 payload_len -= namelen + bytes_read; 430 filesize = bfd_get_file_size (abfd); 431 if (filesize != 0 && namelen > filesize) 432 { 433 bfd_set_error (bfd_error_file_truncated); 434 return FALSE; 435 } 436 name = bfd_alloc (abfd, namelen + prefixlen + 1); 437 if (!name) 438 goto error_return; 439 memcpy (name, prefix, prefixlen); 440 if (bfd_bread (name + prefixlen, namelen, abfd) != namelen) 441 goto error_return; 442 name[prefixlen + namelen] = 0; 443 444 bfdsec = bfd_make_section_anyway_with_flags (abfd, name, 445 SEC_HAS_CONTENTS); 446 if (bfdsec == NULL) 447 goto error_return; 448 449 bfdsec->size = payload_len; 450 } 451 452 bfdsec->vma = vma; 453 bfdsec->lma = vma; 454 bfdsec->alignment_power = 0; 455 bfdsec->filepos = bfd_tell (abfd); 456 if (bfdsec->size != 0) 457 { 458 bfdsec->contents = _bfd_alloc_and_read (abfd, bfdsec->size, 459 bfdsec->size); 460 if (!bfdsec->contents) 461 goto error_return; 462 } 463 464 vma += bfdsec->size; 465 } 466 467 /* Make sure we're at actual EOF. There's no indication in the 468 WebAssembly format of how long the file is supposed to be. */ 469 if (error) 470 goto error_return; 471 472 return TRUE; 473 474 error_return: 475 return FALSE; 476 } 477 478 /* Put a numbered section ASECT of ABFD into the table of numbered 479 sections pointed to by FSARG. */ 480 481 static void 482 wasm_register_section (bfd *abfd ATTRIBUTE_UNUSED, 483 asection *asect, 484 void *fsarg) 485 { 486 sec_ptr *numbered_sections = fsarg; 487 int idx = wasm_section_name_to_code (asect->name); 488 489 if (idx == 0) 490 return; 491 492 numbered_sections[idx] = asect; 493 } 494 495 struct compute_section_arg 496 { 497 bfd_vma pos; 498 bfd_boolean failed; 499 }; 500 501 /* Compute the file position of ABFD's section ASECT. FSARG is a 502 pointer to the current file position. 503 504 We allow section names of the form .wasm.id to encode the numbered 505 section with ID id, if it exists; otherwise, a custom section with 506 ID "id" is produced. Arbitrary section names are for sections that 507 are assumed already to contain a section header; those are appended 508 to the WebAssembly module verbatim. */ 509 510 static void 511 wasm_compute_custom_section_file_position (bfd *abfd, 512 sec_ptr asect, 513 void *fsarg) 514 { 515 struct compute_section_arg *fs = fsarg; 516 int idx; 517 518 if (fs->failed) 519 return; 520 521 idx = wasm_section_name_to_code (asect->name); 522 523 if (idx != 0) 524 return; 525 526 if (CONST_STRNEQ (asect->name, WASM_SECTION_PREFIX)) 527 { 528 const char *name = asect->name + strlen (WASM_SECTION_PREFIX); 529 bfd_size_type payload_len = asect->size; 530 bfd_size_type name_len = strlen (name); 531 bfd_size_type nl = name_len; 532 533 payload_len += name_len; 534 535 do 536 { 537 payload_len++; 538 nl >>= 7; 539 } 540 while (nl); 541 542 bfd_seek (abfd, fs->pos, SEEK_SET); 543 if (! wasm_write_uleb128 (abfd, 0) 544 || ! wasm_write_uleb128 (abfd, payload_len) 545 || ! wasm_write_uleb128 (abfd, name_len) 546 || bfd_bwrite (name, name_len, abfd) != name_len) 547 goto error_return; 548 fs->pos = asect->filepos = bfd_tell (abfd); 549 } 550 else 551 { 552 asect->filepos = fs->pos; 553 } 554 555 556 fs->pos += asect->size; 557 return; 558 559 error_return: 560 fs->failed = TRUE; 561 } 562 563 /* Compute the file positions for the sections of ABFD. Currently, 564 this writes all numbered sections first, in order, then all custom 565 sections, in section order. 566 567 The spec says that the numbered sections must appear in order of 568 their ids, but custom sections can appear in any position and any 569 order, and more than once. FIXME: support that. */ 570 571 static bfd_boolean 572 wasm_compute_section_file_positions (bfd *abfd) 573 { 574 bfd_byte magic[SIZEOF_WASM_MAGIC] = WASM_MAGIC; 575 bfd_byte vers[SIZEOF_WASM_VERSION] = WASM_VERSION; 576 sec_ptr numbered_sections[WASM_NUMBERED_SECTIONS]; 577 struct compute_section_arg fs; 578 unsigned int i; 579 580 bfd_seek (abfd, (bfd_vma) 0, SEEK_SET); 581 582 if (bfd_bwrite (magic, sizeof (magic), abfd) != (sizeof magic) 583 || bfd_bwrite (vers, sizeof (vers), abfd) != sizeof (vers)) 584 return FALSE; 585 586 for (i = 0; i < WASM_NUMBERED_SECTIONS; i++) 587 numbered_sections[i] = NULL; 588 589 bfd_map_over_sections (abfd, wasm_register_section, numbered_sections); 590 591 fs.pos = bfd_tell (abfd); 592 for (i = 0; i < WASM_NUMBERED_SECTIONS; i++) 593 { 594 sec_ptr sec = numbered_sections[i]; 595 bfd_size_type size; 596 597 if (! sec) 598 continue; 599 size = sec->size; 600 if (bfd_seek (abfd, fs.pos, SEEK_SET) != 0) 601 return FALSE; 602 if (! wasm_write_uleb128 (abfd, i) 603 || ! wasm_write_uleb128 (abfd, size)) 604 return FALSE; 605 fs.pos = sec->filepos = bfd_tell (abfd); 606 fs.pos += size; 607 } 608 609 fs.failed = FALSE; 610 611 bfd_map_over_sections (abfd, wasm_compute_custom_section_file_position, &fs); 612 613 if (fs.failed) 614 return FALSE; 615 616 abfd->output_has_begun = TRUE; 617 618 return TRUE; 619 } 620 621 static bfd_boolean 622 wasm_set_section_contents (bfd *abfd, 623 sec_ptr section, 624 const void *location, 625 file_ptr offset, 626 bfd_size_type count) 627 { 628 if (count == 0) 629 return TRUE; 630 631 if (! abfd->output_has_begun 632 && ! wasm_compute_section_file_positions (abfd)) 633 return FALSE; 634 635 if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0 636 || bfd_bwrite (location, count, abfd) != count) 637 return FALSE; 638 639 return TRUE; 640 } 641 642 static bfd_boolean 643 wasm_write_object_contents (bfd* abfd) 644 { 645 bfd_byte magic[] = WASM_MAGIC; 646 bfd_byte vers[] = WASM_VERSION; 647 648 if (bfd_seek (abfd, 0, SEEK_SET) != 0) 649 return FALSE; 650 651 if (bfd_bwrite (magic, sizeof (magic), abfd) != sizeof (magic) 652 || bfd_bwrite (vers, sizeof (vers), abfd) != sizeof (vers)) 653 return FALSE; 654 655 return TRUE; 656 } 657 658 static bfd_boolean 659 wasm_mkobject (bfd *abfd) 660 { 661 tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type)); 662 663 if (! tdata) 664 return FALSE; 665 666 tdata->symbols = NULL; 667 tdata->symcount = 0; 668 669 abfd->tdata.any = tdata; 670 671 return TRUE; 672 } 673 674 static long 675 wasm_get_symtab_upper_bound (bfd *abfd) 676 { 677 tdata_type *tdata = abfd->tdata.any; 678 679 return (tdata->symcount + 1) * (sizeof (asymbol *)); 680 } 681 682 static long 683 wasm_canonicalize_symtab (bfd *abfd, asymbol **alocation) 684 { 685 tdata_type *tdata = abfd->tdata.any; 686 size_t i; 687 688 for (i = 0; i < tdata->symcount; i++) 689 alocation[i] = &tdata->symbols[i]; 690 alocation[i] = NULL; 691 692 return tdata->symcount; 693 } 694 695 static asymbol * 696 wasm_make_empty_symbol (bfd *abfd) 697 { 698 size_t amt = sizeof (asymbol); 699 asymbol *new_symbol = (asymbol *) bfd_zalloc (abfd, amt); 700 701 if (! new_symbol) 702 return NULL; 703 new_symbol->the_bfd = abfd; 704 return new_symbol; 705 } 706 707 static void 708 wasm_print_symbol (bfd *abfd, 709 void * filep, 710 asymbol *symbol, 711 bfd_print_symbol_type how) 712 { 713 FILE *file = (FILE *) filep; 714 715 switch (how) 716 { 717 case bfd_print_symbol_name: 718 fprintf (file, "%s", symbol->name); 719 break; 720 721 default: 722 bfd_print_symbol_vandf (abfd, filep, symbol); 723 fprintf (file, " %-5s %s", symbol->section->name, symbol->name); 724 } 725 } 726 727 static void 728 wasm_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED, 729 asymbol *symbol, 730 symbol_info *ret) 731 { 732 bfd_symbol_info (symbol, ret); 733 } 734 735 /* Check whether ABFD is a WebAssembly module; if so, scan it. */ 736 737 static bfd_cleanup 738 wasm_object_p (bfd *abfd) 739 { 740 bfd_boolean error; 741 asection *s; 742 743 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) 744 return NULL; 745 746 if (!wasm_read_header (abfd, &error)) 747 { 748 bfd_set_error (bfd_error_wrong_format); 749 return NULL; 750 } 751 752 if (!wasm_mkobject (abfd)) 753 return NULL; 754 755 if (!wasm_scan (abfd) 756 || !bfd_default_set_arch_mach (abfd, bfd_arch_wasm32, 0)) 757 { 758 bfd_release (abfd, abfd->tdata.any); 759 abfd->tdata.any = NULL; 760 return NULL; 761 } 762 763 s = bfd_get_section_by_name (abfd, WASM_NAME_SECTION); 764 if (s != NULL && wasm_scan_name_function_section (abfd, s)) 765 abfd->flags |= HAS_SYMS; 766 767 return _bfd_no_cleanup; 768 } 769 770 /* BFD_JUMP_TABLE_WRITE */ 771 #define wasm_set_arch_mach _bfd_generic_set_arch_mach 772 773 /* BFD_JUMP_TABLE_SYMBOLS */ 774 #define wasm_get_symbol_version_string _bfd_nosymbols_get_symbol_version_string 775 #define wasm_bfd_is_local_label_name bfd_generic_is_local_label_name 776 #define wasm_bfd_is_target_special_symbol _bfd_bool_bfd_asymbol_false 777 #define wasm_get_lineno _bfd_nosymbols_get_lineno 778 #define wasm_find_nearest_line _bfd_nosymbols_find_nearest_line 779 #define wasm_find_line _bfd_nosymbols_find_line 780 #define wasm_find_inliner_info _bfd_nosymbols_find_inliner_info 781 #define wasm_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol 782 #define wasm_read_minisymbols _bfd_generic_read_minisymbols 783 #define wasm_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol 784 785 const bfd_target wasm_vec = 786 { 787 "wasm", /* Name. */ 788 bfd_target_unknown_flavour, 789 BFD_ENDIAN_LITTLE, 790 BFD_ENDIAN_LITTLE, 791 (HAS_SYMS | WP_TEXT), /* Object flags. */ 792 (SEC_CODE | SEC_DATA | SEC_HAS_CONTENTS), /* Section flags. */ 793 0, /* Leading underscore. */ 794 ' ', /* AR_pad_char. */ 795 255, /* AR_max_namelen. */ 796 0, /* Match priority. */ 797 /* Routines to byte-swap various sized integers from the data sections. */ 798 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 799 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 800 bfd_getl16, bfd_getl_signed_16, bfd_putl16, 801 802 /* Routines to byte-swap various sized integers from the file headers. */ 803 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 804 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 805 bfd_getl16, bfd_getl_signed_16, bfd_putl16, 806 807 { 808 _bfd_dummy_target, 809 wasm_object_p, /* bfd_check_format. */ 810 _bfd_dummy_target, 811 _bfd_dummy_target, 812 }, 813 { 814 _bfd_bool_bfd_false_error, 815 wasm_mkobject, 816 _bfd_generic_mkarchive, 817 _bfd_bool_bfd_false_error, 818 }, 819 { /* bfd_write_contents. */ 820 _bfd_bool_bfd_false_error, 821 wasm_write_object_contents, 822 _bfd_write_archive_contents, 823 _bfd_bool_bfd_false_error, 824 }, 825 826 BFD_JUMP_TABLE_GENERIC (_bfd_generic), 827 BFD_JUMP_TABLE_COPY (_bfd_generic), 828 BFD_JUMP_TABLE_CORE (_bfd_nocore), 829 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 830 BFD_JUMP_TABLE_SYMBOLS (wasm), 831 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), 832 BFD_JUMP_TABLE_WRITE (wasm), 833 BFD_JUMP_TABLE_LINK (_bfd_nolink), 834 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 835 836 NULL, 837 838 NULL, 839 }; 840