Don't mess around with EPOCROOT until actually entering raptor so we know what the original was
Put the original epocroot back on the front of the whatcomp output. This allows what output to be
either relative or absolute depending on what your epocroot is.
// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "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:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// e32tools/e32image/e32image.cpp
// Basic operations on E32Image files which are used by ROMBUILD.
// These are independent of the original file format from which the
// E32Image file was derived.
//
//
#include <time.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include "h_utl.h"
#if defined (__MSVCDOTNET__) || defined(__TOOLS2__)
#include <fstream>
#else //!__MSVCDOTNET__
#include <fstream.h>
#endif //__MSVCDOTNET__
#include <assert.h>
#ifndef __LINUX__
#include <io.h>
#endif
#include "h_ver.h"
// get E32ImageHeader class...
#define INCLUDE_E32IMAGEHEADER_IMPLEMENTATION
#define RETURN_FAILURE(_r) return (fprintf(stderr, "line %d\n", __LINE__),_r)
//#define E32IMAGEHEADER_TRACE(_t) printf _t
#include "e32image.h"
#include "byte_pair.h"
void DeflateCompress(char* bytes, TInt size, ostream& os);
void InflateUnCompress(unsigned char* source, int sourcesize, unsigned char* dest, int destsize);
void CompressPages(TUint8 * bytes, TInt size, ostream &os, CBytePair *aBPE);
int DecompressPages(TUint8 * bytes, istream& is, CBytePair *aBPE);
// needed by E32ImageHeaderV::ValidateHeader...
void Mem::Crc32(TUint32& aCrc, const TAny* aPtr, TInt aLength)
{
HMem::Crc32(aCrc, aPtr, aLength);
}
//
// E32 Image files
//
E32ImageFile::E32ImageFile()
: iData(NULL), iSize(0), iOrigHdr(NULL), iHdr(NULL), iFileName(NULL)
#ifndef __LINUX__
, iWideFileName(NULL)
#endif
, iError(0), iSource(EE32Image), iOrigHdrOffsetAdj(0), iExportBitMap(0)
{}
E32ImageFile::~E32ImageFile()
{
free(iData);
delete [] iFileName;
#ifndef __LINUX__
delete [] iWideFileName;
#endif
if (iHdr && iHdr != iOrigHdr)
delete iHdr;
free(iExportBitMap);
}
// dummy implementation
TBool E32ImageFile::Translate(const char*, TUint, TBool, TBool)
{
return EFalse;
}
Int64 timeToInt64(TInt aTime)
{
aTime-=(30*365*24*60*60+7*24*60*60); // seconds since midnight Jan 1st, 2000
Int64 daysTo2000AD=730497;
Int64 t=daysTo2000AD*24*3600+aTime; // seconds since 0000
t=t+3600; // BST (?)
return t*1000000; // milliseconds
}
class TE32ImageUids : public TCheckedUid
{
public:
TE32ImageUids(TUint32 aUid1, TUint32 aUid2, TUint32 aUid3) : TCheckedUid(TUidType(TUid::Uid(aUid1), TUid::Uid(aUid2), TUid::Uid(aUid3))) {}
TUint Check() { return TCheckedUid::Check(); }
};
void E32ImageFile::SetDefaultHeader()
{
iHdr = (E32ImageHeaderV*)iOrigHdr;
iHdr->iUid1 = 0;
iHdr->iUid2 = 0;
iHdr->iUid3 = 0;
iHdr->iHeaderCrc = 0;
iHdr->iSignature = 0x434f5045u;
iHdr->iModuleVersion = 0x00010000u;
iHdr->iCompressionType = 0;
iHdr->iToolsVersion = TVersion(MajorVersion, MinorVersion, Build);
Int64 time1(timeToInt64(time(0)));
iHdr->iTimeLo=(TUint32)time1;
iHdr->iTimeHi=(TUint32)(time1>>32);
iHdr->iFlags = KImageHdrFmt_V;
iHdr->iCodeSize = 0;
iHdr->iDataSize = 0;
iHdr->iHeapSizeMin = 0;
iHdr->iHeapSizeMax = 0;
iHdr->iStackSize = 0;
iHdr->iBssSize = 0;
iHdr->iEntryPoint = 0;
iHdr->iCodeBase = 0;
iHdr->iDataBase = 0;
iHdr->iDllRefTableCount = 0;
iHdr->iExportDirOffset = 0;
iHdr->iExportDirCount = 0;
iHdr->iTextSize = 0;
iHdr->iCodeOffset = 0;
iHdr->iDataOffset = 0;
iHdr->iImportOffset = 0;
iHdr->iCodeRelocOffset = 0;
iHdr->iDataRelocOffset = 0;
iHdr->iProcessPriority = (TUint16)EPriorityForeground;
iHdr->iUncompressedSize = 0;
iHdr->iS.iSecureId = 0;
iHdr->iS.iVendorId = 0;
iHdr->iExceptionDescriptor = 0;
iHdr->iSpare2 = 0;
iHdr->iExportDescSize = 0;
iHdr->iExportDescType = KImageHdr_ExpD_NoHoles;
iHdr->iExportDesc[0] = 0;
}
void E32ImageFile::SetCallEntryPoints(TInt aBool)
{
if (aBool)
iHdr->iFlags&=~KImageNoCallEntryPoint;
else
iHdr->iFlags|=KImageNoCallEntryPoint;
}
void E32ImageFile::SetFixedAddress(TInt aBool)
{
if (aBool)
iHdr->iFlags|=KImageFixedAddressExe;
else
iHdr->iFlags&=~KImageFixedAddressExe;
}
void E32ImageFile::SetPriority(TProcessPriority aPri)
{
iHdr->iProcessPriority = (TUint16)aPri;
}
void E32ImageFile::SetCapability(SCapabilitySet& aCapabilities)
{
iHdr->iS.iCaps = aCapabilities;
}
void E32ImageFile::SetFPU(unsigned int aFPU)
{
iHdr->iFlags &=~ KImageHWFloatMask;
if (aFPU == 1)
iHdr->iFlags |= KImageHWFloat_VFPv2;
}
void E32ImageFile::Adjust(TInt aSize, TBool aAllowShrink)
//
// Adjust the size of allocated data and fix the member data
//
{
TInt asize = ALIGN4(aSize);
if (asize == iSize)
return;
if (iSize == 0)
{
iSize = asize;
iData = (char*)malloc(iSize);
memset(iData, 0, iSize);
}
else if (aAllowShrink || asize > iSize)
{
TInt oldsize = iSize;
iSize = asize;
iData = (char*)realloc(iData, iSize);
if (iSize > oldsize)
memset(iData+oldsize, 0, iSize-oldsize);
}
if (!iData)
iSize = 0;
if (iHdr && iHdr == iOrigHdr)
iHdr = (E32ImageHeaderV*)iData;
iOrigHdr = (E32ImageHeader*)iData;
}
TInt E32ImageFile::ReadHeader(ifstream& is)
{
Adjust(sizeof(E32ImageHeader), EFalse);
is.read(iData, sizeof(E32ImageHeader));
TInt hdrsz = iOrigHdr->TotalSize();
if (hdrsz > 0x10000 || hdrsz <= 0)
return KErrCorrupt; // sanity check
if (hdrsz > (TInt)sizeof(E32ImageHeader))
{
Adjust(hdrsz, EFalse);
is.read(iData+sizeof(E32ImageHeader), hdrsz-sizeof(E32ImageHeader));
}
TUint32 uncompressedSize;
TInt r = iOrigHdr->ValidateHeader(iFileSize,uncompressedSize);
if (r != KErrNone)
{
fprintf(stderr, "Integrity check failed %d\n", r);
return r;
}
iHdr = (E32ImageHeaderV*)iOrigHdr;
return KErrNone;
}
void E32ImageFile::SetStackSize(TInt aSize)
{
iHdr->iStackSize=aSize;
}
void E32ImageFile::SetHeapSizeMin(TInt aSize)
{
iHdr->iHeapSizeMin=aSize;
}
void E32ImageFile::SetHeapSizeMax(TInt aSize)
{
iHdr->iHeapSizeMax=aSize;
}
TUint E32ImageFile::TextOffset()
//
// Return the offset of the text section
//
{
return 0;
}
TUint E32ImageFile::DataOffset()
//
// return the offset of the initialised data
//
{
return iHdr->iCodeSize;
}
TUint E32ImageFile::BssOffset()
//
// return the offset from the start of code where the bss is linked
//
{
return DataOffset()+iHdr->iDataSize;
}
TInt E32ImageFile::IsDll()
//
//
//
{
return iHdr->iFlags&KImageDll;
}
void E32ImageFile::RelocateSection(char* aPtr, char* aRelocs, TUint aCodeDelta, TUint aDataDelta, char* aImagePtr, TLinAddr** aIATRefs, TBool keepIAT)
//
// Relocates the section data at aPtr
//
{
TUint codeStart=iHdr->iCodeBase;
TUint codeFinish=codeStart+iHdr->iCodeSize;
TUint iatStart = aIATRefs ? codeStart+iHdr->iTextSize : 0;
TUint iatFinish = aIATRefs ? iatStart+NumberOfImports()*sizeof(TUint) : 0;
// Print(ELog,"IAT: %x->%x\n",iatStart,iatFinish);
char* relocs=aRelocs;
TUint page=0;
TInt size=0;
TInt i=((E32RelocSection *)relocs)->iNumberOfRelocs;
relocs+=sizeof(E32RelocSection);
while (i>0)
{
if (size>0)
{
TUint offset=*(TUint16 *)relocs;
relocs+=2;
if (offset!=0)
{ // its a reloc
TUint va=page+(offset&0x0fff);
TUint relocType=offset&0xf000;
TUint *dataptr=(TUint *)(aPtr+va);
assert((char *)dataptr < aRelocs);
TUint data=*dataptr;
// Print(ELog,"data %x\n",data);
if (relocType == KTextRelocType)
*dataptr=data+aCodeDelta; // points to text/rdata section
else if (relocType == KDataRelocType)
*dataptr=data+aDataDelta;
else
{
if (relocType != KInferredRelocType)
Print(EError,"Unrecognized relocation type %x\n",relocType);
if (data>=iatStart && data<iatFinish)
{
TUint iatNum = (data-iatStart)/sizeof(TLinAddr);
// If "keepIAT" is used then the importing instruction must import through the IAT entry,
// but otherwise we change the IAT entry to point to the bit of code doing the importing
// and do the real fix-up later on in TRomBuilderEntry::FixupImports.
// NB: We always want to do this for X86 or data exports dont work.
if (keepIAT || (iHdr->iCpuIdentifier & 0x1000) /*denotes X86*/)
*dataptr=data+aCodeDelta;
else
{
if ((TUint)aIATRefs[iatNum]>65535)
Print(EWarning, "Multiple relocations for IAT entry %d (0x%x, 0x%x)\n",
iatNum, aIATRefs[iatNum], dataptr);
else
aIATRefs[iatNum] = (TLinAddr*)(aImagePtr+va); // ROM image address of importing pointer
}
}
else if (data>=codeStart && data<codeFinish)
*dataptr=data+aCodeDelta; // points to text/rdata section
else
*dataptr=data+aDataDelta; // points to data section
}
--i;
}
size-=2;
}
else
{ // next page of relocs
page=*(TUint *)relocs;
relocs+=4;
size=*(TUint *)relocs;
relocs+=4;
size-=8;
}
}
}
void E32ImageFile::SetUids(TUid aUid1, TUid aUid2, TUid aUid3)
{
iHdr->iUid1=aUid1.iUid;
iHdr->iUid2=aUid2.iUid;
iHdr->iUid3=aUid3.iUid;
}
void E32ImageFile::SetSecureId(TUint32 aId)
{
((E32ImageHeaderV*)iHdr)->iS.iSecureId = aId;
}
void E32ImageFile::SetVendorId(TUint32 aId)
{
((E32ImageHeaderV*)iHdr)->iS.iVendorId = aId;
}
void E32ImageFile::UpdateHeaderCrc()
{
TE32ImageUids u(iHdr->iUid1, iHdr->iUid2, iHdr->iUid3);
iHdr->iUidChecksum = u.Check();
TInt hdrsz = iHdr->TotalSize();
TInt orighdrsz = iOrigHdr->TotalSize();
iHdr->iUncompressedSize = iSize - orighdrsz;
iHdr->iHeaderCrc = KImageCrcInitialiser;
TUint32 crc = 0;
HMem::Crc32(crc, iHdr, hdrsz);
iHdr->iHeaderCrc = crc;
}
TInt E32ImageFile::NumberOfImports()
//
// Return the number of imports made by this image
//
{
if (iHdr->iDllRefTableCount==0 || iHdr->iImportOffset==0)
return 0;
TUint impfmt = iHdr->ImportFormat();
const E32ImportSection* isection = (const E32ImportSection*)(iData + iOrigHdr->iImportOffset);
TInt d;
TInt nImports = 0;
const E32ImportBlock* b = (const E32ImportBlock*)(isection+1);
for (d=0; d<iHdr->iDllRefTableCount; d++)
{
nImports += b->iNumberOfImports;
b = b->NextBlock(impfmt);
}
if (impfmt==KImageImpFmt_PE || impfmt==KImageImpFmt_PE2)
{
TUint *imports=(TUint *)(iData + iOrigHdr->iCodeOffset + iHdr->iTextSize);
TInt i=0;
while (*imports++)
i++;
assert(i==nImports);
}
return nImports;
}
// Work out which exports are missing from the export directory
void E32ImageFile::CreateExportBitMap()
{
TInt nexp = iOrigHdr->iExportDirCount;
TInt memsz = (nexp + 7) >> 3;
iExportBitMap = (TUint8*)malloc(memsz);
memset(iExportBitMap, 0xff, memsz);
TUint* exports = (TUint*)(iData + iOrigHdr->iExportDirOffset);
TUint absoluteEntryPoint = iOrigHdr->iEntryPoint + iOrigHdr->iCodeBase;
TUint impfmt = iOrigHdr->ImportFormat();
TUint hdrfmt = iOrigHdr->HeaderFormat();
TUint absentVal = (impfmt == KImageImpFmt_ELF) ? absoluteEntryPoint : iOrigHdr->iEntryPoint;
TInt i;
iMissingExports = 0;
for (i=0; i<nexp; ++i)
{
if (exports[i] == absentVal)
{
iExportBitMap[i>>3] &= ~(1u << (i & 7));
++iMissingExports;
}
}
if (hdrfmt < KImageHdrFmt_V && iMissingExports)
{
fprintf(stderr, "Bad exports\n");
exit(999);
}
}
// Append an export description to the E32ImageHeader if necessary
void E32ImageFile::AddExportDescription()
{
if (iMissingExports == 0)
return; // nothing to do
TInt nexp = iOrigHdr->iExportDirCount;
TInt memsz = (nexp + 7) >> 3; // size of complete bitmap
TInt mbs = (memsz + 7) >> 3; // size of meta-bitmap
TInt nbytes = 0;
TInt i;
for (i=0; i<memsz; ++i)
if (iExportBitMap[i] != 0xff)
++nbytes; // number of groups of 8
TUint8 edt = KImageHdr_ExpD_FullBitmap;
TInt extra_space = memsz - 1;
if (mbs + nbytes < memsz)
{
edt = KImageHdr_ExpD_SparseBitmap8;
extra_space = mbs + nbytes - 1;
}
extra_space = (extra_space + sizeof(TUint) - 1) &~ (sizeof(TUint) - 1);
TInt hdrsz = sizeof(E32ImageHeaderV) + extra_space;
iHdr = (E32ImageHeaderV*)malloc(hdrsz);
memcpy(iHdr, iOrigHdr, sizeof(E32ImageHeaderV));
iHdr->iExportDescType = edt;
if (edt == KImageHdr_ExpD_FullBitmap)
{
iHdr->iExportDescSize = (TUint16)memsz;
memcpy(iHdr->iExportDesc, iExportBitMap, memsz);
}
else
{
iHdr->iExportDescSize = (TUint16)(mbs + nbytes);
memset(iHdr->iExportDesc, 0, extra_space + 1);
TUint8* mptr = iHdr->iExportDesc;
TUint8* gptr = mptr + mbs;
for (i=0; i<memsz; ++i)
{
if (iExportBitMap[i] != 0xff)
{
mptr[i>>3] |= (1u << (i&7));
*gptr++ = iExportBitMap[i];
}
}
}
iHdr->iCodeOffset += extra_space;
if (iHdr->iDataOffset)
iHdr->iDataOffset += extra_space;
if (iHdr->iCodeRelocOffset)
iHdr->iCodeRelocOffset += extra_space;
if (iHdr->iDataRelocOffset)
iHdr->iDataRelocOffset += extra_space;
if (iHdr->iImportOffset)
iHdr->iImportOffset += extra_space;
if (iHdr->iExportDirOffset)
iHdr->iExportDirOffset += extra_space;
}
// Check the export description is consistent with the export directory
TInt E32ImageFile::CheckExportDescription()
{
TUint hdrfmt = iOrigHdr->HeaderFormat();
if (hdrfmt < KImageHdrFmt_V && iMissingExports)
return KErrCorrupt;
if (iHdr->iExportDescType == KImageHdr_ExpD_NoHoles)
{
return iMissingExports ? KErrCorrupt : KErrNone;
}
TInt nexp = iOrigHdr->iExportDirCount;
TInt memsz = (nexp + 7) >> 3; // size of complete bitmap
TInt mbs = (memsz + 7) >> 3; // size of meta-bitmap
TInt eds = iHdr->iExportDescSize;
if (iHdr->iExportDescType == KImageHdr_ExpD_FullBitmap)
{
if (eds != memsz)
return KErrCorrupt;
if (memcmp(iHdr->iExportDesc, iExportBitMap, eds) == 0)
return KErrNone;
return KErrCorrupt;
}
if (iHdr->iExportDescType != KImageHdr_ExpD_SparseBitmap8)
return KErrNotSupported;
TInt nbytes = 0;
TInt i;
for (i=0; i<memsz; ++i)
if (iExportBitMap[i] != 0xff)
++nbytes; // number of groups of 8
TInt exp_extra = mbs + nbytes;
if (eds != exp_extra)
return KErrCorrupt;
const TUint8* mptr = iHdr->iExportDesc;
const TUint8* gptr = mptr + mbs;
for (i=0; i<memsz; ++i)
{
TUint mbit = mptr[i>>3] & (1u << (i&7));
if (iExportBitMap[i] != 0xff)
{
if (!mbit || *gptr++ != iExportBitMap[i])
return KErrCorrupt;
}
else if (mbit)
return KErrCorrupt;
}
return KErrNone;
}
TInt E32ImageFile::Validate()
{
TInt orighdrsz = iOrigHdr->TotalSize();
TInt r = iHdr->ValidateWholeImage(iData+orighdrsz,iSize-orighdrsz);
if(r!=KErrNone)
return r;
return r;
}
ostream& operator<<(ostream& os, const E32ImageFile& aImage)
//
// Output an E32ImageFile
//
{
CBytePair bpe(EFalse);
E32ImageHeaderV* h = aImage.iHdr;
TUint hdrfmt = h->HeaderFormat();
if (hdrfmt != KImageHdrFmt_V)
return os; // don't generate old binary formats
TInt hdrsz = h->TotalSize();
TInt orighdrsz = aImage.iOrigHdr->TotalSize();
os.write((const char*)aImage.iHdr, hdrsz);
TUint compression = h->CompressionType();
if (compression == KUidCompressionDeflate)
{
int srcsize = aImage.iSize - orighdrsz;
DeflateCompress(aImage.iData + orighdrsz, srcsize, os);
}
else if (compression == KUidCompressionBytePair)
{
// Compress and write out code part
int srcStart = orighdrsz;
CompressPages( (TUint8*)aImage.iData + srcStart, aImage.iOrigHdr->iCodeSize, os, &bpe);
// Compress and write out data part
srcStart += aImage.iOrigHdr->iCodeSize;
int srcLen = aImage.iSize - srcStart;
//Print(EWarning," Data part start:0x%08x, len:%d (0x%08x)\n", srcStart, aImage.iOrigHdr->iDataSize, aImage.iOrigHdr->iDataSize);
//CompressPages((TUint8*)aImage.iData + srcStart, aImage.iOrigHdr->iDataSize, os);
CompressPages((TUint8*)aImage.iData + srcStart, srcLen, os, &bpe);
}
else if (compression == KFormatNotCompressed)
{
int srcsize = aImage.iSize - orighdrsz;
os.write(aImage.iData + orighdrsz, srcsize); // image not to be compressed
}
return os;
}
ifstream& operator>>(ifstream& is, E32ImageFile& aImage)
//
// Input an E32ImageFile
//
{
CBytePair bpe(EFalse);
aImage.iError = aImage.ReadHeader(is);
if (aImage.iError != KErrNone)
return is;
E32ImageHeader* oh = aImage.iOrigHdr;
TInt orighdrsz = oh->TotalSize();
int remainder = aImage.iSize - orighdrsz;
TUint compression = oh->CompressionType();
if (compression == 0)
{
is.read(aImage.iData + orighdrsz, remainder);
}
else if (compression == KUidCompressionDeflate)
{ //Uncompress
aImage.iError = KErrNoMemory;
unsigned int uncompsize = ((E32ImageHeaderComp*)aImage.iOrigHdr)->iUncompressedSize;
aImage.Adjust(uncompsize + orighdrsz);
if (aImage.iData==NULL)
return is;
oh = aImage.iOrigHdr;
unsigned char* compressedData = new unsigned char[remainder];
if (compressedData==NULL)
return is;
is.read(reinterpret_cast<char *>(compressedData), remainder);
unsigned int destsize = uncompsize;
InflateUnCompress( compressedData, remainder, (unsigned char*)(aImage.iData + orighdrsz), destsize);
if (destsize != uncompsize)
Print(EWarning, "Inconsistent sizes discovered during uncompression.\n");
delete [] compressedData;
if ((TUint)orighdrsz > oh->iCodeOffset)
{
// need to adjust code offsets in original
aImage.iOrigHdrOffsetAdj = (TUint)orighdrsz - oh->iCodeOffset;
aImage.OffsetAdjust(oh->iCodeOffset);
aImage.OffsetAdjust(oh->iDataOffset);
aImage.OffsetAdjust(oh->iCodeRelocOffset);
aImage.OffsetAdjust(oh->iDataRelocOffset);
aImage.OffsetAdjust(oh->iImportOffset);
aImage.OffsetAdjust(oh->iExportDirOffset);
}
aImage.iError = KErrNone;
}
else if(compression == KUidCompressionBytePair)
{ // Uncompress
aImage.iError = KErrNoMemory;
unsigned int uncompsize = ((E32ImageHeaderComp*)aImage.iOrigHdr)->iUncompressedSize;
aImage.Adjust(uncompsize + orighdrsz);
if (aImage.iData==NULL)
return is;
oh = aImage.iOrigHdr;
// Read and decompress code part of the image
unsigned int uncompressedCodeSize = DecompressPages((TUint8 *) (aImage.iData + orighdrsz), is, &bpe);
// Read and decompress data part of the image
unsigned int uncompressedDataSize = DecompressPages((TUint8 *) (aImage.iData + orighdrsz + uncompressedCodeSize), is, &bpe);
if (uncompressedCodeSize + uncompressedDataSize != uncompsize)
Print(EWarning, "Inconsistent sizes discovered during uncompression.\n");
if ((TUint)orighdrsz > oh->iCodeOffset)
{
// need to adjust code offsets in original
aImage.iOrigHdrOffsetAdj = (TUint)orighdrsz - oh->iCodeOffset;
aImage.OffsetAdjust(oh->iCodeOffset);
aImage.OffsetAdjust(oh->iDataOffset);
aImage.OffsetAdjust(oh->iCodeRelocOffset);
aImage.OffsetAdjust(oh->iDataRelocOffset);
aImage.OffsetAdjust(oh->iImportOffset);
aImage.OffsetAdjust(oh->iExportDirOffset);
}
aImage.iError = KErrNone;
}
aImage.CreateExportBitMap();
return is;
}
TInt E32ImageFile::IsE32ImageFile(char *aFileName)
{
#ifdef __LINUX__
E32ImageFile f;
struct stat buf;
if (stat(aFileName, &buf) < 0)
{
return FALSE;
}
f.iFileSize = buf.st_size;
#else
_finddata_t fileinfo;
int ret=_findfirst((char *)aFileName,&fileinfo);
if (ret==-1)
return FALSE;
E32ImageFile f;
f.iFileSize = fileinfo.size;
#endif
ifstream ifile(aFileName, ios::in | ios::binary);
if(!ifile.is_open())
return FALSE;
TInt r = f.ReadHeader(ifile);
ifile.close();
return (r == KErrNone);
}
TInt E32ImageFile::IsValid()
{
return (iError == KErrNone);
}
TInt E32ImageFile::Open(const char* aFileName)
//
// Open an E32 Image file
//
{
#ifdef __LINUX__
struct stat buf;
if (stat(aFileName, &buf) < 0)
{
Print(EError,"Cannot open %s for input.\n",aFileName);
return 1;
}
iFileSize = buf.st_size;
#else
_finddata_t fileinfo;
int ret=_findfirst((char *)aFileName,&fileinfo);
if (ret==-1)
{
Print(EError,"Cannot open %s for input.\n",aFileName);
return 1;
}
iFileSize = fileinfo.size;
#endif
Adjust(iFileSize);
ifstream ifile((char *)aFileName, ios::in | ios::binary);
if(!ifile.is_open())
{
Print(EError,"Cannot open %s for input.\n",aFileName);
return 1;
}
ifile >> *this;
ifile.close();
if (iError != KErrNone)
return iError;
iFileName=strdup((char *)aFileName);
if (iFileName==NULL)
return KErrNoMemory;
return KErrNone;
}
#ifndef __LINUX__
TInt E32ImageFile::Open(const wchar_t* aFileName)
//
// Open an E32 Image file
//
{
_wfinddata_t fileinfo;
int ret=_wfindfirst(aFileName,&fileinfo);
if (ret==-1)
{
Print(EError,"Cannot open %ls for input.\n",aFileName);
return 1;
}
iFileSize = fileinfo.size;
Adjust(iFileSize);
FILE* file = _wfopen(aFileName, L"rb");
if(!file)
{
Print(EError,"Cannot open %ls for input.\n",aFileName);
return 1;
}
#ifdef __TOOLS2__
char *tmp; // Convert wide character name to char *, then open a file.
wcstombs(tmp,aFileName,100);
ifstream ifile(tmp, ios::in | ios::binary);
#else
ifstream ifile(fileno(file));
#endif
if(!ifile.is_open())
{
Print(EError,"Cannot open %ls for input,\n",aFileName);
return 1;
}
ifile >> *this;
ifile.close();
fclose(file);
if (iError != KErrNone)
return iError;
iWideFileName=wcsdup(aFileName);
if (iWideFileName==NULL)
return KErrNoMemory;
return KErrNone;
}
#endif
TUint E32ImageFile::VaOfOrdinal(TUint aOrdinal)
// return the offset of the exported symbol
{
TUint* exportdir = (TUint*)(iData + iOrigHdr->iExportDirOffset);
return exportdir[aOrdinal-KOrdinalBase];
}
// Determine the type of entry point in this module and set the flags
// in the E32Image header accordingly.
TInt E32ImageFile::DetermineEntryPointType()
{
TUint cpu = iHdr->CpuIdentifier();
if (cpu != ECpuArmV4 && cpu != ECpuArmV5)
return KErrNone; // if not ARM, leave EPT as 0
TUint epOffset = iHdr->iEntryPoint;
if (epOffset & 3)
return KErrNone; // if entry point not 4 byte aligned, must be old style
TUint fileOffset = epOffset + iHdr->iCodeOffset;
if (fileOffset+4 > (TUint)iSize)
return KErrCorrupt; // entry point is past the end of the file??
TInt ept = 0; // old style if first instruction not recognised
unsigned char* p = (unsigned char*)iData + fileOffset + 4;
TUint32 x = *--p;
x<<=8;
x|=*--p;
x<<=8;
x|=*--p;
x<<=8;
x|=*--p;
if ((x & 0xffffff00) == 0xe31f0000)
{
// starts with tst pc, #n - new entry point
ept = (x & 0xff) + 1;
}
if (ept>7)
return KErrNotSupported;
iHdr->iFlags |= (ept<<KImageEptShift);
return KErrNone;
}