Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Copyright (C) 2015-2017 Josh Poimboeuf <jpoimboe@redhat.com>
  4 */
  5
 
 
 
 
 
 
 
 
 
 
  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
 12#define ERROR(format, ...)				\
 13	fprintf(stderr,					\
 14		"error: objtool: " format "\n",		\
 15		##__VA_ARGS__)
 16
 17struct opts opts;
 18
 19static const char * const check_usage[] = {
 20	"objtool <actions> [<options>] file.o",
 21	NULL,
 22};
 23
 24static const char * const env_usage[] = {
 25	"OBJTOOL_ARGS=\"<options>\"",
 26	NULL,
 27};
 28
 29static int parse_dump(const struct option *opt, const char *str, int unset)
 30{
 31	if (!str || !strcmp(str, "orc")) {
 32		opts.dump_orc = true;
 33		return 0;
 34	}
 35
 36	return -1;
 37}
 38
 39static int parse_hacks(const struct option *opt, const char *str, int unset)
 40{
 41	bool found = false;
 42
 43	/*
 44	 * Use strstr() as a lazy method of checking for comma-separated
 45	 * options.
 46	 *
 47	 * No string provided == enable all options.
 48	 */
 49
 50	if (!str || strstr(str, "jump_label")) {
 51		opts.hack_jump_label = true;
 52		found = true;
 53	}
 54
 55	if (!str || strstr(str, "noinstr")) {
 56		opts.hack_noinstr = true;
 57		found = true;
 58	}
 59
 60	if (!str || strstr(str, "skylake")) {
 61		opts.hack_skylake = true;
 62		found = true;
 63	}
 64
 65	return found ? 0 : -1;
 66}
 67
 68static const struct option check_options[] = {
 69	OPT_GROUP("Actions:"),
 70	OPT_CALLBACK_OPTARG('h', "hacks", NULL, NULL, "jump_label,noinstr,skylake", "patch toolchain bugs/limitations", parse_hacks),
 71	OPT_BOOLEAN('i', "ibt", &opts.ibt, "validate and annotate IBT"),
 72	OPT_BOOLEAN('m', "mcount", &opts.mcount, "annotate mcount/fentry calls for ftrace"),
 73	OPT_BOOLEAN('n', "noinstr", &opts.noinstr, "validate noinstr rules"),
 74	OPT_BOOLEAN('o', "orc", &opts.orc, "generate ORC metadata"),
 75	OPT_BOOLEAN('r', "retpoline", &opts.retpoline, "validate and annotate retpoline usage"),
 76	OPT_BOOLEAN(0,   "rethunk", &opts.rethunk, "validate and annotate rethunk usage"),
 77	OPT_BOOLEAN(0,   "unret", &opts.unret, "validate entry unret placement"),
 78	OPT_INTEGER(0,   "prefix", &opts.prefix, "generate prefix symbols"),
 79	OPT_BOOLEAN('l', "sls", &opts.sls, "validate straight-line-speculation mitigations"),
 80	OPT_BOOLEAN('s', "stackval", &opts.stackval, "validate frame pointer rules"),
 81	OPT_BOOLEAN('t', "static-call", &opts.static_call, "annotate static calls"),
 82	OPT_BOOLEAN('u', "uaccess", &opts.uaccess, "validate uaccess rules for SMAP"),
 83	OPT_BOOLEAN(0  , "cfi", &opts.cfi, "annotate kernel control flow integrity (kCFI) function preambles"),
 84	OPT_CALLBACK_OPTARG(0, "dump", NULL, NULL, "orc", "dump metadata", parse_dump),
 85
 86	OPT_GROUP("Options:"),
 87	OPT_BOOLEAN(0, "backtrace", &opts.backtrace, "unwind on error"),
 88	OPT_BOOLEAN(0, "backup", &opts.backup, "create .orig files before modification"),
 89	OPT_BOOLEAN(0, "dry-run", &opts.dryrun, "don't write modifications"),
 90	OPT_BOOLEAN(0, "link", &opts.link, "object is a linked object"),
 91	OPT_BOOLEAN(0, "module", &opts.module, "object is part of a kernel module"),
 92	OPT_BOOLEAN(0, "mnop", &opts.mnop, "nop out mcount call sites"),
 93	OPT_BOOLEAN(0, "no-unreachable", &opts.no_unreachable, "skip 'unreachable instruction' warnings"),
 94	OPT_BOOLEAN(0, "sec-address", &opts.sec_address, "print section addresses in warnings"),
 95	OPT_BOOLEAN(0, "stats", &opts.stats, "print statistics"),
 96	OPT_BOOLEAN('v', "verbose", &opts.verbose, "verbose warnings"),
 97
 98	OPT_END(),
 99};
100
101int cmd_parse_options(int argc, const char **argv, const char * const usage[])
102{
103	const char *envv[16] = { };
104	char *env;
105	int envc;
106
107	env = getenv("OBJTOOL_ARGS");
108	if (env) {
109		envv[0] = "OBJTOOL_ARGS";
110		for (envc = 1; envc < ARRAY_SIZE(envv); ) {
111			envv[envc++] = env;
112			env = strchr(env, ' ');
113			if (!env)
114				break;
115			*env = '\0';
116			env++;
117		}
118
119		parse_options(envc, envv, check_options, env_usage, 0);
120	}
121
122	env = getenv("OBJTOOL_VERBOSE");
123	if (env && !strcmp(env, "1"))
124		opts.verbose = true;
125
126	argc = parse_options(argc, argv, check_options, usage, 0);
127	if (argc != 1)
128		usage_with_options(usage, check_options);
129	return argc;
130}
131
132static bool opts_valid(void)
133{
134	if (opts.hack_jump_label	||
135	    opts.hack_noinstr		||
136	    opts.ibt			||
137	    opts.mcount			||
138	    opts.noinstr		||
139	    opts.orc			||
140	    opts.retpoline		||
141	    opts.rethunk		||
142	    opts.sls			||
143	    opts.stackval		||
144	    opts.static_call		||
145	    opts.uaccess) {
146		if (opts.dump_orc) {
147			ERROR("--dump can't be combined with other actions");
148			return false;
149		}
150
151		return true;
152	}
153
154	if (opts.unret && !opts.rethunk) {
155		ERROR("--unret requires --rethunk");
156		return false;
157	}
158
159	if (opts.dump_orc)
160		return true;
161
162	ERROR("At least one action required");
163	return false;
164}
165
166static bool mnop_opts_valid(void)
167{
168	if (opts.mnop && !opts.mcount) {
169		ERROR("--mnop requires --mcount");
170		return false;
171	}
172
173	return true;
174}
175
176static bool link_opts_valid(struct objtool_file *file)
177{
178	if (opts.link)
179		return true;
180
181	if (has_multiple_files(file->elf)) {
182		ERROR("Linked object detected, forcing --link");
183		opts.link = true;
184		return true;
185	}
186
187	if (opts.noinstr) {
188		ERROR("--noinstr requires --link");
189		return false;
190	}
191
192	if (opts.ibt) {
193		ERROR("--ibt requires --link");
194		return false;
195	}
196
197	if (opts.unret) {
198		ERROR("--unret requires --link");
199		return false;
200	}
201
202	return true;
203}
204
205int objtool_run(int argc, const char **argv)
206{
207	const char *objname;
208	struct objtool_file *file;
209	int ret;
210
211	argc = cmd_parse_options(argc, argv, check_usage);
212	objname = argv[0];
213
214	if (!opts_valid())
215		return 1;
216
217	if (opts.dump_orc)
218		return orc_dump(objname);
219
220	file = objtool_open_read(objname);
221	if (!file)
222		return 1;
223
224	if (!mnop_opts_valid())
225		return 1;
226
227	if (!link_opts_valid(file))
228		return 1;
229
230	ret = check(file);
231	if (ret)
232		return ret;
233
234	if (file->elf->changed)
235		return elf_write(file->elf);
236
237	return 0;
238}
v5.9
 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 "builtin.h"
19#include "objtool.h"
 
 
 
 
 
 
20
21bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats, validate_dup, vmlinux;
22
23static const char * const check_usage[] = {
24	"objtool check [<options>] file.o",
 
 
 
 
 
25	NULL,
26};
27
28const struct option check_options[] = {
29	OPT_BOOLEAN('f', "no-fp", &no_fp, "Skip frame pointer validation"),
30	OPT_BOOLEAN('u', "no-unreachable", &no_unreachable, "Skip 'unreachable instruction' warnings"),
31	OPT_BOOLEAN('r', "retpoline", &retpoline, "Validate retpoline assumptions"),
32	OPT_BOOLEAN('m', "module", &module, "Indicates the object will be part of a kernel module"),
33	OPT_BOOLEAN('b', "backtrace", &backtrace, "unwind on error"),
34	OPT_BOOLEAN('a', "uaccess", &uaccess, "enable uaccess checking"),
35	OPT_BOOLEAN('s', "stats", &stats, "print statistics"),
36	OPT_BOOLEAN('d', "duplicate", &validate_dup, "duplicate validation for vmlinux.o"),
37	OPT_BOOLEAN('l', "vmlinux", &vmlinux, "vmlinux.o validation"),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38	OPT_END(),
39};
40
41int cmd_check(int argc, const char **argv)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42{
43	const char *objname, *s;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
45	argc = parse_options(argc, argv, check_options, check_usage, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
46
47	if (argc != 1)
48		usage_with_options(check_usage, check_options);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50	objname = argv[0];
51
52	s = strstr(objname, "vmlinux.o");
53	if (s && !s[9])
54		vmlinux = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
56	return check(objname, false);
57}