Index: src/cmd/internal/rsc.io/x86/x86asm/xedext_test.go |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/src/cmd/internal/rsc.io/x86/x86asm/xedext_test.go |
@@ -0,0 +1,206 @@ |
+package x86asm |
+ |
+import ( |
+ "bytes" |
+ "fmt" |
+ "io" |
+ "log" |
+ "os" |
+ "strconv" |
+ "strings" |
+ "testing" |
+) |
+ |
+// xed binary from Intel sde-external-6.22.0-2014-03-06. |
+const xedPath = "/Users/rsc/bin/xed" |
+ |
+func testXedArch(t *testing.T, arch int, generate func(func([]byte))) { |
+ if testing.Short() { |
+ t.Skip("skipping libmach test in short mode") |
+ } |
+ |
+ if _, err := os.Stat(xedPath); err != nil { |
+ t.Fatal(err) |
+ } |
+ |
+ testExtDis(t, "intel", arch, xed, generate, allowedMismatchXed) |
+} |
+ |
+func testXed32(t *testing.T, generate func(func([]byte))) { |
+ testXedArch(t, 32, generate) |
+} |
+ |
+func testXed64(t *testing.T, generate func(func([]byte))) { |
+ testXedArch(t, 64, generate) |
+} |
+ |
+func xed(ext *ExtDis) error { |
+ b, err := ext.Run(xedPath, fmt.Sprintf("-%d", ext.Arch), "-n", "1G", "-ir", ext.File.Name()) |
+ if err != nil { |
+ return err |
+ } |
+ |
+ nmatch := 0 |
+ next := uint32(start) |
+ var ( |
+ addr uint32 |
+ encbuf [32]byte |
+ enc []byte |
+ text string |
+ ) |
+ |
+ var xedEnd = []byte("# end of text section") |
+ var xedEnd1 = []byte("# Errors") |
+ |
+ eof := false |
+ for { |
+ line, err := b.ReadSlice('\n') |
+ if err != nil { |
+ if err == io.EOF { |
+ break |
+ } |
+ return fmt.Errorf("reading objdump output: %v", err) |
+ } |
+ if debug { |
+ os.Stdout.Write(line) |
+ } |
+ if bytes.HasPrefix(line, xedEnd) || bytes.HasPrefix(line, xedEnd1) { |
+ eof = true |
+ } |
+ if eof { |
+ continue |
+ } |
+ nmatch++ |
+ addr, enc, text = parseLineXed(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 |
+ } |
+ switch text { |
+ case "repz": |
+ text = "rep" |
+ case "repnz": |
+ text = "repn" |
+ default: |
+ text = strings.Replace(text, "repz ", "rep ", -1) |
+ text = strings.Replace(text, "repnz ", "repn ", -1) |
+ } |
+ 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 |
+} |
+ |
+var ( |
+ xedInRaw = []byte("In raw...") |
+ xedDots = []byte("...") |
+ xdis = []byte("XDIS ") |
+ xedError = []byte("ERROR: ") |
+ xedNoDecode = []byte("Could not decode at offset: 0x") |
+) |
+ |
+func parseLineXed(line []byte, encstart []byte) (addr uint32, enc []byte, text string) { |
+ oline := line |
+ if bytes.HasPrefix(line, xedInRaw) || bytes.HasPrefix(line, xedDots) { |
+ return 0, nil, "" |
+ } |
+ if bytes.HasPrefix(line, xedError) { |
+ i := bytes.IndexByte(line[len(xedError):], ' ') |
+ if i < 0 { |
+ log.Fatalf("cannot parse error: %q", oline) |
+ } |
+ errstr := string(line[len(xedError):]) |
+ i = bytes.Index(line, xedNoDecode) |
+ if i < 0 { |
+ log.Fatalf("cannot parse error: %q", oline) |
+ } |
+ i += len(xedNoDecode) |
+ j := bytes.IndexByte(line[i:], ' ') |
+ if j < 0 { |
+ log.Fatalf("cannot parse error: %q", oline) |
+ } |
+ x, err := strconv.ParseUint(string(trimSpace(line[i:i+j])), 16, 32) |
+ if err != nil { |
+ log.Fatalf("cannot parse disassembly: %q", oline) |
+ } |
+ addr = uint32(x) |
+ return addr, nil, errstr |
+ } |
+ |
+ if !bytes.HasPrefix(line, xdis) { |
+ log.Fatalf("cannot parse disassembly: %q", oline) |
+ } |
+ |
+ i := bytes.IndexByte(line, ':') |
+ if i < 0 { |
+ log.Fatalf("cannot parse disassembly: %q", oline) |
+ } |
+ x, err := strconv.ParseUint(string(trimSpace(line[len(xdis):i])), 16, 32) |
+ if err != nil { |
+ log.Fatalf("cannot parse disassembly: %q", oline) |
+ } |
+ addr = uint32(x) |
+ |
+ // spaces |
+ i++ |
+ for i < len(line) && line[i] == ' ' { |
+ i++ |
+ } |
+ // instruction class, spaces |
+ for i < len(line) && line[i] != ' ' { |
+ i++ |
+ } |
+ for i < len(line) && line[i] == ' ' { |
+ i++ |
+ } |
+ // instruction set, spaces |
+ for i < len(line) && line[i] != ' ' { |
+ i++ |
+ } |
+ for i < len(line) && line[i] == ' ' { |
+ i++ |
+ } |
+ |
+ // hex |
+ hexStart := i |
+ for i < len(line) && line[i] != ' ' { |
+ i++ |
+ } |
+ hexEnd := i |
+ for i < len(line) && line[i] == ' ' { |
+ i++ |
+ } |
+ |
+ // text |
+ textStart := i |
+ for i < len(line) && line[i] != '\n' { |
+ i++ |
+ } |
+ textEnd := i |
+ |
+ enc, ok := parseHex(line[hexStart:hexEnd], encstart) |
+ if !ok { |
+ log.Fatalf("cannot parse disassembly: %q", oline) |
+ } |
+ |
+ return addr, enc, string(fixSpace(line[textStart:textEnd])) |
+} |