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