decode.c 16 KB

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