xref: /linux/tools/objtool/arch/x86/decode.c (revision 84e85359f4999a439aa12e04bf0ae9e13e00fc66)
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 #define CONFIG_64BIT 1
15 #include <asm/nops.h>
16 
17 #include <asm/orc_types.h>
18 #include <objtool/check.h>
19 #include <objtool/elf.h>
20 #include <objtool/arch.h>
21 #include <objtool/warn.h>
22 #include <objtool/endianness.h>
23 #include <objtool/builtin.h>
24 #include <arch/elf.h>
25 
26 static int is_x86_64(const struct elf *elf)
27 {
28 	switch (elf->ehdr.e_machine) {
29 	case EM_X86_64:
30 		return 1;
31 	case EM_386:
32 		return 0;
33 	default:
34 		WARN("unexpected ELF machine type %d", elf->ehdr.e_machine);
35 		return -1;
36 	}
37 }
38 
39 bool arch_callee_saved_reg(unsigned char reg)
40 {
41 	switch (reg) {
42 	case CFI_BP:
43 	case CFI_BX:
44 	case CFI_R12:
45 	case CFI_R13:
46 	case CFI_R14:
47 	case CFI_R15:
48 		return true;
49 
50 	case CFI_AX:
51 	case CFI_CX:
52 	case CFI_DX:
53 	case CFI_SI:
54 	case CFI_DI:
55 	case CFI_SP:
56 	case CFI_R8:
57 	case CFI_R9:
58 	case CFI_R10:
59 	case CFI_R11:
60 	case CFI_RA:
61 	default:
62 		return false;
63 	}
64 }
65 
66 unsigned long arch_dest_reloc_offset(int addend)
67 {
68 	return addend + 4;
69 }
70 
71 unsigned long arch_jump_destination(struct instruction *insn)
72 {
73 	return insn->offset + insn->len + insn->immediate;
74 }
75 
76 bool arch_pc_relative_reloc(struct reloc *reloc)
77 {
78 	/*
79 	 * All relocation types where P (the address of the target)
80 	 * is included in the computation.
81 	 */
82 	switch (reloc->type) {
83 	case R_X86_64_PC8:
84 	case R_X86_64_PC16:
85 	case R_X86_64_PC32:
86 	case R_X86_64_PC64:
87 
88 	case R_X86_64_PLT32:
89 	case R_X86_64_GOTPC32:
90 	case R_X86_64_GOTPCREL:
91 		return true;
92 
93 	default:
94 		break;
95 	}
96 
97 	return false;
98 }
99 
100 #define ADD_OP(op) \
101 	if (!(op = calloc(1, sizeof(*op)))) \
102 		return -1; \
103 	else for (list_add_tail(&op->list, ops_list); op; op = NULL)
104 
105 /*
106  * Helpers to decode ModRM/SIB:
107  *
108  * r/m| AX  CX  DX  BX |  SP |  BP |  SI  DI |
109  *    | R8  R9 R10 R11 | R12 | R13 | R14 R15 |
110  * Mod+----------------+-----+-----+---------+
111  * 00 |    [r/m]       |[SIB]|[IP+]|  [r/m]  |
112  * 01 |  [r/m + d8]    |[S+d]|   [r/m + d8]  |
113  * 10 |  [r/m + d32]   |[S+D]|   [r/m + d32] |
114  * 11 |                   r/ m               |
115  */
116 
117 #define mod_is_mem()	(modrm_mod != 3)
118 #define mod_is_reg()	(modrm_mod == 3)
119 
120 #define is_RIP()   ((modrm_rm & 7) == CFI_BP && modrm_mod == 0)
121 #define have_SIB() ((modrm_rm & 7) == CFI_SP && mod_is_mem())
122 
123 #define rm_is(reg) (have_SIB() ? \
124 		    sib_base == (reg) && sib_index == CFI_SP : \
125 		    modrm_rm == (reg))
126 
127 #define rm_is_mem(reg)	(mod_is_mem() && !is_RIP() && rm_is(reg))
128 #define rm_is_reg(reg)	(mod_is_reg() && modrm_rm == (reg))
129 
130 static bool has_notrack_prefix(struct insn *insn)
131 {
132 	int i;
133 
134 	for (i = 0; i < insn->prefixes.nbytes; i++) {
135 		if (insn->prefixes.bytes[i] == 0x3e)
136 			return true;
137 	}
138 
139 	return false;
140 }
141 
142 int arch_decode_instruction(struct objtool_file *file, const struct section *sec,
143 			    unsigned long offset, unsigned int maxlen,
144 			    unsigned int *len, enum insn_type *type,
145 			    unsigned long *immediate,
146 			    struct list_head *ops_list)
147 {
148 	const struct elf *elf = file->elf;
149 	struct insn insn;
150 	int x86_64, ret;
151 	unsigned char op1, op2, op3, prefix,
152 		      rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0,
153 		      modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0,
154 		      sib = 0, /* sib_scale = 0, */ sib_index = 0, sib_base = 0;
155 	struct stack_op *op = NULL;
156 	struct symbol *sym;
157 	u64 imm;
158 
159 	x86_64 = is_x86_64(elf);
160 	if (x86_64 == -1)
161 		return -1;
162 
163 	ret = insn_decode(&insn, sec->data->d_buf + offset, maxlen,
164 			  x86_64 ? INSN_MODE_64 : INSN_MODE_32);
165 	if (ret < 0) {
166 		WARN("can't decode instruction at %s:0x%lx", sec->name, offset);
167 		return -1;
168 	}
169 
170 	*len = insn.length;
171 	*type = INSN_OTHER;
172 
173 	if (insn.vex_prefix.nbytes)
174 		return 0;
175 
176 	prefix = insn.prefixes.bytes[0];
177 
178 	op1 = insn.opcode.bytes[0];
179 	op2 = insn.opcode.bytes[1];
180 	op3 = insn.opcode.bytes[2];
181 
182 	if (insn.rex_prefix.nbytes) {
183 		rex = insn.rex_prefix.bytes[0];
184 		rex_w = X86_REX_W(rex) >> 3;
185 		rex_r = X86_REX_R(rex) >> 2;
186 		rex_x = X86_REX_X(rex) >> 1;
187 		rex_b = X86_REX_B(rex);
188 	}
189 
190 	if (insn.modrm.nbytes) {
191 		modrm = insn.modrm.bytes[0];
192 		modrm_mod = X86_MODRM_MOD(modrm);
193 		modrm_reg = X86_MODRM_REG(modrm) + 8*rex_r;
194 		modrm_rm  = X86_MODRM_RM(modrm)  + 8*rex_b;
195 	}
196 
197 	if (insn.sib.nbytes) {
198 		sib = insn.sib.bytes[0];
199 		/* sib_scale = X86_SIB_SCALE(sib); */
200 		sib_index = X86_SIB_INDEX(sib) + 8*rex_x;
201 		sib_base  = X86_SIB_BASE(sib)  + 8*rex_b;
202 	}
203 
204 	switch (op1) {
205 
206 	case 0x1:
207 	case 0x29:
208 		if (rex_w && rm_is_reg(CFI_SP)) {
209 
210 			/* add/sub reg, %rsp */
211 			ADD_OP(op) {
212 				op->src.type = OP_SRC_ADD;
213 				op->src.reg = modrm_reg;
214 				op->dest.type = OP_DEST_REG;
215 				op->dest.reg = CFI_SP;
216 			}
217 		}
218 		break;
219 
220 	case 0x50 ... 0x57:
221 
222 		/* push reg */
223 		ADD_OP(op) {
224 			op->src.type = OP_SRC_REG;
225 			op->src.reg = (op1 & 0x7) + 8*rex_b;
226 			op->dest.type = OP_DEST_PUSH;
227 		}
228 
229 		break;
230 
231 	case 0x58 ... 0x5f:
232 
233 		/* pop reg */
234 		ADD_OP(op) {
235 			op->src.type = OP_SRC_POP;
236 			op->dest.type = OP_DEST_REG;
237 			op->dest.reg = (op1 & 0x7) + 8*rex_b;
238 		}
239 
240 		break;
241 
242 	case 0x68:
243 	case 0x6a:
244 		/* push immediate */
245 		ADD_OP(op) {
246 			op->src.type = OP_SRC_CONST;
247 			op->dest.type = OP_DEST_PUSH;
248 		}
249 		break;
250 
251 	case 0x70 ... 0x7f:
252 		*type = INSN_JUMP_CONDITIONAL;
253 		break;
254 
255 	case 0x80 ... 0x83:
256 		/*
257 		 * 1000 00sw : mod OP r/m : immediate
258 		 *
259 		 * s - sign extend immediate
260 		 * w - imm8 / imm32
261 		 *
262 		 * OP: 000 ADD    100 AND
263 		 *     001 OR     101 SUB
264 		 *     010 ADC    110 XOR
265 		 *     011 SBB    111 CMP
266 		 */
267 
268 		/* 64bit only */
269 		if (!rex_w)
270 			break;
271 
272 		/* %rsp target only */
273 		if (!rm_is_reg(CFI_SP))
274 			break;
275 
276 		imm = insn.immediate.value;
277 		if (op1 & 2) { /* sign extend */
278 			if (op1 & 1) { /* imm32 */
279 				imm <<= 32;
280 				imm = (s64)imm >> 32;
281 			} else { /* imm8 */
282 				imm <<= 56;
283 				imm = (s64)imm >> 56;
284 			}
285 		}
286 
287 		switch (modrm_reg & 7) {
288 		case 5:
289 			imm = -imm;
290 			/* fallthrough */
291 		case 0:
292 			/* add/sub imm, %rsp */
293 			ADD_OP(op) {
294 				op->src.type = OP_SRC_ADD;
295 				op->src.reg = CFI_SP;
296 				op->src.offset = imm;
297 				op->dest.type = OP_DEST_REG;
298 				op->dest.reg = CFI_SP;
299 			}
300 			break;
301 
302 		case 4:
303 			/* and imm, %rsp */
304 			ADD_OP(op) {
305 				op->src.type = OP_SRC_AND;
306 				op->src.reg = CFI_SP;
307 				op->src.offset = insn.immediate.value;
308 				op->dest.type = OP_DEST_REG;
309 				op->dest.reg = CFI_SP;
310 			}
311 			break;
312 
313 		default:
314 			/* WARN ? */
315 			break;
316 		}
317 
318 		break;
319 
320 	case 0x89:
321 		if (!rex_w)
322 			break;
323 
324 		if (modrm_reg == CFI_SP) {
325 
326 			if (mod_is_reg()) {
327 				/* mov %rsp, reg */
328 				ADD_OP(op) {
329 					op->src.type = OP_SRC_REG;
330 					op->src.reg = CFI_SP;
331 					op->dest.type = OP_DEST_REG;
332 					op->dest.reg = modrm_rm;
333 				}
334 				break;
335 
336 			} else {
337 				/* skip RIP relative displacement */
338 				if (is_RIP())
339 					break;
340 
341 				/* skip nontrivial SIB */
342 				if (have_SIB()) {
343 					modrm_rm = sib_base;
344 					if (sib_index != CFI_SP)
345 						break;
346 				}
347 
348 				/* mov %rsp, disp(%reg) */
349 				ADD_OP(op) {
350 					op->src.type = OP_SRC_REG;
351 					op->src.reg = CFI_SP;
352 					op->dest.type = OP_DEST_REG_INDIRECT;
353 					op->dest.reg = modrm_rm;
354 					op->dest.offset = insn.displacement.value;
355 				}
356 				break;
357 			}
358 
359 			break;
360 		}
361 
362 		if (rm_is_reg(CFI_SP)) {
363 
364 			/* mov reg, %rsp */
365 			ADD_OP(op) {
366 				op->src.type = OP_SRC_REG;
367 				op->src.reg = modrm_reg;
368 				op->dest.type = OP_DEST_REG;
369 				op->dest.reg = CFI_SP;
370 			}
371 			break;
372 		}
373 
374 		/* fallthrough */
375 	case 0x88:
376 		if (!rex_w)
377 			break;
378 
379 		if (rm_is_mem(CFI_BP)) {
380 
381 			/* mov reg, disp(%rbp) */
382 			ADD_OP(op) {
383 				op->src.type = OP_SRC_REG;
384 				op->src.reg = modrm_reg;
385 				op->dest.type = OP_DEST_REG_INDIRECT;
386 				op->dest.reg = CFI_BP;
387 				op->dest.offset = insn.displacement.value;
388 			}
389 			break;
390 		}
391 
392 		if (rm_is_mem(CFI_SP)) {
393 
394 			/* mov reg, disp(%rsp) */
395 			ADD_OP(op) {
396 				op->src.type = OP_SRC_REG;
397 				op->src.reg = modrm_reg;
398 				op->dest.type = OP_DEST_REG_INDIRECT;
399 				op->dest.reg = CFI_SP;
400 				op->dest.offset = insn.displacement.value;
401 			}
402 			break;
403 		}
404 
405 		break;
406 
407 	case 0x8b:
408 		if (!rex_w)
409 			break;
410 
411 		if (rm_is_mem(CFI_BP)) {
412 
413 			/* mov disp(%rbp), reg */
414 			ADD_OP(op) {
415 				op->src.type = OP_SRC_REG_INDIRECT;
416 				op->src.reg = CFI_BP;
417 				op->src.offset = insn.displacement.value;
418 				op->dest.type = OP_DEST_REG;
419 				op->dest.reg = modrm_reg;
420 			}
421 			break;
422 		}
423 
424 		if (rm_is_mem(CFI_SP)) {
425 
426 			/* mov disp(%rsp), reg */
427 			ADD_OP(op) {
428 				op->src.type = OP_SRC_REG_INDIRECT;
429 				op->src.reg = CFI_SP;
430 				op->src.offset = insn.displacement.value;
431 				op->dest.type = OP_DEST_REG;
432 				op->dest.reg = modrm_reg;
433 			}
434 			break;
435 		}
436 
437 		break;
438 
439 	case 0x8d:
440 		if (mod_is_reg()) {
441 			WARN("invalid LEA encoding at %s:0x%lx", sec->name, offset);
442 			break;
443 		}
444 
445 		/* skip non 64bit ops */
446 		if (!rex_w)
447 			break;
448 
449 		/* skip RIP relative displacement */
450 		if (is_RIP())
451 			break;
452 
453 		/* skip nontrivial SIB */
454 		if (have_SIB()) {
455 			modrm_rm = sib_base;
456 			if (sib_index != CFI_SP)
457 				break;
458 		}
459 
460 		/* lea disp(%src), %dst */
461 		ADD_OP(op) {
462 			op->src.offset = insn.displacement.value;
463 			if (!op->src.offset) {
464 				/* lea (%src), %dst */
465 				op->src.type = OP_SRC_REG;
466 			} else {
467 				/* lea disp(%src), %dst */
468 				op->src.type = OP_SRC_ADD;
469 			}
470 			op->src.reg = modrm_rm;
471 			op->dest.type = OP_DEST_REG;
472 			op->dest.reg = modrm_reg;
473 		}
474 		break;
475 
476 	case 0x8f:
477 		/* pop to mem */
478 		ADD_OP(op) {
479 			op->src.type = OP_SRC_POP;
480 			op->dest.type = OP_DEST_MEM;
481 		}
482 		break;
483 
484 	case 0x90:
485 		*type = INSN_NOP;
486 		break;
487 
488 	case 0x9c:
489 		/* pushf */
490 		ADD_OP(op) {
491 			op->src.type = OP_SRC_CONST;
492 			op->dest.type = OP_DEST_PUSHF;
493 		}
494 		break;
495 
496 	case 0x9d:
497 		/* popf */
498 		ADD_OP(op) {
499 			op->src.type = OP_SRC_POPF;
500 			op->dest.type = OP_DEST_MEM;
501 		}
502 		break;
503 
504 	case 0x0f:
505 
506 		if (op2 == 0x01) {
507 
508 			if (modrm == 0xca)
509 				*type = INSN_CLAC;
510 			else if (modrm == 0xcb)
511 				*type = INSN_STAC;
512 
513 		} else if (op2 >= 0x80 && op2 <= 0x8f) {
514 
515 			*type = INSN_JUMP_CONDITIONAL;
516 
517 		} else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 ||
518 			   op2 == 0x35) {
519 
520 			/* sysenter, sysret */
521 			*type = INSN_CONTEXT_SWITCH;
522 
523 		} else if (op2 == 0x0b || op2 == 0xb9) {
524 
525 			/* ud2 */
526 			*type = INSN_BUG;
527 
528 		} else if (op2 == 0x0d || op2 == 0x1f) {
529 
530 			/* nopl/nopw */
531 			*type = INSN_NOP;
532 
533 		} else if (op2 == 0x1e) {
534 
535 			if (prefix == 0xf3 && (modrm == 0xfa || modrm == 0xfb))
536 				*type = INSN_ENDBR;
537 
538 
539 		} else if (op2 == 0x38 && op3 == 0xf8) {
540 			if (insn.prefixes.nbytes == 1 &&
541 			    insn.prefixes.bytes[0] == 0xf2) {
542 				/* ENQCMD cannot be used in the kernel. */
543 				WARN("ENQCMD instruction at %s:%lx", sec->name,
544 				     offset);
545 			}
546 
547 		} else if (op2 == 0xa0 || op2 == 0xa8) {
548 
549 			/* push fs/gs */
550 			ADD_OP(op) {
551 				op->src.type = OP_SRC_CONST;
552 				op->dest.type = OP_DEST_PUSH;
553 			}
554 
555 		} else if (op2 == 0xa1 || op2 == 0xa9) {
556 
557 			/* pop fs/gs */
558 			ADD_OP(op) {
559 				op->src.type = OP_SRC_POP;
560 				op->dest.type = OP_DEST_MEM;
561 			}
562 		}
563 
564 		break;
565 
566 	case 0xc9:
567 		/*
568 		 * leave
569 		 *
570 		 * equivalent to:
571 		 * mov bp, sp
572 		 * pop bp
573 		 */
574 		ADD_OP(op) {
575 			op->src.type = OP_SRC_REG;
576 			op->src.reg = CFI_BP;
577 			op->dest.type = OP_DEST_REG;
578 			op->dest.reg = CFI_SP;
579 		}
580 		ADD_OP(op) {
581 			op->src.type = OP_SRC_POP;
582 			op->dest.type = OP_DEST_REG;
583 			op->dest.reg = CFI_BP;
584 		}
585 		break;
586 
587 	case 0xcc:
588 		/* int3 */
589 		*type = INSN_TRAP;
590 		break;
591 
592 	case 0xe3:
593 		/* jecxz/jrcxz */
594 		*type = INSN_JUMP_CONDITIONAL;
595 		break;
596 
597 	case 0xe9:
598 	case 0xeb:
599 		*type = INSN_JUMP_UNCONDITIONAL;
600 		break;
601 
602 	case 0xc2:
603 	case 0xc3:
604 		*type = INSN_RETURN;
605 		break;
606 
607 	case 0xc7: /* mov imm, r/m */
608 		if (!opts.noinstr)
609 			break;
610 
611 		if (insn.length == 3+4+4 && !strncmp(sec->name, ".init.text", 10)) {
612 			struct reloc *immr, *disp;
613 			struct symbol *func;
614 			int idx;
615 
616 			immr = find_reloc_by_dest(elf, (void *)sec, offset+3);
617 			disp = find_reloc_by_dest(elf, (void *)sec, offset+7);
618 
619 			if (!immr || strcmp(immr->sym->name, "pv_ops"))
620 				break;
621 
622 			idx = (immr->addend + 8) / sizeof(void *);
623 
624 			func = disp->sym;
625 			if (disp->sym->type == STT_SECTION)
626 				func = find_symbol_by_offset(disp->sym->sec, disp->addend);
627 			if (!func) {
628 				WARN("no func for pv_ops[]");
629 				return -1;
630 			}
631 
632 			objtool_pv_add(file, idx, func);
633 		}
634 
635 		break;
636 
637 	case 0xcf: /* iret */
638 		/*
639 		 * Handle sync_core(), which has an IRET to self.
640 		 * All other IRET are in STT_NONE entry code.
641 		 */
642 		sym = find_symbol_containing(sec, offset);
643 		if (sym && sym->type == STT_FUNC) {
644 			ADD_OP(op) {
645 				/* add $40, %rsp */
646 				op->src.type = OP_SRC_ADD;
647 				op->src.reg = CFI_SP;
648 				op->src.offset = 5*8;
649 				op->dest.type = OP_DEST_REG;
650 				op->dest.reg = CFI_SP;
651 			}
652 			break;
653 		}
654 
655 		/* fallthrough */
656 
657 	case 0xca: /* retf */
658 	case 0xcb: /* retf */
659 		*type = INSN_CONTEXT_SWITCH;
660 		break;
661 
662 	case 0xe0: /* loopne */
663 	case 0xe1: /* loope */
664 	case 0xe2: /* loop */
665 		*type = INSN_JUMP_CONDITIONAL;
666 		break;
667 
668 	case 0xe8:
669 		*type = INSN_CALL;
670 		/*
671 		 * For the impact on the stack, a CALL behaves like
672 		 * a PUSH of an immediate value (the return address).
673 		 */
674 		ADD_OP(op) {
675 			op->src.type = OP_SRC_CONST;
676 			op->dest.type = OP_DEST_PUSH;
677 		}
678 		break;
679 
680 	case 0xfc:
681 		*type = INSN_CLD;
682 		break;
683 
684 	case 0xfd:
685 		*type = INSN_STD;
686 		break;
687 
688 	case 0xff:
689 		if (modrm_reg == 2 || modrm_reg == 3) {
690 
691 			*type = INSN_CALL_DYNAMIC;
692 			if (has_notrack_prefix(&insn))
693 				WARN("notrack prefix found at %s:0x%lx", sec->name, offset);
694 
695 		} else if (modrm_reg == 4) {
696 
697 			*type = INSN_JUMP_DYNAMIC;
698 			if (has_notrack_prefix(&insn))
699 				WARN("notrack prefix found at %s:0x%lx", sec->name, offset);
700 
701 		} else if (modrm_reg == 5) {
702 
703 			/* jmpf */
704 			*type = INSN_CONTEXT_SWITCH;
705 
706 		} else if (modrm_reg == 6) {
707 
708 			/* push from mem */
709 			ADD_OP(op) {
710 				op->src.type = OP_SRC_CONST;
711 				op->dest.type = OP_DEST_PUSH;
712 			}
713 		}
714 
715 		break;
716 
717 	default:
718 		break;
719 	}
720 
721 	*immediate = insn.immediate.nbytes ? insn.immediate.value : 0;
722 
723 	return 0;
724 }
725 
726 void arch_initial_func_cfi_state(struct cfi_init_state *state)
727 {
728 	int i;
729 
730 	for (i = 0; i < CFI_NUM_REGS; i++) {
731 		state->regs[i].base = CFI_UNDEFINED;
732 		state->regs[i].offset = 0;
733 	}
734 
735 	/* initial CFA (call frame address) */
736 	state->cfa.base = CFI_SP;
737 	state->cfa.offset = 8;
738 
739 	/* initial RA (return address) */
740 	state->regs[CFI_RA].base = CFI_CFA;
741 	state->regs[CFI_RA].offset = -8;
742 }
743 
744 const char *arch_nop_insn(int len)
745 {
746 	static const char nops[5][5] = {
747 		{ BYTES_NOP1 },
748 		{ BYTES_NOP2 },
749 		{ BYTES_NOP3 },
750 		{ BYTES_NOP4 },
751 		{ BYTES_NOP5 },
752 	};
753 
754 	if (len < 1 || len > 5) {
755 		WARN("invalid NOP size: %d\n", len);
756 		return NULL;
757 	}
758 
759 	return nops[len-1];
760 }
761 
762 #define BYTE_RET	0xC3
763 
764 const char *arch_ret_insn(int len)
765 {
766 	static const char ret[5][5] = {
767 		{ BYTE_RET },
768 		{ BYTE_RET, 0xcc },
769 		{ BYTE_RET, 0xcc, BYTES_NOP1 },
770 		{ BYTE_RET, 0xcc, BYTES_NOP2 },
771 		{ BYTE_RET, 0xcc, BYTES_NOP3 },
772 	};
773 
774 	if (len < 1 || len > 5) {
775 		WARN("invalid RET size: %d\n", len);
776 		return NULL;
777 	}
778 
779 	return ret[len-1];
780 }
781 
782 int arch_decode_hint_reg(u8 sp_reg, int *base)
783 {
784 	switch (sp_reg) {
785 	case ORC_REG_UNDEFINED:
786 		*base = CFI_UNDEFINED;
787 		break;
788 	case ORC_REG_SP:
789 		*base = CFI_SP;
790 		break;
791 	case ORC_REG_BP:
792 		*base = CFI_BP;
793 		break;
794 	case ORC_REG_SP_INDIRECT:
795 		*base = CFI_SP_INDIRECT;
796 		break;
797 	case ORC_REG_R10:
798 		*base = CFI_R10;
799 		break;
800 	case ORC_REG_R13:
801 		*base = CFI_R13;
802 		break;
803 	case ORC_REG_DI:
804 		*base = CFI_DI;
805 		break;
806 	case ORC_REG_DX:
807 		*base = CFI_DX;
808 		break;
809 	default:
810 		return -1;
811 	}
812 
813 	return 0;
814 }
815 
816 bool arch_is_retpoline(struct symbol *sym)
817 {
818 	return !strncmp(sym->name, "__x86_indirect_", 15);
819 }
820 
821 bool arch_is_rethunk(struct symbol *sym)
822 {
823 	return !strcmp(sym->name, "__x86_return_thunk");
824 }
825