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