1 //===- 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"
13 #include "InputSegment.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 Optional<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 
45 void ObjFile::dumpInfo() const {
46   log("reloc info for: " + getName() + "\n" +
47       "        FunctionIndexOffset : " + Twine(FunctionIndexOffset) + "\n" +
48       "         NumFunctionImports : " + Twine(NumFunctionImports()) + "\n" +
49       "           NumGlobalImports : " + Twine(NumGlobalImports()) + "\n");
50 }
51 
52 bool ObjFile::isImportedFunction(uint32_t Index) const {
53   return Index < NumFunctionImports();
54 }
55 
56 Symbol *ObjFile::getFunctionSymbol(uint32_t Index) const {
57   return FunctionSymbols[Index];
58 }
59 
60 Symbol *ObjFile::getTableSymbol(uint32_t Index) const {
61   return TableSymbols[Index];
62 }
63 
64 Symbol *ObjFile::getGlobalSymbol(uint32_t Index) const {
65   return GlobalSymbols[Index];
66 }
67 
68 uint32_t ObjFile::getRelocatedAddress(uint32_t Index) const {
69   return getGlobalSymbol(Index)->getVirtualAddress();
70 }
71 
72 uint32_t ObjFile::relocateFunctionIndex(uint32_t Original) const {
73   Symbol *Sym = getFunctionSymbol(Original);
74   uint32_t Index = Sym->getOutputIndex();
75   DEBUG(dbgs() << "relocateFunctionIndex: " << toString(*Sym) << ": "
76                << Original << " -> " << Index << "\n");
77   return Index;
78 }
79 
80 uint32_t ObjFile::relocateTypeIndex(uint32_t Original) const {
81   return TypeMap[Original];
82 }
83 
84 uint32_t ObjFile::relocateTableIndex(uint32_t Original) const {
85   Symbol *Sym = getTableSymbol(Original);
86   uint32_t Index = Sym->getTableIndex();
87   DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original
88                << " -> " << Index << "\n");
89   return Index;
90 }
91 
92 uint32_t ObjFile::relocateGlobalIndex(uint32_t Original) const {
93   Symbol *Sym = getGlobalSymbol(Original);
94   uint32_t Index = Sym->getOutputIndex();
95   DEBUG(dbgs() << "relocateGlobalIndex: " << toString(*Sym) << ": " << Original
96                << " -> " << Index << "\n");
97   return Index;
98 }
99 
100 void ObjFile::parse() {
101   // Parse a memory buffer as a wasm file.
102   DEBUG(dbgs() << "Parsing object: " << toString(this) << "\n");
103   std::unique_ptr<Binary> Bin = CHECK(createBinary(MB), toString(this));
104 
105   auto *Obj = dyn_cast<WasmObjectFile>(Bin.get());
106   if (!Obj)
107     fatal(toString(this) + ": not a wasm file");
108   if (!Obj->isRelocatableObject())
109     fatal(toString(this) + ": not a relocatable wasm file");
110 
111   Bin.release();
112   WasmObj.reset(Obj);
113 
114   // Find the code and data sections.  Wasm objects can have at most one code
115   // and one data section.
116   for (const SectionRef &Sec : WasmObj->sections()) {
117     const WasmSection &Section = WasmObj->getWasmSection(Sec);
118     if (Section.Type == WASM_SEC_CODE)
119       CodeSection = &Section;
120     else if (Section.Type == WASM_SEC_DATA)
121       DataSection = &Section;
122   }
123 
124   initializeSymbols();
125 }
126 
127 // Return the InputSegment in which a given symbol is defined.
128 InputSegment *ObjFile::getSegment(const WasmSymbol &WasmSym) {
129   uint32_t Address = WasmObj->getWasmSymbolValue(WasmSym);
130   for (InputSegment *Segment : Segments) {
131     if (Address >= Segment->startVA() && Address < Segment->endVA()) {
132       DEBUG(dbgs() << "Found symbol in segment: " << WasmSym.Name << " -> "
133                    << Segment->getName() << "\n");
134 
135       return Segment;
136     }
137   }
138   error("symbol not found in any segment: " + WasmSym.Name);
139   return nullptr;
140 }
141 
142 static void copyRelocationsRange(std::vector<WasmRelocation> &To,
143                                  ArrayRef<WasmRelocation> From, size_t Start,
144                                  size_t End) {
145   for (const WasmRelocation &R : From)
146     if (R.Offset >= Start && R.Offset < End)
147       To.push_back(R);
148 }
149 
150 void ObjFile::initializeSymbols() {
151   Symbols.reserve(WasmObj->getNumberOfSymbols());
152 
153   for (const WasmImport &Import : WasmObj->imports()) {
154     switch (Import.Kind) {
155     case WASM_EXTERNAL_FUNCTION:
156       ++FunctionImports;
157       break;
158     case WASM_EXTERNAL_GLOBAL:
159       ++GlobalImports;
160       break;
161     }
162   }
163 
164   FunctionSymbols.resize(FunctionImports + WasmObj->functions().size());
165   GlobalSymbols.resize(GlobalImports + WasmObj->globals().size());
166 
167   for (const WasmSegment &S : WasmObj->dataSegments()) {
168     InputSegment *Seg = make<InputSegment>(&S, this);
169     copyRelocationsRange(Seg->Relocations, DataSection->Relocations,
170                          Seg->getInputSectionOffset(),
171                          Seg->getInputSectionOffset() + Seg->getSize());
172     Segments.emplace_back(Seg);
173   }
174 
175   // Populate `FunctionSymbols` and `GlobalSymbols` based on the WasmSymbols
176   // in the object
177   for (const SymbolRef &Sym : WasmObj->symbols()) {
178     const WasmSymbol &WasmSym = WasmObj->getWasmSymbol(Sym.getRawDataRefImpl());
179     Symbol *S;
180     switch (WasmSym.Type) {
181     case WasmSymbol::SymbolType::FUNCTION_IMPORT:
182     case WasmSymbol::SymbolType::GLOBAL_IMPORT:
183       S = createUndefined(WasmSym);
184       break;
185     case WasmSymbol::SymbolType::GLOBAL_EXPORT:
186       S = createDefined(WasmSym, getSegment(WasmSym));
187       break;
188     case WasmSymbol::SymbolType::FUNCTION_EXPORT:
189       S = createDefined(WasmSym);
190       break;
191     case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
192       // These are for debugging only, no need to create linker symbols for them
193       continue;
194     }
195 
196     Symbols.push_back(S);
197     if (WasmSym.isFunction()) {
198       DEBUG(dbgs() << "Function: " << WasmSym.ElementIndex << " -> "
199                    << toString(*S) << "\n");
200       FunctionSymbols[WasmSym.ElementIndex] = S;
201       if (WasmSym.HasAltIndex)
202         FunctionSymbols[WasmSym.AltIndex] = S;
203     } else {
204       DEBUG(dbgs() << "Global: " << WasmSym.ElementIndex << " -> "
205                    << toString(*S) << "\n");
206       GlobalSymbols[WasmSym.ElementIndex] = S;
207       if (WasmSym.HasAltIndex)
208         GlobalSymbols[WasmSym.AltIndex] = S;
209     }
210   }
211 
212   DEBUG(for (size_t I = 0; I < FunctionSymbols.size(); ++I)
213             assert(FunctionSymbols[I] != nullptr);
214         for (size_t I = 0; I < GlobalSymbols.size(); ++I)
215             assert(GlobalSymbols[I] != nullptr););
216 
217   // Populate `TableSymbols` with all symbols that are called indirectly
218   uint32_t SegmentCount = WasmObj->elements().size();
219   if (SegmentCount) {
220     if (SegmentCount > 1)
221       fatal(getName() + ": contains more than one element segment");
222     const WasmElemSegment &Segment = WasmObj->elements()[0];
223     if (Segment.Offset.Opcode != WASM_OPCODE_I32_CONST)
224       fatal(getName() + ": unsupported element segment");
225     if (Segment.TableIndex != 0)
226       fatal(getName() + ": unsupported table index in elem segment");
227     if (Segment.Offset.Value.Int32 != 0)
228       fatal(getName() + ": unsupported element segment offset");
229     TableSymbols.reserve(Segment.Functions.size());
230     for (uint64_t FunctionIndex : Segment.Functions)
231       TableSymbols.push_back(getFunctionSymbol(FunctionIndex));
232   }
233 
234   DEBUG(dbgs() << "TableSymbols: " << TableSymbols.size() << "\n");
235   DEBUG(dbgs() << "Functions   : " << FunctionSymbols.size() << "\n");
236   DEBUG(dbgs() << "Globals     : " << GlobalSymbols.size() << "\n");
237 }
238 
239 Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) {
240   return Symtab->addUndefined(this, &Sym);
241 }
242 
243 Symbol *ObjFile::createDefined(const WasmSymbol &Sym,
244                                const InputSegment *Segment) {
245   Symbol *S;
246   if (Sym.isLocal()) {
247     S = make<Symbol>(Sym.Name, true);
248     Symbol::Kind Kind;
249     if (Sym.Type == WasmSymbol::SymbolType::FUNCTION_EXPORT)
250       Kind = Symbol::Kind::DefinedFunctionKind;
251     else if (Sym.Type == WasmSymbol::SymbolType::GLOBAL_EXPORT)
252       Kind = Symbol::Kind::DefinedGlobalKind;
253     else
254       llvm_unreachable("invalid local symbol type");
255     S->update(Kind, this, &Sym, Segment);
256     return S;
257   }
258   return Symtab->addDefined(this, &Sym, Segment);
259 }
260 
261 void ArchiveFile::parse() {
262   // Parse a MemoryBufferRef as an archive file.
263   DEBUG(dbgs() << "Parsing library: " << toString(this) << "\n");
264   File = CHECK(Archive::create(MB), toString(this));
265 
266   // Read the symbol table to construct Lazy symbols.
267   int Count = 0;
268   for (const Archive::Symbol &Sym : File->symbols()) {
269     Symtab->addLazy(this, &Sym);
270     ++Count;
271   }
272   DEBUG(dbgs() << "Read " << Count << " symbols\n");
273 }
274 
275 void ArchiveFile::addMember(const Archive::Symbol *Sym) {
276   const Archive::Child &C =
277       CHECK(Sym->getMember(),
278             "could not get the member for symbol " + Sym->getName());
279 
280   // Don't try to load the same member twice (this can happen when members
281   // mutually reference each other).
282   if (!Seen.insert(C.getChildOffset()).second)
283     return;
284 
285   DEBUG(dbgs() << "loading lazy: " << Sym->getName() << "\n");
286   DEBUG(dbgs() << "from archive: " << toString(this) << "\n");
287 
288   MemoryBufferRef MB =
289       CHECK(C.getMemoryBufferRef(),
290             "could not get the buffer for the member defining symbol " +
291                 Sym->getName());
292 
293   if (identify_magic(MB.getBuffer()) != file_magic::wasm_object) {
294     error("unknown file type: " + MB.getBufferIdentifier());
295     return;
296   }
297 
298   InputFile *Obj = make<ObjFile>(MB);
299   Obj->ParentName = ParentName;
300   Symtab->addFile(Obj);
301 }
302 
303 // Returns a string in the format of "foo.o" or "foo.a(bar.o)".
304 std::string lld::toString(const wasm::InputFile *File) {
305   if (!File)
306     return "<internal>";
307 
308   if (File->ParentName.empty())
309     return File->getName();
310 
311   return (File->ParentName + "(" + File->getName() + ")").str();
312 }
313