blob: 12ee9ec6f8cc4c5f873b2397d4454ba6ea261fb7 [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"
Sam Cleggc94d3932017-11-17 18:14:09 +000011#include "Config.h"
Sam Clegg5fa274b2018-01-10 01:13:34 +000012#include "InputChunks.h"
Sam Clegg93102972018-02-23 05:08:53 +000013#include "InputGlobal.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000014#include "SymbolTable.h"
15#include "lld/Common/ErrorHandler.h"
Rui Ueyama2017d522017-11-28 20:39:17 +000016#include "lld/Common/Memory.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000017#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
23using namespace lld;
24using namespace lld::wasm;
25
26using namespace llvm;
27using namespace llvm::object;
28using namespace llvm::wasm;
29
30Optional<MemoryBufferRef> lld::wasm::readFile(StringRef Path) {
31 log("Loading: " + Path);
32
33 auto MBOrErr = MemoryBuffer::getFile(Path);
34 if (auto EC = MBOrErr.getError()) {
35 error("cannot open " + Path + ": " + EC.message());
36 return None;
37 }
38 std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
39 MemoryBufferRef MBRef = MB->getMemBufferRef();
40 make<std::unique_ptr<MemoryBuffer>>(std::move(MB)); // take MB ownership
41
42 return MBRef;
43}
44
45void ObjFile::dumpInfo() const {
Rui Ueyama0a9583c2018-02-28 02:57:37 +000046 log("info for: " + getName() +
47 "\n Symbols : " + Twine(Symbols.size()) +
48 "\n Function Imports : " + Twine(WasmObj->getNumImportedFunctions()) +
49 "\n Global Imports : " + Twine(WasmObj->getNumImportedGlobals()));
Sam Cleggc94d3932017-11-17 18:14:09 +000050}
51
Sam Cleggd96d9352018-01-10 19:22:42 +000052// Relocations contain an index into the function, global or table index
53// space of the input file. This function takes a relocation and returns the
54// relocated index (i.e. translates from the input index space to the output
55// index space).
56uint32_t ObjFile::calcNewIndex(const WasmRelocation &Reloc) const {
Rui Ueyamad1063bb2018-02-28 00:26:26 +000057 if (Reloc.Type == R_WEBASSEMBLY_TYPE_INDEX_LEB) {
58 assert(TypeIsUsed[Reloc.Index]);
59 return TypeMap[Reloc.Index];
60 }
61 return Symbols[Reloc.Index]->getOutputSymbolIndex();
Sam Cleggd96d9352018-01-10 19:22:42 +000062}
63
Sam Cleggab604a92018-01-23 01:25:56 +000064// Translate from the relocation's index into the final linked output value.
65uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const {
66 switch (Reloc.Type) {
67 case R_WEBASSEMBLY_TABLE_INDEX_I32:
Nicholas Wilson2e55ee72018-03-09 17:06:38 +000068 case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
69 return getFunctionSymbol(Reloc.Index)->getTableIndex();
Sam Cleggab604a92018-01-23 01:25:56 +000070 case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
71 case R_WEBASSEMBLY_MEMORY_ADDR_I32:
72 case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
Rui Ueyamad1063bb2018-02-28 00:26:26 +000073 if (auto *Sym = dyn_cast<DefinedData>(getDataSymbol(Reloc.Index)))
74 return Sym->getVirtualAddress() + Reloc.Addend;
75 return Reloc.Addend;
Sam Cleggab604a92018-01-23 01:25:56 +000076 case R_WEBASSEMBLY_TYPE_INDEX_LEB:
Rui Ueyamad1063bb2018-02-28 00:26:26 +000077 return TypeMap[Reloc.Index];
Sam Cleggab604a92018-01-23 01:25:56 +000078 case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
Rui Ueyamad1063bb2018-02-28 00:26:26 +000079 return getFunctionSymbol(Reloc.Index)->getOutputIndex();
Sam Cleggab604a92018-01-23 01:25:56 +000080 case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
Rui Ueyamad1063bb2018-02-28 00:26:26 +000081 return getGlobalSymbol(Reloc.Index)->getOutputIndex();
Sam Cleggab604a92018-01-23 01:25:56 +000082 default:
83 llvm_unreachable("unknown relocation type");
84 }
85}
86
Sam Cleggc94d3932017-11-17 18:14:09 +000087void 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
Sam Clegg8f6d2de2018-01-31 23:48:14 +0000111 TypeMap.resize(getWasmObj()->types().size());
112 TypeIsUsed.resize(getWasmObj()->types().size(), false);
113
Rui Ueyama0a9583c2018-02-28 02:57:37 +0000114 // Populate `Segments`.
115 for (const WasmSegment &S : WasmObj->dataSegments()) {
116 InputSegment *Seg = make<InputSegment>(S, this);
117 Seg->copyRelocations(*DataSection);
118 Segments.emplace_back(Seg);
119 }
Sam Clegg8d146bb2018-01-09 23:56:44 +0000120
Rui Ueyama0a9583c2018-02-28 02:57:37 +0000121 // Populate `Functions`.
122 ArrayRef<WasmFunction> Funcs = WasmObj->functions();
123 ArrayRef<uint32_t> FuncTypes = WasmObj->functionTypes();
124 ArrayRef<WasmSignature> Types = WasmObj->types();
125 Functions.reserve(Funcs.size());
Sam Clegg8d146bb2018-01-09 23:56:44 +0000126
Rui Ueyama0a9583c2018-02-28 02:57:37 +0000127 for (size_t I = 0, E = Funcs.size(); I != E; ++I) {
128 InputFunction *F =
129 make<InputFunction>(Types[FuncTypes[I]], &Funcs[I], this);
130 F->copyRelocations(*CodeSection);
131 Functions.emplace_back(F);
132 }
133
134 // Populate `Globals`.
135 for (const WasmGlobal &G : WasmObj->globals())
136 Globals.emplace_back(make<InputGlobal>(G));
137
138 // Populate `Symbols` based on the WasmSymbols in the object.
139 Symbols.reserve(WasmObj->getNumberOfSymbols());
140 for (const SymbolRef &Sym : WasmObj->symbols()) {
141 const WasmSymbol &WasmSym = WasmObj->getWasmSymbol(Sym.getRawDataRefImpl());
142 if (Symbol *Sym = createDefined(WasmSym))
143 Symbols.push_back(Sym);
144 else
145 Symbols.push_back(createUndefined(WasmSym));
146 }
Sam Clegg93102972018-02-23 05:08:53 +0000147}
148
Sam Clegge0f6fcd2018-01-12 22:25:17 +0000149bool ObjFile::isExcludedByComdat(InputChunk *Chunk) const {
Rui Ueyamadcf62342018-03-01 23:29:05 +0000150 StringRef S = Chunk->getComdat();
151 if (S.empty())
152 return false;
153 return !Symtab->addComdat(S, this);
Sam Clegge0f6fcd2018-01-12 22:25:17 +0000154}
155
Sam Clegg93102972018-02-23 05:08:53 +0000156FunctionSymbol *ObjFile::getFunctionSymbol(uint32_t Index) const {
157 return cast<FunctionSymbol>(Symbols[Index]);
158}
159
160GlobalSymbol *ObjFile::getGlobalSymbol(uint32_t Index) const {
161 return cast<GlobalSymbol>(Symbols[Index]);
162}
163
164DataSymbol *ObjFile::getDataSymbol(uint32_t Index) const {
165 return cast<DataSymbol>(Symbols[Index]);
166}
167
Rui Ueyama4b56adc2018-02-28 00:50:54 +0000168Symbol *ObjFile::createDefined(const WasmSymbol &Sym) {
169 if (!Sym.isDefined())
170 return nullptr;
171
Rui Ueyamae89b0ef2018-03-02 21:19:55 +0000172 StringRef Name = Sym.Info.Name;
173 uint32_t Flags = Sym.Info.Flags;
174
Rui Ueyama4b56adc2018-02-28 00:50:54 +0000175 switch (Sym.Info.Kind) {
176 case WASM_SYMBOL_TYPE_FUNCTION: {
Rui Ueyama0a9583c2018-02-28 02:57:37 +0000177 InputFunction *Func =
178 Functions[Sym.Info.ElementIndex - WasmObj->getNumImportedFunctions()];
Rui Ueyama4b56adc2018-02-28 00:50:54 +0000179 if (isExcludedByComdat(Func)) {
180 Func->Live = false;
181 return nullptr;
182 }
183
184 if (Sym.isBindingLocal())
Rui Ueyamae89b0ef2018-03-02 21:19:55 +0000185 return make<DefinedFunction>(Name, Flags, this, Func);
186 return Symtab->addDefinedFunction(Name, Flags, this, Func);
Rui Ueyama4b56adc2018-02-28 00:50:54 +0000187 }
188 case WASM_SYMBOL_TYPE_DATA: {
Rui Ueyama0a9583c2018-02-28 02:57:37 +0000189 InputSegment *Seg = Segments[Sym.Info.DataRef.Segment];
Rui Ueyama4b56adc2018-02-28 00:50:54 +0000190 if (isExcludedByComdat(Seg)) {
191 Seg->Live = false;
192 return nullptr;
193 }
194
195 uint32_t Offset = Sym.Info.DataRef.Offset;
196 uint32_t Size = Sym.Info.DataRef.Size;
197
198 if (Sym.isBindingLocal())
Rui Ueyamae89b0ef2018-03-02 21:19:55 +0000199 return make<DefinedData>(Name, Flags, this, Seg, Offset, Size);
200 return Symtab->addDefinedData(Name, Flags, this, Seg, Offset, Size);
Rui Ueyama4b56adc2018-02-28 00:50:54 +0000201 }
202 case WASM_SYMBOL_TYPE_GLOBAL:
Rui Ueyama0a9583c2018-02-28 02:57:37 +0000203 InputGlobal *Global =
204 Globals[Sym.Info.ElementIndex - WasmObj->getNumImportedGlobals()];
Rui Ueyama4b56adc2018-02-28 00:50:54 +0000205 if (Sym.isBindingLocal())
Rui Ueyamae89b0ef2018-03-02 21:19:55 +0000206 return make<DefinedGlobal>(Name, Flags, this, Global);
207 return Symtab->addDefinedGlobal(Name, Flags, this, Global);
Rui Ueyama4b56adc2018-02-28 00:50:54 +0000208 }
209 llvm_unreachable("unkown symbol kind");
210}
211
Sam Clegg93102972018-02-23 05:08:53 +0000212Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) {
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000213 StringRef Name = Sym.Info.Name;
214 uint32_t Flags = Sym.Info.Flags;
215
216 switch (Sym.Info.Kind) {
217 case WASM_SYMBOL_TYPE_FUNCTION:
218 return Symtab->addUndefinedFunction(Name, Flags, this, Sym.FunctionType);
219 case WASM_SYMBOL_TYPE_DATA:
220 return Symtab->addUndefinedData(Name, Flags, this);
221 case WASM_SYMBOL_TYPE_GLOBAL:
222 return Symtab->addUndefinedGlobal(Name, Flags, this, Sym.GlobalType);
223 }
224 llvm_unreachable("unkown symbol kind");
Sam Cleggc94d3932017-11-17 18:14:09 +0000225}
226
Sam Cleggc94d3932017-11-17 18:14:09 +0000227void ArchiveFile::parse() {
228 // Parse a MemoryBufferRef as an archive file.
229 DEBUG(dbgs() << "Parsing library: " << toString(this) << "\n");
Rui Ueyamabdc51502017-12-06 22:08:17 +0000230 File = CHECK(Archive::create(MB), toString(this));
Sam Cleggc94d3932017-11-17 18:14:09 +0000231
232 // Read the symbol table to construct Lazy symbols.
233 int Count = 0;
234 for (const Archive::Symbol &Sym : File->symbols()) {
235 Symtab->addLazy(this, &Sym);
236 ++Count;
237 }
238 DEBUG(dbgs() << "Read " << Count << " symbols\n");
239}
240
241void ArchiveFile::addMember(const Archive::Symbol *Sym) {
242 const Archive::Child &C =
Rui Ueyamabdc51502017-12-06 22:08:17 +0000243 CHECK(Sym->getMember(),
Sam Cleggc94d3932017-11-17 18:14:09 +0000244 "could not get the member for symbol " + Sym->getName());
245
246 // Don't try to load the same member twice (this can happen when members
247 // mutually reference each other).
248 if (!Seen.insert(C.getChildOffset()).second)
249 return;
250
Sam Clegga681a112017-12-06 03:10:39 +0000251 DEBUG(dbgs() << "loading lazy: " << Sym->getName() << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000252 DEBUG(dbgs() << "from archive: " << toString(this) << "\n");
253
254 MemoryBufferRef MB =
Rui Ueyamabdc51502017-12-06 22:08:17 +0000255 CHECK(C.getMemoryBufferRef(),
Sam Cleggc94d3932017-11-17 18:14:09 +0000256 "could not get the buffer for the member defining symbol " +
257 Sym->getName());
258
259 if (identify_magic(MB.getBuffer()) != file_magic::wasm_object) {
260 error("unknown file type: " + MB.getBufferIdentifier());
261 return;
262 }
263
264 InputFile *Obj = make<ObjFile>(MB);
265 Obj->ParentName = ParentName;
266 Symtab->addFile(Obj);
267}
268
269// Returns a string in the format of "foo.o" or "foo.a(bar.o)".
Sam Clegg7e756632017-12-05 16:50:46 +0000270std::string lld::toString(const wasm::InputFile *File) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000271 if (!File)
272 return "<internal>";
273
274 if (File->ParentName.empty())
275 return File->getName();
276
277 return (File->ParentName + "(" + File->getName() + ")").str();
278}