56
|
1 |
// Copyright (c) 2007-2010 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 "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 |
// Trace Core
|
|
15 |
//
|
|
16 |
|
|
17 |
#include "TraceCore.h"
|
|
18 |
#include "BTraceOstCategoryHandler.h"
|
|
19 |
#include "BTraceOstCategoryBitmap.h"
|
|
20 |
#include "TraceCoreWriter.h"
|
|
21 |
#include "TraceCoreDebug.h"
|
|
22 |
#include "TraceCoreConstants.h"
|
|
23 |
#include "OstTraceDefinitions.h"
|
|
24 |
#ifdef OST_TRACE_COMPILER_IN_USE
|
|
25 |
#include "BTraceOstCategoryHandlerTraces.h"
|
|
26 |
#endif
|
|
27 |
|
|
28 |
#ifndef __SMP__
|
|
29 |
/**
|
|
30 |
* Length of Trace group ID + Trace ID in the MultiPart traces data part
|
|
31 |
*/
|
|
32 |
const TUint KTraceGroupIdLen = 4;
|
|
33 |
|
|
34 |
/**
|
|
35 |
* Length of BTrace header
|
|
36 |
*/
|
|
37 |
const TUint KBTraceHeaderLen = 4;
|
|
38 |
|
|
39 |
/**
|
|
40 |
* Length of single BTrace variable
|
|
41 |
*/
|
|
42 |
const TUint KBTraceVariableLen = 4;
|
|
43 |
|
|
44 |
/**
|
|
45 |
* Four bytes
|
|
46 |
*/
|
|
47 |
const TUint KFourBytes = 4;
|
|
48 |
|
|
49 |
#endif // !__SMP__
|
|
50 |
/**
|
|
51 |
* Group value in GroupId
|
|
52 |
*/
|
|
53 |
const TUint32 KGroupMask = 0xffff0000;
|
|
54 |
|
|
55 |
|
|
56 |
/**
|
|
57 |
* Constructor
|
|
58 |
*/
|
|
59 |
DBTraceOstCategoryHandler::DBTraceOstCategoryHandler()
|
|
60 |
: iAllTracesDeactivated( ETrue )
|
|
61 |
, iCacheItem1( iComponentGroupCache ) // One "cache" item contains ComponentId, groupId, and activation info (3*32bit)
|
|
62 |
, iCacheItem2( iComponentGroupCache+3 ) //CodForChk_Dis_Magic
|
|
63 |
, iCacheItem3( iComponentGroupCache+6 ) //CodForChk_Dis_Magic
|
|
64 |
, iCacheItem4( iComponentGroupCache+9 ) //CodForChk_Dis_Magic
|
|
65 |
, iOstTraceBitmap( NULL )
|
|
66 |
{
|
|
67 |
}
|
|
68 |
|
|
69 |
|
|
70 |
/**
|
|
71 |
* Destructor
|
|
72 |
*/
|
|
73 |
DBTraceOstCategoryHandler::~DBTraceOstCategoryHandler()
|
|
74 |
{
|
|
75 |
// Delete trace bitmap
|
|
76 |
delete iOstTraceBitmap;
|
|
77 |
}
|
|
78 |
|
|
79 |
|
|
80 |
/**
|
|
81 |
* Initializes this handler
|
|
82 |
*
|
|
83 |
* @param aHandler The BTrace handler
|
|
84 |
*/
|
|
85 |
TInt DBTraceOstCategoryHandler::Init()
|
|
86 |
{
|
|
87 |
TInt ret = KErrNone;
|
|
88 |
|
|
89 |
#ifdef __SMP__
|
|
90 |
for( TInt i = 0; i<MAX_MULTIPART_TRACES; i++ )
|
|
91 |
{
|
|
92 |
iMultipartArray[i].iMultiPartId = 0xffffffff;
|
|
93 |
iFreeList[i] = 1; // Set Free
|
|
94 |
}
|
|
95 |
#endif // __SMP__
|
|
96 |
|
|
97 |
for (TUint category = KMaxKernelCategory + 1; category <= KMaxCategory; category++)
|
|
98 |
{
|
|
99 |
if (category != KCategoryNokiaBranchCoverage) // Is this exception needed?
|
|
100 |
{
|
|
101 |
ret = AddCategory( category );
|
|
102 |
if (ret != KErrNone)
|
|
103 |
{
|
|
104 |
break;
|
|
105 |
}
|
|
106 |
}
|
|
107 |
}
|
|
108 |
|
|
109 |
if (ret == KErrNone)
|
|
110 |
{
|
|
111 |
iOstTraceBitmap = new DBTraceOstCategoryBitmap( this );
|
|
112 |
if ( iOstTraceBitmap != NULL )
|
|
113 |
{
|
|
114 |
// Initialize TraceBitmap
|
|
115 |
ret = iOstTraceBitmap->Init();
|
|
116 |
if ( ret == KErrNone )
|
|
117 |
{
|
|
118 |
ret = iOstTraceBitmap->RegisterActivationNotification( *this );
|
|
119 |
if ( ret == KErrNone )
|
|
120 |
{
|
|
121 |
ret = Register();
|
|
122 |
if ( ret == KErrNone )
|
|
123 |
{
|
|
124 |
TC_TRACE( ETraceLevelNormal, Kern::Printf(
|
|
125 |
"DBTraceAutogenCategoryHandler::Init - Register OK" ) );
|
|
126 |
}
|
|
127 |
// Register failed
|
|
128 |
else
|
|
129 |
{
|
|
130 |
ret = KErrGeneral;
|
|
131 |
}
|
|
132 |
}
|
|
133 |
// RegisterActivationNotification failed
|
|
134 |
else
|
|
135 |
{
|
|
136 |
ret = KErrGeneral;
|
|
137 |
}
|
|
138 |
}
|
|
139 |
}
|
|
140 |
// Memory allocation failed
|
|
141 |
else
|
|
142 |
{
|
|
143 |
TC_TRACE( ETraceLevelError, Kern::Printf( "DBTraceOstCategoryHandler::Init - Memory allocation failed" ) );
|
|
144 |
ret = KErrNoMemory;
|
|
145 |
}
|
|
146 |
}
|
|
147 |
TC_TRACE( ETraceLevelError, Kern::Printf( "<DBTraceOstCategoryHandler::Init() - %d", ret ) );
|
|
148 |
return ret;
|
|
149 |
}
|
|
150 |
|
|
151 |
/**
|
|
152 |
* Set settings
|
|
153 |
*
|
|
154 |
* @param aSettings Settings
|
|
155 |
*/
|
|
156 |
void DBTraceOstCategoryHandler::SetSettings( DTraceCoreSettings* aSettings )
|
|
157 |
{
|
|
158 |
OstTrace1( TRACE_FLOW, DBTRACEOSTCATEGORYHANDLER_SETSETTINGS_ENTRY, "> DBTraceOstCategoryHandler::SetSettings 0x%x", ( TUint )( aSettings ) );
|
|
159 |
DBTraceCategoryHandler::SetSettings( aSettings );
|
|
160 |
if ( iOstTraceBitmap != NULL && aSettings != NULL )
|
|
161 |
{
|
|
162 |
// Reads the bitmap configuration from settings
|
|
163 |
iOstTraceBitmap->ReadFromSettings( *aSettings );
|
|
164 |
}
|
|
165 |
}
|
|
166 |
|
|
167 |
/**
|
|
168 |
* Notification that the activation state has changed.
|
|
169 |
*
|
|
170 |
* @param aActivation the activation interface that was updated
|
|
171 |
* @param aFromSettings ETrue if activation was due to settings read, EFalse if from some other source
|
|
172 |
* @param aComponentId Component ID of the activation
|
|
173 |
*/
|
|
174 |
void DBTraceOstCategoryHandler::ActivationChanged( MTraceCoreActivation& aActivation, TBool aFromSettings,
|
|
175 |
TUint32 /*aComponentId*/)
|
|
176 |
{
|
|
177 |
OstTrace1( TRACE_FLOW, DBTRACEOSTCATEGORYHANDLER_ACTIVATIONCHANGED_ENTRY, "> DBTraceOstCategoryHandler::ActivationChanged 0x%x", ( TUint )&( aActivation ) );
|
|
178 |
|
|
179 |
// Call the bitmap to write changes to settings saver
|
|
180 |
if ( !aFromSettings )
|
|
181 |
{
|
|
182 |
if ( iSettings != NULL )
|
|
183 |
{
|
|
184 |
aActivation.WriteToSettings( *iSettings );
|
|
185 |
}
|
|
186 |
}
|
|
187 |
}
|
|
188 |
|
|
189 |
/**
|
|
190 |
* Handler for KCategoryNokiaOst
|
|
191 |
*
|
|
192 |
* @param aHeader BTrace header
|
|
193 |
* @param aHeader2 Extra header data
|
|
194 |
* @param aContext The thread context in which this function was called
|
|
195 |
* @param a1 The first trace parameter
|
|
196 |
* @param a2 The second trace parameter
|
|
197 |
* @param a3 The third trace parameter
|
|
198 |
* @param aExtra Extra trace data
|
|
199 |
* @param aPc The program counter value
|
|
200 |
* @return ETrue if trace was processed, EFalse if not
|
|
201 |
*/
|
|
202 |
TBool DBTraceOstCategoryHandler::HandleFrame( TUint32 aHeader, TUint32 aHeader2, const TUint32 aContext,
|
|
203 |
const TUint32 a1, const TUint32 a2, const TUint32 a3,
|
|
204 |
const TUint32 aExtra, const TUint32 aPc )
|
|
205 |
{
|
|
206 |
TBool retval(EFalse);
|
|
207 |
if ( iWriter != NULL && !iAllTracesDeactivated )
|
|
208 |
{
|
|
209 |
__ASSERT_DEBUG( iOstTraceBitmap != NULL,
|
|
210 |
Kern::Fault( "DBTraceOstCategoryHandler::HandleFrame - NULL", KErrGeneral ) );
|
|
211 |
|
|
212 |
// Check if tracing is certified
|
|
213 |
DTraceCore* tracecore = DTraceCore::GetInstance();
|
|
214 |
if (!tracecore || !tracecore->IsTraceCertified())
|
|
215 |
{
|
|
216 |
return EFalse;
|
|
217 |
}
|
|
218 |
|
|
219 |
// Check if the trace is a multipart trace
|
|
220 |
TBool isMultiPart = CheckMultiPart(aHeader, aHeader2);
|
|
221 |
|
|
222 |
if (isMultiPart)
|
|
223 |
{
|
|
224 |
|
|
225 |
#ifdef __SMP__
|
|
226 |
// Handle the multipart trace
|
|
227 |
retval = HandleMultiPart(aHeader, aHeader2, aContext, a1, a2, a3, aExtra, aPc);
|
|
228 |
#else
|
|
229 |
// Handle the multipart trace. Returns EFalse if trace is not activated.
|
|
230 |
TBool isActivatedMultiPart = HandleMultiPart(aHeader, aHeader2, aContext, a1, a2, a3, aExtra, aPc);
|
|
231 |
if (isActivatedMultiPart)
|
|
232 |
{
|
|
233 |
retval = ETrue;
|
|
234 |
}
|
|
235 |
else
|
|
236 |
{
|
|
237 |
retval = EFalse;
|
|
238 |
}
|
|
239 |
#endif // __SMP__
|
|
240 |
|
|
241 |
}
|
|
242 |
// Not a multipart trace
|
|
243 |
else
|
|
244 |
{
|
|
245 |
|
|
246 |
// Take group and leave trace id away
|
|
247 |
TUint32 group = a2 & KGroupMask;
|
|
248 |
|
|
249 |
if ((*iCacheItem1) == a1 && (*(iCacheItem1 + 1)) == group)
|
|
250 |
{
|
|
251 |
retval = *(iCacheItem1 + 2); //CodForChk_Dis_Magic
|
|
252 |
}
|
|
253 |
else if ((*iCacheItem2) == a1 && (*(iCacheItem2 + 1)) == group)
|
|
254 |
{
|
|
255 |
retval = *(iCacheItem2 + 2); //CodForChk_Dis_Magic
|
|
256 |
}
|
|
257 |
else if ((*iCacheItem3) == a1 && (*(iCacheItem3 + 1)) == group)
|
|
258 |
{
|
|
259 |
retval = *(iCacheItem3 + 2); //CodForChk_Dis_Magic
|
|
260 |
}
|
|
261 |
else if ((*iCacheItem4) == a1 && (*(iCacheItem4 + 1)) == group)
|
|
262 |
{
|
|
263 |
retval = *(iCacheItem4 + 2); //CodForChk_Dis_Magic
|
|
264 |
}
|
|
265 |
else
|
|
266 |
{
|
|
267 |
retval = iOstTraceBitmap->IsTraceActivated(a1, a2);
|
|
268 |
|
|
269 |
iTemp = iCacheItem1;
|
|
270 |
iCacheItem1 = iCacheItem4;
|
|
271 |
iCacheItem4 = iCacheItem3;
|
|
272 |
iCacheItem3 = iCacheItem2;
|
|
273 |
iCacheItem2 = iTemp;
|
|
274 |
*iCacheItem1 = a1;
|
|
275 |
*(iCacheItem1 + 1) = group;
|
|
276 |
*(iCacheItem1 + 2) = retval;
|
|
277 |
|
|
278 |
}
|
|
279 |
|
|
280 |
if ( ( ( aHeader >> ( BTrace::ESubCategoryIndex * KByteSize ) ) & KByteMask ) == EOstTraceActivationQuery )
|
|
281 |
{
|
|
282 |
//Trace from here is not allowed
|
|
283 |
}
|
|
284 |
else if ( retval )
|
|
285 |
{
|
|
286 |
CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
|
|
287 |
TUint8 recordSize = static_cast< TUint8 >( ( aHeader >> ( BTrace::ESizeIndex * KByteSize ) ) & KByteMask );
|
|
288 |
iWriter->WriteTraceCoreFrame( a1, a2, aHeader, aHeader2, aContext, a1, a2, a3, aExtra, aPc, recordSize );
|
|
289 |
}
|
|
290 |
}
|
|
291 |
}
|
|
292 |
else
|
|
293 |
{
|
|
294 |
if( iWriter == NULL )
|
|
295 |
{
|
|
296 |
//Trace from here is not allowed
|
|
297 |
retval = EFalse;
|
|
298 |
}
|
|
299 |
|
|
300 |
}
|
|
301 |
|
|
302 |
//Trace from here is not allowed
|
|
303 |
return retval;
|
|
304 |
}
|
|
305 |
|
|
306 |
/**
|
|
307 |
* Checks if the given trace is a Multipart trace
|
|
308 |
*
|
|
309 |
* @param aHeader Header data
|
|
310 |
* @param aHeader2 Extra header data
|
|
311 |
* @return ETrue if trace is a Multipart trace, EFalse if not
|
|
312 |
*/
|
|
313 |
inline TBool DBTraceOstCategoryHandler::CheckMultiPart( TUint32 aHeader, TUint32 aHeader2 )
|
|
314 |
{
|
|
315 |
TBool retval = EFalse;
|
|
316 |
TUint8 flags = static_cast< TUint8 >( ( aHeader >> ( BTrace::EFlagsIndex * KByteSize ) ) & KByteMask );
|
|
317 |
if (flags & BTrace::EHeader2Present)
|
|
318 |
{
|
|
319 |
// First, middle or last part of Multipart trace
|
|
320 |
if (aHeader2 & BTrace::EMultipartFlagMask)
|
|
321 |
{
|
|
322 |
retval = ETrue;
|
|
323 |
}
|
|
324 |
}
|
|
325 |
|
|
326 |
//Trace from here is not allowed
|
|
327 |
return retval;
|
|
328 |
}
|
|
329 |
|
|
330 |
/**
|
|
331 |
* Checks if there is a dropped trace and updates header if so
|
|
332 |
*
|
|
333 |
* @param aHeader Header data
|
|
334 |
*/
|
|
335 |
inline TBool DBTraceOstCategoryHandler::CheckDroppedTrace( TUint32& aHeader )
|
|
336 |
{
|
|
337 |
TBool ret(EFalse);
|
|
338 |
|
|
339 |
DTraceCore* tracecore = DTraceCore::GetInstance();
|
|
340 |
if (tracecore && (tracecore->PreviousTraceDropped())) //if previous trace was dropped
|
|
341 |
{
|
|
342 |
//set flags back to EFalse first
|
|
343 |
tracecore->SetPreviousTraceDropped(EFalse);
|
|
344 |
|
|
345 |
//set missing flag in BTrace
|
|
346 |
aHeader |= BTrace::EMissingRecord<<(BTrace::EFlagsIndex * KByteSize);
|
|
347 |
|
|
348 |
ret = ETrue;
|
|
349 |
}
|
|
350 |
|
|
351 |
return ret;
|
|
352 |
}
|
|
353 |
|
|
354 |
#ifdef __SMP__
|
|
355 |
|
|
356 |
|
|
357 |
TInt DBTraceOstCategoryHandler::Find( TUint32 aMultiPartId )
|
|
358 |
{
|
|
359 |
TInt ret(KErrNotFound);
|
|
360 |
for( TInt i = 0; i<MAX_MULTIPART_TRACES; i++ )
|
|
361 |
{
|
|
362 |
if( iMultipartArray[i].iMultiPartId == aMultiPartId )
|
|
363 |
{
|
|
364 |
ret = i;
|
|
365 |
break;
|
|
366 |
}
|
|
367 |
}
|
|
368 |
return ret;
|
|
369 |
}
|
|
370 |
|
|
371 |
void DBTraceOstCategoryHandler::Remove( TUint32 aIndex )
|
|
372 |
{
|
|
373 |
iMultipartArray[aIndex].iMultiPartId = 0xffffffff;
|
|
374 |
iFreeList[aIndex] = 1; // Set free
|
|
375 |
}
|
|
376 |
|
|
377 |
/**
|
|
378 |
*
|
|
379 |
* @return KErrNone if added, otherwise KErrNotFound.
|
|
380 |
*/
|
|
381 |
TInt DBTraceOstCategoryHandler::InsertIfNotExist( TMultiPartActivationInfo &aMultiPartTrace )
|
|
382 |
{
|
|
383 |
TInt ret = Find( aMultiPartTrace.iMultiPartId );
|
|
384 |
if( ret == KErrNotFound )
|
|
385 |
{
|
|
386 |
// Find free slot
|
|
387 |
for( TInt freeIndex = 0; freeIndex<MAX_MULTIPART_TRACES; freeIndex++ )
|
|
388 |
{
|
|
389 |
if( iFreeList[freeIndex] )
|
|
390 |
{
|
|
391 |
iFreeList[freeIndex] = 0; // Set reserved
|
|
392 |
iMultipartArray[freeIndex].iComponentId = aMultiPartTrace.iComponentId;
|
|
393 |
iMultipartArray[freeIndex].iTraceWord = aMultiPartTrace.iTraceWord;
|
|
394 |
iMultipartArray[freeIndex].iMultiPartId = aMultiPartTrace.iMultiPartId;
|
|
395 |
ret = KErrNone;
|
|
396 |
break;
|
|
397 |
}
|
|
398 |
}
|
|
399 |
|
|
400 |
}
|
|
401 |
return ret;
|
|
402 |
}
|
|
403 |
|
|
404 |
|
|
405 |
/**
|
|
406 |
* Handles this Multipart trace
|
|
407 |
*
|
|
408 |
* @param aHeader BTrace header
|
|
409 |
* @param aHeader2 Extra header data
|
|
410 |
* @param aContext The thread context in which this function was called
|
|
411 |
* @param a1 First parameter
|
|
412 |
* @param a2 Second parameter
|
|
413 |
* @param aData The data
|
|
414 |
* @param aExtra Extra trace data
|
|
415 |
* @param aPc The program counter value
|
|
416 |
* @return ETrue if trace is activated
|
|
417 |
*/
|
|
418 |
TBool DBTraceOstCategoryHandler::HandleMultiPart( TUint32 aHeader, TUint32 aHeader2, const TUint32 aContext,
|
|
419 |
const TUint32 a1, const TUint32 a2, const TUint32 aData, const TUint32 aExtra,
|
|
420 |
const TUint32 aPc)
|
|
421 |
{
|
|
422 |
TBool retval = ETrue;
|
|
423 |
TInt multiPartOffset = aHeader2 & BTrace::EMultipartFlagMask;
|
|
424 |
TUint8 recordSize = static_cast< TUint8 >( ( aHeader >> ( BTrace::ESizeIndex * KByteSize ) ) & KByteMask );
|
|
425 |
|
|
426 |
// First part of multipart trace
|
|
427 |
if (multiPartOffset == BTrace::EMultipartFirst)
|
|
428 |
{
|
|
429 |
// Create new MultiPart activation info and save it to the array
|
|
430 |
TMultiPartActivationInfo activationInfo;
|
|
431 |
activationInfo.iComponentId = a2;
|
|
432 |
|
|
433 |
// This should be safe operation as if there is not enough data, the trace should not
|
|
434 |
// be first part of multipart trace
|
|
435 |
TUint32* ptr = reinterpret_cast< TUint32* >(aData);
|
|
436 |
activationInfo.iTraceWord = *ptr++;
|
|
437 |
activationInfo.iMultiPartId = aExtra;
|
|
438 |
retval = iOstTraceBitmap->IsTraceActivated( activationInfo.iComponentId, activationInfo.iTraceWord );
|
|
439 |
|
|
440 |
if (retval)
|
|
441 |
{
|
|
442 |
// Insert the item to the array
|
|
443 |
TInt ret = InsertIfNotExist( activationInfo );
|
|
444 |
|
|
445 |
if (KErrNone == ret)
|
|
446 |
{
|
|
447 |
CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
|
|
448 |
|
|
449 |
// Write the trace. Skip first 4 bytes as it's the traceWord which is given in different parameter
|
|
450 |
iWriter->WriteTraceCoreFrame( activationInfo.iComponentId, activationInfo.iTraceWord,
|
|
451 |
aHeader, aHeader2, aContext, activationInfo.iComponentId,
|
|
452 |
activationInfo.iTraceWord, aData + 4, aExtra, aPc, recordSize - 4 );
|
|
453 |
}
|
|
454 |
else
|
|
455 |
{
|
|
456 |
retval = EFalse;
|
|
457 |
}
|
|
458 |
}
|
|
459 |
}
|
|
460 |
// Middle or last part of multipart trace
|
|
461 |
else if (multiPartOffset == BTrace::EMultipartMiddle || multiPartOffset == BTrace::EMultipartLast)
|
|
462 |
{
|
|
463 |
// Check index of component id in array
|
|
464 |
TMultiPartActivationInfo tempInfo;
|
|
465 |
tempInfo.iMultiPartId = aExtra;
|
|
466 |
|
|
467 |
TInt index = Find( aExtra );
|
|
468 |
|
|
469 |
if (index != KErrNotFound)
|
|
470 |
{
|
|
471 |
CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
|
|
472 |
|
|
473 |
TMultiPartActivationInfo activationInfo;
|
|
474 |
activationInfo.iComponentId = iMultipartArray[index].iComponentId;
|
|
475 |
activationInfo.iTraceWord = iMultipartArray[index].iTraceWord;
|
|
476 |
activationInfo.iMultiPartId = iMultipartArray[index].iMultiPartId;
|
|
477 |
|
|
478 |
// Write the trace
|
|
479 |
iWriter->WriteTraceCoreFrame( activationInfo.iComponentId, activationInfo.iTraceWord, aHeader, aHeader2,
|
|
480 |
aContext, activationInfo.iComponentId, activationInfo.iTraceWord, aData, aExtra, aPc, recordSize );
|
|
481 |
|
|
482 |
// Last part, remove the item from the array
|
|
483 |
if (multiPartOffset == BTrace::EMultipartLast)
|
|
484 |
{
|
|
485 |
Remove(index);
|
|
486 |
}
|
|
487 |
}
|
|
488 |
}
|
|
489 |
|
|
490 |
//Trace from here is not allowed
|
|
491 |
|
|
492 |
return retval;
|
|
493 |
}
|
|
494 |
|
|
495 |
#else // __SMP__
|
|
496 |
|
|
497 |
/**
|
|
498 |
* Handles this Multipart trace
|
|
499 |
*
|
|
500 |
* @param aHeader BTrace header
|
|
501 |
* @param aHeader2 Extra header data
|
|
502 |
* @param aContext The thread context in which this function was called
|
|
503 |
* @param a1 First parameter
|
|
504 |
* @param a2 Second parameter
|
|
505 |
* @param aData The data
|
|
506 |
* @param aExtra Extra trace data
|
|
507 |
* @param aPc The program counter value
|
|
508 |
* @return ETrue if trace was processed, EFalse if not
|
|
509 |
*/
|
|
510 |
TBool DBTraceOstCategoryHandler::HandleMultiPart( TUint32 aHeader, TUint32 aHeader2, const TUint32 aContext,
|
|
511 |
const TUint32 a1, const TUint32 a2, const TUint32 aData, const TUint32 aExtra,
|
|
512 |
const TUint32 aPc)
|
|
513 |
{
|
|
514 |
TBool retval = EFalse;
|
|
515 |
|
|
516 |
if (iMultiPartTrace.iMultiPartId == 0 || iMultiPartTrace.iMultiPartId == aExtra)
|
|
517 |
{
|
|
518 |
// First part of multipart trace
|
|
519 |
if ((aHeader2 & BTrace::EMultipartFlagMask) == BTrace::EMultipartFirst)
|
|
520 |
{
|
|
521 |
TUint32 componentId = a2;
|
|
522 |
TUint32* ptr = ( TUint32* )aData;
|
|
523 |
TUint32 traceWord = *ptr++;
|
|
524 |
retval = iOstTraceBitmap->IsTraceActivated( componentId, traceWord );
|
|
525 |
if (retval)
|
|
526 |
{
|
|
527 |
CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
|
|
528 |
|
|
529 |
// Set values
|
|
530 |
iMultiPartTrace.iMultiPartId = aExtra;
|
|
531 |
iMultiPartTrace.iComponentId = componentId;
|
|
532 |
iMultiPartTrace.iTraceWord = traceWord;
|
|
533 |
iMultiPartTrace.iContext = aContext;
|
|
534 |
iMultiPartTrace.iPc = aPc;
|
|
535 |
iMultiPartTrace.iHeader = aHeader;
|
|
536 |
|
|
537 |
// Remove the multipart information from the header2
|
|
538 |
aHeader2 &= ~BTrace::EMultipartFlagMask;
|
|
539 |
iMultiPartTrace.iHeader2 = aHeader2;
|
|
540 |
|
|
541 |
// Copy the data
|
|
542 |
TUint8 recordSize = static_cast< TUint8 >( ( aHeader >> ( BTrace::ESizeIndex * KByteSize ) ) & KByteMask );
|
|
543 |
TUint32 dataSize = recordSize - CalculateDataStartOffset(aHeader);
|
|
544 |
memcpy(iMultiPartTrace.iData, (TUint8*)aData + KTraceGroupIdLen, dataSize - KTraceGroupIdLen);
|
|
545 |
iMultiPartTrace.iDataInserted = dataSize - KTraceGroupIdLen;
|
|
546 |
}
|
|
547 |
}
|
|
548 |
// Middle part of multipart trace
|
|
549 |
else if ((aHeader2 & BTrace::EMultipartFlagMask) == BTrace::EMultipartMiddle)
|
|
550 |
{
|
|
551 |
retval = ETrue;
|
|
552 |
// Add to the data buffer
|
|
553 |
TUint8 recordSize = static_cast< TUint8 >( ( aHeader >> ( BTrace::ESizeIndex * KByteSize ) ) & KByteMask );
|
|
554 |
TUint32 dataSize = recordSize - CalculateDataStartOffset(aHeader);
|
|
555 |
|
|
556 |
// Check that trace is not too big
|
|
557 |
if (iMultiPartTrace.iDataInserted + dataSize < MAX_TRACE_DATA_SIZE)
|
|
558 |
{
|
|
559 |
CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
|
|
560 |
memcpy(iMultiPartTrace.iData + iMultiPartTrace.iDataInserted, (TUint8*)aData, dataSize);
|
|
561 |
iMultiPartTrace.iDataInserted += dataSize;
|
|
562 |
}
|
|
563 |
}
|
|
564 |
// Last part of multipart trace
|
|
565 |
else if ((aHeader2 & BTrace::EMultipartFlagMask) == BTrace::EMultipartLast)
|
|
566 |
{
|
|
567 |
retval = ETrue;
|
|
568 |
TUint32 totalDataLen = a1;
|
|
569 |
TUint32 offset = a2;
|
|
570 |
|
|
571 |
// Add to the data buffer
|
|
572 |
TUint32 partLen = totalDataLen - offset;
|
|
573 |
TUint32 dataStartOffset = CalculateDataStartOffset(iMultiPartTrace.iHeader);
|
|
574 |
|
|
575 |
// Check that trace is not too big
|
|
576 |
if (iMultiPartTrace.iDataInserted + partLen <= MAX_TRACE_DATA_SIZE)
|
|
577 |
{
|
|
578 |
CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
|
|
579 |
|
|
580 |
// If the last part contains only last four bytes, it's a value instead of pointer
|
|
581 |
if (partLen == KFourBytes)
|
|
582 |
{
|
|
583 |
iMultiPartTrace.iData[iMultiPartTrace.iDataInserted] = aData & KByteMask;
|
|
584 |
iMultiPartTrace.iData[iMultiPartTrace.iDataInserted + 1] = (aData >> 8) & KByteMask; //CodForChk_Dis_Magic
|
|
585 |
iMultiPartTrace.iData[iMultiPartTrace.iDataInserted + 2] = (aData >> 16) & KByteMask; //CodForChk_Dis_Magic
|
|
586 |
iMultiPartTrace.iData[iMultiPartTrace.iDataInserted + 3] = (aData >> 24) & KByteMask; //CodForChk_Dis_Magic
|
|
587 |
}
|
|
588 |
else
|
|
589 |
{
|
|
590 |
memcpy(iMultiPartTrace.iData + iMultiPartTrace.iDataInserted, (TUint8*)aData, partLen);
|
|
591 |
}
|
|
592 |
|
|
593 |
// Total data length. Four bytes is taken out because it was parsed out from the data
|
|
594 |
// array when parsing first part of the trace
|
|
595 |
totalDataLen = totalDataLen + dataStartOffset - KFourBytes;
|
|
596 |
|
|
597 |
}
|
|
598 |
else
|
|
599 |
{
|
|
600 |
// Total data length. Four bytes is taken out because it was parsed out from the data
|
|
601 |
// array when parsing first part of the trace
|
|
602 |
totalDataLen = iMultiPartTrace.iDataInserted + dataStartOffset - KFourBytes;
|
|
603 |
}
|
|
604 |
|
|
605 |
// Write the trace
|
|
606 |
iWriter->WriteTraceCoreFrame( iMultiPartTrace.iComponentId, iMultiPartTrace.iTraceWord,
|
|
607 |
iMultiPartTrace.iHeader, iMultiPartTrace.iHeader2, iMultiPartTrace.iContext,
|
|
608 |
iMultiPartTrace.iComponentId, iMultiPartTrace.iTraceWord, (TUint32)iMultiPartTrace.iData,
|
|
609 |
iMultiPartTrace.iMultiPartId, iMultiPartTrace.iPc, totalDataLen);
|
|
610 |
|
|
611 |
iMultiPartTrace.iMultiPartId = 0;
|
|
612 |
}
|
|
613 |
}
|
|
614 |
|
|
615 |
return retval;
|
|
616 |
}
|
|
617 |
|
|
618 |
/**
|
|
619 |
* Calculates data start offset
|
|
620 |
*
|
|
621 |
* @param aHeader BTrace header
|
|
622 |
*/
|
|
623 |
TUint32 DBTraceOstCategoryHandler::CalculateDataStartOffset( TUint32 aHeader )
|
|
624 |
{
|
|
625 |
TUint32 offset = 0;
|
|
626 |
TUint8 flags = static_cast< TUint8 >( ( aHeader >> ( BTrace::EFlagsIndex * KByteSize ) ) & KByteMask );
|
|
627 |
|
|
628 |
// First add header length
|
|
629 |
offset += KBTraceHeaderLen;
|
|
630 |
|
|
631 |
// Header2 is present
|
|
632 |
if ( flags & BTrace::EHeader2Present )
|
|
633 |
{
|
|
634 |
offset += KBTraceVariableLen;
|
|
635 |
}
|
|
636 |
// Timestamp is present
|
|
637 |
if ( flags & BTrace::ETimestampPresent )
|
|
638 |
{
|
|
639 |
offset += KBTraceVariableLen;
|
|
640 |
}
|
|
641 |
// Timestamp2 is present
|
|
642 |
if ( flags & BTrace::ETimestamp2Present )
|
|
643 |
{
|
|
644 |
offset += KBTraceVariableLen;
|
|
645 |
}
|
|
646 |
// Context ID is present
|
|
647 |
if ( flags & BTrace::EContextIdPresent )
|
|
648 |
{
|
|
649 |
offset += KBTraceVariableLen;
|
|
650 |
}
|
|
651 |
// Program counter is present
|
|
652 |
if ( flags & BTrace::EPcPresent )
|
|
653 |
{
|
|
654 |
offset += KBTraceVariableLen;
|
|
655 |
}
|
|
656 |
// Extra value is present
|
|
657 |
if ( flags & BTrace::EExtraPresent )
|
|
658 |
{
|
|
659 |
offset += KBTraceVariableLen;
|
|
660 |
}
|
|
661 |
|
|
662 |
// Next 8 bytes came with first and second parameter of the multipart trace
|
|
663 |
offset += KFourBytes;
|
|
664 |
offset += KFourBytes;
|
|
665 |
|
|
666 |
return offset;
|
|
667 |
}
|
|
668 |
|
|
669 |
#endif // !__SMP__
|
|
670 |
|
|
671 |
// End of File
|