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