podman

Форк
0
392 строки · 7.2 Кб
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
		} else if inst.Args[1] == nil { // look for register-only 64-bit instruction, like PUSHQ AX
70
			if r, ok := inst.Args[0].(Reg); ok && RAX <= r && r <= R15 {
71
				s = 64
72
			}
73
		}
74
		switch s {
75
		case 8:
76
			op += "B"
77
		case 16:
78
			op += "W"
79
		case 32:
80
			op += "L"
81
		case 64:
82
			op += "Q"
83
		}
84
	}
85

86
	if inst.Op == CMP {
87
		// Use reads-left-to-right ordering for comparisons.
88
		// See issue 60920.
89
		args[0], args[1] = args[1], args[0]
90
	}
91

92
	if args != nil {
93
		op += " " + strings.Join(args, ", ")
94
	}
95

96
	return rep + prefix + op
97
}
98

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

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

161
func memArgToSymbol(a Mem, pc uint64, instrLen int, symname SymLookup) (string, int64) {
162
	if a.Segment != 0 || a.Disp == 0 || a.Index != 0 || a.Scale != 0 {
163
		return "", 0
164
	}
165

166
	var disp uint64
167
	switch a.Base {
168
	case IP, EIP, RIP:
169
		disp = uint64(a.Disp + int64(pc) + int64(instrLen))
170
	case 0:
171
		disp = uint64(a.Disp)
172
	default:
173
		return "", 0
174
	}
175

176
	s, base := symname(disp)
177
	return s, int64(disp) - int64(base)
178
}
179

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

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

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

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

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

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