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
36typedef struct
37{
38  asymbol *      symbols;
39  bfd_size_type  symcount;
40} tdata_type;
41
42static 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
63static const char *
64wasm_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
75static unsigned int
76wasm_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
104static bfd_vma
105wasm_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
151static bfd_boolean
152wasm_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
187static bfd_boolean
188wasm_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
204static bfd_boolean
205wasm_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
223static bfd_boolean
224wasm_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
238static bfd_boolean
239wasm_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
354static int
355wasm_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
372static bfd_boolean
373wasm_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
474static void
475wasm_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
488struct 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
503static void
504wasm_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
564static bfd_boolean
565wasm_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
614static bfd_boolean
615wasm_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
635static bfd_boolean
636wasm_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
651static bfd_boolean
652wasm_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
667static long
668wasm_get_symtab_upper_bound (bfd *abfd)
669{
670  tdata_type *tdata = abfd->tdata.any;
671
672  return (tdata->symcount + 1) * (sizeof (asymbol *));
673}
674
675static long
676wasm_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
688static asymbol *
689wasm_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
700static void
701wasm_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
720static void
721wasm_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
730static const bfd_target *
731wasm_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
778const 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