diff options
Diffstat (limited to 'tools/objtool/orc_gen.c')
| -rw-r--r-- | tools/objtool/orc_gen.c | 117 |
1 files changed, 11 insertions, 106 deletions
diff --git a/tools/objtool/orc_gen.c b/tools/objtool/orc_gen.c index 1f22b7ebae58..1045e1380ffd 100644 --- a/tools/objtool/orc_gen.c +++ b/tools/objtool/orc_gen.c @@ -6,107 +6,12 @@ #include <stdlib.h> #include <string.h> -#include <linux/objtool.h> +#include <linux/objtool_types.h> #include <asm/orc_types.h> #include <objtool/check.h> +#include <objtool/orc.h> #include <objtool/warn.h> -#include <objtool/endianness.h> - -static int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi, - struct instruction *insn) -{ - struct cfi_reg *bp = &cfi->regs[CFI_BP]; - - memset(orc, 0, sizeof(*orc)); - - if (!cfi) { - orc->end = 0; - orc->sp_reg = ORC_REG_UNDEFINED; - return 0; - } - - orc->end = cfi->end; - - if (cfi->cfa.base == CFI_UNDEFINED) { - orc->sp_reg = ORC_REG_UNDEFINED; - return 0; - } - - switch (cfi->cfa.base) { - case CFI_SP: - orc->sp_reg = ORC_REG_SP; - break; - case CFI_SP_INDIRECT: - orc->sp_reg = ORC_REG_SP_INDIRECT; - break; - case CFI_BP: - orc->sp_reg = ORC_REG_BP; - break; - case CFI_BP_INDIRECT: - orc->sp_reg = ORC_REG_BP_INDIRECT; - break; - case CFI_R10: - orc->sp_reg = ORC_REG_R10; - break; - case CFI_R13: - orc->sp_reg = ORC_REG_R13; - break; - case CFI_DI: - orc->sp_reg = ORC_REG_DI; - break; - case CFI_DX: - orc->sp_reg = ORC_REG_DX; - break; - default: - WARN_FUNC("unknown CFA base reg %d", - insn->sec, insn->offset, cfi->cfa.base); - return -1; - } - - switch (bp->base) { - case CFI_UNDEFINED: - orc->bp_reg = ORC_REG_UNDEFINED; - break; - case CFI_CFA: - orc->bp_reg = ORC_REG_PREV_SP; - break; - case CFI_BP: - orc->bp_reg = ORC_REG_BP; - break; - default: - WARN_FUNC("unknown BP base reg %d", - insn->sec, insn->offset, bp->base); - return -1; - } - - orc->sp_offset = cfi->cfa.offset; - orc->bp_offset = bp->offset; - orc->type = cfi->type; - - return 0; -} - -static int write_orc_entry(struct elf *elf, struct section *orc_sec, - struct section *ip_sec, unsigned int idx, - struct section *insn_sec, unsigned long insn_off, - struct orc_entry *o) -{ - struct orc_entry *orc; - - /* populate ORC data */ - orc = (struct orc_entry *)orc_sec->data->d_buf + idx; - memcpy(orc, o, sizeof(*orc)); - orc->sp_offset = bswap_if_needed(elf, orc->sp_offset); - orc->bp_offset = bswap_if_needed(elf, orc->bp_offset); - - /* populate reloc for ip */ - if (elf_add_reloc_to_insn(elf, ip_sec, idx * sizeof(int), R_X86_64_PC32, - insn_sec, insn_off)) - return -1; - - return 0; -} struct orc_list_entry { struct list_head list; @@ -147,15 +52,11 @@ int orc_create(struct objtool_file *file) struct orc_list_entry *entry; struct list_head orc_list; - struct orc_entry null = { - .sp_reg = ORC_REG_UNDEFINED, - .bp_reg = ORC_REG_UNDEFINED, - .type = UNWIND_HINT_TYPE_CALL, - }; + struct orc_entry null = { .type = ORC_TYPE_UNDEFINED }; /* Build a deduplicated list of ORC entries: */ INIT_LIST_HEAD(&orc_list); - for_each_sec(file, sec) { + for_each_sec(file->elf, sec) { struct orc_entry orc, prev_orc = {0}; struct instruction *insn; bool empty = true; @@ -224,12 +125,16 @@ int orc_create(struct objtool_file *file) WARN("file already has .orc_unwind section, skipping"); return -1; } - orc_sec = elf_create_section(file->elf, ".orc_unwind", 0, - sizeof(struct orc_entry), nr); + orc_sec = elf_create_section(file->elf, ".orc_unwind", + nr * sizeof(struct orc_entry), + sizeof(struct orc_entry), + SHT_PROGBITS, + 1, + SHF_ALLOC); if (!orc_sec) return -1; - sec = elf_create_section(file->elf, ".orc_unwind_ip", 0, sizeof(int), nr); + sec = elf_create_section_pair(file->elf, ".orc_unwind_ip", sizeof(int), nr, nr); if (!sec) return -1; |
