blob: a048cdcd1f816ec4ba98286e8071fb265266ec40 [file] [log] [blame]
From aac056c528cf139e6881211ee7fe6743c79a68d4 Mon Sep 17 00:00:00 2001
From: Oliver Stannard <oliver.stannard@linaro.org>
Date: Tue, 2 Mar 2021 13:49:14 +0000
Subject: [PATCH] [objdump][ARM] Use correct offset when printing ARM/Thumb
branch targets
llvm-objdump only uses one MCInstrAnalysis object, so if ARM and Thumb
code is mixed in one object, or if an object is disassembled without
explicitly setting the triple to match the ISA used, then branch and
call targets will be printed incorrectly.
This could be fixed by creating two MCInstrAnalysis objects in
llvm-objdump, like we currently do for SubtargetInfo. However, I don't
think there's any reason we need two separate sub-classes of
MCInstrAnalysis, so instead these can be merged into one, and the ISA
determined by checking the opcode of the instruction.
Differential revision: https://reviews.llvm.org/D97766
---
lld/test/ELF/arm-thunk-many-passes.s | 35 +++++-----
llvm/lib/Target/ARM/ARMInstrInfo.td | 1 +
.../ARM/MCTargetDesc/ARMMCTargetDesc.cpp | 69 +++++-------------
.../llvm-objdump/ELF/ARM/branch-symbols.s | 70 +++++++++++++++++++
4 files changed, 109 insertions(+), 66 deletions(-)
create mode 100644 llvm/test/tools/llvm-objdump/ELF/ARM/branch-symbols.s
diff --git a/lld/test/ELF/arm-thunk-many-passes.s b/lld/test/ELF/arm-thunk-many-passes.s
index e7efb81c580e..9e8f428bb01f 100644
--- a/lld/test/ELF/arm-thunk-many-passes.s
+++ b/lld/test/ELF/arm-thunk-many-passes.s
@@ -7,7 +7,7 @@
// RUN: sym = .;" > %t.script
// RUN: ld.lld --script %t.script %t -o %t2
// RUN: llvm-readobj --sections --symbols %t2 | FileCheck --check-prefix=CHECK-ELF %s
-// RUN: llvm-objdump --no-show-raw-insn --start-address=0x11000 --stop-address=0x1103c -d %t2 | FileCheck %s
+// RUN: llvm-objdump --no-show-raw-insn --start-address=0x11000 --stop-address=0x11048 -d %t2 | FileCheck %s
// An example of thunk generation that takes the maximum number of permitted
// passes to converge. We start with a set of branches of which all but one are
@@ -35,21 +35,24 @@
// CHECK-ELF-NEXT: Value: 0x101104C
// CHECK: 00011000 <_start>:
-// CHECK-NEXT: 11000: b.w #14680132 <__Thumbv7ABSLongThunk_f3>
-// CHECK-NEXT: 11004: b.w #14680128 <__Thumbv7ABSLongThunk_f3>
-// CHECK-NEXT: 11008: b.w #14680128 <__Thumbv7ABSLongThunk_f4>
-// CHECK-NEXT: 1100c: b.w #14680124 <__Thumbv7ABSLongThunk_f4>
-// CHECK-NEXT: 11010: b.w #14680124 <__Thumbv7ABSLongThunk_f5>
-// CHECK-NEXT: 11014: b.w #14680120 <__Thumbv7ABSLongThunk_f5>
-// CHECK-NEXT: 11018: b.w #14680120 <__Thumbv7ABSLongThunk_f6>
-// CHECK-NEXT: 1101c: b.w #14680116 <__Thumbv7ABSLongThunk_f6>
-// CHECK-NEXT: 11020: b.w #14680116 <__Thumbv7ABSLongThunk_f7>
-// CHECK-NEXT: 11024: b.w #14680112 <__Thumbv7ABSLongThunk_f7>
-// CHECK-NEXT: 11028: b.w #14680112 <__Thumbv7ABSLongThunk_f8>
-// CHECK-NEXT: 1102c: b.w #14680108 <__Thumbv7ABSLongThunk_f8>
-// CHECK-NEXT: 11030: b.w #14680108 <__Thumbv7ABSLongThunk_f9>
-// CHECK-NEXT: 11034: b.w #14680104 <__Thumbv7ABSLongThunk_f9>
-// CHECK-NEXT: 11038: b.w #14680104 <__Thumbv7ABSLongThunk_f10>
+// CHECK-NEXT: 11000: b.w #14680132 <__Thumbv7ABSLongThunk_f2>
+// CHECK-NEXT: 11004: b.w #14680128 <__Thumbv7ABSLongThunk_f2>
+// CHECK-NEXT: 11008: b.w #14680128 <__Thumbv7ABSLongThunk_f3>
+// CHECK-NEXT: 1100c: b.w #14680124 <__Thumbv7ABSLongThunk_f3>
+// CHECK-NEXT: 11010: b.w #14680124 <__Thumbv7ABSLongThunk_f4>
+// CHECK-NEXT: 11014: b.w #14680120 <__Thumbv7ABSLongThunk_f4>
+// CHECK-NEXT: 11018: b.w #14680120 <__Thumbv7ABSLongThunk_f5>
+// CHECK-NEXT: 1101c: b.w #14680116 <__Thumbv7ABSLongThunk_f5>
+// CHECK-NEXT: 11020: b.w #14680116 <__Thumbv7ABSLongThunk_f6>
+// CHECK-NEXT: 11024: b.w #14680112 <__Thumbv7ABSLongThunk_f6>
+// CHECK-NEXT: 11028: b.w #14680112 <__Thumbv7ABSLongThunk_f7>
+// CHECK-NEXT: 1102c: b.w #14680108 <__Thumbv7ABSLongThunk_f7>
+// CHECK-NEXT: 11030: b.w #14680108 <__Thumbv7ABSLongThunk_f8>
+// CHECK-NEXT: 11034: b.w #14680104 <__Thumbv7ABSLongThunk_f8>
+// CHECK-NEXT: 11038: b.w #14680104 <__Thumbv7ABSLongThunk_f9>
+// CHECK-NEXT: 1103c: b.w #14680100 <__Thumbv7ABSLongThunk_f9>
+// CHECK-NEXT: 11040: b.w #14680100 <__Thumbv7ABSLongThunk_f10>
+// CHECK-NEXT: 11044: b.w #14680096 <__Thumbv7ABSLongThunk_f10>
.thumb
diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td
index 8dcb319923ae..b96e098e07ac 100644
--- a/llvm/lib/Target/ARM/ARMInstrInfo.td
+++ b/llvm/lib/Target/ARM/ARMInstrInfo.td
@@ -2619,6 +2619,7 @@ def BXJ : ABI<0b0001, (outs), (ins GPR:$func), NoItinerary, "bxj", "\t$func",
let Inst{7-4} = 0b0010;
let Inst{3-0} = func;
let isBranch = 1;
+ let isIndirectBranch = 1;
}
// Tail calls.
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
index 68c8d175710c..a8271257cbfe 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
@@ -408,54 +408,28 @@ public:
return MCInstrAnalysis::isConditionalBranch(Inst);
}
- bool evaluateBranch(const MCInst &Inst, uint64_t Addr,
- uint64_t Size, uint64_t &Target) const override {
- // We only handle PCRel branches for now.
- if (Inst.getNumOperands() == 0 ||
- Info->get(Inst.getOpcode()).OpInfo[0].OperandType !=
- MCOI::OPERAND_PCREL)
- return false;
-
- int64_t Imm = Inst.getOperand(0).getImm();
- Target = Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes.
- return true;
- }
-};
-
-class ThumbMCInstrAnalysis : public ARMMCInstrAnalysis {
-public:
- ThumbMCInstrAnalysis(const MCInstrInfo *Info) : ARMMCInstrAnalysis(Info) {}
-
bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const override {
- unsigned OpId;
- switch (Inst.getOpcode()) {
- default:
- OpId = 0;
- if (Inst.getNumOperands() == 0)
- return false;
- break;
- case ARM::MVE_WLSTP_8:
- case ARM::MVE_WLSTP_16:
- case ARM::MVE_WLSTP_32:
- case ARM::MVE_WLSTP_64:
- case ARM::t2WLS:
- case ARM::MVE_LETP:
- case ARM::t2LEUpdate:
- OpId = 2;
- break;
- case ARM::t2LE:
- OpId = 1;
- break;
+ const MCInstrDesc &Desc = Info->get(Inst.getOpcode());
+
+ // Find the PC-relative immediate operand in the instruction.
+ bool FoundImm = false;
+ int64_t Imm;
+ for (unsigned OpNum = 0; OpNum < Desc.getNumOperands(); ++OpNum) {
+ if (Inst.getOperand(OpNum).isImm() &&
+ Desc.OpInfo[OpNum].OperandType == MCOI::OPERAND_PCREL) {
+ Imm = Inst.getOperand(OpNum).getImm();
+ FoundImm = true;
+ }
}
-
- // We only handle PCRel branches for now.
- if (Info->get(Inst.getOpcode()).OpInfo[OpId].OperandType !=
- MCOI::OPERAND_PCREL)
+ if (!FoundImm)
return false;
- // In Thumb mode the PC is always off by 4 bytes.
- Target = Addr + Inst.getOperand(OpId).getImm() + 4;
+ // For ARM instructions the PC offset is 8 bytes, for Thumb instructions it
+ // is 4 bytes.
+ uint64_t Offset = ((Desc.TSFlags & ARMII::FormMask) == ARMII::ThumbFrm) ? 4 : 8;
+
+ Target = Addr + Imm + Offset;
return true;
}
};
@@ -466,10 +440,6 @@ static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) {
return new ARMMCInstrAnalysis(Info);
}
-static MCInstrAnalysis *createThumbMCInstrAnalysis(const MCInstrInfo *Info) {
- return new ThumbMCInstrAnalysis(Info);
-}
-
bool ARM::isCDECoproc(size_t Coproc, const MCSubtargetInfo &STI) {
// Unfortunately we don't have ARMTargetInfo in the disassembler, so we have
// to rely on feature bits.
@@ -517,10 +487,9 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARMTargetMC() {
}
// Register the MC instruction analyzer.
- for (Target *T : {&getTheARMLETarget(), &getTheARMBETarget()})
+ for (Target *T : {&getTheARMLETarget(), &getTheARMBETarget(),
+ &getTheThumbLETarget(), &getTheThumbBETarget()})
TargetRegistry::RegisterMCInstrAnalysis(*T, createARMMCInstrAnalysis);
- for (Target *T : {&getTheThumbLETarget(), &getTheThumbBETarget()})
- TargetRegistry::RegisterMCInstrAnalysis(*T, createThumbMCInstrAnalysis);
for (Target *T : {&getTheARMLETarget(), &getTheThumbLETarget()}) {
TargetRegistry::RegisterMCCodeEmitter(*T, createARMLEMCCodeEmitter);
diff --git a/llvm/test/tools/llvm-objdump/ELF/ARM/branch-symbols.s b/llvm/test/tools/llvm-objdump/ELF/ARM/branch-symbols.s
new file mode 100644
index 000000000000..d967c21ae048
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/ELF/ARM/branch-symbols.s
@@ -0,0 +1,70 @@
+@ RUN: llvm-mc < %s --triple=armv8a -mattr=+mve,+lob -filetype=obj | llvm-objdump -dr - --triple armv8a --mattr=+mve,+lob --no-show-raw-insn | FileCheck %s
+@ RUN: llvm-mc < %s --triple=thumbv8a -mattr=+mve,+lob -filetype=obj | llvm-objdump -dr - --triple armv8a --mattr=+mve,+lob --no-show-raw-insn | FileCheck %s
+
+foo:
+
+ // Branches
+ .arm
+ b foo
+ ble foo
+@ CHECK: 0: b #-8 <foo>
+@ CHECK: 4: ble #-12 <foo>
+
+ .thumb
+ b foo
+ b.w foo
+ ble foo
+ ble.w foo
+ le foo
+ le lr, foo
+ cbz r0, bar
+ cbnz r0, bar
+@ CHECK: 8: b #-12 <foo>
+@ CHECK: a: b.w #-14 <foo>
+@ CHECK: e: ble #-18 <foo>
+@ CHECK: 10: ble.w #-20 <foo>
+@ CHECK: 14: le #-24 <foo>
+@ CHECK: 18: le lr, #-28 <foo>
+@ CHECK: 1c: cbz r0, #40 <bar>
+@ CHECK: 1e: cbnz r0, #38 <bar>
+
+ // Calls without relocations (these offsets al correspond to label foo).
+ .arm
+ bl #-40
+ blx #-44
+ bleq #-48
+@ CHECK: 20: bl #-40 <foo>
+@ CHECK: 24: blx #-44 <foo>
+@ CHECK: 28: bleq #-48 <foo>
+
+ .thumb
+ bl #-48
+ blx #-52
+@ CHECK: 2c: bl #-48 <foo>
+@ CHECK: 30: blx #-52 <foo>
+
+ // Calls with relocations. These currently emit a reference to their own
+ // location, because we don't take relocations into account when printing
+ // branch targets.
+ .arm
+ bl baz
+ blx baz
+ bleq baz
+@ CHECK: 34: bl #-8 <$a.4>
+@ CHECK: 00000034: R_ARM_CALL baz
+@ CHECK: 38: blx #-8 <$a.4+0x4>
+@ CHECK: 00000038: R_ARM_CALL baz
+@ CHECK: 3c: bleq #-8 <$a.4+0x8>
+@ CHECK: 0000003c: R_ARM_JUMP24 baz
+
+ .thumb
+ bl baz
+ blx baz
+@ CHECK: 40: bl #-4 <$t.5>
+@ CHECK: 00000040: R_ARM_THM_CALL baz
+@ CHECK: 44: blx #-4 <$t.5+0x4>
+@ CHECK: 00000044: R_ARM_THM_CALL baz
+
+bar:
+
+
--
2.30.1.766.gb4fecdf3b7-goog