orc.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. #include <linux/objtool_types.h>
  3. #include <asm/orc_types.h>
  4. #include <objtool/check.h>
  5. #include <objtool/orc.h>
  6. #include <objtool/warn.h>
  7. #include <objtool/endianness.h>
  8. int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi, struct instruction *insn)
  9. {
  10. struct cfi_reg *bp = &cfi->regs[CFI_BP];
  11. memset(orc, 0, sizeof(*orc));
  12. if (!cfi) {
  13. /*
  14. * This is usually either unreachable nops/traps (which don't
  15. * trigger unreachable instruction warnings), or
  16. * STACK_FRAME_NON_STANDARD functions.
  17. */
  18. orc->type = ORC_TYPE_UNDEFINED;
  19. return 0;
  20. }
  21. switch (cfi->type) {
  22. case UNWIND_HINT_TYPE_UNDEFINED:
  23. orc->type = ORC_TYPE_UNDEFINED;
  24. return 0;
  25. case UNWIND_HINT_TYPE_END_OF_STACK:
  26. orc->type = ORC_TYPE_END_OF_STACK;
  27. return 0;
  28. case UNWIND_HINT_TYPE_CALL:
  29. orc->type = ORC_TYPE_CALL;
  30. break;
  31. case UNWIND_HINT_TYPE_REGS:
  32. orc->type = ORC_TYPE_REGS;
  33. break;
  34. case UNWIND_HINT_TYPE_REGS_PARTIAL:
  35. orc->type = ORC_TYPE_REGS_PARTIAL;
  36. break;
  37. default:
  38. WARN_INSN(insn, "unknown unwind hint type %d", cfi->type);
  39. return -1;
  40. }
  41. orc->signal = cfi->signal;
  42. switch (cfi->cfa.base) {
  43. case CFI_SP:
  44. orc->sp_reg = ORC_REG_SP;
  45. break;
  46. case CFI_SP_INDIRECT:
  47. orc->sp_reg = ORC_REG_SP_INDIRECT;
  48. break;
  49. case CFI_BP:
  50. orc->sp_reg = ORC_REG_BP;
  51. break;
  52. case CFI_BP_INDIRECT:
  53. orc->sp_reg = ORC_REG_BP_INDIRECT;
  54. break;
  55. case CFI_R10:
  56. orc->sp_reg = ORC_REG_R10;
  57. break;
  58. case CFI_R13:
  59. orc->sp_reg = ORC_REG_R13;
  60. break;
  61. case CFI_DI:
  62. orc->sp_reg = ORC_REG_DI;
  63. break;
  64. case CFI_DX:
  65. orc->sp_reg = ORC_REG_DX;
  66. break;
  67. default:
  68. WARN_INSN(insn, "unknown CFA base reg %d", cfi->cfa.base);
  69. return -1;
  70. }
  71. switch (bp->base) {
  72. case CFI_UNDEFINED:
  73. orc->bp_reg = ORC_REG_UNDEFINED;
  74. break;
  75. case CFI_CFA:
  76. orc->bp_reg = ORC_REG_PREV_SP;
  77. break;
  78. case CFI_BP:
  79. orc->bp_reg = ORC_REG_BP;
  80. break;
  81. default:
  82. WARN_INSN(insn, "unknown BP base reg %d", bp->base);
  83. return -1;
  84. }
  85. orc->sp_offset = cfi->cfa.offset;
  86. orc->bp_offset = bp->offset;
  87. return 0;
  88. }
  89. int write_orc_entry(struct elf *elf, struct section *orc_sec,
  90. struct section *ip_sec, unsigned int idx,
  91. struct section *insn_sec, unsigned long insn_off,
  92. struct orc_entry *o)
  93. {
  94. struct orc_entry *orc;
  95. /* populate ORC data */
  96. orc = (struct orc_entry *)orc_sec->data->d_buf + idx;
  97. memcpy(orc, o, sizeof(*orc));
  98. orc->sp_offset = bswap_if_needed(elf, orc->sp_offset);
  99. orc->bp_offset = bswap_if_needed(elf, orc->bp_offset);
  100. /* populate reloc for ip */
  101. if (!elf_init_reloc_text_sym(elf, ip_sec, idx * sizeof(int), idx,
  102. insn_sec, insn_off))
  103. return -1;
  104. return 0;
  105. }
  106. static const char *reg_name(unsigned int reg)
  107. {
  108. switch (reg) {
  109. case ORC_REG_PREV_SP:
  110. return "prevsp";
  111. case ORC_REG_DX:
  112. return "dx";
  113. case ORC_REG_DI:
  114. return "di";
  115. case ORC_REG_BP:
  116. return "bp";
  117. case ORC_REG_SP:
  118. return "sp";
  119. case ORC_REG_R10:
  120. return "r10";
  121. case ORC_REG_R13:
  122. return "r13";
  123. case ORC_REG_BP_INDIRECT:
  124. return "bp(ind)";
  125. case ORC_REG_SP_INDIRECT:
  126. return "sp(ind)";
  127. default:
  128. return "?";
  129. }
  130. }
  131. static const char *orc_type_name(unsigned int type)
  132. {
  133. switch (type) {
  134. case ORC_TYPE_UNDEFINED:
  135. return "(und)";
  136. case ORC_TYPE_END_OF_STACK:
  137. return "end";
  138. case ORC_TYPE_CALL:
  139. return "call";
  140. case ORC_TYPE_REGS:
  141. return "regs";
  142. case ORC_TYPE_REGS_PARTIAL:
  143. return "regs (partial)";
  144. default:
  145. return "?";
  146. }
  147. }
  148. static void print_reg(unsigned int reg, int offset)
  149. {
  150. if (reg == ORC_REG_BP_INDIRECT)
  151. printf("(bp%+d)", offset);
  152. else if (reg == ORC_REG_SP_INDIRECT)
  153. printf("(sp)%+d", offset);
  154. else if (reg == ORC_REG_UNDEFINED)
  155. printf("(und)");
  156. else
  157. printf("%s%+d", reg_name(reg), offset);
  158. }
  159. void orc_print_dump(struct elf *dummy_elf, struct orc_entry *orc, int i)
  160. {
  161. printf("type:%s", orc_type_name(orc[i].type));
  162. printf(" sp:");
  163. print_reg(orc[i].sp_reg, bswap_if_needed(dummy_elf, orc[i].sp_offset));
  164. printf(" bp:");
  165. print_reg(orc[i].bp_reg, bswap_if_needed(dummy_elf, orc[i].bp_offset));
  166. printf(" signal:%d\n", orc[i].signal);
  167. }