lkml.org 
[lkml]   [2020]   [Apr]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH v2 09/14] objtool: Move the IRET hack into the arch decoder
    From: Miroslav Benes <mbenes@suse.cz>

    Quoting Julien:

    "And the other suggestion is my other email was that you don't even
    need to add INSN_EXCEPTION_RETURN. You can keep IRET as
    INSN_CONTEXT_SWITCH by default and x86 decoder lookups the symbol
    conaining an iret. If it's a function symbol, it can just set the type
    to INSN_OTHER so that it caries on to the next instruction after
    having handled the stack_op."

    Suggested-by: Julien Thierry <jthierry@redhat.com>
    Signed-off-by: Miroslav Benes <mbenes@suse.cz>
    Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
    ---
    tools/objtool/arch.h | 1 -
    tools/objtool/arch/x86/decode.c | 28 ++++++++++++++++++----------
    tools/objtool/check.c | 11 -----------
    tools/objtool/elf.c | 4 ++--
    tools/objtool/elf.h | 2 +-
    5 files changed, 21 insertions(+), 25 deletions(-)

    --- a/tools/objtool/arch.h
    +++ b/tools/objtool/arch.h
    @@ -19,7 +19,6 @@ enum insn_type {
    INSN_CALL,
    INSN_CALL_DYNAMIC,
    INSN_RETURN,
    - INSN_EXCEPTION_RETURN,
    INSN_CONTEXT_SWITCH,
    INSN_BUG,
    INSN_NOP,
    --- a/tools/objtool/arch/x86/decode.c
    +++ b/tools/objtool/arch/x86/decode.c
    @@ -94,6 +94,7 @@ int arch_decode_instruction(const struct
    rex_x = 0, modrm = 0, modrm_mod = 0, modrm_rm = 0,
    modrm_reg = 0, sib = 0;
    struct stack_op *op = NULL;
    + struct symbol *sym;

    x86_64 = is_x86_64(elf);
    if (x86_64 == -1)
    @@ -469,17 +470,24 @@ int arch_decode_instruction(const struct
    break;

    case 0xcf: /* iret */
    - *type = INSN_EXCEPTION_RETURN;
    -
    - ADD_OP(op) {
    - /* add $40, %rsp */
    - op->src.type = OP_SRC_ADD;
    - op->src.reg = CFI_SP;
    - op->src.offset = 5*8;
    - op->dest.type = OP_DEST_REG;
    - op->dest.reg = CFI_SP;
    + /*
    + * Handle sync_core(), which has an IRET to self.
    + * All other IRET are in STT_NONE entry code.
    + */
    + sym = find_symbol_containing(sec, offset);
    + if (sym && sym->type == STT_FUNC) {
    + ADD_OP(op) {
    + /* add $40, %rsp */
    + op->src.type = OP_SRC_ADD;
    + op->src.reg = CFI_SP;
    + op->src.offset = 5*8;
    + op->dest.type = OP_DEST_REG;
    + op->dest.reg = CFI_SP;
    + }
    + break;
    }
    - break;
    +
    + /* fallthrough */

    case 0xca: /* retf */
    case 0xcb: /* retf */
    --- a/tools/objtool/check.c
    +++ b/tools/objtool/check.c
    @@ -2308,17 +2308,6 @@ static int validate_branch(struct objtoo

    break;

    - case INSN_EXCEPTION_RETURN:
    - /*
    - * This handles x86's sync_core() case, where we use an
    - * IRET to self. All 'normal' IRET instructions are in
    - * STT_NOTYPE entry symbols.
    - */
    - if (func)
    - break;
    -
    - return 0;
    -
    case INSN_CONTEXT_SWITCH:
    if (func && (!next_insn || !next_insn->hint)) {
    WARN_FUNC("unsupported instruction in callable function",
    --- a/tools/objtool/elf.c
    +++ b/tools/objtool/elf.c
    @@ -61,7 +61,7 @@ static void rb_add(struct rb_root *tree,
    rb_insert_color(node, tree);
    }

    -static struct rb_node *rb_find_first(struct rb_root *tree, const void *key,
    +static struct rb_node *rb_find_first(const struct rb_root *tree, const void *key,
    int (*cmp)(const void *key, const struct rb_node *))
    {
    struct rb_node *node = tree->rb_node;
    @@ -189,7 +189,7 @@ struct symbol *find_func_by_offset(struc
    return NULL;
    }

    -struct symbol *find_symbol_containing(struct section *sec, unsigned long offset)
    +struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset)
    {
    struct rb_node *node;

    --- a/tools/objtool/elf.h
    +++ b/tools/objtool/elf.h
    @@ -124,7 +124,7 @@ struct section *find_section_by_name(con
    struct symbol *find_func_by_offset(struct section *sec, unsigned long offset);
    struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
    struct symbol *find_symbol_by_name(const struct elf *elf, const char *name);
    -struct symbol *find_symbol_containing(struct section *sec, unsigned long offset);
    +struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset);
    struct rela *find_rela_by_dest(const struct elf *elf, struct section *sec, unsigned long offset);
    struct rela *find_rela_by_dest_range(const struct elf *elf, struct section *sec,
    unsigned long offset, unsigned int len);

    \
     
     \ /
      Last update: 2020-04-28 21:22    [W:5.099 / U:1.364 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site