• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
print_help(void)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 
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)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