diff -r 22486c9c7b15 -r 378360dbbdba bintools/petools/pefile/pe_reloc.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bintools/petools/pefile/pe_reloc.cpp Wed Jun 30 11:35:58 2010 +0800 @@ -0,0 +1,374 @@ +// 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 +#include +#include +#include +#include "pe_file.h" +#include "h_utl.h" +#include + +extern char* gX86imp; +extern int gX86num_imp_dlls; +extern int gX86imp_size; +extern int gX86num_imports; +extern int* gX86imp_relocs; + +TInt sizeOfCodeRelocs(TUint *relocs, TUint *relocsection, TInt nrelocs) + { + + TInt bytecount=0; + TInt page=-1; + TInt i; + for (i=0; iiNumberOfRelocs=ncoderelocs; + ((E32RelocSection *)section)->iSize=bytecount; + return section; + } + +char *E32ImageFile_PE::CreateDataRelocs(TUint *relocs, TUint *relocsection, TInt nrelocs, TInt &aSize) + { + + TInt bytecount=sizeOfDataRelocs(relocs, relocsection, nrelocs); + aSize=0; + if (bytecount==0) + return NULL; + aSize=bytecount+sizeof(E32RelocSection); + + char *section=new char [bytecount+sizeof(E32RelocSection)]; + char *data=section+sizeof(E32RelocSection); + char *startofblock=data; + + TInt ndatarelocs=0; + TInt page=-1; + TInt pagesize=8; + TInt i; + for (i=0; iiNumberOfRelocs=ndatarelocs; + ((E32RelocSection *)section)->iSize=bytecount; + return section; + } + +void checkreloc(PEFile &aPeFile, TUint va, TUint reloc) + { + + // Allow the section find routine to use heuristics to resolve addresses + // which have been offset by the compiler + TInt s = aPeFile.FindSectionByVa(va, 1); + switch(s) + { + case KTextSection: + case KConstSection: + case KDataSection: + case KCrtSection: + case KBssSection: + case KImportSection: + return; + default: + break; + } + Print(EAlways, "bad relocation: [%08x] = %08x\n", reloc, va); + } + +void E32ImageFile_PE::FixRelocs(PEFile &aPeFile, TUint *relocation, TUint *relocsection, TInt aNumberOfRelocs) + { + + TUint *data; + TInt i; +#if 0 + Print(EAlways, "Linked base %08x\n", aPeFile.iLinkedBase); + for (i=0; iVirtualAddress; + TUint finish = start + aPeFile.iSectionHeader[i]->Misc.VirtualSize; + Print(EAlways, "Section %d %08x-%08x\n", i, start, finish); + } +#endif + for (i=0; iVirtualAddress; + data=(TUint *)(aPeFile.iSectionData[KTextSection]+relocation[i]); + if (!gLittleEndian) ByteSwap(*data); + checkreloc(aPeFile, *data, relocation[i]+aPeFile.iSectionHeader[KTextSection]->VirtualAddress); + *data=FixAddress(aPeFile, *data); + if (!gLittleEndian) ByteSwap(*data); + break; + case KConstSection: + relocation[i]-=aPeFile.iSectionHeader[KConstSection]->VirtualAddress; + data=(TUint *)(aPeFile.iSectionData[KConstSection]+relocation[i]); + if (!gLittleEndian) ByteSwap(*data); + checkreloc(aPeFile, *data, relocation[i]+aPeFile.iSectionHeader[KConstSection]->VirtualAddress); + relocation[i]+=ConstOffset(); + *data=FixAddress(aPeFile, *data); + if (!gLittleEndian) ByteSwap(*data); + break; + case KCrtSection: + relocation[i]-=aPeFile.iSectionHeader[KCrtSection]->VirtualAddress; + data=(TUint *)(aPeFile.iSectionData[KCrtSection]+relocation[i]); + if (!gLittleEndian) ByteSwap(*data); + checkreloc(aPeFile, *data, relocation[i]+aPeFile.iSectionHeader[KCrtSection]->VirtualAddress); + relocation[i]+=iCrtOffset; + *data=FixAddress(aPeFile, *data); + if (!gLittleEndian) ByteSwap(*data); + break; + case KDataSection: + relocation[i]-=aPeFile.iSectionHeader[KDataSection]->VirtualAddress; + data=(TUint *)(aPeFile.iSectionData[KDataSection]+relocation[i]); + if (!gLittleEndian) ByteSwap(*data); + checkreloc(aPeFile, *data, relocation[i]+aPeFile.iSectionHeader[KDataSection]->VirtualAddress); + *data=FixAddress(aPeFile, *data); + if (!gLittleEndian) ByteSwap(*data); + break; + default: + Print(EWarning, "Relocation in invalid section.\n"); + break; + } + } + reorderRelocs(relocation, relocsection, aNumberOfRelocs); + } + +TUint E32ImageFile_PE::FixAddress(PEFile &aPeFile, TUint va) +// +// Fix the given virtual address for the new headers +// + { + + // Allow the section find routine to use heuristics to resolve addresses + // which have been offset by the compiler + TInt section=aPeFile.FindSectionByVa(va, 1); + switch(section) + { + case KTextSection: + va-=aPeFile.iLinkedBase; + va-=aPeFile.iSectionHeader[KTextSection]->VirtualAddress; + va+=iHdr->iCodeBase; + break; + case KConstSection: + va-=aPeFile.iLinkedBase; + va-=aPeFile.iSectionHeader[KConstSection]->VirtualAddress; + if (gX86imp) + { + TUint old_iat_size=(gX86num_imports+gX86num_imp_dlls)<<2; + if (vaiTextSize; +// fprintf(stderr,"IAT OFF %x ",va); + va=gX86imp_relocs[va>>2]+iHdr->iCodeBase+offset; +// fprintf(stderr,"-> %x\n",va); + break; + } + } + va+=iHdr->iCodeBase+ConstOffset(); +// fprintf(stderr,"const reloc -> %x\n",va); + break; + case KDataSection: + va-=aPeFile.iLinkedBase; + va-=aPeFile.iSectionHeader[KDataSection]->VirtualAddress; + va+=iHdr->iDataBase; //DataOffset(); + break; + case KCrtSection: + va-=aPeFile.iLinkedBase; + va-=aPeFile.iSectionHeader[KCrtSection]->VirtualAddress; + va+=iHdr->iCodeBase+iCrtOffset; + break; + case KBssSection: + va-=aPeFile.iLinkedBase; + va-=aPeFile.iSectionHeader[KBssSection]->VirtualAddress; + va+=iHdr->iDataBase+iHdr->iDataSize; + break; + case KImportSection: + va-=aPeFile.iLinkedBase; + va=FixImportThunk(aPeFile, va-aPeFile.iSectionHeader[KImportSection]->VirtualAddress); + va+=iHdr->iCodeBase; + break; + default: + if (va < 0x10000u) + { + // assume it's a relocation relative to an omitted section + break; + } + Print(EWarning, "Address to relocate cannot be resolved to .text, .rdata, .idata or data sections\n"); + Print(EWarning, "Problem address = %08x (section %d)\n", va, section); + break; + } + // va is now an offset from the start of the text + return va; + } + +