1 /* |
|
2 * Copyright (c) 2009 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 "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: Class responsible to parse data files |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "../inc/CATDatParser.h" |
|
20 #include "../inc/CATProject.h" |
|
21 #include "../inc/CATModule2.h" |
|
22 #include "../inc/CATMemoryAddress.h" |
|
23 #include "../inc/catromsymbol.h" |
|
24 |
|
25 // ----------------------------------------------------------------------------- |
|
26 // CATDatParser::CATDatParser |
|
27 // Constructor only for testing! |
|
28 // (No module vector defined so no locating codelines / call stacks) |
|
29 // ----------------------------------------------------------------------------- |
|
30 CATDatParser::CATDatParser() |
|
31 { |
|
32 LOG_FUNC_ENTRY("CATDatParser::CATDatParser"); |
|
33 Construct(); |
|
34 } |
|
35 |
|
36 // ----------------------------------------------------------------------------- |
|
37 // CATDatParser::CATDatParser |
|
38 // Constructor |
|
39 // ----------------------------------------------------------------------------- |
|
40 CATDatParser::CATDatParser(vector<CATModule2*>* pModules ) |
|
41 { |
|
42 LOG_FUNC_ENTRY("CATDatParser::CATDatParser"); |
|
43 Construct(); |
|
44 m_pModules = pModules; |
|
45 } |
|
46 |
|
47 // ----------------------------------------------------------------------------- |
|
48 // CATDatParser::Construct |
|
49 // "Real" constructor |
|
50 // ----------------------------------------------------------------------------- |
|
51 void CATDatParser::Construct() |
|
52 { |
|
53 LOG_FUNC_ENTRY("CATDatParser::Construct"); |
|
54 |
|
55 m_iDataVersion = 1; // Default version of data. |
|
56 m_bDllLoadFound = false; |
|
57 m_bProcessStartFound = false; |
|
58 m_bSubtestOnGoing = false; |
|
59 |
|
60 m_DataSaver.InitXML(); |
|
61 |
|
62 m_eBuildType = -2; |
|
63 m_eProcess_state = not_started; |
|
64 m_eProjectBuildType = -1; |
|
65 |
|
66 m_iCurrentProcessId = 0; |
|
67 m_iLeakNumber = 0; |
|
68 m_iLogLevel = 3; |
|
69 m_iOffSet = 0; |
|
70 |
|
71 m_iPinPointedLeaks = 0; |
|
72 m_iPinPointedSubTestLeaks = 0; |
|
73 m_iSubtestStartHandleCount = 0; |
|
74 m_iSuccesfullRuns = 0; |
|
75 m_iTotalNumberOfLeaks = 0; |
|
76 m_iTotalRuns = 0; |
|
77 |
|
78 m_pRomSymbol = 0; |
|
79 m_pModules = 0; |
|
80 |
|
81 m_sCurrentProcessName = ""; |
|
82 m_sInputFile = ""; |
|
83 m_sInputFileTemp = ""; |
|
84 m_sOutputFile = ""; |
|
85 m_sProjectPlatform = ""; |
|
86 m_vRomSymbolFiles.clear(); |
|
87 m_vDllLoadModList.clear(); |
|
88 m_vDllLoadModListSubTest.clear(); |
|
89 m_vHandleLeaks.clear(); |
|
90 m_vMemoryAddress.clear(); |
|
91 } |
|
92 |
|
93 // ----------------------------------------------------------------------------- |
|
94 // CATDatParser::~CATDatParser |
|
95 // Destructor |
|
96 // ----------------------------------------------------------------------------- |
|
97 CATDatParser::~CATDatParser() |
|
98 { |
|
99 LOG_FUNC_ENTRY("CATDatParser::~CATDatParser"); |
|
100 |
|
101 if ( m_In.is_open() ) |
|
102 m_In.close(); |
|
103 // Delete temporary input file if any |
|
104 if ( !m_sInputFileTemp.empty() ) |
|
105 { |
|
106 if ( FileExists( m_sInputFileTemp.c_str() ) ) |
|
107 FileDelete( m_sInputFileTemp, false ); |
|
108 } |
|
109 // Clean memory addresses if any |
|
110 CleanMemoryAddresses(); |
|
111 // Delete rom symbol. |
|
112 if ( m_pRomSymbol ) |
|
113 { |
|
114 delete m_pRomSymbol; |
|
115 m_pRomSymbol = NULL; |
|
116 } |
|
117 } |
|
118 |
|
119 // ----------------------------------------------------------------------------- |
|
120 // CATDatParser::Analyze |
|
121 // Analyze given data file |
|
122 // ----------------------------------------------------------------------------- |
|
123 int CATDatParser::Analyze() |
|
124 { |
|
125 LOG_FUNC_ENTRY("CATDatParser::Analyze"); |
|
126 // Return if input file not set |
|
127 if ( m_sInputFile.empty() ) |
|
128 return AT_RETURN_CODE::INVALID_DATA_FILE; |
|
129 // If open close first |
|
130 if ( m_In.is_open() ) |
|
131 m_In.close(); |
|
132 // Open file |
|
133 m_In.open( m_sInputFile.c_str() ); |
|
134 if ( ! m_In.good() ) |
|
135 return AT_RETURN_CODE::INVALID_DATA_FILE; |
|
136 try { |
|
137 // If rom symbol file specified. |
|
138 if ( ! m_vRomSymbolFiles.empty() ) |
|
139 { |
|
140 // Create new rom symbol file "parser". |
|
141 m_pRomSymbol = new CATRomSymbol(); |
|
142 m_pRomSymbol->m_bShowProgressMessages = true; |
|
143 // Set symbol files. |
|
144 if ( ! m_pRomSymbol->SetSymbols( m_vRomSymbolFiles ) ) |
|
145 { |
|
146 cout << AT_MSG << "Rom/Rofs symbols error: " << m_pRomSymbol->GetError() << endl; |
|
147 // If file open fails we delete it and will not use it. |
|
148 delete m_pRomSymbol; |
|
149 m_pRomSymbol = NULL; |
|
150 cout << AT_MSG << "Analyze aborted." << endl; |
|
151 return AT_RETURN_CODE::SYMBOL_FILE_ERROR; |
|
152 } |
|
153 } |
|
154 // Return code |
|
155 int iRet = 0; |
|
156 // Clear variables |
|
157 ClearParsingVariables(); |
|
158 // If output defined disable printing |
|
159 if ( ! m_sOutputFile.empty() ) |
|
160 m_DataSaver.SetPrintFlag( false ); |
|
161 // Header |
|
162 Header(); |
|
163 // Parsing |
|
164 iRet = Parse(); |
|
165 // Footer |
|
166 if ( iRet == AT_RETURN_CODE::OK ) |
|
167 Footer(); |
|
168 // If output defined save xml |
|
169 if ( ! m_sOutputFile.empty() ) |
|
170 m_DataSaver.SaveLinesToFile( m_sOutputFile.c_str(), XML_DATA ); |
|
171 // Return |
|
172 return iRet; |
|
173 } catch ( int i ) |
|
174 { |
|
175 cout << AT_MSG << "Error, Analyze failed. : " << i << endl; |
|
176 return AT_RETURN_CODE::UNHANDLED_EXCEPTION; |
|
177 } |
|
178 } |
|
179 // ----------------------------------------------------------------------------- |
|
180 // CATDatParser::Header |
|
181 // Print header of report |
|
182 // ----------------------------------------------------------------------------- |
|
183 void CATDatParser::Header() |
|
184 { |
|
185 LOG_FUNC_ENTRY("CATDatParser::Header"); |
|
186 // Analyze report header |
|
187 m_DataSaver.AddString( "Atool.exe v." ); |
|
188 m_DataSaver.AddString( ATOOL_VERSION ); |
|
189 m_DataSaver.AddString( "\n" ); |
|
190 m_DataSaver.AddString( "Analyzing memory leaks..." ); |
|
191 m_DataSaver.AddLineToLast(); |
|
192 } |
|
193 |
|
194 // ----------------------------------------------------------------------------- |
|
195 // CATDatParser::Footer |
|
196 // Print footer of report |
|
197 // ----------------------------------------------------------------------------- |
|
198 void CATDatParser::Footer() |
|
199 { |
|
200 LOG_FUNC_ENTRY("CATDatParser::Footer"); |
|
201 m_DataSaver.AddString( "\nTotal Runs: " ); |
|
202 m_DataSaver.AddInteger( m_iTotalRuns ); |
|
203 m_DataSaver.AddLineToLast(); |
|
204 |
|
205 int iFailedRuns = m_iTotalRuns - m_iSuccesfullRuns; |
|
206 m_DataSaver.AddString( "Failed Runs: " ); |
|
207 m_DataSaver.AddInteger( iFailedRuns ); |
|
208 m_DataSaver.AddLineToLast(); |
|
209 |
|
210 char cTemp[128]; |
|
211 string sResult( itoa( m_iTotalRuns, cTemp, 10 ) ); |
|
212 sResult.append( ";" ); |
|
213 sResult.append( itoa( iFailedRuns, cTemp, 10 ) ); |
|
214 sResult.append( ";" ); |
|
215 |
|
216 m_DataSaver.SaveXML( sResult, RESULT ); |
|
217 } |
|
218 |
|
219 // ----------------------------------------------------------------------------- |
|
220 // CATDatParser::ClearParsingVariables |
|
221 // Clear/Reset all member variables related to parsing data file |
|
222 // ----------------------------------------------------------------------------- |
|
223 void CATDatParser::ClearParsingVariables() |
|
224 { |
|
225 LOG_FUNC_ENTRY("CATDatParser::ClearParsingVariables"); |
|
226 // Clear variables related to analyze |
|
227 m_eProcess_state = not_started; |
|
228 m_bProcessStartFound = false; |
|
229 m_bDllLoadFound = false; |
|
230 m_iTotalNumberOfLeaks = 0; |
|
231 m_iPinPointedLeaks = 0; |
|
232 m_iLeakNumber = 0; |
|
233 m_iTotalRuns = 0; |
|
234 m_iSuccesfullRuns = 0; |
|
235 m_bSubtestOnGoing = false; |
|
236 m_iSubtestStartHandleCount = 0; |
|
237 CleanMemoryAddresses(); |
|
238 } |
|
239 |
|
240 // ----------------------------------------------------------------------------- |
|
241 // CATDatParser::Parse |
|
242 // Parses data file. Note! header and footer of the report are done in |
|
243 // separate functions. |
|
244 // ----------------------------------------------------------------------------- |
|
245 int CATDatParser::Parse() |
|
246 { |
|
247 LOG_FUNC_ENTRY("CATDatParser::Parse"); |
|
248 // Read all lines |
|
249 char cLine[MAX_LINE_LENGTH]; |
|
250 do |
|
251 { |
|
252 string sLine; |
|
253 try { |
|
254 m_In.getline( cLine, MAX_LINE_LENGTH ); |
|
255 sLine = cLine ; |
|
256 } catch(...) |
|
257 { |
|
258 LOG_STRING( AT_MSG << "Unexpected error, reading data file." ); |
|
259 continue; |
|
260 } |
|
261 if( sLine.find( LABEL_DATA_FILE_VERSION ) != string::npos ) |
|
262 { |
|
263 // Check data file version |
|
264 if( sLine.find( AT_DATA_FILE_VERSION ) == string::npos ) |
|
265 { |
|
266 return AT_RETURN_CODE::WRONG_DATA_FILE_VERSION; |
|
267 } |
|
268 } |
|
269 else if( sLine.find( LABEL_PROCESS_START ) != string::npos ) |
|
270 { |
|
271 if ( ! ParseProcessStart( sLine ) ) |
|
272 return AT_RETURN_CODE::ANALYZE_ERROR; |
|
273 } |
|
274 else if( sLine.find( LABEL_DLL_LOAD ) != string::npos ) |
|
275 { |
|
276 if ( ! ParseDllLoad( sLine ) ) |
|
277 return AT_RETURN_CODE::ANALYZE_ERROR; |
|
278 } |
|
279 else if( sLine.find( LABEL_DLL_UNLOAD ) != string::npos ) |
|
280 { |
|
281 if ( ! ParseDllUnload( sLine ) ) |
|
282 return AT_RETURN_CODE::ANALYZE_ERROR; |
|
283 } |
|
284 else if( sLine.find( LABEL_MEM_LEAK ) != string::npos) |
|
285 { |
|
286 if ( ! ParseMemLeak( sLine ) ) |
|
287 return AT_RETURN_CODE::ANALYZE_ERROR; |
|
288 } |
|
289 else if( sLine.find( LABEL_PROCESS_END ) != string::npos ) |
|
290 { |
|
291 if ( ! ParseProcessEnd( sLine ) ) |
|
292 return AT_RETURN_CODE::ANALYZE_ERROR; |
|
293 } |
|
294 else if( sLine.find( LABEL_ERROR_OCCURED ) != string::npos ) |
|
295 { |
|
296 if ( ! ParseErrorOccured( sLine ) ) |
|
297 return AT_RETURN_CODE::ANALYZE_ERROR; |
|
298 } |
|
299 else if( sLine.find( LABEL_HANDLE_LEAK ) != string::npos ) |
|
300 { |
|
301 if ( ! ParseHandleLeak( sLine ) ) |
|
302 return AT_RETURN_CODE::ANALYZE_ERROR; |
|
303 } |
|
304 else if( sLine.find( LABEL_TEST_START ) != string::npos ) |
|
305 { |
|
306 if ( ! ParseTestStart( sLine ) ) |
|
307 return AT_RETURN_CODE::ANALYZE_ERROR; |
|
308 } |
|
309 else if( sLine.find( LABEL_TEST_END ) != string::npos ) |
|
310 { |
|
311 if ( ! ParseTestEnd( sLine ) ) |
|
312 return AT_RETURN_CODE::ANALYZE_ERROR; |
|
313 } |
|
314 else if( sLine.find( LABEL_LOGGING_CANCELLED ) != string::npos ) |
|
315 { |
|
316 if ( ! ParseLoggingCancelled( sLine ) ) |
|
317 return AT_RETURN_CODE::ANALYZE_ERROR; |
|
318 } |
|
319 } |
|
320 while( m_In.good() ); |
|
321 // Message of failed run if process start was last line in data. |
|
322 if ( m_eProcess_state == ongoing ) |
|
323 { |
|
324 m_DataSaver.AddString( "Test run failed.\n" ); |
|
325 m_DataSaver.AddLineToLast(); |
|
326 } |
|
327 return AT_RETURN_CODE::OK; |
|
328 } |
|
329 |
|
330 // ----------------------------------------------------------------------------- |
|
331 // CATDatParser::ParseProcessStart |
|
332 // ----------------------------------------------------------------------------- |
|
333 bool CATDatParser::ParseProcessStart( string& sLine) |
|
334 { |
|
335 LOG_FUNC_ENTRY("CATDatParser::ParseProcessStart"); |
|
336 if ( m_eProcess_state == ongoing ) |
|
337 { |
|
338 m_DataSaver.AddString( "Test run failed.\n" ); |
|
339 m_DataSaver.AddLineToLast(); |
|
340 } |
|
341 m_eProcess_state = ongoing; |
|
342 m_bProcessStartFound = true; |
|
343 |
|
344 // Clear handle leaks |
|
345 m_vHandleLeaks.clear(); |
|
346 // Increment runs |
|
347 m_iTotalRuns++; |
|
348 // Clean leak count |
|
349 m_iTotalNumberOfLeaks = 0; |
|
350 // Clean pin pointed leaks count. |
|
351 m_iPinPointedLeaks = 0; |
|
352 // Clean leak number |
|
353 m_iLeakNumber = 0; |
|
354 |
|
355 // Clean loaded mods |
|
356 m_vDllLoadModList.clear(); |
|
357 m_vDllLoadModListSubTest.clear(); |
|
358 |
|
359 // Skip text PROCESS_START |
|
360 GetStringUntilNextSpace( sLine ); |
|
361 // Get process name |
|
362 m_sCurrentProcessName = GetStringUntilNextSpace( sLine ); |
|
363 // Get Pid |
|
364 string sPid = GetStringUntilNextSpace( sLine ); |
|
365 m_iCurrentProcessId = _httoi( sPid.c_str() ); |
|
366 |
|
367 // Header for process tart |
|
368 m_DataSaver.AddString( "\n--------------------------------\n" ); |
|
369 m_DataSaver.AddString( "Test Run start (" ); |
|
370 m_DataSaver.AddString( m_sCurrentProcessName.c_str() ); |
|
371 m_DataSaver.AddString( "): " ); |
|
372 |
|
373 // Get start time |
|
374 string sTime = GetStringUntilNextSpace( sLine ); |
|
375 sTime = ConvertTimeToLocalTime( sTime ); |
|
376 m_DataSaver.AddString( sTime.c_str() ); |
|
377 |
|
378 // Create data for xml |
|
379 string sData( sTime ); |
|
380 sData.append( ";" ); |
|
381 |
|
382 // Build mode UDEB/UREL. |
|
383 string sBuildType = GetStringUntilNextSpace( sLine ); |
|
384 |
|
385 m_DataSaver.AddString( " Build target: " ); |
|
386 if( sBuildType.compare( "0" ) == 0 ) |
|
387 { |
|
388 m_eBuildType = CATProject::UREL; |
|
389 } |
|
390 else if( sBuildType.compare( "1" ) == 0 ) |
|
391 { |
|
392 m_eBuildType = CATProject::UDEB; |
|
393 } |
|
394 m_DataSaver.AddString( CATProject::GetBuildTypeString( m_eBuildType ).c_str() ); |
|
395 |
|
396 // Version. |
|
397 string sVersion = GetStringUntilNextSpace( sLine ); |
|
398 unsigned int iVer = 0; |
|
399 if ( hexToDec( sVersion, iVer ) && iVer != 0 ) |
|
400 m_iDataVersion = iVer; |
|
401 |
|
402 // End line in data. |
|
403 m_DataSaver.AddLineToLast(); |
|
404 |
|
405 // xml |
|
406 sData.append( CATProject::GetBuildTypeString( m_eBuildType ) ); |
|
407 sData.append( ";" ); |
|
408 sData.append( m_sCurrentProcessName ); |
|
409 m_DataSaver.SaveXML( sData, RUN ); |
|
410 |
|
411 // If projects platform defined check that it is same in data. (future feature). |
|
412 if ( ! m_sProjectPlatform.empty() ) |
|
413 { |
|
414 // If platform info is added to data file do check here. |
|
415 } |
|
416 // If projects build type defined check that it is same in data. |
|
417 if ( m_eProjectBuildType != -1 ) |
|
418 { |
|
419 if ( m_eBuildType != m_eProjectBuildType ) |
|
420 { |
|
421 string sError(AT_MSG); |
|
422 sError.append( "Error, analyzed data has build type of " ); |
|
423 sError.append( CATProject::GetBuildTypeString( m_eBuildType ) ); |
|
424 sError.append( " and project has build type " ); |
|
425 sError.append( CATProject::GetBuildTypeString( m_eProjectBuildType ) ); |
|
426 sError.append( ". Pinpointed code lines are not valid." ); |
|
427 m_DataSaver.AddString( sError.c_str(), false ); |
|
428 m_DataSaver.AddLineToLast(); |
|
429 } |
|
430 } |
|
431 return true; |
|
432 } |
|
433 |
|
434 // ----------------------------------------------------------------------------- |
|
435 // CATDatParser::ParseProcessEnd |
|
436 // ----------------------------------------------------------------------------- |
|
437 bool CATDatParser::ParseProcessEnd( string& sLine ) |
|
438 { |
|
439 LOG_FUNC_ENTRY("CATDatParser::ParseProcessEnd"); |
|
440 GetStringUntilNextSpace( sLine ); |
|
441 |
|
442 // Get process id |
|
443 string sProcessID = GetStringUntilNextSpace( sLine ); |
|
444 unsigned long iProcessID = _httoi( sProcessID.c_str() ); |
|
445 |
|
446 // Get time |
|
447 string sTime = GetStringUntilNextSpace( sLine ); |
|
448 |
|
449 // Convert leak time |
|
450 sTime = ConvertTimeToLocalTime( sTime ); |
|
451 |
|
452 // Process started? |
|
453 if( iProcessID == m_iCurrentProcessId ) |
|
454 { |
|
455 m_iSuccesfullRuns++; |
|
456 m_DataSaver.AddLineToLast(); |
|
457 m_DataSaver.AddString( "Test Run end (" ); |
|
458 m_DataSaver.AddString( m_sCurrentProcessName.c_str() ); |
|
459 m_DataSaver.AddString( "): " ); |
|
460 m_DataSaver.AddString( sTime.c_str() ); |
|
461 m_DataSaver.AddLineToLast(); |
|
462 m_DataSaver.AddString( "Build target: " ); |
|
463 m_DataSaver.AddString( CATProject::GetBuildTypeString( m_eBuildType ).c_str() ); |
|
464 m_DataSaver.AddLineToLast(); |
|
465 |
|
466 m_eProcess_state = stopped; |
|
467 // Number of leaks |
|
468 if ( m_iLogLevel == 1 || m_iLogLevel == 2 ) |
|
469 { |
|
470 if ( m_iPinPointedLeaks > 0 ) |
|
471 { |
|
472 m_DataSaver.AddInteger( m_iPinPointedLeaks ); |
|
473 m_DataSaver.AddString( " number of pinpointed memory leak(s)." ); |
|
474 m_DataSaver.AddLineToLast(); |
|
475 } |
|
476 m_DataSaver.AddInteger( m_iLeakNumber ); |
|
477 m_DataSaver.AddString( " total number of memory leak(s)." ); |
|
478 m_DataSaver.AddLineToLast(); |
|
479 } |
|
480 else |
|
481 { |
|
482 m_DataSaver.AddInteger( m_iTotalNumberOfLeaks ); |
|
483 m_DataSaver.AddString( " memory leak(s) found." ); |
|
484 m_DataSaver.AddLineToLast(); |
|
485 } |
|
486 |
|
487 // xml |
|
488 char cTemp[128]; |
|
489 m_DataSaver.SaveXML( itoa( m_iTotalNumberOfLeaks, cTemp, 10 ) , MEM_LEAKS ); |
|
490 |
|
491 // Print all modules which have leaks |
|
492 for( size_t i = 0 ; i < m_vDllLoadModList.size() ; i++ ) |
|
493 { |
|
494 if( m_vDllLoadModList.at(i).iLeaks > 0 ) |
|
495 { |
|
496 m_DataSaver.AddInteger( m_vDllLoadModList.at(i).iLeaks ); |
|
497 m_DataSaver.AddString( " memory leak(s) in module: " ); |
|
498 m_DataSaver.AddString( m_vDllLoadModList.at(i).sModuleName.c_str() ); |
|
499 m_DataSaver.AddLineToLast(); |
|
500 |
|
501 // xml |
|
502 string sModuleNameAndLeaks( m_vDllLoadModList[i].sModuleName ); |
|
503 sModuleNameAndLeaks.append(";"); |
|
504 sModuleNameAndLeaks.append( itoa( m_vDllLoadModList[i].iLeaks, cTemp, 10 ) ); |
|
505 m_DataSaver.SaveXML( sModuleNameAndLeaks , MEM_LEAK_MODULE ); |
|
506 } |
|
507 } |
|
508 |
|
509 if ( m_vHandleLeaks.size() > 0 ) |
|
510 { |
|
511 // We have handle leaks |
|
512 bool bHandLeaksFound = false; |
|
513 int iTotalNrOfLeaks = 0; |
|
514 // Print handle leaks |
|
515 for( size_t i = 0 ; i < m_vHandleLeaks.size() ; i++ ) |
|
516 { |
|
517 string sTempHandleLeak( m_vHandleLeaks[i] ); |
|
518 // Name. |
|
519 string sHandleLeakModule( GetStringUntilNextSpace( sTempHandleLeak ) ); |
|
520 // Count. |
|
521 string sNrOfLeaks( GetStringUntilNextSpace(sTempHandleLeak) ); |
|
522 unsigned long iNrOfLeaks = _httoi( sNrOfLeaks.c_str() ); |
|
523 iTotalNrOfLeaks += iNrOfLeaks; |
|
524 if( iNrOfLeaks ) |
|
525 { |
|
526 if( !bHandLeaksFound ) |
|
527 { |
|
528 m_DataSaver.SaveXML( sNrOfLeaks , HANDLE_LEAKS ); |
|
529 } |
|
530 bHandLeaksFound = true; |
|
531 m_DataSaver.AddInteger( iNrOfLeaks ); |
|
532 // Just print out how many leaks found. |
|
533 // Because its always unknown. |
|
534 m_DataSaver.AddString( " handle leak(s) found." ); |
|
535 m_DataSaver.AddLineToLast(); |
|
536 |
|
537 // xml |
|
538 string sXMLInfo( sHandleLeakModule ); |
|
539 sXMLInfo.append( ";" ); sXMLInfo.append( sNrOfLeaks ); |
|
540 m_DataSaver.SaveXML( sXMLInfo , HANDLE_LEAK_MODULE ); |
|
541 } |
|
542 } |
|
543 // Update number if handle leaks |
|
544 m_DataSaver.SaveXML( itoa( iTotalNrOfLeaks, cTemp, 10 ) , HANDLE_LEAKS ); |
|
545 if( !bHandLeaksFound ) |
|
546 { |
|
547 //m_DataSaver.AddLineToLast(); |
|
548 m_DataSaver.AddString( TEXT_NO_HANDLE_LEAKS ); |
|
549 m_DataSaver.AddLineToLast(); |
|
550 } |
|
551 } |
|
552 else |
|
553 { |
|
554 // No handle leaks |
|
555 m_DataSaver.AddLineToLast(); |
|
556 m_DataSaver.AddString( TEXT_NO_HANDLE_LEAKS ); |
|
557 m_DataSaver.AddLineToLast(); |
|
558 } |
|
559 |
|
560 // Process end to xml |
|
561 m_DataSaver.SaveXML( sTime, RUN_END ); |
|
562 // Reset current process |
|
563 m_iCurrentProcessId = 0; |
|
564 } |
|
565 |
|
566 // If no dll load or process start found |
|
567 if ( ! m_bProcessStartFound || !m_bDllLoadFound ) |
|
568 { |
|
569 m_DataSaver.AddLineToLast(); |
|
570 m_DataSaver.AddString( AT_ANALYZE_INSUFFICIENT_LOGGING_DATA ); |
|
571 m_DataSaver.AddLineToLast(); |
|
572 } |
|
573 |
|
574 return true; |
|
575 } |
|
576 |
|
577 // ----------------------------------------------------------------------------- |
|
578 // CATDatParser::ParseDllLoad |
|
579 // ----------------------------------------------------------------------------- |
|
580 bool CATDatParser::ParseDllLoad( string& sLine ) |
|
581 { |
|
582 LOG_FUNC_ENTRY("CATDatParser::ParseDllLoad"); |
|
583 //DLL_LOAD <DLL name> <Time stamp> <Memory start address> <Memory end address> |
|
584 m_bDllLoadFound = true; |
|
585 DLL_LOAD_INFO structDllInfo; |
|
586 structDllInfo.iStartAddress = 0; |
|
587 structDllInfo.iEndAddress = 0; |
|
588 structDllInfo.iLeaks = 0; |
|
589 |
|
590 // Skip "DLL_LOAD " |
|
591 GetStringUntilNextSpace( sLine ); |
|
592 |
|
593 // Get module name |
|
594 structDllInfo.sModuleName = GetStringUntilNextSpace( sLine ); |
|
595 ChangeToLower( structDllInfo.sModuleName ); |
|
596 |
|
597 // Create module from this if project platform emulator |
|
598 if ( _stricmp( "winscw", m_sProjectPlatform.c_str() ) == 0 ) |
|
599 CreateWinscwModule( structDllInfo.sModuleName ); |
|
600 |
|
601 if ( m_iDataVersion >= AT_DLL_TIMESTAMP_DATA_VERSION ) |
|
602 { |
|
603 // Pickup module loading time. |
|
604 string sLoadTime = GetStringUntilNextSpace( sLine ); |
|
605 unsigned long long ull; |
|
606 if ( hexToDec( sLoadTime, ull ) ) |
|
607 structDllInfo.iLoadTime = ull; |
|
608 } |
|
609 |
|
610 // Get dll start memory string address from line |
|
611 // Convert string address to real memory address |
|
612 structDllInfo.iStartAddress = |
|
613 _httoi( GetStringUntilNextSpace( sLine ).c_str() ); |
|
614 |
|
615 // Get dll end memory string address from line |
|
616 // Convert string address to real memory address |
|
617 structDllInfo.iEndAddress = |
|
618 _httoi( |
|
619 GetStringUntilNextSpace( sLine ).c_str() ); |
|
620 |
|
621 // Is module already loaded, if not add it to list. |
|
622 bool bFound = false; |
|
623 for( vector<DLL_LOAD_INFO>::iterator it = m_vDllLoadModList.begin(); |
|
624 it != m_vDllLoadModList.end() ; it++ ) |
|
625 { |
|
626 if( (*it).sModuleName.compare( structDllInfo.sModuleName ) == 0 ) |
|
627 { |
|
628 bFound = true; |
|
629 break; |
|
630 } |
|
631 } |
|
632 if( ! bFound ) |
|
633 m_vDllLoadModList.push_back( structDllInfo ); |
|
634 |
|
635 // Sub test module list. |
|
636 bFound = false; |
|
637 for( vector<DLL_LOAD_INFO>::iterator it = m_vDllLoadModListSubTest.begin(); |
|
638 it != m_vDllLoadModListSubTest.end() ; it++ ) |
|
639 { |
|
640 if( (*it).sModuleName.compare( structDllInfo.sModuleName ) == 0 ) |
|
641 { |
|
642 bFound = true; |
|
643 break; |
|
644 } |
|
645 } |
|
646 if( ! bFound ) |
|
647 m_vDllLoadModListSubTest.push_back( structDllInfo ); |
|
648 |
|
649 return true; |
|
650 } |
|
651 |
|
652 // ----------------------------------------------------------------------------- |
|
653 // CATDatParser::ParseDllUnload |
|
654 // ----------------------------------------------------------------------------- |
|
655 bool CATDatParser::ParseDllUnload( string& sLine ) |
|
656 { |
|
657 LOG_FUNC_ENTRY("CATDatParser::ParseDllUnload"); |
|
658 |
|
659 // Ignore unloads on older version because no timestamps. |
|
660 if ( m_iDataVersion < AT_DLL_TIMESTAMP_DATA_VERSION ) |
|
661 { |
|
662 return true; |
|
663 } |
|
664 |
|
665 // Skip "DLL_UNLOAD " |
|
666 GetStringUntilNextSpace( sLine ); |
|
667 |
|
668 // Get module name |
|
669 string sModuleName = GetStringUntilNextSpace( sLine ); |
|
670 ChangeToLower( sModuleName ); |
|
671 |
|
672 // Unload time |
|
673 unsigned long long ull; |
|
674 string sUnload = GetStringUntilNextSpace( sLine ); |
|
675 if ( ! hexToDec( sUnload, ull ) ) |
|
676 return true; |
|
677 |
|
678 // Set module unload time. |
|
679 vector<DLL_LOAD_INFO>::iterator it; |
|
680 for( it = m_vDllLoadModList.begin() ; it != m_vDllLoadModList.end() ; it++ ) |
|
681 { |
|
682 if ( sModuleName.compare( it->sModuleName ) == 0 ) |
|
683 { |
|
684 (*it).iUnloadTime = ull; |
|
685 break; |
|
686 } |
|
687 } |
|
688 for( it = m_vDllLoadModListSubTest.begin() ; it != m_vDllLoadModListSubTest.end() ; it++ ) |
|
689 { |
|
690 if ( sModuleName.compare( it->sModuleName ) == 0 ) |
|
691 { |
|
692 (*it).iUnloadTime = ull; |
|
693 break; |
|
694 } |
|
695 } |
|
696 return true; |
|
697 } |
|
698 // ----------------------------------------------------------------------------- |
|
699 // CATDatParser::ParseLoggingCancelled |
|
700 // ----------------------------------------------------------------------------- |
|
701 bool CATDatParser::ParseLoggingCancelled( string& sLine ) |
|
702 { |
|
703 LOG_FUNC_ENTRY("CATDatParser::ParseLoggingCancelled"); |
|
704 // Skip text "LOGGING_CANCELLED" |
|
705 GetStringUntilNextSpace( sLine ); |
|
706 |
|
707 // Get time |
|
708 string sTime( GetStringUntilNextSpace( sLine ) ); |
|
709 sTime = ConvertTimeToLocalTime( sTime ); |
|
710 m_DataSaver.AddString( "Logging Cancelled." ); |
|
711 m_DataSaver.AddLineToLast(); |
|
712 return true; |
|
713 } |
|
714 |
|
715 // ----------------------------------------------------------------------------- |
|
716 // CATDatParser::ParseHandleLeak |
|
717 // ----------------------------------------------------------------------------- |
|
718 bool CATDatParser::ParseHandleLeak( string& sLine ) |
|
719 { |
|
720 LOG_FUNC_ENTRY("CATDatParser::ParseHandleLeak"); |
|
721 // Skip text "HANDLE_LEAK" |
|
722 GetStringUntilNextSpace( sLine ); |
|
723 m_vHandleLeaks.push_back( sLine ); |
|
724 return true; |
|
725 } |
|
726 |
|
727 // ----------------------------------------------------------------------------- |
|
728 // CATDatParser::ParseTestStart |
|
729 // ----------------------------------------------------------------------------- |
|
730 bool CATDatParser::ParseTestStart( string& sLine ) |
|
731 { |
|
732 LOG_FUNC_ENTRY("CATDatParser::ParseTestStart"); |
|
733 m_bSubtestOnGoing = true; |
|
734 m_iLeakNumber = 0; |
|
735 m_iPinPointedSubTestLeaks = 0; |
|
736 |
|
737 // Reset subtest leaked modules list |
|
738 for( size_t i = 0 ; i < m_vDllLoadModListSubTest.size() ; i++ ) |
|
739 { |
|
740 m_vDllLoadModListSubTest.at(i).iLeaks = 0; |
|
741 } |
|
742 |
|
743 // Skip text "TEST_START" |
|
744 GetStringUntilNextSpace( sLine ); |
|
745 // Time |
|
746 string sTime( GetStringUntilNextSpace( sLine ) ); |
|
747 sTime = ConvertTimeToLocalTime( sTime ); |
|
748 // Name |
|
749 string sSubTestName( GetStringUntilNextSpace( sLine ) ); |
|
750 m_DataSaver.AddLineToLast(); |
|
751 |
|
752 // Get handle count in subtest start |
|
753 string sSubTestStartHandleCount( GetStringUntilNextSpace( sLine ) ); |
|
754 m_iSubtestStartHandleCount = atoi( sSubTestStartHandleCount.c_str() ); |
|
755 |
|
756 // Add start to report |
|
757 m_DataSaver.AddString( "\nSub test (" ); |
|
758 m_DataSaver.AddString( sSubTestName.c_str() ); |
|
759 m_DataSaver.AddString( ") start: " ); |
|
760 m_DataSaver.AddString( sTime.c_str() ); |
|
761 |
|
762 // m_DataSaver.AddLineToLast(); |
|
763 |
|
764 // Add start to xml |
|
765 string sResult( sSubTestName ); |
|
766 sResult.append( ";" ); |
|
767 sResult.append( sTime ); |
|
768 sResult.append( ";" ); |
|
769 m_DataSaver.SaveXML( sResult, TEST_START ); |
|
770 return true; |
|
771 } |
|
772 |
|
773 // ----------------------------------------------------------------------------- |
|
774 // CATDatParser::ParseTestEnd |
|
775 // ----------------------------------------------------------------------------- |
|
776 bool CATDatParser::ParseTestEnd( string& sLine ) |
|
777 { |
|
778 LOG_FUNC_ENTRY("CATDatParser::ParseTestEnd"); |
|
779 // Skip text "TEST_END" |
|
780 GetStringUntilNextSpace( sLine ); |
|
781 |
|
782 // Time |
|
783 string sTime( GetStringUntilNextSpace( sLine ) ); |
|
784 sTime = ConvertTimeToLocalTime( sTime ); |
|
785 |
|
786 // Name |
|
787 string sSubTestName( GetStringUntilNextSpace( sLine ) ); |
|
788 m_DataSaver.AddLineToLast(); |
|
789 |
|
790 // Add test end info to report |
|
791 m_DataSaver.AddString( "Sub test (" ); |
|
792 m_DataSaver.AddString( sSubTestName.c_str() ); |
|
793 m_DataSaver.AddString( ") end: " ); |
|
794 m_DataSaver.AddString( sTime.c_str() ); |
|
795 m_DataSaver.AddLineToLast(); |
|
796 |
|
797 // Leak count to report in subtest |
|
798 if( m_iLeakNumber > 0 ) |
|
799 { |
|
800 if ( m_iLogLevel == 1 || m_iLogLevel == 2 ) |
|
801 { |
|
802 m_DataSaver.AddInteger( m_iPinPointedSubTestLeaks ); |
|
803 m_DataSaver.AddString( " number of pinpointed memory leaks." ); |
|
804 m_DataSaver.AddLineToLast(); |
|
805 m_DataSaver.AddInteger( m_iLeakNumber ); |
|
806 m_DataSaver.AddString( " memory leaks found." ); |
|
807 } |
|
808 else |
|
809 { |
|
810 m_DataSaver.AddInteger( m_iLeakNumber ); |
|
811 m_DataSaver.AddString( " memory leaks found." ); |
|
812 } |
|
813 } |
|
814 else |
|
815 { |
|
816 m_DataSaver.AddString( "No memory leaks found." ); |
|
817 } |
|
818 m_DataSaver.AddLineToLast(); |
|
819 |
|
820 // Use sTime to store info to xml |
|
821 sTime.append(";"); |
|
822 char cTemp[128]; |
|
823 // Print all modules whitch have leaks |
|
824 for( unsigned int i = 0 ; i < m_vDllLoadModListSubTest.size() ; i++ ) |
|
825 { |
|
826 if( m_vDllLoadModListSubTest.at(i).iLeaks > 0 ) |
|
827 { |
|
828 // Normal report |
|
829 m_DataSaver.AddInteger( m_vDllLoadModListSubTest[i].iLeaks ); |
|
830 m_DataSaver.AddString( " memory leaks in module: " ); |
|
831 m_DataSaver.AddString( m_vDllLoadModListSubTest.at(i).sModuleName.c_str() ); |
|
832 m_DataSaver.AddLineToLast(); |
|
833 // xml |
|
834 string sModuleNameAndLeaks( m_vDllLoadModListSubTest.at(i).sModuleName ); |
|
835 sModuleNameAndLeaks.append(";"); |
|
836 sModuleNameAndLeaks.append( itoa( m_vDllLoadModListSubTest.at(i).iLeaks, cTemp, 10 ) ); |
|
837 m_DataSaver.SaveXML( sModuleNameAndLeaks , SUBTEST_MEM_LEAK_MODULE ); |
|
838 } |
|
839 } |
|
840 // Handle count |
|
841 int iEndHandleCount = atoi( GetStringUntilNextSpace( sLine ).c_str() ); |
|
842 // Is there handle leaks in subtest? |
|
843 if( iEndHandleCount > m_iSubtestStartHandleCount ) |
|
844 { |
|
845 // Print normal report |
|
846 m_DataSaver.AddInteger( iEndHandleCount - m_iSubtestStartHandleCount ); |
|
847 m_DataSaver.AddString( " handle leaks in subtest: " ); |
|
848 m_DataSaver.AddString( sSubTestName.c_str() ); |
|
849 m_DataSaver.AddString( "." ); |
|
850 m_DataSaver.AddLineToLast(); |
|
851 |
|
852 // Print handle leaks to XML |
|
853 string sNrOfHandleLeaks( itoa( iEndHandleCount - m_iSubtestStartHandleCount, cTemp, 10 ) ); |
|
854 sNrOfHandleLeaks.append( ";" ); |
|
855 m_DataSaver.SaveXML( sNrOfHandleLeaks, SUBTEST_HANDLE_LEAKS ); |
|
856 } |
|
857 else |
|
858 { |
|
859 // No handle leaks |
|
860 m_DataSaver.AddString( TEXT_NO_HANDLE_LEAKS ); |
|
861 m_DataSaver.AddLineToLast(); |
|
862 } |
|
863 // Save xml |
|
864 m_DataSaver.SaveXML( sTime, TEST_END ); |
|
865 // Back to normal leaks |
|
866 m_bSubtestOnGoing = false; |
|
867 return true; |
|
868 } |
|
869 |
|
870 // ----------------------------------------------------------------------------- |
|
871 // CATDatParser::ParseErrorOccured |
|
872 // ----------------------------------------------------------------------------- |
|
873 bool CATDatParser::ParseErrorOccured( string& sLine ) |
|
874 { |
|
875 LOG_FUNC_ENTRY("CATDatParser::ParseErrorOccured"); |
|
876 string sTime,sError; |
|
877 |
|
878 // Skip text "ERROR_OCCURED:" |
|
879 GetStringUntilNextSpace( sLine ); |
|
880 |
|
881 // Get error |
|
882 sError = GetStringUntilNextSpace( sLine ); |
|
883 // Get and convert error time |
|
884 sTime = GetStringUntilNextSpace( sLine ); |
|
885 sTime = ConvertTimeToLocalTime( sTime ); |
|
886 |
|
887 // Print error line |
|
888 m_DataSaver.AddLineToLast(); |
|
889 m_DataSaver.AddString( "Error occured on: " ); |
|
890 m_DataSaver.AddString( sTime.c_str() ); |
|
891 m_DataSaver.AddString( ". " ); |
|
892 m_DataSaver.AddString( "Symbian error code: " ); |
|
893 m_DataSaver.AddString( sError.c_str() ); |
|
894 m_DataSaver.AddString( "." ); |
|
895 m_DataSaver.AddLineToLast(); |
|
896 |
|
897 return true; |
|
898 } |
|
899 |
|
900 // ----------------------------------------------------------------------------- |
|
901 // CATDatParser::ParseMemLeak |
|
902 // ----------------------------------------------------------------------------- |
|
903 bool CATDatParser::ParseMemLeak( string& sLine ) |
|
904 { |
|
905 LOG_FUNC_ENTRY("CATDatParser::ParseMemLeak"); |
|
906 // Increment leak count |
|
907 if ( ! m_bSubtestOnGoing ) |
|
908 m_iTotalNumberOfLeaks++; |
|
909 |
|
910 // Increase leak number |
|
911 m_iLeakNumber++; |
|
912 |
|
913 // Leak data variables |
|
914 string sModuleName; |
|
915 string sLeakSize; |
|
916 string sTime; |
|
917 unsigned long long iTime = 0; |
|
918 string sLeakAddress; |
|
919 |
|
920 // Skip text "MEM_LEAK" |
|
921 GetStringUntilNextSpace( sLine ); |
|
922 // Get leak address |
|
923 sLeakAddress = GetStringUntilNextSpace( sLine ); |
|
924 // Get time |
|
925 sTime = GetStringUntilNextSpace( sLine ); |
|
926 // Convert time to decimal |
|
927 hexToDec( sTime, iTime ); |
|
928 // Get memory reserve size |
|
929 sLeakSize = GetStringUntilNextSpace( sLine ); |
|
930 // Convert leak time |
|
931 sTime = ConvertTimeToLocalTime( sTime ); |
|
932 |
|
933 // Loop thru call stack and put memory addresses in vector |
|
934 CleanMemoryAddresses(); // Clean memory address vector |
|
935 CATMemoryAddress* pMemAddr = 0; |
|
936 vector<string> vStrings = ParseStringToVector( sLine, ' ' ); |
|
937 for( size_t i = 0; i < vStrings.size() ; i++ ) |
|
938 { |
|
939 pMemAddr = new CATMemoryAddress( vStrings.at(i), m_iOffSet ); |
|
940 // Set address time |
|
941 pMemAddr->SetTime( iTime ); |
|
942 // Set address module name |
|
943 if ( pMemAddr->FindSetModuleName( &m_vDllLoadModList ) ) |
|
944 { |
|
945 // Increment leaks in module once |
|
946 if ( sModuleName.empty() ) |
|
947 { |
|
948 if ( m_bSubtestOnGoing ) |
|
949 m_vDllLoadModListSubTest.at( pMemAddr->GetDllLoadInfoIndex() ).iLeaks++; |
|
950 else |
|
951 m_vDllLoadModList.at( pMemAddr->GetDllLoadInfoIndex() ).iLeaks++; |
|
952 // Set leak's module where it was located. |
|
953 sModuleName = pMemAddr->GetModuleName(); |
|
954 } |
|
955 } |
|
956 // Add it to vector |
|
957 m_vMemoryAddress.push_back( pMemAddr ); |
|
958 } |
|
959 // If logging level is 0 Skip printing / locating code lines for call stack items. |
|
960 if ( m_iLogLevel == 0 ) |
|
961 return true; |
|
962 if ( m_pModules && vStrings.size() > 0 ) |
|
963 { |
|
964 // Have we successfully located code line for memory address |
|
965 bool bSuccesfullAddressToLine = false; |
|
966 for( size_t x = 0; x < m_vMemoryAddress.size(); x++ ) |
|
967 { |
|
968 int iIndexInDll = m_vMemoryAddress.at( x )->GetDllLoadInfoIndex(); |
|
969 if ( iIndexInDll != -1 ) |
|
970 { |
|
971 // Dll module name from data file |
|
972 string sDllName = m_vDllLoadModList.at( iIndexInDll ).sModuleName; |
|
973 // Find module from project. These are read from makefiles. |
|
974 for ( size_t y = 0; y < m_pModules->size() ; y++ ) |
|
975 { |
|
976 // Module name from project data (makefiles) |
|
977 string sModuleName = m_pModules->at( y )->GetBinaryName(); |
|
978 // If we find module from project ones, use it to located code line for memory address |
|
979 // Note! dll names can be pretty messy i.e. DLL_LOAD 10281fc6.dll{000a0000}[10281fc6] 81d57b88 81e60a90 |
|
980 if ( sDllName.find( sModuleName ) != string::npos ) |
|
981 { |
|
982 m_pModules->at( y )->AddressToLine( m_vMemoryAddress.at( x ) ); |
|
983 if ( ! bSuccesfullAddressToLine ) |
|
984 { |
|
985 int iPPState = m_vMemoryAddress.at( x )->GetAddressToLineState(); |
|
986 if ( iPPState == CATMemoryAddress::EXACT || iPPState == CATMemoryAddress::FUNCTION ) |
|
987 { |
|
988 bSuccesfullAddressToLine = true; |
|
989 if ( m_bSubtestOnGoing ) |
|
990 m_iPinPointedSubTestLeaks++; |
|
991 else |
|
992 m_iPinPointedLeaks++; |
|
993 } |
|
994 } |
|
995 } |
|
996 } |
|
997 } |
|
998 } |
|
999 // If rom/rofs specified we use it to try get binary and function names |
|
1000 // for addresses currently out of process range. |
|
1001 if ( m_pRomSymbol ) |
|
1002 { |
|
1003 for( size_t x = 0; x < m_vMemoryAddress.size(); x++ ) |
|
1004 { |
|
1005 if ( m_vMemoryAddress.at(x)->GetAddressToLineState() == CATMemoryAddress::OUT_OF_PROCESS |
|
1006 || m_vMemoryAddress.at(x)->GetAddressToLineState() == CATMemoryAddress::OUT_OF_RANGE ) |
|
1007 { |
|
1008 m_pRomSymbol->AddressToLine( m_vMemoryAddress.at(x) ); |
|
1009 } |
|
1010 } |
|
1011 } |
|
1012 } |
|
1013 // Print leak |
|
1014 PrintMemLeak( sTime, sLeakSize, sLeakAddress, sModuleName); |
|
1015 return true; |
|
1016 } |
|
1017 |
|
1018 // ----------------------------------------------------------------------------- |
|
1019 // CATDatParser::PrintMemLeak |
|
1020 // ----------------------------------------------------------------------------- |
|
1021 void CATDatParser::PrintMemLeak(const string& sTime, |
|
1022 const string& sLeakSize, |
|
1023 const string& sLeakAddr, |
|
1024 const string& sModuleName) |
|
1025 { |
|
1026 LOG_FUNC_ENTRY("CATDatParser::PrintMemLeak"); |
|
1027 // Print header data of leak |
|
1028 m_DataSaver.AddString("\nMemory leak "); |
|
1029 m_DataSaver.AddInteger( m_iLeakNumber, true); |
|
1030 |
|
1031 // Leak size |
|
1032 m_DataSaver.AddString( " (" ); |
|
1033 m_DataSaver.AddInteger( _httoi( sLeakSize.c_str() ), true ); |
|
1034 m_DataSaver.AddString( " bytes) " ); |
|
1035 |
|
1036 // Leak address |
|
1037 m_DataSaver.AddString("(0x"); |
|
1038 m_DataSaver.AddString( sLeakAddr.c_str(), true ); |
|
1039 m_DataSaver.AddString( ") " ); |
|
1040 |
|
1041 // Time |
|
1042 m_DataSaver.AddString( sTime.c_str(), true ); |
|
1043 m_DataSaver.AddString( " " ); |
|
1044 |
|
1045 // Module name |
|
1046 m_DataSaver.AddString( sModuleName.c_str(), true ); |
|
1047 m_DataSaver.SaveCarbideDataHeader(); |
|
1048 |
|
1049 // Add header line |
|
1050 m_DataSaver.AddLineToLast(); |
|
1051 |
|
1052 // Print the call stack items |
|
1053 for( size_t i = 0 ; i < m_vMemoryAddress.size() ; i++ ) |
|
1054 { |
|
1055 // On log levels 1 & 2 we only print located code lines. |
|
1056 #ifndef ADDR2LINE |
|
1057 if( |
|
1058 ( m_iLogLevel == 1 || m_iLogLevel == 2 ) |
|
1059 && |
|
1060 ( m_vMemoryAddress.at(i)->GetAddressToLineState() != CATMemoryAddress::EXACT |
|
1061 && m_vMemoryAddress.at(i)->GetAddressToLineState() != CATMemoryAddress::FUNCTION ) |
|
1062 ) |
|
1063 { |
|
1064 // Skips to next |
|
1065 continue; |
|
1066 } |
|
1067 #endif |
|
1068 #ifdef ADDR2LINE |
|
1069 if( ( m_iLogLevel == 1 || m_iLogLevel == 2 ) |
|
1070 && m_vMemoryAddress.at(i)->GetAddressToLineState() != CATMemoryAddress::EXACT ) |
|
1071 { |
|
1072 // Skips to next |
|
1073 continue; |
|
1074 } |
|
1075 #endif |
|
1076 else if ( m_vMemoryAddress.at(i)->GetAddressToLineState() == CATMemoryAddress::OUT_OF_PROCESS ) |
|
1077 { |
|
1078 // Is memory address out of modules range |
|
1079 string sTemp; |
|
1080 sTemp.append( m_vMemoryAddress.at(i)->GetAddressString() ); |
|
1081 sTemp.append( " Address out of process memory."); |
|
1082 m_DataSaver.AddString( sTemp.c_str(), true ); |
|
1083 m_DataSaver.AddLineToLast(); |
|
1084 continue; |
|
1085 } |
|
1086 |
|
1087 // Print memory address |
|
1088 m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetAddressString().c_str(), true ); |
|
1089 |
|
1090 // Space (only for console output) |
|
1091 m_DataSaver.AddString( " " ); |
|
1092 |
|
1093 m_DataSaver.AddCarbideData( |
|
1094 NumberToHexString( m_vMemoryAddress.at(i)->GetOffSetFromModuleStart() ) ); |
|
1095 |
|
1096 // Module name |
|
1097 m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetModuleName().c_str(), true ); |
|
1098 |
|
1099 // Print call stack memory address details depending on state of memory address |
|
1100 switch( m_vMemoryAddress.at(i)->GetAddressToLineState() ) |
|
1101 { |
|
1102 // Address outside of known processes |
|
1103 case CATMemoryAddress::OUT_OF_PROCESS: |
|
1104 m_DataSaver.AddLineToLast(); |
|
1105 break; |
|
1106 // Address located outside of known modules symbols |
|
1107 case CATMemoryAddress::OUT_OF_RANGE: |
|
1108 m_DataSaver.AddString( " " ); |
|
1109 m_DataSaver.AddString( "???", true ); |
|
1110 m_DataSaver.AddLineToLast(); |
|
1111 break; |
|
1112 // Symbol state is currently used when using rom symbol file. |
|
1113 // From it we get module name & function name. |
|
1114 case CATMemoryAddress::SYMBOL: |
|
1115 m_DataSaver.AddString( " " ); |
|
1116 m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFunctionName().c_str(), true ); |
|
1117 if ( ! m_vMemoryAddress.at( i )->GetFileName().empty() ) |
|
1118 { |
|
1119 m_DataSaver.AddString( " (" ); |
|
1120 m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFileName().c_str(), true ); |
|
1121 m_DataSaver.AddString( ")" ); |
|
1122 } |
|
1123 m_DataSaver.AddLineToLast(); |
|
1124 break; |
|
1125 // Lst & Map implementation |
|
1126 #ifndef ADDR2LINE |
|
1127 case CATMemoryAddress::FUNCTION: |
|
1128 case CATMemoryAddress::EXACT: |
|
1129 m_DataSaver.AddString( " " ); |
|
1130 m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFunctionName().c_str(), true ); |
|
1131 // Small difference displaying details depending on build urel/udeb |
|
1132 if ( m_eBuildType == CATProject::UREL ) |
|
1133 { |
|
1134 // UREL |
|
1135 // Set build info to data saver |
|
1136 m_DataSaver.SetBuild( false ); |
|
1137 // urel = functionname: linenumber (filename) |
|
1138 m_DataSaver.AddString( ": " ); |
|
1139 if ( m_vMemoryAddress.at(i)->GetFunctionLineNumber() != -1 ) |
|
1140 m_DataSaver.AddInteger( m_vMemoryAddress.at(i)->GetFunctionLineNumber(), true ); |
|
1141 else if ( m_vMemoryAddress.at(i)->GetExactLineNumber() != -1 ) |
|
1142 m_DataSaver.AddInteger( m_vMemoryAddress.at(i)->GetExactLineNumber(), true ); |
|
1143 m_DataSaver.AddString( " (" ); |
|
1144 m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFileName().c_str(), true ); |
|
1145 m_DataSaver.AddString( ")" ); |
|
1146 m_DataSaver.AddLineToLast(); |
|
1147 } |
|
1148 else |
|
1149 { |
|
1150 // UDEB |
|
1151 // udeb = functionname: (filename:linenumber) |
|
1152 m_DataSaver.AddString( " (" ); |
|
1153 m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFileName().c_str(), true ); |
|
1154 m_DataSaver.AddString( ":" ); |
|
1155 if( m_vMemoryAddress.at(i)->GetExactLineNumber() != -1 ) |
|
1156 m_DataSaver.AddInteger( m_vMemoryAddress.at(i)->GetExactLineNumber(), true ); |
|
1157 else |
|
1158 m_DataSaver.AddString( "???", true ); |
|
1159 m_DataSaver.AddString( ")" ); |
|
1160 m_DataSaver.AddLineToLast(); |
|
1161 } |
|
1162 break; |
|
1163 #endif |
|
1164 // addr2line implementation (new). |
|
1165 #ifdef ADDR2LINE |
|
1166 case CATMemoryAddress::FUNCTION: |
|
1167 m_DataSaver.AddString( " " ); |
|
1168 m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFunctionName().c_str(), true ); |
|
1169 m_DataSaver.AddString( " (" ); |
|
1170 m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFileName().c_str(), true ); |
|
1171 m_DataSaver.AddString( ":" ); |
|
1172 if( m_vMemoryAddress.at(i)->GetExactLineNumber() != -1 ) |
|
1173 m_DataSaver.AddInteger( m_vMemoryAddress.at(i)->GetFunctionLineNumber(), true ); |
|
1174 else |
|
1175 m_DataSaver.AddString( "???", true ); |
|
1176 m_DataSaver.AddString( ")" ); |
|
1177 m_DataSaver.AddLineToLast(); |
|
1178 break; |
|
1179 case CATMemoryAddress::EXACT: |
|
1180 m_DataSaver.AddString( " " ); |
|
1181 m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFunctionName().c_str(), true ); |
|
1182 m_DataSaver.AddString( " (" ); |
|
1183 m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFileName().c_str(), true ); |
|
1184 m_DataSaver.AddString( ":" ); |
|
1185 if( m_vMemoryAddress.at(i)->GetExactLineNumber() != -1 ) |
|
1186 m_DataSaver.AddInteger( m_vMemoryAddress.at(i)->GetExactLineNumber(), true ); |
|
1187 else |
|
1188 m_DataSaver.AddString( "???", true ); |
|
1189 m_DataSaver.AddString( ")" ); |
|
1190 m_DataSaver.AddLineToLast(); |
|
1191 break; |
|
1192 #endif |
|
1193 } // End switch |
|
1194 // On logging level 1 we only print one located code line |
|
1195 #ifndef ADDR2LINE |
|
1196 if ( m_iLogLevel == 1 && ( m_vMemoryAddress.at(i)->GetAddressToLineState() == CATMemoryAddress::EXACT || |
|
1197 m_vMemoryAddress.at(i)->GetAddressToLineState() == CATMemoryAddress::FUNCTION ) ) |
|
1198 break; |
|
1199 #endif |
|
1200 #ifdef ADDR2LINE |
|
1201 if ( m_iLogLevel == 1 && m_vMemoryAddress.at(i)->GetAddressToLineState() == CATMemoryAddress::EXACT ) |
|
1202 break; |
|
1203 #endif |
|
1204 } // End call stack items loop |
|
1205 } |
|
1206 |
|
1207 // ----------------------------------------------------------------------------- |
|
1208 // CATDatParser::SetInputFile |
|
1209 // ----------------------------------------------------------------------------- |
|
1210 void CATDatParser::SetInputFile(const string& sInputFile) |
|
1211 { |
|
1212 LOG_FUNC_ENTRY("CATDatParser::SetInputFile"); |
|
1213 m_sInputFile = sInputFile; |
|
1214 } |
|
1215 |
|
1216 // ----------------------------------------------------------------------------- |
|
1217 // CATDatParser::SetOutputFile |
|
1218 // ----------------------------------------------------------------------------- |
|
1219 void CATDatParser::SetOutputFile(const string& sOutpuFile) |
|
1220 { |
|
1221 LOG_FUNC_ENTRY("CATDatParser::SetOutputFile"); |
|
1222 m_sOutputFile = sOutpuFile; |
|
1223 } |
|
1224 |
|
1225 // ----------------------------------------------------------------------------- |
|
1226 // CATDatParser::SetRomSymbolFiles |
|
1227 // ----------------------------------------------------------------------------- |
|
1228 void CATDatParser::SetRomSymbolFiles(const vector<string>& vRomSymbolFiles) |
|
1229 { |
|
1230 LOG_FUNC_ENTRY("CATDatParser::SetRomSymbolFiles"); |
|
1231 m_vRomSymbolFiles = vRomSymbolFiles; |
|
1232 } |
|
1233 |
|
1234 // ----------------------------------------------------------------------------- |
|
1235 // CATDatParser::SetLogLevel |
|
1236 // ----------------------------------------------------------------------------- |
|
1237 void CATDatParser::SetLogLevel(int iLogLevel) |
|
1238 { |
|
1239 LOG_FUNC_ENTRY("CATDatParser::SetLogLevel"); |
|
1240 m_iLogLevel = iLogLevel; |
|
1241 } |
|
1242 |
|
1243 // ----------------------------------------------------------------------------- |
|
1244 // CATDatParser::GetLogLevel |
|
1245 // ----------------------------------------------------------------------------- |
|
1246 int CATDatParser::GetLogLevel() const |
|
1247 { |
|
1248 LOG_LOW_FUNC_ENTRY("CATDatParser::GetLogLevel"); |
|
1249 return m_iLogLevel; |
|
1250 } |
|
1251 |
|
1252 // ----------------------------------------------------------------------------- |
|
1253 // CATDatParser::CleanMemoryAddresses |
|
1254 // ----------------------------------------------------------------------------- |
|
1255 void CATDatParser::CleanMemoryAddresses() |
|
1256 { |
|
1257 LOG_LOW_FUNC_ENTRY("CATDatParser::CleanMemoryAddresses"); |
|
1258 // Cleanup memory addressses. |
|
1259 for( vector<CATMemoryAddress*>::iterator it = m_vMemoryAddress.begin(); it != m_vMemoryAddress.end(); it++ ) |
|
1260 { |
|
1261 delete *it; |
|
1262 } |
|
1263 m_vMemoryAddress.clear(); |
|
1264 } |
|
1265 |
|
1266 // ----------------------------------------------------------------------------- |
|
1267 // CATDatParser::ConvertTimeToLocalTime |
|
1268 // ----------------------------------------------------------------------------- |
|
1269 string CATDatParser::ConvertTimeToLocalTime( string sInputTime ) |
|
1270 { |
|
1271 LOG_LOW_FUNC_ENTRY("CATDatParser::ConvertTimeToLocalTime"); |
|
1272 //Is process end abnormal? |
|
1273 if( sInputTime.compare( LABEL_ABNORMAL ) == 0 ) |
|
1274 { |
|
1275 return string( AT_ANALYZE_ABNORMAL_EXIT ); |
|
1276 } |
|
1277 else |
|
1278 // Check that input time is at least 32-bit |
|
1279 if( sInputTime.length() <= 8 ) |
|
1280 { |
|
1281 sInputTime.clear(); |
|
1282 return sInputTime; |
|
1283 } |
|
1284 |
|
1285 string sTemp = sInputTime; |
|
1286 const char* pTemp = sTemp.c_str(); |
|
1287 |
|
1288 // Are all characters hex |
|
1289 for( unsigned int i = 0 ; i < sTemp.size() ; i++ ) |
|
1290 { |
|
1291 if( !IsHexCharacter( (pTemp + i) ) ) |
|
1292 { |
|
1293 return sInputTime; |
|
1294 } |
|
1295 } |
|
1296 |
|
1297 // Get LSB bits |
|
1298 string sLsb; |
|
1299 sLsb.append( sInputTime.substr( sInputTime.length()-8, sInputTime.length() ) ); |
|
1300 unsigned int iLsbTime = (unsigned int)_httoi( sLsb.c_str() ); |
|
1301 |
|
1302 // Get MSB bits |
|
1303 string sMsb; |
|
1304 sMsb.append( sInputTime.substr( 0, sInputTime.length()-8 ) ); |
|
1305 unsigned int iMsbTime = (unsigned int)_httoi( sMsb.c_str() ); |
|
1306 |
|
1307 // Get time in microsecods |
|
1308 long long sdf = iMsbTime * 0x100000000 + iLsbTime; |
|
1309 |
|
1310 // Get original time (starting at year 1970 ) |
|
1311 long long llOrigTime = sdf; |
|
1312 |
|
1313 // Get seconds |
|
1314 sdf = ( sdf )/1000000; |
|
1315 |
|
1316 // Check that sdf contains some time value |
|
1317 if( sdf <= 0) |
|
1318 { |
|
1319 // Error in time calculation |
|
1320 // Return empty string |
|
1321 sInputTime.clear(); |
|
1322 return sInputTime; |
|
1323 } |
|
1324 |
|
1325 // Original time after year 1970 in seconds |
|
1326 long long llOrignTimeInSeconds = sdf; |
|
1327 |
|
1328 // Calculate new time which does not include millisecods |
|
1329 long long llDiffTime = (llOrignTimeInSeconds * 1000000); |
|
1330 |
|
1331 // Calculate time difference in milliseconds |
|
1332 int llDiffTimeInMilliSecods = (int)( llOrigTime - llDiffTime )/1000; |
|
1333 |
|
1334 // Convert difference time to char |
|
1335 char cDiffInMilliSeconds[20]; |
|
1336 _itoa( llDiffTimeInMilliSecods, cDiffInMilliSeconds, 10 ); |
|
1337 |
|
1338 // Time info structure |
|
1339 struct tm *timeinfo; |
|
1340 |
|
1341 // Get local time |
|
1342 timeinfo = localtime ( (time_t*) &sdf ); |
|
1343 |
|
1344 // Create string and append memory leak time to it |
|
1345 string sTime; |
|
1346 sTime.append( asctime( timeinfo ) ); |
|
1347 |
|
1348 // Remove last char of locale time string which is \n |
|
1349 sTime.resize( (int)sTime.length()-1 ); |
|
1350 |
|
1351 // Get last space index |
|
1352 int iLastSpace = (int)sTime.find_last_of(" "); |
|
1353 |
|
1354 // If last space index is valid |
|
1355 if( iLastSpace <= (int)sTime.length() && iLastSpace > 0) |
|
1356 { |
|
1357 string sTempTime; |
|
1358 // Append first part of original time string |
|
1359 sTempTime.append( sTime.substr( 0, iLastSpace ) ); |
|
1360 |
|
1361 // Append millisecods |
|
1362 sTempTime.append( "." ); |
|
1363 sTempTime.append( cDiffInMilliSeconds ); |
|
1364 |
|
1365 // Append the rest of the original time string part |
|
1366 sTempTime.append( sTime.substr( iLastSpace, sTime.length())); |
|
1367 |
|
1368 // Clear original and append new time string which includes millisecods |
|
1369 sTime.clear(); |
|
1370 sTime.append( sTempTime ); |
|
1371 } |
|
1372 |
|
1373 // Return memory leak time |
|
1374 return sTime.c_str(); |
|
1375 } |
|
1376 |
|
1377 bool CATDatParser::CreateWinscwModule( const string& sBinaryName ) |
|
1378 { |
|
1379 LOG_FUNC_ENTRY( "CATDatParser::CreateWinscwModule" ); |
|
1380 // Is module already created? |
|
1381 for( vector<CATModule2*>::iterator it = m_pModules->begin(); it != m_pModules->end(); it++ ) |
|
1382 { |
|
1383 if ( _stricmp( sBinaryName.c_str(), (*it)->GetBinaryName().c_str() ) == 0 ) |
|
1384 return true; |
|
1385 } |
|
1386 // No create new one and set its values. |
|
1387 CATModule2* mod = new CATModule2(); |
|
1388 mod->SetTarget( RemovePathAndExt( sBinaryName, true ) ); |
|
1389 mod->SetRequestedTargetExt( GetExtension( sBinaryName ) ); |
|
1390 mod->SetReleasePath( string( "\\epoc32\\release" ) ); |
|
1391 if ( m_eBuildType == CATProject::UDEB ) |
|
1392 mod->SetFullVariantPath( string( "winscw\\udeb" ) ); |
|
1393 else |
|
1394 mod->SetFullVariantPath( string( "winscw\\urel" ) ); |
|
1395 mod->SetVariantPlatform( string( "winscw" ) ); |
|
1396 m_pModules->push_back( mod ); |
|
1397 return true; |
|
1398 } |
|
1399 |
|
1400 // ----------------------------------------------------------------------------- |
|
1401 // CATDatParser::FindModuleUsingAddress |
|
1402 // Function finds module using given address. |
|
1403 // ----------------------------------------------------------------------------- |
|
1404 int CATDatParser::FindModuleUsingAddress( unsigned long iAddress ) const |
|
1405 { |
|
1406 LOG_LOW_FUNC_ENTRY("CATDatParser::FindModuleUsingAddress"); |
|
1407 int iRet = -1; |
|
1408 for( unsigned int i = 0 ; i < m_vDllLoadModList.size() ; i++ ) |
|
1409 { |
|
1410 // Is address between start and end address? |
|
1411 if( iAddress > m_vDllLoadModList[i].iStartAddress && iAddress < m_vDllLoadModList[i].iEndAddress ) |
|
1412 { |
|
1413 iRet = i; |
|
1414 break; |
|
1415 } |
|
1416 } |
|
1417 return iRet; |
|
1418 } |
|
1419 |
|
1420 // ----------------------------------------------------------------------------- |
|
1421 // CATDatParser::FindModuleUsingPID |
|
1422 // Function finds module using module id. |
|
1423 // ----------------------------------------------------------------------------- |
|
1424 /* |
|
1425 int CATDatParser::FindModuleUsingPID( unsigned long iPID ) const |
|
1426 { |
|
1427 LOG_FUNC_ENTRY("CATDatParser::FindModuleUsingPID"); |
|
1428 |
|
1429 int iRet = -1; |
|
1430 |
|
1431 // Change module name characters to lowercase |
|
1432 for( unsigned int i = 0 ; i < m_vDllLoadModList.size() ; i++ ) |
|
1433 { |
|
1434 if( m_vDllLoadModList[i].iPID == iPID ) |
|
1435 { |
|
1436 iRet = i; |
|
1437 break; |
|
1438 } |
|
1439 } |
|
1440 return iRet; |
|
1441 } |
|
1442 */ |
|
1443 // ----------------------------------------------------------------------------- |
|
1444 // CATDatParser::FindModuleUsingName |
|
1445 // Function finds module using module name. |
|
1446 // ----------------------------------------------------------------------------- |
|
1447 int CATDatParser::FindModuleUsingName( const char* pModName ) |
|
1448 { |
|
1449 LOG_LOW_FUNC_ENTRY("CATDatParser::FindModuleUsingName"); |
|
1450 |
|
1451 // Mod name empty? |
|
1452 if( pModName == NULL || *pModName == 0 ) |
|
1453 return -1; |
|
1454 |
|
1455 int iRet = -1; |
|
1456 string sModName( pModName ); |
|
1457 // Change module name characters to lowercase |
|
1458 ChangeToLower( sModName ); |
|
1459 // Remove variant marks (dots) |
|
1460 RemoveAllAfterDotIfTwoDots( sModName); |
|
1461 for( unsigned int i = 0 ; i < m_vDllLoadModList.size() ; i++ ) |
|
1462 { |
|
1463 string sTemp( m_vDllLoadModList[i].sModuleName ); |
|
1464 ChangeToLower( sTemp ); |
|
1465 // Remove variant marks (dots) |
|
1466 RemoveAllAfterDotIfTwoDots( sTemp ); |
|
1467 if( sTemp.find( sModName ) != string::npos ) |
|
1468 { |
|
1469 iRet = i; |
|
1470 break; |
|
1471 } |
|
1472 } |
|
1473 return iRet; |
|
1474 } |
|
1475 |
|
1476 // ----------------------------------------------------------------------------- |
|
1477 // CATDatParser::SetPrintFlag |
|
1478 // ----------------------------------------------------------------------------- |
|
1479 void CATDatParser::SetPringFlag( bool bPrintFlag ) |
|
1480 { |
|
1481 LOG_FUNC_ENTRY("CATDatParser::SetPringFlag"); |
|
1482 m_DataSaver.SetPrintFlag( bPrintFlag ); |
|
1483 } |
|
1484 // ----------------------------------------------------------------------------- |
|
1485 // CATDatParser::SetOffSet |
|
1486 // ----------------------------------------------------------------------------- |
|
1487 void CATDatParser::SetOffSet( int iOffSet ) |
|
1488 { |
|
1489 LOG_FUNC_ENTRY("CATDatParser::SetOffSet"); |
|
1490 m_iOffSet = iOffSet; |
|
1491 } |
|
1492 |
|
1493 // ----------------------------------------------------------------------------- |
|
1494 // CATDatParser::GetOffSet |
|
1495 // ----------------------------------------------------------------------------- |
|
1496 int CATDatParser::GetOffSet( ) const |
|
1497 { |
|
1498 LOG_LOW_FUNC_ENTRY("CATDatParser::GetOffSet"); |
|
1499 return m_iOffSet; |
|
1500 } |
|
1501 |
|
1502 // ----------------------------------------------------------------------------- |
|
1503 // Set project platform. |
|
1504 // ----------------------------------------------------------------------------- |
|
1505 void CATDatParser::SetProjectPlatform( const string& sPlatform ) |
|
1506 { |
|
1507 LOG_FUNC_ENTRY("CATDatParser::SetProjectPlatform"); |
|
1508 m_sProjectPlatform = sPlatform; |
|
1509 |
|
1510 // Check that platform not empty before determing platform from it. |
|
1511 if ( sPlatform.empty() ) |
|
1512 return; |
|
1513 |
|
1514 // Set functions offset in mapfiles correct (depending on platform). |
|
1515 if ( _stricmp( sPlatform.c_str(), "armv5" ) == 0 ) |
|
1516 { |
|
1517 m_iOffSet = FUNCTIONS_OFFSET_IN_MAP_FILE_ARMV5; |
|
1518 } |
|
1519 else if ( _stricmp( sPlatform.c_str(), "winscw" ) == 0 ) |
|
1520 { |
|
1521 m_iOffSet = FUNCTIONS_OFFSET_IN_MAP_FILE_WINSCW; |
|
1522 } |
|
1523 else if ( _stricmp( sPlatform.c_str(), "gcce" ) == 0 ) |
|
1524 { |
|
1525 m_iOffSet = FUNCTIONS_OFFSET_IN_GCCE; |
|
1526 } |
|
1527 else |
|
1528 { |
|
1529 LOG_STRING( AT_MSG << "Error, cannot set function's offset in map file, invalid platform: " << sPlatform ); |
|
1530 } |
|
1531 } |
|
1532 |
|
1533 // ----------------------------------------------------------------------------- |
|
1534 // Set projects build type. Use enumeration defined in CATProject. |
|
1535 // ----------------------------------------------------------------------------- |
|
1536 void CATDatParser::SetProjectBuildType( int eBuildType ) |
|
1537 { |
|
1538 LOG_FUNC_ENTRY("CATDatParser::SetProjectBuildType"); |
|
1539 m_eProjectBuildType = eBuildType; |
|
1540 } |
|
1541 |
|
1542 //EOF |
|