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