bintools/elftools/elftran/elf_reloc.cpp
changeset 0 044383f39525
child 675 02e65118a746
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bintools/elftools/elftran/elf_reloc.cpp	Tue Oct 27 16:36:35 2009 +0000
@@ -0,0 +1,154 @@
+/*
+* 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 the License "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 "elftran.h"
+#include "elffile.h"
+#include "h_utl.h"
+#include <assert.h>
+
+TInt sizeOfRelocs(Elf32_Rel **relocs, TInt nrelocs)
+	{
+
+	TInt bytecount=0;
+	TInt page=-1;
+	TInt i;
+	for (i=0; i<nrelocs; i++)
+		{
+		TInt p=relocs[i]->r_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; i<nrelocs; i++)
+		{
+		TInt p=relocs[i]->r_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; i<numberOfCodeRelocs; i++)
+	        {
+		data=aElfFile.CodePtrFromAddr(codeRelocs[i]->r_offset);
+		checkreloc(aElfFile, *data, codeRelocs[i]->r_offset);
+		//*data=FixAddress(aElfFile, *data, codeRelocs[i]);
+		}
+// fix defect
+	for (TInt j=0; j<numberOfDataRelocs; j++)
+	        {
+		data=aElfFile.DataPtrFromAddr(dataRelocs[j]->r_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;
+	
+	}
+