github.com/huandu/go@v0.0.0-20151114150818-04e615e41150/src/cmd/internal/rsc.io/x86/x86asm/xedext_test.go (about)

     1  package x86asm
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"log"
     8  	"os"
     9  	"strconv"
    10  	"strings"
    11  	"testing"
    12  )
    13  
    14  // xed binary from Intel sde-external-6.22.0-2014-03-06.
    15  const xedPath = "/Users/rsc/bin/xed"
    16  
    17  func testXedArch(t *testing.T, arch int, generate func(func([]byte))) {
    18  	if testing.Short() {
    19  		t.Skip("skipping libmach test in short mode")
    20  	}
    21  
    22  	if _, err := os.Stat(xedPath); err != nil {
    23  		t.Fatal(err)
    24  	}
    25  
    26  	testExtDis(t, "intel", arch, xed, generate, allowedMismatchXed)
    27  }
    28  
    29  func testXed32(t *testing.T, generate func(func([]byte))) {
    30  	testXedArch(t, 32, generate)
    31  }
    32  
    33  func testXed64(t *testing.T, generate func(func([]byte))) {
    34  	testXedArch(t, 64, generate)
    35  }
    36  
    37  func xed(ext *ExtDis) error {
    38  	b, err := ext.Run(xedPath, fmt.Sprintf("-%d", ext.Arch), "-n", "1G", "-ir", ext.File.Name())
    39  	if err != nil {
    40  		return err
    41  	}
    42  
    43  	nmatch := 0
    44  	next := uint32(start)
    45  	var (
    46  		addr   uint32
    47  		encbuf [32]byte
    48  		enc    []byte
    49  		text   string
    50  	)
    51  
    52  	var xedEnd = []byte("# end of text section")
    53  	var xedEnd1 = []byte("# Errors")
    54  
    55  	eof := false
    56  	for {
    57  		line, err := b.ReadSlice('\n')
    58  		if err != nil {
    59  			if err == io.EOF {
    60  				break
    61  			}
    62  			return fmt.Errorf("reading objdump output: %v", err)
    63  		}
    64  		if debug {
    65  			os.Stdout.Write(line)
    66  		}
    67  		if bytes.HasPrefix(line, xedEnd) || bytes.HasPrefix(line, xedEnd1) {
    68  			eof = true
    69  		}
    70  		if eof {
    71  			continue
    72  		}
    73  		nmatch++
    74  		addr, enc, text = parseLineXed(line, encbuf[:0])
    75  		if addr > next {
    76  			return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line)
    77  		}
    78  		if addr < next {
    79  			continue
    80  		}
    81  		switch text {
    82  		case "repz":
    83  			text = "rep"
    84  		case "repnz":
    85  			text = "repn"
    86  		default:
    87  			text = strings.Replace(text, "repz ", "rep ", -1)
    88  			text = strings.Replace(text, "repnz ", "repn ", -1)
    89  		}
    90  		if m := pcrelw.FindStringSubmatch(text); m != nil {
    91  			targ, _ := strconv.ParseUint(m[2], 16, 64)
    92  			text = fmt.Sprintf("%s .%+#x", m[1], int16(uint32(targ)-uint32(uint16(addr))-uint32(len(enc))))
    93  		}
    94  		if m := pcrel.FindStringSubmatch(text); m != nil {
    95  			targ, _ := strconv.ParseUint(m[2], 16, 64)
    96  			text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc))))
    97  		}
    98  		ext.Dec <- ExtInst{addr, encbuf, len(enc), text}
    99  		encbuf = [32]byte{}
   100  		enc = nil
   101  		next += 32
   102  	}
   103  	if next != start+uint32(ext.Size) {
   104  		return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size)
   105  	}
   106  	if err := ext.Wait(); err != nil {
   107  		return fmt.Errorf("exec: %v", err)
   108  	}
   109  
   110  	return nil
   111  }
   112  
   113  var (
   114  	xedInRaw    = []byte("In raw...")
   115  	xedDots     = []byte("...")
   116  	xdis        = []byte("XDIS ")
   117  	xedError    = []byte("ERROR: ")
   118  	xedNoDecode = []byte("Could not decode at offset: 0x")
   119  )
   120  
   121  func parseLineXed(line []byte, encstart []byte) (addr uint32, enc []byte, text string) {
   122  	oline := line
   123  	if bytes.HasPrefix(line, xedInRaw) || bytes.HasPrefix(line, xedDots) {
   124  		return 0, nil, ""
   125  	}
   126  	if bytes.HasPrefix(line, xedError) {
   127  		i := bytes.IndexByte(line[len(xedError):], ' ')
   128  		if i < 0 {
   129  			log.Fatalf("cannot parse error: %q", oline)
   130  		}
   131  		errstr := string(line[len(xedError):])
   132  		i = bytes.Index(line, xedNoDecode)
   133  		if i < 0 {
   134  			log.Fatalf("cannot parse error: %q", oline)
   135  		}
   136  		i += len(xedNoDecode)
   137  		j := bytes.IndexByte(line[i:], ' ')
   138  		if j < 0 {
   139  			log.Fatalf("cannot parse error: %q", oline)
   140  		}
   141  		x, err := strconv.ParseUint(string(trimSpace(line[i:i+j])), 16, 32)
   142  		if err != nil {
   143  			log.Fatalf("cannot parse disassembly: %q", oline)
   144  		}
   145  		addr = uint32(x)
   146  		return addr, nil, errstr
   147  	}
   148  
   149  	if !bytes.HasPrefix(line, xdis) {
   150  		log.Fatalf("cannot parse disassembly: %q", oline)
   151  	}
   152  
   153  	i := bytes.IndexByte(line, ':')
   154  	if i < 0 {
   155  		log.Fatalf("cannot parse disassembly: %q", oline)
   156  	}
   157  	x, err := strconv.ParseUint(string(trimSpace(line[len(xdis):i])), 16, 32)
   158  	if err != nil {
   159  		log.Fatalf("cannot parse disassembly: %q", oline)
   160  	}
   161  	addr = uint32(x)
   162  
   163  	// spaces
   164  	i++
   165  	for i < len(line) && line[i] == ' ' {
   166  		i++
   167  	}
   168  	// instruction class, spaces
   169  	for i < len(line) && line[i] != ' ' {
   170  		i++
   171  	}
   172  	for i < len(line) && line[i] == ' ' {
   173  		i++
   174  	}
   175  	// instruction set, spaces
   176  	for i < len(line) && line[i] != ' ' {
   177  		i++
   178  	}
   179  	for i < len(line) && line[i] == ' ' {
   180  		i++
   181  	}
   182  
   183  	// hex
   184  	hexStart := i
   185  	for i < len(line) && line[i] != ' ' {
   186  		i++
   187  	}
   188  	hexEnd := i
   189  	for i < len(line) && line[i] == ' ' {
   190  		i++
   191  	}
   192  
   193  	// text
   194  	textStart := i
   195  	for i < len(line) && line[i] != '\n' {
   196  		i++
   197  	}
   198  	textEnd := i
   199  
   200  	enc, ok := parseHex(line[hexStart:hexEnd], encstart)
   201  	if !ok {
   202  		log.Fatalf("cannot parse disassembly: %q", oline)
   203  	}
   204  
   205  	return addr, enc, string(fixSpace(line[textStart:textEnd]))
   206  }