Performance improvements to terminalkeyboardcons.
// patchdata.cpp+ −
// + −
// Copyright (c) 2008 - 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/ioutils.h>+ −
#include <f32image.h>+ −
#include "sf_deflate.h"+ −
#include <e32rom.h>+ −
#include <fshell/memoryaccesscmd.h>+ −
+ −
using namespace IoUtils;+ −
+ −
IMPORT_C extern const TInt KHeapMinCellSize;+ −
+ −
class CCmdPatchdata : public CMemoryAccessCommandBase+ −
{+ −
public:+ −
static CCommandBase* NewLC();+ −
~CCmdPatchdata();+ −
private:+ −
CCmdPatchdata();+ −
void HandleXipL();+ −
+ −
private: // From CCommandBase.+ −
virtual const TDesC& Name() const;+ −
virtual void DoRunL();+ −
virtual void ArgumentsL(RCommandArgumentList& aArguments);+ −
virtual void OptionsL(RCommandOptionList& aOptions);+ −
private:+ −
// The stuff from elsewhere+ −
void LoadFileInflateL(E32ImageHeaderComp* aHeader,TUint8* aRestOfFileData,TUint32 aRestOfFileSize);+ −
void LoadFileNoCompressL(E32ImageHeaderComp* aHeader,TUint8* aRestOfFileData,TUint32 aRestOfFileSize);+ −
TInt LoadFile(TUint32 aCompression,E32ImageHeaderComp* aHeader,TUint8* aRestOfFileData,TUint32 iRestOfFileSize); + −
+ −
private:+ −
HBufC* iDll;+ −
TInt iOrdinal;+ −
TInt iNewValue;+ −
TFileName iPath;+ −
TFileName iNewPath;+ −
RFile iFile;+ −
TBool iVerbose;+ −
};+ −
+ −
+ −
CCommandBase* CCmdPatchdata::NewLC()+ −
{+ −
CCmdPatchdata* self = new(ELeave) CCmdPatchdata();+ −
CleanupStack::PushL(self);+ −
self->BaseConstructL();+ −
return self;+ −
}+ −
+ −
CCmdPatchdata::~CCmdPatchdata()+ −
{+ −
delete iDll;+ −
iFile.Close();+ −
}+ −
+ −
CCmdPatchdata::CCmdPatchdata()+ −
{+ −
}+ −
+ −
const TDesC& CCmdPatchdata::Name() const+ −
{+ −
_LIT(KName, "patchdata"); + −
return KName;+ −
}+ −
+ −
void CCmdPatchdata::ArgumentsL(RCommandArgumentList& aArguments)+ −
{+ −
aArguments.AppendStringL(iDll, _L("dll-name"));+ −
aArguments.AppendIntL(iOrdinal, _L("ordinal"));+ −
aArguments.AppendUintL((TUint&)iNewValue, _L("value"));+ −
}+ −
+ −
void CCmdPatchdata::OptionsL(RCommandOptionList& aOptions)+ −
{+ −
aOptions.AppendBoolL(iVerbose, _L("verbose"));+ −
}+ −
+ −
EXE_BOILER_PLATE(CCmdPatchdata)+ −
+ −
void CCmdPatchdata::DoRunL()+ −
{+ −
if (!iDll)+ −
{+ −
// Just print some standard ones+ −
Printf(_L("KHeapMinCellSize: %d\r\n"), KHeapMinCellSize);+ −
return;+ −
}+ −
+ −
TBool scan = !iArguments.IsPresent(1);+ −
TBool change = iArguments.IsPresent(2);+ −
+ −
// First figure out where the dll is - easiest way is to load it+ −
#ifdef __WINS__+ −
PrintWarning(_L("On WINS, exe-name must be a complete path to a E32 DLL"));+ −
iPath = *iDll;+ −
#else+ −
// Can't use RLibrary because we have all caps and the DLL won't+ −
TFindFile find(FsL());+ −
TInt found = find.FindByDir(*iDll, _L("Y:\\sys\\bin\\"));+ −
LeaveIfErr(found, _L("Couldn't find DLL %S"), iDll);+ −
iPath = find.File();+ −
+ −
if (FsL().IsFileInRom(iPath) != NULL)+ −
{+ −
HandleXipL();+ −
return;+ −
}+ −
#endif+ −
+ −
iNewPath = iPath;+ −
TUint fileopenmode = EFileRead|EFileStream|EFileShareAny;+ −
+ −
if (change) fileopenmode = EFileWrite|EFileStream|EFileShareAny;+ −
+ −
if (change && iPath[0] != 'c')+ −
{+ −
// If file is already on c then we just patch in place+ −
+ −
// We have a new value to set - so copy the DLL to C in preparation for patching it+ −
iNewPath[0] = 'c';+ −
+ −
//CleanupStack::PushL(TCleanupItem(&DeleteModifiedBinary, this));+ −
+ −
TInt err = FsL().MkDirAll(iNewPath); // In case C:\sys\bin doesn't exist yet+ −
if (err && err != KErrAlreadyExists)+ −
{+ −
PrintError(err, _L("Couldn't create C:\\sys\\bin"));+ −
User::Leave(err);+ −
}+ −
+ −
CFileMan* fm = CFileMan::NewL(Fs());+ −
CleanupStack::PushL(fm);+ −
+ −
LeaveIfErr(fm->Copy(iPath, iNewPath), _L("Couldn't copy file from %S to %S"), &iPath, &iNewPath);+ −
// Clear the read-only bit in the case where we've copied from ROM+ −
LeaveIfErr(Fs().SetAtt(iNewPath, 0, KEntryAttReadOnly), _L("Couldn't unset read-only flag"));+ −
CleanupStack::PopAndDestroy(fm);+ −
}+ −
+ −
// Now start fiddling+ −
LeaveIfErr(iFile.Open(FsL(), iNewPath, fileopenmode), _L("Couldn't open file %S"), &iNewPath);+ −
+ −
///// Begin code lifted from chkdeps+ −
E32ImageHeaderV* imageHeader=new(ELeave)E32ImageHeaderV;+ −
CleanupStack::PushL(imageHeader);+ −
TPckg<E32ImageHeaderV> ptr(*imageHeader);+ −
LeaveIfErr(iFile.Read(ptr, sizeof(E32ImageHeaderV)), _L("Couldn't read E32ImageHeader"));+ −
+ −
if (!scan && (iOrdinal <= 0 || iOrdinal-1 >= imageHeader->iExportDirCount)) // -1 because ordinals are 1-based in DEF files+ −
{+ −
LeaveIfErr(KErrArgument, _L("ordinal out of range: only %d exports in file"), imageHeader->iExportDirCount);+ −
}+ −
if (imageHeader->HeaderFormat() >= KImageHdrFmt_V && imageHeader->iExportDescType != KImageHdr_ExpD_NoHoles)+ −
{+ −
LeaveIfErr(KErrNotSupported, _L("Don't understand files whose export table format isn't KImageHdr_ExpD_NoHoles (format is %d)"), imageHeader->iExportDescType);+ −
}+ −
+ −
TInt exportOffset = imageHeader->iExportDirOffset;+ −
+ −
// Decompress rest of image+ −
TUint32 compression = imageHeader->CompressionType();+ −
TInt restOfFileSize=0;+ −
TUint8* restOfFileData=NULL;+ −
//detect the size of import information+ −
if (compression != KFormatNotCompressed)+ −
{+ −
// Compressed executable+ −
// iCodeOffset = header size for format V or above+ −
// = sizeof(E32ImageHeader) for format J+ −
restOfFileSize = imageHeader->UncompressedFileSize() - imageHeader->iCodeOffset;+ −
}+ −
else+ −
{+ −
TInt FileSize;+ −
iFile.Size(FileSize); + −
restOfFileSize = FileSize-imageHeader->TotalSize();+ −
} + −
//restOfFileSize -= imageHeader->iCodeSize; // the size of the exe less header & code+ −
+ −
//allocate memory for rest of file+ −
if (restOfFileSize >0)+ −
{+ −
restOfFileData = (TUint8*)User::AllocLC(restOfFileSize ); + −
}+ −
+ −
LeaveIfErr(LoadFile(compression,imageHeader,restOfFileData,restOfFileSize), _L("Failed to load file data")); // Read import information in+ −
+ −
///// End code lifted from chkdeps+ −
+ −
const TInt headerSize = imageHeader->iCodeOffset;+ −
exportOffset -= headerSize; // we are indexing into restoffile which doesn't have the header+ −
+ −
TInt* exports = (TInt*)(restOfFileData + exportOffset);+ −
+ −
if (scan)+ −
{+ −
//Printf(_L("TextSize = %d\r\n"), imageHeader->iTextSize);+ −
//Printf(_L("CodeSize = %d\r\n"), imageHeader->iCodeSize);+ −
//Printf(_L("dataoffset = %d\r\n"), imageHeader->iDataOffset);+ −
//Printf(_L("importoffset= %d\r\n"), imageHeader->iImportOffset);+ −
//Printf(_L("exportdiroffset= %d\r\n"), imageHeader->iExportDirOffset);+ −
for (TInt i = 0; i < imageHeader->iExportDirCount; i++)+ −
{+ −
// No direct way of figuring out where code stops and const data starts. Export table sits between them though+ −
// so use this to distiguish. (Don't know if my logic here is right but it seems to mainly work...)+ −
TInt valoffset = exports[i] - imageHeader->iCodeBase;+ −
if (iVerbose)+ −
{+ −
Printf(_L("export[%d] = %d\r\n"), i, valoffset + headerSize);+ −
}+ −
if (valoffset >= (TInt)imageHeader->iExportDirOffset-headerSize)+ −
{+ −
TInt val = *(TInt*)(restOfFileData + valoffset);+ −
Printf(_L("Ordinal %d: 0x%08x (%d)\r\n"), i+1, val, val);+ −
}+ −
}+ −
}+ −
else+ −
{+ −
TInt valoffset = exports[iOrdinal-1] - imageHeader->iCodeBase; // Subtract one from ordinal as they're 1-based in DEF files+ −
TInt& val = *(TInt*)(restOfFileData + valoffset);+ −
+ −
if (change)+ −
{+ −
TInt oldVal = val;+ −
val = iNewValue; // This updates restOfFileData+ −
// Now write everything back to file. The data has to be written uncompressed as there is no compression+ −
// code we can easily rip off. We have to update the header irrespective to increment the version+ −
iFile.SetSize(headerSize);+ −
+ −
imageHeader->iCompressionType = KFormatNotCompressed;+ −
// Update the version to sort out linking bug (probably not an issue for most uses of patchable data, but it could be in theory)+ −
if ((imageHeader->iModuleVersion & 0x0000ffffu) == 0x0000ffffu)+ −
{+ −
// Don't update if version is XXXXffff as incrementing it would raise the major version - which is considered incompatible+ −
PrintWarning(_L("Couldn't update DLL's minor version as it is already at its maximum value"));+ −
}+ −
else+ −
{+ −
imageHeader->iModuleVersion++;+ −
}+ −
+ −
// Update e32 checksum+ −
imageHeader->iHeaderCrc = KImageCrcInitialiser;+ −
TUint32 crc = 0;+ −
Mem::Crc32(crc, imageHeader, imageHeader->TotalSize());+ −
imageHeader->iHeaderCrc = crc;+ −
LeaveIfErr(iFile.Write(0, ptr), _L("Couldn't write updated header back to file"));+ −
+ −
TPtrC8 data(restOfFileData, restOfFileSize);+ −
LeaveIfErr(iFile.Write(headerSize, data), _L("Couldn't write patched DLL code back to file"));+ −
+ −
Printf(_L("Ordinal %d: old value was 0x%08x, new value is 0x%08x"), iOrdinal, oldVal, iNewValue);+ −
}+ −
else+ −
{+ −
Printf(_L("Ordinal %d: 0x%08x (%d)\r\n"), iOrdinal, val, val);+ −
}+ −
}+ −
+ −
CleanupStack::PopAndDestroy(2, imageHeader); // imageHeader, restOfFileData+ −
}+ −
+ −
void FileCleanup(TAny* aPtr)+ −
{+ −
TFileInput* f=(TFileInput*)aPtr;+ −
f->Cancel();+ −
delete f;+ −
}+ −
+ −
void CCmdPatchdata::LoadFileInflateL(E32ImageHeaderComp* aHeader,TUint8* aRestOfFileData,TUint32 aRestOfFileSize)+ −
{+ −
TInt pos = aHeader->TotalSize();+ −
User::LeaveIfError(iFile.Seek(ESeekStart,pos)); // Start at beginning of compressed data+ −
+ −
TFileInput* file = new (ELeave) TFileInput(iFile);+ −
CleanupStack::PushL(TCleanupItem(&FileCleanup,file));+ −
CInflater* inflater=CInflater::NewLC(*file);+ −
+ −
/*if (aHeader->iCodeSize)+ −
{+ −
TUint8* CodeData = (TUint8*)User::AllocLC(aHeader->iCodeSize );+ −
TInt count=inflater->ReadL((TUint8*)CodeData ,aHeader->iCodeSize,&Mem::Move);+ −
if(count!=aHeader->iCodeSize)+ −
User::Leave(KErrCorrupt);+ −
CleanupStack::PopAndDestroy(CodeData);+ −
}*/+ −
+ −
if (aRestOfFileSize)+ −
{+ −
TUint32 count=inflater->ReadL(aRestOfFileData,aRestOfFileSize,&Mem::Move);+ −
if(count!=aRestOfFileSize)+ −
User::Leave(KErrCorrupt);+ −
}+ −
CleanupStack::PopAndDestroy(2,file);+ −
}+ −
+ −
void CCmdPatchdata::LoadFileNoCompressL(E32ImageHeaderComp* aHeader,TUint8* aRestOfFileData,TUint32 aRestOfFileSize)+ −
{+ −
TInt pos = (aHeader->TotalSize() /*+aHeader->iCodeSize*/);+ −
if (aRestOfFileSize)+ −
{+ −
User::LeaveIfError(iFile.Seek(ESeekStart,pos));+ −
TPtr8 ptrToData((TText8*)(aRestOfFileData),aRestOfFileSize,aRestOfFileSize);+ −
User::LeaveIfError(iFile.Read(ptrToData, (TInt)aRestOfFileSize)); + −
}+ −
} + −
//function loads file's import information calling decompression routine if needed+ −
TInt CCmdPatchdata::LoadFile(TUint32 aCompression,E32ImageHeaderComp* aHeader,TUint8* aRestOfFileData,TUint32 aRestOfFileSize)+ −
{+ −
TInt r=KErrNone;+ −
if(aCompression==KFormatNotCompressed)+ −
{+ −
TRAP(r,LoadFileNoCompressL(aHeader,aRestOfFileData,aRestOfFileSize)); + −
}+ −
else if(aCompression==KUidCompressionDeflate)+ −
{+ −
TRAP(r,LoadFileInflateL(aHeader,aRestOfFileData,aRestOfFileSize));+ −
}+ −
else+ −
r=KErrNotSupported;+ −
+ −
return r;+ −
}+ −
+ −
void CCmdPatchdata::HandleXipL()+ −
{+ −
TBool scan = !iArguments.IsPresent(1);+ −
TBool change = iArguments.IsPresent(2);+ −
TRomImageHeader* imageHeader = (TRomImageHeader*)FsL().IsFileInRom(iPath);+ −
+ −
if (!scan && (iOrdinal <= 0 || iOrdinal-1 >= imageHeader->iExportDirCount)) // -1 because ordinals are 1-based in DEF files+ −
{+ −
LeaveIfErr(KErrArgument, _L("ordinal out of range: only %d exports in file"), imageHeader->iExportDirCount);+ −
}+ −
+ −
TLinAddr* exports = (TLinAddr*)(imageHeader->iExportDir);+ −
+ −
if (scan)+ −
{+ −
for (TInt i = 0; i < imageHeader->iExportDirCount; i++)+ −
{+ −
TLinAddr valAddr = exports[i];+ −
if (iVerbose)+ −
{+ −
Printf(_L("export[%d] = 0x%08x\r\n"), i, valAddr);+ −
}+ −
valAddr &= ~3; // Clear thumb bit - code exports can have this set. No idea why some can have bit 1 set...+ −
// There really doesn't seem to be a way to figure out where code stops and const data starts, for core images. It generally looks to come after the export dir but it gives false positives+ −
if (valAddr > (TLinAddr)imageHeader)+ −
{+ −
TInt val = *(TInt*)valAddr;+ −
Printf(_L("Ordinal %d: 0x%08x (%d)\r\n"), i+1, val, val);+ −
}+ −
}+ −
}+ −
else+ −
{+ −
TLinAddr valAddr = exports[iOrdinal-1]; // Subtract one from ordinal as they're 1-based in DEF files+ −
TInt val = *(TInt*)(valAddr);+ −
+ −
if (change)+ −
{+ −
TInt oldVal = val;+ −
+ −
#ifdef FSHELL_MEMORY_ACCESS_SUPPORT+ −
LoadMemoryAccessL();+ −
TPckg<TInt> valPkg(iNewValue);+ −
LeaveIfErr(iMemAccess.WriteShadowMemory(valAddr, valPkg), _L("Couldn't write shadow for new value"));+ −
#else+ −
LeaveIfErr(KErrNotSupported, _L("Can't update patchdata for DLLs in core image without memoryaccess support"));+ −
#endif+ −
+ −
+ −
Printf(_L("Ordinal %d: old value was 0x%08x, new value is 0x%08x"), iOrdinal, oldVal, iNewValue);+ −
}+ −
else+ −
{+ −
Printf(_L("Ordinal %d: 0x%08x (%d)\r\n"), iOrdinal, val, val);+ −
}+ −
}+ −
}+ −
+ −