os/kernelhwsrv/kerneltest/e32test/debug/d_debugapi.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/debug/d_debugapi.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,470 @@
     1.4 +// Copyright (c) 2005-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_debugapi.cpp
    1.18 +// LDD-based debug agent. It uses debugAPI provided by kernel extension 
    1.19 +// kdebug.dll (ARMv5) or kdebugv6 (ARMv6) to access and display various
    1.20 +// kernel objects. It uses debug port as output. See t_DebugAPI.cpp
    1.21 +// 
    1.22 +//
    1.23 +
    1.24 +#include <kernel/kern_priv.h>
    1.25 +#include "d_debugapi.h"
    1.26 +
    1.27 +_LIT(KClientPanicCat, "D_DEBUGAPI");
    1.28 +#define KMaxNameSize 20
    1.29 +
    1.30 +TInt DDebugAPIChecker::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
    1.31 +	{
    1.32 +	//This is the entry point for all debuggers. Super page contains the address of DebuggerInfo instance.
    1.33 +	iDebugInfo = Kern::SuperPage().iDebuggerInfo;
    1.34 +
    1.35 +	if (!iDebugInfo)
    1.36 +		{
    1.37 +		Kern::Printf("Error:Debugger is not installed");
    1.38 +		return KErrNotReady;
    1.39 +		}
    1.40 +	return GetOffsets(); //Obtain the copy of offsets.
    1.41 +	}
    1.42 +
    1.43 +/** 
    1.44 +Copies the offset tables from Debug API Kernel extension.
    1.45 +*/
    1.46 +TInt DDebugAPIChecker::GetOffsets()
    1.47 +	{
    1.48 +	//Get the memory-model-specific offset table
    1.49 +	switch (iDebugInfo->iMemoryModelType)
    1.50 +		{
    1.51 +	case EARMv5MMU:
    1.52 +		iMMUType = iDebugInfo->iMemoryModelType;
    1.53 +		if ((iVariantOffsetTable = new TMovingDebugOffsetTable)==NULL)
    1.54 +			return KErrNoMemory;
    1.55 +		memcpy(iVariantOffsetTable, iDebugInfo->iMemModelObjectOffsetTable, sizeof(TMovingDebugOffsetTable));
    1.56 +		break;
    1.57 +			
    1.58 +	case EARMv6MMU:
    1.59 +		iMMUType = iDebugInfo->iMemoryModelType;
    1.60 +		if ((iVariantOffsetTable = new TMultipleDebugOffsetTable)==NULL)
    1.61 +			return KErrNoMemory;
    1.62 +		memcpy(iVariantOffsetTable, iDebugInfo->iMemModelObjectOffsetTable, sizeof(TMultipleDebugOffsetTable));
    1.63 +		break;
    1.64 +
    1.65 +	default:
    1.66 +		return KErrNotSupported;
    1.67 +		}
    1.68 +
    1.69 +	//Get the main offset table
    1.70 +	if ((iOffsetTable = new TDebugOffsetTable)==NULL)
    1.71 +		{
    1.72 +		delete iVariantOffsetTable;
    1.73 +		return KErrNoMemory;
    1.74 +		}
    1.75 +	memcpy(iOffsetTable, iDebugInfo->iObjectOffsetTable, sizeof(TDebugOffsetTable));
    1.76 +
    1.77 +	//Get the scheduler's address
    1.78 +	iScheduler = (TInt*)iDebugInfo->iScheduler;
    1.79 +	return KErrNone;
    1.80 +	}
    1.81 +
    1.82 +DDebugAPIChecker::~DDebugAPIChecker()
    1.83 +	{
    1.84 +	delete iVariantOffsetTable;
    1.85 +	delete iOffsetTable;
    1.86 +	}
    1.87 +
    1.88 +/**
    1.89 +Transfer Symbian-like string into C style string.
    1.90 +The magic numbers come from descriptor implementation.
    1.91 +@param aSymbianName The address of the symbian-like string (TDesC8 type)
    1.92 +@param aCharName The address of the C style string
    1.93 +@returns aCharName
    1.94 +*/
    1.95 +TUint8* DDebugAPIChecker::ExtractName(TInt aSymbianName, TUint8* aCharName)
    1.96 +	{
    1.97 +	if(!aSymbianName) //zero length case
    1.98 +		{
    1.99 +		aCharName[0] = '*';	aCharName[1] = 0;
   1.100 +		return 	aCharName;
   1.101 +		}
   1.102 +	TInt nameLen =	Read((void*)aSymbianName, 0);	//The type & length of the desc. is kept in the first word
   1.103 +
   1.104 +	//We actually need only EBuf type of descriptor in this test.
   1.105 +	if (nameLen >> 28 != 3)		
   1.106 +		{
   1.107 +		aCharName[0] = '?';
   1.108 +		aCharName[1] = 0;
   1.109 +		return 	aCharName;
   1.110 +		}
   1.111 +
   1.112 +	nameLen &= 0x0fffffff;
   1.113 +	const TUint8* namePtr =	(TUint8*)(aSymbianName+8);
   1.114 +
   1.115 +	TInt charNameLen = nameLen<(KMaxNameSize-1) ? nameLen : KMaxNameSize-1;
   1.116 +	memcpy(aCharName, namePtr, charNameLen);
   1.117 +	aCharName[charNameLen] = 0;
   1.118 +	return 	aCharName;
   1.119 +	}
   1.120 +
   1.121 +/**
   1.122 +Prints the list of processes
   1.123 +*/
   1.124 +TInt DDebugAPIChecker::Process()
   1.125 +	{
   1.126 +	DObjectCon* processCon;
   1.127 +	TUint8 charName[KMaxNameSize];
   1.128 +
   1.129 +	//Fetch the address of the object container for processes
   1.130 +	processCon = iDebugInfo->iContainers[EProcess];
   1.131 +
   1.132 +	//Pend on the container's mutex before accessing any data
   1.133 +	NKern::ThreadEnterCS();
   1.134 +	processCon->Wait();
   1.135 +
   1.136 +	TInt containerCount = Read(processCon, iOffsetTable->iObjectCon_Count);
   1.137 +	TInt** containerObjects = (TInt**)Read(processCon, iOffsetTable->iObjectCon_Objects);
   1.138 +
   1.139 +	Kern::Printf("PROCESS TABLE:");
   1.140 +	Kern::Printf("Id attribut codeSeg  BccRunAd DatBssSC Name");
   1.141 +	for (TInt i = 0; i < containerCount; i++)
   1.142 +		{
   1.143 +		TInt* process =					containerObjects[i];
   1.144 +		TInt processId =				Read(process, iOffsetTable->iProcess_Id);
   1.145 +		TInt processAttributes =		Read(process, iOffsetTable->iProcess_Attributes);
   1.146 +		TInt processCodeSeg =			Read(process, iOffsetTable->iProcess_CodeSeg);
   1.147 +		TInt processCBssRunAddress =	Read(process, iOffsetTable->iProcess_DataBssRunAddress);
   1.148 +		TInt processDataBssStackChunk = Read(process, iOffsetTable->iProcess_DataBssStackChunk);
   1.149 +		TInt processName =				Read(process, iOffsetTable->iProcess_Name);
   1.150 +
   1.151 +		Kern::Printf("%02x %08x %08x %08x %08x %s", 
   1.152 +				processId, 
   1.153 +				processAttributes,
   1.154 +				processCodeSeg,
   1.155 +				processCBssRunAddress,
   1.156 +				processDataBssStackChunk,
   1.157 +				ExtractName(processName, charName));
   1.158 +		}
   1.159 +
   1.160 +	//Release container's mutex
   1.161 +	processCon->Signal();
   1.162 +	NKern::ThreadLeaveCS();
   1.163 +
   1.164 +	return KErrNone;
   1.165 +	}
   1.166 +
   1.167 +
   1.168 +/**
   1.169 +Prints the list of chunks
   1.170 +*/
   1.171 +TInt DDebugAPIChecker::Chunk()
   1.172 +	{
   1.173 +	TInt state = -1;
   1.174 +	TInt homeBase = -1;
   1.175 +	TInt* owningProcess = (TInt*)-1;
   1.176 +
   1.177 +	DObjectCon* processCon;
   1.178 +	TUint8 charName[KMaxNameSize];
   1.179 +
   1.180 +	//Fetch the address of the object container for processes
   1.181 +	processCon = iDebugInfo->iContainers[EChunk];
   1.182 +
   1.183 +	//Pend on the container's mutex before accessing any data.
   1.184 +	NKern::ThreadEnterCS();
   1.185 +	processCon->Wait();
   1.186 +
   1.187 +	TInt containerCount = Read(processCon, iOffsetTable->iObjectCon_Count);
   1.188 +	TInt** containerObjects = (TInt**)Read(processCon, iOffsetTable->iObjectCon_Objects);
   1.189 +
   1.190 +	Kern::Printf("CHUNK TABLE:");
   1.191 +	Kern::Printf("size     attribut type     state    HomeBase process");
   1.192 +	for (TInt i = 0; i < containerCount; i++)
   1.193 +		{
   1.194 +		TInt* chunk =			containerObjects[i];
   1.195 +		TInt size =				Read(chunk, iOffsetTable->iChunk_Size);
   1.196 +		TInt attributes =		Read(chunk, iOffsetTable->iChunk_Attributes);
   1.197 +		TInt type =				Read(chunk, iOffsetTable->iChunk_ChunkType);
   1.198 +		
   1.199 +		//This part is memory-model specific
   1.200 +		switch (iDebugInfo->iMemoryModelType)
   1.201 +		{
   1.202 +		case EARMv5MMU:
   1.203 +			{
   1.204 +			TMovingDebugOffsetTable* variantOffsets = (TMovingDebugOffsetTable*)iVariantOffsetTable;
   1.205 +			state =			Read(chunk, iOffsetTable->iChunk_ChunkState);//armv5 specific
   1.206 +			homeBase =		Read(chunk, iOffsetTable->iChunk_HomeBase);//armv5 specific
   1.207 +			owningProcess =	(TInt*)Read(chunk, iOffsetTable->iChunk_OwningProcess);//armv5
   1.208 +			
   1.209 +			//In moving MM, the specific offsets are provided in both tables. Check the values match.
   1.210 +			if (   state         != Read(chunk, variantOffsets->iChunk_ChunkState) 
   1.211 +				|| homeBase      !=	Read(chunk, variantOffsets->iChunk_HomeBase)
   1.212 +				|| owningProcess != (TInt*)Read(chunk, variantOffsets->iChunk_OwningProcess) )
   1.213 +				{
   1.214 +				Kern::Printf("Error: Offsets in main & specific table do not match");
   1.215 +				return KErrGeneral;
   1.216 +				}
   1.217 +			}
   1.218 +			break;
   1.219 +
   1.220 +		case EARMv6MMU:
   1.221 +			{
   1.222 +			TMultipleDebugOffsetTable* variantOffsets = (TMultipleDebugOffsetTable*)iVariantOffsetTable;
   1.223 +			owningProcess =	(TInt*)Read(chunk, variantOffsets->iChunk_OwningProcess);
   1.224 +			break;
   1.225 +			}
   1.226 +		default:
   1.227 +			Kern::Printf("Error: Unsupported memory model");
   1.228 +			return KErrGeneral;
   1.229 +		}
   1.230 +
   1.231 +		TInt processName;
   1.232 +		if(owningProcess)
   1.233 +			processName = Read(owningProcess, iOffsetTable->iProcess_Name);
   1.234 +		else
   1.235 +			processName = 0;
   1.236 +
   1.237 +		Kern::Printf("%08x %08x %08x %08x %08x %s", 
   1.238 +				size, 
   1.239 +				attributes,
   1.240 +				type,
   1.241 +				state,
   1.242 +				homeBase,
   1.243 +				ExtractName(processName, charName));
   1.244 +		}
   1.245 +
   1.246 +	//Release container's mutex
   1.247 +	processCon->Signal();
   1.248 +	NKern::ThreadLeaveCS();
   1.249 +
   1.250 +	return KErrNone;
   1.251 +	}
   1.252 +
   1.253 +/**
   1.254 +Prints the list of threads
   1.255 +*/
   1.256 +TInt DDebugAPIChecker::Thread()
   1.257 +	{
   1.258 +
   1.259 +	DObjectCon* processCon;
   1.260 +	TUint8 threadCharName[KMaxNameSize];
   1.261 +	TUint8 processCharName[KMaxNameSize];
   1.262 +
   1.263 +	//Fetch the address of the object container for threads
   1.264 +	processCon = iDebugInfo->iContainers[EThread];
   1.265 +
   1.266 +	//Pend on the container's mutex before accessing any data
   1.267 +	NKern::ThreadEnterCS();
   1.268 +	processCon->Wait();
   1.269 +
   1.270 +	TInt containerCount = Read(processCon, iOffsetTable->iObjectCon_Count);
   1.271 +	TInt** containerObjects = (TInt**)Read(processCon, iOffsetTable->iObjectCon_Objects);
   1.272 +
   1.273 +	Kern::Printf("THREAD TABLE:");
   1.274 +	Kern::Printf("Id Pri Typ SupStack+Size UsrStack+Size ContType SavedSP   ThreadName    Process");
   1.275 +
   1.276 +	for (TInt i = 0; i < containerCount; i++)
   1.277 +		{
   1.278 +		TInt* thread =			containerObjects[i];
   1.279 +		TInt id =				Read(thread, iOffsetTable->iThread_Id);
   1.280 +		TInt supStack =			Read(thread, iOffsetTable->iThread_SupervisorStack);
   1.281 +		TInt supStackSize =		Read(thread, iOffsetTable->iThread_SupervisorStackSize);
   1.282 +		TInt userStackRunAddr =	Read(thread, iOffsetTable->iThread_UserStackRunAddress);
   1.283 +		TInt userStackSize =	Read(thread, iOffsetTable->iThread_UserStackSize);
   1.284 +		TInt userContextType =	Read8(thread, iOffsetTable->iThread_UserContextType);
   1.285 +
   1.286 +		TInt savedSP	=		Read(thread, iOffsetTable->iThread_SavedSupervisorSP);
   1.287 +		TInt priority =			Read8(thread, iOffsetTable->iThread_Priority);
   1.288 +		TInt type =				Read8(thread, iOffsetTable->iThread_ThreadType);
   1.289 +		TInt name =				Read(thread, iOffsetTable->iThread_Name);
   1.290 +		TInt* owningProcess =	(TInt*)Read(thread, iOffsetTable->iThread_OwningProcess);
   1.291 +
   1.292 +		TInt processName =		Read(owningProcess, iOffsetTable->iProcess_Name);
   1.293 +
   1.294 +		Kern::Printf("%02x %3x %3x %08x %04x %08x %04x %08x %08x %14s %s", 
   1.295 +				id,
   1.296 +				priority, 
   1.297 +				type,
   1.298 +				supStack,
   1.299 +				supStackSize,
   1.300 +				userStackRunAddr,
   1.301 +				userStackSize,
   1.302 +				userContextType,
   1.303 +				savedSP,
   1.304 +				ExtractName(name, threadCharName),
   1.305 +				ExtractName(processName, processCharName)
   1.306 +				);
   1.307 +		}
   1.308 +
   1.309 +	//Release container's mutex
   1.310 +	processCon->Signal();
   1.311 +	NKern::ThreadLeaveCS();
   1.312 +
   1.313 +	return KErrNone;
   1.314 +	}
   1.315 +
   1.316 +/**
   1.317 +Reads memory location that belongs to the other process and compares the value with provided one.
   1.318 +The input argument contains the following data:
   1.319 +	- ProcessId of the process that owns the address space in question
   1.320 +	- Address of memory location to be read.
   1.321 +	- The value at the location.
   1.322 +	*/
   1.323 +TInt DDebugAPIChecker::IPAccess(TAny* a1)
   1.324 +	{
   1.325 +	TInt* process;
   1.326 +	TInt otherProcess = 0;
   1.327 +	TBool processFound = EFalse;
   1.328 +	TBool currentProcessFound = EFalse;
   1.329 +	DObjectCon* processCon;
   1.330 +
   1.331 +	RDebugAPIChecker::IPAccessArgs args;
   1.332 +	kumemget32 (&args, a1, sizeof(args));
   1.333 +
   1.334 +	//Find the addresses of the current nano-thread & SymbianOS-thread
   1.335 +	TInt currentNThread = Read(iScheduler, iOffsetTable->iScheduler_CurrentThread);
   1.336 +	TInt currentDThread = currentNThread - iOffsetTable->iThread_NThread;
   1.337 +	
   1.338 +	//Find the addresses of the current process
   1.339 +	TInt currentProcess = Read((void*)currentDThread, iOffsetTable->iThread_OwningProcess);
   1.340 +
   1.341 +	//Find process in the container with given processID
   1.342 +	processCon = iDebugInfo->iContainers[EProcess];
   1.343 +
   1.344 +	//Pend on the container's mutex before accessing any data
   1.345 +	NKern::ThreadEnterCS();
   1.346 +	processCon->Wait();
   1.347 +
   1.348 +	TInt containerCount = Read(processCon, iOffsetTable->iObjectCon_Count);
   1.349 +	TInt** containerObjects = (TInt**)Read(processCon, iOffsetTable->iObjectCon_Objects);
   1.350 +
   1.351 +	for (TInt i = 0; i < containerCount; i++)
   1.352 +		{
   1.353 +		process = containerObjects[i];
   1.354 +		TInt processId = Read(process, iOffsetTable->iProcess_Id);
   1.355 +
   1.356 +		if (currentProcess == (TInt)process)
   1.357 +			currentProcessFound = ETrue;
   1.358 +
   1.359 +		if (processId == (TInt)args.iProcessID)
   1.360 +			{
   1.361 +			otherProcess = (TInt)process;
   1.362 +			processFound = ETrue;
   1.363 +			}
   1.364 +		}
   1.365 +
   1.366 +	if(!(processFound &&  currentProcessFound))
   1.367 +		{
   1.368 +		Kern::Printf("Could not find the-current-process or the-other-process in the process container");
   1.369 +		processCon->Signal();
   1.370 +		NKern::ThreadLeaveCS();
   1.371 +		return KErrNotFound;
   1.372 +		}
   1.373 +
   1.374 +	//Release container's mutex
   1.375 +	processCon->Signal();
   1.376 +	NKern::ThreadLeaveCS();
   1.377 +
   1.378 +	switch (iMMUType)
   1.379 +		{
   1.380 +	case EARMv6MMU:
   1.381 +		{
   1.382 +		TMultipleDebugOffsetTable* variantOffsets = (TMultipleDebugOffsetTable*)iVariantOffsetTable;
   1.383 +		iCurrentProcess_OsAsid =		Read((void*)currentProcess, variantOffsets->iProcess_OsAsid);
   1.384 +		iCurrentProcess_LocalPageDir =	Read((void*)currentProcess, variantOffsets->iProcess_LocalPageDir);
   1.385 +		iOtherProcess_OsAsid =			Read((void*)otherProcess, variantOffsets->iProcess_OsAsid);
   1.386 +		iOtherProcess_LocalPageDir =	Read((void*)otherProcess, variantOffsets->iProcess_LocalPageDir);
   1.387 +		iAddress =						args.iAddress;
   1.388 +
   1.389 +		TUint r = ReadFromOtherProcessArmv6();
   1.390 +		
   1.391 +		//Chech if the value we just read matches the provided value.
   1.392 +		if ( r != args.iValue)
   1.393 +			{
   1.394 +			Kern::Printf("Returned value does not match");
   1.395 +			return KErrGeneral;
   1.396 +			}
   1.397 +		break;	
   1.398 +		}
   1.399 +	default:
   1.400 +		return KErrNotSupported;
   1.401 +		}	
   1.402 +
   1.403 +  return KErrNone;
   1.404 +	}
   1.405 +
   1.406 +TInt DDebugAPIChecker::Request(TInt aFunction, TAny* a1, TAny* /*a2*/)
   1.407 +	{
   1.408 +	TInt r = KErrNone;
   1.409 +	switch (aFunction)
   1.410 +		{
   1.411 +	case RDebugAPIChecker::ETProcess:
   1.412 +		r = Process();
   1.413 +		break;
   1.414 +
   1.415 +	case RDebugAPIChecker::ETChunk:
   1.416 +		r = Chunk();
   1.417 +		break;
   1.418 +
   1.419 +	case RDebugAPIChecker::ETThread:
   1.420 +		r = Thread();
   1.421 +		break;
   1.422 +
   1.423 +	case RDebugAPIChecker::ETIPAccess:
   1.424 +		r = IPAccess(a1);
   1.425 +		break;
   1.426 +
   1.427 +	default:
   1.428 +		Kern::PanicCurrentThread(KClientPanicCat, __LINE__);
   1.429 +		break;
   1.430 +		}
   1.431 +	return r;
   1.432 +	}
   1.433 +
   1.434 +//////////////////////////////////////////////////////////////////////////////
   1.435 +
   1.436 +class DTestFactory : public DLogicalDevice
   1.437 +	{
   1.438 +public:
   1.439 +	DTestFactory();
   1.440 +	// from DLogicalDevice
   1.441 +	virtual TInt Install();
   1.442 +	virtual void GetCaps(TDes8& aDes) const;
   1.443 +	virtual TInt Create(DLogicalChannelBase*& aChannel);
   1.444 +	};
   1.445 +
   1.446 +DTestFactory::DTestFactory()
   1.447 +    {
   1.448 +    iVersion = RDebugAPIChecker::Version();
   1.449 +    iParseMask = KDeviceAllowUnit;
   1.450 +    iUnitsMask = 0x3;
   1.451 +    }
   1.452 +
   1.453 +TInt DTestFactory::Create(DLogicalChannelBase*& aChannel)
   1.454 +    {
   1.455 +	aChannel = new DDebugAPIChecker;
   1.456 +	return (aChannel ? KErrNone : KErrNoMemory);
   1.457 +    }
   1.458 +
   1.459 +TInt DTestFactory::Install()
   1.460 +    {
   1.461 +    return SetName(&KTestLddName);
   1.462 +    }
   1.463 +
   1.464 +void DTestFactory::GetCaps(TDes8& /*aDes*/) const
   1.465 +    {
   1.466 +    }
   1.467 +
   1.468 +//////////////////////////////////////////////////////////////////////////////
   1.469 +
   1.470 +DECLARE_STANDARD_LDD()
   1.471 +	{
   1.472 +    return new DTestFactory;
   1.473 +	}