summaryrefslogtreecommitdiff
path: root/tools/objtool
diff options
context:
space:
mode:
Diffstat (limited to 'tools/objtool')
-rw-r--r--tools/objtool/Makefile21
-rw-r--r--tools/objtool/check.c3
-rw-r--r--tools/objtool/disas.c14
-rw-r--r--tools/objtool/elf.c13
-rw-r--r--tools/objtool/klp-diff.c14
5 files changed, 44 insertions, 21 deletions
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index 9b4503113ce5..a40f30232929 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -77,8 +77,21 @@ HOST_OVERRIDES := CC="$(HOSTCC)" LD="$(HOSTLD)" AR="$(HOSTAR)"
# We check using HOSTCC directly rather than the shared feature framework
# because objtool is a host tool that links against host libraries.
#
-HAVE_LIBOPCODES := $(shell echo 'int main(void) { return 0; }' | \
- $(HOSTCC) -xc - -o /dev/null -lopcodes 2>/dev/null && echo y)
+# When using shared libraries, -lopcodes is sufficient as dependencies are
+# resolved automatically. With static libraries, we must explicitly link
+# against libopcodes' dependencies: libbfd, libiberty, and sometimes libz.
+# Try each combination and use the first one that succeeds.
+#
+LIBOPCODES_LIBS := $(shell \
+ for libs in "-lopcodes" \
+ "-lopcodes -lbfd" \
+ "-lopcodes -lbfd -liberty" \
+ "-lopcodes -lbfd -liberty -lz"; do \
+ echo 'extern void disassemble_init_for_target(void *);' \
+ 'int main(void) { disassemble_init_for_target(0); return 0; }' | \
+ $(HOSTCC) -xc - -o /dev/null $$libs 2>/dev/null && \
+ echo "$$libs" && break; \
+ done)
# Styled disassembler support requires binutils >= 2.39
HAVE_DISASM_STYLED := $(shell echo '$(pound)include <dis-asm.h>' | \
@@ -86,10 +99,10 @@ HAVE_DISASM_STYLED := $(shell echo '$(pound)include <dis-asm.h>' | \
BUILD_DISAS := n
-ifeq ($(HAVE_LIBOPCODES),y)
+ifneq ($(LIBOPCODES_LIBS),)
BUILD_DISAS := y
OBJTOOL_CFLAGS += -DDISAS -DPACKAGE='"objtool"'
- OBJTOOL_LDFLAGS += -lopcodes
+ OBJTOOL_LDFLAGS += $(LIBOPCODES_LIBS)
ifeq ($(HAVE_DISASM_STYLED),y)
OBJTOOL_CFLAGS += -DDISASM_INIT_STYLED
endif
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 3f7999317f4d..719ec727efd4 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -197,7 +197,8 @@ static bool is_rust_noreturn(const struct symbol *func)
* as well as changes to the source code itself between versions (since
* these come from the Rust standard library).
*/
- return str_ends_with(func->name, "_4core5sliceSp15copy_from_slice17len_mismatch_fail") ||
+ return str_ends_with(func->name, "_4core3num22from_ascii_radix_panic") ||
+ str_ends_with(func->name, "_4core5sliceSp15copy_from_slice17len_mismatch_fail") ||
str_ends_with(func->name, "_4core6option13expect_failed") ||
str_ends_with(func->name, "_4core6option13unwrap_failed") ||
str_ends_with(func->name, "_4core6result13unwrap_failed") ||
diff --git a/tools/objtool/disas.c b/tools/objtool/disas.c
index 2b5059f55e40..26f08d41f2b1 100644
--- a/tools/objtool/disas.c
+++ b/tools/objtool/disas.c
@@ -108,6 +108,8 @@ static int sprint_name(char *str, const char *name, unsigned long offset)
#define DINFO_FPRINTF(dinfo, ...) \
((*(dinfo)->fprintf_func)((dinfo)->stream, __VA_ARGS__))
+#define bfd_vma_fmt \
+ __builtin_choose_expr(sizeof(bfd_vma) == sizeof(unsigned long), "%#lx <%s>", "%#llx <%s>")
static int disas_result_fprintf(struct disas_context *dctx,
const char *fmt, va_list ap)
@@ -170,10 +172,10 @@ static void disas_print_addr_sym(struct section *sec, struct symbol *sym,
if (sym) {
sprint_name(symstr, sym->name, addr - sym->offset);
- DINFO_FPRINTF(dinfo, "0x%lx <%s>", addr, symstr);
+ DINFO_FPRINTF(dinfo, bfd_vma_fmt, addr, symstr);
} else {
str = offstr(sec, addr);
- DINFO_FPRINTF(dinfo, "0x%lx <%s>", addr, str);
+ DINFO_FPRINTF(dinfo, bfd_vma_fmt, addr, str);
free(str);
}
}
@@ -252,7 +254,7 @@ static void disas_print_addr_reloc(bfd_vma addr, struct disassemble_info *dinfo)
* example: "lea 0x0(%rip),%rdi". The kernel can reference
* the next IP with _THIS_IP_ macro.
*/
- DINFO_FPRINTF(dinfo, "0x%lx <_THIS_IP_>", addr);
+ DINFO_FPRINTF(dinfo, bfd_vma_fmt, addr, "_THIS_IP_");
return;
}
@@ -264,11 +266,11 @@ static void disas_print_addr_reloc(bfd_vma addr, struct disassemble_info *dinfo)
*/
if (reloc->sym->type == STT_SECTION) {
str = offstr(reloc->sym->sec, reloc->sym->offset + offset);
- DINFO_FPRINTF(dinfo, "0x%lx <%s>", addr, str);
+ DINFO_FPRINTF(dinfo, bfd_vma_fmt, addr, str);
free(str);
} else {
sprint_name(symstr, reloc->sym->name, offset);
- DINFO_FPRINTF(dinfo, "0x%lx <%s>", addr, symstr);
+ DINFO_FPRINTF(dinfo, bfd_vma_fmt, addr, symstr);
}
}
@@ -311,7 +313,7 @@ static void disas_print_address(bfd_vma addr, struct disassemble_info *dinfo)
*/
sym = insn_call_dest(insn);
if (sym && (sym->offset == addr || (sym->offset == 0 && is_reloc))) {
- DINFO_FPRINTF(dinfo, "0x%lx <%s>", addr, sym->name);
+ DINFO_FPRINTF(dinfo, bfd_vma_fmt, addr, sym->name);
return;
}
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 6a8ed9c62323..2c02c7b49265 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -18,15 +18,14 @@
#include <errno.h>
#include <libgen.h>
#include <ctype.h>
+#include <linux/align.h>
+#include <linux/kernel.h>
#include <linux/interval_tree_generic.h>
+#include <linux/log2.h>
#include <objtool/builtin.h>
#include <objtool/elf.h>
#include <objtool/warn.h>
-#define ALIGN_UP(x, align_to) (((x) + ((align_to)-1)) & ~((align_to)-1))
-#define ALIGN_UP_POW2(x) (1U << ((8 * sizeof(x)) - __builtin_clz((x) - 1U)))
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-
static inline u32 str_hash(const char *str)
{
return jhash(str, strlen(str), 0);
@@ -1336,7 +1335,7 @@ unsigned int elf_add_string(struct elf *elf, struct section *strtab, const char
return -1;
}
- offset = ALIGN_UP(strtab->sh.sh_size, strtab->sh.sh_addralign);
+ offset = ALIGN(strtab->sh.sh_size, strtab->sh.sh_addralign);
if (!elf_add_data(elf, strtab, str, strlen(str) + 1))
return -1;
@@ -1378,7 +1377,7 @@ void *elf_add_data(struct elf *elf, struct section *sec, const void *data, size_
sec->data->d_size = size;
sec->data->d_align = 1;
- offset = ALIGN_UP(sec->sh.sh_size, sec->sh.sh_addralign);
+ offset = ALIGN(sec->sh.sh_size, sec->sh.sh_addralign);
sec->sh.sh_size = offset + size;
mark_sec_changed(elf, sec, true);
@@ -1502,7 +1501,7 @@ static int elf_alloc_reloc(struct elf *elf, struct section *rsec)
rsec->data->d_size = nr_relocs_new * elf_rela_size(elf);
rsec->sh.sh_size = rsec->data->d_size;
- nr_alloc = MAX(64, ALIGN_UP_POW2(nr_relocs_new));
+ nr_alloc = max(64UL, roundup_pow_of_two(nr_relocs_new));
if (nr_alloc <= rsec->nr_alloc_relocs)
return 0;
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index 4d1f9e9977eb..d94531e3f64e 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -1425,9 +1425,6 @@ static int clone_special_sections(struct elfs *e)
{
struct section *patched_sec;
- if (create_fake_symbols(e->patched))
- return -1;
-
for_each_sec(e->patched, patched_sec) {
if (is_special_section(patched_sec)) {
if (clone_special_section(e, patched_sec))
@@ -1704,6 +1701,17 @@ int cmd_klp_diff(int argc, const char **argv)
if (!e.out)
return -1;
+ /*
+ * Special section fake symbols are needed so that individual special
+ * section entries can be extracted by clone_special_sections().
+ *
+ * Note the fake symbols are also needed by clone_included_functions()
+ * because __WARN_printf() call sites add references to bug table
+ * entries in the calling functions.
+ */
+ if (create_fake_symbols(e.patched))
+ return -1;
+
if (clone_included_functions(&e))
return -1;