Skip to content

Commit

Permalink
goversion: fixes for Go 1.10
Browse files Browse the repository at this point in the history
- Move -d flag to binary, not library.
- Update amd64 patterns for Go 1.10.
- Implement f.Entry for Mach-O

Fixes #4.
  • Loading branch information
rsc committed Mar 9, 2018
1 parent 04f0b81 commit bbd79cf
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 10 deletions.
4 changes: 4 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ var (
verbose = flag.Bool("v", false, "print verbose information")
)

func init() {
flag.BoolVar(&version.DebugMatch, "d", version.DebugMatch, "print debug information")
}

func usage() {
fmt.Fprintf(os.Stderr, "usage: goversion [-crypto] [-v] path...\n")
flag.PrintDefaults()
Expand Down
56 changes: 47 additions & 9 deletions version/asm.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ package version

import (
"encoding/binary"
"flag"
"fmt"
"os"
)

type matcher [][]uint32

const (
pWild uint32 = 0xff00
pAddr uint32 = 0x10000
pEnd uint32 = 0x20000
pWild uint32 = 0xff00
pAddr uint32 = 0x10000
pEnd uint32 = 0x20000
pRelAddr uint32 = 0x30000

opMaybe = 1 + iota
opMust
Expand All @@ -27,6 +27,11 @@ const (
)

var amd64Matcher = matcher{
{opMaybe | opAnchor,
// __rt0_amd64_darwin:
// JMP __rt0_amd64
0xe9, pWild | pAddr, pWild, pWild, pWild | pEnd, 0xcc, 0xcc, 0xcc,
},
{opMaybe,
// _rt0_amd64_linux:
// lea 0x8(%rsp), %rsi
Expand All @@ -49,6 +54,16 @@ var amd64Matcher = matcher{
0xb8, pWild | pAddr, pWild, pWild, pWild,
0xff, 0xe0,
},
{opMaybe,
// __rt0_amd64:
// mov (%rsp), %rdi
// lea 8(%rsp), %rsi
// jmp runtime.rt0_g0
0x48, 0x8b, 0x3c, 0x24,
0x48, 0x8d, 0x74, 0x24, 0x08,
0xe9, pWild | pAddr, pWild, pWild, pWild | pEnd,
0xcc, 0xcc,
},
{opMaybe,
// _start (toward end)
// lea __libc_csu_fini(%rip), %r8
Expand Down Expand Up @@ -109,7 +124,6 @@ var amd64Matcher = matcher{
// callq runtime.args
// callq runtime.osinit
// callq runtime.schedinit (ADDR)
// lea mainPC(%rip), %rax
0x89, 0x04, 0x24,
0x48, 0x8b, 0x44, 0x24, 0x18,
0x48, 0x89, 0x44, 0x24, 0x08,
Expand Down Expand Up @@ -195,6 +209,15 @@ var amd64Matcher = matcher{
0x48, 0x8d, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
0x48, 0xc7, 0x40, 0x08, 0x07, 0x00, 0x00, 0x00,
},
{opDone,
// schedinit (toward end)
// cmpq $0x0, ADDR(%rip)
// jne <short>
// movq $0x7, ADDR(%rip)
0x48, 0x83, 0x3d, pWild | pAddr, pWild, pWild, pWild, 0x00,
0x75, pWild,
0x48, 0xc7, 0x05 | pEnd, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00,
},
{opDone,
// test %eax, %eax
// jne <later>
Expand All @@ -204,13 +227,22 @@ var amd64Matcher = matcher{
},
}

var debugMatch = flag.Bool("d", false, "print debug information")
var DebugMatch bool

func (m matcher) match(f exe, addr uint64) (uint64, bool) {
data, err := f.ReadData(addr, 512)
if DebugMatch {
fmt.Fprintf(os.Stderr, "data @%#x: %x\n", addr, data[:16])
}
if err != nil {
if DebugMatch {
fmt.Fprintf(os.Stderr, "match: %v\n", err)
}
return 0, false
}
if DebugMatch {
fmt.Fprintf(os.Stderr, "data: %x\n", data[:32])
}
Matchers:
for pc, p := range m {
op := p[0]
Expand All @@ -236,7 +268,7 @@ Matchers:
}
}
// matched
if *debugMatch {
if DebugMatch {
fmt.Fprintf(os.Stderr, "match (%d) %#x+%d %x %x\n", pc, addr, i, p, data[i:i+len(p)])
}
if a != -1 {
Expand All @@ -251,7 +283,7 @@ Matchers:
}
}
if op&^opFlags == opDone {
if *debugMatch {
if DebugMatch {
fmt.Fprintf(os.Stderr, "done %x\n", addr)
}
return addr, true
Expand All @@ -262,11 +294,14 @@ Matchers:
if err != nil {
return 0, false
}
if DebugMatch {
fmt.Fprintf(os.Stderr, "reload @%#x: %x\n", addr, data[:32])
}
}
continue Matchers
}
// not matched
if *debugMatch {
if DebugMatch {
fmt.Fprintf(os.Stderr, "no match (%d) %#x %x %x\n", pc, addr, p, data[:32])
}
if op&^opFlags == opMust {
Expand All @@ -280,6 +315,9 @@ Matchers:
func readBuildVersionX86Asm(f exe) (isGo bool, buildVersion string) {
entry := f.Entry()
if entry == 0 {
if DebugMatch {
fmt.Fprintf(os.Stderr, "missing entry!\n")
}
return
}
addr, ok := amd64Matcher.match(f, entry)
Expand Down
12 changes: 12 additions & 0 deletions version/exe.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,18 @@ func (x *machoExe) Close() error {
}

func (x *machoExe) Entry() uint64 {
for _, load := range x.f.Loads {
b, ok := load.(macho.LoadBytes)
if !ok {
continue
}
bo := x.f.ByteOrder
const x86_THREAD_STATE64 = 4
cmd, siz := macho.LoadCmd(bo.Uint32(b[0:4])), bo.Uint32(b[4:8])
if cmd == macho.LoadCmdUnixThread && siz == 184 && bo.Uint32(b[8:12]) == x86_THREAD_STATE64 {
return bo.Uint64(b[144:])
}
}
return 0
}

Expand Down
2 changes: 1 addition & 1 deletion version/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func ReadExe(file string) (Version, error) {
}
}

if *debugMatch {
if DebugMatch {
v.Release = ""
}
if err := findModuleInfo(&v, f); err != nil {
Expand Down

0 comments on commit bbd79cf

Please sign in to comment.