|
1 #include <boost/regex.hpp> |
|
2 #define MAX_LINE 65535 |
|
3 #include "symbolgenerator.h" |
|
4 #include "e32image.h" |
|
5 |
|
6 #if defined(__LINUX__) |
|
7 #define PATH_SEPARATOR '/' |
|
8 #else |
|
9 #define PATH_SEPARATOR '\\' |
|
10 #endif |
|
11 |
|
12 boost::mutex SymbolGenerator::iMutexSingleton; |
|
13 SymbolGenerator* SymbolGenerator::iInst = NULL; |
|
14 SymbolGenerator* SymbolGenerator::GetInstance(){ |
|
15 iMutexSingleton.lock(); |
|
16 if(iInst == NULL) { |
|
17 iInst = new SymbolGenerator(); |
|
18 } |
|
19 iMutexSingleton.unlock(); |
|
20 return iInst; |
|
21 } |
|
22 void SymbolGenerator::Release() { |
|
23 iMutexSingleton.lock(); |
|
24 if(iInst != NULL) { |
|
25 delete iInst; |
|
26 iInst = NULL; |
|
27 } |
|
28 iMutexSingleton.unlock(); |
|
29 } |
|
30 void SymbolGenerator::SetSymbolFileName( const string& fileName ){ |
|
31 if(iSymFile.is_open()) |
|
32 iSymFile.close(); |
|
33 string s = fileName.substr(0,fileName.rfind('.'))+".symbol"; |
|
34 printf("* Writing %s - ROFS symbol file\n", s.c_str()); |
|
35 iSymFile.open(s.c_str()); |
|
36 } |
|
37 void SymbolGenerator::AddFile( const string& fileName, bool isExecutable ){ |
|
38 iMutex.lock(); |
|
39 iQueueFiles.push(TPlacedEntry(fileName,isExecutable)); |
|
40 iMutex.unlock(); |
|
41 iCond.notify_all(); |
|
42 } |
|
43 void SymbolGenerator::ProcessExecutable( const string& fileName ){ |
|
44 char str[MAX_LINE]; |
|
45 string outString; |
|
46 outString = "\nFrom "; |
|
47 outString += fileName + "\n\n"; |
|
48 iSymFile.write(outString.c_str(),outString.length()); |
|
49 string mapFile2 = fileName+".map"; |
|
50 size_t dot = fileName.rfind('.'); |
|
51 string mapFile = fileName.substr(0,dot)+".map"; |
|
52 ifstream fMap; |
|
53 fMap.open(mapFile2.c_str()); |
|
54 if(!fMap.is_open()) { |
|
55 fMap.open(mapFile.c_str()); |
|
56 } |
|
57 |
|
58 if(!fMap.is_open()) { |
|
59 printf("%s\nWarning: Can't open \"%s\" or \"%s\"\n",fileName.c_str(),mapFile2.c_str(),mapFile.c_str()); |
|
60 int binSize = GetSizeFromBinFile(fileName); |
|
61 memset(str,0,sizeof(str)); |
|
62 sprintf(str,"%04x", binSize); |
|
63 outString = "00000000 "; |
|
64 outString += str; |
|
65 outString += " "; |
|
66 outString += fileName.substr(fileName.rfind(PATH_SEPARATOR)+1)+"\n"; |
|
67 iSymFile.write(outString.c_str(),outString.length()); |
|
68 } |
|
69 else { |
|
70 if(!fMap.good()) fMap.clear(); |
|
71 boost::regex regARMV5("ARMV5", boost::regex::icase); |
|
72 boost::regex regGCCEoARMV4("(GCCE|ARMV4)", boost::regex::icase); |
|
73 boost::cmatch what; |
|
74 if(regex_search(fileName, what, regARMV5)) { |
|
75 ProcessArmv5File(fileName, fMap); |
|
76 } |
|
77 else if(regex_search(fileName, what, regGCCEoARMV4)) { |
|
78 ProcessGcceOrArm4File(fileName, fMap); |
|
79 } |
|
80 else { |
|
81 printf("\nWarning: cannot determine linker type used to create %s\n",fileName.c_str()); |
|
82 outString = "00000000 0000 "; |
|
83 outString += fileName.substr(fileName.rfind(PATH_SEPARATOR)+1)+"\n"; |
|
84 iSymFile.write(outString.c_str(),outString.length()); |
|
85 } |
|
86 } |
|
87 } |
|
88 void SymbolGenerator::ProcessDatafile( const string& fileName ){ |
|
89 string line = "\nFrom "+fileName+"\n\n00000000 0000 "+fileName.substr(fileName.rfind(PATH_SEPARATOR)+1)+"\n"; |
|
90 iSymFile.write(line.c_str(),line.length()); |
|
91 } |
|
92 void SymbolGenerator::ProcessArmv5File( const string& fileName, ifstream& aMap ){ |
|
93 aMap.seekg (0, ios::beg); |
|
94 char str[MAX_LINE]; |
|
95 string outString; |
|
96 aMap.getline(str,MAX_LINE); |
|
97 boost::cmatch what; |
|
98 boost::regex reg("^ARM Linker"); |
|
99 if(!regex_search(str, what, reg)) { |
|
100 printf("\nWarning: expecting %s to be generated by ARM linker\n", fileName.c_str()); |
|
101 outString = "00000000 0000 "+fileName.substr(fileName.rfind(PATH_SEPARATOR)+1)+"\n"; |
|
102 iSymFile.write(outString.c_str(),outString.length()); |
|
103 } |
|
104 reg.assign("Global Symbols"); |
|
105 while(aMap.getline(str,MAX_LINE)) { |
|
106 if(regex_search(str, what, reg)) { |
|
107 break; |
|
108 } |
|
109 } |
|
110 |
|
111 reg.assign("^\\s*(.+)\\s*0x(\\S+)\\s+[^\\d]*(\\d+)\\s+(.*)$"); |
|
112 string sSym,sTmp,sSection; |
|
113 unsigned int addr,size,baseOffset = 0; |
|
114 map<unsigned int,string> syms; |
|
115 char symString[MAX_LINE]; |
|
116 while(aMap.getline(str,MAX_LINE)) { |
|
117 if(regex_search(str, what, reg)) { |
|
118 sSym.assign(what[1].first,what[1].second-what[1].first); |
|
119 sTmp.assign(what[2].first,what[2].second-what[2].first); |
|
120 addr = strtol(sTmp.c_str(), NULL, 16); |
|
121 sTmp.assign(what[3].first,what[3].second-what[3].first); |
|
122 size = strtol(sTmp.c_str(), NULL, 10); |
|
123 sSection.assign(what[4].first,what[4].second-what[4].first); |
|
124 if(sSection.find("(StubCode)") != string::npos) |
|
125 size = 8; |
|
126 if(addr > 0) { |
|
127 memset(symString,0,sizeof(symString)); |
|
128 sprintf(symString,"%04x ",size); |
|
129 outString = symString; |
|
130 outString += sSym+" "; |
|
131 outString += sSection; |
|
132 if(baseOffset == 0) |
|
133 baseOffset = addr; |
|
134 unsigned int k = addr - baseOffset; |
|
135 if( (syms.find(k) == syms.end()) || size != 0) |
|
136 syms[k] = outString; |
|
137 } |
|
138 // end of addr>0 |
|
139 } |
|
140 // end of regex_search |
|
141 } |
|
142 |
|
143 map<unsigned int,string>::iterator it; |
|
144 for(it = syms.begin(); it != syms.end(); it++) { |
|
145 memset(str,0,sizeof(str)); |
|
146 sprintf(str,"%08x",it->first); |
|
147 outString = str; |
|
148 outString += " "; |
|
149 outString += it->second+"\n"; |
|
150 iSymFile.write(outString.c_str(),outString.length()); |
|
151 } |
|
152 } |
|
153 void SymbolGenerator::ProcessGcceOrArm4File( const string& fileName, ifstream& aMap ){ |
|
154 aMap.seekg (0, ios_base::beg); |
|
155 char str[MAX_LINE]; |
|
156 aMap.getline(str,MAX_LINE); |
|
157 boost::cmatch what; |
|
158 boost::regex reg("^\\.text\\s+"); |
|
159 while(aMap.getline(str,MAX_LINE)) { |
|
160 if(regex_search(str, what, reg)) { |
|
161 break; |
|
162 } |
|
163 } |
|
164 |
|
165 reg.assign("^\\.text\\s+(\\w+)\\s+\\w+"); |
|
166 if(!regex_search(str, what, reg)) { |
|
167 printf("ERROR: Can't get .text section info for \"%s\"\n",fileName.c_str()); |
|
168 } |
|
169 else { |
|
170 string sTmp, sLibFile; |
|
171 sTmp.assign(what[1].first,what[1].second-what[1].first); |
|
172 unsigned int imgText = strtol(sTmp.c_str(), NULL, 16); |
|
173 |
|
174 reg.assign("^LONG 0x.*", boost::regex::icase); |
|
175 boost::cmatch what1; |
|
176 boost::regex reg1("^\\s(\\.text)?\\s+(0x\\w+)\\s+(0x\\w+)\\s+(.*)$", boost::regex::icase); |
|
177 boost::regex reg2("^\\s+(\\w+)\\s\\s+([a-zA-Z_].+)", boost::regex::icase); |
|
178 boost::regex reg3(".*lib\\(.*d\\d*s_?\\d{5}.o\\)$", boost::regex::icase); |
|
179 |
|
180 map<unsigned int,string> syms; |
|
181 unsigned int addr, len, stubhex; |
|
182 |
|
183 while(aMap.getline(str,MAX_LINE)) { |
|
184 if(strlen(str) == 0) |
|
185 break; |
|
186 else if(regex_search(str, what, reg1)) { |
|
187 sLibFile.assign(what[4].first,what[4].second-what[4].first); |
|
188 if(!regex_search(sLibFile, what1, reg)) { |
|
189 sTmp.assign(what[2].first,what[2].second-what[2].first); |
|
190 addr = strtol(sTmp.c_str(), NULL, 16); |
|
191 sTmp.assign(what[3].first,what[3].second-what[3].first); |
|
192 len = strtol(sTmp.c_str(), NULL, 16); |
|
193 syms[addr+len] = ""; |
|
194 if(regex_search(sLibFile, what, reg3)) { |
|
195 stubhex = addr; |
|
196 } |
|
197 } |
|
198 } |
|
199 else if(regex_search(str, what, reg2)) { |
|
200 sTmp.assign(what[1].first,what[1].second-what[1].first); |
|
201 addr = strtol(sTmp.c_str(), NULL, 16); |
|
202 sTmp.assign(what[2].first,what[2].second-what[2].first); |
|
203 syms[addr] = (addr == stubhex)? ("stub "+sTmp) : sTmp; |
|
204 } |
|
205 } |
|
206 |
|
207 map<unsigned int,string>::iterator it = syms.begin(); |
|
208 map<unsigned int,string>::iterator itp = it++; |
|
209 string outString; |
|
210 for(; it != syms.end(); itp = it++) { |
|
211 if(itp->second != "") { |
|
212 memset(str,0,sizeof(str)); |
|
213 sprintf(str,"%08x %04x ",(itp->first-imgText), (it->first-itp->first)); |
|
214 outString = str; |
|
215 outString += it->second+"\n"; |
|
216 iSymFile.write(outString.c_str(),outString.length()); |
|
217 } |
|
218 } |
|
219 } |
|
220 } |
|
221 int SymbolGenerator::GetSizeFromBinFile( const string& fileName ){ |
|
222 TInt ret = 0; |
|
223 ifstream aIf(fileName.c_str(), ios_base::binary); |
|
224 if( !aIf.is_open() ) { |
|
225 printf("Warning: Cannot open file \n"); |
|
226 } |
|
227 else { |
|
228 E32ImageFile e32Image; |
|
229 TUint32 aSz; |
|
230 |
|
231 aIf.seekg(0,ios_base::end); |
|
232 aSz = aIf.tellg(); |
|
233 |
|
234 e32Image.Adjust(aSz); |
|
235 e32Image.iFileSize = aSz; |
|
236 |
|
237 aIf.seekg(0,ios_base::beg); |
|
238 aIf >> e32Image; |
|
239 ret = e32Image.iOrigHdr->iCodeSize; |
|
240 } |
|
241 return ret; |
|
242 } |
|
243 void SymbolGenerator::thrd_func(){ |
|
244 SymbolGenerator* me = GetInstance(); |
|
245 |
|
246 TPlacedEntry pe("",false); |
|
247 while(1) { |
|
248 if(1) { |
|
249 //scope the code block with if(1) for lock |
|
250 boost::mutex::scoped_lock lock(me->iMutex); |
|
251 while(me->iQueueFiles.empty()) |
|
252 me->iCond.wait(lock); |
|
253 /* |
|
254 if(me->iQueueFiles.empty()) { |
|
255 boost::this_thread::sleep(boost::posix_time::milliseconds(10)); |
|
256 continue; |
|
257 } |
|
258 */ |
|
259 |
|
260 pe = me->iQueueFiles.front(); |
|
261 me->iQueueFiles.pop(); |
|
262 } |
|
263 |
|
264 if(pe.iFileName == "") |
|
265 break; |
|
266 else if(pe.iExecutable) |
|
267 me->ProcessExecutable(pe.iFileName); |
|
268 else |
|
269 me->ProcessDatafile(pe.iFileName); |
|
270 } |
|
271 } |
|
272 SymbolGenerator::SymbolGenerator() : boost::thread(thrd_func) { |
|
273 } |
|
274 SymbolGenerator::~SymbolGenerator(){ |
|
275 if(joinable()) |
|
276 join(); |
|
277 iSymFile.flush(); |
|
278 iSymFile.close(); |
|
279 } |