Added ENotifyKeypresses and ECaptureCtrlC flags to CCommandBase.
Commands can now get keypresses and handle ctrl-C via callbacks instead of having to implement custom active objects. As part of this extended the CCommandBase extension interface to MCommandExtensionsV2 for the new virtual functions KeyPressed(TUint aKeyCode, TUint aModifiers) and CtrlCPressed(). sudo now cleans up correctly by using ECaptureCtrlC.
// 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 <fshell/bsym.h>
#include <fshell/ltkutils.h>
#include "bsymtree.h"
#include <fshell/descriptorutils.h>
#include <fshell/iocli.h>
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<SSymbol> 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<CMapFileImpl*>(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<CMapFileImpl*>(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;
}