bintools/elftools/elftran/elf_tran.cpp
changeset 0 044383f39525
child 590 360bd6b35136
--- /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 <time.h>
+#include <malloc.h>
+#include <string.h>
+#include "elftran.h"
+#include <e32std.h>
+#include <elfdefs.h>
+#include "elffile.h"
+#include <h_ver.h>
+#include <h_utl.h>
+
+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);
+	}