objtool: Fix libopcodes linking with static libraries

Commit 436326bc525d ("objtool: fix build failure due to missing libopcodes
check") tests for libopcodes using an empty main(), which passes even when
static libraries lack their dependencies. This causes undefined reference
errors (xmalloc, bfd_get_bits, etc.) when linking against static libopcodes
without its required libbfd and libiberty.

Fix by testing with an actual libopcodes symbol and trying increasingly
complete library combinations until one succeeds.

Fixes: 436326bc525d ("objtool: fix build failure due to missing libopcodes check")
Reported-by: Rafael J. Wysocki <rafael@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Tested-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
Link: https://patch.msgid.link/20260121162532.1596238-1-sashal@kernel.org

authored by Sasha Levin and committed by Peter Zijlstra 3f2de814 24d479d2

+17 -4
+17 -4
tools/objtool/Makefile
··· 77 # We check using HOSTCC directly rather than the shared feature framework 78 # because objtool is a host tool that links against host libraries. 79 # 80 - HAVE_LIBOPCODES := $(shell echo 'int main(void) { return 0; }' | \ 81 - $(HOSTCC) -xc - -o /dev/null -lopcodes 2>/dev/null && echo y) 82 83 # Styled disassembler support requires binutils >= 2.39 84 HAVE_DISASM_STYLED := $(shell echo '$(pound)include <dis-asm.h>' | \ ··· 99 100 BUILD_DISAS := n 101 102 - ifeq ($(HAVE_LIBOPCODES),y) 103 BUILD_DISAS := y 104 OBJTOOL_CFLAGS += -DDISAS -DPACKAGE='"objtool"' 105 - OBJTOOL_LDFLAGS += -lopcodes 106 ifeq ($(HAVE_DISASM_STYLED),y) 107 OBJTOOL_CFLAGS += -DDISASM_INIT_STYLED 108 endif
··· 77 # We check using HOSTCC directly rather than the shared feature framework 78 # because objtool is a host tool that links against host libraries. 79 # 80 + # When using shared libraries, -lopcodes is sufficient as dependencies are 81 + # resolved automatically. With static libraries, we must explicitly link 82 + # against libopcodes' dependencies: libbfd, libiberty, and sometimes libz. 83 + # Try each combination and use the first one that succeeds. 84 + # 85 + LIBOPCODES_LIBS := $(shell \ 86 + for libs in "-lopcodes" \ 87 + "-lopcodes -lbfd" \ 88 + "-lopcodes -lbfd -liberty" \ 89 + "-lopcodes -lbfd -liberty -lz"; do \ 90 + echo 'extern void disassemble_init_for_target(void *);' \ 91 + 'int main(void) { disassemble_init_for_target(0); return 0; }' | \ 92 + $(HOSTCC) -xc - -o /dev/null $$libs 2>/dev/null && \ 93 + echo "$$libs" && break; \ 94 + done) 95 96 # Styled disassembler support requires binutils >= 2.39 97 HAVE_DISASM_STYLED := $(shell echo '$(pound)include <dis-asm.h>' | \ ··· 86 87 BUILD_DISAS := n 88 89 + ifneq ($(LIBOPCODES_LIBS),) 90 BUILD_DISAS := y 91 OBJTOOL_CFLAGS += -DDISAS -DPACKAGE='"objtool"' 92 + OBJTOOL_LDFLAGS += $(LIBOPCODES_LIBS) 93 ifeq ($(HAVE_DISASM_STYLED),y) 94 OBJTOOL_CFLAGS += -DDISASM_INIT_STYLED 95 endif