• 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     {"start-address", required_argument, 0, 's'},
14     {"inc-address",   required_argument, 0, 'i'},
15     {"locals-only",   no_argument,       0, 'l'},
16     {"quiet",         no_argument,       0, 'Q'},
17     {"noupdate",      no_argument,       0, 'n'},
18     {"lookup",        required_argument, 0, 'L'},
19     {"default",       required_argument, 0, 'D'},
20     {"verbose",       no_argument,       0, 'V'},
21     {"help",          no_argument,       0, 'h'},
22 	{"mapfile",       required_argument, 0, 'M'},
23 	{"output",        required_argument, 0, 'o'},
24     {"prelinkmap",    required_argument, 0, 'p'},
25     {0, 0, 0, 0},
26 };
27 
28 /* This array must parallel long_options[] */
29 static const char *descriptions[] = {
30     "start address to prelink libraries to",
31     "address increment for each library",
32     "prelink local relocations only",
33     "suppress informational and non-fatal error messages",
34     "do a dry run--calculate the prelink info but do not update any files",
35     "provide a directory for library lookup",
36     "provide a default library or executable for symbol lookup",
37     "print verbose output",
38     "print help screen",
39 	"print a list of prelink addresses to file (prefix filename with + to append instead of overwrite)",
40     "specify an output directory (if multiple inputs) or file (is single input)",
41     "specify a file with prelink addresses instead of a --start-address/--inc-address combination",
42 };
43 
print_help(const char * name)44 void print_help(const char *name) {
45     fprintf(stdout,
46             "invokation:\n"
47             "\t%s file1 [file2 file3 ...] -Ldir1 [-Ldir2 ...] -saddr -iinc [-Vqn] [-M<logfile>]\n"
48             "\t%s -l file [-Vqn] [-M<logfile>]\n"
49             "\t%s -h\n\n", name, name, name);
50     fprintf(stdout, "options:\n");
51     struct option *opt = long_options;
52     const char **desc = descriptions;
53     while (opt->name) {
54         fprintf(stdout, "\t-%c/--%s%s: %s\n",
55                 opt->val,
56                 opt->name,
57                 (opt->has_arg ? " (argument)" : ""),
58                 *desc);
59         opt++;
60         desc++;
61     }
62 }
63 
get_options(int argc,char ** argv,int * start_addr,int * inc_addr,int * locals_only,int * quiet,int * dry_run,char *** dirs,int * num_dirs,char *** defaults,int * num_defaults,int * verbose,char ** mapfile,char ** output,char ** prelinkmap)64 int get_options(int argc, char **argv,
65                 int *start_addr,
66                 int *inc_addr,
67                 int *locals_only,
68                 int *quiet,
69                 int *dry_run,
70                 char ***dirs,
71                 int *num_dirs,
72                 char ***defaults,
73                 int *num_defaults,
74                 int *verbose,
75 				char **mapfile,
76                 char **output,
77                 char **prelinkmap) {
78     int c;
79 
80     ASSERT(dry_run); *dry_run = 0;
81     ASSERT(quiet); *quiet = 0;
82     ASSERT(verbose); *verbose = 0;
83     ASSERT(dirs); *dirs = NULL;
84     ASSERT(num_dirs); *num_dirs = 0;
85     ASSERT(defaults); *defaults = NULL;
86     ASSERT(num_defaults); *num_defaults = 0;
87     ASSERT(start_addr); *start_addr = -1;
88     ASSERT(inc_addr); *inc_addr =   -1;
89     ASSERT(locals_only); *locals_only = 0;
90 	ASSERT(mapfile); *mapfile = NULL;
91 	ASSERT(output); *output = NULL;
92     ASSERT(prelinkmap); *prelinkmap = NULL;
93     int dirs_size = 0;
94     int defaults_size = 0;
95 
96     while (1) {
97         /* getopt_long stores the option index here. */
98         int option_index = 0;
99 
100         c = getopt_long (argc, argv,
101                          "VhnQlL:D:s:i:M:o:p:",
102                          long_options,
103                          &option_index);
104         /* Detect the end of the options. */
105         if (c == -1) break;
106 
107         if (isgraph(c)) {
108             INFO ("option -%c with value `%s'\n", c, (optarg ?: "(null)"));
109         }
110 
111 #define SET_STRING_OPTION(name) do {                                   \
112     ASSERT(optarg);                                                    \
113     (*name) = strdup(optarg);                                          \
114 } while(0)
115 
116 #define SET_REPEATED_STRING_OPTION(arr, num, size) do {                \
117 	if (*num == size) {                                                \
118 		size += 10;                                                    \
119 		*arr = (char **)REALLOC(*arr, size * sizeof(char *));          \
120 	}                                                                  \
121 	SET_STRING_OPTION(((*arr) + *num));                                \
122 	(*num)++;                                                          \
123 } while(0)
124 
125 #define SET_INT_OPTION(val) do {                                       \
126     ASSERT(optarg);                                                    \
127 	if (strlen(optarg) >= 2 && optarg[0] == '0' && optarg[1] == 'x') { \
128 			FAILIF(1 != sscanf(optarg+2, "%x", val),                   \
129 				   "Expecting a hexadecimal argument!\n");             \
130 	} else {                                                           \
131 		FAILIF(1 != sscanf(optarg, "%d", val),                         \
132 			   "Expecting a decimal argument!\n");                     \
133 	}                                                                  \
134 } while(0)
135 
136         switch (c) {
137         case 0:
138             /* If this option set a flag, do nothing else now. */
139             if (long_options[option_index].flag != 0)
140                 break;
141             INFO ("option %s", long_options[option_index].name);
142             if (optarg)
143                 INFO (" with arg %s", optarg);
144             INFO ("\n");
145             break;
146         case 'Q': *quiet = 1; break;
147 		case 'n': *dry_run = 1; break;
148 		case 'M':
149 			SET_STRING_OPTION(mapfile);
150 			break;
151 		case 'o':
152 			SET_STRING_OPTION(output);
153 			break;
154         case 'p':
155             SET_STRING_OPTION(prelinkmap);
156             break;
157         case 's':
158             SET_INT_OPTION(start_addr);
159             break;
160         case 'i':
161             SET_INT_OPTION(inc_addr);
162             break;
163         case 'L':
164             SET_REPEATED_STRING_OPTION(dirs, num_dirs, dirs_size);
165             break;
166         case 'D':
167             SET_REPEATED_STRING_OPTION(defaults, num_defaults, defaults_size);
168             break;
169         case 'l': *locals_only = 1; break;
170         case 'h': print_help(argv[0]); exit(1); break;
171         case 'V': *verbose = 1; break;
172         case '?':
173             /* getopt_long already printed an error message. */
174             break;
175 
176 #undef SET_STRING_OPTION
177 #undef SET_REPEATED_STRING_OPTION
178 #undef SET_INT_OPTION
179 
180         default:
181             FAILIF(1, "Unknown option");
182         }
183     }
184 
185     return optind;
186 }
187