tools/elf4rom/src/elfrom.cpp
changeset 34 92d87f2e53c2
equal deleted inserted replaced
33:1af5c1be89f8 34:92d87f2e53c2
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 *
       
     5 * This program is free software: you can redistribute it and/or modify
       
     6 * it under the terms of the GNU Lesser General Public License as published by
       
     7 * the Free Software Foundation, either version 3 of the License, or
       
     8 * (at your option) any later version.
       
     9 *
       
    10 * This program is distributed in the hope that it will be useful,
       
    11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    13 * GNU Lesser General Public License for more details.
       
    14 * 
       
    15 * You should have received a copy of the GNU Lesser General Public License
       
    16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
       
    17 */
       
    18 
       
    19 #include <fcntl.h>
       
    20 #include <string.h>
       
    21 #include <iostream>
       
    22 #include <sstream>
       
    23 #include <iomanip>
       
    24 
       
    25 using namespace std;
       
    26 
       
    27 #include "elfromerror.h"
       
    28 #include "elfrom.h"
       
    29 #include "inputfile.h"
       
    30 
       
    31 #define NO_GAPS
       
    32 
       
    33 void ElfRom::SetupE32RomData() {
       
    34 	SetupRomElf32_EHdr();
       
    35 	SetupRomImage();
       
    36 }
       
    37 
       
    38 // TODO: don't use primary file - fill header in by hand.
       
    39 void ElfRom::SetupRomElf32_EHdr() {
       
    40 	//create ELF header
       
    41 
       
    42 	unsigned char c[EI_NIDENT] = {ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, ELFCLASS32, ELFDATA2LSB, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
       
    43 	Elf32_Ehdr elf32_ehdr;
       
    44 
       
    45 	for (int i=0; i <EI_NIDENT;i++)
       
    46 		elf32_ehdr.e_ident[i] = c[i];
       
    47 
       
    48 	elf32_ehdr.e_type		= ET_EXEC;
       
    49 	elf32_ehdr.e_machine	= EM_ARM;
       
    50 	elf32_ehdr.e_version	= EV_CURRENT;
       
    51 	elf32_ehdr.e_entry		= iRomDetails->iRomPhysAddr;
       
    52 	elf32_ehdr.e_shoff		= sizeof(Elf32_Ehdr);
       
    53 	
       
    54 // ARM specific flags 
       
    55 // e_entry contains a program-loader entry point
       
    56 #define EF_ARM_HASENTRY 0x02
       
    57 // Each subsection of the symbol table is sorted by symbol value
       
    58 #define EF_ARM_SYMSARESORTED 0x04
       
    59 // Symbols in dynamic symbol tables that are defined in sections
       
    60 // included in program segment n have st_shndx = n+ 1. 
       
    61 #define EF_ARM_DYNSYMSUSESEGIDX 0x8
       
    62 // Mapping symbols precede other local symbols in the symbol table
       
    63 #define EF_ARM_MAPSYMSFIRST 0x10
       
    64 // This masks an 8-bit version number, the version of the ARM EABI to
       
    65 // which this ELF file conforms. This EABI is version 2. A value of 0
       
    66 // denotes unknown conformance. (current version is 0x02000000)
       
    67 #define EF_ARM_EABIMASK 0xFF000000
       
    68 
       
    69 #define EF_ARM_EABI_VERSION 0x02000000
       
    70 #define EF_ARM_BPABI_VERSION 0x04000000
       
    71 
       
    72 	elf32_ehdr.e_flags		= EF_ARM_BPABI_VERSION | EF_ARM_HASENTRY;
       
    73 	elf32_ehdr.e_ehsize		= sizeof(Elf32_Ehdr);
       
    74 	elf32_ehdr.e_phentsize 	= sizeof(Elf32_Phdr);
       
    75 	elf32_ehdr.e_shentsize 	= sizeof(Elf32_Shdr);
       
    76 	elf32_ehdr.e_shnum		= 0;
       
    77 	elf32_ehdr.e_shstrndx	= 0;
       
    78 	elf32_ehdr.e_phnum		= 02;
       
    79 	new (&iElf32Header) Elf32Header(elf32_ehdr);
       
    80 #if 0
       
    81 	iElf32Header.SetEntryPoint(iRomDetails->iRomPhysAddr);
       
    82 	elf_end(e);
       
    83 	close(fd);
       
    84 #endif
       
    85 	iElf32Header.SetEntryPoint(iRomDetails->iRomPhysAddr);
       
    86 	iElf32Header.AddData(iOutputFile);
       
    87 	assert(iElf32Header.GetOffset() == 0);
       
    88 	if (iRomDetails->iTrace){
       
    89 		cout << "\nElf header added.\n";
       
    90 	}
       
    91 
       
    92 }
       
    93 
       
    94 
       
    95 void ElfRom::SetupRomImage(){
       
    96 	// ensure image size is known and we know how to get hold of it
       
    97 	iE32RomImage.SetupRomData();
       
    98 	iE32RomImage.AddData(iOutputFile);
       
    99 	assert(iE32RomImage.GetOffset() == iElf32Header.Size());
       
   100 	if (iRomDetails->iTrace){
       
   101 		size_t offset = iE32RomImage.GetOffset();
       
   102 		size_t size = iE32RomImage.Size();
       
   103 		cout << "\nAdded ROM image " << iRomDetails->iRomFile << "\n";
       
   104 		cout.fill('0');
       
   105 		cout << hex << "      offset 0x" << setw(8)
       
   106 			<< offset << " size = 0x" << setw(8) << size << "\n" ;
       
   107 	}
       
   108 }
       
   109 
       
   110 void ElfRom::SetupProgramHeaderTable(){
       
   111 	size_t offsetx = AddBootStrapProgramHeader();
       
   112 	RomDetails::XIPFileList::iterator aXIPFile = iRomDetails->iXIPFiles.begin();
       
   113 	RomDetails::XIPFileList::iterator end = iRomDetails->iXIPFiles.end();
       
   114 	unsigned int p = iRomDetails->iRomPhysAddr;
       
   115 	unsigned int v = iRomDetails->iRomBaseLinearAddr;
       
   116 	int addend = v > p ? -(v - p) : p - v;
       
   117 	
       
   118 	if (iRomDetails->iTrace){
       
   119 		cout << "\nAdding program headers for e32images\n";
       
   120 	}
       
   121 	
       
   122 	while (aXIPFile != end) {
       
   123 		offsetx = SetupProgramHeaders(*aXIPFile, offsetx, addend);
       
   124 		aXIPFile++;
       
   125 	}
       
   126 	AddFinalHeader(offsetx);
       
   127 
       
   128 #ifdef NO_GAPS
       
   129 	// check there are no gaps or overlaps in the phdrs
       
   130 	Elf32_Word bsz = iBootStrapPHdr.GetPhdrFilesz();
       
   131 	Elf32_Word coffset = iBootStrapPHdr.GetPhdrOffset() + bsz;
       
   132 	Elf32_Addr phys_addr = iBootStrapPHdr.GetPhdrPaddr() + bsz;
       
   133 	ElfPHdrList::iterator aCheckHdr = iElfPHdrList.begin();
       
   134 	ElfPHdrList::iterator endCheckHdr = iElfPHdrList.end();
       
   135 	while(aCheckHdr != endCheckHdr) {
       
   136 		Elf32_Word o = aCheckHdr->GetPhdrOffset();
       
   137 		if (coffset != o){
       
   138 			cerr << "Error: Phdr table broken - offsets incorrect\n";
       
   139 			assert(coffset == o);
       
   140 		}
       
   141 		Elf32_Addr addr = aCheckHdr->GetPhdrPaddr();
       
   142 		if (phys_addr > addr){
       
   143 			cerr << "Error: Phdr table broken - physical addresses incorrect\n";
       
   144 			assert(phys_addr <= addr);
       
   145 		}
       
   146 		size_t sz = aCheckHdr->GetPhdrFilesz();
       
   147 		coffset = o + sz;
       
   148 		phys_addr = addr + sz;
       
   149 		aCheckHdr++;
       
   150 	}
       
   151 #endif
       
   152 	
       
   153 	ElfPHdrList::iterator aHdr = iElfPHdrList.begin();
       
   154 	ElfPHdrList::iterator endHdr = iElfPHdrList.end();
       
   155 	while (aHdr != endHdr) {
       
   156 		aHdr->AddData(iOutputFile);
       
   157 		aHdr++;
       
   158 	}
       
   159 }
       
   160 
       
   161 size_t ElfRom::AddBootStrapProgramHeader(){
       
   162 	iBootStrapPHdr.SetPhdrType(PT_LOAD);
       
   163 	iBootStrapPHdr.SetPhdrOffset(iE32RomImage.GetOffset());
       
   164 	iBootStrapPHdr.SetPhdrVaddr(iRomDetails->iRomPhysAddr);
       
   165 	iBootStrapPHdr.SetPhdrPaddr(iRomDetails->iRomPhysAddr);
       
   166 	iBootStrapPHdr.SetPhdrAlign(4);
       
   167 	iBootStrapPHdr.SetPhdrFlags(PF_X + PF_R);
       
   168 	size_t bootstrapsize = iRomDetails->iXIPFiles[0].iLoadAddr - iRomDetails->iRomBaseLinearAddr;
       
   169 	iBootStrapPHdr.SetPhdrFilesz(bootstrapsize);
       
   170 	iBootStrapPHdr.SetPhdrMemsz(bootstrapsize);
       
   171 		
       
   172 	iBootStrapPHdr.AddData(iOutputFile);
       
   173 	assert((iElf32Header.Size() + iE32RomImage.Size()) == iBootStrapPHdr.GetOffset());
       
   174 	iElf32Header.AddProgramHdr();
       
   175 	iElf32Header.SetProgramHdrOffset(iBootStrapPHdr.GetOffset());
       
   176 	if (iRomDetails->iTrace){
       
   177 		size_t offset = iBootStrapPHdr.GetOffset();
       
   178 		cout << "\nAdded PHdr for bootstrap\n";
       
   179 		cout.fill('0');
       
   180 		cout << hex << "      offset 0x" << setw(8) << offset 
       
   181 			 << " size = 0x" << setw(8) << bootstrapsize << "\n";
       
   182 	}
       
   183 
       
   184 	return iE32RomImage.GetOffset() + bootstrapsize;
       
   185 }
       
   186 
       
   187 static inline size_t InitE32HdrPHdr(ElfPHdr & hdr, size_t offset, Elf32_Word vaddr, Elf32_Word paddr, Elf32_Word size){
       
   188 	hdr.SetPhdrType(PT_LOAD);
       
   189 	hdr.SetPhdrOffset(offset);
       
   190 	hdr.SetPhdrVaddr(vaddr);
       
   191 	hdr.SetPhdrPaddr(paddr);
       
   192 	hdr.SetPhdrAlign(0);
       
   193 	hdr.SetPhdrFlags(PF_R);
       
   194 	hdr.SetPhdrFilesz(size);
       
   195 	hdr.SetPhdrMemsz(size);
       
   196 		
       
   197 	return offset + size;	
       
   198 	
       
   199 }
       
   200 static inline size_t InitROPHdr(ElfPHdr & hdr, size_t offset, Elf32_Word vaddr, Elf32_Word paddr, Elf32_Word size){
       
   201 	hdr.SetPhdrType(PT_LOAD);
       
   202 	hdr.SetPhdrOffset(offset);
       
   203 	hdr.SetPhdrVaddr(vaddr);
       
   204 	hdr.SetPhdrPaddr(paddr);
       
   205 	hdr.SetPhdrAlign(4);
       
   206 	hdr.SetPhdrFlags(PF_X + PF_R);
       
   207 	hdr.SetPhdrFilesz(size);
       
   208 	hdr.SetPhdrMemsz(size);
       
   209 		
       
   210 	return offset + size;	
       
   211 	
       
   212 }
       
   213 
       
   214 static inline size_t InitRWPHdr(ElfPHdr & hdr, size_t offset, Elf32_Word vaddr, Elf32_Word paddr, Elf32_Word fsize, Elf32_Word msize){
       
   215 	hdr.SetPhdrType(PT_LOAD);
       
   216 	hdr.SetPhdrOffset(offset);
       
   217 	hdr.SetPhdrVaddr(vaddr);
       
   218 	hdr.SetPhdrPaddr(paddr);
       
   219 	hdr.SetPhdrAlign(4);
       
   220 	hdr.SetPhdrFlags(PF_X + PF_R);
       
   221 	hdr.SetPhdrFilesz(fsize);
       
   222 	hdr.SetPhdrMemsz(msize);
       
   223 		
       
   224 	return offset + fsize;	
       
   225 	
       
   226 }
       
   227 
       
   228 size_t ElfRom::SetupProgramHeaders(XIPFileDetails & aXIPFileDetails, size_t offset, int addend){
       
   229 	ElfPHdr e32hdr;
       
   230 	Elf32_Word e32hdrVaddr = aXIPFileDetails.iLoadAddr;
       
   231 	Elf32_Word e32hdrPaddr = aXIPFileDetails.iLoadAddr + addend;
       
   232 	Elf32_Word e32hdrSize = aXIPFileDetails.iROAddr - aXIPFileDetails.iLoadAddr ;
       
   233 	size_t e32hdrOffsetInRom = aXIPFileDetails.iLoadAddr - iRomDetails->iRomBaseLinearAddr;
       
   234 	size_t e32hdrOffsetInElf = iE32RomImage.GetOffset() + e32hdrOffsetInRom;
       
   235 #ifdef NO_GAPS
       
   236 	// But actually the offset we'll use is the one we were given as an argument.
       
   237 	// This means we need to adjust the size, vaddr and paddr by the difference
       
   238 	size_t diff = e32hdrOffsetInElf - offset;
       
   239 	e32hdrSize += diff;
       
   240 	e32hdrVaddr -= diff;
       
   241 	e32hdrPaddr -= diff;
       
   242 	offset = InitE32HdrPHdr(e32hdr, offset, e32hdrVaddr, e32hdrPaddr, e32hdrSize);
       
   243 #else
       
   244 	offset = InitE32HdrPHdr(e32hdr, e32hdrOffsetInElf, e32hdrVaddr, e32hdrPaddr, e32hdrSize);
       
   245 #endif
       
   246 	iElf32Header.AddProgramHdr();
       
   247 	iElfPHdrList.push_back(e32hdr);
       
   248 	ElfPHdr thdr;
       
   249 	Elf32_Word textVaddr = aXIPFileDetails.iROAddr;
       
   250 	Elf32_Word textPaddr = aXIPFileDetails.iROAddr + addend;
       
   251 	Elf32_Word textSize = aXIPFileDetails.iROSize;
       
   252 	size_t textOffsetInRom = aXIPFileDetails.iROAddr - iRomDetails->iRomBaseLinearAddr;
       
   253 	size_t textOffsetInElf = iE32RomImage.GetOffset() + textOffsetInRom;
       
   254 	offset = InitROPHdr(thdr, textOffsetInElf, textVaddr, textPaddr, textSize);
       
   255 	iElf32Header.AddProgramHdr();
       
   256 	iElfPHdrList.push_back(thdr);
       
   257 
       
   258 	if (iRomDetails->iTrace){
       
   259 		cout << "  " << aXIPFileDetails.iE32File << "\n";
       
   260 		cout.fill(' ');
       
   261 		cout << left << "    .text\n";
       
   262 		cout.fill('0');
       
   263 		cout << "      paddr = 0x" << right << setw(8) << textPaddr << " vaddr = 0x" << right << setw(8)<< textVaddr
       
   264 		     << " offset = 0x" << right << setw(8) << textOffsetInElf 
       
   265 			 << " size = 0x" << setw(8) << textSize << "\n" << flush;
       
   266 	}
       
   267 	
       
   268 	if (aXIPFileDetails.iRWSize > 0){
       
   269 		ElfPHdr dhdr;
       
   270 		Elf32_Word dataVaddr = aXIPFileDetails.iRWAddr;
       
   271 		Elf32_Word dataPaddr = aXIPFileDetails.iROMDataAddr + addend;
       
   272 		Elf32_Word fsize = aXIPFileDetails.iRWSize;
       
   273 		Elf32_Word msize = aXIPFileDetails.iBSSDataSize;
       
   274 		size_t dataOffsetInRom = aXIPFileDetails.iROMDataAddr - iRomDetails->iRomBaseLinearAddr;
       
   275 		size_t dataOffsetInElf = iE32RomImage.GetOffset() + dataOffsetInRom;
       
   276 		offset = InitRWPHdr(dhdr, dataOffsetInElf, dataVaddr, dataPaddr, fsize, msize);
       
   277 		iElf32Header.AddProgramHdr();
       
   278 		iElfPHdrList.push_back(dhdr);
       
   279 		
       
   280 		if (iRomDetails->iTrace){
       
   281 			cout.fill(' ');
       
   282 			cout << left << "    .data\n";
       
   283 			cout.fill('0');
       
   284 			cout << "      paddr = 0x" << right << setw(8) << dataPaddr << " vaddr = 0x" << right << setw(8)<< dataVaddr  
       
   285 				 << " offset = 0x" << right << setw(8)<< dataOffsetInElf
       
   286 				 << " size = 0x" << right << setw(8) << fsize << "\n" << flush;
       
   287 		}
       
   288 		
       
   289 	}
       
   290 	return offset;
       
   291 }
       
   292 
       
   293 // This adds a header for the remainder of the ROM image after the last XIP file
       
   294 size_t ElfRom::AddFinalHeader(size_t offset){
       
   295 	ElfPHdr & lastHdr = iElfPHdrList.back();
       
   296 	Elf32_Word startAddr = lastHdr.GetPhdrPaddr() + lastHdr.GetPhdrFilesz();
       
   297 	ElfPHdr e32hdr;
       
   298 	Elf32_Word e32hdrVaddr = startAddr;
       
   299 	Elf32_Word e32hdrPaddr = startAddr;
       
   300 	Elf32_Word e32hdrSize = iE32RomImage.Size() - offset + iE32RomImage.GetOffset();
       
   301 
       
   302 	offset = InitE32HdrPHdr(e32hdr, offset, e32hdrVaddr, e32hdrPaddr, e32hdrSize);
       
   303 
       
   304 	iElf32Header.AddProgramHdr();
       
   305 	iElfPHdrList.push_back(e32hdr);	
       
   306 	
       
   307 	if (iRomDetails->iTrace){
       
   308 		cout << "\nAdded final PHdr\n" << "      offset 0x" << hex << right << setw(8) << offset 
       
   309 			<< " size = 0x" << setw(8) << e32hdrSize << "\n";
       
   310 	}
       
   311 	return offset;
       
   312 }
       
   313 
       
   314 void ElfRom::SetupAuxilarySections(){
       
   315 	SetupLogFile();
       
   316 }
       
   317 
       
   318 void ElfRom::SetupLogFile(){
       
   319 	if (!iRomDetails->iLogFile.size()) return;
       
   320 	InputFile * aLogFile = new InputFile(iRomDetails->iLogFile);
       
   321 	ElfSectionFileData * aLogFileData = new ElfSectionFileData(aLogFile);
       
   322 	Elf32_Shdr shdr;
       
   323 	shdr.sh_name = 0; // for now.
       
   324 	shdr.sh_offset = 0; // for now
       
   325 	shdr.sh_info = 0;
       
   326 	shdr.sh_link = SHN_UNDEF;
       
   327 	shdr.sh_addr = 0;
       
   328 	shdr.sh_addralign = 0;
       
   329 	shdr.sh_type = SHT_PROGBITS;
       
   330 	shdr.sh_size = 0; // for now.
       
   331 	shdr.sh_flags = 0;
       
   332 	shdr.sh_entsize = 0;
       
   333 
       
   334 	ElfSection aLogFileSection(aLogFileData, "ROMLogFile", shdr);
       
   335 	iElfSectionManager.AddSection(aLogFileSection);
       
   336 
       
   337 }
       
   338 
       
   339 void ElfRom::SetupELFRomData() {
       
   340 	SetupProgramHeaderTable();
       
   341 	SetupAuxilarySections();
       
   342 	if (!iRomDetails->iStrip){
       
   343 		SetupSectionHeaderTable();
       
   344 		SetupSymbolTable();
       
   345 		if (!iRomDetails->iNoDwarf){
       
   346 			SetupDwarfSections();
       
   347 		}
       
   348 	}
       
   349 }
       
   350 
       
   351 void ElfRom::SetupSectionHeaderTable(){
       
   352 	RomDetails::XIPFileList::iterator aXIPFile = iRomDetails->iXIPFiles.begin();
       
   353 	RomDetails::XIPFileList::iterator end = iRomDetails->iXIPFiles.end();
       
   354 
       
   355 	if (iRomDetails->iTrace && aXIPFile != end){
       
   356 		cout << "\nAdding Section headers from associated ELF files\n";
       
   357 	}
       
   358 
       
   359 	while (aXIPFile != end) {
       
   360 		SetupSectionHeaders(*aXIPFile);
       
   361 		aXIPFile++;
       
   362 	}
       
   363 }
       
   364 
       
   365 void ElfRom::SetupSectionHeaders(XIPFileDetails & aXIPFileDetails) {
       
   366 	// Open ELF file
       
   367 	PathName aPath = aXIPFileDetails.iElfFile;
       
   368 	
       
   369 	if (aPath.size() == 0) return;
       
   370 	
       
   371 	int fd;
       
   372 	Elf * e;
       
   373 	size_t shstrndx;
       
   374 	bool hasSectionStringTable = true;
       
   375 
       
   376 
       
   377 	if ((fd = open(aPath.c_str(), O_RDONLY|O_BINARY, 0)) < 0){
       
   378 		warnx(EX_NOINPUT, "open \"%s\" failed\n", aPath.c_str());
       
   379 		goto finish;
       
   380 	}
       
   381 	if ((e = elf_begin(fd, ELF_C_READ , NULL)) == NULL)
       
   382 		errx(EX_SOFTWARE, "elf_begin() failed: %s.\n", elf_errmsg(-1));
       
   383 	if (elf_kind(e) != ELF_K_ELF)
       
   384 		errx(EX_SOFTWARE, "file not of kind ELF_K_ELF: %s.\n", aPath.c_str());
       
   385 	if (elf_getshstrndx(e, &shstrndx) == 0) {
       
   386 		hasSectionStringTable = false;
       
   387 		warnx(EX_SOFTWARE, "getshstrndx() failed for \"%s\"\n", aPath.c_str());
       
   388 	}
       
   389 	if (hasSectionStringTable){
       
   390 		SetUpSegmentInfo(aXIPFileDetails, e);
       
   391 		SetupSectionHeaders(aXIPFileDetails, e, shstrndx);
       
   392 	}
       
   393 
       
   394 	elf_end(e);
       
   395 	close(fd);	
       
   396 finish:
       
   397 	return;
       
   398 }
       
   399 
       
   400 void ElfRom::SetupSectionHeaders(XIPFileDetails & aXIPFileDetails, Elf * e, size_t shstrndx){
       
   401 	// Iterate through sections looking for the ones we're after. Namely:
       
   402 	// text, data, bss/zi, symtab, strtable,  and .debug*
       
   403 	Elf_Scn * scn = NULL; 
       
   404 	Elf32_Shdr * shdr;
       
   405 	SectionNumberMap aSectionNumberMap;
       
   406 	SectionVaddrAddendMap aSectionVaddrAddendMap;
       
   407 
       
   408 	String aPath(aXIPFileDetails.iElfFile);
       
   409 	
       
   410 	const char * debugName = ".debug";
       
   411 	const size_t debugNameLength = strlen(debugName);
       
   412 	const char * staticStrTab = ".strtab";
       
   413 	
       
   414 	if (iRomDetails->iTrace){
       
   415 		cout << "  " << aXIPFileDetails.iElfFile << "\n";
       
   416 	}
       
   417 	
       
   418 	while ((scn = elf_nextscn(e, scn)) != NULL) {
       
   419 
       
   420     	if ((shdr = elf32_getshdr(scn)) == NULL)
       
   421     		errx(EX_SOFTWARE, "getshdr() failed: %s.\n", elf_errmsg(-1));
       
   422     	
       
   423 		size_t aOldNdx = elf_ndxscn(scn);
       
   424     	char * name = elf_strptr(e, shstrndx, shdr->sh_name);
       
   425     	VirtualAddr sectionAddr = shdr->sh_addr;
       
   426 
       
   427     	switch (shdr->sh_type) {
       
   428     	case SHT_NOBITS:
       
   429     		// Check for BSS or ZI
       
   430     		if ((shdr->sh_flags & SHF_WRITE) && (shdr->sh_flags & SHF_ALLOC)) {
       
   431     			// set up section number mapping
       
   432     			size_t aNew = AddBssSectionHeader(aXIPFileDetails, shdr, name);
       
   433     			aSectionNumberMap.push_back(SectionNumberMapping(aOldNdx, aNew));
       
   434     			// set up address adjustment for relocation of e.g. symbols
       
   435     			int addend = aXIPFileDetails.iBSSAddr - sectionAddr;
       
   436     			aSectionVaddrAddendMap.push_back(SectionVaddrAddendMapping(aOldNdx, addend));
       
   437     		}
       
   438     		break;
       
   439 #define ARM_EXIDX	(SHT_LOPROC + 1)
       
   440     	case ARM_EXIDX:    		
       
   441     	case SHT_PROGBITS:
       
   442     		// text/ro or data/rw will have SHF_ALLOC set
       
   443     		if (shdr->sh_flags & SHF_ALLOC) {
       
   444     			size_t aNew = 0;
       
   445     		    int addend = 0;
       
   446     		    if (shdr->sh_flags & SHF_WRITE) {
       
   447     				aNew = AddRwSectionHeader(aXIPFileDetails, shdr, name);
       
   448     				addend = aXIPFileDetails.iRWAddr - sectionAddr;
       
   449     		    } else {
       
   450     				aNew = AddRoSectionHeader(aXIPFileDetails, shdr, name);
       
   451     				addend = aXIPFileDetails.iROAddr - sectionAddr;
       
   452     		    }
       
   453     			// set up section number mapping
       
   454     		    aSectionNumberMap.push_back(SectionNumberMapping(aOldNdx, aNew)); 
       
   455     			// set up address adjustment for relocation of e.g. symbols
       
   456     		    aSectionVaddrAddendMap.push_back(SectionVaddrAddendMapping(aOldNdx, addend));     	
       
   457     		} else if (!iRomDetails->iNoDwarf && !strncmp(debugName, name, debugNameLength)) {
       
   458     			iDwarfFound = true;
       
   459     			iDwarfManager.AddSection(aXIPFileDetails, name, shdr);
       
   460     		}
       
   461     		break;
       
   462     	case SHT_SYMTAB:
       
   463     		iElfSymbolTableManager.AddSymbolTable(aPath, shdr->sh_offset, shdr->sh_size, shdr->sh_info);
       
   464     		break;
       
   465     	case SHT_STRTAB:
       
   466     		if (!strcmp(staticStrTab, name))
       
   467     			iElfSymbolTableManager.AddStringTable(aPath, shdr->sh_offset, shdr->sh_size);
       
   468     		break;
       
   469     	}
       
   470     }
       
   471 	iElfSymbolTableManager.Finalize(aSectionNumberMap, aSectionVaddrAddendMap);
       
   472 }
       
   473 
       
   474 size_t ElfRom::AddRoSectionHeader(XIPFileDetails & aXIPFileDetails, Elf32_Shdr * aShdr, char * aName){
       
   475 	size_t delta = aShdr->sh_addr - aXIPFileDetails.iElfTextBase;
       
   476 	VirtualAddr vaddr = aXIPFileDetails.iROAddr + delta;
       
   477 	size_t offsetInRom = vaddr - iRomDetails->iRomBaseLinearAddr;
       
   478 	size_t offsetInElf = iE32RomImage.GetOffset() + offsetInRom;
       
   479 	aShdr->sh_addr = vaddr;
       
   480 	return AddROMSectionHeader(aXIPFileDetails, aShdr, aName, offsetInElf );
       
   481 }
       
   482 
       
   483 size_t ElfRom::AddRwSectionHeader(XIPFileDetails & aXIPFileDetails, Elf32_Shdr * aShdr, char * aName){		
       
   484 	size_t delta = aShdr->sh_addr - aXIPFileDetails.iElfDataBase;
       
   485 	VirtualAddr vaddr = aXIPFileDetails.iROMDataAddr + delta;
       
   486 	size_t offsetInRom = vaddr - iRomDetails->iRomBaseLinearAddr;
       
   487 	size_t offsetInElf = iE32RomImage.GetOffset() + offsetInRom;	
       
   488 	aShdr->sh_addr = aXIPFileDetails.iRWAddr;
       
   489 	return AddROMSectionHeader(aXIPFileDetails, aShdr, aName, offsetInElf);
       
   490 }
       
   491 
       
   492 size_t ElfRom::AddBssSectionHeader(XIPFileDetails & aXIPFileDetails, Elf32_Shdr * aShdr, char * aName){	
       
   493 	size_t delta = aShdr->sh_addr - aXIPFileDetails.iElfDataBase;
       
   494 	VirtualAddr vaddr = aXIPFileDetails.iROMDataAddr + delta;
       
   495 	size_t offsetInRom = vaddr - iRomDetails->iRomBaseLinearAddr;
       
   496 	size_t offsetInElf = iE32RomImage.GetOffset() + offsetInRom;	
       
   497 	aShdr->sh_addr = aXIPFileDetails.iBSSAddr;
       
   498 	return AddROMSectionHeader(aXIPFileDetails, aShdr, aName, offsetInElf);
       
   499 }
       
   500 
       
   501 size_t ElfRom::AddROMSectionHeader(XIPFileDetails & aXIPFileDetails, Elf32_Shdr * aShdr, char * aName, size_t aOffset){	
       
   502 	ElfSectionData * romData = aOffset ? 
       
   503 								(ElfSectionData *)new ElfSectionRomData(aOffset, aShdr->sh_size) 
       
   504 								: (ElfSectionData *)new ElfSectionNoData();
       
   505 	ElfSection aSection(romData, aName, *aShdr);
       
   506 	iElfSectionManager.AddSection(aSection);
       
   507 	
       
   508 	if (iRomDetails->iTrace){
       
   509 		cout.fill(' ');
       
   510 		cout << "    " << left << setw(22) << aName << "\n";
       
   511 		cout.fill('0');
       
   512 		cout << "      vaddr = 0x" << right << hex << setw(8) << aShdr->sh_addr << " offset = 0x" 
       
   513 			 << right << hex << setw(8) << aOffset 
       
   514 			 << " size = 0x" << right << hex << setw(8) << aShdr->sh_size << "\n";
       
   515 	}
       
   516 	return aSection.GetIndex();
       
   517 }
       
   518 
       
   519 void ElfRom::SetUpSegmentInfo(XIPFileDetails & aXIPFileDetails, Elf * e){
       
   520 	Elf32_Ehdr * ehdr = elf32_getehdr(e);
       
   521 	if (ehdr == NULL)
       
   522 		errx(EX_SOFTWARE, "elf32_getehdr() failed: %s.", elf_errmsg(-1));
       
   523 	size_t n = ehdr->e_phnum;
       
   524 	Elf32_Phdr * phdr = elf32_getphdr(e);
       
   525 	if (phdr == NULL)
       
   526 		errx(EX_SOFTWARE, "elf32_getphdr() failed: %s.", elf_errmsg(-1));
       
   527 
       
   528 	for (size_t i = 0; i < n; i++) {
       
   529 		if (phdr[i].p_flags & PF_X){
       
   530 			VirtualAddr segmentAddr = phdr[i].p_vaddr;
       
   531 	    	aXIPFileDetails.iElfTextBase = segmentAddr;
       
   532 	    	aXIPFileDetails.iElfTextLimit = segmentAddr + phdr[i].p_memsz;
       
   533 			
       
   534 		} else if (phdr[i].p_flags & PF_W){
       
   535 	    	aXIPFileDetails.iElfDataBase = phdr[i].p_vaddr;
       
   536 		}
       
   537 	}	
       
   538 }
       
   539 
       
   540 void ElfRom::SetupSymbolTable(){
       
   541 	iElfSymbolTableManager.AddSymbolTable();
       
   542 	if (iRomDetails->iTrace){
       
   543 		cout << "\nAdded section headers for combined symbol table and symbol string table\n";
       
   544 	}
       
   545 }
       
   546 
       
   547 void ElfRom::SetupDwarfSections(){
       
   548 	if (iRomDetails->iTrace && iDwarfFound){
       
   549 		cout << "\nSetting up Dwarf Sections\n";
       
   550 	} else if (iRomDetails->iTrace && !iDwarfFound && !iRomDetails->iNoDwarf){
       
   551 		cout << "\nWarning: No Dwarf information found\n";
       
   552 		return;
       
   553 	}
       
   554 	iDwarfManager.SetupSections();
       
   555 }
       
   556 
       
   557 void ElfRom::AddData() {
       
   558 	iElfSectionManager.AddData();
       
   559 	iElf32Header.SetSectionHdrOffset(iElfSectionManager.GetOffset());
       
   560 }
       
   561 
       
   562 void ElfRom::Dump(){
       
   563 	iOutputFile.Dump();
       
   564 	if (iRomDetails->iTrace){
       
   565 		cout << "\nWrote " << iRomDetails->iElfRomFile << " " << dec << iOutputFile.Size() << " bytes\n";
       
   566 	}	
       
   567 }