[PowerPC][llvm-objdump] enable --symbolize-operands for PowerPC ELF/XCOFF.

Summary: When disassembling, symbolize a branch target operand
to print a label instead of a real address.

Reviewed By: shchenz

Differential Revision: https://reviews.llvm.org/D114492
This commit is contained in:
Esme-Yi 2021-12-21 04:17:57 +00:00
parent 8f85d5205d
commit b66328701a
6 changed files with 165 additions and 12 deletions

View File

@ -29,23 +29,22 @@
# SYMBOL: 10020020 0 NOTYPE LOCAL DEFAULT [<other: 0x60>] 2 caller_14
# SYMBOL: 10020040 8 FUNC LOCAL DEFAULT 2 __toc_save_callee
# CHECK-LABEL: callee
# CHECK-LABEL: <callee>:
# CHECK: blr
# CHECK-LABEL: caller
# CHECK: bl 0x10020040
# CHECK-LABEL: <caller>:
# CHECK: bl 0x10020040 <__toc_save_callee>
# CHECK-NEXT: ld 2, 24(1)
# CHECK-NEXT: blr
# CHECK-LABEL: caller_14
# CHECK: bfl 0, 0x10020040
# CHECK-LABEL: <caller_14>:
# CHECK: bfl 0, 0x10020040 <__toc_save_callee>
# CHECK-NEXT: ld 2, 24(1)
# CHECK-NEXT: blr
# CHECK-LABEL: __toc_save_callee
# CHECK-LABEL: <__toc_save_callee>:
# CHECK-NEXT: std 2, 24(1)
# CHECK-NEXT: b 0x10010000
# CHECK-NEXT: b 0x10010000 <callee>
.section .text_callee, "ax", %progbits
callee:

View File

@ -226,7 +226,7 @@ OPTIONS
When printing a PC-relative global symbol reference, print it as an offset from the leading symbol.
Only works with an X86 linked image.
Only works with PowerPC objects or X86 linked images.
Example:
A non-symbolized branch instruction with a local target and pc-relative memory access like

View File

