os/kernelhwsrv/kerneltest/e32utils/analyse/trace.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include "analyse.h"
sl@0
    17
#include "trace.h"
sl@0
    18
#include "nonxip.h"
sl@0
    19
#include <memory.h>
sl@0
    20
#include <string.h>
sl@0
    21
sl@0
    22
#ifdef __MSVCDOTNET__
sl@0
    23
#include <strstream>
sl@0
    24
#include <fstream>
sl@0
    25
#else //!__MSVCDOTNET__
sl@0
    26
#include <strstrea.h>
sl@0
    27
#include <fstream.h>
sl@0
    28
#endif //__MSVCDOTNET__
sl@0
    29
sl@0
    30
namespace {
sl@0
    31
sl@0
    32
template <class T>
sl@0
    33
class Map
sl@0
    34
	{
sl@0
    35
	enum {KInitialSize = 16};
sl@0
    36
	typedef T* Entry;
sl@0
    37
public:
sl@0
    38
	Map();
sl@0
    39
	T* Find(int aId) const;
sl@0
    40
	int Add(T& aT);
sl@0
    41
private:
sl@0
    42
	static void Insert(Entry* aMap, int aSize, T& aT);
sl@0
    43
	void Rehash();
sl@0
    44
private:
sl@0
    45
	Entry* iMap;
sl@0
    46
	int iSize;
sl@0
    47
	int iCount;
sl@0
    48
	int iThreshold;
sl@0
    49
	};
sl@0
    50
sl@0
    51
template <class T>
sl@0
    52
Map<T>::Map()
sl@0
    53
	:iMap(0), iSize(0), iCount(0), iThreshold(0)
sl@0
    54
	{}
sl@0
    55
sl@0
    56
template <class T>
sl@0
    57
T* Map<T>::Find(int aId) const
sl@0
    58
	{
sl@0
    59
	if (iSize == 0)
sl@0
    60
		return 0;
sl@0
    61
sl@0
    62
	unsigned hash = aId;
sl@0
    63
	for (;;)
sl@0
    64
		{
sl@0
    65
		hash &= (iSize-1);
sl@0
    66
		Entry x = iMap[hash];
sl@0
    67
		if (x == 0)
sl@0
    68
			return 0;
sl@0
    69
		if (x->iId == aId)
sl@0
    70
			return x;
sl@0
    71
		if (x->iId < aId)
sl@0
    72
			return 0;
sl@0
    73
		++hash;
sl@0
    74
		}
sl@0
    75
	}
sl@0
    76
sl@0
    77
template <class T>
sl@0
    78
int Map<T>::Add(T& aT)
sl@0
    79
	{
sl@0
    80
	if (iCount == iThreshold)
sl@0
    81
		Rehash();
sl@0
    82
sl@0
    83
	Insert(iMap,iSize,aT);
sl@0
    84
	return iCount++;
sl@0
    85
	}
sl@0
    86
sl@0
    87
template <class T>
sl@0
    88
void Map<T>::Rehash()
sl@0
    89
	{
sl@0
    90
	if (iSize == 0)
sl@0
    91
		{
sl@0
    92
		iMap = new Entry[KInitialSize];
sl@0
    93
		memset(iMap,0,KInitialSize*sizeof(Entry));
sl@0
    94
		iSize = KInitialSize;
sl@0
    95
		}
sl@0
    96
	else
sl@0
    97
		{
sl@0
    98
		int size = iSize * 2;
sl@0
    99
		Entry* map = new Entry[size];
sl@0
   100
		memset(map,0,size*sizeof(Entry));
sl@0
   101
		for (Entry* p = iMap + iSize; --p >= iMap; )
sl@0
   102
			if (*p != 0)
sl@0
   103
				Insert(map, size, **p);
sl@0
   104
		delete [] iMap;
sl@0
   105
		iMap = map;
sl@0
   106
		iSize = size;
sl@0
   107
		}
sl@0
   108
	iThreshold = (iSize * 3) / 4;	// 75%
sl@0
   109
	}
sl@0
   110
sl@0
   111
template <class T>
sl@0
   112
void Map<T>::Insert(typename Map<T>::Entry* aMap, int aSize, T& aT)
sl@0
   113
	{
sl@0
   114
	Entry e = &aT;
sl@0
   115
	unsigned hash = aT.iId;
sl@0
   116
	for (;;)
sl@0
   117
		{
sl@0
   118
		hash &= (aSize-1);
sl@0
   119
		Entry x = aMap[hash];
sl@0
   120
		if (x == 0)
sl@0
   121
			{
sl@0
   122
			aMap[hash] = e;
sl@0
   123
			return;
sl@0
   124
			}
sl@0
   125
		if (x->iId < e->iId)
sl@0
   126
			{
sl@0
   127
			aMap[hash] = e;
sl@0
   128
			e = x;
sl@0
   129
			}
sl@0
   130
		++hash;
sl@0
   131
		}
sl@0
   132
	}
sl@0
   133
sl@0
   134
};	// local namespace
sl@0
   135
