2000-07-29 22:34:15 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* dump.c */
|
|
|
|
/* */
|
|
|
|
/* Dump subroutines for the od65 object file dump utility */
|
|
|
|
/* */
|
|
|
|
/* */
|
|
|
|
/* */
|
2012-01-03 21:41:34 +00:00
|
|
|
/* (C) 2002-2012, Ullrich von Bassewitz */
|
2009-09-28 15:59:18 +00:00
|
|
|
/* Roemerstrasse 52 */
|
|
|
|
/* D-70794 Filderstadt */
|
|
|
|
/* EMail: uz@cc65.org */
|
2000-07-29 22:34:15 +00:00
|
|
|
/* */
|
|
|
|
/* */
|
|
|
|
/* This software is provided 'as-is', without any expressed or implied */
|
|
|
|
/* warranty. In no event will the authors be held liable for any damages */
|
|
|
|
/* arising from the use of this software. */
|
|
|
|
/* */
|
|
|
|
/* Permission is granted to anyone to use this software for any purpose, */
|
|
|
|
/* including commercial applications, and to alter it and redistribute it */
|
|
|
|
/* freely, subject to the following restrictions: */
|
|
|
|
/* */
|
|
|
|
/* 1. The origin of this software must not be misrepresented; you must not */
|
|
|
|
/* claim that you wrote the original software. If you use this software */
|
|
|
|
/* in a product, an acknowledgment in the product documentation would be */
|
|
|
|
/* appreciated but is not required. */
|
|
|
|
/* 2. Altered source versions must be plainly marked as such, and must not */
|
|
|
|
/* be misrepresented as being the original software. */
|
|
|
|
/* 3. This notice may not be removed or altered from any source */
|
|
|
|
/* distribution. */
|
|
|
|
/* */
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-10-30 19:30:26 +00:00
|
|
|
#include <string.h>
|
2000-07-30 14:25:30 +00:00
|
|
|
#include <time.h>
|
|
|
|
|
2000-07-29 22:34:15 +00:00
|
|
|
/* common */
|
2003-11-07 19:28:37 +00:00
|
|
|
#include "addrsize.h"
|
2000-11-20 15:22:57 +00:00
|
|
|
#include "cddefs.h"
|
2003-05-25 17:57:50 +00:00
|
|
|
#include "coll.h"
|
2000-07-30 19:51:33 +00:00
|
|
|
#include "exprdefs.h"
|
|
|
|
#include "filepos.h"
|
2011-01-29 22:16:03 +00:00
|
|
|
#include "lidefs.h"
|
2000-07-29 22:34:15 +00:00
|
|
|
#include "objdefs.h"
|
2000-07-30 14:25:30 +00:00
|
|
|
#include "optdefs.h"
|
2011-07-31 14:01:27 +00:00
|
|
|
#include "scopedefs.h"
|
2000-07-30 21:02:44 +00:00
|
|
|
#include "symdefs.h"
|
2000-07-30 14:25:30 +00:00
|
|
|
#include "xmalloc.h"
|
2000-07-29 22:34:15 +00:00
|
|
|
|
|
|
|
/* od65 */
|
2000-07-30 14:25:30 +00:00
|
|
|
#include "error.h"
|
2000-07-29 22:34:15 +00:00
|
|
|
#include "fileio.h"
|
|
|
|
#include "dump.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2003-05-25 17:57:50 +00:00
|
|
|
/* Code */
|
2000-07-29 22:34:15 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
2003-05-25 17:57:50 +00:00
|
|
|
static void DestroyStrPool (Collection* C)
|
|
|
|
/* Free all strings in the given pool plus the item pointers. Note: The
|
|
|
|
* collection may not be reused later.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
unsigned I;
|
|
|
|
for (I = 0; I < CollCount (C); ++I) {
|
|
|
|
xfree (CollAtUnchecked (C, I));
|
|
|
|
}
|
|
|
|
DoneCollection (C);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char* GetString (const Collection* C, unsigned Index)
|
|
|
|
/* Get a string from a collection. In fact, this function calls CollConstAt,
|
|
|
|
* but will print a somewhat more readable error message if the index is out
|
|
|
|
* of bounds.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
if (Index >= CollCount (C)) {
|
|
|
|
Error ("Invalid string index (%u) - file corrupt!", Index);
|
|
|
|
}
|
|
|
|
return CollConstAt (C, Index);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-07-30 14:25:30 +00:00
|
|
|
static void DumpObjHeaderSection (const char* Name,
|
|
|
|
unsigned long Offset,
|
|
|
|
unsigned long Size)
|
2000-07-29 22:34:15 +00:00
|
|
|
/* Dump a header section */
|
|
|
|
{
|
|
|
|
printf (" %s:\n", Name);
|
2000-07-30 19:51:33 +00:00
|
|
|
printf (" Offset:%24lu\n", Offset);
|
|
|
|
printf (" Size: %24lu\n", Size);
|
2000-07-29 22:34:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-07-30 16:15:04 +00:00
|
|
|
static char* TimeToStr (unsigned long Time)
|
|
|
|
/* Convert the time into a string and return it */
|
|
|
|
{
|
|
|
|
/* Get the time and convert to string */
|
|
|
|
time_t T = (time_t) Time;
|
|
|
|
char* S = asctime (localtime (&T));
|
|
|
|
|
|
|
|
/* Remove the trailing newline */
|
|
|
|
unsigned Len = strlen (S);
|
|
|
|
if (Len > 0 && S[Len-1] == '\n') {
|
2011-01-27 16:47:45 +00:00
|
|
|
S[Len-1 ] = '\0';
|
2000-07-30 16:15:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the time string */
|
|
|
|
return S;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-27 16:47:45 +00:00
|
|
|
static void SkipLineInfoList (FILE* F)
|
|
|
|
/* Skip a line info list from the given file */
|
|
|
|
{
|
|
|
|
/* Count preceeds the list */
|
|
|
|
unsigned long Count = ReadVar (F);
|
|
|
|
|
|
|
|
/* Skip indices */
|
|
|
|
while (Count--) {
|
|
|
|
(void) ReadVar (F);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-21 19:08:23 +00:00
|
|
|
static void SkipSpanList (FILE* F)
|
|
|
|
/* Skip a span list from the given file */
|
|
|
|
{
|
|
|
|
/* Count preceeds the list */
|
|
|
|
unsigned long Count = ReadVar (F);
|
|
|
|
|
|
|
|
/* Skip indices */
|
|
|
|
while (Count--) {
|
|
|
|
(void) ReadVar (F);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-07-30 19:51:33 +00:00
|
|
|
static void SkipExpr (FILE* F)
|
|
|
|
/* Skip an expression from the given file */
|
|
|
|
{
|
|
|
|
/* Read the node tag and handle NULL nodes */
|
|
|
|
unsigned char Op = Read8 (F);
|
|
|
|
if (Op == EXPR_NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check the tag and handle the different expression types */
|
|
|
|
if (EXPR_IS_LEAF (Op)) {
|
|
|
|
switch (Op) {
|
|
|
|
|
|
|
|
case EXPR_LITERAL:
|
|
|
|
(void) Read32Signed (F);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EXPR_SYMBOL:
|
|
|
|
/* Read the import number */
|
2003-05-25 17:57:50 +00:00
|
|
|
(void) ReadVar (F);
|
2000-07-30 19:51:33 +00:00
|
|
|
break;
|
|
|
|
|
2002-12-24 14:39:09 +00:00
|
|
|
case EXPR_SECTION:
|
2012-01-03 21:41:34 +00:00
|
|
|
case EXPR_BANK:
|
2000-07-30 19:51:33 +00:00
|
|
|
/* Read the segment number */
|
2012-01-03 21:41:34 +00:00
|
|
|
(void) ReadVar (F);
|
2011-01-27 16:47:45 +00:00
|
|
|
break;
|
2000-07-30 19:51:33 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
Error ("Invalid expression op: %02X", Op);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/* Not a leaf node */
|
|
|
|
SkipExpr (F);
|
|
|
|
SkipExpr (F);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-11-20 15:22:57 +00:00
|
|
|
static const char* GetExportFlags (unsigned Flags, const unsigned char* ConDes)
|
2000-10-30 19:52:22 +00:00
|
|
|
/* Get the export flags as a (static) string */
|
|
|
|
{
|
|
|
|
/* Static buffer */
|
2000-11-20 15:22:57 +00:00
|
|
|
static char TypeDesc[256];
|
|
|
|
static char* T;
|
2000-10-30 19:52:22 +00:00
|
|
|
|
2000-11-20 15:22:57 +00:00
|
|
|
unsigned Count;
|
|
|
|
unsigned I;
|
|
|
|
|
2010-08-17 21:04:28 +00:00
|
|
|
/* Symbol type */
|
2003-11-28 22:12:14 +00:00
|
|
|
TypeDesc[0] = '\0';
|
2010-08-17 21:04:28 +00:00
|
|
|
switch (Flags & SYM_MASK_TYPE) {
|
|
|
|
case SYM_STD: strcat (TypeDesc, "SYM_STD"); break;
|
|
|
|
case SYM_CHEAP_LOCAL: strcat (TypeDesc, "SYM_CHEAP_LOCAL"); break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Symbol usage */
|
2011-01-27 16:47:45 +00:00
|
|
|
switch (Flags & SYM_MASK_LABEL) {
|
2010-08-17 21:04:28 +00:00
|
|
|
case SYM_EQUATE: strcat (TypeDesc, ",SYM_EQUATE"); break;
|
|
|
|
case SYM_LABEL: strcat (TypeDesc, ",SYM_LABEL"); break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Type of expression */
|
2010-08-17 20:47:27 +00:00
|
|
|
switch (Flags & SYM_MASK_VAL) {
|
2010-08-17 21:04:28 +00:00
|
|
|
case SYM_CONST: strcat (TypeDesc, ",SYM_CONST"); break;
|
|
|
|
case SYM_EXPR: strcat (TypeDesc, ",SYM_EXPR"); break;
|
2000-10-30 19:52:22 +00:00
|
|
|
}
|
2000-11-20 15:22:57 +00:00
|
|
|
|
2011-06-13 18:43:50 +00:00
|
|
|
/* Size available? */
|
|
|
|
if (SYM_HAS_SIZE (Flags)) {
|
|
|
|
strcat (TypeDesc, ",SYM_SIZE");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-11-20 15:22:57 +00:00
|
|
|
/* Constructor/destructor declarations */
|
|
|
|
T = TypeDesc + strlen (TypeDesc);
|
2010-08-17 20:47:27 +00:00
|
|
|
Count = SYM_GET_CONDES_COUNT (Flags);
|
2003-11-28 22:12:14 +00:00
|
|
|
if (Count > 0 && ConDes) {
|
2011-06-13 18:43:50 +00:00
|
|
|
T += sprintf (T, ",SYM_CONDES=");
|
|
|
|
for (I = 0; I < Count; ++I) {
|
|
|
|
unsigned Type = CD_GET_TYPE (ConDes[I]);
|
|
|
|
unsigned Prio = CD_GET_PRIO (ConDes[I]);
|
|
|
|
if (I > 0) {
|
|
|
|
*T++ = ',';
|
|
|
|
}
|
2000-11-20 15:22:57 +00:00
|
|
|
T += sprintf (T, "[%u,%u]", Type, Prio);
|
2011-06-13 18:43:50 +00:00
|
|
|
}
|
2000-10-30 19:52:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the result */
|
|
|
|
return TypeDesc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-07-31 14:01:27 +00:00
|
|
|
static const char* GetScopeType (unsigned Type)
|
|
|
|
/* Return the name of a scope type */
|
|
|
|
{
|
|
|
|
switch (Type) {
|
2011-07-31 15:37:51 +00:00
|
|
|
case SCOPE_GLOBAL: return "Global scope";
|
|
|
|
case SCOPE_FILE: return "File scope";
|
2011-07-31 17:11:10 +00:00
|
|
|
case SCOPE_SCOPE: return ".SCOPE or .PROC";
|
2011-07-31 15:37:51 +00:00
|
|
|
case SCOPE_STRUCT: return ".STRUCT";
|
|
|
|
case SCOPE_ENUM: return ".ENUM";
|
|
|
|
case SCOPE_UNDEF: return "Undefined";
|
2011-07-31 14:01:27 +00:00
|
|
|
default: return "Unknown scope type";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-07-30 14:25:30 +00:00
|
|
|
void DumpObjHeader (FILE* F, unsigned long Offset)
|
2000-07-29 22:34:15 +00:00
|
|
|
/* Dump the header of the given object file */
|
|
|
|
{
|
|
|
|
ObjHeader H;
|
|
|
|
|
|
|
|
/* Seek to the header position */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset);
|
2000-07-29 22:34:15 +00:00
|
|
|
|
|
|
|
/* Read the header */
|
|
|
|
ReadObjHeader (F, &H);
|
|
|
|
|
|
|
|
/* Now dump the information */
|
|
|
|
|
2000-07-30 14:25:30 +00:00
|
|
|
/* Output a header */
|
|
|
|
printf (" Header:\n");
|
|
|
|
|
2000-07-29 22:34:15 +00:00
|
|
|
/* Magic */
|
2000-07-30 19:51:33 +00:00
|
|
|
printf (" Magic:%17s0x%08lX\n", "", H.Magic);
|
2000-07-29 22:34:15 +00:00
|
|
|
|
|
|
|
/* Version */
|
2000-07-30 19:51:33 +00:00
|
|
|
printf (" Version:%25u\n", H.Version);
|
2000-07-29 22:34:15 +00:00
|
|
|
|
|
|
|
/* Flags */
|
2000-07-30 19:51:33 +00:00
|
|
|
printf (" Flags:%21s0x%04X (", "", H.Flags);
|
2000-07-29 22:34:15 +00:00
|
|
|
if (H.Flags & OBJ_FLAGS_DBGINFO) {
|
2000-07-30 14:25:30 +00:00
|
|
|
printf ("OBJ_FLAGS_DBGINFO");
|
2000-07-29 22:34:15 +00:00
|
|
|
}
|
|
|
|
printf (")\n");
|
|
|
|
|
|
|
|
/* Options */
|
2000-07-30 14:25:30 +00:00
|
|
|
DumpObjHeaderSection ("Options", H.OptionOffs, H.OptionSize);
|
2000-07-29 22:34:15 +00:00
|
|
|
|
|
|
|
/* Files */
|
2000-07-30 14:25:30 +00:00
|
|
|
DumpObjHeaderSection ("Files", H.FileOffs, H.FileSize);
|
2000-07-29 22:34:15 +00:00
|
|
|
|
|
|
|
/* Segments */
|
2000-07-30 14:25:30 +00:00
|
|
|
DumpObjHeaderSection ("Segments", H.SegOffs, H.SegSize);
|
2000-07-29 22:34:15 +00:00
|
|
|
|
|
|
|
/* Imports */
|
2000-07-30 14:25:30 +00:00
|
|
|
DumpObjHeaderSection ("Imports", H.ImportOffs, H.ImportSize);
|
2000-07-29 22:34:15 +00:00
|
|
|
|
|
|
|
/* Exports */
|
2000-07-30 14:25:30 +00:00
|
|
|
DumpObjHeaderSection ("Exports", H.ExportOffs, H.ExportSize);
|
2000-07-29 22:34:15 +00:00
|
|
|
|
|
|
|
/* Debug symbols */
|
2000-07-30 14:25:30 +00:00
|
|
|
DumpObjHeaderSection ("Debug symbols", H.DbgSymOffs, H.DbgSymSize);
|
2003-05-25 17:57:50 +00:00
|
|
|
|
|
|
|
/* Line infos */
|
|
|
|
DumpObjHeaderSection ("Line infos", H.LineInfoOffs, H.LineInfoSize);
|
|
|
|
|
|
|
|
/* String pool */
|
|
|
|
DumpObjHeaderSection ("String pool", H.StrPoolOffs, H.StrPoolSize);
|
2011-07-31 12:25:44 +00:00
|
|
|
|
|
|
|
/* Assertions */
|
|
|
|
DumpObjHeaderSection ("Assertions", H.AssertOffs, H.AssertSize);
|
|
|
|
|
|
|
|
/* Scopes */
|
|
|
|
DumpObjHeaderSection ("Scopes", H.ScopeOffs, H.ScopeSize);
|
2000-07-30 14:25:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DumpObjOptions (FILE* F, unsigned long Offset)
|
|
|
|
/* Dump the file options */
|
|
|
|
{
|
2003-05-25 17:57:50 +00:00
|
|
|
ObjHeader H;
|
|
|
|
Collection StrPool = AUTO_COLLECTION_INITIALIZER;
|
|
|
|
unsigned Count;
|
|
|
|
unsigned I;
|
2000-07-30 14:25:30 +00:00
|
|
|
|
2003-05-25 17:57:50 +00:00
|
|
|
/* Seek to the header position and read the header */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset);
|
2000-07-30 14:25:30 +00:00
|
|
|
ReadObjHeader (F, &H);
|
|
|
|
|
2003-05-25 17:57:50 +00:00
|
|
|
/* Seek to the start of the string pool and read it */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset + H.StrPoolOffs);
|
2003-05-25 17:57:50 +00:00
|
|
|
ReadStrPool (F, &StrPool);
|
|
|
|
|
2000-07-30 14:25:30 +00:00
|
|
|
/* Seek to the start of the options */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset + H.OptionOffs);
|
2000-07-30 14:25:30 +00:00
|
|
|
|
|
|
|
/* Output a header */
|
|
|
|
printf (" Options:\n");
|
|
|
|
|
|
|
|
/* Read the number of options and print it */
|
2000-08-02 13:23:06 +00:00
|
|
|
Count = ReadVar (F);
|
2000-07-30 16:15:04 +00:00
|
|
|
printf (" Count:%27u\n", Count);
|
2000-07-30 14:25:30 +00:00
|
|
|
|
|
|
|
/* Read and print all options */
|
|
|
|
for (I = 0; I < Count; ++I) {
|
|
|
|
|
2003-06-03 22:19:46 +00:00
|
|
|
const char* ArgStr;
|
2003-05-25 21:06:57 +00:00
|
|
|
unsigned ArgLen;
|
2000-07-30 14:25:30 +00:00
|
|
|
|
2003-05-25 21:06:57 +00:00
|
|
|
/* Read the type of the option and the value */
|
|
|
|
unsigned char Type = Read8 (F);
|
|
|
|
unsigned long Val = ReadVar (F);
|
2000-07-30 14:25:30 +00:00
|
|
|
|
|
|
|
/* Get the type of the argument */
|
2003-05-25 21:06:57 +00:00
|
|
|
unsigned char ArgType = Type & OPT_ARGMASK;
|
2000-07-30 14:25:30 +00:00
|
|
|
|
2003-05-25 21:06:57 +00:00
|
|
|
/* Determine which option follows */
|
|
|
|
const char* TypeDesc;
|
|
|
|
switch (Type) {
|
2000-07-30 14:25:30 +00:00
|
|
|
case OPT_COMMENT: TypeDesc = "OPT_COMMENT"; break;
|
2003-05-25 21:06:57 +00:00
|
|
|
case OPT_AUTHOR: TypeDesc = "OPT_AUTHOR"; break;
|
|
|
|
case OPT_TRANSLATOR:TypeDesc = "OPT_TRANSLATOR"; break;
|
|
|
|
case OPT_COMPILER: TypeDesc = "OPT_COMPILER"; break;
|
|
|
|
case OPT_OS: TypeDesc = "OPT_OS"; break;
|
|
|
|
case OPT_DATETIME: TypeDesc = "OPT_DATETIME"; break;
|
|
|
|
default: TypeDesc = "OPT_UNKNOWN"; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Print the header */
|
|
|
|
printf (" Index:%27u\n", I);
|
|
|
|
|
|
|
|
/* Print the data */
|
|
|
|
printf (" Type:%22s0x%02X (%s)\n", "", Type, TypeDesc);
|
|
|
|
switch (ArgType) {
|
|
|
|
|
|
|
|
case OPT_ARGSTR:
|
|
|
|
ArgStr = GetString (&StrPool, Val);
|
|
|
|
ArgLen = strlen (ArgStr);
|
2009-09-28 15:59:18 +00:00
|
|
|
printf (" Data:%*s\"%s\"\n", (int)(24-ArgLen), "", ArgStr);
|
2003-05-25 21:06:57 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OPT_ARGNUM:
|
|
|
|
printf (" Data:%26lu", Val);
|
2011-08-18 16:26:44 +00:00
|
|
|
if (Type == OPT_DATETIME) {
|
2003-05-25 21:06:57 +00:00
|
|
|
/* Print the time as a string */
|
|
|
|
printf (" (%s)", TimeToStr (Val));
|
|
|
|
}
|
2000-07-30 14:25:30 +00:00
|
|
|
printf ("\n");
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* Unknown argument type. This means that we cannot determine
|
|
|
|
* the option length, so we cannot proceed.
|
|
|
|
*/
|
|
|
|
Error ("Unknown option type: 0x%02X", Type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2003-05-25 17:57:50 +00:00
|
|
|
|
|
|
|
/* Destroy the string pool */
|
|
|
|
DestroyStrPool (&StrPool);
|
2000-07-29 22:34:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-07-30 16:15:04 +00:00
|
|
|
void DumpObjFiles (FILE* F, unsigned long Offset)
|
|
|
|
/* Dump the source files */
|
|
|
|
{
|
2003-05-25 17:57:50 +00:00
|
|
|
ObjHeader H;
|
|
|
|
Collection StrPool = AUTO_COLLECTION_INITIALIZER;
|
|
|
|
unsigned Count;
|
|
|
|
unsigned I;
|
2000-07-30 16:15:04 +00:00
|
|
|
|
2003-05-25 17:57:50 +00:00
|
|
|
/* Seek to the header position and read the header */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset);
|
2000-07-30 16:15:04 +00:00
|
|
|
ReadObjHeader (F, &H);
|
|
|
|
|
2003-05-25 17:57:50 +00:00
|
|
|
/* Seek to the start of the string pool and read it */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset + H.StrPoolOffs);
|
2003-05-25 17:57:50 +00:00
|
|
|
ReadStrPool (F, &StrPool);
|
|
|
|
|
2001-05-23 19:03:40 +00:00
|
|
|
/* Seek to the start of the source files */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset + H.FileOffs);
|
2000-07-30 16:15:04 +00:00
|
|
|
|
|
|
|
/* Output a header */
|
|
|
|
printf (" Files:\n");
|
|
|
|
|
|
|
|
/* Read the number of files and print it */
|
2000-08-02 13:23:06 +00:00
|
|
|
Count = ReadVar (F);
|
2000-07-30 16:15:04 +00:00
|
|
|
printf (" Count:%27u\n", Count);
|
|
|
|
|
2000-07-30 21:02:44 +00:00
|
|
|
/* Read and print all files */
|
2000-07-30 16:15:04 +00:00
|
|
|
for (I = 0; I < Count; ++I) {
|
|
|
|
|
|
|
|
/* Read the data for one file */
|
2003-11-08 23:20:49 +00:00
|
|
|
const char* Name = GetString (&StrPool, ReadVar (F));
|
2000-07-30 16:15:04 +00:00
|
|
|
unsigned long MTime = Read32 (F);
|
2011-01-27 16:47:45 +00:00
|
|
|
unsigned long Size = ReadVar (F);
|
2000-07-30 16:15:04 +00:00
|
|
|
unsigned Len = strlen (Name);
|
|
|
|
|
|
|
|
/* Print the header */
|
2000-07-30 19:51:33 +00:00
|
|
|
printf (" Index:%27u\n", I);
|
|
|
|
|
|
|
|
/* Print the data */
|
2009-09-28 15:59:18 +00:00
|
|
|
printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
|
2000-07-30 19:51:33 +00:00
|
|
|
printf (" Size:%26lu\n", Size);
|
|
|
|
printf (" Modification time:%13lu (%s)\n", MTime, TimeToStr (MTime));
|
|
|
|
}
|
2003-05-25 17:57:50 +00:00
|
|
|
|
|
|
|
/* Destroy the string pool */
|
|
|
|
DestroyStrPool (&StrPool);
|
2000-07-30 19:51:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DumpObjSegments (FILE* F, unsigned long Offset)
|
|
|
|
/* Dump the segments in the object file */
|
|
|
|
{
|
2003-05-25 17:57:50 +00:00
|
|
|
ObjHeader H;
|
|
|
|
Collection StrPool = AUTO_COLLECTION_INITIALIZER;
|
|
|
|
unsigned Count;
|
|
|
|
unsigned I;
|
2000-07-30 19:51:33 +00:00
|
|
|
|
2003-05-25 17:57:50 +00:00
|
|
|
/* Seek to the header position and read the header */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset);
|
2000-07-30 19:51:33 +00:00
|
|
|
ReadObjHeader (F, &H);
|
|
|
|
|
2003-05-25 17:57:50 +00:00
|
|
|
/* Seek to the start of the string pool and read it */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset + H.StrPoolOffs);
|
2003-05-25 17:57:50 +00:00
|
|
|
ReadStrPool (F, &StrPool);
|
|
|
|
|
2001-05-23 19:03:40 +00:00
|
|
|
/* Seek to the start of the segments */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset + H.SegOffs);
|
2000-07-30 19:51:33 +00:00
|
|
|
|
|
|
|
/* Output a header */
|
|
|
|
printf (" Segments:\n");
|
|
|
|
|
2000-07-30 21:02:44 +00:00
|
|
|
/* Read the number of segments and print it */
|
2000-08-02 13:23:06 +00:00
|
|
|
Count = ReadVar (F);
|
2000-07-30 19:51:33 +00:00
|
|
|
printf (" Count:%27u\n", Count);
|
|
|
|
|
2000-07-30 21:02:44 +00:00
|
|
|
/* Read and print all segments */
|
2000-07-30 19:51:33 +00:00
|
|
|
for (I = 0; I < Count; ++I) {
|
2003-05-25 21:06:57 +00:00
|
|
|
|
2000-07-30 19:51:33 +00:00
|
|
|
/* Read the data for one segments */
|
2003-06-03 22:19:46 +00:00
|
|
|
unsigned long DataSize = Read32 (F);
|
|
|
|
unsigned long NextSeg = ftell (F) + DataSize;
|
2003-08-10 16:27:35 +00:00
|
|
|
const char* Name = GetString (&StrPool, ReadVar (F));
|
2003-06-03 22:19:46 +00:00
|
|
|
unsigned Len = strlen (Name);
|
2012-01-04 22:45:26 +00:00
|
|
|
unsigned Flags = ReadVar (F);
|
2011-08-19 20:58:14 +00:00
|
|
|
unsigned long Size = ReadVar (F);
|
2011-12-27 22:56:39 +00:00
|
|
|
unsigned long Align = ReadVar (F);
|
2003-11-07 19:28:37 +00:00
|
|
|
unsigned char AddrSize = Read8 (F);
|
2003-06-03 22:19:46 +00:00
|
|
|
unsigned long FragCount = ReadVar (F);
|
2000-07-30 19:51:33 +00:00
|
|
|
|
|
|
|
/* Print the header */
|
|
|
|
printf (" Index:%27u\n", I);
|
2000-07-30 16:15:04 +00:00
|
|
|
|
|
|
|
/* Print the data */
|
2009-09-28 15:59:18 +00:00
|
|
|
printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
|
2012-01-04 22:45:26 +00:00
|
|
|
printf (" Flags:%25u\n", Flags);
|
2000-07-30 16:15:04 +00:00
|
|
|
printf (" Size:%26lu\n", Size);
|
2011-12-27 22:56:39 +00:00
|
|
|
printf (" Alignment:%21lu\n", Align);
|
2003-11-07 19:28:37 +00:00
|
|
|
printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize,
|
|
|
|
AddrSizeToStr (AddrSize));
|
2003-06-03 22:19:46 +00:00
|
|
|
printf (" Fragment count:%16lu\n", FragCount);
|
2000-07-30 16:15:04 +00:00
|
|
|
|
2003-06-03 22:19:46 +00:00
|
|
|
/* Seek to the end of the segment data (start of next) */
|
|
|
|
FileSetPos (F, NextSeg);
|
2000-07-30 16:15:04 +00:00
|
|
|
}
|
2003-05-25 17:57:50 +00:00
|
|
|
|
|
|
|
/* Destroy the string pool */
|
|
|
|
DestroyStrPool (&StrPool);
|
2000-07-30 16:15:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-07-30 21:02:44 +00:00
|
|
|
void DumpObjImports (FILE* F, unsigned long Offset)
|
|
|
|
/* Dump the imports in the object file */
|
|
|
|
{
|
2003-05-25 17:57:50 +00:00
|
|
|
ObjHeader H;
|
|
|
|
Collection StrPool = AUTO_COLLECTION_INITIALIZER;
|
|
|
|
unsigned Count;
|
|
|
|
unsigned I;
|
2000-07-30 21:02:44 +00:00
|
|
|
|
2003-05-25 17:57:50 +00:00
|
|
|
/* Seek to the header position and read the header */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset);
|
2000-07-30 21:02:44 +00:00
|
|
|
ReadObjHeader (F, &H);
|
|
|
|
|
2003-05-25 17:57:50 +00:00
|
|
|
/* Seek to the start of the string pool and read it */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset + H.StrPoolOffs);
|
2003-05-25 17:57:50 +00:00
|
|
|
ReadStrPool (F, &StrPool);
|
|
|
|
|
2001-05-23 19:03:40 +00:00
|
|
|
/* Seek to the start of the imports */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset + H.ImportOffs);
|
2000-07-30 21:02:44 +00:00
|
|
|
|
|
|
|
/* Output a header */
|
|
|
|
printf (" Imports:\n");
|
|
|
|
|
|
|
|
/* Read the number of imports and print it */
|
2000-08-02 13:23:06 +00:00
|
|
|
Count = ReadVar (F);
|
2000-07-30 21:02:44 +00:00
|
|
|
printf (" Count:%27u\n", Count);
|
|
|
|
|
|
|
|
/* Read and print all imports */
|
|
|
|
for (I = 0; I < Count; ++I) {
|
|
|
|
|
|
|
|
/* Read the data for one import */
|
2003-11-28 22:12:14 +00:00
|
|
|
unsigned char AddrSize = Read8 (F);
|
|
|
|
const char* Name = GetString (&StrPool, ReadVar (F));
|
|
|
|
unsigned Len = strlen (Name);
|
2011-01-27 16:47:45 +00:00
|
|
|
|
2011-08-18 16:26:44 +00:00
|
|
|
/* Skip both line info lists */
|
2011-08-19 20:58:14 +00:00
|
|
|
SkipLineInfoList (F);
|
2011-01-27 16:47:45 +00:00
|
|
|
SkipLineInfoList (F);
|
2000-07-30 21:02:44 +00:00
|
|
|
|
|
|
|
/* Print the header */
|
|
|
|
printf (" Index:%27u\n", I);
|
|
|
|
|
|
|
|
/* Print the data */
|
2003-11-28 22:12:14 +00:00
|
|
|
printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize,
|
|
|
|
AddrSizeToStr (AddrSize));
|
2009-09-28 15:59:18 +00:00
|
|
|
printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
|
2000-07-30 21:02:44 +00:00
|
|
|
}
|
2003-05-25 17:57:50 +00:00
|
|
|
|
|
|
|
/* Destroy the string pool */
|
|
|
|
DestroyStrPool (&StrPool);
|
2000-07-30 21:02:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DumpObjExports (FILE* F, unsigned long Offset)
|
|
|
|
/* Dump the exports in the object file */
|
|
|
|
{
|
2003-05-25 17:57:50 +00:00
|
|
|
ObjHeader H;
|
|
|
|
Collection StrPool = AUTO_COLLECTION_INITIALIZER;
|
|
|
|
unsigned Count;
|
|
|
|
unsigned I;
|
2000-07-30 21:02:44 +00:00
|
|
|
|
2003-05-25 17:57:50 +00:00
|
|
|
/* Seek to the header position and read the header */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset);
|
2000-07-30 21:02:44 +00:00
|
|
|
ReadObjHeader (F, &H);
|
|
|
|
|
2003-05-25 17:57:50 +00:00
|
|
|
/* Seek to the start of the string pool and read it */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset + H.StrPoolOffs);
|
2003-05-25 17:57:50 +00:00
|
|
|
ReadStrPool (F, &StrPool);
|
|
|
|
|
2001-05-23 19:03:40 +00:00
|
|
|
/* Seek to the start of the exports */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset + H.ExportOffs);
|
2000-07-30 21:02:44 +00:00
|
|
|
|
|
|
|
/* Output a header */
|
|
|
|
printf (" Exports:\n");
|
|
|
|
|
|
|
|
/* Read the number of exports and print it */
|
2000-08-02 13:23:06 +00:00
|
|
|
Count = ReadVar (F);
|
2000-07-30 21:02:44 +00:00
|
|
|
printf (" Count:%27u\n", Count);
|
|
|
|
|
|
|
|
/* Read and print all exports */
|
|
|
|
for (I = 0; I < Count; ++I) {
|
|
|
|
|
2000-07-31 22:21:37 +00:00
|
|
|
unsigned long Value = 0;
|
2011-06-13 18:43:50 +00:00
|
|
|
unsigned long Size = 0;
|
|
|
|
unsigned char ConDes[CD_TYPE_COUNT];
|
2003-05-25 17:57:50 +00:00
|
|
|
const char* Name;
|
2000-11-20 15:22:57 +00:00
|
|
|
unsigned Len;
|
|
|
|
|
2000-07-30 21:02:44 +00:00
|
|
|
|
|
|
|
/* Read the data for one export */
|
2010-08-17 21:04:28 +00:00
|
|
|
unsigned Type = ReadVar (F);
|
2003-11-28 22:12:14 +00:00
|
|
|
unsigned char AddrSize = Read8 (F);
|
2010-08-17 20:47:27 +00:00
|
|
|
ReadData (F, ConDes, SYM_GET_CONDES_COUNT (Type));
|
2003-05-25 17:57:50 +00:00
|
|
|
Name = GetString (&StrPool, ReadVar (F));
|
2000-11-20 15:22:57 +00:00
|
|
|
Len = strlen (Name);
|
2011-06-13 18:43:50 +00:00
|
|
|
if (SYM_IS_CONST (Type)) {
|
2000-07-31 22:21:37 +00:00
|
|
|
Value = Read32 (F);
|
2011-06-13 18:43:50 +00:00
|
|
|
} else {
|
|
|
|
SkipExpr (F);
|
2000-07-30 21:02:44 +00:00
|
|
|
}
|
2011-06-13 18:43:50 +00:00
|
|
|
if (SYM_HAS_SIZE (Type)) {
|
|
|
|
Size = ReadVar (F);
|
|
|
|
}
|
2011-01-27 16:47:45 +00:00
|
|
|
|
2011-08-18 16:26:44 +00:00
|
|
|
/* Skip both line infos lists */
|
2011-08-19 20:58:14 +00:00
|
|
|
SkipLineInfoList (F);
|
2011-01-27 16:47:45 +00:00
|
|
|
SkipLineInfoList (F);
|
2000-07-30 21:02:44 +00:00
|
|
|
|
|
|
|
/* Print the header */
|
|
|
|
printf (" Index:%27u\n", I);
|
|
|
|
|
|
|
|
/* Print the data */
|
2000-11-20 15:22:57 +00:00
|
|
|
printf (" Type:%22s0x%02X (%s)\n", "", Type, GetExportFlags (Type, ConDes));
|
2003-11-28 22:12:14 +00:00
|
|
|
printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize,
|
|
|
|
AddrSizeToStr (AddrSize));
|
2009-09-28 15:59:18 +00:00
|
|
|
printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
|
2011-06-13 18:43:50 +00:00
|
|
|
if (SYM_IS_CONST (Type)) {
|
|
|
|
printf (" Value:%15s0x%08lX (%lu)\n", "", Value, Value);
|
|
|
|
}
|
|
|
|
if (SYM_HAS_SIZE (Type)) {
|
|
|
|
printf (" Size:%16s0x%04lX (%lu)\n", "", Size, Size);
|
2000-07-31 22:21:37 +00:00
|
|
|
}
|
|
|
|
}
|
2003-05-25 17:57:50 +00:00
|
|
|
|
|
|
|
/* Destroy the string pool */
|
|
|
|
DestroyStrPool (&StrPool);
|
2000-07-31 22:21:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DumpObjDbgSyms (FILE* F, unsigned long Offset)
|
|
|
|
/* Dump the debug symbols from an object file */
|
|
|
|
{
|
2003-05-25 17:57:50 +00:00
|
|
|
ObjHeader H;
|
|
|
|
Collection StrPool = AUTO_COLLECTION_INITIALIZER;
|
|
|
|
unsigned Count;
|
|
|
|
unsigned I;
|
2000-07-31 22:21:37 +00:00
|
|
|
|
2003-05-25 17:57:50 +00:00
|
|
|
/* Seek to the header position and read the header */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset);
|
2000-07-31 22:21:37 +00:00
|
|
|
ReadObjHeader (F, &H);
|
|
|
|
|
2003-05-25 17:57:50 +00:00
|
|
|
/* Seek to the start of the string pool and read it */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset + H.StrPoolOffs);
|
2003-05-25 17:57:50 +00:00
|
|
|
ReadStrPool (F, &StrPool);
|
|
|
|
|
2001-05-23 19:03:40 +00:00
|
|
|
/* Seek to the start of the debug syms */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset + H.DbgSymOffs);
|
2000-07-31 22:21:37 +00:00
|
|
|
|
|
|
|
/* Output a header */
|
|
|
|
printf (" Debug symbols:\n");
|
|
|
|
|
|
|
|
/* Check if the object file was compiled with debug info */
|
|
|
|
if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) {
|
|
|
|
/* Print that there no debug symbols and bail out */
|
|
|
|
printf (" Count:%27u\n", 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read the number of exports and print it */
|
2000-08-02 13:23:06 +00:00
|
|
|
Count = ReadVar (F);
|
2000-07-31 22:21:37 +00:00
|
|
|
printf (" Count:%27u\n", Count);
|
|
|
|
|
|
|
|
/* Read and print all debug symbols */
|
|
|
|
for (I = 0; I < Count; ++I) {
|
|
|
|
|
2011-06-13 18:43:50 +00:00
|
|
|
unsigned long Value = 0;
|
|
|
|
unsigned long Size = 0;
|
2011-08-16 12:53:48 +00:00
|
|
|
unsigned ImportId = 0;
|
|
|
|
unsigned ExportId = 0;
|
2000-07-31 22:21:37 +00:00
|
|
|
|
|
|
|
/* Read the data for one symbol */
|
2010-08-17 21:04:28 +00:00
|
|
|
unsigned Type = ReadVar (F);
|
2003-11-28 22:12:14 +00:00
|
|
|
unsigned char AddrSize = Read8 (F);
|
2011-07-31 13:28:54 +00:00
|
|
|
unsigned long Owner = ReadVar (F);
|
2003-11-28 22:12:14 +00:00
|
|
|
const char* Name = GetString (&StrPool, ReadVar (F));
|
|
|
|
unsigned Len = strlen (Name);
|
2011-06-13 18:43:50 +00:00
|
|
|
if (SYM_IS_CONST (Type)) {
|
2000-07-31 22:21:37 +00:00
|
|
|
Value = Read32 (F);
|
2011-06-13 18:43:50 +00:00
|
|
|
} else {
|
|
|
|
SkipExpr (F);
|
2000-07-31 22:21:37 +00:00
|
|
|
}
|
2011-06-13 18:43:50 +00:00
|
|
|
if (SYM_HAS_SIZE (Type)) {
|
|
|
|
Size = ReadVar (F);
|
|
|
|
}
|
2011-08-16 12:53:48 +00:00
|
|
|
if (SYM_IS_IMPORT (Type)) {
|
|
|
|
ImportId = ReadVar (F);
|
|
|
|
}
|
|
|
|
if (SYM_IS_EXPORT (Type)) {
|
|
|
|
ExportId = ReadVar (F);
|
|
|
|
}
|
2011-01-27 16:47:45 +00:00
|
|
|
|
2011-08-18 16:26:44 +00:00
|
|
|
/* Skip both line info lists */
|
2011-08-19 20:58:14 +00:00
|
|
|
SkipLineInfoList (F);
|
2011-01-27 16:47:45 +00:00
|
|
|
SkipLineInfoList (F);
|
2000-07-31 22:21:37 +00:00
|
|
|
|
|
|
|
/* Print the header */
|
|
|
|
printf (" Index:%27u\n", I);
|
|
|
|
|
|
|
|
/* Print the data */
|
2003-11-28 22:12:14 +00:00
|
|
|
printf (" Type:%22s0x%02X (%s)\n", "", Type, GetExportFlags (Type, 0));
|
|
|
|
printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize,
|
|
|
|
AddrSizeToStr (AddrSize));
|
2011-07-31 13:28:54 +00:00
|
|
|
printf (" Owner:%25lu\n", Owner);
|
2009-09-28 15:59:18 +00:00
|
|
|
printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
|
2011-06-13 18:43:50 +00:00
|
|
|
if (SYM_IS_CONST (Type)) {
|
2000-07-31 22:21:37 +00:00
|
|
|
printf (" Value:%15s0x%08lX (%lu)\n", "", Value, Value);
|
|
|
|
}
|
2011-06-13 18:43:50 +00:00
|
|
|
if (SYM_HAS_SIZE (Type)) {
|
2011-07-31 15:37:51 +00:00
|
|
|
printf (" Size:%20s0x%04lX (%lu)\n", "", Size, Size);
|
2011-06-13 18:43:50 +00:00
|
|
|
}
|
2011-08-16 12:53:48 +00:00
|
|
|
if (SYM_IS_IMPORT (Type)) {
|
|
|
|
printf (" Import:%24u\n", ImportId);
|
|
|
|
}
|
|
|
|
if (SYM_IS_EXPORT (Type)) {
|
|
|
|
printf (" Export:%24u\n", ExportId);
|
|
|
|
}
|
2000-07-30 21:02:44 +00:00
|
|
|
}
|
2003-05-25 17:57:50 +00:00
|
|
|
|
|
|
|
/* Destroy the string pool */
|
|
|
|
DestroyStrPool (&StrPool);
|
2000-07-30 21:02:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2001-05-23 19:03:40 +00:00
|
|
|
void DumpObjLineInfo (FILE* F, unsigned long Offset)
|
|
|
|
/* Dump the line info from an object file */
|
|
|
|
{
|
2003-05-25 17:57:50 +00:00
|
|
|
ObjHeader H;
|
|
|
|
Collection StrPool = AUTO_COLLECTION_INITIALIZER;
|
|
|
|
unsigned Count;
|
|
|
|
unsigned I;
|
2001-05-23 19:03:40 +00:00
|
|
|
|
2003-05-25 17:57:50 +00:00
|
|
|
/* Seek to the header position and read the header */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset);
|
2001-05-23 19:03:40 +00:00
|
|
|
ReadObjHeader (F, &H);
|
|
|
|
|
2003-05-25 17:57:50 +00:00
|
|
|
/* Seek to the start of the string pool and read it */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset + H.StrPoolOffs);
|
2003-05-25 17:57:50 +00:00
|
|
|
ReadStrPool (F, &StrPool);
|
|
|
|
|
2001-05-23 19:03:40 +00:00
|
|
|
/* Seek to the start of line infos */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset + H.LineInfoOffs);
|
2001-05-23 19:03:40 +00:00
|
|
|
|
|
|
|
/* Output a header */
|
|
|
|
printf (" Line info:\n");
|
|
|
|
|
|
|
|
/* Check if the object file was compiled with debug info */
|
|
|
|
if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) {
|
|
|
|
/* Print that there no line infos and bail out */
|
|
|
|
printf (" Count:%27u\n", 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read the number of line infos and print it */
|
|
|
|
Count = ReadVar (F);
|
|
|
|
printf (" Count:%27u\n", Count);
|
|
|
|
|
|
|
|
/* Read and print all line infos */
|
|
|
|
for (I = 0; I < Count; ++I) {
|
|
|
|
|
2011-01-27 16:47:45 +00:00
|
|
|
FilePos Pos;
|
2011-08-21 19:08:23 +00:00
|
|
|
unsigned Type;
|
2011-01-29 22:16:03 +00:00
|
|
|
|
|
|
|
/* File position of line info */
|
2001-05-23 19:03:40 +00:00
|
|
|
ReadFilePos (F, &Pos);
|
|
|
|
|
2011-08-21 19:08:23 +00:00
|
|
|
/* Type of line info */
|
|
|
|
Type = ReadVar (F);
|
|
|
|
|
|
|
|
/* Skip the spans */
|
|
|
|
SkipSpanList (F);
|
|
|
|
|
2001-05-23 19:03:40 +00:00
|
|
|
/* Print the header */
|
|
|
|
printf (" Index:%27u\n", I);
|
|
|
|
|
|
|
|
/* Print the data */
|
2011-01-29 22:16:03 +00:00
|
|
|
printf (" Type:%26u\n", LI_GET_TYPE (Type));
|
|
|
|
printf (" Count:%25u\n", LI_GET_COUNT (Type));
|
2011-08-15 16:09:34 +00:00
|
|
|
printf (" Line:%26u\n", Pos.Line);
|
2001-05-23 19:03:40 +00:00
|
|
|
printf (" Col:%27u\n", Pos.Col);
|
|
|
|
printf (" Name:%26u\n", Pos.Name);
|
|
|
|
}
|
2003-05-25 17:57:50 +00:00
|
|
|
|
|
|
|
/* Destroy the string pool */
|
|
|
|
DestroyStrPool (&StrPool);
|
2001-05-23 19:03:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-07-31 12:25:44 +00:00
|
|
|
void DumpObjScopes (FILE* F, unsigned long Offset)
|
|
|
|
/* Dump the scopes from an object file */
|
|
|
|
{
|
|
|
|
ObjHeader H;
|
|
|
|
Collection StrPool = AUTO_COLLECTION_INITIALIZER;
|
|
|
|
unsigned Count;
|
|
|
|
unsigned I;
|
|
|
|
|
|
|
|
/* Seek to the header position and read the header */
|
|
|
|
FileSetPos (F, Offset);
|
|
|
|
ReadObjHeader (F, &H);
|
|
|
|
|
|
|
|
/* Seek to the start of the string pool and read it */
|
|
|
|
FileSetPos (F, Offset + H.StrPoolOffs);
|
|
|
|
ReadStrPool (F, &StrPool);
|
|
|
|
|
|
|
|
/* Seek to the start of scopes */
|
|
|
|
FileSetPos (F, Offset + H.ScopeOffs);
|
|
|
|
|
|
|
|
/* Output a header */
|
|
|
|
printf (" Scopes:\n");
|
|
|
|
|
|
|
|
/* Check if the object file was compiled with debug info */
|
|
|
|
if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) {
|
|
|
|
/* Print that there no scopes and bail out */
|
|
|
|
printf (" Count:%27u\n", 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read the number of scopes and print it */
|
|
|
|
Count = ReadVar (F);
|
|
|
|
printf (" Count:%27u\n", Count);
|
|
|
|
|
|
|
|
/* Read and print all scopes */
|
|
|
|
for (I = 0; I < Count; ++I) {
|
|
|
|
|
|
|
|
const char* Name;
|
|
|
|
unsigned Len;
|
|
|
|
|
2011-07-31 15:37:51 +00:00
|
|
|
/* Read the data */
|
|
|
|
unsigned ParentId = ReadVar (F);
|
|
|
|
unsigned LexicalLevel = ReadVar (F);
|
|
|
|
unsigned Flags = ReadVar (F);
|
|
|
|
const char* ScopeType = GetScopeType (ReadVar (F));
|
|
|
|
|
2011-07-31 12:25:44 +00:00
|
|
|
/* Print the header */
|
|
|
|
printf (" Index:%27u\n", I);
|
|
|
|
|
2011-07-31 14:01:27 +00:00
|
|
|
/* Print the data */
|
2011-07-31 15:37:51 +00:00
|
|
|
printf (" Parent id:%21u\n", ParentId);
|
|
|
|
printf (" Lexical level:%17u\n", LexicalLevel);
|
|
|
|
printf (" Flags:%21s0x%02X\n", "", Flags);
|
|
|
|
printf (" Type:%26s\n", ScopeType);
|
2011-07-31 12:25:44 +00:00
|
|
|
|
|
|
|
/* Resolve and print the name */
|
|
|
|
Name = GetString (&StrPool, ReadVar (F));
|
|
|
|
Len = strlen (Name);
|
|
|
|
printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
|
|
|
|
|
2011-07-31 15:37:51 +00:00
|
|
|
/* Size */
|
|
|
|
if (SCOPE_HAS_SIZE (Flags)) {
|
|
|
|
unsigned long Size = ReadVar (F);
|
|
|
|
printf (" Size:%20s0x%04lX (%lu)\n", "", Size, Size);
|
|
|
|
}
|
|
|
|
|
2011-08-07 18:47:38 +00:00
|
|
|
/* Label */
|
|
|
|
if (SCOPE_HAS_LABEL (Flags)) {
|
|
|
|
unsigned LabelId = ReadVar (F);
|
|
|
|
printf (" Label id:%22u\n", LabelId);
|
|
|
|
}
|
|
|
|
|
2011-08-21 19:08:23 +00:00
|
|
|
/* Skip the spans */
|
|
|
|
SkipSpanList (F);
|
2011-07-31 12:25:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Destroy the string pool */
|
|
|
|
DestroyStrPool (&StrPool);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2002-11-25 17:32:16 +00:00
|
|
|
void DumpObjSegSize (FILE* F, unsigned long Offset)
|
|
|
|
/* Dump the sizes of the segment in the object file */
|
|
|
|
{
|
2003-05-25 17:57:50 +00:00
|
|
|
ObjHeader H;
|
|
|
|
Collection StrPool = AUTO_COLLECTION_INITIALIZER;
|
|
|
|
unsigned Count;
|
2002-11-25 17:32:16 +00:00
|
|
|
|
2003-05-25 17:57:50 +00:00
|
|
|
/* Seek to the header position and read the header */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset);
|
2002-11-25 17:32:16 +00:00
|
|
|
ReadObjHeader (F, &H);
|
|
|
|
|
2003-05-25 17:57:50 +00:00
|
|
|
/* Seek to the start of the string pool and read it */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset + H.StrPoolOffs);
|
2003-05-25 17:57:50 +00:00
|
|
|
ReadStrPool (F, &StrPool);
|
|
|
|
|
2002-11-25 17:32:16 +00:00
|
|
|
/* Seek to the start of the segments */
|
2003-06-03 22:19:46 +00:00
|
|
|
FileSetPos (F, Offset + H.SegOffs);
|
2002-11-25 17:32:16 +00:00
|
|
|
|
|
|
|
/* Output a header */
|
|
|
|
printf (" Segment sizes:\n");
|
|
|
|
|
|
|
|
/* Read the number of segments */
|
|
|
|
Count = ReadVar (F);
|
|
|
|
|
|
|
|
/* Read and print the sizes of all segments */
|
|
|
|
while (Count--) {
|
|
|
|
|
2012-06-03 13:39:28 +00:00
|
|
|
/* Read the data for one segment */
|
2003-06-03 22:19:46 +00:00
|
|
|
unsigned long DataSize = Read32 (F);
|
|
|
|
unsigned long NextSeg = ftell (F) + DataSize;
|
2003-08-10 16:27:35 +00:00
|
|
|
const char* Name = GetString (&StrPool, ReadVar (F));
|
2003-06-03 22:19:46 +00:00
|
|
|
unsigned Len = strlen (Name);
|
2012-06-03 13:39:28 +00:00
|
|
|
(void) ReadVar (F); /* Skip segment flags */
|
2011-08-19 20:58:14 +00:00
|
|
|
unsigned long Size = ReadVar (F);
|
2002-11-25 17:32:16 +00:00
|
|
|
|
2003-06-03 22:19:46 +00:00
|
|
|
/* Skip alignment, type and fragment count */
|
2011-12-27 22:56:39 +00:00
|
|
|
(void) ReadVar (F);
|
2002-11-25 17:32:16 +00:00
|
|
|
(void) Read8 (F);
|
2003-06-03 22:19:46 +00:00
|
|
|
(void) ReadVar (F);
|
2002-11-25 17:32:16 +00:00
|
|
|
|
|
|
|
/* Print the size for this segment */
|
2009-09-28 15:59:18 +00:00
|
|
|
printf (" %s:%*s%6lu\n", Name, (int)(24-Len), "", Size);
|
2002-11-25 17:32:16 +00:00
|
|
|
|
2003-06-03 22:19:46 +00:00
|
|
|
/* Seek to the end of the segment data (start of next) */
|
|
|
|
FileSetPos (F, NextSeg);
|
2003-08-10 16:27:35 +00:00
|
|
|
}
|
2003-05-25 17:57:50 +00:00
|
|
|
|
|
|
|
/* Destroy the string pool */
|
|
|
|
DestroyStrPool (&StrPool);
|
2002-11-25 17:32:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-08-02 13:23:06 +00:00
|
|
|
|
2011-08-19 20:58:14 +00:00
|
|
|
|