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