Vendor import of lld trunk r308421:

https://llvm.org/svn/llvm-project/lld/trunk@308421
This commit is contained in:
Dimitry Andric 2017-07-19 07:02:58 +00:00
parent 2678297743
commit da06c7cfa0
135 changed files with 1878 additions and 396 deletions

View file

@ -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());

View file

@ -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()),

View file

@ -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;

View file

@ -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();
}

View file

@ -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));
}

View file

@ -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:

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -16,7 +16,7 @@ namespace lld {
namespace elf {
void unlinkAsync(StringRef Path);
std::error_code tryCreateFile(StringRef Path);
}
}
} // namespace elf
} // namespace lld
#endif

View file

@ -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 {

View file

@ -14,6 +14,6 @@ namespace lld {
namespace elf {
template <class ELFT> void doIcf();
}
}
} // namespace lld
#endif

View file

@ -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 {

View file

@ -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

View file

@ -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];

View file

@ -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;
}

View file

@ -17,7 +17,7 @@ namespace elf {
struct OutputSectionCommand;
template <class ELFT>
void writeMapFile(llvm::ArrayRef<OutputSectionCommand *> Script);
}
}
} // namespace elf
} // namespace lld
#endif

View file

@ -61,7 +61,7 @@ inline void freeArena() {
Alloc->reset();
BAlloc.Reset();
}
}
}
} // namespace elf
} // namespace lld
#endif

View file

@ -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>;

View file

@ -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));

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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() {

View file

@ -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;

View file

@ -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

View file

@ -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.

View file

@ -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;

View file

@ -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);

View file

@ -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);
}

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,2 @@
EXPORTS
f

View file

@ -0,0 +1,3 @@
LIBRARY library.ext
EXPORTS
f

View file

@ -0,0 +1,3 @@
LIBRARY library
EXPORTS
f

13
test/COFF/Inputs/object.s Normal file
View file

@ -0,0 +1,13 @@
.text
.def f
.scl 2
.type 32
.endef
.global f
f:
retq $0
.section .drectve,"rd"
.ascii " /EXPORT:f"

View 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
...

View 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
...

View 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 ]
...

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 \

View file

@ -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

View file

@ -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

View 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

View file

@ -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 \

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 *`:

View file

@ -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

View file

@ -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

View 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
...

View 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 *`:

View 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
View 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
...

View file

@ -1,3 +1,4 @@
; REQUIRES: x86
; RUN: rm -fr %T/savetemps
; RUN: mkdir %T/savetemps
; RUN: llvm-as -o %T/savetemps/savetemps.obj %s

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,5 +1,5 @@
.section .ctors, "aw", @progbits
.byte 0xA1
.quad 0xA1
.section .dtors, "aw", @progbits
.byte 0xA2
.quad 0xA2

View file

@ -1,5 +1,5 @@
.section .ctors, "aw", @progbits
.byte 0xB1
.quad 0xB1
.section .dtors, "aw", @progbits
.byte 0xB2
.quad 0xB2

View file

@ -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.

View 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

View file

@ -1,6 +0,0 @@
.text
.globl x
.type x, @function
x:
.symver x, xx@@VER

View file

@ -1 +0,0 @@
call xx@PLT

View file

@ -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

View file

@ -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:

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
View 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

View file

@ -38,7 +38,7 @@
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK: NEEDED SharedLibrary ({{.*}}.so)
# CHECK: NEEDED Shared library: [{{.*}}.so]
.section .text.foo, "ax"
.globl foo

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View 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

View 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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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