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 }