tools/objtool/Build | 1 + tools/objtool/Makefile | 2 +- tools/objtool/arch/loongarch/decode.c | 17 + tools/objtool/arch/powerpc/decode.c | 18 + tools/objtool/arch/x86/decode.c | 15 + tools/objtool/builtin-check.c | 1 + tools/objtool/check.c | 829 ++++++++++++++++-------- tools/objtool/disas.c | 452 +++++++++++++ tools/objtool/include/objtool/arch.h | 7 + tools/objtool/include/objtool/builtin.h | 1 + tools/objtool/include/objtool/check.h | 29 + tools/objtool/include/objtool/warn.h | 17 +- 12 files changed, 1122 insertions(+), 267 deletions(-) create mode 100644 tools/objtool/disas.c
Hi,
This RFC provides two 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.
Note: some changes are architecture specific (x86, powerpc, loongarch). So far,
I have only tested on x86, and some code might be x86 specific. Any feedback
about the behavior on powerpc and loongarch is welcome.
Thanks,
alex.
-----
Example: Trace the validation of the os_save() function in vmlinux.o
$ ./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
65c20: os_xsave+0x0 push %r12 - state: cfa=rsp+16 r12=(cfa-16) stack_size=16
65c22: os_xsave+0x2 mov 0x0(%rip),%eax # alternatives_patched
65c28: os_xsave+0x8 push %rbp - state: cfa=rsp+24 rbp=(cfa-24) stack_size=24
65c29: os_xsave+0x9 mov %rdi,%rbp
65c2c: os_xsave+0xc push %rbx - state: cfa=rsp+32 rbx=(cfa-32) stack_size=32
65c2d: os_xsave+0xd mov 0x8(%rdi),%rbx
65c31: os_xsave+0x11 mov %rbx,%r12
65c34: os_xsave+0x14 shr $0x20,%r12
65c38: os_xsave+0x18 test %eax,%eax
65c3a: os_xsave+0x1a je 65c6a <os_xsave+0x4a> - jump taken
65c6a: os_xsave+0x4a | ud2
65c6c: os_xsave+0x4c | jmp 65c3c <os_xsave+0x1c> - unconditional jump
65c3c: os_xsave+0x1c | xor %edx,%edx
65c3e: os_xsave+0x1e | mov %rbx,%rsi
65c41: os_xsave+0x21 | mov %rbp,%rdi
65c44: os_xsave+0x24 | callq xfd_validate_state - call
65c49: os_xsave+0x29 | mov %ebx,%eax
65c4b: os_xsave+0x2b | mov %r12d,%edx
65c4e: os_xsave+0x2e | <alternative.65c4e> alt 1/4 begin
65c55: os_xsave+0x35 | | test %ebx,%ebx
65c57: os_xsave+0x37 | | jne 65c6e <os_xsave+0x4e> - jump taken
65c6e: os_xsave+0x4e | | | ud2
65c70: os_xsave+0x50 | | | pop %rbx - state: cfa=rsp+24 rbx=<undef> stack_size=24
65c71: os_xsave+0x51 | | | pop %rbp - state: cfa=rsp+16 rbp=<undef> stack_size=16
65c72: os_xsave+0x52 | | | pop %r12 - state: cfa=rsp+8 r12=<undef> stack_size=8
65c74: os_xsave+0x54 | | | xor %eax,%eax
65c76: os_xsave+0x56 | | | xor %edx,%edx
65c78: os_xsave+0x58 | | | xor %esi,%esi
65c7a: os_xsave+0x5a | | | xor %edi,%edi
65c7c: os_xsave+0x5c | | | jmpq __x86_return_thunk - return
65c57: os_xsave+0x37 | | jne 65c6e <os_xsave+0x4e> - jump not taken
65c59: os_xsave+0x39 | | pop %rbx - state: cfa=rsp+24 rbx=<undef> stack_size=24
65c5a: os_xsave+0x3a | | pop %rbp - state: cfa=rsp+16 rbp=<undef> stack_size=16
65c5b: os_xsave+0x3b | | pop %r12 - state: cfa=rsp+8 r12=<undef> stack_size=8
65c5d: os_xsave+0x3d | | xor %eax,%eax
65c5f: os_xsave+0x3f | | xor %edx,%edx
65c61: os_xsave+0x41 | | xor %esi,%esi
65c63: os_xsave+0x43 | | xor %edi,%edi
65c65: os_xsave+0x45 | | jmpq __x86_return_thunk - return
| <alternative.65c4e> alt 1/4 end
65c4e: os_xsave+0x2e | <alternative.65c4e> alt 2/4 begin
1c3d: .altinstr_replacement+0x1c3d | | xsaves64 0x40(%rbp)
65c53: os_xsave+0x33 | | xor %ebx,%ebx
65c55: os_xsave+0x35 | | test %ebx,%ebx - already visited
| <alternative.65c4e> alt 2/4 end
65c4e: os_xsave+0x2e | <alternative.65c4e> alt 3/4 begin
1c38: .altinstr_replacement+0x1c38 | | xsavec64 0x40(%rbp)
65c53: os_xsave+0x33 | | xor %ebx,%ebx - already visited
| <alternative.65c4e> alt 3/4 end
65c4e: os_xsave+0x2e | <alternative.65c4e> alt 4/4 begin
1c33: .altinstr_replacement+0x1c33 | | xsaveopt64 0x40(%rbp)
65c53: os_xsave+0x33 | | xor %ebx,%ebx - already visited
| <alternative.65c4e> alt 4/4 end
65c4e: os_xsave+0x2e | <alternative.65c4e> alt default
65c4e: os_xsave+0x2e | xsave64 0x40(%rbp)
65c53: os_xsave+0x33 | xor %ebx,%ebx - already visited
65c3a: os_xsave+0x1a je 65c6a <os_xsave+0x4a> - jump not taken
65c3c: os_xsave+0x1c xor %edx,%edx - already visited
os_xsave: validation end
-----
Alexandre Chartre (13):
objtool: Move disassembly functions to a separated file
objtool: Create disassembly context
objtool: Disassemble code with libopcodes instead of running objdump
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: Improve tracing of alternative instructions
objtool: Do not validate IBT for .return_sites and .call_sites
tools/objtool/Build | 1 +
tools/objtool/Makefile | 2 +-
tools/objtool/arch/loongarch/decode.c | 17 +
tools/objtool/arch/powerpc/decode.c | 18 +
tools/objtool/arch/x86/decode.c | 15 +
tools/objtool/builtin-check.c | 1 +
tools/objtool/check.c | 829 ++++++++++++++++--------
tools/objtool/disas.c | 452 +++++++++++++
tools/objtool/include/objtool/arch.h | 7 +
tools/objtool/include/objtool/builtin.h | 1 +
tools/objtool/include/objtool/check.h | 29 +
tools/objtool/include/objtool/warn.h | 17 +-
12 files changed, 1122 insertions(+), 267 deletions(-)
create mode 100644 tools/objtool/disas.c
--
2.43.5
On Fri, Jun 06, 2025 at 05:34:27PM +0200, Alexandre Chartre wrote:
> Hi,
>
> This RFC provides two 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.
What do I need for this to build? It wasn't compiling due to missing
bfd.h, so I installed binutils-devel (Fedora) and now I get:
In file included from disas.c:12:
/home/jpoimboe/git/linux/tools/include/tools/dis-asm-compat.h:10:6: error: redeclaration of ‘enum disassembler_style’
10 | enum disassembler_style {DISASSEMBLER_STYLE_NOT_EMPTY};
| ^~~~~~~~~~~~~~~~~~
In file included from /home/jpoimboe/git/linux/tools/objtool/include/objtool/arch.h:10,
from disas.c:6:
/usr/include/dis-asm.h:53:6: note: originally defined here
53 | enum disassembler_style
| ^~~~~~~~~~~~~~~~~~
/home/jpoimboe/git/linux/tools/include/tools/dis-asm-compat.h: In function ‘init_disassemble_info_compat’:
/home/jpoimboe/git/linux/tools/include/tools/dis-asm-compat.h:50:9: error: too few arguments to function ‘init_disassemble_info’
50 | init_disassemble_info(info, stream,
| ^~~~~~~~~~~~~~~~~~~~~
/usr/include/dis-asm.h:480:13: note: declared here
480 | extern void init_disassemble_info (struct disassemble_info *dinfo, void *stream,
| ^~~~~~~~~~~~~~~~~~~~~
make[4]: *** [/home/jpoimboe/git/linux/tools/build/Makefile.build:86: /home/jpoimboe/git/linux/tools/objtool/disas.o] Error 1
make[4]: *** Waiting for unfinished jobs....
make[3]: *** [Makefile:65: /home/jpoimboe/git/linux/tools/objtool/objtool-in.o] Error 2
make[2]: *** [Makefile:73: objtool] Error 2
make[1]: *** [/home/jpoimboe/git/linux/Makefile:1448: tools/objtool] Error 2
make: *** [Makefile:248: __sub-make] Error 2
--
Josh
On 6/9/25 20:31, Josh Poimboeuf wrote:
> On Fri, Jun 06, 2025 at 05:34:27PM +0200, Alexandre Chartre wrote:
>> Hi,
>>
>> This RFC provides two 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.
>
> What do I need for this to build? It wasn't compiling due to missing
> bfd.h, so I installed binutils-devel (Fedora) and now I get:
That's because of the more recent binutils versions, while I have been using an old
one (2.30) and some functions have changed. But tools/dis-asm-compat.h handles that
when the appropriate #define is set.
Below is a quick fix (tested with binutils 2.41), and I will work on a proper fix
(by using the tools/ features to check the disassembler version).
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index 00350fc7c662..300ea727e454 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -36,6 +36,8 @@ WARNINGS := $(EXTRA_WARNINGS) -Wno-switch-default -Wno-switch-enum -Wno-packed -
OBJTOOL_CFLAGS := -Werror $(WARNINGS) $(KBUILD_HOSTCFLAGS) -g $(INCLUDES) $(LIBELF_FLAGS)
OBJTOOL_LDFLAGS := $(LIBELF_LIBS) $(LIBSUBCMD) $(KBUILD_HOSTLDFLAGS) -lopcodes
+OBJTOOL_CFLAGS += -DDISASM_INIT_STYLED
+
# Allow old libelf to be used:
elfshdr := $(shell echo '$(pound)include <libelf.h>' | $(HOSTCC) $(OBJTOOL_CFLAGS) -x c -E - 2>/dev/null | grep elf_getshdr)
OBJTOOL_CFLAGS += $(if $(elfshdr),,-DLIBELF_USE_DEPRECATED)
alex.
> In file included from disas.c:12:
> /home/jpoimboe/git/linux/tools/include/tools/dis-asm-compat.h:10:6: error: redeclaration of ‘enum disassembler_style’
> 10 | enum disassembler_style {DISASSEMBLER_STYLE_NOT_EMPTY};
> | ^~~~~~~~~~~~~~~~~~
> In file included from /home/jpoimboe/git/linux/tools/objtool/include/objtool/arch.h:10,
> from disas.c:6:
> /usr/include/dis-asm.h:53:6: note: originally defined here
> 53 | enum disassembler_style
> | ^~~~~~~~~~~~~~~~~~
> /home/jpoimboe/git/linux/tools/include/tools/dis-asm-compat.h: In function ‘init_disassemble_info_compat’:
> /home/jpoimboe/git/linux/tools/include/tools/dis-asm-compat.h:50:9: error: too few arguments to function ‘init_disassemble_info’
> 50 | init_disassemble_info(info, stream,
> | ^~~~~~~~~~~~~~~~~~~~~
> /usr/include/dis-asm.h:480:13: note: declared here
> 480 | extern void init_disassemble_info (struct disassemble_info *dinfo, void *stream,
> | ^~~~~~~~~~~~~~~~~~~~~
> make[4]: *** [/home/jpoimboe/git/linux/tools/build/Makefile.build:86: /home/jpoimboe/git/linux/tools/objtool/disas.o] Error 1
> make[4]: *** Waiting for unfinished jobs....
> make[3]: *** [Makefile:65: /home/jpoimboe/git/linux/tools/objtool/objtool-in.o] Error 2
> make[2]: *** [Makefile:73: objtool] Error 2
> make[1]: *** [/home/jpoimboe/git/linux/Makefile:1448: tools/objtool] Error 2
> make: *** [Makefile:248: __sub-make] Error 2
>
On 6/10/25 09:07, Alexandre Chartre wrote:
>
>
> On 6/9/25 20:31, Josh Poimboeuf wrote:
>> On Fri, Jun 06, 2025 at 05:34:27PM +0200, Alexandre Chartre wrote:
>>> Hi,
>>>
>>> This RFC provides two 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.
>>
>> What do I need for this to build? It wasn't compiling due to missing
>> bfd.h, so I installed binutils-devel (Fedora) and now I get:
>
> That's because of the more recent binutils versions, while I have been using an old
> one (2.30) and some functions have changed. But tools/dis-asm-compat.h handles that
> when the appropriate #define is set.
>
> Below is a quick fix (tested with binutils 2.41), and I will work on a proper fix
> (by using the tools/ features to check the disassembler version).
>
Here is the patch to handle both old and new binutils versions:
8<------------------------------------------------------------------->8
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index 00350fc7c662..91a2858fea14 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -7,6 +7,11 @@ srctree := $(patsubst %/,%,$(dir $(CURDIR)))
srctree := $(patsubst %/,%,$(dir $(srctree)))
endif
+FEATURE_USER = .objtool
+FEATURE_TESTS = disassembler-init-styled
+FEATURE_DISPLAY = disassembler-init-styled
+include $(srctree)/tools/build/Makefile.feature
+
LIBSUBCMD_DIR = $(srctree)/tools/lib/subcmd/
ifneq ($(OUTPUT),)
LIBSUBCMD_OUTPUT = $(abspath $(OUTPUT))/libsubcmd
@@ -40,6 +45,10 @@ OBJTOOL_LDFLAGS := $(LIBELF_LIBS) $(LIBSUBCMD) $(KBUILD_HOSTLDFLAGS) -lopcodes
elfshdr := $(shell echo '$(pound)include <libelf.h>' | $(HOSTCC) $(OBJTOOL_CFLAGS) -x c -E - 2>/dev/null | grep elf_getshdr)
OBJTOOL_CFLAGS += $(if $(elfshdr),,-DLIBELF_USE_DEPRECATED)
+ifeq ($(feature-disassembler-init-styled), 1)
+OBJTOOL_CFLAGS += -DDISASM_INIT_STYLED
+endif
+
# Always want host compilation.
HOST_OVERRIDES := CC="$(HOSTCC)" LD="$(HOSTLD)" AR="$(HOSTAR)"
8<------------------------------------------------------------------->8
alex.
> diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
> index 00350fc7c662..300ea727e454 100644
> --- a/tools/objtool/Makefile
> +++ b/tools/objtool/Makefile
> @@ -36,6 +36,8 @@ WARNINGS := $(EXTRA_WARNINGS) -Wno-switch-default -Wno-switch-enum -Wno-packed -
> OBJTOOL_CFLAGS := -Werror $(WARNINGS) $(KBUILD_HOSTCFLAGS) -g $(INCLUDES) $(LIBELF_FLAGS)
> OBJTOOL_LDFLAGS := $(LIBELF_LIBS) $(LIBSUBCMD) $(KBUILD_HOSTLDFLAGS) -lopcodes
>
> +OBJTOOL_CFLAGS += -DDISASM_INIT_STYLED
> +
> # Allow old libelf to be used:
> elfshdr := $(shell echo '$(pound)include <libelf.h>' | $(HOSTCC) $(OBJTOOL_CFLAGS) -x c -E - 2>/dev/null | grep elf_getshdr)
> OBJTOOL_CFLAGS += $(if $(elfshdr),,-DLIBELF_USE_DEPRECATED)
>
>
> alex.
>
>
>> In file included from disas.c:12:
>> /home/jpoimboe/git/linux/tools/include/tools/dis-asm-compat.h:10:6: error: redeclaration of ‘enum disassembler_style’
>> 10 | enum disassembler_style {DISASSEMBLER_STYLE_NOT_EMPTY};
>> | ^~~~~~~~~~~~~~~~~~
>> In file included from /home/jpoimboe/git/linux/tools/objtool/include/objtool/arch.h:10,
>> from disas.c:6:
>> /usr/include/dis-asm.h:53:6: note: originally defined here
>> 53 | enum disassembler_style
>> | ^~~~~~~~~~~~~~~~~~
>> /home/jpoimboe/git/linux/tools/include/tools/dis-asm-compat.h: In function ‘init_disassemble_info_compat’:
>> /home/jpoimboe/git/linux/tools/include/tools/dis-asm-compat.h:50:9: error: too few arguments to function ‘init_disassemble_info’
>> 50 | init_disassemble_info(info, stream,
>> | ^~~~~~~~~~~~~~~~~~~~~
>> /usr/include/dis-asm.h:480:13: note: declared here
>> 480 | extern void init_disassemble_info (struct disassemble_info *dinfo, void *stream,
>> | ^~~~~~~~~~~~~~~~~~~~~
>> make[4]: *** [/home/jpoimboe/git/linux/tools/build/Makefile.build:86: /home/jpoimboe/git/linux/tools/objtool/disas.o] Error 1
>> make[4]: *** Waiting for unfinished jobs....
>> make[3]: *** [Makefile:65: /home/jpoimboe/git/linux/tools/objtool/objtool-in.o] Error 2
>> make[2]: *** [Makefile:73: objtool] Error 2
>> make[1]: *** [/home/jpoimboe/git/linux/Makefile:1448: tools/objtool] Error 2
>> make: *** [Makefile:248: __sub-make] Error 2
>>
>
On Tue, Jun 10, 2025 at 03:00:50PM +0200, Alexandre Chartre wrote: > Here is the patch to handle both old and new binutils versions: > > 8<------------------------------------------------------------------->8 > diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile > index 00350fc7c662..91a2858fea14 100644 > --- a/tools/objtool/Makefile > +++ b/tools/objtool/Makefile > @@ -7,6 +7,11 @@ srctree := $(patsubst %/,%,$(dir $(CURDIR))) > srctree := $(patsubst %/,%,$(dir $(srctree))) > endif > +FEATURE_USER = .objtool > +FEATURE_TESTS = disassembler-init-styled > +FEATURE_DISPLAY = disassembler-init-styled > +include $(srctree)/tools/build/Makefile.feature Thanks, that worked. That Makefile.feature thing is nice (except it prints an annoying newline on every build after the first one). Can we also use that to determine if binutils-devel (or binutils-dev or whatever) is installed, and then make the build of disas.c optional? Then if somebody tries to use '--trace', it could tell them to install the binutils development package and rebuild objtool. That way we don't disrupt everybody's kernel build for a feature they probably won't use. That would also mean disas_warned_funcs() would be disabled on missing binutils-devel. But I think that's probably fine. In fact that will now have less reason for existing now that we have this tracing. Maybe we won't need it at all. -- Josh
On 6/10/25 23:05, Josh Poimboeuf wrote: > On Tue, Jun 10, 2025 at 03:00:50PM +0200, Alexandre Chartre wrote: >> Here is the patch to handle both old and new binutils versions: >> >> 8<------------------------------------------------------------------->8 >> diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile >> index 00350fc7c662..91a2858fea14 100644 >> --- a/tools/objtool/Makefile >> +++ b/tools/objtool/Makefile >> @@ -7,6 +7,11 @@ srctree := $(patsubst %/,%,$(dir $(CURDIR))) >> srctree := $(patsubst %/,%,$(dir $(srctree))) >> endif >> +FEATURE_USER = .objtool >> +FEATURE_TESTS = disassembler-init-styled >> +FEATURE_DISPLAY = disassembler-init-styled >> +include $(srctree)/tools/build/Makefile.feature > > Thanks, that worked. > > That Makefile.feature thing is nice (except it prints an annoying > newline on every build after the first one). > > Can we also use that to determine if binutils-devel (or binutils-dev or > whatever) is installed, and then make the build of disas.c optional? This would probably require a new feature test, I will look at it. > Then if somebody tries to use '--trace', it could tell them to install > the binutils development package and rebuild objtool. That way we don't > disrupt everybody's kernel build for a feature they probably won't use. > > That would also mean disas_warned_funcs() would be disabled on missing > binutils-devel. But I think that's probably fine. In fact that will > now have less reason for existing now that we have this tracing. Maybe > we won't need it at all. > We can also fall back to using objdump if binutils-devel is not there. And thanks for all the other comments, I will address them and resubmit. I am also adding the "disas" option. alex.
On Wed, Jun 11, 2025 at 08:00:32AM +0200, Alexandre Chartre wrote: > > That would also mean disas_warned_funcs() would be disabled on missing > > binutils-devel. But I think that's probably fine. In fact that will > > now have less reason for existing now that we have this tracing. Maybe > > we won't need it at all. > > > > We can also fall back to using objdump if binutils-devel is not there. I don't think that is needed; normal builds will never use this code. Just print "Rebuild with libopcodes for disasm support" or somesuch when not present. Then developers will know what to do when they need it.
On Fri, Jun 06, 2025 at 05:34:27PM +0200, Alexandre Chartre wrote: > Hi, > > This RFC provides two 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. Ah, nice to get rid of that awful objdump hack. > - 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. This is pretty freaking awesome! I assume we could eventually build on this work to have an "objtool disas" subcommand, which would basically be an improved "objdump -d" which annotates alternatives and other runtime patching. -- Josh
On 6/6/25 17:58, Josh Poimboeuf wrote: > On Fri, Jun 06, 2025 at 05:34:27PM +0200, Alexandre Chartre wrote: >> Hi, >> >> This RFC provides two 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. > > Ah, nice to get rid of that awful objdump hack. > >> - 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. > > This is pretty freaking awesome! > > I assume we could eventually build on this work to have an "objtool > disas" subcommand, which would basically be an improved "objdump -d" > which annotates alternatives and other runtime patching. > Yes, good idea. I will look at it. alex.
© 2016 - 2026 Red Hat, Inc.