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 36typedef struct 37{ 38 asymbol * symbols; 39 bfd_size_type symcount; 40} tdata_type; 41 42static 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 63static const char * 64wasm_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 75static unsigned int 76wasm_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 104static bfd_vma 105wasm_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 151static bfd_boolean 152wasm_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 187static bfd_boolean 188wasm_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 204static bfd_boolean 205wasm_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 223static bfd_boolean 224wasm_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 238static bfd_boolean 239wasm_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 249 p = asect->contents; 250 end = asect->contents + asect->size; 251 252 if (!p) 253 return FALSE; 254 255 while (p < end) 256 { 257 bfd_byte subsection_code = *p++; 258 if (subsection_code == WASM_FUNCTION_SUBSECTION) 259 break; 260 261 /* subsection_code is documented to be a varuint7, meaning that 262 it has to be a single byte in the 0 - 127 range. If it isn't, 263 the spec must have changed underneath us, so give up. */ 264 if (subsection_code & 0x80) 265 return FALSE; 266 267 READ_LEB128 (payload_size, p, end); 268 269 if (payload_size > (size_t) (end - p)) 270 return FALSE; 271 272 p += payload_size; 273 } 274 275 if (p >= end) 276 return FALSE; 277 278 READ_LEB128 (payload_size, p, end); 279 280 if (payload_size > (size_t) (end - p)) 281 return FALSE; 282 283 end = p + payload_size; 284 285 READ_LEB128 (symcount, p, end); 286 287 /* Sanity check: each symbol has at least two bytes. */ 288 if (symcount > payload_size / 2) 289 return FALSE; 290 291 tdata->symcount = symcount; 292 293 space_function_index 294 = bfd_make_section_with_flags (abfd, WASM_SECTION_FUNCTION_INDEX, 295 SEC_READONLY | SEC_CODE); 296 297 if (!space_function_index) 298 space_function_index 299 = bfd_get_section_by_name (abfd, WASM_SECTION_FUNCTION_INDEX); 300 301 if (!space_function_index) 302 return FALSE; 303 304 symbols = bfd_alloc2 (abfd, tdata->symcount, sizeof (asymbol)); 305 if (!symbols) 306 return FALSE; 307 308 for (symcount = 0; p < end && symcount < tdata->symcount; symcount++) 309 { 310 bfd_vma idx; 311 bfd_vma len; 312 char *name; 313 asymbol *sym; 314 315 READ_LEB128 (idx, p, end); 316 READ_LEB128 (len, p, end); 317 318 if (len > (size_t) (end - p)) 319 goto error_return; 320 321 name = bfd_alloc (abfd, len + 1); 322 if (!name) 323 goto error_return; 324 325 memcpy (name, p, len); 326 name[len] = 0; 327 p += len; 328 329 sym = &symbols[symcount]; 330 sym->the_bfd = abfd; 331 sym->name = name; 332 sym->value = idx; 333 sym->flags = BSF_GLOBAL | BSF_FUNCTION; 334 sym->section = space_function_index; 335 sym->udata.p = NULL; 336 } 337 338 if (symcount < tdata->symcount) 339 goto error_return; 340 341 tdata->symbols = symbols; 342 abfd->symcount = symcount; 343 344 return TRUE; 345 346 error_return: 347 bfd_release (abfd, symbols); 348 return FALSE; 349} 350 351/* Read a byte from ABFD and return it, or EOF for EOF or error. 352 Set ERRORPTR on non-EOF error. */ 353 354static int 355wasm_read_byte (bfd *abfd, bfd_boolean *errorptr) 356{ 357 bfd_byte byte; 358 359 if (bfd_bread (&byte, (bfd_size_type) 1, abfd) != 1) 360 { 361 if (bfd_get_error () != bfd_error_file_truncated) 362 *errorptr = TRUE; 363 return EOF; 364 } 365 366 return byte; 367} 368 369/* Scan the wasm module ABFD, creating sections and symbols. 370 Return TRUE on success. */ 371 372static bfd_boolean 373wasm_scan (bfd *abfd) 374{ 375 bfd_boolean error = FALSE; 376 /* Fake VMAs for now. Choose 0x80000000 as base to avoid clashes 377 with actual data addresses. */ 378 bfd_vma vma = 0x80000000; 379 int section_code; 380 unsigned int bytes_read; 381 asection *bfdsec; 382 383 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) 384 goto error_return; 385 386 if (!wasm_read_header (abfd, &error)) 387 goto error_return; 388 389 while ((section_code = wasm_read_byte (abfd, &error)) != EOF) 390 { 391 if (section_code != 0) 392 { 393 const char *sname = wasm_section_code_to_name (section_code); 394 395 if (!sname) 396 goto error_return; 397 398 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, 399 SEC_HAS_CONTENTS); 400 if (bfdsec == NULL) 401 goto error_return; 402 403 bfdsec->vma = vma; 404 bfdsec->lma = vma; 405 bfdsec->size = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE); 406 if (error) 407 goto error_return; 408 bfdsec->filepos = bfd_tell (abfd); 409 bfdsec->alignment_power = 0; 410 } 411 else 412 { 413 bfd_vma payload_len; 414 file_ptr section_start; 415 bfd_vma namelen; 416 char *name; 417 char *prefix = WASM_SECTION_PREFIX; 418 size_t prefixlen = strlen (prefix); 419 420 payload_len = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE); 421 if (error) 422 goto error_return; 423 section_start = bfd_tell (abfd); 424 namelen = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE); 425 if (error || namelen > payload_len) 426 goto error_return; 427 name = bfd_alloc (abfd, namelen + prefixlen + 1); 428 if (!name) 429 goto error_return; 430 memcpy (name, prefix, prefixlen); 431 if (bfd_bread (name + prefixlen, namelen, abfd) != namelen) 432 goto error_return; 433 name[prefixlen + namelen] = 0; 434 435 bfdsec = bfd_make_section_anyway_with_flags (abfd, name, 436 SEC_HAS_CONTENTS); 437 if (bfdsec == NULL) 438 goto error_return; 439 440 bfdsec->vma = vma; 441 bfdsec->lma = vma; 442 bfdsec->filepos = bfd_tell (abfd); 443 bfdsec->size = section_start + payload_len - bfdsec->filepos; 444 bfdsec->alignment_power = 0; 445 } 446 447 if (bfdsec->size != 0) 448 { 449 bfdsec->contents = bfd_alloc (abfd, bfdsec->size); 450 if (!bfdsec->contents) 451 goto error_return; 452 453 if (bfd_bread (bfdsec->contents, bfdsec->size, abfd) != bfdsec->size) 454 goto error_return; 455 } 456 457 vma += bfdsec->size; 458 } 459 460 /* Make sure we're at actual EOF. There's no indication in the 461 WebAssembly format of how long the file is supposed to be. */ 462 if (error) 463 goto error_return; 464 465 return TRUE; 466 467 error_return: 468 return FALSE; 469} 470 471/* Put a numbered section ASECT of ABFD into the table of numbered 472 sections pointed to by FSARG. */ 473 474static void 475wasm_register_section (bfd *abfd ATTRIBUTE_UNUSED, 476 asection *asect, 477 void *fsarg) 478{ 479 sec_ptr *numbered_sections = fsarg; 480 int idx = wasm_section_name_to_code (asect->name); 481 482 if (idx == 0) 483 return; 484 485 numbered_sections[idx] = asect; 486} 487 488struct compute_section_arg 489{ 490 bfd_vma pos; 491 bfd_boolean failed; 492}; 493 494/* Compute the file position of ABFD's section ASECT. FSARG is a 495 pointer to the current file position. 496 497 We allow section names of the form .wasm.id to encode the numbered 498 section with ID id, if it exists; otherwise, a custom section with 499 ID "id" is produced. Arbitrary section names are for sections that 500 are assumed already to contain a section header; those are appended 501 to the WebAssembly module verbatim. */ 502 503static void 504wasm_compute_custom_section_file_position (bfd *abfd, 505 sec_ptr asect, 506 void *fsarg) 507{ 508 struct compute_section_arg *fs = fsarg; 509 int idx; 510 511 if (fs->failed) 512 return; 513 514 idx = wasm_section_name_to_code (asect->name); 515 516 if (idx != 0) 517 return; 518 519 if (CONST_STRNEQ (asect->name, WASM_SECTION_PREFIX)) 520 { 521 const char *name = asect->name + strlen (WASM_SECTION_PREFIX); 522 bfd_size_type payload_len = asect->size; 523 bfd_size_type name_len = strlen (name); 524 bfd_size_type nl = name_len; 525 526 payload_len += name_len; 527 528 do 529 { 530 payload_len++; 531 nl >>= 7; 532 } 533 while (nl); 534 535 bfd_seek (abfd, fs->pos, SEEK_SET); 536 if (! wasm_write_uleb128 (abfd, 0) 537 || ! wasm_write_uleb128 (abfd, payload_len) 538 || ! wasm_write_uleb128 (abfd, name_len) 539 || bfd_bwrite (name, name_len, abfd) != name_len) 540 goto error_return; 541 fs->pos = asect->filepos = bfd_tell (abfd); 542 } 543 else 544 { 545 asect->filepos = fs->pos; 546 } 547 548 549 fs->pos += asect->size; 550 return; 551 552 error_return: 553 fs->failed = TRUE; 554} 555 556/* Compute the file positions for the sections of ABFD. Currently, 557 this writes all numbered sections first, in order, then all custom 558 sections, in section order. 559 560 The spec says that the numbered sections must appear in order of 561 their ids, but custom sections can appear in any position and any 562 order, and more than once. FIXME: support that. */ 563 564static bfd_boolean 565wasm_compute_section_file_positions (bfd *abfd) 566{ 567 bfd_byte magic[SIZEOF_WASM_MAGIC] = WASM_MAGIC; 568 bfd_byte vers[SIZEOF_WASM_VERSION] = WASM_VERSION; 569 sec_ptr numbered_sections[WASM_NUMBERED_SECTIONS]; 570 struct compute_section_arg fs; 571 unsigned int i; 572 573 bfd_seek (abfd, (bfd_vma) 0, SEEK_SET); 574 575 if (bfd_bwrite (magic, sizeof (magic), abfd) != (sizeof magic) 576 || bfd_bwrite (vers, sizeof (vers), abfd) != sizeof (vers)) 577 return FALSE; 578 579 for (i = 0; i < WASM_NUMBERED_SECTIONS; i++) 580 numbered_sections[i] = NULL; 581 582 bfd_map_over_sections (abfd, wasm_register_section, numbered_sections); 583 584 fs.pos = bfd_tell (abfd); 585 for (i = 0; i < WASM_NUMBERED_SECTIONS; i++) 586 { 587 sec_ptr sec = numbered_sections[i]; 588 bfd_size_type size; 589 590 if (! sec) 591 continue; 592 size = sec->size; 593 if (bfd_seek (abfd, fs.pos, SEEK_SET) != 0) 594 return FALSE; 595 if (! wasm_write_uleb128 (abfd, i) 596 || ! wasm_write_uleb128 (abfd, size)) 597 return FALSE; 598 fs.pos = sec->filepos = bfd_tell (abfd); 599 fs.pos += size; 600 } 601 602 fs.failed = FALSE; 603 604 bfd_map_over_sections (abfd, wasm_compute_custom_section_file_position, &fs); 605 606 if (fs.failed) 607 return FALSE; 608 609 abfd->output_has_begun = TRUE; 610 611 return TRUE; 612} 613 614static bfd_boolean 615wasm_set_section_contents (bfd *abfd, 616 sec_ptr section, 617 const void *location, 618 file_ptr offset, 619 bfd_size_type count) 620{ 621 if (count == 0) 622 return TRUE; 623 624 if (! abfd->output_has_begun 625 && ! wasm_compute_section_file_positions (abfd)) 626 return FALSE; 627 628 if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0 629 || bfd_bwrite (location, count, abfd) != count) 630 return FALSE; 631 632 return TRUE; 633} 634 635static bfd_boolean 636wasm_write_object_contents (bfd* abfd) 637{ 638 bfd_byte magic[] = WASM_MAGIC; 639 bfd_byte vers[] = WASM_VERSION; 640 641 if (bfd_seek (abfd, 0, SEEK_SET) != 0) 642 return FALSE; 643 644 if (bfd_bwrite (magic, sizeof (magic), abfd) != sizeof (magic) 645 || bfd_bwrite (vers, sizeof (vers), abfd) != sizeof (vers)) 646 return FALSE; 647 648 return TRUE; 649} 650 651static bfd_boolean 652wasm_mkobject (bfd *abfd) 653{ 654 tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type)); 655 656 if (! tdata) 657 return FALSE; 658 659 tdata->symbols = NULL; 660 tdata->symcount = 0; 661 662 abfd->tdata.any = tdata; 663 664 return TRUE; 665} 666 667static long 668wasm_get_symtab_upper_bound (bfd *abfd) 669{ 670 tdata_type *tdata = abfd->tdata.any; 671 672 return (tdata->symcount + 1) * (sizeof (asymbol *)); 673} 674 675static long 676wasm_canonicalize_symtab (bfd *abfd, asymbol **alocation) 677{ 678 tdata_type *tdata = abfd->tdata.any; 679 size_t i; 680 681 for (i = 0; i < tdata->symcount; i++) 682 alocation[i] = &tdata->symbols[i]; 683 alocation[i] = NULL; 684 685 return tdata->symcount; 686} 687 688static asymbol * 689wasm_make_empty_symbol (bfd *abfd) 690{ 691 bfd_size_type amt = sizeof (asymbol); 692 asymbol *new_symbol = (asymbol *) bfd_zalloc (abfd, amt); 693 694 if (! new_symbol) 695 return NULL; 696 new_symbol->the_bfd = abfd; 697 return new_symbol; 698} 699 700static void 701wasm_print_symbol (bfd *abfd, 702 void * filep, 703 asymbol *symbol, 704 bfd_print_symbol_type how) 705{ 706 FILE *file = (FILE *) filep; 707 708 switch (how) 709 { 710 case bfd_print_symbol_name: 711 fprintf (file, "%s", symbol->name); 712 break; 713 714 default: 715 bfd_print_symbol_vandf (abfd, filep, symbol); 716 fprintf (file, " %-5s %s", symbol->section->name, symbol->name); 717 } 718} 719 720static void 721wasm_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED, 722 asymbol *symbol, 723 symbol_info *ret) 724{ 725 bfd_symbol_info (symbol, ret); 726} 727 728/* Check whether ABFD is a WebAssembly module; if so, scan it. */ 729 730static const bfd_target * 731wasm_object_p (bfd *abfd) 732{ 733 bfd_boolean error; 734 asection *s; 735 736 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) 737 return NULL; 738 739 if (!wasm_read_header (abfd, &error)) 740 { 741 bfd_set_error (bfd_error_wrong_format); 742 return NULL; 743 } 744 745 if (!wasm_mkobject (abfd)) 746 return NULL; 747 748 if (!wasm_scan (abfd) 749 || !bfd_default_set_arch_mach (abfd, bfd_arch_wasm32, 0)) 750 { 751 bfd_release (abfd, abfd->tdata.any); 752 abfd->tdata.any = NULL; 753 return NULL; 754 } 755 756 s = bfd_get_section_by_name (abfd, WASM_NAME_SECTION); 757 if (s != NULL && wasm_scan_name_function_section (abfd, s)) 758 abfd->flags |= HAS_SYMS; 759 760 return abfd->xvec; 761} 762 763/* BFD_JUMP_TABLE_WRITE */ 764#define wasm_set_arch_mach _bfd_generic_set_arch_mach 765 766/* BFD_JUMP_TABLE_SYMBOLS */ 767#define wasm_get_symbol_version_string _bfd_nosymbols_get_symbol_version_string 768#define wasm_bfd_is_local_label_name bfd_generic_is_local_label_name 769#define wasm_bfd_is_target_special_symbol _bfd_bool_bfd_asymbol_false 770#define wasm_get_lineno _bfd_nosymbols_get_lineno 771#define wasm_find_nearest_line _bfd_nosymbols_find_nearest_line 772#define wasm_find_line _bfd_nosymbols_find_line 773#define wasm_find_inliner_info _bfd_nosymbols_find_inliner_info 774#define wasm_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol 775#define wasm_read_minisymbols _bfd_generic_read_minisymbols 776#define wasm_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol 777 778const bfd_target wasm_vec = 779{ 780 "wasm", /* Name. */ 781 bfd_target_unknown_flavour, 782 BFD_ENDIAN_LITTLE, 783 BFD_ENDIAN_LITTLE, 784 (HAS_SYMS | WP_TEXT), /* Object flags. */ 785 (SEC_CODE | SEC_DATA | SEC_HAS_CONTENTS), /* Section flags. */ 786 0, /* Leading underscore. */ 787 ' ', /* AR_pad_char. */ 788 255, /* AR_max_namelen. */ 789 0, /* Match priority. */ 790 /* Routines to byte-swap various sized integers from the data sections. */ 791 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 792 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 793 bfd_getl16, bfd_getl_signed_16, bfd_putl16, 794 795 /* Routines to byte-swap various sized integers from the file headers. */ 796 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 797 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 798 bfd_getl16, bfd_getl_signed_16, bfd_putl16, 799 800 { 801 _bfd_dummy_target, 802 wasm_object_p, /* bfd_check_format. */ 803 _bfd_dummy_target, 804 _bfd_dummy_target, 805 }, 806 { 807 _bfd_bool_bfd_false_error, 808 wasm_mkobject, 809 _bfd_generic_mkarchive, 810 _bfd_bool_bfd_false_error, 811 }, 812 { /* bfd_write_contents. */ 813 _bfd_bool_bfd_false_error, 814 wasm_write_object_contents, 815 _bfd_write_archive_contents, 816 _bfd_bool_bfd_false_error, 817 }, 818 819 BFD_JUMP_TABLE_GENERIC (_bfd_generic), 820 BFD_JUMP_TABLE_COPY (_bfd_generic), 821 BFD_JUMP_TABLE_CORE (_bfd_nocore), 822 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 823 BFD_JUMP_TABLE_SYMBOLS (wasm), 824 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), 825 BFD_JUMP_TABLE_WRITE (wasm), 826 BFD_JUMP_TABLE_LINK (_bfd_nolink), 827 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 828 829 NULL, 830 831 NULL, 832}; 833