-
Notifications
You must be signed in to change notification settings - Fork 12k
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
[ELF] Don't resolve relocations referencing SHN_ABS to tombstone in non-SHF_ALLOC sections #79238
Conversation
Created using spr 1.3.4
@llvm/pr-subscribers-lld-elf @llvm/pr-subscribers-lld Author: Fangrui Song (MaskRay) ChangesA SHN_ABS symbol has never been considered for InputSection::relocateNonAlloc. The problem is that We currently apply tombstone for a relocation referencing Full diff: https://github.com/llvm/llvm-project/pull/79238.diff 2 Files Affected:
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index c728dd6c6306aa0..0e0b9783bd88a0f 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -961,12 +961,11 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
// vector. The computed value is st_value plus a non-negative offset.
// Negative values are invalid, so -1 can be used as the tombstone value.
//
- // If the referenced symbol is discarded (made Undefined), or the
- // section defining the referenced symbol is garbage collected,
- // sym.getOutputSection() is nullptr. `ds->folded` catches the ICF folded
- // case. However, resolving a relocation in .debug_line to -1 would stop
- // debugger users from setting breakpoints on the folded-in function, so
- // exclude .debug_line.
+ // If the referenced symbol is relative to a discarded section (due to
+ // --gc-sections, COMDAT, etc), it has been converted to a Undefined.
+ // `ds->folded` catches the ICF folded case. However, resolving a
+ // relocation in .debug_line to -1 would stop debugger users from setting
+ // breakpoints on the folded-in function, so exclude .debug_line.
//
// For pre-DWARF-v5 .debug_loc and .debug_ranges, -1 is a reserved value
// (base address selection entry), use 1 (which is used by GNU ld for
@@ -974,7 +973,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
//
// TODO To reduce disruption, we use 0 instead of -1 as the tombstone
// value. Enable -1 in a future release.
- if (!sym.getOutputSection() || (ds && ds->folded && !isDebugLine)) {
+ if (!ds || (ds->folded && !isDebugLine)) {
// If -z dead-reloc-in-nonalloc= is specified, respect it.
uint64_t value = SignExtend64<bits>(*tombstone);
// For a 32-bit local TU reference in .debug_names, X86_64::relocate
diff --git a/lld/test/ELF/dead-reloc-in-nonalloc.s b/lld/test/ELF/dead-reloc-in-nonalloc.s
index 145604eb883a9af..b675fc50fc2ea2f 100644
--- a/lld/test/ELF/dead-reloc-in-nonalloc.s
+++ b/lld/test/ELF/dead-reloc-in-nonalloc.s
@@ -17,7 +17,7 @@
# AA: Contents of section .debug_info:
# AA-NEXT: 0000 [[ADDR]] 00000000 aaaaaaaa 00000000
# AA: Contents of section .not_debug:
-# AA-NEXT: 0000 bbbbbbbb bbbbbbbb 00000000 .
+# AA-NEXT: 0000 bbbbbbbb 2a000000 00000000 .
## Specifying zero can get a behavior similar to GNU ld.
# RUN: ld.lld --icf=all -z dead-reloc-in-nonalloc=.debug_info=0 %t.o %tabs.o -o %tzero
|
This patch resolves the issue we have. I posted an example of the kind of code that triggers it in the previous PR. |
Thanks for verification. Do you have more information about edit: figured out. added to the description. |
Created using spr 1.3.4
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 looks good to me, but someone else should probably chime in as well to approve.
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.
Code changes LGTM too. I can't think of a case when a C/C++ compiler would directly generate a reference to an SHN_ABS symbol as I don't think there is a way of expressing such a symbol in C/C++ and debug generation concentrates on describing entities in the same module. I've asked a colleague that knows more about debug generation than I do. If I get an answer I'll post another comment.
There is a typo in the description (SHN_ANS) -> (SHN_ABS)
Created using spr 1.3.4
Fixed a typo and added an example
|
Hmm, interesting. Thanks for the fix. |
…on-SHF_ALLOC sections (llvm#79238) A SHN_ABS symbol has never been considered for InputSection::relocateNonAlloc. Before llvm#74686, the code did made it work in the absence of `-z dead-reloc-in-nonalloc=`. There is now a report about such SHN_ABS uses (llvm#74686 (comment)) and I think it makes sense for non-SHF_ALLOC to support SHN_ABS, like SHF_ALLOC sections do. ``` // clang -g __attribute__((weak)) int symbol; int *foo() { return &symbol; } 0x00000023: DW_TAG_variable [2] (0x0000000c) ... DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0) ``` .debug_addr references `symbol`, which can be redefined by a symbol assignment or --defsym to become a SHN_ABS symbol. The problem is that `!sym.getOutputSection()` cannot discern SHN_ABS from a symbol whose section has been discarded. Since commit 1981b1b, a symbol relative to a discarded section is changed to `Undefined`, so the `SHN_ABS` check become trivial. We currently apply tombstone for a relocation referencing `SharedSymbol`. This patch does not change the behavior. (cherry picked from commit 8abf8d1)
…on-SHF_ALLOC sections (#79238) A SHN_ABS symbol has never been considered for InputSection::relocateNonAlloc. Before #74686, the code did made it work in the absence of `-z dead-reloc-in-nonalloc=`. There is now a report about such SHN_ABS uses (#74686 (comment)) and I think it makes sense for non-SHF_ALLOC to support SHN_ABS, like SHF_ALLOC sections do. ``` // clang -g __attribute__((weak)) int symbol; int *foo() { return &symbol; } 0x00000023: DW_TAG_variable [2] (0x0000000c) ... DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0) ``` .debug_addr references `symbol`, which can be redefined by a symbol assignment or --defsym to become a SHN_ABS symbol. The problem is that `!sym.getOutputSection()` cannot discern SHN_ABS from a symbol whose section has been discarded. Since commit 1981b1b, a symbol relative to a discarded section is changed to `Undefined`, so the `SHN_ABS` check become trivial. We currently apply tombstone for a relocation referencing `SharedSymbol`. This patch does not change the behavior. (cherry picked from commit 8abf8d1)
…on-SHF_ALLOC sections (llvm#79238) A SHN_ABS symbol has never been considered for InputSection::relocateNonAlloc. Before llvm#74686, the code did made it work in the absence of `-z dead-reloc-in-nonalloc=`. There is now a report about such SHN_ABS uses (llvm#74686 (comment)) and I think it makes sense for non-SHF_ALLOC to support SHN_ABS, like SHF_ALLOC sections do. ``` // clang -g __attribute__((weak)) int symbol; int *foo() { return &symbol; } 0x00000023: DW_TAG_variable [2] (0x0000000c) ... DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0) ``` .debug_addr references `symbol`, which can be redefined by a symbol assignment or --defsym to become a SHN_ABS symbol. The problem is that `!sym.getOutputSection()` cannot discern SHN_ABS from a symbol whose section has been discarded. Since commit 1981b1b, a symbol relative to a discarded section is changed to `Undefined`, so the `SHN_ABS` check become trivial. We currently apply tombstone for a relocation referencing `SharedSymbol`. This patch does not change the behavior. (cherry picked from commit 8abf8d1)
…on-SHF_ALLOC sections (llvm#79238) A SHN_ABS symbol has never been considered for InputSection::relocateNonAlloc. Before llvm#74686, the code did made it work in the absence of `-z dead-reloc-in-nonalloc=`. There is now a report about such SHN_ABS uses (llvm#74686 (comment)) and I think it makes sense for non-SHF_ALLOC to support SHN_ABS, like SHF_ALLOC sections do. ``` // clang -g __attribute__((weak)) int symbol; int *foo() { return &symbol; } 0x00000023: DW_TAG_variable [2] (0x0000000c) ... DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0) ``` .debug_addr references `symbol`, which can be redefined by a symbol assignment or --defsym to become a SHN_ABS symbol. The problem is that `!sym.getOutputSection()` cannot discern SHN_ABS from a symbol whose section has been discarded. Since commit 1981b1b, a symbol relative to a discarded section is changed to `Undefined`, so the `SHN_ABS` check become trivial. We currently apply tombstone for a relocation referencing `SharedSymbol`. This patch does not change the behavior. (cherry picked from commit 8abf8d1)
…on-SHF_ALLOC sections (llvm#79238) A SHN_ABS symbol has never been considered for InputSection::relocateNonAlloc. Before llvm#74686, the code did made it work in the absence of `-z dead-reloc-in-nonalloc=`. There is now a report about such SHN_ABS uses (llvm#74686 (comment)) and I think it makes sense for non-SHF_ALLOC to support SHN_ABS, like SHF_ALLOC sections do. ``` // clang -g __attribute__((weak)) int symbol; int *foo() { return &symbol; } 0x00000023: DW_TAG_variable [2] (0x0000000c) ... DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0) ``` .debug_addr references `symbol`, which can be redefined by a symbol assignment or --defsym to become a SHN_ABS symbol. The problem is that `!sym.getOutputSection()` cannot discern SHN_ABS from a symbol whose section has been discarded. Since commit 1981b1b, a symbol relative to a discarded section is changed to `Undefined`, so the `SHN_ABS` check become trivial. We currently apply tombstone for a relocation referencing `SharedSymbol`. This patch does not change the behavior. (cherry picked from commit 8abf8d1)
…on-SHF_ALLOC sections (llvm#79238) A SHN_ABS symbol has never been considered for InputSection::relocateNonAlloc. Before llvm#74686, the code did made it work in the absence of `-z dead-reloc-in-nonalloc=`. There is now a report about such SHN_ABS uses (llvm#74686 (comment)) and I think it makes sense for non-SHF_ALLOC to support SHN_ABS, like SHF_ALLOC sections do. ``` // clang -g __attribute__((weak)) int symbol; int *foo() { return &symbol; } 0x00000023: DW_TAG_variable [2] (0x0000000c) ... DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0) ``` .debug_addr references `symbol`, which can be redefined by a symbol assignment or --defsym to become a SHN_ABS symbol. The problem is that `!sym.getOutputSection()` cannot discern SHN_ABS from a symbol whose section has been discarded. Since commit 1981b1b, a symbol relative to a discarded section is changed to `Undefined`, so the `SHN_ABS` check become trivial. We currently apply tombstone for a relocation referencing `SharedSymbol`. This patch does not change the behavior. (cherry picked from commit 8abf8d1)
Do you want to cherry pick #74686 and this follow-up #79238 with an older code base like lld 17? You can consider cherry picking 1981b1b as well, but there are multiple follow-up commits. Note, if your llvm is locked into a certain version, it should be quite straightforward to sync just |
It's even worse I am trying to cherry pick #74686 and #79238 onto llvm-15 (although llvm-17 is next). I looked into cherry picking 1981b1b, but it touches a lot of code that is not even in llvm-15. Thus I was wondering if check is possible some other way. So without this LLD will tombstone some addresses in a .debug section OR if dead-reloc-in-nonalloc is specified, correct? |
Without checking 1981b1b , you can check a SHN_ABS symbol with something like |
ok thanks. Appreciate the help. |
A SHN_ABS symbol has never been considered for InputSection::relocateNonAlloc.
Before #74686, the code did made it work in the absence of
-z dead-reloc-in-nonalloc=
.There is now a report about such SHN_ABS uses
(#74686 (comment))
and I think it makes sense for non-SHF_ALLOC to support SHN_ABS, like
SHF_ALLOC sections do.
.debug_addr references
symbol
, which can be redefined by a symbolassignment or --defsym to become a SHN_ABS symbol.
The problem is that
!sym.getOutputSection()
cannot discern SHN_ABSfrom a symbol whose section has been discarded. Since commit
1981b1b, a symbol relative to a
discarded section is changed to
Undefined
, so theSHN_ABS
checkbecome trivial.
We currently apply tombstone for a relocation referencing
SharedSymbol
. This patch does not change the behavior.