diff -r 000000000000 -r 83f4b4db085c toolsandutils/e32tools/elftools/elftran/elf_reloc.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolsandutils/e32tools/elftools/elftran/elf_reloc.cpp Tue Feb 02 01:39:43 2010 +0200 @@ -0,0 +1,152 @@ +// 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 "elftran.h" +#include "elffile.h" +#include "h_utl.h" +#include + +TInt sizeOfRelocs(Elf32_Rel **relocs, TInt nrelocs) + { + + TInt bytecount=0; + TInt page=-1; + TInt i; + for (i=0; ir_offset&0xfffff000; + if (page!=p) + { + if (bytecount%4!=0) + bytecount+=2; + bytecount+=8; // page, block size + page=p; + } + bytecount+=2; + } + if (bytecount%4!=0) + bytecount+=2; + return bytecount; + } + +char* E32ImageFile_ELF::CreateRelocs(ELFFile& aElfFile, Elf32_Rel **relocs, TInt nrelocs, TInt &aSize, TUint aBase) + { + + TInt bytecount=sizeOfRelocs(relocs, 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 page=-1; + TInt pagesize=8; + TInt i; + for (i=0; ir_offset&0xfffff000; + if (page!=p) + { + if (pagesize%4!=0) + { + *(TUint16 *)data=0; + data+=2; + pagesize+=2; + } + if (page == -1) page = p; + *(TUint *)startofblock=page - aBase; + *(TUint *)(startofblock+4)=pagesize; + pagesize=8; + page=p; + startofblock=data; + data+=8; + } + TUint16 relocType = aElfFile.GetRelocType(relocs[i]); + *(TUint16 *)data=(TUint16)((relocs[i]->r_offset&0xfff)|relocType); + data+=2; + pagesize+=2; + } + if (pagesize%4!=0) + { + *(TUint16 *)data=0; + data+=2; + pagesize+=2; + } + *(TUint *)startofblock=page - aBase; + *(TUint *)(startofblock+4)=pagesize; + ((E32RelocSection *)section)->iNumberOfRelocs=nrelocs; + ((E32RelocSection *)section)->iSize=bytecount; + return section; + } + +void checkreloc(ELFFile& aElfFile, TUint va, TUint reloc) + { + // This will warn if appears to be outside any known segment. + // NB. Such relocations can occur as the result of 'optimizations' + // and aren't 'bugs'. + // It turns out that the released version of RVCT makes such widespread + // use of the optimization that this warning is disconcerting and + // unhelpful. + (void) aElfFile; + (void)va; + (void)reloc; +#if 0 + if (!aElfFile.GetSegmentFromAddr(va)) + Print(EWarning, "dubious relocation: [%08x] = %08x\n", reloc, va); +#endif + } + +void E32ImageFile_ELF::FixRelocs(ELFFile &aElfFile, Elf32_Rel **codeRelocs, Elf32_Rel **dataRelocs) + { + TUint *data; + TInt numberOfCodeRelocs = aElfFile.NumberOfCodeRelocs(); + TInt numberOfDataRelocs = aElfFile.NumberOfDataRelocs(); + for (TInt i=0; ir_offset); + checkreloc(aElfFile, *data, codeRelocs[i]->r_offset); + //*data=FixAddress(aElfFile, *data, codeRelocs[i]); + } +// fix defect + for (TInt j=0; jr_offset); + checkreloc(aElfFile, *data, dataRelocs[j]->r_offset); + //*data=FixAddress(aElfFile, *data, dataRelocs[j]); + } + } + +TUint E32ImageFile_ELF::FixAddress(ELFFile &aElfFile, TUint va, Elf32_Rel * rel) +// +// Fix the given virtual address for the new headers +// + { + Elf32_Phdr * segment = aElfFile.GetSegmentFromAddr(rel->r_offset); + assert(aElfFile.CodeSegmentP(segment) || aElfFile.DataSegmentP(segment)); + TUint offset = va - segment->p_vaddr; + if (aElfFile.CodeSegmentP(segment)) + return (TUint)aElfFile.GetCode() + offset; + else + return (TUint)aElfFile.GetData() + offset; + + } +