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

Generated by: LCOV version 1.13