sl@0
   136
class Decoder
sl@0
   137
	{
sl@0
   138
public:
sl@0
   139
	enum {ELazyIndexThread = -1, EFilteredThread = -2, ENullThread = -3};
sl@0
   140
	enum TValid {EOk, EBadFile, EBadVersion};
sl@0
   141
public:
sl@0
   142
	Decoder(const TraceData* aTrace, int aLength, unsigned aBeginSample, unsigned aEndSample);
sl@0
   143
	TValid Validate();
sl@0
   144
	void DecodeTrace(Sampler& aSampler, NonXIP* aNonXIP);
sl@0
   145
private:
sl@0
   146
	int DecodeInt();
sl@0
   147
	unsigned DecodeUint();
sl@0
   148
	char* DecodeName();
sl@0
   149
	const Process* DecodeProcess();
sl@0
   150
	Thread* DecodeThread();
sl@0
   151
private:
sl@0
   152
	unsigned iBegin;
sl@0
   153
	unsigned iEnd;
sl@0
   154
	const TraceData* iTrace;
sl@0
   155
	const TraceData* iLimit;
sl@0
   156
	Map<Process> iProcesses;
sl@0
   157
	Map<Thread> iThreads;
sl@0
   158
public:
sl@0
   159
	unsigned iSamples;
sl@0
   160
	unsigned iActive;
sl@0
   161
	};
sl@0
   162
sl@0
   163
Decoder::Decoder(const TraceData* aTrace, int aLength, unsigned aBeginSample, unsigned aEndSample)
sl@0
   164
	:iBegin(aBeginSample), iEnd(aEndSample),
sl@0
   165
	iTrace(aTrace), iLimit(aTrace + aLength),
sl@0
   166
	iSamples(0), iActive(0)
sl@0
   167
	{}
sl@0
   168
sl@0
   169
int Decoder::DecodeInt()
sl@0
   170
	{
sl@0
   171
	int val = 0;
sl@0
   172
	int shift = 0;
sl@0
   173
	unsigned byte;
sl@0
   174
	do
sl@0
   175
		{
sl@0
   176
		byte = *iTrace++;
sl@0
   177
		val |= (byte & 0x7f) << shift;
sl@0
   178
		shift += 7;
sl@0
   179
		} while ((byte & 0x80) == 0);
sl@0
   180
	if (shift < 32)
sl@0
   181
		{	// sign extend
sl@0
   182
		shift = 32 - shift;
sl@0
   183
		val = val << shift >> shift;
sl@0
   184
		}
sl@0
   185
	return val;
sl@0
   186
	}
sl@0
   187
sl@0
   188
unsigned Decoder::DecodeUint()
sl@0
   189
	{
sl@0
   190
	unsigned val = 0;
sl@0
   191
	int shift = 0;
sl@0
   192
	unsigned byte;
sl@0
   193
	do
sl@0
   194
		{
sl@0
   195
		byte = *iTrace++;
sl@0
   196
		val |= (byte & 0x7f) << shift;
sl@0
   197
		shift += 7;
sl@0
   198
		} while ((byte & 0x80) == 0);
sl@0
   199
	return val;
sl@0
   200
	}
sl@0
   201
sl@0
   202
char* Decoder::DecodeName()
sl@0
   203
	{
sl@0
   204
	int len = *iTrace++;
sl@0
   205
	char* name = new char[len+1];
sl@0
   206
	memcpy(name, iTrace, len);
sl@0
   207
	name[len] = '\0';
sl@0
   208
	iTrace += len;
sl@0
   209
	return name;
sl@0
   210
	}
