bintools/petools/pefile/pe_imp.cpp
changeset 600 6d08f4a05d93
equal deleted inserted replaced
599:fa7a3cc6effd 600:6d08f4a05d93
       
     1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <stdlib.h>
       
    17 #include <string.h>
       
    18 #include <e32std.h>
       
    19 #include <e32std_private.h>
       
    20 #include "h_utl.h"
       
    21 #include "pe_file.h"
       
    22 
       
    23 TInt E32ImageFile_PE::CopyImportAddrTable(char *aPtr, PEFile &aPeFile)
       
    24 //
       
    25 // Copy the import address table entries
       
    26 //
       
    27 	{
       
    28 
       
    29 	TUint *ptr=(TUint *)aPtr;
       
    30 	char *importsection=aPeFile.iSectionData[KImportSection];
       
    31 	TUint *src=(TUint *)importsection;
       
    32 	while (*src)
       
    33 		{
       
    34 		TUint vaoffset=src[4];
       
    35 		if (!gLittleEndian) ByteSwap(vaoffset);
       
    36 		TUint offset=vaoffset-aPeFile.iSectionHeader[KImportSection]->VirtualAddress; // find the offset into the section of import addr table
       
    37 		vaoffset=src[3];
       
    38 		if (!gLittleEndian) ByteSwap(vaoffset);
       
    39 		TUint exportername=vaoffset-aPeFile.iSectionHeader[KImportSection]->VirtualAddress;
       
    40 		TUint *p=(TUint *)(importsection+offset);
       
    41 		while (*p)
       
    42 			{
       
    43 			if ((*p&0x80000000)==0)
       
    44 				{
       
    45 				Print(EError, "%s exporting symbol by name\n", importsection+exportername);
       
    46 				return KErrGeneral;
       
    47 				}
       
    48 			*ptr++=(*p++)&0x7fffffff; // mask out the high bit (- indicates export by ordinal)
       
    49 			}
       
    50 		src+=5;
       
    51 		}
       
    52 	*ptr++=0;
       
    53 	return KErrNone;
       
    54 	}
       
    55 
       
    56 extern char* gX86imp;
       
    57 extern int gX86num_imports;
       
    58 extern int gX86num_imp_dlls;
       
    59 extern int gX86imp_size;
       
    60 int* gX86imp_relocs=NULL;
       
    61 
       
    62 TInt CrunchImportSection(TAny* aSection, TInt aNumImpDlls, TInt aNumImports)
       
    63 	{
       
    64 	// Remove lists of ordinals from import section
       
    65 	TInt* d = (TInt*)aSection;
       
    66 	TInt orig_size = *d;
       
    67 	TInt offset_correction = aNumImports*sizeof(TUint);
       
    68 	*d -= offset_correction;	// reduce total section size
       
    69 	TInt *dd = d+1;
       
    70 	TInt *ss = d+1;
       
    71 
       
    72 	TInt i;
       
    73 	for (i=0; i<aNumImpDlls; ++i)
       
    74 		{
       
    75 		*dd++ = *ss++ - offset_correction;	// copy name offset and reduce it appropriately
       
    76 		TInt nimp = *ss++;					// number of imports from this DLL
       
    77 		*dd++ = nimp;						// copy it
       
    78 		ss += nimp;							// skip the ordinals in the original list
       
    79 		}
       
    80 	TInt used_size = (ss - d) * sizeof(TInt);
       
    81 	memcpy(dd, ss, orig_size - used_size);	// copy name strings
       
    82 
       
    83 	return *d;	// return new total section size
       
    84 	}
       
    85 
       
    86 char *E32ImageFile_PE::CreateImportSection(const PEFile &aPeFile, TInt &aSize)
       
    87 //
       
    88 // Create a new format import section
       
    89 //
       
    90 	{
       
    91 
       
    92 	int total_imports = 0;
       
    93 	if (gX86imp)
       
    94 		{
       
    95 		TUint *rdata=(TUint*)aPeFile.iSectionData[KConstSection];
       
    96 		TInt bytecount=gX86imp_size;
       
    97 		char* section=new char[bytecount];
       
    98 		memcpy(section,gX86imp,bytecount);
       
    99 		int i;
       
   100 		int j=0;
       
   101 		int* s=(int*)section;
       
   102 		s++;
       
   103 		gX86imp_relocs=new int[gX86num_imports+gX86num_imp_dlls];
       
   104 		for (i=0; i<gX86num_imp_dlls; ++i)
       
   105 			{
       
   106 			++s;
       
   107 			int n=*s++;
       
   108 			total_imports += n;
       
   109 			while (n--)
       
   110 				{
       
   111 				int rdata_int_offset=*s>>2;
       
   112 				*s=rdata[rdata_int_offset]&0x7fffffffu;	// rdata offset to ordinal
       
   113 				gX86imp_relocs[rdata_int_offset]=j<<2;
       
   114 				++j;
       
   115 				++s;
       
   116 				}
       
   117 			}
       
   118 		*(TInt*)section = bytecount;
       
   119 		aSize = CrunchImportSection(section, gX86num_imp_dlls, total_imports);
       
   120 		return section;
       
   121 		}
       
   122 	PIMAGE_SECTION_HEADER aHeader=aPeFile.iSectionHeader[KImportSection];
       
   123 	TUint *aSrc=(TUint *)aPeFile.iSectionData[KImportSection];
       
   124 
       
   125 	TInt nimportdlls=aPeFile.NumberOfImportDlls();
       
   126 	if (nimportdlls==0)
       
   127 		{
       
   128 		aSize=0;
       
   129 		return NULL;
       
   130 		}
       
   131 	E32ImportBlock *block=new E32ImportBlock [nimportdlls];
       
   132 	char **name=new char* [nimportdlls];
       
   133 	TUint **import=new TUint* [nimportdlls];
       
   134 
       
   135 	TInt bytecount=sizeof(E32ImportSection)+sizeof(E32ImportBlock)*nimportdlls;
       
   136 	TUint *src=aSrc;
       
   137 	TInt i;
       
   138 	for (i=0; i<nimportdlls; i++)
       
   139 		{
       
   140 		TUint vaoffset=src[4];
       
   141 		if (!gLittleEndian) ByteSwap(vaoffset);
       
   142 		TUint offset=vaoffset-aHeader->VirtualAddress; // find the offset into the section of import addr table
       
   143 		TUint *p=aSrc+offset/4;
       
   144 		block[i].iNumberOfImports=0;
       
   145 		while (*p++)
       
   146 			block[i].iNumberOfImports++;
       
   147 		total_imports += block[i].iNumberOfImports;
       
   148 		import[i]=new TUint [block[i].iNumberOfImports];
       
   149 		TInt j;
       
   150 		p=aSrc+offset/4;
       
   151 		for (j=0; j<block[i].iNumberOfImports; j++)
       
   152 			{
       
   153 			import[i][j]=(*p++)&0x7fffffffu;
       
   154 			bytecount+=4;
       
   155 			}
       
   156 		// name
       
   157 		vaoffset=src[3];
       
   158 		if (!gLittleEndian) ByteSwap(vaoffset);
       
   159 		offset=vaoffset-aHeader->VirtualAddress;
       
   160 		name[i]=((char *)aSrc)+offset;
       
   161 		bytecount+=strlen(name[i])+1;
       
   162 		src+=5;
       
   163 		}
       
   164 
       
   165 	bytecount=ALIGN4(bytecount);
       
   166 	char *section=new char [bytecount];
       
   167 	char *s=section+sizeof(E32ImportSection);
       
   168 	for (i=0; i<nimportdlls; i++)
       
   169 		{
       
   170 		memcpy(s, (char *)&block[i], sizeof(E32ImportBlock));
       
   171 		s+=sizeof(E32ImportBlock);
       
   172 		memcpy(s, (char *)import[i], block[i].iNumberOfImports*4);
       
   173 		s+=block[i].iNumberOfImports*4;
       
   174 		}
       
   175 	char *t=section+sizeof(E32ImportSection);
       
   176 	for (i=0; i<nimportdlls; i++)
       
   177 		{
       
   178 		((E32ImportBlock *)t)->iOffsetOfDllName=s-section;
       
   179 		strcpy(s, name[i]);
       
   180 		s+=strlen(name[i])+1;
       
   181 		t += ((E32ImportBlock *)t)->iNumberOfImports * sizeof(TUint) + sizeof(E32ImportBlock);
       
   182 		}
       
   183 	while ((s-section)<bytecount)
       
   184 		*s++=0;
       
   185 
       
   186 	// free mem
       
   187 	for (i=0; i<nimportdlls; i++)
       
   188 		delete import[i];
       
   189 	delete block;
       
   190 	delete import;
       
   191 	delete name;
       
   192 
       
   193 	*(TInt*)section = bytecount;
       
   194 	aSize = CrunchImportSection(section, nimportdlls, total_imports);
       
   195 	return section;
       
   196 	}
       
   197 
       
   198 TUint E32ImageFile_PE::FixImportThunk(PEFile &aPeFile, TUint va)
       
   199 //
       
   200 // Fix an access to the import address table
       
   201 //
       
   202 	{
       
   203 
       
   204 	TUint *imports=(TUint *)aPeFile.iSectionData[KImportSection];
       
   205 	TUint n=0;
       
   206 	TUint importoffset=imports[4];
       
   207 	if (!gLittleEndian) ByteSwap(importoffset);
       
   208 	TUint iat=importoffset-aPeFile.iSectionHeader[KImportSection]->VirtualAddress;
       
   209 
       
   210 	while (iat<va)
       
   211 		{
       
   212 		if (*((TUint *)(aPeFile.iSectionData[KImportSection]+iat))==0)
       
   213 			{
       
   214 			imports+=5;
       
   215 			importoffset=imports[4];
       
   216 			if (!gLittleEndian) ByteSwap(importoffset);
       
   217 			iat=importoffset-aPeFile.iSectionHeader[KImportSection]->VirtualAddress;
       
   218 			}
       
   219 		else
       
   220 			{
       
   221 			n++;
       
   222 			iat+=4;
       
   223 			}
       
   224 		}
       
   225 
       
   226 	// Flag errors brought about by a corrupt input binary
       
   227 	if (iat>va)
       
   228 		{
       
   229 		Print(EError, "%s is corrupt - problem processing import address table.\n", this->iFileName);
       
   230 		return (TUint)KErrGeneral;
       
   231 		}
       
   232 		
       
   233 	return iHdr->iTextSize+n*sizeof(TUint);
       
   234 	}
       
   235