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