1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package x86asm 6 7 import ( 8 "bytes" 9 "fmt" 10 "io" 11 "log" 12 "os" 13 "strconv" 14 "testing" 15 ) 16 17 const plan9Path = "testdata/libmach8db" 18 19 func testPlan9Arch(t *testing.T, arch int, generate func(func([]byte))) { 20 if testing.Short() { 21 t.Skip("skipping libmach test in short mode") 22 } 23 if _, err := os.Stat(plan9Path); err != nil { 24 t.Skip(err) 25 } 26 27 testExtDis(t, "plan9", arch, plan9, generate, allowedMismatchPlan9) 28 } 29 30 func testPlan932(t *testing.T, generate func(func([]byte))) { 31 testPlan9Arch(t, 32, generate) 32 } 33 34 func testPlan964(t *testing.T, generate func(func([]byte))) { 35 testPlan9Arch(t, 64, generate) 36 } 37 38 func plan9(ext *ExtDis) error { 39 flag := "-8" 40 if ext.Arch == 64 { 41 flag = "-6" 42 } 43 b, err := ext.Run(plan9Path, flag, ext.File.Name()) 44 if err != nil { 45 return err 46 } 47 48 nmatch := 0 49 next := uint32(start) 50 var ( 51 addr uint32 52 encbuf [32]byte 53 enc []byte 54 text string 55 ) 56 57 for { 58 line, err := b.ReadSlice('\n') 59 if err != nil { 60 if err == io.EOF { 61 break 62 } 63 return fmt.Errorf("reading libmach8db output: %v", err) 64 } 65 if debug { 66 os.Stdout.Write(line) 67 } 68 nmatch++ 69 addr, enc, text = parseLinePlan9(line, encbuf[:0]) 70 if addr > next { 71 return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line) 72 } 73 if addr < next { 74 continue 75 } 76 if m := pcrelw.FindStringSubmatch(text); m != nil { 77 targ, _ := strconv.ParseUint(m[2], 16, 64) 78 text = fmt.Sprintf("%s .%+#x", m[1], int16(uint32(targ)-uint32(uint16(addr))-uint32(len(enc)))) 79 } 80 if m := pcrel.FindStringSubmatch(text); m != nil { 81 targ, _ := strconv.ParseUint(m[2], 16, 64) 82 text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc)))) 83 } 84 ext.Dec <- ExtInst{addr, encbuf, len(enc), text} 85 encbuf = [32]byte{} 86 enc = nil 87 next += 32 88 } 89 if next != start+uint32(ext.Size) { 90 return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size) 91 } 92 if err := ext.Wait(); err != nil { 93 return fmt.Errorf("exec: %v", err) 94 } 95 96 return nil 97 } 98 99 func parseLinePlan9(line []byte, encstart []byte) (addr uint32, enc []byte, text string) { 100 i := bytes.IndexByte(line, ' ') 101 if i < 0 || line[0] != '0' || line[1] != 'x' { 102 log.Fatalf("cannot parse disassembly: %q", line) 103 } 104 j := bytes.IndexByte(line[i+1:], ' ') 105 if j < 0 { 106 log.Fatalf("cannot parse disassembly: %q", line) 107 } 108 j += i + 1 109 x, err := strconv.ParseUint(string(trimSpace(line[2:i])), 16, 32) 110 if err != nil { 111 log.Fatalf("cannot parse disassembly: %q", line) 112 } 113 addr = uint32(x) 114 enc, ok := parseHex(line[i+1:j], encstart) 115 if !ok { 116 log.Fatalf("cannot parse disassembly: %q", line) 117 } 118 return addr, enc, string(fixSpace(line[j+1:])) 119 } 120