sl@0
   211
sl@0
   212
const Process* Decoder::DecodeProcess()
sl@0
   213
	{
sl@0
   214
	int pid = DecodeUint();
sl@0
   215
	const Process* p = iProcesses.Find(pid);
sl@0
   216
	if (p)
sl@0
   217
		return p;
sl@0
   218
sl@0
   219
	Process* np = new Process;
sl@0
   220
	np->iId = pid;
sl@0
   221
	np->iName = DecodeName();
sl@0
   222
	iProcesses.Add(*np);
sl@0
   223
	return np;
sl@0
   224
	}
sl@0
   225
sl@0
   226
Thread* Decoder::DecodeThread()
sl@0
   227
	{
sl@0
   228
	int tid = DecodeUint();
sl@0
   229
	Thread* t = iThreads.Find(tid);
sl@0
   230
	if (t)
sl@0
   231
		return t;
sl@0
   232
sl@0
   233
	const Process* p = DecodeProcess();
sl@0
   234
	char* name = DecodeName();
sl@0
   235
	Thread* nt = new Thread;
sl@0
   236
	nt->iId = tid;
sl@0
   237
	nt->iName = name;
sl@0
   238
	nt->iProcess = p;
sl@0
   239
	iThreads.Add(*nt);
sl@0
   240
	if (!Analyse::Option(Analyse::ENull) && stricmp(name,"NULL") == 0)
sl@0
   241
		{
sl@0
   242
		nt->iIndex = ENullThread;
sl@0
   243
		return nt;
sl@0
   244
		}
sl@0
   245
	else
sl@0
   246
		{
sl@0
   247
		strstream s;
sl@0
   248
		s << p->iName << "::" << name << '\0';
sl@0
   249
		if (Analyse::Match(s.str(), Analyse::sThread))
sl@0
   250
			nt->iIndex = ELazyIndexThread;
sl@0
   251
		else
sl@0
   252
			nt->iIndex = EFilteredThread;
sl@0
   253
		}
sl@0
   254
	return nt;
sl@0
   255
	}
sl@0
   256
	
sl@0
   257
Decoder::TValid Decoder::Validate()
sl@0
   258
//
sl@0
   259
// Check the trace header
sl@0
   260
//
sl@0
   261
	{
sl@0
   262
	char* tag = DecodeName();
sl@0
   263
	int check = strcmp(tag, "profile");
sl@0
   264
	delete [] tag;
sl@0
   265
	if (check != 0)
sl@0
   266
		return EBadFile;
sl@0
   267
	int ver = DecodeUint();
sl@0
   268
	if (ver != MajorVersion)
sl@0
   269
		return EBadVersion;
sl@0
   270
	return EOk;
sl@0
   271
	}
sl@0
   272
sl@0
   273
