bintools/petools/pefile/pe_reloc.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 "pe_file.h"
       
    21 #include "h_utl.h"
       
    22 #include <stdio.h>
       
    23 
       
    24 extern char* gX86imp;
       
    25 extern int gX86num_imp_dlls;
       
    26 extern int gX86imp_size;
       
    27 extern int gX86num_imports;
       
    28 extern int* gX86imp_relocs;
       
    29 
       
    30 TInt sizeOfCodeRelocs(TUint *relocs, TUint *relocsection, TInt nrelocs)
       
    31 	{
       
    32 
       
    33 	TInt bytecount=0;
       
    34 	TInt page=-1;
       
    35 	TInt i;
       
    36 	for (i=0; i<nrelocs; i++)
       
    37 		{
       
    38 		if ((TInt)relocsection[i]==KTextSection || (TInt)relocsection[i]==KConstSection || (TInt)relocsection[i]==KCrtSection)
       
    39 			{
       
    40 			TInt p=relocs[i]&0xfffff000;
       
    41 			if (page!=p)
       
    42 				{
       
    43 				if (bytecount%4!=0)
       
    44 					bytecount+=2;
       
    45 				bytecount+=8; // page, block size
       
    46 				page=p;
       
    47 				}
       
    48 			bytecount+=2;
       
    49 			}
       
    50 		}
       
    51 	if (bytecount%4!=0)
       
    52 		bytecount+=2;
       
    53 	return bytecount;
       
    54 	}
       
    55 
       
    56 TInt sizeOfDataRelocs(TUint *relocs, TUint *relocsection, TInt nrelocs)
       
    57 	{
       
    58 
       
    59 	TInt bytecount=0;
       
    60 	TInt page=-1;
       
    61 	TInt i;
       
    62 	for (i=0; i<nrelocs; i++)
       
    63 		{
       
    64 		if ((TInt)relocsection[i]==KDataSection)
       
    65 			{
       
    66 			TInt p=relocs[i]&0xfffff000;
       
    67 			if (page!=p)
       
    68 				{
       
    69 				if (bytecount%4!=0)
       
    70 					bytecount+=2;
       
    71 				bytecount+=8; // page, block size
       
    72 				page=p;
       
    73 				}
       
    74 			bytecount+=2;
       
    75 			}
       
    76 		}
       
    77 	if (bytecount%4!=0)
       
    78 		bytecount+=2;
       
    79 	return bytecount;
       
    80 	}
       
    81 
       
    82 void reorderRelocs(TUint aReloc[], TUint aRelocSection[], TInt aNumberOfRelocs)
       
    83 //
       
    84 // sort the relocations in section order
       
    85 //
       
    86 	{
       
    87 	TUint *temp=new TUint [aNumberOfRelocs];
       
    88 	TUint *tempsection=new TUint [aNumberOfRelocs];
       
    89 	TInt idx=0;
       
    90 	TUint section=0;
       
    91 	while (idx<aNumberOfRelocs)
       
    92 		{
       
    93 		for (TInt i=0; i<aNumberOfRelocs; i++)
       
    94 			{
       
    95 			if (aRelocSection[i]==section)
       
    96 				{
       
    97 				temp[idx]=aReloc[i];
       
    98 				tempsection[idx]=aRelocSection[i];
       
    99 				idx++;
       
   100 				}
       
   101 			}
       
   102 		section++;
       
   103 		}
       
   104 	memcpy((char *)aReloc, (char *)temp, aNumberOfRelocs*sizeof(TUint));
       
   105 	memcpy((char *)aRelocSection, (char *)tempsection, aNumberOfRelocs*sizeof(TUint));
       
   106 	delete [] temp;
       
   107 	delete [] tempsection;
       
   108 	}
       
   109 
       
   110 char *E32ImageFile_PE::CreateCodeRelocs(TUint *relocs, TUint *relocsection, TInt nrelocs, TInt &aSize)
       
   111 	{
       
   112 
       
   113 	TInt bytecount=sizeOfCodeRelocs(relocs, relocsection, nrelocs);
       
   114 	aSize=0;
       
   115 	if (bytecount==0)
       
   116 		return NULL;
       
   117 	aSize=bytecount+sizeof(E32RelocSection);
       
   118 
       
   119 	char *section=new char [bytecount+sizeof(E32RelocSection)];
       
   120 	char *data=section+sizeof(E32RelocSection);
       
   121 	char *startofblock=data;
       
   122 
       
   123 	TInt ncoderelocs=0;
       
   124 	TInt page=-1;
       
   125 	TInt pagesize=8;
       
   126 	TInt i;
       
   127 	for (i=0; i<nrelocs; i++)
       
   128 		{
       
   129 		if ((TInt)relocsection[i]==KTextSection || (TInt)relocsection[i]==KConstSection || (TInt)relocsection[i]==KCrtSection)
       
   130 			{
       
   131 			TInt p=relocs[i]&0xfffff000;
       
   132 			if (page!=p)
       
   133 				{
       
   134 				if (pagesize%4!=0)
       
   135 					{
       
   136 					*(TUint16 *)data=0;
       
   137 					data+=2;
       
   138 					pagesize+=2;
       
   139 					}
       
   140 				*(TUint *)startofblock=page;
       
   141 				*(TUint *)(startofblock+4)=pagesize;
       
   142 				pagesize=8;
       
   143 				page=p;
       
   144 				startofblock=data;
       
   145 				data+=8;
       
   146 				}
       
   147 			*(TUint16 *)data=(TUint16)((relocs[i]&0xfff)|0x3000);
       
   148 			data+=2;
       
   149 			pagesize+=2;
       
   150 			ncoderelocs++;
       
   151 			}
       
   152 		}
       
   153 	if (pagesize%4!=0)
       
   154 		{
       
   155 		*(TUint16 *)data=0;
       
   156 		data+=2;
       
   157 		pagesize+=2;
       
   158 		}
       
   159 	*(TUint *)startofblock=page;
       
   160 	*(TUint *)(startofblock+4)=pagesize;
       
   161 	((E32RelocSection *)section)->iNumberOfRelocs=ncoderelocs;
       
   162 	((E32RelocSection *)section)->iSize=bytecount;
       
   163 	return section;
       
   164 	}
       
   165 
       
   166 char *E32ImageFile_PE::CreateDataRelocs(TUint *relocs, TUint *relocsection, TInt nrelocs, TInt &aSize)
       
   167 	{
       
   168 
       
   169 	TInt bytecount=sizeOfDataRelocs(relocs, relocsection, nrelocs);
       
   170 	aSize=0;
       
   171 	if (bytecount==0)
       
   172 		return NULL;
       
   173 	aSize=bytecount+sizeof(E32RelocSection);
       
   174 
       
   175 	char *section=new char [bytecount+sizeof(E32RelocSection)];
       
   176 	char *data=section+sizeof(E32RelocSection);
       
   177 	char *startofblock=data;
       
   178 
       
   179 	TInt ndatarelocs=0;
       
   180 	TInt page=-1;
       
   181 	TInt pagesize=8;
       
   182 	TInt i;
       
   183 	for (i=0; i<nrelocs; i++)
       
   184 		{
       
   185 		if ((TInt)relocsection[i]==KDataSection)
       
   186 			{
       
   187 			TInt p=relocs[i]&0xfffff000;
       
   188 			if (page!=p)
       
   189 				{
       
   190 				if (pagesize%4!=0)
       
   191 					{
       
   192 					*(TUint16 *)data=0;
       
   193 					data+=2;
       
   194 					pagesize+=2;
       
   195 					}
       
   196 				*(TUint *)startofblock=page;
       
   197 				*(TUint *)(startofblock+4)=pagesize;
       
   198 				pagesize=8;
       
   199 				page=p;
       
   200 				startofblock=data;
       
   201 				data+=8;
       
   202 				}
       
   203 			*(TUint16 *)data=(TUint16)((relocs[i]&0xfff)|0x3000);
       
   204 			data+=2;
       
   205 			pagesize+=2;
       
   206 			ndatarelocs++;
       
   207 			}
       
   208 		}
       
   209 	if (pagesize%4!=0)
       
   210 		{
       
   211 		*(TUint16 *)data=0;
       
   212 		data+=2;
       
   213 		pagesize+=2;
       
   214 		}
       
   215 	*(TUint *)startofblock=page;
       
   216 	*(TUint *)(startofblock+4)=pagesize;
       
   217 
       
   218 	((E32RelocSection *)section)->iNumberOfRelocs=ndatarelocs;
       
   219 	((E32RelocSection *)section)->iSize=bytecount;
       
   220 	return section;
       
   221 	}
       
   222 
       
   223 void checkreloc(PEFile &aPeFile, TUint va, TUint reloc)
       
   224 	{
       
   225 
       
   226 	// Allow the section find routine to use heuristics to resolve addresses
       
   227 	// which have been offset by the compiler
       
   228 	TInt s = aPeFile.FindSectionByVa(va, 1);
       
   229 	switch(s)
       
   230 		{
       
   231 		case KTextSection:
       
   232 		case KConstSection:
       
   233 		case KDataSection:
       
   234 		case KCrtSection:
       
   235 		case KBssSection:
       
   236 		case KImportSection:
       
   237 			return;
       
   238 		default:
       
   239 			break;
       
   240 		}
       
   241 	Print(EAlways, "bad relocation:  [%08x] = %08x\n", reloc, va);
       
   242 	}
       
   243 
       
   244 void E32ImageFile_PE::FixRelocs(PEFile &aPeFile, TUint *relocation, TUint *relocsection, TInt aNumberOfRelocs)
       
   245 	{
       
   246 
       
   247 	TUint *data;
       
   248 	TInt i;
       
   249 #if 0
       
   250 	Print(EAlways, "Linked base %08x\n", aPeFile.iLinkedBase);
       
   251 	for (i=0; i<KNumberOfSections; i++)
       
   252 		{
       
   253 		if (!aPeFile.iSectionHeader[i])
       
   254 			continue;
       
   255 		TUint start = aPeFile.iSectionHeader[i]->VirtualAddress;
       
   256 		TUint finish = start + aPeFile.iSectionHeader[i]->Misc.VirtualSize;
       
   257 		Print(EAlways, "Section %d %08x-%08x\n", i, start, finish);
       
   258 		}
       
   259 #endif
       
   260 	for (i=0; i<aNumberOfRelocs; i++)
       
   261 		{
       
   262 		switch (relocsection[i])
       
   263 			{
       
   264 		case KTextSection:
       
   265 			relocation[i]-=aPeFile.iSectionHeader[KTextSection]->VirtualAddress;
       
   266 			data=(TUint *)(aPeFile.iSectionData[KTextSection]+relocation[i]);
       
   267 			if (!gLittleEndian) ByteSwap(*data);
       
   268 			checkreloc(aPeFile, *data, relocation[i]+aPeFile.iSectionHeader[KTextSection]->VirtualAddress);
       
   269 			*data=FixAddress(aPeFile, *data);
       
   270 			if (!gLittleEndian) ByteSwap(*data);
       
   271 			break;
       
   272 		case KConstSection:
       
   273 			relocation[i]-=aPeFile.iSectionHeader[KConstSection]->VirtualAddress;
       
   274 			data=(TUint *)(aPeFile.iSectionData[KConstSection]+relocation[i]);
       
   275 			if (!gLittleEndian) ByteSwap(*data);
       
   276 			checkreloc(aPeFile, *data, relocation[i]+aPeFile.iSectionHeader[KConstSection]->VirtualAddress);
       
   277 			relocation[i]+=ConstOffset();
       
   278 			*data=FixAddress(aPeFile, *data);
       
   279 			if (!gLittleEndian) ByteSwap(*data);
       
   280 			break;
       
   281 		case KCrtSection:
       
   282 			relocation[i]-=aPeFile.iSectionHeader[KCrtSection]->VirtualAddress;
       
   283 			data=(TUint *)(aPeFile.iSectionData[KCrtSection]+relocation[i]);
       
   284 			if (!gLittleEndian) ByteSwap(*data);
       
   285 			checkreloc(aPeFile, *data, relocation[i]+aPeFile.iSectionHeader[KCrtSection]->VirtualAddress);
       
   286 			relocation[i]+=iCrtOffset;
       
   287 			*data=FixAddress(aPeFile, *data);
       
   288 			if (!gLittleEndian) ByteSwap(*data);
       
   289 			break;
       
   290 		case KDataSection:
       
   291 			relocation[i]-=aPeFile.iSectionHeader[KDataSection]->VirtualAddress;
       
   292 			data=(TUint *)(aPeFile.iSectionData[KDataSection]+relocation[i]);
       
   293 			if (!gLittleEndian) ByteSwap(*data);
       
   294 			checkreloc(aPeFile, *data, relocation[i]+aPeFile.iSectionHeader[KDataSection]->VirtualAddress);
       
   295 			*data=FixAddress(aPeFile, *data);
       
   296 			if (!gLittleEndian) ByteSwap(*data);
       
   297 			break;
       
   298 		default:
       
   299 			Print(EWarning, "Relocation in invalid section.\n");
       
   300 			break;
       
   301 			}
       
   302 		}
       
   303 	reorderRelocs(relocation, relocsection, aNumberOfRelocs);
       
   304 	}
       
   305 
       
   306 TUint E32ImageFile_PE::FixAddress(PEFile &aPeFile, TUint va)
       
   307 //
       
   308 // Fix the given virtual address for the new headers
       
   309 //
       
   310 	{
       
   311 
       
   312 	// Allow the section find routine to use heuristics to resolve addresses
       
   313 	// which have been offset by the compiler
       
   314 	TInt section=aPeFile.FindSectionByVa(va, 1);
       
   315 	switch(section)
       
   316 		{
       
   317 		case KTextSection:
       
   318 			va-=aPeFile.iLinkedBase;
       
   319 			va-=aPeFile.iSectionHeader[KTextSection]->VirtualAddress;
       
   320 			va+=iHdr->iCodeBase;
       
   321 			break;
       
   322 		case KConstSection:
       
   323 			va-=aPeFile.iLinkedBase;
       
   324 			va-=aPeFile.iSectionHeader[KConstSection]->VirtualAddress;
       
   325 			if (gX86imp)
       
   326 				{
       
   327 				TUint old_iat_size=(gX86num_imports+gX86num_imp_dlls)<<2;
       
   328 				if (va<old_iat_size)
       
   329 					{
       
   330 					TInt offset=iHdr->iTextSize;
       
   331 //					fprintf(stderr,"IAT OFF %x ",va);
       
   332 					va=gX86imp_relocs[va>>2]+iHdr->iCodeBase+offset;
       
   333 //					fprintf(stderr,"-> %x\n",va);
       
   334 					break;
       
   335 					}
       
   336 				}
       
   337 			va+=iHdr->iCodeBase+ConstOffset();
       
   338 //			fprintf(stderr,"const reloc -> %x\n",va);
       
   339 			break;
       
   340 		case KDataSection:
       
   341 			va-=aPeFile.iLinkedBase;
       
   342 			va-=aPeFile.iSectionHeader[KDataSection]->VirtualAddress;
       
   343 			va+=iHdr->iDataBase; //DataOffset();
       
   344 			break;
       
   345 		case KCrtSection:
       
   346 			va-=aPeFile.iLinkedBase;
       
   347 			va-=aPeFile.iSectionHeader[KCrtSection]->VirtualAddress;
       
   348 			va+=iHdr->iCodeBase+iCrtOffset;
       
   349 			break;
       
   350 		case KBssSection:
       
   351 			va-=aPeFile.iLinkedBase;
       
   352 			va-=aPeFile.iSectionHeader[KBssSection]->VirtualAddress;
       
   353 			va+=iHdr->iDataBase+iHdr->iDataSize;
       
   354 			break;
       
   355 		case KImportSection:
       
   356 			va-=aPeFile.iLinkedBase;
       
   357 			va=FixImportThunk(aPeFile, va-aPeFile.iSectionHeader[KImportSection]->VirtualAddress);
       
   358 			va+=iHdr->iCodeBase;
       
   359 			break;
       
   360 		default:
       
   361 			if (va < 0x10000u)
       
   362 				{
       
   363 				// assume it's a relocation relative to an omitted section
       
   364 				break;
       
   365 				}
       
   366 			Print(EWarning, "Address to relocate cannot be resolved to .text, .rdata, .idata or data sections\n");
       
   367 			Print(EWarning, "Problem address = %08x (section %d)\n", va, section);
       
   368 			break;
       
   369 		}
       
   370 	// va is now an offset from the start of the text
       
   371 	return va;
       
   372 	}
       
   373 
       
   374