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