• Josh Poimboeuf's avatar
    objtool: Detect RIP-relative switch table references · 6f5ec299
    Josh Poimboeuf authored
    Typically a switch table can be found by detecting a .rodata access
    followed an indirect jump:
    
        1969:	4a 8b 0c e5 00 00 00 	mov    0x0(,%r12,8),%rcx
        1970:	00
    			196d: R_X86_64_32S	.rodata+0x438
        1971:	e9 00 00 00 00       	jmpq   1976 <dispc_runtime_suspend+0xb6a>
    			1972: R_X86_64_PC32	__x86_indirect_thunk_rcx-0x4
    
    Randy Dunlap reported a case (seen with GCC 4.8) where the .rodata
    access uses RIP-relative addressing:
    
        19bd:	48 8b 3d 00 00 00 00 	mov    0x0(%rip),%rdi        # 19c4 <dispc_runtime_suspend+0xbb8>
    			19c0: R_X86_64_PC32	.rodata+0x45c
        19c4:	e9 00 00 00 00       	jmpq   19c9 <dispc_runtime_suspend+0xbbd>
    			19c5: R_X86_64_PC32	__x86_indirect_thunk_rdi-0x4
    
    In this case the relocation addend needs to be adjusted accordingly in
    order to find the location of the switch table.
    
    The fix is for case 3 (as described in the comments), but also make the
    existing case 1 & 2 checks more precise by only adjusting the addend for
    R_X86_64_PC32 relocations.
    
    This fixes the following warnings:
    
      drivers/video/fbdev/omap2/omapfb/dss/dispc.o: warning: objtool: dispc_runtime_suspend()+0xbb8: sibling call from callable instruction with modified stack frame
      drivers/video/fbdev/omap2/omapfb/dss/dispc.o: warning: objtool: dispc_runtime_resume()+0xcc5: sibling call from callable instruction with modified stack frame
    Reported-by: default avatarRandy Dunlap <rdunlap@infradead.org>
    Signed-off-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Link: http://lkml.kernel.org/r/b6098294fd67afb69af8c47c9883d7a68bf0f8ea.1526305958.git.jpoimboe@redhat.comSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
    6f5ec299
check.c 52.3 KB