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 size_t fixup_offset ( size_t ImageBase
, size_t offset
)
21 if ( offset
>= ImageBase
)
27 my_atoi ( const char* a
)
30 const char* fmt
= "%x";
49 sscanf ( a
, fmt
, &i
);
54 find_rossym_section ( PIMAGE_FILE_HEADER PEFileHeader
,
55 PIMAGE_SECTION_HEADER PESectionHeaders
)
58 for ( i
= 0; i
< PEFileHeader
->NumberOfSections
; i
++ )
60 if ( 0 == strcmp ( (char*)PESectionHeaders
[i
].Name
, ".rossym" ) )
61 return &PESectionHeaders
[i
];
67 find_and_print_offset (
71 PSYMBOLFILE_HEADER RosSymHeader
= (PSYMBOLFILE_HEADER
)data
;
72 PROSSYM_ENTRY Entries
= (PROSSYM_ENTRY
)((char*)data
+ RosSymHeader
->SymbolsOffset
);
73 char* Strings
= (char*)data
+ RosSymHeader
->StringsOffset
;
74 size_t symbols
= RosSymHeader
->SymbolsLength
/ sizeof(ROSSYM_ENTRY
);
77 //if ( RosSymHeader->SymbolsOffset )
79 for ( i
= 0; i
< symbols
; i
++ )
81 if ( Entries
[i
].Address
> offset
)
87 PROSSYM_ENTRY e
= &Entries
[i
];
88 printf ( "%s:%lu (%s)",
89 &Strings
[e
->FileOffset
],
91 &Strings
[e
->FunctionOffset
] );
100 process_data ( const void* FileData
, size_t FileSize
, size_t offset
)
102 PIMAGE_DOS_HEADER PEDosHeader
;
103 PIMAGE_FILE_HEADER PEFileHeader
;
104 PIMAGE_OPTIONAL_HEADER PEOptHeader
;
105 PIMAGE_SECTION_HEADER PESectionHeaders
;
106 PIMAGE_SECTION_HEADER PERosSymSectionHeader
;
110 /* Check if MZ header exists */
111 PEDosHeader
= (PIMAGE_DOS_HEADER
)FileData
;
112 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
|| PEDosHeader
->e_lfanew
== 0L)
114 perror("Input file is not a PE image.\n");
118 /* Locate PE file header */
119 /* sizeof(ULONG) = sizeof(MAGIC) */
120 PEFileHeader
= (PIMAGE_FILE_HEADER
)((char *)FileData
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
122 /* Locate optional header */
123 PEOptHeader
= (PIMAGE_OPTIONAL_HEADER
)(PEFileHeader
+ 1);
124 ImageBase
= PEOptHeader
->ImageBase
;
126 /* Locate PE section headers */
127 PESectionHeaders
= (PIMAGE_SECTION_HEADER
)((char *) PEOptHeader
+ PEFileHeader
->SizeOfOptionalHeader
);
129 /* make sure offset is what we want */
130 offset
= fixup_offset ( ImageBase
, offset
);
132 /* find rossym section */
133 PERosSymSectionHeader
= find_rossym_section (
134 PEFileHeader
, PESectionHeaders
);
135 if ( !PERosSymSectionHeader
)
137 fprintf ( stderr
, "Couldn't find rossym section in executable\n" );
140 res
= find_and_print_offset ( (char*)FileData
+ PERosSymSectionHeader
->PointerToRawData
,
148 process_file ( const char* file_name
, size_t offset
)
154 FileData
= load_file ( file_name
, &FileSize
);
157 fprintf ( stderr
, "An error occured loading '%s'\n", file_name
);
161 res
= process_data ( FileData
, FileSize
, offset
);
168 int main ( int argc
, const char** argv
)
176 fprintf(stderr
, "Usage: raddr2line <exefile> <offset>\n");
180 path
= convert_path ( argv
[1] );
181 offset
= my_atoi ( argv
[2] );
183 res
= process_file ( path
, offset
);