• Josh Poimboeuf's avatar
    objtool: Fix seg fault on bad switch table entry · e65050b9
    Josh Poimboeuf authored
    In one rare case, Clang generated the following code:
    
     5ca:       83 e0 21                and    $0x21,%eax
     5cd:       b9 04 00 00 00          mov    $0x4,%ecx
     5d2:       ff 24 c5 00 00 00 00    jmpq   *0x0(,%rax,8)
                        5d5: R_X86_64_32S       .rodata+0x38
    
    which uses the corresponding jump table relocations:
    
      000000000038  000200000001 R_X86_64_64       0000000000000000 .text + 834
      000000000040  000200000001 R_X86_64_64       0000000000000000 .text + 5d9
      000000000048  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000050  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000058  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000060  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000068  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000070  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000078  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000080  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000088  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000090  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000098  000200000001 R_X86_64_64       0000000000000000 .text + b96
      0000000000a0  000200000001 R_X86_64_64       0000000000000000 .text + b96
      0000000000a8  000200000001 R_X86_64_64       0000000000000000 .text + b96
      0000000000b0  000200000001 R_X86_64_64       0000000000000000 .text + b96
      0000000000b8  000200000001 R_X86_64_64       0000000000000000 .text + b96
      0000000000c0  000200000001 R_X86_64_64       0000000000000000 .text + b96
      0000000000c8  000200000001 R_X86_64_64       0000000000000000 .text + b96
      0000000000d0  000200000001 R_X86_64_64       0000000000000000 .text + b96
      0000000000d8  000200000001 R_X86_64_64       0000000000000000 .text + b96
      0000000000e0  000200000001 R_X86_64_64       0000000000000000 .text + b96
      0000000000e8  000200000001 R_X86_64_64       0000000000000000 .text + b96
      0000000000f0  000200000001 R_X86_64_64       0000000000000000 .text + b96
      0000000000f8  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000100  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000108  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000110  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000118  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000120  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000128  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000130  000200000001 R_X86_64_64       0000000000000000 .text + b96
      000000000138  000200000001 R_X86_64_64       0000000000000000 .text + 82f
      000000000140  000200000001 R_X86_64_64       0000000000000000 .text + 828
    
    Since %eax was masked with 0x21, only the first two and the last two
    entries are possible.
    
    Objtool doesn't actually emulate all the code, so it isn't smart enough
    to know that all the middle entries aren't reachable.  They point to the
    NOP padding area after the end of the function, so objtool seg faulted
    when it tried to dereference a NULL insn->func.
    
    After this fix, objtool still gives an "unreachable" error because it
    stops reading the jump table when it encounters the bad addresses:
    
      /home/jpoimboe/objtool-tests/adm1275.o: warning: objtool: adm1275_probe()+0x828: unreachable instruction
    
    While the above code is technically correct, it's very wasteful of
    memory -- it uses 34 jump table entries when only 4 are needed.  It's
    also not possible for objtool to validate this type of switch table
    because the unused entries point outside the function and objtool has no
    way of determining if that's intentional.  Hopefully the Clang folks can
    fix it.
    Reported-by: default avatarArnd Bergmann <arnd@arndb.de>
    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/a9db88eec4f1ca089e040989846961748238b6d8.1563413318.git.jpoimboe@redhat.com
    e65050b9
check.c 58.8 KB