-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[lld][MachO] Fix symbol insertion in transplantSymbolsAtOffset
#120737
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
@llvm/pr-subscribers-lld Author: Carlo Cabrera (carlocab) ChangesThe existing comparison does not insert symbols in the intended place. Unfortunately, it is not very clear how to test this. Suggestions Closes #120559. Full diff: https://github.com/llvm/llvm-project/pull/120737.diff 1 Files Affected:
diff --git a/lld/MachO/SymbolTable.cpp b/lld/MachO/SymbolTable.cpp
index f0a92da8777e13..36e421b52abcac 100644
--- a/lld/MachO/SymbolTable.cpp
+++ b/lld/MachO/SymbolTable.cpp
@@ -69,7 +69,7 @@ static void transplantSymbolsAtOffset(InputSection *fromIsec,
// Ensure the symbols will still be in address order after our insertions.
auto insertIt = llvm::upper_bound(toIsec->symbols, toOff,
[](uint64_t off, const Symbol *s) {
- return cast<Defined>(s)->value < off;
+ return cast<Defined>(s)->value > off;
});
llvm::erase_if(fromIsec->symbols, [&](Symbol *s) {
auto *d = cast<Defined>(s);
|
@llvm/pr-subscribers-lld-macho Author: Carlo Cabrera (carlocab) ChangesThe existing comparison does not insert symbols in the intended place. Unfortunately, it is not very clear how to test this. Suggestions Closes #120559. Full diff: https://github.com/llvm/llvm-project/pull/120737.diff 1 Files Affected:
diff --git a/lld/MachO/SymbolTable.cpp b/lld/MachO/SymbolTable.cpp
index f0a92da8777e13..36e421b52abcac 100644
--- a/lld/MachO/SymbolTable.cpp
+++ b/lld/MachO/SymbolTable.cpp
@@ -69,7 +69,7 @@ static void transplantSymbolsAtOffset(InputSection *fromIsec,
// Ensure the symbols will still be in address order after our insertions.
auto insertIt = llvm::upper_bound(toIsec->symbols, toOff,
[](uint64_t off, const Symbol *s) {
- return cast<Defined>(s)->value < off;
+ return cast<Defined>(s)->value > off;
});
llvm::erase_if(fromIsec->symbols, [&](Symbol *s) {
auto *d = cast<Defined>(s);
|
The existing comparison does not insert symbols in the intended place. Unfortunately, it is not very clear how to test this. Suggestions appreciated. Closes llvm#120559.
627f54b
to
7353c9b
Compare
transplantSymbolsAtOffset
transplantSymbolsAtOffset
These comments probably best describe the problem and why this is the correct fix: #120559 (comment), #120559 (comment) |
About adding a test for this - |
I hadn't looked at I'll give it a try, but would appreciate as many hints as possible. Not really familiar with how symbols are laid out in x86 assembly. |
Nice idea with the assert. Adding So that might be enough, considering that there already is a test case that would trigger such an assert. |
Ooops, was a bit fast. That is_sorted call needs to supply the comparison function. |
This comment notwithstanding, I added an assertion anyway since it seems like an improvement. Interestingly, the assertion I just added does not fire with Apple Clang/libc++ even if I drop the |
Does it fire with any other build config when run against the current test set ? |
It should fire with GCC, except GCC crashes before the
Yes, understood, but I'm still looking into the right way to modify |
GCC doesn't crash without
Currently I think
Given the tests have |
Right.
No, weirdly. However, it seems we can assert on
Thanks; I'll give this a try after the weekend. |
cbadcfb
to
b99bbc0
Compare
lld/MachO/SymbolTable.cpp
Outdated
assert(llvm::is_sorted(toIsec->symbols, | ||
[](const Defined *s, const Defined *t) { | ||
return s->value < t->value; | ||
}) && | ||
"Symbols should still be sorted at exit."); |
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'll probably get rid of this one, since I can't get it to fire. My theory is that the failure of this assertion can only be a consequence of UB, so the compiler just optimises this away. (No real evidence to support this though, so could be wrong!)
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.
Does is_partitioned
trigger without expensive checks ? On which tests does it trigger ?
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've verified that is_partitioned
triggers with expensive checks with Clang, and without expensive checks with GCC.
The failing tests (for both) are
Failed Tests (3):
lld :: MachO/local-alias-to-weak.s
lld :: MachO/symtab.s
lld :: MachO/weak-definition-gc.s
I haven't yet verified the assertion failure for Clang without expensive checks. The build is running now; I'll report back soon.
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.
Verified with Clang without expensive checks and the comparison in symSucceedsOff
reversed:
Failed Tests (3):
lld :: MachO/local-alias-to-weak.s
lld :: MachO/symtab.s
lld :: MachO/weak-definition-gc.s
To be sure, all errors are of the form
Assertion failed: (std::is_partitioned(toIsec->symbols.begin(), toIsec->symbols.end(), [toOff, symSucceedsOff](const Symbol *s) { return !symSucceedsOff(toOff, s); }) && "Symbols in toIsec must be partitioned by toOff."), function transplantSymbolsAtOffset, file SymbolTable.cpp, line 78.
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.
Great, thanks for checking this.
This should help catch problems with symbol insertion.
b99bbc0
to
e77e289
Compare
Tried this: diff --git a/lld/MachO/SymbolTable.cpp b/lld/MachO/SymbolTable.cpp
index a61e60a944fb..4b6e462f6bdd 100644
--- a/lld/MachO/SymbolTable.cpp
+++ b/lld/MachO/SymbolTable.cpp
@@ -68,7 +68,7 @@ static void transplantSymbolsAtOffset(InputSection *fromIsec,
uint64_t fromOff, uint64_t toOff) {
// Ensure the symbols will still be in address order after our insertions.
auto symSucceedsOff = [](uint64_t off, const Symbol *s) {
- return cast<Defined>(s)->value > off;
+ return cast<Defined>(s)->value < off;
};
assert(std::is_partitioned(toIsec->symbols.begin(), toIsec->symbols.end(),
[symSucceedsOff, toOff](const Symbol *s) {
@@ -96,6 +96,11 @@ static void transplantSymbolsAtOffset(InputSection *fromIsec,
}
return true;
});
+ assert(llvm::is_sorted(toIsec->symbols,
+ [](const Defined *s, const Defined *t) {
+ return s->value < t->value;
+ }) &&
+ "Symbols should still be sorted at exit.");
}
Defined *SymbolTable::addDefined(StringRef name, InputFile *file,
diff --git a/lld/test/MachO/alias-symbols.s b/lld/test/MachO/alias-symbols.s
index 44a388c35722..231ada5aa4c8 100644
--- a/lld/test/MachO/alias-symbols.s
+++ b/lld/test/MachO/alias-symbols.s
@@ -124,7 +124,9 @@ _strong:
_weak_1:
.space 1
_weak_2:
- .space 1
+ .long 1
+_weak_3:
+ .long 1
_dead:
.space 1
_pext: Still no failure 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.
LGTM
To be sure that we're not in a "works on my machine" situation, I pushed 0db5264e5918221edec3dacd2e8c0c6328769517 to ensure that the https://buildkite.com/llvm-project/github-pull-requests/builds/131531#0193ee8b-b917-40e0-a963-6ac1f5e01685 Going to revert that commit then merge. |
0db5264
to
e77e289
Compare
The existing comparison does not insert symbols in the intended place.
Closes #120559.