linux/tools/objtool/objtool.c
<<
>>
Prefs
   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
  35#include "builtin.h"
  36
  37#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
  38
  39struct cmd_struct {
  40        const char *name;
  41        int (*fn)(int, const char **);
  42        const char *help;
  43};
  44
  45static const char objtool_usage_string[] =
  46        "objtool [OPTIONS] COMMAND [ARGS]";
  47
  48static struct cmd_struct objtool_cmds[] = {
  49        {"check",       cmd_check,      "Perform stack metadata validation on an object file" },
  50};
  51
  52bool help;
  53
  54static 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(1);
  74}
  75
  76static 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                        fprintf(stderr, "\n Usage: %s\n",
  90                                objtool_usage_string);
  91                        exit(1);
  92                }
  93
  94                (*argv)++;
  95                (*argc)--;
  96        }
  97}
  98
  99static void handle_internal_command(int argc, const char **argv)
 100{
 101        const char *cmd = argv[0];
 102        unsigned int i, ret;
 103
 104        for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) {
 105                struct cmd_struct *p = objtool_cmds+i;
 106
 107                if (strcmp(p->name, cmd))
 108                        continue;
 109
 110                ret = p->fn(argc, argv);
 111
 112                exit(ret);
 113        }
 114
 115        cmd_usage();
 116}
 117
 118int main(int argc, const char **argv)
 119{
 120        static const char *UNUSED = "OBJTOOL_NOT_IMPLEMENTED";
 121
 122        /* libsubcmd init */
 123        exec_cmd_init("objtool", UNUSED, UNUSED, UNUSED);
 124        pager_init(UNUSED);
 125
 126        argv++;
 127        argc--;
 128        handle_options(&argc, &argv);
 129
 130        if (!argc || help)
 131                cmd_usage();
 132
 133        handle_internal_command(argc, argv);
 134
 135        return 0;
 136}
 137