Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

objtool/x86: Separate arch-specific and generic parts

Move init_orc_entry(), write_orc_entry(), reg_name(), orc_type_name()
and print_reg() from generic orc_gen.c and orc_dump.c to arch-specific
orc.c, then introduce a new function orc_print_dump() to print info.

This is preparation for later patch, no functionality change.

Co-developed-by: Jinyang He <hejinyang@loongson.cn>
Signed-off-by: Jinyang He <hejinyang@loongson.cn>
Co-developed-by: Youling Tang <tangyouling@loongson.cn>
Signed-off-by: Youling Tang <tangyouling@loongson.cn>
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>

authored by

Tiezhu Yang and committed by
Huacai Chen
b8e85e6f b2d23158

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