Memory leaks and ineffective bounds checking in wasm_scan
[deliverable/binutils-gdb.git] / bfd / wasm-module.c
CommitLineData
a6be0538 1/* BFD back-end for WebAssembly modules.
b3adc24a 2 Copyright (C) 2017-2020 Free Software Foundation, Inc.
a6be0538
PC
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"
a6be0538 31#include <limits.h>
a6be0538
PC
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
07d6d2b8
AM
105wasm_read_leb128 (bfd * abfd,
106 bfd_boolean * error_return,
107 unsigned int * length_return,
108 bfd_boolean sign)
a6be0538
PC
109{
110 bfd_vma result = 0;
111 unsigned int num_read = 0;
112 unsigned int shift = 0;
113 unsigned char byte = 0;
27c1c427 114 int status = 1;
a6be0538
PC
115
116 while (bfd_bread (&byte, 1, abfd) == 1)
117 {
118 num_read++;
119
27c1c427
AM
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;
a6be0538 130
a6be0538 131 if ((byte & 0x80) == 0)
07d6d2b8 132 {
27c1c427
AM
133 status &= ~1;
134 if (sign && (shift < 8 * sizeof (result)) && (byte & 0x40))
135 result |= -((bfd_vma) 1 << shift);
07d6d2b8
AM
136 break;
137 }
a6be0538
PC
138 }
139
140 if (length_return != NULL)
141 *length_return = num_read;
142 if (error_return != NULL)
27c1c427 143 *error_return = status != 0;
a6be0538
PC
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)
07d6d2b8 160 c |= 0x80;
a6be0538
PC
161
162 if (bfd_bwrite (&c, 1, abfd) != 1)
07d6d2b8 163 return FALSE;
a6be0538
PC
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. */
07d6d2b8
AM
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 } \
a6be0538
PC
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
a6be0538
PC
249 p = asect->contents;
250 end = asect->contents + asect->size;
251
0c0adcc5 252 if (!p)
a6be0538
PC
253 return FALSE;
254
255 while (p < end)
256 {
257 bfd_byte subsection_code = *p++;
258 if (subsection_code == WASM_FUNCTION_SUBSECTION)
07d6d2b8 259 break;
a6be0538
PC
260
261 /* subsection_code is documented to be a varuint7, meaning that
07d6d2b8
AM
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. */
a6be0538 264 if (subsection_code & 0x80)
07d6d2b8 265 return FALSE;
a6be0538
PC
266
267 READ_LEB128 (payload_size, p, end);
268
0c0adcc5 269 if (payload_size > (size_t) (end - p))
07d6d2b8 270 return FALSE;
a6be0538
PC
271
272 p += payload_size;
273 }
274
275 if (p >= end)
276 return FALSE;
277
278 READ_LEB128 (payload_size, p, end);
279
0c0adcc5 280 if (payload_size > (size_t) (end - p))
a6be0538
PC
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. */
0c0adcc5 288 if (symcount > payload_size / 2)
a6be0538
PC
289 return FALSE;
290
291 tdata->symcount = symcount;
292
0c0adcc5
AM
293 space_function_index
294 = bfd_make_section_with_flags (abfd, WASM_SECTION_FUNCTION_INDEX,
295 SEC_READONLY | SEC_CODE);
a6be0538 296
0c0adcc5
AM
297 if (!space_function_index)
298 space_function_index
299 = bfd_get_section_by_name (abfd, WASM_SECTION_FUNCTION_INDEX);
a6be0538 300
0c0adcc5 301 if (!space_function_index)
a6be0538
PC
302 return FALSE;
303
0c0adcc5
AM
304 symbols = bfd_alloc2 (abfd, tdata->symcount, sizeof (asymbol));
305 if (!symbols)
a6be0538
PC
306 return FALSE;
307
308 for (symcount = 0; p < end && symcount < tdata->symcount; symcount++)
309 {
87993319 310 bfd_vma idx;
a6be0538
PC
311 bfd_vma len;
312 char *name;
313 asymbol *sym;
314
87993319 315 READ_LEB128 (idx, p, end);
a6be0538
PC
316 READ_LEB128 (len, p, end);
317
0c0adcc5 318 if (len > (size_t) (end - p))
07d6d2b8 319 goto error_return;
a6be0538 320
0c0adcc5
AM
321 name = bfd_alloc (abfd, len + 1);
322 if (!name)
07d6d2b8 323 goto error_return;
a6be0538
PC
324
325 memcpy (name, p, len);
0c0adcc5 326 name[len] = 0;
a6be0538
PC
327 p += len;
328
329 sym = &symbols[symcount];
330 sym->the_bfd = abfd;
331 sym->name = name;
87993319 332 sym->value = idx;
a6be0538
PC
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:
a6be0538
PC
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)
07d6d2b8 362 *errorptr = TRUE;
a6be0538
PC
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;
a6be0538
PC
381 asection *bfdsec;
382
383 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
384 goto error_return;
385
0c0adcc5 386 if (!wasm_read_header (abfd, &error))
a6be0538
PC
387 goto error_return;
388
389 while ((section_code = wasm_read_byte (abfd, &error)) != EOF)
390 {
391 if (section_code != 0)
07d6d2b8
AM
392 {
393 const char *sname = wasm_section_code_to_name (section_code);
394
0c0adcc5 395 if (!sname)
07d6d2b8
AM
396 goto error_return;
397
0c0adcc5
AM
398 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname,
399 SEC_HAS_CONTENTS);
07d6d2b8
AM
400 if (bfdsec == NULL)
401 goto error_return;
07d6d2b8
AM
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 }
a6be0538 411 else
07d6d2b8
AM
412 {
413 bfd_vma payload_len;
414 file_ptr section_start;
415 bfd_vma namelen;
0c0adcc5 416 char *name;
07d6d2b8 417 char *prefix = WASM_SECTION_PREFIX;
0c0adcc5 418 size_t prefixlen = strlen (prefix);
07d6d2b8
AM
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;
0c0adcc5
AM
427 name = bfd_alloc (abfd, namelen + prefixlen + 1);
428 if (!name)
07d6d2b8 429 goto error_return;
0c0adcc5
AM
430 memcpy (name, prefix, prefixlen);
431 if (bfd_bread (name + prefixlen, namelen, abfd) != namelen)
a6be0538 432 goto error_return;
0c0adcc5 433 name[prefixlen + namelen] = 0;
a6be0538 434
0c0adcc5
AM
435 bfdsec = bfd_make_section_anyway_with_flags (abfd, name,
436 SEC_HAS_CONTENTS);
07d6d2b8
AM
437 if (bfdsec == NULL)
438 goto error_return;
a6be0538 439
07d6d2b8
AM
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 }
a6be0538
PC
446
447 if (bfdsec->size != 0)
07d6d2b8 448 {
0c0adcc5
AM
449 bfdsec->contents = bfd_alloc (abfd, bfdsec->size);
450 if (!bfdsec->contents)
07d6d2b8 451 goto error_return;
a6be0538 452
07d6d2b8 453 if (bfd_bread (bfdsec->contents, bfdsec->size, abfd) != bfdsec->size)
a6be0538 454 goto error_return;
07d6d2b8 455 }
a6be0538
PC
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:
a6be0538
PC
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,
07d6d2b8 476 asection *asect,
a6be0538
PC
477 void *fsarg)
478{
479 sec_ptr *numbered_sections = fsarg;
87993319 480 int idx = wasm_section_name_to_code (asect->name);
a6be0538 481
87993319 482 if (idx == 0)
a6be0538
PC
483 return;
484
87993319 485 numbered_sections[idx] = asect;
a6be0538
PC
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,
07d6d2b8 506 void *fsarg)
a6be0538
PC
507{
508 struct compute_section_arg *fs = fsarg;
87993319 509 int idx;
a6be0538
PC
510
511 if (fs->failed)
512 return;
513
87993319 514 idx = wasm_section_name_to_code (asect->name);
a6be0538 515
87993319 516 if (idx != 0)
a6be0538
PC
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
07d6d2b8
AM
529 {
530 payload_len++;
531 nl >>= 7;
532 }
a6be0538
PC
533 while (nl);
534
535 bfd_seek (abfd, fs->pos, SEEK_SET);
536 if (! wasm_write_uleb128 (abfd, 0)
07d6d2b8
AM
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;
a6be0538
PC
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)
07d6d2b8 591 continue;
a6be0538
PC
592 size = sec->size;
593 if (bfd_seek (abfd, fs.pos, SEEK_SET) != 0)
07d6d2b8 594 return FALSE;
a6be0538 595 if (! wasm_write_uleb128 (abfd, i)
07d6d2b8
AM
596 || ! wasm_write_uleb128 (abfd, size))
597 return FALSE;
a6be0538
PC
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,
07d6d2b8
AM
616 sec_ptr section,
617 const void *location,
618 file_ptr offset,
619 bfd_size_type count)
a6be0538
PC
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,
07d6d2b8
AM
702 void * filep,
703 asymbol *symbol,
704 bfd_print_symbol_type how)
a6be0538
PC
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,
07d6d2b8
AM
722 asymbol *symbol,
723 symbol_info *ret)
a6be0538
PC
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;
0c0adcc5 734 asection *s;
a6be0538
PC
735
736 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
737 return NULL;
738
0c0adcc5 739 if (!wasm_read_header (abfd, &error))
a6be0538
PC
740 {
741 bfd_set_error (bfd_error_wrong_format);
742 return NULL;
743 }
744
0c0adcc5 745 if (!wasm_mkobject (abfd))
a6be0538
PC
746 return NULL;
747
0c0adcc5
AM
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 }
a6be0538 755
0c0adcc5
AM
756 s = bfd_get_section_by_name (abfd, WASM_NAME_SECTION);
757 if (s != NULL && wasm_scan_name_function_section (abfd, s))
a6be0538
PC
758 abfd->flags |= HAS_SYMS;
759
760 return abfd->xvec;
761}
762
763/* BFD_JUMP_TABLE_WRITE */
07d6d2b8 764#define wasm_set_arch_mach _bfd_generic_set_arch_mach
a6be0538
PC
765
766/* BFD_JUMP_TABLE_SYMBOLS */
07d6d2b8
AM
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
d00dd7dc 769#define wasm_bfd_is_target_special_symbol _bfd_bool_bfd_asymbol_false
07d6d2b8
AM
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
a6be0538
PC
777
778const bfd_target wasm_vec =
779{
07d6d2b8 780 "wasm", /* Name. */
a6be0538
PC
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. */
07d6d2b8
AM
786 0, /* Leading underscore. */
787 ' ', /* AR_pad_char. */
788 255, /* AR_max_namelen. */
a6be0538
PC
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 {
d00dd7dc 807 _bfd_bool_bfd_false_error,
a6be0538
PC
808 wasm_mkobject,
809 _bfd_generic_mkarchive,
d00dd7dc 810 _bfd_bool_bfd_false_error,
a6be0538
PC
811 },
812 { /* bfd_write_contents. */
d00dd7dc 813 _bfd_bool_bfd_false_error,
a6be0538
PC
814 wasm_write_object_contents,
815 _bfd_write_archive_contents,
d00dd7dc 816 _bfd_bool_bfd_false_error,
a6be0538
PC
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};
This page took 0.229915 seconds and 4 git commands to generate.