1 /*****************************************************************************/
5 /* Dump subroutines for the od65 object file dump utility */
9 /* (C) 2000 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@musoftware.de */
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. */
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: */
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 */
32 /*****************************************************************************/
54 /*****************************************************************************/
56 /*****************************************************************************/
60 static void DumpObjHeaderSection (const char* Name,
63 /* Dump a header section */
65 printf (" %s:\n", Name);
66 printf (" Offset:%24lu\n", Offset);
67 printf (" Size: %24lu\n", Size);
72 static char* TimeToStr (unsigned long Time)
73 /* Convert the time into a string and return it */
75 /* Get the time and convert to string */
76 time_t T = (time_t) Time;
77 char* S = asctime (localtime (&T));
79 /* Remove the trailing newline */
80 unsigned Len = strlen (S);
81 if (Len > 0 && S[Len-1] == '\n') {
85 /* Return the time string */
91 static void SkipExpr (FILE* F)
92 /* Skip an expression from the given file */
94 /* Read the node tag and handle NULL nodes */
95 unsigned char Op = Read8 (F);
96 if (Op == EXPR_NULL) {
100 /* Check the tag and handle the different expression types */
101 if (EXPR_IS_LEAF (Op)) {
105 (void) Read32Signed (F);
109 /* Read the import number */
114 /* Read the segment number */
119 Error ("Invalid expression op: %02X", Op);
125 /* Not a leaf node */
134 static unsigned SkipFragment (FILE* F)
135 /* Skip a fragment from the given file and return the size */
140 /* Read the fragment type */
141 unsigned char Type = Read8 (F);
143 /* Handle the different fragment types */
170 Size = Type & FRAG_BYTEMASK;
178 Error ("Unknown fragment type: 0x%02X", Type);
185 /* Now read the fragment data */
186 switch (Type & FRAG_TYPEMASK) {
190 FileSeek (F, ftell (F) + Size);
201 /* Skip the file position of the fragment */
202 ReadFilePos (F, &Pos);
204 /* Return the size */
210 void DumpObjHeader (FILE* F, unsigned long Offset)
211 /* Dump the header of the given object file */
215 /* Seek to the header position */
216 FileSeek (F, Offset);
218 /* Read the header */
219 ReadObjHeader (F, &H);
221 /* Now dump the information */
223 /* Output a header */
224 printf (" Header:\n");
227 printf (" Magic:%17s0x%08lX\n", "", H.Magic);
230 printf (" Version:%25u\n", H.Version);
233 printf (" Flags:%21s0x%04X (", "", H.Flags);
234 if (H.Flags & OBJ_FLAGS_DBGINFO) {
235 printf ("OBJ_FLAGS_DBGINFO");
240 DumpObjHeaderSection ("Options", H.OptionOffs, H.OptionSize);
243 DumpObjHeaderSection ("Files", H.FileOffs, H.FileSize);
246 DumpObjHeaderSection ("Segments", H.SegOffs, H.SegSize);
249 DumpObjHeaderSection ("Imports", H.ImportOffs, H.ImportSize);
252 DumpObjHeaderSection ("Exports", H.ExportOffs, H.ExportSize);
255 DumpObjHeaderSection ("Debug symbols", H.DbgSymOffs, H.DbgSymSize);
260 void DumpObjOptions (FILE* F, unsigned long Offset)
261 /* Dump the file options */
267 /* Seek to the header position */
268 FileSeek (F, Offset);
270 /* Read the header */
271 ReadObjHeader (F, &H);
273 /* Seek to the start of the options */
274 FileSeek (F, Offset + H.OptionOffs);
276 /* Output a header */
277 printf (" Options:\n");
279 /* Read the number of options and print it */
281 printf (" Count:%27u\n", Count);
283 /* Read and print all options */
284 for (I = 0; I < Count; ++I) {
286 unsigned long ArgNum;
290 /* Read the type of the option */
291 unsigned char Type = Read8 (F);
293 /* Get the type of the argument */
294 unsigned char ArgType = Type & OPT_ARGMASK;
296 /* Determine which option follows */
297 const char* TypeDesc;
299 case OPT_COMMENT: TypeDesc = "OPT_COMMENT"; break;
300 case OPT_AUTHOR: TypeDesc = "OPT_AUTHOR"; break;
301 case OPT_TRANSLATOR:TypeDesc = "OPT_TRANSLATOR"; break;
302 case OPT_COMPILER: TypeDesc = "OPT_COMPILER"; break;
303 case OPT_OS: TypeDesc = "OPT_OS"; break;
304 case OPT_DATETIME: TypeDesc = "OPT_DATETIME"; break;
305 default: TypeDesc = "OPT_UNKNOWN"; break;
308 /* Print the header */
309 printf (" Index:%27u\n", I);
312 printf (" Type:%22s0x%02X (%s)\n", "", Type, TypeDesc);
316 ArgStr = ReadMallocedStr (F);
317 ArgLen = strlen (ArgStr);
318 printf (" Data:%*s\"%s\"\n", 24-ArgLen, "", ArgStr);
324 printf (" Data:%26lu", ArgNum);
325 if (Type == OPT_DATETIME) {
326 /* Print the time as a string */
327 printf (" (%s)", TimeToStr (ArgNum));
333 /* Unknown argument type. This means that we cannot determine
334 * the option length, so we cannot proceed.
336 Error ("Unknown option type: 0x%02X", Type);
344 void DumpObjFiles (FILE* F, unsigned long Offset)
345 /* Dump the source files */
351 /* Seek to the header position */
352 FileSeek (F, Offset);
354 /* Read the header */
355 ReadObjHeader (F, &H);
357 /* Seek to the start of the options */
358 FileSeek (F, Offset + H.FileOffs);
360 /* Output a header */
361 printf (" Files:\n");
363 /* Read the number of files and print it */
365 printf (" Count:%27u\n", Count);
367 /* Read and print all files */
368 for (I = 0; I < Count; ++I) {
370 /* Read the data for one file */
371 unsigned long MTime = Read32 (F);
372 unsigned long Size = Read32 (F);
373 char* Name = ReadMallocedStr (F);
374 unsigned Len = strlen (Name);
376 /* Print the header */
377 printf (" Index:%27u\n", I);
380 printf (" Name:%*s\"%s\"\n", 24-Len, "", Name);
381 printf (" Size:%26lu\n", Size);
382 printf (" Modification time:%13lu (%s)\n", MTime, TimeToStr (MTime));
391 void DumpObjSegments (FILE* F, unsigned long Offset)
392 /* Dump the segments in the object file */
399 /* Seek to the header position */
400 FileSeek (F, Offset);
402 /* Read the header */
403 ReadObjHeader (F, &H);
405 /* Seek to the start of the options */
406 FileSeek (F, Offset + H.SegOffs);
408 /* Output a header */
409 printf (" Segments:\n");
411 /* Read the number of segments and print it */
413 printf (" Count:%27u\n", Count);
415 /* Read and print all segments */
416 for (I = 0; I < Count; ++I) {
418 /* Read the data for one segments */
419 char* Name = ReadMallocedStr (F);
420 unsigned Len = strlen (Name);
421 unsigned long Size = Read32 (F);
422 unsigned Align = (1U << Read8 (F));
423 unsigned char Type = Read8 (F);
425 /* Get the description for the type */
426 const char* TypeDesc;
428 case SEGTYPE_DEFAULT: TypeDesc = "SEGTYPE_DEFAULT"; break;
429 case SEGTYPE_ABS: TypeDesc = "SEGTYPE_ABS"; break;
430 case SEGTYPE_ZP: TypeDesc = "SEGTYPE_ZP"; break;
431 case SEGTYPE_FAR: TypeDesc = "SEGTYPE_FAR"; break;
432 default: TypeDesc = "SEGTYPE_UNKNOWN"; break;
435 /* Print the header */
436 printf (" Index:%27u\n", I);
439 printf (" Name:%*s\"%s\"\n", 24-Len, "", Name);
440 printf (" Size:%26lu\n", Size);
441 printf (" Alignment:%21u\n", Align);
442 printf (" Type:%22s0x%02X (%s)\n", "", Type, TypeDesc);
447 /* Skip the fragments for this segment, counting them */
450 unsigned FragSize = SkipFragment (F);
451 if (FragSize > Size) {
452 /* OOPS - file data invalid */
453 Error ("Invalid fragment data - file corrupt!");
459 /* Print the fragment count */
460 printf (" Fragment count:%16u\n", FragCount);
466 void DumpObjImports (FILE* F, unsigned long Offset)
467 /* Dump the imports in the object file */
474 /* Seek to the header position */
475 FileSeek (F, Offset);
477 /* Read the header */
478 ReadObjHeader (F, &H);
480 /* Seek to the start of the options */
481 FileSeek (F, Offset + H.ImportOffs);
483 /* Output a header */
484 printf (" Imports:\n");
486 /* Read the number of imports and print it */
488 printf (" Count:%27u\n", Count);
490 /* Read and print all imports */
491 for (I = 0; I < Count; ++I) {
493 const char* TypeDesc;
495 /* Read the data for one import */
496 unsigned char Type = Read8 (F);
497 char* Name = ReadMallocedStr (F);
498 unsigned Len = strlen (Name);
499 ReadFilePos (F, &Pos);
501 /* Get a description for the type */
503 case IMP_ZP: TypeDesc = "IMP_ZP"; break;
504 case IMP_ABS: TypeDesc = "IMP_ABS"; break;
505 default: TypeDesc = "IMP_UNKNOWN"; break;
508 /* Print the header */
509 printf (" Index:%27u\n", I);
512 printf (" Type:%22s0x%02X (%s)\n", "", Type, TypeDesc);
513 printf (" Name:%*s\"%s\"\n", 24-Len, "", Name);
522 void DumpObjExports (FILE* F, unsigned long Offset)
523 /* Dump the exports in the object file */
530 /* Seek to the header position */
531 FileSeek (F, Offset);
533 /* Read the header */
534 ReadObjHeader (F, &H);
536 /* Seek to the start of the options */
537 FileSeek (F, Offset + H.ExportOffs);
539 /* Output a header */
540 printf (" Exports:\n");
542 /* Read the number of exports and print it */
544 printf (" Count:%27u\n", Count);
546 /* Read and print all exports */
547 for (I = 0; I < Count; ++I) {
549 unsigned long Value = 0;
551 const char* TypeDesc;
553 /* Read the data for one export */
554 unsigned char Type = Read8 (F);
555 char* Name = ReadMallocedStr (F);
556 unsigned Len = strlen (Name);
557 if (Type & EXP_EXPR) {
564 ReadFilePos (F, &Pos);
566 /* Get a description for the type */
568 case EXP_ABS|EXP_CONST: TypeDesc = "EXP_ABS,EXP_CONST"; break;
569 case EXP_ZP|EXP_CONST: TypeDesc = "EXP_ZP,EXP_CONST"; break;
570 case EXP_ABS|EXP_EXPR: TypeDesc = "EXP_ABS,EXP_EXPR"; break;
571 case EXP_ZP|EXP_EXPR: TypeDesc = "EXP_ZP,EXP_EXPR"; break;
572 default: TypeDesc = "EXP_UNKNOWN"; break;
575 /* Print the header */
576 printf (" Index:%27u\n", I);
579 printf (" Type:%22s0x%02X (%s)\n", "", Type, TypeDesc);
580 printf (" Name:%*s\"%s\"\n", 24-Len, "", Name);
582 printf (" Value:%15s0x%08lX (%lu)\n", "", Value, Value);
592 void DumpObjDbgSyms (FILE* F, unsigned long Offset)
593 /* Dump the debug symbols from an object file */
600 /* Seek to the header position */
601 FileSeek (F, Offset);
603 /* Read the header */
604 ReadObjHeader (F, &H);
606 /* Seek to the start of the options */
607 FileSeek (F, Offset + H.DbgSymOffs);
609 /* Output a header */
610 printf (" Debug symbols:\n");
612 /* Check if the object file was compiled with debug info */
613 if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) {
614 /* Print that there no debug symbols and bail out */
615 printf (" Count:%27u\n", 0);
619 /* Read the number of exports and print it */
621 printf (" Count:%27u\n", Count);
623 /* Read and print all debug symbols */
624 for (I = 0; I < Count; ++I) {
626 unsigned long Value = 0;
628 const char* TypeDesc;
630 /* Read the data for one symbol */
631 unsigned char Type = Read8 (F);
632 char* Name = ReadMallocedStr (F);
633 unsigned Len = strlen (Name);
634 if (Type & EXP_EXPR) {
641 ReadFilePos (F, &Pos);
643 /* Get a description for the type */
645 case EXP_ABS|EXP_CONST: TypeDesc = "EXP_ABS,EXP_CONST"; break;
646 case EXP_ZP|EXP_CONST: TypeDesc = "EXP_ZP,EXP_CONST"; break;
647 case EXP_ABS|EXP_EXPR: TypeDesc = "EXP_ABS,EXP_EXPR"; break;
648 case EXP_ZP|EXP_EXPR: TypeDesc = "EXP_ZP,EXP_EXPR"; break;
649 default: TypeDesc = "EXP_UNKNOWN"; break;
652 /* Print the header */
653 printf (" Index:%27u\n", I);
656 printf (" Type:%22s0x%02X (%s)\n", "", Type, TypeDesc);
657 printf (" Name:%*s\"%s\"\n", 24-Len, "", Name);
659 printf (" Value:%15s0x%08lX (%lu)\n", "", Value, Value);