• Jann Horn's avatar
    objtool: Support repeated uses of the same C jump table · bd98c813
    Jann Horn authored
    This fixes objtool for both a GCC issue and a Clang issue:
    
    1) GCC issue:
    
       kernel/bpf/core.o: warning: objtool: ___bpf_prog_run()+0x8d5: sibling call from callable instruction with modified stack frame
    
       With CONFIG_RETPOLINE=n, GCC is doing the following optimization in
       ___bpf_prog_run().
    
       Before:
    
               select_insn:
                       jmp *jumptable(,%rax,8)
                       ...
               ALU64_ADD_X:
                       ...
                       jmp select_insn
               ALU_ADD_X:
                       ...
                       jmp select_insn
    
       After:
    
               select_insn:
                       jmp *jumptable(, %rax, 8)
                       ...
               ALU64_ADD_X:
                       ...
                       jmp *jumptable(, %rax, 8)
               ALU_ADD_X:
                       ...
                       jmp *jumptable(, %rax, 8)
    
       This confuses objtool.  It has never seen multiple indirect jump
       sites which use the same jump table.
    
       For GCC switch tables, the only way of detecting the size of a table
       is by continuing to scan for more tables.  The size of the previous
       table can only be determined after another switch table is found, or
       when the scan reaches the end of the function.
    
       That logic was reused for C jump tables, and was based on the
       assumption that each jump table only has a single jump site.  The
       above optimization breaks that assumption.
    
    2) Clang issue:
    
       drivers/usb/misc/sisusbvga/sisusb.o: warning: objtool: sisusb_write_mem_bulk()+0x588: can't find switch jump table
    
       With clang 9, code can be generated where a function contains two
       indirect jump instructions which use the same switch table.
    
    The fix is the same for both issues: split the jump table parsing into
    two passes.
    
    In the first pass, locate the heads of all switch tables for the
    function and mark their locations.
    
    In the second pass, parse the switch tables and add them.
    
    Fixes: e55a7325 ("bpf: Fix ORC unwinding in non-JIT BPF code")
    Reported-by: default avatarRandy Dunlap <rdunlap@infradead.org>
    Reported-by: default avatarArnd Bergmann <arnd@arndb.de>
    Signed-off-by: default avatarJann Horn <jannh@google.com>
    Signed-off-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Tested-by: default avatarNick Desaulniers <ndesaulniers@google.com>
    Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
    Link: https://lkml.kernel.org/r/e995befaada9d4d8b2cf788ff3f566ba900d2b4d.1563413318.git.jpoimboe@redhat.comCo-developed-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
    bd98c813
elf.h 2.43 KB