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 /*****************************************************************************/
53 /*****************************************************************************/
55 /*****************************************************************************/
59 static void DumpObjHeaderSection (const char* Name,
62 /* Dump a header section */
64 printf (" %s:\n", Name);
65 printf (" Offset:%24lu\n", Offset);
66 printf (" Size: %24lu\n", Size);
71 static char* TimeToStr (unsigned long Time)
72 /* Convert the time into a string and return it */
74 /* Get the time and convert to string */
75 time_t T = (time_t) Time;
76 char* S = asctime (localtime (&T));
78 /* Remove the trailing newline */
79 unsigned Len = strlen (S);
80 if (Len > 0 && S[Len-1] == '\n') {
84 /* Return the time string */
90 static void SkipExpr (FILE* F)
91 /* Skip an expression from the given file */
93 /* Read the node tag and handle NULL nodes */
94 unsigned char Op = Read8 (F);
95 if (Op == EXPR_NULL) {
99 /* Check the tag and handle the different expression types */
100 if (EXPR_IS_LEAF (Op)) {
104 (void) Read32Signed (F);
108 /* Read the import number */
113 /* Read the segment number */
118 Error ("Invalid expression op: %02X", Op);
124 /* Not a leaf node */
133 static unsigned SkipFragment (FILE* F)
134 /* Skip a fragment from the given file and return the size */
139 /* Read the fragment type */
140 unsigned char Type = Read8 (F);
142 /* Handle the different fragment types */
169 Size = Type & FRAG_BYTEMASK;
177 Error ("Unknown fragment type: 0x%02X", Type);
184 /* Now read the fragment data */
185 switch (Type & FRAG_TYPEMASK) {
189 FileSeek (F, ftell (F) + Size);
200 /* Skip the file position of the fragment */
201 ReadFilePos (F, &Pos);
203 /* Return the size */
209 void DumpObjHeader (FILE* F, unsigned long Offset)
210 /* Dump the header of the given object file */
214 /* Seek to the header position */
215 FileSeek (F, Offset);
217 /* Read the header */
218 ReadObjHeader (F, &H);
220 /* Now dump the information */
222 /* Output a header */
223 printf (" Header:\n");
226 printf (" Magic:%17s0x%08lX\n", "", H.Magic);
229 printf (" Version:%25u\n", H.Version);
232 printf (" Flags:%21s0x%04X (", "", H.Flags);
233 if (H.Flags & OBJ_FLAGS_DBGINFO) {
234 printf ("OBJ_FLAGS_DBGINFO");
239 DumpObjHeaderSection ("Options", H.OptionOffs, H.OptionSize);
242 DumpObjHeaderSection ("Files", H.FileOffs, H.FileSize);
245 DumpObjHeaderSection ("Segments", H.SegOffs, H.SegSize);
248 DumpObjHeaderSection ("Imports", H.ImportOffs, H.ImportSize);
251 DumpObjHeaderSection ("Exports", H.ExportOffs, H.ExportSize);
254 DumpObjHeaderSection ("Debug symbols", H.DbgSymOffs, H.DbgSymSize);
259 void DumpObjOptions (FILE* F, unsigned long Offset)
260 /* Dump the file options */
266 /* Seek to the header position */
267 FileSeek (F, Offset);
269 /* Read the header */
270 ReadObjHeader (F, &H);
272 /* Seek to the start of the options */
273 FileSeek (F, Offset + H.OptionOffs);
275 /* Output a header */
276 printf (" Options:\n");
278 /* Read the number of options and print it */
280 printf (" Count:%27u\n", Count);
282 /* Read and print all options */
283 for (I = 0; I < Count; ++I) {
285 unsigned long ArgNum;
289 /* Read the type of the option */
290 unsigned char Type = Read8 (F);
292 /* Get the type of the argument */
293 unsigned char ArgType = Type & OPT_ARGMASK;
295 /* Determine which option follows */
296 const char* TypeDesc;
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;
307 /* Print the header */
308 printf (" Index:%27u\n", I);
311 printf (" Type:%22s0x%02X (%s)\n", "", Type, TypeDesc);
315 ArgStr = ReadMallocedStr (F);
316 ArgLen = strlen (ArgStr);
317 printf (" Data:%*s\"%s\"\n", 24-ArgLen, "", ArgStr);
323 printf (" Data:%26lu", ArgNum);
324 if (Type == OPT_DATETIME) {
325 /* Print the time as a string */
326 printf (" (%s)", TimeToStr (ArgNum));
332 /* Unknown argument type. This means that we cannot determine
333 * the option length, so we cannot proceed.
335 Error ("Unknown option type: 0x%02X", Type);
343 void DumpObjFiles (FILE* F, unsigned long Offset)
344 /* Dump the source files */
350 /* Seek to the header position */
351 FileSeek (F, Offset);
353 /* Read the header */
354 ReadObjHeader (F, &H);
356 /* Seek to the start of the options */
357 FileSeek (F, Offset + H.FileOffs);
359 /* Output a header */
360 printf (" Files:\n");
362 /* Read the number of files and print it */
364 printf (" Count:%27u\n", Count);
366 /* Read and print all options */
367 for (I = 0; I < Count; ++I) {
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);
375 /* Print the header */
376 printf (" Index:%27u\n", I);
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));
390 void DumpObjSegments (FILE* F, unsigned long Offset)
391 /* Dump the segments in the object file */
398 /* Seek to the header position */
399 FileSeek (F, Offset);
401 /* Read the header */
402 ReadObjHeader (F, &H);
404 /* Seek to the start of the options */
405 FileSeek (F, Offset + H.SegOffs);
407 /* Output a header */
408 printf (" Segments:\n");
410 /* Read the number of files and print it */
412 printf (" Count:%27u\n", Count);
414 /* Read and print all options */
415 for (I = 0; I < Count; ++I) {
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);
424 /* Get the description for the type */
425 const char* TypeDesc;
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;
434 /* Print the header */
435 printf (" Index:%27u\n", I);
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);
446 /* Skip the fragments for this segment, counting them */
449 unsigned FragSize = SkipFragment (F);
450 if (FragSize > Size) {
451 /* OOPS - file data invalid */
452 Error ("Invalid fragment data - file corrupt!");
458 /* Print the fragment count */
459 printf (" Fragment count:%16u\n", FragCount);