Skip to content

Commit 46934b6

Browse files
committed
[LLD] Improve thin archive handling
- Combine new functions as suggested by MaskRay in review. - Remove code that worked around a crash that can no longer occur now that the implementation is structured as a new ThinLTO backend. - Record whether an archive was thin or not and pass this information into the BitcodeFile constructor. This replaces code that reopened the archive file and checked the archive magic.
1 parent 36fe827 commit 46934b6

File tree

4 files changed

+36
-63
lines changed

4 files changed

+36
-63
lines changed

lld/ELF/Config.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ class LinkerDriver {
166166
template <class ELFT> void link(llvm::opt::InputArgList &args);
167167
template <class ELFT> void compileBitcodeFiles(bool skipLinkedOutput);
168168
bool tryAddFatLTOFile(MemoryBufferRef mb, StringRef archiveName,
169-
uint64_t offsetInArchive, bool lazy);
169+
uint64_t offsetInArchive, bool isThinArchive,
170+
bool lazy);
170171
// True if we are in --whole-archive and --no-whole-archive.
171172
bool inWholeArchive = false;
172173

lld/ELF/Driver.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -231,15 +231,16 @@ static bool isBitcode(MemoryBufferRef mb) {
231231
}
232232

233233
bool LinkerDriver::tryAddFatLTOFile(MemoryBufferRef mb, StringRef archiveName,
234-
uint64_t offsetInArchive, bool lazy) {
234+
uint64_t offsetInArchive,
235+
bool isThinArchive, bool lazy) {
235236
if (!ctx.arg.fatLTOObjects)
236237
return false;
237238
Expected<MemoryBufferRef> fatLTOData =
238239
IRObjectFile::findBitcodeInMemBuffer(mb);
239240
if (errorToBool(fatLTOData.takeError()))
240241
return false;
241-
files.push_back(std::make_unique<BitcodeFile>(ctx, *fatLTOData, archiveName,
242-
offsetInArchive, lazy));
242+
files.push_back(std::make_unique<BitcodeFile>(
243+
ctx, *fatLTOData, archiveName, offsetInArchive, isThinArchive, lazy));
243244
return true;
244245
}
245246

