Commit a3493b33 authored by Josh Poimboeuf's avatar Josh Poimboeuf
Browse files

objtool/klp: Add --debug-checksum=<funcs> to show per-instruction checksums



Add a --debug-checksum=<funcs> option to the check subcommand to print
the calculated checksum of each instruction in the given functions.

This is useful for determining where two versions of a function begin to
diverge.

Acked-by: default avatarPetr Mladek <pmladek@suse.com>
Tested-by: default avatarJoe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: default avatarJosh Poimboeuf <jpoimboe@kernel.org>
parent 0d83da43
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -94,6 +94,7 @@ static const struct option check_options[] = {
	OPT_GROUP("Options:"),
	OPT_BOOLEAN(0,		 "backtrace", &opts.backtrace, "unwind on error"),
	OPT_BOOLEAN(0,		 "backup", &opts.backup, "create backup (.orig) file on warning/error"),
	OPT_STRING(0,		 "debug-checksum", &opts.debug_checksum,  "funcs", "enable checksum debug output"),
	OPT_BOOLEAN(0,		 "dry-run", &opts.dryrun, "don't write modifications"),
	OPT_BOOLEAN(0,		 "link", &opts.link, "object is a linked object"),
	OPT_BOOLEAN(0,		 "module", &opts.module, "object is part of a kernel module"),
@@ -168,6 +169,11 @@ static bool opts_valid(void)
	}
#endif

	if (opts.debug_checksum && !opts.checksum) {
		ERROR("--debug-checksum requires --checksum");
		return false;
	}

	if (opts.checksum		||
	    opts.hack_jump_label	||
	    opts.hack_noinstr		||
+42 −0
Original line number Diff line number Diff line
@@ -3580,6 +3580,44 @@ static bool skip_alt_group(struct instruction *insn)
	return alt_insn->type == INSN_CLAC || alt_insn->type == INSN_STAC;
}

static int checksum_debug_init(struct objtool_file *file)
{
	char *dup, *s;

	if (!opts.debug_checksum)
		return 0;

	dup = strdup(opts.debug_checksum);
	if (!dup) {
		ERROR_GLIBC("strdup");
		return -1;
	}

	s = dup;
	while (*s) {
		struct symbol *func;
		char *comma;

		comma = strchr(s, ',');
		if (comma)
			*comma = '\0';

		func = find_symbol_by_name(file->elf, s);
		if (!func || !is_func_sym(func))
			WARN("--debug-checksum: can't find '%s'", s);
		else
			func->debug_checksum = 1;

		if (!comma)
			break;

		s = comma + 1;
	}

	free(dup);
	return 0;
}

static void checksum_update_insn(struct objtool_file *file, struct symbol *func,
				 struct instruction *insn)
{
@@ -4818,6 +4856,10 @@ int check(struct objtool_file *file)
	cfi_hash_add(&init_cfi);
	cfi_hash_add(&func_cfi);

	ret = checksum_debug_init(file);
	if (ret)
		goto out;

	ret = decode_sections(file);
	if (ret)
		goto out;
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ struct opts {
	/* options: */
	bool backtrace;
	bool backup;
	const char *debug_checksum;
	bool dryrun;
	bool link;
	bool mnop;
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ static inline void checksum_update(struct symbol *func,
				   const void *data, size_t size)
{
	XXH3_64bits_update(func->csum.state, data, size);
	dbg_checksum(func, insn, XXH3_64bits_digest(func->csum.state));
}

static inline void checksum_finish(struct symbol *func)
+1 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ struct symbol {
	u8 nocfi             : 1;
	u8 cold		     : 1;
	u8 prefix	     : 1;
	u8 debug_checksum    : 1;
	struct list_head pv_target;
	struct reloc *relocs;
	struct section *group_sec;
Loading