|
1 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "analyse.h" |
|
17 #include "symbols.h" |
|
18 |
|
19 #ifdef __MSVCDOTNET__ |
|
20 #include <fstream> |
|
21 #else //!__MSVCDOTNET__ |
|
22 #include <fstream.h> |
|
23 #endif //__MSVCDOTNET__ |
|
24 |
|
25 namespace { |
|
26 unsigned ParseHex(const char* aText, int aLength) |
|
27 { |
|
28 unsigned value = 0; |
|
29 const char* end = aText + aLength; |
|
30 do |
|
31 { |
|
32 unsigned c = *aText++ - '0'; |
|
33 if (c > 9) |
|
34 c -= 'a' - '0' - 10; |
|
35 value = (value << 4) + c; |
|
36 } while (aText < end); |
|
37 return value; |
|
38 } |
|
39 }; |
|
40 |
|
41 |
|
42 // class SymbolFile |
|
43 |
|
44 SymbolFile::SymbolFile(const char* aSymbolFile, bool aRofs) |
|
45 :iText(0), iTextLower(0) |
|
46 { |
|
47 ifstream file; |
|
48 #ifdef __MSVCDOTNET__ |
|
49 file.open(aSymbolFile, ios::binary); |
|
50 #else //!__MSVCDOTNET__ |
|
51 file.open(aSymbolFile, ios::nocreate | ios::binary); |
|
52 #endif //__MSVCDOTNET__ |
|
53 if (!file) |
|
54 { |
|
55 cerr << "Unable to open ROM symbol file '" << aSymbolFile << '\'' << endl; |
|
56 Analyse::Abort(); |
|
57 } |
|
58 // |
|
59 file.seekg(0, ios::end); |
|
60 iLength = file.tellg(); |
|
61 // |
|
62 iText = new char[iLength+1]; |
|
63 file.seekg(0, ios::beg); |
|
64 file.read(iText, iLength); |
|
65 iText[iLength] = '\0'; |
|
66 // |
|
67 file.close(); |
|
68 |
|
69 if (aRofs) |
|
70 { |
|
71 iTextLower = new char[iLength+1]; |
|
72 for(char *p = iTextLower, *c = iText, *end = iText + iLength;c < end;c++, p++) |
|
73 *p = tolower(*c); |
|
74 } |
|
75 } |
|
76 |
|
77 SymbolFile::~SymbolFile() |
|
78 { |
|
79 delete [] iText; |
|
80 if (iTextLower) |
|
81 delete [] iTextLower; |
|
82 } |
|
83 |
|
84 bool SymbolFile::Parse(SymbolFile::Parser& aParser, const char* aModuleName, PC aAddress, PC aModuleLength, int aModuleId) const |
|
85 { |
|
86 char* text = 0; |
|
87 PC first_pc_limit = 0, last_pc_limit = 0; |
|
88 TState state = EPreFile; |
|
89 PC lastPC = 0; |
|
90 bool inSyms = false; |
|
91 const char *prevName = 0; |
|
92 int lastLen = 0; |
|
93 |
|
94 if (aModuleName) // should parse only one module |
|
95 { |
|
96 bool not_found = false; |
|
97 char * name = strstr(iTextLower, aModuleName); |
|
98 if (name) |
|
99 { |
|
100 for(char * p = name; p != iTextLower && *p != '\n';p--); |
|
101 if (*p == '\n' || p == iTextLower) |
|
102 { |
|
103 name = ++p; |
|
104 text = iText + (name - iTextLower); |
|
105 } |
|
106 else |
|
107 not_found = true; |
|
108 } |
|
109 else |
|
110 not_found = true; |
|
111 |
|
112 if (not_found) |
|
113 return false; |
|
114 |
|
115 state = EFile; |
|
116 } |
|
117 else |
|
118 text = iText; |
|
119 |
|
120 const char* end = iText + iLength; |
|
121 while (text < end && state != EError) |
|
122 { |
|
123 char* endl = strchr(text, '\r'); |
|
124 if (endl == 0) |
|
125 { |
|
126 if (!aModuleName) |
|
127 { |
|
128 state = EError; |
|
129 break; |
|
130 } |
|
131 else |
|
132 { |
|
133 char* p = text + strlen(text); |
|
134 if (*(p+1) == '\n') |
|
135 endl = p; |
|
136 else |
|
137 { |
|
138 state = EError; |
|
139 break; |
|
140 } |
|
141 } |
|
142 } |
|
143 switch (state) |
|
144 { |
|
145 case EPreFile: |
|
146 if (endl != text) |
|
147 state = EError; |
|
148 else |
|
149 state = EFile; |
|
150 break; |
|
151 case EFile: |
|
152 if (strncmp(text, "From", 4) != 0) |
|
153 state = EError; |
|
154 else |
|
155 { |
|
156 *endl = '\0'; |
|
157 char* name = strrchr(text, '\\'); |
|
158 if (name == 0) |
|
159 name = text + 8; |
|
160 else |
|
161 ++name; |
|
162 aParser.File(name); |
|
163 state = EPostFile; |
|
164 } |
|
165 break; |
|
166 case EPostFile: |
|
167 if (endl != text) |
|
168 state = EError; |
|
169 else |
|
170 state = ESymbol; |
|
171 break; |
|
172 case ESymbol: |
|
173 if (text == endl) |
|
174 { |
|
175 if (aModuleName) |
|
176 goto Quit; |
|
177 else |
|
178 state = EFile; |
|
179 } |
|
180 else |
|
181 { |
|
182 PC pc = ParseHex(text, 8); |
|
183 pc &= ~1; // should be odd address, error in symbol table |
|
184 |
|
185 if(aModuleName) |
|
186 pc += aAddress; |
|
187 |
|
188 *endl = '\0'; |
|
189 |
|
190 char* codeType = strrchr(text+20, '('); |
|
191 |
|
192 if ( codeType == NULL || (strcmp(codeType,"(.data)") != 0 && |
|
193 strcmp(codeType,"(.bss)") != 0 && |
|
194 strcmp(codeType,"(.init_array)") != 0 && |
|
195 strcmp(codeType,"(linker$$defined$$symbols)") != 0 && |
|
196 strcmp(codeType,"(ExportTable)") != 0) ) |
|
197 { |
|
198 if(inSyms && (pc > (lastPC + lastLen))) |
|
199 { |
|
200 memcpy((void *)(prevName - 15), "<static> after ", 15); |
|
201 aParser.Symbol(prevName - 15, lastPC + lastLen, pc - (lastPC + lastLen)); |
|
202 } |
|
203 |
|
204 int length = ParseHex(text + 12, 4); |
|
205 |
|
206 if(pc >= lastPC + lastLen) |
|
207 { |
|
208 bool is_added = aParser.Symbol(text + 20, pc, length); |
|
209 if (is_added && aModuleName && !first_pc_limit) |
|
210 { |
|
211 first_pc_limit = pc + length; |
|
212 last_pc_limit = pc + aModuleLength; |
|
213 } |
|
214 } |
|
215 |
|
216 prevName = text + 20; |
|
217 if(pc + length > lastPC + lastLen) |
|
218 { |
|
219 lastLen = length; |
|
220 lastPC = pc; |
|
221 } |
|
222 inSyms = true; |
|
223 } |
|
224 } |
|
225 break; |
|
226 case EError: |
|
227 break; |
|
228 } |
|
229 text = endl + 2; |
|
230 } |
|
231 if (state == EError) |
|
232 Analyse::Abort("Bad ROM symbol file format"); |
|
233 |
|
234 Quit: |
|
235 if(aModuleName && lastPC == first_pc_limit && (lastPC + lastLen) < last_pc_limit) |
|
236 { |
|
237 memcpy((void *)(prevName - 10), "<anon> in ", 10); |
|
238 aParser.Symbol(prevName - 10, lastPC + lastLen, last_pc_limit - (lastPC + lastLen)); |
|
239 } |
|
240 aParser.Done(first_pc_limit, last_pc_limit, aModuleId); |
|
241 |
|
242 return true; |
|
243 } |