cubefs

Форк
0
381 строка · 6.9 Кб
1
// Copyright 2014 The Go Authors.  All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4

5
package x86asm
6

7
import (
8
	"fmt"
9
	"strings"
10
)
11

12
type SymLookup func(uint64) (string, uint64)
13

14
// GoSyntax returns the Go assembler syntax for the instruction.
15
// The syntax was originally defined by Plan 9.
16
// The pc is the program counter of the instruction, used for expanding
17
// PC-relative addresses into absolute ones.
18
// The symname function queries the symbol table for the program
19
// being disassembled. Given a target address it returns the name and base
20
// address of the symbol containing the target, if any; otherwise it returns "", 0.
21
func GoSyntax(inst Inst, pc uint64, symname SymLookup) string {
22
	if symname == nil {
23
		symname = func(uint64) (string, uint64) { return "", 0 }
24
	}
25
	var args []string
26
	for i := len(inst.Args) - 1; i >= 0; i-- {
27
		a := inst.Args[i]
28
		if a == nil {
29
			continue
30
		}
31
		args = append(args, plan9Arg(&inst, pc, symname, a))
32
	}
33

34
	var rep string
35
	var last Prefix
36
	for _, p := range inst.Prefix {
37
		if p == 0 || p.IsREX() || p.IsVEX() {
38
			break
39
		}
40

41
		switch {
42
		// Don't show prefixes implied by the instruction text.
43
		case p&0xFF00 == PrefixImplicit:
44
			continue
45
		// Only REP and REPN are recognized repeaters. Plan 9 syntax
46
		// treats them as separate opcodes.
47
		case p&0xFF == PrefixREP:
48
			rep = "REP; "
49
		case p&0xFF == PrefixREPN:
50
			rep = "REPNE; "
51
		default:
52
			last = p
53
		}
54
	}
55

56
	prefix := ""
57
	switch last & 0xFF {
58
	case 0, 0x66, 0x67:
59
		// ignore
60
	default:
61
		prefix += last.String() + " "
62
	}
63

64
	op := inst.Op.String()
65
	if plan9Suffix[inst.Op] {
66
		s := inst.DataSize
67
		if inst.MemBytes != 0 {
68
			s = inst.MemBytes * 8
69
		}
70
		switch s {
71
		case 8:
72
			op += "B"
73
		case 16:
74
			op += "W"
75
		case 32:
76
			op += "L"
77
		case 64:
78
			op += "Q"
79
		}
80
	}
81

82
	if args != nil {
83
		op += " " + strings.Join(args, ", ")
84
	}
85

86
	return rep + prefix + op
87
}
88

89
func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
90
	switch a := arg.(type) {
91
	case Reg:
92
		return plan9Reg[a]
93
	case Rel:
94
		if pc == 0 {
95
			break
96
		}
97
		// If the absolute address is the start of a symbol, use the name.
98
		// Otherwise use the raw address, so that things like relative
99
		// jumps show up as JMP 0x123 instead of JMP f+10(SB).
100
		// It is usually easier to search for 0x123 than to do the mental
101
		// arithmetic to find f+10.
102
		addr := pc + uint64(inst.Len) + uint64(a)
103
		if s, base := symname(addr); s != "" && addr == base {
104
			return fmt.Sprintf("%s(SB)", s)
105
		}
106
		return fmt.Sprintf("%#x", addr)
107

108
	case Imm:
109
		if s, base := symname(uint64(a)); s != "" {
110
			suffix := ""
111
			if uint64(a) != base {
112
				suffix = fmt.Sprintf("%+d", uint64(a)-base)
113
			}
114
			return fmt.Sprintf("$%s%s(SB)", s, suffix)
115
		}
116
		if inst.Mode == 32 {
117
			return fmt.Sprintf("$%#x", uint32(a))
118
		}
119
		if Imm(int32(a)) == a {
120
			return fmt.Sprintf("$%#x", int64(a))
121
		}
122
		return fmt.Sprintf("$%#x", uint64(a))
123
	case Mem:
124
		if s, disp := memArgToSymbol(a, pc, inst.Len, symname); s != "" {
125
			suffix := ""
126
			if disp != 0 {
127
				suffix = fmt.Sprintf("%+d", disp)
128
			}
129
			return fmt.Sprintf("%s%s(SB)", s, suffix)
130
		}
131
		s := ""
132
		if a.Segment != 0 {
133
			s += fmt.Sprintf("%s:", plan9Reg[a.Segment])
134
		}
135
		if a.Disp != 0 {
136
			s += fmt.Sprintf("%#x", a.Disp)
137
		} else {
138
			s += "0"
139
		}
140
		if a.Base != 0 {
141
			s += fmt.Sprintf("(%s)", plan9Reg[a.Base])
142
		}
143
		if a.Index != 0 && a.Scale != 0 {
144
			s += fmt.Sprintf("(%s*%d)", plan9Reg[a.Index], a.Scale)
145
		}
146
		return s
147
	}
