mirror of
https://github.com/reactos/reactos.git
synced 2024-08-30 15:18:33 +00:00
193 lines
4 KiB
C
193 lines
4 KiB
C
/*
|
|
* Usage: raddr2line input-file address/offset
|
|
*
|
|
* 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 "rsym.h"
|
|
|
|
/* Assume if an offset > ABS_TRESHOLD, then it must be absolute */
|
|
#define ABS_TRESHOLD 0x00400000L
|
|
|
|
size_t fixup_offset ( size_t ImageBase, size_t offset )
|
|
{
|
|
if (offset > ABS_TRESHOLD)
|
|
offset -= ImageBase;
|
|
|
|
return offset;
|
|
}
|
|
|
|
long
|
|
my_atoi ( const char* a )
|
|
{
|
|
int i = 0;
|
|
const char* fmt = "%x";
|
|
|
|
if ( *a == '0' )
|
|
{
|
|
switch ( *++a )
|
|
{
|
|
case 'x':
|
|
fmt = "%x";
|
|
++a;
|
|
break;
|
|
case 'd':
|
|
fmt = "%d";
|
|
++a;
|
|
break;
|
|
default:
|
|
fmt = "%o";
|
|
break;
|
|
}
|
|
}
|
|
sscanf ( a, fmt, &i );
|
|
return i;
|
|
}
|
|
|
|
PIMAGE_SECTION_HEADER
|
|
find_rossym_section ( PIMAGE_FILE_HEADER PEFileHeader,
|
|
PIMAGE_SECTION_HEADER PESectionHeaders )
|
|
{
|
|
size_t i;
|
|
for ( i = 0; i < PEFileHeader->NumberOfSections; i++ )
|
|
{
|
|
if ( 0 == strcmp ( (char*)PESectionHeaders[i].Name, ".rossym" ) )
|
|
return &PESectionHeaders[i];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int
|
|
find_and_print_offset (
|
|
void* data,
|
|
size_t offset )
|
|
{
|
|
PSYMBOLFILE_HEADER RosSymHeader = (PSYMBOLFILE_HEADER)data;
|
|
PROSSYM_ENTRY Entries = (PROSSYM_ENTRY)((char*)data + RosSymHeader->SymbolsOffset);
|
|
char* Strings = (char*)data + RosSymHeader->StringsOffset;
|
|
size_t symbols = RosSymHeader->SymbolsLength / sizeof(ROSSYM_ENTRY);
|
|
size_t i;
|
|
|
|
//if ( RosSymHeader->SymbolsOffset )
|
|
|
|
for ( i = 0; i < symbols; i++ )
|
|
{
|
|
if ( Entries[i].Address > offset )
|
|
{
|
|
if ( !i-- )
|
|
return 1;
|
|
else
|
|
{
|
|
PROSSYM_ENTRY e = &Entries[i];
|
|
printf ( "%s:%u (%s)\n",
|
|
&Strings[e->FileOffset],
|
|
(unsigned int)e->SourceLine,
|
|
&Strings[e->FunctionOffset] );
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
process_data ( const void* FileData, size_t offset )
|
|
{
|
|
PIMAGE_DOS_HEADER PEDosHeader;
|
|
PIMAGE_FILE_HEADER PEFileHeader;
|
|
PIMAGE_OPTIONAL_HEADER PEOptHeader;
|
|
PIMAGE_SECTION_HEADER PESectionHeaders;
|
|
PIMAGE_SECTION_HEADER PERosSymSectionHeader;
|
|
size_t ImageBase;
|
|
int res;
|
|
|
|
/* 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");
|
|
return 1;
|
|
}
|
|
|
|
/* Locate PE file header */
|
|
/* sizeof(ULONG) = sizeof(MAGIC) */
|
|
PEFileHeader = (PIMAGE_FILE_HEADER)((char *)FileData + PEDosHeader->e_lfanew + sizeof(ULONG));
|
|
|
|
/* Locate optional header */
|
|
PEOptHeader = (PIMAGE_OPTIONAL_HEADER)(PEFileHeader + 1);
|
|
ImageBase = PEOptHeader->ImageBase;
|
|
|
|
/* Locate PE section headers */
|
|
PESectionHeaders = (PIMAGE_SECTION_HEADER)((char *) PEOptHeader + PEFileHeader->SizeOfOptionalHeader);
|
|
|
|
/* make sure offset is what we want */
|
|
offset = fixup_offset ( ImageBase, offset );
|
|
|
|
/* find rossym section */
|
|
PERosSymSectionHeader = find_rossym_section (
|
|
PEFileHeader, PESectionHeaders );
|
|
if ( !PERosSymSectionHeader )
|
|
{
|
|
fprintf ( stderr, "Couldn't find rossym section in executable\n" );
|
|
return 1;
|
|
}
|
|
res = find_and_print_offset ( (char*)FileData + PERosSymSectionHeader->PointerToRawData,
|
|
offset );
|
|
if ( res )
|
|
printf ( "??:0\n" );
|
|
return res;
|
|
}
|
|
|
|
int
|
|
process_file ( const char* file_name, size_t offset )
|
|
{
|
|
void* FileData;
|
|
size_t FileSize;
|
|
int res = 1;
|
|
|
|
FileData = load_file ( file_name, &FileSize );
|
|
if ( !FileData )
|
|
{
|
|
fprintf ( stderr, "An error occured loading '%s'\n", file_name );
|
|
}
|
|
else
|
|
{
|
|
res = process_data ( FileData, offset );
|
|
free ( FileData );
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
int main ( int argc, const char** argv )
|
|
{
|
|
char* path;
|
|
size_t offset;
|
|
int res;
|
|
|
|
if ( argc != 3 )
|
|
{
|
|
fprintf(stderr, "Usage: raddr2line <exefile> <offset>\n");
|
|
exit(1);
|
|
}
|
|
|
|
path = convert_path ( argv[1] );
|
|
offset = my_atoi ( argv[2] );
|
|
|
|
res = process_file ( path, offset );
|
|
|
|
free ( path );
|
|
|
|
return res;
|
|
}
|