mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
519 lines
11 KiB
519 lines
11 KiB
/***********************************************************************
|
|
* Microsoft (R) Debugging Information Dumper
|
|
*
|
|
* Copyright (C) Microsoft Corp 1987-1995. All rights reserved.
|
|
*
|
|
* File: dumpsym6.c
|
|
*
|
|
* File Comments:
|
|
*
|
|
***********************************************************************/
|
|
|
|
#include <assert.h>
|
|
#include <io.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "cvdef.h"
|
|
#include "cvinfo.h"
|
|
#include "cvexefmt.h"
|
|
#include "cvdump.h" // Various definitions
|
|
#include "debsym.h" // SYMBOLS definitions
|
|
#include "symrec.h" // SYMBOLS definitions
|
|
|
|
|
|
LOCAL void C6SymError(void);
|
|
LOCAL void C6BlockSym(void);
|
|
LOCAL void C6ProcSym(void);
|
|
LOCAL void C6LabSym(void);
|
|
LOCAL void C6WithSym(void);
|
|
LOCAL void C6EntrySym(void);
|
|
LOCAL void C6SkipSym(void);
|
|
LOCAL void C6ChangeModel(void);
|
|
LOCAL void C6CodeSegSym(void);
|
|
LOCAL void C6EndSym(void);
|
|
LOCAL void C6BpSym(void);
|
|
LOCAL void C6RegSym(void);
|
|
LOCAL void C6ConSym(void);
|
|
LOCAL void C6CobolTypeDefSym(void);
|
|
LOCAL void C6LocalSym(void);
|
|
LOCAL void C6ChangeModelSym(void);
|
|
|
|
|
|
extern int iModToList; // The module number to list
|
|
extern long cbRec; // # bytes left in record
|
|
extern WORD rect; // Type of symbol record
|
|
extern WORD Gets (); // Get a byte of input
|
|
extern WORD WGets (); // Get a word of input
|
|
extern ulong LGets (); // Get a long word of input
|
|
|
|
extern char f386;
|
|
|
|
int cIndent = 0;
|
|
#define GetOffset() (f386 ? LGets () : (long) WGets ())
|
|
|
|
typedef struct {
|
|
uchar tsym;
|
|
void (*pfcn) (void);
|
|
} symfcn;
|
|
|
|
const symfcn SymFcnC6[] =
|
|
{
|
|
{ S_BLOCK, C6BlockSym },
|
|
{ S_PROC, C6ProcSym },
|
|
{ S_END, C6EndSym },
|
|
{ S_BPREL, C6BpSym },
|
|
{ S_LOCAL, C6LocalSym },
|
|
{ S_LABEL, C6LabSym },
|
|
{ S_WITH, C6WithSym },
|
|
{ S_REG, C6RegSym },
|
|
{ S_CONST, C6ConSym },
|
|
{ S_ENTRY, C6EntrySym },
|
|
{ S_NOOP, C6SkipSym },
|
|
{ S_CODSEG, C6CodeSegSym },
|
|
{ S_TYPEDEF, C6CobolTypeDefSym },
|
|
{ S_CHGMODEL, C6ChangeModelSym },
|
|
};
|
|
|
|
#define SYMCNT (sizeof SymFcnC6 / sizeof (SymFcnC6[0]))
|
|
|
|
|
|
void C6SymError (void)
|
|
{
|
|
Fatal ("Illegal symbol type found\n");
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
*
|
|
* Display SYMBOLS section.
|
|
*
|
|
*/
|
|
|
|
void DumpSym (void)
|
|
{
|
|
PMOD pMod;
|
|
ulong cbSym;
|
|
ulong ulSignature;
|
|
uchar name[256];
|
|
|
|
printf ("\n\n*** SYMBOLS section\n");
|
|
for (pMod = ModList; pMod != NULL; pMod = pMod->next) {
|
|
if (((cbSym = pMod->SymbolSize) != 0) &&
|
|
((iModToList == 0) || ((ushort)iModToList == pMod->iMod))) {
|
|
_lseek(exefile, lfoBase + pMod->SymbolsAddr, SEEK_SET);
|
|
cIndent = 0;
|
|
strcpy (name, pMod->ModName);
|
|
printf ("%s\n", name);
|
|
cbRec = 4;
|
|
ulSignature = LGets ();
|
|
switch( ulSignature ){
|
|
case 1L: //M00 - 1L should not be hardcoded
|
|
// Dump C7 debug info
|
|
cbSym -= sizeof (ulong); // Subtract size of signature
|
|
DumpModSymC7 (cbSym);
|
|
break;
|
|
|
|
default:
|
|
// Symbols are in C6 format
|
|
// M00 - seek could be eliminated for speed improvement
|
|
// Re-seek because first four bytes are not signature
|
|
_lseek(exefile, lfoBase + pMod->SymbolsAddr, SEEK_SET);
|
|
DumpModSymC6 (cbSym);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
putchar ('\n');
|
|
}
|
|
|
|
|
|
void DumpModSymC6(ulong cbSym)
|
|
{
|
|
char sb[255]; // String buffer
|
|
WORD cbName; // Length of string
|
|
ushort i;
|
|
|
|
while (cbSym > 0) {
|
|
// Get record length
|
|
cbRec = 1;
|
|
cbRec = Gets ();
|
|
cbSym -= cbRec + 1;
|
|
rect = Gets ();
|
|
f386 = (char) (rect & 0x80); // check for 32-bit sym
|
|
rect &= ~0x80;
|
|
for (i = 0; i < SYMCNT; i++) {
|
|
if (SymFcnC6[i].tsym == (uchar) rect) {
|
|
SymFcnC6[i].pfcn ();
|
|
break;
|
|
}
|
|
}
|
|
if( i == SYMCNT ){
|
|
// Couldn't find symbol record type in the table
|
|
Fatal("Invalid symbol record type");
|
|
}
|
|
if (cbRec > 0) {
|
|
// display symbol name
|
|
cbName = Gets ();
|
|
GetBytes (sb, (size_t) cbName);
|
|
sb[cbName] = '\0';
|
|
printf ("\t%s", sb);
|
|
}
|
|
putchar ('\n');
|
|
if (cbRec) {
|
|
Fatal("Invalid file");
|
|
}
|
|
putchar ('\n');
|
|
}
|
|
}
|
|
|
|
|
|
LOCAL void PrtIndent (void)
|
|
{
|
|
int n;
|
|
|
|
for (n = cIndent; n > 0; putchar (' '), n--);
|
|
}
|
|
|
|
|
|
LOCAL void C6EndSym (void)
|
|
{
|
|
cIndent--;
|
|
PrtIndent ();
|
|
printf ("End");
|
|
}
|
|
|
|
|
|
LOCAL void C6BpSym (void)
|
|
{
|
|
BPSYMTYPE bp;
|
|
|
|
bp.off = GetOffset ();
|
|
bp.typind = WGets ();
|
|
PrtIndent ();
|
|
if (f386) {
|
|
printf ("BP-relative:\toff = %08lx, type %8s", bp.off, SzNameType(bp.typind));
|
|
}
|
|
else {
|
|
printf ("BP-relative:\toff = %04lx, type %8s", bp.off, SzNameType(bp.typind));
|
|
}
|
|
}
|
|
|
|
|
|
LOCAL void C6LocalSym (void)
|
|
{
|
|
LOCSYMTYPE loc;
|
|
|
|
loc.off = GetOffset ();
|
|
loc.seg = WGets ();
|
|
loc.typind = WGets ();
|
|
PrtIndent ();
|
|
printf ( "Local:\tseg:off = %04x:%0*lx",
|
|
loc.seg,
|
|
f386? 8 : 4,
|
|
loc.off
|
|
);
|
|
printf (", type %8s, ", SzNameType(loc.typind));
|
|
}
|
|
|
|
|
|
const char * const namereg[] =
|
|
{
|
|
"AL", // 0
|
|
"CL", // 1
|
|
"DL", // 2
|
|
"BL", // 3
|
|
"AH", // 4
|
|
"CH", // 5
|
|
"DH", // 6
|
|
"BH", // 7
|
|
"AX", // 8
|
|
"CX", // 9
|
|
"DX", // 10
|
|
"BX", // 11
|
|
"SP", // 12
|
|
"BP", // 13
|
|
"SI", // 14
|
|
"DI", // 15
|
|
"EAX", // 16
|
|
"ECX", // 17
|
|
"EDX", // 18
|
|
"EBX", // 19
|
|
"ESP", // 20
|
|
"EBP", // 21
|
|
"ESI", // 22
|
|
"EDI", // 23
|
|
"ES", // 24
|
|
"CS", // 25
|
|
"SS", // 26
|
|
"DS", // 27
|
|
"FS", // 28
|
|
"GS", // 29
|
|
"???", // 30
|
|
"???", // 31
|
|
"DX:AX", // 32
|
|
"ES:BX", // 33
|
|
"IP", // 34
|
|
"FLAGS", // 35
|
|
|
|
};
|
|
|
|
const char * const name87[] =
|
|
{
|
|
"ST (0)",
|
|
"ST (1)",
|
|
"ST (2)",
|
|
"ST (3)",
|
|
"ST (4)",
|
|
"ST (5)",
|
|
"ST (6)",
|
|
"ST (7)"
|
|
};
|
|
|
|
const char *SzNameReg(uchar reg)
|
|
{
|
|
if (reg <= 37) {
|
|
return (namereg[reg]);
|
|
}
|
|
if (reg < 128 || reg > 135) {
|
|
return ("???");
|
|
}
|
|
return (name87[reg - 128]);
|
|
}
|
|
|
|
LOCAL void C6RegSym (void)
|
|
{
|
|
REGSYMTYPE regsym;
|
|
|
|
regsym.typind = WGets ();
|
|
regsym.reg = (char) Gets ();
|
|
|
|
PrtIndent ();
|
|
printf("Register:\ttype %8s, register = %s, ",
|
|
SzNameType(regsym.typind),
|
|
SzNameReg(regsym.reg));
|
|
}
|
|
|
|
LOCAL void C6ConSym (void)
|
|
{
|
|
long len;
|
|
WORD type;
|
|
WORD code;
|
|
static char buf[1024];
|
|
|
|
type = WGets ();
|
|
PrtIndent ();
|
|
printf ("Constant:\ttype %8s, ", SzNameType(type));
|
|
|
|
code = Gets();
|
|
if (code < 128) {
|
|
len = code;
|
|
// skip value bytes
|
|
GetBytes(buf, (size_t) len);
|
|
} else {
|
|
switch (code) {
|
|
case 133: // unsigned word
|
|
case 137: // signed word
|
|
len = WGets ();
|
|
printf ("%x", (int) len);
|
|
break;
|
|
|
|
case 134: // signed long
|
|
case 138: // unsigned long
|
|
len = LGets ();
|
|
printf ("%lx", len);
|
|
break;
|
|
|
|
case 136: // signed byte
|
|
len = Gets ();
|
|
printf ("%x", (int) len);
|
|
break;
|
|
|
|
default:
|
|
printf ("??");
|
|
return;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// now we should be at the name of the symbol
|
|
}
|
|
|
|
LOCAL void C6BlockSym (void)
|
|
{
|
|
BLKSYMTYPE block;
|
|
int n;
|
|
|
|
block.off = GetOffset();
|
|
block.len = WGets();
|
|
PrtIndent ();
|
|
cIndent++;
|
|
n = f386? 8 : 4;
|
|
|
|
printf ( "Block Start : off = %0*lx, len = %04x",
|
|
n, block.off, block.len);
|
|
}
|
|
|
|
LOCAL void C6ProcSym (void)
|
|
{
|
|
PROCSYMTYPE proc;
|
|
int n;
|
|
|
|
proc.off = GetOffset ();
|
|
proc.typind = WGets ();
|
|
proc.len = WGets ();
|
|
proc.startoff = WGets ();
|
|
proc.endoff = WGets ();
|
|
proc.res = WGets();
|
|
proc.rtntyp = (char) Gets ();
|
|
|
|
|
|
PrtIndent ();
|
|
cIndent++;
|
|
n = f386? 8 : 4;
|
|
|
|
printf ( "Proc Start: off = %0*lx, type %8s, len = %04x\n",
|
|
n, proc.off, SzNameType(proc.typind), proc.len);
|
|
printf ( "\tDebug start = %04x, debug end = %04x, ",
|
|
proc.startoff, proc.endoff);
|
|
switch (proc.rtntyp) {
|
|
case S_NEAR:
|
|
printf ("NEAR,");
|
|
break;
|
|
case S_FAR:
|
|
printf ("FAR,");
|
|
break;
|
|
default:
|
|
printf ("???,");
|
|
}
|
|
}
|
|
|
|
LOCAL void C6LabSym ()
|
|
{
|
|
LABSYMTYPE dat;
|
|
int n;
|
|
|
|
dat.off = GetOffset ();
|
|
dat.rtntyp = (char) Gets ();
|
|
PrtIndent ();
|
|
n = f386? 8 : 4;
|
|
|
|
printf ( "Code label: off = %0*lx,",
|
|
n, dat.off);
|
|
switch (dat.rtntyp) {
|
|
case S_NEAR:
|
|
printf ("NEAR,");
|
|
break;
|
|
case S_FAR:
|
|
printf ("FAR,");
|
|
break;
|
|
default:
|
|
printf ("???,");
|
|
}
|
|
}
|
|
|
|
LOCAL void C6WithSym ()
|
|
{
|
|
WITHSYMTYPE dat;
|
|
int n;
|
|
|
|
dat.off = GetOffset ();
|
|
dat.len = WGets ();
|
|
PrtIndent ();
|
|
cIndent++;
|
|
n = f386? 8 : 4;
|
|
|
|
printf ( "'With Start: off = %0*lx, len = %04x",
|
|
n, dat.off,dat.len);
|
|
}
|
|
|
|
LOCAL void C6EntrySym (void)
|
|
{
|
|
PROCSYMTYPE proc;
|
|
int n;
|
|
|
|
proc.off = GetOffset ();
|
|
proc.typind = WGets ();
|
|
proc.len = WGets ();
|
|
proc.startoff = WGets ();
|
|
proc.endoff = WGets ();
|
|
proc.res = WGets();
|
|
proc.rtntyp = (char) Gets ();
|
|
|
|
|
|
PrtIndent ();
|
|
cIndent++;
|
|
n = f386? 8 : 4;
|
|
|
|
printf ( "FORTARN Entry: off = %0*lx, type %8s, len = %04x\n",
|
|
n, proc.off, SzNameType(proc.typind), proc.len);
|
|
printf ( "\tDebug start = %04x, debug end = %04x, ",
|
|
proc.startoff, proc.endoff);
|
|
switch (proc.rtntyp) {
|
|
case S_NEAR:
|
|
printf ("NEAR,");
|
|
break;
|
|
case S_FAR:
|
|
printf ("FAR,");
|
|
break;
|
|
default:
|
|
printf ("???,");
|
|
}
|
|
}
|
|
|
|
LOCAL void C6SkipSym (void)
|
|
{
|
|
printf("Skip: %d bytes\n", cbRec);
|
|
|
|
// skip the bytes in the skip record
|
|
|
|
while (cbRec > 0) {
|
|
Gets ();
|
|
}
|
|
}
|
|
|
|
LOCAL void C6CodeSegSym(void)
|
|
{
|
|
ushort seg;
|
|
ushort res;
|
|
|
|
seg = WGets();
|
|
res = WGets();
|
|
|
|
printf("Change Default Seg: seg = %04x\n", seg);
|
|
}
|
|
|
|
|
|
LOCAL void C6CobolTypeDefSym (void)
|
|
{
|
|
ushort type;
|
|
|
|
type = WGets ();
|
|
printf ("Cobol Typedef: type = %d,", type);
|
|
}
|
|
|
|
|
|
|
|
LOCAL void C6ChangeModelSym (void)
|
|
{
|
|
ushort offset;
|
|
ushort model;
|
|
ushort byte1;
|
|
ushort byte2;
|
|
ushort byte3;
|
|
ushort byte4;
|
|
|
|
offset = WGets ();
|
|
model= Gets ();
|
|
byte1 = Gets();
|
|
byte2 = Gets();
|
|
byte3 = Gets();
|
|
byte4 = Gets();
|
|
printf ("Change Model: offset = 0x%04x model = 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
|
|
offset, model, byte1, byte2, byte3, byte4);
|
|
}
|