ppc64/ppc64asm: improve PCrel argument decoding

If an object is built for PIE, CALL opcodes will target the symbol's
local entry point. When disassembling, we should print the symbol
name if the target is the symbol+8.

The local entry offset on PPC64 is almost always 0 or 8. For pure go,
it is always 0 or 8 today.

If a call looks like it targets a local entry, print it as
"CALL symbol+8(SB)".

Change-Id: I72a2f1eaafd226ed5466384c63040d2f375a541f
Reviewed-on: https://go-review.googlesource.com/c/arch/+/432166
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Run-TryBot: Paul Murphy <murp@ibm.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Paul E. Murphy 2022-09-20 16:52:35 -05:00 коммит произвёл Paul Murphy
Родитель 2926576b28
Коммит 6a65923eb7
4 изменённых файлов: 34 добавлений и 3 удалений

Просмотреть файл

@ -31,6 +31,15 @@ func TestDecode(t *testing.T) {
}
}
// Provide a fake symbol to verify PCrel argument decoding.
func symlookup(pc uint64) (string, uint64) {
foopc := uint64(0x100000)
if pc >= foopc && pc < foopc+0x10 {
return "foo", foopc
}
return "", 0
}
func decode(data []byte, t *testing.T, filename string) {
all := string(data)
// Simulate PC based on number of instructions found in the test file.
@ -68,7 +77,14 @@ func decode(data []byte, t *testing.T, filename string) {
case "gnu":
out = GNUSyntax(inst, pc)
case "plan9":
out = GoSyntax(inst, pc, nil)
pc := pc
// Hack: Setting PC to 0 effectively transforms the PC relative address
// of CALL (bl) into an absolute address when decoding in GoSyntax. This
// simplifies the testing of symbol lookups via symlookup above.
if inst.Op == BL {
pc = 0
}
out = GoSyntax(inst, pc, symlookup)
default:
t.Errorf("unknown syntax %q", syntax)
continue

Просмотреть файл

@ -47,6 +47,10 @@ func allowedMismatchObjdump(text string, size int, inst *Inst, dec ExtInst) bool
return true
case SYNC, WAIT, RFEBB: // ISA 3.1 adds more bits and extended mnemonics for these book ii instructions.
return true
case BL:
// TODO: Ignore these for now. The output format from gnu objdump is dependent on more than the
// instruction itself e.g: decode(48100009) = "bl 0x100008", 4, want "bl .+0x100008", 4
return true
}
if len(dec.enc) >= 4 {

Просмотреть файл

@ -168,8 +168,9 @@ func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) strin
}
// plan9Arg formats arg (which is the argIndex's arg in inst) according to Plan 9 rules.
//
// NOTE: because Plan9Syntax is the only caller of this func, and it receives a copy
// of inst, it's ok to modify inst.Args here.
// of inst, it's ok to modify inst.Args here.
func plan9Arg(inst *Inst, argIndex int, pc uint64, arg Arg, symname func(uint64) (string, uint64)) string {
// special cases for load/store instructions
if _, ok := arg.(Offset); ok {
@ -211,9 +212,16 @@ func plan9Arg(inst *Inst, argIndex int, pc uint64, arg Arg, symname func(uint64)
return fmt.Sprintf("SPR(%d)", int(arg))
case PCRel:
addr := pc + uint64(int64(arg))
if s, base := symname(addr); s != "" && base == addr {
s, base := symname(addr)
if s != "" && addr == base {
return fmt.Sprintf("%s(SB)", s)
}
if inst.Op == BL && s != "" && (addr-base) == 8 {
// When decoding an object built for PIE, a CALL targeting
// a global entry point will be adjusted to the local entry
// if any. For now, assume any symname+8 PC is a local call.
return fmt.Sprintf("%s+%d(SB)", s, addr-base)
}
return fmt.Sprintf("%#x", addr)
case Label:
return fmt.Sprintf("%#x", int(arg))

3
ppc64/ppc64asm/testdata/decode.txt поставляемый
Просмотреть файл

@ -469,6 +469,9 @@ f0400fe0| plan9 XVCVSXDDP VS1,VS2
7c6802a6| plan9 MOVD LR,R3
7c6902a6| plan9 MOVD CTR,R3
4c8c0000| plan9 MOVFL CR3,CR1
48100001| plan9 CALL foo(SB)
48100009| plan9 CALL foo+8(SB)
4810000d| plan9 CALL 0x10000c
7c6803a6| gnu mtlr r3
7c6802a6| gnu mflr r3
7c6903a6| gnu mtctr r3