|
1 /* |
|
2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <vector> |
|
19 #include <boost/regex.hpp> |
|
20 #define MAX_LINE 65535 |
|
21 #include "symbolgenerator.h" |
|
22 #include "e32image.h" |
|
23 #include "h_utl.h" |
|
24 |
|
25 #if defined(__LINUX__) |
|
26 #define PATH_SEPARATOR '/' |
|
27 #else |
|
28 #define PATH_SEPARATOR '\\' |
|
29 #endif |
|
30 extern TInt gThreadNum; |
|
31 extern TBool gGenBsymbols; |
|
32 |
|
33 boost::mutex SymbolGenerator::iMutexSingleton; |
|
34 SymbolGenerator* SymbolGenerator::iInst = NULL; |
|
35 SymbolGenerator* SymbolGenerator::GetInstance(){ |
|
36 iMutexSingleton.lock(); |
|
37 if(iInst == NULL) { |
|
38 iInst = new SymbolGenerator(); |
|
39 } |
|
40 iMutexSingleton.unlock(); |
|
41 return iInst; |
|
42 } |
|
43 void SymbolGenerator::Release() { |
|
44 if(iInst != NULL) { |
|
45 iInst->join(); |
|
46 } |
|
47 iMutexSingleton.lock(); |
|
48 if(iInst != NULL) { |
|
49 delete iInst; |
|
50 iInst = NULL; |
|
51 } |
|
52 iMutexSingleton.unlock(); |
|
53 } |
|
54 void SymbolGenerator::SetSymbolFileName( const string& fileName ){ |
|
55 if(iSymFile.is_open()) |
|
56 iSymFile.close(); |
|
57 if(gGenBsymbols) |
|
58 { |
|
59 string s = fileName.substr(0,fileName.rfind('.'))+".bsym"; |
|
60 if(iImageType == ERofsImage) |
|
61 { |
|
62 printf("* Writing %s - ROFS BSymbol file\n", s.c_str()); |
|
63 } |
|
64 else |
|
65 { |
|
66 printf("* Writing %s - ROM BSymbol file\n", s.c_str()); |
|
67 } |
|
68 iSymFile.open(s.c_str(), ios_base::binary); |
|
69 } |
|
70 else |
|
71 { |
|
72 string s = fileName.substr(0,fileName.rfind('.'))+".symbol"; |
|
73 if(iImageType == ERofsImage) |
|
74 { |
|
75 printf("* Writing %s - ROFS Symbol file\n", s.c_str()); |
|
76 } |
|
77 else |
|
78 { |
|
79 printf("* Writing %s - ROM Symbol file\n", s.c_str()); |
|
80 } |
|
81 iSymFile.open(s.c_str()); |
|
82 } |
|
83 |
|
84 } |
|
85 void SymbolGenerator::AddFile( const string& fileName, bool isExecutable ){ |
|
86 iMutex.lock(); |
|
87 iQueueFiles.push(TPlacedEntry(fileName, "" , isExecutable)); |
|
88 iMutex.unlock(); |
|
89 iCond.notify_all(); |
|
90 } |
|
91 |
|
92 void SymbolGenerator::AddEntry(const TPlacedEntry& aEntry) |
|
93 { |
|
94 iMutex.lock(); |
|
95 iQueueFiles.push(aEntry); |
|
96 iMutex.unlock(); |
|
97 iCond.notify_all(); |
|
98 } |
|
99 |
|
100 void SymbolGenerator::SetFinished() |
|
101 { |
|
102 |
|
103 iFinished = true; |
|
104 iCond.notify_all(); |
|
105 } |
|
106 TPlacedEntry SymbolGenerator::GetNextPlacedEntry() |
|
107 { |
|
108 TPlacedEntry pe("", "", false); |
|
109 if(1) |
|
110 { |
|
111 boost::mutex::scoped_lock lock(iMutex); |
|
112 while(!iFinished && iQueueFiles.empty()) |
|
113 iCond.wait(lock); |
|
114 if(!iQueueFiles.empty()) |
|
115 { |
|
116 pe = iQueueFiles.front(); |
|
117 iQueueFiles.pop(); |
|
118 } |
|
119 } |
|
120 return pe; |
|
121 } |
|
122 void SymbolGenerator::thrd_func(){ |
|
123 boost::thread_group threads; |
|
124 SymbolWorker worker; |
|
125 for(int i=0; i < gThreadNum; i++) |
|
126 { |
|
127 threads.create_thread(worker); |
|
128 } |
|
129 threads.join_all(); |
|
130 SymbolGenerator::GetInstance()->FlushSymbolFileContent(); |
|
131 } |
|
132 SymbolGenerator::SymbolGenerator() : boost::thread(thrd_func),iFinished(false) { |
|
133 if(gGenBsymbols) |
|
134 { |
|
135 iSymbolType = ESymBsym; |
|
136 } |
|
137 else |
|
138 { |
|
139 iSymbolType = ESymCommon; |
|
140 } |
|
141 } |
|
142 SymbolGenerator::~SymbolGenerator(){ |
|
143 if(joinable()) |
|
144 join(); |
|
145 iSymFile.flush(); |
|
146 iSymFile.close(); |
|
147 } |
|
148 void SymbolGenerator::FlushSymbolFileContent() |
|
149 { |
|
150 if(iSymbolType == ESymCommon) |
|
151 { |
|
152 return; |
|
153 } |
|
154 TBsymHeader tmpBsymHeader; |
|
155 memset(&tmpBsymHeader, 0, sizeof(tmpBsymHeader)); |
|
156 tmpBsymHeader.iMagic[0] = 'B'; |
|
157 tmpBsymHeader.iMagic[1] = 'S'; |
|
158 tmpBsymHeader.iMagic[2] = 'Y'; |
|
159 tmpBsymHeader.iMagic[3] = 'M'; |
|
160 tmpBsymHeader.iMajorVer[0] = BsymMajorVer >> 8; |
|
161 tmpBsymHeader.iMajorVer[1] = BsymMajorVer & 0xff; |
|
162 tmpBsymHeader.iMinorVer[0] = BsymMinorVer >> 8; |
|
163 tmpBsymHeader.iMinorVer[1] = BsymMinorVer & 0xff; |
|
164 if(ByteOrderUtil::IsLittleEndian()) |
|
165 { |
|
166 tmpBsymHeader.iEndiannessFlag = 0; |
|
167 } |
|
168 else |
|
169 { |
|
170 tmpBsymHeader.iEndiannessFlag = 1; |
|
171 } |
|
172 tmpBsymHeader.iCompressionFlag = 1; |
|
173 //count the space for TDbgUnitEntries and TSymbolEntries |
|
174 int fileCount = iMapFileInfoSet.size(); |
|
175 TUint32 sizeNeeded = fileCount * sizeof(TDbgUnitEntry); |
|
176 for(int i = 0; i < fileCount; i++) |
|
177 { |
|
178 sizeNeeded += iMapFileInfoSet[i].iSymbolPCEntrySet.size() * sizeof(TSymbolEntry); |
|
179 } |
|
180 //write string to the temporary memory area |
|
181 MemoryWriter mWriter; |
|
182 mWriter.SetOffset(sizeNeeded); |
|
183 mWriter.SetStringTableStart(sizeNeeded); |
|
184 mWriter.AddEmptyString(); |
|
185 |
|
186 //first to prepare the file info entries TDbgUnitEntry |
|
187 TUint32 startSymbolIndex = 0; |
|
188 for(int i = 0; i < fileCount; i++) |
|
189 { |
|
190 iMapFileInfoSet[i].iDbgUnitPCEntry.iDbgUnitEntry.iStartSymbolIndex = startSymbolIndex; |
|
191 iMapFileInfoSet[i].iDbgUnitPCEntry.iDbgUnitEntry.iPCNameOffset = mWriter.AddString(iMapFileInfoSet[i].iDbgUnitPCEntry.iPCName); |
|
192 iMapFileInfoSet[i].iDbgUnitPCEntry.iDbgUnitEntry.iDevNameOffset = mWriter.AddString(iMapFileInfoSet[i].iDbgUnitPCEntry.iDevName); |
|
193 startSymbolIndex += iMapFileInfoSet[i].iSymbolPCEntrySet.size(); |
|
194 } |
|
195 //second to layout the symbols unit for the mapfile |
|
196 for(int i = 0; i < fileCount; i++) |
|
197 { |
|
198 int symbolcount = iMapFileInfoSet[i].iSymbolPCEntrySet.size(); |
|
199 for(int j =0; j< symbolcount; j++) |
|
200 { |
|
201 iMapFileInfoSet[i].iSymbolPCEntrySet[j].iSymbolEntry.iScopeNameOffset = mWriter.AddScopeName(iMapFileInfoSet[i].iSymbolPCEntrySet[j].iScopeName); |
|
202 iMapFileInfoSet[i].iSymbolPCEntrySet[j].iSymbolEntry.iNameOffset = mWriter.AddString(iMapFileInfoSet[i].iSymbolPCEntrySet[j].iName); |
|
203 iMapFileInfoSet[i].iSymbolPCEntrySet[j].iSymbolEntry.iSecNameOffset = mWriter.AddString(iMapFileInfoSet[i].iSymbolPCEntrySet[j].iSecName); |
|
204 } |
|
205 } |
|
206 |
|
207 //write out the BSym file content |
|
208 char* pstart = mWriter.GetDataPointer(); |
|
209 //write out the map file info |
|
210 int unitlen = sizeof(TDbgUnitEntry); |
|
211 for(int i = 0; i < fileCount; i++) |
|
212 { |
|
213 memcpy(pstart, &iMapFileInfoSet[i].iDbgUnitPCEntry.iDbgUnitEntry, unitlen); |
|
214 pstart += unitlen; |
|
215 } |
|
216 //wirte out the symbol unit info |
|
217 unitlen = sizeof(TSymbolEntry); |
|
218 for(int i = 0; i < fileCount; i++) |
|
219 { |
|
220 int symbolcount = iMapFileInfoSet[i].iSymbolPCEntrySet.size(); |
|
221 for(int j =0; j < symbolcount; j++) |
|
222 { |
|
223 memcpy(pstart, &iMapFileInfoSet[i].iSymbolPCEntrySet[j].iSymbolEntry, unitlen); |
|
224 pstart += unitlen; |
|
225 } |
|
226 } |
|
227 //write out the memory out to the symbol file |
|
228 |
|
229 int totalPages = (mWriter.GetOffset() + ( BSYM_PAGE_SIZE -1)) / 4096; |
|
230 TUint32 compressInfoLength = sizeof(TCompressedHeaderInfo) + sizeof(TPageInfo)*(totalPages -1); |
|
231 char* tmpBuffer = new char[compressInfoLength]; |
|
232 TCompressedHeaderInfo * pCompressedHeaderInfo = (TCompressedHeaderInfo *) tmpBuffer; |
|
233 pCompressedHeaderInfo->iPageSize = BSYM_PAGE_SIZE; |
|
234 pCompressedHeaderInfo->iTotalPageNumber = totalPages; |
|
235 TPageInfo* tmpPage = &pCompressedHeaderInfo->iPages[0]; |
|
236 for(int i = 0; i < totalPages; i++) |
|
237 { |
|
238 tmpPage->iPageStartOffset = i * BSYM_PAGE_SIZE; |
|
239 if(tmpPage->iPageStartOffset + BSYM_PAGE_SIZE < mWriter.GetOffset()) |
|
240 { |
|
241 tmpPage->iPageDataSize = BSYM_PAGE_SIZE; |
|
242 } |
|
243 else |
|
244 { |
|
245 tmpPage->iPageDataSize = mWriter.GetOffset() - tmpPage->iPageStartOffset; |
|
246 } |
|
247 tmpPage++; |
|
248 } |
|
249 |
|
250 //prepare the TBsymHeader, TDbgUnitEntry and TSymbolEntry to the memory |
|
251 tmpBsymHeader.iDbgUnitOffset = sizeof(TBsymHeader) + compressInfoLength; |
|
252 tmpBsymHeader.iDbgUnitCount = fileCount; |
|
253 tmpBsymHeader.iSymbolOffset = fileCount*sizeof(TDbgUnitEntry); |
|
254 tmpBsymHeader.iSymbolCount = startSymbolIndex; |
|
255 tmpBsymHeader.iStringTableOffset = mWriter.GetStringTableStart(); |
|
256 tmpBsymHeader.iStringTableBytes = mWriter.GetOffset() - tmpBsymHeader.iStringTableOffset; |
|
257 tmpBsymHeader.iUncompressSize = mWriter.GetOffset(); |
|
258 //start the compress threads |
|
259 Print(EAlways, "Start compress for Bsymbol file\n"); |
|
260 PageCompressWorker compressWorker(pCompressedHeaderInfo, mWriter.GetDataPointer()); |
|
261 boost::thread_group threads; |
|
262 for(int i=0; i < gThreadNum; i++) |
|
263 { |
|
264 threads.create_thread(compressWorker); |
|
265 } |
|
266 threads.join_all(); |
|
267 Print(EAlways, "Complete compress for Bsymbol file\n"); |
|
268 //pack all the pages together |
|
269 tmpPage = &pCompressedHeaderInfo->iPages[0]; |
|
270 TPageInfo* prePage = NULL; |
|
271 char* pchar = mWriter.GetDataPointer(); |
|
272 for(int i=0; i < totalPages -1; i++) |
|
273 { |
|
274 prePage = tmpPage; |
|
275 tmpPage++; |
|
276 memcpy(pchar + prePage->iPageStartOffset + prePage->iPageDataSize, pchar + tmpPage->iPageStartOffset, tmpPage->iPageDataSize); |
|
277 tmpPage->iPageStartOffset = prePage->iPageStartOffset + prePage->iPageDataSize; |
|
278 |
|
279 } |
|
280 tmpBsymHeader.iCompressedSize = tmpPage->iPageStartOffset + tmpPage->iPageDataSize; |
|
281 mWriter.SetOffset(tmpBsymHeader.iCompressedSize); |
|
282 tmpBsymHeader.iCompressInfoOffset = sizeof(TBsymHeader); |
|
283 |
|
284 iSymFile.write((char*)&tmpBsymHeader, sizeof(TBsymHeader)); |
|
285 iSymFile.write((char*)pCompressedHeaderInfo, compressInfoLength); |
|
286 iSymFile.write(mWriter.GetDataPointer(), mWriter.GetOffset()); |
|
287 delete[] tmpBuffer; |
|
288 for(int i = 0; i < fileCount; i++) |
|
289 { |
|
290 iMapFileInfoSet[i].iSymbolPCEntrySet.clear(); |
|
291 } |
|
292 iMapFileInfoSet.clear(); |
|
293 } |
|
294 |
|
295 SymbolWorker::SymbolWorker() |
|
296 { |
|
297 } |
|
298 SymbolWorker::~SymbolWorker() |
|
299 { |
|
300 } |
|
301 void SymbolWorker::operator()() |
|
302 { |
|
303 SymbolProcessUnit* aSymbolProcessUnit; |
|
304 SymbolGenerator* symbolgenerator = SymbolGenerator::GetInstance(); |
|
305 if(symbolgenerator->GetImageType() == ERomImage) |
|
306 { |
|
307 aSymbolProcessUnit = new CommenRomSymbolProcessUnit(); |
|
308 } |
|
309 else |
|
310 { |
|
311 if(gGenBsymbols) |
|
312 { |
|
313 aSymbolProcessUnit = new BsymRofsSymbolProcessUnit(symbolgenerator); |
|
314 } |
|
315 else |
|
316 { |
|
317 aSymbolProcessUnit = new CommenRofsSymbolProcessUnit(); |
|
318 } |
|
319 } |
|
320 |
|
321 while(1) |
|
322 { |
|
323 if(symbolgenerator->HasFinished() && symbolgenerator->IsEmpty()) |
|
324 { |
|
325 break; |
|
326 } |
|
327 TPlacedEntry pe = symbolgenerator->GetNextPlacedEntry(); |
|
328 if(pe.iFileName.empty()) |
|
329 continue; |
|
330 |
|
331 aSymbolProcessUnit->ProcessEntry(pe); |
|
332 |
|
333 symbolgenerator->LockOutput(); |
|
334 aSymbolProcessUnit->FlushStdOut(cout); |
|
335 aSymbolProcessUnit->FlushSymbolContent(symbolgenerator->GetOutputFileStream()); |
|
336 symbolgenerator->UnlockOutput(); |
|
337 } |
|
338 delete aSymbolProcessUnit; |
|
339 } |
|
340 TCompressedHeaderInfo* PageCompressWorker::pHeaderInfo = NULL; |
|
341 int PageCompressWorker::currentPage = 0; |
|
342 boost::mutex PageCompressWorker::m_mutex; |
|
343 int PageCompressWorker::m_error = 0; |
|
344 char* PageCompressWorker::iChar = NULL; |
|
345 |
|
346 PageCompressWorker::PageCompressWorker(TCompressedHeaderInfo* aHeaderInfo, char* aChar) |
|
347 { |
|
348 pHeaderInfo = aHeaderInfo; |
|
349 iChar = aChar; |
|
350 } |
|
351 |
|
352 PageCompressWorker::~PageCompressWorker() {} |
|
353 void PageCompressWorker::operator()() |
|
354 { |
|
355 int tobecompress = 0; |
|
356 CBytePair bpe; |
|
357 while(1) |
|
358 { |
|
359 m_mutex.lock(); |
|
360 tobecompress =currentPage; |
|
361 currentPage++; |
|
362 m_mutex.unlock(); |
|
363 if(tobecompress >= (int) pHeaderInfo->iTotalPageNumber) |
|
364 break; |
|
365 TPageInfo* current = &pHeaderInfo->iPages[0] + tobecompress; |
|
366 TUint8* in = (TUint8*)(iChar + current->iPageStartOffset); |
|
367 TUint8* out = in; |
|
368 TInt outSize = BytePairCompress(out, in, current->iPageDataSize, &bpe); |
|
369 if(outSize == KErrTooBig) |
|
370 { |
|
371 outSize = BSYM_PAGE_SIZE; |
|
372 } |
|
373 if(outSize < 0) |
|
374 { |
|
375 m_mutex.lock(); |
|
376 m_error = -1; |
|
377 m_mutex.unlock(); |
|
378 break; |
|
379 } |
|
380 current->iPageDataSize = outSize; |
|
381 } |
|
382 |
|
383 } |
|
384 |