libraries/ltkutils/src/symbolics.cpp
changeset 0 7f656887cf89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libraries/ltkutils/src/symbolics.cpp	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,187 @@
+// symbolics.cpp
+// 
+// Copyright (c) 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+// 
+// Initial Contributors:
+// Accenture - Initial contribution
+//
+#include <fshell/bsym.h>
+#include <fshell/ltkutils.h>
+#include <fshell/stringhash.h>
+#include <fshell/iocli.h>
+#include "bsymtree.h"
+
+using namespace LtkUtils;
+using namespace IoUtils;
+
+EXPORT_C CSymbolics::CSymbolics(RFs& aFs)
+	: iFs(aFs)
+	{
+	}
+
+EXPORT_C CSymbolics::~CSymbolics()
+	{
+	iBsyms.ResetAndDestroy();
+	TStringHashIter<CMapFile*> iter(iCodeSegHash);
+	while (iter.NextValue() != NULL)
+		{
+		CMapFile** file = iter.CurrentValue();
+		delete *file;
+		}
+	iCodeSegHash.Close();
+	delete iTabCompleteTree;
+	delete iTabCompleteCodeseg;
+	}
+
+EXPORT_C void CSymbolics::AddBsymFileL(const TDesC& aFileName)
+	{
+	CBsymFile* file = CBsymFile::NewL(iFs, aFileName);
+	TInt err = iBsyms.Append(file);
+	if (err)
+		{
+		delete file;
+		User::Leave(err);
+		}
+	}
+
+EXPORT_C void CSymbolics::AddMapFileL(const TDesC& aFileName)
+	{
+	CMapFile* file = CMapFile::NewL(iFs, aFileName);
+	CleanupStack::PushL(file);
+	AddMapFileL(file);
+	CleanupStack::Pop(file);
+	}
+
+EXPORT_C void CSymbolics::AddMapFileL(CMapFile* aMapFile)
+	{
+	aMapFile->GetFileNameL(iTempString);
+	TParsePtrC parse(iTempString);
+	TPtrC name = parse.Name(); // Don't use NameAndExt, that will include the .map!
+	TPtr namePtr((TUint16*)name.Ptr(), name.Length(), name.Length()); // Nasty but TParsePtr won't give us a non-const Name().
+	namePtr.LowerCase();
+	User::LeaveIfError(iCodeSegHash.Insert(namePtr, aMapFile));
+	}
+
+EXPORT_C void CSymbolics::SetFallbackMapFileDirL(const TDesC& aDir)
+	{
+	iFallbackMapFileDir = aDir;
+	}
+
+EXPORT_C TPtrC CSymbolics::LookupL(TUint32 aRomAddress)
+	{
+	for (TInt i = 0; i < iBsyms.Count(); i++)
+		{
+		TPtrC res = iBsyms[i]->LookupL(aRomAddress);
+		if (res.Length()) return res;
+		}
+	return TPtrC();
+	}
+
+EXPORT_C TPtrC CSymbolics::LookupL(const TDesC& aCodeseg, TUint32 aOffset)
+	{
+	CMapFile* mapFile = FindOrLoadMapFileL(aCodeseg);
+
+	iTempString.Zero();
+	if (mapFile)
+		{
+		mapFile->Lookup(aOffset, iTempString);
+		if (iTempString.Length())
+			{
+			iTempString.AppendFormat(_L(" (%S)"), &aCodeseg);
+			}
+		}
+	else
+		{
+		// Try BSYMs in case it's in ROFS
+		for (TInt i = 0; i < iBsyms.Count(); i++)
+			{
+			TPtrC res = iBsyms[i]->LookupL(aCodeseg, aOffset);
+			}
+		}
+	return TPtrC(iTempString);
+	}
+
+EXPORT_C void CSymbolics::CompleteL(const TDesC& aCodeseg, TDes& aSymbolName, CDesC16Array& aSuggestions)
+	{
+	RNode* tree = TreeForCodesegL(aCodeseg);
+	if (tree)
+		{
+		tree->CompleteL(aSymbolName, aSuggestions);
+		}
+	}
+
+RNode* CSymbolics::TreeForCodesegL(const TDesC& aCodeseg)
+	{
+	iTempString.Copy(aCodeseg);
+	iTempString.LowerCase();
+	if (iTabCompleteCodeseg && *iTabCompleteCodeseg != iTempString)
+		{
+		// If iTabCompleteCodeseg is set it means that iTabCompleteTree (if it's non-null) matches.
+		delete iTabCompleteCodeseg;
+		iTabCompleteCodeseg = NULL;
+		delete iTabCompleteTree;
+		iTabCompleteTree = NULL;
+		}
+	if (!iTabCompleteCodeseg) iTabCompleteCodeseg = iTempString.AllocL();
+
+	if (iTabCompleteTree == NULL)
+		{
+		for (TInt i = 0; i < iBsyms.Count(); i++)
+			{
+			RNode* tree = iBsyms[i]->CreateCompletionTreeL(*iTabCompleteCodeseg);
+			if (tree)
+				{
+				iTabCompleteTree = tree;
+				break;
+				}
+			}
+		}
+	// Try the map files now
+	if (iTabCompleteTree == NULL)
+		{
+		CMapFile* mapFile = FindOrLoadMapFileL(aCodeseg);
+		if (mapFile)
+			{
+			iTabCompleteTree = mapFile->CreateCompletionTreeL();
+			}
+		}
+	return iTabCompleteTree;
+	}
+
+EXPORT_C TUint32 CSymbolics::CodesegOffsetFromSymbolNameL(const TDesC& aCodeseg, const TDesC& aSymbolName)
+	{
+	RNode* tree = TreeForCodesegL(aCodeseg);
+	if (!tree) User::Leave(KErrNotFound);
+	return tree->ValueForStringL(aSymbolName);
+	}
+
+CMapFile* CSymbolics::FindOrLoadMapFileL(const TDesC& aCodeseg)
+	{
+	iTempString.Copy(aCodeseg);
+	iTempString.LowerCase();
+
+	// If it's already loaded, return it
+	CMapFile* mapFile = iCodeSegHash.FindPtr(iTempString);
+	if (mapFile) return mapFile;
+
+	if (iFallbackMapFileDir.Length() == 0) return NULL;
+	// Try loading the mapfile
+	TFileName2 fn = iFallbackMapFileDir;
+	fn.AppendComponentL(iTempString);
+	fn.Append(_L(".map"));
+	TEntry e;
+	if (iFs.Entry(fn, e) == KErrNone)
+		{
+		TRAPD(err, AddMapFileL(fn));
+		StaticLeaveIfErr(err, _L("Could not load map file %S"), &fn);
+		// AddMapFileL overwrites iTempString, so restore it (nasty but I object to wasting buffers on the stack...)
+		iTempString.Copy(aCodeseg);
+		iTempString.LowerCase();
+		return iCodeSegHash.FindPtr(iTempString);
+		}
+	return NULL;
+	}