Create the AHCI branch for Aman's work
[reactos.git] / sdk / tools / rsym / raddr2line.c
1 /*
2 * Usage: raddr2line input-file address/offset
3 *
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.
11 */
12
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
16
17 #include "rsym.h"
18
19 /* Assume if an offset > ABS_TRESHOLD, then it must be absolute */
20 #define ABS_TRESHOLD 0x00400000L
21
22 size_t fixup_offset ( size_t ImageBase, size_t offset )
23 {
24 if (offset > ABS_TRESHOLD)
25 offset -= ImageBase;
26
27 return offset;
28 }
29
30 long
31 my_atoi ( const char* a )
32 {
33 int i = 0;
34 const char* fmt = "%x";
35
36 if ( *a == '0' )
37 {
38 switch ( *++a )
39 {
40 case 'x':
41 fmt = "%x";
42 ++a;
43 break;
44 case 'd':
45 fmt = "%d";
46 ++a;
47 break;
48 default:
49 fmt = "%o";
50 break;
51 }
52 }
53 sscanf ( a, fmt, &i );
54 return i;
55 }
56
57 PIMAGE_SECTION_HEADER
58 find_rossym_section ( PIMAGE_FILE_HEADER PEFileHeader,
59 PIMAGE_SECTION_HEADER PESectionHeaders )
60 {
61 size_t i;
62 for ( i = 0; i < PEFileHeader->NumberOfSections; i++ )
63 {
64 if ( 0 == strcmp ( (char*)PESectionHeaders[i].Name, ".rossym" ) )
65 return &PESectionHeaders[i];
66 }
67 return NULL;
68 }
69
70 int
71 find_and_print_offset (
72 void* data,
73 size_t offset )
74 {
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);
79 size_t i;
80
81 //if ( RosSymHeader->SymbolsOffset )
82
83 for ( i = 0; i < symbols; i++ )
84 {
85 if ( Entries[i].Address > offset )
86 {
87 if ( !i-- )
88 return 1;
89 else
90 {
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] );
96 return 0;
97 }
98 }
99 }
100 return 1;
101 }
102
103 int
104 process_data ( const void* FileData, size_t offset )
105 {
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;
111 size_t ImageBase;
112 int res;
113
114 /* Check if MZ header exists */
115 PEDosHeader = (PIMAGE_DOS_HEADER)FileData;
116 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC || PEDosHeader->e_lfanew == 0L)
117 {
118 perror("Input file is not a PE image.\n");
119 return 1;
120 }
121
122 /* Locate PE file header */
123 /* sizeof(ULONG) = sizeof(MAGIC) */
124 PEFileHeader = (PIMAGE_FILE_HEADER)((char *)FileData + PEDosHeader->e_lfanew + sizeof(ULONG));
125
126 /* Locate optional header */
127 PEOptHeader = (PIMAGE_OPTIONAL_HEADER)(PEFileHeader + 1);
128 ImageBase = PEOptHeader->ImageBase;
129
130 /* Locate PE section headers */
131 PESectionHeaders = (PIMAGE_SECTION_HEADER)((char *) PEOptHeader + PEFileHeader->SizeOfOptionalHeader);
132
133 /* make sure offset is what we want */
134 offset = fixup_offset ( ImageBase, offset );
135
136 /* find rossym section */
137 PERosSymSectionHeader = find_rossym_section (
138 PEFileHeader, PESectionHeaders );
139 if ( !PERosSymSectionHeader )
140 {
141 fprintf ( stderr, "Couldn't find rossym section in executable\n" );
142 return 1;
143 }
144 res = find_and_print_offset ( (char*)FileData + PERosSymSectionHeader->PointerToRawData,
145 offset );
146 if ( res )
147 printf ( "??:0\n" );
148 return res;
149 }
150
151 int
152 process_file ( const char* file_name, size_t offset )
153 {
154 void* FileData;
155 size_t FileSize;
156 int res = 1;
157
158 FileData = load_file ( file_name, &FileSize );
159 if ( !FileData )
160 {
161 fprintf ( stderr, "An error occured loading '%s'\n", file_name );
162 }
163 else
164 {
165 res = process_data ( FileData, offset );
166 free ( FileData );
167 }
168
169 return res;
170 }
171
172 int main ( int argc, const char** argv )
173 {
174 char* path;
175 size_t offset;
176 int res;
177
178 if ( argc != 3 )
179 {
180 fprintf(stderr, "Usage: raddr2line <exefile> <offset>\n");
181 exit(1);
182 }
183
184 path = convert_path ( argv[1] );
185 offset = my_atoi ( argv[2] );
186
187 res = process_file ( path, offset );
188
189 free ( path );
190
191 return res;
192 }