objtool: Move object file loading out of check()

Structure objtool_file can be used by different subcommands. In fact
it already is, by check and orc.

Provide a function that allows to initialize objtool_file, that builtin
can call, without relying on check to do the correct setup for them and
explicitly hand the objtool_file to them.

Reviewed-by: Miroslav Benes <mbenes@suse.cz>
Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
This commit is contained in:
Julien Thierry 2020-08-25 13:47:39 +01:00 committed by Josh Poimboeuf
parent 7c9903c9bf
commit 6545eb030e
6 changed files with 60 additions and 35 deletions

View File

@ -41,6 +41,7 @@ const struct option check_options[] = {
int cmd_check(int argc, const char **argv) int cmd_check(int argc, const char **argv)
{ {
const char *objname, *s; const char *objname, *s;
struct objtool_file *file;
argc = parse_options(argc, argv, check_options, check_usage, 0); argc = parse_options(argc, argv, check_options, check_usage, 0);
@ -53,5 +54,9 @@ int cmd_check(int argc, const char **argv)
if (s && !s[9]) if (s && !s[9])
vmlinux = true; vmlinux = true;
return check(objname, false); file = objtool_open_read(objname);
if (!file)
return 1;
return check(file, false);
} }

View File

@ -31,13 +31,19 @@ int cmd_orc(int argc, const char **argv)
usage_with_options(orc_usage, check_options); usage_with_options(orc_usage, check_options);
if (!strncmp(argv[0], "gen", 3)) { if (!strncmp(argv[0], "gen", 3)) {
struct objtool_file *file;
argc = parse_options(argc, argv, check_options, orc_usage, 0); argc = parse_options(argc, argv, check_options, orc_usage, 0);
if (argc != 1) if (argc != 1)
usage_with_options(orc_usage, check_options); usage_with_options(orc_usage, check_options);
objname = argv[0]; objname = argv[0];
return check(objname, true); file = objtool_open_read(objname);
if (!file)
return 1;
return check(file, true);
} }
if (!strcmp(argv[0], "dump")) { if (!strcmp(argv[0], "dump")) {

View File

@ -28,7 +28,6 @@ struct alternative {
bool skip_orig; bool skip_orig;
}; };
const char *objname;
struct cfi_init_state initial_func_cfi; struct cfi_init_state initial_func_cfi;
struct instruction *find_insn(struct objtool_file *file, struct instruction *find_insn(struct objtool_file *file,
@ -2909,37 +2908,22 @@ static int validate_reachable_instructions(struct objtool_file *file)
return 0; return 0;
} }
static struct objtool_file file; int check(struct objtool_file *file, bool orc)
int check(const char *_objname, bool orc)
{ {
int ret, warnings = 0; int ret, warnings = 0;
objname = _objname;
file.elf = elf_open_read(objname, O_RDWR);
if (!file.elf)
return 1;
INIT_LIST_HEAD(&file.insn_list);
hash_init(file.insn_hash);
INIT_LIST_HEAD(&file.static_call_list);
file.c_file = !vmlinux && find_section_by_name(file.elf, ".comment");
file.ignore_unreachables = no_unreachable;
file.hints = false;
arch_initial_func_cfi_state(&initial_func_cfi); arch_initial_func_cfi_state(&initial_func_cfi);
ret = decode_sections(&file); ret = decode_sections(file);
if (ret < 0) if (ret < 0)
goto out; goto out;
warnings += ret; warnings += ret;
if (list_empty(&file.insn_list)) if (list_empty(&file->insn_list))
goto out; goto out;
if (vmlinux && !validate_dup) { if (vmlinux && !validate_dup) {
ret = validate_vmlinux_functions(&file); ret = validate_vmlinux_functions(file);
if (ret < 0) if (ret < 0)
goto out; goto out;
@ -2948,46 +2932,46 @@ int check(const char *_objname, bool orc)
} }
if (retpoline) { if (retpoline) {
ret = validate_retpoline(&file); ret = validate_retpoline(file);
if (ret < 0) if (ret < 0)
return ret; return ret;
warnings += ret; warnings += ret;
} }
ret = validate_functions(&file); ret = validate_functions(file);
if (ret < 0) if (ret < 0)
goto out; goto out;
warnings += ret; warnings += ret;
ret = validate_unwind_hints(&file, NULL); ret = validate_unwind_hints(file, NULL);
if (ret < 0) if (ret < 0)
goto out; goto out;
warnings += ret; warnings += ret;
if (!warnings) { if (!warnings) {
ret = validate_reachable_instructions(&file); ret = validate_reachable_instructions(file);
if (ret < 0) if (ret < 0)
goto out; goto out;
warnings += ret; warnings += ret;
} }
ret = create_static_call_sections(&file); ret = create_static_call_sections(file);
if (ret < 0) if (ret < 0)
goto out; goto out;
warnings += ret; warnings += ret;
if (orc) { if (orc) {
ret = create_orc(&file); ret = create_orc(file);
if (ret < 0) if (ret < 0)
goto out; goto out;
ret = create_orc_sections(&file); ret = create_orc_sections(file);
if (ret < 0) if (ret < 0)
goto out; goto out;
} }
if (file.elf->changed) { if (file->elf->changed) {
ret = elf_write(file.elf); ret = elf_write(file->elf);
if (ret < 0) if (ret < 0)
goto out; goto out;
} }

View File

@ -22,6 +22,8 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include "builtin.h" #include "builtin.h"
#include "objtool.h"
#include "warn.h"
struct cmd_struct { struct cmd_struct {
const char *name; const char *name;
@ -39,6 +41,34 @@ static struct cmd_struct objtool_cmds[] = {
bool help; bool help;
const char *objname;
static struct objtool_file file;
struct objtool_file *objtool_open_read(const char *_objname)
{
if (objname) {
if (strcmp(objname, _objname)) {
WARN("won't handle more than one file at a time");
return NULL;
}
return &file;
}
objname = _objname;
file.elf = elf_open_read(objname, O_RDWR);
if (!file.elf)
return NULL;
INIT_LIST_HEAD(&file.insn_list);
hash_init(file.insn_hash);
INIT_LIST_HEAD(&file.static_call_list);
file.c_file = !vmlinux && find_section_by_name(file.elf, ".comment");
file.ignore_unreachables = no_unreachable;
file.hints = false;
return &file;
}
static void cmd_usage(void) static void cmd_usage(void)
{ {
unsigned int i, longest = 0; unsigned int i, longest = 0;

View File

@ -20,7 +20,9 @@ struct objtool_file {
bool ignore_unreachables, c_file, hints, rodata; bool ignore_unreachables, c_file, hints, rodata;
}; };
int check(const char *objname, bool orc); struct objtool_file *objtool_open_read(const char *_objname);
int check(struct objtool_file *file, bool orc);
int orc_dump(const char *objname); int orc_dump(const char *objname);
int create_orc(struct objtool_file *file); int create_orc(struct objtool_file *file);
int create_orc_sections(struct objtool_file *file); int create_orc_sections(struct objtool_file *file);

View File

@ -17,9 +17,7 @@
return ENOSYS; \ return ENOSYS; \
}) })
const char __weak *objname; int __weak check(struct objtool_file *file, bool orc)
int __weak check(const char *_objname, bool orc)
{ {
UNSUPPORTED("check subcommand"); UNSUPPORTED("check subcommand");
} }