llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lld Author: Vitaly Buka (vitalybuka) <details> <summary>Changes</summary> In CFI jump table relaxation (relaxCFIJumpTables), moving the jump table before the last entry moves the entire jump table into the output section of that last entry. If jump table entries target functions in different output sections (for example, some in .text.hot and some in .text.unlikely or a different section), moving the jump table before the last entry can drag the jump table and its other entries into a section that does not match them. Only allow moving the jump table before the last entry if every entry in the jump table targets a section whose parent output section matches the last entry's output section. Assisted-by: Gemini --- Full diff: https://github.com/llvm/llvm-project/pull/222234.diff 2 Files Affected: - (modified) lld/ELF/Arch/X86_64.cpp (+17-1) - (modified) lld/test/ELF/x86-64-relax-jump-tables.s (+24) ``````````diff diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp index f172080dc2b6a..c49c5e0d54530 100644 --- a/lld/ELF/Arch/X86_64.cpp +++ b/lld/ELF/Arch/X86_64.cpp @@ -355,6 +355,12 @@ void X86_64::relaxCFIJumpTables() const { // Figure out the movable section for the last entry. We do this first // because the last entry controls which output section the jump table is // placed into, which affects move eligibility for other sections. + // + // The compiler can assign the jump table to a hot section (e.g. + // .text.hot). We prefer to keep it that way and avoid dragging the jump + // table into the output section of the last entry if other entries + // reside elsewhere. However, moving the jump table is likely fine if all + // entries are from that same output section. auto *lastSec = [&]() -> InputSection * { // If the jump table section is more aligned than the entry size, skip // this because there's no guarantee that we'll be able to emit a @@ -369,7 +375,17 @@ void X86_64::relaxCFIJumpTables() const { if (rels.size() >= 2 && rels[rels.size() - 2].offset >= sec->size - sec->entsize) return nullptr; - return getMovableSection(rels.back()); + InputSection *last = getMovableSection(rels.back()); + if (!last) + return nullptr; + + for (Relocation &r : rels) { + InputSection *target = getMovableSection(r); + if (!target || target->getParent() != last->getParent()) + return nullptr; + } + + return last; }(); OutputSection *targetOutputSec; if (lastSec) { diff --git a/lld/test/ELF/x86-64-relax-jump-tables.s b/lld/test/ELF/x86-64-relax-jump-tables.s index a19ab19f9c1c8..b2c98691afabf 100644 --- a/lld/test/ELF/x86-64-relax-jump-tables.s +++ b/lld/test/ELF/x86-64-relax-jump-tables.s @@ -198,6 +198,30 @@ jmp f21.cfi f21.cfi: ret $21 +## All entries must match the last entry's output section. +## f22 and f23 are in different output sections, so jt10 should not be moved +## before f23. +# CHECK: <f22>: +# CHECK-NEXT: jmp {{.*}} <f22.cfi> +# CHECK: <f23>: +# CHECK-NEXT: jmp {{.*}} <f23.cfi> +.section .text.jt10,"ax",@llvm_cfi_jump_table,8 +f22: +jmp f22.cfi +.balign 8, 0xcc +f23: +jmp f23.cfi +.balign 8, 0xcc + +.section .text.f22,"ax",@progbits +f22.cfi: +ret $22 +.zero 16 + +.section foo2,"ax",@progbits +f23.cfi: +ret $23 + # CHECK: <f1>: # CHECK-NEXT: <f1.cfi>: # CHECK-NEXT: retq $0x1 `````````` </details> https://github.com/llvm/llvm-project/pull/222234 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
