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

Generated by: LCOV version 1.13