Re: [PATCH v6 03/30] objtool: Disassemble code with libopcodes instead of running objdump

From: Alexandre Chartre
Date: Wed Dec 10 2025 - 11:38:06 EST




On 12/10/25 16:26, Guenter Roeck wrote:
On 12/9/25 23:53, Alexandre Chartre wrote:


On 12/10/25 06:08, Guenter Roeck wrote:
On 12/9/25 14:25, Maciej W. Rozycki wrote:
On Tue, 9 Dec 2025, Alexandre Chartre wrote:

Bisect log is attached. I see the problem with gcc 11.4.0, 13.3.0, and
14.3.0. I tried with both Ubuntu 22.04 and 24.04.

This sounds like a configuration issue depending on the binutils version; in
particular the setting of DISASM_INIT_STYLED (although that's supposed to be
automatically configured by tools/objtool/Makefile).

  I only came across these patches now.

  As attractive as it may seem how is this stuff supposed to fly given that
binutils internal libraries promise no stable API to out-of-tree software.
The interfaces can change anytime, just as it is with our internals.

  Wouldn't it make sense to improve objdump instead so as to provide the
features required?

  Also is it actually legal to link objtool and libopcodes together, given
that they are GPLv2 and GPLv3 respectively?

  FWIW asking as one of the binutils contributors and port maintainers.


After some more digging I found that the version of binutils installed in
the system determines if the build error is seen or not. So I can have
a toolchain with the latest binutils version, but the build still fails if
the binutils version installed in the system is too old. 2.38 (as in
Ubuntu 22.04) is too old since it does not define 'enum disassembler_style'
in dis-asm.h. As far as I can see that enum was only introduced with
binutils 2.39.

Now the problem is that DISASM_INIT_STYLED is evaluated with
tools/build/feature/test-disassembler-init-styled.c, which checks for
the existence of struct disassemble_info (not the enum). AFAICS that
structure was introduced with binutils-2_18.

Unless my analysis is wrong that means that Linux will now fail to build
on systems with binutils 2.18 ... 2.38 installed.


test-disassembler-init-styled.c tests that init_disassemble_info() has four
arguments. If this fails then this means that it has only three args and in
that case enum disassembler_style is not defined, and the build should be done
without defining DISASM_INIT_STYLED.

init_disassemble_info() was changed from 3 args to 4 args by the following
binutils change, and enum disassembler_style was introduced at the same time:

   https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=60a3da00bd5407f07

This change has caused the Linux build to fail, and this was fixed by commit
a45b3d6926231 ("tools include: add dis-asm-compat.h to handle version differences")
which introduced dis-asm-compat.h

Can you check that init_disassemble_info() is declared with only 3 arguments
in your dis-asm.h file? (/usr/include/dis-asm.h).

dis-asm.h should either:

- declare init_disassemble_info() with 3 args and not define enum disassembler_style

or

- declare init_disassemble_info() with 4 args and define enum disassembler_style


Thanks for the clarification.

Here is the declaration:

/* Method to initialize a disassemble_info struct.  This should be
   called by all applications creating such a struct.  */
extern void init_disassemble_info (struct disassemble_info *dinfo, void *stream,
                                   fprintf_ftype fprintf_func);

So it has three arguments, but DISASM_INIT_STYLED is defined anyway.

I think I found the problem: not even "make mrproper" or "make distclean" deletes
./tools/objtool/feature/test-disassembler-init-styled.bin, and the file existed
in my tree. So DISASM_INIT_STYLED just ended up being defined until I deleted
the file manually.

This condition also happens in my build system. I have not been able to re-create
the situation where the .bin file exists but shouldn't, but it somehow does happen.


That's weird because the "clean" rule in tools/objtool/Makefile should remove the
entire tools/objtool/feature directory:

$ cat tools/objtool/Makefile
...
clean: $(LIBSUBCMD)-clean
$(call QUIET_CLEAN, objtool) $(RM) $(OBJTOOL)
$(Q)find $(OUTPUT) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
$(Q)$(RM) $(OUTPUT)arch/x86/lib/cpu-feature-names.c $(OUTPUT)fixdep
$(Q)$(RM) $(OUTPUT)arch/x86/lib/inat-tables.c $(OUTPUT)fixdep
$(Q)$(RM) -- $(OUTPUT)FEATURE-DUMP.objtool
$(Q)$(RM) -r -- $(OUTPUT)feature

see $(Q)$(RM) -r -- $(OUTPUT)feature

alex.