Coverage Report

Created: 2019-05-19 14:56

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/wasm/InputFiles.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- InputFiles.cpp -----------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "InputFiles.h"
10
#include "Config.h"
11
#include "InputChunks.h"
12
#include "InputEvent.h"
13
#include "InputGlobal.h"
14
#include "SymbolTable.h"
15
#include "lld/Common/ErrorHandler.h"
16
#include "lld/Common/Memory.h"
17
#include "llvm/Object/Binary.h"
18
#include "llvm/Object/Wasm.h"
19
#include "llvm/Support/raw_ostream.h"
20
21
#define DEBUG_TYPE "lld"
22
23
using namespace lld;
24
using namespace lld::wasm;
25
26
using namespace llvm;
27
using namespace llvm::object;
28
using namespace llvm::wasm;
29
30
290
Optional<MemoryBufferRef> lld::wasm::readFile(StringRef Path) {
31
290
  log("Loading: " + Path);
32
290
33
290
  auto MBOrErr = MemoryBuffer::getFile(Path);
34
290
  if (auto EC = MBOrErr.getError()) {
35
2
    error("cannot open " + Path + ": " + EC.message());
36
2
    return None;
37
2
  }
38
288
  std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
39
288
  MemoryBufferRef MBRef = MB->getMemBufferRef();
40
288
  make<std::unique_ptr<MemoryBuffer>>(std::move(MB)); // take MB ownership
41
288
42
288
  return MBRef;
43
288
}
44
45
InputFile *lld::wasm::createObjectFile(MemoryBufferRef MB,
46
285
                                       StringRef ArchiveName) {
47
285
  file_magic Magic = identify_magic(MB.getBuffer());
48
285
  if (Magic == file_magic::wasm_object) {
49
240
    std::unique_ptr<Binary> Bin = check(createBinary(MB));
50
240
    auto *Obj = cast<WasmObjectFile>(Bin.get());
51
240
    if (Obj->isSharedObject())
52
1
      return make<SharedFile>(MB);
53
239
    return make<ObjFile>(MB, ArchiveName);
54
239
  }
55
45
56
45
  if (Magic == file_magic::bitcode)
57
45
    return make<BitcodeFile>(MB, ArchiveName);
58
0
59
0
  fatal("unknown file type: " + MB.getBufferIdentifier());
60
0
}
61
62
0
void ObjFile::dumpInfo() const {
63
0
  log("info for: " + toString(this) +
64
0
      "\n              Symbols : " + Twine(Symbols.size()) +
65
0
      "\n     Function Imports : " + Twine(WasmObj->getNumImportedFunctions()) +
66
0
      "\n       Global Imports : " + Twine(WasmObj->getNumImportedGlobals()) +
67
0
      "\n        Event Imports : " + Twine(WasmObj->getNumImportedEvents()));
68
0
}
69
70
// Relocations contain either symbol or type indices.  This function takes a
71
// relocation and returns relocated index (i.e. translates from the input
72
// symbol/type space to the output symbol/type space).
73
206
uint32_t ObjFile::calcNewIndex(const WasmRelocation &Reloc) const {
74
206
  if (Reloc.Type == R_WASM_TYPE_INDEX_LEB) {
75
0
    assert(TypeIsUsed[Reloc.Index]);
76
0
    return TypeMap[Reloc.Index];
77
0
  }
78
206
  return Symbols[Reloc.Index]->getOutputSymbolIndex();
79
206
}
80
81
// Relocations can contain addend for combined sections. This function takes a
82
// relocation and returns updated addend by offset in the output section.
83
151
uint32_t ObjFile::calcNewAddend(const WasmRelocation &Reloc) const {
84
151
  switch (Reloc.Type) {
85
151
  case R_WASM_MEMORY_ADDR_LEB:
86
149
  case R_WASM_MEMORY_ADDR_SLEB:
87
149
  case R_WASM_MEMORY_ADDR_I32:
88
149
  case R_WASM_FUNCTION_OFFSET_I32:
89
149
    return Reloc.Addend;
90
149
  case R_WASM_SECTION_OFFSET_I32:
91
2
    return getSectionSymbol(Reloc.Index)->Section->OutputOffset + Reloc.Addend;
92
149
  default:
93
0
    llvm_unreachable("unexpected relocation type");
94
151
  }
95
151
}
96
97
// Calculate the value we expect to find at the relocation location.
98
// This is used as a sanity check before applying a relocation to a given
99
// location.  It is useful for catching bugs in the compiler and linker.
100
0
uint32_t ObjFile::calcExpectedValue(const WasmRelocation &Reloc) const {
101
0
  switch (Reloc.Type) {
102
0
  case R_WASM_TABLE_INDEX_I32:
103
0
  case R_WASM_TABLE_INDEX_SLEB:
104
0
  case R_WASM_TABLE_INDEX_REL_SLEB: {
105
0
    const WasmSymbol &Sym = WasmObj->syms()[Reloc.Index];
106
0
    return TableEntries[Sym.Info.ElementIndex];
107
0
  }
108
0
  case R_WASM_MEMORY_ADDR_SLEB:
109
0
  case R_WASM_MEMORY_ADDR_I32:
110
0
  case R_WASM_MEMORY_ADDR_LEB:
111
0
  case R_WASM_MEMORY_ADDR_REL_SLEB: {
112
0
    const WasmSymbol &Sym = WasmObj->syms()[Reloc.Index];
113
0
    if (Sym.isUndefined())
114
0
      return 0;
115
0
    const WasmSegment &Segment =
116
0
        WasmObj->dataSegments()[Sym.Info.DataRef.Segment];
117
0
    return Segment.Data.Offset.Value.Int32 + Sym.Info.DataRef.Offset +
118
0
           Reloc.Addend;
119
0
  }
120
0
  case R_WASM_FUNCTION_OFFSET_I32: {
121
0
    const WasmSymbol &Sym = WasmObj->syms()[Reloc.Index];
122
0
    InputFunction *F =
123
0
        Functions[Sym.Info.ElementIndex - WasmObj->getNumImportedFunctions()];
124
0
    return F->getFunctionInputOffset() + F->getFunctionCodeOffset() +
125
0
           Reloc.Addend;
126
0
  }
127
0
  case R_WASM_SECTION_OFFSET_I32:
128
0
    return Reloc.Addend;
129
0
  case R_WASM_TYPE_INDEX_LEB:
130
0
    return Reloc.Index;
131
0
  case R_WASM_FUNCTION_INDEX_LEB:
132
0
  case R_WASM_GLOBAL_INDEX_LEB:
133
0
  case R_WASM_EVENT_INDEX_LEB: {
134
0
    const WasmSymbol &Sym = WasmObj->syms()[Reloc.Index];
135
0
    return Sym.Info.ElementIndex;
136
0
  }
137
0
  default:
138
0
    llvm_unreachable("unknown relocation type");
139
0
  }
140
0
}
141
142
// Translate from the relocation's index into the final linked output value.
143
489
uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const {
144
489
  const Symbol* Sym = nullptr;
145
489
  if (Reloc.Type != R_WASM_TYPE_INDEX_LEB) {
146
474
    Sym = Symbols[Reloc.Index];
147
474
148
474
    // We can end up with relocations against non-live symbols.  For example
149
474
    // in debug sections.
150
474
    if ((isa<FunctionSymbol>(Sym) || 
isa<DataSymbol>(Sym)281
) &&
!Sym->isLive()401
)
151
11
      return 0;
152
463
153
463
    // Special handling for undefined data symbols.  Most relocations against
154
463
    // such symbols cannot be resolved.
155
463
    if (isa<DataSymbol>(Sym) && 
Sym->isUndefined()204
) {
156
12
      if (Sym->isWeak() || 
Config->Relocatable5
)
157
9
        return 0;
158
3
      // R_WASM_MEMORY_ADDR_I32 relocations in PIC code are turned into runtime
159
3
      // fixups in __wasm_apply_relocs
160
3
      if (Config->Pic && Reloc.Type == R_WASM_MEMORY_ADDR_I32)
161
3
        return 0;
162
0
      if (Reloc.Type != R_WASM_GLOBAL_INDEX_LEB) {
163
0
        llvm_unreachable(
164
0
          ("invalid relocation against undefined data symbol: " + toString(*Sym))
165
0
              .c_str());
166
0
      }
167
466
    }
168
463
  }
169
466
170
466
  switch (Reloc.Type) {
171
466
  case R_WASM_TABLE_INDEX_I32:
172
56
  case R_WASM_TABLE_INDEX_SLEB:
173
56
  case R_WASM_TABLE_INDEX_REL_SLEB:
174
56
    if (Config->Pic && 
!getFunctionSymbol(Reloc.Index)->hasTableIndex()6
)
175
1
      return 0;
176
55
    return getFunctionSymbol(Reloc.Index)->getTableIndex();
177
188
  case R_WASM_MEMORY_ADDR_SLEB:
178
188
  case R_WASM_MEMORY_ADDR_I32:
179
188
  case R_WASM_MEMORY_ADDR_LEB:
180
188
  case R_WASM_MEMORY_ADDR_REL_SLEB:
181
188
    return cast<DefinedData>(Sym)->getVirtualAddress() + Reloc.Addend;
182
188
  case R_WASM_TYPE_INDEX_LEB:
183
15
    return TypeMap[Reloc.Index];
184
188
  case R_WASM_FUNCTION_INDEX_LEB:
185
118
    return getFunctionSymbol(Reloc.Index)->getFunctionIndex();
186
188
  case R_WASM_GLOBAL_INDEX_LEB:
187
39
    if (auto GS = dyn_cast<GlobalSymbol>(Sym))
188
34
      return GS->getGlobalIndex();
189
5
    return Sym->getGOTIndex();
190
5
  case R_WASM_EVENT_INDEX_LEB:
191
2
    return getEventSymbol(Reloc.Index)->getEventIndex();
192
11
  case R_WASM_FUNCTION_OFFSET_I32: {
193
11
    auto *F = cast<DefinedFunction>(Sym);
194
11
    return F->Function->OutputOffset + F->Function->getFunctionCodeOffset() +
195
11
           Reloc.Addend;
196
5
  }
197
40
  case R_WASM_SECTION_OFFSET_I32:
198
40
    return getSectionSymbol(Reloc.Index)->Section->OutputOffset + Reloc.Addend;
199
5
  default:
200
0
    llvm_unreachable("unknown relocation type");
201
466
  }
202
466
}
203
204
template <class T>
205
static void setRelocs(const std::vector<T *> &Chunks,
206
562
                      const WasmSection *Section) {
207
562
  if (!Section)
208
291
    return;
209
271
210
271
  ArrayRef<WasmRelocation> Relocs = Section->Relocations;
211
271
  assert(std::is_sorted(Relocs.begin(), Relocs.end(),
212
271
                        [](const WasmRelocation &R1, const WasmRelocation &R2) {
213
271
                          return R1.Offset < R2.Offset;
214
271
                        }));
215
271
  assert(std::is_sorted(
216
271
      Chunks.begin(), Chunks.end(), [](InputChunk *C1, InputChunk *C2) {
217
271
        return C1->getInputSectionOffset() < C2->getInputSectionOffset();
218
271
      }));
219
271
220
271
  auto RelocsNext = Relocs.begin();
221
271
  auto RelocsEnd = Relocs.end();
222
2.84k
  auto RelocLess = [](const WasmRelocation &R, uint32_t Val) {
223
2.84k
    return R.Offset < Val;
224
2.84k
  };
InputFiles.cpp:void setRelocs<lld::wasm::InputSegment>(std::__1::vector<lld::wasm::InputSegment*, std::__1::allocator<lld::wasm::InputSegment*> > const&, llvm::object::WasmSection const*)::'lambda'(llvm::wasm::WasmRelocation const&, unsigned int)::operator()(llvm::wasm::WasmRelocation const&, unsigned int) const
Line
Count
Source
222
168
  auto RelocLess = [](const WasmRelocation &R, uint32_t Val) {
223
168
    return R.Offset < Val;
224
168
  };
InputFiles.cpp:void setRelocs<lld::wasm::InputFunction>(std::__1::vector<lld::wasm::InputFunction*, std::__1::allocator<lld::wasm::InputFunction*> > const&, llvm::object::WasmSection const*)::'lambda'(llvm::wasm::WasmRelocation const&, unsigned int)::operator()(llvm::wasm::WasmRelocation const&, unsigned int) const
Line
Count
Source
222
2.68k
  auto RelocLess = [](const WasmRelocation &R, uint32_t Val) {
223
2.68k
    return R.Offset < Val;
224
2.68k
  };
225
623
  for (InputChunk *C : Chunks) {
226
623
    auto RelocsStart = std::lower_bound(RelocsNext, RelocsEnd,
227
623
                                        C->getInputSectionOffset(), RelocLess);
228
623
    RelocsNext = std::lower_bound(
229
623
        RelocsStart, RelocsEnd, C->getInputSectionOffset() + C->getInputSize(),
230
623
        RelocLess);
231
623
    C->setRelocations(ArrayRef<WasmRelocation>(RelocsStart, RelocsNext));
232
623
  }
233
271
}
InputFiles.cpp:void setRelocs<lld::wasm::InputSegment>(std::__1::vector<lld::wasm::InputSegment*, std::__1::allocator<lld::wasm::InputSegment*> > const&, llvm::object::WasmSection const*)
Line
Count
Source
206
281
                      const WasmSection *Section) {
207
281
  if (!Section)
208
225
    return;
209
56
210
56
  ArrayRef<WasmRelocation> Relocs = Section->Relocations;
211
56
  assert(std::is_sorted(Relocs.begin(), Relocs.end(),
212
56
                        [](const WasmRelocation &R1, const WasmRelocation &R2) {
213
56
                          return R1.Offset < R2.Offset;
214
56
                        }));
215
56
  assert(std::is_sorted(
216
56
      Chunks.begin(), Chunks.end(), [](InputChunk *C1, InputChunk *C2) {
217
56
        return C1->getInputSectionOffset() < C2->getInputSectionOffset();
218
56
      }));
219
56
220
56
  auto RelocsNext = Relocs.begin();
221
56
  auto RelocsEnd = Relocs.end();
222
56
  auto RelocLess = [](const WasmRelocation &R, uint32_t Val) {
223
56
    return R.Offset < Val;
224
56
  };
225
117
  for (InputChunk *C : Chunks) {
226
117
    auto RelocsStart = std::lower_bound(RelocsNext, RelocsEnd,
227
117
                                        C->getInputSectionOffset(), RelocLess);
228
117
    RelocsNext = std::lower_bound(
229
117
        RelocsStart, RelocsEnd, C->getInputSectionOffset() + C->getInputSize(),
230
117
        RelocLess);
231
117
    C->setRelocations(ArrayRef<WasmRelocation>(RelocsStart, RelocsNext));
232
117
  }
233
56
}
InputFiles.cpp:void setRelocs<lld::wasm::InputFunction>(std::__1::vector<lld::wasm::InputFunction*, std::__1::allocator<lld::wasm::InputFunction*> > const&, llvm::object::WasmSection const*)
Line
Count
Source
206
281
                      const WasmSection *Section) {
207
281
  if (!Section)
208
66
    return;
209
215
210
215
  ArrayRef<WasmRelocation> Relocs = Section->Relocations;
211
215
  assert(std::is_sorted(Relocs.begin(), Relocs.end(),
212
215
                        [](const WasmRelocation &R1, const WasmRelocation &R2) {
213
215
                          return R1.Offset < R2.Offset;
214
215
                        }));
215
215
  assert(std::is_sorted(
216
215
      Chunks.begin(), Chunks.end(), [](InputChunk *C1, InputChunk *C2) {
217
215
        return C1->getInputSectionOffset() < C2->getInputSectionOffset();
218
215
      }));
219
215
220
215
  auto RelocsNext = Relocs.begin();
221
215
  auto RelocsEnd = Relocs.end();
222
215
  auto RelocLess = [](const WasmRelocation &R, uint32_t Val) {
223
215
    return R.Offset < Val;
224
215
  };
225
506
  for (InputChunk *C : Chunks) {
226
506
    auto RelocsStart = std::lower_bound(RelocsNext, RelocsEnd,
227
506
                                        C->getInputSectionOffset(), RelocLess);
228
506
    RelocsNext = std::lower_bound(
229
506
        RelocsStart, RelocsEnd, C->getInputSectionOffset() + C->getInputSize(),
230
506
        RelocLess);
231
506
    C->setRelocations(ArrayRef<WasmRelocation>(RelocsStart, RelocsNext));
232
506
  }
233
215
}
234
235
281
void ObjFile::parse(bool IgnoreComdats) {
236
281
  // Parse a memory buffer as a wasm file.
237
281
  LLVM_DEBUG(dbgs() << "Parsing object: " << toString(this) << "\n");
238
281
  std::unique_ptr<Binary> Bin = CHECK(createBinary(MB), toString(this));
239
281
240
281
  auto *Obj = dyn_cast<WasmObjectFile>(Bin.get());
241
281
  if (!Obj)
242
0
    fatal(toString(this) + ": not a wasm file");
243
281
  if (!Obj->isRelocatableObject())
244
0
    fatal(toString(this) + ": not a relocatable wasm file");
245
281
246
281
  Bin.release();
247
281
  WasmObj.reset(Obj);
248
281
249
281
  // Build up a map of function indices to table indices for use when
250
281
  // verifying the existing table index relocations
251
281
  uint32_t TotalFunctions =
252
281
      WasmObj->getNumImportedFunctions() + WasmObj->functions().size();
253
281
  TableEntries.resize(TotalFunctions);
254
281
  for (const WasmElemSegment &Seg : WasmObj->elements()) {
255
37
    if (Seg.Offset.Opcode != WASM_OPCODE_I32_CONST)
256
0
      fatal(toString(this) + ": invalid table elements");
257
37
    uint32_t Offset = Seg.Offset.Value.Int32;
258
98
    for (uint32_t Index = 0; Index < Seg.Functions.size(); 
Index++61
) {
259
61
260
61
      uint32_t FunctionIndex = Seg.Functions[Index];
261
61
      TableEntries[FunctionIndex] = Offset + Index;
262
61
    }
263
37
  }
264
281
265
281
  // Find the code and data sections.  Wasm objects can have at most one code
266
281
  // and one data section.
267
281
  uint32_t SectionIndex = 0;
268
1.53k
  for (const SectionRef &Sec : WasmObj->sections()) {
269
1.53k
    const WasmSection &Section = WasmObj->getWasmSection(Sec);
270
1.53k
    if (Section.Type == WASM_SEC_CODE) {
271
215
      CodeSection = &Section;
272
1.32k
    } else if (Section.Type == WASM_SEC_DATA) {
273
56
      DataSection = &Section;
274
1.26k
    } else if (Section.Type == WASM_SEC_CUSTOM) {
275
506
      CustomSections.emplace_back(make<InputSection>(Section, this));
276
506
      CustomSections.back()->setRelocations(Section.Relocations);
277
506
      CustomSectionsByIndex[SectionIndex] = CustomSections.back();
278
506
    }
279
1.53k
    SectionIndex++;
280
1.53k
  }
281
281
282
281
  TypeMap.resize(getWasmObj()->types().size());
283
281
  TypeIsUsed.resize(getWasmObj()->types().size(), false);
284
281
285
281
  ArrayRef<StringRef> Comdats = WasmObj->linkingData().Comdats;
286
285
  for (unsigned I = 0; I < Comdats.size(); 
++I4
)
287
4
    if (IgnoreComdats)
288
1
      KeptComdats.push_back(true);
289
3
    else
290
3
      KeptComdats.push_back(Symtab->addComdat(Comdats[I]));
291
281
292
281
  // Populate `Segments`.
293
281
  for (const WasmSegment &S : WasmObj->dataSegments())
294
117
    Segments.emplace_back(make<InputSegment>(S, this));
295
281
  setRelocs(Segments, DataSection);
296
281
297
281
  // Populate `Functions`.
298
281
  ArrayRef<WasmFunction> Funcs = WasmObj->functions();
299
281
  ArrayRef<uint32_t> FuncTypes = WasmObj->functionTypes();
300
281
  ArrayRef<WasmSignature> Types = WasmObj->types();
301
281
  Functions.reserve(Funcs.size());
302
281
303
787
  for (size_t I = 0, E = Funcs.size(); I != E; 
++I506
)
304
506
    Functions.emplace_back(
305
506
        make<InputFunction>(Types[FuncTypes[I]], &Funcs[I], this));
306
281
  setRelocs(Functions, CodeSection);
307
281
308
281
  // Populate `Globals`.
309
281
  for (const WasmGlobal &G : WasmObj->globals())
310
4
    Globals.emplace_back(make<InputGlobal>(G, this));
311
281
312
281
  // Populate `Events`.
313
281
  for (const WasmEvent &E : WasmObj->events())
314
2
    Events.emplace_back(make<InputEvent>(Types[E.Type.SigIndex], E, this));
315
281
316
281
  // Populate `Symbols` based on the WasmSymbols in the object.
317
281
  Symbols.reserve(WasmObj->getNumberOfSymbols());
318
783
  for (const SymbolRef &Sym : WasmObj->symbols()) {
319
783
    const WasmSymbol &WasmSym = WasmObj->getWasmSymbol(Sym.getRawDataRefImpl());
320
783
    if (Symbol *Sym = createDefined(WasmSym))
321
649
      Symbols.push_back(Sym);
322
134
    else
323
134
      Symbols.push_back(createUndefined(WasmSym));
324
783
  }
325
281
}
326
327
627
bool ObjFile::isExcludedByComdat(InputChunk *Chunk) const {
328
627
  uint32_t C = Chunk->getComdat();
329
627
  if (C == UINT32_MAX)
330
627
    
return false620
;
331
7
  return !KeptComdats[C];
332
7
}
333
334
222
FunctionSymbol *ObjFile::getFunctionSymbol(uint32_t Index) const {
335
222
  return cast<FunctionSymbol>(Symbols[Index]);
336
222
}
337
338
0
GlobalSymbol *ObjFile::getGlobalSymbol(uint32_t Index) const {
339
0
  return cast<GlobalSymbol>(Symbols[Index]);
340
0
}
341
342
2
EventSymbol *ObjFile::getEventSymbol(uint32_t Index) const {
343
2
  return cast<EventSymbol>(Symbols[Index]);
344
2
}
345
346
42
SectionSymbol *ObjFile::getSectionSymbol(uint32_t Index) const {
347
42
  return cast<SectionSymbol>(Symbols[Index]);
348
42
}
349
350
0
DataSymbol *ObjFile::getDataSymbol(uint32_t Index) const {
351
0
  return cast<DataSymbol>(Symbols[Index]);
352
0
}
353
354
783
Symbol *ObjFile::createDefined(const WasmSymbol &Sym) {
355
783
  if (!Sym.isDefined())
356
132
    return nullptr;
357
651
358
651
  StringRef Name = Sym.Info.Name;
359
651
  uint32_t Flags = Sym.Info.Flags;
360
651
361
651
  switch (Sym.Info.Kind) {
362
651
  case WASM_SYMBOL_TYPE_FUNCTION: {
363
510
    InputFunction *Func =
364
510
        Functions[Sym.Info.ElementIndex - WasmObj->getNumImportedFunctions()];
365
510
    if (isExcludedByComdat(Func)) {
366
1
      Func->Live = false;
367
1
      return nullptr;
368
1
    }
369
509
370
509
    if (Sym.isBindingLocal())
371
44
      return make<DefinedFunction>(Name, Flags, this, Func);
372
465
    return Symtab->addDefinedFunction(Name, Flags, this, Func);
373
465
  }
374
465
  case WASM_SYMBOL_TYPE_DATA: {
375
117
    InputSegment *Seg = Segments[Sym.Info.DataRef.Segment];
376
117
    if (isExcludedByComdat(Seg)) {
377
1
      Seg->Live = false;
378
1
      return nullptr;
379
1
    }
380
116
381
116
    uint32_t Offset = Sym.Info.DataRef.Offset;
382
116
    uint32_t Size = Sym.Info.DataRef.Size;
383
116
384
116
    if (Sym.isBindingLocal())
385
24
      return make<DefinedData>(Name, Flags, this, Seg, Offset, Size);
386
92
    return Symtab->addDefinedData(Name, Flags, this, Seg, Offset, Size);
387
92
  }
388
92
  case WASM_SYMBOL_TYPE_GLOBAL: {
389
4
    InputGlobal *Global =
390
4
        Globals[Sym.Info.ElementIndex - WasmObj->getNumImportedGlobals()];
391
4
    if (Sym.isBindingLocal())
392
0
      return make<DefinedGlobal>(Name, Flags, this, Global);
393
4
    return Symtab->addDefinedGlobal(Name, Flags, this, Global);
394
4
  }
395
18
  case WASM_SYMBOL_TYPE_SECTION: {
396
18
    InputSection *Section = CustomSectionsByIndex[Sym.Info.ElementIndex];
397
18
    assert(Sym.isBindingLocal());
398
18
    return make<SectionSymbol>(Name, Flags, Section, this);
399
4
  }
400
4
  case WASM_SYMBOL_TYPE_EVENT: {
401
2
    InputEvent *Event =
402
2
        Events[Sym.Info.ElementIndex - WasmObj->getNumImportedEvents()];
403
2
    if (Sym.isBindingLocal())
404
0
      return make<DefinedEvent>(Name, Flags, this, Event);
405
2
    return Symtab->addDefinedEvent(Name, Flags, this, Event);
406
2
  }
407
0
  }
408
0
  llvm_unreachable("unknown symbol kind");
409
0
}
410
411
134
Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) {
412
134
  StringRef Name = Sym.Info.Name;
413
134
  uint32_t Flags = Sym.Info.Flags;
414
134
415
134
  switch (Sym.Info.Kind) {
416
134
  case WASM_SYMBOL_TYPE_FUNCTION:
417
96
    return Symtab->addUndefinedFunction(Name, Sym.Info.ImportName,
418
96
                                        Sym.Info.ImportModule, Flags, this,
419
96
                                        Sym.Signature);
420
134
  case WASM_SYMBOL_TYPE_DATA:
421
23
    return Symtab->addUndefinedData(Name, Flags, this);
422
134
  case WASM_SYMBOL_TYPE_GLOBAL:
423
15
    return Symtab->addUndefinedGlobal(Name, Sym.Info.ImportName,
424
15
                                      Sym.Info.ImportModule, Flags, this,
425
15
                                      Sym.GlobalType);
426
134
  case WASM_SYMBOL_TYPE_SECTION:
427
0
    llvm_unreachable("section symbols cannot be undefined");
428
0
  }
429
0
  llvm_unreachable("unknown symbol kind");
430
0
}
431
432
16
void ArchiveFile::parse(bool IgnoreComdats) {
433
16
  // Parse a MemoryBufferRef as an archive file.
434
16
  LLVM_DEBUG(dbgs() << "Parsing library: " << toString(this) << "\n");
435
16
  File = CHECK(Archive::create(MB), toString(this));
436
16
437
16
  // Read the symbol table to construct Lazy symbols.
438
16
  int Count = 0;
439
52
  for (const Archive::Symbol &Sym : File->symbols()) {
440
52
    Symtab->addLazy(this, &Sym);
441
52
    ++Count;
442
52
  }
443
16
  LLVM_DEBUG(dbgs() << "Read " << Count << " symbols\n");
444
16
}
445
446
15
void ArchiveFile::addMember(const Archive::Symbol *Sym) {
447
15
  const Archive::Child &C =
448
15
      CHECK(Sym->getMember(),
449
15
            "could not get the member for symbol " + Sym->getName());
450
15
451
15
  // Don't try to load the same member twice (this can happen when members
452
15
  // mutually reference each other).
453
15
  if (!Seen.insert(C.getChildOffset()).second)
454
0
    return;
455
15
456
15
  LLVM_DEBUG(dbgs() << "loading lazy: " << Sym->getName() << "\n");
457
15
  LLVM_DEBUG(dbgs() << "from archive: " << toString(this) << "\n");
458
15
459
15
  MemoryBufferRef MB =
460
15
      CHECK(C.getMemoryBufferRef(),
461
15
            "could not get the buffer for the member defining symbol " +
462
15
                Sym->getName());
463
15
464
15
  InputFile *Obj = createObjectFile(MB, getName());
465
15
  Symtab->addFile(Obj);
466
15
}
467
468
static uint8_t mapVisibility(GlobalValue::VisibilityTypes GvVisibility) {
469
  switch (GvVisibility) {
470
  case GlobalValue::DefaultVisibility:
471
    return WASM_SYMBOL_VISIBILITY_DEFAULT;
472
  case GlobalValue::HiddenVisibility:
473
  case GlobalValue::ProtectedVisibility:
474
    return WASM_SYMBOL_VISIBILITY_HIDDEN;
475
  }
476
  llvm_unreachable("unknown visibility");
477
}
478
479
static Symbol *createBitcodeSymbol(const std::vector<bool> &KeptComdats,
480
                                   const lto::InputFile::Symbol &ObjSym,
481
63
                                   BitcodeFile &F) {
482
63
  StringRef Name = Saver.save(ObjSym.getName());
483
63
484
63
  uint32_t Flags = ObjSym.isWeak() ? 
WASM_SYMBOL_BINDING_WEAK5
:
058
;
485
63
  Flags |= mapVisibility(ObjSym.getVisibility());
486
63
487
63
  int C = ObjSym.getComdatIndex();
488
63
  bool ExcludedByComdat = C != -1 && 
!KeptComdats[C]2
;
489
63
490
63
  if (ObjSym.isUndefined() || 
ExcludedByComdat49
) {
491
15
    if (ObjSym.isExecutable())
492
14
      return Symtab->addUndefinedFunction(Name, Name, DefaultModule, Flags, &F,
493
14
                                          nullptr);
494
1
    return Symtab->addUndefinedData(Name, Flags, &F);
495
1
  }
496
48
497
48
  if (ObjSym.isExecutable())
498
46
    return Symtab->addDefinedFunction(Name, Flags, &F, nullptr);
499
2
  return Symtab->addDefinedData(Name, Flags, &F, nullptr, 0, 0);
500
2
}
501
502
43
void BitcodeFile::parse(bool IgnoreComdats) {
503
43
  Obj = check(lto::InputFile::create(MemoryBufferRef(
504
43
      MB.getBuffer(), Saver.save(ArchiveName + MB.getBufferIdentifier()))));
505
43
  Triple T(Obj->getTargetTriple());
506
43
  if (T.getArch() != Triple::wasm32) {
507
1
    error(toString(MB.getBufferIdentifier()) + ": machine type must be wasm32");
508
1
    return;
509
1
  }
510
42
  std::vector<bool> KeptComdats;
511
42
  for (StringRef S : Obj->getComdatTable())
512
2
    if (IgnoreComdats)
513
0
      KeptComdats.push_back(true);
514
2
    else
515
2
      KeptComdats.push_back(Symtab->addComdat(S));
516
42
517
42
  for (const lto::InputFile::Symbol &ObjSym : Obj->symbols())
518
63
    Symbols.push_back(createBitcodeSymbol(KeptComdats, ObjSym, *this));
519
42
}
520
521
// Returns a string in the format of "foo.o" or "foo.a(bar.o)".
522
336
std::string lld::toString(const wasm::InputFile *File) {
523
336
  if (!File)
524
3
    return "<internal>";
525
333
526
333
  if (File->ArchiveName.empty())
527
307
    return File->getName();
528
26
529
26
  return (File->ArchiveName + "(" + File->getName() + ")").str();
530
26
}