xref: /netbsd-src/external/gpl3/gdb/dist/bfd/wasm-module.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
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   size_t amt;
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 (payload_size > (size_t) (end - p))
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 (payload_size > (size_t) (end - p))
282     return FALSE;
283 
284   end = p + payload_size;
285 
286   READ_LEB128 (symcount, p, end);
287 
288   /* Sanity check: each symbol has at least two bytes.  */
289   if (symcount > payload_size / 2)
290     return FALSE;
291 
292   tdata->symcount = symcount;
293 
294   space_function_index
295     = bfd_make_section_with_flags (abfd, WASM_SECTION_FUNCTION_INDEX,
296 				   SEC_READONLY | SEC_CODE);
297 
298   if (!space_function_index)
299     space_function_index
300       = bfd_get_section_by_name (abfd, WASM_SECTION_FUNCTION_INDEX);
301 
302   if (!space_function_index)
303     return FALSE;
304 
305   if (_bfd_mul_overflow (tdata->symcount, sizeof (asymbol), &amt))
306     {
307       bfd_set_error (bfd_error_file_too_big);
308       return FALSE;
309     }
310   symbols = bfd_alloc (abfd, amt);
311   if (!symbols)
312     return FALSE;
313 
314   for (symcount = 0; p < end && symcount < tdata->symcount; symcount++)
315     {
316       bfd_vma idx;
317       bfd_vma len;
318       char *name;
319       asymbol *sym;
320 
321       READ_LEB128 (idx, p, end);
322       READ_LEB128 (len, p, end);
323 
324       if (len > (size_t) (end - p))
325 	goto error_return;
326 
327       name = bfd_alloc (abfd, len + 1);
328       if (!name)
329 	goto error_return;
330 
331       memcpy (name, p, len);
332       name[len] = 0;
333       p += len;
334 
335       sym = &symbols[symcount];
336       sym->the_bfd = abfd;
337       sym->name = name;
338       sym->value = idx;
339       sym->flags = BSF_GLOBAL | BSF_FUNCTION;
340       sym->section = space_function_index;
341       sym->udata.p = NULL;
342     }
343 
344   if (symcount < tdata->symcount)
345     goto error_return;
346 
347   tdata->symbols = symbols;
348   abfd->symcount = symcount;
349 
350   return TRUE;
351 
352  error_return:
353   bfd_release (abfd, symbols);
354   return FALSE;
355 }
356 
357 /* Read a byte from ABFD and return it, or EOF for EOF or error.
358    Set ERRORPTR on non-EOF error.  */
359 
360 static int
361 wasm_read_byte (bfd *abfd, bfd_boolean *errorptr)
362 {
363   bfd_byte byte;
364 
365   if (bfd_bread (&byte, (bfd_size_type) 1, abfd) != 1)
366     {
367       if (bfd_get_error () != bfd_error_file_truncated)
368 	*errorptr = TRUE;
369       return EOF;
370     }
371 
372   return byte;
373 }
374 
375 /* Scan the wasm module ABFD, creating sections and symbols.
376    Return TRUE on success.  */
377 
378 static bfd_boolean
379 wasm_scan (bfd *abfd)
380 {
381   bfd_boolean error = FALSE;
382   /* Fake VMAs for now. Choose 0x80000000 as base to avoid clashes
383      with actual data addresses.  */
384   bfd_vma vma = 0x80000000;
385   int section_code;
386   unsigned int bytes_read;
387   asection *bfdsec;
388 
389   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
390     goto error_return;
391 
392   if (!wasm_read_header (abfd, &error))
393     goto error_return;
394 
395   while ((section_code = wasm_read_byte (abfd, &error)) != EOF)
396     {
397       if (section_code != 0)
398 	{
399 	  const char *sname = wasm_section_code_to_name (section_code);
400 
401 	  if (!sname)
402 	    goto error_return;
403 
404 	  bfdsec = bfd_make_section_anyway_with_flags (abfd, sname,
405 						       SEC_HAS_CONTENTS);
406 	  if (bfdsec == NULL)
407 	    goto error_return;
408 
409 	  bfdsec->size = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE);
410 	  if (error)
411 	    goto error_return;
412 	}
413       else
414 	{
415 	  bfd_vma payload_len;
416 	  bfd_vma namelen;
417 	  char *name;
418 	  char *prefix = WASM_SECTION_PREFIX;
419 	  size_t prefixlen = strlen (prefix);
420 	  ufile_ptr filesize;
421 
422 	  payload_len = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE);
423 	  if (error)
424 	    goto error_return;
425 	  namelen = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE);
426 	  if (error || bytes_read > payload_len
427 	      || namelen > payload_len - bytes_read)
428 	    goto error_return;
429 	  payload_len -= namelen + bytes_read;
430 	  filesize = bfd_get_file_size (abfd);
431 	  if (filesize != 0 && namelen > filesize)
432 	    {
433 	      bfd_set_error (bfd_error_file_truncated);
434 	      return FALSE;
435 	    }
436 	  name = bfd_alloc (abfd, namelen + prefixlen + 1);
437 	  if (!name)
438 	    goto error_return;
439 	  memcpy (name, prefix, prefixlen);
440 	  if (bfd_bread (name + prefixlen, namelen, abfd) != namelen)
441 	    goto error_return;
442 	  name[prefixlen + namelen] = 0;
443 
444 	  bfdsec = bfd_make_section_anyway_with_flags (abfd, name,
445 						       SEC_HAS_CONTENTS);
446 	  if (bfdsec == NULL)
447 	    goto error_return;
448 
449 	  bfdsec->size = payload_len;
450 	}
451 
452       bfdsec->vma = vma;
453       bfdsec->lma = vma;
454       bfdsec->alignment_power = 0;
455       bfdsec->filepos = bfd_tell (abfd);
456       if (bfdsec->size != 0)
457 	{
458 	  bfdsec->contents = _bfd_alloc_and_read (abfd, bfdsec->size,
459 						  bfdsec->size);
460 	  if (!bfdsec->contents)
461 	    goto error_return;
462 	}
463 
464       vma += bfdsec->size;
465     }
466 
467   /* Make sure we're at actual EOF.  There's no indication in the
468      WebAssembly format of how long the file is supposed to be.  */
469   if (error)
470     goto error_return;
471 
472   return TRUE;
473 
474  error_return:
475   return FALSE;
476 }
477 
478 /* Put a numbered section ASECT of ABFD into the table of numbered
479    sections pointed to by FSARG.  */
480 
481 static void
482 wasm_register_section (bfd *abfd ATTRIBUTE_UNUSED,
483 		       asection *asect,
484 		       void *fsarg)
485 {
486   sec_ptr *numbered_sections = fsarg;
487   int idx = wasm_section_name_to_code (asect->name);
488 
489   if (idx == 0)
490     return;
491 
492   numbered_sections[idx] = asect;
493 }
494 
495 struct compute_section_arg
496 {
497   bfd_vma pos;
498   bfd_boolean failed;
499 };
500 
501 /* Compute the file position of ABFD's section ASECT.  FSARG is a
502    pointer to the current file position.
503 
504    We allow section names of the form .wasm.id to encode the numbered
505    section with ID id, if it exists; otherwise, a custom section with
506    ID "id" is produced.  Arbitrary section names are for sections that
507    are assumed already to contain a section header; those are appended
508    to the WebAssembly module verbatim.  */
509 
510 static void
511 wasm_compute_custom_section_file_position (bfd *abfd,
512 					   sec_ptr asect,
513 					   void *fsarg)
514 {
515   struct compute_section_arg *fs = fsarg;
516   int idx;
517 
518   if (fs->failed)
519     return;
520 
521   idx = wasm_section_name_to_code (asect->name);
522 
523   if (idx != 0)
524     return;
525 
526   if (CONST_STRNEQ (asect->name, WASM_SECTION_PREFIX))
527     {
528       const char *name = asect->name + strlen (WASM_SECTION_PREFIX);
529       bfd_size_type payload_len = asect->size;
530       bfd_size_type name_len = strlen (name);
531       bfd_size_type nl = name_len;
532 
533       payload_len += name_len;
534 
535       do
536 	{
537 	  payload_len++;
538 	  nl >>= 7;
539 	}
540       while (nl);
541 
542       bfd_seek (abfd, fs->pos, SEEK_SET);
543       if (! wasm_write_uleb128 (abfd, 0)
544 	  || ! wasm_write_uleb128 (abfd, payload_len)
545 	  || ! wasm_write_uleb128 (abfd, name_len)
546 	  || bfd_bwrite (name, name_len, abfd) != name_len)
547 	goto error_return;
548       fs->pos = asect->filepos = bfd_tell (abfd);
549     }
550   else
551     {
552       asect->filepos = fs->pos;
553     }
554 
555 
556   fs->pos += asect->size;
557   return;
558 
559  error_return:
560   fs->failed = TRUE;
561 }
562 
563 /* Compute the file positions for the sections of ABFD.  Currently,
564    this writes all numbered sections first, in order, then all custom
565    sections, in section order.
566 
567    The spec says that the numbered sections must appear in order of
568    their ids, but custom sections can appear in any position and any
569    order, and more than once. FIXME: support that.  */
570 
571 static bfd_boolean
572 wasm_compute_section_file_positions (bfd *abfd)
573 {
574   bfd_byte magic[SIZEOF_WASM_MAGIC] = WASM_MAGIC;
575   bfd_byte vers[SIZEOF_WASM_VERSION] = WASM_VERSION;
576   sec_ptr numbered_sections[WASM_NUMBERED_SECTIONS];
577   struct compute_section_arg fs;
578   unsigned int i;
579 
580   bfd_seek (abfd, (bfd_vma) 0, SEEK_SET);
581 
582   if (bfd_bwrite (magic, sizeof (magic), abfd) != (sizeof magic)
583       || bfd_bwrite (vers, sizeof (vers), abfd) != sizeof (vers))
584     return FALSE;
585 
586   for (i = 0; i < WASM_NUMBERED_SECTIONS; i++)
587     numbered_sections[i] = NULL;
588 
589   bfd_map_over_sections (abfd, wasm_register_section, numbered_sections);
590 
591   fs.pos = bfd_tell (abfd);
592   for (i = 0; i < WASM_NUMBERED_SECTIONS; i++)
593     {
594       sec_ptr sec = numbered_sections[i];
595       bfd_size_type size;
596 
597       if (! sec)
598 	continue;
599       size = sec->size;
600       if (bfd_seek (abfd, fs.pos, SEEK_SET) != 0)
601 	return FALSE;
602       if (! wasm_write_uleb128 (abfd, i)
603 	  || ! wasm_write_uleb128 (abfd, size))
604 	return FALSE;
605       fs.pos = sec->filepos = bfd_tell (abfd);
606       fs.pos += size;
607     }
608 
609   fs.failed = FALSE;
610 
611   bfd_map_over_sections (abfd, wasm_compute_custom_section_file_position, &fs);
612 
613   if (fs.failed)
614     return FALSE;
615 
616   abfd->output_has_begun = TRUE;
617 
618   return TRUE;
619 }
620 
621 static bfd_boolean
622 wasm_set_section_contents (bfd *abfd,
623 			   sec_ptr section,
624 			   const void *location,
625 			   file_ptr offset,
626 			   bfd_size_type count)
627 {
628   if (count == 0)
629     return TRUE;
630 
631   if (! abfd->output_has_begun
632       && ! wasm_compute_section_file_positions (abfd))
633     return FALSE;
634 
635   if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
636       || bfd_bwrite (location, count, abfd) != count)
637     return FALSE;
638 
639   return TRUE;
640 }
641 
642 static bfd_boolean
643 wasm_write_object_contents (bfd* abfd)
644 {
645   bfd_byte magic[] = WASM_MAGIC;
646   bfd_byte vers[] = WASM_VERSION;
647 
648   if (bfd_seek (abfd, 0, SEEK_SET) != 0)
649     return FALSE;
650 
651   if (bfd_bwrite (magic, sizeof (magic), abfd) != sizeof (magic)
652       || bfd_bwrite (vers, sizeof (vers), abfd) != sizeof (vers))
653     return FALSE;
654 
655   return TRUE;
656 }
657 
658 static bfd_boolean
659 wasm_mkobject (bfd *abfd)
660 {
661   tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
662 
663   if (! tdata)
664     return FALSE;
665 
666   tdata->symbols = NULL;
667   tdata->symcount = 0;
668 
669   abfd->tdata.any = tdata;
670 
671   return TRUE;
672 }
673 
674 static long
675 wasm_get_symtab_upper_bound (bfd *abfd)
676 {
677   tdata_type *tdata = abfd->tdata.any;
678 
679   return (tdata->symcount + 1) * (sizeof (asymbol *));
680 }
681 
682 static long
683 wasm_canonicalize_symtab (bfd *abfd, asymbol **alocation)
684 {
685   tdata_type *tdata = abfd->tdata.any;
686   size_t i;
687 
688   for (i = 0; i < tdata->symcount; i++)
689     alocation[i] = &tdata->symbols[i];
690   alocation[i] = NULL;
691 
692   return tdata->symcount;
693 }
694 
695 static asymbol *
696 wasm_make_empty_symbol (bfd *abfd)
697 {
698   size_t amt = sizeof (asymbol);
699   asymbol *new_symbol = (asymbol *) bfd_zalloc (abfd, amt);
700 
701   if (! new_symbol)
702     return NULL;
703   new_symbol->the_bfd = abfd;
704   return new_symbol;
705 }
706 
707 static void
708 wasm_print_symbol (bfd *abfd,
709 		   void * filep,
710 		   asymbol *symbol,
711 		   bfd_print_symbol_type how)
712 {
713   FILE *file = (FILE *) filep;
714 
715   switch (how)
716     {
717     case bfd_print_symbol_name:
718       fprintf (file, "%s", symbol->name);
719       break;
720 
721     default:
722       bfd_print_symbol_vandf (abfd, filep, symbol);
723       fprintf (file, " %-5s %s", symbol->section->name, symbol->name);
724     }
725 }
726 
727 static void
728 wasm_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
729 		      asymbol *symbol,
730 		      symbol_info *ret)
731 {
732   bfd_symbol_info (symbol, ret);
733 }
734 
735 /* Check whether ABFD is a WebAssembly module; if so, scan it.  */
736 
737 static bfd_cleanup
738 wasm_object_p (bfd *abfd)
739 {
740   bfd_boolean error;
741   asection *s;
742 
743   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
744     return NULL;
745 
746   if (!wasm_read_header (abfd, &error))
747     {
748       bfd_set_error (bfd_error_wrong_format);
749       return NULL;
750     }
751 
752   if (!wasm_mkobject (abfd))
753     return NULL;
754 
755   if (!wasm_scan (abfd)
756       || !bfd_default_set_arch_mach (abfd, bfd_arch_wasm32, 0))
757     {
758       bfd_release (abfd, abfd->tdata.any);
759       abfd->tdata.any = NULL;
760       return NULL;
761     }
762 
763   s = bfd_get_section_by_name (abfd, WASM_NAME_SECTION);
764   if (s != NULL && wasm_scan_name_function_section (abfd, s))
765     abfd->flags |= HAS_SYMS;
766 
767   return _bfd_no_cleanup;
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