bintools/elftools/elftran/elf_tran.cpp
author raptorbot <raptorbot@systemstesthead.symbian.intra>
Fri, 18 Dec 2009 19:57:42 +0000
branchwip
changeset 117 ecf683438dc6
parent 0 044383f39525
child 590 360bd6b35136
permissions -rw-r--r--
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) 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);
	}