1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/debug/d_eventtracker.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,916 @@
1.4 +// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32test\debug\d_eventtracker.cpp
1.18 +// LDD-based debug agent used to track kernel events. See
1.19 +// t_eventtracker.cpp
1.20 +//
1.21 +//
1.22 +
1.23 +#include <kernel/kern_priv.h>
1.24 +#include "reventtracker.h"
1.25 +#include "d_eventtracker.h"
1.26 +#include "nk_trace.h"
1.27 +
1.28 +#ifdef __MARM__
1.29 +#include <kernel/kdebug.h>
1.30 +#endif //__MARM__
1.31 +
1.32 +#ifdef _DEBUG
1.33 +static const char KPanicCat[] = "D_EVENTTRACKER";
1.34 +#endif // _DEBUG
1.35 +_LIT(KClientPanicCat, "D_EVENTTRACKER");
1.36 +
1.37 +DEventTracker* TheEventTracker;
1.38 +
1.39 +//////////////////////////////////////////////////////////////////////////////
1.40 +
1.41 +/** Data about objects being tracked.
1.42 + All tracked objects are kept in a tracking list. The object address
1.43 + is a key and so must be unique.
1.44 + */
1.45 +
1.46 +TTrackedItem::TTrackedItem(const DBase* aObject)
1.47 + : iObject(aObject), iAccountedFor(EFalse)
1.48 + {
1.49 + }
1.50 +
1.51 +
1.52 +/** Subclass for DObjects being tracked */
1.53 +
1.54 +TTrackedObject::TTrackedObject(DObject* aObject, TObjectType aType)
1.55 + : TTrackedItem(aObject),
1.56 + iType(aType)
1.57 + {
1.58 + aObject->FullName(iFullName);
1.59 + }
1.60 +
1.61 +TBool TTrackedObject::CheckIntegrity(const TDesC& aName, TObjectType aType) const
1.62 + {
1.63 + TBool ok = EFalse;
1.64 +
1.65 + if (aType == iType)
1.66 + {
1.67 + if (aType == EThread || aType == EProcess)
1.68 + {
1.69 + ok = (iFullName == aName);
1.70 + }
1.71 + else
1.72 + {
1.73 + ok = ETrue;
1.74 + }
1.75 + }
1.76 +
1.77 + if (!ok)
1.78 + {
1.79 + Kern::Printf("EVENTTRACKER: container / tracking list mismatch (0x%08x)", iObject);
1.80 + Kern::Printf("EVENTTRACKER: \tcontainer: %S (type %d)", &aName, aType);
1.81 + Kern::Printf("EVENTTRACKER: \ttracking list: %S (type %d)", &iFullName, iType);
1.82 + }
1.83 +
1.84 + return ok;
1.85 + }
1.86 +
1.87 +/** Subclass for DCodeSegs being tracked */
1.88 +
1.89 +TTrackedCodeSeg::TTrackedCodeSeg(const DCodeSeg* aCodeSeg)
1.90 + : TTrackedItem(aCodeSeg),
1.91 + iAccessCount(aCodeSeg ? aCodeSeg->iAccessCount : 0)
1.92 + {
1.93 + }
1.94 +
1.95 +TBool TTrackedCodeSeg::CheckIntegrity(TInt aAccessCount) const
1.96 + {
1.97 + const TBool ok = (aAccessCount == iAccessCount);
1.98 +
1.99 + if (!ok)
1.100 + {
1.101 + Kern::Printf("EVENTTRACKER: code seg list / tracking list mismatch (0x%08x)", iObject);
1.102 + Kern::Printf("EVENTTRACKER: \tcode seg list: %d", aAccessCount);
1.103 + Kern::Printf("EVENTTRACKER: \ttracking list: %d", iAccessCount);
1.104 + }
1.105 +
1.106 + return ok;
1.107 + }
1.108 +
1.109 +
1.110 +/** Event handler and container for all objects being tracked. */
1.111 +
1.112 +DEventTracker::DEventTracker()
1.113 + : DKernelEventHandler(EventHandler, this)
1.114 + {
1.115 + __ASSERT_DEBUG(!TheEventTracker, Kern::Fault(KPanicCat, __LINE__));
1.116 +
1.117 + TheEventTracker = this;
1.118 + }
1.119 +
1.120 +
1.121 +//
1.122 +// If aUseHook is true, the event tracker hooks the stop-mode debugger
1.123 +// breakpoint in preference to adding itself to the kernel event handler
1.124 +// queue. In order to clean up on its destruction, it has to
1.125 +// reset the breakpoint by installing a dummy nop breakpoint
1.126 +// handler, which is cut-and-pasted from kdebug.dll in order to
1.127 +// avoid a dependency on kdebug.dll. In order to use the event
1.128 +// tracker using the stop-mode debugger breakpoint rather than
1.129 +// the kernel event handler queue, kdebug.dll must be present in
1.130 +// the ROM
1.131 +//
1.132 +TInt DEventTracker::Create(DLogicalDevice* aDevice, TBool aUseHook)
1.133 + {
1.134 + TInt err = aDevice->Open();
1.135 +
1.136 + if (err)
1.137 + {
1.138 + return err;
1.139 + }
1.140 +
1.141 + iDevice = aDevice;
1.142 +
1.143 + err = Kern::MutexCreate(iLock, _L("EventHandlerLock"), KMutexOrdNone);
1.144 +
1.145 + if (!err)
1.146 + {
1.147 + if (aUseHook)
1.148 + {
1.149 + // Find debugger info, if any
1.150 + DDebuggerInfo* const debugInfo = Kern::SuperPage().iDebuggerInfo;
1.151 +
1.152 + // Test stop-mode breakpoint if available
1.153 + if (debugInfo)
1.154 + {
1.155 +#ifdef __MARM__
1.156 + // Receive all events
1.157 + for (TInt i = 0; i < ((EEventLimit + 31) >> 5); ++i)
1.158 + {
1.159 + debugInfo->iEventMask[i] = 0xffffffffu;
1.160 + }
1.161 +
1.162 + __KTRACE_OPT(KDEBUGGER, Kern::Printf("EVENTTRACKER: Copying breakpoint (0x%x) into handler (0x%x), size %d", &BranchToEventHandler, debugInfo->iEventHandlerBreakpoint, BreakPointSize()));
1.163 +
1.164 + // Set up breakpoint to call handler
1.165 + memcpy((TAny*)debugInfo->iEventHandlerBreakpoint, (TAny*) &BranchToEventHandler, BreakPointSize());
1.166 +#else // !__MARM__
1.167 + err = KErrNotFound;
1.168 +#endif // __MARM__
1.169 + }
1.170 + else
1.171 + {
1.172 + err = KErrNotFound;
1.173 + }
1.174 + }
1.175 + else
1.176 + {
1.177 + err = Add();
1.178 + }
1.179 + }
1.180 +
1.181 + return err;
1.182 + }
1.183 +
1.184 +
1.185 +DEventTracker::~DEventTracker()
1.186 + {
1.187 +#ifdef __MARM__
1.188 + // Remove breakpoint, if any
1.189 + DDebuggerInfo* const debugInfo = Kern::SuperPage().iDebuggerInfo;
1.190 + if (debugInfo)
1.191 + {
1.192 + CopyDummyHandler(debugInfo->iEventHandlerBreakpoint);
1.193 + }
1.194 +#endif //__MARM__
1.195 +
1.196 + // clean-up tracking list
1.197 + SDblQueLink* link = iItems.GetFirst();
1.198 + while (link)
1.199 + {
1.200 + delete _LOFF(link, TTrackedItem, iLink);
1.201 + link = iItems.GetFirst();
1.202 + }
1.203 +
1.204 + if (iLock)
1.205 + {
1.206 + iLock->Close(NULL);
1.207 + }
1.208 +
1.209 + if (iDevice)
1.210 + {
1.211 + iDevice->Close(NULL);
1.212 + }
1.213 +
1.214 + TheEventTracker = NULL;
1.215 + }
1.216 +
1.217 +
1.218 +TInt DEventTracker::Start()
1.219 + {
1.220 + TInt err = AddExistingObjects();
1.221 +
1.222 + if (!err)
1.223 + {
1.224 + iTracking = ETrue;
1.225 + }
1.226 +
1.227 + return err;
1.228 + }
1.229 +
1.230 +
1.231 +TInt DEventTracker::Stop()
1.232 + {
1.233 + NKern::ThreadEnterCS();
1.234 + Kern::MutexWait(*iLock);
1.235 +
1.236 + iTracking = EFalse;
1.237 +
1.238 + Kern::MutexSignal(*iLock);
1.239 + NKern::ThreadLeaveCS();
1.240 +
1.241 + DumpCounters();
1.242 +
1.243 + return CheckIntegrity();
1.244 + }
1.245 +
1.246 +
1.247 +TUint DEventTracker::EventHandler(TKernelEvent aType, TAny* a1, TAny* a2, TAny* aThis)
1.248 + {
1.249 + return ((DEventTracker*)aThis)->HandleEvent(aType, a1, a2);
1.250 + }
1.251 +
1.252 +
1.253 +TUint DEventTracker::HandleEvent(TKernelEvent aType, TAny* a1, TAny* a2)
1.254 + {
1.255 + __KTRACE_OPT(KDEBUGGER, Kern::Printf("EVENTTRACKER: Handling event type 0x%x", aType));
1.256 +
1.257 + Kern::MutexWait(*iLock);
1.258 +
1.259 + if (iTracking)
1.260 + {
1.261 + ++iCounters[aType];
1.262 +
1.263 + switch (aType)
1.264 + {
1.265 + case EEventAddProcess:
1.266 + AddObject(EProcess, (DObject*)a1);
1.267 + break;
1.268 + case EEventUpdateProcess:
1.269 + // could be renaming or chunk addition/deletion
1.270 + UpdateObject(EProcess, (DObject*)a1, EFalse);
1.271 + break;
1.272 + case EEventRemoveProcess:
1.273 + RemoveObject(EProcess, (DObject*)a1);
1.274 + break;
1.275 + case EEventAddThread:
1.276 + AddObject(EThread, (DObject*)a1);
1.277 + break;
1.278 + case EEventUpdateThread:
1.279 + UpdateObject(EThread, (DObject*)a1, ETrue);
1.280 + break;
1.281 + case EEventRemoveThread:
1.282 + RemoveObject(EThread, (DObject*)a1);
1.283 + break;
1.284 + case EEventAddLibrary:
1.285 + {
1.286 + DLibrary* pL = (DLibrary*)a1;
1.287 + if (pL->iMapCount == 1)
1.288 + AddObject(ELibrary, pL);
1.289 + }
1.290 + break;
1.291 + case EEventRemoveLibrary:
1.292 + {
1.293 + DLibrary* pL = (DLibrary*)a1;
1.294 + if (pL->iMapCount == 0)
1.295 + RemoveObject(ELibrary, pL);
1.296 + }
1.297 + break;
1.298 + case EEventNewChunk:
1.299 + AddObject(EChunk, (DObject*)a1);
1.300 + break;
1.301 + case EEventDeleteChunk:
1.302 + RemoveObject(EChunk, (DObject*)a1);
1.303 + break;
1.304 + case EEventAddCodeSeg:
1.305 + {
1.306 + AddCodeSeg((DCodeSeg*)a1, (DProcess*)a2);
1.307 + }
1.308 + break;
1.309 + case EEventRemoveCodeSeg:
1.310 + {
1.311 + RemoveCodeSeg((DCodeSeg*)a1, (DProcess*)a2);
1.312 + }
1.313 + break;
1.314 + case EEventLoadedProcess:
1.315 + {
1.316 + __KTRACE_OPT(KDEBUGGER, Kern::Printf("EVENTTRACKER: Process %O loaded", a1));
1.317 + ProcessLoaded((DProcess*)a1);
1.318 + }
1.319 + break;
1.320 + case EEventUnloadingProcess:
1.321 + __KTRACE_OPT(KDEBUGGER, Kern::Printf("EVENTTRACKER: Process %O unloaded", a1));
1.322 + break;
1.323 + default:
1.324 + // no-op
1.325 + __KTRACE_OPT(KDEBUGGER, Kern::Printf("EVENTTRACKER: Handling default case"));
1.326 + break;
1.327 + }
1.328 + }
1.329 +
1.330 + Kern::MutexSignal(*iLock);
1.331 +
1.332 + // Allow other handlers to see this event
1.333 + return DKernelEventHandler::ERunNext;
1.334 + }
1.335 +
1.336 +
1.337 +void DEventTracker::AddObject(TObjectType aType, DObject* aObject)
1.338 + {
1.339 + TTrackedObject* trackedObject = (TTrackedObject*)LookupItem(aObject);
1.340 +
1.341 + if (trackedObject)
1.342 + {
1.343 + Kern::Printf("EVENTTRACKER: Found orphaned object %O in tracking list while adding new object", aObject);
1.344 + ++iErrorCount;
1.345 + return;
1.346 + }
1.347 +
1.348 + NKern::ThreadEnterCS();
1.349 + trackedObject = new TTrackedObject(aObject, aType);
1.350 + NKern::ThreadLeaveCS();
1.351 +
1.352 + if (trackedObject)
1.353 + {
1.354 + __KTRACE_OPT(KDEBUGGER, Kern::Printf("EVENTTRACKER: Adding %O (type %d) to tracking list", aObject, aType));
1.355 + __KTRACE_OPT(KDEBUGGER, Kern::Printf("EVENTTRACKER: DBase ptr == 0x%x", trackedObject->iObject));
1.356 + iItems.Add(&trackedObject->iLink);
1.357 + }
1.358 + else
1.359 + {
1.360 + iOOM = ETrue;
1.361 + ++iErrorCount;
1.362 + }
1.363 + }
1.364 +
1.365 +
1.366 +void DEventTracker::RemoveObject(TObjectType aType, DObject* aObject)
1.367 + {
1.368 + TTrackedObject* const trackedObject = (TTrackedObject*)LookupItem(aObject);
1.369 +
1.370 + if (trackedObject)
1.371 + {
1.372 + TFullName name;
1.373 + aObject->FullName(name);
1.374 + if (!trackedObject->CheckIntegrity(name, aType))
1.375 + {
1.376 + ++iErrorCount;
1.377 + }
1.378 + __KTRACE_OPT(KDEBUGGER, Kern::Printf("EVENTTRACKER: Removing %S (type %d) from tracking list", &name, aType));
1.379 + trackedObject->iLink.Deque();
1.380 +
1.381 + NKern::ThreadEnterCS();
1.382 + delete trackedObject;
1.383 + NKern::ThreadLeaveCS();
1.384 + }
1.385 + else
1.386 + {
1.387 + Kern::Printf("EVENTTRACKER: %O (type %d) removed but not in tracking list", aObject, aType);
1.388 + ++iErrorCount;
1.389 + }
1.390 + }
1.391 +
1.392 +
1.393 +void DEventTracker::UpdateObject(TObjectType aType, DObject* aObject, TBool aMustBeRenamed)
1.394 + {
1.395 + TTrackedObject* const trackedObject = (TTrackedObject*)LookupItem(aObject);
1.396 +
1.397 + if (trackedObject)
1.398 + {
1.399 + TFullName newName;
1.400 + aObject->FullName(newName);
1.401 + if (newName != trackedObject->iFullName)
1.402 + {
1.403 + __KTRACE_OPT(KDEBUGGER, Kern::Printf("EVENTTRACKER: Renaming %S --> %S (type %d)",
1.404 + &trackedObject->iFullName, &newName));
1.405 + trackedObject->iFullName = newName;
1.406 + }
1.407 + else if (aMustBeRenamed)
1.408 + {
1.409 + Kern::Printf("EVENTTRACKER: %O (type %d) renamed with same name", aObject, aType);
1.410 + ++iErrorCount;
1.411 + }
1.412 + }
1.413 + else
1.414 + {
1.415 + Kern::Printf("EVENTTRACKER: %O (type %d) updated but not in tracking list", aObject, aType);
1.416 + Kern::Printf("EVENTTRACKER: DBase ptr == 0x%x", (DBase*)aObject);
1.417 + ++iErrorCount;
1.418 + }
1.419 + }
1.420 +
1.421 +void DEventTracker::AddCodeSeg(DCodeSeg* aCodeSeg, DProcess* aProcess)
1.422 + {
1.423 + TTrackedCodeSeg* trackedCodeSeg = (TTrackedCodeSeg*)LookupItem(aCodeSeg);
1.424 +
1.425 + if (trackedCodeSeg)
1.426 + {
1.427 + if (aProcess && (aProcess->iTempCodeSeg == aCodeSeg))
1.428 + {
1.429 + // This is the exe code seg for a loading process
1.430 + // and hence the access count is currently
1.431 + // incremented by one
1.432 + ++trackedCodeSeg->iAccessCount;
1.433 + }
1.434 +
1.435 + if (trackedCodeSeg->iAccessCount != aCodeSeg->iAccessCount)
1.436 + {
1.437 + Kern::Printf(
1.438 + "EVENTTRACKER: Access count for %C (%d) does not match the tracking list (%d)",
1.439 + aCodeSeg,
1.440 + aCodeSeg->iAccessCount,
1.441 + trackedCodeSeg->iAccessCount
1.442 + );
1.443 + ++iErrorCount;
1.444 + return;
1.445 + }
1.446 + }
1.447 +
1.448 + if (!trackedCodeSeg)
1.449 + {
1.450 + NKern::ThreadEnterCS();
1.451 + trackedCodeSeg = new TTrackedCodeSeg(aCodeSeg);
1.452 + NKern::ThreadLeaveCS();
1.453 +
1.454 + if (trackedCodeSeg)
1.455 + {
1.456 + __KTRACE_OPT(KDEBUGGER, Kern::Printf("EVENTTRACKER: Adding %C to tracking list", aCodeSeg));
1.457 + iItems.Add(&trackedCodeSeg->iLink);
1.458 + }
1.459 + }
1.460 + else // trackedCodeSeg
1.461 + {
1.462 + if (aProcess)
1.463 + {
1.464 + __KTRACE_OPT(KDEBUGGER, Kern::Printf("EVENTTRACKER: Updating access count for %C (%d), attaching to process %O", aCodeSeg, aCodeSeg->iAccessCount, aProcess));
1.465 + }
1.466 + else // !aProcess
1.467 + {
1.468 + Kern::Printf("EVENTTRACKER: Found orphaned code seg %C in tracking list while adding new code seg", aCodeSeg);
1.469 + ++iErrorCount;
1.470 + }
1.471 + }
1.472 +
1.473 + if (!trackedCodeSeg)
1.474 + {
1.475 + iOOM = ETrue;
1.476 + ++iErrorCount;
1.477 + }
1.478 + }
1.479 +
1.480 +void DEventTracker::ProcessLoaded(DProcess* aProcess)
1.481 + {
1.482 + if (aProcess->iCodeSeg)
1.483 + {
1.484 + TTrackedCodeSeg* trackedCodeSeg = (TTrackedCodeSeg*)LookupItem(aProcess->iCodeSeg);
1.485 +
1.486 + if (trackedCodeSeg)
1.487 + {
1.488 + // This is the exe code seg for a process that
1.489 + // has completed loading and hence the access
1.490 + // count has just been decremented by one
1.491 + --trackedCodeSeg->iAccessCount;
1.492 + }
1.493 + }
1.494 + }
1.495 +
1.496 +void DEventTracker::RemoveCodeSeg(DCodeSeg* aCodeSeg, DProcess* aProcess)
1.497 + {
1.498 + TTrackedCodeSeg* const trackedCodeSeg = (TTrackedCodeSeg*)LookupItem(aCodeSeg);
1.499 +
1.500 + if (trackedCodeSeg)
1.501 + {
1.502 + if (!trackedCodeSeg->CheckIntegrity(aCodeSeg->iAccessCount))
1.503 + {
1.504 + ++iErrorCount;
1.505 + }
1.506 +
1.507 + if (aCodeSeg->iAccessCount == 1)
1.508 + {
1.509 + __KTRACE_OPT(KDEBUGGER, Kern::Printf("EVENTTRACKER: Removing %C from tracking list, process %O", aCodeSeg, aProcess));
1.510 + trackedCodeSeg->iLink.Deque();
1.511 +
1.512 + NKern::ThreadEnterCS();
1.513 + delete trackedCodeSeg;
1.514 + NKern::ThreadLeaveCS();
1.515 + }
1.516 + }
1.517 + else
1.518 + {
1.519 + Kern::Printf("EVENTTRACKER: %C removed but not in tracking list. Removing from process %O", aCodeSeg, aProcess);
1.520 + ++iErrorCount;
1.521 + }
1.522 + }
1.523 +
1.524 +
1.525 +/** Add all objects from relevant containers into the tracking list. */
1.526 +
1.527 +TInt DEventTracker::AddExistingObjects()
1.528 + {
1.529 + // Tracking can be started only after all containers read to avoid
1.530 + // race conditions.
1.531 + __ASSERT_DEBUG(!iTracking, Kern::Fault(KPanicCat, __LINE__));
1.532 +
1.533 + TInt err = KErrNone;
1.534 + Kern::Printf("Adding processes");
1.535 + err = AddObjectsFromContainer(EProcess);
1.536 + if (err)
1.537 + {
1.538 + return err;
1.539 + }
1.540 + Kern::Printf("Adding threads");
1.541 + err = AddObjectsFromContainer(EThread);
1.542 + if (err)
1.543 + {
1.544 + return err;
1.545 + }
1.546 + Kern::Printf("Adding libraries");
1.547 + err = AddObjectsFromContainer(ELibrary);
1.548 + if (err)
1.549 + {
1.550 + return err;
1.551 + }
1.552 + Kern::Printf("Adding chunks");
1.553 + err = AddObjectsFromContainer(EChunk);
1.554 + if (err)
1.555 + {
1.556 + return err;
1.557 + }
1.558 + Kern::Printf("Adding LDDs");
1.559 + err = AddObjectsFromContainer(ELogicalDevice);
1.560 + if (err)
1.561 + {
1.562 + return err;
1.563 + }
1.564 + Kern::Printf("Adding PDDs");
1.565 + err = AddObjectsFromContainer(EPhysicalDevice);
1.566 + if (err)
1.567 + {
1.568 + return err;
1.569 + }
1.570 + Kern::Printf("Adding code segs");
1.571 + return AddCodeSegsFromList();
1.572 + }
1.573 +
1.574 +/** Add all objects from specified container into tracking list. */
1.575 +
1.576 +TInt DEventTracker::AddObjectsFromContainer(TObjectType aType)
1.577 + {
1.578 + DObjectCon* const container = Kern::Containers()[aType];
1.579 +
1.580 + NKern::ThreadEnterCS();
1.581 + container->Wait();
1.582 +
1.583 + const TInt count = container->Count();
1.584 + TInt err = KErrNone;
1.585 +
1.586 + for (TInt i = 0; (i < count && err == KErrNone); ++i)
1.587 + {
1.588 + DObject* const object = (*container)[i];
1.589 + if (object->Open() == KErrNone)
1.590 + {
1.591 + AddObject(aType, object);
1.592 + if (iOOM)
1.593 + {
1.594 + err = KErrNoMemory;
1.595 + }
1.596 + object->Close(NULL);
1.597 + }
1.598 + }
1.599 +
1.600 + container->Signal();
1.601 + NKern::ThreadLeaveCS();
1.602 +
1.603 + return err;
1.604 + }
1.605 +
1.606 +TInt DEventTracker::AddCodeSegsFromList()
1.607 + {
1.608 + Kern::AccessCode();
1.609 +
1.610 + const SDblQueLink* const anchor = &Kern::CodeSegList()->iA;
1.611 + for (SDblQueLink* link = Kern::CodeSegList()->First(); link != anchor; link = link->iNext)
1.612 + {
1.613 + DCodeSeg* const codeSeg = _LOFF(link, DCodeSeg, iLink);
1.614 + AddCodeSeg(codeSeg, NULL);
1.615 + }
1.616 +
1.617 + Kern::EndAccessCode();
1.618 +
1.619 + return KErrNone;
1.620 + }
1.621 +
1.622 +
1.623 +/** Check that tracking list matches existing objects.
1.624 + @return number of discrepancies found
1.625 + */
1.626 +
1.627 +TInt DEventTracker::CheckIntegrity()
1.628 + {
1.629 + // Tracking must be stopped to avoid race conditions.
1.630 + __ASSERT_DEBUG(!iTracking, Kern::Fault(KPanicCat, __LINE__));
1.631 +
1.632 + if (iOOM)
1.633 + {
1.634 + Kern::Printf("EVENTTRACKER: OOM during tracking");
1.635 + }
1.636 +
1.637 + CheckContainerIntegrity(EProcess);
1.638 + CheckContainerIntegrity(EThread);
1.639 + CheckContainerIntegrity(ELibrary);
1.640 + CheckContainerIntegrity(EChunk);
1.641 + CheckContainerIntegrity(ELogicalDevice);
1.642 + CheckContainerIntegrity(EPhysicalDevice);
1.643 + CheckCodeSegListIntegrity();
1.644 +
1.645 + CheckAllAccountedFor();
1.646 +
1.647 + if (iErrorCount)
1.648 + {
1.649 + Kern::Printf("EVENTTRACKER: %d error(s) found", iErrorCount);
1.650 + return KErrGeneral;
1.651 + }
1.652 +
1.653 + return KErrNone;
1.654 + }
1.655 +
1.656 +/** Check all objects in specified container are in tracking list. */
1.657 +
1.658 +void DEventTracker::CheckContainerIntegrity(TObjectType aType)
1.659 + {
1.660 + DObjectCon* const container = Kern::Containers()[aType];
1.661 +
1.662 + NKern::ThreadEnterCS();
1.663 + container->Wait();
1.664 +
1.665 + const TInt count = container->Count();
1.666 +
1.667 + for (TInt i = 0; i < count; ++i)
1.668 + {
1.669 + DObject* const object = (*container)[i];
1.670 + if (object->Open() == KErrNone)
1.671 + {
1.672 + TFullName name;
1.673 + object->FullName(name);
1.674 +
1.675 + TTrackedObject* const trackedObject = (TTrackedObject*)LookupItem(object);
1.676 +
1.677 + if (trackedObject)
1.678 + {
1.679 + trackedObject->iAccountedFor = ETrue;
1.680 + if (!trackedObject->CheckIntegrity(name, aType))
1.681 + {
1.682 + ++iErrorCount;
1.683 + }
1.684 + }
1.685 + else
1.686 + {
1.687 + Kern::Printf("EVENTTRACKER: %S (type %d) is in container but not in tracking list", &name, aType);
1.688 + ++iErrorCount;
1.689 + }
1.690 +
1.691 + object->Close(NULL);
1.692 + }
1.693 + }
1.694 +
1.695 + container->Signal();
1.696 + NKern::ThreadLeaveCS();
1.697 + }
1.698 +
1.699 +void DEventTracker::CheckCodeSegListIntegrity()
1.700 + {
1.701 + Kern::AccessCode();
1.702 +
1.703 + const SDblQueLink* const anchor = &Kern::CodeSegList()->iA;
1.704 + for (SDblQueLink* link = Kern::CodeSegList()->First(); link != anchor; link = link->iNext)
1.705 + {
1.706 + DCodeSeg* const codeSeg = _LOFF(link, DCodeSeg, iLink);
1.707 + TTrackedCodeSeg* const trackedCodeSeg = (TTrackedCodeSeg*)LookupItem(codeSeg);
1.708 +
1.709 + if (trackedCodeSeg)
1.710 + {
1.711 + trackedCodeSeg->iAccountedFor = ETrue;
1.712 + if (!trackedCodeSeg->CheckIntegrity(codeSeg->iAccessCount))
1.713 + {
1.714 + ++iErrorCount;
1.715 + }
1.716 + }
1.717 + else
1.718 + {
1.719 + Kern::Printf("EVENTTRACKER: %C is in global list but not in tracking list", codeSeg);
1.720 + ++iErrorCount;
1.721 + }
1.722 + }
1.723 +
1.724 + Kern::EndAccessCode();
1.725 + }
1.726 +
1.727 +
1.728 +/** Check that all objects in tracking list have been accounted for. */
1.729 +void DEventTracker::CheckAllAccountedFor()
1.730 + {
1.731 + const SDblQueLink* link = iItems.GetFirst();
1.732 + while (link)
1.733 + {
1.734 + TTrackedItem* const item = _LOFF(link, TTrackedItem, iLink);
1.735 + if (!item->iAccountedFor)
1.736 + {
1.737 + Kern::Printf(
1.738 + "EVENTTRACKER: 0x%x is in tracking list but not in container / list",
1.739 + &item->iObject
1.740 + );
1.741 + ++iErrorCount;
1.742 + }
1.743 + link = iItems.GetFirst();
1.744 + }
1.745 + }
1.746 +
1.747 +/** Look for specified object in the tracking list.
1.748 + @pre iLock held
1.749 + @post iLock held
1.750 + */
1.751 +TTrackedItem* DEventTracker::LookupItem(DBase* aItem) const
1.752 + {
1.753 + const SDblQueLink* const anchor = &iItems.iA;
1.754 +
1.755 + for (SDblQueLink* link = iItems.First(); link != anchor; link = link->iNext)
1.756 + {
1.757 + TTrackedItem* const item = _LOFF(link, TTrackedItem, iLink);
1.758 +
1.759 + if (item->iObject == aItem)
1.760 + {
1.761 + return item;
1.762 + }
1.763 + }
1.764 +
1.765 + return NULL;
1.766 + }
1.767 +
1.768 +
1.769 +void DEventTracker::DumpCounters() const
1.770 + {
1.771 + static const char* const KEventName[] =
1.772 + {
1.773 + "SwExc ",
1.774 + "HwExc ",
1.775 + "AddProcess ",
1.776 + "UpdateProcess ",
1.777 + "RemoveProcess ",
1.778 + "AddThread ",
1.779 + "StartThread ",
1.780 + "UpdateThread ",
1.781 + "KillThread ",
1.782 + "RemoveThread ",
1.783 + "NewChunk ",
1.784 + "UpdateChunk ",
1.785 + "DeleteChunk ",
1.786 + "AddLibrary ",
1.787 + "RemoveLibrary ",
1.788 + "LoadLdd ",
1.789 + "UnloadLdd ",
1.790 + "LoadPdd ",
1.791 + "UnloadPdd ",
1.792 + "UserTrace ",
1.793 + "AddCodeSeg ",
1.794 + "RemoveCodeSeg ",
1.795 + "LoadedProcess ",
1.796 + "UnloadingProcess"
1.797 + };
1.798 +
1.799 + Kern::Printf("EVENT USAGE STATISTICS:");
1.800 +
1.801 + for (TInt i = 0; i < EEventLimit; ++i)
1.802 + {
1.803 + Kern::Printf("\t%s\t\t %d times", KEventName[i], iCounters[i]);
1.804 + }
1.805 + }
1.806 +
1.807 +#ifdef __MARM__
1.808 +void DEventTracker::CopyDummyHandler(TLinAddr aLinAddr)
1.809 + {
1.810 + const TUint handlerSize = DummyHandlerSize();
1.811 +
1.812 + // Copy the breakpoint-able handler into RAM by copying from the one (possibly) in ROM
1.813 + memcpy((TAny*)aLinAddr, (TAny*) &DummyHandler, handlerSize);
1.814 + __KTRACE_OPT(KBOOT, Kern::Printf("Breakpoint-able handler copied from 0x%x to (va) 0x%x, size %d", &DummyHandler, aLinAddr, handlerSize));
1.815 + }
1.816 +#endif
1.817 +
1.818 +//////////////////////////////////////////////////////////////////////////////
1.819 +
1.820 +class DTestChannel : public DLogicalChannelBase
1.821 + {
1.822 +public:
1.823 + virtual ~DTestChannel();
1.824 +protected:
1.825 + // from DLogicalChannelBase
1.826 + virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
1.827 + virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2);
1.828 +private:
1.829 + DEventTracker* iHandler;
1.830 + };
1.831 +
1.832 +
1.833 +// called in thread critical section
1.834 +TInt DTestChannel::DoCreate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
1.835 + {
1.836 + if((TUint)aUnit>=2)
1.837 + return KErrNotSupported;
1.838 +
1.839 + TBool useHook = aUnit;
1.840 +
1.841 + iHandler = new DEventTracker;
1.842 +
1.843 + if (!iHandler)
1.844 + {
1.845 + return KErrNoMemory;
1.846 + }
1.847 +
1.848 + return iHandler->Create(iDevice, useHook);
1.849 + }
1.850 +
1.851 +// called in thread critical section
1.852 +DTestChannel::~DTestChannel()
1.853 + {
1.854 + if (iHandler)
1.855 + {
1.856 + iHandler->Close();
1.857 + }
1.858 + }
1.859 +
1.860 +
1.861 +TInt DTestChannel::Request(TInt aFunction, TAny* /*a1*/, TAny* /*a2*/)
1.862 + {
1.863 + TInt r = KErrNone;
1.864 + switch (aFunction)
1.865 + {
1.866 + case REventTracker::EStart:
1.867 + iHandler->Start();
1.868 + break;
1.869 + case REventTracker::EStop:
1.870 + iHandler->Stop();
1.871 + break;
1.872 + default:
1.873 + Kern::PanicCurrentThread(KClientPanicCat, __LINE__);
1.874 + break;
1.875 + }
1.876 + return r;
1.877 + }
1.878 +
1.879 +
1.880 +//////////////////////////////////////////////////////////////////////////////
1.881 +
1.882 +class DTestFactory : public DLogicalDevice
1.883 + {
1.884 +public:
1.885 + DTestFactory();
1.886 + // from DLogicalDevice
1.887 + virtual TInt Install();
1.888 + virtual void GetCaps(TDes8& aDes) const;
1.889 + virtual TInt Create(DLogicalChannelBase*& aChannel);
1.890 + };
1.891 +
1.892 +DTestFactory::DTestFactory()
1.893 + {
1.894 + iVersion = REventTracker::Version();
1.895 + iParseMask = KDeviceAllowUnit;
1.896 + iUnitsMask = 0x3;
1.897 + }
1.898 +
1.899 +TInt DTestFactory::Create(DLogicalChannelBase*& aChannel)
1.900 + {
1.901 + aChannel = new DTestChannel;
1.902 + return (aChannel ? KErrNone : KErrNoMemory);
1.903 + }
1.904 +
1.905 +TInt DTestFactory::Install()
1.906 + {
1.907 + return SetName(&KTestLddName);
1.908 + }
1.909 +
1.910 +void DTestFactory::GetCaps(TDes8& /*aDes*/) const
1.911 + {
1.912 + }
1.913 +
1.914 +//////////////////////////////////////////////////////////////////////////////
1.915 +
1.916 +DECLARE_STANDARD_LDD()
1.917 + {
1.918 + return new DTestFactory;
1.919 + }