• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
4  */
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 
9 #define unlikely(cond) (cond)
10 #include <asm/insn.h>
11 #include "../../../arch/x86/lib/inat.c"
12 #include "../../../arch/x86/lib/insn.c"
13 
14 #include "../../check.h"
15 #include "../../elf.h"
16 #include "../../arch.h"
17 #include "../../warn.h"
18 #include <asm/orc_types.h>
19 #include "arch_elf.h"
20 
21 static unsigned char op_to_cfi_reg[][2] = {
22 	{CFI_AX, CFI_R8},
23 	{CFI_CX, CFI_R9},
24 	{CFI_DX, CFI_R10},
25 	{CFI_BX, CFI_R11},
26 	{CFI_SP, CFI_R12},
27 	{CFI_BP, CFI_R13},
28 	{CFI_SI, CFI_R14},
29 	{CFI_DI, CFI_R15},
30 };
31 
is_x86_64(const struct elf * elf)32 static int is_x86_64(const struct elf *elf)
33 {
34 	switch (elf->ehdr.e_machine) {
35 	case EM_X86_64:
36 		return 1;
37 	case EM_386:
38 		return 0;
39 	default:
40 		WARN("unexpected ELF machine type %d", elf->ehdr.e_machine);
41 		return -1;
42 	}
43 }
44 
arch_callee_saved_reg(unsigned char reg)45 bool arch_callee_saved_reg(unsigned char reg)
46 {
47 	switch (reg) {
48 	case CFI_BP:
49 	case CFI_BX:
50 	case CFI_R12:
51 	case CFI_R13:
52 	case CFI_R14:
53 	case CFI_R15:
54 		return true;
55 
56 	case CFI_AX:
57 	case CFI_CX:
58 	case CFI_DX:
59 	case CFI_SI:
60 	case CFI_DI:
61 	case CFI_SP:
62 	case CFI_R8:
63 	case CFI_R9:
64 	case CFI_R10:
65 	case CFI_R11:
66 	case CFI_RA:
67 	default:
68 		return false;
69 	}
70 }
71 
arch_dest_reloc_offset(int addend)72 unsigned long arch_dest_reloc_offset(int addend)
73 {
74 	return addend + 4;
75 }
76 
arch_jump_destination(struct instruction * insn)77 unsigned long arch_jump_destination(struct instruction *insn)
78 {
79 	return insn->offset + insn->len + insn->immediate;
80 }
81 
82 #define ADD_OP(op) \
83 	if (!(op = calloc(1, sizeof(*op)))) \
84 		return -1; \
85 	else for (list_add_tail(&op->list, ops_list); op; op = NULL)
86 
arch_decode_instruction(const struct elf * elf,const struct section * sec,unsigned long offset,unsigned int maxlen,unsigned int * len,enum insn_type * type,unsigned long * immediate,struct list_head * ops_list)87 int arch_decode_instruction(const struct elf *elf, const struct section *sec,
88 			    unsigned long offset, unsigned int maxlen,
89 			    unsigned int *len, enum insn_type *type,
90 			    unsigned long *immediate,
91 			    struct list_head *ops_list)
92 {
93 	struct insn insn;
94 	int x86_64, sign;
95 	unsigned char op1, op2, rex = 0, rex_b = 0, rex_r = 0, rex_w = 0,
96 		      rex_x = 0, modrm = 0, modrm_mod = 0, modrm_rm = 0,
97 		      modrm_reg = 0, sib = 0;
98 	struct stack_op *op = NULL;
99 	struct symbol *sym;
100 
101 	x86_64 = is_x86_64(elf);
102 	if (x86_64 == -1)
103 		return -1;
104 
105 	insn_init(&insn, sec->data->d_buf + offset, maxlen, x86_64);
106 	insn_get_length(&insn);
107 
108 	if (!insn_complete(&insn)) {
109 		WARN("can't decode instruction at %s:0x%lx", sec->name, offset);
110 		return -1;
111 	}
112 
113 	*len = insn.length;
114 	*type = INSN_OTHER;
115 
116 	if (insn.vex_prefix.nbytes)
117 		return 0;
118 
119 	op1 = insn.opcode.bytes[0];
120 	op2 = insn.opcode.bytes[1];
121 
122 	if (insn.rex_prefix.nbytes) {
123 		rex = insn.rex_prefix.bytes[0];
124 		rex_w = X86_REX_W(rex) >> 3;
125 		rex_r = X86_REX_R(rex) >> 2;
126 		rex_x = X86_REX_X(rex) >> 1;
127 		rex_b = X86_REX_B(rex);
128 	}
129 
130 	if (insn.modrm.nbytes) {
131 		modrm = insn.modrm.bytes[0];
132 		modrm_mod = X86_MODRM_MOD(modrm);
133 		modrm_reg = X86_MODRM_REG(modrm);
134 		modrm_rm = X86_MODRM_RM(modrm);
135 	}
136 
137 	if (insn.sib.nbytes)
138 		sib = insn.sib.bytes[0];
139 
140 	switch (op1) {
141 
142 	case 0x1:
143 	case 0x29:
144 		if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) {
145 
146 			/* add/sub reg, %rsp */
147 			ADD_OP(op) {
148 				op->src.type = OP_SRC_ADD;
149 				op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
150 				op->dest.type = OP_DEST_REG;
151 				op->dest.reg = CFI_SP;
152 			}
153 		}
154 		break;
155 
156 	case 0x50 ... 0x57:
157 
158 		/* push reg */
159 		ADD_OP(op) {
160 			op->src.type = OP_SRC_REG;
161 			op->src.reg = op_to_cfi_reg[op1 & 0x7][rex_b];
162 			op->dest.type = OP_DEST_PUSH;
163 		}
164 
165 		break;
166 
167 	case 0x58 ... 0x5f:
168 
169 		/* pop reg */
170 		ADD_OP(op) {
171 			op->src.type = OP_SRC_POP;
172 			op->dest.type = OP_DEST_REG;
173 			op->dest.reg = op_to_cfi_reg[op1 & 0x7][rex_b];
174 		}
175 
176 		break;
177 
178 	case 0x68:
179 	case 0x6a:
180 		/* push immediate */
181 		ADD_OP(op) {
182 			op->src.type = OP_SRC_CONST;
183 			op->dest.type = OP_DEST_PUSH;
184 		}
185 		break;
186 
187 	case 0x70 ... 0x7f:
188 		*type = INSN_JUMP_CONDITIONAL;
189 		break;
190 
191 	case 0x81:
192 	case 0x83:
193 		if (rex != 0x48)
194 			break;
195 
196 		if (modrm == 0xe4) {
197 			/* and imm, %rsp */
198 			ADD_OP(op) {
199 				op->src.type = OP_SRC_AND;
200 				op->src.reg = CFI_SP;
201 				op->src.offset = insn.immediate.value;
202 				op->dest.type = OP_DEST_REG;
203 				op->dest.reg = CFI_SP;
204 			}
205 			break;
206 		}
207 
208 		if (modrm == 0xc4)
209 			sign = 1;
210 		else if (modrm == 0xec)
211 			sign = -1;
212 		else
213 			break;
214 
215 		/* add/sub imm, %rsp */
216 		ADD_OP(op) {
217 			op->src.type = OP_SRC_ADD;
218 			op->src.reg = CFI_SP;
219 			op->src.offset = insn.immediate.value * sign;
220 			op->dest.type = OP_DEST_REG;
221 			op->dest.reg = CFI_SP;
222 		}
223 		break;
224 
225 	case 0x89:
226 		if (rex_w && !rex_r && modrm_mod == 3 && modrm_reg == 4) {
227 
228 			/* mov %rsp, reg */
229 			ADD_OP(op) {
230 				op->src.type = OP_SRC_REG;
231 				op->src.reg = CFI_SP;
232 				op->dest.type = OP_DEST_REG;
233 				op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
234 			}
235 			break;
236 		}
237 
238 		if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) {
239 
240 			/* mov reg, %rsp */
241 			ADD_OP(op) {
242 				op->src.type = OP_SRC_REG;
243 				op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
244 				op->dest.type = OP_DEST_REG;
245 				op->dest.reg = CFI_SP;
246 			}
247 			break;
248 		}
249 
250 		/* fallthrough */
251 	case 0x88:
252 		if (!rex_b &&
253 		    (modrm_mod == 1 || modrm_mod == 2) && modrm_rm == 5) {
254 
255 			/* mov reg, disp(%rbp) */
256 			ADD_OP(op) {
257 				op->src.type = OP_SRC_REG;
258 				op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
259 				op->dest.type = OP_DEST_REG_INDIRECT;
260 				op->dest.reg = CFI_BP;
261 				op->dest.offset = insn.displacement.value;
262 			}
263 
264 		} else if (rex_w && !rex_b && modrm_rm == 4 && sib == 0x24) {
265 
266 			/* mov reg, disp(%rsp) */
267 			ADD_OP(op) {
268 				op->src.type = OP_SRC_REG;
269 				op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
270 				op->dest.type = OP_DEST_REG_INDIRECT;
271 				op->dest.reg = CFI_SP;
272 				op->dest.offset = insn.displacement.value;
273 			}
274 		}
275 
276 		break;
277 
278 	case 0x8b:
279 		if (rex_w && !rex_b && modrm_mod == 1 && modrm_rm == 5) {
280 
281 			/* mov disp(%rbp), reg */
282 			ADD_OP(op) {
283 				op->src.type = OP_SRC_REG_INDIRECT;
284 				op->src.reg = CFI_BP;
285 				op->src.offset = insn.displacement.value;
286 				op->dest.type = OP_DEST_REG;
287 				op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
288 			}
289 
290 		} else if (rex_w && !rex_b && sib == 0x24 &&
291 			   modrm_mod != 3 && modrm_rm == 4) {
292 
293 			/* mov disp(%rsp), reg */
294 			ADD_OP(op) {
295 				op->src.type = OP_SRC_REG_INDIRECT;
296 				op->src.reg = CFI_SP;
297 				op->src.offset = insn.displacement.value;
298 				op->dest.type = OP_DEST_REG;
299 				op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
300 			}
301 		}
302 
303 		break;
304 
305 	case 0x8d:
306 		if (sib == 0x24 && rex_w && !rex_b && !rex_x) {
307 
308 			ADD_OP(op) {
309 				if (!insn.displacement.value) {
310 					/* lea (%rsp), reg */
311 					op->src.type = OP_SRC_REG;
312 				} else {
313 					/* lea disp(%rsp), reg */
314 					op->src.type = OP_SRC_ADD;
315 					op->src.offset = insn.displacement.value;
316 				}
317 				op->src.reg = CFI_SP;
318 				op->dest.type = OP_DEST_REG;
319 				op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
320 			}
321 
322 		} else if (rex == 0x48 && modrm == 0x65) {
323 
324 			/* lea disp(%rbp), %rsp */
325 			ADD_OP(op) {
326 				op->src.type = OP_SRC_ADD;
327 				op->src.reg = CFI_BP;
328 				op->src.offset = insn.displacement.value;
329 				op->dest.type = OP_DEST_REG;
330 				op->dest.reg = CFI_SP;
331 			}
332 
333 		} else if (rex == 0x49 && modrm == 0x62 &&
334 			   insn.displacement.value == -8) {
335 
336 			/*
337 			 * lea -0x8(%r10), %rsp
338 			 *
339 			 * Restoring rsp back to its original value after a
340 			 * stack realignment.
341 			 */
342 			ADD_OP(op) {
343 				op->src.type = OP_SRC_ADD;
344 				op->src.reg = CFI_R10;
345 				op->src.offset = -8;
346 				op->dest.type = OP_DEST_REG;
347 				op->dest.reg = CFI_SP;
348 			}
349 
350 		} else if (rex == 0x49 && modrm == 0x65 &&
351 			   insn.displacement.value == -16) {
352 
353 			/*
354 			 * lea -0x10(%r13), %rsp
355 			 *
356 			 * Restoring rsp back to its original value after a
357 			 * stack realignment.
358 			 */
359 			ADD_OP(op) {
360 				op->src.type = OP_SRC_ADD;
361 				op->src.reg = CFI_R13;
362 				op->src.offset = -16;
363 				op->dest.type = OP_DEST_REG;
364 				op->dest.reg = CFI_SP;
365 			}
366 		}
367 
368 		break;
369 
370 	case 0x8f:
371 		/* pop to mem */
372 		ADD_OP(op) {
373 			op->src.type = OP_SRC_POP;
374 			op->dest.type = OP_DEST_MEM;
375 		}
376 		break;
377 
378 	case 0x90:
379 		*type = INSN_NOP;
380 		break;
381 
382 	case 0x9c:
383 		/* pushf */
384 		ADD_OP(op) {
385 			op->src.type = OP_SRC_CONST;
386 			op->dest.type = OP_DEST_PUSHF;
387 		}
388 		break;
389 
390 	case 0x9d:
391 		/* popf */
392 		ADD_OP(op) {
393 			op->src.type = OP_SRC_POPF;
394 			op->dest.type = OP_DEST_MEM;
395 		}
396 		break;
397 
398 	case 0x0f:
399 
400 		if (op2 == 0x01) {
401 
402 			if (modrm == 0xca)
403 				*type = INSN_CLAC;
404 			else if (modrm == 0xcb)
405 				*type = INSN_STAC;
406 
407 		} else if (op2 >= 0x80 && op2 <= 0x8f) {
408 
409 			*type = INSN_JUMP_CONDITIONAL;
410 
411 		} else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 ||
412 			   op2 == 0x35) {
413 
414 			/* sysenter, sysret */
415 			*type = INSN_CONTEXT_SWITCH;
416 
417 		} else if (op2 == 0x0b || op2 == 0xb9) {
418 
419 			/* ud2 */
420 			*type = INSN_BUG;
421 
422 		} else if (op2 == 0x0d || op2 == 0x1f) {
423 
424 			/* nopl/nopw */
425 			*type = INSN_NOP;
426 
427 		} else if (op2 == 0xa0 || op2 == 0xa8) {
428 
429 			/* push fs/gs */
430 			ADD_OP(op) {
431 				op->src.type = OP_SRC_CONST;
432 				op->dest.type = OP_DEST_PUSH;
433 			}
434 
435 		} else if (op2 == 0xa1 || op2 == 0xa9) {
436 
437 			/* pop fs/gs */
438 			ADD_OP(op) {
439 				op->src.type = OP_SRC_POP;
440 				op->dest.type = OP_DEST_MEM;
441 			}
442 		}
443 
444 		break;
445 
446 	case 0xc9:
447 		/*
448 		 * leave
449 		 *
450 		 * equivalent to:
451 		 * mov bp, sp
452 		 * pop bp
453 		 */
454 		ADD_OP(op)
455 			op->dest.type = OP_DEST_LEAVE;
456 
457 		break;
458 
459 	case 0xcc:
460 		/* int3 */
461 		*type = INSN_TRAP;
462 		break;
463 
464 	case 0xe3:
465 		/* jecxz/jrcxz */
466 		*type = INSN_JUMP_CONDITIONAL;
467 		break;
468 
469 	case 0xe9:
470 	case 0xeb:
471 		*type = INSN_JUMP_UNCONDITIONAL;
472 		break;
473 
474 	case 0xc2:
475 	case 0xc3:
476 		*type = INSN_RETURN;
477 		break;
478 
479 	case 0xcf: /* iret */
480 		/*
481 		 * Handle sync_core(), which has an IRET to self.
482 		 * All other IRET are in STT_NONE entry code.
483 		 */
484 		sym = find_symbol_containing(sec, offset);
485 		if (sym && sym->type == STT_FUNC) {
486 			ADD_OP(op) {
487 				/* add $40, %rsp */
488 				op->src.type = OP_SRC_ADD;
489 				op->src.reg = CFI_SP;
490 				op->src.offset = 5*8;
491 				op->dest.type = OP_DEST_REG;
492 				op->dest.reg = CFI_SP;
493 			}
494 			break;
495 		}
496 
497 		/* fallthrough */
498 
499 	case 0xca: /* retf */
500 	case 0xcb: /* retf */
501 		*type = INSN_CONTEXT_SWITCH;
502 		break;
503 
504 	case 0xe8:
505 		*type = INSN_CALL;
506 		/*
507 		 * For the impact on the stack, a CALL behaves like
508 		 * a PUSH of an immediate value (the return address).
509 		 */
510 		ADD_OP(op) {
511 			op->src.type = OP_SRC_CONST;
512 			op->dest.type = OP_DEST_PUSH;
513 		}
514 		break;
515 
516 	case 0xfc:
517 		*type = INSN_CLD;
518 		break;
519 
520 	case 0xfd:
521 		*type = INSN_STD;
522 		break;
523 
524 	case 0xff:
525 		if (modrm_reg == 2 || modrm_reg == 3)
526 
527 			*type = INSN_CALL_DYNAMIC;
528 
529 		else if (modrm_reg == 4)
530 
531 			*type = INSN_JUMP_DYNAMIC;
532 
533 		else if (modrm_reg == 5)
534 
535 			/* jmpf */
536 			*type = INSN_CONTEXT_SWITCH;
537 
538 		else if (modrm_reg == 6) {
539 
540 			/* push from mem */
541 			ADD_OP(op) {
542 				op->src.type = OP_SRC_CONST;
543 				op->dest.type = OP_DEST_PUSH;
544 			}
545 		}
546 
547 		break;
548 
549 	default:
550 		break;
551 	}
552 
553 	*immediate = insn.immediate.nbytes ? insn.immediate.value : 0;
554 
555 	return 0;
556 }
557 
arch_initial_func_cfi_state(struct cfi_init_state * state)558 void arch_initial_func_cfi_state(struct cfi_init_state *state)
559 {
560 	int i;
561 
562 	for (i = 0; i < CFI_NUM_REGS; i++) {
563 		state->regs[i].base = CFI_UNDEFINED;
564 		state->regs[i].offset = 0;
565 	}
566 
567 	/* initial CFA (call frame address) */
568 	state->cfa.base = CFI_SP;
569 	state->cfa.offset = 8;
570 
571 	/* initial RA (return address) */
572 	state->regs[CFI_RA].base = CFI_CFA;
573 	state->regs[CFI_RA].offset = -8;
574 }
575 
arch_nop_insn(int len)576 const char *arch_nop_insn(int len)
577 {
578 	static const char nops[5][5] = {
579 		/* 1 */ { 0x90 },
580 		/* 2 */ { 0x66, 0x90 },
581 		/* 3 */ { 0x0f, 0x1f, 0x00 },
582 		/* 4 */ { 0x0f, 0x1f, 0x40, 0x00 },
583 		/* 5 */ { 0x0f, 0x1f, 0x44, 0x00, 0x00 },
584 	};
585 
586 	if (len < 1 || len > 5) {
587 		WARN("invalid NOP size: %d\n", len);
588 		return NULL;
589 	}
590 
591 	return nops[len-1];
592 }
593 
594 #define BYTE_RET	0xC3
595 
arch_ret_insn(int len)596 const char *arch_ret_insn(int len)
597 {
598 	static const char ret[5][5] = {
599 		{ BYTE_RET },
600 		{ BYTE_RET, 0xcc },
601 		{ BYTE_RET, 0xcc, 0x90 },
602 		{ BYTE_RET, 0xcc, 0x66, 0x90 },
603 		{ BYTE_RET, 0xcc, 0x0f, 0x1f, 0x00 },
604 	};
605 
606 	if (len < 1 || len > 5) {
607 		WARN("invalid RET size: %d\n", len);
608 		return NULL;
609 	}
610 
611 	return ret[len-1];
612 }
613 
arch_decode_hint_reg(u8 sp_reg,int * base)614 int arch_decode_hint_reg(u8 sp_reg, int *base)
615 {
616 	switch (sp_reg) {
617 	case ORC_REG_UNDEFINED:
618 		*base = CFI_UNDEFINED;
619 		break;
620 	case ORC_REG_SP:
621 		*base = CFI_SP;
622 		break;
623 	case ORC_REG_BP:
624 		*base = CFI_BP;
625 		break;
626 	case ORC_REG_SP_INDIRECT:
627 		*base = CFI_SP_INDIRECT;
628 		break;
629 	case ORC_REG_R10:
630 		*base = CFI_R10;
631 		break;
632 	case ORC_REG_R13:
633 		*base = CFI_R13;
634 		break;
635 	case ORC_REG_DI:
636 		*base = CFI_DI;
637 		break;
638 	case ORC_REG_DX:
639 		*base = CFI_DX;
640 		break;
641 	default:
642 		return -1;
643 	}
644 
645 	return 0;
646 }
647 
arch_is_retpoline(struct symbol * sym)648 bool arch_is_retpoline(struct symbol *sym)
649 {
650 	return !strncmp(sym->name, "__x86_indirect_", 15);
651 }
652 
arch_is_rethunk(struct symbol * sym)653 bool arch_is_rethunk(struct symbol *sym)
654 {
655 	return !strcmp(sym->name, "__x86_return_thunk");
656 }
657