mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +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 */
|
||||
} STAB_ENTRY, *PSTAB_ENTRY;
|
||||
|
||||
#define N_FUN 0x24
|
||||
#define N_SLINE 0x44
|
||||
#define N_SO 0x64
|
||||
/* http://www.math.utah.edu/docs/info/stabs_12.html */
|
||||
#define N_GYSM 0x20
|
||||
#define N_FNAME 0x22
|
||||
#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_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_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 */
|
||||
|
||||
|
|
Loading…
Reference in a new issue