Re: odd objtool 'unreachable instruction' warning

From: Alexandre Chartre

Date: Thu Oct 30 2025 - 05:51:27 EST



On 10/29/25 17:17, Linus Torvalds wrote:
On Tue, 28 Oct 2025 at 18:50, Josh Poimboeuf <jpoimboe@xxxxxxxxxx> wrote:

Just to clarify, Alexandre is working on objTOOL, not objDUMP :-)

Bah. Not the first time I misread - or miswrite - one for the other.

I actually have a stupid alias for disassembly, because I can't ever
remember the long argument names:

alias disassemble='objdump --disassemble --no-show-raw-insn --no-addresses'

so one day when somebody has an improved script around this, I'll just
change the alias.

(Those flags, btw, are really bad flags in general, because you can't
figure out where the jumps go when you don't see addresses. But my
use-case is generally to look at the compiler-generated asm for
"details", and then I use that objdump disassembly to get a filtered
view of what the code looks like without all the section annotations
and without all the other noise. So that alias is more about my
workflow than about any kind of sane use).

Now, if objtool disassembly ever gives the kind of good disassembly
that 'perf report' does - with branches turned into arrows etc - that
would be lovely, and I'd replace my hacky alias in a heartbeat.
FWIW, this can be slightly improved by adding '-w' (objdump -drw) which
at least puts the function name on the same line:

call 34d <delayed_put_task_struct+0x1d> 349: R_X86_64_PLT32 rethook_flush_task-0x4

Yeah, that's better, and I think I could massage it with some
scripting even more.

But I've thought about writing some simple scripting to make objdump
output clearer many times, and I never really end up caring enough.

So I think I'll wait for Alexandre to do that for me ;)


I am currently working on a new version (V3) which is mostly done.
Alternatives are now disassemble side-by-side and reloc is handled.
I am finishing cleaning up patches and I will hopefully send them
soon.

Here are some examples:

Example with stac/clac:

4e6b6: read_ldt+0xb6 test %rsi,%rsi
4e6b9: read_ldt+0xb9 jne 0x4e6e6 <read_ldt+0xe6>
4e6bb: read_ldt+0xbb | <alternative.4e6bb> | X86_FEATURE_SMAP
4e6bb: read_ldt+0xbb | NOP1 | stac
4e6bc: read_ldt+0xbc | NOP1 |
4e6bd: read_ldt+0xbd | NOP1 |
4e6be: read_ldt+0xbe xor %eax,%eax
4e6c0: read_ldt+0xc0 | <alternative.4e6c0> | EXCEPTION | !X86_FEATURE_FSRS
4e6c0: read_ldt+0xc0 | rep stos %al,%es:(%rdi) | jmp 4e6c5 <read_ldt+0xc5> | callq 0x1707 <rep_stos_alternative>
4e6c2: read_ldt+0xc2 | NOP1 | |
4e6c3: read_ldt+0xc3 | NOP1 | |
4e6c4: read_ldt+0xc4 | NOP1 | |
4e6c5: read_ldt+0xc5 | <alternative.4e6c5> | X86_FEATURE_SMAP
4e6c5: read_ldt+0xc5 | NOP1 | clac
4e6c6: read_ldt+0xc6 | NOP1 |
4e6c7: read_ldt+0xc7 | NOP1 |
4e6c8: read_ldt+0xc8 test %rcx,%rcx
4e6cb: read_ldt+0xcb jne 0x4e6e6 <read_ldt+0xe6>
4e6cd: read_ldt+0xcd mov %rbp,%rdi
4e6d0: read_ldt+0xd0 callq 0x4e6d5 <up_read>

__switch_to_asm disassembly:

$ ./tools/objtool/objtool --disas=__switch_to_asm --link vmlinux.o
__switch_to_asm:
82c0: __switch_to_asm push %rbp
82c1: __switch_to_asm+0x1 push %rbx
82c2: __switch_to_asm+0x2 push %r12
82c4: __switch_to_asm+0x4 push %r13
82c6: __switch_to_asm+0x6 push %r14
82c8: __switch_to_asm+0x8 push %r15
82ca: __switch_to_asm+0xa mov %rsp,0x1670(%rdi)
82d1: __switch_to_asm+0x11 mov 0x1670(%rsi),%rsp
82d8: __switch_to_asm+0x18 mov 0xad8(%rsi),%rbx
82df: __switch_to_asm+0x1f mov %rbx,%gs:0x0(%rip) # 0x82e7 <__stack_chk_guard>
82e7: __switch_to_asm+0x27 | <alternative.82e7> | !X86_FEATURE_ALWAYS | X86_FEATURE_RSB_CTXSW
82e7: __switch_to_asm+0x27 | jmp 0x8312 <__switch_to_asm+0x52> | NOP1 | mov $0x10,%r12
82e8: __switch_to_asm+0x28 | | NOP1 |
82e9: __switch_to_asm+0x29 | NOP1 | callq 0x82ef <__switch_to_asm+0x2f> |
82ea: __switch_to_asm+0x2a | NOP1 | |
82eb: __switch_to_asm+0x2b | NOP1 | |
82ec: __switch_to_asm+0x2c | NOP1 | |
82ed: __switch_to_asm+0x2d | NOP1 | |
82ee: __switch_to_asm+0x2e | NOP1 | int3 | callq 0x82f4 <__switch_to_asm+0x34>
82ef: __switch_to_asm+0x2f | NOP1 | add $0x8,%rsp |
82f0: __switch_to_asm+0x30 | NOP1 | |
82f1: __switch_to_asm+0x31 | NOP1 | |
82f2: __switch_to_asm+0x32 | NOP1 | |
82f3: __switch_to_asm+0x33 | NOP1 | lfence | int3
82f4: __switch_to_asm+0x34 | NOP1 | | callq 0x82fa <__switch_to_asm+0x3a>
82f5: __switch_to_asm+0x35 | NOP1 | |
82f6: __switch_to_asm+0x36 | NOP1 | |
82f7: __switch_to_asm+0x37 | NOP1 | |
82f8: __switch_to_asm+0x38 | NOP1 | |
82f9: __switch_to_asm+0x39 | NOP1 | | int3
82fa: __switch_to_asm+0x3a | NOP1 | | add $0x10,%rsp
82fb: __switch_to_asm+0x3b | NOP1 | |
82fc: __switch_to_asm+0x3c | NOP1 | |
82fd: __switch_to_asm+0x3d | NOP1 | |
82fe: __switch_to_asm+0x3e | NOP1 | | dec %r12
82ff: __switch_to_asm+0x3f | NOP1 | |
8300: __switch_to_asm+0x40 | NOP1 | |
8301: __switch_to_asm+0x41 | NOP1 | | jne 0x82ee <__switch_to_asm+0x2e>
8302: __switch_to_asm+0x42 | NOP1 | |
8303: __switch_to_asm+0x43 | NOP1 | | lfence
8304: __switch_to_asm+0x44 | NOP1 | |
8305: __switch_to_asm+0x45 | NOP1 | |
8306: __switch_to_asm+0x46 | NOP1 | | movq $0xffffffffffffffff,%gs:0x0(%rip) # 0x20b <__x86_call_depth>
8307: __switch_to_asm+0x47 | NOP1 | |
8308: __switch_to_asm+0x48 | NOP1 | |
8309: __switch_to_asm+0x49 | NOP1 | |
830a: __switch_to_asm+0x4a | NOP1 | |
830b: __switch_to_asm+0x4b | NOP1 | |
830c: __switch_to_asm+0x4c | NOP1 | |
830d: __switch_to_asm+0x4d | NOP1 | |
830e: __switch_to_asm+0x4e | NOP1 | |
830f: __switch_to_asm+0x4f | NOP1 | |
8310: __switch_to_asm+0x50 | NOP1 | |
8311: __switch_to_asm+0x51 | NOP1 | |
8312: __switch_to_asm+0x52 pop %r15
8314: __switch_to_asm+0x54 pop %r14
8316: __switch_to_asm+0x56 pop %r13
8318: __switch_to_asm+0x58 pop %r12
831a: __switch_to_asm+0x5a pop %rbx
831b: __switch_to_asm+0x5b pop %rbp
831c: __switch_to_asm+0x5c jmpq 0x8321 <__switch_to>

alex.