forked from OSchip/llvm-project
[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:
parent
8f85d5205d
commit
b66328701a
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue