xref: /netbsd-src/external/gpl3/binutils.old/dist/bfd/wasm-module.c (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
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 
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 
354 static int
355 wasm_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 
372 static bfd_boolean
373 wasm_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 
474 static void
475 wasm_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 
488 struct 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 
503 static void
504 wasm_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 
564 static bfd_boolean
565 wasm_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 
614 static bfd_boolean
615 wasm_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 
635 static bfd_boolean
636 wasm_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 
651 static bfd_boolean
652 wasm_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 
667 static long
668 wasm_get_symtab_upper_bound (bfd *abfd)
669 {
670   tdata_type *tdata = abfd->tdata.any;
671 
672   return (tdata->symcount + 1) * (sizeof (asymbol *));
673 }
674 
675 static long
676 wasm_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 
688 static asymbol *
689 wasm_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 
700 static void
701 wasm_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 
720 static void
721 wasm_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 
730 static const bfd_target *
731 wasm_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 
778 const 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