diff -r 000000000000 -r 7f656887cf89 libraries/ltkutils/src/mapfile.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libraries/ltkutils/src/mapfile.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,289 @@ +// mapfile.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 +#include +#include "bsymtree.h" +#include + +#include +using namespace LtkUtils; +using namespace IoUtils; + +const TInt KSymbolGranularity = 256; // I have no idea... + +struct SSymbol + { + TUint iAddress; + TUint iLength; + HBufC8* iName; + }; + +NONSHARABLE_CLASS(CMapFileImpl) : public CMapFile + { +public: + CMapFileImpl(); + ~CMapFileImpl(); + void ConstructL(RFs& aFs, const TDesC& aFileName); + void DoLookup(TUint32 aOffsetInCodeSeg, TDes& aResult); + RNode* DoCreateCompletionTreeL(); + +private: + RArray iSymbols; + }; + +EXPORT_C CMapFile* CMapFile::NewL(RFs& aFs, const TDesC& aFileName) + { + CMapFileImpl* result = new (ELeave) CMapFileImpl; + CleanupStack::PushL(result); + //CleanupStack::PushL((CBase*)1); //DEBUG + result->ConstructL(aFs, aFileName); + //CleanupStack::Pop(); //DEBUG + CleanupStack::Pop(result); + return result; + } + +CMapFile::CMapFile() + { + } + +CMapFileImpl::CMapFileImpl() + : iSymbols(KSymbolGranularity, _FOFF(SSymbol, iAddress)) + { + } + +CMapFileImpl::~CMapFileImpl() + { + const TInt count = iSymbols.Count(); + for (TInt i = 0; i < count; i++) + { + delete iSymbols[i].iName; + } + iSymbols.Close(); + } + +EXPORT_C CMapFile::~CMapFile() + { + iReadBuf.Close(); + delete iFileName; + } + +#undef LeaveIfErr +#define LeaveIfErr(args...) StaticLeaveIfErr(args) + +void CMapFileImpl::ConstructL(RFs& aFs, const TDesC& aFileName) + { + iFileName = aFileName.AllocL(); + iReadBuf.CreateL(4096); + LeaveIfErr(iFile.Open(aFs, aFileName, EFileShareReadersOnly), _L("Couldn't open file %S"), &aFileName); + + TPtrC8 line; + TBool rvct = EFalse; + _LIT8(KRvct, "ARM Linker, RVCT"); + if (GetNextLine(line) && HasPrefix(line, KRvct)) rvct = ETrue; + TBool foundOffset = EFalse; + TInt linenum = 0; // for debugging + + if (rvct) + { + TInt local = ETrue; + while (GetNextLine(line)) + { + linenum++; + if (line.Length() == 0) continue; + _LIT8(KRVCTOffsetLine, " Image$$ER_RO$$Base "); + if (!foundOffset) + { + if (HasPrefix(line, KRVCTOffsetLine)) + { + TLex8 lex(line.Mid(KRVCTOffsetLine().Length())); + iTextOffset = HexLexL(lex); + foundOffset = ETrue; + + // No go through any symbols we found before this, and correct their offsets + for (TInt i = 0; i < iSymbols.Count(); i++) + { + iSymbols[i].iAddress -= iTextOffset; + } + continue; + } + } + + _LIT8(KGlobalSection, " Global Symbols"); + if (HasPrefix(line, KGlobalSection)) local = EFalse; // We've reached the global section, don't have to ignore so much stuff + + SSymbol symbol; + + // This is rather awkward, because there's no proper delimiting between symbol name and the next stuff + _LIT8(KSpaces, " "); + if (line.Length() < 55) continue; + TInt foundSpaces = line.Mid(55).Find(KSpaces); + if (foundSpaces == KErrNotFound) continue; + TInt spp = 55 + foundSpaces - 10; + symbol.iName = line.Left(spp).AllocLC(); + symbol.iName->Des().Trim(); + + TLex8 lex(line); + lex.Inc(spp); + symbol.iAddress = HexLexL(lex) - iTextOffset; + lex.SkipSpace(); + if (local) + { + // In local symbols section we have to worry about non-code stuff + _LIT8(KArm, "ARM Code "); + _LIT8(KThumb, "Thumb Code"); + TPtrC8 type = lex.Remainder().Left(KThumb().Length()); + if (type != KArm && type != KThumb) + { + CleanupStack::PopAndDestroy(symbol.iName); + continue; + } + } + + lex.Inc(10); // Far enough to get over "ARM Code" or "Thumb Code" + lex.SkipSpace(); + User::LeaveIfError(lex.Val(symbol.iLength)); + if (symbol.iLength == 0) + { + CleanupStack::PopAndDestroy(symbol.iName); + continue; // todo thunks lie about their size... + } + + User::LeaveIfError(iSymbols.Append(symbol)); + CleanupStack::Pop(symbol.iName); + } + } + else + { + while (GetNextLine(line)) + { + linenum++; + _LIT8(KGccTextOffsetLine, "Address of section .text set to "); + if (HasPrefix(line, KGccTextOffsetLine)) + { + // GCCE style + TLex8 lex(line.Mid(KGccTextOffsetLine().Length())); + iTextOffset = HexLexL(lex); + continue; + } + + _LIT8(KFin, ".fini"); + if (line == KFin) break; + if (line.Length() < 16) continue; + TLex8 lex(line); + lex.Inc(16); + SSymbol symbol; + symbol.iLength = 4; // unless otherwise updated by the next symbol addr + TInt err = HexLex(lex, symbol.iAddress); + if (err) continue; + symbol.iAddress -= iTextOffset; + lex.SkipSpace(); + if (lex.Offset() < 42) continue; // Code symbols have space up to column 42 + symbol.iName = lex.Remainder().AllocLC(); + + User::LeaveIfError(iSymbols.Append(symbol)); + CleanupStack::Pop(symbol.iName); + } + // GCCE doesn't even sort the symbols in its map file. Unbelievable! Or possibly even inconceivable! + iSymbols.SortUnsigned(); + for (TInt i = 1; i < iSymbols.Count(); i++) + { + SSymbol& prevSymbol = iSymbols[i - 1]; + prevSymbol.iLength = iSymbols[i].iAddress - prevSymbol.iAddress; + } + } + iFile.Close(); + iReadBuf.Close(); + } + +TBool CMapFile::GetNextLine(TPtrC8& aPtr) + { + _LIT8(KNewline, "\r\n"); + iReadBuf.Delete(0, aPtr.Length()); + if (HasPrefix(iReadBuf, KNewline)) iReadBuf.Delete(0, KNewline().Length()); + + TInt newline = iReadBuf.Find(KNewline); + if (newline != KErrNotFound) + { + aPtr.Set(iReadBuf.Left(newline)); + return ETrue; + } + // Otherwise need to try reading some more from file + TPtr8 restOfDesc((TUint8*)iReadBuf.Ptr() + iReadBuf.Size(), 0, iReadBuf.MaxSize() - iReadBuf.Size()); + TInt err = iFile.Read(restOfDesc); + if (err) restOfDesc.Zero(); + iReadBuf.SetLength(iReadBuf.Length() + restOfDesc.Length()); + + // Now re-try looking for newline + newline = iReadBuf.Find(KNewline); + if (newline != KErrNotFound) + { + aPtr.Set(iReadBuf.Left(newline + KNewline().Length())); + return ETrue; + } + + // No more newlines, just return whatever's left in the buffer + aPtr.Set(iReadBuf); + return aPtr.Length() != 0; // And return whether it's worth having + } + +EXPORT_C void CMapFile::Lookup(TUint32 aOffsetInCodeSeg, TDes& aResult) + { + //TUint32 offset = aOffsetInCodeSeg & 0xFFFFFFFE; // Mask bottom bit as it just indicates thumb mode + CMapFileImpl* impl = static_cast(this); // We know we're actually a CMapFileImpl + impl->DoLookup(aOffsetInCodeSeg, aResult); + } + +void CMapFileImpl::DoLookup(TUint32 aOffsetInCodeSeg, TDes& aResult) + { + TInt pos = 0; + SSymbol dummy; dummy.iAddress = aOffsetInCodeSeg; + TBool found = iSymbols.FindInUnsignedKeyOrder(dummy, pos) == KErrNone; + if (!found && pos != 0) pos--; + + aResult.Zero(); + const SSymbol& symbol = iSymbols[pos]; + if (aOffsetInCodeSeg >= symbol.iAddress && aOffsetInCodeSeg < symbol.iAddress + symbol.iLength) + { + aResult.Copy(*symbol.iName); + aResult.AppendFormat(_L(" + 0x%x"), aOffsetInCodeSeg - symbol.iAddress); + } + } + +EXPORT_C void CMapFile::GetFileNameL(TDes& aFileName) const + { + aFileName.Copy(*iFileName); + } + +RNode* CMapFile::CreateCompletionTreeL() + { + CMapFileImpl* impl = static_cast(this); // We know we're actually a CMapFileImpl + return impl->DoCreateCompletionTreeL(); + } + +RNode* CMapFileImpl::DoCreateCompletionTreeL() + { + RNode* result = RNode::NewL(); + CleanupDeletePushL(result); + + RLtkBuf tempBuf; + tempBuf.CreateLC(256); + for (TInt i = 0; i < iSymbols.Count(); i++) + { + tempBuf.Zero(); + tempBuf.AppendL(*iSymbols[i].iName); + tempBuf.ReserveExtraL(1); + result->InsertStringL(tempBuf.PtrZ(), iSymbols[i].iAddress); + } + CleanupStack::PopAndDestroy(&tempBuf); + CleanupStack::Pop(result); + return result; + }