libraries/ltkutils/src/mapfile.cpp
changeset 0 7f656887cf89
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // mapfile.cpp
       
     2 // 
       
     3 // Copyright (c) 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "Eclipse Public License v1.0"
       
     6 // which accompanies this distribution, and is available
       
     7 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 // 
       
     9 // Initial Contributors:
       
    10 // Accenture - Initial contribution
       
    11 //
       
    12 #include <fshell/bsym.h>
       
    13 #include <fshell/ltkutils.h>
       
    14 #include "bsymtree.h"
       
    15 #include <fshell/descriptorutils.h>
       
    16 
       
    17 #include <fshell/iocli.h>
       
    18 using namespace LtkUtils;
       
    19 using namespace IoUtils;
       
    20 
       
    21 const TInt KSymbolGranularity = 256; // I have no idea...
       
    22 
       
    23 struct SSymbol
       
    24 	{
       
    25 	TUint iAddress;
       
    26 	TUint iLength;
       
    27 	HBufC8* iName;
       
    28 	};
       
    29 
       
    30 NONSHARABLE_CLASS(CMapFileImpl) : public CMapFile
       
    31 	{
       
    32 public:
       
    33 	CMapFileImpl();
       
    34 	~CMapFileImpl();
       
    35 	void ConstructL(RFs& aFs, const TDesC& aFileName);
       
    36 	void DoLookup(TUint32 aOffsetInCodeSeg, TDes& aResult);
       
    37 	RNode* DoCreateCompletionTreeL();
       
    38 
       
    39 private:
       
    40 	RArray<SSymbol> iSymbols;
       
    41 	};
       
    42 
       
    43 EXPORT_C CMapFile* CMapFile::NewL(RFs& aFs, const TDesC& aFileName)
       
    44 	{
       
    45 	CMapFileImpl* result = new (ELeave) CMapFileImpl;
       
    46 	CleanupStack::PushL(result);
       
    47 	//CleanupStack::PushL((CBase*)1); //DEBUG
       
    48 	result->ConstructL(aFs, aFileName);
       
    49 	//CleanupStack::Pop(); //DEBUG
       
    50 	CleanupStack::Pop(result);
       
    51 	return result;
       
    52 	}
       
    53 
       
    54 CMapFile::CMapFile()
       
    55 	{
       
    56 	}
       
    57 
       
    58 CMapFileImpl::CMapFileImpl()
       
    59 	: iSymbols(KSymbolGranularity, _FOFF(SSymbol, iAddress))
       
    60 	{
       
    61 	}
       
    62 
       
    63 CMapFileImpl::~CMapFileImpl()
       
    64 	{
       
    65 	const TInt count = iSymbols.Count();
       
    66 	for (TInt i = 0; i < count; i++)
       
    67 		{
       
    68 		delete iSymbols[i].iName;
       
    69 		}
       
    70 	iSymbols.Close();
       
    71 	}
       
    72 
       
    73 EXPORT_C CMapFile::~CMapFile()
       
    74 	{
       
    75 	iReadBuf.Close();
       
    76 	delete iFileName;
       
    77 	}
       
    78 
       
    79 #undef LeaveIfErr
       
    80 #define LeaveIfErr(args...) StaticLeaveIfErr(args)
       
    81 
       
    82 void CMapFileImpl::ConstructL(RFs& aFs, const TDesC& aFileName)
       
    83 	{
       
    84 	iFileName = aFileName.AllocL();
       
    85 	iReadBuf.CreateL(4096);
       
    86 	LeaveIfErr(iFile.Open(aFs, aFileName, EFileShareReadersOnly), _L("Couldn't open file %S"), &aFileName);
       
    87 
       
    88 	TPtrC8 line;
       
    89 	TBool rvct = EFalse;
       
    90 	_LIT8(KRvct, "ARM Linker, RVCT");
       
    91 	if (GetNextLine(line) && HasPrefix(line, KRvct)) rvct = ETrue;
       
    92 	TBool foundOffset = EFalse;
       
    93 	TInt linenum = 0; // for debugging
       
    94 
       
    95 	if (rvct)
       
    96 		{
       
    97 		TInt local = ETrue;
       
    98 		while (GetNextLine(line))
       
    99 			{
       
   100 			linenum++;
       
   101 			if (line.Length() == 0) continue;
       
   102 			_LIT8(KRVCTOffsetLine, "    Image$$ER_RO$$Base                       ");
       
   103 			if (!foundOffset)
       
   104 				{
       
   105 				if (HasPrefix(line, KRVCTOffsetLine))
       
   106 					{
       
   107 					TLex8 lex(line.Mid(KRVCTOffsetLine().Length()));
       
   108 					iTextOffset = HexLexL(lex);
       
   109 					foundOffset = ETrue;
       
   110 
       
   111 					// No go through any symbols we found before this, and correct their offsets
       
   112 					for (TInt i = 0; i < iSymbols.Count(); i++)
       
   113 						{
       
   114 						iSymbols[i].iAddress -= iTextOffset;
       
   115 						}
       
   116 					continue;
       
   117 					}
       
   118 				}
       
   119 
       
   120 			_LIT8(KGlobalSection, "    Global Symbols");
       
   121 			if (HasPrefix(line, KGlobalSection)) local = EFalse; // We've reached the global section, don't have to ignore so much stuff
       
   122 
       
   123 			SSymbol symbol;
       
   124 
       
   125 			// This is rather awkward, because there's no proper delimiting between symbol name and the next stuff
       
   126 			_LIT8(KSpaces, "   ");
       
   127 			if (line.Length() < 55) continue;
       
   128 			TInt foundSpaces = line.Mid(55).Find(KSpaces);
       
   129 			if (foundSpaces == KErrNotFound) continue;
       
   130 			TInt spp = 55 + foundSpaces - 10;
       
   131 			symbol.iName = line.Left(spp).AllocLC();
       
   132 			symbol.iName->Des().Trim();
       
   133 				
       
   134 			TLex8 lex(line);
       
   135 			lex.Inc(spp);
       
   136 			symbol.iAddress = HexLexL(lex) - iTextOffset;
       
   137 			lex.SkipSpace();
       
   138 			if (local)
       
   139 				{
       
   140 				// In local symbols section we have to worry about non-code stuff
       
   141 				_LIT8(KArm,   "ARM Code  ");
       
   142 				_LIT8(KThumb, "Thumb Code");
       
   143 				TPtrC8 type = lex.Remainder().Left(KThumb().Length());
       
   144 				if (type != KArm && type != KThumb)
       
   145 					{
       
   146 					CleanupStack::PopAndDestroy(symbol.iName);
       
   147 					continue;
       
   148 					}
       
   149 				}
       
   150 
       
   151 			lex.Inc(10); // Far enough to get over "ARM Code" or "Thumb Code"
       
   152 			lex.SkipSpace();
       
   153 			User::LeaveIfError(lex.Val(symbol.iLength));
       
   154 			if (symbol.iLength == 0)
       
   155 				{
       
   156 				CleanupStack::PopAndDestroy(symbol.iName);
       
   157 				continue; // todo thunks lie about their size...
       
   158 				}
       
   159 
       
   160 			User::LeaveIfError(iSymbols.Append(symbol));
       
   161 			CleanupStack::Pop(symbol.iName);
       
   162 			}
       
   163 		}
       
   164 	else
       
   165 		{
       
   166 		while (GetNextLine(line))
       
   167 			{
       
   168 			linenum++;
       
   169 			_LIT8(KGccTextOffsetLine, "Address of section .text set to ");
       
   170 			if (HasPrefix(line, KGccTextOffsetLine))
       
   171 				{
       
   172 				// GCCE style
       
   173 				TLex8 lex(line.Mid(KGccTextOffsetLine().Length()));
       
   174 				iTextOffset = HexLexL(lex);
       
   175 				continue;
       
   176 				}
       
   177 
       
   178 			_LIT8(KFin, ".fini");
       
   179 			if (line == KFin) break;
       
   180 			if (line.Length() < 16) continue;
       
   181 			TLex8 lex(line);
       
   182 			lex.Inc(16);
       
   183 			SSymbol symbol;
       
   184 			symbol.iLength = 4; // unless otherwise updated by the next symbol addr
       
   185 			TInt err = HexLex(lex, symbol.iAddress);
       
   186 			if (err) continue;
       
   187 			symbol.iAddress -= iTextOffset;
       
   188 			lex.SkipSpace();
       
   189 			if (lex.Offset() < 42) continue; // Code symbols have space up to column 42
       
   190 			symbol.iName = lex.Remainder().AllocLC();
       
   191 
       
   192 			User::LeaveIfError(iSymbols.Append(symbol));
       
   193 			CleanupStack::Pop(symbol.iName);
       
   194 			}
       
   195 		// GCCE doesn't even sort the symbols in its map file. Unbelievable! Or possibly even inconceivable!
       
   196 		iSymbols.SortUnsigned();
       
   197 		for (TInt i = 1; i < iSymbols.Count(); i++)
       
   198 			{
       
   199 			SSymbol& prevSymbol = iSymbols[i - 1];
       
   200 			prevSymbol.iLength = iSymbols[i].iAddress - prevSymbol.iAddress;
       
   201 			}
       
   202 		}
       
   203 	iFile.Close();
       
   204 	iReadBuf.Close();
       
   205 	}
       
   206 
       
   207 TBool CMapFile::GetNextLine(TPtrC8& aPtr)
       
   208 	{
       
   209 	_LIT8(KNewline, "\r\n");
       
   210 	iReadBuf.Delete(0, aPtr.Length());
       
   211 	if (HasPrefix(iReadBuf, KNewline)) iReadBuf.Delete(0, KNewline().Length());
       
   212 
       
   213 	TInt newline = iReadBuf.Find(KNewline);
       
   214 	if (newline != KErrNotFound)
       
   215 		{
       
   216 		aPtr.Set(iReadBuf.Left(newline));
       
   217 		return ETrue;
       
   218 		}
       
   219 	// Otherwise need to try reading some more from file
       
   220 	TPtr8 restOfDesc((TUint8*)iReadBuf.Ptr() + iReadBuf.Size(), 0, iReadBuf.MaxSize() - iReadBuf.Size());
       
   221 	TInt err = iFile.Read(restOfDesc);
       
   222 	if (err) restOfDesc.Zero();
       
   223 	iReadBuf.SetLength(iReadBuf.Length() + restOfDesc.Length());
       
   224 	
       
   225 	// Now re-try looking for newline
       
   226 	newline = iReadBuf.Find(KNewline);
       
   227 	if (newline != KErrNotFound)
       
   228 		{
       
   229 		aPtr.Set(iReadBuf.Left(newline + KNewline().Length()));
       
   230 		return ETrue;
       
   231 		}
       
   232 
       
   233 	// No more newlines, just return whatever's left in the buffer
       
   234 	aPtr.Set(iReadBuf);
       
   235 	return aPtr.Length() != 0; // And return whether it's worth having
       
   236 	}
       
   237 
       
   238 EXPORT_C void CMapFile::Lookup(TUint32 aOffsetInCodeSeg, TDes& aResult)
       
   239 	{
       
   240 	//TUint32 offset = aOffsetInCodeSeg & 0xFFFFFFFE; // Mask bottom bit as it just indicates thumb mode
       
   241 	CMapFileImpl* impl = static_cast<CMapFileImpl*>(this); // We know we're actually a CMapFileImpl
       
   242 	impl->DoLookup(aOffsetInCodeSeg, aResult);
       
   243 	}
       
   244 
       
   245 void CMapFileImpl::DoLookup(TUint32 aOffsetInCodeSeg, TDes& aResult)
       
   246 	{
       
   247 	TInt pos = 0;
       
   248 	SSymbol dummy; dummy.iAddress = aOffsetInCodeSeg;
       
   249 	TBool found = iSymbols.FindInUnsignedKeyOrder(dummy, pos) == KErrNone;
       
   250 	if (!found && pos != 0) pos--;
       
   251 
       
   252 	aResult.Zero();
       
   253 	const SSymbol& symbol = iSymbols[pos];
       
   254 	if (aOffsetInCodeSeg >= symbol.iAddress && aOffsetInCodeSeg < symbol.iAddress + symbol.iLength)
       
   255 		{
       
   256 		aResult.Copy(*symbol.iName);
       
   257 		aResult.AppendFormat(_L(" + 0x%x"), aOffsetInCodeSeg - symbol.iAddress);
       
   258 		}
       
   259 	}
       
   260 
       
   261 EXPORT_C void CMapFile::GetFileNameL(TDes& aFileName) const
       
   262 	{
       
   263 	aFileName.Copy(*iFileName);
       
   264 	}
       
   265 
       
   266 RNode* CMapFile::CreateCompletionTreeL()
       
   267 	{
       
   268 	CMapFileImpl* impl = static_cast<CMapFileImpl*>(this); // We know we're actually a CMapFileImpl
       
   269 	return impl->DoCreateCompletionTreeL();
       
   270 	}
       
   271 
       
   272 RNode* CMapFileImpl::DoCreateCompletionTreeL()
       
   273 	{
       
   274 	RNode* result = RNode::NewL();
       
   275 	CleanupDeletePushL(result);
       
   276 
       
   277 	RLtkBuf tempBuf;
       
   278 	tempBuf.CreateLC(256);
       
   279 	for (TInt i = 0; i < iSymbols.Count(); i++)
       
   280 		{
       
   281 		tempBuf.Zero();
       
   282 		tempBuf.AppendL(*iSymbols[i].iName);
       
   283 		tempBuf.ReserveExtraL(1);
       
   284 		result->InsertStringL(tempBuf.PtrZ(), iSymbols[i].iAddress);
       
   285 		}
       
   286 	CleanupStack::PopAndDestroy(&tempBuf);
       
   287 	CleanupStack::Pop(result);
       
   288 	return result;
       
   289 	}