• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // SPDX-License-Identifier: GPL-2.0-or-later
2  /*
3   * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
4   */
5  
6  /*
7   * objtool:
8   *
9   * The 'check' subcmd analyzes every .o file and ensures the validity of its
10   * stack 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 <stdio.h>
17  #include <stdbool.h>
18  #include <string.h>
19  #include <stdlib.h>
20  #include <subcmd/exec-cmd.h>
21  #include <subcmd/pager.h>
22  #include <linux/kernel.h>
23  
24  #include "builtin.h"
25  #include "objtool.h"
26  #include "warn.h"
27  
28  struct cmd_struct {
29  	const char *name;
30  	int (*fn)(int, const char **);
31  	const char *help;
32  };
33  
34  static const char objtool_usage_string[] =
35  	"objtool COMMAND [ARGS]";
36  
37  static struct cmd_struct objtool_cmds[] = {
38  	{"check",	cmd_check,	"Perform stack metadata validation on an object file" },
39  	{"orc",		cmd_orc,	"Generate in-place ORC unwind tables for an object file" },
40  };
41  
42  bool help;
43  
44  const char *objname;
45  static struct objtool_file file;
46  
objtool_open_read(const char * _objname)47  struct objtool_file *objtool_open_read(const char *_objname)
48  {
49  	if (objname) {
50  		if (strcmp(objname, _objname)) {
51  			WARN("won't handle more than one file at a time");
52  			return NULL;
53  		}
54  		return &file;
55  	}
56  	objname = _objname;
57  
58  	file.elf = elf_open_read(objname, O_RDWR);
59  	if (!file.elf)
60  		return NULL;
61  
62  	INIT_LIST_HEAD(&file.insn_list);
63  	hash_init(file.insn_hash);
64  	INIT_LIST_HEAD(&file.retpoline_call_list);
65  	INIT_LIST_HEAD(&file.return_thunk_list);
66  	INIT_LIST_HEAD(&file.static_call_list);
67  	file.c_file = !vmlinux && find_section_by_name(file.elf, ".comment");
68  	file.ignore_unreachables = no_unreachable;
69  	file.hints = false;
70  
71  	return &file;
72  }
73  
cmd_usage(void)74  static void cmd_usage(void)
75  {
76  	unsigned int i, longest = 0;
77  
78  	printf("\n usage: %s\n\n", objtool_usage_string);
79  
80  	for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) {
81  		if (longest < strlen(objtool_cmds[i].name))
82  			longest = strlen(objtool_cmds[i].name);
83  	}
84  
85  	puts(" Commands:");
86  	for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) {
87  		printf("   %-*s   ", longest, objtool_cmds[i].name);
88  		puts(objtool_cmds[i].help);
89  	}
90  
91  	printf("\n");
92  
93  	if (!help)
94  		exit(129);
95  	exit(0);
96  }
97  
handle_options(int * argc,const char *** argv)98  static void handle_options(int *argc, const char ***argv)
99  {
100  	while (*argc > 0) {
101  		const char *cmd = (*argv)[0];
102  
103  		if (cmd[0] != '-')
104  			break;
105  
106  		if (!strcmp(cmd, "--help") || !strcmp(cmd, "-h")) {
107  			help = true;
108  			break;
109  		} else {
110  			fprintf(stderr, "Unknown option: %s\n", cmd);
111  			cmd_usage();
112  		}
113  
114  		(*argv)++;
115  		(*argc)--;
116  	}
117  }
118  
handle_internal_command(int argc,const char ** argv)119  static void handle_internal_command(int argc, const char **argv)
120  {
121  	const char *cmd = argv[0];
122  	unsigned int i, ret;
123  
124  	for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) {
125  		struct cmd_struct *p = objtool_cmds+i;
126  
127  		if (strcmp(p->name, cmd))
128  			continue;
129  
130  		ret = p->fn(argc, argv);
131  
132  		exit(ret);
133  	}
134  
135  	cmd_usage();
136  }
137  
main(int argc,const char ** argv)138  int main(int argc, const char **argv)
139  {
140  	static const char *UNUSED = "OBJTOOL_NOT_IMPLEMENTED";
141  
142  	/* libsubcmd init */
143  	exec_cmd_init("objtool", UNUSED, UNUSED, UNUSED);
144  	pager_init(UNUSED);
145  
146  	argv++;
147  	argc--;
148  	handle_options(&argc, &argv);
149  
150  	if (!argc || help)
151  		cmd_usage();
152  
153  	handle_internal_command(argc, argv);
154  
155  	return 0;
156  }
157