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