...

Source file src/golang.org/x/arch/x86/x86asm/xedext_test.go

Documentation: golang.org/x/arch/x86/x86asm

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

View as plain text