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 void ObjFile::initializeSymbols() {
143   Symbols.reserve(WasmObj->getNumberOfSymbols());
144 
145   for (const WasmImport &Import : WasmObj->imports()) {
146     switch (Import.Kind) {
147     case WASM_EXTERNAL_FUNCTION:
148       ++FunctionImports;
149       break;
150     case WASM_EXTERNAL_GLOBAL:
151       ++GlobalImports;
152       break;
153     }
154   }
155 
156   FunctionSymbols.resize(FunctionImports + WasmObj->functions().size());
157   GlobalSymbols.resize(GlobalImports + WasmObj->globals().size());
158 
159   for (const WasmSegment &Seg : WasmObj->dataSegments())
160     Segments.emplace_back(make<InputSegment>(&Seg, this));
161 
162   // Populate `FunctionSymbols` and `GlobalSymbols` based on the WasmSymbols
163   // in the object
164   for (const SymbolRef &Sym : WasmObj->symbols()) {
165     const WasmSymbol &WasmSym = WasmObj->getWasmSymbol(Sym.getRawDataRefImpl());
166     Symbol *S;
167     switch (WasmSym.Type) {
168     case WasmSymbol::SymbolType::FUNCTION_IMPORT:
169     case WasmSymbol::SymbolType::GLOBAL_IMPORT:
170       S = createUndefined(WasmSym);
171       break;
172     case WasmSymbol::SymbolType::GLOBAL_EXPORT:
173       S = createDefined(WasmSym, getSegment(WasmSym));
174       break;
175     case WasmSymbol::SymbolType::FUNCTION_EXPORT:
176       S = createDefined(WasmSym);
177       break;
178     case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
179       // These are for debugging only, no need to create linker symbols for them
180       continue;
181     }
182 
183     Symbols.push_back(S);
184     if (WasmSym.isFunction()) {
185       DEBUG(dbgs() << "Function: " << WasmSym.ElementIndex << " -> "
186                    << toString(*S) << "\n");
187       FunctionSymbols[WasmSym.ElementIndex] = S;
188     } else {
189       DEBUG(dbgs() << "Global: " << WasmSym.ElementIndex << " -> "
190                    << toString(*S) << "\n");
191       GlobalSymbols[WasmSym.ElementIndex] = S;
192     }
193   }
194 
195   // Populate `TableSymbols` with all symbols that are called indirectly
196   uint32_t SegmentCount = WasmObj->elements().size();
197   if (SegmentCount) {
198     if (SegmentCount > 1)
199       fatal(getName() + ": contains more than one element segment");
200     const WasmElemSegment &Segment = WasmObj->elements()[0];
201     if (Segment.Offset.Opcode != WASM_OPCODE_I32_CONST)
202       fatal(getName() + ": unsupported element segment");
203     if (Segment.TableIndex != 0)
204       fatal(getName() + ": unsupported table index in elem segment");
205     if (Segment.Offset.Value.Int32 != 0)
206       fatal(getName() + ": unsupported element segment offset");
207     TableSymbols.reserve(Segment.Functions.size());
208     for (uint64_t FunctionIndex : Segment.Functions)
209       TableSymbols.push_back(getFunctionSymbol(FunctionIndex));
210   }
211 
212   DEBUG(dbgs() << "TableSymbols: " << TableSymbols.size() << "\n");
213   DEBUG(dbgs() << "Functions   : " << FunctionSymbols.size() << "\n");
214   DEBUG(dbgs() << "Globals     : " << GlobalSymbols.size() << "\n");
215 }
216 
217 Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) {
218   return Symtab->addUndefined(this, &Sym);
219 }
220 
221 Symbol *ObjFile::createDefined(const WasmSymbol &Sym,
222                                const InputSegment *Segment) {
223   Symbol *S;
224   if (Sym.isLocal()) {
225     S = make<Symbol>(Sym.Name, true);
226     Symbol::Kind Kind;
227     if (Sym.Type == WasmSymbol::SymbolType::FUNCTION_EXPORT)
228       Kind = Symbol::Kind::DefinedFunctionKind;
229     else if (Sym.Type == WasmSymbol::SymbolType::GLOBAL_EXPORT)
230       Kind = Symbol::Kind::DefinedGlobalKind;
231     else
232       llvm_unreachable("invalid local symbol type");
233     S->update(Kind, this, &Sym, Segment);
234     return S;
235   }
236   return Symtab->addDefined(this, &Sym, Segment);
237 }
238 
239 void ArchiveFile::parse() {
240   // Parse a MemoryBufferRef as an archive file.
241   DEBUG(dbgs() << "Parsing library: " << toString(this) << "\n");
242   File = CHECK(Archive::create(MB), toString(this));
243 
244   // Read the symbol table to construct Lazy symbols.
245   int Count = 0;
246   for (const Archive::Symbol &Sym : File->symbols()) {
247     Symtab->addLazy(this, &Sym);
248     ++Count;
249   }
250   DEBUG(dbgs() << "Read " << Count << " symbols\n");
251 }
252 
253 void ArchiveFile::addMember(const Archive::Symbol *Sym) {
254   const Archive::Child &C =
255       CHECK(Sym->getMember(),
256             "could not get the member for symbol " + Sym->getName());
257 
258   // Don't try to load the same member twice (this can happen when members
259   // mutually reference each other).
260   if (!Seen.insert(C.getChildOffset()).second)
261     return;
262 
263   DEBUG(dbgs() << "loading lazy: " << Sym->getName() << "\n");
264   DEBUG(dbgs() << "from archive: " << toString(this) << "\n");
265 
266   MemoryBufferRef MB =
267       CHECK(C.getMemoryBufferRef(),
268             "could not get the buffer for the member defining symbol " +
269                 Sym->getName());
270 
271   if (identify_magic(MB.getBuffer()) != file_magic::wasm_object) {
272     error("unknown file type: " + MB.getBufferIdentifier());
273     return;
274   }
275 
276   InputFile *Obj = make<ObjFile>(MB);
277   Obj->ParentName = ParentName;
278   Symtab->addFile(Obj);
279 }
280 
281 // Returns a string in the format of "foo.o" or "foo.a(bar.o)".
282 std::string lld::toString(const wasm::InputFile *File) {
283   if (!File)
284     return "<internal>";
285 
286   if (File->ParentName.empty())
287     return File->getName();
288 
289   return (File->ParentName + "(" + File->getName() + ")").str();
290 }
291