From 8787a619d694e9834c5413c00907e1d00a4bc748 Mon Sep 17 00:00:00 2001 From: Vladislav Dzhidzhoev Date: Fri, 7 Mar 2025 12:50:35 +0100 Subject: [PATCH 1/8] [llvm-objdump][ARM] Find ELF file PLT entries for arm, thumb This implements arm, armeb, thumb, thumbeb PLT entries parsing support in ELF for llvm-objdump. Implementation is similar to AArch64MCInstrAnalysis::findPltEntries. PLT entry signatures are based on LLD code for PLT generation (ARM::writePlt). llvm-objdump tests are generated based on lld/test/ELF/arm-plt-reloc.s, lld/test/ELF/armv8-thumb-plt-reloc.s. --- .../tools/llvm-objdump/ARM/plt.c | 243 ++++++++++++++++++ lld/test/ELF/arm-gnu-ifunc-plt.s | 4 + lld/test/ELF/arm-mixed-plts.s | 2 + lld/test/ELF/arm-plt-reloc.s | 38 ++- lld/test/ELF/arm-thumb-interwork-shared.s | 4 + lld/test/ELF/arm-thumb-interwork-thunk.s | 16 ++ lld/test/ELF/arm-thumb-plt-range-thunk-os.s | 6 + lld/test/ELF/arm-thumb-plt-reloc.s | 6 + lld/test/ELF/arm-thunk-multipass-plt.s | 4 + lld/test/ELF/arm-thunk-re-add.s | 4 + lld/test/ELF/armv8-thumb-plt-reloc.s | 6 + llvm/lib/Object/ELFObjectFile.cpp | 6 + .../ARM/MCTargetDesc/ARMMCTargetDesc.cpp | 132 ++++++++++ llvm/tools/llvm-objdump/llvm-objdump.cpp | 46 +++- 14 files changed, 508 insertions(+), 9 deletions(-) create mode 100644 cross-project-tests/tools/llvm-objdump/ARM/plt.c diff --git a/cross-project-tests/tools/llvm-objdump/ARM/plt.c b/cross-project-tests/tools/llvm-objdump/ARM/plt.c new file mode 100644 index 0000000000000..4bcf8536492c9 --- /dev/null +++ b/cross-project-tests/tools/llvm-objdump/ARM/plt.c @@ -0,0 +1,243 @@ +// Test PLT section parsing on arm. + +// RUN: %clang -target armv6a-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: -nostdlib -nostdinc -shared %s -o %t1 +// RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ +// RUN: -d %t1 | FileCheck %s --check-prefixes=CHECK,LE + +// Test PLT section parsing on armeb. + +// RUN: %clang -target armv6aeb-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: -nostdlib -nostdinc -shared %s -o %t2 +// RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ +// RUN: -d %t2 | FileCheck %s --check-prefixes=CHECK,BE +// RUN: obj2yaml %t2 | FileCheck %s --check-prefixes=NOBE8 + +// Test PLT section parsing on armeb with be8. + +// RUN: %clang -target armv7aeb-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: -nostdlib -nostdinc -shared %s -o %t3 +// RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ +// RUN: -d %t3 | FileCheck %s --check-prefixes=CHECK,BE +// RUN: obj2yaml %t3 | FileCheck %s --check-prefixes=BE8 + +// LE: file format elf32-littlearm +// BE: file format elf32-bigarm +// NOBE8-NOT: EF_ARM_BE8 +// BE8: EF_ARM_BE8 + +// CHECK: Disassembly of section .text: +// CHECK-EMPTY: +// CHECK-NEXT: <_start>: +// CHECK-NEXT: push {r11, lr} +// CHECK-NEXT: mov r11, sp +// CHECK-NEXT: bl 0x10240 +// CHECK-NEXT: bl 0x10250 +// CHECK-NEXT: bl 0x10260 + +// CHECK: Disassembly of section .plt: +// CHECK: 00010240 : +// CHECK-NEXT: add r12, pc, #0, #12 +// CHECK-NEXT: add r12, r12, #32, #20 +// CHECK-NEXT: ldr pc, [r12, #132]! +// CHECK-NEXT: .word 0xd4d4d4d4 +// CHECK-EMPTY: +// CHECK-NEXT: 00010250 : +// CHECK-NEXT: add r12, pc, #0, #12 +// CHECK-NEXT: add r12, r12, #32, #20 +// CHECK-NEXT: ldr pc, [r12, #120]! +// CHECK-NEXT: .word 0xd4d4d4d4 +// CHECK-EMPTY: +// CHECK-NEXT: 00010260 : +// CHECK-NEXT: add r12, pc, #0, #12 +// CHECK-NEXT: add r12, r12, #32, #20 +// CHECK-NEXT: ldr pc, [r12, #108]! +// CHECK-NEXT: .word 0xd4d4d4d4 + +// Test PLT section parsing on thumb. + +// RUN: %clang -target thumbv8.1m.main-none-linux-eabi \ +// RUN: -nostdlib -nostdinc -c %s -o %t4.o +// RUN: ld.lld --shared %t4.o -o %t4 +// RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ +// RUN: -d %t4 | FileCheck %s --check-prefixes=THUMB,LE + +// Test PLT section parsing on thumbeb. + +// RUN: %clang -target thumbebv8.1m.main-none-linux-eabi \ +// RUN: -nostdlib -nostdinc -c %s -o %t5.o +// RUN: ld.lld --shared %t5.o -o %t5 +// RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ +// RUN: -d %t5 | FileCheck %s --check-prefixes=THUMB,BE +// RUN: obj2yaml %t5 | FileCheck %s --check-prefixes=NOBE8 + +// Test PLT section parsing on thumbeb with be8. + +// RUN: %clang -target thumbebv8.1m.main-none-linux-eabi \ +// RUN: -nostdlib -nostdinc -c %s -o %t6.o +// RUN: ld.lld --shared --be8 %t6.o -o %t6 +// RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ +// RUN: -d %t6 | FileCheck %s --check-prefixes=THUMB,BE +// RUN: obj2yaml %t6 | FileCheck %s --check-prefixes=BE8 + +// THUMB: Disassembly of section .text: +// THUMB-EMPTY: +// THUMB-NEXT: <_start>: +// THUMB-NEXT: push {r7, lr} +// THUMB-NEXT: mov r7, sp +// THUMB-NEXT: bl 0x10270 +// THUMB-NEXT: bl 0x10280 +// THUMB-NEXT: bl 0x10290 + +// THUMB: Disassembly of section .plt: +// THUMB-EMPTY: +// THUMB: 00010270 : +// THUMB-NEXT: movw r12, #136 +// THUMB-NEXT: movt r12, #2 +// THUMB-NEXT: add r12, pc +// THUMB-NEXT: ldr.w pc, [r12] +// THUMB-NEXT: b 0x1027a +// THUMB-EMPTY: +// THUMB-NEXT: 00010280 : +// THUMB-NEXT: movw r12, #124 +// THUMB-NEXT: movt r12, #2 +// THUMB-NEXT: add r12, pc +// THUMB-NEXT: ldr.w pc, [r12] +// THUMB-NEXT: b 0x1028a +// THUMB-EMPTY: +// THUMB-NEXT: 00010290 : +// THUMB-NEXT: movw r12, #112 +// THUMB-NEXT: movt r12, #2 +// THUMB-NEXT: add r12, pc +// THUMB-NEXT: ldr.w pc, [r12] +// THUMB-NEXT: b 0x1029a + +// Test PLT section with long entries parsing on arm. + +// RUN: echo "SECTIONS { \ +// RUN: .text 0x1000 : { *(.text) } \ +// RUN: .plt 0x2000 : { *(.plt) *(.plt.*) } \ +// RUN: .got.plt 0x9000000 : { *(.got.plt) } \ +// RUN: }" > %t.long.script + +// RUN: %clang -target armv6a-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: -Xlinker --script=%t.long.script -nostdlib -nostdinc \ +// RUN: -shared %s -o %t7 +// RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ +// RUN: -d %t7 | FileCheck %s --check-prefixes=CHECKLONG,LE + +// Test PLT section with long entries parsing on armeb. + +// RUN: %clang -target armv6aeb-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: -Xlinker --script=%t.long.script -nostdlib -nostdinc \ +// RUN: -shared %s -o %t8 +// RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ +// RUN: -d %t8 | FileCheck %s --check-prefixes=CHECKLONG,BE +// RUN: obj2yaml %t8 | FileCheck %s --check-prefixes=NOBE8 + +// Test PLT section with long entries parsing on armeb with be8. + +// RUN: %clang -target armv7aeb-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: -Xlinker --script=%t.long.script -nostdlib -nostdinc \ +// RUN: -shared %s -o %t9 +// RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ +// RUN: -d %t9 | FileCheck %s --check-prefixes=CHECKLONG,BE +// RUN: obj2yaml %t9 | FileCheck %s --check-prefixes=BE8 + +// CHECKLONG: Disassembly of section .text: +// CHECKLONG-EMPTY: +// CHECKLONG-NEXT: <_start>: +// CHECKLONG-NEXT: push {r11, lr} +// CHECKLONG-NEXT: mov r11, sp +// CHECKLONG-NEXT: bl 0x2020 +// CHECKLONG-NEXT: bl 0x2030 +// CHECKLONG-NEXT: bl 0x2040 + +// CHECKLONG: Disassembly of section .plt: +// CHECKLONG: 00002020 : +// CHECKLONG-NEXT: ldr r12, [pc, #4] +// CHECKLONG-NEXT: add r12, r12, pc +// CHECKLONG-NEXT: ldr pc, [r12] +// CHECKLONG-NEXT: .word 0x08ffdfe0 +// CHECKLONG-EMPTY: +// CHECKLONG-NEXT: 00002030 : +// CHECKLONG-NEXT: ldr r12, [pc, #4] +// CHECKLONG-NEXT: add r12, r12, pc +// CHECKLONG-NEXT: ldr pc, [r12] +// CHECKLONG-NEXT: .word 0x08ffdfd4 +// CHECKLONG-EMPTY: +// CHECKLONG-NEXT: 00002040 : +// CHECKLONG-NEXT: ldr r12, [pc, #4] +// CHECKLONG-NEXT: add r12, r12, pc +// CHECKLONG-NEXT: ldr pc, [r12] +// CHECKLONG-NEXT: .word 0x08ffdfc8 + +// Test PLT section with mixed long and short entries parsing on arm. + +// RUN: echo "SECTIONS { \ +// RUN: .text 0x1000 : { *(.text) } \ +// RUN: .plt 0x2000 : { *(.plt) *(.plt.*) } \ +// RUN: .got.plt 0x8002020 : { *(.got.plt) } \ +// RUN: }" > %t.mix.script + +// RUN: %clang -target armv6a-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: -Xlinker --script=%t.mix.script -nostdlib -nostdinc \ +// RUN: -shared %s -o %t10 +// RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ +// RUN: -d %t10 | FileCheck %s --check-prefixes=CHECKMIX,LE + +// Test PLT section with mixed long and short entries parsing on armeb. + +// RUN: %clang -target armv6aeb-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: -Xlinker --script=%t.mix.script -nostdlib -nostdinc \ +// RUN: -shared %s -o %t11 +// RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ +// RUN: -d %t11 | FileCheck %s --check-prefixes=CHECKMIX,BE +// RUN: obj2yaml %t11 | FileCheck %s --check-prefixes=NOBE8 + +// Test PLT section with mixed long and short entries parsing on armeb with be8. + +// RUN: %clang -target armv7aeb-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: -Xlinker --script=%t.mix.script -nostdlib -nostdinc \ +// RUN: -shared %s -o %t12 +// RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ +// RUN: -d %t12 | FileCheck %s --check-prefixes=CHECKMIX,BE +// RUN: obj2yaml %t12 | FileCheck %s --check-prefixes=BE8 + +// CHECKMIX: Disassembly of section .text: +// CHECKMIX-EMPTY: +// CHECKMIX-NEXT: <_start>: +// CHECKMIX-NEXT: push {r11, lr} +// CHECKMIX-NEXT: mov r11, sp +// CHECKMIX-NEXT: bl 0x2020 +// CHECKMIX-NEXT: bl 0x2030 +// CHECKMIX-NEXT: bl 0x2040 + +// CHECKMIX: Disassembly of section .plt: +// CHECKMIX: 00002020 : +// CHECKMIX-NEXT: ldr r12, [pc, #4] +// CHECKMIX-NEXT: add r12, r12, pc +// CHECKMIX-NEXT: ldr pc, [r12] +// CHECKMIX-NEXT: .word 0x08000000 +// CHECKMIX-EMPTY: +// CHECKMIX-NEXT: 00002030 : +// CHECKMIX-NEXT: add r12, pc, #133169152 +// CHECKMIX-NEXT: add r12, r12, #1044480 +// CHECKMIX-NEXT: ldr pc, [r12, #4088]! +// CHECKMIX-NEXT: .word 0xd4d4d4d4 +// CHECKMIX-EMPTY: +// CHECKMIX-NEXT: 00002040 : +// CHECKMIX-NEXT: add r12, pc, #133169152 +// CHECKMIX-NEXT: add r12, r12, #1044480 +// CHECKMIX-NEXT: ldr pc, [r12, #4076]! +// CHECKMIX-NEXT: .word 0xd4d4d4d4 + +extern void *func1(); +extern void *func2(); +extern void *func3(); + +void _start() { + func1(); + func2(); + func3(); +} diff --git a/lld/test/ELF/arm-gnu-ifunc-plt.s b/lld/test/ELF/arm-gnu-ifunc-plt.s index 55592c0843d6a..f3960b3f42f7f 100644 --- a/lld/test/ELF/arm-gnu-ifunc-plt.s +++ b/lld/test/ELF/arm-gnu-ifunc-plt.s @@ -53,10 +53,14 @@ // DISASM-NEXT: 20214: d4 d4 d4 d4 .word 0xd4d4d4d4 // DISASM-NEXT: 20218: d4 d4 d4 d4 .word 0xd4d4d4d4 // DISASM-NEXT: 2021c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DISASM-EMPTY: +// DISASM-NEXT: : // DISASM-NEXT: 20220: add r12, pc, #0, #12 // DISASM-NEXT: 20224: add r12, r12, #32 // DISASM-NEXT: 20228: ldr pc, [r12, #212]! // DISASM-NEXT: 2022c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DISASM-EMPTY: +// DISASM-NEXT: : // DISASM-NEXT: 20230: add r12, pc, #0, #12 // DISASM-NEXT: 20234: add r12, r12, #32 // DISASM-NEXT: 20238: ldr pc, [r12, #200]! diff --git a/lld/test/ELF/arm-mixed-plts.s b/lld/test/ELF/arm-mixed-plts.s index 801de70f4f101..529983dfd9266 100644 --- a/lld/test/ELF/arm-mixed-plts.s +++ b/lld/test/ELF/arm-mixed-plts.s @@ -18,6 +18,8 @@ # CHECK-NEXT: d4 d4 d4 d4 .word 0xd4d4d4d4 # CHECK-NEXT: d4 d4 d4 d4 .word 0xd4d4d4d4 # CHECK-NEXT: d4 d4 d4 d4 .word 0xd4d4d4d4 +# CHECK-EMPTY: +# CHECK-NEXT: : # CHECK-NEXT: e28fc600 add r12, pc, #0, #12 # CHECK-NEXT: e28cca20 add r12, r12, #32, #20 # CHECK-NEXT: e5bcf06c ldr pc, [r12, #0x6c]! diff --git a/lld/test/ELF/arm-plt-reloc.s b/lld/test/ELF/arm-plt-reloc.s index bfd51467e7425..6f5777ff1052c 100644 --- a/lld/test/ELF/arm-plt-reloc.s +++ b/lld/test/ELF/arm-plt-reloc.s @@ -74,16 +74,22 @@ _start: // DSO-NEXT: 10248: d4 d4 d4 d4 .word 0xd4d4d4d4 // DSO-NEXT: 1024c: d4 d4 d4 d4 .word 0xd4d4d4d4 // (0x10250 + 8) + (0 RoR 12) + (32 RoR 20 = 0x20000) + 140 = 0x302e4 +// DSO-EMPTY: +// DSO-NEXT: : // DSO-NEXT: 10250: add r12, pc, #0, #12 // DSO-NEXT: 10254: add r12, r12, #32, #20 // DSO-NEXT: 10258: ldr pc, [r12, #140]! // DSO-NEXT: 1025c: d4 d4 d4 d4 .word 0xd4d4d4d4 // (0x10260 + 8) + (0 RoR 12) + (32 RoR 20 = 0x20000) + 128 = 0x302e8 +// DSO-EMPTY: +// DSO-NEXT: : // DSO-NEXT: 10260: add r12, pc, #0, #12 // DSO-NEXT: 10264: add r12, r12, #32, #20 // DSO-NEXT: 10268: ldr pc, [r12, #128]! // DSO-NEXT: 1026c: d4 d4 d4 d4 .word 0xd4d4d4d4 // (0x10270 + 8) + (0 RoR 12) + (32 RoR 20 = 0x20000) + 116 = 0x302ec +// DSO-EMPTY: +// DSO-NEXT: : // DSO-NEXT: 10270: add r12, pc, #0, #12 // DSO-NEXT: 10274: add r12, r12, #32, #20 // DSO-NEXT: 10278: ldr pc, [r12, #116]! @@ -152,14 +158,20 @@ _start: // CHECKHIGH-NEXT: 2014: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECKHIGH-NEXT: 2018: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECKHIGH-NEXT: 201c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECKHIGH-EMPTY: +// CHECKHIGH-NEXT: : // CHECKHIGH-NEXT: 2020: add r12, pc, #16, #12 // CHECKHIGH-NEXT: 2024: add r12, r12, #1036288 // CHECKHIGH-NEXT: 2028: ldr pc, [r12, #4068]! // CHECKHIGH-NEXT: 202c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECKHIGH-EMPTY: +// CHECKHIGH-NEXT: : // CHECKHIGH-NEXT: 2030: add r12, pc, #16, #12 // CHECKHIGH-NEXT: 2034: add r12, r12, #1036288 // CHECKHIGH-NEXT: 2038: ldr pc, [r12, #4056]! // CHECKHIGH-NEXT: 203c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECKHIGH-EMPTY: +// CHECKHIGH-NEXT: : // CHECKHIGH-NEXT: 2040: add r12, pc, #16, #12 // CHECKHIGH-NEXT: 2044: add r12, r12, #1036288 // CHECKHIGH-NEXT: 2048: ldr pc, [r12, #4044]! @@ -220,14 +232,20 @@ _start: // CHECKLONG-NEXT: 2014: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECKLONG-NEXT: 2018: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECKLONG-NEXT: 201c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECKLONG-EMPTY: +// CHECKLONG-NEXT: : // CHECKLONG-NEXT: 2020: ldr r12, [pc, #4] // CHECKLONG-NEXT: 2024: add r12, r12, pc // CHECKLONG-NEXT: 2028: ldr pc, [r12] // CHECKLONG-NEXT: 202c: e0 f0 10 11 .word 0x1110f0e0 +// CHECKLONG-EMPTY: +// CHECKLONG-NEXT: : // CHECKLONG-NEXT: 2030: ldr r12, [pc, #4] // CHECKLONG-NEXT: 2034: add r12, r12, pc // CHECKLONG-NEXT: 2038: ldr pc, [r12] // CHECKLONG-NEXT: 203c: d4 f0 10 11 .word 0x1110f0d4 +// CHECKLONG-EMPTY: +// CHECKLONG-NEXT: : // CHECKLONG-NEXT: 2040: ldr r12, [pc, #4] // CHECKLONG-NEXT: 2044: add r12, r12, pc // CHECKLONG-NEXT: 2048: ldr pc, [r12] @@ -257,14 +275,20 @@ _start: // CHECKLONG-EB-NEXT: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECKLONG-EB-NEXT: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECKLONG-EB-NEXT: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECKLONG-EB-EMPTY: +// CHECKLONG-EB-NEXT: : // CHECKLONG-EB-NEXT: 2020: ldr r12, [pc, #4] // CHECKLONG-EB-NEXT: add r12, r12, pc // CHECKLONG-EB-NEXT: ldr pc, [r12] // CHECKLONG-EB-NEXT: 11 10 f0 e0 .word 0x1110f0e0 +// CHECKLONG-EB-EMPTY: +// CHECKLONG-EB-NEXT: : // CHECKLONG-EB-NEXT: 2030: ldr r12, [pc, #4] // CHECKLONG-EB-NEXT: add r12, r12, pc // CHECKLONG-EB-NEXT: ldr pc, [r12] // CHECKLONG-EB-NEXT: 11 10 f0 d4 .word 0x1110f0d4 +// CHECKLONG-EB-EMPTY: +// CHECKLONG-EB-NEXT: : // CHECKLONG-EB-NEXT: 2040: ldr r12, [pc, #4] // CHECKLONG-EB-NEXT: add r12, r12, pc // CHECKLONG-EB-NEXT: ldr pc, [r12] @@ -299,7 +323,7 @@ _start: // RUN: llvm-objdump --no-print-imm-hex --triple=armv7aeb-none-linux-gnueabi -d --no-show-raw-insn %t6.be | FileCheck --check-prefix=CHECKMIX-EB %s // RUN: llvm-readobj -S -r %t6.be | FileCheck --check-prefix=DSORELMIX %s // RUN: ld.lld --be8 --hash-style=sysv --script %t3.script -shared %t1.be %t2.be -o %t6.be -// RUN: llvm-objdump --no-print-imm-hex --triple=armv7a-none-linux-gnueabi -d --no-show-raw-insn %t6.be | FileCheck --check-prefix=CHECKMIX-EB %s +// RUN: llvm-objdump --no-print-imm-hex --triple=armv7aeb-none-linux-gnueabi -d --no-show-raw-insn %t6.be | FileCheck --check-prefix=CHECKMIX-EB %s // RUN: llvm-readobj -S -r %t6.be | FileCheck --check-prefix=DSORELMIX %s // CHECKMIX: Disassembly of section .text: @@ -326,14 +350,20 @@ _start: // CHECKMIX-NEXT: 2014: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECKMIX-NEXT: 2018: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECKMIX-NEXT: 201c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECKMIX-EMPTY: +// CHECKMIX-NEXT: : // CHECKMIX-NEXT: 2020: ldr r12, [pc, #4] // CHECKMIX-NEXT: 2024: add r12, r12, pc // CHECKMIX-NEXT: 2028: ldr pc, [r12] // CHECKMIX-NEXT: 202c: 00 00 00 08 .word 0x08000000 +// CHECKMIX-EMPTY: +// CHECKMIX-NEXT: : // CHECKMIX-NEXT: 2030: add r12, pc, #133169152 // CHECKMIX-NEXT: 2034: add r12, r12, #1044480 // CHECKMIX-NEXT: 2038: ldr pc, [r12, #4088]! // CHECKMIX-NEXT: 203c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECKMIX-EMPTY: +// CHECKMIX-NEXT: : // CHECKMIX-NEXT: 2040: add r12, pc, #133169152 // CHECKMIX-NEXT: 2044: add r12, r12, #1044480 // CHECKMIX-NEXT: 2048: ldr pc, [r12, #4076]! @@ -363,14 +393,20 @@ _start: // CHECKMIX-EB-NEXT: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECKMIX-EB-NEXT: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECKMIX-EB-NEXT: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECKMIX-EB-EMPTY: +// CHECKMIX-EB-NEXT: : // CHECKMIX-EB-NEXT: 2020: ldr r12, [pc, #4] // CHECKMIX-EB-NEXT: add r12, r12, pc // CHECKMIX-EB-NEXT: ldr pc, [r12] // CHECKMIX-EB-NEXT: 08 00 00 00 .word 0x08000000 +// CHECKMIX-EB-EMPTY: +// CHECKMIX-EB-NEXT: : // CHECKMIX-EB-NEXT: 2030: add r12, pc, #133169152 // CHECKMIX-EB-NEXT: add r12, r12, #1044480 // CHECKMIX-EB-NEXT: ldr pc, [r12, #4088]! // CHECKMIX-EB-NEXT: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECKMIX-EB-EMPTY: +// CHECKMIX-EB-NEXT: : // CHECKMIX-EB-NEXT: 2040: add r12, pc, #133169152 // CHECKMIX-EB-NEXT: add r12, r12, #1044480 // CHECKMIX-EB-NEXT: ldr pc, [r12, #4076]! diff --git a/lld/test/ELF/arm-thumb-interwork-shared.s b/lld/test/ELF/arm-thumb-interwork-shared.s index 03bed000a02e6..8a616f9d75797 100644 --- a/lld/test/ELF/arm-thumb-interwork-shared.s +++ b/lld/test/ELF/arm-thumb-interwork-shared.s @@ -45,10 +45,14 @@ sym1: // CHECK-NEXT: .word 0xd4d4d4d4 // CHECK-NEXT: .word 0xd4d4d4d4 // CHECK-NEXT: .word 0xd4d4d4d4 +// CHECK-EMPTY: +// CHECK-NEXT: : // CHECK-NEXT: 10230: add r12, pc, #0, #12 // CHECK-NEXT: add r12, r12, #32 // CHECK-NEXT: ldr pc, [r12, #124]! // CHECK-NEXT: 1023c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-EMPTY: +// CHECK-NEXT: : // CHECK-NEXT: 10240: add r12, pc, #0, #12 // CHECK-NEXT: add r12, r12, #32 // CHECK-NEXT: ldr pc, [r12, #112]! diff --git a/lld/test/ELF/arm-thumb-interwork-thunk.s b/lld/test/ELF/arm-thumb-interwork-thunk.s index 39a2e737cc9d2..a01be31bfd9ae 100644 --- a/lld/test/ELF/arm-thumb-interwork-thunk.s +++ b/lld/test/ELF/arm-thumb-interwork-thunk.s @@ -298,34 +298,50 @@ _start: // CHECK-ARM-PLT-NEXT: 1624: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECK-ARM-PLT-NEXT: 1628: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECK-ARM-PLT-NEXT: 162c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-ARM-PLT-EMPTY: +// CHECK-ARM-PLT-NEXT: // CHECK-ARM-PLT-NEXT: 1630: add r12, pc, #0, #12 // CHECK-ARM-PLT-NEXT: 1634: add r12, r12, #0, #20 // CHECK-ARM-PLT-NEXT: 1638: ldr pc, [r12, #648]! // CHECK-ARM-PLT-NEXT: 163c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-ARM-PLT-EMPTY: +// CHECK-ARM-PLT-NEXT: // CHECK-ARM-PLT-NEXT: 1640: add r12, pc, #0, #12 // CHECK-ARM-PLT-NEXT: 1644: add r12, r12, #0, #20 // CHECK-ARM-PLT-NEXT: 1648: ldr pc, [r12, #636]! // CHECK-ARM-PLT-NEXT: 164c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-ARM-PLT-EMPTY: +// CHECK-ARM-PLT-NEXT: // CHECK-ARM-PLT-NEXT: 1650: add r12, pc, #0, #12 // CHECK-ARM-PLT-NEXT: 1654: add r12, r12, #0, #20 // CHECK-ARM-PLT-NEXT: 1658: ldr pc, [r12, #624]! // CHECK-ARM-PLT-NEXT: 165c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-ARM-PLT-EMPTY: +// CHECK-ARM-PLT-NEXT: // CHECK-ARM-PLT-NEXT: 1660: add r12, pc, #0, #12 // CHECK-ARM-PLT-NEXT: 1664: add r12, r12, #0, #20 // CHECK-ARM-PLT-NEXT: 1668: ldr pc, [r12, #612]! // CHECK-ARM-PLT-NEXT: 166c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-ARM-PLT-EMPTY: +// CHECK-ARM-PLT-NEXT: // CHECK-ARM-PLT-NEXT: 1670: add r12, pc, #0, #12 // CHECK-ARM-PLT-NEXT: 1674: add r12, r12, #0, #20 // CHECK-ARM-PLT-NEXT: 1678: ldr pc, [r12, #600]! // CHECK-ARM-PLT-NEXT: 167c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-ARM-PLT-EMPTY: +// CHECK-ARM-PLT-NEXT: // CHECK-ARM-PLT-NEXT: 1680: add r12, pc, #0, #12 // CHECK-ARM-PLT-NEXT: 1684: add r12, r12, #0, #20 // CHECK-ARM-PLT-NEXT: 1688: ldr pc, [r12, #588]! // CHECK-ARM-PLT-NEXT: 168c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-ARM-PLT-EMPTY: +// CHECK-ARM-PLT-NEXT: // CHECK-ARM-PLT-NEXT: 1690: add r12, pc, #0, #12 // CHECK-ARM-PLT-NEXT: 1694: add r12, r12, #0, #20 // CHECK-ARM-PLT-NEXT: 1698: ldr pc, [r12, #576]! // CHECK-ARM-PLT-NEXT: 169c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-ARM-PLT-EMPTY: +// CHECK-ARM-PLT-NEXT: // CHECK-ARM-PLT-NEXT: 16a0: add r12, pc, #0, #12 // CHECK-ARM-PLT-NEXT: 16a4: add r12, r12, #0, #20 // CHECK-ARM-PLT-NEXT: 16a8: ldr pc, [r12, #564]! diff --git a/lld/test/ELF/arm-thumb-plt-range-thunk-os.s b/lld/test/ELF/arm-thumb-plt-range-thunk-os.s index 65e7e4b525926..945cef6d4b4d5 100644 --- a/lld/test/ELF/arm-thumb-plt-range-thunk-os.s +++ b/lld/test/ELF/arm-thumb-plt-range-thunk-os.s @@ -96,14 +96,20 @@ far_nonpreemptible_alias: // CHECK4-NEXT: 4000024: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECK4-NEXT: 4000028: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECK4-NEXT: 400002c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK4-EMPTY: +// CHECK4-NEXT: : // CHECK4-NEXT: 4000030: e28fc600 add r12, pc, #0, #12 // CHECK4-NEXT: 4000034: e28cca20 add r12, r12, #32 // CHECK4-NEXT: 4000038: e5bcf08c ldr pc, [r12, #140]! // CHECK4-NEXT: 400003c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK4-EMPTY: +// CHECK4-NEXT: : // CHECK4-NEXT: 4000040: e28fc600 add r12, pc, #0, #12 // CHECK4-NEXT: 4000044: e28cca20 add r12, r12, #32 // CHECK4-NEXT: 4000048: e5bcf080 ldr pc, [r12, #128]! // CHECK4-NEXT: 400004c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK4-EMPTY: +// CHECK4-NEXT: : // CHECK4-NEXT: 4000050: e28fc600 add r12, pc, #0, #12 // CHECK4-NEXT: 4000054: e28cca20 add r12, r12, #32 // CHECK4-NEXT: 4000058: e5bcf074 ldr pc, [r12, #116]! diff --git a/lld/test/ELF/arm-thumb-plt-reloc.s b/lld/test/ELF/arm-thumb-plt-reloc.s index 4a1fd020452c9..9c4674779e3b9 100644 --- a/lld/test/ELF/arm-thumb-plt-reloc.s +++ b/lld/test/ELF/arm-thumb-plt-reloc.s @@ -83,16 +83,22 @@ _start: // DSO-NEXT: 10248: d4 d4 d4 d4 .word 0xd4d4d4d4 // DSO-NEXT: 1024c: d4 d4 d4 d4 .word 0xd4d4d4d4 // (0x10250 + 8) + (0 RoR 12) + (32 RoR 20 = 0x20000) + 140 = 0x302e4 +// DSO-EMPTY: +// DSO-NEXT: : // DSO-NEXT: 10250: e28fc600 add r12, pc, #0, #12 // DSO-NEXT: 10254: e28cca20 add r12, r12, #32, #20 // DSO-NEXT: 10258: e5bcf08c ldr pc, [r12, #140]! // DSO-NEXT: 1025c: d4 d4 d4 d4 .word 0xd4d4d4d4 // (0x10260 + 8) + (0 RoR 12) + (32 RoR 20 = 0x20000) + 128 = 0x302e8 +// DSO-EMPTY: +// DSO-NEXT: : // DSO-NEXT: 10260: e28fc600 add r12, pc, #0, #12 // DSO-NEXT: 10264: e28cca20 add r12, r12, #32, #20 // DSO-NEXT: 10268: e5bcf080 ldr pc, [r12, #128]! // DSO-NEXT: 1026c: d4 d4 d4 d4 .word 0xd4d4d4d4 // (0x10270 + 8) + (0 RoR 12) + (32 RoR 20 = 0x20000) + 116 = 0x302ec +// DSO-EMPTY: +// DSO-NEXT: : // DSO-NEXT: 10270: e28fc600 add r12, pc, #0, #12 // DSO-NEXT: 10274: e28cca20 add r12, r12, #32, #20 // DSO-NEXT: 10278: e5bcf074 ldr pc, [r12, #116]! diff --git a/lld/test/ELF/arm-thunk-multipass-plt.s b/lld/test/ELF/arm-thunk-multipass-plt.s index 2e8f054ce3f73..ecf69d58b510e 100644 --- a/lld/test/ELF/arm-thunk-multipass-plt.s +++ b/lld/test/ELF/arm-thunk-multipass-plt.s @@ -86,10 +86,14 @@ preemptible2: // CHECK-PLT-NEXT: d00034: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECK-PLT-NEXT: d00038: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECK-PLT-NEXT: d0003c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-PLT-EMPTY: +// CHECK-PLT-NEXT: : // CHECK-PLT-NEXT: d00040: add r12, pc, #0, #12 // CHECK-PLT-NEXT: d00044: add r12, r12, #32, #20 // CHECK-PLT-NEXT: d00048: ldr pc, [r12, #124]! // CHECK-PLT-NEXT: d0004c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-PLT-EMPTY: +// CHECK-PLT-NEXT: : // CHECK-PLT-NEXT: d00050: add r12, pc, #0, #12 // CHECK-PLT-NEXT: d00054: add r12, r12, #32, #20 // CHECK-PLT-NEXT: d00058: ldr pc, [r12, #112]! diff --git a/lld/test/ELF/arm-thunk-re-add.s b/lld/test/ELF/arm-thunk-re-add.s index 7505ec045fff0..1745237d38829 100644 --- a/lld/test/ELF/arm-thunk-re-add.s +++ b/lld/test/ELF/arm-thunk-re-add.s @@ -109,10 +109,14 @@ callers: // CHECK3-NEXT: 1100034: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECK3-NEXT: 1100038: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECK3-NEXT: 110003c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK3-EMPTY: +// CHECK3-NEXT: : // CHECK3-NEXT: 1100040: e28fc600 add r12, pc, #0, #12 // CHECK3-NEXT: 1100044: e28cca20 add r12, r12, #32 // CHECK3-NEXT: 1100048: e5bcf07c ldr pc, [r12, #124]! // CHECK3-NEXT: 110004c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK3-EMPTY: +// CHECK3-NEXT: : // CHECK3-NEXT: 1100050: e28fc600 add r12, pc, #0, #12 // CHECK3-NEXT: 1100054: e28cca20 add r12, r12, #32 // CHECK3-NEXT: 1100058: e5bcf070 ldr pc, [r12, #112]! diff --git a/lld/test/ELF/armv8-thumb-plt-reloc.s b/lld/test/ELF/armv8-thumb-plt-reloc.s index 5b6e4b5fdd139..df2b960684b93 100644 --- a/lld/test/ELF/armv8-thumb-plt-reloc.s +++ b/lld/test/ELF/armv8-thumb-plt-reloc.s @@ -101,18 +101,24 @@ _start: // DSO-NEXT: .word 0xd4d4d4d4 /// 136 + 2 << 16 + 0x1026c = 0x302f4 = got entry 1 +// DSO-EMPTY: +// DSO-NEXT: : // DSO-NEXT: 10260: f240 0c88 movw r12, #136 // DSO-NEXT: f2c0 0c02 movt r12, #2 // DSO-NEXT: 44fc add r12, pc // DSO-NEXT: f8dc f000 ldr.w pc, [r12] // DSO-NEXT: e7fc b 0x1026a /// 124 + 2 << 16 + 0x1027c = 0x302f8 = got entry 2 +// DSO-EMPTY: +// DSO-NEXT: : // DSO-NEXT: 10270: f240 0c7c movw r12, #124 // DSO-NEXT: f2c0 0c02 movt r12, #2 // DSO-NEXT: 44fc add r12, pc // DSO-NEXT: f8dc f000 ldr.w pc, [r12] // DSO-NEXT: e7fc b 0x1027a /// 112 + 2 << 16 + 0x1028c = 0x302fc = got entry 3 +// DSO-EMPTY: +// DSO-NEXT: : // DSO-NEXT: 10280: f240 0c70 movw r12, #112 // DSO-NEXT: f2c0 0c02 movt r12, #2 // DSO-NEXT: 44fc add r12, pc diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp index 21cb77e399a97..bf6d51919b5ca 100644 --- a/llvm/lib/Object/ELFObjectFile.cpp +++ b/llvm/lib/Object/ELFObjectFile.cpp @@ -799,6 +799,12 @@ ELFObjectFileBase::getPltEntries(const MCSubtargetInfo &STI) const { case Triple::aarch64_be: JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT; break; + case Triple::arm: + case Triple::armeb: + case Triple::thumb: + case Triple::thumbeb: + JumpSlotReloc = ELF::R_ARM_JUMP_SLOT; + break; case Triple::hexagon: JumpSlotReloc = ELF::R_HEX_JMP_SLOT; GlobDatReloc = ELF::R_HEX_GLOB_DAT; diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp index e1af3150a8403..51f71bbdd7329 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp @@ -392,6 +392,18 @@ static MCRelocationInfo *createARMMCRelocationInfo(const Triple &TT, return llvm::createMCRelocationInfo(TT, Ctx); } +template +static bool instructionsMatch(const T (&Insns)[N], const uint8_t *Buf, + llvm::endianness E) { + for (size_t I = 0; I < N; ++I) { + T Val = support::endian::read(Buf + I * sizeof(T), E); + if (Val != Insns[I]) { + return false; + } + } + return true; +} + namespace { class ARMMCInstrAnalysis : public MCInstrAnalysis { @@ -431,6 +443,126 @@ class ARMMCInstrAnalysis : public MCInstrAnalysis { std::optional evaluateMemoryOperandAddress(const MCInst &Inst, const MCSubtargetInfo *STI, uint64_t Addr, uint64_t Size) const override; + + std::vector> + findPltEntries(uint64_t PltSectionVA, ArrayRef PltContents, + const MCSubtargetInfo &STI) const override { + llvm::endianness DataEndianness = STI.getTargetTriple().isLittleEndian() + ? endianness::little + : endianness::big; + llvm::endianness InstrEndianness = + STI.checkFeatures("+big-endian-instructions") ? endianness::big + : endianness::little; + + // Do a lightweight parsing of PLT entries. + std::vector> Result; + if (STI.checkFeatures("+thumb-mode")) { + for (uint64_t Byte = 0, End = PltContents.size(); Byte + 12 < End; + Byte += 16) { + // Expected instruction sequence: + // + // movw ip, #lower16 + // movt ip, #upper16 + // add ip, pc + // ldr.w pc, [ip] + // b . -4 + + uint32_t MovwPart1 = + support::endian::read16(PltContents.data() + Byte, InstrEndianness); + if ((MovwPart1 & 0xffb0) != 0xf200) + continue; + + uint32_t MovwPart2 = support::endian::read16( + PltContents.data() + Byte + 2, InstrEndianness); + if ((MovwPart2 & 0x8f00) != 0xc00) + continue; + + uint64_t OffsetLower = + (MovwPart2 & 0xff) + ((MovwPart2 & 0x7000) >> 4) + + ((MovwPart1 & 0x400) << 1) + ((MovwPart1 & 0xf) << 12); + + uint32_t MovtPart1 = support::endian::read16( + PltContents.data() + Byte + 4, InstrEndianness); + if ((MovtPart1 & 0xfbf0) != 0xf2c0) + continue; + + uint32_t MovtPart2 = support::endian::read16( + PltContents.data() + Byte + 6, InstrEndianness); + if ((MovtPart2 & 0x8f00) != 0xc00) + continue; + + uint64_t OffsetHigher = + ((MovtPart2 & 0xff) << 16) + ((MovtPart2 & 0x7000) << 12) + + ((MovtPart1 & 0x400) << 17) + ((MovtPart1 & 0xf) << 28); + + const uint16_t Insns[] = { + 0x44fc, // add ip, pc + 0xf8dc, 0xf000, // ldr.w pc, [ip] + 0xe7fc, // b . -4 + }; + + if (instructionsMatch(Insns, PltContents.data() + Byte + 8, + InstrEndianness)) { + // add ip, pc at Byte + 8 + thumb-pc-bias = 12 + uint64_t Offset = + (PltSectionVA + Byte + 12) + OffsetLower + OffsetHigher; + Result.emplace_back(PltSectionVA + Byte, Offset); + } + } + } else { + const uint32_t LongEntryInsns[] = { + 0xe59fc004, // ldr ip, L2 + 0xe08cc00f, // L1: add ip, ip, pc + 0xe59cf000, // ldr pc, [ip] + }; + + for (uint64_t Byte = 0, End = PltContents.size(); Byte + 12 < End; + Byte += 4) { + // Is it a long entry? + if (instructionsMatch(LongEntryInsns, PltContents.data() + Byte, + InstrEndianness)) { + // Expected instruction sequence: + // + // ldr ip, L2 + // L1: add ip, ip, pc + // ldr pc, [ip] + // L2: .word Offset(&(.got.plt) - L1 - 8 + + uint64_t Offset = (PltSectionVA + Byte + 12) + + support::endian::read32( + PltContents.data() + Byte + 12, DataEndianness); + Result.emplace_back(PltSectionVA + Byte, Offset); + Byte += 12; + } else { + // Expected instruction sequence: + // + // L1: add ip, pc, #0x0NN00000 Offset(&(.got.plt) - L1 - 8 + // add ip, ip, #0x000NN000 Offset(&(.got.plt) - L1 - 8 + // ldr pc, [ip, #0x00000NNN] Offset(&(.got.plt) - L1 - 8 + + uint32_t Add1 = support::endian::read32(PltContents.data() + Byte, + InstrEndianness); + if ((Add1 & 0xe28fc600) != 0xe28fc600) + continue; + uint32_t Add2 = support::endian::read32(PltContents.data() + Byte + 4, + InstrEndianness); + if ((Add2 & 0xe28cca00) != 0xe28cca00) + continue; + uint32_t Ldr = support::endian::read32(PltContents.data() + Byte + 8, + InstrEndianness); + if ((Ldr & 0xe5bcf000) != 0xe5bcf000) + continue; + + // add ip, pc, #offset at Byte + 0 + arm-pc-bias = 8 + uint64_t Offset = (PltSectionVA + Byte + 8) + ((Add1 & 0xff) << 20) + + ((Add2 & 0xff) << 12) + (Ldr & 0xfff); + Result.emplace_back(PltSectionVA + Byte, Offset); + Byte += 8; + } + } + } + return Result; + } }; } // namespace diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index beed2ddcd981d..c8803965e31c0 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -1233,12 +1233,7 @@ addMissingWasmCodeSymbols(const WasmObjectFile &Obj, } } -static void addPltEntries(const MCSubtargetInfo &STI, const ObjectFile &Obj, - std::map &AllSymbols, - StringSaver &Saver) { - auto *ElfObj = dyn_cast(&Obj); - if (!ElfObj) - return; +DenseMap getSectionNames(const ObjectFile &Obj) { DenseMap Sections; for (SectionRef Section : Obj.sections()) { Expected SecNameOrErr = Section.getName(); @@ -1248,13 +1243,23 @@ static void addPltEntries(const MCSubtargetInfo &STI, const ObjectFile &Obj, } Sections[*SecNameOrErr] = Section; } + return Sections; +} + +static void addPltEntries(const MCSubtargetInfo &STI, const ObjectFile &Obj, + DenseMap &SectionNames, + std::map &AllSymbols, + StringSaver &Saver) { + auto *ElfObj = dyn_cast(&Obj); + if (!ElfObj) + return; for (auto Plt : ElfObj->getPltEntries(STI)) { if (Plt.Symbol) { SymbolRef Symbol(*Plt.Symbol, ElfObj); uint8_t SymbolType = getElfSymbolType(Obj, Symbol); if (Expected NameOrErr = Symbol.getName()) { if (!NameOrErr->empty()) - AllSymbols[Sections[Plt.Section]].emplace_back( + AllSymbols[SectionNames[Plt.Section]].emplace_back( Plt.Address, Saver.save((*NameOrErr + "@plt").str()), SymbolType); continue; } else { @@ -1770,9 +1775,34 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj, if (Obj.isELF() && Obj.sections().empty()) createFakeELFSections(Obj); + DisassemblerTarget *PltTarget = DT; + auto SectionNames = getSectionNames(Obj); + if (SecondaryTarget && isArmElf(Obj)) { + auto PltSectionRef = SectionNames.find(".plt"); + if (PltSectionRef != SectionNames.end()) { + bool PltIsThumb = false; + for (auto [Addr, SymbolName] : AllMappingSymbols[PltSectionRef->second]) { + if (Addr == 0) { + if (SymbolName == 't') { + PltIsThumb = true; + break; + } + if (SymbolName == 'a') { + break; + } + } + } + + if (PrimaryTarget.SubtargetInfo->checkFeatures("+thumb-mode")) + PltTarget = PltIsThumb ? &PrimaryTarget : &*SecondaryTarget; + else + PltTarget = PltIsThumb ? &*SecondaryTarget : &PrimaryTarget; + } + } BumpPtrAllocator A; StringSaver Saver(A); - addPltEntries(*DT->SubtargetInfo, Obj, AllSymbols, Saver); + addPltEntries(*PltTarget->SubtargetInfo, Obj, SectionNames, AllSymbols, + Saver); // Create a mapping from virtual address to section. An empty section can // cause more than one section at the same address. Sort such sections to be From 30a96bf4c9077210482c73183a3cda81a65a6631 Mon Sep 17 00:00:00 2001 From: Vladislav Dzhidzhoev Date: Mon, 17 Mar 2025 13:56:38 +0100 Subject: [PATCH 2/8] Addressed @MaskRay comments --- .../tools/llvm-objdump/ARM/plt.c | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/cross-project-tests/tools/llvm-objdump/ARM/plt.c b/cross-project-tests/tools/llvm-objdump/ARM/plt.c index 4bcf8536492c9..4f7e75904dafd 100644 --- a/cross-project-tests/tools/llvm-objdump/ARM/plt.c +++ b/cross-project-tests/tools/llvm-objdump/ARM/plt.c @@ -1,13 +1,13 @@ // Test PLT section parsing on arm. -// RUN: %clang -target armv6a-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: %clang --target=armv6a-none-linux-gnueabi -fuse-ld=lld \ // RUN: -nostdlib -nostdinc -shared %s -o %t1 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ // RUN: -d %t1 | FileCheck %s --check-prefixes=CHECK,LE // Test PLT section parsing on armeb. -// RUN: %clang -target armv6aeb-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: %clang --target=armv6aeb-none-linux-gnueabi -fuse-ld=lld \ // RUN: -nostdlib -nostdinc -shared %s -o %t2 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ // RUN: -d %t2 | FileCheck %s --check-prefixes=CHECK,BE @@ -15,7 +15,7 @@ // Test PLT section parsing on armeb with be8. -// RUN: %clang -target armv7aeb-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: %clang --target=armv7aeb-none-linux-gnueabi -fuse-ld=lld \ // RUN: -nostdlib -nostdinc -shared %s -o %t3 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ // RUN: -d %t3 | FileCheck %s --check-prefixes=CHECK,BE @@ -31,24 +31,24 @@ // CHECK-NEXT: <_start>: // CHECK-NEXT: push {r11, lr} // CHECK-NEXT: mov r11, sp -// CHECK-NEXT: bl 0x10240 -// CHECK-NEXT: bl 0x10250 -// CHECK-NEXT: bl 0x10260 +// CHECK-NEXT: bl {{.*}} +// CHECK-NEXT: bl {{.*}} +// CHECK-NEXT: bl {{.*}} // CHECK: Disassembly of section .plt: -// CHECK: 00010240 : +// CHECK: : // CHECK-NEXT: add r12, pc, #0, #12 // CHECK-NEXT: add r12, r12, #32, #20 // CHECK-NEXT: ldr pc, [r12, #132]! // CHECK-NEXT: .word 0xd4d4d4d4 // CHECK-EMPTY: -// CHECK-NEXT: 00010250 : +// CHECK-NEXT: : // CHECK-NEXT: add r12, pc, #0, #12 // CHECK-NEXT: add r12, r12, #32, #20 // CHECK-NEXT: ldr pc, [r12, #120]! // CHECK-NEXT: .word 0xd4d4d4d4 // CHECK-EMPTY: -// CHECK-NEXT: 00010260 : +// CHECK-NEXT: : // CHECK-NEXT: add r12, pc, #0, #12 // CHECK-NEXT: add r12, r12, #32, #20 // CHECK-NEXT: ldr pc, [r12, #108]! @@ -56,7 +56,7 @@ // Test PLT section parsing on thumb. -// RUN: %clang -target thumbv8.1m.main-none-linux-eabi \ +// RUN: %clang --target=thumbv8.1m.main-none-linux-eabi \ // RUN: -nostdlib -nostdinc -c %s -o %t4.o // RUN: ld.lld --shared %t4.o -o %t4 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ @@ -64,7 +64,7 @@ // Test PLT section parsing on thumbeb. -// RUN: %clang -target thumbebv8.1m.main-none-linux-eabi \ +// RUN: %clang --target=thumbebv8.1m.main-none-linux-eabi \ // RUN: -nostdlib -nostdinc -c %s -o %t5.o // RUN: ld.lld --shared %t5.o -o %t5 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ @@ -73,7 +73,7 @@ // Test PLT section parsing on thumbeb with be8. -// RUN: %clang -target thumbebv8.1m.main-none-linux-eabi \ +// RUN: %clang --target=thumbebv8.1m.main-none-linux-eabi \ // RUN: -nostdlib -nostdinc -c %s -o %t6.o // RUN: ld.lld --shared --be8 %t6.o -o %t6 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ @@ -85,32 +85,32 @@ // THUMB-NEXT: <_start>: // THUMB-NEXT: push {r7, lr} // THUMB-NEXT: mov r7, sp -// THUMB-NEXT: bl 0x10270 -// THUMB-NEXT: bl 0x10280 -// THUMB-NEXT: bl 0x10290 +// THUMB-NEXT: bl {{.*}} +// THUMB-NEXT: bl {{.*}} +// THUMB-NEXT: bl {{.*}} // THUMB: Disassembly of section .plt: // THUMB-EMPTY: -// THUMB: 00010270 : +// THUMB: : // THUMB-NEXT: movw r12, #136 // THUMB-NEXT: movt r12, #2 // THUMB-NEXT: add r12, pc // THUMB-NEXT: ldr.w pc, [r12] -// THUMB-NEXT: b 0x1027a +// THUMB-NEXT: b 0x // THUMB-EMPTY: -// THUMB-NEXT: 00010280 : +// THUMB-NEXT: : // THUMB-NEXT: movw r12, #124 // THUMB-NEXT: movt r12, #2 // THUMB-NEXT: add r12, pc // THUMB-NEXT: ldr.w pc, [r12] -// THUMB-NEXT: b 0x1028a +// THUMB-NEXT: b 0x // THUMB-EMPTY: -// THUMB-NEXT: 00010290 : +// THUMB-NEXT: : // THUMB-NEXT: movw r12, #112 // THUMB-NEXT: movt r12, #2 // THUMB-NEXT: add r12, pc // THUMB-NEXT: ldr.w pc, [r12] -// THUMB-NEXT: b 0x1029a +// THUMB-NEXT: b 0x // Test PLT section with long entries parsing on arm. @@ -120,7 +120,7 @@ // RUN: .got.plt 0x9000000 : { *(.got.plt) } \ // RUN: }" > %t.long.script -// RUN: %clang -target armv6a-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: %clang --target=armv6a-none-linux-gnueabi -fuse-ld=lld \ // RUN: -Xlinker --script=%t.long.script -nostdlib -nostdinc \ // RUN: -shared %s -o %t7 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ @@ -128,7 +128,7 @@ // Test PLT section with long entries parsing on armeb. -// RUN: %clang -target armv6aeb-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: %clang --target=armv6aeb-none-linux-gnueabi -fuse-ld=lld \ // RUN: -Xlinker --script=%t.long.script -nostdlib -nostdinc \ // RUN: -shared %s -o %t8 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ @@ -137,7 +137,7 @@ // Test PLT section with long entries parsing on armeb with be8. -// RUN: %clang -target armv7aeb-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: %clang --target=armv7aeb-none-linux-gnueabi -fuse-ld=lld \ // RUN: -Xlinker --script=%t.long.script -nostdlib -nostdinc \ // RUN: -shared %s -o %t9 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ @@ -180,7 +180,7 @@ // RUN: .got.plt 0x8002020 : { *(.got.plt) } \ // RUN: }" > %t.mix.script -// RUN: %clang -target armv6a-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: %clang --target=armv6a-none-linux-gnueabi -fuse-ld=lld \ // RUN: -Xlinker --script=%t.mix.script -nostdlib -nostdinc \ // RUN: -shared %s -o %t10 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ @@ -188,7 +188,7 @@ // Test PLT section with mixed long and short entries parsing on armeb. -// RUN: %clang -target armv6aeb-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: %clang --target=armv6aeb-none-linux-gnueabi -fuse-ld=lld \ // RUN: -Xlinker --script=%t.mix.script -nostdlib -nostdinc \ // RUN: -shared %s -o %t11 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ @@ -197,7 +197,7 @@ // Test PLT section with mixed long and short entries parsing on armeb with be8. -// RUN: %clang -target armv7aeb-none-linux-gnueabi -fuse-ld=ld.lld \ +// RUN: %clang --target=armv7aeb-none-linux-gnueabi -fuse-ld=lld \ // RUN: -Xlinker --script=%t.mix.script -nostdlib -nostdinc \ // RUN: -shared %s -o %t12 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ From def15be6aa7fc24669ead13f963c18b639ddb180 Mon Sep 17 00:00:00 2001 From: Vladislav Dzhidzhoev Date: Tue, 18 Mar 2025 10:13:41 +0100 Subject: [PATCH 3/8] Addressed @MaskRay comments --- .../ARM/MCTargetDesc/ARMMCTargetDesc.cpp | 242 +++++++++--------- llvm/tools/llvm-objdump/llvm-objdump.cpp | 18 +- 2 files changed, 132 insertions(+), 128 deletions(-) diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp index 51f71bbdd7329..67a347dc38d60 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp @@ -397,9 +397,8 @@ static bool instructionsMatch(const T (&Insns)[N], const uint8_t *Buf, llvm::endianness E) { for (size_t I = 0; I < N; ++I) { T Val = support::endian::read(Buf + I * sizeof(T), E); - if (Val != Insns[I]) { + if (Val != Insns[I]) return false; - } } return true; } @@ -446,123 +445,7 @@ class ARMMCInstrAnalysis : public MCInstrAnalysis { std::vector> findPltEntries(uint64_t PltSectionVA, ArrayRef PltContents, - const MCSubtargetInfo &STI) const override { - llvm::endianness DataEndianness = STI.getTargetTriple().isLittleEndian() - ? endianness::little - : endianness::big; - llvm::endianness InstrEndianness = - STI.checkFeatures("+big-endian-instructions") ? endianness::big - : endianness::little; - - // Do a lightweight parsing of PLT entries. - std::vector> Result; - if (STI.checkFeatures("+thumb-mode")) { - for (uint64_t Byte = 0, End = PltContents.size(); Byte + 12 < End; - Byte += 16) { - // Expected instruction sequence: - // - // movw ip, #lower16 - // movt ip, #upper16 - // add ip, pc - // ldr.w pc, [ip] - // b . -4 - - uint32_t MovwPart1 = - support::endian::read16(PltContents.data() + Byte, InstrEndianness); - if ((MovwPart1 & 0xffb0) != 0xf200) - continue; - - uint32_t MovwPart2 = support::endian::read16( - PltContents.data() + Byte + 2, InstrEndianness); - if ((MovwPart2 & 0x8f00) != 0xc00) - continue; - - uint64_t OffsetLower = - (MovwPart2 & 0xff) + ((MovwPart2 & 0x7000) >> 4) + - ((MovwPart1 & 0x400) << 1) + ((MovwPart1 & 0xf) << 12); - - uint32_t MovtPart1 = support::endian::read16( - PltContents.data() + Byte + 4, InstrEndianness); - if ((MovtPart1 & 0xfbf0) != 0xf2c0) - continue; - - uint32_t MovtPart2 = support::endian::read16( - PltContents.data() + Byte + 6, InstrEndianness); - if ((MovtPart2 & 0x8f00) != 0xc00) - continue; - - uint64_t OffsetHigher = - ((MovtPart2 & 0xff) << 16) + ((MovtPart2 & 0x7000) << 12) + - ((MovtPart1 & 0x400) << 17) + ((MovtPart1 & 0xf) << 28); - - const uint16_t Insns[] = { - 0x44fc, // add ip, pc - 0xf8dc, 0xf000, // ldr.w pc, [ip] - 0xe7fc, // b . -4 - }; - - if (instructionsMatch(Insns, PltContents.data() + Byte + 8, - InstrEndianness)) { - // add ip, pc at Byte + 8 + thumb-pc-bias = 12 - uint64_t Offset = - (PltSectionVA + Byte + 12) + OffsetLower + OffsetHigher; - Result.emplace_back(PltSectionVA + Byte, Offset); - } - } - } else { - const uint32_t LongEntryInsns[] = { - 0xe59fc004, // ldr ip, L2 - 0xe08cc00f, // L1: add ip, ip, pc - 0xe59cf000, // ldr pc, [ip] - }; - - for (uint64_t Byte = 0, End = PltContents.size(); Byte + 12 < End; - Byte += 4) { - // Is it a long entry? - if (instructionsMatch(LongEntryInsns, PltContents.data() + Byte, - InstrEndianness)) { - // Expected instruction sequence: - // - // ldr ip, L2 - // L1: add ip, ip, pc - // ldr pc, [ip] - // L2: .word Offset(&(.got.plt) - L1 - 8 - - uint64_t Offset = (PltSectionVA + Byte + 12) + - support::endian::read32( - PltContents.data() + Byte + 12, DataEndianness); - Result.emplace_back(PltSectionVA + Byte, Offset); - Byte += 12; - } else { - // Expected instruction sequence: - // - // L1: add ip, pc, #0x0NN00000 Offset(&(.got.plt) - L1 - 8 - // add ip, ip, #0x000NN000 Offset(&(.got.plt) - L1 - 8 - // ldr pc, [ip, #0x00000NNN] Offset(&(.got.plt) - L1 - 8 - - uint32_t Add1 = support::endian::read32(PltContents.data() + Byte, - InstrEndianness); - if ((Add1 & 0xe28fc600) != 0xe28fc600) - continue; - uint32_t Add2 = support::endian::read32(PltContents.data() + Byte + 4, - InstrEndianness); - if ((Add2 & 0xe28cca00) != 0xe28cca00) - continue; - uint32_t Ldr = support::endian::read32(PltContents.data() + Byte + 8, - InstrEndianness); - if ((Ldr & 0xe5bcf000) != 0xe5bcf000) - continue; - - // add ip, pc, #offset at Byte + 0 + arm-pc-bias = 8 - uint64_t Offset = (PltSectionVA + Byte + 8) + ((Add1 & 0xff) << 20) + - ((Add2 & 0xff) << 12) + (Ldr & 0xfff); - Result.emplace_back(PltSectionVA + Byte, Offset); - Byte += 8; - } - } - } - return Result; - } + const MCSubtargetInfo &STI) const override; }; } // namespace @@ -753,6 +636,127 @@ std::optional ARMMCInstrAnalysis::evaluateMemoryOperandAddress( } } +std::vector> +ARMMCInstrAnalysis::findPltEntries(uint64_t PltSectionVA, + ArrayRef PltContents, + const MCSubtargetInfo &STI) const { + llvm::endianness DataEndianness = STI.getTargetTriple().isLittleEndian() + ? endianness::little + : endianness::big; + llvm::endianness InstrEndianness = + STI.checkFeatures("+big-endian-instructions") ? endianness::big + : endianness::little; + + // Do a lightweight parsing of PLT entries. + std::vector> Result; + if (STI.checkFeatures("+thumb-mode")) { + for (uint64_t Byte = 0, End = PltContents.size(); Byte + 12 < End; + Byte += 16) { + // Expected instruction sequence: + // + // movw ip, #lower16 + // movt ip, #upper16 + // add ip, pc + // ldr.w pc, [ip] + // b . -4 + + uint32_t MovwPart1 = + support::endian::read16(PltContents.data() + Byte, InstrEndianness); + if ((MovwPart1 & 0xffb0) != 0xf200) + continue; + + uint32_t MovwPart2 = support::endian::read16( + PltContents.data() + Byte + 2, InstrEndianness); + if ((MovwPart2 & 0x8f00) != 0xc00) + continue; + + uint64_t OffsetLower = (MovwPart2 & 0xff) + ((MovwPart2 & 0x7000) >> 4) + + ((MovwPart1 & 0x400) << 1) + + ((MovwPart1 & 0xf) << 12); + + uint32_t MovtPart1 = support::endian::read16( + PltContents.data() + Byte + 4, InstrEndianness); + if ((MovtPart1 & 0xfbf0) != 0xf2c0) + continue; + + uint32_t MovtPart2 = support::endian::read16( + PltContents.data() + Byte + 6, InstrEndianness); + if ((MovtPart2 & 0x8f00) != 0xc00) + continue; + + uint64_t OffsetHigher = + ((MovtPart2 & 0xff) << 16) + ((MovtPart2 & 0x7000) << 12) + + ((MovtPart1 & 0x400) << 17) + ((MovtPart1 & 0xf) << 28); + + const uint16_t Insns[] = { + 0x44fc, // add ip, pc + 0xf8dc, 0xf000, // ldr.w pc, [ip] + 0xe7fc, // b . -4 + }; + + if (instructionsMatch(Insns, PltContents.data() + Byte + 8, + InstrEndianness)) { + // add ip, pc at Byte + 8 + thumb-pc-bias = 12 + uint64_t Offset = + (PltSectionVA + Byte + 12) + OffsetLower + OffsetHigher; + Result.emplace_back(PltSectionVA + Byte, Offset); + } + } + } else { + const uint32_t LongEntryInsns[] = { + 0xe59fc004, // ldr ip, L2 + 0xe08cc00f, // L1: add ip, ip, pc + 0xe59cf000, // ldr pc, [ip] + }; + + for (uint64_t Byte = 0, End = PltContents.size(); Byte + 12 < End; + Byte += 4) { + // Is it a long entry? + if (instructionsMatch(LongEntryInsns, PltContents.data() + Byte, + InstrEndianness)) { + // Expected instruction sequence: + // + // ldr ip, L2 + // L1: add ip, ip, pc + // ldr pc, [ip] + // L2: .word Offset(&(.got.plt) - L1 - 8 + + uint64_t Offset = (PltSectionVA + Byte + 12) + + support::endian::read32( + PltContents.data() + Byte + 12, DataEndianness); + Result.emplace_back(PltSectionVA + Byte, Offset); + Byte += 12; + } else { + // Expected instruction sequence: + // + // L1: add ip, pc, #0x0NN00000 Offset(&(.got.plt) - L1 - 8 + // add ip, ip, #0x000NN000 Offset(&(.got.plt) - L1 - 8 + // ldr pc, [ip, #0x00000NNN] Offset(&(.got.plt) - L1 - 8 + + uint32_t Add1 = + support::endian::read32(PltContents.data() + Byte, InstrEndianness); + if ((Add1 & 0xe28fc600) != 0xe28fc600) + continue; + uint32_t Add2 = support::endian::read32(PltContents.data() + Byte + 4, + InstrEndianness); + if ((Add2 & 0xe28cca00) != 0xe28cca00) + continue; + uint32_t Ldr = support::endian::read32(PltContents.data() + Byte + 8, + InstrEndianness); + if ((Ldr & 0xe5bcf000) != 0xe5bcf000) + continue; + + // add ip, pc, #offset at Byte + 0 + arm-pc-bias = 8 + uint64_t Offset = (PltSectionVA + Byte + 8) + ((Add1 & 0xff) << 20) + + ((Add2 & 0xff) << 12) + (Ldr & 0xfff); + Result.emplace_back(PltSectionVA + Byte, Offset); + Byte += 8; + } + } + } + return Result; +} + static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) { return new ARMMCInstrAnalysis(Info); } diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index c8803965e31c0..8491d4244e364 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -1233,7 +1233,7 @@ addMissingWasmCodeSymbols(const WasmObjectFile &Obj, } } -DenseMap getSectionNames(const ObjectFile &Obj) { +static DenseMap getSectionNames(const ObjectFile &Obj) { DenseMap Sections; for (SectionRef Section : Obj.sections()) { Expected SecNameOrErr = Section.getName(); @@ -1782,15 +1782,15 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj, if (PltSectionRef != SectionNames.end()) { bool PltIsThumb = false; for (auto [Addr, SymbolName] : AllMappingSymbols[PltSectionRef->second]) { - if (Addr == 0) { - if (SymbolName == 't') { - PltIsThumb = true; - break; - } - if (SymbolName == 'a') { - break; - } + if (Addr != 0) + continue; + + if (SymbolName == 't') { + PltIsThumb = true; + break; } + if (SymbolName == 'a') + break; } if (PrimaryTarget.SubtargetInfo->checkFeatures("+thumb-mode")) From f8563f9b342d812032cba2f28dead7efbc0cb668 Mon Sep 17 00:00:00 2001 From: Vladislav Dzhidzhoev Date: Tue, 18 Mar 2025 14:33:54 +0100 Subject: [PATCH 4/8] Move instructionsMatch closer to it's caller --- .../ARM/MCTargetDesc/ARMMCTargetDesc.cpp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp index 67a347dc38d60..43ee66ff43fe6 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp @@ -392,17 +392,6 @@ static MCRelocationInfo *createARMMCRelocationInfo(const Triple &TT, return llvm::createMCRelocationInfo(TT, Ctx); } -template -static bool instructionsMatch(const T (&Insns)[N], const uint8_t *Buf, - llvm::endianness E) { - for (size_t I = 0; I < N; ++I) { - T Val = support::endian::read(Buf + I * sizeof(T), E); - if (Val != Insns[I]) - return false; - } - return true; -} - namespace { class ARMMCInstrAnalysis : public MCInstrAnalysis { @@ -636,6 +625,17 @@ std::optional ARMMCInstrAnalysis::evaluateMemoryOperandAddress( } } +template +static bool instructionsMatch(const T (&Insns)[N], const uint8_t *Buf, + llvm::endianness E) { + for (size_t I = 0; I < N; ++I) { + T Val = support::endian::read(Buf + I * sizeof(T), E); + if (Val != Insns[I]) + return false; + } + return true; +} + std::vector> ARMMCInstrAnalysis::findPltEntries(uint64_t PltSectionVA, ArrayRef PltContents, From 52f97da96ac1f828f0eceac758a7971c1ce23e6f Mon Sep 17 00:00:00 2001 From: Vladislav Dzhidzhoev Date: Tue, 18 Mar 2025 14:53:41 +0100 Subject: [PATCH 5/8] Early exit --- .../Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp index 43ee66ff43fe6..c756bff3b501a 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp @@ -694,13 +694,13 @@ ARMMCInstrAnalysis::findPltEntries(uint64_t PltSectionVA, 0xe7fc, // b . -4 }; - if (instructionsMatch(Insns, PltContents.data() + Byte + 8, - InstrEndianness)) { - // add ip, pc at Byte + 8 + thumb-pc-bias = 12 - uint64_t Offset = - (PltSectionVA + Byte + 12) + OffsetLower + OffsetHigher; - Result.emplace_back(PltSectionVA + Byte, Offset); - } + if (!instructionsMatch(Insns, PltContents.data() + Byte + 8, + InstrEndianness)) + continue; + + // add ip, pc at Byte + 8 + thumb-pc-bias = 12 + uint64_t Offset = (PltSectionVA + Byte + 12) + OffsetLower + OffsetHigher; + Result.emplace_back(PltSectionVA + Byte, Offset); } } else { const uint32_t LongEntryInsns[] = { From 195284d73e2d43f3e8fe4662fe8b5e5b749a321d Mon Sep 17 00:00:00 2001 From: Vladislav Dzhidzhoev Date: Wed, 26 Mar 2025 17:04:38 +0100 Subject: [PATCH 6/8] Don't run cross project test if configuration is unsupported --- cross-project-tests/tools/llvm-objdump/ARM/lit.local.cfg | 2 ++ cross-project-tests/tools/llvm-objdump/ARM/plt.c | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 cross-project-tests/tools/llvm-objdump/ARM/lit.local.cfg diff --git a/cross-project-tests/tools/llvm-objdump/ARM/lit.local.cfg b/cross-project-tests/tools/llvm-objdump/ARM/lit.local.cfg new file mode 100644 index 0000000000000..b75c427fd8a64 --- /dev/null +++ b/cross-project-tests/tools/llvm-objdump/ARM/lit.local.cfg @@ -0,0 +1,2 @@ +if "ARM" not in config.targets_to_build: + config.unsupported = True diff --git a/cross-project-tests/tools/llvm-objdump/ARM/plt.c b/cross-project-tests/tools/llvm-objdump/ARM/plt.c index 4f7e75904dafd..03f3ce0f7c5ac 100644 --- a/cross-project-tests/tools/llvm-objdump/ARM/plt.c +++ b/cross-project-tests/tools/llvm-objdump/ARM/plt.c @@ -1,5 +1,7 @@ // Test PLT section parsing on arm. +// REQUIRES: ld.lld + // RUN: %clang --target=armv6a-none-linux-gnueabi -fuse-ld=lld \ // RUN: -nostdlib -nostdinc -shared %s -o %t1 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ From 5e249ee5b84c90996c328c5e5785affb47e201e3 Mon Sep 17 00:00:00 2001 From: Vladislav Dzhidzhoev Date: Wed, 26 Mar 2025 17:22:01 +0100 Subject: [PATCH 7/8] Remove unused flags --- cross-project-tests/tools/llvm-objdump/ARM/plt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cross-project-tests/tools/llvm-objdump/ARM/plt.c b/cross-project-tests/tools/llvm-objdump/ARM/plt.c index 03f3ce0f7c5ac..81e7f810bb29e 100644 --- a/cross-project-tests/tools/llvm-objdump/ARM/plt.c +++ b/cross-project-tests/tools/llvm-objdump/ARM/plt.c @@ -59,7 +59,7 @@ // Test PLT section parsing on thumb. // RUN: %clang --target=thumbv8.1m.main-none-linux-eabi \ -// RUN: -nostdlib -nostdinc -c %s -o %t4.o +// RUN: -c %s -o %t4.o // RUN: ld.lld --shared %t4.o -o %t4 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ // RUN: -d %t4 | FileCheck %s --check-prefixes=THUMB,LE @@ -67,7 +67,7 @@ // Test PLT section parsing on thumbeb. // RUN: %clang --target=thumbebv8.1m.main-none-linux-eabi \ -// RUN: -nostdlib -nostdinc -c %s -o %t5.o +// RUN: -c %s -o %t5.o // RUN: ld.lld --shared %t5.o -o %t5 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ // RUN: -d %t5 | FileCheck %s --check-prefixes=THUMB,BE @@ -76,7 +76,7 @@ // Test PLT section parsing on thumbeb with be8. // RUN: %clang --target=thumbebv8.1m.main-none-linux-eabi \ -// RUN: -nostdlib -nostdinc -c %s -o %t6.o +// RUN: -c %s -o %t6.o // RUN: ld.lld --shared --be8 %t6.o -o %t6 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ // RUN: -d %t6 | FileCheck %s --check-prefixes=THUMB,BE From 51fba01f3535a16604d3374c11f0efb55d33e038 Mon Sep 17 00:00:00 2001 From: Vladislav Dzhidzhoev Date: Wed, 26 Mar 2025 17:22:23 +0100 Subject: [PATCH 8/8] Rename test variables --- .../tools/llvm-objdump/ARM/plt.c | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/cross-project-tests/tools/llvm-objdump/ARM/plt.c b/cross-project-tests/tools/llvm-objdump/ARM/plt.c index 81e7f810bb29e..6f4b668cc01a3 100644 --- a/cross-project-tests/tools/llvm-objdump/ARM/plt.c +++ b/cross-project-tests/tools/llvm-objdump/ARM/plt.c @@ -3,25 +3,25 @@ // REQUIRES: ld.lld // RUN: %clang --target=armv6a-none-linux-gnueabi -fuse-ld=lld \ -// RUN: -nostdlib -nostdinc -shared %s -o %t1 +// RUN: -nostdlib -nostdinc -shared %s -o %t.v6a // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ -// RUN: -d %t1 | FileCheck %s --check-prefixes=CHECK,LE +// RUN: -d %t.v6a | FileCheck %s --check-prefixes=CHECK,LE // Test PLT section parsing on armeb. // RUN: %clang --target=armv6aeb-none-linux-gnueabi -fuse-ld=lld \ -// RUN: -nostdlib -nostdinc -shared %s -o %t2 +// RUN: -nostdlib -nostdinc -shared %s -o %t.v6aeb // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ -// RUN: -d %t2 | FileCheck %s --check-prefixes=CHECK,BE -// RUN: obj2yaml %t2 | FileCheck %s --check-prefixes=NOBE8 +// RUN: -d %t.v6aeb | FileCheck %s --check-prefixes=CHECK,BE +// RUN: obj2yaml %t.v6aeb | FileCheck %s --check-prefixes=NOBE8 // Test PLT section parsing on armeb with be8. // RUN: %clang --target=armv7aeb-none-linux-gnueabi -fuse-ld=lld \ -// RUN: -nostdlib -nostdinc -shared %s -o %t3 +// RUN: -nostdlib -nostdinc -shared %s -o %t.v7aeb // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ -// RUN: -d %t3 | FileCheck %s --check-prefixes=CHECK,BE -// RUN: obj2yaml %t3 | FileCheck %s --check-prefixes=BE8 +// RUN: -d %t.v7aeb | FileCheck %s --check-prefixes=CHECK,BE +// RUN: obj2yaml %t.v7aeb | FileCheck %s --check-prefixes=BE8 // LE: file format elf32-littlearm // BE: file format elf32-bigarm @@ -59,28 +59,28 @@ // Test PLT section parsing on thumb. // RUN: %clang --target=thumbv8.1m.main-none-linux-eabi \ -// RUN: -c %s -o %t4.o -// RUN: ld.lld --shared %t4.o -o %t4 +// RUN: -c %s -o %t.v8.o +// RUN: ld.lld --shared %t.v8.o -o %t.v8 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ -// RUN: -d %t4 | FileCheck %s --check-prefixes=THUMB,LE +// RUN: -d %t.v8 | FileCheck %s --check-prefixes=THUMB,LE // Test PLT section parsing on thumbeb. // RUN: %clang --target=thumbebv8.1m.main-none-linux-eabi \ -// RUN: -c %s -o %t5.o -// RUN: ld.lld --shared %t5.o -o %t5 +// RUN: -c %s -o %t.v8eb.o +// RUN: ld.lld --shared %t.v8eb.o -o %t.v8eb // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ -// RUN: -d %t5 | FileCheck %s --check-prefixes=THUMB,BE -// RUN: obj2yaml %t5 | FileCheck %s --check-prefixes=NOBE8 +// RUN: -d %t.v8eb | FileCheck %s --check-prefixes=THUMB,BE +// RUN: obj2yaml %t.v8eb | FileCheck %s --check-prefixes=NOBE8 // Test PLT section parsing on thumbeb with be8. // RUN: %clang --target=thumbebv8.1m.main-none-linux-eabi \ -// RUN: -c %s -o %t6.o -// RUN: ld.lld --shared --be8 %t6.o -o %t6 +// RUN: -c %s -o %t.v8eb.be8.o +// RUN: ld.lld --shared --be8 %t.v8eb.be8.o -o %t.v8eb.be8 // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ -// RUN: -d %t6 | FileCheck %s --check-prefixes=THUMB,BE -// RUN: obj2yaml %t6 | FileCheck %s --check-prefixes=BE8 +// RUN: -d %t.v8eb.be8 | FileCheck %s --check-prefixes=THUMB,BE +// RUN: obj2yaml %t.v8eb.be8 | FileCheck %s --check-prefixes=BE8 // THUMB: Disassembly of section .text: // THUMB-EMPTY: @@ -124,27 +124,27 @@ // RUN: %clang --target=armv6a-none-linux-gnueabi -fuse-ld=lld \ // RUN: -Xlinker --script=%t.long.script -nostdlib -nostdinc \ -// RUN: -shared %s -o %t7 +// RUN: -shared %s -o %t.v6a.long // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ -// RUN: -d %t7 | FileCheck %s --check-prefixes=CHECKLONG,LE +// RUN: -d %t.v6a.long | FileCheck %s --check-prefixes=CHECKLONG,LE // Test PLT section with long entries parsing on armeb. // RUN: %clang --target=armv6aeb-none-linux-gnueabi -fuse-ld=lld \ // RUN: -Xlinker --script=%t.long.script -nostdlib -nostdinc \ -// RUN: -shared %s -o %t8 +// RUN: -shared %s -o %t.v6aeb.long // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ -// RUN: -d %t8 | FileCheck %s --check-prefixes=CHECKLONG,BE -// RUN: obj2yaml %t8 | FileCheck %s --check-prefixes=NOBE8 +// RUN: -d %t.v6aeb.long | FileCheck %s --check-prefixes=CHECKLONG,BE +// RUN: obj2yaml %t.v6aeb.long | FileCheck %s --check-prefixes=NOBE8 // Test PLT section with long entries parsing on armeb with be8. // RUN: %clang --target=armv7aeb-none-linux-gnueabi -fuse-ld=lld \ // RUN: -Xlinker --script=%t.long.script -nostdlib -nostdinc \ -// RUN: -shared %s -o %t9 +// RUN: -shared %s -o %t.v7aeb.long // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ -// RUN: -d %t9 | FileCheck %s --check-prefixes=CHECKLONG,BE -// RUN: obj2yaml %t9 | FileCheck %s --check-prefixes=BE8 +// RUN: -d %t.v7aeb.long | FileCheck %s --check-prefixes=CHECKLONG,BE +// RUN: obj2yaml %t.v7aeb.long | FileCheck %s --check-prefixes=BE8 // CHECKLONG: Disassembly of section .text: // CHECKLONG-EMPTY: @@ -184,27 +184,27 @@ // RUN: %clang --target=armv6a-none-linux-gnueabi -fuse-ld=lld \ // RUN: -Xlinker --script=%t.mix.script -nostdlib -nostdinc \ -// RUN: -shared %s -o %t10 +// RUN: -shared %s -o %t.v6a.mix // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ -// RUN: -d %t10 | FileCheck %s --check-prefixes=CHECKMIX,LE +// RUN: -d %t.v6a.mix | FileCheck %s --check-prefixes=CHECKMIX,LE // Test PLT section with mixed long and short entries parsing on armeb. // RUN: %clang --target=armv6aeb-none-linux-gnueabi -fuse-ld=lld \ // RUN: -Xlinker --script=%t.mix.script -nostdlib -nostdinc \ -// RUN: -shared %s -o %t11 +// RUN: -shared %s -o %t.v6aeb.mix // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ -// RUN: -d %t11 | FileCheck %s --check-prefixes=CHECKMIX,BE -// RUN: obj2yaml %t11 | FileCheck %s --check-prefixes=NOBE8 +// RUN: -d %t.v6aeb.mix | FileCheck %s --check-prefixes=CHECKMIX,BE +// RUN: obj2yaml %t.v6aeb.mix | FileCheck %s --check-prefixes=NOBE8 // Test PLT section with mixed long and short entries parsing on armeb with be8. // RUN: %clang --target=armv7aeb-none-linux-gnueabi -fuse-ld=lld \ // RUN: -Xlinker --script=%t.mix.script -nostdlib -nostdinc \ -// RUN: -shared %s -o %t12 +// RUN: -shared %s -o %t.v7aeb.mix // RUN: llvm-objdump --no-show-raw-insn --no-print-imm-hex \ -// RUN: -d %t12 | FileCheck %s --check-prefixes=CHECKMIX,BE -// RUN: obj2yaml %t12 | FileCheck %s --check-prefixes=BE8 +// RUN: -d %t.v7aeb.mix | FileCheck %s --check-prefixes=CHECKMIX,BE +// RUN: obj2yaml %t.v7aeb.mix | FileCheck %s --check-prefixes=BE8 // CHECKMIX: Disassembly of section .text: // CHECKMIX-EMPTY: