1
2
3
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
View as plain text