Skip to content

Commit 4ff113d

Browse files
[lld-macho] Support archives with no index
1 parent edf2131 commit 4ff113d

File tree

5 files changed

+99
-57
lines changed

5 files changed

+99
-57
lines changed

lld/MachO/Driver.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,6 @@ static InputFile *addFile(StringRef path, LoadType loadType,
314314
std::unique_ptr<object::Archive> archive = CHECK(
315315
object::Archive::create(mbref), path + ": failed to parse archive");
316316

317-
if (!archive->isEmpty() && !archive->hasSymbolTable())
318-
error(path + ": archive has no index; run ranlib to add one");
319317
file = make<ArchiveFile>(std::move(archive), isForceHidden);
320318

321319
if (tar && file->getArchive().isThin())
@@ -362,9 +360,11 @@ static InputFile *addFile(StringRef path, LoadType loadType,
362360
": Archive::children failed: " + toString(std::move(e)));
363361
}
364362
} else if (isCommandLineLoad && config->forceLoadObjC) {
365-
for (const object::Archive::Symbol &sym : file->getArchive().symbols())
366-
if (sym.getName().starts_with(objc::symbol_names::klass))
367-
file->fetch(sym);
363+
if (file->getArchive().getNumberOfSymbols() > 0) {
364+
for (const object::Archive::Symbol &sym : file->getArchive().symbols())
365+
if (sym.getName().starts_with(objc::symbol_names::klass))
366+
file->fetch(sym);
367+
}
368368

369369
// TODO: no need to look for ObjC sections for a given archive member if
370370
// we already found that it contains an ObjC symbol.
@@ -394,7 +394,6 @@ static InputFile *addFile(StringRef path, LoadType loadType,
394394
": Archive::children failed: " + toString(std::move(e)));
395395
}
396396
}
397-
398397
file->addLazySymbols();
399398
loadedArchives[path] = ArchiveFileInfo{file, isCommandLineLoad};
400399
newFile = file;

