toolsandutils/e32tools/elf2e32/source/elffilesupplied.cpp
changeset 0 83f4b4db085c
child 1 d4b442d23379
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toolsandutils/e32tools/elf2e32/source/elffilesupplied.cpp	Tue Feb 02 01:39:43 2010 +0200
@@ -0,0 +1,655 @@
+// Copyright (c) 2004-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:
+//
+
+#include "elffilesupplied.h"
+#include "pl_elfexecutable.h"
+#include "errorhandler.h"
+#include "pl_dso_handler.h"
+#include "deffile.h"
+#include "pl_elfexports.h"
+#include "pl_dllsymbol.h"
+#include "elf2e32.h"
+#include "staticlibsymbols.h"
+
+#include <algorithm>
+#include <iostream>
+#include<hash_set>
+
+using namespace std;
+
+/**
+Constructor for class ElfFileSupplied to initialize members and create instance of class DSOHandler
+@param aParameterListInterface - Instance of class ParameterListInterface
+@internalComponent
+@released
+*/
+ElfFileSupplied::ElfFileSupplied(ParameterListInterface* aParameterListInterface) : UseCaseBase(aParameterListInterface) ,
+	iNumAbsentExports(-1),iExportBitMap(NULL),iE32ImageFile(NULL), iElfExecutable(NULL),  \
+	iExportDescSize(0), iExportDescType(0)
+{
+	iElfIfc = new DSOHandler(aParameterListInterface);
+}
+
+/**
+Destructor for class ElfFileSupplied to release allocated memory
+@internalComponent
+@released
+*/
+ElfFileSupplied::~ElfFileSupplied()
+{
+	iSymList.clear();
+	delete iElfIfc;
+	delete [] iExportBitMap;
+}
+
+/**
+Execute Function for the Elf File Supplied use case
+@return 0 on success
+@internalComponent
+@released
+*/
+int ElfFileSupplied::Execute() 
+{
+	ReadElfFile();
+	iElfIfc->ProcessElfFile();
+	try
+	{
+		ProcessExports();
+	}
+	catch(SymbolMissingFromElfError& aSme)
+	{
+		/* Only DEF file would be generated if symbols found in
+		 * DEF file are missing from the ELF file.
+		 */
+		WriteDefFile();
+		throw aSme;
+	}
+	GenerateOutput();
+	return 0;
+}
+
+/**
+Function to read ELF File
+@internalComponent
+@released
+*/
+void ElfFileSupplied::ReadElfFile() 
+{
+	char * aElfFileName = UseCaseBase::InputElfFileName();
+	
+	iElfIfc->ReadElfFile(aElfFileName);
+	iElfExecutable = iElfIfc->ElfExecutableP();
+}
+
+/**
+Function to process exports
+@internalComponent
+@released
+*/
+void ElfFileSupplied::ProcessExports() 
+{
+	ValidateExports(NULL);
+	CreateExports();
+}
+
+/**
+Function to write DEF File
+@internalComponent
+@released
+*/
+void ElfFileSupplied::WriteDefFile() 
+{
+	char * aDEFFileName = UseCaseBase::DefOutput();
+	DefFile deffile;
+
+	deffile.WriteDefFile(aDEFFileName, &iSymList);
+}
+
+/**
+Function to create exports
+@internalComponent
+@released
+*/
+void ElfFileSupplied::CreateExports()
+{
+	if (iElfExecutable->iExports || GetNamedSymLookup())
+	{
+		CreateExportTable();	
+		CreateExportBitMap();
+	}
+}
+
+/**
+Function to validate exports
+@param aDefExports - List of export symbols from Def file and/or sysdef.
+@internalComponent
+@released
+*/
+void ElfFileSupplied::ValidateExports(SymbolList *aDefExports)
+{
+	/**
+	 * Symbols from DEF file (DEF_Symbols) => Valid_DEF + Absent
+	 * Symbols from ELF file (ELF_Symbols) => Existing  + NEW
+	 * 1. if the set {Valid_DEF - ELF_Symbols} is non-empty then, symbols are missing
+	 *			from Elf and it is an error if the mode is UNFROZEN
+	 * 2. if the intersection set {Absent,ELF_Symbols} is non-empty, absent symbols
+	 *			are exported from Elf..warn for this
+	 * 3. if the set {ELF_Symbols - Valid_DEF} is non-empty, these are the NEW symbols
+	 * 4. if there are symbols marked absent in DEF file but exported in ELF,
+	 *		add them into the new list retaining the ordinal number as of the
+	 *		absent symbol(using PtrELFExportNameCompareUpdateOrdinal).
+	 **/
+
+	PLUINT32 aMaxOrdinal = 0;
+	int len = strlen("_ZTI");
+	
+	typedef SymbolList::iterator Iterator;
+
+	Iterator aPos, aEnd;
+
+	//SymbolList *aDefExports, aDefValidExports, aDefAbsentExports, aElfExports;
+	SymbolList aDefValidExports, aDefAbsentExports, aElfExports;
+
+	//aDefExports = iDefIfc->GetSymbolEntryList();
+	if (aDefExports)
+		{
+		aPos = aDefExports->begin();
+		aEnd = aDefExports->end();
+
+		while(aPos != aEnd)
+			{
+				if( (*aPos)->Absent() ){
+					aDefAbsentExports.insert(aDefAbsentExports.end(), *aPos);
+				}
+				else {
+					aDefValidExports.insert(aDefValidExports.end(), *aPos);
+				}
+											
+				if( aMaxOrdinal < (*aPos)->OrdNum() ){
+					aMaxOrdinal = (*aPos)->OrdNum();
+				}
+				aPos++;
+			}
+		}
+
+	iSymList = aDefValidExports;
+
+	if (iElfIfc->ElfExecutableP()->iExports)
+		iElfIfc->GetElfExportSymbolList( aElfExports );
+	else if (!aDefExports)
+		return;
+	
+	// REVISIT - return back if elfexports and defexports is NULL 
+
+	aDefValidExports.sort(ElfExports::PtrELFExportNameCompare());
+	aElfExports.sort(ElfExports::PtrELFExportNameCompare());
+
+	aDefAbsentExports.sort(ElfExports::PtrELFExportNameCompare());
+
+	//Check for Case 1... {Valid_DEF - ELF_Symbols}
+	{
+		SymbolList aResult(aDefValidExports.size());
+		Iterator aResultPos = aResult.begin();
+
+		Iterator aMissingListEnd = set_difference(aDefValidExports.begin(), aDefValidExports.end(), \
+			aElfExports.begin(), aElfExports.end(), aResultPos, ElfExports::PtrELFExportNameCompareUpdateAttributes());
+
+		std::list<String> aMissingSymNameList;
+		while (aResultPos != aMissingListEnd) {
+			// {Valid_DEF - ELF_Symbols} is non empty
+			(*aResultPos)->SetSymbolStatus(Missing); // Set the symbol Status as Missing
+			aMissingSymNameList.push_back((*aResultPos)->SymbolName());
+			aResultPos++;
+			//throw error
+		}
+		if( aMissingSymNameList.size() ) {
+			if (!Unfrozen())
+				throw SymbolMissingFromElfError(SYMBOLMISSINGFROMELFERROR, aMissingSymNameList, UseCaseBase::InputElfFileName());
+			else
+				cout << "Elf2e32: Warning: " << aMissingSymNameList.size() << " Frozen Export(s) missing from the ELF file" << endl;
+		}
+	}
+
+	//Check for Case 2... intersection set {Absent,ELF_Symbols}
+	{
+		if(aDefAbsentExports.size())
+		{
+			SymbolList aResult(aDefAbsentExports.size());
+			Iterator aResultPos = aResult.begin();
+
+			Iterator aAbsentListEnd = set_intersection(aDefAbsentExports.begin(), aDefAbsentExports.end(), \
+				aElfExports.begin(), aElfExports.end(), aResultPos, ElfExports::PtrELFExportNameCompareUpdateAttributes());
+			
+			while( aResultPos != aAbsentListEnd ) 
+			{
+				// intersection set {Absent,ELF_Symbols} is non-empty
+
+				iSymList.insert(iSymList.end(), *aResultPos);
+				cout << "Elf2e32: Warning: Symbol " << (*aResultPos)->SymbolName() << " absent in the DEF file, but present in the ELF file" << endl;
+				aResultPos++;
+			}
+		}
+	}
+
+	//Do 3
+	{
+		SymbolList aResult(aElfExports.size());
+		Iterator aResultPos = aResult.begin();
+
+		Iterator aNewListEnd = set_difference(aElfExports.begin(), aElfExports.end(), \
+			aDefValidExports.begin(), aDefValidExports.end(), aResultPos, ElfExports::PtrELFExportNameCompare());
+
+		bool aIgnoreNonCallable = GetIgnoreNonCallable();
+		bool aIsCustomDll = IsCustomDllTarget();
+		bool aExcludeUnwantedExports = ExcludeUnwantedExports();
+
+		while( aResultPos != aNewListEnd ) 
+		{
+			
+			if( !(*aResultPos)->Absent() ) 
+			{
+				/* For a custom dll and for option "--excludeunwantedexports", the new exports should be filtered,
+				 * so that only the exports from the frozen DEF file are considered.
+				 */
+				if ((aIsCustomDll || aExcludeUnwantedExports) && UnWantedSymbolp((*aResultPos)->SymbolName()))
+				{
+					iElfExecutable->iExports->ExportsFilteredP(true);
+					iElfExecutable->iExports->iFilteredExports.insert(iElfExecutable->iExports->iFilteredExports.end(),(DllSymbol *)(*aResultPos));
+					aResultPos++;
+					continue;
+				}
+				if (aIgnoreNonCallable)
+				{
+					// Ignore the non callable exports
+					if ((!strncmp("_ZTI", (*aResultPos)->SymbolName(), len)) ||
+					    (!strncmp("_ZTV", (*aResultPos)->SymbolName(), len)))
+					{
+						iElfExecutable->iExports->ExportsFilteredP(true);
+						iElfExecutable->iExports->iFilteredExports.insert(iElfExecutable->iExports->iFilteredExports.end(),(DllSymbol *)(*aResultPos));
+						aResultPos++;
+						continue;
+					}
+				}
+				(*aResultPos)->SetOrdinal( ++aMaxOrdinal );
+				(*aResultPos)->SetSymbolStatus(New); // Set the symbol Status as NEW
+				iSymList.insert(iSymList.end(), *aResultPos);			
+				if(WarnForNewExports())
+					cout << "Elf2e32: Warning: New Symbol " << (*aResultPos)->SymbolName() << " found, export(s) not yet Frozen" << endl;
+			}
+			aResultPos++;
+		}
+	}
+
+	//Do 4
+	{
+		if(aDefAbsentExports.size())
+		{
+			SymbolList aResult(aDefAbsentExports.size());
+			Iterator aResultPos = aResult.begin();
+
+			Iterator aAbsentListEnd = set_difference(aDefAbsentExports.begin(), aDefAbsentExports.end(), \
+				aElfExports.begin(), aElfExports.end(), aResultPos, ElfExports::PtrELFExportNameCompareUpdateAttributes());
+			
+			DllSymbol *aSymbol;
+			bool aAbsent = true;
+			while( aResultPos != aAbsentListEnd  ) {
+				//aElfExports.insert(aElfExports.end(), *aResultPos);
+				aSymbol = new DllSymbol( *aResultPos, SymbolTypeCode, aAbsent);
+				iElfExecutable->iExports->Add(iElfExecutable->iSOName, aSymbol);
+				//aElfExports.insert(aElfExports.end(), (Symbol*)aSymbol);
+				iSymList.insert(iSymList.end(), (Symbol*)aSymbol);
+				aResultPos++;
+			}
+			aElfExports.sort(ElfExports::PtrELFExportOrdinalCompare());
+			iSymList.sort(ElfExports::PtrELFExportOrdinalCompare());
+		}
+	}
+
+	if(iElfExecutable->iExports && iElfExecutable->iExports->ExportsFilteredP() ) {
+		iElfExecutable->iExports->FilterExports();
+	}
+
+	aElfExports.clear();
+	aDefAbsentExports.clear();
+	aDefValidExports.clear();
+
+} 
+
+/**
+Function to generate output which is E32 Image file, DEF File and DSO file, if
+exports are available.
+@internalComponent
+@released
+*/
+void ElfFileSupplied::GenerateOutput() 
+{
+	if (iElfExecutable->iExports)
+	{
+		Elf2E32::ValidateDSOGeneration(iParameterListInterface, ETargetTypeNotSet);
+		WriteDefFile();
+		WriteDSOFile();
+	}
+	Elf2E32::ValidateE32ImageGeneration(iParameterListInterface, ETargetTypeNotSet);
+	WriteE32();
+}
+
+/**
+Function to write DSO file.
+@internalComponent
+@released
+*/
+void ElfFileSupplied::WriteDSOFile()
+{
+	char * aLinkAs = UseCaseBase::LinkAsDLLName();
+	char * aDSOName = UseCaseBase::DSOOutput();
+	char * aDSOFileName = UseCaseBase::FileName(aDSOName);
+
+	iElfIfc->WriteElfFile( aDSOName, aDSOFileName, aLinkAs, iSymList );
+}
+
+/**
+Function to write E32 Image file.
+@internalComponent
+@released
+*/
+void ElfFileSupplied::WriteE32()
+{
+
+	const char * aE32FileName = OutputE32FileName();
+
+	iE32ImageFile = new E32ImageFile(aE32FileName, iElfExecutable, this);
+
+	try
+	{
+		iE32ImageFile->GenerateE32Image();
+
+		if (iE32ImageFile->WriteImage(aE32FileName))
+		{
+			//GetELF2E32()->AddFileCleanup(aE32FileName);
+			delete iE32ImageFile;
+		}
+	}
+	catch (...)
+	{
+		delete iE32ImageFile;
+		throw;
+	}
+}
+
+/**
+Function to check image is Dll or not.
+@return True if image is Dll, otherwise false.
+@internalComponent
+@released
+*/
+bool ElfFileSupplied::ImageIsDll() 
+{ 
+	return (iElfExecutable->LookupStaticSymbol("_E32Dll") != NULL);
+}
+
+/**
+Function to allocate E32 Image header.
+@return pointer to E32ImageHeaderV
+@internalComponent
+@released
+*/
+E32ImageHeaderV * ElfFileSupplied::AllocateE32ImageHeader()
+{
+	if (iNumAbsentExports == 0)
+	{
+		return new E32ImageHeaderV;
+	}
+
+	int nexp = GetNumExports();
+	size_t memsz = (nexp + 7) >> 3;	// size of complete bitmap
+	size_t mbs = (memsz + 7) >> 3;	// size of meta-bitmap
+	size_t nbytes = 0;
+	PLUINT32 i;
+	for (i=0; i<memsz; ++i)
+		if (iExportBitMap[i] != 0xff)
+			++nbytes;				// number of groups of 8
+	PLUINT8 edt = KImageHdr_ExpD_FullBitmap;
+	PLUINT32 extra_space = memsz - 1;
+	if (mbs + nbytes < memsz)
+	{
+		edt = KImageHdr_ExpD_SparseBitmap8;
+		extra_space = mbs + nbytes - 1;
+	}
+	extra_space = (extra_space + sizeof(PLUINT32) - 1) &~ (sizeof(PLUINT32) - 1);
+	size_t aExtendedHeaderSize = sizeof(E32ImageHeaderV) + extra_space;
+	iE32ImageFile->SetExtendedE32ImageHeaderSize(aExtendedHeaderSize);
+	E32ImageHeaderV * aHdr = (E32ImageHeaderV *)new PLUINT8[aExtendedHeaderSize];
+
+	iExportDescType = edt;
+	if (edt == KImageHdr_ExpD_FullBitmap)
+	{
+		iExportDescSize = (PLUINT16)memsz;
+		memcpy(aHdr->iExportDesc, iExportBitMap, memsz);
+	}
+	else
+	{
+		iExportDescSize = (PLUINT16) (mbs + nbytes);
+		memset(aHdr->iExportDesc, 0, extra_space + 1);
+		PLUINT8* mptr = aHdr->iExportDesc;
+		PLUINT8* gptr = mptr + mbs;
+		for (i=0; i<memsz; ++i)
+		{
+			if (iExportBitMap[i] != 0xff)
+			{
+				mptr[i>>3] |= (1u << (i&7));
+				*gptr++ = iExportBitMap[i];
+			}
+		}
+	}
+	return aHdr;
+}
+
+/**
+Function to create export table
+@internalComponent
+@released
+*/
+void ElfFileSupplied::CreateExportTable()
+{
+	ElfExports::ExportList aList;
+	
+	if(iElfExecutable->iExports)
+		aList = iElfExecutable->GetExportsInOrdinalOrder();
+
+	iExportTable.CreateExportTable(iElfExecutable, aList);
+}
+
+/**
+Function to create export bitmap
+@internalComponent
+@released
+*/
+void ElfFileSupplied::CreateExportBitMap()
+{
+	int nexp = GetNumExports();
+	size_t memsz = (nexp + 7) >> 3;
+	iExportBitMap = new PLUINT8[memsz];
+	memset(iExportBitMap, 0xff, memsz);
+	// skip header
+	PLUINT32 * exports = ((PLUINT32 *)GetExportTable()) + 1;
+	PLUINT32 absentVal = iElfExecutable->EntryPointOffset() + iElfExecutable->GetROBase();
+	iNumAbsentExports = 0;
+	for (int i=0; i<nexp; ++i)
+	{
+		if (exports[i] == absentVal)
+		{
+			iExportBitMap[i>>3] &= ~(1u << (i & 7));
+			++iNumAbsentExports;
+		}
+	}
+}
+
+/**
+Function to get number of exports
+@return Number of exports in export table
+@internalComponent
+@released
+*/
+size_t ElfFileSupplied::GetNumExports()
+{
+	return iExportTable.GetNumExports();
+}
+
+/**
+Function to check export table is required.
+@return True for E32 image if allocation requires space for export table.
+@internalComponent
+@released
+*/
+bool ElfFileSupplied::AllocateExportTableP()
+{
+	return iExportTable.AllocateP();
+}
+
+/**
+Function to get export table
+@return Pointer to export table
+@internalComponent
+@released
+*/
+char * ElfFileSupplied::GetExportTable()
+{
+	return (char *)iExportTable.GetExportTable();
+}
+
+/**
+Function to get export table size
+@return size of export table
+@internalComponent
+@released
+*/
+size_t ElfFileSupplied::GetExportTableSize()
+{
+	return iExportTable.GetExportTableSize();
+}
+
+/**
+Function to get export table Virtual address
+@return the export table VA
+@internalComponent
+@released
+*/
+size_t ElfFileSupplied::GetExportTableAddress()
+{
+	return iExportTable.iExportTableAddress;
+}
+
+/**
+Function to get export offset
+@return size of export offset
+@internalComponent
+@released
+*/
+size_t ElfFileSupplied::GetExportOffset()
+{
+	return iE32ImageFile->GetExportOffset();
+}
+
+/**
+Function to get symbol type based on the encoded names.
+@return CODE or DATA
+@internalComponent
+@released
+*/
+SymbolType ElfFileSupplied::SymbolTypeF(char * aName)
+{
+	size_t prefixLength = strlen("_ZTV");
+	bool classImpedimenta = false;
+	classImpedimenta = !strncmp(aName, "_ZTV", prefixLength) ||
+					   !strncmp(aName, "_ZTI", prefixLength) ||
+					   !strncmp(aName, "_ZTS", prefixLength) ;
+
+	return classImpedimenta? SymbolTypeData : SymbolTypeCode;
+}
+
+/**
+Function to get export description size
+@return export description size
+@internalComponent
+@released
+*/
+PLUINT16 ElfFileSupplied::GetExportDescSize()
+{
+	return iExportDescSize;
+}
+
+/**
+Function to get export description type
+@return export description type
+@internalComponent
+@released
+*/
+PLUINT8 ElfFileSupplied::GetExportDescType()
+{
+	return iExportDescType;
+}
+
+/**
+Function to indicate if the new exports are to be reported as warnings.
+@return export description type
+@internalComponent
+@released
+*/
+bool ElfFileSupplied::WarnForNewExports()
+{
+	return true;
+}
+
+/**
+To check if the two strings are equal
+@internalComponent
+@released
+*/
+struct eqstr
+{
+  bool operator()(const char* s1, const char* s2) const
+  {
+    return strcmp(s1, s2) == 0;
+  }
+};
+
+/**
+Function to provide a predicate which checks whether a symbol name is unwanted:
+@return 1 if new symbols are present in the static library list else return 0
+@param aSymbol symbols to be checked if part of static lib
+@internalComponent
+@released
+*/ 
+int ElfFileSupplied::UnWantedSymbolp(const char * aSymbol)
+{
+  static hash_set<const char*, hash<const char*>, eqstr> aSymbolSet;
+  int symbollistsize=sizeof(Unwantedruntimesymbols)/sizeof(Unwantedruntimesymbols[0]);
+  static bool FLAG=false;
+  while(!FLAG)
+  {
+	for(int i=0;i<symbollistsize;i++)
+	{
+		aSymbolSet.insert(Unwantedruntimesymbols[i]);
+	}
+	FLAG=true;
+  }
+  hash_set<const char*, hash<const char*>, eqstr>::const_iterator it
+    = aSymbolSet.find(aSymbol);
+  if(it != aSymbolSet.end())
+	return 1;
+  else 
+	return 0;
+}
+