mirror of
https://github.com/reactos/reactos.git
synced 2025-01-03 21:09:19 +00:00
utility to dump stab info out of an executable
svn path=/trunk/; revision=19577
This commit is contained in:
parent
5c787a3532
commit
20e4ab9e5a
2 changed files with 246 additions and 3 deletions
210
reactos/tools/dumpstab.c
Normal file
210
reactos/tools/dumpstab.c
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
/*
|
||||||
|
* Usage: dumpstab input-file
|
||||||
|
*
|
||||||
|
* There are two sources of information: the .stab/.stabstr
|
||||||
|
* sections of the executable and the COFF symbol table. Most
|
||||||
|
* of the information is in the .stab/.stabstr sections.
|
||||||
|
* However, most of our asm files don't contain .stab directives,
|
||||||
|
* so routines implemented in assembler won't show up in the
|
||||||
|
* .stab section. They are present in the COFF symbol table.
|
||||||
|
* So, we mostly use the .stab/.stabstr sections, but we augment
|
||||||
|
* the info there with info from the COFF symbol table when
|
||||||
|
* possible.
|
||||||
|
*
|
||||||
|
* This is a tool and is compiled using the host compiler,
|
||||||
|
* i.e. on Linux gcc and not mingw-gcc (cross-compiler).
|
||||||
|
* Therefore we can't include SDK headers and we have to
|
||||||
|
* duplicate some definitions here.
|
||||||
|
* Also note that the internal functions are "old C-style",
|
||||||
|
* returning an int, where a return of 0 means success and
|
||||||
|
* non-zero is failure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "rsym.h"
|
||||||
|
|
||||||
|
const char*
|
||||||
|
stab_type_name ( int stab_type )
|
||||||
|
{
|
||||||
|
static char buf[32];
|
||||||
|
switch ( stab_type )
|
||||||
|
{
|
||||||
|
#define X(n) case n: return #n;
|
||||||
|
X(N_GYSM)
|
||||||
|
X(N_FNAME)
|
||||||
|
X(N_FUN)
|
||||||
|
X(N_STSYM)
|
||||||
|
X(N_LCSYM)
|
||||||
|
X(N_MAIN)
|
||||||
|
X(N_PC)
|
||||||
|
X(N_NSYMS)
|
||||||
|
X(N_NOMAP)
|
||||||
|
X(N_RSYM)
|
||||||
|
X(N_M2C)
|
||||||
|
X(N_SLINE)
|
||||||
|
X(N_DSLINE)
|
||||||
|
X(N_BSLINE)
|
||||||
|
//X(N_BROWS)
|
||||||
|
X(N_DEFD)
|
||||||
|
X(N_EHDECL)
|
||||||
|
//X(N_MOD2)
|
||||||
|
X(N_CATCH)
|
||||||
|
X(N_SSYM)
|
||||||
|
X(N_SO)
|
||||||
|
X(N_LSYM)
|
||||||
|
X(N_BINCL)
|
||||||
|
X(N_SOL)
|
||||||
|
X(N_PSYM)
|
||||||
|
X(N_EINCL)
|
||||||
|
X(N_ENTRY)
|
||||||
|
X(N_LBRAC)
|
||||||
|
X(N_EXCL)
|
||||||
|
X(N_SCOPE)
|
||||||
|
X(N_RBRAC)
|
||||||
|
X(N_BCOMM)
|
||||||
|
X(N_ECOMM)
|
||||||
|
X(N_ECOML)
|
||||||
|
X(N_LENG)
|
||||||
|
}
|
||||||
|
sprintf ( buf, "%lu", stab_type );
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
GetStabInfo(void *FileData, PIMAGE_FILE_HEADER PEFileHeader,
|
||||||
|
PIMAGE_SECTION_HEADER PESectionHeaders,
|
||||||
|
ULONG *StabSymbolsLength, void **StabSymbolsBase,
|
||||||
|
ULONG *StabStringsLength, void **StabStringsBase)
|
||||||
|
{
|
||||||
|
ULONG Idx;
|
||||||
|
|
||||||
|
/* Load .stab and .stabstr sections if available */
|
||||||
|
*StabSymbolsBase = NULL;
|
||||||
|
*StabSymbolsLength = 0;
|
||||||
|
*StabStringsBase = NULL;
|
||||||
|
*StabStringsLength = 0;
|
||||||
|
|
||||||
|
for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
|
||||||
|
{
|
||||||
|
/* printf("section: '%.08s'\n", PESectionHeaders[Idx].Name); */
|
||||||
|
if ((strncmp((char*)PESectionHeaders[Idx].Name, ".stab", 5) == 0)
|
||||||
|
&& (PESectionHeaders[Idx].Name[5] == 0))
|
||||||
|
{
|
||||||
|
/* printf(".stab section found. Size %d\n",
|
||||||
|
PESectionHeaders[Idx].SizeOfRawData); */
|
||||||
|
|
||||||
|
*StabSymbolsLength = PESectionHeaders[Idx].SizeOfRawData;
|
||||||
|
*StabSymbolsBase = (void *)((char *) FileData + PESectionHeaders[Idx].PointerToRawData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncmp((char*)PESectionHeaders[Idx].Name, ".stabstr", 8) == 0)
|
||||||
|
{
|
||||||
|
/* printf(".stabstr section found. Size %d\n",
|
||||||
|
PESectionHeaders[Idx].SizeOfRawData); */
|
||||||
|
|
||||||
|
*StabStringsLength = PESectionHeaders[Idx].SizeOfRawData;
|
||||||
|
*StabStringsBase = (void *)((char *) FileData + PESectionHeaders[Idx].PointerToRawData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
IterateStabs(ULONG StabSymbolsLength, void *StabSymbolsBase,
|
||||||
|
ULONG StabStringsLength, void *StabStringsBase,
|
||||||
|
ULONG_PTR ImageBase, PIMAGE_FILE_HEADER PEFileHeader,
|
||||||
|
PIMAGE_SECTION_HEADER PESectionHeaders)
|
||||||
|
{
|
||||||
|
PSTAB_ENTRY e;
|
||||||
|
ULONG Count, i;
|
||||||
|
|
||||||
|
e = StabSymbolsBase;
|
||||||
|
Count = StabSymbolsLength / sizeof(STAB_ENTRY);
|
||||||
|
if (Count == 0) /* No symbol info */
|
||||||
|
return;
|
||||||
|
|
||||||
|
printf ( "type,other,desc,value,str\n" );
|
||||||
|
for (i = 0; i < Count; i++)
|
||||||
|
{
|
||||||
|
printf ( "%s,%lu(0x%x),%lu(0x%x),%lu(0x%x),%s\n",
|
||||||
|
stab_type_name(e[i].n_type),
|
||||||
|
e[i].n_other,
|
||||||
|
e[i].n_other,
|
||||||
|
e[i].n_desc,
|
||||||
|
e[i].n_desc,
|
||||||
|
e[i].n_value,
|
||||||
|
e[i].n_value,
|
||||||
|
(char *) StabStringsBase + e[i].n_strx );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
PIMAGE_DOS_HEADER PEDosHeader;
|
||||||
|
PIMAGE_FILE_HEADER PEFileHeader;
|
||||||
|
PIMAGE_OPTIONAL_HEADER PEOptHeader;
|
||||||
|
PIMAGE_SECTION_HEADER PESectionHeaders;
|
||||||
|
ULONG ImageBase;
|
||||||
|
void *StabBase;
|
||||||
|
ULONG StabsLength;
|
||||||
|
void *StabStringBase;
|
||||||
|
ULONG StabStringsLength;
|
||||||
|
char* path1;
|
||||||
|
size_t FileSize;
|
||||||
|
void *FileData;
|
||||||
|
|
||||||
|
if (2 != argc)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: dumpstabs <exefile>\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
path1 = convert_path(argv[1]);
|
||||||
|
|
||||||
|
FileData = load_file ( path1, &FileSize );
|
||||||
|
if ( !FileData )
|
||||||
|
{
|
||||||
|
fprintf ( stderr, "An error occured loading '%s'\n", path1 );
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if MZ header exists */
|
||||||
|
PEDosHeader = (PIMAGE_DOS_HEADER) FileData;
|
||||||
|
if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC || PEDosHeader->e_lfanew == 0L)
|
||||||
|
{
|
||||||
|
perror("Input file is not a PE image.\n");
|
||||||
|
free(FileData);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Locate PE file header */
|
||||||
|
/* sizeof(ULONG) = sizeof(MAGIC) */
|
||||||
|
PEFileHeader = (PIMAGE_FILE_HEADER)((char *) FileData + PEDosHeader->e_lfanew + sizeof(ULONG));
|
||||||
|
|
||||||
|
/* Locate optional header */
|
||||||
|
assert(sizeof(ULONG) == 4);
|
||||||
|
PEOptHeader = (PIMAGE_OPTIONAL_HEADER)(PEFileHeader + 1);
|
||||||
|
ImageBase = PEOptHeader->ImageBase;
|
||||||
|
|
||||||
|
/* Locate PE section headers */
|
||||||
|
PESectionHeaders = (PIMAGE_SECTION_HEADER)((char *) PEOptHeader + PEFileHeader->SizeOfOptionalHeader);
|
||||||
|
|
||||||
|
if (GetStabInfo(FileData, PEFileHeader, PESectionHeaders, &StabsLength, &StabBase,
|
||||||
|
&StabStringsLength, &StabStringBase))
|
||||||
|
{
|
||||||
|
free(FileData);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
IterateStabs( StabsLength, StabBase, StabStringsLength, StabStringBase,
|
||||||
|
ImageBase, PEFileHeader, PESectionHeaders);
|
||||||
|
|
||||||
|
free(FileData);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -179,9 +179,42 @@ typedef struct _STAB_ENTRY {
|
||||||
ULONG n_value; /* value of symbol */
|
ULONG n_value; /* value of symbol */
|
||||||
} STAB_ENTRY, *PSTAB_ENTRY;
|
} STAB_ENTRY, *PSTAB_ENTRY;
|
||||||
|
|
||||||
|
/* http://www.math.utah.edu/docs/info/stabs_12.html */
|
||||||
|
#define N_GYSM 0x20
|
||||||
|
#define N_FNAME 0x22
|
||||||
#define N_FUN 0x24
|
#define N_FUN 0x24
|
||||||
|
#define N_STSYM 0x26
|
||||||
|
#define N_LCSYM 0x28
|
||||||
|
#define N_MAIN 0x2A
|
||||||
|
#define N_PC 0x30
|
||||||
|
#define N_NSYMS 0x32
|
||||||
|
#define N_NOMAP 0x34
|
||||||
|
#define N_RSYM 0x40
|
||||||
|
#define N_M2C 0x42
|
||||||
#define N_SLINE 0x44
|
#define N_SLINE 0x44
|
||||||
|
#define N_DSLINE 0x46
|
||||||
|
#define N_BSLINE 0x48
|
||||||
|
#define N_BROWS 0x48
|
||||||
|
#define N_DEFD 0x4A
|
||||||
|
#define N_EHDECL 0x50
|
||||||
|
#define N_MOD2 0x50
|
||||||
|
#define N_CATCH 0x54
|
||||||
|
#define N_SSYM 0x60
|
||||||
#define N_SO 0x64
|
#define N_SO 0x64
|
||||||
|
#define N_LSYM 0x80
|
||||||
|
#define N_BINCL 0x82
|
||||||
|
#define N_SOL 0x84
|
||||||
|
#define N_PSYM 0xA0
|
||||||
|
#define N_EINCL 0xA2
|
||||||
|
#define N_ENTRY 0xA4
|
||||||
|
#define N_LBRAC 0xC0
|
||||||
|
#define N_EXCL 0xC2
|
||||||
|
#define N_SCOPE 0xC4
|
||||||
|
#define N_RBRAC 0xE0
|
||||||
|
#define N_BCOMM 0xE2
|
||||||
|
#define N_ECOMM 0xE4
|
||||||
|
#define N_ECOML 0xE8
|
||||||
|
#define N_LENG 0xFE
|
||||||
|
|
||||||
/* COFF symbol table */
|
/* COFF symbol table */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue