[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251119143247.3944213-1-alexandre.chartre@oracle.com>
Date: Wed, 19 Nov 2025 15:32:17 +0100
From: Alexandre Chartre <alexandre.chartre@...cle.com>
To: linux-kernel@...r.kernel.org, mingo@...nel.org, jpoimboe@...nel.org,
peterz@...radead.org, david.laight.linux@...il.com
Cc: alexandre.chartre@...cle.com
Subject: [PATCH v5 00/30] objtool: Function validation tracing
Hi,
These patches change objtool to disassemble code with libopcodes instead
of running objdump. You will find below:
- Changes: list of changes made in this version
- Overview: overview of the changes
- Notes: description of some particular behavior
- Examples: output examples
Patches are now based on tip/master.
I am deferring the following changes to future patches:
- Josh: convert --disas option to subcommand
- David: provide branch distance for small branches
Thanks,
alex.
-----
Changes:
========
V5:
---
- patches are now based on tip/master
- remove the resolution of direct/PV calls
(added in V4 but this needs more work)
- Josh: fix rname
- Josh: change names for jump tables and exception tables
- Josh: display header line for single-line alternatives
- Josh: make NOP<n> lowercase
- Josh: fix alternatives order
- Josh: trim trailing NOPs
- David: indicate the number of trailing NOPs (nop*<n>)
- David: provide compact output for alternatives disassembly.
The compact output is now the default, and there is a --wide
option to provide a wide output where alternatives are displayed
side-by-side.
V4:
---
This version fixes a build issue when disassembly is not available. Compared
with V3, this is addresses by changes in patch 14 (objtool: Improve tracing
of alternative instructions). Other patches are similar to V3.
V3:
---
This version addresses comments from Josh and Peter, in particular:
- Josh: replace ERROR in disas_context_create with WARN
- Josh: do not change offstr() outside the disassembler
- Josh: duplicated "falls through to next function" warning
- Josh: validate_symbol() has extra newline before return
- Josh: "make -s" should be completely silent
- Josh: instructions with unwinding state changes are printing twice
- Josh: explain TRACE_INSN(insn, NULL): this prints an instruction with no
additional message.
- Peter: display alternative on a single line
- Peter: display nop-like instruction as NOP<n>
- Peter: in alternative show differences between jmp.d8 and jmp.d32 (jmp/jmpq is used now)
- Peter: show alternative feature name and flags
- Peter: alternative jumps to altinstr_aux - see NOTE below:
Disassembly can show default alternative jumping to .altinstr_aux
- Peter: some jump label target seems wrong (jmp +0) - NOTE below:
Disassembly can show alternative jumping to the next instruction
Other improvements:
- An alternatives is displayed on single line if each alternative has a
single instruction. Otherwise alternatives are dispayed side-by-side,
with one column for each lternative. XXX option?
- Each alternative of a group alternative is displayed with its feature
name and flags: <flags><feature-name>
<flags> is made of the following characters:
'!' : ALT_FLAG_NOT
'+' : ALT_FLAG_DIRECT_CALL
'?' : unknown flag (i.e. any other flags)
- A jump table is displayed the same way as an alternative, with the default
branch (or not) instruction, and the corresponding substitute instruction.
It is identified with the "JUMP" name.
- An exception table is displayed the same way as an alternative, with the
default instruction (which can cause an exception), and a "resume at <desc>"
string which indicates where the execution resumes if there is an exception.
It is identified with the "EXCEPTION" name.
- An exception table can be present for an instruction which also has an
alternative. In that case, the exception table is displayed similarly
as the different group alternatives for this instruction.
- Print the destination name of pv_ops calls when we can figure out if
XENPV mode is used or not. If the PV mode can't be predicted then print
the default pv_ops destination as a destination example. **REMOVED IN V5**
- If a group alternative is a direct call then print the corresponding
pv_ops call. **REMOVED IN V5**
Overview:
=========
This provides the following changes to objtool.
- Disassemble code with libopcodes instead of running objdump
objtool executes the objdump command to disassemble code. In particular,
if objtool fails to validate a function then it will use objdump to
disassemble the entire file which is not very helpful when processing
a large file (like vmlinux.o).
Using libopcodes provides more control about the disassembly scope and
output, and it is possible to disassemble a single instruction or
a single function. Now when objtool fails to validate a function it
will disassemble that single function instead of disassembling the
entire file.
- Add the --trace <function> option to trace function validation
Figuring out why a function validation has failed can be difficult because
objtool checks all code flows (including alternatives) and maintains
instructions states (in particular call frame information).
The trace option allows to follow the function validation done by objtool
instruction per instruction, see what objtool is doing and get function
validation information. An output example is shown below.
- Add the --disas <function> option to disassemble functions
Disassembly is done using libopcodes and it will show the different code
alternatives.
Note: some changes are architecture specific (x86, powerpc, loongarch). Any
feedback about the behavior on powerpc and loongarch is welcome.
Notes:
======
Disassembly can show default alternative jumping to .altinstr_aux
-----------------------------------------------------------------
Disassembly can show a default alternative jumping to .altinstr_aux. This
happens when the _static_cpu_has() function is used. Its default code
jumps to .altinstr_aux where a test sequence is executed (test; jnz; jmp).
At runtime, this sequence is not used because the _static_cpu_has()
an alternative with the X86_FEATURE_ALWAYS feature.
debc: perf_get_x86_pmu_capability+0xc jmpq 0xdec1 <.altinstr_aux+0xfc> | NOP5 (X86_FEATURE_HYBRID_CPU) | jmpq 0x61a <perf_get_x86_pmu_capability+0x37> (X86_FEATURE_ALWAYS) # <alternative.debc>
dec1: perf_get_x86_pmu_capability+0x11 ud2
Disassembly can show alternative jumping to the next instruction
----------------------------------------------------------------
The disassembly can show jump tables with an alternative which jumps
to the next instruction.
For example:
def9: perf_get_x86_pmu_capability+0x49 NOP2 | jmp defb <perf_get_x86_pmu_capability+0x4b> (JUMP) # <alternative.def9>
defb: perf_get_x86_pmu_capability+0x4b mov 0x0(%rip),%rdi # 0xdf02 <x86_pmu+0xd8>
This disassembly is correct. These instructions come from:
cap->num_counters_gp = x86_pmu_num_counters(NULL)):
which will end up executing this statement:
if (static_branch_unlikely(&perf_is_hybrid) && NULL)
<do something>;
This statement is optimized to do nothing because the condition is
always false. But static_branch_unlikely() is implemented with a jump
table inside an "asm goto" statement, and "asm goto" statements are
not optimized.
So basically the code is optimized like this:
if (static_branch_unlikely(&perf_is_hybrid))
;
And this translates to the assembly code above.
Examples:
=========
Example 1 (--trace option): Trace the validation of the os_save() function
--------------------------------------------------------------------------
$ ./tools/objtool/objtool --hacks=jump_label --hacks=noinstr --hacks=skylake --ibt --orc --retpoline --rethunk --sls --static-call --uaccess --prefix=16 --link --trace os_xsave -v vmlinux.o
os_xsave: validation begin
59be0: os_xsave+0x0 push %r12 - state: cfa=rsp+16 r12=(cfa-16) stack_size=16
59be2: os_xsave+0x2 mov 0x0(%rip),%eax # 0x59be8 <alternatives_patched>
59be8: os_xsave+0x8 push %rbp - state: cfa=rsp+24 rbp=(cfa-24) stack_size=24
59be9: os_xsave+0x9 mov %rdi,%rbp
59bec: os_xsave+0xc push %rbx - state: cfa=rsp+32 rbx=(cfa-32) stack_size=32
59bed: os_xsave+0xd mov 0x8(%rdi),%rbx
59bf1: os_xsave+0x11 mov %rbx,%r12
59bf4: os_xsave+0x14 shr $0x20,%r12
59bf8: os_xsave+0x18 test %eax,%eax
59bfa: os_xsave+0x1a je 0x59c22 <os_xsave+0x42> - jump taken
59c22: os_xsave+0x42 | ud2
59c24: os_xsave+0x44 | jmp 0x59bfc <os_xsave+0x1c> - unconditional jump
59bfc: os_xsave+0x1c | | xor %edx,%edx
59bfe: os_xsave+0x1e | | mov %rbx,%rsi
59c01: os_xsave+0x21 | | mov %rbp,%rdi
59c04: os_xsave+0x24 | | callq 0x59c09 <xfd_validate_state> - call
59c09: os_xsave+0x29 | | mov %ebx,%eax
59c0b: os_xsave+0x2b | | mov %r12d,%edx
| | / <alternative.59c0e> X86_FEATURE_XSAVEOPT
1b29: .altinstr_replacement+0x1b29 | | | xsaveopt64 0x40(%rbp)
59c13: os_xsave+0x33 | | | xor %ebx,%ebx
59c15: os_xsave+0x35 | | | test %ebx,%ebx
59c17: os_xsave+0x37 | | | jne 0x59c26 <os_xsave+0x46> - jump taken
59c26: os_xsave+0x46 | | | | ud2
59c28: os_xsave+0x48 | | | | pop %rbx - state: cfa=rsp+24 rbx=<undef> stack_size=24
59c29: os_xsave+0x49 | | | | pop %rbp - state: cfa=rsp+16 rbp=<undef> stack_size=16
59c2a: os_xsave+0x4a | | | | pop %r12 - state: cfa=rsp+8 r12=<undef> stack_size=8
59c2c: os_xsave+0x4c | | | | jmpq 0x59c31 <__x86_return_thunk> - return
59c17: os_xsave+0x37 | | | jne 0x59c26 <os_xsave+0x46> - jump not taken
59c19: os_xsave+0x39 | | | pop %rbx - state: cfa=rsp+24 rbx=<undef> stack_size=24
59c1a: os_xsave+0x3a | | | pop %rbp - state: cfa=rsp+16 rbp=<undef> stack_size=16
59c1b: os_xsave+0x3b | | | pop %r12 - state: cfa=rsp+8 r12=<undef> stack_size=8
59c1d: os_xsave+0x3d | | | jmpq 0x59c22 <__x86_return_thunk> - return
| | \ <alternative.59c0e> X86_FEATURE_XSAVEOPT
| | / <alternative.59c0e> X86_FEATURE_XSAVEC
1b2e: .altinstr_replacement+0x1b2e | | | xsavec64 0x40(%rbp)
59c13: os_xsave+0x33 | | | xor %ebx,%ebx - already visited
| | \ <alternative.59c0e> X86_FEATURE_XSAVEC
| | / <alternative.59c0e> X86_FEATURE_XSAVES
1b33: .altinstr_replacement+0x1b33 | | | xsaves64 0x40(%rbp)
59c13: os_xsave+0x33 | | | xor %ebx,%ebx - already visited
| | \ <alternative.59c0e> X86_FEATURE_XSAVES
| | / <alternative.59c0e> EXCEPTION for instruction at 0x59c0e <os_xsave+0x2e>
59c15: os_xsave+0x35 | | | test %ebx,%ebx - already visited
| | \ <alternative.59c0e> EXCEPTION
| | / <alternative.59c0e> DEFAULT
59c0e: os_xsave+0x2e | | xsave64 0x40(%rbp)
59c13: os_xsave+0x33 | | xor %ebx,%ebx - already visited
59bfa: os_xsave+0x1a je 0x59c22 <os_xsave+0x42> - jump not taken
59bfc: os_xsave+0x1c xor %edx,%edx - already visited
os_xsave: validation end
Example 2 (--disas option): Single Instruction Alternatives
-----------------------------------------------------------
Compact Output (default):
Alternatives with single instructions are displayed each on one line,
with the instruction and a description of the alternative.
$ ./tools/objtool/objtool --disas=perf_get_x86_pmu_capability --link vmlinux.o
perf_get_x86_pmu_capability:
deb0: perf_get_x86_pmu_capability+0x0 endbr64
deb4: perf_get_x86_pmu_capability+0x4 callq 0xdeb9 <__fentry__>
deb9: perf_get_x86_pmu_capability+0x9 mov %rdi,%rdx
debc: perf_get_x86_pmu_capability+0xc <alternative.debc>
= jmpq 0xdec1 <.altinstr_aux+0xfc> (if DEFAULT)
= jmpq 0x622 <perf_get_x86_pmu_capability+0x37> (if X86_FEATURE_ALWAYS)
= nop5 (if X86_FEATURE_HYBRID_CPU)
dec1: perf_get_x86_pmu_capability+0x11 ud2
dec3: perf_get_x86_pmu_capability+0x13 movq $0x0,(%rdx)
deca: perf_get_x86_pmu_capability+0x1a movq $0x0,0x8(%rdx)
ded2: perf_get_x86_pmu_capability+0x22 movq $0x0,0x10(%rdx)
deda: perf_get_x86_pmu_capability+0x2a movq $0x0,0x18(%rdx)
dee2: perf_get_x86_pmu_capability+0x32 jmpq 0xdee7 <__x86_return_thunk>
dee7: perf_get_x86_pmu_capability+0x37 cmpq $0x0,0x0(%rip) # 0xdeef <x86_pmu+0x10>
deef: perf_get_x86_pmu_capability+0x3f je 0xdec3 <perf_get_x86_pmu_capability+0x13>
def1: perf_get_x86_pmu_capability+0x41 mov 0x0(%rip),%eax # 0xdef7 <x86_pmu+0x8>
def7: perf_get_x86_pmu_capability+0x47 mov %eax,(%rdi)
def9: perf_get_x86_pmu_capability+0x49 <jump_table.def9>
= nop2 (if DEFAULT)
= jmp defb <perf_get_x86_pmu_capability+0x4b> (if JUMP)
defb: perf_get_x86_pmu_capability+0x4b mov 0x0(%rip),%rdi # 0xdf02 <x86_pmu+0xd8>
df02: perf_get_x86_pmu_capability+0x52 <alternative.df02>
= callq 0xdf07 <__sw_hweight64> (if DEFAULT)
= popcnt %rdi,%rax (if X86_FEATURE_POPCNT)
df07: perf_get_x86_pmu_capability+0x57 mov %eax,0x4(%rdx)
df0a: perf_get_x86_pmu_capability+0x5a <jump_table.df0a>
= nop2 (if DEFAULT)
= jmp df0c <perf_get_x86_pmu_capability+0x5c> (if JUMP)
df0c: perf_get_x86_pmu_capability+0x5c mov 0x0(%rip),%rdi # 0xdf13 <x86_pmu+0xe0>
df13: perf_get_x86_pmu_capability+0x63 <alternative.df13>
= callq 0xdf18 <__sw_hweight64> (if DEFAULT)
= popcnt %rdi,%rax (if X86_FEATURE_POPCNT)
df18: perf_get_x86_pmu_capability+0x68 mov %eax,0x8(%rdx)
df1b: perf_get_x86_pmu_capability+0x6b mov 0x0(%rip),%eax # 0xdf21 <x86_pmu+0xf8>
df21: perf_get_x86_pmu_capability+0x71 mov %eax,0xc(%rdx)
df24: perf_get_x86_pmu_capability+0x74 mov %eax,0x10(%rdx)
df27: perf_get_x86_pmu_capability+0x77 mov 0x0(%rip),%rax # 0xdf2e <x86_pmu+0x108>
df2e: perf_get_x86_pmu_capability+0x7e mov %eax,0x14(%rdx)
df31: perf_get_x86_pmu_capability+0x81 mov 0x0(%rip),%eax # 0xdf37 <x86_pmu+0x110>
df37: perf_get_x86_pmu_capability+0x87 mov %eax,0x18(%rdx)
df3a: perf_get_x86_pmu_capability+0x8a movzbl 0x0(%rip),%ecx # 0xdf41 <x86_pmu+0x1d1>
df41: perf_get_x86_pmu_capability+0x91 movzbl 0x1c(%rdx),%eax
df45: perf_get_x86_pmu_capability+0x95 shr %cl
df47: perf_get_x86_pmu_capability+0x97 and $0x1,%ecx
df4a: perf_get_x86_pmu_capability+0x9a and $0xfffffffe,%eax
df4d: perf_get_x86_pmu_capability+0x9d or %ecx,%eax
df4f: perf_get_x86_pmu_capability+0x9f mov %al,0x1c(%rdx)
df52: perf_get_x86_pmu_capability+0xa2 jmpq 0xdf57 <__x86_return_thunk>
Wide Output (--wide option):
Alternatives with single instructions are displayed side-by-side,
with an header.
$ ./tools/objtool/objtool --disas=perf_get_x86_pmu_capability --wide --link vmlinux.o
perf_get_x86_pmu_capability:
deb0: perf_get_x86_pmu_capability+0x0 endbr64
deb4: perf_get_x86_pmu_capability+0x4 callq 0xdeb9 <__fentry__>
deb9: perf_get_x86_pmu_capability+0x9 mov %rdi,%rdx
debc: perf_get_x86_pmu_capability+0xc | <alternative.debc> | X86_FEATURE_ALWAYS | X86_FEATURE_HYBRID_CPU
debc: perf_get_x86_pmu_capability+0xc | jmpq 0xdec1 <.altinstr_aux+0xfc> | jmpq 0x622 <perf_get_x86_pmu_capability+0x37> | nop5
dec1: perf_get_x86_pmu_capability+0x11 ud2
dec3: perf_get_x86_pmu_capability+0x13 movq $0x0,(%rdx)
deca: perf_get_x86_pmu_capability+0x1a movq $0x0,0x8(%rdx)
ded2: perf_get_x86_pmu_capability+0x22 movq $0x0,0x10(%rdx)
deda: perf_get_x86_pmu_capability+0x2a movq $0x0,0x18(%rdx)
dee2: perf_get_x86_pmu_capability+0x32 jmpq 0xdee7 <__x86_return_thunk>
dee7: perf_get_x86_pmu_capability+0x37 cmpq $0x0,0x0(%rip) # 0xdeef <x86_pmu+0x10>
deef: perf_get_x86_pmu_capability+0x3f je 0xdec3 <perf_get_x86_pmu_capability+0x13>
def1: perf_get_x86_pmu_capability+0x41 mov 0x0(%rip),%eax # 0xdef7 <x86_pmu+0x8>
def7: perf_get_x86_pmu_capability+0x47 mov %eax,(%rdi)
def9: perf_get_x86_pmu_capability+0x49 | <jump_table.def9> | JUMP
def9: perf_get_x86_pmu_capability+0x49 | nop2 | jmp defb <perf_get_x86_pmu_capability+0x4b>
defb: perf_get_x86_pmu_capability+0x4b mov 0x0(%rip),%rdi # 0xdf02 <x86_pmu+0xd8>
df02: perf_get_x86_pmu_capability+0x52 | <alternative.df02> | X86_FEATURE_POPCNT
df02: perf_get_x86_pmu_capability+0x52 | callq 0xdf07 <__sw_hweight64> | popcnt %rdi,%rax
df07: perf_get_x86_pmu_capability+0x57 mov %eax,0x4(%rdx)
df0a: perf_get_x86_pmu_capability+0x5a | <jump_table.df0a> | JUMP
df0a: perf_get_x86_pmu_capability+0x5a | nop2 | jmp df0c <perf_get_x86_pmu_capability+0x5c>
df0c: perf_get_x86_pmu_capability+0x5c mov 0x0(%rip),%rdi # 0xdf13 <x86_pmu+0xe0>
df13: perf_get_x86_pmu_capability+0x63 | <alternative.df13> | X86_FEATURE_POPCNT
df13: perf_get_x86_pmu_capability+0x63 | callq 0xdf18 <__sw_hweight64> | popcnt %rdi,%rax
df18: perf_get_x86_pmu_capability+0x68 mov %eax,0x8(%rdx)
df1b: perf_get_x86_pmu_capability+0x6b mov 0x0(%rip),%eax # 0xdf21 <x86_pmu+0xf8>
df21: perf_get_x86_pmu_capability+0x71 mov %eax,0xc(%rdx)
df24: perf_get_x86_pmu_capability+0x74 mov %eax,0x10(%rdx)
df27: perf_get_x86_pmu_capability+0x77 mov 0x0(%rip),%rax # 0xdf2e <x86_pmu+0x108>
df2e: perf_get_x86_pmu_capability+0x7e mov %eax,0x14(%rdx)
df31: perf_get_x86_pmu_capability+0x81 mov 0x0(%rip),%eax # 0xdf37 <x86_pmu+0x110>
df37: perf_get_x86_pmu_capability+0x87 mov %eax,0x18(%rdx)
df3a: perf_get_x86_pmu_capability+0x8a movzbl 0x0(%rip),%ecx # 0xdf41 <x86_pmu+0x1d1>
df41: perf_get_x86_pmu_capability+0x91 movzbl 0x1c(%rdx),%eax
df45: perf_get_x86_pmu_capability+0x95 shr %cl
df47: perf_get_x86_pmu_capability+0x97 and $0x1,%ecx
df4a: perf_get_x86_pmu_capability+0x9a and $0xfffffffe,%eax
df4d: perf_get_x86_pmu_capability+0x9d or %ecx,%eax
df4f: perf_get_x86_pmu_capability+0x9f mov %al,0x1c(%rdx)
df52: perf_get_x86_pmu_capability+0xa2 jmpq 0xdf57 <__x86_return_thunk>
Example 3 (--disas option): Alternatives with multiple instructions
-------------------------------------------------------------------
Compact Output (default):
Alternatives with multiple instructions are displayed one above the other,
with an header describing the alternative.
$ ./tools/objtool/objtool --disas=__switch_to_asm --link vmlinux.o
__switch_to_asm:
82c0: __switch_to_asm+0x0 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>
= DEFAULT
82e7: __switch_to_asm+0x27 | jmp 0x8312 <__switch_to_asm+0x52>
82e9: __switch_to_asm+0x29 | nop*41
|
= X86_FEATURE_RSB_CTXSW
82e7: __switch_to_asm+0x27 | mov $0x10,%r12
82ee: __switch_to_asm+0x2e | callq 0x82f4 <__switch_to_asm+0x34>
82f3: __switch_to_asm+0x33 | int3
82f4: __switch_to_asm+0x34 | callq 0x82fa <__switch_to_asm+0x3a>
82f9: __switch_to_asm+0x39 | int3
82fa: __switch_to_asm+0x3a | add $0x10,%rsp
82fe: __switch_to_asm+0x3e | dec %r12
8301: __switch_to_asm+0x41 | jne 0x82ee <__switch_to_asm+0x2e>
8303: __switch_to_asm+0x43 | lfence
8306: __switch_to_asm+0x46 | movq $0xffffffffffffffff,%gs:0x0(%rip) # 0x20b <__x86_call_depth>
|
= !X86_FEATURE_ALWAYS
82e7: __switch_to_asm+0x27 | nop1
82e8: __switch_to_asm+0x28 | nop1
82e9: __switch_to_asm+0x29 | callq 0x82ef <__switch_to_asm+0x2f>
82ee: __switch_to_asm+0x2e | int3
82ef: __switch_to_asm+0x2f | add $0x8,%rsp
82f3: __switch_to_asm+0x33 | lfence
|
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>
Wide Output (--wide option):
Alternatives with multiple instructions are displayed side-by-side, with
an header describing the alternative. The code in the first column is the
default code of the alternative.
$ ./tools/objtool/objtool --disas=__switch_to_asm --wide --link vmlinux.o
__switch_to_asm:
82c0: __switch_to_asm+0x0 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_RSB_CTXSW | !X86_FEATURE_ALWAYS
82e7: __switch_to_asm+0x27 | jmp 0x8312 <__switch_to_asm+0x52> | mov $0x10,%r12 | nop1
82e8: __switch_to_asm+0x28 | | | nop1
82e9: __switch_to_asm+0x29 | nop*41 | | callq 0x82ef <__switch_to_asm+0x2f>
82ee: __switch_to_asm+0x2e | | callq 0x82f4 <__switch_to_asm+0x34> | int3
82ef: __switch_to_asm+0x2f | | | add $0x8,%rsp
82f3: __switch_to_asm+0x33 | | int3 | lfence
82f4: __switch_to_asm+0x34 | | callq 0x82fa <__switch_to_asm+0x3a> |
82f9: __switch_to_asm+0x39 | | int3 |
82fa: __switch_to_asm+0x3a | | add $0x10,%rsp |
82fe: __switch_to_asm+0x3e | | dec %r12 |
8301: __switch_to_asm+0x41 | | jne 0x82ee <__switch_to_asm+0x2e> |
8303: __switch_to_asm+0x43 | | lfence |
8306: __switch_to_asm+0x46 | | movq $0xffffffffffffffff,%gs:0x0(%rip) # 0x20b <__x86_call_depth> |
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>
-----
Alexandre Chartre (30):
objtool: Move disassembly functions to a separated file
objtool: Create disassembly context
objtool: Disassemble code with libopcodes instead of running objdump
tool build: Remove annoying newline in build output
objtool: Print symbol during disassembly
objtool: Store instruction disassembly result
objtool: Disassemble instruction on warning or backtrace
objtool: Extract code to validate instruction from the validate branch
loop
objtool: Record symbol name max length
objtool: Add option to trace function validation
objtool: Trace instruction state changes during function validation
objtool: Improve register reporting during function validation
objtool: Identify the different types of alternatives
objtool: Add functions to better name alternatives
objtool: Improve tracing of alternative instructions
objtool: Do not validate IBT for .return_sites and .call_sites
objtool: Add the --disas=<function-pattern> action
objtool: Preserve alternatives order
objtool: Print headers for alternatives
objtool: Disassemble group alternatives
objtool: Print addresses with alternative instructions
objtool: Disassemble exception table alternatives
objtool: Disassemble jump table alternatives
objtool: Fix address references in alternatives
objtool: Provide access to feature and flags of group alternatives
objtool: Function to get the name of a CPU feature
objtool: Improve naming of group alternatives
objtool: Compact output for alternatives with one instruction
objtool: Add wide output for disassembly
objtool: Trim trailing NOPs in alternative
.../x86/tools/gen-cpu-feature-names-x86.awk | 33 +
tools/build/Makefile.feature | 4 +-
tools/objtool/Build | 3 +
tools/objtool/Makefile | 24 +
tools/objtool/arch/loongarch/decode.c | 23 +
tools/objtool/arch/loongarch/special.c | 5 +
tools/objtool/arch/powerpc/decode.c | 24 +
tools/objtool/arch/powerpc/special.c | 5 +
tools/objtool/arch/x86/Build | 8 +
tools/objtool/arch/x86/decode.c | 20 +
tools/objtool/arch/x86/special.c | 10 +
tools/objtool/builtin-check.c | 4 +
tools/objtool/check.c | 648 +++++----
tools/objtool/disas.c | 1245 +++++++++++++++++
tools/objtool/include/objtool/arch.h | 11 +
tools/objtool/include/objtool/builtin.h | 3 +
tools/objtool/include/objtool/check.h | 35 +-
tools/objtool/include/objtool/disas.h | 81 ++
tools/objtool/include/objtool/special.h | 4 +-
tools/objtool/include/objtool/trace.h | 141 ++
tools/objtool/include/objtool/warn.h | 17 +-
tools/objtool/special.c | 2 +
tools/objtool/trace.c | 203 +++
23 files changed, 2254 insertions(+), 299 deletions(-)
create mode 100644 tools/arch/x86/tools/gen-cpu-feature-names-x86.awk
create mode 100644 tools/objtool/disas.c
create mode 100644 tools/objtool/include/objtool/disas.h
create mode 100644 tools/objtool/include/objtool/trace.h
create mode 100644 tools/objtool/trace.c
--
2.43.5
Powered by blists - more mailing lists