-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[RISCV][LLD] Unable to resolve R_RISCV_ALIGN when mixing +C and -C object files #63964
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
Comments
@llvm/issue-subscribers-backend-risc-v |
@llvm/issue-subscribers-lld-elf |
I haven't checked the case in detail but from the looking of it, this symptom is very likely the same as riscv-collab/riscv-gnu-toolchain#445 (I shall add more information to https://maskray.me/blog/2021-03-14-the-dark-side-of-riscv-linker-relaxation "Linker friendly On the lld side, an |
I think your analysis is correct. We need the following change.
Without it, we have the reported crash: cat > without-c.c <<e
// Other is left undefined in the link. Calls to this function are simply
// spacing to get the offsets just right
void other();
void __attribute__((noinline, aligned(32))) foo() {
other();
other();
other();
// LLD uses a compressed instruction for relaxing this call
foo();
other();
return;
}
// It's the alignment of this function that we can not satisfy.
void __attribute__((noinline, aligned(32))) bar() {
return;
}
e
truncate -s0 with-c.c
clang --target=riscv64-unknown-linux-gnu -c -fpic with-c.c -march=rv64gc -O3
clang --target=riscv64-unknown-linux-gnu -c -fpic without-c.c -march=rv64g -O3
ld.lld -shared with-c.o without-c.o # crash |
This fixes a mis-link when mixing compressed and non-compressed input to LLD. When relaxing calls, we must respect the source file that the section came from when deciding whether it's legal to use compressed instructions. If the call in question comes from a non-rvc source, then it will not expect 2-byte alignments and cascading failures may result. This fixes llvm#63964. The symptom seen there is that a latter RISCV_ALIGN can't be satisfied and we either fail an assert or produce a totally bogus link result. (It can be easily reproduced by putting .p2align 5 right before the nop in the reduced test case and running check-lld on an assertions enabled build.) However, it's important to note this is just one possible symptom of the problem. If the resulting binary has a runtime switch between rvc and non-rvc routines (via e.g. ifuncs), then even if we manage to link we may execute invalid instructions on a machine which doesn't implement compressed instructions.
…cts (#73977) This fixes a mis-link when mixing compressed and non-compressed input to LLD. When relaxing calls, we must respect the source file that the section came from when deciding whether it's legal to use compressed instructions. If the call in question comes from a non-rvc source, then it will not expect 2-byte alignments and cascading failures may result. This fixes #63964. The symptom seen there is that a latter RISCV_ALIGN can't be satisfied and we either fail an assert or produce a totally bogus link result. (It can be easily reproduced by putting .p2align 5 right before the nop in the reduced test case and running check-lld on an assertions enabled build.) However, it's important to note this is just one possible symptom of the problem. If the resulting binary has a runtime switch between rvc and non-rvc routines (via e.g. ifuncs), then even if we manage to link we may execute invalid instructions on a machine which doesn't implement compressed instructions.
When linking object files which were generated with and without compressed instructions, we will sometimes fail to resolve a R_RISCV_ALIGN relocation.
In assert builds, this results in an assert failure with the following message:
ld.lld: ../llvm-project/lld/ELF/Arch/RISCV.cpp:687: bool relax(lld::elf::InputSection&): Assertion
static_cast<int32_t>(remove) >= 0 && "R_RISCV_ALIGN needs expanding the content"' failed.`In non-assert builds, you sometimes get linker errors such as
"section size decrease is too large: 4294967472"
. This is likely not the only symptom of the broken internal invariant implied by the assert above.Here's a small stand alone reproducer:
I believe the root issue here is that we're enabling call relaxation based on whether any object file in the link had compressed enabled, not whether the object file corresponding to the section being processed does. The following diff seems to fix at least my motivating case, but I don't know if this is a full fix or not.
Here's a related patch which turns the assertion into a recoverable error. In this test case, the problem was an internal invariant violation, but I don't think there's anything preventing an invalid object file from reaching here.
The text was updated successfully, but these errors were encountered: