The MS-DOS Encyclopedia: Appendix N: An Object Module Dump Utility

Archive of outdated Microsoft articles and reference materials


The MS-DOS Encyclopedia

Appendix N: An Object Module Dump Utility

     The program OBJDUMP.C displays the contents of an object file as
     individual object records. It can be used to study the structure of
     object modules as well as to verify the output of a language
     translator. The program recognizes all of the object record types
     discussed in PROGRAMMING IN THE MS-DOS ENVIRONMENT: PROGRAMMING TOOLS:
     Object Modules.

     OBJDUMP.C should be executed with the following syntax:

     OBJDUMP filename

     where filename is a complete filename specification. For example, to
     dump the contents of the object file MYPROG.OBJ, the user would type

     C>OBJDUMP MYPROG.OBJ  <Enter>

     The following is a typical object record as displayed by OBJDUMP:

Record 9:  96h LNAMES
96 002Eh 00 06 44 47 52 4F 55 50 05 5F 54 45 58 54 04 43   ..DGROUP._TEXT.C
         4F 44 45 05 5F 44 41 54 41 04 44 41 54 41 05 43   ODE._DATA.DATA.C
         4F 4E 53 54 04 5F 42 53 53 03 42 53 53 3F         ONST._BSS.BSS?

     This sample LNAMES record defines a null name and eight names used in
     subsequent SEGDEF and GRPDEF records. The first 3 bytes of the record
     (the identifying byte and the 2-byte record length) are displayed to
     the left of the hexadecimal and ASCII listings of the contents of the
     record.

/*************************************************************************
*                                                                         *
* OBJDUMP.C __ display contents of an object file                         *
*                                                                         *
*                                                                         *
*     Compile:  msc objdump;   (Microsoft C version 4.0 or later)         *
*     Link:     link objdump;                                             *
*     Execute:  objdump <filename>                                        *
*                                                                         *
**************************************************************************/

#include        <fcntl.h>

#define         TRUE    1
#define         FALSE   0
main( argc, argv )
int        argc;
char       **argv;
{
        unsigned char        CurrentByte;
        int    ObjFileHandle;
        int    CurrentLineLength;               /* length of output line */
        int    ObjRecordNumber = 0;
        int    ObjRecordLength;
        int    ObjRecordOffset = 0; /* offset into current object record */
        char   ASCIIEquiv[17];
        char   FormatString[24];
        char   *ObjRecordName();
        char   *memset();


/* open the object file */

        ObjFileHandle = open( argv[1],O_BINARY );

        if( ObjFileHandle == -1 )
        {
          printf( "\nCan't open object file\n" );
          exit( 1 );
        }

/* process the object file character by character */

        while( read( ObjFileHandle, &CurrentByte, 1 ) )
        {
         switch( ObjRecordOffset ) /* action depends on offset to record */
         {
           case(0):                           /* start of object record */
             printf( "\n\nRecord %d:  %02Xh %s",
              ++ObjRecordNumber, CurrentByte, ObjRecordName(CurrentByte) );
             printf( "\n%02X ", CurrentByte );
             ++ObjRecordOffset;
             break;

            case(1):                       /* first byte of length field */
             ObjRecordLength = CurrentByte;
             ++ObjRecordOffset;
             break;

            case(2):                      /* second byte of length field */
             ObjRecordLength += CurrentByte << 8; /* compute rec length */
             printf( "%04Xh ", ObjRecordLength );        /* show length */
             CurrentLineLength = 0;
             memset( ASCIIEquiv, '\0' , 17 );       /* zero this string */
             ++ObjRecordOffset;
             break;
            default:                  * remaining bytes in object record */
              printf( "%02X ", CurrentByte );                     /* hex */

              if( CurrentByte < 0x20 || CurrentByte > 0x7F )    /* ASCII */
               CurrentByte = '.';
              ASCIIEquiv[CurrentLineLength++] = CurrentByte;

              if( CurrentLineLength == 16 ||/* if end of output line ... */
                 ObjRecordOffset == ObjRecordLength+2 )
              {                                        /* ... display it */
                sprintf( FormatString, "%%%ds%%s\n         ",
                  3*(16-CurrentLineLength)+2 );
                printf( FormatString, " ", ASCIIEquiv );
                memset( ASCIIEquiv, '\0', 17 );
                CurrentLineLength = 0;
              }

              if( ++ObjRecordOffset == ObjRecordLength+3 )/* if done ... */
                ObjRecordOffset = 0;       /* ... process another record */
              break;
          }
        }

        if( CurrentLineLength ) /* display remainder of last output line */
          printf( "  %s", ASCIIEquiv );

        close( ObjFileHandle );

        printf( "\n%d object records\n", ObjRecordNumber );

        return( 0 );
}


char *ObjRecordName( n )                    /* return object record name */
int        n;                                         /* n = record type */
{
        int        i;

        static        struct
        {
          int        RecordNumber;
          char        *RecordName;
        }                RecordStruct[] =
                        {
                          0x80,"THEADR",
                          0x88,"COMENT",
                          0x8A,"MODEND",
                          0x8C,"EXTDEF",
                          0x8E,"TYPDEF",
                          0x90,"PUBDEF",
                          0x94,"LINNUM",
                          0x96,"LNAMES",
                          0x98,"SEGDEF",
                          0x9A,"GRPDEF",
                          0x9C,"FIXUPP",
                          0xA0,"LEDATA",
                          0xA2,"LIDATA",
                          0xB0,"COMDEF",
                          0x00,"******"
                        };

    int   RecordTableSize = sizeof(RecordStruct)/sizeof(RecordStruct[0]);


        for( i=0; i<RecordTableSize-1; i++ )      /* scan table for name */
          if ( RecordStruct[i].RecordNumber == n )
            break;

        return( RecordStruct[i].RecordName );
}


                                                           Richard Wilton

Return to The MS-DOS Encyclopedia: Contents