xref: /openbmc/linux/tools/objtool/objtool.c (revision 1ccea77e2a2687cae171b7987eb44730ec8c6d5f)
1*1ccea77eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2442f04c3SJosh Poimboeuf /*
3442f04c3SJosh Poimboeuf  * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
4442f04c3SJosh Poimboeuf  */
5442f04c3SJosh Poimboeuf 
6442f04c3SJosh Poimboeuf /*
7442f04c3SJosh Poimboeuf  * objtool:
8442f04c3SJosh Poimboeuf  *
9442f04c3SJosh Poimboeuf  * The 'check' subcmd analyzes every .o file and ensures the validity of its
10442f04c3SJosh Poimboeuf  * stack trace metadata.  It enforces a set of rules on asm code and C inline
11442f04c3SJosh Poimboeuf  * assembly code so that stack traces can be reliable.
12442f04c3SJosh Poimboeuf  *
13442f04c3SJosh Poimboeuf  * For more information, see tools/objtool/Documentation/stack-validation.txt.
14442f04c3SJosh Poimboeuf  */
15442f04c3SJosh Poimboeuf 
16442f04c3SJosh Poimboeuf #include <stdio.h>
17442f04c3SJosh Poimboeuf #include <stdbool.h>
18442f04c3SJosh Poimboeuf #include <string.h>
19442f04c3SJosh Poimboeuf #include <stdlib.h>
20442f04c3SJosh Poimboeuf #include <subcmd/exec-cmd.h>
21442f04c3SJosh Poimboeuf #include <subcmd/pager.h>
2200614597SArnaldo Carvalho de Melo #include <linux/kernel.h>
23442f04c3SJosh Poimboeuf 
24442f04c3SJosh Poimboeuf #include "builtin.h"
25442f04c3SJosh Poimboeuf 
26442f04c3SJosh Poimboeuf struct cmd_struct {
27442f04c3SJosh Poimboeuf 	const char *name;
28442f04c3SJosh Poimboeuf 	int (*fn)(int, const char **);
29442f04c3SJosh Poimboeuf 	const char *help;
30442f04c3SJosh Poimboeuf };
31442f04c3SJosh Poimboeuf 
32442f04c3SJosh Poimboeuf static const char objtool_usage_string[] =
33627fce14SJosh Poimboeuf 	"objtool COMMAND [ARGS]";
34442f04c3SJosh Poimboeuf 
35442f04c3SJosh Poimboeuf static struct cmd_struct objtool_cmds[] = {
36442f04c3SJosh Poimboeuf 	{"check",	cmd_check,	"Perform stack metadata validation on an object file" },
37627fce14SJosh Poimboeuf 	{"orc",		cmd_orc,	"Generate in-place ORC unwind tables for an object file" },
38442f04c3SJosh Poimboeuf };
39442f04c3SJosh Poimboeuf 
40442f04c3SJosh Poimboeuf bool help;
41442f04c3SJosh Poimboeuf 
42442f04c3SJosh Poimboeuf static void cmd_usage(void)
43442f04c3SJosh Poimboeuf {
44442f04c3SJosh Poimboeuf 	unsigned int i, longest = 0;
45442f04c3SJosh Poimboeuf 
46442f04c3SJosh Poimboeuf 	printf("\n usage: %s\n\n", objtool_usage_string);
47442f04c3SJosh Poimboeuf 
48442f04c3SJosh Poimboeuf 	for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) {
49442f04c3SJosh Poimboeuf 		if (longest < strlen(objtool_cmds[i].name))
50442f04c3SJosh Poimboeuf 			longest = strlen(objtool_cmds[i].name);
51442f04c3SJosh Poimboeuf 	}
52442f04c3SJosh Poimboeuf 
53442f04c3SJosh Poimboeuf 	puts(" Commands:");
54442f04c3SJosh Poimboeuf 	for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) {
55442f04c3SJosh Poimboeuf 		printf("   %-*s   ", longest, objtool_cmds[i].name);
56442f04c3SJosh Poimboeuf 		puts(objtool_cmds[i].help);
57442f04c3SJosh Poimboeuf 	}
58442f04c3SJosh Poimboeuf 
59442f04c3SJosh Poimboeuf 	printf("\n");
60442f04c3SJosh Poimboeuf 
616a93bb7eSKamalesh Babulal 	exit(129);
62442f04c3SJosh Poimboeuf }
63442f04c3SJosh Poimboeuf 
64442f04c3SJosh Poimboeuf static void handle_options(int *argc, const char ***argv)
65442f04c3SJosh Poimboeuf {
66442f04c3SJosh Poimboeuf 	while (*argc > 0) {
67442f04c3SJosh Poimboeuf 		const char *cmd = (*argv)[0];
68442f04c3SJosh Poimboeuf 
69442f04c3SJosh Poimboeuf 		if (cmd[0] != '-')
70442f04c3SJosh Poimboeuf 			break;
71442f04c3SJosh Poimboeuf 
72442f04c3SJosh Poimboeuf 		if (!strcmp(cmd, "--help") || !strcmp(cmd, "-h")) {
73442f04c3SJosh Poimboeuf 			help = true;
74442f04c3SJosh Poimboeuf 			break;
75442f04c3SJosh Poimboeuf 		} else {
76442f04c3SJosh Poimboeuf 			fprintf(stderr, "Unknown option: %s\n", cmd);
776a93bb7eSKamalesh Babulal 			cmd_usage();
78442f04c3SJosh Poimboeuf 		}
79442f04c3SJosh Poimboeuf 
80442f04c3SJosh Poimboeuf 		(*argv)++;
81442f04c3SJosh Poimboeuf 		(*argc)--;
82442f04c3SJosh Poimboeuf 	}
83442f04c3SJosh Poimboeuf }
84442f04c3SJosh Poimboeuf 
85442f04c3SJosh Poimboeuf static void handle_internal_command(int argc, const char **argv)
86442f04c3SJosh Poimboeuf {
87442f04c3SJosh Poimboeuf 	const char *cmd = argv[0];
88442f04c3SJosh Poimboeuf 	unsigned int i, ret;
89442f04c3SJosh Poimboeuf 
90442f04c3SJosh Poimboeuf 	for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) {
91442f04c3SJosh Poimboeuf 		struct cmd_struct *p = objtool_cmds+i;
92442f04c3SJosh Poimboeuf 
93442f04c3SJosh Poimboeuf 		if (strcmp(p->name, cmd))
94442f04c3SJosh Poimboeuf 			continue;
95442f04c3SJosh Poimboeuf 
96442f04c3SJosh Poimboeuf 		ret = p->fn(argc, argv);
97442f04c3SJosh Poimboeuf 
98442f04c3SJosh Poimboeuf 		exit(ret);
99442f04c3SJosh Poimboeuf 	}
100442f04c3SJosh Poimboeuf 
101442f04c3SJosh Poimboeuf 	cmd_usage();
102442f04c3SJosh Poimboeuf }
103442f04c3SJosh Poimboeuf 
104442f04c3SJosh Poimboeuf int main(int argc, const char **argv)
105442f04c3SJosh Poimboeuf {
106442f04c3SJosh Poimboeuf 	static const char *UNUSED = "OBJTOOL_NOT_IMPLEMENTED";
107442f04c3SJosh Poimboeuf 
108442f04c3SJosh Poimboeuf 	/* libsubcmd init */
109442f04c3SJosh Poimboeuf 	exec_cmd_init("objtool", UNUSED, UNUSED, UNUSED);
110442f04c3SJosh Poimboeuf 	pager_init(UNUSED);
111442f04c3SJosh Poimboeuf 
112442f04c3SJosh Poimboeuf 	argv++;
113442f04c3SJosh Poimboeuf 	argc--;
114442f04c3SJosh Poimboeuf 	handle_options(&argc, &argv);
115442f04c3SJosh Poimboeuf 
116442f04c3SJosh Poimboeuf 	if (!argc || help)
117442f04c3SJosh Poimboeuf 		cmd_usage();
118442f04c3SJosh Poimboeuf 
119442f04c3SJosh Poimboeuf 	handle_internal_command(argc, argv);
120442f04c3SJosh Poimboeuf 
121442f04c3SJosh Poimboeuf 	return 0;
122442f04c3SJosh Poimboeuf }
123