@ -28,6 +28,7 @@
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCRegisterInfo.h"
@ -368,6 +369,31 @@ static MCInstPrinter *createPPCMCInstPrinter(const Triple &T,
return new PPCInstPrinter(MAI, MII, MRI, T);
}
namespace {
class PPCMCInstrAnalysis : public MCInstrAnalysis {
public:
explicit PPCMCInstrAnalysis(const MCInstrInfo *Info)
: MCInstrAnalysis(Info) {}
bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const override {
unsigned NumOps = Inst.getNumOperands();
if (NumOps == 0 ||
Info->get(Inst.getOpcode()).OpInfo[NumOps - 1].OperandType !=
MCOI::OPERAND_PCREL)
return false;
Target = Addr + Inst.getOperand(NumOps - 1).getImm() * Size;
return true;
}
};
} // end anonymous namespace
static MCInstrAnalysis *createPPCMCInstrAnalysis(const MCInstrInfo *Info) {
return new PPCMCInstrAnalysis(Info);
}
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTargetMC() {
for (Target *T : {&getThePPC32Target(), &getThePPC32LETarget(),
&getThePPC64Target(), &getThePPC64LETarget()}) {
@ -383,6 +409,9 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTargetMC() {
// Register the MC subtarget info.
TargetRegistry::RegisterMCSubtargetInfo(*T, createPPCMCSubtargetInfo);
// Register the MC instruction analyzer.
TargetRegistry::RegisterMCInstrAnalysis(*T, createPPCMCInstrAnalysis);
// Register the MC Code Emitter
TargetRegistry::RegisterMCCodeEmitter(*T, createPPCMCCodeEmitter);

View File

@ -0,0 +1,59 @@
; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu %s -filetype=obj -o %t
; RUN: llvm-objdump %t -d --symbolize-operands --no-show-raw-insn \
; RUN: | FileCheck %s
;; Expect to find the branch labels.
; CHECK-LABEL: <internal>:
; CHECK: <L0>:
; CHECK-NEXT: 20: addi 3, 3, 1
; CHECK-NEXT: 24: bdnz 0x20 <L0>
; CHECK-NEXT: 28: blr
; CHECK-LABEL: <foo>:
; CHECK: 6c: b 0x74 <L0>
; CHECK-NEXT: <L2>:
; CHECK-NEXT: 70: bf 8, 0x94 <L1>
; CHECK-NEXT: <L0>:
; CHECK-NEXT: 74: clrldi 3, 30, 32
; CHECK-NEXT: 78: bl 0x0 <internal>
; CHECK-NEXT: 7c: mr 30, 3
; CHECK-NEXT: 80: cmplwi 30, 11
; CHECK-NEXT: 84: bt 0, 0x70 <L2>
; CHECK-NEXT: 88: bl 0x88 <foo+0x48>
; CHECK-NEXT: 8c: nop
; CHECK-NEXT: 90: b 0x70 <L2>
; CHECK-NEXT: <L1>:
; CHECK-NEXT: 94: ld 30, 32(1)
define internal i32 @internal(i32 %a) {
entry:
br label %for.body
for.body:
%i = phi i32 [ 0, %entry ], [ %next, %for.body ]
%next = add nuw nsw i32 %i, 1
%cond = icmp eq i32 %next, %a
br i1 %cond, label %exit, label %for.body
exit:
ret i32 %next
}
declare void @extern()
define void @foo(i1 %breakcond) {
entry:
br label %loop
loop:
%tmp23phi = phi i32 [ %tmp23, %endif ], [ 0, %entry ]
%tmp23 = call i32 @internal(i32 %tmp23phi)
%tmp27 = icmp ult i32 10, %tmp23
br i1 %tmp27, label %then, label %endif
then: ; preds = %bb
call void @extern()
br label %endif
endif: ; preds = %bb28, %bb
br i1 %breakcond, label %loop, label %loopexit
loopexit:
ret void
}

View File

@ -0,0 +1,63 @@
; RUN: llc -mtriple=powerpc-ibm-aix-xcoff %s -filetype=obj -o %t
; RUN: llvm-objdump %t -d --symbolize-operands --no-show-raw-insn \
; RUN: | FileCheck %s
;; Expect to find the branch labels.
; CHECK-LABEL: <.text>:
;; TODO: <.internal> should be printed instead of <.text>.
; CHECK-NEXT: 0: mr 4, 3
; CHECK-NEXT: 4: li 3, 0
; CHECK-NEXT: 8: mtctr 4
; CHECK-NEXT: <L0>:
; CHECK-NEXT: c: addi 3, 3, 1
; CHECK-NEXT: 10: bdnz 0xc <L0>
; CHECK-NEXT: 14: blr
; CHECK-LABEL: <.foo>:
; CHECK: 5c: b 0x64 <L0>
; CHECK-NEXT: <L2>:
; CHECK-NEXT: 60: bf 8, 0x84 <L1>
; CHECK-NEXT: <L0>:
; CHECK-NEXT: 64: mr 3, 31
; CHECK-NEXT: 68: bl 0x0 <.text>
; CHECK-NEXT: 6c: mr 31, 3
; CHECK-NEXT: 70: cmplwi 3, 11
; CHECK-NEXT: 74: bt 0, 0x60 <L2>
; CHECK-NEXT: 78: bl 0x0 <.text>
; CHECK-NEXT: 7c: nop
; CHECK-NEXT: 80: b 0x60 <L2>
; CHECK-NEXT: <L1>:
; CHECK-NEXT: 84: lwz 31, 60(1)
define internal i32 @internal(i32 %a) {
entry:
br label %for.body
for.body:
%i = phi i32 [ 0, %entry ], [ %next, %for.body ]
%next = add nuw nsw i32 %i, 1
%cond = icmp eq i32 %next, %a
br i1 %cond, label %exit, label %for.body
exit:
ret i32 %next
}
declare void @extern()
define void @foo(i1 %breakcond) {
entry:
br label %loop
loop:
%tmp23phi = phi i32 [ %tmp23, %endif ], [ 0, %entry ]
%tmp23 = call i32 @internal(i32 %tmp23phi)
%tmp27 = icmp ult i32 10, %tmp23
br i1 %tmp27, label %then, label %endif
then: ; preds = %bb
call void @extern()
br label %endif
endif: ; preds = %bb28, %bb
br i1 %breakcond, label %loop, label %loopexit
loopexit:
ret void
}

View File

@ -978,8 +978,8 @@ collectLocalBranchTargets(ArrayRef<uint8_t> Bytes, const MCInstrAnalysis *MIA,
const MCSubtargetInfo *STI, uint64_t SectionAddr,
uint64_t Start, uint64_t End,
std::unordered_map<uint64_t, std::string> &Labels) {
// So far only supports X86.
if (!STI->getTargetTriple().isX86())
// So far only supports PowerPC and X86.
if (!STI->getTargetTriple().isPPC() && !STI->getTargetTriple().isX86())
return;
Labels.clear();
@ -999,8 +999,11 @@ collectLocalBranchTargets(ArrayRef<uint8_t> Bytes, const MCInstrAnalysis *MIA,
if (Disassembled && MIA) {
uint64_t Target;
bool TargetKnown = MIA->evaluateBranch(Inst, Index, Size, Target);
// On PowerPC, if the address of a branch is the same as the target, it
// means that it's a function call. Do not mark the label for this case.
if (TargetKnown && (Target >= Start && Target < End) &&
!Labels.count(Target))
!Labels.count(Target) &&
!(STI->getTargetTriple().isPPC() && Target == Index))
Labels[Target] = ("L" + Twine(LabelCount++)).str();
}