LCOV - code coverage report
Current view: top level - lib/Object - WasmObjectFile.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 595 691 86.1 %
Date: 2018-10-20 13:21:21 Functions: 78 92 84.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #include "llvm/ADT/ArrayRef.h"
      11             : #include "llvm/ADT/DenseSet.h"
      12             : #include "llvm/ADT/STLExtras.h"
      13             : #include "llvm/ADT/StringRef.h"
      14             : #include "llvm/ADT/StringSet.h"
      15             : #include "llvm/ADT/Triple.h"
      16             : #include "llvm/BinaryFormat/Wasm.h"
      17             : #include "llvm/MC/SubtargetFeature.h"
      18             : #include "llvm/Object/Binary.h"
      19             : #include "llvm/Object/Error.h"
      20             : #include "llvm/Object/ObjectFile.h"
      21             : #include "llvm/Object/SymbolicFile.h"
      22             : #include "llvm/Object/Wasm.h"
      23             : #include "llvm/Support/Endian.h"
      24             : #include "llvm/Support/Error.h"
      25             : #include "llvm/Support/ErrorHandling.h"
      26             : #include "llvm/Support/LEB128.h"
      27             : #include <algorithm>
      28             : #include <cassert>
      29             : #include <cstdint>
      30             : #include <cstring>
      31             : #include <system_error>
      32             : 
      33             : #define DEBUG_TYPE "wasm-object"
      34             : 
      35             : using namespace llvm;
      36             : using namespace object;
      37             : 
      38           0 : void WasmSymbol::print(raw_ostream &Out) const {
      39           0 :   Out << "Name=" << Info.Name
      40           0 :       << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind))
      41           0 :       << ", Flags=" << Info.Flags;
      42           0 :   if (!isTypeData()) {
      43           0 :     Out << ", ElemIndex=" << Info.ElementIndex;
      44           0 :   } else if (isDefined()) {
      45           0 :     Out << ", Segment=" << Info.DataRef.Segment;
      46           0 :     Out << ", Offset=" << Info.DataRef.Offset;
      47           0 :     Out << ", Size=" << Info.DataRef.Size;
      48             :   }
      49           0 : }
      50             : 
      51             : #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
      52             : LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); }
      53             : #endif
      54             : 
      55             : Expected<std::unique_ptr<WasmObjectFile>>
      56         360 : ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
      57             :   Error Err = Error::success();
      58         360 :   auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err);
      59         358 :   if (Err)
      60             :     return std::move(Err);
      61             : 
      62             :   return std::move(ObjectFile);
      63             : }
      64             : 
      65             : #define VARINT7_MAX ((1 << 7) - 1)
      66             : #define VARINT7_MIN (-(1 << 7))
      67             : #define VARUINT7_MAX (1 << 7)
      68             : #define VARUINT1_MAX (1)
      69             : 
      70           0 : static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
      71           0 :   if (Ctx.Ptr == Ctx.End)
      72           0 :     report_fatal_error("EOF while reading uint8");
      73        7184 :   return *Ctx.Ptr++;
      74             : }
      75             : 
      76           0 : static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
      77           0 :   if (Ctx.Ptr + 4 > Ctx.End)
      78           0 :     report_fatal_error("EOF while reading uint32");
      79             :   uint32_t Result = support::endian::read32le(Ctx.Ptr);
      80         359 :   Ctx.Ptr += 4;
      81           0 :   return Result;
      82             : }
      83             : 
      84           0 : static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
      85           0 :   if (Ctx.Ptr + 4 > Ctx.End)
      86           0 :     report_fatal_error("EOF while reading float64");
      87             :   int32_t Result = 0;
      88           0 :   memcpy(&Result, Ctx.Ptr, sizeof(Result));
      89           0 :   Ctx.Ptr += sizeof(Result);
      90           0 :   return Result;
      91             : }
      92             : 
      93           0 : static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
      94           0 :   if (Ctx.Ptr + 8 > Ctx.End)
      95           0 :     report_fatal_error("EOF while reading float64");
      96             :   int64_t Result = 0;
      97           0 :   memcpy(&Result, Ctx.Ptr, sizeof(Result));
      98           0 :   Ctx.Ptr += sizeof(Result);
      99           0 :   return Result;
     100             : }
     101             : 
     102           0 : static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
     103             :   unsigned Count;
     104           0 :   const char *Error = nullptr;
     105           0 :   uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
     106           0 :   if (Error)
     107           0 :     report_fatal_error(Error);
     108           0 :   Ctx.Ptr += Count;
     109           0 :   return Result;
     110             : }
     111             : 
     112        3794 : static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
     113        3794 :   uint32_t StringLen = readULEB128(Ctx);
     114        3794 :   if (Ctx.Ptr + StringLen > Ctx.End)
     115           1 :     report_fatal_error("EOF while reading string");
     116             :   StringRef Return =
     117             :       StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
     118        3793 :   Ctx.Ptr += StringLen;
     119        3793 :   return Return;
     120             : }
     121             : 
     122           0 : static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
     123             :   unsigned Count;
     124           0 :   const char *Error = nullptr;
     125           0 :   uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
     126           0 :   if (Error)
     127           0 :     report_fatal_error(Error);
     128           0 :   Ctx.Ptr += Count;
     129           0 :   return Result;
     130             : }
     131             : 
     132         891 : static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
     133         891 :   int64_t result = readLEB128(Ctx);
     134         891 :   if (result > VARUINT1_MAX || result < 0)
     135           0 :     report_fatal_error("LEB is outside Varuint1 range");
     136         891 :   return result;
     137             : }
     138             : 
     139         894 : static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
     140         894 :   int64_t result = readLEB128(Ctx);
     141         894 :   if (result > INT32_MAX || result < INT32_MIN)
     142           0 :     report_fatal_error("LEB is outside Varint32 range");
     143         894 :   return result;
     144             : }
     145             : 
     146       16882 : static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
     147       16882 :   uint64_t result = readULEB128(Ctx);
     148       16881 :   if (result > UINT32_MAX)
     149           0 :     report_fatal_error("LEB is outside Varuint32 range");
     150       16881 :   return result;
     151             : }
     152             : 
     153             : static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
     154          12 :   return readLEB128(Ctx);
     155             : }
     156             : 
     157             : static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
     158         449 :   return readUint8(Ctx);
     159             : }
     160             : 
     161         449 : static Error readInitExpr(wasm::WasmInitExpr &Expr,
     162             :                           WasmObjectFile::ReadContext &Ctx) {
     163         449 :   Expr.Opcode = readOpcode(Ctx);
     164             : 
     165         449 :   switch (Expr.Opcode) {
     166         436 :   case wasm::WASM_OPCODE_I32_CONST:
     167         436 :     Expr.Value.Int32 = readVarint32(Ctx);
     168         436 :     break;
     169             :   case wasm::WASM_OPCODE_I64_CONST:
     170          12 :     Expr.Value.Int64 = readVarint64(Ctx);
     171          12 :     break;
     172           0 :   case wasm::WASM_OPCODE_F32_CONST:
     173           0 :     Expr.Value.Float32 = readFloat32(Ctx);
     174           0 :     break;
     175           0 :   case wasm::WASM_OPCODE_F64_CONST:
     176           0 :     Expr.Value.Float64 = readFloat64(Ctx);
     177           0 :     break;
     178           1 :   case wasm::WASM_OPCODE_GET_GLOBAL:
     179           1 :     Expr.Value.Global = readULEB128(Ctx);
     180           1 :     break;
     181           0 :   default:
     182             :     return make_error<GenericBinaryError>("Invalid opcode in init_expr",
     183             :                                           object_error::parse_failed);
     184             :   }
     185             : 
     186             :   uint8_t EndOpcode = readOpcode(Ctx);
     187         449 :   if (EndOpcode != wasm::WASM_OPCODE_END) {
     188             :     return make_error<GenericBinaryError>("Invalid init_expr",
     189             :                                           object_error::parse_failed);
     190             :   }
     191             :   return Error::success();
     192             : }
     193             : 
     194         657 : static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
     195             :   wasm::WasmLimits Result;
     196         657 :   Result.Flags = readVaruint1(Ctx);
     197         657 :   Result.Initial = readVaruint32(Ctx);
     198         657 :   if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
     199          83 :     Result.Maximum = readVaruint32(Ctx);
     200         657 :   return Result;
     201             : }
     202             : 
     203         328 : static wasm::WasmTable readTable(WasmObjectFile::ReadContext &Ctx) {
     204             :   wasm::WasmTable Table;
     205         328 :   Table.ElemType = readUint8(Ctx);
     206         328 :   Table.Limits = readLimits(Ctx);
     207         328 :   return Table;
     208             : }
     209             : 
     210        2236 : static Error readSection(WasmSection &Section,
     211             :                          WasmObjectFile::ReadContext &Ctx) {
     212        2236 :   Section.Offset = Ctx.Ptr - Ctx.Start;
     213        2236 :   Section.Type = readUint8(Ctx);
     214             :   LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
     215        2236 :   uint32_t Size = readVaruint32(Ctx);
     216        2235 :   if (Size == 0)
     217             :     return make_error<StringError>("Zero length section",
     218             :                                    object_error::parse_failed);
     219        2235 :   if (Ctx.Ptr + Size > Ctx.End)
     220             :     return make_error<StringError>("Section too large",
     221             :                                    object_error::parse_failed);
     222        2233 :   if (Section.Type == wasm::WASM_SEC_CUSTOM) {
     223             :     WasmObjectFile::ReadContext SectionCtx;
     224         586 :     SectionCtx.Start = Ctx.Ptr;
     225         586 :     SectionCtx.Ptr = Ctx.Ptr;
     226         586 :     SectionCtx.End = Ctx.Ptr + Size;
     227             : 
     228         586 :     Section.Name = readString(SectionCtx);
     229             : 
     230         585 :     uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
     231         585 :     Ctx.Ptr += SectionNameSize;
     232         585 :     Size -= SectionNameSize;
     233             :   }
     234        2232 :   Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
     235        2232 :   Ctx.Ptr += Size;
     236             :   return Error::success();
     237             : }
     238             : 
     239         360 : WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
     240         360 :     : ObjectFile(Binary::ID_Wasm, Buffer) {
     241             :   ErrorAsOutParameter ErrAsOutParam(&Err);
     242         720 :   Header.Magic = getData().substr(0, 4);
     243             :   if (Header.Magic != StringRef("\0asm", 4)) {
     244             :     Err =
     245             :         make_error<StringError>("Bad magic number", object_error::parse_failed);
     246           0 :     return;
     247             :   }
     248             : 
     249             :   ReadContext Ctx;
     250         360 :   Ctx.Start = getPtr(0);
     251         360 :   Ctx.Ptr = Ctx.Start + 4;
     252         360 :   Ctx.End = Ctx.Start + getData().size();
     253             : 
     254         360 :   if (Ctx.Ptr + 4 > Ctx.End) {
     255             :     Err = make_error<StringError>("Missing version number",
     256             :                                   object_error::parse_failed);
     257           1 :     return;
     258             :   }
     259             : 
     260         359 :   Header.Version = readUint32(Ctx);
     261         359 :   if (Header.Version != wasm::WasmVersion) {
     262             :     Err = make_error<StringError>("Bad version number",
     263             :                                   object_error::parse_failed);
     264           2 :     return;
     265             :   }
     266             : 
     267             :   WasmSection Sec;
     268        2584 :   while (Ctx.Ptr < Ctx.End) {
     269        4470 :     if ((Err = readSection(Sec, Ctx)))
     270             :       return;
     271        4464 :     if ((Err = parseSection(Sec)))
     272             :       return;
     273             : 
     274        2227 :     Sections.push_back(Sec);
     275             :   }
     276             : }
     277             : 
     278        2232 : Error WasmObjectFile::parseSection(WasmSection &Sec) {
     279             :   ReadContext Ctx;
     280        2232 :   Ctx.Start = Sec.Content.data();
     281        2232 :   Ctx.End = Ctx.Start + Sec.Content.size();
     282        2232 :   Ctx.Ptr = Ctx.Start;
     283        2232 :   switch (Sec.Type) {
     284         585 :   case wasm::WASM_SEC_CUSTOM:
     285         585 :     return parseCustomSection(Sec, Ctx);
     286         318 :   case wasm::WASM_SEC_TYPE:
     287         318 :     return parseTypeSection(Ctx);
     288         274 :   case wasm::WASM_SEC_IMPORT:
     289         274 :     return parseImportSection(Ctx);
     290         311 :   case wasm::WASM_SEC_FUNCTION:
     291         311 :     return parseFunctionSection(Ctx);
     292          77 :   case wasm::WASM_SEC_TABLE:
     293          77 :     return parseTableSection(Ctx);
     294          76 :   case wasm::WASM_SEC_MEMORY:
     295          76 :     return parseMemorySection(Ctx);
     296          70 :   case wasm::WASM_SEC_GLOBAL:
     297          70 :     return parseGlobalSection(Ctx);
     298          66 :   case wasm::WASM_SEC_EXPORT:
     299          66 :     return parseExportSection(Ctx);
     300           2 :   case wasm::WASM_SEC_START:
     301           2 :     return parseStartSection(Ctx);
     302          51 :   case wasm::WASM_SEC_ELEM:
     303          51 :     return parseElemSection(Ctx);
     304         311 :   case wasm::WASM_SEC_CODE:
     305         311 :     return parseCodeSection(Ctx);
     306          91 :   case wasm::WASM_SEC_DATA:
     307          91 :     return parseDataSection(Ctx);
     308           0 :   default:
     309             :     return make_error<GenericBinaryError>("Bad section type",
     310             :                                           object_error::parse_failed);
     311             :   }
     312             : }
     313             : 
     314          74 : Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
     315             :   llvm::DenseSet<uint64_t> Seen;
     316         222 :   if (Functions.size() != FunctionTypes.size()) {
     317             :     return make_error<GenericBinaryError>("Names must come after code section",
     318             :                                           object_error::parse_failed);
     319             :   }
     320             : 
     321         147 :   while (Ctx.Ptr < Ctx.End) {
     322             :     uint8_t Type = readUint8(Ctx);
     323          74 :     uint32_t Size = readVaruint32(Ctx);
     324          74 :     const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
     325          74 :     switch (Type) {
     326          74 :     case wasm::WASM_NAMES_FUNCTION: {
     327          74 :       uint32_t Count = readVaruint32(Ctx);
     328         510 :       while (Count--) {
     329         437 :         uint32_t Index = readVaruint32(Ctx);
     330         437 :         if (!Seen.insert(Index).second)
     331             :           return make_error<GenericBinaryError>("Function named more than once",
     332             :                                                 object_error::parse_failed);
     333         436 :         StringRef Name = readString(Ctx);
     334         436 :         if (!isValidFunctionIndex(Index) || Name.empty())
     335             :           return make_error<GenericBinaryError>("Invalid name entry",
     336             :                                                 object_error::parse_failed);
     337         436 :         DebugNames.push_back(wasm::WasmFunctionName{Index, Name});
     338         436 :         if (isDefinedFunctionIndex(Index))
     339         418 :           getDefinedFunction(Index).DebugName = Name;
     340             :       }
     341             :       break;
     342             :     }
     343             :     // Ignore local names for now
     344           0 :     case wasm::WASM_NAMES_LOCAL:
     345             :     default:
     346           0 :       Ctx.Ptr += Size;
     347           0 :       break;
     348             :     }
     349          73 :     if (Ctx.Ptr != SubSectionEnd)
     350             :       return make_error<GenericBinaryError>(
     351             :           "Name sub-section ended prematurely", object_error::parse_failed);
     352             :   }
     353             : 
     354          73 :   if (Ctx.Ptr != Ctx.End)
     355             :     return make_error<GenericBinaryError>("Name section ended prematurely",
     356             :                                           object_error::parse_failed);
     357             :   return Error::success();
     358             : }
     359             : 
     360         275 : Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
     361         275 :   HasLinkingSection = true;
     362         825 :   if (Functions.size() != FunctionTypes.size()) {
     363             :     return make_error<GenericBinaryError>(
     364             :         "Linking data must come after code section",
     365             :         object_error::parse_failed);
     366             :   }
     367             : 
     368         275 :   LinkingData.Version = readVaruint32(Ctx);
     369         275 :   if (LinkingData.Version != wasm::WasmMetadataVersion) {
     370             :     return make_error<GenericBinaryError>(
     371           1 :         "Unexpected metadata version: " + Twine(LinkingData.Version) +
     372           1 :             " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
     373             :         object_error::parse_failed);
     374             :   }
     375             : 
     376         274 :   const uint8_t *OrigEnd = Ctx.End;
     377         635 :   while (Ctx.Ptr < OrigEnd) {
     378         362 :     Ctx.End = OrigEnd;
     379             :     uint8_t Type = readUint8(Ctx);
     380         362 :     uint32_t Size = readVaruint32(Ctx);
     381             :     LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
     382             :                       << "\n");
     383         362 :     Ctx.End = Ctx.Ptr + Size;
     384         362 :     switch (Type) {
     385         263 :     case wasm::WASM_SYMBOL_TABLE:
     386         526 :       if (Error Err = parseLinkingSectionSymtab(Ctx))
     387         263 :         return Err;
     388             :       break;
     389          74 :     case wasm::WASM_SEGMENT_INFO: {
     390          74 :       uint32_t Count = readVaruint32(Ctx);
     391         148 :       if (Count > DataSegments.size())
     392             :         return make_error<GenericBinaryError>("Too many segment names",
     393             :                                               object_error::parse_failed);
     394         235 :       for (uint32_t i = 0; i < Count; i++) {
     395         322 :         DataSegments[i].Data.Name = readString(Ctx);
     396         322 :         DataSegments[i].Data.Alignment = readVaruint32(Ctx);
     397         322 :         DataSegments[i].Data.Flags = readVaruint32(Ctx);
     398             :       }
     399             :       break;
     400             :     }
     401           7 :     case wasm::WASM_INIT_FUNCS: {
     402           7 :       uint32_t Count = readVaruint32(Ctx);
     403           7 :       LinkingData.InitFunctions.reserve(Count);
     404          51 :       for (uint32_t i = 0; i < Count; i++) {
     405             :         wasm::WasmInitFunc Init;
     406          44 :         Init.Priority = readVaruint32(Ctx);
     407          44 :         Init.Symbol = readVaruint32(Ctx);
     408          44 :         if (!isValidFunctionSymbol(Init.Symbol))
     409           0 :           return make_error<GenericBinaryError>("Invalid function symbol: " +
     410           0 :                                                     Twine(Init.Symbol),
     411             :                                                 object_error::parse_failed);
     412          44 :         LinkingData.InitFunctions.emplace_back(Init);
     413             :       }
     414             :       break;
     415             :     }
     416           5 :     case wasm::WASM_COMDAT_INFO:
     417          10 :       if (Error Err = parseLinkingSectionComdat(Ctx))
     418           5 :         return Err;
     419             :       break;
     420          13 :     default:
     421          13 :       Ctx.Ptr += Size;
     422          13 :       break;
     423             :     }
     424         361 :     if (Ctx.Ptr != Ctx.End)
     425             :       return make_error<GenericBinaryError>(
     426             :           "Linking sub-section ended prematurely", object_error::parse_failed);
     427             :   }
     428         273 :   if (Ctx.Ptr != OrigEnd)
     429             :     return make_error<GenericBinaryError>("Linking section ended prematurely",
     430             :                                           object_error::parse_failed);
     431             :   return Error::success();
     432             : }
     433             : 
     434         263 : Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
     435         263 :   uint32_t Count = readVaruint32(Ctx);
     436         263 :   LinkingData.SymbolTable.reserve(Count);
     437         263 :   Symbols.reserve(Count);
     438             :   StringSet<> SymbolNames;
     439             : 
     440             :   std::vector<wasm::WasmImport *> ImportedGlobals;
     441             :   std::vector<wasm::WasmImport *> ImportedFunctions;
     442         526 :   ImportedGlobals.reserve(Imports.size());
     443         526 :   ImportedFunctions.reserve(Imports.size());
     444         903 :   for (auto &I : Imports) {
     445         640 :     if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
     446         144 :       ImportedFunctions.emplace_back(&I);
     447         496 :     else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
     448          20 :       ImportedGlobals.emplace_back(&I);
     449             :   }
     450             : 
     451        1362 :   while (Count--) {
     452             :     wasm::WasmSymbolInfo Info;
     453        1100 :     const wasm::WasmSignature *FunctionType = nullptr;
     454        1100 :     const wasm::WasmGlobalType *GlobalType = nullptr;
     455             : 
     456        1100 :     Info.Kind = readUint8(Ctx);
     457        1100 :     Info.Flags = readVaruint32(Ctx);
     458        1100 :     bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
     459             : 
     460        1100 :     switch (Info.Kind) {
     461         863 :     case wasm::WASM_SYMBOL_TYPE_FUNCTION:
     462         863 :       Info.ElementIndex = readVaruint32(Ctx);
     463        1726 :       if (!isValidFunctionIndex(Info.ElementIndex) ||
     464         863 :           IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
     465             :         return make_error<GenericBinaryError>("invalid function symbol index",
     466             :                                               object_error::parse_failed);
     467         863 :       if (IsDefined) {
     468         719 :         Info.Name = readString(Ctx);
     469         719 :         unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
     470        1438 :         FunctionType = &Signatures[FunctionTypes[FuncIndex]];
     471         719 :         wasm::WasmFunction &Function = Functions[FuncIndex];
     472         719 :         if (Function.SymbolName.empty())
     473         712 :           Function.SymbolName = Info.Name;
     474             :       } else {
     475         144 :         wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
     476         144 :         FunctionType = &Signatures[Import.SigIndex];
     477         144 :         Info.Name = Import.Field;
     478         144 :         Info.Module = Import.Module;
     479             :       }
     480             :       break;
     481             : 
     482          27 :     case wasm::WASM_SYMBOL_TYPE_GLOBAL:
     483          27 :       Info.ElementIndex = readVaruint32(Ctx);
     484          54 :       if (!isValidGlobalIndex(Info.ElementIndex) ||
     485          27 :           IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
     486             :         return make_error<GenericBinaryError>("invalid global symbol index",
     487             :                                               object_error::parse_failed);
     488          27 :       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
     489             :                             wasm::WASM_SYMBOL_BINDING_WEAK)
     490             :         return make_error<GenericBinaryError>("undefined weak global symbol",
     491             :                                               object_error::parse_failed);
     492          26 :       if (IsDefined) {
     493           7 :         Info.Name = readString(Ctx);
     494           7 :         unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
     495           7 :         wasm::WasmGlobal &Global = Globals[GlobalIndex];
     496           7 :         GlobalType = &Global.Type;
     497           7 :         if (Global.SymbolName.empty())
     498           7 :           Global.SymbolName = Info.Name;
     499             :       } else {
     500          19 :         wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
     501          19 :         Info.Name = Import.Field;
     502          19 :         GlobalType = &Import.Global;
     503             :       }
     504             :       break;
     505             : 
     506         188 :     case wasm::WASM_SYMBOL_TYPE_DATA:
     507         188 :       Info.Name = readString(Ctx);
     508         188 :       if (IsDefined) {
     509         166 :         uint32_t Index = readVaruint32(Ctx);
     510         332 :         if (Index >= DataSegments.size())
     511             :           return make_error<GenericBinaryError>("invalid data symbol index",
     512             :                                                 object_error::parse_failed);
     513         166 :         uint32_t Offset = readVaruint32(Ctx);
     514         166 :         uint32_t Size = readVaruint32(Ctx);
     515         332 :         if (Offset + Size > DataSegments[Index].Data.Content.size())
     516             :           return make_error<GenericBinaryError>("invalid data symbol offset",
     517             :                                                 object_error::parse_failed);
     518         166 :         Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
     519             :       }
     520             :       break;
     521             : 
     522          22 :     case wasm::WASM_SYMBOL_TYPE_SECTION: {
     523          22 :       if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
     524             :           wasm::WASM_SYMBOL_BINDING_LOCAL)
     525             :         return make_error<GenericBinaryError>(
     526             :             "Section symbols must have local binding",
     527             :             object_error::parse_failed);
     528          22 :       Info.ElementIndex = readVaruint32(Ctx);
     529             :       // Use somewhat unique section name as symbol name.
     530          22 :       StringRef SectionName = Sections[Info.ElementIndex].Name;
     531          22 :       Info.Name = SectionName;
     532             :       break;
     533             :     }
     534             : 
     535           0 :     default:
     536             :       return make_error<GenericBinaryError>("Invalid symbol type",
     537             :                                             object_error::parse_failed);
     538             :     }
     539             : 
     540        1099 :     if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
     541        1099 :             wasm::WASM_SYMBOL_BINDING_LOCAL &&
     542         978 :         !SymbolNames.insert(Info.Name).second)
     543           0 :       return make_error<GenericBinaryError>("Duplicate symbol name " +
     544           0 :                                                 Twine(Info.Name),
     545             :                                             object_error::parse_failed);
     546        1099 :     LinkingData.SymbolTable.emplace_back(Info);
     547        1099 :     Symbols.emplace_back(LinkingData.SymbolTable.back(), FunctionType,
     548             :                          GlobalType);
     549             :     LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
     550             :   }
     551             : 
     552             :   return Error::success();
     553             : }
     554             : 
     555           5 : Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
     556           5 :   uint32_t ComdatCount = readVaruint32(Ctx);
     557             :   StringSet<> ComdatSet;
     558          11 :   for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
     559           6 :     StringRef Name = readString(Ctx);
     560          12 :     if (Name.empty() || !ComdatSet.insert(Name).second)
     561           0 :       return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " +
     562           0 :                                                 Twine(Name),
     563             :                                             object_error::parse_failed);
     564           6 :     LinkingData.Comdats.emplace_back(Name);
     565           6 :     uint32_t Flags = readVaruint32(Ctx);
     566           6 :     if (Flags != 0)
     567             :       return make_error<GenericBinaryError>("Unsupported COMDAT flags",
     568             :                                             object_error::parse_failed);
     569             : 
     570           6 :     uint32_t EntryCount = readVaruint32(Ctx);
     571          17 :     while (EntryCount--) {
     572          11 :       unsigned Kind = readVaruint32(Ctx);
     573          11 :       unsigned Index = readVaruint32(Ctx);
     574          11 :       switch (Kind) {
     575           0 :       default:
     576             :         return make_error<GenericBinaryError>("Invalid COMDAT entry type",
     577             :                                               object_error::parse_failed);
     578           5 :       case wasm::WASM_COMDAT_DATA:
     579          10 :         if (Index >= DataSegments.size())
     580             :           return make_error<GenericBinaryError>(
     581             :               "COMDAT data index out of range", object_error::parse_failed);
     582           5 :         if (DataSegments[Index].Data.Comdat != UINT32_MAX)
     583             :           return make_error<GenericBinaryError>("Data segment in two COMDATs",
     584             :                                                 object_error::parse_failed);
     585           5 :         DataSegments[Index].Data.Comdat = ComdatIndex;
     586           5 :         break;
     587           6 :       case wasm::WASM_COMDAT_FUNCTION:
     588           6 :         if (!isDefinedFunctionIndex(Index))
     589             :           return make_error<GenericBinaryError>(
     590             :               "COMDAT function index out of range", object_error::parse_failed);
     591           6 :         if (getDefinedFunction(Index).Comdat != UINT32_MAX)
     592             :           return make_error<GenericBinaryError>("Function in two COMDATs",
     593             :                                                 object_error::parse_failed);
     594           6 :         getDefinedFunction(Index).Comdat = ComdatIndex;
     595           6 :         break;
     596             :       }
     597             :     }
     598             :   }
     599             :   return Error::success();
     600             : }
     601             : 
     602         175 : Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
     603         175 :   uint32_t SectionIndex = readVaruint32(Ctx);
     604         350 :   if (SectionIndex >= Sections.size())
     605             :     return make_error<GenericBinaryError>("Invalid section index",
     606             :                                           object_error::parse_failed);
     607             :   WasmSection &Section = Sections[SectionIndex];
     608         175 :   uint32_t RelocCount = readVaruint32(Ctx);
     609         175 :   uint32_t EndOffset = Section.Content.size();
     610             :   uint32_t PreviousOffset = 0;
     611         978 :   while (RelocCount--) {
     612         803 :     wasm::WasmRelocation Reloc = {};
     613         803 :     Reloc.Type = readVaruint32(Ctx);
     614         803 :     Reloc.Offset = readVaruint32(Ctx);
     615         803 :     if (Reloc.Offset < PreviousOffset)
     616             :       return make_error<GenericBinaryError>("Relocations not in offset order",
     617             :                                             object_error::parse_failed);
     618             :     PreviousOffset = Reloc.Offset;
     619         803 :     Reloc.Index = readVaruint32(Ctx);
     620         803 :     switch (Reloc.Type) {
     621         288 :     case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
     622             :     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
     623             :     case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
     624         288 :       if (!isValidFunctionSymbol(Reloc.Index))
     625             :         return make_error<GenericBinaryError>("Bad relocation function index",
     626             :                                               object_error::parse_failed);
     627             :       break;
     628          17 :     case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
     629          34 :       if (Reloc.Index >= Signatures.size())
     630             :         return make_error<GenericBinaryError>("Bad relocation type index",
     631             :                                               object_error::parse_failed);
     632             :       break;
     633          40 :     case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
     634          40 :       if (!isValidGlobalSymbol(Reloc.Index))
     635             :         return make_error<GenericBinaryError>("Bad relocation global index",
     636             :                                               object_error::parse_failed);
     637             :       break;
     638         375 :     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
     639             :     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
     640             :     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
     641         375 :       if (!isValidDataSymbol(Reloc.Index))
     642             :         return make_error<GenericBinaryError>("Bad relocation data index",
     643             :                                               object_error::parse_failed);
     644         375 :       Reloc.Addend = readVarint32(Ctx);
     645         375 :       break;
     646          25 :     case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
     647          25 :       if (!isValidFunctionSymbol(Reloc.Index))
     648             :         return make_error<GenericBinaryError>("Bad relocation function index",
     649             :                                               object_error::parse_failed);
     650          25 :       Reloc.Addend = readVarint32(Ctx);
     651          25 :       break;
     652          58 :     case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
     653          58 :       if (!isValidSectionSymbol(Reloc.Index))
     654             :         return make_error<GenericBinaryError>("Bad relocation section index",
     655             :                                               object_error::parse_failed);
     656          58 :       Reloc.Addend = readVarint32(Ctx);
     657          58 :       break;
     658           0 :     default:
     659           0 :       return make_error<GenericBinaryError>("Bad relocation type: " +
     660           0 :                                                 Twine(Reloc.Type),
     661             :                                             object_error::parse_failed);
     662             :     }
     663             : 
     664             :     // Relocations must fit inside the section, and must appear in order.  They
     665             :     // also shouldn't overlap a function/element boundary, but we don't bother
     666             :     // to check that.
     667             :     uint64_t Size = 5;
     668         803 :     if (Reloc.Type == wasm::R_WEBASSEMBLY_TABLE_INDEX_I32 ||
     669         745 :         Reloc.Type == wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32 ||
     670         687 :         Reloc.Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32 ||
     671             :         Reloc.Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32)
     672             :       Size = 4;
     673         803 :     if (Reloc.Offset + Size > EndOffset)
     674             :       return make_error<GenericBinaryError>("Bad relocation offset",
     675             :                                             object_error::parse_failed);
     676             : 
     677         803 :     Section.Relocations.push_back(Reloc);
     678             :   }
     679         175 :   if (Ctx.Ptr != Ctx.End)
     680             :     return make_error<GenericBinaryError>("Reloc section ended prematurely",
     681             :                                           object_error::parse_failed);
     682             :   return Error::success();
     683             : }
     684             : 
     685         585 : Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
     686             :   if (Sec.Name == "name") {
     687         148 :     if (Error Err = parseNameSection(Ctx))
     688             :       return Err;
     689             :   } else if (Sec.Name == "linking") {
     690         550 :     if (Error Err = parseLinkingSection(Ctx))
     691             :       return Err;
     692             :   } else if (Sec.Name.startswith("reloc.")) {
     693         350 :     if (Error Err = parseRelocSection(Sec.Name, Ctx))
     694             :       return Err;
     695             :   }
     696             :   return Error::success();
     697             : }
     698             : 
     699         318 : Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
     700         318 :   uint32_t Count = readVaruint32(Ctx);
     701         318 :   Signatures.reserve(Count);
     702         823 :   while (Count--) {
     703         505 :     wasm::WasmSignature Sig;
     704         505 :     uint8_t Form = readUint8(Ctx);
     705         505 :     if (Form != wasm::WASM_TYPE_FUNC) {
     706             :       return make_error<GenericBinaryError>("Invalid signature type",
     707             :                                             object_error::parse_failed);
     708             :     }
     709         505 :     uint32_t ParamCount = readVaruint32(Ctx);
     710         505 :     Sig.Params.reserve(ParamCount);
     711         674 :     while (ParamCount--) {
     712         169 :       uint32_t ParamType = readUint8(Ctx);
     713         169 :       Sig.Params.push_back(wasm::ValType(ParamType));
     714             :     }
     715         505 :     uint32_t ReturnCount = readVaruint32(Ctx);
     716         505 :     if (ReturnCount) {
     717         247 :       if (ReturnCount != 1) {
     718             :         return make_error<GenericBinaryError>(
     719             :             "Multiple return types not supported", object_error::parse_failed);
     720             :       }
     721         247 :       Sig.Returns.push_back(wasm::ValType(readUint8(Ctx)));
     722             :     }
     723             :     Signatures.push_back(std::move(Sig));
     724             :   }
     725         318 :   if (Ctx.Ptr != Ctx.End)
     726             :     return make_error<GenericBinaryError>("Type section ended prematurely",
     727             :                                           object_error::parse_failed);
     728             :   return Error::success();
     729             : }
     730             : 
     731         274 : Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
     732         274 :   uint32_t Count = readVaruint32(Ctx);
     733         274 :   Imports.reserve(Count);
     734         958 :   for (uint32_t i = 0; i < Count; i++) {
     735             :     wasm::WasmImport Im;
     736         684 :     Im.Module = readString(Ctx);
     737         684 :     Im.Field = readString(Ctx);
     738         684 :     Im.Kind = readUint8(Ctx);
     739         684 :     switch (Im.Kind) {
     740         157 :     case wasm::WASM_EXTERNAL_FUNCTION:
     741         157 :       NumImportedFunctions++;
     742         157 :       Im.SigIndex = readVaruint32(Ctx);
     743         157 :       break;
     744          24 :     case wasm::WASM_EXTERNAL_GLOBAL:
     745          24 :       NumImportedGlobals++;
     746          24 :       Im.Global.Type = readUint8(Ctx);
     747          24 :       Im.Global.Mutable = readVaruint1(Ctx);
     748          24 :       break;
     749         252 :     case wasm::WASM_EXTERNAL_MEMORY:
     750         252 :       Im.Memory = readLimits(Ctx);
     751         252 :       break;
     752         251 :     case wasm::WASM_EXTERNAL_TABLE:
     753         251 :       Im.Table = readTable(Ctx);
     754         251 :       if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC)
     755             :         return make_error<GenericBinaryError>("Invalid table element type",
     756             :                                               object_error::parse_failed);
     757             :       break;
     758           0 :     default:
     759             :       return make_error<GenericBinaryError>("Unexpected import kind",
     760             :                                             object_error::parse_failed);
     761             :     }
     762         684 :     Imports.push_back(Im);
     763             :   }
     764         274 :   if (Ctx.Ptr != Ctx.End)
     765             :     return make_error<GenericBinaryError>("Import section ended prematurely",
     766             :                                           object_error::parse_failed);
     767             :   return Error::success();
     768             : }
     769             : 
     770         311 : Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
     771         311 :   uint32_t Count = readVaruint32(Ctx);
     772         311 :   FunctionTypes.reserve(Count);
     773         622 :   uint32_t NumTypes = Signatures.size();
     774        1271 :   while (Count--) {
     775         960 :     uint32_t Type = readVaruint32(Ctx);
     776         960 :     if (Type >= NumTypes)
     777             :       return make_error<GenericBinaryError>("Invalid function type",
     778             :                                             object_error::parse_failed);
     779         960 :     FunctionTypes.push_back(Type);
     780             :   }
     781         311 :   if (Ctx.Ptr != Ctx.End)
     782             :     return make_error<GenericBinaryError>("Function section ended prematurely",
     783             :                                           object_error::parse_failed);
     784             :   return Error::success();
     785             : }
     786             : 
     787          77 : Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
     788          77 :   uint32_t Count = readVaruint32(Ctx);
     789          77 :   Tables.reserve(Count);
     790         154 :   while (Count--) {
     791         154 :     Tables.push_back(readTable(Ctx));
     792          77 :     if (Tables.back().ElemType != wasm::WASM_TYPE_ANYFUNC) {
     793             :       return make_error<GenericBinaryError>("Invalid table element type",
     794             :                                             object_error::parse_failed);
     795             :     }
     796             :   }
     797          77 :   if (Ctx.Ptr != Ctx.End)
     798             :     return make_error<GenericBinaryError>("Table section ended prematurely",
     799             :                                           object_error::parse_failed);
     800             :   return Error::success();
     801             : }
     802             : 
     803          76 : Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
     804          76 :   uint32_t Count = readVaruint32(Ctx);
     805          76 :   Memories.reserve(Count);
     806         153 :   while (Count--) {
     807         154 :     Memories.push_back(readLimits(Ctx));
     808             :   }
     809          76 :   if (Ctx.Ptr != Ctx.End)
     810             :     return make_error<GenericBinaryError>("Memory section ended prematurely",
     811             :                                           object_error::parse_failed);
     812             :   return Error::success();
     813             : }
     814             : 
     815          70 : Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
     816          70 :   GlobalSection = Sections.size();
     817          70 :   uint32_t Count = readVaruint32(Ctx);
     818          70 :   Globals.reserve(Count);
     819         280 :   while (Count--) {
     820             :     wasm::WasmGlobal Global;
     821         210 :     Global.Index = NumImportedGlobals + Globals.size();
     822         210 :     Global.Type.Type = readUint8(Ctx);
     823         210 :     Global.Type.Mutable = readVaruint1(Ctx);
     824         420 :     if (Error Err = readInitExpr(Global.InitExpr, Ctx))
     825             :       return Err;
     826         210 :     Globals.push_back(Global);
     827             :   }
     828          70 :   if (Ctx.Ptr != Ctx.End)
     829             :     return make_error<GenericBinaryError>("Global section ended prematurely",
     830             :                                           object_error::parse_failed);
     831             :   return Error::success();
     832             : }
     833             : 
     834          66 : Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
     835          66 :   uint32_t Count = readVaruint32(Ctx);
     836          66 :   Exports.reserve(Count);
     837         388 :   for (uint32_t i = 0; i < Count; i++) {
     838             :     wasm::WasmExport Ex;
     839         323 :     Ex.Name = readString(Ctx);
     840         323 :     Ex.Kind = readUint8(Ctx);
     841         323 :     Ex.Index = readVaruint32(Ctx);
     842         323 :     switch (Ex.Kind) {
     843         123 :     case wasm::WASM_EXTERNAL_FUNCTION:
     844         123 :       if (!isValidFunctionIndex(Ex.Index))
     845             :         return make_error<GenericBinaryError>("Invalid function export",
     846             :                                               object_error::parse_failed);
     847             :       break;
     848         136 :     case wasm::WASM_EXTERNAL_GLOBAL:
     849         136 :       if (!isValidGlobalIndex(Ex.Index))
     850             :         return make_error<GenericBinaryError>("Invalid global export",
     851             :                                               object_error::parse_failed);
     852             :       break;
     853             :     case wasm::WASM_EXTERNAL_MEMORY:
     854             :     case wasm::WASM_EXTERNAL_TABLE:
     855             :       break;
     856           0 :     default:
     857             :       return make_error<GenericBinaryError>("Unexpected export kind",
     858             :                                             object_error::parse_failed);
     859             :     }
     860         322 :     Exports.push_back(Ex);
     861             :   }
     862          65 :   if (Ctx.Ptr != Ctx.End)
     863             :     return make_error<GenericBinaryError>("Export section ended prematurely",
     864             :                                           object_error::parse_failed);
     865             :   return Error::success();
     866             : }
     867             : 
     868        2567 : bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
     869        5134 :   return Index < NumImportedFunctions + FunctionTypes.size();
     870             : }
     871             : 
     872        1305 : bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
     873        1305 :   return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
     874             : }
     875             : 
     876         170 : bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
     877         340 :   return Index < NumImportedGlobals + Globals.size();
     878             : }
     879             : 
     880          27 : bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
     881          27 :   return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
     882             : }
     883             : 
     884         357 : bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
     885         714 :   return Index < Symbols.size() && Symbols[Index].isTypeFunction();
     886             : }
     887             : 
     888          40 : bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
     889          80 :   return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
     890             : }
     891             : 
     892         375 : bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
     893         750 :   return Index < Symbols.size() && Symbols[Index].isTypeData();
     894             : }
     895             : 
     896          58 : bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
     897         116 :   return Index < Symbols.size() && Symbols[Index].isTypeSection();
     898             : }
     899             : 
     900         430 : wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
     901             :   assert(isDefinedFunctionIndex(Index));
     902         860 :   return Functions[Index - NumImportedFunctions];
     903             : }
     904             : 
     905           0 : wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
     906             :   assert(isDefinedGlobalIndex(Index));
     907           0 :   return Globals[Index - NumImportedGlobals];
     908             : }
     909             : 
     910           2 : Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
     911           2 :   StartFunction = readVaruint32(Ctx);
     912           2 :   if (!isValidFunctionIndex(StartFunction))
     913             :     return make_error<GenericBinaryError>("Invalid start function",
     914             :                                           object_error::parse_failed);
     915             :   return Error::success();
     916             : }
     917             : 
     918         311 : Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
     919         311 :   CodeSection = Sections.size();
     920         311 :   uint32_t FunctionCount = readVaruint32(Ctx);
     921         622 :   if (FunctionCount != FunctionTypes.size()) {
     922             :     return make_error<GenericBinaryError>("Invalid function count",
     923             :                                           object_error::parse_failed);
     924             :   }
     925             : 
     926        1271 :   while (FunctionCount--) {
     927             :     wasm::WasmFunction Function;
     928         960 :     const uint8_t *FunctionStart = Ctx.Ptr;
     929         960 :     uint32_t Size = readVaruint32(Ctx);
     930         960 :     const uint8_t *FunctionEnd = Ctx.Ptr + Size;
     931             : 
     932         960 :     Function.CodeOffset = Ctx.Ptr - FunctionStart;
     933         960 :     Function.Index = NumImportedFunctions + Functions.size();
     934         960 :     Function.CodeSectionOffset = FunctionStart - Ctx.Start;
     935         960 :     Function.Size = FunctionEnd - FunctionStart;
     936             : 
     937         960 :     uint32_t NumLocalDecls = readVaruint32(Ctx);
     938         960 :     Function.Locals.reserve(NumLocalDecls);
     939         984 :     while (NumLocalDecls--) {
     940             :       wasm::WasmLocalDecl Decl;
     941          24 :       Decl.Count = readVaruint32(Ctx);
     942          24 :       Decl.Type = readUint8(Ctx);
     943          24 :       Function.Locals.push_back(Decl);
     944             :     }
     945             : 
     946         960 :     uint32_t BodySize = FunctionEnd - Ctx.Ptr;
     947         960 :     Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
     948             :     // This will be set later when reading in the linking metadata section.
     949         960 :     Function.Comdat = UINT32_MAX;
     950         960 :     Ctx.Ptr += BodySize;
     951             :     assert(Ctx.Ptr == FunctionEnd);
     952         960 :     Functions.push_back(Function);
     953             :   }
     954         311 :   if (Ctx.Ptr != Ctx.End)
     955             :     return make_error<GenericBinaryError>("Code section ended prematurely",
     956             :                                           object_error::parse_failed);
     957             :   return Error::success();
     958             : }
     959             : 
     960          51 : Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
     961          51 :   uint32_t Count = readVaruint32(Ctx);
     962          51 :   ElemSegments.reserve(Count);
     963         102 :   while (Count--) {
     964             :     wasm::WasmElemSegment Segment;
     965          51 :     Segment.TableIndex = readVaruint32(Ctx);
     966          51 :     if (Segment.TableIndex != 0) {
     967             :       return make_error<GenericBinaryError>("Invalid TableIndex",
     968             :                                             object_error::parse_failed);
     969             :     }
     970         102 :     if (Error Err = readInitExpr(Segment.Offset, Ctx))
     971             :       return Err;
     972          51 :     uint32_t NumElems = readVaruint32(Ctx);
     973         154 :     while (NumElems--) {
     974         103 :       Segment.Functions.push_back(readVaruint32(Ctx));
     975             :     }
     976          51 :     ElemSegments.push_back(Segment);
     977             :   }
     978          51 :   if (Ctx.Ptr != Ctx.End)
     979             :     return make_error<GenericBinaryError>("Elem section ended prematurely",
     980             :                                           object_error::parse_failed);
     981             :   return Error::success();
     982             : }
     983             : 
     984          91 : Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
     985          91 :   DataSection = Sections.size();
     986          91 :   uint32_t Count = readVaruint32(Ctx);
     987          91 :   DataSegments.reserve(Count);
     988         279 :   while (Count--) {
     989             :     WasmSegment Segment;
     990         188 :     Segment.Data.MemoryIndex = readVaruint32(Ctx);
     991         376 :     if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
     992             :       return Err;
     993         188 :     uint32_t Size = readVaruint32(Ctx);
     994         188 :     if (Size > (size_t)(Ctx.End - Ctx.Ptr))
     995             :       return make_error<GenericBinaryError>("Invalid segment size",
     996             :                                             object_error::parse_failed);
     997         188 :     Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
     998             :     // The rest of these Data fields are set later, when reading in the linking
     999             :     // metadata section.
    1000         188 :     Segment.Data.Alignment = 0;
    1001         188 :     Segment.Data.Flags = 0;
    1002         188 :     Segment.Data.Comdat = UINT32_MAX;
    1003         188 :     Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
    1004         188 :     Ctx.Ptr += Size;
    1005         188 :     DataSegments.push_back(Segment);
    1006             :   }
    1007          91 :   if (Ctx.Ptr != Ctx.End)
    1008             :     return make_error<GenericBinaryError>("Data section ended prematurely",
    1009             :                                           object_error::parse_failed);
    1010             :   return Error::success();
    1011             : }
    1012             : 
    1013         360 : const uint8_t *WasmObjectFile::getPtr(size_t Offset) const {
    1014         360 :   return reinterpret_cast<const uint8_t *>(getData().data() + Offset);
    1015             : }
    1016             : 
    1017         106 : const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
    1018         106 :   return Header;
    1019             : }
    1020             : 
    1021         718 : void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }
    1022             : 
    1023         196 : uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
    1024             :   uint32_t Result = SymbolRef::SF_None;
    1025         196 :   const WasmSymbol &Sym = getWasmSymbol(Symb);
    1026             : 
    1027             :   LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
    1028         196 :   if (Sym.isBindingWeak())
    1029             :     Result |= SymbolRef::SF_Weak;
    1030         196 :   if (!Sym.isBindingLocal())
    1031         186 :     Result |= SymbolRef::SF_Global;
    1032         196 :   if (Sym.isHidden())
    1033          23 :     Result |= SymbolRef::SF_Hidden;
    1034         196 :   if (!Sym.isDefined())
    1035          40 :     Result |= SymbolRef::SF_Undefined;
    1036         196 :   if (Sym.isTypeFunction())
    1037         139 :     Result |= SymbolRef::SF_Executable;
    1038         196 :   return Result;
    1039             : }
    1040             : 
    1041         220 : basic_symbol_iterator WasmObjectFile::symbol_begin() const {
    1042             :   DataRefImpl Ref;
    1043             :   Ref.d.a = 0;
    1044         660 :   return BasicSymbolRef(Ref, this);
    1045             : }
    1046             : 
    1047         278 : basic_symbol_iterator WasmObjectFile::symbol_end() const {
    1048             :   DataRefImpl Ref;
    1049         556 :   Ref.d.a = Symbols.size();
    1050         834 :   return BasicSymbolRef(Ref, this);
    1051             : }
    1052             : 
    1053        1029 : const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
    1054        2058 :   return Symbols[Symb.d.a];
    1055             : }
    1056             : 
    1057           0 : const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
    1058           0 :   return getWasmSymbol(Symb.getRawDataRefImpl());
    1059             : }
    1060             : 
    1061         101 : Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
    1062         101 :   return getWasmSymbol(Symb).Info.Name;
    1063             : }
    1064             : 
    1065          55 : Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
    1066          55 :   return getSymbolValue(Symb);
    1067             : }
    1068             : 
    1069          45 : uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
    1070          45 :   switch (Sym.Info.Kind) {
    1071          30 :   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
    1072             :   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
    1073          30 :     return Sym.Info.ElementIndex;
    1074          12 :   case wasm::WASM_SYMBOL_TYPE_DATA: {
    1075             :     // The value of a data symbol is the segment offset, plus the symbol
    1076             :     // offset within the segment.
    1077          12 :     uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
    1078          12 :     const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
    1079             :     assert(Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST);
    1080          12 :     return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
    1081             :   }
    1082             :   case wasm::WASM_SYMBOL_TYPE_SECTION:
    1083             :     return 0;
    1084             :   }
    1085           0 :   llvm_unreachable("invalid symbol type");
    1086             : }
    1087             : 
    1088          45 : uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
    1089          45 :   return getWasmSymbolValue(getWasmSymbol(Symb));
    1090             : }
    1091             : 
    1092           0 : uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
    1093           0 :   llvm_unreachable("not yet implemented");
    1094             :   return 0;
    1095             : }
    1096             : 
    1097           0 : uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
    1098           0 :   llvm_unreachable("not yet implemented");
    1099             :   return 0;
    1100             : }
    1101             : 
    1102             : Expected<SymbolRef::Type>
    1103          15 : WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
    1104          15 :   const WasmSymbol &Sym = getWasmSymbol(Symb);
    1105             : 
    1106          15 :   switch (Sym.Info.Kind) {
    1107           9 :   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
    1108             :     return SymbolRef::ST_Function;
    1109           0 :   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
    1110             :     return SymbolRef::ST_Other;
    1111           6 :   case wasm::WASM_SYMBOL_TYPE_DATA:
    1112             :     return SymbolRef::ST_Data;
    1113           0 :   case wasm::WASM_SYMBOL_TYPE_SECTION:
    1114             :     return SymbolRef::ST_Debug;
    1115             :   }
    1116             : 
    1117           0 :   llvm_unreachable("Unknown WasmSymbol::SymbolType");
    1118             :   return SymbolRef::ST_Other;
    1119             : }
    1120             : 
    1121             : Expected<section_iterator>
    1122          22 : WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
    1123          22 :   const WasmSymbol &Sym = getWasmSymbol(Symb);
    1124          44 :   if (Sym.isUndefined())
    1125           2 :     return section_end();
    1126             : 
    1127             :   DataRefImpl Ref;
    1128          20 :   switch (Sym.Info.Kind) {
    1129           9 :   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
    1130           9 :     Ref.d.a = CodeSection;
    1131           9 :     break;
    1132           0 :   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
    1133           0 :     Ref.d.a = GlobalSection;
    1134           0 :     break;
    1135           8 :   case wasm::WASM_SYMBOL_TYPE_DATA:
    1136           8 :     Ref.d.a = DataSection;
    1137           8 :     break;
    1138           3 :   case wasm::WASM_SYMBOL_TYPE_SECTION: {
    1139           3 :     Ref.d.a = Sym.Info.ElementIndex;
    1140           3 :     break;
    1141             :   }
    1142           0 :   default:
    1143           0 :     llvm_unreachable("Unknown WasmSymbol::SymbolType");
    1144             :   }
    1145          80 :   return section_iterator(SectionRef(Ref, this));
    1146             : }
    1147             : 
    1148        2014 : void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
    1149             : 
    1150         232 : std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
    1151             :                                                StringRef &Res) const {
    1152         232 :   const WasmSection &S = Sections[Sec.d.a];
    1153             : #define ECase(X)                                                               \
    1154             :   case wasm::WASM_SEC_##X:                                                     \
    1155             :     Res = #X;                                                                  \
    1156             :     break
    1157         232 :   switch (S.Type) {
    1158          16 :     ECase(TYPE);
    1159          10 :     ECase(IMPORT);
    1160          15 :     ECase(FUNCTION);
    1161           6 :     ECase(TABLE);
    1162           6 :     ECase(MEMORY);
    1163           6 :     ECase(GLOBAL);
    1164           6 :     ECase(EXPORT);
    1165           0 :     ECase(START);
    1166           5 :     ECase(ELEM);
    1167          25 :     ECase(CODE);
    1168          19 :     ECase(DATA);
    1169         118 :   case wasm::WASM_SEC_CUSTOM:
    1170         118 :     Res = S.Name;
    1171         118 :     break;
    1172             :   default:
    1173           0 :     return object_error::invalid_section_index;
    1174             :   }
    1175             : #undef ECase
    1176         232 :   return std::error_code();
    1177             : }
    1178             : 
    1179           8 : uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
    1180             : 
    1181          14 : uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
    1182          14 :   return Sec.d.a;
    1183             : }
    1184             : 
    1185           8 : uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
    1186           8 :   const WasmSection &S = Sections[Sec.d.a];
    1187           8 :   return S.Content.size();
    1188             : }
    1189             : 
    1190          54 : std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec,
    1191             :                                                    StringRef &Res) const {
    1192          54 :   const WasmSection &S = Sections[Sec.d.a];
    1193             :   // This will never fail since wasm sections can never be empty (user-sections
    1194             :   // must have a name and non-user sections each have a defined structure).
    1195          54 :   Res = StringRef(reinterpret_cast<const char *>(S.Content.data()),
    1196             :                   S.Content.size());
    1197          54 :   return std::error_code();
    1198             : }
    1199             : 
    1200           0 : uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
    1201           0 :   return 1;
    1202             : }
    1203             : 
    1204          52 : bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
    1205          52 :   return false;
    1206             : }
    1207             : 
    1208           7 : bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
    1209           7 :   return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
    1210             : }
    1211             : 
    1212           7 : bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
    1213           7 :   return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
    1214             : }
    1215             : 
    1216          60 : bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
    1217             : 
    1218          52 : bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
    1219             : 
    1220           0 : bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
    1221             : 
    1222          72 : relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
    1223             :   DataRefImpl RelocRef;
    1224          72 :   RelocRef.d.a = Ref.d.a;
    1225             :   RelocRef.d.b = 0;
    1226         216 :   return relocation_iterator(RelocationRef(RelocRef, this));
    1227             : }
    1228             : 
    1229          72 : relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
    1230          72 :   const WasmSection &Sec = getWasmSection(Ref);
    1231             :   DataRefImpl RelocRef;
    1232          72 :   RelocRef.d.a = Ref.d.a;
    1233         144 :   RelocRef.d.b = Sec.Relocations.size();
    1234         216 :   return relocation_iterator(RelocationRef(RelocRef, this));
    1235             : }
    1236             : 
    1237          55 : void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
    1238             : 
    1239          55 : uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
    1240          55 :   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
    1241          55 :   return Rel.Offset;
    1242             : }
    1243             : 
    1244          55 : symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
    1245          55 :   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
    1246          55 :   if (Rel.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB)
    1247           3 :     return symbol_end();
    1248             :   DataRefImpl Sym;
    1249          52 :   Sym.d.a = Rel.Index;
    1250             :   Sym.d.b = 0;
    1251         156 :   return symbol_iterator(SymbolRef(Sym, this));
    1252             : }
    1253             : 
    1254          50 : uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
    1255          50 :   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
    1256          50 :   return Rel.Type;
    1257             : }
    1258             : 
    1259          41 : void WasmObjectFile::getRelocationTypeName(
    1260             :     DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
    1261          41 :   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
    1262             :   StringRef Res = "Unknown";
    1263             : 
    1264             : #define WASM_RELOC(name, value)                                                \
    1265             :   case wasm::name:                                                             \
    1266             :     Res = #name;                                                               \
    1267             :     break;
    1268             : 
    1269          41 :   switch (Rel.Type) {
    1270             : #include "llvm/BinaryFormat/WasmRelocs.def"
    1271             :   }
    1272             : 
    1273             : #undef WASM_RELOC
    1274             : 
    1275          41 :   Result.append(Res.begin(), Res.end());
    1276          41 : }
    1277             : 
    1278         311 : section_iterator WasmObjectFile::section_begin() const {
    1279             :   DataRefImpl Ref;
    1280             :   Ref.d.a = 0;
    1281         933 :   return section_iterator(SectionRef(Ref, this));
    1282             : }
    1283             : 
    1284         409 : section_iterator WasmObjectFile::section_end() const {
    1285             :   DataRefImpl Ref;
    1286         818 :   Ref.d.a = Sections.size();
    1287        1227 :   return section_iterator(SectionRef(Ref, this));
    1288             : }
    1289             : 
    1290          35 : uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
    1291             : 
    1292          26 : StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
    1293             : 
    1294          32 : Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; }
    1295             : 
    1296           0 : SubtargetFeatures WasmObjectFile::getFeatures() const {
    1297           0 :   return SubtargetFeatures();
    1298             : }
    1299             : 
    1300         192 : bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
    1301             : 
    1302        1975 : const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
    1303             :   assert(Ref.d.a < Sections.size());
    1304        3950 :   return Sections[Ref.d.a];
    1305             : }
    1306             : 
    1307             : const WasmSection &
    1308        1889 : WasmObjectFile::getWasmSection(const SectionRef &Section) const {
    1309        1889 :   return getWasmSection(Section.getRawDataRefImpl());
    1310             : }
    1311             : 
    1312             : const wasm::WasmRelocation &
    1313          41 : WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
    1314          41 :   return getWasmRelocation(Ref.getRawDataRefImpl());
    1315             : }
    1316             : 
    1317             : const wasm::WasmRelocation &
    1318         242 : WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
    1319             :   assert(Ref.d.a < Sections.size());
    1320         242 :   const WasmSection &Sec = Sections[Ref.d.a];
    1321             :   assert(Ref.d.b < Sec.Relocations.size());
    1322         484 :   return Sec.Relocations[Ref.d.b];
    1323             : }

Generated by: LCOV version 1.13