diff options
Diffstat (limited to 'COFF/InputFiles.cpp')
-rw-r--r-- | COFF/InputFiles.cpp | 156 |
1 files changed, 119 insertions, 37 deletions
diff --git a/COFF/InputFiles.cpp b/COFF/InputFiles.cpp index c00d5c5b494e..faec3ba160a5 100644 --- a/COFF/InputFiles.cpp +++ b/COFF/InputFiles.cpp @@ -47,6 +47,24 @@ using llvm::Triple; using llvm::support::ulittle32_t; namespace lld { + +// Returns the last element of a path, which is supposed to be a filename. +static StringRef getBasename(StringRef path) { + return sys::path::filename(path, sys::path::Style::windows); +} + +// Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)". +std::string toString(const coff::InputFile *file) { + if (!file) + return "<internal>"; + if (file->parentName.empty() || file->kind() == coff::InputFile::ImportKind) + return file->getName(); + + return (getBasename(file->parentName) + "(" + getBasename(file->getName()) + + ")") + .str(); +} + namespace coff { std::vector<ObjFile *> ObjFile::instances; @@ -73,6 +91,10 @@ static void checkAndSetWeakAlias(SymbolTable *symtab, InputFile *f, } } +static bool ignoredSymbolName(StringRef name) { + return name == "@feat.00" || name == "@comp.id"; +} + ArchiveFile::ArchiveFile(MemoryBufferRef m) : InputFile(ArchiveKind, m) {} void ArchiveFile::parse() { @@ -81,20 +103,20 @@ void ArchiveFile::parse() { // Read the symbol table to construct Lazy objects. for (const Archive::Symbol &sym : file->symbols()) - symtab->addLazy(this, sym); + symtab->addLazyArchive(this, sym); } // Returns a buffer pointing to a member file containing a given symbol. -void ArchiveFile::addMember(const Archive::Symbol *sym) { +void ArchiveFile::addMember(const Archive::Symbol &sym) { const Archive::Child &c = - CHECK(sym->getMember(), - "could not get the member for symbol " + sym->getName()); + CHECK(sym.getMember(), + "could not get the member for symbol " + toCOFFString(sym)); // Return an empty buffer if we have already returned the same buffer. if (!seen.insert(c.getChildOffset()).second) return; - driver->enqueueArchiveMember(c, sym->getName(), getName()); + driver->enqueueArchiveMember(c, sym, getName()); } std::vector<MemoryBufferRef> getArchiveMembers(Archive *file) { @@ -116,6 +138,49 @@ std::vector<MemoryBufferRef> getArchiveMembers(Archive *file) { return v; } +void LazyObjFile::fetch() { + if (mb.getBuffer().empty()) + return; + + InputFile *file; + if (isBitcode(mb)) + file = make<BitcodeFile>(mb, "", 0, std::move(symbols)); + else + file = make<ObjFile>(mb, std::move(symbols)); + mb = {}; + symtab->addFile(file); +} + +void LazyObjFile::parse() { + if (isBitcode(this->mb)) { + // Bitcode file. + std::unique_ptr<lto::InputFile> obj = + CHECK(lto::InputFile::create(this->mb), this); + for (const lto::InputFile::Symbol &sym : obj->symbols()) { + if (!sym.isUndefined()) + symtab->addLazyObject(this, sym.getName()); + } + return; + } + + // Native object file. + std::unique_ptr<Binary> coffObjPtr = CHECK(createBinary(mb), this); + COFFObjectFile *coffObj = cast<COFFObjectFile>(coffObjPtr.get()); + uint32_t numSymbols = coffObj->getNumberOfSymbols(); + for (uint32_t i = 0; i < numSymbols; ++i) { + COFFSymbolRef coffSym = check(coffObj->getSymbol(i)); + if (coffSym.isUndefined() || !coffSym.isExternal() || + coffSym.isWeakExternal()) + continue; + StringRef name; + coffObj->getSymbolName(coffSym, name); + if (coffSym.isAbsolute() && ignoredSymbolName(name)) + continue; + symtab->addLazyObject(this, name); + i += coffSym.getNumberOfAuxSymbols(); + } +} + void ObjFile::parse() { // Parse a memory buffer as a COFF file. std::unique_ptr<Binary> bin = CHECK(createBinary(mb), this); @@ -206,10 +271,6 @@ SectionChunk *ObjFile::readSection(uint32_t sectionNumber, if (def) c->checksum = def->CheckSum; - // link.exe uses the presence of .rsrc$01 for LNK4078, so match that. - if (name == ".rsrc$01") - isResourceObjFile = true; - // CodeView sections are stored to a different vector because they are not // linked in the regular manner. if (c->isCodeView()) @@ -226,12 +287,18 @@ SectionChunk *ObjFile::readSection(uint32_t sectionNumber, // relocations, in .rdata, leader symbol name matches the MSVC name mangling // for string literals) are subject to string tail merging. MergeChunk::addSection(c); + else if (name == ".rsrc" || name.startswith(".rsrc$")) + resourceChunks.push_back(c); else chunks.push_back(c); return c; } +void ObjFile::includeResourceChunks() { + chunks.insert(chunks.end(), resourceChunks.begin(), resourceChunks.end()); +} + void ObjFile::readAssociativeDefinition( COFFSymbolRef sym, const coff_aux_section_definition *def) { readAssociativeDefinition(sym, def, def->getNumber(sym.isBigObj())); @@ -315,7 +382,8 @@ Symbol *ObjFile::createRegular(COFFSymbolRef sym) { StringRef name; coffObj->getSymbolName(sym, name); if (sc) - return symtab->addRegular(this, name, sym.getGeneric(), sc); + return symtab->addRegular(this, name, sym.getGeneric(), sc, + sym.getValue()); // For MinGW symbols named .weak.* that point to a discarded section, // don't create an Undefined symbol. If nothing ever refers to the symbol, // everything should be fine. If something actually refers to the symbol @@ -469,7 +537,7 @@ void ObjFile::handleComdatSelection(COFFSymbolRef sym, COMDATType &selection, // if the two comdat sections have e.g. different alignment. // Match that. if (leaderChunk->getContents() != newChunk.getContents()) - symtab->reportDuplicate(leader, this); + symtab->reportDuplicate(leader, this, &newChunk, sym.getValue()); break; } @@ -524,13 +592,11 @@ Optional<Symbol *> ObjFile::createDefined( if (sym.isAbsolute()) { StringRef name = getName(); - // Skip special symbols. - if (name == "@comp.id") - return nullptr; - if (name == "@feat.00") { + if (name == "@feat.00") feat00Flags = sym.getValue(); + // Skip special symbols. + if (ignoredSymbolName(name)) return nullptr; - } if (sym.isExternal()) return symtab->addAbsolute(name, sym); @@ -552,7 +618,7 @@ Optional<Symbol *> ObjFile::createDefined( // Comdat handling. // A comdat symbol consists of two symbol table entries. // The first symbol entry has the name of the section (e.g. .text), fixed - // values for the other fields, and one auxilliary record. + // values for the other fields, and one auxiliary record. // The second symbol entry has the name of the comdat symbol, called the // "comdat leader". // When this function is called for the first symbol entry of a comdat, @@ -622,7 +688,7 @@ ArrayRef<uint8_t> ObjFile::getDebugSection(StringRef secName) { return {}; } -// OBJ files systematically store critical informations in a .debug$S stream, +// OBJ files systematically store critical information in a .debug$S stream, // even if the TU was compiled with no debug info. At least two records are // always there. S_OBJNAME stores a 32-bit signature, which is loaded into the // PCHSignature member. S_COMPILE3 stores compile-time cmd-line flags. This is @@ -723,6 +789,37 @@ void ObjFile::initializeDependencies() { debugTypesObj = makeTpiSource(this); } +// Used only for DWARF debug info, which is not common (except in MinGW +// environments). This returns an optional pair of file name and line +// number for where the variable was defined. +Optional<std::pair<StringRef, uint32_t>> +ObjFile::getVariableLocation(StringRef var) { + if (!dwarf) { + dwarf = make<DWARFCache>(DWARFContext::create(*getCOFFObj())); + if (!dwarf) + return None; + } + if (config->machine == I386) + var.consume_front("_"); + Optional<std::pair<std::string, unsigned>> ret = dwarf->getVariableLoc(var); + if (!ret) + return None; + return std::make_pair(saver.save(ret->first), ret->second); +} + +// Used only for DWARF debug info, which is not common (except in MinGW +// environments). +Optional<DILineInfo> ObjFile::getDILineInfo(uint32_t offset, + uint32_t sectionIndex) { + if (!dwarf) { + dwarf = make<DWARFCache>(DWARFContext::create(*getCOFFObj())); + if (!dwarf) + return None; + } + + return dwarf->getDILineInfo(offset, sectionIndex); +} + StringRef ltrim1(StringRef s, const char *chars) { if (!s.empty() && strchr(chars, s[0])) return s.substr(1); @@ -780,8 +877,9 @@ void ImportFile::parse() { } BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName, - uint64_t offsetInArchive) - : InputFile(BitcodeKind, mb) { + uint64_t offsetInArchive, + std::vector<Symbol *> &&symbols) + : InputFile(BitcodeKind, mb), symbols(std::move(symbols)) { std::string path = mb.getBufferIdentifier().str(); if (config->thinLTOIndexOnly) path = replaceThinLTOSuffix(mb.getBufferIdentifier()); @@ -860,22 +958,6 @@ std::string replaceThinLTOSuffix(StringRef path) { return (path + repl).str(); return path; } + } // namespace coff } // namespace lld - -// Returns the last element of a path, which is supposed to be a filename. -static StringRef getBasename(StringRef path) { - return sys::path::filename(path, sys::path::Style::windows); -} - -// Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)". -std::string lld::toString(const coff::InputFile *file) { - if (!file) - return "<internal>"; - if (file->parentName.empty() || file->kind() == coff::InputFile::ImportKind) - return file->getName(); - - return (getBasename(file->parentName) + "(" + getBasename(file->getName()) + - ")") - .str(); -} |