1 #include <debug.h> 2 #include <cmdline.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <getopt.h> 6 #include <string.h> 7 #include <ctype.h> 8 9 extern char *optarg; 10 extern int optind, opterr, optopt; 11 12 static struct option long_options[] = 13 { 14 {"verbose", no_argument, 0, 'V'}, 15 {"quiet", no_argument, 0, 'Q'}, 16 {"shady", no_argument, 0, 'S'}, 17 {"print", no_argument, 0, 'p'}, 18 {"help", no_argument, 0, 'h'}, 19 {"outfile", required_argument, 0, 'o'}, 20 {"filter", required_argument, 0, 'f'}, 21 {"dry", no_argument, 0, 'n'}, 22 {"strip", no_argument, 0, 's'}, 23 {0, 0, 0, 0}, 24 }; 25 26 /* This array must parallel long_options[] */ 27 static 28 const char *descriptions[sizeof(long_options)/sizeof(long_options[0])] = { 29 "print verbose output", 30 "suppress errors and warnings", 31 "patch ABS symbols whose values coincide with section starts and ends", 32 "print the symbol table (if specified, only -V is allowed)", 33 "this help screen", 34 "specify an output file (if not provided, input file is modified)", 35 "specify a symbol-filter file", 36 "dry run (perform all calculations but do not modify the ELF file)", 37 "strip debug sections, if they are present" 38 }; 39 40 void print_help(void) 41 { 42 fprintf(stdout, 43 "invokation:\n" 44 "\tsoslim file1 [file2 file3 ... fileN] [-Ldir1 -Ldir2 ... -LdirN] " 45 "[-Vpn]\n" 46 "or\n" 47 "\tsoslim -h\n\n"); 48 fprintf(stdout, "options:\n"); 49 struct option *opt = long_options; 50 const char **desc = descriptions; 51 while (opt->name) { 52 fprintf(stdout, "\t-%c/--%-15s %s\n", 53 opt->val, 54 opt->name, 55 *desc); 56 opt++; 57 desc++; 58 } 59 } 60 61 int get_options(int argc, char **argv, 62 char **outfile, 63 char **symsfile, 64 int *print_symtab, 65 int *verbose, 66 int *quiet, 67 int *shady, 68 int *dry_run, 69 int *strip_debug) 70 { 71 int c; 72 73 ASSERT(outfile); 74 *outfile = NULL; 75 ASSERT(symsfile); 76 *symsfile = NULL; 77 ASSERT(print_symtab); 78 *print_symtab = 0; 79 ASSERT(verbose); 80 *verbose = 0; 81 ASSERT(quiet); 82 *quiet = 0; 83 ASSERT(shady); 84 *shady = 0; 85 ASSERT(dry_run); 86 *dry_run = 0; 87 ASSERT(strip_debug); 88 *strip_debug = 0; 89 90 while (1) { 91 /* getopt_long stores the option index here. */ 92 int option_index = 0; 93 94 c = getopt_long (argc, argv, 95 "QVSphi:o:y:Y:f:ns", 96 long_options, 97 &option_index); 98 /* Detect the end of the options. */ 99 if (c == -1) break; 100 101 if (isgraph(c)) { 102 INFO ("option -%c with value `%s'\n", c, (optarg ?: "(null)")); 103 } 104 105 #define SET_STRING_OPTION(name) do { \ 106 ASSERT(optarg); \ 107 *name = strdup(optarg); \ 108 } while(0) 109 110 switch (c) { 111 case 0: 112 /* If this option set a flag, do nothing else now. */ 113 if (long_options[option_index].flag != 0) 114 break; 115 INFO ("option %s", long_options[option_index].name); 116 if (optarg) 117 INFO (" with arg %s", optarg); 118 INFO ("\n"); 119 break; 120 case 'p': *print_symtab = 1; break; 121 case 'h': print_help(); exit(1); break; 122 case 'V': *verbose = 1; break; 123 case 'Q': *quiet = 1; break; 124 case 'S': *shady = 1; break; 125 case 'n': *dry_run = 1; break; 126 case 's': *strip_debug = 1; break; 127 case 'o': SET_STRING_OPTION(outfile); break; 128 case 'f': SET_STRING_OPTION(symsfile); break; 129 case '?': 130 /* getopt_long already printed an error message. */ 131 break; 132 133 #undef SET_STRING_OPTION 134 135 default: 136 FAILIF(1, "Unknown option"); 137 } 138 } 139 140 return optind; 141 } 142