bintools/petools/pefile/pe_imp.cpp
changeset 607 378360dbbdba
parent 600 6d08f4a05d93
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bintools/petools/pefile/pe_imp.cpp	Wed Jun 30 11:35:58 2010 +0800
@@ -0,0 +1,235 @@
+// 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:
+//
+
+#include <stdlib.h>
+#include <string.h>
+#include <e32std.h>
+#include <e32std_private.h>
+#include "h_utl.h"
+#include "pe_file.h"
+
+TInt E32ImageFile_PE::CopyImportAddrTable(char *aPtr, PEFile &aPeFile)
+//
+// Copy the import address table entries
+//
+	{
+
+	TUint *ptr=(TUint *)aPtr;
+	char *importsection=aPeFile.iSectionData[KImportSection];
+	TUint *src=(TUint *)importsection;
+	while (*src)
+		{
+		TUint vaoffset=src[4];
+		if (!gLittleEndian) ByteSwap(vaoffset);
+		TUint offset=vaoffset-aPeFile.iSectionHeader[KImportSection]->VirtualAddress; // find the offset into the section of import addr table
+		vaoffset=src[3];
+		if (!gLittleEndian) ByteSwap(vaoffset);
+		TUint exportername=vaoffset-aPeFile.iSectionHeader[KImportSection]->VirtualAddress;
+		TUint *p=(TUint *)(importsection+offset);
+		while (*p)
+			{
+			if ((*p&0x80000000)==0)
+				{
+				Print(EError, "%s exporting symbol by name\n", importsection+exportername);
+				return KErrGeneral;
+				}
+			*ptr++=(*p++)&0x7fffffff; // mask out the high bit (- indicates export by ordinal)
+			}
+		src+=5;
+		}
+	*ptr++=0;
+	return KErrNone;
+	}
+
+extern char* gX86imp;
+extern int gX86num_imports;
+extern int gX86num_imp_dlls;
+extern int gX86imp_size;
+int* gX86imp_relocs=NULL;
+
+TInt CrunchImportSection(TAny* aSection, TInt aNumImpDlls, TInt aNumImports)
+	{
+	// Remove lists of ordinals from import section
+	TInt* d = (TInt*)aSection;
+	TInt orig_size = *d;
+	TInt offset_correction = aNumImports*sizeof(TUint);
+	*d -= offset_correction;	// reduce total section size
+	TInt *dd = d+1;
+	TInt *ss = d+1;
+
+	TInt i;
+	for (i=0; i<aNumImpDlls; ++i)
+		{
+		*dd++ = *ss++ - offset_correction;	// copy name offset and reduce it appropriately
+		TInt nimp = *ss++;					// number of imports from this DLL
+		*dd++ = nimp;						// copy it
+		ss += nimp;							// skip the ordinals in the original list
+		}
+	TInt used_size = (ss - d) * sizeof(TInt);
+	memcpy(dd, ss, orig_size - used_size);	// copy name strings
+
+	return *d;	// return new total section size
+	}
+
+char *E32ImageFile_PE::CreateImportSection(const PEFile &aPeFile, TInt &aSize)
+//
+// Create a new format import section
+//
+	{
+
+	int total_imports = 0;
+	if (gX86imp)
+		{
+		TUint *rdata=(TUint*)aPeFile.iSectionData[KConstSection];
+		TInt bytecount=gX86imp_size;
+		char* section=new char[bytecount];
+		memcpy(section,gX86imp,bytecount);
+		int i;
+		int j=0;
+		int* s=(int*)section;
+		s++;
+		gX86imp_relocs=new int[gX86num_imports+gX86num_imp_dlls];
+		for (i=0; i<gX86num_imp_dlls; ++i)
+			{
+			++s;
+			int n=*s++;
+			total_imports += n;
+			while (n--)
+				{
+				int rdata_int_offset=*s>>2;
+				*s=rdata[rdata_int_offset]&0x7fffffffu;	// rdata offset to ordinal
+				gX86imp_relocs[rdata_int_offset]=j<<2;
+				++j;
+				++s;
+				}
+			}
+		*(TInt*)section = bytecount;
+		aSize = CrunchImportSection(section, gX86num_imp_dlls, total_imports);
+		return section;
+		}
+	PIMAGE_SECTION_HEADER aHeader=aPeFile.iSectionHeader[KImportSection];
+	TUint *aSrc=(TUint *)aPeFile.iSectionData[KImportSection];
+
+	TInt nimportdlls=aPeFile.NumberOfImportDlls();
+	if (nimportdlls==0)
+		{
+		aSize=0;
+		return NULL;
+		}
+	E32ImportBlock *block=new E32ImportBlock [nimportdlls];
+	char **name=new char* [nimportdlls];
+	TUint **import=new TUint* [nimportdlls];
+
+	TInt bytecount=sizeof(E32ImportSection)+sizeof(E32ImportBlock)*nimportdlls;
+	TUint *src=aSrc;
+	TInt i;
+	for (i=0; i<nimportdlls; i++)
+		{
+		TUint vaoffset=src[4];
+		if (!gLittleEndian) ByteSwap(vaoffset);
+		TUint offset=vaoffset-aHeader->VirtualAddress; // find the offset into the section of import addr table
+		TUint *p=aSrc+offset/4;
+		block[i].iNumberOfImports=0;
+		while (*p++)
+			block[i].iNumberOfImports++;
+		total_imports += block[i].iNumberOfImports;
+		import[i]=new TUint [block[i].iNumberOfImports];
+		TInt j;
+		p=aSrc+offset/4;
+		for (j=0; j<block[i].iNumberOfImports; j++)
+			{
+			import[i][j]=(*p++)&0x7fffffffu;
+			bytecount+=4;
+			}
+		// name
+		vaoffset=src[3];
+		if (!gLittleEndian) ByteSwap(vaoffset);
+		offset=vaoffset-aHeader->VirtualAddress;
+		name[i]=((char *)aSrc)+offset;
+		bytecount+=strlen(name[i])+1;
+		src+=5;
+		}
+
+	bytecount=ALIGN4(bytecount);
+	char *section=new char [bytecount];
+	char *s=section+sizeof(E32ImportSection);
+	for (i=0; i<nimportdlls; i++)
+		{
+		memcpy(s, (char *)&block[i], sizeof(E32ImportBlock));
+		s+=sizeof(E32ImportBlock);
+		memcpy(s, (char *)import[i], block[i].iNumberOfImports*4);
+		s+=block[i].iNumberOfImports*4;
+		}
+	char *t=section+sizeof(E32ImportSection);
+	for (i=0; i<nimportdlls; i++)
+		{
+		((E32ImportBlock *)t)->iOffsetOfDllName=s-section;
+		strcpy(s, name[i]);
+		s+=strlen(name[i])+1;
+		t += ((E32ImportBlock *)t)->iNumberOfImports * sizeof(TUint) + sizeof(E32ImportBlock);
+		}
+	while ((s-section)<bytecount)
+		*s++=0;
+
+	// free mem
+	for (i=0; i<nimportdlls; i++)
+		delete import[i];
+	delete block;
+	delete import;
+	delete name;
+
+	*(TInt*)section = bytecount;
+	aSize = CrunchImportSection(section, nimportdlls, total_imports);
+	return section;
+	}
+
+TUint E32ImageFile_PE::FixImportThunk(PEFile &aPeFile, TUint va)
+//
+// Fix an access to the import address table
+//
+	{
+
+	TUint *imports=(TUint *)aPeFile.iSectionData[KImportSection];
+	TUint n=0;
+	TUint importoffset=imports[4];
+	if (!gLittleEndian) ByteSwap(importoffset);
+	TUint iat=importoffset-aPeFile.iSectionHeader[KImportSection]->VirtualAddress;
+
+	while (iat<va)
+		{
+		if (*((TUint *)(aPeFile.iSectionData[KImportSection]+iat))==0)
+			{
+			imports+=5;
+			importoffset=imports[4];
+			if (!gLittleEndian) ByteSwap(importoffset);
+			iat=importoffset-aPeFile.iSectionHeader[KImportSection]->VirtualAddress;
+			}
+		else
+			{
+			n++;
+			iat+=4;
+			}
+		}
+
+	// Flag errors brought about by a corrupt input binary
+	if (iat>va)
+		{
+		Print(EError, "%s is corrupt - problem processing import address table.\n", this->iFileName);
+		return (TUint)KErrGeneral;
+		}
+		
+	return iHdr->iTextSize+n*sizeof(TUint);
+	}
+