void Decoder::DecodeTrace(Sampler& aSampler, NonXIP* aNonXIP)
sl@0
   274
	{
sl@0
   275
	PC pc = 0;
sl@0
   276
	Thread* thread = 0;
sl@0
   277
	int sample = 0;
sl@0
   278
	int threadIndexer = 0;
sl@0
   279
	while (iTrace < iLimit && sample < iEnd)
sl@0
   280
		{
sl@0
   281
		int count = 1;
sl@0
   282
		int diff = DecodeInt();
sl@0
   283
		if (diff & 1)
sl@0
   284
			{
sl@0
   285
			diff &= ~1;
sl@0
   286
			thread = DecodeThread();
sl@0
   287
			}
sl@0
   288
		else if (diff == 0)
sl@0
   289
			{
sl@0
   290
			unsigned int next = DecodeUint();
sl@0
   291
			if (next != 0) 
sl@0
   292
				count = next;
sl@0
   293
			else	// non-XIP
sl@0
   294
				{
sl@0
   295
				next = DecodeUint();
sl@0
   296
				if (next == 0) // footer
sl@0
   297
					{
sl@0
   298
					aNonXIP->iRowBufferErrors = DecodeUint();
sl@0
   299
					aNonXIP->iCookBufferErrors = DecodeUint();
sl@0
   300
					aNonXIP->iReportMask = DecodeUint();
sl@0
   301
					}
sl@0
   302
				else if (next & 1) // segment deletion
sl@0
   303
					{
sl@0
   304
					PC address = next & ~1;
sl@0
   305
					aNonXIP->DeleteSegment(address);
sl@0
   306
					}
sl@0
   307
				else	// segment creation
sl@0
   308
					{
sl@0
   309
					PC address = next;
sl@0
   310
					PC seg_size = DecodeUint();
sl@0
   311
					char * seg_name = DecodeName();
sl@0
   312
					aNonXIP->AddSegment(address, seg_size, seg_name + 3);
sl@0
   313
					}
sl@0
   314
				continue;
sl@0
   315
				}
sl@0
   316
			}
sl@0
   317
		pc += diff;
sl@0
   318
		while (--count >= 0)
sl@0
   319
			{
sl@0
   320
			if (sample >= iBegin)
sl@0
   321
				{
sl@0
   322
				++iSamples;
sl@0
   323
				if (thread->iIndex != ENullThread)
sl@0
   324
					++iActive;
sl@0
   325
				if (thread->iIndex >= ELazyIndexThread)
sl@0
   326
					{
sl@0
   327
					if (thread->iIndex == ELazyIndexThread)
sl@0
   328
						thread->iIndex = threadIndexer++;
sl@0
   329
					aSampler.Sample(sample, *thread, pc);
sl@0
   330
					}
sl@0
   331
				}
sl@0
   332
			if (++sample >= iEnd)
sl@0
   333
				break;
sl@0
   334
			}
sl@0
   335
		}
sl@0
   336
	}
sl@0
   337
sl@0
   338
Trace::Trace()
sl@0
   339
	:iTrace(0), iLength(0), iDecoder(0)
sl@0
   340
	{}
sl@0
   341
sl@0
   342
Trace::~Trace()
sl@0
   343
	{
sl@0
   344
	delete [] iTrace;
sl@0
   345
	delete iDecoder;
sl@0
   346
	}
sl@0
   347
sl@0
   348
void Trace::Load(const char* aTraceFile, unsigned aBegin, unsigned aEnd)
sl@0
   349
	{
sl@0
   350
	ifstream file;
sl@0
   351
#ifdef __MSVCDOTNET__
sl@0
   352
	file.open(aTraceFile, ios::binary);
sl@0
   353
#else //!__MSVCDOTNET__
sl@0
   354
	file.open(aTraceFile, ios::nocreate | ios::binary);
sl@0
   355
#endif //__MSVCDOTNET__
sl@0
   356
	if (!file)
sl@0
   357
		{
sl@0
   358
		cerr << "Unable to open trace file '" << aTraceFile << '\'' << endl;
sl@0
   359
		Analyse::Abort();
sl@0
   360
		}
sl@0
   361
//
sl@0
   362
	file.seekg(0, ios::end);
sl@0
   363
	iLength = file.tellg();
sl@0
   364
//
sl@0
   365
	iTrace = new TraceData[iLength];
sl@0
   366
	file.seekg(0, ios::beg);
sl@0
   367
	file.read(reinterpret_cast<char *>(iTrace), iLength);
sl@0
   368
//
sl@0
   369
	file.close();
sl@0
   370
//
sl@0
   371
	iDecoder = new Decoder(iTrace, iLength, aBegin, aEnd);
sl@0
   372
	switch (iDecoder->Validate())
sl@0
   373
		{
sl@0
   374
	case Decoder::EOk:
sl@0
   375
		break;
sl@0
   376
	case Decoder::EBadFile:
sl@0
   377
		cerr << "'" << aTraceFile << "' is not a valid trace file" << endl;
sl@0
   378
		Analyse::Abort();
sl@0
   379
		break;
sl@0
   380
	case Decoder::EBadVersion:
sl@0
   381
		Analyse::Abort("Trace file version not supported");
sl@0
   382
		break;
sl@0
   383
		}
sl@0
   384
	}
sl@0
   385
sl@0
   386
void Trace::Decode(Sampler& aSampler, NonXIP* aNonXIP)
sl@0
   387
	{
sl@0
   388
	iDecoder->DecodeTrace(aSampler, aNonXIP);
sl@0
   389
	aSampler.Complete(iDecoder->iSamples, iDecoder->iActive);
sl@0
   390
	}
sl@0
   391
sl@0
   392
sl@0
   393