0
|
1 |
// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
2 |
// All rights reserved.
|
|
3 |
// This component and the accompanying materials are made available
|
|
4 |
// under the terms of "Eclipse Public License v1.0"
|
|
5 |
// which accompanies this distribution, and is available
|
|
6 |
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
|
7 |
//
|
|
8 |
// Initial Contributors:
|
|
9 |
// Nokia Corporation - initial contribution.
|
|
10 |
//
|
|
11 |
// Contributors:
|
|
12 |
//
|
|
13 |
// Description:
|
|
14 |
//
|
|
15 |
|
|
16 |
#include <e32debug.h>
|
|
17 |
#include <e32btrace.h>
|
|
18 |
#include <d32btrace.h>
|
|
19 |
|
|
20 |
#include "servercrashdatasource.h"
|
|
21 |
|
|
22 |
// Required for interface to Debug Security Server via RSecuritySvrSession
|
|
23 |
#include "coredumpsession.h"
|
|
24 |
|
|
25 |
CServerCrashDataSource::CServerCrashDataSource(RSecuritySvrSession &aSource)
|
|
26 |
: iSecSess(aSource)
|
|
27 |
{
|
|
28 |
//no implementation
|
|
29 |
}
|
|
30 |
|
|
31 |
CServerCrashDataSource* CServerCrashDataSource::NewL(RSecuritySvrSession &aSource)
|
|
32 |
{
|
|
33 |
CServerCrashDataSource *self = new(ELeave) CServerCrashDataSource(aSource);
|
|
34 |
CleanupStack::PushL(self);
|
|
35 |
self->ConstructL();
|
|
36 |
CleanupStack::Pop();
|
|
37 |
return self;
|
|
38 |
}
|
|
39 |
|
|
40 |
|
|
41 |
TTag* CServerCrashDataSource::GetTag(const TTagHeader* aTagHdr, const TInt aElement)
|
|
42 |
{
|
|
43 |
TUint8* ptr = (TUint8*)aTagHdr + sizeof(TTagHeader);
|
|
44 |
TUint8* blockEnd = ptr + (aTagHdr->iNumTags * sizeof(TTag));
|
|
45 |
|
|
46 |
while(ptr < blockEnd)
|
|
47 |
{
|
|
48 |
TTag* tag = (TTag*)ptr;
|
|
49 |
if(tag->iTagId == aElement)
|
|
50 |
{
|
|
51 |
return tag;
|
|
52 |
}
|
|
53 |
ptr += sizeof(TTag);
|
|
54 |
}
|
|
55 |
return NULL;
|
|
56 |
}
|
|
57 |
|
|
58 |
// second-phase constructor
|
|
59 |
void CServerCrashDataSource::ConstructL()
|
|
60 |
{
|
|
61 |
LOG_MSG("->CServerCrashDataSource::ConstructL()\n" );
|
|
62 |
// Get the debug func block and make appropriate changes to our structures
|
|
63 |
TInt err;
|
|
64 |
TUint32 bufsize = 0;
|
|
65 |
LOG_MSG( " -> iSecSess->GetDebugFunctionalityBufSize( &bufsize )\n" );
|
|
66 |
err = iSecSess.GetDebugFunctionalityBufSize( &bufsize );
|
|
67 |
|
|
68 |
if( (err != KErrNone) || (0 == bufsize) )
|
|
69 |
{
|
|
70 |
// No debug functionality block, cannot do much without that.
|
|
71 |
LOG_MSG2("CServerCrashDataSource::ConstructL() - unable to get debug functionality block! err:%d\n", err);
|
|
72 |
User::Leave( KErrNotSupported );
|
|
73 |
}
|
|
74 |
|
|
75 |
RBuf8 DFBlock;
|
|
76 |
DFBlock.CreateL(bufsize);
|
|
77 |
DFBlock.CleanupClosePushL();
|
|
78 |
|
|
79 |
LOG_MSG2( " -> HBufC8::NewLC( bufsize=%d )\n", bufsize );
|
|
80 |
|
|
81 |
|
|
82 |
LOG_MSG("CServerCrashDataSource::ConstrucL -> GetDebugFunctionality()\n" );
|
|
83 |
err = iSecSess.GetDebugFunctionality(DFBlock);
|
|
84 |
if( KErrNone != err )
|
|
85 |
{
|
|
86 |
LOG_MSG( "CServerCrashDataSource::ConstructL() : ERROR !* : Could not retrieve debug functionality block\n" );
|
|
87 |
User::Leave( KErrNotSupported );
|
|
88 |
}
|
|
89 |
|
|
90 |
LOG_MSG( " -> GetDebugHeader( EDF_TagHdrId_RegistersCore )\n" );
|
|
91 |
TTagHeader * hdr = GetDebugHeader( ETagHeaderIdRegistersCore, DFBlock );
|
|
92 |
|
|
93 |
if( hdr == NULL )
|
|
94 |
{
|
|
95 |
LOG_MSG( "Could not retrieve ETagHeaderIdRegistersCore register debug block\n" );
|
|
96 |
}
|
|
97 |
else if( 0 == hdr->iNumTags )
|
|
98 |
{
|
|
99 |
LOG_MSG( "Zero tags found for ETagHeaderIdRegistersCore register debug block\n" );
|
|
100 |
}
|
|
101 |
else
|
|
102 |
{
|
|
103 |
|
|
104 |
iRegisterList.ReserveL( (TInt)hdr->iNumTags );
|
|
105 |
|
|
106 |
// Skip the header to get to the tags
|
|
107 |
TUint8 * ptr = ((TUint8 *) hdr) + sizeof( TTagHeader );
|
|
108 |
TTag * tag = (TTag *) ptr;
|
|
109 |
|
|
110 |
TRegisterData regData;
|
|
111 |
TRegisterData * reg = ®Data;
|
|
112 |
|
|
113 |
// Process all the register tags
|
|
114 |
for( TInt regIdx = 0; regIdx < hdr->iNumTags; regIdx ++ )
|
|
115 |
{
|
|
116 |
reg->iRegClass = 0; // Core = 0
|
|
117 |
reg->iId = tag->iTagId; //
|
|
118 |
reg->iSubId = 0; //
|
|
119 |
reg->iSize = 2; // Should all be 32 bits == 2.
|
|
120 |
reg->iAvailable = ETrue;
|
|
121 |
reg->iValue64 = 0;
|
|
122 |
iRegisterList.Append( *reg );
|
|
123 |
tag++;
|
|
124 |
}
|
|
125 |
}
|
|
126 |
|
|
127 |
hdr = GetDebugHeader( ETagHeaderIdMemory, DFBlock );
|
|
128 |
if( hdr == NULL )
|
|
129 |
{
|
|
130 |
LOG_MSG( "Could not retrieve ETagHeaderIdMemory. Cannot read memory\n" );
|
|
131 |
iMaxMemReadSize = 0;
|
|
132 |
}
|
|
133 |
else if( 0 == hdr->iNumTags )
|
|
134 |
{
|
|
135 |
LOG_MSG( "Zero tags found for ETagHeaderIdMemory register debug block\n" );
|
|
136 |
iMaxMemReadSize = 0;
|
|
137 |
}
|
|
138 |
else
|
|
139 |
{
|
|
140 |
TTag* tag = GetTag( hdr, EMemoryMaxBlockSize );
|
|
141 |
if( tag )
|
|
142 |
{
|
|
143 |
//LOG_MSG2( " EMemoryMaxBlockSize =0x%X\n", tag->iValue );
|
|
144 |
iMaxMemReadSize = tag->iValue;
|
|
145 |
}
|
|
146 |
}
|
|
147 |
|
|
148 |
iLastThreadListSize = 1;
|
|
149 |
iLastProcListSize = 1;
|
|
150 |
iLastRegListSize = 1;
|
|
151 |
|
|
152 |
CleanupStack::PopAndDestroy(&DFBlock);
|
|
153 |
}
|
|
154 |
|
|
155 |
//
|
|
156 |
// Returns the start of the sub block for this TTagHdrId_e
|
|
157 |
//
|
|
158 |
TTagHeader * CServerCrashDataSource::GetDebugHeader( const TTagHeaderId aTagHdrId, const TDesC8 &aDFBlock )
|
|
159 |
{
|
|
160 |
TInt DFBlockSize = aDFBlock.Size();
|
|
161 |
|
|
162 |
TTagHeader* headerPtr = (TTagHeader*) aDFBlock.Ptr();
|
|
163 |
TUint8 * ptr = (TUint8 * ) aDFBlock.Ptr();
|
|
164 |
|
|
165 |
while( headerPtr < ( (TTagHeader*)aDFBlock.Ptr() + DFBlockSize ) )
|
|
166 |
{
|
|
167 |
|
|
168 |
if( headerPtr->iTagHdrId != aTagHdrId )
|
|
169 |
{
|
|
170 |
ptr += sizeof(TTagHeader) + ( headerPtr->iNumTags * sizeof(TTag) );
|
|
171 |
headerPtr = (TTagHeader*) ptr;
|
|
172 |
}
|
|
173 |
else
|
|
174 |
{
|
|
175 |
return ( headerPtr );
|
|
176 |
}
|
|
177 |
}
|
|
178 |
|
|
179 |
return NULL;
|
|
180 |
}
|
|
181 |
|
|
182 |
// destructor
|
|
183 |
CServerCrashDataSource::~CServerCrashDataSource()
|
|
184 |
{
|
|
185 |
LOG_MSG( "server_crashdatasource.cpp::CServerCrashDataSource::~CServerCrashDataSource()\n" );
|
|
186 |
iRegisterList.Reset();
|
|
187 |
iThreadListBuffer.Close();
|
|
188 |
iProcListBuffer.Close();
|
|
189 |
iExecutableListBuffer.Close();
|
|
190 |
}
|
|
191 |
|
|
192 |
void CServerCrashDataSource::SetRegValuesL( const TUint64 aThreadId, RRegisterList &aRegisterList )
|
|
193 |
{
|
|
194 |
|
|
195 |
LOG_MSG2("->CServerCrashDataSource::SetRegValuesL(aThreadId=%Lu)\n", aThreadId);
|
|
196 |
|
|
197 |
TInt numberOfRegisters = aRegisterList.Count();
|
|
198 |
|
|
199 |
RBuf8 ids;
|
|
200 |
ids.CreateL( numberOfRegisters * sizeof(TFunctionalityRegister) );
|
|
201 |
ids.CleanupClosePushL();
|
|
202 |
|
|
203 |
TInt totalByteSize = 0; // Keeps track of the number of bytes that we are requesting
|
|
204 |
|
|
205 |
for( TInt i=0; i < numberOfRegisters; i++ )
|
|
206 |
{
|
|
207 |
TRegisterInfo reg = (TRegisterInfo)( aRegisterList[i].iId );
|
|
208 |
|
|
209 |
// iSize = (0 == 1 byte); (3 == 8 bytes)
|
|
210 |
TInt byteSize = (aRegisterList[i].iSize) << 1;
|
|
211 |
totalByteSize += byteSize;
|
|
212 |
ids.Append( reinterpret_cast<const TUint8*>(®), sizeof(TRegisterInfo) );
|
|
213 |
}
|
|
214 |
|
|
215 |
|
|
216 |
RBuf8 registerValues;
|
|
217 |
registerValues.CreateL( totalByteSize );
|
|
218 |
registerValues.CleanupClosePushL();
|
|
219 |
|
|
220 |
RBuf8 registerFlags;
|
|
221 |
registerFlags.CreateL( numberOfRegisters );
|
|
222 |
registerFlags.CleanupClosePushL();
|
|
223 |
|
|
224 |
LOG_MSG("CServerCrashDataSource::SetRegValuesL - reading registers\n");
|
|
225 |
User::LeaveIfError(iSecSess.ReadRegisters( aThreadId, ids, registerValues, registerFlags ));
|
|
226 |
|
|
227 |
// Now copy the values back to the array and mark the availability from the flags
|
|
228 |
|
|
229 |
TUint8* valuePtr = (TUint8*) registerValues.Ptr();
|
|
230 |
|
|
231 |
for( TInt i=0; i < numberOfRegisters; i++ )
|
|
232 |
{
|
|
233 |
|
|
234 |
TRegisterData & reg = aRegisterList[i];
|
|
235 |
|
|
236 |
switch( reg.iSize )
|
|
237 |
{
|
|
238 |
case 0:
|
|
239 |
reg.iValue8 = *((TUint8 *)valuePtr);
|
|
240 |
valuePtr += 1;
|
|
241 |
break;
|
|
242 |
case 1:
|
|
243 |
reg.iValue16 = *((TUint16 *)valuePtr);
|
|
244 |
valuePtr += 2;
|
|
245 |
break;
|
|
246 |
case 2:
|
|
247 |
reg.iValue32 = *((TUint32 *)valuePtr);
|
|
248 |
valuePtr += 4;
|
|
249 |
break;
|
|
250 |
case 3:
|
|
251 |
reg.iValue64 = *((TUint64 *)valuePtr);
|
|
252 |
valuePtr += 8;
|
|
253 |
break;
|
|
254 |
}
|
|
255 |
|
|
256 |
if( EValid == registerFlags[i] )
|
|
257 |
{
|
|
258 |
reg.iAvailable = ETrue;
|
|
259 |
}
|
|
260 |
else
|
|
261 |
{
|
|
262 |
reg.iAvailable = EFalse;
|
|
263 |
}
|
|
264 |
}
|
|
265 |
|
|
266 |
CleanupStack::PopAndDestroy(®isterFlags);
|
|
267 |
CleanupStack::PopAndDestroy(®isterValues);
|
|
268 |
CleanupStack::PopAndDestroy(&ids);
|
|
269 |
}
|
|
270 |
|
|
271 |
|
|
272 |
void CServerCrashDataSource::PrintRegs( RRegisterList & aRegisterList )
|
|
273 |
{
|
|
274 |
|
|
275 |
LOG_MSG( "CServerCrashDataSource::PrintRegs()\n" );
|
|
276 |
|
|
277 |
if( aRegisterList.Count() > 0 )
|
|
278 |
{
|
|
279 |
|
|
280 |
|
|
281 |
for( TInt i = 0; i < aRegisterList.Count(); i ++ )
|
|
282 |
{
|
|
283 |
|
|
284 |
TRegisterData & reg = aRegisterList[i];
|
|
285 |
|
|
286 |
RDebug::Printf( " reg[%d] iRegClass=%d, iId=%d, iSubId=%d, iSize=%d, iAvailable=%d\n",
|
|
287 |
i, reg.iRegClass, reg.iId, reg.iSubId, reg.iSize, reg.iAvailable );
|
|
288 |
|
|
289 |
switch ( reg.iSize )
|
|
290 |
{
|
|
291 |
case 0:
|
|
292 |
RDebug::Printf( " iValue8=0x%X\n", reg.iValue8 ); break;
|
|
293 |
case 1:
|
|
294 |
RDebug::Printf( " iValue16=0x%X\n", reg.iValue16 ); break;
|
|
295 |
case 2:
|
|
296 |
RDebug::Printf( " iValue32=0x%X\n", reg.iValue32 ); break;
|
|
297 |
case 3:
|
|
298 |
RDebug::Printf( " iValue64=0x%X%X\n",
|
|
299 |
I64HIGH(reg.iValue64), I64LOW(reg.iValue64) );
|
|
300 |
break;
|
|
301 |
}
|
|
302 |
}
|
|
303 |
}
|
|
304 |
else
|
|
305 |
{
|
|
306 |
RDebug::Printf( " No registers to print\n" );
|
|
307 |
}
|
|
308 |
}
|
|
309 |
|
|
310 |
|
|
311 |
|
|
312 |
void CServerCrashDataSource::GetRegisterListL( RRegisterList & aRegisterList )
|
|
313 |
{
|
|
314 |
|
|
315 |
LOG_MSG("CServerCrashDataSource::GetRegisterListL()\n");
|
|
316 |
/* Copy the registers that were returned in the debug functionality block */
|
|
317 |
|
|
318 |
aRegisterList.Reset();
|
|
319 |
TInt count = iRegisterList.Count();
|
|
320 |
for(TInt i = 0; i < count; ++i)
|
|
321 |
{
|
|
322 |
aRegisterList.AppendL( iRegisterList[i] );
|
|
323 |
}
|
|
324 |
}
|
|
325 |
|
|
326 |
void CServerCrashDataSource::ReadRegistersL( const TUint64 aThreadId, RRegisterList & aRegisterList )
|
|
327 |
{
|
|
328 |
|
|
329 |
LOG_MSG2("CServerCrashDataSource::ReadRegistersL(aThreadId=%Lu)\n", aThreadId);
|
|
330 |
|
|
331 |
if( aRegisterList.Count() )
|
|
332 |
{
|
|
333 |
LOG_MSG("CServerCrashDataSource::ReadRegistersL - register list already supplied\n" );
|
|
334 |
SetRegValuesL( aThreadId, aRegisterList );
|
|
335 |
}
|
|
336 |
else
|
|
337 |
{
|
|
338 |
LOG_MSG("CServerCrashDataSource::ReadRegistersL - suppliying register list\n" );
|
|
339 |
GetRegisterListL( aRegisterList );
|
|
340 |
SetRegValuesL( aThreadId, aRegisterList );
|
|
341 |
}
|
|
342 |
|
|
343 |
//PrintRegs( aRegisterList );
|
|
344 |
}
|
|
345 |
|
|
346 |
|
|
347 |
/**
|
|
348 |
Purpose:
|
|
349 |
Read memory from the security server. If the length of the data is greater
|
|
350 |
than the maximum length supported by the security server (as reported debug
|
|
351 |
functionality block tag EMemoryMaxBlockSize), break up the read into reads
|
|
352 |
of this maximum size.
|
|
353 |
|
|
354 |
@pre Must be connected to the debug security server
|
|
355 |
@pre Must be attached to the process that owns aThreadId
|
|
356 |
|
|
357 |
@param aThreadId - The id of the thread relative to which the read should take place
|
|
358 |
@param aAddress - The virtual address to read from
|
|
359 |
@param aLength - The number of bytes to read
|
|
360 |
@param aData - The buffer to read into
|
|
361 |
@return Any error which may be returned by Security Server::ReadMemory()
|
|
362 |
*/
|
|
363 |
void CServerCrashDataSource::ReadMemoryL(
|
|
364 |
const TUint64 aThreadId,
|
|
365 |
const TUint32 aAddress,
|
|
366 |
const TUint32 aLength,
|
|
367 |
TDes8 & aData )
|
|
368 |
{
|
|
369 |
LOG_MSG4("->CServerCrashDataSource::ReadMemoryL(aThreadId=0x%X, aAddress=0x%X, aLength=%d)\n",
|
|
370 |
I64LOW(aThreadId), aAddress, aLength);
|
|
371 |
TInt err;
|
|
372 |
|
|
373 |
if( aLength <= iMaxMemReadSize )
|
|
374 |
{
|
|
375 |
err = iSecSess.ReadMemory( aThreadId, aAddress, aLength, aData, EAccess32, EEndLE8);
|
|
376 |
}
|
|
377 |
else
|
|
378 |
{
|
|
379 |
// If aLength is greater than iMaxMemReadSize, then break up the read into
|
|
380 |
// smaller packets and append them to aData
|
|
381 |
|
|
382 |
RBuf8 readData;
|
|
383 |
readData.CreateL( iMaxMemReadSize );
|
|
384 |
|
|
385 |
TInt readLength = iMaxMemReadSize;
|
|
386 |
TInt readSoFar = 0;
|
|
387 |
do
|
|
388 |
{
|
|
389 |
LOG_MSG3( " iSecSess->ReadMemory(addr=0x%X, length=%d)\n", aAddress+readSoFar, readLength );
|
|
390 |
err = iSecSess.ReadMemory( aThreadId, aAddress+readSoFar, readLength, readData, EAccess32, EEndLE8 );
|
|
391 |
if(err != KErrNone)
|
|
392 |
break;
|
|
393 |
|
|
394 |
readSoFar += readLength;
|
|
395 |
aData.Append( readData );
|
|
396 |
if( (aLength - readSoFar) < iMaxMemReadSize )
|
|
397 |
{
|
|
398 |
readLength = aLength - readSoFar;
|
|
399 |
}
|
|
400 |
}
|
|
401 |
while( readSoFar < aLength );
|
|
402 |
readData.Close();
|
|
403 |
}
|
|
404 |
User::LeaveIfError(err);
|
|
405 |
}
|
|
406 |
|
|
407 |
|
|
408 |
void CServerCrashDataSource::GetProcessListL( RProcessPointerList & aProcessList,
|
|
409 |
TUint & aTotalProcessListDescSize )
|
|
410 |
{
|
|
411 |
//LOG_MSG( "CServerCrashDataSource::GetProcessListL()\n" );
|
|
412 |
|
|
413 |
// Delete any objects in the array, since we will replace them.
|
|
414 |
aProcessList.ResetAndDestroy();
|
|
415 |
aTotalProcessListDescSize = 0;
|
|
416 |
|
|
417 |
if( iProcListBuffer.Size() != iLastProcListSize )
|
|
418 |
{
|
|
419 |
LOG_MSG2( " iProcListBuffer.ReAlloc( %d)\n", iLastProcListSize );
|
|
420 |
iProcListBuffer.ReAllocL( iLastProcListSize );
|
|
421 |
}
|
|
422 |
|
|
423 |
DoGetListL( EProcesses, (TUint)(-1), (TUint)(-1), iProcListBuffer, iLastProcListSize );
|
|
424 |
|
|
425 |
iLastProcListSize = iProcListBuffer.Size();
|
|
426 |
|
|
427 |
TUint8* ptr = (TUint8*)( iProcListBuffer.Ptr() );
|
|
428 |
const TUint8* ptrEnd = ptr + iLastProcListSize;
|
|
429 |
//LOG_MSG3( " Data start,end=(0x%x, 0x%x)\n", ptr, ptrEnd );
|
|
430 |
|
|
431 |
while( ptr < ptrEnd )
|
|
432 |
{
|
|
433 |
|
|
434 |
TProcessListEntry *entry = (TProcessListEntry*)ptr;
|
|
435 |
|
|
436 |
if( !entry )
|
|
437 |
{
|
|
438 |
LOG_MSG( " ERROR !* : TProcessListEntry is NULL\n" );
|
|
439 |
User::Leave(KErrBadHandle);
|
|
440 |
}
|
|
441 |
|
|
442 |
TUint64 id = entry->iProcessId;
|
|
443 |
if( entry->iFileNameLength == 0 )
|
|
444 |
{
|
|
445 |
LOG_MSG4( " Skipping process 0x%X%X : entry->iFileNameLength=%d",
|
|
446 |
I64HIGH(entry->iProcessId), I64LOW(entry->iProcessId), entry->iFileNameLength );
|
|
447 |
ptr += Align4( entry->GetSize() );
|
|
448 |
continue;
|
|
449 |
}
|
|
450 |
|
|
451 |
/*
|
|
452 |
LOG_MSG4( " process 0x%X%X has iFileNameLength=%d",
|
|
453 |
I64HIGH(entry->iProcessId), I64LOW(entry->iProcessId), entry->iFileNameLength );
|
|
454 |
*/
|
|
455 |
|
|
456 |
TPtrC entryName(&(entry->iNames[0]), entry->iFileNameLength);
|
|
457 |
|
|
458 |
CProcessInfo *procInfoPtr = CProcessInfo::NewL(id, entryName );
|
|
459 |
|
|
460 |
TInt err = aProcessList.Append( procInfoPtr );
|
|
461 |
if(err != KErrNone)
|
|
462 |
{
|
|
463 |
delete procInfoPtr;
|
|
464 |
User::Leave(err);
|
|
465 |
}
|
|
466 |
|
|
467 |
aTotalProcessListDescSize += procInfoPtr->Size();
|
|
468 |
|
|
469 |
ptr += Align4( entry->GetSize() );
|
|
470 |
}
|
|
471 |
}
|
|
472 |
|
|
473 |
|
|
474 |
void CServerCrashDataSource::GetExecutableListL( RExecutablePointerList & aExecutableList,
|
|
475 |
TUint & aTotalExecutableListDescSize )
|
|
476 |
{
|
|
477 |
LOG_MSG( "CServerCrashDataSource::GetExecutableListL()\n" );
|
|
478 |
|
|
479 |
// Delete any objects in the array, since we will replace them.
|
|
480 |
aExecutableList.ResetAndDestroy();
|
|
481 |
aTotalExecutableListDescSize = 0;
|
|
482 |
|
|
483 |
if( iExecutableListBuffer.Size() != iLastExecutableListSize )
|
|
484 |
{
|
|
485 |
LOG_MSG2( " iExecutableListBuffer.ReAlloc( %d)\n", iLastExecutableListSize );
|
|
486 |
iExecutableListBuffer.ReAllocL( iLastExecutableListSize );
|
|
487 |
}
|
|
488 |
|
|
489 |
DoGetListL( EExecutables, (TUint)(-1), (TUint)(-1), iExecutableListBuffer, iLastExecutableListSize );
|
|
490 |
|
|
491 |
iLastExecutableListSize = iExecutableListBuffer.Size();
|
|
492 |
|
|
493 |
TUint8* ptr = (TUint8*)( iExecutableListBuffer.Ptr() );
|
|
494 |
const TUint8* ptrEnd = ptr + iLastExecutableListSize;
|
|
495 |
//LOG_MSG3( " Data start,end=(0x%x, 0x%x)\n", ptr, ptrEnd );
|
|
496 |
|
|
497 |
while( ptr < ptrEnd )
|
|
498 |
{
|
|
499 |
|
|
500 |
TExecutablesListEntry *entry = (TExecutablesListEntry*)ptr;
|
|
501 |
|
|
502 |
if( !entry )
|
|
503 |
{
|
|
504 |
LOG_MSG( " ERROR !* : TExecutablesListEntry is NULL\n" );
|
|
505 |
User::Leave(KErrBadHandle);
|
|
506 |
}
|
|
507 |
|
|
508 |
if( entry->iNameLength == 0 )
|
|
509 |
{
|
|
510 |
LOG_MSG( " Skipping executable : entry->iNameLength=0" );
|
|
511 |
ptr += Align4( entry->GetSize() );
|
|
512 |
continue;
|
|
513 |
}
|
|
514 |
|
|
515 |
TPtrC entryName(&(entry->iName[0]), entry->iNameLength);
|
|
516 |
|
|
517 |
CExecutableInfo *executableInfoPtr =
|
|
518 |
CExecutableInfo::NewL(entryName, entry->iIsActivelyDebugged, entry->iIsPassivelyDebugged );
|
|
519 |
|
|
520 |
TInt err = aExecutableList.Append( executableInfoPtr );
|
|
521 |
if(err != KErrNone)
|
|
522 |
{
|
|
523 |
delete executableInfoPtr;
|
|
524 |
User::Leave(err);
|
|
525 |
}
|
|
526 |
|
|
527 |
aTotalExecutableListDescSize += executableInfoPtr->Size();
|
|
528 |
|
|
529 |
ptr += Align4( entry->GetSize() );
|
|
530 |
}
|
|
531 |
}
|
|
532 |
|
|
533 |
|
|
534 |
void CServerCrashDataSource::DoGetListL(const TListId aListId,
|
|
535 |
const TThreadId aThreadId,
|
|
536 |
const TProcessId aProcessId,
|
|
537 |
RBuf8 & aBuffer,
|
|
538 |
TUint32 & aSize )
|
|
539 |
{
|
|
540 |
|
|
541 |
LOG_MSG5( "->CServerCrashDataSource::DoGetList(aListId=%d, aThredId=%Lu, aProcessId=%Lu, aSize=%d\n", aListId, aThreadId.Id(), aProcessId.Id(), aSize );
|
|
542 |
|
|
543 |
TInt ret;
|
|
544 |
TListLevel listLevel;
|
|
545 |
|
|
546 |
if( ((TUint)-1 == (TUint)aThreadId) && ((TUint)-1 == (TUint)aProcessId) )
|
|
547 |
{
|
|
548 |
listLevel = EListGlobal;
|
|
549 |
ret = iSecSess.GetList( aListId, aBuffer, aSize );
|
|
550 |
}
|
|
551 |
else if( ((TUint)-1 != (TUint)aThreadId) && ((TUint)-1 == (TUint)aProcessId) )
|
|
552 |
{
|
|
553 |
listLevel = EListThread;
|
|
554 |
LOG_MSG("CServerCrashDataSource::DoGetList - EListThread");
|
|
555 |
ret = iSecSess.GetList( aThreadId, aListId, aBuffer, aSize );
|
|
556 |
}
|
|
557 |
else
|
|
558 |
{
|
|
559 |
listLevel = EListProcess;
|
|
560 |
LOG_MSG("CServerCrashDataSource::DoGetList - EListProcess");
|
|
561 |
ret = iSecSess.GetList( aProcessId, aListId, aBuffer, aSize );
|
|
562 |
}
|
|
563 |
|
|
564 |
while( KErrTooBig == ret )
|
|
565 |
{
|
|
566 |
LOG_MSG2( "CServerCrashDataSource::DoGetListL - list too big, new size=%d\n", aSize );
|
|
567 |
|
|
568 |
// Too big, and aSize should have been modified to the required new size
|
|
569 |
// Since the list could have increased in size between calls, give it an
|
|
570 |
// extra margin.
|
|
571 |
aSize += 256;
|
|
572 |
|
|
573 |
aBuffer.ReAllocL( aSize );
|
|
574 |
|
|
575 |
if( EListGlobal == listLevel )
|
|
576 |
{
|
|
577 |
ret = iSecSess.GetList( aListId, aBuffer, aSize );
|
|
578 |
}
|
|
579 |
else if( EListThread == listLevel )
|
|
580 |
{
|
|
581 |
ret = iSecSess.GetList( aThreadId, aListId, aBuffer, aSize );
|
|
582 |
}
|
|
583 |
else
|
|
584 |
{
|
|
585 |
ret = iSecSess.GetList( aProcessId, aListId, aBuffer, aSize );
|
|
586 |
}
|
|
587 |
|
|
588 |
}
|
|
589 |
User::LeaveIfError(ret);
|
|
590 |
}
|
|
591 |
|
|
592 |
/** Obtain the thread list. If aProcessId is negative, we obtain the entire system
|
|
593 |
thread list. If aProcessId is positive we get the thread list for that process */
|
|
594 |
void CServerCrashDataSource::GetThreadListL( const TUint64 aProcessId,
|
|
595 |
RThreadPointerList & aThreadList,
|
|
596 |
TUint & aTotalThreadListDescSize )
|
|
597 |
{
|
|
598 |
LOG_MSG2( "->CServerCrashDataSource::GetThreadListL(aProcessId=%Lu)\n", aProcessId);
|
|
599 |
|
|
600 |
// Delete any objects in the array, since we will replace them.
|
|
601 |
aThreadList.ResetAndDestroy();
|
|
602 |
|
|
603 |
aTotalThreadListDescSize = 0;
|
|
604 |
|
|
605 |
if( iThreadListBuffer.Size() != iLastThreadListSize )
|
|
606 |
{
|
|
607 |
LOG_MSG2("CServerCrashDataSource::GetThreadListL -> iThreadListBuffer.ReAlloc(%d)\n", iLastThreadListSize );
|
|
608 |
iThreadListBuffer.ReAllocL( iLastThreadListSize );
|
|
609 |
}
|
|
610 |
|
|
611 |
LOG_MSG( "CServerCrashDataSource::GetThreadListL -> DoGetListL()\n" );
|
|
612 |
DoGetListL( EThreads, (TUint)-1, aProcessId, iThreadListBuffer, iLastThreadListSize );
|
|
613 |
|
|
614 |
iLastThreadListSize = iThreadListBuffer.Size();
|
|
615 |
|
|
616 |
|
|
617 |
CThreadInfo * threadInfoPtr;
|
|
618 |
RThread thread;
|
|
619 |
TThreadStackInfo stackInfo;
|
|
620 |
TThreadListEntry * entry;
|
|
621 |
TUint usrStackSize;
|
|
622 |
TLinAddr usrStackAddr;
|
|
623 |
TLinAddr svcStackPtr;
|
|
624 |
TLinAddr svcStackBase;
|
|
625 |
TUint svcStackSize;
|
|
626 |
|
|
627 |
TUint priority;
|
|
628 |
|
|
629 |
TUint8* ptr = (TUint8*)( iThreadListBuffer.Ptr() );
|
|
630 |
const TUint8* ptrEnd = ptr + iLastThreadListSize;
|
|
631 |
//LOG_MSG3( " Data start,end=(0x%x, 0x%x)\n", ptr, ptrEnd );
|
|
632 |
|
|
633 |
while( ptr < ptrEnd )
|
|
634 |
{
|
|
635 |
|
|
636 |
entry = (TThreadListEntry*)ptr;
|
|
637 |
|
|
638 |
if( !entry )
|
|
639 |
{
|
|
640 |
LOG_MSG( " ERROR !* : TThreadListEntry is NULL\n" );
|
|
641 |
User::Leave(KErrBadHandle);
|
|
642 |
}
|
|
643 |
|
|
644 |
if( entry->iNameLength == 0 )
|
|
645 |
{
|
|
646 |
LOG_MSG4( " Skipping Thread 0x%X%X : entry->iNameLength=%d",
|
|
647 |
I64HIGH(entry->iThreadId), I64LOW(entry->iThreadId), entry->iNameLength );
|
|
648 |
ptr += Align4( entry->GetSize() );
|
|
649 |
continue;
|
|
650 |
}
|
|
651 |
|
|
652 |
//LOG_MSG3( " entry &=0x%X, size=%d\n", &(entry->iThreadId), entry->GetSize() );
|
|
653 |
//LOG_MSG3( " entry->iThreadId= 0x%X%X\n", I64HIGH(entry->iThreadId), I64LOW(entry->iThreadId) );
|
|
654 |
//LOG_MSG3( " found tid=%d, pid=%d\n", I64LOW(entry->iThreadId), I64LOW(entry->iProcessId) );
|
|
655 |
|
|
656 |
if( entry->iSupervisorStackPtrValid )
|
|
657 |
{
|
|
658 |
svcStackPtr = entry->iSupervisorStackPtr;
|
|
659 |
}
|
|
660 |
else
|
|
661 |
{
|
|
662 |
svcStackPtr = 0;
|
|
663 |
}
|
|
664 |
|
|
665 |
if( entry->iSupervisorStackBaseValid )
|
|
666 |
{
|
|
667 |
svcStackBase = entry->iSupervisorStackBase;
|
|
668 |
}
|
|
669 |
else
|
|
670 |
{
|
|
671 |
svcStackBase = 0;
|
|
672 |
}
|
|
673 |
|
|
674 |
if( entry->iSupervisorStackSizeValid )
|
|
675 |
{
|
|
676 |
svcStackSize = entry->iSupervisorStackSize;
|
|
677 |
}
|
|
678 |
else
|
|
679 |
{
|
|
680 |
svcStackSize = 0;
|
|
681 |
}
|
|
682 |
|
|
683 |
|
|
684 |
|
|
685 |
if( KErrNone == thread.Open( entry->iThreadId ) )
|
|
686 |
{
|
|
687 |
priority = (TUint)(thread.Priority());
|
|
688 |
|
|
689 |
if( KErrNone == thread.StackInfo( stackInfo ) )
|
|
690 |
{
|
|
691 |
usrStackAddr = stackInfo.iLimit;
|
|
692 |
usrStackSize = stackInfo.iBase - stackInfo.iLimit;
|
|
693 |
}
|
|
694 |
else
|
|
695 |
{
|
|
696 |
usrStackSize = 0;
|
|
697 |
usrStackAddr = 0;
|
|
698 |
}
|
|
699 |
|
|
700 |
thread.Close();
|
|
701 |
}
|
|
702 |
else
|
|
703 |
{
|
|
704 |
usrStackSize = 0;
|
|
705 |
usrStackAddr = 0;
|
|
706 |
priority = 0;
|
|
707 |
}
|
|
708 |
|
|
709 |
/*
|
|
710 |
LOG_MSG3( " entry->iNameLength=%d, &(entry->iName[0])=0x%X\n",
|
|
711 |
entry->iNameLength, &(entry->iName[0]) );
|
|
712 |
*/
|
|
713 |
|
|
714 |
TPtrC entryName( &(entry->iName[0]), entry->iNameLength );
|
|
715 |
//LOG_MSG2( " -> threadInfoPtr = CThreadInfo::NewL( name.Size()=%d)\n", entryName.Size() );
|
|
716 |
|
|
717 |
threadInfoPtr = CThreadInfo::NewL(
|
|
718 |
entry->iThreadId,
|
|
719 |
entryName,
|
|
720 |
entry->iProcessId,
|
|
721 |
(TUint)priority,
|
|
722 |
svcStackPtr,
|
|
723 |
svcStackBase,
|
|
724 |
svcStackSize,
|
|
725 |
usrStackAddr,
|
|
726 |
usrStackSize );
|
|
727 |
|
|
728 |
/*
|
|
729 |
LOG_MSG3( " threadInfoPtr->iSvcStackAddr=0x%X, threadInfoPtr->iSvcStackSize=0x%X\n",
|
|
730 |
threadInfoPtr->SvcStackAddr(), threadInfoPtr->SvcStackSize() );
|
|
731 |
*/
|
|
732 |
|
|
733 |
TInt err = aThreadList.Append( threadInfoPtr );
|
|
734 |
if( err != KErrNone )
|
|
735 |
{
|
|
736 |
// We use this id so as not to use Push(), AppendL(), Pop()
|
|
737 |
delete threadInfoPtr;
|
|
738 |
User::Leave( err );
|
|
739 |
}
|
|
740 |
|
|
741 |
aTotalThreadListDescSize += threadInfoPtr->Size();
|
|
742 |
|
|
743 |
/*
|
|
744 |
LOG_MSG3( " aTotalThreadListDescSize = %d after adding %d\n",
|
|
745 |
aTotalThreadListDescSize, threadInfoPtr->Size() );
|
|
746 |
|
|
747 |
RBuf rPrintBuf;
|
|
748 |
rPrintBuf.Create( threadInfoPtr->Name());
|
|
749 |
RDebug::Printf( " <- rPrintBuf.Create(), rPrintBuf.Length()=%d\n", rPrintBuf.Length() );
|
|
750 |
char* cl = (char*) rPrintBuf.Collapse().PtrZ();
|
|
751 |
RDebug::Printf(" name=%s\n", cl );
|
|
752 |
rPrintBuf.Close();
|
|
753 |
*/
|
|
754 |
|
|
755 |
ptr += Align4( entry->GetSize() );
|
|
756 |
//LOG_MSG2( " ptr += Align4(entry->GetSize()) = 0x%X\n", ptr );
|
|
757 |
|
|
758 |
} // while
|
|
759 |
|
|
760 |
}
|
|
761 |
|
|
762 |
void CServerCrashDataSource::GetCodeSegmentsL( const TUint64 aTid, RCodeSegPointerList &aCodeSegList, TUint & aTotalCodeSegListDescSize )
|
|
763 |
{
|
|
764 |
LOG_MSG2("->CServerCrashDataSource::GetCodeSegmentsL(aTid=%Lu)\n", aTid );
|
|
765 |
|
|
766 |
aCodeSegList.ResetAndDestroy();
|
|
767 |
aTotalCodeSegListDescSize = 0;
|
|
768 |
|
|
769 |
TUint32 size = KMaxFileName;
|
|
770 |
RBuf8 buffer;
|
|
771 |
buffer.CreateL(KMaxFileName);
|
|
772 |
CleanupClosePushL(buffer);
|
|
773 |
|
|
774 |
DoGetListL( ECodeSegs, aTid, (TUint)-1, buffer, size );
|
|
775 |
LOG_MSG2( " DoGetListL( ECodeSegs ) returned buffer.Size()=0x%X\n", buffer.Size() );
|
|
776 |
|
|
777 |
TUint8* ptr = (TUint8*)buffer.Ptr();
|
|
778 |
const TUint8* ptrEnd = ptr + size;
|
|
779 |
|
|
780 |
while(ptr < ptrEnd)
|
|
781 |
{
|
|
782 |
TCodeSegListEntry* entry = (TCodeSegListEntry*)ptr;
|
|
783 |
|
|
784 |
LOG_MSG4( " entry->CodeBase=0x%X, CodeSize=0x%X, ConstDataSize=0x%X\n",
|
|
785 |
entry->iCodeBase, entry->iCodeSize, entry->iConstDataSize );
|
|
786 |
LOG_MSG4( " InitDataBase=0x%X, InitDataSize=0x%X, UnintDataSize=0x%X\n",
|
|
787 |
entry->iInitialisedDataBase, entry->iInitialisedDataSize, entry->iUninitialisedDataSize );
|
|
788 |
LOG_MSG3( " IsXip=0x%X, CodeSegType=0x%X\n", entry->iIsXip, entry->iCodeSegType );
|
|
789 |
|
|
790 |
TCodeSegInfo *codeSeg = new(ELeave) TCodeSegInfo;
|
|
791 |
|
|
792 |
TPtr name(&(entry->iName[0]), entry->iNameLength, entry->iNameLength);
|
|
793 |
codeSeg->iName = name;
|
|
794 |
|
|
795 |
codeSeg->iType = entry->iCodeSegType;
|
|
796 |
codeSeg->iXIP = entry->iIsXip;
|
|
797 |
|
|
798 |
codeSeg->iCodeSize = entry->iCodeSize;
|
|
799 |
codeSeg->iCodeRunAddr = entry->iCodeBase;
|
|
800 |
if( codeSeg->iXIP )
|
|
801 |
{
|
|
802 |
codeSeg->iCodeLoadAddr = codeSeg->iCodeRunAddr;
|
|
803 |
}
|
|
804 |
else
|
|
805 |
{
|
|
806 |
codeSeg->iCodeLoadAddr = 0; //TODO
|
|
807 |
}
|
|
808 |
|
|
809 |
codeSeg->iRoDataSize = entry->iConstDataSize;
|
|
810 |
codeSeg->iRoDataRunAddr = entry->iCodeBase + entry->iCodeSize;
|
|
811 |
if( codeSeg->iXIP )
|
|
812 |
{
|
|
813 |
codeSeg->iRoDataLoadAddr = codeSeg->iRoDataRunAddr;
|
|
814 |
}
|
|
815 |
else
|
|
816 |
{
|
|
817 |
codeSeg->iRoDataLoadAddr = 0; //TODO
|
|
818 |
}
|
|
819 |
|
|
820 |
codeSeg->iDataSize = entry->iInitialisedDataSize + entry->iUninitialisedDataSize;
|
|
821 |
codeSeg->iDataRunAddr = entry->iInitialisedDataBase;
|
|
822 |
if( codeSeg->iXIP )
|
|
823 |
{
|
|
824 |
codeSeg->iDataLoadAddr = codeSeg->iDataRunAddr;
|
|
825 |
}
|
|
826 |
else
|
|
827 |
{
|
|
828 |
codeSeg->iDataLoadAddr = 0; //TODO
|
|
829 |
}
|
|
830 |
|
|
831 |
TInt err = aCodeSegList.Append(codeSeg);
|
|
832 |
if(err != KErrNone)
|
|
833 |
{
|
|
834 |
delete codeSeg;
|
|
835 |
User::Leave(err);
|
|
836 |
}
|
|
837 |
|
|
838 |
aTotalCodeSegListDescSize += sizeof(TCodeSegInfo);
|
|
839 |
ptr += Align4(entry->GetSize());
|
|
840 |
}
|
|
841 |
|
|
842 |
CleanupStack::PopAndDestroy(&buffer);
|
|
843 |
}
|
|
844 |
|
|
845 |
/**
|
|
846 |
* Returns the size of the trace data available
|
|
847 |
* @return Trace Size
|
|
848 |
* @leave One of the system wide codes
|
|
849 |
*/
|
|
850 |
TUint CServerCrashDataSource::GetAvailableTraceSizeL()
|
|
851 |
{
|
|
852 |
LOG_MSG("->CServerCrashDataSource::GetAvailableTraceSizeL()");
|
|
853 |
|
|
854 |
RBTrace trace;
|
|
855 |
User::LeaveIfError(trace.Open());
|
|
856 |
|
|
857 |
TUint8 *data = NULL;
|
|
858 |
TInt size = trace.GetData(data);
|
|
859 |
|
|
860 |
trace.Close();
|
|
861 |
|
|
862 |
return size;
|
|
863 |
}
|
|
864 |
|
|
865 |
/**
|
|
866 |
Reads data from the trace buffer into the supplied descriptor. Not supported. Recommended
|
|
867 |
approach is to use the live trace framework.
|
|
868 |
@param aTraceData The buffer to be read into
|
|
869 |
@param aPos Ignored
|
|
870 |
*/
|
|
871 |
void CServerCrashDataSource::ReadTraceBufferL(TDes8 &aTraceData, TUint aPos)
|
|
872 |
{
|
|
873 |
LOG_MSG("->CServerCrashDataSource::ReadTraceBuffer() -- Not supported: Please use the live trace system");
|
|
874 |
|
|
875 |
User::Leave(KErrNotSupported);
|
|
876 |
}
|
|
877 |
|
|
878 |
/**
|
|
879 |
* Gets locks data
|
|
880 |
* @param aLockData stores lock data
|
|
881 |
* @leave one of the OS wide codes
|
|
882 |
*/
|
|
883 |
void CServerCrashDataSource::GetLocksL(TSCMLockData& aLockData)
|
|
884 |
{
|
|
885 |
User::Leave(KErrNotSupported);
|
|
886 |
}
|
|
887 |
|
|
888 |
/**
|
|
889 |
* Gets the ROM build info if available
|
|
890 |
* @param aRomHeader
|
|
891 |
* @leave one of the OS wide codes
|
|
892 |
*/
|
|
893 |
void CServerCrashDataSource::GetROMBuildInfoL(TRomHeaderData& aRomHeader)
|
|
894 |
{
|
|
895 |
User::Leave(KErrNotSupported);
|
|
896 |
}
|
|
897 |
|
|
898 |
/**
|
|
899 |
* @see CCrashDataSource::GetExceptionStackSizeL
|
|
900 |
*/
|
|
901 |
TUint CServerCrashDataSource::GetExceptionStackSizeL(const Debug::TArmProcessorModes aMode)
|
|
902 |
{
|
|
903 |
User::Leave(KErrNotSupported);
|
|
904 |
return 0; //comp warnings
|
|
905 |
}
|
|
906 |
|
|
907 |
/**
|
|
908 |
* @see CCrashDataSource::GetExceptionStackL
|
|
909 |
*/
|
|
910 |
void CServerCrashDataSource::GetExceptionStackL(const Debug::TArmProcessorModes aMode, TDes8& aStack, TUint aStartReadPoint)
|
|
911 |
{
|
|
912 |
User::Leave(KErrNotSupported);
|
|
913 |
}
|
|
914 |
|
|
915 |
/**
|
|
916 |
* @see CCrashDataSource::GetVersion
|
|
917 |
*/
|
|
918 |
TVersion CServerCrashDataSource::GetVersion() const
|
|
919 |
{
|
|
920 |
return KServerCrashDataSourceVersion;
|
|
921 |
}
|
|
922 |
|
|
923 |
/**
|
|
924 |
* @see CCrashDataSource::GetDataSourceFunctionalityBufSize
|
|
925 |
*/
|
|
926 |
TInt CServerCrashDataSource::GetDataSourceFunctionalityBufSize(TUint& aBufSize)
|
|
927 |
{
|
|
928 |
return KErrNotSupported;
|
|
929 |
}
|
|
930 |
|
|
931 |
/**
|
|
932 |
* @see CCrashDataSource::GetDataSourceFunctionality
|
|
933 |
*/
|
|
934 |
TInt CServerCrashDataSource::GetDataSourceFunctionality(TDes8& aFuncBuffer)
|
|
935 |
{
|
|
936 |
return KErrNotSupported;
|
|
937 |
}
|
|
938 |
|
|
939 |
TInt CServerCrashDataSource::GetVariantSpecificDataSize(TUint& aDataSize)
|
|
940 |
{
|
|
941 |
(void)aDataSize;
|
|
942 |
return KErrNotSupported;
|
|
943 |
}
|
|
944 |
|
|
945 |
TInt CServerCrashDataSource::GetVariantSpecificData(TDes8 &aVarSpecData)
|
|
946 |
{
|
|
947 |
(void)aVarSpecData;
|
|
948 |
return KErrNotSupported;
|
|
949 |
}
|
|
950 |
|
|
951 |
//eof
|