-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[lld-macho] Save all thin archive members in repro tarball #97169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The repro file in llvm#94716 contains a few thin archives without their member object files present. I couldn't figure out why this happened (issue in repro tarball generation?), but this caused an "unhandled Error" crash on `LLVM_ENABLE_ABI_BREAKING_CHECKS` builds.
@llvm/pr-subscribers-lld-macho Author: Daniel Bertalan (BertalanD) ChangesThe repro file in #94716 contains a few thin archives without their member object files present. I couldn't figure out why this happened (issue in repro tarball generation?), but this caused an "unhandled Error" crash on Full diff: https://github.com/llvm/llvm-project/pull/97169.diff 1 Files Affected:
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 9dddabcf3680c..eb64e764100b2 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -349,7 +349,12 @@ static InputFile *addFile(StringRef path, LoadType loadType,
Error e = Error::success();
for (const object::Archive::Child &c : file->getArchive().children(e)) {
Expected<MemoryBufferRef> mb = c.getMemoryBufferRef();
- if (!mb || !hasObjCSection(*mb))
+ if (!mb) {
+ llvm::consumeError(mb.takeError());
+ continue;
+ }
+
+ if (!hasObjCSection(*mb))
continue;
if (Error e = file->fetch(c, "-ObjC"))
error(toString(file) + ": -ObjC failed to load archive member: " +
|
@llvm/pr-subscribers-lld Author: Daniel Bertalan (BertalanD) ChangesThe repro file in #94716 contains a few thin archives without their member object files present. I couldn't figure out why this happened (issue in repro tarball generation?), but this caused an "unhandled Error" crash on Full diff: https://github.com/llvm/llvm-project/pull/97169.diff 1 Files Affected:
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 9dddabcf3680c..eb64e764100b2 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -349,7 +349,12 @@ static InputFile *addFile(StringRef path, LoadType loadType,
Error e = Error::success();
for (const object::Archive::Child &c : file->getArchive().children(e)) {
Expected<MemoryBufferRef> mb = c.getMemoryBufferRef();
- if (!mb || !hasObjCSection(*mb))
+ if (!mb) {
+ llvm::consumeError(mb.takeError());
+ continue;
+ }
+
+ if (!hasObjCSection(*mb))
continue;
if (Error e = file->fetch(c, "-ObjC"))
error(toString(file) + ": -ObjC failed to load archive member: " +
|
# RUN: sed s/SYM/_unused/ %s | llvm-mc -filetype=obj -triple=x86_64-apple-macos -o %t/unused.o | ||
|
||
# RUN: cd %t; llvm-ar rcsT unused.a unused.o | ||
## FIXME: Absolute paths don't end up relativized in the repro file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is #97845
lld/MachO/Driver.cpp
Outdated
if (!mb || !hasObjCSection(*mb)) | ||
if (!mb) { | ||
// Thin archives from repro tarballs can contain missing members | ||
// if the member was not loaded later during the initial link. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add a if (c.getParent()->isThin())
here to not drop valid errors?
But outside or repro files, .o files referenced from an archive being missing seems like something we probably want to diag on, hmm.
Maybe we should eagerly put all .o files referenced from thin archives into the repro file always, not just when they're referenced?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not crashing on this seems nice too though, so maybe in addition to adding all .o files from a thin archive to repro files, it'd be nice to also consumeError() here if isThin(), but emit a diag instead of doing it silently.
That seems like a good approach to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ended up basically going for the approach outlined here:
- also include unused object files in the repro tarball
- warn on missing member
- make warning toggleable so we don't get spam on stderr when processing old repro files
My last question is what should happen if we don't find members when force-loading, i.e.:
llvm-project/lld/MachO/Driver.cpp
Lines 333 to 335 in 2ad7b4a
if (Error e = file->fetch(c, reason)) | |
error(toString(file) + ": " + reason + | |
" failed to load archive member: " + toString(std::move(e))); |
Downgrade this to a warning too? This was not affected by the issue we're fixing (since fetch()
was called unconditionally here), but if we add a user-facing option, we should be consistent about our behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense to me, yes.
lld/MachO/Driver.cpp
Outdated
@@ -349,7 +366,18 @@ static InputFile *addFile(StringRef path, LoadType loadType, | |||
Error e = Error::success(); | |||
for (const object::Archive::Child &c : file->getArchive().children(e)) { | |||
Expected<MemoryBufferRef> mb = c.getMemoryBufferRef(); | |||
if (!mb || !hasObjCSection(*mb)) | |||
if (!mb) { | |||
// For a long time, only referenced object files were included in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit "included in from"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other than that, looks great, thanks!
This comment was marked as outdated.
This comment was marked as outdated.
# RUN: %lld %t/main.o %t/unused.a -ObjC --no-warn-thin-archive-missing-members -o /dev/null \ | ||
# RUN: | FileCheck %s --implicit-check-not 'warning' --allow-empty | ||
|
||
# WARN: ld64.lld: warning: {{.*}}unused.a: -ObjC failed to open archive member: 'unused.o' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made some adjustment to hopefully make the test more conventional 2d756d9
Summary: Previously, we only saved those members of thin archives into a repro file that were actually used during linking. However, -ObjC handling requires us to inspect all members, even those that don't end up being loaded. We weren't handling missing members correctly and crashed with an "unhandled `Error`" failure in LLVM_ENABLE_ABI_BREAKING_CHECKS builds. To fix this, we now eagerly load all object files and warn when encountering missing members (in the instances where it wasn't a hard error before). To avoid having to patch out the checks when dealing with older repro files, the `--no-warn-thin-archive-missing-members` flag is added as an escape hatch. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60250793
Previously, we only saved those members of thin archives into a repro
file that were actually used during linking. However, -ObjC handling
requires us to inspect all members, even those that don't end up being
loaded.
We weren't handling missing members correctly and crashed with an
"unhandled
Error
" failure in LLVM_ENABLE_ABI_BREAKING_CHECKS builds.To fix this, we now eagerly load all object files and warn when
encountering missing members (in the instances where it wasn't a hard
error before). To avoid having to patch out the checks when dealing
with older repro files, the
--no-warn-thin-archive-missing-members
flag is added as an escape hatch.