1 /* 2 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com> 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 /* 19 * objtool: 20 * 21 * The 'check' subcmd analyzes every .o file and ensures the validity of its 22 * stack trace metadata. It enforces a set of rules on asm code and C inline 23 * assembly code so that stack traces can be reliable. 24 * 25 * For more information, see tools/objtool/Documentation/stack-validation.txt. 26 */ 27 28 #include <stdio.h> 29 #include <stdbool.h> 30 #include <string.h> 31 #include <stdlib.h> 32 #include <subcmd/exec-cmd.h> 33 #include <subcmd/pager.h> 34 #include <linux/kernel.h> 35 36 #include "builtin.h" 37 38 struct cmd_struct { 39 const char *name; 40 int (*fn)(int, const char **); 41 const char *help; 42 }; 43 44 static const char objtool_usage_string[] = 45 "objtool COMMAND [ARGS]"; 46 47 static struct cmd_struct objtool_cmds[] = { 48 {"check", cmd_check, "Perform stack metadata validation on an object file" }, 49 {"orc", cmd_orc, "Generate in-place ORC unwind tables for an object file" }, 50 }; 51 52 bool help; 53 54 static void cmd_usage(void) 55 { 56 unsigned int i, longest = 0; 57 58 printf("\n usage: %s\n\n", objtool_usage_string); 59 60 for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) { 61 if (longest < strlen(objtool_cmds[i].name)) 62 longest = strlen(objtool_cmds[i].name); 63 } 64 65 puts(" Commands:"); 66 for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) { 67 printf(" %-*s ", longest, objtool_cmds[i].name); 68 puts(objtool_cmds[i].help); 69 } 70 71 printf("\n"); 72 73 exit(129); 74 } 75 76 static void handle_options(int *argc, const char ***argv) 77 { 78 while (*argc > 0) { 79 const char *cmd = (*argv)[0]; 80 81 if (cmd[0] != '-') 82 break; 83 84 if (!strcmp(cmd, "--help") || !strcmp(cmd, "-h")) { 85 help = true; 86 break; 87 } else { 88 fprintf(stderr, "Unknown option: %s\n", cmd); 89 cmd_usage(); 90 } 91 92 (*argv)++; 93 (*argc)--; 94 } 95 } 96 97 static void handle_internal_command(int argc, const char **argv) 98 { 99 const char *cmd = argv[0]; 100 unsigned int i, ret; 101 102 for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) { 103 struct cmd_struct *p = objtool_cmds+i; 104 105 if (strcmp(p->name, cmd)) 106 continue; 107 108 ret = p->fn(argc, argv); 109 110 exit(ret); 111 } 112 113 cmd_usage(); 114 } 115 116 int main(int argc, const char **argv) 117 { 118 static const char *UNUSED = "OBJTOOL_NOT_IMPLEMENTED"; 119 120 /* libsubcmd init */ 121 exec_cmd_init("objtool", UNUSED, UNUSED, UNUSED); 122 pager_init(UNUSED); 123 124 argv++; 125 argc--; 126 handle_options(&argc, &argv); 127 128 if (!argc || help) 129 cmd_usage(); 130 131 handle_internal_command(argc, argv); 132 133 return 0; 134 } 135