lld/MachO/InputFiles.cpp

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2159,9 +2159,34 @@ ArchiveFile::ArchiveFile(std::unique_ptr<object::Archive> &&f, bool forceHidden)
21592159
void ArchiveFile::addLazySymbols() {
21602160
// Avoid calling getMemoryBufferRef() on zero-symbol archive
21612161
// since that crashes.
2162-
if (file->isEmpty() || file->getNumberOfSymbols() == 0)
2162+
if (file->isEmpty())
21632163
return;
21642164

2165+
if (file->getNumberOfSymbols() == 0) {
2166+
// No index, treat each child as a lazy object file.
2167+
Error e = Error::success();
2168+
for (const object::Archive::Child &c : file->children(e)) {
2169+
// Check `seen` but don't insert so a future eager load can still happen.
2170+
if (seen.contains(c.getChildOffset()))
2171+
continue;
2172+
if (!seenLazy.insert(c.getChildOffset()).second) {
2173+
continue;
2174+
}
2175+
// First check seen.
2176+
// Then, write to and check seenLazy
2177+
// Then, get the file, check for error, and add it to inputs.
2178+
auto file = childToObjectFile(c, /*lazy=*/true);
2179+
if (!file)
2180+
error(toString(this) +
2181+
": couldn't process child: " + toString(file.takeError()));
2182+
inputFiles.insert(*file);
2183+
}
2184+
if (e)
2185+
error(toString(this) +
2186+
": Archive::children failed: " + toString(std::move(e)));
2187+
return;
2188+
}
2189+
21652190
Error err = Error::success();
21662191
auto child = file->child_begin(err);
21672192
// Ignore the I/O error here - will be reported later.
@@ -2191,16 +2216,17 @@ void ArchiveFile::addLazySymbols() {
21912216

21922217
static Expected<InputFile *>
21932218
loadArchiveMember(MemoryBufferRef mb, uint32_t modTime, StringRef archiveName,
2194-
uint64_t offsetInArchive, bool forceHidden, bool compatArch) {
2219+
uint64_t offsetInArchive, bool forceHidden, bool compatArch,
2220+
bool lazy) {
21952221
if (config->zeroModTime)
21962222
modTime = 0;
21972223

21982224
switch (identify_magic(mb.getBuffer())) {
21992225
case file_magic::macho_object:
2200-
return make<ObjFile>(mb, modTime, archiveName, /*lazy=*/false, forceHidden,
2226+
return make<ObjFile>(mb, modTime, archiveName, lazy, forceHidden,
22012227
compatArch);
22022228
case file_magic::bitcode:
2203-
return make<BitcodeFile>(mb, archiveName, offsetInArchive, /*lazy=*/false,
2229+
return make<BitcodeFile>(mb, archiveName, offsetInArchive, lazy,
22042230
forceHidden, compatArch);
22052231
default:
22062232
return createStringError(inconvertibleErrorCode(),
@@ -2209,22 +2235,11 @@ loadArchiveMember(MemoryBufferRef mb, uint32_t modTime, StringRef archiveName,
22092235
}
22102236
}
22112237

2212-
Error ArchiveFile::fetch(const object::Archive::Child &c, StringRef reason) {
2238+
Error ArchiveFile::fetch(const object::Archive::Child &c, StringRef reason,
2239+
bool lazy) {
22132240
if (!seen.insert(c.getChildOffset()).second)
22142241
return Error::success();
2215-
2216-
Expected<MemoryBufferRef> mb = c.getMemoryBufferRef();
2217-
if (!mb)
2218-
return mb.takeError();
2219-
2220-
Expected<TimePoint<std::chrono::seconds>> modTime = c.getLastModified();
2221-
if (!modTime)
2222-
return modTime.takeError();
2223-
2224-
Expected<InputFile *> file =
2225-
loadArchiveMember(*mb, toTimeT(*modTime), getName(), c.getChildOffset(),
2226-
forceHidden, compatArch);
2227-
2242+
auto file = childToObjectFile(c, /*lazy=*/false);
22282243
if (!file)
22292244
return file.takeError();
22302245

@@ -2251,6 +2266,23 @@ void ArchiveFile::fetch(const object::Archive::Symbol &sym) {
22512266
toMachOString(symCopy) + ": " + toString(std::move(e)));
22522267
}
22532268

2269+
Expected<InputFile *>
2270+
ArchiveFile::childToObjectFile(const llvm::object::Archive::Child &c,
2271+
bool lazy) {
2272+
Expected<MemoryBufferRef> mb = c.getMemoryBufferRef();
2273+
if (!mb)
2274+
return mb.takeError();
2275+
2276+
Expected<TimePoint<std::chrono::seconds>> modTime = c.getLastModified();
2277+
if (!modTime)
2278+
return modTime.takeError();
2279+
2280+
Expected<InputFile *> file =
2281+
loadArchiveMember(*mb, toTimeT(*modTime), getName(), c.getChildOffset(),
2282+
forceHidden, compatArch, lazy);
2283+
return file;
2284+
}
2285+
22542286
static macho::Symbol *createBitcodeSymbol(const lto::InputFile::Symbol &objSym,
22552287
BitcodeFile &file) {
22562288
StringRef name = saver().save(objSym.getName());

lld/MachO/InputFiles.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,15 +292,19 @@ class ArchiveFile final : public InputFile {
292292
void fetch(const llvm::object::Archive::Symbol &);
293293
// LLD normally doesn't use Error for error-handling, but the underlying
294294
// Archive library does, so this is the cleanest way to wrap it.
295-
Error fetch(const llvm::object::Archive::Child &, StringRef reason);
295+
Error fetch(const llvm::object::Archive::Child &, StringRef reason,
296+
bool lazy = false);
296297
const llvm::object::Archive &getArchive() const { return *file; };
297298
static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; }
298299

299300
private:
301+
Expected<InputFile *> childToObjectFile(const llvm::object::Archive::Child &c,
302+
bool lazy);
300303
std::unique_ptr<llvm::object::Archive> file;
301304
// Keep track of children fetched from the archive by tracking
302305
// which address offsets have been fetched already.
303306
llvm::DenseSet<uint64_t> seen;
307+
llvm::DenseSet<uint64_t> seenLazy;
304308
// Load all symbols with hidden visibility (-load_hidden).
305309
bool forceHidden;
306310
};

lld/test/MachO/archive-no-index.s

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# REQUIRES: x86
2+
3+
# RUN: rm -rf %t; split-file %s %t
4+
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos -o %t/main.o %t/main.s
5+
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos -o %t/lib.o %t/lib.s
6+
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos -o %t/lib2.o %t/lib2.s
7+
# RUN: llvm-ar crST %t/lib.a %t/lib.o %t/lib2.o
8+
# RUN: %lld %t/main.o %t/lib.a -o %t/out
9+
10+
## Test that every kind of eager load mechanism still works.
11+
# RUN: %lld %t/main.o %t/lib.a -all_load -o %t/all_load
12+
# RUN: llvm-nm %t/all_load | FileCheck %s --check-prefix FORCED-LOAD
13+
# RUN: %lld %t/main.o -force_load %t/lib.a -o %t/force_load
14+
# RUN: llvm-nm %t/force_load | FileCheck %s --check-prefix FORCED-LOAD
15+
# RUN: %lld %t/main.o %t/lib.a -ObjC -o %t/objc
16+
# RUN: llvm-nm %t/objc | FileCheck %s --check-prefix FORCED-LOAD
17+
18+
# FORCED-LOAD: T _bar
19+
20+
#--- lib.s
21+
.global _foo
22+
_foo:
23+
ret
24+
25+
#--- lib2.s
26+
.section __DATA,__objc_catlist
27+
.quad 0x1234
28+
29+
.section __TEXT,__text
30+
.global _bar
31+
_bar:
32+
ret
33+
34+
#--- main.s
35+
.global _main
36+
_main:
37+
call _foo
38+
mov $0, %rax
39+
ret

lld/test/MachO/invalid/archive-no-index.s

Lines changed: 0 additions & 32 deletions
This file was deleted.

0 commit comments

Comments
 (0)