[BACK]Return to wasm-module.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / gpl3 / binutils.old / dist / bfd

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>