diff -r 000000000000 -r 044383f39525 bintools/elftools/elftran/elf_tran.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bintools/elftools/elftran/elf_tran.cpp Tue Oct 27 16:36:35 2009 +0000 @@ -0,0 +1,301 @@ +/* +* Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "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: +* +*/ + + +#include +#include +#include +#include "elftran.h" +#include +#include +#include "elffile.h" +#include +#include + +extern TUid gUid1, gUid2, gUid3; +extern int gSetUid1, gSetUid2, gSetUid3; + +int gAlignConstSection=FALSE; +TUint gConstSectionAddressMask=0; + +E32ImageFile* E32ImageFile::New() + { + return new E32ImageFile_ELF; + } + +E32ImageFile_ELF::E32ImageFile_ELF() + { + } + +E32ImageFile_ELF::~E32ImageFile_ELF() + { + } + +TInt E32ImageFile_ELF::DoCodeHeader(ELFFile &aElfFile) +// +// Calculate the code parts of the ELFFile +// + { + + TInt size=ALIGN4(aElfFile.GetCodeSize()); + iHdr->iCodeSize = iHdr->iTextSize = size; + // make it the offset from the beginning of the file..... + if(iHdr->iExportDirCount==0) + iHdr->iExportDirOffset = 0; + else + iHdr->iExportDirOffset = aElfFile.GetExportTableOffset() + iHdr->iCodeOffset; + + return size; + } + +TInt E32ImageFile_ELF::DoDataHeader(ELFFile &aElfFile, TUint aDataBase) + { + + if (aDataBase==0 && aElfFile.iDataSegmentHdr) + aDataBase=aElfFile.iDataSegmentHdr->p_vaddr; + TInt size=0; + + iHdr->iDataBase=aDataBase; + + if (aElfFile.HasInitialisedData()) + { + size=ALIGN4(aElfFile.GetDataSize()); + iHdr->iDataOffset = iHdr->iCodeOffset + iHdr->iCodeSize; + iHdr->iDataSize = size; + } + if (aElfFile.HasBssData()) + { + iHdr->iBssSize = ALIGN4(aElfFile.GetBssSize()); + } + return size; + } + +TInt E32ImageFile_ELF::CopyCode(char *p, ELFFile &aElfFile) +// +// Copies the files code sections to p +// returns the number of bytes copied or KErrGeneral +// + { + TInt size=aElfFile.GetCodeSize(); + memcpy(p, (char *)aElfFile.GetCode(), size); + p+=ALIGN4(size); + return iHdr->iCodeSize = size; + } + +TInt E32ImageFile_ELF::CopyData(char *p, ELFFile &aElfFile) + { + TInt size=aElfFile.GetDataSize(); + if (size) memcpy(p, (char *)aElfFile.GetData(), size); + return size; + } + +TInt E32ImageFile_ELF::Translate(const char* aFileName, TUint aDataBase, TBool aAllowDllData, \ + TBool aSymLkupEnabled) +// +// Translate a ELF format file to a E32Image file +// + +{ + iSource = EElfFile; + ELFFile elffile; + if (!elffile.Init((const TText * const)aFileName)) return KErrGeneral; + + iFileName = strdup(aFileName); + + Adjust(ALIGN4(sizeof(E32ImageHeaderV))); // fixed for now because holes not supported + SetDefaultHeader(); + iHdr->iDllRefTableCount = elffile.NumberOfImportDlls(); + iHdr->iExportDirCount = elffile.NumberOfExports(); + iHdr->iCodeBase = elffile.iLinkedBase; + + if(aSymLkupEnabled) + { + if( !SetUpLookupTable(elffile) ) + return KErrGeneral; + } + + + TInt size = ALIGN4(sizeof(E32ImageHeaderV)); // fixed for now because holes not supported + iHdr->iCodeOffset = size; + TInt pos = size; + size+=DoCodeHeader(elffile); + + size += DoSymbolLookupHeader(elffile, size - pos); + + TInt nimports=elffile.NumberOfImports(); + TInt importSectionSize; + char *newImportSection=CreateImportSection(elffile, importSectionSize); + + TInt t=DoDataHeader(elffile, aDataBase); + if (t>0) + { + iHdr->iDataOffset = size; + size += t; + } + if (importSectionSize!=0) + { + iHdr->iImportOffset=size; + size+=ALIGN4(importSectionSize); + } + + char *newCodeRelocs=NULL; + char *newDataRelocs=NULL; + TInt codeRelocSize=0, dataRelocSize=0; + TInt nCodeRelocs=elffile.NumberOfCodeRelocs(); + TInt nDataRelocs=elffile.NumberOfDataRelocs(); + if (nCodeRelocs + nDataRelocs) + { + Elf32_Rel **codeRelocs=new Elf32_Rel * [nCodeRelocs]; + Elf32_Rel **dataRelocs=new Elf32_Rel * [nDataRelocs]; + if (!elffile.GetRelocs(codeRelocs, dataRelocs)) return KErrGeneral; + + FixRelocs(elffile, codeRelocs, dataRelocs); + if (elffile.iCodeSegmentHdr) + newCodeRelocs=CreateRelocs(elffile, codeRelocs, nCodeRelocs, codeRelocSize, elffile.iCodeSegmentHdr->p_vaddr); + if (elffile.iDataSegmentHdr) + newDataRelocs=CreateRelocs(elffile, dataRelocs, nDataRelocs, dataRelocSize, elffile.iDataSegmentHdr->p_vaddr); + if (codeRelocSize) + { + iHdr->iCodeRelocOffset = size; + size += codeRelocSize; + } + if (dataRelocSize) + { + iHdr->iDataRelocOffset = size; + size += dataRelocSize; + } + delete [] codeRelocs; + delete [] dataRelocs; + } + + Adjust(size); + t=CopyCode(iData + pos, elffile); + if (t<0) + return KErrGeneral; + pos += t; + t = CopyExportSymInfo(iData+pos, elffile); + if (t<0) + return KErrGeneral; + pos += t; + + pos += CopyData(iData + pos, elffile); + if (nimports) + { + memcpy(iData + pos, newImportSection, importSectionSize); + pos += ALIGN4(importSectionSize); + } + if (codeRelocSize) + { + memcpy(iData + pos, newCodeRelocs, codeRelocSize); + pos += codeRelocSize; + } + if (dataRelocSize) + { + memcpy(iData + pos, newDataRelocs, dataRelocSize); + pos += dataRelocSize; + } + + // locate the entry point + TUint entryPointOffset=elffile.GetEntryPointOffset(); + + // Arrange a header for this E32 Image + iHdr->iCpuIdentifier = (TUint16)ECpuArmV4; + // Import format is ELF-derived + iHdr->iFlags |= KImageImpFmt_ELF; + // ABI is ARM EABI + iHdr->iFlags |= KImageABI_EABI; + if (ImageIsDll(elffile)) + { + iHdr->iFlags |= KImageDll; + if (iHdr->iDataSize && !aAllowDllData) + return Print(EError, "Dll '%s' has initialised data.\n", iFileName); + if (iHdr->iBssSize && !aAllowDllData) + return Print(EError, "Dll '%s' has uninitialised data.\n", iFileName); + } + iHdr->iHeapSizeMin = elffile.iHeapCommittedSize; + iHdr->iHeapSizeMax = elffile.iHeapReservedSize; + iHdr->iStackSize = elffile.iStackCommittedSize; + iHdr->iEntryPoint = entryPointOffset; + TInt r = DetermineEntryPointType(); + if (r == KErrCorrupt) + return Print(EError, "File '%s': Bad Entry Point.\n", iFileName); + else if (r == KErrNotSupported) + return Print(EError, "File '%s': Bad Entry Point Type.\n", iFileName); + + SetUpExceptions(elffile); + + delete [] newImportSection; + delete [] newCodeRelocs; + delete [] newDataRelocs; + + return KErrNone; + } + +TBool E32ImageFile_ELF::Translate(ELFFile &aElfFile) + { + // VT fix for warning + // fix warning in Linux + return Translate((const char*)aElfFile.iFileName, 0, EFalse); + } + +TBool E32ImageFile_ELF::ImageIsDll(ELFFile& aElfFile) + { + return aElfFile.ImageIsDll(); + } + +void E32ImageFile_ELF::SetUpExceptions(ELFFile &aElfFile) + { + aElfFile.GetExceptionIndexInfo(iHdr->iExceptionDescriptor); + } + +void E32ImageFile_ELF::SetSymNameLookup(TInt aSymNameLkupEnabled) + { + if(aSymNameLkupEnabled) + iHdr->iFlags |= KImageNmdExpData; + else + iHdr->iFlags &= ~KImageNmdExpData; + } +TBool E32ImageFile_ELF::IsNamedLookupEnabled() +{ + return (iHdr->iFlags & KImageNmdExpData); +} + +TBool E32ImageFile_ELF::SetUpLookupTable(ELFFile &aElfFile) +// Symbol lookup by name is enabled. Create the symbol table with names +// and their values. +{ + if(!aElfFile.SetUpLookupTable() ) + return FALSE; + SetSymNameLookup(TRUE); + return TRUE; +} + +// Build the infrastructure for symbol lookup via name +TInt E32ImageFile_ELF::DoSymbolLookupHeader(ELFFile &aElfFile, TInt aBaseOffset) + { + if(!IsNamedLookupEnabled()) + return 0; + + aElfFile.SetLookupTblBase(aBaseOffset); + return aElfFile.GetLookupTblSize(); + } +TUint E32ImageFile_ELF::CopyExportSymInfo(char *p, ELFFile &aElfFile) + { + iHdr->iCodeSize += aElfFile.GetLookupTblSize(); + iHdr->iTextSize = iHdr->iCodeSize ; + return aElfFile.GetSymLookupSection(p); + }