148
	return arg.String()
149
}
150

151
func memArgToSymbol(a Mem, pc uint64, instrLen int, symname SymLookup) (string, int64) {
152
	if a.Segment != 0 || a.Disp == 0 || a.Index != 0 || a.Scale != 0 {
153
		return "", 0
154
	}
155

156
	var disp uint64
157
	switch a.Base {
158
	case IP, EIP, RIP:
159
		disp = uint64(a.Disp + int64(pc) + int64(instrLen))
160
	case 0:
161
		disp = uint64(a.Disp)
162
	default:
163
		return "", 0
164
	}
165

166
	s, base := symname(disp)
167
	return s, int64(disp) - int64(base)
168
}
169

170
var plan9Suffix = [maxOp + 1]bool{
171
	ADC:       true,
172
	ADD:       true,
173
	AND:       true,
174
	BSF:       true,
175
	BSR:       true,
176
	BT:        true,
177
	BTC:       true,
178
	BTR:       true,
179
	BTS:       true,
180
	CMP:       true,
181
	CMPXCHG:   true,
182
	CVTSI2SD:  true,
183
	CVTSI2SS:  true,
184
	CVTSD2SI:  true,
185
	CVTSS2SI:  true,
186
	CVTTSD2SI: true,
187
	CVTTSS2SI: true,
188
	DEC:       true,
189
	DIV:       true,
190
	FLDENV:    true,
191
	FRSTOR:    true,
192
	IDIV:      true,
193
	IMUL:      true,
194
	IN:        true,
195
	INC:       true,
196
	LEA:       true,
197
	MOV:       true,
198
	MOVNTI:    true,
199
	MUL:       true,
200
	NEG:       true,
201
	NOP:       true,
202
	NOT:       true,
203
	OR:        true,
204
	OUT:       true,
205
	POP:       true,
206
	POPA:      true,
207
	PUSH:      true,
208
	PUSHA:     true,
209
	RCL:       true,
210
	RCR:       true,
211
	ROL:       true,
212
	ROR:       true,
213
	SAR:       true,
214
	SBB:       true,
215
	SHL:       true,
216
	SHLD:      true,
217
	SHR:       true,
218
	SHRD:      true,
219
	SUB:       true,
220
	TEST:      true,
221
	XADD:      true,
222
	XCHG:      true,
223
	XOR:       true,
224
}
225

