mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
Vendor import of lld trunk r308421:
https://llvm.org/svn/llvm-project/lld/trunk@308421
This commit is contained in:
parent
2678297743
commit
da06c7cfa0
135 changed files with 1878 additions and 396 deletions
|
|
@ -210,7 +210,15 @@ void SectionChunk::writeTo(uint8_t *Buf) const {
|
|||
memcpy(Buf + OutputSectionOff, A.data(), A.size());
|
||||
|
||||
// Apply relocations.
|
||||
size_t InputSize = getSize();
|
||||
for (const coff_relocation &Rel : Relocs) {
|
||||
// Check for an invalid relocation offset. This check isn't perfect, because
|
||||
// we don't have the relocation size, which is only known after checking the
|
||||
// machine and relocation type. As a result, a relocation may overwrite the
|
||||
// beginning of the following input section.
|
||||
if (Rel.VirtualAddress >= InputSize)
|
||||
fatal("relocation points beyond the end of its parent section");
|
||||
|
||||
uint8_t *Off = Buf + OutputSectionOff + Rel.VirtualAddress;
|
||||
|
||||
// Get the output section of the symbol for this relocation. The output
|
||||
|
|
@ -227,7 +235,7 @@ void SectionChunk::writeTo(uint8_t *Buf) const {
|
|||
// sections are not GC roots and can end up with these kinds of relocations.
|
||||
// Skip these relocations.
|
||||
if (!OS && !isa<DefinedAbsolute>(Sym) && !isa<DefinedSynthetic>(Sym)) {
|
||||
if (isCodeView())
|
||||
if (isCodeView() || isDWARF())
|
||||
continue;
|
||||
fatal("relocation against symbol in discarded section: " +
|
||||
Sym->getName());
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ protected:
|
|||
};
|
||||
|
||||
// A chunk corresponding a section of an input file.
|
||||
class SectionChunk : public Chunk {
|
||||
class SectionChunk final : public Chunk {
|
||||
// Identical COMDAT Folding feature accesses section internal data.
|
||||
friend class ICF;
|
||||
|
||||
|
|
@ -188,6 +188,9 @@ public:
|
|||
return SectionName == ".debug" || SectionName.startswith(".debug$");
|
||||
}
|
||||
|
||||
// True if this is a DWARF debug info chunk.
|
||||
bool isDWARF() const { return SectionName.startswith(".debug_"); }
|
||||
|
||||
// Allow iteration over the bodies of this chunk's relocated symbols.
|
||||
llvm::iterator_range<symbol_iterator> symbols() const {
|
||||
return llvm::make_range(symbol_iterator(File, Relocs.begin()),
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ struct Configuration {
|
|||
SymbolBody *Entry = nullptr;
|
||||
bool NoEntry = false;
|
||||
std::string OutputFile;
|
||||
std::string ImportName;
|
||||
bool ColorDiagnostics;
|
||||
bool DoGC = true;
|
||||
bool DoICF = true;
|
||||
|
|
|
|||
|
|
@ -429,7 +429,32 @@ static std::string getImplibPath() {
|
|||
return Out.str();
|
||||
}
|
||||
|
||||
static void createImportLibrary() {
|
||||
//
|
||||
// The import name is caculated as the following:
|
||||
//
|
||||
// | LIBRARY w/ ext | LIBRARY w/o ext | no LIBRARY
|
||||
// -----+----------------+---------------------+------------------
|
||||
// LINK | {value} | {value}.{.dll/.exe} | {output name}
|
||||
// LIB | {value} | {value}.dll | {output name}.dll
|
||||
//
|
||||
static std::string getImportName(bool AsLib) {
|
||||
SmallString<128> Out;
|
||||
|
||||
if (Config->ImportName.empty()) {
|
||||
Out.assign(sys::path::filename(Config->OutputFile));
|
||||
if (AsLib)
|
||||
sys::path::replace_extension(Out, ".dll");
|
||||
} else {
|
||||
Out.assign(Config->ImportName);
|
||||
if (!sys::path::has_extension(Out))
|
||||
sys::path::replace_extension(Out,
|
||||
(Config->DLL || AsLib) ? ".dll" : ".exe");
|
||||
}
|
||||
|
||||
return Out.str();
|
||||
}
|
||||
|
||||
static void createImportLibrary(bool AsLib) {
|
||||
std::vector<COFFShortExport> Exports;
|
||||
for (Export &E1 : Config->Exports) {
|
||||
COFFShortExport E2;
|
||||
|
|
@ -444,9 +469,8 @@ static void createImportLibrary() {
|
|||
Exports.push_back(E2);
|
||||
}
|
||||
|
||||
std::string DLLName = sys::path::filename(Config->OutputFile);
|
||||
std::string Path = getImplibPath();
|
||||
writeImportLibrary(DLLName, Path, Exports, Config->Machine);
|
||||
writeImportLibrary(getImportName(AsLib), getImplibPath(), Exports,
|
||||
Config->Machine);
|
||||
}
|
||||
|
||||
static void parseModuleDefs(StringRef Path) {
|
||||
|
|
@ -457,6 +481,7 @@ static void parseModuleDefs(StringRef Path) {
|
|||
|
||||
if (Config->OutputFile.empty())
|
||||
Config->OutputFile = Saver.save(M.OutputFile);
|
||||
Config->ImportName = Saver.save(M.ImportName);
|
||||
if (M.ImageBase)
|
||||
Config->ImageBase = M.ImageBase;
|
||||
if (M.StackReserve)
|
||||
|
|
@ -992,7 +1017,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
|
|||
// Handle generation of import library from a def file.
|
||||
if (!Args.hasArgNoClaim(OPT_INPUT)) {
|
||||
fixupExports();
|
||||
createImportLibrary();
|
||||
createImportLibrary(/*AsLib=*/true);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
|
@ -1117,7 +1142,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
|
|||
// need to create a .lib file.
|
||||
if (!Config->Exports.empty() || Config->DLL) {
|
||||
fixupExports();
|
||||
createImportLibrary();
|
||||
createImportLibrary(/*AsLib=*/false);
|
||||
assignExportOrdinals();
|
||||
}
|
||||
|
||||
|
|
|
|||
424
COFF/PDB.cpp
424
COFF/PDB.cpp
|
|
@ -14,28 +14,29 @@
|
|||
#include "SymbolTable.h"
|
||||
#include "Symbols.h"
|
||||
#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
|
||||
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
|
||||
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
|
||||
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
|
||||
#include "llvm/DebugInfo/MSF/MSFCommon.h"
|
||||
#include "llvm/DebugInfo/PDB/GenericError.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
|
||||
#include "llvm/DebugInfo/PDB/PDB.h"
|
||||
#include "llvm/Object/COFF.h"
|
||||
#include "llvm/Support/BinaryByteStream.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
|
@ -53,8 +54,81 @@ using llvm::object::coff_section;
|
|||
|
||||
static ExitOnError ExitOnErr;
|
||||
|
||||
namespace {
|
||||
/// Map from type index and item index in a type server PDB to the
|
||||
/// corresponding index in the destination PDB.
|
||||
struct CVIndexMap {
|
||||
SmallVector<TypeIndex, 0> TPIMap;
|
||||
SmallVector<TypeIndex, 0> IPIMap;
|
||||
bool IsTypeServerMap = false;
|
||||
};
|
||||
|
||||
class PDBLinker {
|
||||
public:
|
||||
PDBLinker(SymbolTable *Symtab)
|
||||
: Alloc(), Symtab(Symtab), Builder(Alloc), TypeTable(Alloc),
|
||||
IDTable(Alloc) {}
|
||||
|
||||
/// Emit the basic PDB structure: initial streams, headers, etc.
|
||||
void initialize(const llvm::codeview::DebugInfo *DI);
|
||||
|
||||
/// Link CodeView from each object file in the symbol table into the PDB.
|
||||
void addObjectsToPDB();
|
||||
|
||||
/// Link CodeView from a single object file into the PDB.
|
||||
void addObjectFile(ObjectFile *File);
|
||||
|
||||
/// Produce a mapping from the type and item indices used in the object
|
||||
/// file to those in the destination PDB.
|
||||
///
|
||||
/// If the object file uses a type server PDB (compiled with /Zi), merge TPI
|
||||
/// and IPI from the type server PDB and return a map for it. Each unique type
|
||||
/// server PDB is merged at most once, so this may return an existing index
|
||||
/// mapping.
|
||||
///
|
||||
/// If the object does not use a type server PDB (compiled with /Z7), we merge
|
||||
/// all the type and item records from the .debug$S stream and fill in the
|
||||
/// caller-provided ObjectIndexMap.
|
||||
const CVIndexMap &mergeDebugT(ObjectFile *File, CVIndexMap &ObjectIndexMap);
|
||||
|
||||
const CVIndexMap &maybeMergeTypeServerPDB(ObjectFile *File,
|
||||
TypeServer2Record &TS);
|
||||
|
||||
/// Add the section map and section contributions to the PDB.
|
||||
void addSections(ArrayRef<uint8_t> SectionTable);
|
||||
|
||||
/// Write the PDB to disk.
|
||||
void commit();
|
||||
|
||||
private:
|
||||
BumpPtrAllocator Alloc;
|
||||
|
||||
SymbolTable *Symtab;
|
||||
|
||||
pdb::PDBFileBuilder Builder;
|
||||
|
||||
/// Type records that will go into the PDB TPI stream.
|
||||
TypeTableBuilder TypeTable;
|
||||
|
||||
/// Item records that will go into the PDB IPI stream.
|
||||
TypeTableBuilder IDTable;
|
||||
|
||||
/// PDBs use a single global string table for filenames in the file checksum
|
||||
/// table.
|
||||
DebugStringTableSubsection PDBStrTab;
|
||||
|
||||
llvm::SmallString<128> NativePath;
|
||||
|
||||
std::vector<pdb::SecMapEntry> SectionMap;
|
||||
|
||||
/// Type index mappings of type server PDBs that we've loaded so far.
|
||||
std::map<GUID, CVIndexMap> TypeServerIndexMappings;
|
||||
};
|
||||
}
|
||||
|
||||
// Returns a list of all SectionChunks.
|
||||
static void addSectionContribs(SymbolTable *Symtab, pdb::DbiStreamBuilder &DbiBuilder) {
|
||||
static void addSectionContribs(SymbolTable *Symtab,
|
||||
pdb::DbiStreamBuilder &DbiBuilder) {
|
||||
for (Chunk *C : Symtab->getChunks())
|
||||
if (auto *SC = dyn_cast<SectionChunk>(C))
|
||||
DbiBuilder.addSectionContrib(SC->File->ModuleDBI, SC->Header);
|
||||
|
|
@ -96,24 +170,115 @@ static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder,
|
|||
});
|
||||
}
|
||||
|
||||
static void mergeDebugT(ObjectFile *File,
|
||||
TypeTableBuilder &IDTable,
|
||||
TypeTableBuilder &TypeTable,
|
||||
SmallVectorImpl<TypeIndex> &TypeIndexMap,
|
||||
pdb::PDBTypeServerHandler &Handler) {
|
||||
static Optional<TypeServer2Record>
|
||||
maybeReadTypeServerRecord(CVTypeArray &Types) {
|
||||
auto I = Types.begin();
|
||||
if (I == Types.end())
|
||||
return None;
|
||||
const CVType &Type = *I;
|
||||
if (Type.kind() != LF_TYPESERVER2)
|
||||
return None;
|
||||
TypeServer2Record TS;
|
||||
if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(Type), TS))
|
||||
fatal(EC, "error reading type server record");
|
||||
return std::move(TS);
|
||||
}
|
||||
|
||||
const CVIndexMap &PDBLinker::mergeDebugT(ObjectFile *File,
|
||||
CVIndexMap &ObjectIndexMap) {
|
||||
ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
|
||||
if (Data.empty())
|
||||
return;
|
||||
return ObjectIndexMap;
|
||||
|
||||
BinaryByteStream Stream(Data, support::little);
|
||||
CVTypeArray Types;
|
||||
BinaryStreamReader Reader(Stream);
|
||||
Handler.addSearchPath(sys::path::parent_path(File->getName()));
|
||||
if (auto EC = Reader.readArray(Types, Reader.getLength()))
|
||||
fatal(EC, "Reader::readArray failed");
|
||||
|
||||
// Look through type servers. If we've already seen this type server, don't
|
||||
// merge any type information.
|
||||
if (Optional<TypeServer2Record> TS = maybeReadTypeServerRecord(Types))
|
||||
return maybeMergeTypeServerPDB(File, *TS);
|
||||
|
||||
// This is a /Z7 object. Fill in the temporary, caller-provided
|
||||
// ObjectIndexMap.
|
||||
if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable,
|
||||
TypeIndexMap, &Handler, Types))
|
||||
fatal(Err, "codeview::mergeTypeStreams failed");
|
||||
ObjectIndexMap.TPIMap, Types))
|
||||
fatal(Err, "codeview::mergeTypeAndIdRecords failed");
|
||||
return ObjectIndexMap;
|
||||
}
|
||||
|
||||
static Expected<std::unique_ptr<pdb::NativeSession>>
|
||||
tryToLoadPDB(const GUID &GuidFromObj, StringRef TSPath) {
|
||||
std::unique_ptr<pdb::IPDBSession> ThisSession;
|
||||
if (auto EC =
|
||||
pdb::loadDataForPDB(pdb::PDB_ReaderType::Native, TSPath, ThisSession))
|
||||
return std::move(EC);
|
||||
|
||||
std::unique_ptr<pdb::NativeSession> NS(
|
||||
static_cast<pdb::NativeSession *>(ThisSession.release()));
|
||||
pdb::PDBFile &File = NS->getPDBFile();
|
||||
auto ExpectedInfo = File.getPDBInfoStream();
|
||||
// All PDB Files should have an Info stream.
|
||||
if (!ExpectedInfo)
|
||||
return ExpectedInfo.takeError();
|
||||
|
||||
// Just because a file with a matching name was found and it was an actual
|
||||
// PDB file doesn't mean it matches. For it to match the InfoStream's GUID
|
||||
// must match the GUID specified in the TypeServer2 record.
|
||||
if (ExpectedInfo->getGuid() != GuidFromObj)
|
||||
return make_error<pdb::GenericError>(
|
||||
pdb::generic_error_code::type_server_not_found, TSPath);
|
||||
|
||||
return std::move(NS);
|
||||
}
|
||||
|
||||
const CVIndexMap &PDBLinker::maybeMergeTypeServerPDB(ObjectFile *File,
|
||||
TypeServer2Record &TS) {
|
||||
// First, check if we already loaded a PDB with this GUID. Return the type
|
||||
// index mapping if we have it.
|
||||
auto Insertion = TypeServerIndexMappings.insert({TS.getGuid(), CVIndexMap()});
|
||||
CVIndexMap &IndexMap = Insertion.first->second;
|
||||
if (!Insertion.second)
|
||||
return IndexMap;
|
||||
|
||||
// Mark this map as a type server map.
|
||||
IndexMap.IsTypeServerMap = true;
|
||||
|
||||
// Check for a PDB at:
|
||||
// 1. The given file path
|
||||
// 2. Next to the object file or archive file
|
||||
auto ExpectedSession = tryToLoadPDB(TS.getGuid(), TS.getName());
|
||||
if (!ExpectedSession) {
|
||||
consumeError(ExpectedSession.takeError());
|
||||
StringRef LocalPath =
|
||||
!File->ParentName.empty() ? File->ParentName : File->getName();
|
||||
SmallString<128> Path = sys::path::parent_path(LocalPath);
|
||||
sys::path::append(
|
||||
Path, sys::path::filename(TS.getName(), sys::path::Style::windows));
|
||||
ExpectedSession = tryToLoadPDB(TS.getGuid(), Path);
|
||||
}
|
||||
if (auto E = ExpectedSession.takeError())
|
||||
fatal(E, "Type server PDB was not found");
|
||||
|
||||
// Merge TPI first, because the IPI stream will reference type indices.
|
||||
auto ExpectedTpi = (*ExpectedSession)->getPDBFile().getPDBTpiStream();
|
||||
if (auto E = ExpectedTpi.takeError())
|
||||
fatal(E, "Type server does not have TPI stream");
|
||||
if (auto Err = mergeTypeRecords(TypeTable, IndexMap.TPIMap,
|
||||
ExpectedTpi->typeArray()))
|
||||
fatal(Err, "codeview::mergeTypeRecords failed");
|
||||
|
||||
// Merge IPI.
|
||||
auto ExpectedIpi = (*ExpectedSession)->getPDBFile().getPDBIpiStream();
|
||||
if (auto E = ExpectedIpi.takeError())
|
||||
fatal(E, "Type server does not have TPI stream");
|
||||
if (auto Err = mergeIdRecords(IDTable, IndexMap.TPIMap, IndexMap.IPIMap,
|
||||
ExpectedIpi->typeArray()))
|
||||
fatal(Err, "codeview::mergeIdRecords failed");
|
||||
|
||||
return IndexMap;
|
||||
}
|
||||
|
||||
static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) {
|
||||
|
|
@ -127,16 +292,22 @@ static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) {
|
|||
|
||||
static void remapTypesInSymbolRecord(ObjectFile *File,
|
||||
MutableArrayRef<uint8_t> Contents,
|
||||
ArrayRef<TypeIndex> TypeIndexMap,
|
||||
const CVIndexMap &IndexMap,
|
||||
ArrayRef<TiReference> TypeRefs) {
|
||||
for (const TiReference &Ref : TypeRefs) {
|
||||
unsigned ByteSize = Ref.Count * sizeof(TypeIndex);
|
||||
if (Contents.size() < Ref.Offset + ByteSize)
|
||||
fatal("symbol record too short");
|
||||
|
||||
// This can be an item index or a type index. Choose the appropriate map.
|
||||
ArrayRef<TypeIndex> TypeOrItemMap = IndexMap.TPIMap;
|
||||
if (Ref.Kind == TiRefKind::IndexRef && IndexMap.IsTypeServerMap)
|
||||
TypeOrItemMap = IndexMap.IPIMap;
|
||||
|
||||
MutableArrayRef<TypeIndex> TIs(
|
||||
reinterpret_cast<TypeIndex *>(Contents.data() + Ref.Offset), Ref.Count);
|
||||
for (TypeIndex &TI : TIs) {
|
||||
if (!remapTypeIndex(TI, TypeIndexMap)) {
|
||||
if (!remapTypeIndex(TI, TypeOrItemMap)) {
|
||||
TI = TypeIndex(SimpleTypeKind::NotTranslated);
|
||||
log("ignoring symbol record in " + File->getName() +
|
||||
" with bad type index 0x" + utohexstr(TI.getIndex()));
|
||||
|
|
@ -241,7 +412,7 @@ static void scopeStackClose(SmallVectorImpl<SymbolScope> &Stack,
|
|||
}
|
||||
|
||||
static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File,
|
||||
ArrayRef<TypeIndex> TypeIndexMap,
|
||||
const CVIndexMap &IndexMap,
|
||||
BinaryStreamRef SymData) {
|
||||
// FIXME: Improve error recovery by warning and skipping records when
|
||||
// possible.
|
||||
|
|
@ -264,7 +435,7 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File,
|
|||
// Re-map all the type index references.
|
||||
MutableArrayRef<uint8_t> Contents =
|
||||
NewData.drop_front(sizeof(RecordPrefix));
|
||||
remapTypesInSymbolRecord(File, Contents, TypeIndexMap, TypeRefs);
|
||||
remapTypesInSymbolRecord(File, Contents, IndexMap, TypeRefs);
|
||||
|
||||
// Fill in "Parent" and "End" fields by maintaining a stack of scopes.
|
||||
CVSymbol NewSym(Sym.kind(), NewData);
|
||||
|
|
@ -289,110 +460,105 @@ static ArrayRef<uint8_t> relocateDebugChunk(BumpPtrAllocator &Alloc,
|
|||
".debug$S");
|
||||
}
|
||||
|
||||
// Add all object files to the PDB. Merge .debug$T sections into IpiData and
|
||||
// TpiData.
|
||||
static void addObjectsToPDB(BumpPtrAllocator &Alloc, SymbolTable *Symtab,
|
||||
pdb::PDBFileBuilder &Builder,
|
||||
TypeTableBuilder &TypeTable,
|
||||
TypeTableBuilder &IDTable) {
|
||||
// Follow type servers. If the same type server is encountered more than
|
||||
// once for this instance of `PDBTypeServerHandler` (for example if many
|
||||
// object files reference the same TypeServer), the types from the
|
||||
// TypeServer will only be visited once.
|
||||
pdb::PDBTypeServerHandler Handler;
|
||||
void PDBLinker::addObjectFile(ObjectFile *File) {
|
||||
// Add a module descriptor for every object file. We need to put an absolute
|
||||
// path to the object into the PDB. If this is a plain object, we make its
|
||||
// path absolute. If it's an object in an archive, we make the archive path
|
||||
// absolute.
|
||||
bool InArchive = !File->ParentName.empty();
|
||||
SmallString<128> Path = InArchive ? File->ParentName : File->getName();
|
||||
sys::fs::make_absolute(Path);
|
||||
sys::path::native(Path, sys::path::Style::windows);
|
||||
StringRef Name = InArchive ? File->getName() : StringRef(Path);
|
||||
|
||||
// PDBs use a single global string table for filenames in the file checksum
|
||||
// table.
|
||||
auto PDBStrTab = std::make_shared<DebugStringTableSubsection>();
|
||||
File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name));
|
||||
File->ModuleDBI->setObjFileName(Path);
|
||||
|
||||
// Visit all .debug$T sections to add them to Builder.
|
||||
for (ObjectFile *File : Symtab->ObjectFiles) {
|
||||
// Add a module descriptor for every object file. We need to put an absolute
|
||||
// path to the object into the PDB. If this is a plain object, we make its
|
||||
// path absolute. If it's an object in an archive, we make the archive path
|
||||
// absolute.
|
||||
bool InArchive = !File->ParentName.empty();
|
||||
SmallString<128> Path = InArchive ? File->ParentName : File->getName();
|
||||
sys::fs::make_absolute(Path);
|
||||
sys::path::native(Path, llvm::sys::path::Style::windows);
|
||||
StringRef Name = InArchive ? File->getName() : StringRef(Path);
|
||||
// Before we can process symbol substreams from .debug$S, we need to process
|
||||
// type information, file checksums, and the string table. Add type info to
|
||||
// the PDB first, so that we can get the map from object file type and item
|
||||
// indices to PDB type and item indices.
|
||||
CVIndexMap ObjectIndexMap;
|
||||
const CVIndexMap &IndexMap = mergeDebugT(File, ObjectIndexMap);
|
||||
|
||||
File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name));
|
||||
File->ModuleDBI->setObjFileName(Path);
|
||||
// Now do all live .debug$S sections.
|
||||
for (SectionChunk *DebugChunk : File->getDebugChunks()) {
|
||||
if (!DebugChunk->isLive() || DebugChunk->getSectionName() != ".debug$S")
|
||||
continue;
|
||||
|
||||
// Before we can process symbol substreams from .debug$S, we need to process
|
||||
// type information, file checksums, and the string table. Add type info to
|
||||
// the PDB first, so that we can get the map from object file type and item
|
||||
// indices to PDB type and item indices.
|
||||
SmallVector<TypeIndex, 128> TypeIndexMap;
|
||||
mergeDebugT(File, IDTable, TypeTable, TypeIndexMap, Handler);
|
||||
ArrayRef<uint8_t> RelocatedDebugContents =
|
||||
relocateDebugChunk(Alloc, DebugChunk);
|
||||
if (RelocatedDebugContents.empty())
|
||||
continue;
|
||||
|
||||
// Now do all line info.
|
||||
for (SectionChunk *DebugChunk : File->getDebugChunks()) {
|
||||
if (!DebugChunk->isLive() || DebugChunk->getSectionName() != ".debug$S")
|
||||
continue;
|
||||
DebugSubsectionArray Subsections;
|
||||
BinaryStreamReader Reader(RelocatedDebugContents, support::little);
|
||||
ExitOnErr(Reader.readArray(Subsections, RelocatedDebugContents.size()));
|
||||
|
||||
ArrayRef<uint8_t> RelocatedDebugContents =
|
||||
relocateDebugChunk(Alloc, DebugChunk);
|
||||
if (RelocatedDebugContents.empty())
|
||||
continue;
|
||||
|
||||
DebugSubsectionArray Subsections;
|
||||
BinaryStreamReader Reader(RelocatedDebugContents, support::little);
|
||||
ExitOnErr(Reader.readArray(Subsections, RelocatedDebugContents.size()));
|
||||
|
||||
DebugStringTableSubsectionRef CVStrTab;
|
||||
DebugChecksumsSubsectionRef Checksums;
|
||||
for (const DebugSubsectionRecord &SS : Subsections) {
|
||||
switch (SS.kind()) {
|
||||
case DebugSubsectionKind::StringTable:
|
||||
ExitOnErr(CVStrTab.initialize(SS.getRecordData()));
|
||||
break;
|
||||
case DebugSubsectionKind::FileChecksums:
|
||||
ExitOnErr(Checksums.initialize(SS.getRecordData()));
|
||||
break;
|
||||
case DebugSubsectionKind::Lines:
|
||||
// We can add the relocated line table directly to the PDB without
|
||||
// modification because the file checksum offsets will stay the same.
|
||||
File->ModuleDBI->addDebugSubsection(SS);
|
||||
break;
|
||||
case DebugSubsectionKind::Symbols:
|
||||
mergeSymbolRecords(Alloc, File, TypeIndexMap, SS.getRecordData());
|
||||
break;
|
||||
default:
|
||||
// FIXME: Process the rest of the subsections.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Checksums.valid()) {
|
||||
// Make a new file checksum table that refers to offsets in the PDB-wide
|
||||
// string table. Generally the string table subsection appears after the
|
||||
// checksum table, so we have to do this after looping over all the
|
||||
// subsections.
|
||||
if (!CVStrTab.valid())
|
||||
fatal(".debug$S sections must have both a string table subsection "
|
||||
"and a checksum subsection table or neither");
|
||||
auto NewChecksums =
|
||||
make_unique<DebugChecksumsSubsection>(*PDBStrTab);
|
||||
for (FileChecksumEntry &FC : Checksums) {
|
||||
StringRef FileName = ExitOnErr(CVStrTab.getString(FC.FileNameOffset));
|
||||
ExitOnErr(Builder.getDbiBuilder().addModuleSourceFile(
|
||||
*File->ModuleDBI, FileName));
|
||||
NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum);
|
||||
}
|
||||
File->ModuleDBI->addDebugSubsection(std::move(NewChecksums));
|
||||
DebugStringTableSubsectionRef CVStrTab;
|
||||
DebugChecksumsSubsectionRef Checksums;
|
||||
for (const DebugSubsectionRecord &SS : Subsections) {
|
||||
switch (SS.kind()) {
|
||||
case DebugSubsectionKind::StringTable:
|
||||
ExitOnErr(CVStrTab.initialize(SS.getRecordData()));
|
||||
break;
|
||||
case DebugSubsectionKind::FileChecksums:
|
||||
ExitOnErr(Checksums.initialize(SS.getRecordData()));
|
||||
break;
|
||||
case DebugSubsectionKind::Lines:
|
||||
// We can add the relocated line table directly to the PDB without
|
||||
// modification because the file checksum offsets will stay the same.
|
||||
File->ModuleDBI->addDebugSubsection(SS);
|
||||
break;
|
||||
case DebugSubsectionKind::Symbols:
|
||||
mergeSymbolRecords(Alloc, File, IndexMap, SS.getRecordData());
|
||||
break;
|
||||
default:
|
||||
// FIXME: Process the rest of the subsections.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Builder.getStringTableBuilder().setStrings(*PDBStrTab);
|
||||
if (Checksums.valid()) {
|
||||
// Make a new file checksum table that refers to offsets in the PDB-wide
|
||||
// string table. Generally the string table subsection appears after the
|
||||
// checksum table, so we have to do this after looping over all the
|
||||
// subsections.
|
||||
if (!CVStrTab.valid())
|
||||
fatal(".debug$S sections must have both a string table subsection "
|
||||
"and a checksum subsection table or neither");
|
||||
auto NewChecksums = make_unique<DebugChecksumsSubsection>(PDBStrTab);
|
||||
for (FileChecksumEntry &FC : Checksums) {
|
||||
StringRef FileName = ExitOnErr(CVStrTab.getString(FC.FileNameOffset));
|
||||
ExitOnErr(Builder.getDbiBuilder().addModuleSourceFile(*File->ModuleDBI,
|
||||
FileName));
|
||||
NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum);
|
||||
}
|
||||
File->ModuleDBI->addDebugSubsection(std::move(NewChecksums));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add all object files to the PDB. Merge .debug$T sections into IpiData and
|
||||
// TpiData.
|
||||
void PDBLinker::addObjectsToPDB() {
|
||||
for (ObjectFile *File : Symtab->ObjectFiles)
|
||||
addObjectFile(File);
|
||||
|
||||
Builder.getStringTableBuilder().setStrings(PDBStrTab);
|
||||
|
||||
// Construct TPI stream contents.
|
||||
addTypeInfo(Builder.getTpiBuilder(), TypeTable);
|
||||
|
||||
// Construct IPI stream contents.
|
||||
addTypeInfo(Builder.getIpiBuilder(), IDTable);
|
||||
|
||||
// Add public and symbol records stream.
|
||||
|
||||
// For now we don't actually write any thing useful to the publics stream, but
|
||||
// the act of "getting" it also creates it lazily so that we write an empty
|
||||
// stream.
|
||||
(void)Builder.getPublicsBuilder();
|
||||
}
|
||||
|
||||
static void addLinkerModuleSymbols(StringRef Path,
|
||||
|
|
@ -423,7 +589,7 @@ static void addLinkerModuleSymbols(StringRef Path,
|
|||
std::string ArgStr = llvm::join(Args, " ");
|
||||
EBS.Fields.push_back("cwd");
|
||||
SmallString<64> cwd;
|
||||
llvm::sys::fs::current_path(cwd);
|
||||
sys::fs::current_path(cwd);
|
||||
EBS.Fields.push_back(cwd);
|
||||
EBS.Fields.push_back("exe");
|
||||
EBS.Fields.push_back(Config->Argv[0]);
|
||||
|
|
@ -442,8 +608,14 @@ static void addLinkerModuleSymbols(StringRef Path,
|
|||
// Creates a PDB file.
|
||||
void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable,
|
||||
const llvm::codeview::DebugInfo *DI) {
|
||||
BumpPtrAllocator Alloc;
|
||||
pdb::PDBFileBuilder Builder(Alloc);
|
||||
PDBLinker PDB(Symtab);
|
||||
PDB.initialize(DI);
|
||||
PDB.addObjectsToPDB();
|
||||
PDB.addSections(SectionTable);
|
||||
PDB.commit();
|
||||
}
|
||||
|
||||
void PDBLinker::initialize(const llvm::codeview::DebugInfo *DI) {
|
||||
ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize
|
||||
|
||||
// Create streams in MSF for predefined streams, namely
|
||||
|
|
@ -455,12 +627,7 @@ void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable,
|
|||
auto &InfoBuilder = Builder.getInfoBuilder();
|
||||
InfoBuilder.setAge(DI ? DI->PDB70.Age : 0);
|
||||
|
||||
llvm::SmallString<128> NativePath(Config->PDBPath.begin(),
|
||||
Config->PDBPath.end());
|
||||
llvm::sys::fs::make_absolute(NativePath);
|
||||
llvm::sys::path::native(NativePath, llvm::sys::path::Style::windows);
|
||||
|
||||
pdb::PDB_UniqueId uuid{};
|
||||
GUID uuid{};
|
||||
if (DI)
|
||||
memcpy(&uuid, &DI->PDB70.Signature, sizeof(uuid));
|
||||
InfoBuilder.setGuid(uuid);
|
||||
|
|
@ -471,32 +638,25 @@ void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable,
|
|||
pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
|
||||
DbiBuilder.setVersionHeader(pdb::PdbDbiV70);
|
||||
ExitOnErr(DbiBuilder.addDbgStream(pdb::DbgHeaderType::NewFPO, {}));
|
||||
}
|
||||
|
||||
// It's not entirely clear what this is, but the * Linker * module uses it.
|
||||
uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath);
|
||||
|
||||
TypeTableBuilder TypeTable(BAlloc);
|
||||
TypeTableBuilder IDTable(BAlloc);
|
||||
addObjectsToPDB(Alloc, Symtab, Builder, TypeTable, IDTable);
|
||||
|
||||
// Add public and symbol records stream.
|
||||
|
||||
// For now we don't actually write any thing useful to the publics stream, but
|
||||
// the act of "getting" it also creates it lazily so that we write an empty
|
||||
// stream.
|
||||
(void)Builder.getPublicsBuilder();
|
||||
|
||||
void PDBLinker::addSections(ArrayRef<uint8_t> SectionTable) {
|
||||
// Add Section Contributions.
|
||||
pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
|
||||
addSectionContribs(Symtab, DbiBuilder);
|
||||
|
||||
// Add Section Map stream.
|
||||
ArrayRef<object::coff_section> Sections = {
|
||||
(const object::coff_section *)SectionTable.data(),
|
||||
SectionTable.size() / sizeof(object::coff_section)};
|
||||
std::vector<pdb::SecMapEntry> SectionMap =
|
||||
pdb::DbiStreamBuilder::createSectionMap(Sections);
|
||||
SectionMap = pdb::DbiStreamBuilder::createSectionMap(Sections);
|
||||
DbiBuilder.setSectionMap(SectionMap);
|
||||
|
||||
// It's not entirely clear what this is, but the * Linker * module uses it.
|
||||
NativePath = Config->PDBPath;
|
||||
sys::fs::make_absolute(NativePath);
|
||||
sys::path::native(NativePath, sys::path::Style::windows);
|
||||
uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath);
|
||||
auto &LinkerModule = ExitOnErr(DbiBuilder.addModuleInfo("* Linker *"));
|
||||
LinkerModule.setPdbFilePathNI(PdbFilePathNI);
|
||||
addLinkerModuleSymbols(NativePath, LinkerModule, Alloc);
|
||||
|
|
@ -504,7 +664,9 @@ void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable,
|
|||
// Add COFF section header stream.
|
||||
ExitOnErr(
|
||||
DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable));
|
||||
}
|
||||
|
||||
void PDBLinker::commit() {
|
||||
// Write to a file.
|
||||
ExitOnErr(Builder.commit(Config->PDBPath));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ public:
|
|||
void addPltHeaderSymbols(InputSectionBase *ISD) const override;
|
||||
bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File,
|
||||
const SymbolBody &S) const override;
|
||||
bool inBranchRange(uint32_t RelocType, uint64_t Src,
|
||||
uint64_t Dst) const override;
|
||||
void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
|
||||
};
|
||||
} // namespace
|
||||
|
|
@ -218,6 +220,49 @@ bool ARM::needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ARM::inBranchRange(uint32_t RelocType, uint64_t Src, uint64_t Dst) const {
|
||||
uint64_t Range;
|
||||
uint64_t InstrSize;
|
||||
|
||||
switch (RelocType) {
|
||||
case R_ARM_PC24:
|
||||
case R_ARM_PLT32:
|
||||
case R_ARM_JUMP24:
|
||||
case R_ARM_CALL:
|
||||
Range = 0x2000000;
|
||||
InstrSize = 4;
|
||||
break;
|
||||
case R_ARM_THM_JUMP19:
|
||||
Range = 0x100000;
|
||||
InstrSize = 2;
|
||||
break;
|
||||
case R_ARM_THM_JUMP24:
|
||||
case R_ARM_THM_CALL:
|
||||
Range = 0x1000000;
|
||||
InstrSize = 2;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
// PC at Src is 2 instructions ahead, immediate of branch is signed
|
||||
if (Src > Dst)
|
||||
Range -= 2 * InstrSize;
|
||||
else
|
||||
Range += InstrSize;
|
||||
|
||||
if ((Dst & 0x1) == 0)
|
||||
// Destination is ARM, if ARM caller then Src is already 4-byte aligned.
|
||||
// If Thumb Caller (BLX) the Src address has bottom 2 bits cleared to ensure
|
||||
// destination will be 4 byte aligned.
|
||||
Src &= ~0x3;
|
||||
else
|
||||
// Bit 0 == 1 denotes Thumb state, it is not part of the range
|
||||
Dst &= ~0x1;
|
||||
|
||||
uint64_t Distance = (Src > Dst) ? Src - Dst : Dst - Src;
|
||||
return Distance <= Range;
|
||||
}
|
||||
|
||||
void ARM::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const {
|
||||
switch (Type) {
|
||||
case R_ARM_ABS32:
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ struct FileFlags {
|
|||
StringRef Filename;
|
||||
uint32_t Flags;
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
static StringRef getAbiName(uint32_t Flags) {
|
||||
switch (Flags) {
|
||||
|
|
@ -337,8 +337,8 @@ uint8_t elf::getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag,
|
|||
return NewFlag;
|
||||
if (compareMipsFpAbi(OldFlag, NewFlag) < 0)
|
||||
error("target floating point ABI '" + getMipsFpAbiName(OldFlag) +
|
||||
"' is incompatible with '" + getMipsFpAbiName(NewFlag) + "': " +
|
||||
FileName);
|
||||
"' is incompatible with '" + getMipsFpAbiName(NewFlag) +
|
||||
"': " + FileName);
|
||||
return OldFlag;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ struct Configuration {
|
|||
std::vector<VersionDefinition> VersionDefinitions;
|
||||
std::vector<llvm::StringRef> Argv;
|
||||
std::vector<llvm::StringRef> AuxiliaryList;
|
||||
std::vector<llvm::StringRef> FilterList;
|
||||
std::vector<llvm::StringRef> SearchPaths;
|
||||
std::vector<llvm::StringRef> SymbolOrderingFile;
|
||||
std::vector<llvm::StringRef> Undefined;
|
||||
|
|
|
|||
|
|
@ -259,6 +259,9 @@ static void checkOptions(opt::InputArgList &Args) {
|
|||
if (Config->Pie && Config->Shared)
|
||||
error("-shared and -pie may not be used together");
|
||||
|
||||
if (!Config->Shared && !Config->FilterList.empty())
|
||||
error("-F may not be used without -shared");
|
||||
|
||||
if (!Config->Shared && !Config->AuxiliaryList.empty())
|
||||
error("-f may not be used without -shared");
|
||||
|
||||
|
|
@ -631,6 +634,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
|
|||
getArg(Args, OPT_export_dynamic, OPT_no_export_dynamic, false);
|
||||
Config->FatalWarnings =
|
||||
getArg(Args, OPT_fatal_warnings, OPT_no_fatal_warnings, false);
|
||||
Config->FilterList = getArgs(Args, OPT_filter);
|
||||
Config->Fini = Args.getLastArgValue(OPT_fini, "_fini");
|
||||
Config->GcSections = getArg(Args, OPT_gc_sections, OPT_no_gc_sections, false);
|
||||
Config->GdbIndex = Args.hasArg(OPT_gdb_index);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ struct EhSectionPiece;
|
|||
|
||||
template <class ELFT> size_t readEhRecordSize(InputSectionBase *S, size_t Off);
|
||||
template <class ELFT> uint8_t getFdeEncoding(EhSectionPiece *P);
|
||||
}
|
||||
}
|
||||
} // namespace elf
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace lld {
|
|||
namespace elf {
|
||||
void unlinkAsync(StringRef Path);
|
||||
std::error_code tryCreateFile(StringRef Path);
|
||||
}
|
||||
}
|
||||
} // namespace elf
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
#define LLD_ELF_GDB_INDEX_H
|
||||
|
||||
#include "InputFiles.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,6 @@ namespace lld {
|
|||
namespace elf {
|
||||
template <class ELFT> void doIcf();
|
||||
}
|
||||
}
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
#define LLD_ELF_INPUT_FILES_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "InputSection.h"
|
||||
#include "Error.h"
|
||||
#include "InputSection.h"
|
||||
#include "Symbols.h"
|
||||
|
||||
#include "lld/Core/LLVM.h"
|
||||
|
|
@ -34,7 +34,7 @@ struct DILineInfo;
|
|||
namespace lto {
|
||||
class InputFile;
|
||||
}
|
||||
}
|
||||
} // namespace llvm
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace llvm {
|
|||
namespace lto {
|
||||
class LTO;
|
||||
}
|
||||
}
|
||||
} // namespace llvm
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
|
|
@ -51,7 +51,7 @@ private:
|
|||
std::vector<SmallString<0>> Buff;
|
||||
std::vector<std::unique_ptr<MemoryBuffer>> Files;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace elf
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -229,6 +229,19 @@ bool LinkerScript::shouldKeep(InputSectionBase *S) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// If an input string is in the form of "foo.N" where N is a number,
|
||||
// return N. Otherwise, returns 65536, which is one greater than the
|
||||
// lowest priority.
|
||||
static int getPriority(StringRef S) {
|
||||
size_t Pos = S.rfind('.');
|
||||
if (Pos == StringRef::npos)
|
||||
return 65536;
|
||||
int V;
|
||||
if (!to_integer(S.substr(Pos + 1), V, 10))
|
||||
return 65536;
|
||||
return V;
|
||||
}
|
||||
|
||||
// A helper function for the SORT() command.
|
||||
static std::function<bool(InputSectionBase *, InputSectionBase *)>
|
||||
getComparator(SortSectionPolicy K) {
|
||||
|
|
@ -449,7 +462,7 @@ void LinkerScript::fabricateDefaultCommands() {
|
|||
// The Sections with -T<section> have been sorted in order of ascending
|
||||
// address. We must lower StartAddr if the lowest -T<section address> as
|
||||
// calls to setDot() must be monotonically increasing.
|
||||
for (auto& KV : Config->SectionStartMap)
|
||||
for (auto &KV : Config->SectionStartMap)
|
||||
StartAddr = std::min(StartAddr, KV.second);
|
||||
|
||||
Commands.push_back(make<SymbolAssignment>(
|
||||
|
|
@ -739,7 +752,7 @@ void LinkerScript::adjustSectionsAfterSorting() {
|
|||
Cmd->MemRegion = findMemoryRegion(Cmd);
|
||||
// Handle align (e.g. ".foo : ALIGN(16) { ... }").
|
||||
if (Cmd->AlignExpr)
|
||||
Cmd->Sec->updateAlignment(Cmd->AlignExpr().getValue());
|
||||
Cmd->Sec->updateAlignment(Cmd->AlignExpr().getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1071,7 +1084,7 @@ template <class ELFT> void OutputSectionCommand::finalize() {
|
|||
}
|
||||
|
||||
if ((Sec->Flags & SHF_LINK_ORDER)) {
|
||||
std::sort(Sections.begin(), Sections.end(), compareByFilePosition);
|
||||
std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition);
|
||||
for (int I = 0, N = Sections.size(); I < N; ++I)
|
||||
*ScriptSections[I] = Sections[I];
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ template <class ELFT> std::vector<DefinedRegular *> getSymbols() {
|
|||
for (SymbolBody *B : File->getSymbols())
|
||||
if (B->File == File && !B->isSection())
|
||||
if (auto *Sym = dyn_cast<DefinedRegular>(B))
|
||||
if (Sym->Section)
|
||||
if (Sym->Section && Sym->Section->Live)
|
||||
V.push_back(Sym);
|
||||
return V;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace elf {
|
|||
struct OutputSectionCommand;
|
||||
template <class ELFT>
|
||||
void writeMapFile(llvm::ArrayRef<OutputSectionCommand *> Script);
|
||||
}
|
||||
}
|
||||
} // namespace elf
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ inline void freeArena() {
|
|||
Alloc->reset();
|
||||
BAlloc.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace elf
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -104,6 +104,8 @@ def export_dynamic_symbol: S<"export-dynamic-symbol">,
|
|||
def fatal_warnings: F<"fatal-warnings">,
|
||||
HelpText<"Treat warnings as errors">;
|
||||
|
||||
def filter: J<"filter=">, HelpText<"Set DT_FILTER field to the specified name">;
|
||||
|
||||
def fini: S<"fini">, MetaVarName<"<symbol>">,
|
||||
HelpText<"Specify a finalizer function">;
|
||||
|
||||
|
|
@ -305,6 +307,7 @@ def alias_exclude_libs: J<"exclude-libs=">, Alias<exclude_libs>;
|
|||
def alias_export_dynamic_E: Flag<["-"], "E">, Alias<export_dynamic>;
|
||||
def alias_export_dynamic_symbol: J<"export-dynamic-symbol=">,
|
||||
Alias<export_dynamic_symbol>;
|
||||
def alias_filter: Separate<["-"], "F">, Alias<filter>;
|
||||
def alias_fini_fini: J<"fini=">, Alias<fini>;
|
||||
def alias_format_b: S<"b">, Alias<format>;
|
||||
def alias_hash_style_hash_style: J<"hash-style=">, Alias<hash_style>;
|
||||
|
|
@ -339,6 +342,7 @@ def alias_Ttext_segment: S<"Ttext-segment">, Alias<Ttext>;
|
|||
def alias_Ttext_segment_eq: J<"Ttext-segment=">, Alias<Ttext>;
|
||||
def alias_undefined_eq: J<"undefined=">, Alias<undefined>;
|
||||
def alias_undefined_u: JoinedOrSeparate<["-"], "u">, Alias<undefined>;
|
||||
def alias_version_script_eq: J<"version-script=">, Alias<version_script>;
|
||||
def alias_version_V: Flag<["-"], "V">, Alias<version>;
|
||||
def alias_wrap_wrap: J<"wrap=">, Alias<wrap>;
|
||||
|
||||
|
|
@ -406,6 +410,3 @@ def EL : F<"EL">;
|
|||
def G: JoinedOrSeparate<["-"], "G">;
|
||||
def Qy : F<"Qy">;
|
||||
|
||||
// Aliases for ignored options
|
||||
def alias_version_script_version_script: J<"version-script=">,
|
||||
Alias<version_script>;
|
||||
|
|
|
|||
|
|
@ -222,16 +222,16 @@ void OutputSectionFactory::addInputSec(InputSectionBase *IS,
|
|||
|
||||
if (Sec) {
|
||||
if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(IS->Flags))
|
||||
error("incompatible section flags for " + Sec->Name +
|
||||
"\n>>> " + toString(IS) + ": 0x" + utohexstr(IS->Flags) +
|
||||
error("incompatible section flags for " + Sec->Name + "\n>>> " +
|
||||
toString(IS) + ": 0x" + utohexstr(IS->Flags) +
|
||||
"\n>>> output section " + Sec->Name + ": 0x" +
|
||||
utohexstr(Sec->Flags));
|
||||
if (Sec->Type != IS->Type) {
|
||||
if (canMergeToProgbits(Sec->Type) && canMergeToProgbits(IS->Type))
|
||||
Sec->Type = SHT_PROGBITS;
|
||||
else
|
||||
error("section type mismatch for " + IS->Name +
|
||||
"\n>>> " + toString(IS) + ": " +
|
||||
error("section type mismatch for " + IS->Name + "\n>>> " +
|
||||
toString(IS) + ": " +
|
||||
getELFSectionTypeName(Config->EMachine, IS->Type) +
|
||||
"\n>>> output section " + Sec->Name + ": " +
|
||||
getELFSectionTypeName(Config->EMachine, Sec->Type));
|
||||
|
|
|
|||
|
|
@ -111,8 +111,8 @@ struct SectionKey {
|
|||
uint64_t Flags;
|
||||
uint32_t Alignment;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace elf
|
||||
} // namespace lld
|
||||
namespace llvm {
|
||||
template <> struct DenseMapInfo<lld::elf::SectionKey> {
|
||||
static lld::elf::SectionKey getEmptyKey();
|
||||
|
|
@ -121,7 +121,7 @@ template <> struct DenseMapInfo<lld::elf::SectionKey> {
|
|||
static bool isEqual(const lld::elf::SectionKey &LHS,
|
||||
const lld::elf::SectionKey &RHS);
|
||||
};
|
||||
}
|
||||
} // namespace llvm
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
|
||||
|
|
@ -150,5 +150,4 @@ extern std::vector<OutputSectionCommand *> OutputSectionCommands;
|
|||
} // namespace elf
|
||||
} // namespace lld
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C,
|
|||
} else {
|
||||
C.Relocations.push_back(
|
||||
{Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_LE), Type,
|
||||
Offset, Addend, &Body});
|
||||
Offset, Addend, &Body});
|
||||
}
|
||||
return Target->TlsGdRelaxSkip;
|
||||
}
|
||||
|
|
@ -1000,16 +1000,20 @@ void ThunkCreator::mergeThunks() {
|
|||
}
|
||||
}
|
||||
|
||||
ThunkSection *ThunkCreator::getOSThunkSec(OutputSection *OS,
|
||||
static uint32_t findEndOfFirstNonExec(OutputSectionCommand &Cmd) {
|
||||
for (BaseCommand *Base : Cmd.Commands)
|
||||
if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
|
||||
for (auto *IS : ISD->Sections)
|
||||
if ((IS->Flags & SHF_EXECINSTR) == 0)
|
||||
return IS->OutSecOff + IS->getSize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
ThunkSection *ThunkCreator::getOSThunkSec(OutputSectionCommand *Cmd,
|
||||
std::vector<InputSection *> *ISR) {
|
||||
if (CurTS == nullptr) {
|
||||
uint32_t Off = 0;
|
||||
for (auto *IS : OS->Sections) {
|
||||
Off = IS->OutSecOff + IS->getSize();
|
||||
if ((IS->Flags & SHF_EXECINSTR) == 0)
|
||||
break;
|
||||
}
|
||||
CurTS = addThunkSection(OS, ISR, Off);
|
||||
uint32_t Off = findEndOfFirstNonExec(*Cmd);
|
||||
CurTS = addThunkSection(Cmd->Sec, ISR, Off);
|
||||
}
|
||||
return CurTS;
|
||||
}
|
||||
|
|
@ -1024,7 +1028,7 @@ ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS, OutputSection *OS) {
|
|||
OutputSectionCommand *C = Script->getCmd(TOS);
|
||||
std::vector<InputSection *> *Range = nullptr;
|
||||
for (BaseCommand *BC : C->Commands)
|
||||
if (auto *ISD = dyn_cast<InputSectionDescription> (BC)) {
|
||||
if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) {
|
||||
InputSection *first = ISD->Sections.front();
|
||||
InputSection *last = ISD->Sections.back();
|
||||
if (IS->OutSecOff >= first->OutSecOff &&
|
||||
|
|
@ -1046,7 +1050,6 @@ ThunkSection *ThunkCreator::addThunkSection(OutputSection *OS,
|
|||
return TS;
|
||||
}
|
||||
|
||||
|
||||
std::pair<Thunk *, bool> ThunkCreator::getThunk(SymbolBody &Body,
|
||||
uint32_t Type) {
|
||||
auto Res = ThunkedSymbols.insert({&Body, std::vector<Thunk *>()});
|
||||
|
|
@ -1066,7 +1069,7 @@ std::pair<Thunk *, bool> ThunkCreator::getThunk(SymbolBody &Body,
|
|||
// InputSectionDescription::Sections.
|
||||
void ThunkCreator::forEachExecInputSection(
|
||||
ArrayRef<OutputSectionCommand *> OutputSections,
|
||||
std::function<void(OutputSection *, std::vector<InputSection *> *,
|
||||
std::function<void(OutputSectionCommand *, std::vector<InputSection *> *,
|
||||
InputSection *)>
|
||||
Fn) {
|
||||
for (OutputSectionCommand *Cmd : OutputSections) {
|
||||
|
|
@ -1077,7 +1080,7 @@ void ThunkCreator::forEachExecInputSection(
|
|||
if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) {
|
||||
CurTS = nullptr;
|
||||
for (InputSection *IS : ISD->Sections)
|
||||
Fn(OS, &ISD->Sections, IS);
|
||||
Fn(Cmd, &ISD->Sections, IS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1103,32 +1106,32 @@ bool ThunkCreator::createThunks(
|
|||
// We separate the creation of ThunkSections from the insertion of the
|
||||
// ThunkSections back into the OutputSection as ThunkSections are not always
|
||||
// inserted into the same OutputSection as the caller.
|
||||
forEachExecInputSection(
|
||||
OutputSections, [&](OutputSection *OS, std::vector<InputSection*> *ISR,
|
||||
InputSection *IS) {
|
||||
for (Relocation &Rel : IS->Relocations) {
|
||||
SymbolBody &Body = *Rel.Sym;
|
||||
if (Thunks.find(&Body) != Thunks.end() ||
|
||||
!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body))
|
||||
continue;
|
||||
Thunk *T;
|
||||
bool IsNew;
|
||||
std::tie(T, IsNew) = getThunk(Body, Rel.Type);
|
||||
if (IsNew) {
|
||||
// Find or create a ThunkSection for the new Thunk
|
||||
ThunkSection *TS;
|
||||
if (auto *TIS = T->getTargetInputSection())
|
||||
TS = getISThunkSec(TIS, OS);
|
||||
else
|
||||
TS = getOSThunkSec(OS, ISR);
|
||||
TS->addThunk(T);
|
||||
Thunks[T->ThunkSym] = T;
|
||||
}
|
||||
// Redirect relocation to Thunk, we never go via the PLT to a Thunk
|
||||
Rel.Sym = T->ThunkSym;
|
||||
Rel.Expr = fromPlt(Rel.Expr);
|
||||
}
|
||||
});
|
||||
forEachExecInputSection(OutputSections, [&](OutputSectionCommand *Cmd,
|
||||
std::vector<InputSection *> *ISR,
|
||||
InputSection *IS) {
|
||||
for (Relocation &Rel : IS->Relocations) {
|
||||
SymbolBody &Body = *Rel.Sym;
|
||||
if (Thunks.find(&Body) != Thunks.end() ||
|
||||
!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body))
|
||||
continue;
|
||||
Thunk *T;
|
||||
bool IsNew;
|
||||
std::tie(T, IsNew) = getThunk(Body, Rel.Type);
|
||||
if (IsNew) {
|
||||
// Find or create a ThunkSection for the new Thunk
|
||||
ThunkSection *TS;
|
||||
if (auto *TIS = T->getTargetInputSection())
|
||||
TS = getISThunkSec(TIS, Cmd->Sec);
|
||||
else
|
||||
TS = getOSThunkSec(Cmd, ISR);
|
||||
TS->addThunk(T);
|
||||
Thunks[T->ThunkSym] = T;
|
||||
}
|
||||
// Redirect relocation to Thunk, we never go via the PLT to a Thunk
|
||||
Rel.Sym = T->ThunkSym;
|
||||
Rel.Expr = fromPlt(Rel.Expr);
|
||||
}
|
||||
});
|
||||
// Merge all created synthetic ThunkSections back into OutputSection
|
||||
mergeThunks();
|
||||
++Pass;
|
||||
|
|
|
|||
|
|
@ -103,7 +103,8 @@ struct RelExprMaskBuilder<Head, Tail...> {
|
|||
// RelExpr's as a constant bit mask and test for membership with a
|
||||
// couple cheap bitwise operations.
|
||||
template <RelExpr... Exprs> bool isRelExprOneOf(RelExpr Expr) {
|
||||
assert(0 <= Expr && (int)Expr < 64 && "RelExpr is too large for 64-bit mask!");
|
||||
assert(0 <= Expr && (int)Expr < 64 &&
|
||||
"RelExpr is too large for 64-bit mask!");
|
||||
return (uint64_t(1) << Expr) & RelExprMaskBuilder<Exprs...>::build();
|
||||
}
|
||||
|
||||
|
|
@ -133,12 +134,12 @@ public:
|
|||
|
||||
private:
|
||||
void mergeThunks();
|
||||
ThunkSection *getOSThunkSec(OutputSection *OS,
|
||||
ThunkSection *getOSThunkSec(OutputSectionCommand *Cmd,
|
||||
std::vector<InputSection *> *ISR);
|
||||
ThunkSection *getISThunkSec(InputSection *IS, OutputSection *OS);
|
||||
void forEachExecInputSection(
|
||||
ArrayRef<OutputSectionCommand *> OutputSections,
|
||||
std::function<void(OutputSection *, std::vector<InputSection *> *,
|
||||
std::function<void(OutputSectionCommand *, std::vector<InputSection *> *,
|
||||
InputSection *)>
|
||||
Fn);
|
||||
std::pair<Thunk *, bool> getThunk(SymbolBody &Body, uint32_t Type);
|
||||
|
|
@ -178,7 +179,7 @@ template <class ELFT>
|
|||
static inline int64_t getAddend(const typename ELFT::Rela &Rel) {
|
||||
return Rel.r_addend;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace elf
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -113,6 +113,12 @@ private:
|
|||
};
|
||||
} // namespace
|
||||
|
||||
static StringRef unquote(StringRef S) {
|
||||
if (S.startswith("\""))
|
||||
return S.substr(1, S.size() - 2);
|
||||
return S;
|
||||
}
|
||||
|
||||
static bool isUnderSysroot(StringRef Path) {
|
||||
if (Config->Sysroot == "")
|
||||
return false;
|
||||
|
|
@ -1103,6 +1109,10 @@ void ScriptParser::readVersionDeclaration(StringRef VerStr) {
|
|||
expect(";");
|
||||
}
|
||||
|
||||
static bool hasWildcard(StringRef S) {
|
||||
return S.find_first_of("?*[") != StringRef::npos;
|
||||
}
|
||||
|
||||
// Reads a list of symbols, e.g. "{ global: foo; bar; local: *; };".
|
||||
std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>>
|
||||
ScriptParser::readSymbols() {
|
||||
|
|
|
|||
|
|
@ -38,29 +38,6 @@ bool StringMatcher::match(StringRef S) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
// If an input string is in the form of "foo.N" where N is a number,
|
||||
// return N. Otherwise, returns 65536, which is one greater than the
|
||||
// lowest priority.
|
||||
int elf::getPriority(StringRef S) {
|
||||
size_t Pos = S.rfind('.');
|
||||
if (Pos == StringRef::npos)
|
||||
return 65536;
|
||||
int V;
|
||||
if (!to_integer(S.substr(Pos + 1), V, 10))
|
||||
return 65536;
|
||||
return V;
|
||||
}
|
||||
|
||||
bool elf::hasWildcard(StringRef S) {
|
||||
return S.find_first_of("?*[") != StringRef::npos;
|
||||
}
|
||||
|
||||
StringRef elf::unquote(StringRef S) {
|
||||
if (!S.startswith("\""))
|
||||
return S;
|
||||
return S.substr(1, S.size() - 2);
|
||||
}
|
||||
|
||||
// Converts a hex string (e.g. "deadbeef") to a vector.
|
||||
std::vector<uint8_t> elf::parseHex(StringRef S) {
|
||||
std::vector<uint8_t> Hex;
|
||||
|
|
|
|||
|
|
@ -21,11 +21,8 @@
|
|||
namespace lld {
|
||||
namespace elf {
|
||||
|
||||
int getPriority(StringRef S);
|
||||
bool hasWildcard(StringRef S);
|
||||
std::vector<uint8_t> parseHex(StringRef S);
|
||||
bool isValidCIdentifier(StringRef S);
|
||||
StringRef unquote(StringRef S);
|
||||
|
||||
// This is a lazy version of StringRef. String size is computed lazily
|
||||
// when it is needed. It is more efficient than StringRef to instantiate
|
||||
|
|
@ -76,7 +73,7 @@ llvm::Optional<std::string> demangle(StringRef Name);
|
|||
inline ArrayRef<uint8_t> toArrayRef(StringRef S) {
|
||||
return {(const uint8_t *)S.data(), S.size()};
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace elf
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -172,8 +172,8 @@ template <class ELFT> void SymbolTable<ELFT>::addSymbolWrap(StringRef Name) {
|
|||
}
|
||||
|
||||
// Creates alias for symbol. Used to implement --defsym=ALIAS=SYM.
|
||||
template <class ELFT> void SymbolTable<ELFT>::addSymbolAlias(StringRef Alias,
|
||||
StringRef Name) {
|
||||
template <class ELFT>
|
||||
void SymbolTable<ELFT>::addSymbolAlias(StringRef Alias, StringRef Name) {
|
||||
SymbolBody *B = find(Name);
|
||||
if (!B) {
|
||||
error("-defsym: undefined symbol: " + Name);
|
||||
|
|
@ -211,13 +211,6 @@ static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
|
|||
// Find an existing symbol or create and insert a new one.
|
||||
template <class ELFT>
|
||||
std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name) {
|
||||
// <name>@@<version> means the symbol is the default version. In that
|
||||
// case symbol <name> must exist and <name>@@<version> will be used to
|
||||
// resolve references to <name>.
|
||||
size_t Pos = Name.find("@@");
|
||||
if (Pos != StringRef::npos)
|
||||
Name = Name.take_front(Pos);
|
||||
|
||||
auto P = Symtab.insert(
|
||||
{CachedHashStringRef(Name), SymIndex((int)SymVector.size(), false)});
|
||||
SymIndex &V = P.first->second;
|
||||
|
|
@ -400,9 +393,8 @@ static void warnOrError(const Twine &Msg) {
|
|||
}
|
||||
|
||||
static void reportDuplicate(SymbolBody *Sym, InputFile *NewFile) {
|
||||
warnOrError("duplicate symbol: " + toString(*Sym) +
|
||||
"\n>>> defined in " + toString(Sym->File) +
|
||||
"\n>>> defined in " + toString(NewFile));
|
||||
warnOrError("duplicate symbol: " + toString(*Sym) + "\n>>> defined in " +
|
||||
toString(Sym->File) + "\n>>> defined in " + toString(NewFile));
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
|
@ -680,7 +672,8 @@ template <class ELFT> void SymbolTable<ELFT>::handleAnonymousVersion() {
|
|||
// Set symbol versions to symbols. This function handles patterns
|
||||
// containing no wildcard characters.
|
||||
template <class ELFT>
|
||||
void SymbolTable<ELFT>::assignExactVersion(SymbolVersion Ver, uint16_t VersionId,
|
||||
void SymbolTable<ELFT>::assignExactVersion(SymbolVersion Ver,
|
||||
uint16_t VersionId,
|
||||
StringRef VersionName) {
|
||||
if (Ver.HasWildcard)
|
||||
return;
|
||||
|
|
@ -724,13 +717,35 @@ void SymbolTable<ELFT>::assignWildcardVersion(SymbolVersion Ver,
|
|||
B->symbol()->VersionId = VersionId;
|
||||
}
|
||||
|
||||
static bool isDefaultVersion(SymbolBody *B) {
|
||||
return B->isInCurrentDSO() && B->getName().find("@@") != StringRef::npos;
|
||||
}
|
||||
|
||||
// This function processes version scripts by updating VersionId
|
||||
// member of symbols.
|
||||
template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() {
|
||||
// Symbol themselves might know their versions because symbols
|
||||
// can contain versions in the form of <name>@<version>.
|
||||
// Let them parse and update their names to exclude version suffix.
|
||||
for (Symbol *Sym : SymVector) {
|
||||
SymbolBody *Body = Sym->body();
|
||||
bool IsDefault = isDefaultVersion(Body);
|
||||
Body->parseSymbolVersion();
|
||||
|
||||
if (!IsDefault)
|
||||
continue;
|
||||
|
||||
// <name>@@<version> means the symbol is the default version. If that's the
|
||||
// case, the symbol is not used only to resolve <name> of version <version>
|
||||
// but also undefined unversioned symbols with name <name>.
|
||||
SymbolBody *S = find(Body->getName());
|
||||
if (S && S->isUndefined())
|
||||
S->copy(Body);
|
||||
}
|
||||
|
||||
// Handle edge cases first.
|
||||
handleAnonymousVersion();
|
||||
|
||||
|
||||
// Now we have version definitions, so we need to set version ids to symbols.
|
||||
// Each version definition has a glob pattern, and all symbols that match
|
||||
// with the pattern get that version.
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ static uint64_t getSymVA(const SymbolBody &Body, int64_t &Addend) {
|
|||
if (D.isTls() && !Config->Relocatable) {
|
||||
if (!Out::TlsPhdr)
|
||||
fatal(toString(D.File) +
|
||||
" has a STT_TLS symbol but doesn't have a PT_TLS section");
|
||||
" has an STT_TLS symbol but doesn't have an SHF_TLS section");
|
||||
return VA - Out::TlsPhdr->p_vaddr;
|
||||
}
|
||||
return VA;
|
||||
|
|
|
|||
|
|
@ -662,7 +662,12 @@ bool GotSection::empty() const {
|
|||
return NumEntries == 0 && !HasGotOffRel;
|
||||
}
|
||||
|
||||
void GotSection::writeTo(uint8_t *Buf) { relocateAlloc(Buf, Buf + Size); }
|
||||
void GotSection::writeTo(uint8_t *Buf) {
|
||||
// Buf points to the start of this section's buffer,
|
||||
// whereas InputSectionBase::relocateAlloc() expects its argument
|
||||
// to point to the start of the output section.
|
||||
relocateAlloc(Buf - OutSecOff, Buf - OutSecOff + Size);
|
||||
}
|
||||
|
||||
MipsGotSection::MipsGotSection()
|
||||
: SyntheticSection(SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL, SHT_PROGBITS, 16,
|
||||
|
|
@ -812,9 +817,7 @@ unsigned MipsGotSection::getLocalEntriesNum() const {
|
|||
LocalEntries32.size();
|
||||
}
|
||||
|
||||
void MipsGotSection::finalizeContents() {
|
||||
updateAllocSize();
|
||||
}
|
||||
void MipsGotSection::finalizeContents() { updateAllocSize(); }
|
||||
|
||||
void MipsGotSection::updateAllocSize() {
|
||||
PageEntriesNum = 0;
|
||||
|
|
@ -838,9 +841,7 @@ bool MipsGotSection::empty() const {
|
|||
return Config->Relocatable;
|
||||
}
|
||||
|
||||
uint64_t MipsGotSection::getGp() const {
|
||||
return ElfSym::MipsGp->getVA(0);
|
||||
}
|
||||
uint64_t MipsGotSection::getGp() const { return ElfSym::MipsGp->getVA(0); }
|
||||
|
||||
static uint64_t readUint(uint8_t *Buf) {
|
||||
if (Config->Is64)
|
||||
|
|
@ -1019,6 +1020,8 @@ DynamicSection<ELFT>::DynamicSection()
|
|||
template <class ELFT> void DynamicSection<ELFT>::addEntries() {
|
||||
// Add strings to .dynstr early so that .dynstr's size will be
|
||||
// fixed early.
|
||||
for (StringRef S : Config->FilterList)
|
||||
add({DT_FILTER, InX::DynStrTab->addString(S)});
|
||||
for (StringRef S : Config->AuxiliaryList)
|
||||
add({DT_AUXILIARY, InX::DynStrTab->addString(S)});
|
||||
if (!Config->Rpath.empty())
|
||||
|
|
@ -1607,7 +1610,7 @@ HashTableSection<ELFT>::HashTableSection()
|
|||
template <class ELFT> void HashTableSection<ELFT>::finalizeContents() {
|
||||
getParent()->Link = InX::DynSymTab->getParent()->SectionIndex;
|
||||
|
||||
unsigned NumEntries = 2; // nbucket and nchain.
|
||||
unsigned NumEntries = 2; // nbucket and nchain.
|
||||
NumEntries += InX::DynSymTab->getNumSymbols(); // The chain entries.
|
||||
|
||||
// Create as many buckets as there are symbols.
|
||||
|
|
@ -1926,9 +1929,7 @@ void GdbIndexSection::writeTo(uint8_t *Buf) {
|
|||
StringPool.write(Buf);
|
||||
}
|
||||
|
||||
bool GdbIndexSection::empty() const {
|
||||
return !Out::DebugInfo;
|
||||
}
|
||||
bool GdbIndexSection::empty() const { return !Out::DebugInfo; }
|
||||
|
||||
template <class ELFT>
|
||||
EhFrameHeader<ELFT>::EhFrameHeader()
|
||||
|
|
@ -2211,9 +2212,7 @@ void MergeSyntheticSection::finalizeContents() {
|
|||
finalizeNoTailMerge();
|
||||
}
|
||||
|
||||
size_t MergeSyntheticSection::getSize() const {
|
||||
return Builder.getSize();
|
||||
}
|
||||
size_t MergeSyntheticSection::getSize() const { return Builder.getSize(); }
|
||||
|
||||
// This function decompresses compressed sections and scans over the input
|
||||
// sections to create mergeable synthetic sections. It removes
|
||||
|
|
@ -2312,7 +2311,7 @@ ThunkSection::ThunkSection(OutputSection *OS, uint64_t Off)
|
|||
}
|
||||
|
||||
void ThunkSection::addThunk(Thunk *T) {
|
||||
uint64_t Off = alignTo(Size, T->alignment);
|
||||
uint64_t Off = alignTo(Size, T->Alignment);
|
||||
T->Offset = Off;
|
||||
Thunks.push_back(T);
|
||||
T->addSymbols(*this);
|
||||
|
|
|
|||
|
|
@ -128,6 +128,11 @@ bool TargetInfo::needsThunk(RelExpr Expr, uint32_t RelocType,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool TargetInfo::inBranchRange(uint32_t RelocType, uint64_t Src,
|
||||
uint64_t Dst) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void TargetInfo::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const {
|
||||
writeGotPlt(Buf, S);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,9 @@ public:
|
|||
// targeting S.
|
||||
virtual bool needsThunk(RelExpr Expr, uint32_t RelocType,
|
||||
const InputFile *File, const SymbolBody &S) const;
|
||||
// Return true if we can reach Dst from Src with Relocation RelocType
|
||||
virtual bool inBranchRange(uint32_t RelocType, uint64_t Src,
|
||||
uint64_t Dst) const;
|
||||
virtual RelExpr getRelExpr(uint32_t Type, const SymbolBody &S,
|
||||
const uint8_t *Loc) const = 0;
|
||||
virtual void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const = 0;
|
||||
|
|
@ -154,6 +157,6 @@ static void checkAlignment(uint8_t *Loc, uint64_t V, uint32_t Type) {
|
|||
lld::toString(Type));
|
||||
}
|
||||
} // namespace elf
|
||||
}
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ inline void parallelForEachN(size_t Begin, size_t End,
|
|||
else
|
||||
for_each_n(llvm::parallel::seq, Begin, End, Fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace elf
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -72,9 +72,7 @@ public:
|
|||
|
||||
class ThumbV7ABSLongThunk final : public Thunk {
|
||||
public:
|
||||
ThumbV7ABSLongThunk(const SymbolBody &Dest) : Thunk(Dest) {
|
||||
alignment = 2;
|
||||
}
|
||||
ThumbV7ABSLongThunk(const SymbolBody &Dest) : Thunk(Dest) { Alignment = 2; }
|
||||
|
||||
uint32_t size() const override { return 10; }
|
||||
void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
|
||||
|
|
@ -84,9 +82,7 @@ public:
|
|||
|
||||
class ThumbV7PILongThunk final : public Thunk {
|
||||
public:
|
||||
ThumbV7PILongThunk(const SymbolBody &Dest) : Thunk(Dest) {
|
||||
alignment = 2;
|
||||
}
|
||||
ThumbV7PILongThunk(const SymbolBody &Dest) : Thunk(Dest) { Alignment = 2; }
|
||||
|
||||
uint32_t size() const override { return 12; }
|
||||
void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
|
||||
|
|
@ -218,10 +214,10 @@ bool ThumbV7PILongThunk::isCompatibleWith(uint32_t RelocType) const {
|
|||
// Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
|
||||
void MipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const {
|
||||
uint64_t S = Destination.getVA();
|
||||
write32(Buf, 0x3c190000, Config->Endianness); // lui $25, %hi(func)
|
||||
write32(Buf, 0x3c190000, Config->Endianness); // lui $25, %hi(func)
|
||||
write32(Buf + 4, 0x08000000 | (S >> 2), Config->Endianness); // j func
|
||||
write32(Buf + 8, 0x27390000, Config->Endianness); // addiu $25, $25, %lo(func)
|
||||
write32(Buf + 12, 0x00000000, Config->Endianness); // nop
|
||||
write32(Buf + 8, 0x27390000, Config->Endianness); // addiu $25, $25, %lo(func)
|
||||
write32(Buf + 12, 0x00000000, Config->Endianness); // nop
|
||||
Target->relocateOne(Buf, R_MIPS_HI16, S);
|
||||
Target->relocateOne(Buf + 8, R_MIPS_LO16, S);
|
||||
}
|
||||
|
|
@ -262,9 +258,7 @@ static Thunk *addThunkArm(uint32_t Reloc, SymbolBody &S) {
|
|||
fatal("unrecognized relocation type");
|
||||
}
|
||||
|
||||
static Thunk *addThunkMips(SymbolBody &S) {
|
||||
return make<MipsThunk>(S);
|
||||
}
|
||||
static Thunk *addThunkMips(SymbolBody &S) { return make<MipsThunk>(S); }
|
||||
|
||||
Thunk *addThunk(uint32_t RelocType, SymbolBody &S) {
|
||||
if (Config->EMachine == EM_ARM)
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ public:
|
|||
const SymbolBody &Destination;
|
||||
SymbolBody *ThunkSym;
|
||||
uint64_t Offset;
|
||||
uint32_t alignment = 4;
|
||||
uint32_t Alignment = 4;
|
||||
};
|
||||
|
||||
// For a Relocation to symbol S create a Thunk to be added to a synthetic
|
||||
|
|
|
|||
|
|
@ -257,7 +257,6 @@ template <class ELFT> void Writer<ELFT>::run() {
|
|||
if (ErrorCount)
|
||||
return;
|
||||
|
||||
|
||||
// Handle -Map option.
|
||||
writeMapFile<ELFT>(OutputSectionCommands);
|
||||
if (ErrorCount)
|
||||
|
|
@ -1331,7 +1330,7 @@ template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
|
|||
// ARM ABI requires .ARM.exidx to be terminated by some piece of data.
|
||||
// We have the terminater synthetic section class. Add that at the end.
|
||||
OutputSectionCommand *Cmd = findSectionCommand(".ARM.exidx");
|
||||
if (!Cmd || Cmd->Commands.empty() || Config->Relocatable)
|
||||
if (!Cmd || !Cmd->Sec || Config->Relocatable)
|
||||
return;
|
||||
|
||||
auto *Sentinel = make<ARMExidxSentinelSection>();
|
||||
|
|
@ -1392,7 +1391,8 @@ OutputSectionCommand *Writer<ELFT>::findSectionCommand(StringRef Name) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
template <class ELFT> OutputSection *Writer<ELFT>::findSectionInScript(StringRef Name) {
|
||||
template <class ELFT>
|
||||
OutputSection *Writer<ELFT>::findSectionInScript(StringRef Name) {
|
||||
if (OutputSectionCommand *Cmd = findSectionCommand(Name))
|
||||
return Cmd->Sec;
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ uint8_t getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag,
|
|||
llvm::StringRef FileName);
|
||||
|
||||
bool isMipsN32Abi(const InputFile *F);
|
||||
}
|
||||
}
|
||||
} // namespace elf
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@ Development status
|
|||
Driver
|
||||
:good:`Mostly done`. Some exotic command line options that are not usually
|
||||
used for application develompent, such as ``/DRIVER``, are not supported.
|
||||
Options for Windows 8 app store are not recognized too
|
||||
(e.g. ``/APPCONTAINER``).
|
||||
|
||||
Linking against DLL
|
||||
:good:`Done`. LLD can read import libraries needed to link against DLL. Both
|
||||
|
|
@ -44,8 +42,7 @@ Creating DLL
|
|||
:good:`Done`. LLD creates a DLL if ``/DLL`` option is given. Exported
|
||||
functions can be specified either via command line (``/EXPORT``) or via
|
||||
module-definition file (.def). Both export-by-name and export-by-ordinal are
|
||||
supported. LLD uses Microsoft ``lib.exe`` tool to create an import library
|
||||
file.
|
||||
supported.
|
||||
|
||||
Windows resource files support
|
||||
:good:`Done`. If an ``.res`` file is given, LLD converts the file to a COFF
|
||||
|
|
|
|||
2
test/COFF/Inputs/default.def
Normal file
2
test/COFF/Inputs/default.def
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
EXPORTS
|
||||
f
|
||||
3
test/COFF/Inputs/extension.def
Normal file
3
test/COFF/Inputs/extension.def
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
LIBRARY library.ext
|
||||
EXPORTS
|
||||
f
|
||||
3
test/COFF/Inputs/named.def
Normal file
3
test/COFF/Inputs/named.def
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
LIBRARY library
|
||||
EXPORTS
|
||||
f
|
||||
13
test/COFF/Inputs/object.s
Normal file
13
test/COFF/Inputs/object.s
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
.text
|
||||
|
||||
.def f
|
||||
.scl 2
|
||||
.type 32
|
||||
.endef
|
||||
.global f
|
||||
f:
|
||||
retq $0
|
||||
|
||||
.section .drectve,"rd"
|
||||
.ascii " /EXPORT:f"
|
||||
255
test/COFF/Inputs/pdb-type-server-simple-a.yaml
Normal file
255
test/COFF/Inputs/pdb-type-server-simple-a.yaml
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
--- !COFF
|
||||
header:
|
||||
Machine: IMAGE_FILE_MACHINE_AMD64
|
||||
Characteristics: [ ]
|
||||
sections:
|
||||
- Name: .drectve
|
||||
Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
|
||||
Alignment: 1
|
||||
SectionData: 2020202F44454641554C544C49423A224C4942434D5422202F44454641554C544C49423A224F4C444E414D45532220
|
||||
- Name: '.debug$S'
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 1
|
||||
Subsections:
|
||||
- !Symbols
|
||||
Records:
|
||||
- Kind: S_OBJNAME
|
||||
ObjNameSym:
|
||||
Signature: 0
|
||||
ObjectName: 'C:\src\llvm-project\build\a.obj'
|
||||
- Kind: S_COMPILE3
|
||||
Compile3Sym:
|
||||
Flags: [ SecurityChecks, HotPatch ]
|
||||
Machine: X64
|
||||
FrontendMajor: 19
|
||||
FrontendMinor: 0
|
||||
FrontendBuild: 24215
|
||||
FrontendQFE: 1
|
||||
BackendMajor: 19
|
||||
BackendMinor: 0
|
||||
BackendBuild: 24215
|
||||
BackendQFE: 1
|
||||
Version: 'Microsoft (R) Optimizing Compiler'
|
||||
- !Symbols
|
||||
Records:
|
||||
- Kind: S_GPROC32_ID
|
||||
ProcSym:
|
||||
CodeSize: 27
|
||||
DbgStart: 4
|
||||
DbgEnd: 22
|
||||
FunctionType: 4098
|
||||
Flags: [ ]
|
||||
DisplayName: main
|
||||
- Kind: S_FRAMEPROC
|
||||
FrameProcSym:
|
||||
TotalFrameBytes: 56
|
||||
PaddingFrameBytes: 0
|
||||
OffsetToPadding: 0
|
||||
BytesOfCalleeSavedRegisters: 0
|
||||
OffsetOfExceptionHandler: 0
|
||||
SectionIdOfExceptionHandler: 0
|
||||
Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ]
|
||||
- Kind: S_REGREL32
|
||||
RegRelativeSym:
|
||||
Offset: 32
|
||||
Type: 4102
|
||||
Register: RSP
|
||||
VarName: f
|
||||
- Kind: S_PROC_ID_END
|
||||
ScopeEndSym:
|
||||
- !Lines
|
||||
CodeSize: 27
|
||||
Flags: [ ]
|
||||
RelocOffset: 0
|
||||
RelocSegment: 0
|
||||
Blocks:
|
||||
- FileName: 'c:\src\llvm-project\build\a.c'
|
||||
Lines:
|
||||
- Offset: 0
|
||||
LineStart: 3
|
||||
IsStatement: true
|
||||
EndDelta: 0
|
||||
- Offset: 4
|
||||
LineStart: 4
|
||||
IsStatement: true
|
||||
EndDelta: 0
|
||||
- Offset: 12
|
||||
LineStart: 5
|
||||
IsStatement: true
|
||||
EndDelta: 0
|
||||
- Offset: 22
|
||||
LineStart: 6
|
||||
IsStatement: true
|
||||
EndDelta: 0
|
||||
Columns:
|
||||
- !Symbols
|
||||
Records:
|
||||
- Kind: S_UDT
|
||||
UDTSym:
|
||||
Type: 4102
|
||||
UDTName: Foo
|
||||
- !FileChecksums
|
||||
Checksums:
|
||||
- FileName: 'c:\src\llvm-project\build\a.c'
|
||||
Kind: MD5
|
||||
Checksum: BF69E7E933074E1B7ED1FE8FB395965B
|
||||
- !StringTable
|
||||
Strings:
|
||||
- 'c:\src\llvm-project\build\a.c'
|
||||
- !Symbols
|
||||
Records:
|
||||
- Kind: S_BUILDINFO
|
||||
BuildInfoSym:
|
||||
BuildId: 4107
|
||||
Relocations:
|
||||
- VirtualAddress: 152
|
||||
SymbolName: main
|
||||
Type: IMAGE_REL_AMD64_SECREL
|
||||
- VirtualAddress: 156
|
||||
SymbolName: main
|
||||
Type: IMAGE_REL_AMD64_SECTION
|
||||
- VirtualAddress: 224
|
||||
SymbolName: main
|
||||
Type: IMAGE_REL_AMD64_SECREL
|
||||
- VirtualAddress: 228
|
||||
SymbolName: main
|
||||
Type: IMAGE_REL_AMD64_SECTION
|
||||
- Name: '.debug$T'
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 1
|
||||
Types:
|
||||
- Kind: LF_TYPESERVER2
|
||||
TypeServer2:
|
||||
Guid: '{41414141-4141-4141-4141-414141414141}'
|
||||
Age: 1
|
||||
Name: 'C:\src\llvm-project\build\ts.pdb'
|
||||
- Name: '.text$mn'
|
||||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 16
|
||||
SectionData: 4883EC38C74424202A000000488D4C2420E8000000004883C438C3
|
||||
Relocations:
|
||||
- VirtualAddress: 18
|
||||
SymbolName: g
|
||||
Type: IMAGE_REL_AMD64_REL32
|
||||
- Name: .xdata
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 4
|
||||
SectionData: '0104010004620000'
|
||||
- Name: .pdata
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 4
|
||||
SectionData: 000000001B00000000000000
|
||||
Relocations:
|
||||
- VirtualAddress: 0
|
||||
SymbolName: '$LN3'
|
||||
Type: IMAGE_REL_AMD64_ADDR32NB
|
||||
- VirtualAddress: 4
|
||||
SymbolName: '$LN3'
|
||||
Type: IMAGE_REL_AMD64_ADDR32NB
|
||||
- VirtualAddress: 8
|
||||
SymbolName: '$unwind$main'
|
||||
Type: IMAGE_REL_AMD64_ADDR32NB
|
||||
symbols:
|
||||
- Name: .drectve
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 47
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 0
|
||||
- Name: '.debug$S'
|
||||
Value: 0
|
||||
SectionNumber: 2
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 388
|
||||
NumberOfRelocations: 4
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 0
|
||||
- Name: '.debug$T'
|
||||
Value: 0
|
||||
SectionNumber: 3
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 64
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 0
|
||||
- Name: '.text$mn'
|
||||
Value: 0
|
||||
SectionNumber: 4
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 27
|
||||
NumberOfRelocations: 1
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 1939996292
|
||||
Number: 0
|
||||
- Name: g
|
||||
Value: 0
|
||||
SectionNumber: 0
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
- Name: main
|
||||
Value: 0
|
||||
SectionNumber: 4
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
- Name: '$LN3'
|
||||
Value: 0
|
||||
SectionNumber: 4
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_LABEL
|
||||
- Name: .xdata
|
||||
Value: 0
|
||||
SectionNumber: 5
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 8
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 931692337
|
||||
Number: 0
|
||||
- Name: '$unwind$main'
|
||||
Value: 0
|
||||
SectionNumber: 5
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
- Name: .pdata
|
||||
Value: 0
|
||||
SectionNumber: 6
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 12
|
||||
NumberOfRelocations: 3
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 567356797
|
||||
Number: 0
|
||||
- Name: '$pdata$main'
|
||||
Value: 0
|
||||
SectionNumber: 6
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
...
|
||||
173
test/COFF/Inputs/pdb-type-server-simple-b.yaml
Normal file
173
test/COFF/Inputs/pdb-type-server-simple-b.yaml
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
--- !COFF
|
||||
header:
|
||||
Machine: IMAGE_FILE_MACHINE_AMD64
|
||||
Characteristics: [ ]
|
||||
sections:
|
||||
- Name: .drectve
|
||||
Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
|
||||
Alignment: 1
|
||||
SectionData: 2020202F44454641554C544C49423A224C4942434D5422202F44454641554C544C49423A224F4C444E414D45532220
|
||||
- Name: '.debug$S'
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 1
|
||||
Subsections:
|
||||
- !Symbols
|
||||
Records:
|
||||
- Kind: S_OBJNAME
|
||||
ObjNameSym:
|
||||
Signature: 0
|
||||
ObjectName: 'C:\src\llvm-project\build\b.obj'
|
||||
- Kind: S_COMPILE3
|
||||
Compile3Sym:
|
||||
Flags: [ SecurityChecks, HotPatch ]
|
||||
Machine: X64
|
||||
FrontendMajor: 19
|
||||
FrontendMinor: 0
|
||||
FrontendBuild: 24215
|
||||
FrontendQFE: 1
|
||||
BackendMajor: 19
|
||||
BackendMinor: 0
|
||||
BackendBuild: 24215
|
||||
BackendQFE: 1
|
||||
Version: 'Microsoft (R) Optimizing Compiler'
|
||||
- !Symbols
|
||||
Records:
|
||||
- Kind: S_GPROC32_ID
|
||||
ProcSym:
|
||||
CodeSize: 13
|
||||
DbgStart: 5
|
||||
DbgEnd: 12
|
||||
FunctionType: 4099
|
||||
Flags: [ ]
|
||||
DisplayName: g
|
||||
- Kind: S_FRAMEPROC
|
||||
FrameProcSym:
|
||||
TotalFrameBytes: 0
|
||||
PaddingFrameBytes: 0
|
||||
OffsetToPadding: 0
|
||||
BytesOfCalleeSavedRegisters: 0
|
||||
OffsetOfExceptionHandler: 0
|
||||
SectionIdOfExceptionHandler: 0
|
||||
Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ]
|
||||
- Kind: S_REGREL32
|
||||
RegRelativeSym:
|
||||
Offset: 8
|
||||
Type: 4097
|
||||
Register: RSP
|
||||
VarName: p
|
||||
- Kind: S_PROC_ID_END
|
||||
ScopeEndSym:
|
||||
- !Lines
|
||||
CodeSize: 13
|
||||
Flags: [ ]
|
||||
RelocOffset: 0
|
||||
RelocSegment: 0
|
||||
Blocks:
|
||||
- FileName: 'c:\src\llvm-project\build\b.c'
|
||||
Lines:
|
||||
- Offset: 0
|
||||
LineStart: 2
|
||||
IsStatement: true
|
||||
EndDelta: 0
|
||||
Columns:
|
||||
- !Symbols
|
||||
Records:
|
||||
- Kind: S_UDT
|
||||
UDTSym:
|
||||
Type: 4102
|
||||
UDTName: Foo
|
||||
- !FileChecksums
|
||||
Checksums:
|
||||
- FileName: 'c:\src\llvm-project\build\b.c'
|
||||
Kind: MD5
|
||||
Checksum: DDF8FD35CD67990C5D4147516BE10D0C
|
||||
- !StringTable
|
||||
Strings:
|
||||
- 'c:\src\llvm-project\build\b.c'
|
||||
- !Symbols
|
||||
Records:
|
||||
- Kind: S_BUILDINFO
|
||||
BuildInfoSym:
|
||||
BuildId: 4111
|
||||
Relocations:
|
||||
- VirtualAddress: 152
|
||||
SymbolName: g
|
||||
Type: IMAGE_REL_AMD64_SECREL
|
||||
- VirtualAddress: 156
|
||||
SymbolName: g
|
||||
Type: IMAGE_REL_AMD64_SECTION
|
||||
- VirtualAddress: 220
|
||||
SymbolName: g
|
||||
Type: IMAGE_REL_AMD64_SECREL
|
||||
- VirtualAddress: 224
|
||||
SymbolName: g
|
||||
Type: IMAGE_REL_AMD64_SECTION
|
||||
- Name: '.debug$T'
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 1
|
||||
Types:
|
||||
- Kind: LF_TYPESERVER2
|
||||
TypeServer2:
|
||||
Guid: '{41414141-4141-4141-4141-414141414141}'
|
||||
Age: 1
|
||||
Name: 'C:\src\llvm-project\build\ts.pdb'
|
||||
- Name: '.text$mn'
|
||||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 16
|
||||
SectionData: 48894C2408488B4424088B00C3
|
||||
symbols:
|
||||
- Name: .drectve
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 47
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 0
|
||||
- Name: '.debug$S'
|
||||
Value: 0
|
||||
SectionNumber: 2
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 360
|
||||
NumberOfRelocations: 4
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 0
|
||||
- Name: '.debug$T'
|
||||
Value: 0
|
||||
SectionNumber: 3
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 64
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 0
|
||||
- Name: '.text$mn'
|
||||
Value: 0
|
||||
SectionNumber: 4
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 13
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 3246683207
|
||||
Number: 0
|
||||
- Name: g
|
||||
Value: 0
|
||||
SectionNumber: 4
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
...
|
||||
147
test/COFF/Inputs/pdb-type-server-simple-ts.yaml
Normal file
147
test/COFF/Inputs/pdb-type-server-simple-ts.yaml
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
---
|
||||
MSF:
|
||||
SuperBlock:
|
||||
BlockSize: 4096
|
||||
FreeBlockMap: 1
|
||||
NumBlocks: 19
|
||||
NumDirectoryBytes: 64
|
||||
Unknown1: 0
|
||||
BlockMapAddr: 17
|
||||
NumDirectoryBlocks: 1
|
||||
DirectoryBlocks: [ 16 ]
|
||||
NumStreams: 0
|
||||
FileSize: 77824
|
||||
PdbStream:
|
||||
Age: 1
|
||||
Guid: '{41414141-4141-4141-4141-414141414141}'
|
||||
Signature: 1500053944
|
||||
Features: [ VC140 ]
|
||||
Version: VC70
|
||||
TpiStream:
|
||||
Version: VC80
|
||||
Records:
|
||||
- Kind: LF_STRUCTURE
|
||||
Class:
|
||||
MemberCount: 0
|
||||
Options: [ None, ForwardReference, HasUniqueName ]
|
||||
FieldList: 0
|
||||
Name: Foo
|
||||
UniqueName: '.?AUFoo@@'
|
||||
DerivationList: 0
|
||||
VTableShape: 0
|
||||
Size: 0
|
||||
- Kind: LF_POINTER
|
||||
Pointer:
|
||||
ReferentType: 4096
|
||||
Attrs: 65548
|
||||
- Kind: LF_ARGLIST
|
||||
ArgList:
|
||||
ArgIndices: [ 4097 ]
|
||||
- Kind: LF_PROCEDURE
|
||||
Procedure:
|
||||
ReturnType: 116
|
||||
CallConv: NearC
|
||||
Options: [ None ]
|
||||
ParameterCount: 1
|
||||
ArgumentList: 4098
|
||||
- Kind: LF_POINTER
|
||||
Pointer:
|
||||
ReferentType: 4099
|
||||
Attrs: 65548
|
||||
- Kind: LF_FIELDLIST
|
||||
FieldList:
|
||||
- Kind: LF_MEMBER
|
||||
DataMember:
|
||||
Attrs: 3
|
||||
Type: 116
|
||||
FieldOffset: 0
|
||||
Name: x
|
||||
- Kind: LF_STRUCTURE
|
||||
Class:
|
||||
MemberCount: 1
|
||||
Options: [ None, HasUniqueName ]
|
||||
FieldList: 4101
|
||||
Name: Foo
|
||||
UniqueName: '.?AUFoo@@'
|
||||
DerivationList: 0
|
||||
VTableShape: 0
|
||||
Size: 4
|
||||
- Kind: LF_ARGLIST
|
||||
ArgList:
|
||||
ArgIndices: [ 0 ]
|
||||
- Kind: LF_PROCEDURE
|
||||
Procedure:
|
||||
ReturnType: 116
|
||||
CallConv: NearC
|
||||
Options: [ None ]
|
||||
ParameterCount: 0
|
||||
ArgumentList: 4103
|
||||
IpiStream:
|
||||
Version: VC80
|
||||
Records:
|
||||
- Kind: LF_STRING_ID
|
||||
StringId:
|
||||
Id: 0
|
||||
String: 'c:\src\llvm-project\build\a.c'
|
||||
- Kind: LF_UDT_SRC_LINE
|
||||
UdtSourceLine:
|
||||
UDT: 4102
|
||||
SourceFile: 4096
|
||||
LineNumber: 1
|
||||
- Kind: LF_FUNC_ID
|
||||
FuncId:
|
||||
ParentScope: 0
|
||||
FunctionType: 4104
|
||||
Name: main
|
||||
- Kind: LF_FUNC_ID
|
||||
FuncId:
|
||||
ParentScope: 0
|
||||
FunctionType: 4099
|
||||
Name: g
|
||||
- Kind: LF_STRING_ID
|
||||
StringId:
|
||||
Id: 0
|
||||
String: 'C:\src\llvm-project\build'
|
||||
- Kind: LF_STRING_ID
|
||||
StringId:
|
||||
Id: 0
|
||||
String: 'C:\PROGRA~2\MICROS~1.0\VC\Bin\amd64\cl.exe'
|
||||
- Kind: LF_STRING_ID
|
||||
StringId:
|
||||
Id: 0
|
||||
String: '-c -Zi -MT -IC:\PROGRA~2\MICROS~1.0\VC\include -IC:\PROGRA~2\MICROS~1.0\VC\atlmfc\include -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\ucrt -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\shared -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\um'
|
||||
- Kind: LF_SUBSTR_LIST
|
||||
StringList:
|
||||
StringIndices: [ 4102 ]
|
||||
- Kind: LF_STRING_ID
|
||||
StringId:
|
||||
Id: 4103
|
||||
String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X'
|
||||
- Kind: LF_STRING_ID
|
||||
StringId:
|
||||
Id: 0
|
||||
String: a.c
|
||||
- Kind: LF_STRING_ID
|
||||
StringId:
|
||||
Id: 0
|
||||
String: 'C:\src\llvm-project\build\ts.pdb'
|
||||
- Kind: LF_BUILDINFO
|
||||
BuildInfo:
|
||||
ArgIndices: [ 4100, 4101, 4105, 4106, 4104 ]
|
||||
- Kind: LF_STRING_ID
|
||||
StringId:
|
||||
Id: 0
|
||||
String: 'c:\src\llvm-project\build\b.c'
|
||||
- Kind: LF_UDT_SRC_LINE
|
||||
UdtSourceLine:
|
||||
UDT: 4102
|
||||
SourceFile: 4108
|
||||
LineNumber: 1
|
||||
- Kind: LF_STRING_ID
|
||||
StringId:
|
||||
Id: 0
|
||||
String: b.c
|
||||
- Kind: LF_BUILDINFO
|
||||
BuildInfo:
|
||||
ArgIndices: [ 4100, 4101, 4110, 4106, 4104 ]
|
||||
...
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: yaml2obj %s > %t.obj
|
||||
# RUN: lld-link /out:%t.exe /entry:main %t.obj %t.obj
|
||||
# RUN: llvm-objdump -d %t.exe | FileCheck %s
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: yaml2obj < %s > %t1.obj
|
||||
# RUN: yaml2obj < %s > %t2.obj
|
||||
# RUN: not lld-link /out:%t.exe %t1.obj %t2.obj >& %t.log
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
REQUIRES: x86
|
||||
RUN: mkdir -p %t
|
||||
RUN: llvm-mc -triple i686-unknown-windows-msvc -filetype obj -o %t/import.o %S/Inputs/constant-import.s
|
||||
RUN: llc -mtriple i686-unknown-windows-msvc -filetype obj -o %t/export.o %S/Inputs/constant-export.ll
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=i686-windows-msvc %s -o %t.obj
|
||||
# RUN: echo -e "LIBRARY foo\nEXPORTS\n stdcall" > %t.def
|
||||
# RUN: lld-link -entry:dllmain -dll -def:%t.def %t.obj -out:%t.dll -implib:%t.lib
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj
|
||||
# RUN: lld-link %t.obj %p/Inputs/std32.lib /subsystem:console \
|
||||
# RUN: /entry:main@0 /alternatename:___delayLoadHelper2@8=_main@0 \
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: yaml2obj < %s > %t.obj
|
||||
# RUN: lld-link /out:%t.exe /entry:main %t.obj
|
||||
# RUN: llvm-as -o %t.lto.obj %S/Inputs/entry-mangled.ll
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
; REQUIRES: x86
|
||||
; RUN: llvm-as -o %t.obj %s
|
||||
; RUN: rm -f %t.lib
|
||||
; RUN: llvm-ar cru %t.lib %t.obj
|
||||
|
|
|
|||
71
test/COFF/implib-name.test
Normal file
71
test/COFF/implib-name.test
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# RUN: mkdir -p %T
|
||||
# RUN: llvm-mc -triple x86_64-unknown-windows-msvc -filetype obj -o %T/object.obj %S/Inputs/object.s
|
||||
|
||||
# RUN: lld-link /dll /machine:x64 /def:%S/Inputs/named.def /out:%T/library.dll %T/object.obj /entry:f /subsystem:CONSOLE
|
||||
# RUN: llvm-ar t %T/library.lib | FileCheck %s -check-prefix CHECK-DEFAULT-DLL-EXT
|
||||
|
||||
# RUN: lld-link /machine:x64 /def:%S/Inputs/named.def /out:%T/library.lib
|
||||
# RUN: llvm-ar t %T/library.lib | FileCheck %s -check-prefix CHECK-DEFAULT-DLL-EXT
|
||||
|
||||
CHECK-DEFAULT-DLL-EXT: library.dll
|
||||
CHECK-DEFAULT-DLL-EXT: library.dll
|
||||
CHECK-DEFAULT-DLL-EXT: library.dll
|
||||
CHECK-DEFAULT-DLL-EXT: library.dll
|
||||
|
||||
# RUN: lld-link /machine:x64 /def:%S/Inputs/named.def /out:%T/library.exe %T/object.obj /entry:f /subsystem:CONSOLE
|
||||
# RUN: llvm-ar t %T/library.lib | FileCheck %s -check-prefix CHECK-DEFAULT-EXE-EXT
|
||||
|
||||
CHECK-DEFAULT-EXE-EXT: library.exe
|
||||
CHECK-DEFAULT-EXE-EXT: library.exe
|
||||
CHECK-DEFAULT-EXE-EXT: library.exe
|
||||
CHECK-DEFAULT-EXE-EXT: library.exe
|
||||
|
||||
# RUN: lld-link /dll /machine:x64 /def:%S/Inputs/extension.def /out:%T/extension.dll /entry:f /subsystem:CONSOLE
|
||||
# RUN: llvm-ar t %T/extension.lib | FileCheck %s -check-prefix CHECK-EXTENSION
|
||||
|
||||
# RUN: lld-link /machine:x64 /def:%S/Inputs/extension.def /out:%T/extension.exe /entry:f /subsystem:CONSOLE
|
||||
# RUN: llvm-ar t %T/extension.lib | FileCheck %s -check-prefix CHECK-EXTENSION
|
||||
|
||||
# RUN: lld-link /machine:x64 /def:%S/Inputs/extension.def /out:%T/extension.lib
|
||||
# RUN: llvm-ar t %T/extension.lib | FileCheck %s -check-prefix CHECK-EXTENSION
|
||||
|
||||
CHECK-EXTENSION: library.ext
|
||||
CHECK-EXTENSION: library.ext
|
||||
CHECK-EXTENSION: library.ext
|
||||
CHECK-EXTENSION: library.ext
|
||||
|
||||
# RUN: lld-link /dll /machine:x64 /def:%S/Inputs/default.def /out:%T/default.dll /entry:f /subsystem:CONSOLE
|
||||
# RUN: llvm-ar t %T/default.lib | FileCheck %s -check-prefix CHECK-OUTPUT-NAME-DLL
|
||||
|
||||
# RUN: lld-link /machine:x64 /def:%S/Inputs/default.def /out:%T/default.lib
|
||||
# RUN: llvm-ar t %T/default.lib | FileCheck %s -check-prefix CHECK-OUTPUT-NAME-DLL
|
||||
|
||||
CHECK-OUTPUT-NAME-DLL: default.dll
|
||||
CHECK-OUTPUT-NAME-DLL: default.dll
|
||||
CHECK-OUTPUT-NAME-DLL: default.dll
|
||||
CHECK-OUTPUT-NAME-DLL: default.dll
|
||||
|
||||
# RUN: lld-link /machine:x64 /def:%S/Inputs/default.def /out:%T/default.exe %T/object.obj /entry:f /subsystem:CONSOLE
|
||||
# RUN: llvm-ar t %T/default.lib | FileCheck %s -check-prefix CHECK-OUTPUT-NAME-EXE
|
||||
|
||||
CHECK-OUTPUT-NAME-EXE: default.exe
|
||||
CHECK-OUTPUT-NAME-EXE: default.exe
|
||||
CHECK-OUTPUT-NAME-EXE: default.exe
|
||||
CHECK-OUTPUT-NAME-EXE: default.exe
|
||||
|
||||
# RUN: lld-link /machine:x64 /out:%T/default.exe %T/object.obj /entry:f /subsystem:CONSOLE
|
||||
# RUN: llvm-ar t %T/default.lib | FileCheck %s -check-prefix CHECK-NODEF-EXE
|
||||
|
||||
CHECK-NODEF-EXE: default.exe
|
||||
CHECK-NODEF-EXE: default.exe
|
||||
CHECK-NODEF-EXE: default.exe
|
||||
CHECK-NODEF-EXE: default.exe
|
||||
|
||||
# RUN: lld-link /machine:x64 /dll /out:%T/default.dll %T/object.obj /entry:f /subsystem:CONSOLE
|
||||
# RUN: llvm-ar t %T/default.lib | FileCheck %s -check-prefix CHECK-NODEF-DLL
|
||||
|
||||
CHECK-NODEF-DLL: default.dll
|
||||
CHECK-NODEF-DLL: default.dll
|
||||
CHECK-NODEF-DLL: default.dll
|
||||
CHECK-NODEF-DLL: default.dll
|
||||
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
# REQUIRES: x86
|
||||
# Verify that the lld can handle .lib files and emit .idata sections.
|
||||
#
|
||||
# RUN: lld-link /out:%t.exe /entry:main /subsystem:console \
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
; REQUIRES: x86
|
||||
; RUN: llvm-as -o %t.obj %s
|
||||
; RUN: lld-link /dll /out:%t.dll %t.obj
|
||||
; RUN: llvm-objdump -d %t.dll | FileCheck %s
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
; REQUIRES: x86
|
||||
;; Make sure we re-create archive files to strip bitcode files.
|
||||
|
||||
;; Do not create empty archives because the MSVC linker
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
; REQUIRES: x86
|
||||
; RUN: opt -thinlto-bc %s -o %t.obj
|
||||
; RUN: llc -filetype=obj %S/Inputs/msvclto-order-a.ll -o %T/msvclto-order-a.obj
|
||||
; RUN: llvm-ar crs %T/msvclto-order-a.lib %T/msvclto-order-a.obj
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
; REQUIRES: x86
|
||||
; RUN: llvm-as -o %t.obj %s
|
||||
; RUN: mkdir -p %t.dir
|
||||
; RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o %t.dir/bitcode.obj %p/Inputs/msvclto.s
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ CHECK: flags = has async eh | opt speed
|
|||
CHECK: 196 | S_END [size = 4]
|
||||
CHECK: 200 | S_GDATA32 [size = 24] `global`
|
||||
CHECK: type = 0x0074 (int), addr = 0000:0000
|
||||
CHECK: 224 | S_BUILDINFO [size = 8] BuildId = `4106`
|
||||
CHECK: 224 | S_BUILDINFO [size = 8] BuildId = `0x100A`
|
||||
CHECK: 232 | S_GPROC32_ID [size = 44] `foo`
|
||||
CHECK: parent = 0, end = 308, addr = 0002:0032, code size = 15
|
||||
CHECK: debug start = 0, debug end = 14, flags = none
|
||||
|
|
@ -81,7 +81,7 @@ CHECK: flags = has async eh | opt speed
|
|||
CHECK: 196 | S_END [size = 4]
|
||||
CHECK: 200 | S_GDATA32 [size = 24] `global`
|
||||
CHECK: type = 0x0074 (int), addr = 0000:0000
|
||||
CHECK: 224 | S_BUILDINFO [size = 8] BuildId = `4109`
|
||||
CHECK: 224 | S_BUILDINFO [size = 8] BuildId = `0x100D`
|
||||
CHECK-NOT: S_GPROC32_ID {{.*}} `foo`
|
||||
CHECK-LABEL: Mod 0002 | `* Linker *`:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: rm -rf %t && mkdir -p %t && cd %t
|
||||
# RUN: llvm-mc -filetype=obj -triple=i686-windows-msvc %s -o foo.obj
|
||||
# RUN: llc %S/Inputs/bar.ll -filetype=obj -mtriple=i686-windows-msvc -o bar.obj
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
# CHECK: original type = 0x1004
|
||||
# CHECK: 240 | S_UDT [size = 12] `Foo`
|
||||
# CHECK: original type = 0x1004
|
||||
# CHECK: 252 | S_BUILDINFO [size = 8] BuildId = `4106`
|
||||
# CHECK: 252 | S_BUILDINFO [size = 8] BuildId = `0x100A`
|
||||
# CHECK-LABEL: Mod 0001 | `* Linker *`:
|
||||
|
||||
--- !COFF
|
||||
|
|
|
|||
132
test/COFF/pdb-type-server-missing.yaml
Normal file
132
test/COFF/pdb-type-server-missing.yaml
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
# This is an object compiled with /Zi (see the LF_TYPESERVER2 record) without an
|
||||
# adjacent type server PDB. Test that LLD fails gracefully on it.
|
||||
|
||||
# FIXME: Ideally we'd do what MSVC does, which is to warn and drop all debug
|
||||
# info in the object with the missing PDB.
|
||||
|
||||
# RUN: yaml2obj %s -o %t.obj
|
||||
# RUN: not lld-link %t.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main 2>&1 | FileCheck %s
|
||||
|
||||
# CHECK: error: Type server PDB was not found
|
||||
|
||||
--- !COFF
|
||||
header:
|
||||
Machine: IMAGE_FILE_MACHINE_AMD64
|
||||
Characteristics: [ ]
|
||||
sections:
|
||||
- Name: '.debug$S'
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 1
|
||||
Subsections:
|
||||
- !Symbols
|
||||
Records:
|
||||
- Kind: S_GPROC32_ID
|
||||
ProcSym:
|
||||
CodeSize: 3
|
||||
DbgStart: 0
|
||||
DbgEnd: 2
|
||||
FunctionType: 4199
|
||||
Flags: [ ]
|
||||
DisplayName: main
|
||||
- Kind: S_FRAMEPROC
|
||||
FrameProcSym:
|
||||
TotalFrameBytes: 0
|
||||
PaddingFrameBytes: 0
|
||||
OffsetToPadding: 0
|
||||
BytesOfCalleeSavedRegisters: 0
|
||||
OffsetOfExceptionHandler: 0
|
||||
SectionIdOfExceptionHandler: 0
|
||||
Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ]
|
||||
- Kind: S_PROC_ID_END
|
||||
ScopeEndSym:
|
||||
- !Lines
|
||||
CodeSize: 3
|
||||
Flags: [ ]
|
||||
RelocOffset: 0
|
||||
RelocSegment: 0
|
||||
Blocks:
|
||||
- FileName: 'c:\src\llvm-project\build\t.c'
|
||||
Lines:
|
||||
- Offset: 0
|
||||
LineStart: 1
|
||||
IsStatement: true
|
||||
EndDelta: 0
|
||||
Columns:
|
||||
- !FileChecksums
|
||||
Checksums:
|
||||
- FileName: 'c:\src\llvm-project\build\t.c'
|
||||
Kind: MD5
|
||||
Checksum: 270A878DCC1B845655B162F56C4F5020
|
||||
- !StringTable
|
||||
Strings:
|
||||
- 'c:\src\llvm-project\build\t.c'
|
||||
Relocations:
|
||||
- VirtualAddress: 44
|
||||
SymbolName: main
|
||||
Type: IMAGE_REL_AMD64_SECREL
|
||||
- VirtualAddress: 48
|
||||
SymbolName: main
|
||||
Type: IMAGE_REL_AMD64_SECTION
|
||||
- VirtualAddress: 100
|
||||
SymbolName: main
|
||||
Type: IMAGE_REL_AMD64_SECREL
|
||||
- VirtualAddress: 104
|
||||
SymbolName: main
|
||||
Type: IMAGE_REL_AMD64_SECTION
|
||||
- Name: '.debug$T'
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 1
|
||||
Types:
|
||||
- Kind: LF_TYPESERVER2
|
||||
TypeServer2:
|
||||
Guid: '{01DF191B-22BF-6B42-96CE-5258B8329FE5}'
|
||||
Age: 18
|
||||
Name: 'C:\src\llvm-project\build\definitely_not_found_for_sure.pdb'
|
||||
- Name: '.text$mn'
|
||||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 16
|
||||
SectionData: 33C0C3
|
||||
symbols:
|
||||
- Name: '.debug$S'
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 328
|
||||
NumberOfRelocations: 4
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 0
|
||||
- Name: '.debug$T'
|
||||
Value: 0
|
||||
SectionNumber: 2
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 564
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 0
|
||||
- Name: '.text$mn'
|
||||
Value: 0
|
||||
SectionNumber: 3
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 3
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 4021952397
|
||||
Number: 0
|
||||
- Name: main
|
||||
Value: 0
|
||||
SectionNumber: 3
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
...
|
||||
91
test/COFF/pdb-type-server-simple.test
Normal file
91
test/COFF/pdb-type-server-simple.test
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
Replicate this scenario:
|
||||
|
||||
$ cat a.c
|
||||
struct Foo { int x; };
|
||||
int g(struct Foo *p);
|
||||
int main() {
|
||||
struct Foo f = {42};
|
||||
return g(&f);
|
||||
}
|
||||
|
||||
$ cat b.c
|
||||
struct Foo { int x; };
|
||||
int g(struct Foo *p) { return p->x; }
|
||||
|
||||
$ cl -c a.c b.c -Zi -Fdts.pdb
|
||||
|
||||
$ lld-link a.obj b.obj -debug -entry:main -nodefaultlib -out:t.exe
|
||||
|
||||
RUN: rm -rf %t && mkdir -p %t && cd %t
|
||||
RUN: yaml2obj %S/Inputs/pdb-type-server-simple-a.yaml -o a.obj
|
||||
RUN: yaml2obj %S/Inputs/pdb-type-server-simple-b.yaml -o b.obj
|
||||
RUN: llvm-pdbutil yaml2pdb %S/Inputs/pdb-type-server-simple-ts.yaml -pdb ts.pdb
|
||||
RUN: lld-link a.obj b.obj -entry:main -debug -out:t.exe -pdb:t.pdb -nodefaultlib
|
||||
RUN: llvm-pdbutil dump -symbols -types -ids %t/t.pdb | FileCheck %s
|
||||
|
||||
|
||||
CHECK-LABEL: Types (TPI Stream)
|
||||
CHECK: ============================================================
|
||||
|
||||
CHECK: [[FOO_DECL:[^ ]*]] | LF_STRUCTURE [size = 36] `Foo`
|
||||
|
||||
CHECK: [[FOO_PTR:[^ ]*]] | LF_POINTER [size = 12]
|
||||
CHECK-NEXT: referent = [[FOO_DECL]]
|
||||
|
||||
CHECK: [[G_ARGS:[^ ]*]] | LF_ARGLIST [size = 12]
|
||||
CHECK-NEXT: [[FOO_PTR]]: `Foo*`
|
||||
|
||||
CHECK: [[G_PROTO:[^ ]*]] | LF_PROCEDURE [size = 16]
|
||||
CHECK-NEXT: return type = 0x0074 (int), # args = 1, param list = [[G_ARGS]]
|
||||
CHECK-NEXT: calling conv = cdecl, options = None
|
||||
|
||||
CHECK: [[FOO_COMPLETE:[^ ]*]] | LF_STRUCTURE [size = 36] `Foo`
|
||||
CHECK-NEXT: unique name: `.?AUFoo@@`
|
||||
CHECK-NEXT: vtable: <no type>, base list: <no type>, field list: 0x{{.*}}
|
||||
CHECK: options: has unique name
|
||||
CHECK: [[MAIN_PROTO:[^ ]*]] | LF_PROCEDURE [size = 16]
|
||||
CHECK: return type = 0x0074 (int), # args = 0, param list = 0x{{.*}}
|
||||
CHECK: calling conv = cdecl, options = None
|
||||
|
||||
|
||||
CHECK-LABEL: Types (IPI Stream)
|
||||
CHECK: ============================================================
|
||||
CHECK: [[MAIN_ID:[^ ]*]] | LF_FUNC_ID [size = 20]
|
||||
CHECK: name = main, type = [[MAIN_PROTO]], parent scope = <no type>
|
||||
CHECK: [[G_ID:[^ ]*]] | LF_FUNC_ID [size = 16]
|
||||
CHECK: name = g, type = [[G_PROTO]], parent scope = <no type>
|
||||
CHECK: [[A_BUILD:[^ ]*]] | LF_BUILDINFO [size = 28]
|
||||
CHECK: {{.*}}: `a.c`
|
||||
CHECK: [[B_BUILD:[^ ]*]] | LF_BUILDINFO [size = 28]
|
||||
CHECK: {{.*}}: `b.c`
|
||||
|
||||
CHECK-LABEL: Symbols
|
||||
CHECK: ============================================================
|
||||
CHECK-LABEL: Mod 0000 | `{{.*}}a.obj`:
|
||||
CHECK: 4 | S_OBJNAME [size = 40] sig=0, `C:\src\llvm-project\build\a.obj`
|
||||
CHECK: 104 | S_GPROC32_ID [size = 44] `main`
|
||||
CHECK: parent = 0, end = 196, addr = 0002:0000, code size = 27
|
||||
CHECK: type = {{.*}}, debug start = 4, debug end = 22, flags = none
|
||||
CHECK: 200 | S_UDT [size = 12] `Foo`
|
||||
CHECK: original type = [[FOO_COMPLETE]]
|
||||
CHECK: 212 | S_BUILDINFO [size = 8] BuildId = `[[A_BUILD]]`
|
||||
CHECK-LABEL: Mod 0001 | `{{.*}}b.obj`:
|
||||
CHECK: 4 | S_OBJNAME [size = 40] sig=0, `C:\src\llvm-project\build\b.obj`
|
||||
CHECK: 44 | S_COMPILE3 [size = 60]
|
||||
CHECK: machine = intel x86-x64, Ver = Microsoft (R) Optimizing Compiler, language = c
|
||||
CHECK: frontend = 19.0.24215.1, backend = 19.0.24215.1
|
||||
CHECK: flags = security checks | hot patchable
|
||||
CHECK: 104 | S_GPROC32_ID [size = 44] `g`
|
||||
CHECK: parent = 0, end = 196, addr = 0002:0032, code size = 13
|
||||
CHECK: type = {{.*}}, debug start = 5, debug end = 12, flags = none
|
||||
CHECK: 148 | S_FRAMEPROC [size = 32]
|
||||
CHECK: size = 0, padding size = 0, offset to padding = 0
|
||||
CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000
|
||||
CHECK: flags = has async eh | opt speed
|
||||
CHECK: 180 | S_REGREL32 [size = 16] `p`
|
||||
CHECK: type = [[FOO_PTR]] (Foo*), register = rsp, offset = 8
|
||||
CHECK: 196 | S_END [size = 4]
|
||||
CHECK: 200 | S_UDT [size = 12] `Foo`
|
||||
CHECK: original type = [[FOO_COMPLETE]]
|
||||
CHECK: 212 | S_BUILDINFO [size = 8] BuildId = `[[B_BUILD]]`
|
||||
CHECK-LABEL: Mod 0002 | `* Linker *`:
|
||||
15
test/COFF/reloc-discarded-dwarf.s
Normal file
15
test/COFF/reloc-discarded-dwarf.s
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t1.obj %s
|
||||
# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t2.obj %s
|
||||
|
||||
# LLD should not error on relocations in DWARF debug sections against symbols in
|
||||
# discarded sections.
|
||||
# RUN: lld-link -entry:main -debug %t1.obj %t2.obj
|
||||
|
||||
.section .text,"xr",discard,main
|
||||
.globl main
|
||||
main:
|
||||
f:
|
||||
retq
|
||||
|
||||
.section .debug_info,"dr"
|
||||
.quad f
|
||||
62
test/COFF/reloc-oob.yaml
Normal file
62
test/COFF/reloc-oob.yaml
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# Make sure LLD does some light relocation bounds checking.
|
||||
|
||||
# RUN: yaml2obj %s -o %t.obj
|
||||
# RUN: not lld-link %t.obj -entry:main -nodefaultlib -out:%t.exe 2>&1 | FileCheck %s
|
||||
|
||||
# CHECK: error: relocation points beyond the end of its parent section
|
||||
|
||||
--- !COFF
|
||||
header:
|
||||
Machine: IMAGE_FILE_MACHINE_I386
|
||||
Characteristics: [ ]
|
||||
sections:
|
||||
- Name: .text
|
||||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 16
|
||||
SectionData: 5589E550C745FC00000000A10000000083C4045DC3
|
||||
Relocations:
|
||||
- VirtualAddress: 24
|
||||
SymbolName: _g
|
||||
Type: IMAGE_REL_I386_DIR32
|
||||
- Name: .data
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
|
||||
Alignment: 4
|
||||
SectionData: 2A000000
|
||||
symbols:
|
||||
- Name: .text
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 21
|
||||
NumberOfRelocations: 1
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 662775349
|
||||
Number: 1
|
||||
- Name: .data
|
||||
Value: 0
|
||||
SectionNumber: 2
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 4
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 3482275674
|
||||
Number: 2
|
||||
- Name: _main
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
- Name: _g
|
||||
Value: 0
|
||||
SectionNumber: 2
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
...
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
; REQUIRES: x86
|
||||
; RUN: rm -fr %T/savetemps
|
||||
; RUN: mkdir %T/savetemps
|
||||
; RUN: llvm-as -o %T/savetemps/savetemps.obj %s
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
; REQUIRES: x86
|
||||
; RUN: rm -fr %T/thinlto-archives
|
||||
; RUN: mkdir %T/thinlto-archives %T/thinlto-archives/a %T/thinlto-archives/b
|
||||
; RUN: opt -thinlto-bc -o %T/thinlto-archives/main.obj %s
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
; REQUIRES: x86
|
||||
; RUN: opt -thinlto-bc %s -o %t.obj
|
||||
; RUN: opt -thinlto-bc %S/Inputs/thinlto-mangled-qux.ll -o %T/thinlto-mangled-qux.obj
|
||||
; RUN: lld-link -out:%t.exe -entry:main %t.obj %T/thinlto-mangled-qux.obj
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
; REQUIRES: x86
|
||||
; RUN: rm -fr %T/thinlto
|
||||
; RUN: mkdir %T/thinlto
|
||||
; RUN: opt -thinlto-bc -o %T/thinlto/main.obj %s
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.section .ctors, "aw", @progbits
|
||||
.byte 0xA1
|
||||
.quad 0xA1
|
||||
|
||||
.section .dtors, "aw", @progbits
|
||||
.byte 0xA2
|
||||
.quad 0xA2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.section .ctors, "aw", @progbits
|
||||
.byte 0xB1
|
||||
.quad 0xB1
|
||||
|
||||
.section .dtors, "aw", @progbits
|
||||
.byte 0xB2
|
||||
.quad 0xB2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.section .ctors, "aw", @progbits
|
||||
.byte 0xC1
|
||||
.quad 0xC1
|
||||
|
||||
.section .dtors, "aw", @progbits
|
||||
.byte 0xC2
|
||||
.quad 0xC2
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
73
test/ELF/Inputs/gdb-index.s
Normal file
73
test/ELF/Inputs/gdb-index.s
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
.text
|
||||
.Ltext0:
|
||||
.globl main2
|
||||
.type main2, @function
|
||||
main2:
|
||||
nop
|
||||
nop
|
||||
.Letext0:
|
||||
|
||||
.section .debug_info,"",@progbits
|
||||
.long 0x30
|
||||
.value 0x4
|
||||
.long 0
|
||||
.byte 0x8
|
||||
.uleb128 0x1
|
||||
.quad .Ltext0
|
||||
.quad .Letext0-.Ltext0
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.byte 0x63
|
||||
.byte 0x88
|
||||
.byte 0xb4
|
||||
.byte 0x61
|
||||
.byte 0xaa
|
||||
.byte 0xb6
|
||||
.byte 0xb0
|
||||
.byte 0x67
|
||||
|
||||
.section .debug_abbrev,"",@progbits
|
||||
.uleb128 0x1
|
||||
.uleb128 0x11
|
||||
.byte 0
|
||||
.uleb128 0x11
|
||||
.uleb128 0x1
|
||||
.uleb128 0x12
|
||||
.uleb128 0x7
|
||||
.uleb128 0x10
|
||||
.uleb128 0x17
|
||||
.uleb128 0x2130
|
||||
.uleb128 0xe
|
||||
.uleb128 0x1b
|
||||
.uleb128 0xe
|
||||
.uleb128 0x2134
|
||||
.uleb128 0x19
|
||||
.uleb128 0x2133
|
||||
.uleb128 0x17
|
||||
.uleb128 0x2131
|
||||
.uleb128 0x7
|
||||
.byte 0
|
||||
.byte 0
|
||||
.byte 0
|
||||
|
||||
.section .debug_gnu_pubnames,"",@progbits
|
||||
.long 0x18
|
||||
.value 0x2
|
||||
.long 0
|
||||
.long 0x33
|
||||
.long 0x18
|
||||
.byte 0x30
|
||||
.string "main2"
|
||||
.long 0
|
||||
|
||||
.section .debug_gnu_pubtypes,"",@progbits
|
||||
.long 0x17
|
||||
.value 0x2
|
||||
.long 0
|
||||
.long 0x33
|
||||
.long 0x2b
|
||||
.byte 0x90
|
||||
.string "int"
|
||||
.long 0
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
.text
|
||||
.globl x
|
||||
.type x, @function
|
||||
x:
|
||||
|
||||
.symver x, xx@@VER
|
||||
|
|
@ -1 +0,0 @@
|
|||
call xx@PLT
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
# REQUIRES: x86
|
||||
# --allow-shlib-undefined and --no-allow-shlib-undefined are fully
|
||||
# ignored in linker implementation.
|
||||
# --allow-shlib-undefined is set by default
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# CHECK-NEXT: Other: 0
|
||||
# CHECK-NEXT: Section: Undefined
|
||||
|
||||
# CHECK: NEEDED SharedLibrary ({{.*}}as-needed-no-reloc{{.*}}2.so)
|
||||
# CHECK: NEEDED Shared library: [{{.*}}as-needed-no-reloc{{.*}}2.so]
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
|
|
|
|||
|
|
@ -28,13 +28,13 @@
|
|||
// RUN: ld.lld %t.o %t.script -o %t2
|
||||
// RUN: llvm-readobj -dynamic-table %t2 | FileCheck -check-prefix=CHECK2 %s
|
||||
|
||||
// CHECK: NEEDED SharedLibrary (shared1)
|
||||
// CHECK: NEEDED SharedLibrary (shared2)
|
||||
// CHECK: NEEDED SharedLibrary (shared3)
|
||||
// CHECK: NEEDED Shared library: [shared1]
|
||||
// CHECK: NEEDED Shared library: [shared2]
|
||||
// CHECK: NEEDED Shared library: [shared3]
|
||||
|
||||
// CHECK2: NEEDED SharedLibrary (shared1)
|
||||
// CHECK2-NOT: NEEDED SharedLibrary (shared2)
|
||||
// CHECK2-NOT: NEEDED SharedLibrary (shared3)
|
||||
// CHECK2: NEEDED Shared library: [shared1]
|
||||
// CHECK2-NOT: NEEDED Shared library: [shared2]
|
||||
// CHECK2-NOT: NEEDED Shared library: [shared3]
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
# RUN: ld.lld %t.o -shared -f aaa --auxiliary bbb -o %t
|
||||
# RUN: llvm-readobj --dynamic-table %t | FileCheck %s
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# REQUIRES: zlib
|
||||
# REQUIRES: zlib, x86
|
||||
|
||||
# RUN: llvm-mc -compress-debug-sections=zlib -filetype=obj -triple=x86_64-unknown-linux %s -o %t
|
||||
# RUN: llvm-readobj -sections %t | FileCheck -check-prefix=ZLIB %s
|
||||
|
|
|
|||
|
|
@ -14,28 +14,35 @@ _start:
|
|||
nop
|
||||
|
||||
.section .ctors, "aw", @progbits
|
||||
.byte 1
|
||||
.quad 1
|
||||
.section .ctors.100, "aw", @progbits
|
||||
.byte 2
|
||||
.quad 2
|
||||
.section .ctors.005, "aw", @progbits
|
||||
.byte 3
|
||||
.quad 3
|
||||
.section .ctors, "aw", @progbits
|
||||
.byte 4
|
||||
.quad 4
|
||||
.section .ctors, "aw", @progbits
|
||||
.byte 5
|
||||
.quad 5
|
||||
|
||||
.section .dtors, "aw", @progbits
|
||||
.byte 0x11
|
||||
.quad 0x11
|
||||
.section .dtors.100, "aw", @progbits
|
||||
.byte 0x12
|
||||
.quad 0x12
|
||||
.section .dtors.005, "aw", @progbits
|
||||
.byte 0x13
|
||||
.quad 0x13
|
||||
.section .dtors, "aw", @progbits
|
||||
.byte 0x14
|
||||
.quad 0x14
|
||||
.section .dtors, "aw", @progbits
|
||||
.byte 0x15
|
||||
.quad 0x15
|
||||
|
||||
// CHECK: Contents of section .ctors:
|
||||
// CHECK-NEXT: a1010405 b10302c1
|
||||
// CHECK-NEXT: 202000 a1000000 00000000 01000000 00000000
|
||||
// CHECK-NEXT: 202010 04000000 00000000 05000000 00000000
|
||||
// CHECK-NEXT: 202020 b1000000 00000000 03000000 00000000
|
||||
// CHECK-NEXT: 202030 02000000 00000000 c1000000 00000000
|
||||
|
||||
// CHECK: Contents of section .dtors:
|
||||
// CHECK-NEXT: a2111415 b21312c2
|
||||
// CHECK-NEXT: 202040 a2000000 00000000 11000000 00000000
|
||||
// CHECK-NEXT: 202050 14000000 00000000 15000000 00000000
|
||||
// CHECK-NEXT: 202060 b2000000 00000000 13000000 00000000
|
||||
// CHECK-NEXT: 202070 12000000 00000000 c2000000 00000000
|
||||
|
|
|
|||
|
|
@ -1,10 +1,18 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: ld.lld -e main %p/Inputs/gdb-index-a.elf %p/Inputs/gdb-index-b.elf -o %t1.exe
|
||||
# RUN: llvm-readobj -sections %t1.exe | FileCheck -check-prefix=CHECK1 %s
|
||||
# CHECK1: Name: .debug_gnu_pubnames
|
||||
# CHECK1: Name: .debug_gnu_pubtypes
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
|
||||
# RUN: ld.lld -gdb-index -e main %p/Inputs/gdb-index-a.elf %p/Inputs/gdb-index-b.elf -o %t2.exe
|
||||
# RUN: llvm-readobj -sections %t2.exe | FileCheck -check-prefix=CHECK2 %s
|
||||
# CHECK2-NOT: Name: .debug_gnu_pubnames
|
||||
# CHECK2-NOT: Name: .debug_gnu_pubtypes
|
||||
# RUN: ld.lld %t.o -o %t1.exe
|
||||
# RUN: llvm-readobj -sections %t1.exe | FileCheck %s
|
||||
# CHECK: .debug_gnu_pubnames
|
||||
# CHECK: .debug_gnu_pubtypes
|
||||
|
||||
# RUN: ld.lld -gdb-index %t.o -o %t2.exe
|
||||
# RUN: llvm-readobj -sections %t2.exe | FileCheck %s --check-prefix=GDB
|
||||
# GDB-NOT: .debug_gnu_pubnames
|
||||
# GDB-NOT: .debug_gnu_pubtypes
|
||||
|
||||
.section .debug_gnu_pubnames,"",@progbits
|
||||
.long 0
|
||||
|
||||
.section .debug_gnu_pubtypes,"",@progbits
|
||||
.long 0
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
|
||||
// CHECK: DynamicSection [
|
||||
// CHECK-NEXT: Tag Type Name/Value
|
||||
// CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so)
|
||||
// CHECK-NEXT: 0x0000000000000001 NEEDED Shared library: [{{.*}}2.so]
|
||||
// CHECK-NEXT: 0x0000000000000015 DEBUG 0x0
|
||||
// CHECK-NEXT: 0x0000000000000017 JMPREL
|
||||
// CHECK-NEXT: 0x0000000000000002 PLTRELSZ 24 (bytes)
|
||||
|
|
|
|||
15
test/ELF/filter.s
Normal file
15
test/ELF/filter.s
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
# RUN: ld.lld %t.o -shared -F foo.so -F boo.so -o %t1
|
||||
# RUN: llvm-readobj --dynamic-table %t1 | FileCheck %s
|
||||
|
||||
# Test alias.
|
||||
# RUN: ld.lld %t.o -shared --filter=foo.so --filter=boo.so -o %t2
|
||||
# RUN: llvm-readobj --dynamic-table %t2 | FileCheck %s
|
||||
|
||||
# CHECK: DynamicSection [
|
||||
# CHECK-NEXT: Tag Type Name/Value
|
||||
# CHECK-NEXT: 0x000000007FFFFFFF FILTER Filter library: [foo.so]
|
||||
# CHECK-NEXT: 0x000000007FFFFFFF FILTER Filter library: [boo.so]
|
||||
|
||||
# RUN: not ld.lld %t.o -F x -o %t 2>&1 | FileCheck -check-prefix=ERR %s
|
||||
# ERR: -F may not be used without -shared
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: ]
|
||||
|
||||
# CHECK: NEEDED SharedLibrary ({{.*}}.so)
|
||||
# CHECK: NEEDED Shared library: [{{.*}}.so]
|
||||
|
||||
.section .text.foo, "ax"
|
||||
.globl foo
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -o %t %s
|
||||
# RUN: ld.lld --gdb-index --gc-sections -o %t2 %t
|
||||
# RUN: llvm-dwarfdump -debug-dump=gdb_index %t2 | FileCheck %s
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -o %t %s
|
||||
# RUN: ld.lld --gdb-index --gc-sections -o %t2 %t
|
||||
# RUN: llvm-dwarfdump -debug-dump=gdb_index %t2 | FileCheck %s
|
||||
|
|
|
|||
|
|
@ -1,32 +1,19 @@
|
|||
## gdb-index-a.elf and gdb-index-b.elf are a test.o and test2.o renamed,
|
||||
## were generated in this way:
|
||||
## test.cpp:
|
||||
## int main() { return 0; }
|
||||
## test2.cpp:
|
||||
## int main2() { return 0; }
|
||||
## Compiled with:
|
||||
## gcc -gsplit-dwarf -c test.cpp test2.cpp
|
||||
## gcc version 5.3.1 20160413
|
||||
## Info about gdb-index: https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html
|
||||
|
||||
# REQUIRES: x86
|
||||
# RUN: ld.lld --gdb-index -e main %p/Inputs/gdb-index-a.elf %p/Inputs/gdb-index-b.elf -o %t
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/gdb-index.s -o %t2.o
|
||||
# RUN: ld.lld --gdb-index -e main %t1.o %t2.o -o %t
|
||||
# RUN: llvm-dwarfdump -debug-dump=gdb_index %t | FileCheck %s
|
||||
# RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=DISASM
|
||||
|
||||
# DISASM: Disassembly of section .text:
|
||||
# DISASM: main:
|
||||
# DISASM-CHECK: 11000: 55 pushq %rbp
|
||||
# DISASM-CHECK: 11001: 48 89 e5 movq %rsp, %rbp
|
||||
# DISASM-CHECK: 11004: b8 00 00 00 00 movl $0, %eax
|
||||
# DISASM-CHECK: 11009: 5d popq %rbp
|
||||
# DISASM-CHECK: 1100a: c3 retq
|
||||
# DISASM: _Z5main2v:
|
||||
# DISASM-CHECK: 1100b: 55 pushq %rbp
|
||||
# DISASM-CHECK: 1100c: 48 89 e5 movq %rsp, %rbp
|
||||
# DISASM-CHECK: 1100f: b8 00 00 00 00 movl $0, %eax
|
||||
# DISASM-CHECK: 11014: 5d popq %rbp
|
||||
# DISASM-CHECK: 11015: c3 retq
|
||||
# DISASM-CHECK: 201000: 90 nop
|
||||
# DISASM-CHECK: 201001: cc int3
|
||||
# DISASM-CHECK: 201002: cc int3
|
||||
# DISASM-CHECK: 201003: cc int3
|
||||
# DISASM: main2:
|
||||
# DISASM-CHECK: 201004: 90 nop
|
||||
# DISASM-CHECK: 201005: 90 nop
|
||||
|
||||
# CHECK: .gnu_index contents:
|
||||
# CHECK-NEXT: Version = 7
|
||||
|
|
@ -34,8 +21,8 @@
|
|||
# CHECK-NEXT: 0: Offset = 0x0, Length = 0x34
|
||||
# CHECK-NEXT: 1: Offset = 0x34, Length = 0x34
|
||||
# CHECK: Address area offset = 0x38, has 2 entries:
|
||||
# CHECK-NEXT: Low/High address = [0x201000, 0x20100b) (Size: 0xb), CU id = 0
|
||||
# CHECK-NEXT: Low/High address = [0x20100b, 0x201016) (Size: 0xb), CU id = 1
|
||||
# CHECK-NEXT: Low/High address = [0x201000, 0x201001) (Size: 0x1), CU id = 0
|
||||
# CHECK-NEXT: Low/High address = [0x201004, 0x201006) (Size: 0x2), CU id = 1
|
||||
# CHECK: Symbol table offset = 0x60, size = 1024, filled slots:
|
||||
# CHECK-NEXT: 489: Name offset = 0x1d, CU vector offset = 0x0
|
||||
# CHECK-NEXT: String name: main, CU vector index: 0
|
||||
|
|
@ -47,3 +34,79 @@
|
|||
# CHECK-NEXT: 0(0x0): 0x30000000
|
||||
# CHECK-NEXT: 1(0x8): 0x90000000 0x90000001
|
||||
# CHECK-NEXT: 2(0x14): 0x30000001
|
||||
|
||||
## The following section contents are created by this using gcc 7.1.0:
|
||||
## echo 'int main() { return 0; }' | gcc -gsplit-dwarf -xc++ -S -o- -
|
||||
|
||||
.text
|
||||
.Ltext0:
|
||||
.globl main
|
||||
.type main, @function
|
||||
main:
|
||||
nop
|
||||
.Letext0:
|
||||
|
||||
.section .debug_info,"",@progbits
|
||||
.long 0x30
|
||||
.value 0x4
|
||||
.long 0
|
||||
.byte 0x8
|
||||
.uleb128 0x1
|
||||
.quad .Ltext0
|
||||
.quad .Letext0-.Ltext0
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.byte 0x63
|
||||
.byte 0x88
|
||||
.byte 0xb4
|
||||
.byte 0x61
|
||||
.byte 0xaa
|
||||
.byte 0xb6
|
||||
.byte 0xb0
|
||||
.byte 0x67
|
||||
|
||||
.section .debug_abbrev,"",@progbits
|
||||
.uleb128 0x1
|
||||
.uleb128 0x11
|
||||
.byte 0
|
||||
.uleb128 0x11
|
||||
.uleb128 0x1
|
||||
.uleb128 0x12
|
||||
.uleb128 0x7
|
||||
.uleb128 0x10
|
||||
.uleb128 0x17
|
||||
.uleb128 0x2130
|
||||
.uleb128 0xe
|
||||
.uleb128 0x1b
|
||||
.uleb128 0xe
|
||||
.uleb128 0x2134
|
||||
.uleb128 0x19
|
||||
.uleb128 0x2133
|
||||
.uleb128 0x17
|
||||
.uleb128 0x2131
|
||||
.uleb128 0x7
|
||||
.byte 0
|
||||
.byte 0
|
||||
.byte 0
|
||||
|
||||
.section .debug_gnu_pubnames,"",@progbits
|
||||
.long 0x18
|
||||
.value 0x2
|
||||
.long 0
|
||||
.long 0x33
|
||||
.long 0x18
|
||||
.byte 0x30
|
||||
.string "main"
|
||||
.long 0
|
||||
|
||||
.section .debug_gnu_pubtypes,"",@progbits
|
||||
.long 0x17
|
||||
.value 0x2
|
||||
.long 0
|
||||
.long 0x33
|
||||
.long 0x2b
|
||||
.byte 0x90
|
||||
.string "int"
|
||||
.long 0
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
// REQUIRES: x86
|
||||
// RUN: llvm-mc %s -o %t.o -triple i386-pc-linux-code16 -filetype=obj
|
||||
|
||||
// RUN: echo ".global foo; foo = 0x1" > %t1.s
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
// REQUIRES: x86
|
||||
// RUN: llvm-mc %s -o %t.o -triple i386-pc-linux-code16 -filetype=obj
|
||||
|
||||
// RUN: echo ".global foo; foo = 0x10202" > %t1.s
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# REQUIRES: x86
|
||||
|
||||
## The test file contains a STT_TLS symbol but has no TLS section.
|
||||
## The test file contains an STT_TLS symbol but has no TLS section.
|
||||
# RUN: not ld.lld %S/Inputs/tls-symbol.elf -o %t 2>&1 | FileCheck %s
|
||||
# CHECK: has a STT_TLS symbol but doesn't have a PT_TLS section
|
||||
# CHECK: has an STT_TLS symbol but doesn't have an SHF_TLS section
|
||||
|
|
|
|||
7
test/ELF/linkerscript/exidx-crash.s
Normal file
7
test/ELF/linkerscript/exidx-crash.s
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# REQUIRES: aarch64
|
||||
|
||||
# We used to crash on this.
|
||||
|
||||
# RUN: llvm-mc %s -o %t.o -filetype=obj -triple=aarch64-pc-linux
|
||||
# RUN: echo "SECTIONS { .ARM.exidx : { *(.foo) } }" > %t.script
|
||||
# RUN: ld.lld -T %t.script %t.o -o %t
|
||||
23
test/ELF/linkerscript/got-write-offset.s
Normal file
23
test/ELF/linkerscript/got-write-offset.s
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux-gnu %s -o %t
|
||||
# RUN: echo "SECTIONS { \
|
||||
# RUN: .data 0x1000 : { *(.data) } \
|
||||
# RUN: .got 0x2000 : { \
|
||||
# RUN: LONG(0) \
|
||||
# RUN: *(.got) \
|
||||
# RUN: } \
|
||||
# RUN: };" > %t.script
|
||||
# RUN: ld.lld -shared -o %t.out --script %t.script %t
|
||||
# RUN: llvm-objdump -s %t.out | FileCheck %s
|
||||
.text
|
||||
.global foo
|
||||
foo:
|
||||
movl bar@GOT, %eax
|
||||
.data
|
||||
.local bar
|
||||
bar:
|
||||
.zero 4
|
||||
# CHECK: Contents of section .data:
|
||||
# CHECK-NEXT: 1000 00000000
|
||||
# CHECK: Contents of section .got:
|
||||
# CHECK-NEXT: 2000 00000000 00100000
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
|
||||
# RUN: echo "SECTIONS { .text : { . = 0xffffffff; *(.text*); } }" > %t.script
|
||||
# RUN: not ld.lld --script %t.script %t.o -o %t 2>&1 | FileCheck %s
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
; REQUIRES: x86
|
||||
; RUN: llvm-as %s -o %t1.o
|
||||
; RUN: llvm-as %p/Inputs/available-externally.ll -o %t2.o
|
||||
; RUN: ld.lld %t1.o %t2.o -m elf_x86_64 -o %t.so -shared -save-temps
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
; REQUIRES: x86
|
||||
; RUN: llvm-as %s -o %t.o
|
||||
; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/comdat.s -o %t2.o -filetype=obj
|
||||
; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t.so -shared
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
; REQUIRES: x86
|
||||
; RUN: llvm-as %s -o %t1.o
|
||||
; RUN: ld.lld -m elf_x86_64 %t1.o -o %t -shared -save-temps
|
||||
; RUN: llvm-dis < %t.0.2.internalize.bc | FileCheck %s
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
; REQUIRES: x86
|
||||
; RUN: llvm-as %s -o %t1.o
|
||||
; RUN: llvm-as %S/Inputs/common3.ll -o %t2.o
|
||||
; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t -shared -save-temps
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue