]> git.sur5r.net Git - cc65/blob - src/od65/dump.c
Added dump of segments
[cc65] / src / od65 / dump.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                  dump.c                                   */
4 /*                                                                           */
5 /*          Dump subroutines for the od65 object file dump utility           */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2000     Ullrich von Bassewitz                                        */
10 /*              Wacholderweg 14                                              */
11 /*              D-70597 Stuttgart                                            */
12 /* EMail:       uz@musoftware.de                                             */
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 <time.h>
37
38 /* common */
39 #include "exprdefs.h"
40 #include "filepos.h"
41 #include "objdefs.h"
42 #include "optdefs.h"
43 #include "segdefs.h"
44 #include "xmalloc.h"
45
46 /* od65 */
47 #include "error.h"
48 #include "fileio.h"
49 #include "dump.h"
50
51
52
53 /*****************************************************************************/
54 /*                                   Code                                    */
55 /*****************************************************************************/
56
57
58
59 static void DumpObjHeaderSection (const char* Name,
60                                   unsigned long Offset,
61                                   unsigned long Size)
62 /* Dump a header section */
63 {
64     printf ("    %s:\n", Name);
65     printf ("      Offset:%24lu\n", Offset);
66     printf ("      Size:  %24lu\n", Size);
67 }
68
69
70
71 static char* TimeToStr (unsigned long Time)
72 /* Convert the time into a string and return it */
73 {
74     /* Get the time and convert to string */
75     time_t T = (time_t) Time;
76     char*  S = asctime (localtime (&T));
77
78     /* Remove the trailing newline */
79     unsigned Len = strlen (S);
80     if (Len > 0 && S[Len-1] == '\n') {
81         S[Len-1 ] = '\0';
82     }
83
84     /* Return the time string */
85     return S;
86 }
87
88
89
90 static void SkipExpr (FILE* F)
91 /* Skip an expression from the given file */
92 {
93     /* Read the node tag and handle NULL nodes */
94     unsigned char Op = Read8 (F);
95     if (Op == EXPR_NULL) {
96         return;
97     }
98
99     /* Check the tag and handle the different expression types */
100     if (EXPR_IS_LEAF (Op)) {
101         switch (Op) {
102
103             case EXPR_LITERAL:
104                 (void) Read32Signed (F);
105                 break;
106
107             case EXPR_SYMBOL:
108                 /* Read the import number */
109                 (void) Read16 (F);
110                 break;
111
112             case EXPR_SEGMENT:
113                 /* Read the segment number */
114                 (void) Read8 (F);
115                 break;
116
117             default:
118                 Error ("Invalid expression op: %02X", Op);
119
120         }
121
122     } else {
123
124         /* Not a leaf node */
125         SkipExpr (F);
126         SkipExpr (F);
127
128     }
129 }
130
131
132
133 static unsigned SkipFragment (FILE* F)
134 /* Skip a fragment from the given file and return the size */
135 {
136     FilePos Pos;
137     unsigned long Size;
138
139     /* Read the fragment type */
140     unsigned char Type = Read8 (F);
141
142     /* Handle the different fragment types */
143     switch (Type) {
144
145         case FRAG_LITERAL8:
146             Size = Read8 (F);
147             break;
148
149         case FRAG_LITERAL16:
150             Size = Read16 (F);
151             break;
152
153         case FRAG_LITERAL24:
154             Size = Read24 (F);
155             break;
156
157         case FRAG_LITERAL32:
158             Size = Read32 (F);
159             break;
160
161         case FRAG_EXPR8:
162         case FRAG_EXPR16:
163         case FRAG_EXPR24:
164         case FRAG_EXPR32:
165         case FRAG_SEXPR8:
166         case FRAG_SEXPR16:
167         case FRAG_SEXPR24:
168         case FRAG_SEXPR32:
169             Size = Type & FRAG_BYTEMASK;
170             break;
171
172         case FRAG_FILL:
173             Size = Read16 (F);
174             break;
175
176         default:
177             Error ("Unknown fragment type: 0x%02X", Type);
178             /* NOTREACHED */
179             return 0;
180     }
181
182
183
184     /* Now read the fragment data */
185     switch (Type & FRAG_TYPEMASK) {
186
187         case FRAG_LITERAL:
188             /* Literal data */
189             FileSeek (F, ftell (F) + Size);
190             break;
191
192         case FRAG_EXPR:
193         case FRAG_SEXPR:
194             /* An expression */
195             SkipExpr (F);
196             break;
197
198     }
199
200     /* Skip the file position of the fragment */
201     ReadFilePos (F, &Pos);
202
203     /* Return the size */
204     return Size;
205 }
206
207
208
209 void DumpObjHeader (FILE* F, unsigned long Offset)
210 /* Dump the header of the given object file */
211 {
212     ObjHeader H;
213
214     /* Seek to the header position */
215     FileSeek (F, Offset);
216
217     /* Read the header */
218     ReadObjHeader (F, &H);
219
220     /* Now dump the information */
221
222     /* Output a header */
223     printf ("  Header:\n");
224
225     /* Magic */
226     printf ("    Magic:%17s0x%08lX\n", "", H.Magic);
227
228     /* Version */
229     printf ("    Version:%25u\n", H.Version);
230
231     /* Flags */
232     printf ("    Flags:%21s0x%04X  (", "", H.Flags);
233     if (H.Flags & OBJ_FLAGS_DBGINFO) {
234         printf ("OBJ_FLAGS_DBGINFO");
235     }
236     printf (")\n");
237
238     /* Options */
239     DumpObjHeaderSection ("Options", H.OptionOffs, H.OptionSize);
240
241     /* Files */
242     DumpObjHeaderSection ("Files", H.FileOffs, H.FileSize);
243
244     /* Segments */
245     DumpObjHeaderSection ("Segments", H.SegOffs, H.SegSize);
246
247     /* Imports */
248     DumpObjHeaderSection ("Imports", H.ImportOffs, H.ImportSize);
249
250     /* Exports */
251     DumpObjHeaderSection ("Exports", H.ExportOffs, H.ExportSize);
252
253     /* Debug symbols */
254     DumpObjHeaderSection ("Debug symbols", H.DbgSymOffs, H.DbgSymSize);
255 }
256
257
258
259 void DumpObjOptions (FILE* F, unsigned long Offset)
260 /* Dump the file options */
261 {
262     ObjHeader H;
263     unsigned Count;
264     unsigned I;
265
266     /* Seek to the header position */
267     FileSeek (F, Offset);
268
269     /* Read the header */
270     ReadObjHeader (F, &H);
271
272     /* Seek to the start of the options */
273     FileSeek (F, Offset + H.OptionOffs);
274
275     /* Output a header */
276     printf ("  Options:\n");
277
278     /* Read the number of options and print it */
279     Count = Read16 (F);
280     printf ("    Count:%27u\n", Count);
281
282     /* Read and print all options */
283     for (I = 0; I < Count; ++I) {
284
285         unsigned long ArgNum;
286         char*         ArgStr;
287         unsigned      ArgLen;
288
289         /* Read the type of the option */
290         unsigned char Type = Read8 (F);
291
292         /* Get the type of the argument */
293         unsigned char ArgType = Type & OPT_ARGMASK;
294
295         /* Determine which option follows */
296         const char* TypeDesc;
297         switch (Type) {
298             case OPT_COMMENT:   TypeDesc = "OPT_COMMENT";       break;
299             case OPT_AUTHOR:    TypeDesc = "OPT_AUTHOR";        break;
300             case OPT_TRANSLATOR:TypeDesc = "OPT_TRANSLATOR";    break;
301             case OPT_COMPILER:  TypeDesc = "OPT_COMPILER";      break;
302             case OPT_OS:        TypeDesc = "OPT_OS";            break;
303             case OPT_DATETIME:  TypeDesc = "OPT_DATETIME";      break;
304             default:            TypeDesc = "OPT_UNKNOWN";       break;
305         }
306
307         /* Print the header */
308         printf ("    Index:%27u\n", I);
309
310         /* Print the data */
311         printf ("      Type:%22s0x%02X  (%s)\n", "", Type, TypeDesc);
312         switch (ArgType) {
313
314             case OPT_ARGSTR:
315                 ArgStr = ReadMallocedStr (F);
316                 ArgLen = strlen (ArgStr);
317                 printf ("      Data:%*s\"%s\"\n", 24-ArgLen, "", ArgStr);
318                 xfree (ArgStr);
319                 break;
320
321             case OPT_ARGNUM:
322                 ArgNum = Read32 (F);
323                 printf ("      Data:%26lu", ArgNum);
324                 if (Type == OPT_DATETIME) {
325                     /* Print the time as a string */
326                     printf ("  (%s)", TimeToStr (ArgNum));
327                 }
328                 printf ("\n");
329                 break;
330
331             default:
332                 /* Unknown argument type. This means that we cannot determine
333                  * the option length, so we cannot proceed.
334                  */
335                 Error ("Unknown option type: 0x%02X", Type);
336                 break;
337         }
338     }
339 }
340
341
342
343 void DumpObjFiles (FILE* F, unsigned long Offset)
344 /* Dump the source files */
345 {
346     ObjHeader H;
347     unsigned Count;
348     unsigned I;
349
350     /* Seek to the header position */
351     FileSeek (F, Offset);
352
353     /* Read the header */
354     ReadObjHeader (F, &H);
355
356     /* Seek to the start of the options */
357     FileSeek (F, Offset + H.FileOffs);
358
359     /* Output a header */
360     printf ("  Files:\n");
361
362     /* Read the number of files and print it */
363     Count = Read8 (F);
364     printf ("    Count:%27u\n", Count);
365
366     /* Read and print all options */
367     for (I = 0; I < Count; ++I) {
368
369         /* Read the data for one file */
370         unsigned long MTime = Read32 (F);
371         unsigned long Size  = Read32 (F);
372         char*         Name  = ReadMallocedStr (F);
373         unsigned      Len   = strlen (Name);
374
375         /* Print the header */
376         printf ("    Index:%27u\n", I);
377
378         /* Print the data */
379         printf ("      Name:%*s\"%s\"\n", 24-Len, "", Name);
380         printf ("      Size:%26lu\n", Size);
381         printf ("      Modification time:%13lu  (%s)\n", MTime, TimeToStr (MTime));
382
383         /* Free the Name */
384         xfree (Name);
385     }
386 }
387
388
389
390 void DumpObjSegments (FILE* F, unsigned long Offset)
391 /* Dump the segments in the object file */
392 {
393     ObjHeader H;
394     unsigned Count;
395     unsigned I;
396     unsigned FragCount;
397
398     /* Seek to the header position */
399     FileSeek (F, Offset);
400
401     /* Read the header */
402     ReadObjHeader (F, &H);
403
404     /* Seek to the start of the options */
405     FileSeek (F, Offset + H.SegOffs);
406
407     /* Output a header */
408     printf ("  Segments:\n");
409
410     /* Read the number of files and print it */
411     Count = Read8 (F);
412     printf ("    Count:%27u\n", Count);
413
414     /* Read and print all options */
415     for (I = 0; I < Count; ++I) {
416
417         /* Read the data for one segments */
418         char*         Name  = ReadMallocedStr (F);
419         unsigned      Len   = strlen (Name);
420         unsigned long Size  = Read32 (F);
421         unsigned      Align = (1U << Read8 (F));
422         unsigned char Type  = Read8 (F);
423
424         /* Get the description for the type */
425         const char* TypeDesc;
426         switch (Type) {
427             case SEGTYPE_DEFAULT:       TypeDesc = "SEGTYPE_DEFAULT";   break;
428             case SEGTYPE_ABS:           TypeDesc = "SEGTYPE_ABS";       break;
429             case SEGTYPE_ZP:            TypeDesc = "SEGTYPE_ZP";        break;
430             case SEGTYPE_FAR:           TypeDesc = "SEGTYPE_FAR";       break;
431             default:                    TypeDesc = "SEGTYPE_UNKNOWN";   break;
432         }
433
434         /* Print the header */
435         printf ("    Index:%27u\n", I);
436
437         /* Print the data */
438         printf ("      Name:%*s\"%s\"\n", 24-Len, "", Name);
439         printf ("      Size:%26lu\n", Size);
440         printf ("      Alignment:%21u\n", Align);
441         printf ("      Type:%22s0x%02X  (%s)\n", "", Type, TypeDesc);
442
443         /* Free the Name */
444         xfree (Name);
445
446         /* Skip the fragments for this segment, counting them */
447         FragCount = 0;
448         while (Size > 0) {
449             unsigned FragSize = SkipFragment (F);
450             if (FragSize > Size) {
451                 /* OOPS - file data invalid */
452                 Error ("Invalid fragment data - file corrupt!");
453             }
454             Size -= FragSize;
455             ++FragCount;
456         }
457
458         /* Print the fragment count */
459         printf ("      Fragment count:%16u\n", FragCount);
460     }
461 }
462
463
464