| #include <debug.h> |
| #include <cmdline.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <getopt.h> |
| #include <string.h> |
| #include <ctype.h> |
| |
| extern char *optarg; |
| extern int optind, opterr, optopt; |
| |
| static struct option long_options[] = |
| { |
| {"verbose", no_argument, 0, 'V'}, |
| {"quiet", no_argument, 0, 'Q'}, |
| {"shady", no_argument, 0, 'S'}, |
| {"print", no_argument, 0, 'p'}, |
| {"help", no_argument, 0, 'h'}, |
| {"outfile", required_argument, 0, 'o'}, |
| {"filter", required_argument, 0, 'f'}, |
| {"dry", no_argument, 0, 'n'}, |
| {"strip", no_argument, 0, 's'}, |
| {0, 0, 0, 0}, |
| }; |
| |
| /* This array must parallel long_options[] */ |
| static |
| const char *descriptions[sizeof(long_options)/sizeof(long_options[0])] = { |
| "print verbose output", |
| "suppress errors and warnings", |
| "patch ABS symbols whose values coincide with section starts and ends", |
| "print the symbol table (if specified, only -V is allowed)", |
| "this help screen", |
| "specify an output file (if not provided, input file is modified)", |
| "specify a symbol-filter file", |
| "dry run (perform all calculations but do not modify the ELF file)", |
| "strip debug sections, if they are present" |
| }; |
| |
| void print_help(void) |
| { |
| fprintf(stdout, |
| "invokation:\n" |
| "\tsoslim file1 [file2 file3 ... fileN] [-Ldir1 -Ldir2 ... -LdirN] " |
| "[-Vpn]\n" |
| "or\n" |
| "\tsoslim -h\n\n"); |
| fprintf(stdout, "options:\n"); |
| struct option *opt = long_options; |
| const char **desc = descriptions; |
| while (opt->name) { |
| fprintf(stdout, "\t-%c/--%-15s %s\n", |
| opt->val, |
| opt->name, |
| *desc); |
| opt++; |
| desc++; |
| } |
| } |
| |
| int get_options(int argc, char **argv, |
| char **outfile, |
| char **symsfile, |
| int *print_symtab, |
| int *verbose, |
| int *quiet, |
| int *shady, |
| int *dry_run, |
| int *strip_debug) |
| { |
| int c; |
| |
| ASSERT(outfile); |
| *outfile = NULL; |
| ASSERT(symsfile); |
| *symsfile = NULL; |
| ASSERT(print_symtab); |
| *print_symtab = 0; |
| ASSERT(verbose); |
| *verbose = 0; |
| ASSERT(quiet); |
| *quiet = 0; |
| ASSERT(shady); |
| *shady = 0; |
| ASSERT(dry_run); |
| *dry_run = 0; |
| ASSERT(strip_debug); |
| *strip_debug = 0; |
| |
| while (1) { |
| /* getopt_long stores the option index here. */ |
| int option_index = 0; |
| |
| c = getopt_long (argc, argv, |
| "QVSphi:o:y:Y:f:ns", |
| long_options, |
| &option_index); |
| /* Detect the end of the options. */ |
| if (c == -1) break; |
| |
| if (isgraph(c)) { |
| INFO ("option -%c with value `%s'\n", c, (optarg ?: "(null)")); |
| } |
| |
| #define SET_STRING_OPTION(name) do { \ |
| ASSERT(optarg); \ |
| *name = strdup(optarg); \ |
| } while(0) |
| |
| switch (c) { |
| case 0: |
| /* If this option set a flag, do nothing else now. */ |
| if (long_options[option_index].flag != 0) |
| break; |
| INFO ("option %s", long_options[option_index].name); |
| if (optarg) |
| INFO (" with arg %s", optarg); |
| INFO ("\n"); |
| break; |
| case 'p': *print_symtab = 1; break; |
| case 'h': print_help(); exit(1); break; |
| case 'V': *verbose = 1; break; |
| case 'Q': *quiet = 1; break; |
| case 'S': *shady = 1; break; |
| case 'n': *dry_run = 1; break; |
| case 's': *strip_debug = 1; break; |
| case 'o': SET_STRING_OPTION(outfile); break; |
| case 'f': SET_STRING_OPTION(symsfile); break; |
| case '?': |
| /* getopt_long already printed an error message. */ |
| break; |
| |
| #undef SET_STRING_OPTION |
| |
| default: |
| FAILIF(1, "Unknown option"); |
| } |
| } |
| |
| return optind; |
| } |