In preparation for porting the checksum code to other arches, make its functionality independent from validate_branch().
Signed-off-by: Josh Poimboeuf <[email protected]> --- tools/objtool/check.c | 71 +++++++++++++++++------- tools/objtool/include/objtool/checksum.h | 6 +- 2 files changed, 53 insertions(+), 24 deletions(-) diff --git a/tools/objtool/check.c b/tools/objtool/check.c index a30379e4ff97..f73cf1382e5c 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -2633,8 +2633,7 @@ static bool validate_branch_enabled(void) { return opts.stackval || opts.orc || - opts.uaccess || - opts.checksum; + opts.uaccess; } static int decode_sections(struct objtool_file *file) @@ -3649,6 +3648,7 @@ static bool skip_alt_group(struct instruction *insn) return alt_insn->type == INSN_CLAC || alt_insn->type == INSN_STAC; } +#ifdef BUILD_KLP static int checksum_debug_init(struct objtool_file *file) { char *dup, *s; @@ -3691,9 +3691,30 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func, struct instruction *insn) { struct reloc *reloc = insn_reloc(file, insn); + struct alternative *alt; unsigned long offset; struct symbol *sym; + for (alt = insn->alts; alt; alt = alt->next) { + struct alt_group *alt_group = alt->insn->alt_group; + + checksum_update(func, insn, &alt->type, sizeof(alt->type)); + + if (alt_group && alt_group->orig_group) { + struct instruction *alt_insn; + + checksum_update(func, insn, &alt_group->feature, sizeof(alt_group->feature)); + + for (alt_insn = alt->insn; alt_insn; alt_insn = next_insn_same_sec(file, alt_insn)) { + checksum_update_insn(file, func, alt_insn); + if (alt_insn == alt_group->last_insn) + break; + } + } else { + checksum_update(func, insn, &alt->insn->offset, sizeof(alt->insn->offset)); + } + } + if (insn->fake) return; @@ -3702,9 +3723,11 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func, if (!reloc) { struct symbol *call_dest = insn_call_dest(insn); - if (call_dest) + if (call_dest) { + /* intra-TU call without reloc */ checksum_update(func, insn, call_dest->demangled_name, strlen(call_dest->demangled_name)); + } return; } @@ -3731,6 +3754,29 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func, checksum_update(func, insn, &offset, sizeof(offset)); } +static int calculate_checksums(struct objtool_file *file) +{ + struct instruction *insn; + struct symbol *func; + + if (checksum_debug_init(file)) + return -1; + + for_each_sym(file->elf, func) { + if (!is_func_sym(func)) + continue; + + checksum_init(func); + + func_for_each_insn(file, func, insn) + checksum_update_insn(file, func, insn); + + checksum_finish(func); + } + return 0; +} +#endif /* BUILD_KLP */ + static int validate_branch(struct objtool_file *file, struct symbol *func, struct instruction *insn, struct insn_state state); static int do_validate_branch(struct objtool_file *file, struct symbol *func, @@ -4012,9 +4058,6 @@ static int do_validate_branch(struct objtool_file *file, struct symbol *func, insn->trace = 0; next_insn = next_insn_to_validate(file, insn); - if (opts.checksum && func && insn->sec) - checksum_update_insn(file, func, insn); - if (func && insn_func(insn) && func != insn_func(insn)->pfunc) { /* Ignore KCFI type preambles, which always fall through */ if (is_prefix_func(func)) @@ -4080,9 +4123,6 @@ static int validate_unwind_hint(struct objtool_file *file, struct symbol *func = insn_func(insn); int ret; - if (opts.checksum) - checksum_init(func); - ret = validate_branch(file, func, insn, *state); if (ret) BT_INSN(insn, "<=== (hint)"); @@ -4525,9 +4565,6 @@ static int validate_symbol(struct objtool_file *file, struct section *sec, func = insn_func(insn); - if (opts.checksum) - checksum_init(func); - if (opts.trace && !fnmatch(opts.trace, sym->name, 0)) { trace_enable(); TRACE("%s: validation begin\n", sym->name); @@ -4540,9 +4577,6 @@ static int validate_symbol(struct objtool_file *file, struct section *sec, TRACE("%s: validation %s\n\n", sym->name, ret ? "failed" : "end"); trace_disable(); - if (opts.checksum) - checksum_finish(func); - return ret; } @@ -4997,10 +5031,6 @@ 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; @@ -5091,6 +5121,9 @@ int check(struct objtool_file *file) warnings += check_abs_references(file); if (opts.checksum) { + ret = calculate_checksums(file); + if (ret) + goto out; ret = create_sym_checksum_section(file); if (ret) goto out; diff --git a/tools/objtool/include/objtool/checksum.h b/tools/objtool/include/objtool/checksum.h index 7fe21608722a..36a17688c716 100644 --- a/tools/objtool/include/objtool/checksum.h +++ b/tools/objtool/include/objtool/checksum.h @@ -32,11 +32,7 @@ static inline void checksum_finish(struct symbol *func) #else /* !BUILD_KLP */ -static inline void checksum_init(struct symbol *func) {} -static inline void checksum_update(struct symbol *func, - struct instruction *insn, - const void *data, size_t size) {} -static inline void checksum_finish(struct symbol *func) {} +static inline int calculate_checksums(struct objtool_file *file) { return -ENOSYS; } #endif /* !BUILD_KLP */ -- 2.53.0

