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 24 if _, err := os.Stat(plan9Path); err != nil { 25 t.Fatal(err) 26 } 27 28 testExtDis(t, "plan9", arch, plan9, generate, allowedMismatchPlan9) 29 } 30 31 func testPlan932(t *testing.T, generate func(func([]byte))) { 32 testPlan9Arch(t, 32, generate) 33 } 34 35 func testPlan964(t *testing.T, generate func(func([]byte))) { 36 testPlan9Arch(t, 64, generate) 37 } 38 39 func plan9(ext *ExtDis) error { 40 flag := "-8" 41 if ext.Arch == 64 { 42 flag = "-6" 43 } 44 b, err := ext.Run(plan9Path, flag, ext.File.Name()) 45 if err != nil { 46 return err 47 } 48 49 nmatch := 0 50 next := uint32(start) 51 var ( 52 addr uint32 53 encbuf [32]byte 54 enc []byte 55 text string 56 ) 57 58 for { 59 line, err := b.ReadSlice('\n') 60 if err != nil { 61 if err == io.EOF { 62 break 63 } 64 return fmt.Errorf("reading libmach8db output: %v", err) 65 } 66 if debug { 67 os.Stdout.Write(line) 68 } 69 nmatch++ 70 addr, enc, text = parseLinePlan9(line, encbuf[:0]) 71 if addr > next { 72 return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line) 73 } 74 if addr < next { 75 continue 76 } 77 if m := pcrelw.FindStringSubmatch(text); m != nil { 78 targ, _ := strconv.ParseUint(m[2], 16, 64) 79 text = fmt.Sprintf("%s .%+#x", m[1], int16(uint32(targ)-uint32(uint16(addr))-uint32(len(enc)))) 80 } 81 if m := pcrel.FindStringSubmatch(text); m != nil { 82 targ, _ := strconv.ParseUint(m[2], 16, 64) 83 text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc)))) 84 } 85 ext.Dec <- ExtInst{addr, encbuf, len(enc), text} 86 encbuf = [32]byte{} 87 enc = nil 88 next += 32 89 } 90 if next != start+uint32(ext.Size) { 91 return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size) 92 } 93 if err := ext.Wait(); err != nil { 94 return fmt.Errorf("exec: %v", err) 95 } 96 97 return nil 98 } 99 100 func parseLinePlan9(line []byte, encstart []byte) (addr uint32, enc []byte, text string) { 101 i := bytes.IndexByte(line, ' ') 102 if i < 0 || line[0] != '0' || line[1] != 'x' { 103 log.Fatalf("cannot parse disassembly: %q", line) 104 } 105 j := bytes.IndexByte(line[i+1:], ' ') 106 if j < 0 { 107 log.Fatalf("cannot parse disassembly: %q", line) 108 } 109 j += i + 1 110 x, err := strconv.ParseUint(string(trimSpace(line[2:i])), 16, 32) 111 if err != nil { 112 log.Fatalf("cannot parse disassembly: %q", line) 113 } 114 addr = uint32(x) 115 enc, ok := parseHex(line[i+1:j], encstart) 116 if !ok { 117 log.Fatalf("cannot parse disassembly: %q", line) 118 } 119 return addr, enc, string(fixSpace(line[j+1:])) 120 } 121