Coverage Report

Created: 2019-07-24 05:18

/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 "lld/Common/Reproduce.h"
18
#include "llvm/Object/Binary.h"
19
#include "llvm/Object/Wasm.h"
20
#include "llvm/Support/TarWriter.h"
21
#include "llvm/Support/raw_ostream.h"
22
23
#define DEBUG_TYPE "lld"
24
25
using namespace lld;
26
using namespace lld::wasm;
27
28
using namespace llvm;
29
using namespace llvm::object;
30
using namespace llvm::wasm;
31
32
std::unique_ptr<llvm::TarWriter> lld::wasm::tar;
33
34
326
Optional<MemoryBufferRef> lld::wasm::readFile(StringRef path) {
35
326
  log("Loading: " + path);
36
326
37
326
  auto mbOrErr = MemoryBuffer::getFile(path);
38
326
  if (auto ec = mbOrErr.getError()) {
39
2
    error("cannot open " + path + ": " + ec.message());
40
2
    return None;
41
2
  }
42
324
  std::unique_ptr<MemoryBuffer> &mb = *mbOrErr;
43
324
  MemoryBufferRef mbref = mb->getMemBufferRef();
44
324
  make<std::unique_ptr<MemoryBuffer>>(std::move(mb)); // take MB ownership
45
324
46
324
  if (tar)
47
1
    tar->append(relativeToRoot(path), mbref.getBuffer());
48
324
  return mbref;
49
324
}
50
51
InputFile *lld::wasm::createObjectFile(MemoryBufferRef mb,
52
319
                                       StringRef archiveName) {
53
319
  file_magic magic = identify_magic(mb.getBuffer());
54
319
  if (magic == file_magic::wasm_object) {
55
273
    std::unique_ptr<Binary> bin =
56
273
        CHECK(createBinary(mb), mb.getBufferIdentifier());
57
273
    auto *obj = cast<WasmObjectFile>(bin.get());
58
273
    if (obj->isSharedObject())
59
1
      return make<SharedFile>(mb);
60
272
    return make<ObjFile>(mb, archiveName);
61
272
  }
62
46
63
46
  if (magic == file_magic::bitcode)
64
46
    return make<BitcodeFile>(mb, archiveName);
65
0
66
0
  fatal("unknown file type: " + mb.getBufferIdentifier());
67
0
}
68
69
0
void ObjFile::dumpInfo() const {
70
0
  log("info for: " + toString(this) +
71
0
      "\n              Symbols : " + Twine(symbols.size()) +
72
0
      "\n     Function Imports : " + Twine(wasmObj->getNumImportedFunctions()) +
73
0
      "\n       Global Imports : " + Twine(wasmObj->getNumImportedGlobals()) +
74
0
      "\n        Event Imports : " + Twine(wasmObj->getNumImportedEvents()));
75
0
}
76
77
// Relocations contain either symbol or type indices.  This function takes a
78
// relocation and returns relocated index (i.e. translates from the input
79
// symbol/type space to the output symbol/type space).
80
210
uint32_t ObjFile::calcNewIndex(const WasmRelocation &reloc) const {
81
210
  if (reloc.Type == R_WASM_TYPE_INDEX_LEB) {
82
0
    assert(typeIsUsed[reloc.Index]);
83
0
    return typeMap[reloc.Index];
84
0
  }
85
210
  const Symbol *sym = symbols[reloc.Index];
86
210
  if (auto *ss = dyn_cast<SectionSymbol>(sym))
87
2
    sym = ss->getOutputSectionSymbol();
88
210
  return sym->getOutputSymbolIndex();
89
210
}
90
91
// Relocations can contain addend for combined sections. This function takes a
92
// relocation and returns updated addend by offset in the output section.
93
152
uint32_t ObjFile::calcNewAddend(const WasmRelocation &reloc) const {
94
152
  switch (reloc.Type) {
95
152
  case R_WASM_MEMORY_ADDR_LEB:
96
150
  case R_WASM_MEMORY_ADDR_SLEB:
97
150
  case R_WASM_MEMORY_ADDR_REL_SLEB:
98
150
  case R_WASM_MEMORY_ADDR_I32:
99
150
  case R_WASM_FUNCTION_OFFSET_I32:
100
150
    return reloc.Addend;
101
150
  case R_WASM_SECTION_OFFSET_I32:
102
2
    return getSectionSymbol(reloc.Index)->section->outputOffset + reloc.Addend;
103
150
  default:
104
0
    llvm_unreachable("unexpected relocation type");
105
152
  }
106
152
}
107
108
// Calculate the value we expect to find at the relocation location.
109
// This is used as a sanity check before applying a relocation to a given
110
// location.  It is useful for catching bugs in the compiler and linker.
111
0
uint32_t ObjFile::calcExpectedValue(const WasmRelocation &reloc) const {
112
0
  switch (reloc.Type) {
113
0
  case R_WASM_TABLE_INDEX_I32:
114
0
  case R_WASM_TABLE_INDEX_SLEB:
115
0
  case R_WASM_TABLE_INDEX_REL_SLEB: {
116
0
    const WasmSymbol &sym = wasmObj->syms()[reloc.Index];
117
0
    return tableEntries[sym.Info.ElementIndex];
118
0
  }
119
0
  case R_WASM_MEMORY_ADDR_SLEB:
120
0
  case R_WASM_MEMORY_ADDR_I32:
121
0
  case R_WASM_MEMORY_ADDR_LEB:
122
0
  case R_WASM_MEMORY_ADDR_REL_SLEB: {
123
0
    const WasmSymbol &sym = wasmObj->syms()[reloc.Index];
124
0
    if (sym.isUndefined())
125
0
      return 0;
126
0
    const WasmSegment &segment =
127
0
        wasmObj->dataSegments()[sym.Info.DataRef.Segment];
128
0
    return segment.Data.Offset.Value.Int32 + sym.Info.DataRef.Offset +
129
0
           reloc.Addend;
130
0
  }
131
0
  case R_WASM_FUNCTION_OFFSET_I32: {
132
0
    const WasmSymbol &sym = wasmObj->syms()[reloc.Index];
133
0
    InputFunction *f =
134
0
        functions[sym.Info.ElementIndex - wasmObj->getNumImportedFunctions()];
135
0
    return f->getFunctionInputOffset() + f->getFunctionCodeOffset() +
136
0
           reloc.Addend;
137
0
  }
138
0
  case R_WASM_SECTION_OFFSET_I32:
139
0
    return reloc.Addend;
140
0
  case R_WASM_TYPE_INDEX_LEB:
141
0
    return reloc.Index;
142
0
  case R_WASM_FUNCTION_INDEX_LEB:
143
0
  case R_WASM_GLOBAL_INDEX_LEB:
144
0
  case R_WASM_EVENT_INDEX_LEB: {
145
0
    const WasmSymbol &sym = wasmObj->syms()[reloc.Index];
146
0
    return sym.Info.ElementIndex;
147
0
  }
148
0
  default:
149
0
    llvm_unreachable("unknown relocation type");
150
0
  }
151
0
}
152
153
// Translate from the relocation's index into the final linked output value.
154
527
uint32_t ObjFile::calcNewValue(const WasmRelocation &reloc) const {
155
527
  const Symbol* sym = nullptr;
156
527
  if (reloc.Type != R_WASM_TYPE_INDEX_LEB) {
157
510
    sym = symbols[reloc.Index];
158
510
159
510
    // We can end up with relocations against non-live symbols.  For example
160
510
    // in debug sections.
161
510
    if ((isa<FunctionSymbol>(sym) || 
isa<DataSymbol>(sym)301
) &&
!sym->isLive()426
)
162
11
      return 0;
163
516
  }
164
516
165
516
  switch (reloc.Type) {
166
516
  case R_WASM_TABLE_INDEX_I32:
167
62
  case R_WASM_TABLE_INDEX_SLEB:
168
62
  case R_WASM_TABLE_INDEX_REL_SLEB:
169
62
    if (config->isPic && 
!getFunctionSymbol(reloc.Index)->hasTableIndex()6
)
170
1
      return 0;
171
61
    return getFunctionSymbol(reloc.Index)->getTableIndex();
172
212
  case R_WASM_MEMORY_ADDR_SLEB:
173
212
  case R_WASM_MEMORY_ADDR_I32:
174
212
  case R_WASM_MEMORY_ADDR_LEB:
175
212
  case R_WASM_MEMORY_ADDR_REL_SLEB:
176
212
    if (isa<UndefinedData>(sym))
177
12
      return 0;
178
200
    return cast<DefinedData>(sym)->getVirtualAddress() + reloc.Addend;
179
200
  case R_WASM_TYPE_INDEX_LEB:
180
18
    return typeMap[reloc.Index];
181
200
  case R_WASM_FUNCTION_INDEX_LEB:
182
125
    return getFunctionSymbol(reloc.Index)->getFunctionIndex();
183
200
  case R_WASM_GLOBAL_INDEX_LEB:
184
47
    if (auto gs = dyn_cast<GlobalSymbol>(sym))
185
42
      return gs->getGlobalIndex();
186
5
    return sym->getGOTIndex();
187
5
  case R_WASM_EVENT_INDEX_LEB:
188
2
    return getEventSymbol(reloc.Index)->getEventIndex();
189
11
  case R_WASM_FUNCTION_OFFSET_I32: {
190
11
    auto *f = cast<DefinedFunction>(sym);
191
11
    return f->function->outputOffset + f->function->getFunctionCodeOffset() +
192
11
           reloc.Addend;
193
5
  }
194
40
  case R_WASM_SECTION_OFFSET_I32:
195
40
    return getSectionSymbol(reloc.Index)->section->outputOffset + reloc.Addend;
196
5
  default:
197
0
    llvm_unreachable("unknown relocation type");
198
516
  }
199
516
}
200
201
template <class T>
202
static void setRelocs(const std::vector<T *> &chunks,
203
630
                      const WasmSection *section) {
204
630
  if (!section)
205
318
    return;
206
312
207
312
  ArrayRef<WasmRelocation> relocs = section->Relocations;
208
312
  assert(std::is_sorted(relocs.begin(), relocs.end(),
209
312
                        [](const WasmRelocation &r1, const WasmRelocation &r2) {
210
312
                          return r1.Offset < r2.Offset;
211
312
                        }));
212
312
  assert(std::is_sorted(
213
312
      chunks.begin(), chunks.end(), [](InputChunk *c1, InputChunk *c2) {
214
312
        return c1->getInputSectionOffset() < c2->getInputSectionOffset();
215
312
      }));
216
312
217
312
  auto relocsNext = relocs.begin();
218
312
  auto relocsEnd = relocs.end();
219
2.93k
  auto relocLess = [](const WasmRelocation &r, uint32_t val) {
220
2.93k
    return r.Offset < val;
221
2.93k
  };
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
219
174
  auto relocLess = [](const WasmRelocation &r, uint32_t val) {
220
174
    return r.Offset < val;
221
174
  };
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
219
2.75k
  auto relocLess = [](const WasmRelocation &r, uint32_t val) {
220
2.75k
    return r.Offset < val;
221
2.75k
  };
222
734
  for (InputChunk *c : chunks) {
223
734
    auto relocsStart = std::lower_bound(relocsNext, relocsEnd,
224
734
                                        c->getInputSectionOffset(), relocLess);
225
734
    relocsNext = std::lower_bound(
226
734
        relocsStart, relocsEnd, c->getInputSectionOffset() + c->getInputSize(),
227
734
        relocLess);
228
734
    c->setRelocations(ArrayRef<WasmRelocation>(relocsStart, relocsNext));
229
734
  }
230
312
}
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
203
315
                      const WasmSection *section) {
204
315
  if (!section)
205
240
    return;
206
75
207
75
  ArrayRef<WasmRelocation> relocs = section->Relocations;
208
75
  assert(std::is_sorted(relocs.begin(), relocs.end(),
209
75
                        [](const WasmRelocation &r1, const WasmRelocation &r2) {
210
75
                          return r1.Offset < r2.Offset;
211
75
                        }));
212
75
  assert(std::is_sorted(
213
75
      chunks.begin(), chunks.end(), [](InputChunk *c1, InputChunk *c2) {
214
75
        return c1->getInputSectionOffset() < c2->getInputSectionOffset();
215
75
      }));
216
75
217
75
  auto relocsNext = relocs.begin();
218
75
  auto relocsEnd = relocs.end();
219
75
  auto relocLess = [](const WasmRelocation &r, uint32_t val) {
220
75
    return r.Offset < val;
221
75
  };
222
192
  for (InputChunk *c : chunks) {
223
192
    auto relocsStart = std::lower_bound(relocsNext, relocsEnd,
224
192
                                        c->getInputSectionOffset(), relocLess);
225
192
    relocsNext = std::lower_bound(
226
192
        relocsStart, relocsEnd, c->getInputSectionOffset() + c->getInputSize(),
227
192
        relocLess);
228
192
    c->setRelocations(ArrayRef<WasmRelocation>(relocsStart, relocsNext));
229
192
  }
230
75
}
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
203
315
                      const WasmSection *section) {
204
315
  if (!section)
205
78
    return;
206
237
207
237
  ArrayRef<WasmRelocation> relocs = section->Relocations;
208
237
  assert(std::is_sorted(relocs.begin(), relocs.end(),
209
237
                        [](const WasmRelocation &r1, const WasmRelocation &r2) {
210
237
                          return r1.Offset < r2.Offset;
211
237
                        }));
212
237
  assert(std::is_sorted(
213
237
      chunks.begin(), chunks.end(), [](InputChunk *c1, InputChunk *c2) {
214
237
        return c1->getInputSectionOffset() < c2->getInputSectionOffset();
215
237
      }));
216
237
217
237
  auto relocsNext = relocs.begin();
218
237
  auto relocsEnd = relocs.end();
219
237
  auto relocLess = [](const WasmRelocation &r, uint32_t val) {
220
237
    return r.Offset < val;
221
237
  };
222
542
  for (InputChunk *c : chunks) {
223
542
    auto relocsStart = std::lower_bound(relocsNext, relocsEnd,
224
542
                                        c->getInputSectionOffset(), relocLess);
225
542
    relocsNext = std::lower_bound(
226
542
        relocsStart, relocsEnd, c->getInputSectionOffset() + c->getInputSize(),
227
542
        relocLess);
228
542
    c->setRelocations(ArrayRef<WasmRelocation>(relocsStart, relocsNext));
229
542
  }
230
237
}
231
232
315
void ObjFile::parse(bool ignoreComdats) {
233
315
  // Parse a memory buffer as a wasm file.
234
315
  LLVM_DEBUG(dbgs() << "Parsing object: " << toString(this) << "\n");
235
315
  std::unique_ptr<Binary> bin = CHECK(createBinary(mb), toString(this));
236
315
237
315
  auto *obj = dyn_cast<WasmObjectFile>(bin.get());
238
315
  if (!obj)
239
0
    fatal(toString(this) + ": not a wasm file");
240
315
  if (!obj->isRelocatableObject())
241
0
    fatal(toString(this) + ": not a relocatable wasm file");
242
315
243
315
  bin.release();
244
315
  wasmObj.reset(obj);
245
315
246
315
  // Build up a map of function indices to table indices for use when
247
315
  // verifying the existing table index relocations
248
315
  uint32_t totalFunctions =
249
315
      wasmObj->getNumImportedFunctions() + wasmObj->functions().size();
250
315
  tableEntries.resize(totalFunctions);
251
315
  for (const WasmElemSegment &seg : wasmObj->elements()) {
252
40
    if (seg.Offset.Opcode != WASM_OPCODE_I32_CONST)
253
0
      fatal(toString(this) + ": invalid table elements");
254
40
    uint32_t offset = seg.Offset.Value.Int32;
255
104
    for (uint32_t index = 0; index < seg.Functions.size(); 
index++64
) {
256
64
257
64
      uint32_t functionIndex = seg.Functions[index];
258
64
      tableEntries[functionIndex] = offset + index;
259
64
    }
260
40
  }
261
315
262
315
  uint32_t sectionIndex = 0;
263
315
264
315
  // Bool for each symbol, true if called directly.  This allows us to implement
265
315
  // a weaker form of signature checking where undefined functions that are not
266
315
  // called directly (i.e. only address taken) don't have to match the defined
267
315
  // function's signature.  We cannot do this for directly called functions
268
315
  // because those signatures are checked at validation times.
269
315
  // See https://bugs.llvm.org/show_bug.cgi?id=40412
270
315
  std::vector<bool> isCalledDirectly(wasmObj->getNumberOfSymbols(), false);
271
1.74k
  for (const SectionRef &sec : wasmObj->sections()) {
272
1.74k
    const WasmSection &section = wasmObj->getWasmSection(sec);
273
1.74k
    // Wasm objects can have at most one code and one data section.
274
1.74k
    if (section.Type == WASM_SEC_CODE) {
275
237
      assert(!codeSection);
276
237
      codeSection = &section;
277
1.50k
    } else if (section.Type == WASM_SEC_DATA) {
278
75
      assert(!dataSection);
279
75
      dataSection = &section;
280
1.42k
    } else if (section.Type == WASM_SEC_CUSTOM) {
281
569
      customSections.emplace_back(make<InputSection>(section, this));
282
569
      customSections.back()->setRelocations(section.Relocations);
283
569
      customSectionsByIndex[sectionIndex] = customSections.back();
284
569
    }
285
1.74k
    sectionIndex++;
286
1.74k
    // Scans relocations to dermine determine if a function symbol is called
287
1.74k
    // directly
288
1.74k
    for (const WasmRelocation &reloc : section.Relocations)
289
564
      if (reloc.Type == R_WASM_FUNCTION_INDEX_LEB)
290
150
        isCalledDirectly[reloc.Index] = true;
291
1.74k
  }
292
315
293
315
  typeMap.resize(getWasmObj()->types().size());
294
315
  typeIsUsed.resize(getWasmObj()->types().size(), false);
295
315
296
315
  ArrayRef<StringRef> comdats = wasmObj->linkingData().Comdats;
297
315
  for (StringRef comdat : comdats) {
298
6
    bool isNew = ignoreComdats || 
symtab->addComdat(comdat)5
;
299
6
    keptComdats.push_back(isNew);
300
6
  }
301
315
302
315
  // Populate `Segments`.
303
315
  for (const WasmSegment &s : wasmObj->dataSegments()) {
304
192
    auto* seg = make<InputSegment>(s, this);
305
192
    seg->discarded = isExcludedByComdat(seg);
306
192
    segments.emplace_back(seg);
307
192
  }
308
315
  setRelocs(segments, dataSection);
309
315
310
315
  // Populate `Functions`.
311
315
  ArrayRef<WasmFunction> funcs = wasmObj->functions();
312
315
  ArrayRef<uint32_t> funcTypes = wasmObj->functionTypes();
313
315
  ArrayRef<WasmSignature> types = wasmObj->types();
314
315
  functions.reserve(funcs.size());
315
315
316
857
  for (size_t i = 0, e = funcs.size(); i != e; 
++i542
) {
317
542
    auto* func = make<InputFunction>(types[funcTypes[i]], &funcs[i], this);
318
542
    func->discarded = isExcludedByComdat(func);
319
542
    functions.emplace_back(func);
320
542
  }
321
315
  setRelocs(functions, codeSection);
322
315
323
315
  // Populate `Globals`.
324
315
  for (const WasmGlobal &g : wasmObj->globals())
325
4
    globals.emplace_back(make<InputGlobal>(g, this));
326
315
327
315
  // Populate `Events`.
328
315
  for (const WasmEvent &e : wasmObj->events())
329
2
    events.emplace_back(make<InputEvent>(types[e.Type.SigIndex], e, this));
330
315
331
315
  // Populate `Symbols` based on the symbols in the object.
332
315
  symbols.reserve(wasmObj->getNumberOfSymbols());
333
911
  for (const SymbolRef &sym : wasmObj->symbols()) {
334
911
    const WasmSymbol &wasmSym = wasmObj->getWasmSymbol(sym.getRawDataRefImpl());
335
911
    if (wasmSym.isDefined()) {
336
764
      // createDefined may fail if the symbol is comdat excluded in which case
337
764
      // we fall back to creating an undefined symbol
338
764
      if (Symbol *d = createDefined(wasmSym)) {
339
761
        symbols.push_back(d);
340
761
        continue;
341
761
      }
342
150
    }
343
150
    size_t idx = symbols.size();
344
150
    symbols.push_back(createUndefined(wasmSym, isCalledDirectly[idx]));
345
150
  }
346
315
}
347
348
734
bool ObjFile::isExcludedByComdat(InputChunk *chunk) const {
349
734
  uint32_t c = chunk->getComdat();
350
734
  if (c == UINT32_MAX)
351
734
    
return false723
;
352
11
  return !keptComdats[c];
353
11
}
354
355
239
FunctionSymbol *ObjFile::getFunctionSymbol(uint32_t index) const {
356
239
  return cast<FunctionSymbol>(symbols[index]);
357
239
}
358
359
0
GlobalSymbol *ObjFile::getGlobalSymbol(uint32_t index) const {
360
0
  return cast<GlobalSymbol>(symbols[index]);
361
0
}
362
363
2
EventSymbol *ObjFile::getEventSymbol(uint32_t index) const {
364
2
  return cast<EventSymbol>(symbols[index]);
365
2
}
366
367
42
SectionSymbol *ObjFile::getSectionSymbol(uint32_t index) const {
368
42
  return cast<SectionSymbol>(symbols[index]);
369
42
}
370
371
0
DataSymbol *ObjFile::getDataSymbol(uint32_t index) const {
372
0
  return cast<DataSymbol>(symbols[index]);
373
0
}
374
375
764
Symbol *ObjFile::createDefined(const WasmSymbol &sym) {
376
764
  StringRef name = sym.Info.Name;
377
764
  uint32_t flags = sym.Info.Flags;
378
764
379
764
  switch (sym.Info.Kind) {
380
764
  case WASM_SYMBOL_TYPE_FUNCTION: {
381
546
    InputFunction *func =
382
546
        functions[sym.Info.ElementIndex - wasmObj->getNumImportedFunctions()];
383
546
    if (sym.isBindingLocal())
384
47
      return make<DefinedFunction>(name, flags, this, func);
385
499
    if (func->discarded)
386
2
      return nullptr;
387
497
    return symtab->addDefinedFunction(name, flags, this, func);
388
497
  }
389
497
  case WASM_SYMBOL_TYPE_DATA: {
390
194
    InputSegment *seg = segments[sym.Info.DataRef.Segment];
391
194
    uint32_t offset = sym.Info.DataRef.Offset;
392
194
    uint32_t size = sym.Info.DataRef.Size;
393
194
    if (sym.isBindingLocal())
394
45
      return make<DefinedData>(name, flags, this, seg, offset, size);
395
149
    if (seg->discarded)
396
1
      return nullptr;
397
148
    return symtab->addDefinedData(name, flags, this, seg, offset, size);
398
148
  }
399
148
  case WASM_SYMBOL_TYPE_GLOBAL: {
400
4
    InputGlobal *global =
401
4
        globals[sym.Info.ElementIndex - wasmObj->getNumImportedGlobals()];
402
4
    if (sym.isBindingLocal())
403
0
      return make<DefinedGlobal>(name, flags, this, global);
404
4
    return symtab->addDefinedGlobal(name, flags, this, global);
405
4
  }
406
18
  case WASM_SYMBOL_TYPE_SECTION: {
407
18
    InputSection *section = customSectionsByIndex[sym.Info.ElementIndex];
408
18
    assert(sym.isBindingLocal());
409
18
    return make<SectionSymbol>(flags, section, this);
410
4
  }
411
4
  case WASM_SYMBOL_TYPE_EVENT: {
412
2
    InputEvent *event =
413
2
        events[sym.Info.ElementIndex - wasmObj->getNumImportedEvents()];
414
2
    if (sym.isBindingLocal())
415
0
      return make<DefinedEvent>(name, flags, this, event);
416
2
    return symtab->addDefinedEvent(name, flags, this, event);
417
2
  }
418
0
  }
419
0
  llvm_unreachable("unknown symbol kind");
420
0
}
421
422
150
Symbol *ObjFile::createUndefined(const WasmSymbol &sym, bool isCalledDirectly) {
423
150
  StringRef name = sym.Info.Name;
424
150
  uint32_t flags = sym.Info.Flags;
425
150
426
150
  switch (sym.Info.Kind) {
427
150
  case WASM_SYMBOL_TYPE_FUNCTION:
428
105
    if (sym.isBindingLocal())
429
0
      return make<UndefinedFunction>(name, sym.Info.ImportName,
430
0
                                     sym.Info.ImportModule, flags, this,
431
0
                                     sym.Signature, isCalledDirectly);
432
105
    return symtab->addUndefinedFunction(name, sym.Info.ImportName,
433
105
                                        sym.Info.ImportModule, flags, this,
434
105
                                        sym.Signature, isCalledDirectly);
435
105
  case WASM_SYMBOL_TYPE_DATA:
436
25
    if (sym.isBindingLocal())
437
0
      return make<UndefinedData>(name, flags, this);
438
25
    return symtab->addUndefinedData(name, flags, this);
439
25
  case WASM_SYMBOL_TYPE_GLOBAL:
440
20
    if (sym.isBindingLocal())
441
0
      return make<UndefinedGlobal>(name, sym.Info.ImportName,
442
0
                                   sym.Info.ImportModule, flags, this,
443
0
                                   sym.GlobalType);
444
20
    return symtab->addUndefinedGlobal(name, sym.Info.ImportName,
445
20
                                      sym.Info.ImportModule, flags, this,
446
20
                                      sym.GlobalType);
447
20
  case WASM_SYMBOL_TYPE_SECTION:
448
0
    llvm_unreachable("section symbols cannot be undefined");
449
0
  }
450
0
  llvm_unreachable("unknown symbol kind");
451
0
}
452
453
16
void ArchiveFile::parse() {
454
16
  // Parse a MemoryBufferRef as an archive file.
455
16
  LLVM_DEBUG(dbgs() << "Parsing library: " << toString(this) << "\n");
456
16
  file = CHECK(Archive::create(mb), toString(this));
457
16
458
16
  // Read the symbol table to construct Lazy symbols.
459
16
  int count = 0;
460
52
  for (const Archive::Symbol &sym : file->symbols()) {
461
52
    symtab->addLazy(this, &sym);
462
52
    ++count;
463
52
  }
464
16
  LLVM_DEBUG(dbgs() << "Read " << count << " symbols\n");
465
16
}
466
467
15
void ArchiveFile::addMember(const Archive::Symbol *sym) {
468
15
  const Archive::Child &c =
469
15
      CHECK(sym->getMember(),
470
15
            "could not get the member for symbol " + sym->getName());
471
15
472
15
  // Don't try to load the same member twice (this can happen when members
473
15
  // mutually reference each other).
474
15
  if (!seen.insert(c.getChildOffset()).second)
475
0
    return;
476
15
477
15
  LLVM_DEBUG(dbgs() << "loading lazy: " << sym->getName() << "\n");
478
15
  LLVM_DEBUG(dbgs() << "from archive: " << toString(this) << "\n");
479
15
480
15
  MemoryBufferRef mb =
481
15
      CHECK(c.getMemoryBufferRef(),
482
15
            "could not get the buffer for the member defining symbol " +
483
15
                sym->getName());
484
15
485
15
  InputFile *obj = createObjectFile(mb, getName());
486
15
  symtab->addFile(obj);
487
15
}
488
489
static uint8_t mapVisibility(GlobalValue::VisibilityTypes gvVisibility) {
490
  switch (gvVisibility) {
491
  case GlobalValue::DefaultVisibility:
492
    return WASM_SYMBOL_VISIBILITY_DEFAULT;
493
  case GlobalValue::HiddenVisibility:
494
  case GlobalValue::ProtectedVisibility:
495
    return WASM_SYMBOL_VISIBILITY_HIDDEN;
496
  }
497
  llvm_unreachable("unknown visibility");
498
}
499
500
static Symbol *createBitcodeSymbol(const std::vector<bool> &keptComdats,
501
                                   const lto::InputFile::Symbol &objSym,
502
65
                                   BitcodeFile &f) {
503
65
  StringRef name = saver.save(objSym.getName());
504
65
505
65
  uint32_t flags = objSym.isWeak() ? 
WASM_SYMBOL_BINDING_WEAK3
:
062
;
506
65
  flags |= mapVisibility(objSym.getVisibility());
507
65
508
65
  int c = objSym.getComdatIndex();
509
65
  bool excludedByComdat = c != -1 && 
!keptComdats[c]2
;
510
65
511
65
  if (objSym.isUndefined() || 
excludedByComdat50
) {
512
16
    if (objSym.isExecutable())
513
15
      return symtab->addUndefinedFunction(name, name, defaultModule, flags, &f,
514
15
                                          nullptr, true);
515
1
    return symtab->addUndefinedData(name, flags, &f);
516
1
  }
517
49
518
49
  if (objSym.isExecutable())
519
46
    return symtab->addDefinedFunction(name, flags, &f, nullptr);
520
3
  return symtab->addDefinedData(name, flags, &f, nullptr, 0, 0);
521
3
}
522
523
43
void BitcodeFile::parse() {
524
43
  obj = check(lto::InputFile::create(MemoryBufferRef(
525
43
      mb.getBuffer(), saver.save(archiveName + mb.getBufferIdentifier()))));
526
43
  Triple t(obj->getTargetTriple());
527
43
  if (t.getArch() != Triple::wasm32) {
528
1
    error(toString(mb.getBufferIdentifier()) + ": machine type must be wasm32");
529
1
    return;
530
1
  }
531
42
  std::vector<bool> keptComdats;
532
42
  for (StringRef s : obj->getComdatTable())
533
2
    keptComdats.push_back(symtab->addComdat(s));
534
42
535
42
  for (const lto::InputFile::Symbol &objSym : obj->symbols())
536
65
    symbols.push_back(createBitcodeSymbol(keptComdats, objSym, *this));
537
42
}
538
539
// Returns a string in the format of "foo.o" or "foo.a(bar.o)".
540
371
std::string lld::toString(const wasm::InputFile *file) {
541
371
  if (!file)
542
3
    return "<internal>";
543
368
544
368
  if (file->archiveName.empty())
545
342
    return file->getName();
546
26
547
26
  return (file->archiveName + "(" + file->getName() + ")").str();
548
26
}