From 905b1c9804e0ed8ad6351966388cb8610bf5c3f1 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Wed, 22 Nov 2017 16:25:13 -0500 Subject: [PATCH] cmd/vendor/golang.org/x/arch: revendor at commit dda8112 Updates #20650 (CL 45099 introduced the feature to x86). Change-Id: If40cc9d87417a05281d8633f05cd91f6f434b136 Reviewed-on: https://go-review.googlesource.com/80843 Run-TryBot: Cherry Zhang Reviewed-by: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- .../golang.org/x/arch/arm/armasm/ext_test.go | 2 +- .../golang.org/x/arch/arm/armasm/inst.go | 2 +- .../x/arch/ppc64/ppc64asm/ext_test.go | 2 +- .../x/arch/x86/x86asm/decode_test.go | 4 +- .../golang.org/x/arch/x86/x86asm/ext_test.go | 6 +- .../x/arch/x86/x86asm/format_test.go | 68 +++++++++++++++++++ .../golang.org/x/arch/x86/x86asm/gnu.go | 36 ++++++++-- .../golang.org/x/arch/x86/x86asm/intel.go | 40 +++++++++-- .../golang.org/x/arch/x86/x86asm/plan9x.go | 35 +++++++--- 9 files changed, 169 insertions(+), 26 deletions(-) create mode 100644 src/cmd/vendor/golang.org/x/arch/x86/x86asm/format_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/ext_test.go b/src/cmd/vendor/golang.org/x/arch/arm/armasm/ext_test.go index 98192b324e..3556ae77bb 100644 --- a/src/cmd/vendor/golang.org/x/arch/arm/armasm/ext_test.go +++ b/src/cmd/vendor/golang.org/x/arch/arm/armasm/ext_test.go @@ -34,7 +34,7 @@ var ( debug = false ) -// A ExtInst represents a single decoded instruction parsed +// An ExtInst represents a single decoded instruction parsed // from an external disassembler's output. type ExtInst struct { addr uint32 diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/inst.go b/src/cmd/vendor/golang.org/x/arch/arm/armasm/inst.go index 60d633bdb6..0e056442b2 100644 --- a/src/cmd/vendor/golang.org/x/arch/arm/armasm/inst.go +++ b/src/cmd/vendor/golang.org/x/arch/arm/armasm/inst.go @@ -105,7 +105,7 @@ func (i Imm) String() string { return fmt.Sprintf("#%#x", uint32(i)) } -// A ImmAlt is an alternate encoding of an integer constant. +// An ImmAlt is an alternate encoding of an integer constant. type ImmAlt struct { Val uint8 Rot uint8 diff --git a/src/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm/ext_test.go b/src/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm/ext_test.go index b5539844fc..95d4d468e0 100644 --- a/src/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm/ext_test.go +++ b/src/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm/ext_test.go @@ -35,7 +35,7 @@ var ( debug = false ) -// A ExtInst represents a single decoded instruction parsed +// An ExtInst represents a single decoded instruction parsed // from an external disassembler's output. type ExtInst struct { addr uint32 diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode_test.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode_test.go index b6098b898e..127be263d7 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode_test.go +++ b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode_test.go @@ -54,9 +54,9 @@ func TestDecode(t *testing.T) { } else { switch syntax { case "gnu": - out = GNUSyntax(inst) + out = GNUSyntax(inst, 0, nil) case "intel": - out = IntelSyntax(inst) + out = IntelSyntax(inst, 0, nil) case "plan9": // [sic] out = GoSyntax(inst, 0, nil) default: diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/ext_test.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/ext_test.go index eadfd71bf5..72fe45b72a 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/ext_test.go +++ b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/ext_test.go @@ -33,7 +33,7 @@ var ( debug = false ) -// A ExtInst represents a single decoded instruction parsed +// An ExtInst represents a single decoded instruction parsed // from an external disassembler's output. type ExtInst struct { addr uint32 @@ -248,9 +248,9 @@ func disasm(syntax string, mode int, src []byte) (inst Inst, text string) { } else { switch syntax { case "gnu": - text = GNUSyntax(inst) + text = GNUSyntax(inst, 0, nil) case "intel": - text = IntelSyntax(inst) + text = IntelSyntax(inst, 0, nil) case "plan9": // [sic] text = GoSyntax(inst, 0, nil) default: diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/format_test.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/format_test.go new file mode 100644 index 0000000000..9f110f8105 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/format_test.go @@ -0,0 +1,68 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x86asm + +import ( + "encoding/hex" + "testing" +) + +func testFormattingSymname(addr uint64) (string, uint64) { + switch addr { + case 0x424080: + return "runtime.printint", 0x424080 + case 0x4c8068: + return "main.A", 0x4c8068 + } + return "", 0 +} + +func TestFormatting(t *testing.T) { + testCases := []struct { + PC uint64 + bytes string + + goSyntax, intelSyntax, gnuSyntax string + }{ + {0x4816b2, "0f8677010000", + "JBE 0x48182f", + "jbe 0x48182f", + "jbe 0x48182f"}, + {0x45065b, "488b442408", + "MOVQ 0x8(SP), AX", + "mov rax, qword ptr [rsp+0x8]", + "mov 0x8(%rsp),%rax"}, + {0x450678, "488b05e9790700", + "MOVQ main.A(SB), AX", + "mov rax, qword ptr [main.A]", + "mov main.A,%rax"}, + {0x450664, "e8173afdff", + "CALL runtime.printint(SB)", + "call runtime.printint", + "callq runtime.printint"}, + {0x45069b, "488d0575d90100", + "LEAQ 0x1d975(IP), AX", + "lea rax, ptr [rip+0x1d975]", + "lea 0x1d975(%rip),%rax"}, + } + + for _, testCase := range testCases { + t.Logf("%#x %s %s", testCase.PC, testCase.bytes, testCase.goSyntax) + bs, _ := hex.DecodeString(testCase.bytes) + inst, err := Decode(bs, 64) + if err != nil { + t.Errorf("decode error %v", err) + } + if out := GoSyntax(inst, testCase.PC, testFormattingSymname); out != testCase.goSyntax { + t.Errorf("GoSyntax: %q", out) + } + if out := IntelSyntax(inst, testCase.PC, testFormattingSymname); out != testCase.intelSyntax { + t.Errorf("IntelSyntax: %q expected: %q", out, testCase.intelSyntax) + } + if out := GNUSyntax(inst, testCase.PC, testFormattingSymname); out != testCase.gnuSyntax { + t.Errorf("GNUSyntax: %q expected: %q", out, testCase.gnuSyntax) + } + } +} diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/gnu.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/gnu.go index 728e5d18e5..75cff72b03 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/gnu.go +++ b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/gnu.go @@ -11,12 +11,16 @@ import ( // GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils. // This general form is often called ``AT&T syntax'' as a reference to AT&T System V Unix. -func GNUSyntax(inst Inst) string { +func GNUSyntax(inst Inst, pc uint64, symname SymLookup) string { // Rewrite instruction to mimic GNU peculiarities. // Note that inst has been passed by value and contains // no pointers, so any changes we make here are local // and will not propagate back out to the caller. + if symname == nil { + symname = func(uint64) (string, uint64) { return "", 0 } + } + // Adjust opcode [sic]. switch inst.Op { case FDIV, FDIVR, FSUB, FSUBR, FDIVP, FDIVRP, FSUBP, FSUBRP: @@ -403,7 +407,7 @@ SuffixLoop: if a == Imm(1) && (inst.Opcode>>24)&^1 == 0xD0 { continue } - args = append(args, gnuArg(&inst, a, &usedPrefixes)) + args = append(args, gnuArg(&inst, pc, symname, a, &usedPrefixes)) } // The default is to print the arguments in reverse Intel order. @@ -513,7 +517,7 @@ SuffixLoop: // gnuArg returns the GNU syntax for the argument x from the instruction inst. // If *usedPrefixes is false and x is a Mem, then the formatting // includes any segment prefixes and sets *usedPrefixes to true. -func gnuArg(inst *Inst, x Arg, usedPrefixes *bool) string { +func gnuArg(inst *Inst, pc uint64, symname SymLookup, x Arg, usedPrefixes *bool) string { if x == nil { return "" } @@ -535,6 +539,13 @@ func gnuArg(inst *Inst, x Arg, usedPrefixes *bool) string { } return gccRegName[x] case Mem: + if s, disp := memArgToSymbol(x, pc, inst.Len, symname); s != "" { + suffix := "" + if disp != 0 { + suffix = fmt.Sprintf("%+d", disp) + } + return fmt.Sprintf("%s%s", s, suffix) + } seg := "" var haveCS, haveDS, haveES, haveFS, haveGS, haveSS bool switch x.Segment { @@ -644,8 +655,25 @@ func gnuArg(inst *Inst, x Arg, usedPrefixes *bool) string { } return fmt.Sprintf("%s%s(%s,%s,%d)", seg, disp, base, index, x.Scale) case Rel: - return fmt.Sprintf(".%+#x", int32(x)) + if pc == 0 { + return fmt.Sprintf(".%+#x", int64(x)) + } else { + addr := pc + uint64(inst.Len) + uint64(x) + if s, base := symname(addr); s != "" && addr == base { + return fmt.Sprintf("%s", s) + } else { + addr := pc + uint64(inst.Len) + uint64(x) + return fmt.Sprintf("%#x", addr) + } + } case Imm: + if s, base := symname(uint64(x)); s != "" { + suffix := "" + if uint64(x) != base { + suffix = fmt.Sprintf("%+d", uint64(x)-base) + } + return fmt.Sprintf("$%s%s", s, suffix) + } if inst.Mode == 32 { return fmt.Sprintf("$%#x", uint32(x)) } diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/intel.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/intel.go index 63fa2cfc1c..472eabda80 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/intel.go +++ b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/intel.go @@ -10,7 +10,11 @@ import ( ) // IntelSyntax returns the Intel assembler syntax for the instruction, as defined by Intel's XED tool. -func IntelSyntax(inst Inst) string { +func IntelSyntax(inst Inst, pc uint64, symname SymLookup) string { + if symname == nil { + symname = func(uint64) (string, uint64) { return "", 0 } + } + var iargs []Arg for _, a := range inst.Args { if a == nil { @@ -256,7 +260,7 @@ func IntelSyntax(inst Inst) string { if a == nil { break } - args = append(args, intelArg(&inst, a)) + args = append(args, intelArg(&inst, pc, symname, a)) } var op string @@ -334,9 +338,16 @@ func IntelSyntax(inst Inst) string { return prefix + op } -func intelArg(inst *Inst, arg Arg) string { +func intelArg(inst *Inst, pc uint64, symname SymLookup, arg Arg) string { switch a := arg.(type) { case Imm: + if s, base := symname(uint64(a)); s != "" { + suffix := "" + if uint64(a) != base { + suffix = fmt.Sprintf("%+d", uint64(a)-base) + } + return fmt.Sprintf("$%s%s", s, suffix) + } if inst.Mode == 32 { return fmt.Sprintf("%#x", uint32(a)) } @@ -417,18 +428,25 @@ func intelArg(inst *Inst, arg Arg) string { } prefix += "ptr " + if s, disp := memArgToSymbol(a, pc, inst.Len, symname); s != "" { + suffix := "" + if disp != 0 { + suffix = fmt.Sprintf("%+d", disp) + } + return prefix + fmt.Sprintf("[%s%s]", s, suffix) + } if a.Segment != 0 { prefix += strings.ToLower(a.Segment.String()) + ":" } prefix += "[" if a.Base != 0 { - prefix += intelArg(inst, a.Base) + prefix += intelArg(inst, pc, symname, a.Base) } if a.Scale != 0 && a.Index != 0 { if a.Base != 0 { prefix += "+" } - prefix += fmt.Sprintf("%s*%d", intelArg(inst, a.Index), a.Scale) + prefix += fmt.Sprintf("%s*%d", intelArg(inst, pc, symname, a.Index), a.Scale) } if a.Disp != 0 { if prefix[len(prefix)-1] == '[' && (a.Disp >= 0 || int64(int32(a.Disp)) != a.Disp) { @@ -440,7 +458,17 @@ func intelArg(inst *Inst, arg Arg) string { prefix += "]" return prefix case Rel: - return fmt.Sprintf(".%+#x", int64(a)) + if pc == 0 { + return fmt.Sprintf(".%+#x", int64(a)) + } else { + addr := pc + uint64(inst.Len) + uint64(a) + if s, base := symname(addr); s != "" && addr == base { + return fmt.Sprintf("%s", s) + } else { + addr := pc + uint64(inst.Len) + uint64(a) + return fmt.Sprintf("%#x", addr) + } + } case Reg: if int(a) < len(intelReg) && intelReg[a] != "" { switch inst.Op { diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go index 41cfc08f10..a93bffd441 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go +++ b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go @@ -9,6 +9,8 @@ import ( "strings" ) +type SymLookup func(uint64) (string, uint64) + // GoSyntax returns the Go assembler syntax for the instruction. // The syntax was originally defined by Plan 9. // The pc is the program counter of the instruction, used for expanding @@ -16,7 +18,7 @@ import ( // The symname function queries the symbol table for the program // being disassembled. Given a target address it returns the name and base // address of the symbol containing the target, if any; otherwise it returns "", 0. -func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) string { +func GoSyntax(inst Inst, pc uint64, symname SymLookup) string { if symname == nil { symname = func(uint64) (string, uint64) { return "", 0 } } @@ -119,14 +121,12 @@ func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg } return fmt.Sprintf("$%#x", uint64(a)) case Mem: - if a.Segment == 0 && a.Disp != 0 && a.Base == 0 && (a.Index == 0 || a.Scale == 0) { - if s, base := symname(uint64(a.Disp)); s != "" { - suffix := "" - if uint64(a.Disp) != base { - suffix = fmt.Sprintf("%+d", uint64(a.Disp)-base) - } - return fmt.Sprintf("%s%s(SB)", s, suffix) + if s, disp := memArgToSymbol(a, pc, inst.Len, symname); s != "" { + suffix := "" + if disp != 0 { + suffix = fmt.Sprintf("%+d", disp) } + return fmt.Sprintf("%s%s(SB)", s, suffix) } s := "" if a.Segment != 0 { @@ -148,6 +148,25 @@ func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg return arg.String() } +func memArgToSymbol(a Mem, pc uint64, instrLen int, symname SymLookup) (string, int64) { + if a.Segment != 0 || a.Disp == 0 || a.Index != 0 || a.Scale != 0 { + return "", 0 + } + + var disp uint64 + switch a.Base { + case IP, EIP, RIP: + disp = uint64(a.Disp + int64(pc) + int64(instrLen)) + case 0: + disp = uint64(a.Disp) + default: + return "", 0 + } + + s, base := symname(disp) + return s, int64(disp) - int64(base) +} + var plan9Suffix = [maxOp + 1]bool{ ADC: true, ADD: true, -- 2.50.0