-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
[llvm-objdump][ARM] Find ELF file PLT entries for arm, thumb #130764
Conversation
@llvm/pr-subscribers-lld-elf @llvm/pr-subscribers-backend-arm Author: Vladislav Dzhidzhoev (dzhidzhoev) ChangesThis 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. Patch is 65.93 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/130764.diff 28 Files Affected:
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: <bar2@plt>:
// 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: <zed2@plt>:
// 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: <bar@plt>:
# 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..a12aea45dfb15 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: <func1@plt>:
// 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: <func2@plt>:
// 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: <func3@plt>:
// 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: <func1@plt>:
// 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: <func2@plt>:
// 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: <func3@plt>:
// 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: <func1@plt>:
// 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: <func2@plt>:
// 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: <func3@plt>:
// 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: <func1@plt>:
// 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: <func2@plt>:
// 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: <func3@plt>:
// CHECKLONG-EB-NEXT: 2040: ldr r12, [pc, #4]
// CHECKLONG-EB-NEXT: add r12, r12, pc
// CHECKLONG-EB-NEXT: ldr pc, [r12]
@@ -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: <func1@plt>:
// 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: <func2@plt>:
// 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: <func3@plt>:
// 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: <func1@plt>:
// 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: <func2@plt>:
// 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: <func3@plt>:
// 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: <elsewhere@plt>:
// 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: <weakref@plt>:
// 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: <thumb_callee1@plt>
// 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: <arm_callee1@plt>
// 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: <arm_caller@plt>
// 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: <thumb_callee2@plt>
// 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: <thumb_callee3@plt>
// 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: <arm_callee2@plt>
// 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: <arm_callee3@plt>
// 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: <thumb_caller@plt>
// 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: <elsewhere@plt>:
// 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: <preemptible@plt>:
// 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: <far_preemptible@plt>:
// 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: <func1@plt>:
// 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: <func2@plt>:
// 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: <func3@plt>:
// 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: <preemptible@plt>:
// 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: <preemptible2@plt>:
// 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: <imported@plt>:
// 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: <imported2@plt>:
// 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: <func1@plt>:
// 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: <func2@plt>:
// 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: <func3@plt>:
// 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/include/llvm/MC/MCInstrAnalysis.h b/llvm/include/llvm/MC/MCInstrAnalysis.h
index b571791c518da..eacadce6b91d9 100644
--- a/llvm/include/llvm/MC/MCInstrAnalysis.h
+++ b/llvm/include/llvm/MC/MCInstrAnalysis.h
@@ -195,7 +195,8 @@ class MCInstrAnalysis {
/// Returns (PLT virtual address, GOT virtual address) pairs for PLT entries.
virtual std::vector<std::pair<uint64_t, uint64_t>>
findPltEntries(uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents,
- const Triple &TargetTriple) const {
+ const Triple &TargetTriple,
+ std::optional<llvm::endianness> InstrEndiannessHint) const {
return {};
}
};
diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp
index d0897c62b3e8e..c9ff42175dccd 100644
--- a/llvm/lib/Object/ELFObjectFile.cpp
+++ b/llvm/lib/Object/ELFObjectFile.cpp
@@ -798,6 +798,12 @@ std::vector<ELFPltEntry> ELFObjectFileBase::getPltEntries() 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;
@@ -833,10 +839,18 @@ std::vector<ELFPltEntry> ELFObjectFileBase::getPltEntries() const {
consumeError(PltContents.takeError());
return {};
}
+ std::optional<llvm::endianness> InstrEndianness;
+ if (const auto *Elf32BE = dyn_cast<ELF32BEObjectFile>(this)) {
+ if (!Elf32BE->isRelocatableObject() &&
+ (Elf32BE->getPlatformFlags() & ELF::EF_ARM_BE8)) {
+ InstrEndianness = endianness::little;
+ }
+ }
+
llvm::a...
[truncated]
|
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.
Thanks for the patch.
This looks correct for the Arm/Thumb details. I've left some stylistic suggestions that I think might help someone reading this for the first time.
For LLD generated PLTs at least, we should only see Thumb2 PLTs for a Cortex-M which I think only supports be8, however it is possible to generate be32 images so I don't think it is worth trying to take advantage of that.
uint32_t InsnPart1 = | ||
support::endian::read16(PltContents.data() + Byte, InstrEndianness); | ||
|
||
// Is Thumb? Check for movw. |
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 think this kind test can be hoisted out of the loop, and cached, although the first entry of the Thumb2 PLT won't be a mov as it will be the PLT header.
All PLT entries will be Arm state or Thumb2. If you've access to the symbol table, the canonical way of determining whether Arm or Thumb is from the mapping symbol at address 0, $a for Arm or $t for Thumb.
It may even be a bit easier to read if we have something like (pseudo code)
test if Arm or Thumb
// Arm is the most common case.
if Arm {
for(...) {
}
}
else {
for (...) {
}
}
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.
We do have access to the symbol table from findPltEntries, though it's a raw symbol table, with no Section->Symbols mapping. Probably we don't want to traverse the whole symbol table in findPltEntries.
Meanwhile, the described logic was implemented in llvm-objdump.cpp here https://reviews.llvm.org/D60927. However, "thumb-ness" for sections is checked during disassembly after addPltEntries call.
I've added the code to detect Thumb usage of .plt section before addPltEntries, and to pass MCSubtargetInfo instead of TargetTriple to findPltEntries, so that findPltEntries can get that information from feature flags. I hope it doesn't violate abstraction layers too much.
((Insn2Part2 & 0xff) << 16) + ((Insn2Part2 & 0x7000) << 12) + | ||
((Insn2Part1 & 0x400) << 17) + ((Insn2Part1 & 0xf) << 28); | ||
|
||
// Check for add |
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.
The remaining instructions of the PLT entry are matched exactly. Could these be put in an array, and looped through. For example
uint16_t Insns =
{ 0x44fc, // add ip, pc
0xf8dc, 0xf000, // ldr.w pc, [ip]
0xe7fc // b . -4 };
// loop from Byte + 8 to Byte + 14
// check insn against array[offset in array]
If any of these fail its likely a corrupt PLT, you may be able to skip to the next PLT start boundary on failure (Byte += 12)
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.
Fixed. I did the same to check long entries.
support::endian::read16(PltContents.data() + Byte, InstrEndianness); | ||
|
||
// Is Thumb? Check for movw. | ||
if ((InsnPart1 & 0xffb0) == 0xf200) { |
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 think it would be helpful if there's an overall expected PLT sequence before we start. For example:
movw ip, #lower16
movt ip, #upper16
add ip, pc
ldr.w pc, [ip]
b . -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.
Added comments for every case
Byte += 12; | ||
} else { | ||
// Check for first add | ||
if ((Insn & 0xe28fc600) != 0xe28fc600) |
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.
Rather than Insn
, Insn2
and Insn3
could you use Add1
, Add2
, Ldr
?
if ((Insn3 & 0xe5bcf000) != 0xe5bcf000) | ||
continue; | ||
|
||
uint64_t Offset = (PltSectionVA + Byte + 8) + ((Insn & 0xff) << 20) + |
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.
Similar to the thumb case. Can we explain that the 8 is the Arm PC-Bias.
@@ -0,0 +1,81 @@ | |||
# RUN: yaml2obj %s -o %t |
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.
We need ET_DYN / ET_EXE to test .plt, but due to project layering we cannot use lld here.
Therefore, we resort to yaml2obj, but I can see that these plt*
files could be challenging to update.
Is it possible to use yaml2obj -D...
to remove some duplication?
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.
Should in look like that 7d7c9ba?
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'm not a great fan of the big binary blobs in the llvm-objdump tests. I wonder if it would be more appropriate for these tests to appear in cross-project-tests
, where they could use both lld and llvm-objdump, since they are testing llvm-objdump's behaviour in conjunction with LLD's PLT generation behaviour. Thoughts @MaskRay?
Another slightly wacky idea could be to write the instructions in assembly, use llvm-mc to generate an object file containing the corresponding sections (with pre-computed values for addresses, where needed), then use llvm-objcopy to extract those sections into files that are somehow read and passed as the -D parameter values to yaml2obj. That's probably too much setup to be worthwhile, but just throwing it out there as an option.
llvm/lib/Object/ELFObjectFile.cpp
Outdated
std::optional<llvm::endianness> InstrEndianness; | ||
if (const auto *Elf32BE = dyn_cast<ELF32BEObjectFile>(this)) { | ||
if (!Elf32BE->isRelocatableObject() && | ||
(Elf32BE->getPlatformFlags() & ELF::EF_ARM_BE8)) { |
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.
Doesn't this need some sort of guard that the machine is actually ARM? Otherwise, in theory, you could have a Big Endian object file for a different machine, which just so happens to have a flag with the same value as EF_ARM_BE8
.
(It's possible I missed something, so apologies if I have)
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.
Thank you for the catch!
Now it uses STI.checkFeatures("+big-endian-instructions") instead of manually checking for flags.
@@ -0,0 +1,104 @@ | |||
# Test PLT section with long entries parsing on arm |
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.
Nit: newer tests among the LLVM tools tend to use ##
for comments, to help distinguish them from RUN and CHECK lines.
Also missing "." at the end of the sentence.
# Test PLT section with long entries parsing on arm | |
## Test PLT section with long entries parsing on arm. |
Applies throughout.
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.
Fixed.
Adding While cross-project-tests might not be the primary focus for all developers, we still have lld/test/ELF tests for the behavior. |
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.
Thanks for the updates. Some really small comments for me, but otherwise looks good to me. I'd better leave the maintainers to approve when they're happy.
llvm/lib/Object/ELFObjectFile.cpp
Outdated
@@ -833,10 +840,11 @@ std::vector<ELFPltEntry> ELFObjectFileBase::getPltEntries() const { | |||
consumeError(PltContents.takeError()); | |||
return {}; | |||
} | |||
|
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.
Was this extra newline intentional? If not I recommend removing to keep the diff as small as possible
@@ -392,6 +392,18 @@ static MCRelocationInfo *createARMMCRelocationInfo(const Triple &TT, | |||
return llvm::createMCRelocationInfo(TT, Ctx); | |||
} | |||
|
|||
template <typename T, size_t N> | |||
bool instructionsAreMatching(const T (&Insns)[N], const uint8_t *Buf, |
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.
Can this be made static?
I suggest instructionsMatch
as a shorter name. Not got a strong opinion.
// ldr.w pc, [ip] | ||
// b . -4 | ||
|
||
// Check for movw. |
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.
With the additional comments above and variable names I think the // Check for comments aren't needed anymore.
|
||
if (instructionsAreMatching(Insns, PltContents.data() + Byte + 8, | ||
InstrEndianness)) { | ||
uint64_t Offset = |
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.
Could we add a comment
// add ip, pc at Byte + 8 +thumb-pc-bias = 12
if ((Ldr & 0xe5bcf000) != 0xe5bcf000) | ||
continue; | ||
|
||
uint64_t Offset = (PltSectionVA + Byte + 8) + ((Add1 & 0xff) << 20) + |
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.
Could we add a comment
// add ip, pc, #offset at Byte + 0 + arm-pc-bias = 8
✅ With the latest revision this PR passed the C/C++ code formatter. |
Done |
@@ -0,0 +1,243 @@ | |||
// Test PLT section parsing on arm. | |||
|
|||
// RUN: %clang -target armv6a-none-linux-gnueabi -fuse-ld=ld.lld \ |
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.
-target
has been deprecated since about clang 3.4. Use --target=
Use -fuse-ld=lld instead of -fuse-ld=ld.lld
, the latter is an abuse of a non-guaranteed behavior of clang driver's -fuse-ld support.
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.
Fixed
// CHECK-NEXT: <_start>: | ||
// CHECK-NEXT: push {r11, lr} | ||
// CHECK-NEXT: mov r11, sp | ||
// CHECK-NEXT: bl 0x10240 <func1@plt> |
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.
bl {{.*}} <func1@plt>
. The addresses are not reliable. (linker layout might change; compiler codegen might be different; %clang
might expand to slightly different options, etc)
(Addresses in lld are sometimes fine as we precisely control how the relocatable files and image files are generated.)
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.
Fixed
|
||
// THUMB: Disassembly of section .plt: | ||
// THUMB-EMPTY: | ||
// THUMB: 00010270 <func1@plt>: |
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.
Delete the leading address. Not reliable
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.
Fixed
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.
Changing Triple to const MCSubtargetInfo &STI
looks good to me, but perhaps the refactoring could be a separate patch
if (PltSectionRef != SectionNames.end()) { | ||
bool PltIsThumb = false; | ||
for (auto [Addr, SymbolName] : AllMappingSymbols[PltSectionRef->second]) { | ||
if (Addr == 0) { |
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.
early return
if (Addr != 0)
break;
...
PltIsThumb = true; | ||
break; | ||
} | ||
if (SymbolName == 'a') { |
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.
remove braces when the body is a single-line simple stmt
auto *ElfObj = dyn_cast<ELFObjectFileBase>(&Obj); | ||
if (!ElfObj) | ||
return; | ||
DenseMap<StringRef, SectionRef> getSectionNames(const ObjectFile &Obj) { |
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.
@@ -431,6 +443,126 @@ class ARMMCInstrAnalysis : public MCInstrAnalysis { | |||
std::optional<uint64_t> | |||
evaluateMemoryOperandAddress(const MCInst &Inst, const MCSubtargetInfo *STI, | |||
uint64_t Addr, uint64_t Size) const override; | |||
|
|||
std::vector<std::pair<uint64_t, uint64_t>> | |||
findPltEntries(uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents, |
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.
Declare it here and define it outside of the class
It allows to check for subtarget features, collected in llvm-objdump.cpp, in findPltEntries, which will be used in llvm#130764.
Created a separate PR for the refactoring change. #131773 |
It allows access to subtarget features, collected in llvm-objdump.cpp, from findPltEntries, which will be used in #130764.
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.
…) (#131773) It allows access to subtarget features, collected in llvm-objdump.cpp, from findPltEntries, which will be used in llvm/llvm-project#130764.
f2d41b6
to
def15be
Compare
Rebased this PR on top of it. |
Gentle ping |
// 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 |
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.
-c
suppresses the link phase. -nostdlib
should be removed, as it only affects linking.
|
||
// 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 \ |
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.
The tet tests v6a/v8m & LE/BE. Perhaps use a more meaningful executable name, say, %tv6
%tv6.be
than %t1
.
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 produced from lld/test/ELF/arm-plt-reloc.s, lld/test/ELF/armv8-thumb-plt-reloc.s.