Annotation of src/external/gpl3/binutils.old/dist/bfd/wasm-module.c, Revision 1.1.1.1.2.2
1.1.1.1.2.2! martin 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: };
CVSweb <webmaster@jp.NetBSD.org>