builtin-check.c (2daf7faba7ded8703e4b4ebc8b161f22272fc91a) builtin-check.c (b51277eb9775ce916f9efd2c51533e481180c1e8)
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2015-2017 Josh Poimboeuf <jpoimboe@redhat.com>
4 */
5
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2015-2017 Josh Poimboeuf <jpoimboe@redhat.com>
4 */
5
6/*
7 * objtool check:
8 *
9 * This command analyzes every .o file and ensures the validity of its stack
10 * trace metadata. It enforces a set of rules on asm code and C inline
11 * assembly code so that stack traces can be reliable.
12 *
13 * For more information, see tools/objtool/Documentation/stack-validation.txt.
14 */
15
16#include <subcmd/parse-options.h>
17#include <string.h>
18#include <stdlib.h>
19#include <objtool/builtin.h>
20#include <objtool/objtool.h>
21
22struct opts opts;
23
24static const char * const check_usage[] = {
6#include <subcmd/parse-options.h>
7#include <string.h>
8#include <stdlib.h>
9#include <objtool/builtin.h>
10#include <objtool/objtool.h>
11
12struct opts opts;
13
14static const char * const check_usage[] = {
25 "objtool check <actions> [<options>] file.o",
15 "objtool <actions> [<options>] file.o",
26 NULL,
27};
28
29static const char * const env_usage[] = {
30 "OBJTOOL_ARGS=\"<options>\"",
31 NULL,
32};
33
16 NULL,
17};
18
19static const char * const env_usage[] = {
20 "OBJTOOL_ARGS=\"<options>\"",
21 NULL,
22};
23
24static int parse_dump(const struct option *opt, const char *str, int unset)
25{
26 if (!str || !strcmp(str, "orc")) {
27 opts.dump_orc = true;
28 return 0;
29 }
30
31 return -1;
32}
33
34const struct option check_options[] = {
35 OPT_GROUP("Actions:"),
36 OPT_BOOLEAN('i', "ibt", &opts.ibt, "validate and annotate IBT"),
37 OPT_BOOLEAN('m', "mcount", &opts.mcount, "annotate mcount/fentry calls for ftrace"),
38 OPT_BOOLEAN('n', "noinstr", &opts.noinstr, "validate noinstr rules"),
34const struct option check_options[] = {
35 OPT_GROUP("Actions:"),
36 OPT_BOOLEAN('i', "ibt", &opts.ibt, "validate and annotate IBT"),
37 OPT_BOOLEAN('m', "mcount", &opts.mcount, "annotate mcount/fentry calls for ftrace"),
38 OPT_BOOLEAN('n', "noinstr", &opts.noinstr, "validate noinstr rules"),
39 OPT_BOOLEAN('o', "orc", &opts.orc, "generate ORC metadata"),
39 OPT_BOOLEAN('r', "retpoline", &opts.retpoline, "validate and annotate retpoline usage"),
40 OPT_BOOLEAN('l', "sls", &opts.sls, "validate straight-line-speculation mitigations"),
41 OPT_BOOLEAN('u', "uaccess", &opts.uaccess, "validate uaccess rules for SMAP"),
40 OPT_BOOLEAN('r', "retpoline", &opts.retpoline, "validate and annotate retpoline usage"),
41 OPT_BOOLEAN('l', "sls", &opts.sls, "validate straight-line-speculation mitigations"),
42 OPT_BOOLEAN('u', "uaccess", &opts.uaccess, "validate uaccess rules for SMAP"),
43 OPT_CALLBACK_OPTARG(0, "dump", NULL, NULL, "orc", "dump metadata", parse_dump),
42
43 OPT_GROUP("Options:"),
44 OPT_BOOLEAN(0, "backtrace", &opts.backtrace, "unwind on error"),
45 OPT_BOOLEAN(0, "backup", &opts.backup, "create .orig files before modification"),
46 OPT_BOOLEAN(0, "dry-run", &opts.dryrun, "don't write modifications"),
47 OPT_BOOLEAN(0, "lto", &opts.lto, "whole-archive like runs"),
48 OPT_BOOLEAN(0, "module", &opts.module, "object is part of a kernel module"),
49 OPT_BOOLEAN(0, "no-fp", &opts.no_fp, "skip frame pointer validation"),

--- 26 unchanged lines hidden (view full) ---

76 }
77
78 argc = parse_options(argc, argv, check_options, usage, 0);
79 if (argc != 1)
80 usage_with_options(usage, check_options);
81 return argc;
82}
83
44
45 OPT_GROUP("Options:"),
46 OPT_BOOLEAN(0, "backtrace", &opts.backtrace, "unwind on error"),
47 OPT_BOOLEAN(0, "backup", &opts.backup, "create .orig files before modification"),
48 OPT_BOOLEAN(0, "dry-run", &opts.dryrun, "don't write modifications"),
49 OPT_BOOLEAN(0, "lto", &opts.lto, "whole-archive like runs"),
50 OPT_BOOLEAN(0, "module", &opts.module, "object is part of a kernel module"),
51 OPT_BOOLEAN(0, "no-fp", &opts.no_fp, "skip frame pointer validation"),

--- 26 unchanged lines hidden (view full) ---

78 }
79
80 argc = parse_options(argc, argv, check_options, usage, 0);
81 if (argc != 1)
82 usage_with_options(usage, check_options);
83 return argc;
84}
85
84int cmd_check(int argc, const char **argv)
86static bool opts_valid(void)
85{
87{
88 if (opts.ibt ||
89 opts.mcount ||
90 opts.noinstr ||
91 opts.orc ||
92 opts.retpoline ||
93 opts.sls ||
94 opts.uaccess) {
95 if (opts.dump_orc) {
96 fprintf(stderr, "--dump can't be combined with other options\n");
97 return false;
98 }
99
100 return true;
101 }
102
103 if (opts.dump_orc)
104 return true;
105
106 fprintf(stderr, "At least one command required\n");
107 return false;
108}
109
110int objtool_run(int argc, const char **argv)
111{
86 const char *objname;
87 struct objtool_file *file;
88 int ret;
89
90 argc = cmd_parse_options(argc, argv, check_usage);
91 objname = argv[0];
92
112 const char *objname;
113 struct objtool_file *file;
114 int ret;
115
116 argc = cmd_parse_options(argc, argv, check_usage);
117 objname = argv[0];
118
119 if (!opts_valid())
120 return 1;
121
122 if (opts.dump_orc)
123 return orc_dump(objname);
124
93 file = objtool_open_read(objname);
94 if (!file)
95 return 1;
96
97 ret = check(file);
98 if (ret)
99 return ret;
100
101 if (file->elf->changed)
102 return elf_write(file->elf);
103
104 return 0;
105}
125 file = objtool_open_read(objname);
126 if (!file)
127 return 1;
128
129 ret = check(file);
130 if (ret)
131 return ret;
132
133 if (file->elf->changed)
134 return elf_write(file->elf);
135
136 return 0;
137}