tools/elf4rom/src/elfrom.cpp
changeset 34 92d87f2e53c2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/elf4rom/src/elfrom.cpp	Fri Jan 15 09:07:44 2010 +0000
@@ -0,0 +1,567 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU Lesser General Public License for more details.
+* 
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <fcntl.h>
+#include <string.h>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+using namespace std;
+
+#include "elfromerror.h"
+#include "elfrom.h"
+#include "inputfile.h"
+
+#define NO_GAPS
+
+void ElfRom::SetupE32RomData() {
+	SetupRomElf32_EHdr();
+	SetupRomImage();
+}
+
+// TODO: don't use primary file - fill header in by hand.
+void ElfRom::SetupRomElf32_EHdr() {
+	//create ELF header
+
+	unsigned char c[EI_NIDENT] = {ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, ELFCLASS32, ELFDATA2LSB, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
+	Elf32_Ehdr elf32_ehdr;
+
+	for (int i=0; i <EI_NIDENT;i++)
+		elf32_ehdr.e_ident[i] = c[i];
+
+	elf32_ehdr.e_type		= ET_EXEC;
+	elf32_ehdr.e_machine	= EM_ARM;
+	elf32_ehdr.e_version	= EV_CURRENT;
+	elf32_ehdr.e_entry		= iRomDetails->iRomPhysAddr;
+	elf32_ehdr.e_shoff		= sizeof(Elf32_Ehdr);
+	
+// ARM specific flags 
+// e_entry contains a program-loader entry point
+#define EF_ARM_HASENTRY 0x02
+// Each subsection of the symbol table is sorted by symbol value
+#define EF_ARM_SYMSARESORTED 0x04
+// Symbols in dynamic symbol tables that are defined in sections
+// included in program segment n have st_shndx = n+ 1. 
+#define EF_ARM_DYNSYMSUSESEGIDX 0x8
+// Mapping symbols precede other local symbols in the symbol table
+#define EF_ARM_MAPSYMSFIRST 0x10
+// This masks an 8-bit version number, the version of the ARM EABI to
+// which this ELF file conforms. This EABI is version 2. A value of 0
+// denotes unknown conformance. (current version is 0x02000000)
+#define EF_ARM_EABIMASK 0xFF000000
+
+#define EF_ARM_EABI_VERSION 0x02000000
+#define EF_ARM_BPABI_VERSION 0x04000000
+
+	elf32_ehdr.e_flags		= EF_ARM_BPABI_VERSION | EF_ARM_HASENTRY;
+	elf32_ehdr.e_ehsize		= sizeof(Elf32_Ehdr);
+	elf32_ehdr.e_phentsize 	= sizeof(Elf32_Phdr);
+	elf32_ehdr.e_shentsize 	= sizeof(Elf32_Shdr);
+	elf32_ehdr.e_shnum		= 0;
+	elf32_ehdr.e_shstrndx	= 0;
+	elf32_ehdr.e_phnum		= 02;
+	new (&iElf32Header) Elf32Header(elf32_ehdr);
+#if 0
+	iElf32Header.SetEntryPoint(iRomDetails->iRomPhysAddr);
+	elf_end(e);
+	close(fd);
+#endif
+	iElf32Header.SetEntryPoint(iRomDetails->iRomPhysAddr);
+	iElf32Header.AddData(iOutputFile);
+	assert(iElf32Header.GetOffset() == 0);
+	if (iRomDetails->iTrace){
+		cout << "\nElf header added.\n";
+	}
+
+}
+
+
+void ElfRom::SetupRomImage(){
+	// ensure image size is known and we know how to get hold of it
+	iE32RomImage.SetupRomData();
+	iE32RomImage.AddData(iOutputFile);
+	assert(iE32RomImage.GetOffset() == iElf32Header.Size());
+	if (iRomDetails->iTrace){
+		size_t offset = iE32RomImage.GetOffset();
+		size_t size = iE32RomImage.Size();
+		cout << "\nAdded ROM image " << iRomDetails->iRomFile << "\n";
+		cout.fill('0');
+		cout << hex << "      offset 0x" << setw(8)
+			<< offset << " size = 0x" << setw(8) << size << "\n" ;
+	}
+}
+
+void ElfRom::SetupProgramHeaderTable(){
+	size_t offsetx = AddBootStrapProgramHeader();
+	RomDetails::XIPFileList::iterator aXIPFile = iRomDetails->iXIPFiles.begin();
+	RomDetails::XIPFileList::iterator end = iRomDetails->iXIPFiles.end();
+	unsigned int p = iRomDetails->iRomPhysAddr;
+	unsigned int v = iRomDetails->iRomBaseLinearAddr;
+	int addend = v > p ? -(v - p) : p - v;
+	
+	if (iRomDetails->iTrace){
+		cout << "\nAdding program headers for e32images\n";
+	}
+	
+	while (aXIPFile != end) {
+		offsetx = SetupProgramHeaders(*aXIPFile, offsetx, addend);
+		aXIPFile++;
+	}
+	AddFinalHeader(offsetx);
+
+#ifdef NO_GAPS
+	// check there are no gaps or overlaps in the phdrs
+	Elf32_Word bsz = iBootStrapPHdr.GetPhdrFilesz();
+	Elf32_Word coffset = iBootStrapPHdr.GetPhdrOffset() + bsz;
+	Elf32_Addr phys_addr = iBootStrapPHdr.GetPhdrPaddr() + bsz;
+	ElfPHdrList::iterator aCheckHdr = iElfPHdrList.begin();
+	ElfPHdrList::iterator endCheckHdr = iElfPHdrList.end();
+	while(aCheckHdr != endCheckHdr) {
+		Elf32_Word o = aCheckHdr->GetPhdrOffset();
+		if (coffset != o){
+			cerr << "Error: Phdr table broken - offsets incorrect\n";
+			assert(coffset == o);
+		}
+		Elf32_Addr addr = aCheckHdr->GetPhdrPaddr();
+		if (phys_addr > addr){
+			cerr << "Error: Phdr table broken - physical addresses incorrect\n";
+			assert(phys_addr <= addr);
+		}
+		size_t sz = aCheckHdr->GetPhdrFilesz();
+		coffset = o + sz;
+		phys_addr = addr + sz;
+		aCheckHdr++;
+	}
+#endif
+	
+	ElfPHdrList::iterator aHdr = iElfPHdrList.begin();
+	ElfPHdrList::iterator endHdr = iElfPHdrList.end();
+	while (aHdr != endHdr) {
+		aHdr->AddData(iOutputFile);
+		aHdr++;
+	}
+}
+
+size_t ElfRom::AddBootStrapProgramHeader(){
+	iBootStrapPHdr.SetPhdrType(PT_LOAD);
+	iBootStrapPHdr.SetPhdrOffset(iE32RomImage.GetOffset());
+	iBootStrapPHdr.SetPhdrVaddr(iRomDetails->iRomPhysAddr);
+	iBootStrapPHdr.SetPhdrPaddr(iRomDetails->iRomPhysAddr);
+	iBootStrapPHdr.SetPhdrAlign(4);
+	iBootStrapPHdr.SetPhdrFlags(PF_X + PF_R);
+	size_t bootstrapsize = iRomDetails->iXIPFiles[0].iLoadAddr - iRomDetails->iRomBaseLinearAddr;
+	iBootStrapPHdr.SetPhdrFilesz(bootstrapsize);
+	iBootStrapPHdr.SetPhdrMemsz(bootstrapsize);
+		
+	iBootStrapPHdr.AddData(iOutputFile);
+	assert((iElf32Header.Size() + iE32RomImage.Size()) == iBootStrapPHdr.GetOffset());
+	iElf32Header.AddProgramHdr();
+	iElf32Header.SetProgramHdrOffset(iBootStrapPHdr.GetOffset());
+	if (iRomDetails->iTrace){
+		size_t offset = iBootStrapPHdr.GetOffset();
+		cout << "\nAdded PHdr for bootstrap\n";
+		cout.fill('0');
+		cout << hex << "      offset 0x" << setw(8) << offset 
+			 << " size = 0x" << setw(8) << bootstrapsize << "\n";
+	}
+
+	return iE32RomImage.GetOffset() + bootstrapsize;
+}
+
+static inline size_t InitE32HdrPHdr(ElfPHdr & hdr, size_t offset, Elf32_Word vaddr, Elf32_Word paddr, Elf32_Word size){
+	hdr.SetPhdrType(PT_LOAD);
+	hdr.SetPhdrOffset(offset);
+	hdr.SetPhdrVaddr(vaddr);
+	hdr.SetPhdrPaddr(paddr);
+	hdr.SetPhdrAlign(0);
+	hdr.SetPhdrFlags(PF_R);
+	hdr.SetPhdrFilesz(size);
+	hdr.SetPhdrMemsz(size);
+		
+	return offset + size;	
+	
+}
+static inline size_t InitROPHdr(ElfPHdr & hdr, size_t offset, Elf32_Word vaddr, Elf32_Word paddr, Elf32_Word size){
+	hdr.SetPhdrType(PT_LOAD);
+	hdr.SetPhdrOffset(offset);
+	hdr.SetPhdrVaddr(vaddr);
+	hdr.SetPhdrPaddr(paddr);
+	hdr.SetPhdrAlign(4);
+	hdr.SetPhdrFlags(PF_X + PF_R);
+	hdr.SetPhdrFilesz(size);
+	hdr.SetPhdrMemsz(size);
+		
+	return offset + size;	
+	
+}
+
+static inline size_t InitRWPHdr(ElfPHdr & hdr, size_t offset, Elf32_Word vaddr, Elf32_Word paddr, Elf32_Word fsize, Elf32_Word msize){
+	hdr.SetPhdrType(PT_LOAD);
+	hdr.SetPhdrOffset(offset);
+	hdr.SetPhdrVaddr(vaddr);
+	hdr.SetPhdrPaddr(paddr);
+	hdr.SetPhdrAlign(4);
+	hdr.SetPhdrFlags(PF_X + PF_R);
+	hdr.SetPhdrFilesz(fsize);
+	hdr.SetPhdrMemsz(msize);
+		
+	return offset + fsize;	
+	
+}
+
+size_t ElfRom::SetupProgramHeaders(XIPFileDetails & aXIPFileDetails, size_t offset, int addend){
+	ElfPHdr e32hdr;
+	Elf32_Word e32hdrVaddr = aXIPFileDetails.iLoadAddr;
+	Elf32_Word e32hdrPaddr = aXIPFileDetails.iLoadAddr + addend;
+	Elf32_Word e32hdrSize = aXIPFileDetails.iROAddr - aXIPFileDetails.iLoadAddr ;
+	size_t e32hdrOffsetInRom = aXIPFileDetails.iLoadAddr - iRomDetails->iRomBaseLinearAddr;
+	size_t e32hdrOffsetInElf = iE32RomImage.GetOffset() + e32hdrOffsetInRom;
+#ifdef NO_GAPS
+	// But actually the offset we'll use is the one we were given as an argument.
+	// This means we need to adjust the size, vaddr and paddr by the difference
+	size_t diff = e32hdrOffsetInElf - offset;
+	e32hdrSize += diff;
+	e32hdrVaddr -= diff;
+	e32hdrPaddr -= diff;
+	offset = InitE32HdrPHdr(e32hdr, offset, e32hdrVaddr, e32hdrPaddr, e32hdrSize);
+#else
+	offset = InitE32HdrPHdr(e32hdr, e32hdrOffsetInElf, e32hdrVaddr, e32hdrPaddr, e32hdrSize);
+#endif
+	iElf32Header.AddProgramHdr();
+	iElfPHdrList.push_back(e32hdr);
+	ElfPHdr thdr;
+	Elf32_Word textVaddr = aXIPFileDetails.iROAddr;
+	Elf32_Word textPaddr = aXIPFileDetails.iROAddr + addend;
+	Elf32_Word textSize = aXIPFileDetails.iROSize;
+	size_t textOffsetInRom = aXIPFileDetails.iROAddr - iRomDetails->iRomBaseLinearAddr;
+	size_t textOffsetInElf = iE32RomImage.GetOffset() + textOffsetInRom;
+	offset = InitROPHdr(thdr, textOffsetInElf, textVaddr, textPaddr, textSize);
+	iElf32Header.AddProgramHdr();
+	iElfPHdrList.push_back(thdr);
+
+	if (iRomDetails->iTrace){
+		cout << "  " << aXIPFileDetails.iE32File << "\n";
+		cout.fill(' ');
+		cout << left << "    .text\n";
+		cout.fill('0');
+		cout << "      paddr = 0x" << right << setw(8) << textPaddr << " vaddr = 0x" << right << setw(8)<< textVaddr
+		     << " offset = 0x" << right << setw(8) << textOffsetInElf 
+			 << " size = 0x" << setw(8) << textSize << "\n" << flush;
+	}
+	
+	if (aXIPFileDetails.iRWSize > 0){
+		ElfPHdr dhdr;
+		Elf32_Word dataVaddr = aXIPFileDetails.iRWAddr;
+		Elf32_Word dataPaddr = aXIPFileDetails.iROMDataAddr + addend;
+		Elf32_Word fsize = aXIPFileDetails.iRWSize;
+		Elf32_Word msize = aXIPFileDetails.iBSSDataSize;
+		size_t dataOffsetInRom = aXIPFileDetails.iROMDataAddr - iRomDetails->iRomBaseLinearAddr;
+		size_t dataOffsetInElf = iE32RomImage.GetOffset() + dataOffsetInRom;
+		offset = InitRWPHdr(dhdr, dataOffsetInElf, dataVaddr, dataPaddr, fsize, msize);
+		iElf32Header.AddProgramHdr();
+		iElfPHdrList.push_back(dhdr);
+		
+		if (iRomDetails->iTrace){
+			cout.fill(' ');
+			cout << left << "    .data\n";
+			cout.fill('0');
+			cout << "      paddr = 0x" << right << setw(8) << dataPaddr << " vaddr = 0x" << right << setw(8)<< dataVaddr  
+				 << " offset = 0x" << right << setw(8)<< dataOffsetInElf
+				 << " size = 0x" << right << setw(8) << fsize << "\n" << flush;
+		}
+		
+	}
+	return offset;
+}
+
+// This adds a header for the remainder of the ROM image after the last XIP file
+size_t ElfRom::AddFinalHeader(size_t offset){
+	ElfPHdr & lastHdr = iElfPHdrList.back();
+	Elf32_Word startAddr = lastHdr.GetPhdrPaddr() + lastHdr.GetPhdrFilesz();
+	ElfPHdr e32hdr;
+	Elf32_Word e32hdrVaddr = startAddr;
+	Elf32_Word e32hdrPaddr = startAddr;
+	Elf32_Word e32hdrSize = iE32RomImage.Size() - offset + iE32RomImage.GetOffset();
+
+	offset = InitE32HdrPHdr(e32hdr, offset, e32hdrVaddr, e32hdrPaddr, e32hdrSize);
+
+	iElf32Header.AddProgramHdr();
+	iElfPHdrList.push_back(e32hdr);	
+	
+	if (iRomDetails->iTrace){
+		cout << "\nAdded final PHdr\n" << "      offset 0x" << hex << right << setw(8) << offset 
+			<< " size = 0x" << setw(8) << e32hdrSize << "\n";
+	}
+	return offset;
+}
+
+void ElfRom::SetupAuxilarySections(){
+	SetupLogFile();
+}
+
+void ElfRom::SetupLogFile(){
+	if (!iRomDetails->iLogFile.size()) return;
+	InputFile * aLogFile = new InputFile(iRomDetails->iLogFile);
+	ElfSectionFileData * aLogFileData = new ElfSectionFileData(aLogFile);
+	Elf32_Shdr shdr;
+	shdr.sh_name = 0; // for now.
+	shdr.sh_offset = 0; // for now
+	shdr.sh_info = 0;
+	shdr.sh_link = SHN_UNDEF;
+	shdr.sh_addr = 0;
+	shdr.sh_addralign = 0;
+	shdr.sh_type = SHT_PROGBITS;
+	shdr.sh_size = 0; // for now.
+	shdr.sh_flags = 0;
+	shdr.sh_entsize = 0;
+
+	ElfSection aLogFileSection(aLogFileData, "ROMLogFile", shdr);
+	iElfSectionManager.AddSection(aLogFileSection);
+
+}
+
+void ElfRom::SetupELFRomData() {
+	SetupProgramHeaderTable();
+	SetupAuxilarySections();
+	if (!iRomDetails->iStrip){
+		SetupSectionHeaderTable();
+		SetupSymbolTable();
+		if (!iRomDetails->iNoDwarf){
+			SetupDwarfSections();
+		}
+	}
+}
+
+void ElfRom::SetupSectionHeaderTable(){
+	RomDetails::XIPFileList::iterator aXIPFile = iRomDetails->iXIPFiles.begin();
+	RomDetails::XIPFileList::iterator end = iRomDetails->iXIPFiles.end();
+
+	if (iRomDetails->iTrace && aXIPFile != end){
+		cout << "\nAdding Section headers from associated ELF files\n";
+	}
+
+	while (aXIPFile != end) {
+		SetupSectionHeaders(*aXIPFile);
+		aXIPFile++;
+	}
+}
+
+void ElfRom::SetupSectionHeaders(XIPFileDetails & aXIPFileDetails) {
+	// Open ELF file
+	PathName aPath = aXIPFileDetails.iElfFile;
+	
+	if (aPath.size() == 0) return;
+	
+	int fd;
+	Elf * e;
+	size_t shstrndx;
+	bool hasSectionStringTable = true;
+
+
+	if ((fd = open(aPath.c_str(), O_RDONLY|O_BINARY, 0)) < 0){
+		warnx(EX_NOINPUT, "open \"%s\" failed\n", aPath.c_str());
+		goto finish;
+	}
+	if ((e = elf_begin(fd, ELF_C_READ , NULL)) == NULL)
+		errx(EX_SOFTWARE, "elf_begin() failed: %s.\n", elf_errmsg(-1));
+	if (elf_kind(e) != ELF_K_ELF)
+		errx(EX_SOFTWARE, "file not of kind ELF_K_ELF: %s.\n", aPath.c_str());
+	if (elf_getshstrndx(e, &shstrndx) == 0) {
+		hasSectionStringTable = false;
+		warnx(EX_SOFTWARE, "getshstrndx() failed for \"%s\"\n", aPath.c_str());
+	}
+	if (hasSectionStringTable){
+		SetUpSegmentInfo(aXIPFileDetails, e);
+		SetupSectionHeaders(aXIPFileDetails, e, shstrndx);
+	}
+
+	elf_end(e);
+	close(fd);	
+finish:
+	return;
+}
+
+void ElfRom::SetupSectionHeaders(XIPFileDetails & aXIPFileDetails, Elf * e, size_t shstrndx){
+	// Iterate through sections looking for the ones we're after. Namely:
+	// text, data, bss/zi, symtab, strtable,  and .debug*
+	Elf_Scn * scn = NULL; 
+	Elf32_Shdr * shdr;
+	SectionNumberMap aSectionNumberMap;
+	SectionVaddrAddendMap aSectionVaddrAddendMap;
+
+	String aPath(aXIPFileDetails.iElfFile);
+	
+	const char * debugName = ".debug";
+	const size_t debugNameLength = strlen(debugName);
+	const char * staticStrTab = ".strtab";
+	
+	if (iRomDetails->iTrace){
+		cout << "  " << aXIPFileDetails.iElfFile << "\n";
+	}
+	
+	while ((scn = elf_nextscn(e, scn)) != NULL) {
+
+    	if ((shdr = elf32_getshdr(scn)) == NULL)
+    		errx(EX_SOFTWARE, "getshdr() failed: %s.\n", elf_errmsg(-1));
+    	
+		size_t aOldNdx = elf_ndxscn(scn);
+    	char * name = elf_strptr(e, shstrndx, shdr->sh_name);
+    	VirtualAddr sectionAddr = shdr->sh_addr;
+
+    	switch (shdr->sh_type) {
+    	case SHT_NOBITS:
+    		// Check for BSS or ZI
+    		if ((shdr->sh_flags & SHF_WRITE) && (shdr->sh_flags & SHF_ALLOC)) {
+    			// set up section number mapping
+    			size_t aNew = AddBssSectionHeader(aXIPFileDetails, shdr, name);
+    			aSectionNumberMap.push_back(SectionNumberMapping(aOldNdx, aNew));
+    			// set up address adjustment for relocation of e.g. symbols
+    			int addend = aXIPFileDetails.iBSSAddr - sectionAddr;
+    			aSectionVaddrAddendMap.push_back(SectionVaddrAddendMapping(aOldNdx, addend));
+    		}
+    		break;
+#define ARM_EXIDX	(SHT_LOPROC + 1)
+    	case ARM_EXIDX:    		
+    	case SHT_PROGBITS:
+    		// text/ro or data/rw will have SHF_ALLOC set
+    		if (shdr->sh_flags & SHF_ALLOC) {
+    			size_t aNew = 0;
+    		    int addend = 0;
+    		    if (shdr->sh_flags & SHF_WRITE) {
+    				aNew = AddRwSectionHeader(aXIPFileDetails, shdr, name);
+    				addend = aXIPFileDetails.iRWAddr - sectionAddr;
+    		    } else {
+    				aNew = AddRoSectionHeader(aXIPFileDetails, shdr, name);
+    				addend = aXIPFileDetails.iROAddr - sectionAddr;
+    		    }
+    			// set up section number mapping
+    		    aSectionNumberMap.push_back(SectionNumberMapping(aOldNdx, aNew)); 
+    			// set up address adjustment for relocation of e.g. symbols
+    		    aSectionVaddrAddendMap.push_back(SectionVaddrAddendMapping(aOldNdx, addend));     	
+    		} else if (!iRomDetails->iNoDwarf && !strncmp(debugName, name, debugNameLength)) {
+    			iDwarfFound = true;
+    			iDwarfManager.AddSection(aXIPFileDetails, name, shdr);
+    		}
+    		break;
+    	case SHT_SYMTAB:
+    		iElfSymbolTableManager.AddSymbolTable(aPath, shdr->sh_offset, shdr->sh_size, shdr->sh_info);
+    		break;
+    	case SHT_STRTAB:
+    		if (!strcmp(staticStrTab, name))
+    			iElfSymbolTableManager.AddStringTable(aPath, shdr->sh_offset, shdr->sh_size);
+    		break;
+    	}
+    }
+	iElfSymbolTableManager.Finalize(aSectionNumberMap, aSectionVaddrAddendMap);
+}
+
+size_t ElfRom::AddRoSectionHeader(XIPFileDetails & aXIPFileDetails, Elf32_Shdr * aShdr, char * aName){
+	size_t delta = aShdr->sh_addr - aXIPFileDetails.iElfTextBase;
+	VirtualAddr vaddr = aXIPFileDetails.iROAddr + delta;
+	size_t offsetInRom = vaddr - iRomDetails->iRomBaseLinearAddr;
+	size_t offsetInElf = iE32RomImage.GetOffset() + offsetInRom;
+	aShdr->sh_addr = vaddr;
+	return AddROMSectionHeader(aXIPFileDetails, aShdr, aName, offsetInElf );
+}
+
+size_t ElfRom::AddRwSectionHeader(XIPFileDetails & aXIPFileDetails, Elf32_Shdr * aShdr, char * aName){		
+	size_t delta = aShdr->sh_addr - aXIPFileDetails.iElfDataBase;
+	VirtualAddr vaddr = aXIPFileDetails.iROMDataAddr + delta;
+	size_t offsetInRom = vaddr - iRomDetails->iRomBaseLinearAddr;
+	size_t offsetInElf = iE32RomImage.GetOffset() + offsetInRom;	
+	aShdr->sh_addr = aXIPFileDetails.iRWAddr;
+	return AddROMSectionHeader(aXIPFileDetails, aShdr, aName, offsetInElf);
+}
+
+size_t ElfRom::AddBssSectionHeader(XIPFileDetails & aXIPFileDetails, Elf32_Shdr * aShdr, char * aName){	
+	size_t delta = aShdr->sh_addr - aXIPFileDetails.iElfDataBase;
+	VirtualAddr vaddr = aXIPFileDetails.iROMDataAddr + delta;
+	size_t offsetInRom = vaddr - iRomDetails->iRomBaseLinearAddr;
+	size_t offsetInElf = iE32RomImage.GetOffset() + offsetInRom;	
+	aShdr->sh_addr = aXIPFileDetails.iBSSAddr;
+	return AddROMSectionHeader(aXIPFileDetails, aShdr, aName, offsetInElf);
+}
+
+size_t ElfRom::AddROMSectionHeader(XIPFileDetails & aXIPFileDetails, Elf32_Shdr * aShdr, char * aName, size_t aOffset){	
+	ElfSectionData * romData = aOffset ? 
+								(ElfSectionData *)new ElfSectionRomData(aOffset, aShdr->sh_size) 
+								: (ElfSectionData *)new ElfSectionNoData();
+	ElfSection aSection(romData, aName, *aShdr);
+	iElfSectionManager.AddSection(aSection);
+	
+	if (iRomDetails->iTrace){
+		cout.fill(' ');
+		cout << "    " << left << setw(22) << aName << "\n";
+		cout.fill('0');
+		cout << "      vaddr = 0x" << right << hex << setw(8) << aShdr->sh_addr << " offset = 0x" 
+			 << right << hex << setw(8) << aOffset 
+			 << " size = 0x" << right << hex << setw(8) << aShdr->sh_size << "\n";
+	}
+	return aSection.GetIndex();
+}
+
+void ElfRom::SetUpSegmentInfo(XIPFileDetails & aXIPFileDetails, Elf * e){
+	Elf32_Ehdr * ehdr = elf32_getehdr(e);
+	if (ehdr == NULL)
+		errx(EX_SOFTWARE, "elf32_getehdr() failed: %s.", elf_errmsg(-1));
+	size_t n = ehdr->e_phnum;
+	Elf32_Phdr * phdr = elf32_getphdr(e);
+	if (phdr == NULL)
+		errx(EX_SOFTWARE, "elf32_getphdr() failed: %s.", elf_errmsg(-1));
+
+	for (size_t i = 0; i < n; i++) {
+		if (phdr[i].p_flags & PF_X){
+			VirtualAddr segmentAddr = phdr[i].p_vaddr;
+	    	aXIPFileDetails.iElfTextBase = segmentAddr;
+	    	aXIPFileDetails.iElfTextLimit = segmentAddr + phdr[i].p_memsz;
+			
+		} else if (phdr[i].p_flags & PF_W){
+	    	aXIPFileDetails.iElfDataBase = phdr[i].p_vaddr;
+		}
+	}	
+}
+
+void ElfRom::SetupSymbolTable(){
+	iElfSymbolTableManager.AddSymbolTable();
+	if (iRomDetails->iTrace){
+		cout << "\nAdded section headers for combined symbol table and symbol string table\n";
+	}
+}
+
+void ElfRom::SetupDwarfSections(){
+	if (iRomDetails->iTrace && iDwarfFound){
+		cout << "\nSetting up Dwarf Sections\n";
+	} else if (iRomDetails->iTrace && !iDwarfFound && !iRomDetails->iNoDwarf){
+		cout << "\nWarning: No Dwarf information found\n";
+		return;
+	}
+	iDwarfManager.SetupSections();
+}
+
+void ElfRom::AddData() {
+	iElfSectionManager.AddData();
+	iElf32Header.SetSectionHdrOffset(iElfSectionManager.GetOffset());
+}
+
+void ElfRom::Dump(){
+	iOutputFile.Dump();
+	if (iRomDetails->iTrace){
+		cout << "\nWrote " << iRomDetails->iElfRomFile << " " << dec << iOutputFile.Size() << " bytes\n";
+	}	
+}