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