@@ -262,13 +263,15 @@ void LinkerDriver::addFile(StringRef path, bool withLOption) {
262263
readLinkerScript(ctx, mbref);
263264
return;
264265
case file_magic::archive: {
266+
bool isThinArchive = mbref.getBuffer().starts_with(ThinArchiveMagic);
265267
auto members = getArchiveMembers(ctx, mbref);
266268
if (inWholeArchive) {
267269
for (const std::pair<MemoryBufferRef, uint64_t> &p : members) {
268270
if (isBitcode(p.first))
269-
files.push_back(std::make_unique<BitcodeFile>(ctx, p.first, path,
270-
p.second, false));
271-
else if (!tryAddFatLTOFile(p.first, path, p.second, false))
271+
files.push_back(std::make_unique<BitcodeFile>(
272+
ctx, p.first, path, p.second, isThinArchive, false));
273+
else if (!tryAddFatLTOFile(p.first, path, p.second, isThinArchive,
274+
false))
272275
files.push_back(createObjFile(ctx, p.first, path));
273276
}
274277
return;
@@ -292,11 +295,11 @@ void LinkerDriver::addFile(StringRef path, bool withLOption) {
292295
for (const std::pair<MemoryBufferRef, uint64_t> &p : members) {
293296
auto magic = identify_magic(p.first.getBuffer());
294297
if (magic == file_magic::elf_relocatable) {
295-
if (!tryAddFatLTOFile(p.first, path, p.second, true))
298+
if (!tryAddFatLTOFile(p.first, path, p.second, isThinArchive, true))
296299
files.push_back(createObjFile(ctx, p.first, path, true));
297300
} else if (magic == file_magic::bitcode)
298-
files.push_back(
299-
std::make_unique<BitcodeFile>(ctx, p.first, path, p.second, true));
301+
files.push_back(std::make_unique<BitcodeFile>(
302+
ctx, p.first, path, p.second, isThinArchive, true));
300303
else
301304
Warn(ctx) << path << ": archive member '"
302305
<< p.first.getBufferIdentifier()
@@ -324,10 +327,11 @@ void LinkerDriver::addFile(StringRef path, bool withLOption) {
324327
return;
325328
}
326329
case file_magic::bitcode:
327-
files.push_back(std::make_unique<BitcodeFile>(ctx, mbref, "", 0, inLib));
330+
files.push_back(
331+
std::make_unique<BitcodeFile>(ctx, mbref, "", 0, false, inLib));
328332
break;
329333
case file_magic::elf_relocatable:
330-
if (!tryAddFatLTOFile(mbref, "", 0, inLib))
334+
if (!tryAddFatLTOFile(mbref, "", 0, false, inLib))
331335
files.push_back(createObjFile(ctx, mbref, "", inLib));
332336
break;
333337
default:

lld/ELF/InputFiles.cpp

Lines changed: 18 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1703,39 +1703,22 @@ static uint8_t getOsAbi(const Triple &t) {
17031703
}
17041704
}
17051705

1706-
// Check if an archive file is a thin archive.
1707-
static bool isThinArchive(Ctx &ctx, StringRef archiveFilePath) {
1708-
const size_t thinArchiveMagicLen = sizeof(ThinArchiveMagic) - 1;
1709-
1710-
ErrorOr<std::unique_ptr<MemoryBuffer>> memBufferOrError =
1711-
MemoryBuffer::getFileSlice(archiveFilePath, thinArchiveMagicLen, 0);
1712-
if (std::error_code ec = memBufferOrError.getError()) {
1713-
ErrAlways(ctx) << "cannot open " << archiveFilePath << ": " << ec.message();
1714-
return false;
1715-
}
1716-
1717-
MemoryBufferRef memBufRef = *memBufferOrError.get();
1718-
return memBufRef.getBuffer().starts_with(ThinArchiveMagic);
1719-
}
1720-
1721-
// Compute a thin archive member full file path.
1722-
static std::string
1723-
computeThinArchiveMemberFullPath(const StringRef modulePath,
1724-
const StringRef archiveName) {
1725-
assert(!archiveName.empty());
1706+
static SmallString<64> dtltoGetMemberPathIfThinArchive(StringRef archivePath,
1707+
StringRef memberPath) {
1708+
assert(!archivePath.empty());
17261709
SmallString<64> archiveMemberPath;
1727-
if (path::is_relative(modulePath)) {
1728-
archiveMemberPath = path::parent_path(archiveName);
1729-
path::append(archiveMemberPath, modulePath);
1710+
if (path::is_relative(memberPath)) {
1711+
archiveMemberPath = path::parent_path(archivePath);
1712+
path::append(archiveMemberPath, memberPath);
17301713
} else
1731-
archiveMemberPath = modulePath;
1732-
1714+
archiveMemberPath = memberPath;
17331715
path::remove_dots(archiveMemberPath, /*remove_dot_dot=*/true);
1734-
return archiveMemberPath.c_str();
1716+
return archiveMemberPath;
17351717
}
17361718

17371719
BitcodeFile::BitcodeFile(Ctx &ctx, MemoryBufferRef mb, StringRef archiveName,
1738-
uint64_t offsetInArchive, bool lazy)
1720+
uint64_t offsetInArchive, bool isThinArchive,
1721+
bool lazy)
17391722
: InputFile(ctx, BitcodeKind, mb) {
17401723
this->archiveName = archiveName;
17411724
this->lazy = lazy;
@@ -1744,12 +1727,13 @@ BitcodeFile::BitcodeFile(Ctx &ctx, MemoryBufferRef mb, StringRef archiveName,
17441727
if (ctx.arg.thinLTOIndexOnly)
17451728
path = replaceThinLTOSuffix(ctx, mb.getBufferIdentifier());
17461729

1747-
// For DTLTO the name needs to be a valid path to a bitcode file.
1748-
bool dtltoThinArchiveHandling = !ctx.arg.dtltoDistributor.empty() &&
1749-
!archiveName.empty() &&
1750-
isThinArchive(ctx, archiveName);
1751-
if (dtltoThinArchiveHandling)
1752-
path = computeThinArchiveMemberFullPath(path, archiveName);
1730+
// For DTLTO the member name needs to be a valid path to a bitcode file on
1731+
// disk. For ThinArchives we compute that. Non-thin archives are not yet
1732+
// supported.
1733+
bool dtltoAdjustThinArchivePath = !archiveName.empty() && isThinArchive &&
1734+
!ctx.arg.dtltoDistributor.empty();
1735+
if (dtltoAdjustThinArchivePath)
1736+
path = dtltoGetMemberPathIfThinArchive(archiveName, path).str();
17531737

17541738
// ThinLTO assumes that all MemoryBufferRefs given to it have a unique
17551739
// name. If two archives define two members with the same name, this
@@ -1758,30 +1742,14 @@ BitcodeFile::BitcodeFile(Ctx &ctx, MemoryBufferRef mb, StringRef archiveName,
17581742
// symbols later in the link stage). So we append file offset to make
17591743
// filename unique.
17601744
StringSaver &ss = ctx.saver;
1761-
StringRef name = (archiveName.empty() || dtltoThinArchiveHandling)
1745+
StringRef name = (archiveName.empty() || dtltoAdjustThinArchivePath)
17621746
? ss.save(path)
17631747
: ss.save(archiveName + "(" + path::filename(path) +
17641748
" at " + utostr(offsetInArchive) + ")");
17651749
MemoryBufferRef mbref(mb.getBuffer(), name);
17661750

17671751
obj = CHECK2(lto::InputFile::create(mbref), this);
17681752

1769-
// A thin archive member file path potentially can be relative to a thin
1770-
// archive. This will result in an invalid file path name passed in
1771-
// 'mb->Identifier', (because from the linker's perspective, relative -
1772-
// means relative to the linker process' current directory).
1773-
// For non-archive bitcodes and referenced archive members, a correctly
1774-
// generated 'name' is used to identify the memory buffer associated with
1775-
// these bitcode files. However, for a non-referenced archive member,
1776-
// incorrect 'mb->Identifer' will be used as a path for generating an empty
1777-
// summary index file later, leading to a crash. We have to fix this problem
1778-
// by replacing the value of 'mb->Identifier' with 'name'.
1779-
// Since the MemoryBufferRef class does not allow an individual access to
1780-
// its data members, we will use the class copy constructor for updating the
1781-
// 'Indentifier' data member value.
1782-
if (dtltoThinArchiveHandling)
1783-
this->mb = mbref;
1784-
17851753
Triple t(obj->getTargetTriple());
17861754
ekind = getBitcodeELFKind(t);
17871755
emachine = getBitcodeMachineKind(ctx, mb.getBufferIdentifier(), t);

lld/ELF/InputFiles.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ template <class ELFT> class ObjFile : public ELFFileBase {
324324
class BitcodeFile : public InputFile {
325325
public:
326326
BitcodeFile(Ctx &, MemoryBufferRef m, StringRef archiveName,
327-
uint64_t offsetInArchive, bool lazy);
327+
uint64_t offsetInArchive, bool isThinArchive, bool lazy);
328328
static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; }
329329
void parse();
330330
void parseLazy();

0 commit comments

Comments
 (0)