1 | /*****************************************************************************/ |
2 | /* */ |
3 | /* main.c */ |
4 | /* */ |
5 | /* Main program of the od65 object file dump utility */ |
6 | /* */ |
7 | /* */ |
8 | /* */ |
9 | /* (C) 2000-2012, Ullrich von Bassewitz */ |
10 | /* Roemerstrasse 52 */ |
11 | /* D-70794 Filderstadt */ |
12 | /* EMail: uz@cc65.org */ |
13 | /* */ |
14 | /* */ |
15 | /* This software is provided 'as-is', without any expressed or implied */ |
16 | /* warranty. In no event will the authors be held liable for any damages */ |
17 | /* arising from the use of this software. */ |
18 | /* */ |
19 | /* Permission is granted to anyone to use this software for any purpose, */ |
20 | /* including commercial applications, and to alter it and redistribute it */ |
21 | /* freely, subject to the following restrictions: */ |
22 | /* */ |
23 | /* 1. The origin of this software must not be misrepresented; you must not */ |
24 | /* claim that you wrote the original software. If you use this software */ |
25 | /* in a product, an acknowledgment in the product documentation would be */ |
26 | /* appreciated but is not required. */ |
27 | /* 2. Altered source versions must be plainly marked as such, and must not */ |
28 | /* be misrepresented as being the original software. */ |
29 | /* 3. This notice may not be removed or altered from any source */ |
30 | /* distribution. */ |
31 | /* */ |
32 | /*****************************************************************************/ |
33 | |
34 | |
35 | |
36 | #include <stdio.h> |
37 | #include <stdlib.h> |
38 | #include <string.h> |
39 | #include <errno.h> |
40 | |
41 | /* common */ |
42 | #include "cmdline.h" |
43 | #include "objdefs.h" |
44 | #include "version.h" |
45 | |
46 | /* od65 */ |
47 | #include "dump.h" |
48 | #include "error.h" |
49 | #include "fileio.h" |
50 | #include "global.h" |
51 | |
52 | |
53 | |
54 | /*****************************************************************************/ |
55 | /* Data */ |
56 | /*****************************************************************************/ |
57 | |
58 | |
59 | |
60 | static unsigned FilesProcessed = 0; |
61 | |
62 | |
63 | |
64 | /*****************************************************************************/ |
65 | /* Code */ |
66 | /*****************************************************************************/ |
67 | |
68 | |
69 | |
70 | static void Usage (void) |
71 | /* Print usage information and exit */ |
72 | { |
73 | printf ("Usage: %s [options] file [options] [file]\n" |
74 | "Short options:\n" |
75 | " -h\t\t\tHelp (this text)\n" |
76 | " -H\t\t\tDump the object file header\n" |
77 | " -S\t\t\tDump segments sizes\n" |
78 | " -V\t\t\tPrint the version number and exit\n" |
79 | "\n" |
80 | "Long options:\n" |
81 | " --dump-all\t\tDump all object file information\n" |
82 | " --dump-dbgsyms\tDump debug symbols\n" |
83 | " --dump-exports\tDump exported symbols\n" |
84 | " --dump-files\t\tDump the source files\n" |
85 | " --dump-header\t\tDump the object file header\n" |
86 | " --dump-imports\tDump imported symbols\n" |
87 | " --dump-lineinfo\tDump line information\n" |
88 | " --dump-options\tDump object file options\n" |
89 | " --dump-segments\tDump the segments in the file\n" |
90 | " --dump-segsize\tDump segments sizes\n" |
91 | " --help\t\tHelp (this text)\n" |
92 | " --version\t\tPrint the version number and exit\n" , |
93 | ProgName); |
94 | } |
95 | |
96 | |
97 | |
98 | static void OptDumpAll (const char* Opt attribute ((unused)), |
99 | const char* Arg attribute ((unused))) |
100 | /* Dump all object file information */ |
101 | { |
102 | What |= D_ALL; |
103 | } |
104 | |
105 | |
106 | |
107 | static void OptDumpDbgSyms (const char* Opt attribute ((unused)), |
108 | const char* Arg attribute ((unused))) |
109 | /* Dump debug symbols contained in the object file */ |
110 | { |
111 | What |= D_DBGSYMS; |
112 | } |
113 | |
114 | |
115 | |
116 | static void OptDumpExports (const char* Opt attribute ((unused)), |
117 | const char* Arg attribute ((unused))) |
118 | /* Dump the exported symbols */ |
119 | { |
120 | What |= D_EXPORTS; |
121 | } |
122 | |
123 | |
124 | |
125 | static void OptDumpFiles (const char* Opt attribute ((unused)), |
126 | const char* Arg attribute ((unused))) |
127 | /* Dump the source files */ |
128 | { |
129 | What |= D_FILES; |
130 | } |
131 | |
132 | |
133 | |
134 | static void (const char* Opt attribute ((unused)), |
135 | const char* Arg attribute ((unused))) |
136 | /* Dump the object file header */ |
137 | { |
138 | What |= D_HEADER; |
139 | } |
140 | |
141 | |
142 | |
143 | static void OptDumpImports (const char* Opt attribute ((unused)), |
144 | const char* Arg attribute ((unused))) |
145 | /* Dump the imported symbols */ |
146 | { |
147 | What |= D_IMPORTS; |
148 | } |
149 | |
150 | |
151 | |
152 | static void OptDumpLineInfo (const char* Opt attribute ((unused)), |
153 | const char* Arg attribute ((unused))) |
154 | /* Dump the line infos */ |
155 | { |
156 | What |= D_LINEINFO; |
157 | } |
158 | |
159 | |
160 | |
161 | static void OptDumpOptions (const char* Opt attribute ((unused)), |
162 | const char* Arg attribute ((unused))) |
163 | /* Dump the object file options */ |
164 | { |
165 | What |= D_OPTIONS; |
166 | } |
167 | |
168 | |
169 | |
170 | static void OptDumpScopes (const char* Opt attribute ((unused)), |
171 | const char* Arg attribute ((unused))) |
172 | /* Dump the scopes in the object file */ |
173 | { |
174 | What |= D_SCOPES; |
175 | } |
176 | |
177 | |
178 | |
179 | static void OptDumpSegments (const char* Opt attribute ((unused)), |
180 | const char* Arg attribute ((unused))) |
181 | /* Dump the segments in the object file */ |
182 | { |
183 | What |= D_SEGMENTS; |
184 | } |
185 | |
186 | |
187 | |
188 | static void OptDumpSegSize (const char* Opt attribute ((unused)), |
189 | const char* Arg attribute ((unused))) |
190 | /* Dump the segments in the object file */ |
191 | { |
192 | What |= D_SEGSIZE; |
193 | } |
194 | |
195 | |
196 | |
197 | static void OptHelp (const char* Opt attribute ((unused)), |
198 | const char* Arg attribute ((unused))) |
199 | /* Print usage information and exit */ |
200 | { |
201 | Usage (); |
202 | exit (EXIT_SUCCESS); |
203 | } |
204 | |
205 | |
206 | |
207 | static void OptVersion (const char* Opt attribute ((unused)), |
208 | const char* Arg attribute ((unused))) |
209 | /* Print the assembler version */ |
210 | { |
211 | fprintf (stderr, "%s V%s\n" , ProgName, GetVersionAsString ()); |
212 | exit(EXIT_SUCCESS); |
213 | } |
214 | |
215 | |
216 | |
217 | static void DumpFile (const char* Name) |
218 | /* Dump information from the named file */ |
219 | { |
220 | unsigned long Magic; |
221 | |
222 | /* Try to open the file */ |
223 | FILE* F = fopen (Name, "rb" ); |
224 | if (F == 0) { |
225 | Error ("Cannot open '%s': %s" , Name, strerror (errno)); |
226 | } |
227 | |
228 | /* Read the magic word */ |
229 | Magic = Read32 (F); |
230 | |
231 | /* Do we know this type of file? */ |
232 | if (Magic != OBJ_MAGIC) { |
233 | |
234 | /* Unknown format */ |
235 | printf ("%s: (no xo65 object file)\n" , Name); |
236 | |
237 | } else if (What == 0) { |
238 | |
239 | /* Special handling if no info was requested */ |
240 | printf ("%s: (no information requested)\n" , Name); |
241 | |
242 | } else { |
243 | |
244 | /* Print the filename */ |
245 | printf ("%s:\n" , Name); |
246 | |
247 | /* Check what to dump */ |
248 | if (What & D_HEADER) { |
249 | DumpObjHeader (F, 0); |
250 | } |
251 | if (What & D_OPTIONS) { |
252 | DumpObjOptions (F, 0); |
253 | } |
254 | if (What & D_FILES) { |
255 | DumpObjFiles (F, 0); |
256 | } |
257 | if (What & D_SEGMENTS) { |
258 | DumpObjSegments (F, 0); |
259 | } |
260 | if (What & D_IMPORTS) { |
261 | DumpObjImports (F, 0); |
262 | } |
263 | if (What & D_EXPORTS) { |
264 | DumpObjExports (F, 0); |
265 | } |
266 | if (What & D_DBGSYMS) { |
267 | DumpObjDbgSyms (F, 0); |
268 | } |
269 | if (What & D_LINEINFO) { |
270 | DumpObjLineInfo (F, 0); |
271 | } |
272 | if (What & D_SCOPES) { |
273 | DumpObjScopes (F, 0); |
274 | } |
275 | if (What & D_SEGSIZE) { |
276 | DumpObjSegSize (F, 0); |
277 | } |
278 | } |
279 | |
280 | /* Close the file */ |
281 | fclose (F); |
282 | } |
283 | |
284 | |
285 | |
286 | int main (int argc, char* argv []) |
287 | /* Assembler main program */ |
288 | { |
289 | /* Program long options */ |
290 | static const LongOpt OptTab[] = { |
291 | { "--dump-all" , 0, OptDumpAll }, |
292 | { "--dump-dbgsyms" , 0, OptDumpDbgSyms }, |
293 | { "--dump-exports" , 0, OptDumpExports }, |
294 | { "--dump-files" , 0, OptDumpFiles }, |
295 | { "--dump-header" , 0, OptDumpHeader }, |
296 | { "--dump-imports" , 0, OptDumpImports }, |
297 | { "--dump-lineinfo" , 0, OptDumpLineInfo }, |
298 | { "--dump-options" , 0, OptDumpOptions }, |
299 | { "--dump-scopes" , 0, OptDumpScopes }, |
300 | { "--dump-segments" , 0, OptDumpSegments }, |
301 | { "--dump-segsize" , 0, OptDumpSegSize }, |
302 | { "--help" , 0, OptHelp }, |
303 | { "--version" , 0, OptVersion }, |
304 | }; |
305 | |
306 | unsigned I; |
307 | |
308 | /* Initialize the cmdline module */ |
309 | InitCmdLine (&argc, &argv, "od65" ); |
310 | |
311 | /* Check the parameters */ |
312 | I = 1; |
313 | while (I < ArgCount) { |
314 | |
315 | /* Get the argument */ |
316 | const char* Arg = ArgVec[I]; |
317 | |
318 | /* Check for an option */ |
319 | if (Arg [0] == '-') { |
320 | switch (Arg [1]) { |
321 | |
322 | case '-': |
323 | LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0])); |
324 | break; |
325 | |
326 | case 'h': |
327 | OptHelp (Arg, 0); |
328 | break; |
329 | |
330 | case 'H': |
331 | OptDumpHeader (Arg, 0); |
332 | break; |
333 | |
334 | case 'S': |
335 | OptDumpSegSize (Arg, 0); |
336 | break; |
337 | |
338 | case 'V': |
339 | OptVersion (Arg, 0); |
340 | break; |
341 | |
342 | default: |
343 | UnknownOption (Arg); |
344 | break; |
345 | |
346 | } |
347 | } else { |
348 | /* Filename. Dump it. */ |
349 | DumpFile (Arg); |
350 | ++FilesProcessed; |
351 | } |
352 | |
353 | /* Next argument */ |
354 | ++I; |
355 | } |
356 | |
357 | /* Print a message if we did not process any files */ |
358 | if (FilesProcessed == 0) { |
359 | fprintf (stderr, "%s: No input files\n" , ProgName); |
360 | } |
361 | |
362 | /* Success */ |
363 | return EXIT_SUCCESS; |
364 | } |
365 | |