linux/tools/objtool/objtool.c
<<
>>
Prefs
   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
  26struct cmd_struct {
  27        const char *name;
  28        int (*fn)(int, const char **);
  29        const char *help;
  30};
  31
  32static const char objtool_usage_string[] =
  33        "objtool COMMAND [ARGS]";
  34
  35static struct cmd_struct objtool_cmds[] = {
  36        {"check",       cmd_check,      "Perform stack metadata validation on an object file" },
  37        {"orc",         cmd_orc,        "Generate in-place ORC unwind tables for an object file" },
  38};
  39
  40bool help;
  41
  42static void cmd_usage(void)
  43{
  44        unsigned int i, longest = 0;
  45
  46        printf("\n usage: %s\n\n", objtool_usage_string);
  47
  48        for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) {
  49                if (longest < strlen(objtool_cmds[i].name))
  50                        longest = strlen(objtool_cmds[i].name);
  51        }
  52
  53        puts(" Commands:");
  54        for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) {
  55                printf("   %-*s   ", longest, objtool_cmds[i].name);
  56                puts(objtool_cmds[i].help);
  57        }
  58
  59        printf("\n");
  60
  61        exit(129);
  62}
  63
  64static void handle_options(int *argc, const char ***argv)
  65{
  66        while (*argc > 0) {
  67                const char *cmd = (*argv)[0];
  68
  69                if (cmd[0] != '-')
  70                        break;
  71
  72                if (!strcmp(cmd, "--help") || !strcmp(cmd, "-h")) {
  73                        help = true;
  74                        break;
  75                } else {
  76                        fprintf(stderr, "Unknown option: %s\n", cmd);
  77                        cmd_usage();
  78                }
  79
  80                (*argv)++;
  81                (*argc)--;
  82        }
  83}
  84
  85static void handle_internal_command(int argc, const char **argv)
  86{
  87        const char *cmd = argv[0];
  88        unsigned int i, ret;
  89
  90        for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) {
  91                struct cmd_struct *p = objtool_cmds+i;
  92
  93                if (strcmp(p->name, cmd))
  94                        continue;
  95
  96                ret = p->fn(argc, argv);
  97
  98                exit(ret);
  99        }
 100
 101        cmd_usage();
 102}
 103
 104int main(int argc, const char **argv)
 105{
 106        static const char *UNUSED = "OBJTOOL_NOT_IMPLEMENTED";
 107
 108        /* libsubcmd init */
 109        exec_cmd_init("objtool", UNUSED, UNUSED, UNUSED);
 110        pager_init(UNUSED);
 111
 112        argv++;
 113        argc--;
 114        handle_options(&argc, &argv);
 115
 116        if (!argc || help)
 117                cmd_usage();
 118
 119        handle_internal_command(argc, argv);
 120
 121        return 0;
 122}
 123