Skip to content

Commit b663287

Browse files
author
Esme-Yi
committed
[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
1 parent 8f85d52 commit b663287

File tree

6 files changed

+165
-12
lines changed

6 files changed

+165
-12
lines changed

lld/test/ELF/ppc64-toc-call-to-pcrel.s

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,22 @@
2929
# SYMBOL: 10020020 0 NOTYPE LOCAL DEFAULT [<other: 0x60>] 2 caller_14
3030
# SYMBOL: 10020040 8 FUNC LOCAL DEFAULT 2 __toc_save_callee
3131

32-
# CHECK-LABEL: callee
32+
# CHECK-LABEL: <callee>:
3333
# CHECK: blr
3434

35-
# CHECK-LABEL: caller
36-
# CHECK: bl 0x10020040
35+
# CHECK-LABEL: <caller>:
36+
# CHECK: bl 0x10020040 <__toc_save_callee>
3737
# CHECK-NEXT: ld 2, 24(1)
3838
# CHECK-NEXT: blr
3939

40-
# CHECK-LABEL: caller_14
41-
# CHECK: bfl 0, 0x10020040
40+
# CHECK-LABEL: <caller_14>:
41+
# CHECK: bfl 0, 0x10020040 <__toc_save_callee>
4242
# CHECK-NEXT: ld 2, 24(1)
4343
# CHECK-NEXT: blr
4444

45-
# CHECK-LABEL: __toc_save_callee
45+
# CHECK-LABEL: <__toc_save_callee>:
4646
# CHECK-NEXT: std 2, 24(1)
47-
# CHECK-NEXT: b 0x10010000
48-
47+
# CHECK-NEXT: b 0x10010000 <callee>
4948

5049
.section .text_callee, "ax", %progbits
5150
callee:

llvm/docs/CommandGuide/llvm-objdump.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ OPTIONS
226226

227227
When printing a PC-relative global symbol reference, print it as an offset from the leading symbol.
228228

229-
Only works with an X86 linked image.
229+
Only works with PowerPC objects or X86 linked images.
230230

231231
Example:
232232
A non-symbolized branch instruction with a local target and pc-relative memory access like

llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "llvm/MC/MCDwarf.h"
2929
#include "llvm/MC/MCELFStreamer.h"
3030
#include "llvm/MC/MCExpr.h"
31+
#include "llvm/MC/MCInstrAnalysis.h"
3132
#include "llvm/MC/MCInstrInfo.h"
3233
#include "llvm/MC/MCObjectWriter.h"
3334
#include "llvm/MC/MCRegisterInfo.h"
@@ -368,6 +369,31 @@ static MCInstPrinter *createPPCMCInstPrinter(const Triple &T,
368369
return new PPCInstPrinter(MAI, MII, MRI, T);
369370
}
370371

372+
namespace {
373+
374+
class PPCMCInstrAnalysis : public MCInstrAnalysis {
375+
public:
376+
explicit PPCMCInstrAnalysis(const MCInstrInfo *Info)
377+
: MCInstrAnalysis(Info) {}
378+
379+
bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
380+
uint64_t &Target) const override {
381+
unsigned NumOps = Inst.getNumOperands();
382+
if (NumOps == 0 ||
383+
Info->get(Inst.getOpcode()).OpInfo[NumOps - 1].OperandType !=
384+
MCOI::OPERAND_PCREL)
385+
return false;
386+
Target = Addr + Inst.getOperand(NumOps - 1).getImm() * Size;
387+
return true;
388+
}
389+
};
390+
391+
} // end anonymous namespace
392+
393+
static MCInstrAnalysis *createPPCMCInstrAnalysis(const MCInstrInfo *Info) {
394+
return new PPCMCInstrAnalysis(Info);
395+
}
396+
371397
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTargetMC() {
372398
for (Target *T : {&getThePPC32Target(), &getThePPC32LETarget(),
373399
&getThePPC64Target(), &getThePPC64LETarget()}) {
@@ -383,6 +409,9 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTargetMC() {
383409
// Register the MC subtarget info.
384410
TargetRegistry::RegisterMCSubtargetInfo(*T, createPPCMCSubtargetInfo);
385411

412+
// Register the MC instruction analyzer.
413+
TargetRegistry::RegisterMCInstrAnalysis(*T, createPPCMCInstrAnalysis);
414+
386415
// Register the MC Code Emitter
387416
TargetRegistry::RegisterMCCodeEmitter(*T, createPPCMCCodeEmitter);
388417

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu %s -filetype=obj -o %t
2+
; RUN: llvm-objdump %t -d --symbolize-operands --no-show-raw-insn \
3+
; RUN: | FileCheck %s
4+
5+
;; Expect to find the branch labels.
6+
; CHECK-LABEL: <internal>:
7+
; CHECK: <L0>:
8+
; CHECK-NEXT: 20: addi 3, 3, 1
9+
; CHECK-NEXT: 24: bdnz 0x20 <L0>
10+
; CHECK-NEXT: 28: blr
11+
12+
; CHECK-LABEL: <foo>:
13+
; CHECK: 6c: b 0x74 <L0>
14+
; CHECK-NEXT: <L2>:
15+
; CHECK-NEXT: 70: bf 8, 0x94 <L1>
16+
; CHECK-NEXT: <L0>:
17+
; CHECK-NEXT: 74: clrldi 3, 30, 32
18+
; CHECK-NEXT: 78: bl 0x0 <internal>
19+
; CHECK-NEXT: 7c: mr 30, 3
20+
; CHECK-NEXT: 80: cmplwi 30, 11
21+
; CHECK-NEXT: 84: bt 0, 0x70 <L2>
22+
; CHECK-NEXT: 88: bl 0x88 <foo+0x48>
23+
; CHECK-NEXT: 8c: nop
24+
; CHECK-NEXT: 90: b 0x70 <L2>
25+
; CHECK-NEXT: <L1>:
26+
; CHECK-NEXT: 94: ld 30, 32(1)
27+
28+
define internal i32 @internal(i32 %a) {
29+
entry:
30+
br label %for.body
31+
32+
for.body:
33+
%i = phi i32 [ 0, %entry ], [ %next, %for.body ]
34+
%next = add nuw nsw i32 %i, 1
35+
%cond = icmp eq i32 %next, %a
36+
br i1 %cond, label %exit, label %for.body
37+
38+
exit:
39+
ret i32 %next
40+
}
41+
42+
declare void @extern()
43+
44+
define void @foo(i1 %breakcond) {
45+
entry:
46+
br label %loop
47+
loop:
48+
%tmp23phi = phi i32 [ %tmp23, %endif ], [ 0, %entry ]
49+
%tmp23 = call i32 @internal(i32 %tmp23phi)
50+
%tmp27 = icmp ult i32 10, %tmp23
51+
br i1 %tmp27, label %then, label %endif
52+
then: ; preds = %bb
53+
call void @extern()
54+
br label %endif
55+
endif: ; preds = %bb28, %bb
56+
br i1 %breakcond, label %loop, label %loopexit
57+
loopexit:
58+
ret void
59+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
; RUN: llc -mtriple=powerpc-ibm-aix-xcoff %s -filetype=obj -o %t
2+
; RUN: llvm-objdump %t -d --symbolize-operands --no-show-raw-insn \
3+
; RUN: | FileCheck %s
4+
5+
;; Expect to find the branch labels.
6+
; CHECK-LABEL: <.text>:
7+
;; TODO: <.internal> should be printed instead of <.text>.
8+
; CHECK-NEXT: 0: mr 4, 3
9+
; CHECK-NEXT: 4: li 3, 0
10+
; CHECK-NEXT: 8: mtctr 4
11+
; CHECK-NEXT: <L0>:
12+
; CHECK-NEXT: c: addi 3, 3, 1
13+
; CHECK-NEXT: 10: bdnz 0xc <L0>
14+
; CHECK-NEXT: 14: blr
15+
16+
; CHECK-LABEL: <.foo>:
17+
; CHECK: 5c: b 0x64 <L0>
18+
; CHECK-NEXT: <L2>:
19+
; CHECK-NEXT: 60: bf 8, 0x84 <L1>
20+
; CHECK-NEXT: <L0>:
21+
; CHECK-NEXT: 64: mr 3, 31
22+
; CHECK-NEXT: 68: bl 0x0 <.text>
23+
; CHECK-NEXT: 6c: mr 31, 3
24+
; CHECK-NEXT: 70: cmplwi 3, 11
25+
; CHECK-NEXT: 74: bt 0, 0x60 <L2>
26+
; CHECK-NEXT: 78: bl 0x0 <.text>
27+
; CHECK-NEXT: 7c: nop
28+
; CHECK-NEXT: 80: b 0x60 <L2>
29+
; CHECK-NEXT: <L1>:
30+
; CHECK-NEXT: 84: lwz 31, 60(1)
31+
32+
define internal i32 @internal(i32 %a) {
33+
entry:
34+
br label %for.body
35+
36+
for.body:
37+
%i = phi i32 [ 0, %entry ], [ %next, %for.body ]
38+
%next = add nuw nsw i32 %i, 1
39+
%cond = icmp eq i32 %next, %a
40+
br i1 %cond, label %exit, label %for.body
41+
42+
exit:
43+
ret i32 %next
44+
}
45+
46+
declare void @extern()
47+
48+
define void @foo(i1 %breakcond) {
49+
entry:
50+
br label %loop
51+
loop:
52+
%tmp23phi = phi i32 [ %tmp23, %endif ], [ 0, %entry ]
53+
%tmp23 = call i32 @internal(i32 %tmp23phi)
54+
%tmp27 = icmp ult i32 10, %tmp23
55+
br i1 %tmp27, label %then, label %endif
56+
then: ; preds = %bb
57+
call void @extern()
58+
br label %endif
59+
endif: ; preds = %bb28, %bb
60+
br i1 %breakcond, label %loop, label %loopexit
61+
loopexit:
62+
ret void
63+
}

llvm/tools/llvm-objdump/llvm-objdump.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -978,8 +978,8 @@ collectLocalBranchTargets(ArrayRef<uint8_t> Bytes, const MCInstrAnalysis *MIA,
978978
const MCSubtargetInfo *STI, uint64_t SectionAddr,
979979
uint64_t Start, uint64_t End,
980980
std::unordered_map<uint64_t, std::string> &Labels) {
981-
// So far only supports X86.
982-
if (!STI->getTargetTriple().isX86())
981+
// So far only supports PowerPC and X86.
982+
if (!STI->getTargetTriple().isPPC() && !STI->getTargetTriple().isX86())
983983
return;
984984

985985
Labels.clear();
@@ -999,8 +999,11 @@ collectLocalBranchTargets(ArrayRef<uint8_t> Bytes, const MCInstrAnalysis *MIA,
999999
if (Disassembled && MIA) {
10001000
uint64_t Target;
10011001
bool TargetKnown = MIA->evaluateBranch(Inst, Index, Size, Target);
1002+
// On PowerPC, if the address of a branch is the same as the target, it
1003+
// means that it's a function call. Do not mark the label for this case.
10021004
if (TargetKnown && (Target >= Start && Target < End) &&
1003-
!Labels.count(Target))
1005+
!Labels.count(Target) &&
1006+
!(STI->getTargetTriple().isPPC() && Target == Index))
10041007
Labels[Target] = ("L" + Twine(LabelCount++)).str();
10051008
}
10061009

0 commit comments

Comments
 (0)