Skip to content

Commit 6dbb0df

Browse files
[lld-macho] Support archives with no index
1 parent b246943 commit 6dbb0df

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
@@ -2156,9 +2156,34 @@ ArchiveFile::ArchiveFile(std::unique_ptr<object::Archive> &&f, bool forceHidden)
21562156
void ArchiveFile::addLazySymbols() {
21572157
// Avoid calling getMemoryBufferRef() on zero-symbol archive
21582158
// since that crashes.
2159-
if (file->isEmpty() || file->getNumberOfSymbols() == 0)
2159+
if (file->isEmpty())
21602160
return;
21612161

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

21892214
static Expected<InputFile *>
21902215
loadArchiveMember(MemoryBufferRef mb, uint32_t modTime, StringRef archiveName,
2191-
uint64_t offsetInArchive, bool forceHidden, bool compatArch) {
2216+
uint64_t offsetInArchive, bool forceHidden, bool compatArch,
2217+
bool lazy) {
21922218
if (config->zeroModTime)
21932219
modTime = 0;
21942220

21952221
switch (identify_magic(mb.getBuffer())) {
21962222
case file_magic::macho_object:
2197-
return make<ObjFile>(mb, modTime, archiveName, /*lazy=*/false, forceHidden,
2223+
return make<ObjFile>(mb, modTime, archiveName, lazy, forceHidden,
21982224
compatArch);
21992225
case file_magic::bitcode:
2200-
return make<BitcodeFile>(mb, archiveName, offsetInArchive, /*lazy=*/false,
2226+
return make<BitcodeFile>(mb, archiveName, offsetInArchive, lazy,
22012227
forceHidden, compatArch);
22022228
default:
22032229
return createStringError(inconvertibleErrorCode(),
@@ -2206,22 +2232,11 @@ loadArchiveMember(MemoryBufferRef mb, uint32_t modTime, StringRef archiveName,
22062232
}
22072233
}
22082234

2209-
Error ArchiveFile::fetch(const object::Archive::Child &c, StringRef reason) {
2235+
Error ArchiveFile::fetch(const object::Archive::Child &c, StringRef reason,
2236+
bool lazy) {
22102237
if (!seen.insert(c.getChildOffset()).second)
22112238
return Error::success();
2212-
2213-
Expected<MemoryBufferRef> mb = c.getMemoryBufferRef();
2214-
if (!mb)
2215-
return mb.takeError();
2216-
2217-
Expected<TimePoint<std::chrono::seconds>> modTime = c.getLastModified();
2218-
if (!modTime)
2219-
return modTime.takeError();
2220-
2221-
Expected<InputFile *> file =
2222-
loadArchiveMember(*mb, toTimeT(*modTime), getName(), c.getChildOffset(),
2223-
forceHidden, compatArch);
2224-
2239+
auto file = childToObjectFile(c, /*lazy=*/false);
22252240
if (!file)
22262241
return file.takeError();
22272242

@@ -2248,6 +2263,23 @@ void ArchiveFile::fetch(const object::Archive::Symbol &sym) {
22482263
toMachOString(symCopy) + ": " + toString(std::move(e)));
22492264
}
22502265

2266+
Expected<InputFile *>
2267+
ArchiveFile::childToObjectFile(const llvm::object::Archive::Child &c,
2268+
bool lazy) {
2269+
Expected<MemoryBufferRef> mb = c.getMemoryBufferRef();
2270+
if (!mb)
2271+
return mb.takeError();
2272+
2273+
Expected<TimePoint<std::chrono::seconds>> modTime = c.getLastModified();
2274+
if (!modTime)
2275+
return modTime.takeError();
2276+
2277+
Expected<InputFile *> file =
2278+
loadArchiveMember(*mb, toTimeT(*modTime), getName(), c.getChildOffset(),
2279+
forceHidden, compatArch, lazy);
2280+
return file;
2281+
}
2282+
22512283
static macho::Symbol *createBitcodeSymbol(const lto::InputFile::Symbol &objSym,
22522284
BitcodeFile &file) {
22532285
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)