226
var plan9Reg = [...]string{
227
	AL:   "AL",
228
	CL:   "CL",
229
	BL:   "BL",
230
	DL:   "DL",
231
	AH:   "AH",
232
	CH:   "CH",
233
	BH:   "BH",
234
	DH:   "DH",
235
	SPB:  "SP",
236
	BPB:  "BP",
237
	SIB:  "SI",
238
	DIB:  "DI",
239
	R8B:  "R8",
240
	R9B:  "R9",
241
	R10B: "R10",
242
	R11B: "R11",
243
	R12B: "R12",
244
	R13B: "R13",
245
	R14B: "R14",
246
	R15B: "R15",
247
	AX:   "AX",
248
	CX:   "CX",
249
	BX:   "BX",
250
	DX:   "DX",
251
	SP:   "SP",
252
	BP:   "BP",
253
	SI:   "SI",
254
	DI:   "DI",
255
	R8W:  "R8",
256
	R9W:  "R9",
257
	R10W: "R10",
258
	R11W: "R11",
259
	R12W: "R12",
260
	R13W: "R13",
261
	R14W: "R14",
262
	R15W: "R15",
263
	EAX:  "AX",
264
	ECX:  "CX",
265
	EDX:  "DX",
266
	EBX:  "BX",
267
	ESP:  "SP",
268
	EBP:  "BP",
269
	ESI:  "SI",
270
	EDI:  "DI",
271
	R8L:  "R8",
272
	R9L:  "R9",
273
	R10L: "R10",
274
	R11L: "R11",
275
	R12L: "R12",
276
	R13L: "R13",
277
	R14L: "R14",
278
	R15L: "R15",
279
	RAX:  "AX",
280
	RCX:  "CX",
281
	RDX:  "DX",
282
	RBX:  "BX",
283
	RSP:  "SP",
284
	RBP:  "BP",
285
	RSI:  "SI",
286
	RDI:  "DI",
287
	R8:   "R8",
288
	R9:   "R9",
289
	R10:  "R10",
290
	R11:  "R11",
291
	R12:  "R12",
292
	R13:  "R13",
293
	R14:  "R14",
294
	R15:  "R15",
295
	IP:   "IP",
296
	EIP:  "IP",
297
	RIP:  "IP",
298
	F0:   "F0",
299
	F1:   "F1",
300
	F2:   "F2",
301
	F3:   "F3",
302
	F4:   "F4",
303
	F5:   "F5",
304
	F6:   "F6",
305
	F7:   "F7",
306
	M0:   "M0",
307
	M1:   "M1",
308
	M2:   "M2",
309
	M3:   "M3",
310
	M4:   "M4",
311
	M5:   "M5",
312
	M6:   "M6",
313
	M7:   "M7",
314
	X0:   "X0",
315
	X1:   "X1",
316
	X2:   "X2",
317
	X3:   "X3",
318
	X4:   "X4",
319
	X5:   "X5",
320
	X6:   "X6",
321
	X7:   "X7",
322
	X8:   "X8",
323
	X9:   "X9",
324
	X10:  "X10",
325
	X11:  "X11",
326
	X12:  "X12",
327
	X13:  "X13",
328
	X14:  "X14",
329
	X15:  "X15",
330
	CS:   "CS",
331
	SS:   "SS",
332
	DS:   "DS",
333
	ES:   "ES",
334
	FS:   "FS",
335
	GS:   "GS",
336
	GDTR: "GDTR",
337
	IDTR: "IDTR",
338
	LDTR: "LDTR",
339
	MSW:  "MSW",
340
	TASK: "TASK",
341
	CR0:  "CR0",
342
	CR1:  "CR1",
343
	CR2:  "CR2",
344
	CR3:  "CR3",
345
	CR4:  "CR4",
346
	CR5:  "CR5",
347
	CR6:  "CR6",
348
	CR7:  "CR7",
349
	CR8:  "CR8",
350
	CR9:  "CR9",
351
	CR10: "CR10",
352
	CR11: "CR11",
353
	CR12: "CR12",
354
	CR13: "CR13",
355
	CR14: "CR14",
356
	CR15: "CR15",
357
	DR0:  "DR0",
358
	DR1:  "DR1",
359
	DR2:  "DR2",
360
	DR3:  "DR3",
361
	DR4:  "DR4",
362
	DR5:  "DR5",
363
	DR6:  "DR6",
364
	DR7:  "DR7",
365
	DR8:  "DR8",
366
	DR9:  "DR9",
367
	DR10: "DR10",
368
	DR11: "DR11",
369
	DR12: "DR12",
370
	DR13: "DR13",
371
	DR14: "DR14",
372
	DR15: "DR15",
373
	TR0:  "TR0",
374
	TR1:  "TR1",
375
	TR2:  "TR2",
376
	TR3:  "TR3",
377
	TR4:  "TR4",
378
	TR5:  "TR5",
379
	TR6:  "TR6",
380
	TR7:  "TR7",
381
}
382

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.