2 * Usage: raddr2line input-file address/offset
4 * This is a tool and is compiled using the host compiler,
5 * i.e. on Linux gcc and not mingw-gcc (cross-compiler).
6 * Therefore we can't include SDK headers and we have to
7 * duplicate some definitions here.
8 * Also note that the internal functions are "old C-style",
9 * returning an int, where a return of 0 means success and
10 * non-zero is failure.
19 /* Assume if an offset > ABS_TRESHOLD, then it must be absolute */
20 #define ABS_TRESHOLD 0x00400000L
22 size_t fixup_offset ( size_t ImageBase
, size_t offset
)
24 if (offset
> ABS_TRESHOLD
)
31 my_atoi ( const char* a
)
34 const char* fmt
= "%x";
53 sscanf ( a
, fmt
, &i
);
58 find_rossym_section ( PIMAGE_FILE_HEADER PEFileHeader
,
59 PIMAGE_SECTION_HEADER PESectionHeaders
)
62 for ( i
= 0; i
< PEFileHeader
->NumberOfSections
; i
++ )
64 if ( 0 == strcmp ( (char*)PESectionHeaders
[i
].Name
, ".rossym" ) )
65 return &PESectionHeaders
[i
];
71 find_and_print_offset (
75 PSYMBOLFILE_HEADER RosSymHeader
= (PSYMBOLFILE_HEADER
)data
;
76 PROSSYM_ENTRY Entries
= (PROSSYM_ENTRY
)((char*)data
+ RosSymHeader
->SymbolsOffset
);
77 char* Strings
= (char*)data
+ RosSymHeader
->StringsOffset
;
78 size_t symbols
= RosSymHeader
->SymbolsLength
/ sizeof(ROSSYM_ENTRY
);
81 //if ( RosSymHeader->SymbolsOffset )
83 for ( i
= 0; i
< symbols
; i
++ )
85 if ( Entries
[i
].Address
> offset
)
91 PROSSYM_ENTRY e
= &Entries
[i
];
92 printf ( "%s:%u (%s)\n",
93 &Strings
[e
->FileOffset
],
94 (unsigned int)e
->SourceLine
,
95 &Strings
[e
->FunctionOffset
] );
104 process_data ( const void* FileData
, size_t offset
)
106 PIMAGE_DOS_HEADER PEDosHeader
;
107 PIMAGE_FILE_HEADER PEFileHeader
;
108 PIMAGE_OPTIONAL_HEADER PEOptHeader
;
109 PIMAGE_SECTION_HEADER PESectionHeaders
;
110 PIMAGE_SECTION_HEADER PERosSymSectionHeader
;
114 /* Check if MZ header exists */
115 PEDosHeader
= (PIMAGE_DOS_HEADER
)FileData
;
116 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
|| PEDosHeader
->e_lfanew
== 0L)
118 perror("Input file is not a PE image.\n");
122 /* Locate PE file header */
123 /* sizeof(ULONG) = sizeof(MAGIC) */
124 PEFileHeader
= (PIMAGE_FILE_HEADER
)((char *)FileData
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
126 /* Locate optional header */
127 PEOptHeader
= (PIMAGE_OPTIONAL_HEADER
)(PEFileHeader
+ 1);
128 ImageBase
= PEOptHeader
->ImageBase
;
130 /* Locate PE section headers */
131 PESectionHeaders
= (PIMAGE_SECTION_HEADER
)((char *) PEOptHeader
+ PEFileHeader
->SizeOfOptionalHeader
);
133 /* make sure offset is what we want */
134 offset
= fixup_offset ( ImageBase
, offset
);
136 /* find rossym section */
137 PERosSymSectionHeader
= find_rossym_section (
138 PEFileHeader
, PESectionHeaders
);
139 if ( !PERosSymSectionHeader
)
141 fprintf ( stderr
, "Couldn't find rossym section in executable\n" );
144 res
= find_and_print_offset ( (char*)FileData
+ PERosSymSectionHeader
->PointerToRawData
,
152 process_file ( const char* file_name
, size_t offset
)
158 FileData
= load_file ( file_name
, &FileSize
);
161 fprintf ( stderr
, "An error occured loading '%s'\n", file_name
);
165 res
= process_data ( FileData
, offset
);
172 int main ( int argc
, const char** argv
)
180 fprintf(stderr
, "Usage: raddr2line <exefile> <offset>\n");
184 path
= convert_path ( argv
[1] );
185 offset
= my_atoi ( argv
[2] );
187 res
= process_file ( path
, offset
);