// Copyright 2014 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 ( "bytes" "fmt" "io" "log" "os" "strconv" "testing" ) const plan9Path = "testdata/libmach8db" func testPlan9Arch(t *testing.T, arch int, generate func(func([]byte))) { if testing.Short() { t.Skip("skipping libmach test in short mode") } if _, err := os.Stat(plan9Path); err != nil { t.Fatal(err) } testExtDis(t, "plan9", arch, plan9, generate, allowedMismatchPlan9) } func testPlan932(t *testing.T, generate func(func([]byte))) { testPlan9Arch(t, 32, generate) } func testPlan964(t *testing.T, generate func(func([]byte))) { testPlan9Arch(t, 64, generate) } func plan9(ext *ExtDis) error { flag := "-8" if ext.Arch == 64 { flag = "-6" } b, err := ext.Run(plan9Path, flag, ext.File.Name()) if err != nil { return err } nmatch := 0 next := uint32(start) var ( addr uint32 encbuf [32]byte enc []byte text string ) for { line, err := b.ReadSlice('\n') if err != nil { if err == io.EOF { break } return fmt.Errorf("reading libmach8db output: %v", err) } if debug { os.Stdout.Write(line) } nmatch++ addr, enc, text = parseLinePlan9(line, encbuf[:0]) if addr > next { return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line) } if addr < next { continue } if m := pcrelw.FindStringSubmatch(text); m != nil { targ, _ := strconv.ParseUint(m[2], 16, 64) text = fmt.Sprintf("%s .%+#x", m[1], int16(uint32(targ)-uint32(uint16(addr))-uint32(len(enc)))) } if m := pcrel.FindStringSubmatch(text); m != nil { targ, _ := strconv.ParseUint(m[2], 16, 64) text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc)))) } ext.Dec <- ExtInst{addr, encbuf, len(enc), text} encbuf = [32]byte{} enc = nil next += 32 } if next != start+uint32(ext.Size) { return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size) } if err := ext.Wait(); err != nil { return fmt.Errorf("exec: %v", err) } return nil } func parseLinePlan9(line []byte, encstart []byte) (addr uint32, enc []byte, text string) { i := bytes.IndexByte(line, ' ') if i < 0 || line[0] != '0' || line[1] != 'x' { log.Fatalf("cannot parse disassembly: %q", line) } j := bytes.IndexByte(line[i+1:], ' ') if j < 0 { log.Fatalf("cannot parse disassembly: %q", line) } j += i + 1 x, err := strconv.ParseUint(string(trimSpace(line[2:i])), 16, 32) if err != nil { log.Fatalf("cannot parse disassembly: %q", line) } addr = uint32(x) enc, ok := parseHex(line[i+1:j], encstart) if !ok { log.Fatalf("cannot parse disassembly: %q", line) } return addr, enc, string(fixSpace(line[j+1:])) }