blob: 965f5b8efe5e06e535300755546ae2386cbdaa38 [file] [log] [blame]
Sam Cleggc94d3932017-11-17 18:14:09 +00001//===- InputFiles.cpp -----------------------------------------------------===//
2//
3// The LLVM Linker
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 "InputFiles.h"
11
12#include "Config.h"
Sam Clegg8d146bb2018-01-09 23:56:44 +000013#include "InputFunction.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000014#include "InputSegment.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000015#include "SymbolTable.h"
16#include "lld/Common/ErrorHandler.h"
Rui Ueyama2017d522017-11-28 20:39:17 +000017#include "lld/Common/Memory.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000018#include "llvm/Object/Binary.h"
19#include "llvm/Object/Wasm.h"
20#include "llvm/Support/raw_ostream.h"
21
22#define DEBUG_TYPE "lld"
23
24using namespace lld;
25using namespace lld::wasm;
26
27using namespace llvm;
28using namespace llvm::object;
29using namespace llvm::wasm;
30
31Optional<MemoryBufferRef> lld::wasm::readFile(StringRef Path) {
32 log("Loading: " + Path);
33
34 auto MBOrErr = MemoryBuffer::getFile(Path);
35 if (auto EC = MBOrErr.getError()) {
36 error("cannot open " + Path + ": " + EC.message());
37 return None;
38 }
39 std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
40 MemoryBufferRef MBRef = MB->getMemBufferRef();
41 make<std::unique_ptr<MemoryBuffer>>(std::move(MB)); // take MB ownership
42
43 return MBRef;
44}
45
46void ObjFile::dumpInfo() const {
Sam Clegg8d146bb2018-01-09 23:56:44 +000047 log("info for: " + getName() + "\n" +
48 " Total Functions : " + Twine(FunctionSymbols.size()) + "\n" +
49 " Total Globals : " + Twine(GlobalSymbols.size()) + "\n" +
50 " Function Imports : " + Twine(NumFunctionImports) + "\n" +
51 " Global Imports : " + Twine(NumGlobalImports) + "\n" +
52 " Table Entries : " + Twine(TableSymbols.size()) + "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +000053}
54
Sam Clegg8d146bb2018-01-09 23:56:44 +000055uint32_t ObjFile::getRelocatedAddress(uint32_t GlobalIndex) const {
56 return GlobalSymbols[GlobalIndex]->getVirtualAddress();
Sam Cleggc94d3932017-11-17 18:14:09 +000057}
58
59uint32_t ObjFile::relocateFunctionIndex(uint32_t Original) const {
Sam Clegg8d146bb2018-01-09 23:56:44 +000060 Symbol *Sym = FunctionSymbols[Original];
Sam Clegg74fe0ba2017-12-07 01:51:24 +000061 uint32_t Index = Sym->getOutputIndex();
62 DEBUG(dbgs() << "relocateFunctionIndex: " << toString(*Sym) << ": "
63 << Original << " -> " << Index << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +000064 return Index;
65}
66
67uint32_t ObjFile::relocateTypeIndex(uint32_t Original) const {
68 return TypeMap[Original];
69}
70
71uint32_t ObjFile::relocateTableIndex(uint32_t Original) const {
Sam Clegg8d146bb2018-01-09 23:56:44 +000072 Symbol *Sym = TableSymbols[Original];
Sam Clegg87e61922018-01-08 23:39:11 +000073 uint32_t Index = Sym->hasTableIndex() ? Sym->getTableIndex() : 0;
Sam Cleggfc1a9122017-12-11 22:00:56 +000074 DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original
75 << " -> " << Index << "\n");
76 return Index;
Sam Cleggc94d3932017-11-17 18:14:09 +000077}
78
79uint32_t ObjFile::relocateGlobalIndex(uint32_t Original) const {
Sam Clegg8d146bb2018-01-09 23:56:44 +000080 Symbol *Sym = GlobalSymbols[Original];
Sam Clegg87e61922018-01-08 23:39:11 +000081 uint32_t Index = Sym->hasOutputIndex() ? Sym->getOutputIndex() : 0;
Sam Clegg74fe0ba2017-12-07 01:51:24 +000082 DEBUG(dbgs() << "relocateGlobalIndex: " << toString(*Sym) << ": " << Original
83 << " -> " << Index << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +000084 return Index;
85}
86
87void ObjFile::parse() {
88 // Parse a memory buffer as a wasm file.
89 DEBUG(dbgs() << "Parsing object: " << toString(this) << "\n");
Rui Ueyamabdc51502017-12-06 22:08:17 +000090 std::unique_ptr<Binary> Bin = CHECK(createBinary(MB), toString(this));
Sam Cleggc94d3932017-11-17 18:14:09 +000091
92 auto *Obj = dyn_cast<WasmObjectFile>(Bin.get());
93 if (!Obj)
94 fatal(toString(this) + ": not a wasm file");
95 if (!Obj->isRelocatableObject())
96 fatal(toString(this) + ": not a relocatable wasm file");
97
98 Bin.release();
99 WasmObj.reset(Obj);
100
101 // Find the code and data sections. Wasm objects can have at most one code
102 // and one data section.
103 for (const SectionRef &Sec : WasmObj->sections()) {
104 const WasmSection &Section = WasmObj->getWasmSection(Sec);
105 if (Section.Type == WASM_SEC_CODE)
106 CodeSection = &Section;
107 else if (Section.Type == WASM_SEC_DATA)
108 DataSection = &Section;
109 }
110
111 initializeSymbols();
112}
113
114// Return the InputSegment in which a given symbol is defined.
Sam Clegg8d146bb2018-01-09 23:56:44 +0000115InputSegment *ObjFile::getSegment(const WasmSymbol &WasmSym) const {
Sam Cleggc94d3932017-11-17 18:14:09 +0000116 uint32_t Address = WasmObj->getWasmSymbolValue(WasmSym);
117 for (InputSegment *Segment : Segments) {
118 if (Address >= Segment->startVA() && Address < Segment->endVA()) {
119 DEBUG(dbgs() << "Found symbol in segment: " << WasmSym.Name << " -> "
120 << Segment->getName() << "\n");
121
122 return Segment;
123 }
124 }
Rui Ueyama29ceba72017-12-15 00:07:15 +0000125 error("symbol not found in any segment: " + WasmSym.Name);
Sam Cleggc94d3932017-11-17 18:14:09 +0000126 return nullptr;
127}
128
Sam Cleggf61676a2017-12-17 17:52:01 +0000129static void copyRelocationsRange(std::vector<WasmRelocation> &To,
130 ArrayRef<WasmRelocation> From, size_t Start,
Sam Clegg8d146bb2018-01-09 23:56:44 +0000131 size_t Size) {
Sam Cleggf61676a2017-12-17 17:52:01 +0000132 for (const WasmRelocation &R : From)
Sam Clegg8d146bb2018-01-09 23:56:44 +0000133 if (R.Offset >= Start && R.Offset < Start + Size)
Sam Cleggf61676a2017-12-17 17:52:01 +0000134 To.push_back(R);
135}
136
Sam Clegg8d146bb2018-01-09 23:56:44 +0000137// Get the signature for a given function symbol, either by looking
138// it up in function sections (for defined functions), of the imports section
139// (for imported functions).
140const WasmSignature *ObjFile::getFunctionSig(const WasmSymbol &Sym) const {
141 DEBUG(dbgs() << "getFunctionSig: " << Sym.Name << "\n");
142 return &WasmObj->types()[Sym.FunctionType];
143}
144
145InputFunction *ObjFile::getFunction(const WasmSymbol &Sym) const {
146 uint32_t FunctionIndex = Sym.ElementIndex - NumFunctionImports;
147 return Functions[FunctionIndex];
148}
149
Sam Cleggc94d3932017-11-17 18:14:09 +0000150void ObjFile::initializeSymbols() {
151 Symbols.reserve(WasmObj->getNumberOfSymbols());
152
153 for (const WasmImport &Import : WasmObj->imports()) {
154 switch (Import.Kind) {
155 case WASM_EXTERNAL_FUNCTION:
Sam Clegg8d146bb2018-01-09 23:56:44 +0000156 ++NumFunctionImports;
Sam Cleggc94d3932017-11-17 18:14:09 +0000157 break;
158 case WASM_EXTERNAL_GLOBAL:
Sam Clegg8d146bb2018-01-09 23:56:44 +0000159 ++NumGlobalImports;
Sam Cleggc94d3932017-11-17 18:14:09 +0000160 break;
161 }
162 }
163
Sam Clegg8d146bb2018-01-09 23:56:44 +0000164 FunctionSymbols.resize(NumFunctionImports + WasmObj->functions().size());
165 GlobalSymbols.resize(NumGlobalImports + WasmObj->globals().size());
Sam Cleggc94d3932017-11-17 18:14:09 +0000166
Sam Cleggf61676a2017-12-17 17:52:01 +0000167 for (const WasmSegment &S : WasmObj->dataSegments()) {
Sam Clegg8d146bb2018-01-09 23:56:44 +0000168 InputSegment *Seg = make<InputSegment>(S, *this);
Sam Cleggf61676a2017-12-17 17:52:01 +0000169 copyRelocationsRange(Seg->Relocations, DataSection->Relocations,
Sam Clegg8d146bb2018-01-09 23:56:44 +0000170 Seg->getInputSectionOffset(), Seg->getSize());
Sam Cleggf61676a2017-12-17 17:52:01 +0000171 Segments.emplace_back(Seg);
172 }
Sam Cleggc94d3932017-11-17 18:14:09 +0000173
Sam Clegg8d146bb2018-01-09 23:56:44 +0000174 ArrayRef<WasmFunction> Funcs = WasmObj->functions();
175 ArrayRef<uint32_t> FuncTypes = WasmObj->functionTypes();
176 ArrayRef<WasmSignature> Types = WasmObj->types();
177 for (size_t I = 0; I < Funcs.size(); ++I) {
178 const WasmFunction &Func = Funcs[I];
179 const WasmSignature &Sig = Types[FuncTypes[I]];
180 InputFunction *Function = make<InputFunction>(Sig, Func, *this);
181 copyRelocationsRange(Function->Relocations, CodeSection->Relocations,
182 Func.CodeSectionOffset, Func.Size);
183 Functions.emplace_back(Function);
184 }
185
Sam Cleggfc1a9122017-12-11 22:00:56 +0000186 // Populate `FunctionSymbols` and `GlobalSymbols` based on the WasmSymbols
187 // in the object
Sam Cleggc94d3932017-11-17 18:14:09 +0000188 for (const SymbolRef &Sym : WasmObj->symbols()) {
189 const WasmSymbol &WasmSym = WasmObj->getWasmSymbol(Sym.getRawDataRefImpl());
Sam Cleggfc1a9122017-12-11 22:00:56 +0000190 Symbol *S;
Sam Cleggc94d3932017-11-17 18:14:09 +0000191 switch (WasmSym.Type) {
192 case WasmSymbol::SymbolType::FUNCTION_IMPORT:
Sam Clegg8d146bb2018-01-09 23:56:44 +0000193 S = createUndefined(WasmSym, getFunctionSig(WasmSym));
194 break;
Sam Cleggc94d3932017-11-17 18:14:09 +0000195 case WasmSymbol::SymbolType::GLOBAL_IMPORT:
196 S = createUndefined(WasmSym);
197 break;
198 case WasmSymbol::SymbolType::GLOBAL_EXPORT:
Sam Clegg8d146bb2018-01-09 23:56:44 +0000199 S = createDefined(WasmSym, getSegment(WasmSym), nullptr);
Sam Cleggc94d3932017-11-17 18:14:09 +0000200 break;
201 case WasmSymbol::SymbolType::FUNCTION_EXPORT:
Sam Clegg8d146bb2018-01-09 23:56:44 +0000202 S = createDefined(WasmSym, nullptr, getFunction(WasmSym));
Sam Cleggc94d3932017-11-17 18:14:09 +0000203 break;
204 case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
205 // These are for debugging only, no need to create linker symbols for them
206 continue;
207 }
208
209 Symbols.push_back(S);
210 if (WasmSym.isFunction()) {
211 DEBUG(dbgs() << "Function: " << WasmSym.ElementIndex << " -> "
212 << toString(*S) << "\n");
213 FunctionSymbols[WasmSym.ElementIndex] = S;
Sam Clegg1cf31bb2017-12-21 02:43:39 +0000214 if (WasmSym.HasAltIndex)
215 FunctionSymbols[WasmSym.AltIndex] = S;
Sam Cleggc94d3932017-11-17 18:14:09 +0000216 } else {
217 DEBUG(dbgs() << "Global: " << WasmSym.ElementIndex << " -> "
218 << toString(*S) << "\n");
219 GlobalSymbols[WasmSym.ElementIndex] = S;
Sam Clegg1cf31bb2017-12-21 02:43:39 +0000220 if (WasmSym.HasAltIndex)
221 GlobalSymbols[WasmSym.AltIndex] = S;
Sam Cleggc94d3932017-11-17 18:14:09 +0000222 }
223 }
224
Sam Clegg1cf31bb2017-12-21 02:43:39 +0000225 DEBUG(for (size_t I = 0; I < FunctionSymbols.size(); ++I)
226 assert(FunctionSymbols[I] != nullptr);
227 for (size_t I = 0; I < GlobalSymbols.size(); ++I)
228 assert(GlobalSymbols[I] != nullptr););
229
Sam Cleggfc1a9122017-12-11 22:00:56 +0000230 // Populate `TableSymbols` with all symbols that are called indirectly
231 uint32_t SegmentCount = WasmObj->elements().size();
232 if (SegmentCount) {
233 if (SegmentCount > 1)
234 fatal(getName() + ": contains more than one element segment");
235 const WasmElemSegment &Segment = WasmObj->elements()[0];
236 if (Segment.Offset.Opcode != WASM_OPCODE_I32_CONST)
237 fatal(getName() + ": unsupported element segment");
238 if (Segment.TableIndex != 0)
239 fatal(getName() + ": unsupported table index in elem segment");
240 if (Segment.Offset.Value.Int32 != 0)
241 fatal(getName() + ": unsupported element segment offset");
242 TableSymbols.reserve(Segment.Functions.size());
243 for (uint64_t FunctionIndex : Segment.Functions)
Sam Clegg8d146bb2018-01-09 23:56:44 +0000244 TableSymbols.push_back(FunctionSymbols[FunctionIndex]);
Sam Cleggfc1a9122017-12-11 22:00:56 +0000245 }
246
247 DEBUG(dbgs() << "TableSymbols: " << TableSymbols.size() << "\n");
248 DEBUG(dbgs() << "Functions : " << FunctionSymbols.size() << "\n");
249 DEBUG(dbgs() << "Globals : " << GlobalSymbols.size() << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000250}
251
Sam Clegg8d146bb2018-01-09 23:56:44 +0000252Symbol *ObjFile::createUndefined(const WasmSymbol &Sym,
253 const WasmSignature *Signature) {
254 return Symtab->addUndefined(this, &Sym, Signature);
Sam Cleggc94d3932017-11-17 18:14:09 +0000255}
256
257Symbol *ObjFile::createDefined(const WasmSymbol &Sym,
Sam Clegg8d146bb2018-01-09 23:56:44 +0000258 const InputSegment *Segment,
259 InputFunction *Function) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000260 Symbol *S;
261 if (Sym.isLocal()) {
262 S = make<Symbol>(Sym.Name, true);
263 Symbol::Kind Kind;
264 if (Sym.Type == WasmSymbol::SymbolType::FUNCTION_EXPORT)
265 Kind = Symbol::Kind::DefinedFunctionKind;
266 else if (Sym.Type == WasmSymbol::SymbolType::GLOBAL_EXPORT)
267 Kind = Symbol::Kind::DefinedGlobalKind;
268 else
269 llvm_unreachable("invalid local symbol type");
Sam Clegg8d146bb2018-01-09 23:56:44 +0000270 S->update(Kind, this, &Sym, Segment, Function);
Sam Cleggc94d3932017-11-17 18:14:09 +0000271 return S;
272 }
Sam Clegg8d146bb2018-01-09 23:56:44 +0000273 return Symtab->addDefined(this, &Sym, Segment, Function);
Sam Cleggc94d3932017-11-17 18:14:09 +0000274}
275
276void ArchiveFile::parse() {
277 // Parse a MemoryBufferRef as an archive file.
278 DEBUG(dbgs() << "Parsing library: " << toString(this) << "\n");
Rui Ueyamabdc51502017-12-06 22:08:17 +0000279 File = CHECK(Archive::create(MB), toString(this));
Sam Cleggc94d3932017-11-17 18:14:09 +0000280
281 // Read the symbol table to construct Lazy symbols.
282 int Count = 0;
283 for (const Archive::Symbol &Sym : File->symbols()) {
284 Symtab->addLazy(this, &Sym);
285 ++Count;
286 }
287 DEBUG(dbgs() << "Read " << Count << " symbols\n");
288}
289
290void ArchiveFile::addMember(const Archive::Symbol *Sym) {
291 const Archive::Child &C =
Rui Ueyamabdc51502017-12-06 22:08:17 +0000292 CHECK(Sym->getMember(),
Sam Cleggc94d3932017-11-17 18:14:09 +0000293 "could not get the member for symbol " + Sym->getName());
294
295 // Don't try to load the same member twice (this can happen when members
296 // mutually reference each other).
297 if (!Seen.insert(C.getChildOffset()).second)
298 return;
299
Sam Clegga681a112017-12-06 03:10:39 +0000300 DEBUG(dbgs() << "loading lazy: " << Sym->getName() << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000301 DEBUG(dbgs() << "from archive: " << toString(this) << "\n");
302
303 MemoryBufferRef MB =
Rui Ueyamabdc51502017-12-06 22:08:17 +0000304 CHECK(C.getMemoryBufferRef(),
Sam Cleggc94d3932017-11-17 18:14:09 +0000305 "could not get the buffer for the member defining symbol " +
306 Sym->getName());
307
308 if (identify_magic(MB.getBuffer()) != file_magic::wasm_object) {
309 error("unknown file type: " + MB.getBufferIdentifier());
310 return;
311 }
312
313 InputFile *Obj = make<ObjFile>(MB);
314 Obj->ParentName = ParentName;
315 Symtab->addFile(Obj);
316}
317
318// Returns a string in the format of "foo.o" or "foo.a(bar.o)".
Sam Clegg7e756632017-12-05 16:50:46 +0000319std::string lld::toString(const wasm::InputFile *File) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000320 if (!File)
321 return "<internal>";
322
323 if (File->ParentName.empty())
324 return File->getName();
325
326 return (File->ParentName + "(" + File->getName() + ")").str();
327}