diff -r c7c26511138f -r 360bd6b35136 bintools/elftools/elftran/elf_file.cpp --- a/bintools/elftools/elftran/elf_file.cpp Wed Jun 16 16:51:40 2010 +0300 +++ b/bintools/elftools/elftran/elf_file.cpp Wed Jun 23 16:56:47 2010 +0800 @@ -1,540 +1,527 @@ -/* -* Copyright (c) 2001-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 -#include -#include "elftran.h" -#include -#include "elffile.h" -#include "elfdll.h" -#include -#include -#include - -TBool hadText, hadReloc = EFalse; - -ELFFile::ELFFile() - : - iHeapCommittedSize(0x1000), - iHeapReservedSize(0x100000), - iStackCommittedSize(0), - - iFileName(0), - iFileHandle(-1), - iElfFile(0), - - iDynamicSegmentHdr(0), - iDynamicSegmentIdx(0), - - iCodeSegmentHdr(0), - iCodeSegmentIdx(0), - - iDataSegmentHdr(0), - iDataSegmentIdx(0), - - iDllData(0), - iCpu(ECpuUnknown) - {} - - - - -ELFFile::~ELFFile() - { - delete [] iFileName; - delete iElfFile; - delete iDllData; - } - - -TBool ELFFile::Init(const TText * const aFileName) -// -// Read the ELF file into memory -// - { - - delete [] iFileName; - iFileName = new TText[strlen((const char *)aFileName)+1]; - strcpy ((char *)iFileName, (const char *)aFileName); - - TInt error = HFile::Open(iFileName, &iFileHandle); - if (error!=0) - return EFalse; - - TInt flength = HFile::GetLength(iFileHandle); - - iElfFile = (Elf32_Ehdr *)HMem::Alloc(0,flength); - if (!iElfFile) - { - Print(EPeError,"Failed to allocate memory to read in file.\n"); - Close(); - return EFalse; - } - - if (!HFile::Read(iFileHandle,iElfFile,flength)) - { - Print(EPeError,"Unable to read file %s.\n",iFileName); - Close(); - return EFalse; - } - - Close(); - - if (!IsValidFileHeader(iElfFile)) - { - Print(EPeError,"Invalid file header.\n"); - return EFalse; - } - // we only support this....for the moment - iCpu = ECpuArmV4; - - if (!InitHeaders()) return EFalse; - - if (!InitDllData()) return EFalse; - - iEntryPoint = iElfFile->e_entry; - - iCodeSize = GetCodeSize(); - iDataSize = GetDataSize(); - iBssSize = GetBssSize(); - - iStackReservedSize = 0x2000; - iStackCommittedSize = 0x2000; - - iLinkedBase = iCodeSegmentHdr->p_vaddr; - - iImageIsDll = iDllData->ImageIsDll(); - - return ETrue; - } - -char * ELFFile::CreateImportSection(TInt &aSize) -// -// get ELFDLLData to do it -// - { - TInt size; - char * newSection = iDllData->CreateImportSection(size); - aSize = size; - return newSection; - } - -TUint ELFFile::GetExportTableOffset(void) - { - return iDllData->GetExportTableOffset(); - } - -TBool ELFFile::InitHeaders(void) - { - TInt nphdrs = iElfFile->e_phnum; - if (nphdrs) - { - // Find the dynamic segment - Elf32_Phdr * aPhdr = ELFADDR(Elf32_Phdr, iElfFile, iElfFile->e_phoff); - iPhdr = aPhdr; - for (TInt idx = 0; idx < nphdrs; idx++) - { - Elf32_Word ptype = aPhdr[idx].p_type; - if (ptype == PT_DYNAMIC) - { - iDynamicSegmentHdr = &aPhdr[idx]; - iDynamicSegmentIdx = idx; - } - else if (ptype == PT_LOAD && - (aPhdr[idx].p_flags & (PF_X + PF_ARM_ENTRY))) - { - iCodeSegmentHdr = &aPhdr[idx]; - iCodeSegmentIdx = idx; - } - else if (ptype == PT_LOAD && - (aPhdr[idx].p_flags & (PF_W + PF_R))) - { - iDataSegmentHdr = &aPhdr[idx]; - iDataSegmentIdx = idx; - } - } - } - - // cache pointer to symbol table - - // Get section header table - Elf32_Shdr * s = ELFADDR(Elf32_Shdr, iElfFile, iElfFile->e_shoff); - // Index of section header for section header string table - TInt stIdx = iElfFile->e_shstrndx; - TInt symIdx = -1; - // Section name string table - char * stringtable = ELFADDR(char, iElfFile, s[stIdx].sh_offset); - // the index at which we find '.symtab' is the index of the symtab section - for (TInt idx = 0; idx < iElfFile->e_shnum; idx++) - { - if (idx != stIdx) - { - if (!strcmp(&stringtable[s[idx].sh_name], ".symtab")) - { - symIdx = idx; - break; - } - } - } - if (symIdx == -1) return EFalse; - - // save section header table - iSectionHeaderTable = s; - // save the index - iSymIdx = symIdx; - // here's the symbol table - iSymTab = ELFADDR(Elf32_Sym, iElfFile, s[symIdx].sh_offset); - return ETrue; - } - -TBool ELFFile::InitDllData(void) - { - if (!iDynamicSegmentHdr) - { -#if defined(_DEBUG) - Print(EWarning, "Image '%s' has no import/export data.\n", iFileName); -#endif - return ETrue; - } - iDllData = new ELFDllData(this); - if (!iDllData) - { - Print(EPeError, "Out of memory allocating DLL data\n"); - return EFalse; - } - - Elf32_Dyn * dyn = ELFADDR(Elf32_Dyn, iElfFile, iDynamicSegmentHdr->p_offset); - TInt idx = 0; - TInt soNameOffset = 0; - while(dyn[idx].d_tag != DT_NULL) // best to make it explicit - { - switch (dyn[idx].d_tag) - { - case DT_HASH: - iDllData->iHashTable = ELFADDR(Elf32_HashTable, dyn, dyn[idx].d_val); - break; - case DT_STRTAB: - iDllData->iDynStrTab = ELFADDR(char, dyn, dyn[idx].d_val); - break; - case DT_SYMTAB: - iDllData->iDynSymTab = ELFADDR(Elf32_Sym, dyn, dyn[idx].d_val); - break; - case DT_RELA: - iDllData->iRela = ELFADDR(Elf32_Rela, dyn, dyn[idx].d_val); - break; - case DT_RELASZ: - iDllData->iRelaSz = dyn[idx].d_val; - break; - case DT_RELAENT: - iDllData->iRelaSz = dyn[idx].d_val; - break; - case DT_STRSZ: - iDllData->iDynStrTabSize = dyn[idx].d_val; - break; - case DT_ARM_SYMTABSZ_21: //For RVCT2.1 - //iDllData->iDynSymTabSize = dyn[idx].d_val; - case DT_ARM_SYMTABSZ: - /* This is same as DT_ARM_SYMTABSZ_21, but for RVCT 2.2 - * The tag value has been changed for RVC2.2 from RVCT2.1. - * We just ignore this. i.e., we get the symbol table size - * from the nchain field of the hash table as noted in section - * 3.2.2.2 of the BPABI. - */ - break; - case DT_SYMENT: - iDllData->iSymSize = dyn[idx].d_val; - break; - case DT_SONAME: - soNameOffset = dyn[idx].d_val; - break; - case DT_REL: - iDllData->iRel = ELFADDR(Elf32_Rel, dyn, dyn[idx].d_val); - break; - case DT_RELSZ: - iDllData->iRelSz = dyn[idx].d_val; - break; - case DT_RELENT: - iDllData->iRelEnt = dyn[idx].d_val; - break; - case DT_NEEDED: - iDllData->AddToDependency(dyn[idx].d_val); - break; - case DT_PLTRELSZ: - case DT_PLTGOT: - case DT_INIT: - case DT_FINI: - case DT_RPATH: - case DT_SYMBOLIC: - case DT_PLTREL: - case DT_DEBUG: - case DT_TEXTREL: - case DT_JMPREL: - case DT_BIND_NOW: - break; - default: - Print(EPeError,"Unrecognized Dyn Array tag in image '%s'.\n", iFileName); - return EFalse; - } - idx++; - } - return iDllData->Init(); - } - - -void ELFFile::Close() -// -// close the ELF file -// - { - HFile::Close(iFileHandle); - } - - - -TInt ELFFile::NumberOfImports() const -// -// Count the total number of imports for this image -// - { - return iDllData->NumberOfImports(); - } - -TInt ELFFile::NumberOfImportDlls() const -// -// Count the number of referenced Dlls -// - { - return iDllData->NumberOfImportDlls(); - } - -TInt ELFFile::NumberOfExports() const -// -// Count the number of exported symbols -// - { - return iDllData->NumberOfExports(); - } - -TInt ELFFile::NumberOfCodeRelocs() - { - return iDllData->NumberOfCodeRelocs(); - } - -TInt ELFFile::NumberOfDataRelocs() - { - return iDllData->NumberOfDataRelocs(); - } - -Elf32_Phdr * ELFFile::GetSegmentFromAddr(Elf32_Addr addr) - { - TInt nphdrs = iElfFile->e_phnum; - for (TInt idx = 0; idx < nphdrs; idx++) - { - // take advantage of unsignedness - if ((addr - iPhdr[idx].p_vaddr) < iPhdr[idx].p_memsz) return &iPhdr[idx]; - } - return NULL; - } - - -TInt ELFFile::NumberOfRelocs() - { - return iDllData->NumberOfRelocs(); - } - -TUint16 ELFFile::GetRelocType(Elf32_Rel *aReloc) - { - // We work out the type by figuring out the segment of the reloc - TInt segmentIdx = ELF32_R_SYM(aReloc->r_info); - - // check to see if its a reserved or special index. - if ((!segmentIdx) || ((segmentIdx >= SHN_LORESERVE) && (segmentIdx <= SHN_HIRESERVE))) - // up until now these have been treated as KInferredRelocType, so lets continue... - return KInferredRelocType; - - // need to see if this section is executable or writable - if (iPhdr[segmentIdx-1].p_flags & PF_X) - return KTextRelocType; - if (iPhdr[segmentIdx-1].p_flags & PF_W) - return KDataRelocType; - // perhaps we should error here. - return KInferredRelocType; - } - -TBool ELFFile::GetRelocs(Elf32_Rel **aCodeRelocs, Elf32_Rel **aDataRelocs) - { - return iDllData->GetRelocs(aCodeRelocs, aDataRelocs); - } - -TUint ELFFile::GetCodeSize() - { - return iCodeSegmentHdr->p_filesz; - } - -TBool ELFFile::HasInitialisedData() - { - return iDataSegmentHdr != NULL && iDataSegmentHdr->p_filesz != 0; - } - -TUint ELFFile::GetDataSize() - { - return iDataSegmentHdr != NULL ? iDataSegmentHdr->p_filesz : 0; - } - -TBool ELFFile::HasBssData() - { - return iDataSegmentHdr != NULL && (iDataSegmentHdr->p_memsz - iDataSegmentHdr->p_filesz) != 0; - } - -TUint ELFFile::GetBssSize() - { - return iDataSegmentHdr != NULL ? iDataSegmentHdr->p_memsz - iDataSegmentHdr->p_filesz: 0; - } - - - - - - -TBool ELFFile::IsValidFileHeader(Elf32_Ehdr * iElfFile) - { - if (!(iElfFile->e_ident[EI_MAG0] == ELFMAG0 && - iElfFile->e_ident[EI_MAG1] == ELFMAG1 && - iElfFile->e_ident[EI_MAG2] == ELFMAG2 && - iElfFile->e_ident[EI_MAG3] == ELFMAG3)) - { - Print(EPeError,"Invalid ELF magic.\n"); - return EFalse; - } - - if (iElfFile->e_ident[EI_CLASS] != ELFCLASS32) - { - Print(EPeError,"File is not a 32 bit object file.\n"); - return EFalse; - } - if (iElfFile->e_ident[EI_DATA] != ELFDATA2LSB) - { - Print(EPeError,"File data encoding is not Little Endian.\n"); - return EFalse; - } - - if (iElfFile->e_machine != EM_ARM) - { - Print(EPeError,"File does not target ARM/THUMB processors.\n"); - return EFalse; - } - - if (!(iElfFile->e_type == ET_EXEC || iElfFile->e_type == ET_DYN)) - { - Print(EPeError,"File is neither an executable nor a shared object\n"); - return EFalse; - } - - return ETrue; - } - - -// Get details of the next import to fix-up in the current file. Fill in the name of the dll -//it is imported from, the ordinal number and the address to write back to. -#define ORDINAL_DONE 0x40000000 - - -// The following static functions are passed an array of PE files to operate on - -Elf32_Sym * ELFFile::FindSymbol(const TText *aName) - { - Elf32_Shdr * s = ELFADDR(Elf32_Shdr, iElfFile, iElfFile->e_shoff); - TInt symIdx = iSymIdx; - Elf32_Sym * sym = iSymTab; - TInt nSyms = s[symIdx].sh_size / s[symIdx].sh_entsize; - char * symStringtable = ELFADDR(char, iElfFile, s[s[symIdx].sh_link].sh_offset); - for (TInt jdx = 0; jdx < nSyms; jdx++) - { - if (!strcmp(&symStringtable[sym[jdx].st_name], (char *)aName)) - return &sym[jdx]; - } - return (Elf32_Sym *)0; - } - -TBool ELFFile::SymbolPresent(TText *aName) - { - return (FindSymbol(aName) != 0); - } - -TBool ELFFile::GetExceptionIndexInfo(TUint32 &aOffset) - { - const TText * aBase = (TText *)".ARM.exidx$$Base"; - const TText * aLimit = (TText *)".ARM.exidx$$Limit"; - Elf32_Sym * exidxBase = FindSymbol(aBase); - Elf32_Sym * exidxLimit = FindSymbol(aLimit); - if (exidxBase && exidxLimit && (exidxLimit->st_value - exidxBase->st_value)) - { - const TText * aExceptionDescriptor = (TText *)"Symbian$$CPP$$Exception$$Descriptor"; - Elf32_Sym * aED = FindSymbol(aExceptionDescriptor); - if (aED) - { - // Set bottom bit so 0 in header slot means an old binary. - // The decriptor is always aligned on a 4 byte boundary. - aOffset = (aED->st_value - iLinkedBase) | 0x00000001; - return ETrue; - } - else - { - Print(EPeError,"Executable has exception table but no exception descriptor\n"); - exit(666); - } - } - return EFalse; - } - -TBool ELFFile::SetUpLookupTable() -{ - if(!iDllData->CreateSymLookupTable() ) { - Print(EPeError,"Failed to create named symbol lookup information\n"); - return FALSE; - } - if(!iDllData->CreateDependency()){ - Print(EPeError,"Failed to create dependency ordering for named symbol lookup\n"); - return FALSE; - } - - iDllData->SetExportSymInfo(); - return TRUE; -} - -void ELFFile::GetExportSymInfoHeader(E32EpocExpSymInfoHdr& aSymInfoHdr) -{ - iDllData->GetExportSymInfoHeader(aSymInfoHdr); -} - -void ELFFile::SetLookupTblBase(TInt aBaseOffset) -{ - iDllData->SetLookupTblBase(aBaseOffset); -} - -TInt ELFFile::GetLookupTblSize() -{ - return iDllData->GetLookupTblSize(); -} - -TUint ELFFile::GetSymLookupSection(char* aBuff) -{ - return iDllData->GetSymLookupSection(aBuff); -} - +/* +* Copyright (c) 2001-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 +#include +#include "elftran.h" +#include "elfdefs.h" +#include "elffile.h" +#include "elfdll.h" +#include "h_utl.h" +#include +#include + +TBool hadText, hadReloc = EFalse; + +ELFFile::ELFFile() + : iHeapCommittedSize(0x1000), iHeapReservedSize(0x100000), iStackCommittedSize(0), + iFileName(0), iFileHandle(-1) , iElfFile(0), + iDynamicSegmentHdr(0), iDynamicSegmentIdx(0), + iCodeSegmentHdr(0), iCodeSegmentIdx(0), + iDataSegmentHdr(0), iDataSegmentIdx(0), + iDllData(0), iCpu(ECpuUnknown) + {} + +ELFFile::~ELFFile() + // + // Destructor + // + { + if(iFileName) + delete [] iFileName; + delete iElfFile; + delete iDllData; + } + + +TBool ELFFile::Init(const char* aFileName) +// +// Read the ELF file into memory +// + { + if(iFileName){ + delete [] iFileName; + iFileName = 0; + } + size_t length = strlen(aFileName) + 1 ; + iFileName = new char[length]; + memcpy (iFileName, aFileName,length); + + TInt error = HFile::Open(iFileName, &iFileHandle); + if (error!=0) + return EFalse; + + TInt flength = HFile::GetLength(iFileHandle); + + iElfFile = (Elf32_Ehdr *)HMem::Alloc(0,flength); + if (!iElfFile) + { + Print(EPeError,"Failed to allocate memory to read in file.\n"); + Close(); + return EFalse; + } + + if (!HFile::Read(iFileHandle,iElfFile,flength)) + { + Print(EPeError,"Unable to read file %s.\n",iFileName); + Close(); + return EFalse; + } + + Close(); + + if (!IsValidFileHeader(iElfFile)) + { + Print(EPeError,"Invalid file header.\n"); + return EFalse; + } + // we only support this....for the moment + iCpu = ECpuArmV4; + + if (!InitHeaders()) return EFalse; + + if (!InitDllData()) return EFalse; + + iEntryPoint = iElfFile->e_entry; + + iCodeSize = GetCodeSize(); + iDataSize = GetDataSize(); + iBssSize = GetBssSize(); + + iStackReservedSize = 0x2000; + iStackCommittedSize = 0x2000; + + iLinkedBase = iCodeSegmentHdr->p_vaddr; + + iImageIsDll = iDllData->ImageIsDll(); + + return ETrue; + } + +char * ELFFile::CreateImportSection(TInt &aSize) +// +// get ELFDLLData to do it +// + { + TInt size; + char * newSection = iDllData->CreateImportSection(size); + aSize = size; + return newSection; + } + +TUint ELFFile::GetExportTableOffset(void) + { + return iDllData->GetExportTableOffset(); + } + +TBool ELFFile::InitHeaders(void) + { + TInt nphdrs = iElfFile->e_phnum; + if (nphdrs) + { + // Find the dynamic segment + Elf32_Phdr * aPhdr = ELFADDR(Elf32_Phdr, iElfFile, iElfFile->e_phoff); + iPhdr = aPhdr; + for (TInt idx = 0; idx < nphdrs; idx++) + { + Elf32_Word ptype = aPhdr[idx].p_type; + if (ptype == PT_DYNAMIC) + { + iDynamicSegmentHdr = &aPhdr[idx]; + iDynamicSegmentIdx = idx; + } + else if (ptype == PT_LOAD && + (aPhdr[idx].p_flags & (PF_X + PF_ARM_ENTRY))) + { + iCodeSegmentHdr = &aPhdr[idx]; + iCodeSegmentIdx = idx; + } + else if (ptype == PT_LOAD && + (aPhdr[idx].p_flags & (PF_W + PF_R))) + { + iDataSegmentHdr = &aPhdr[idx]; + iDataSegmentIdx = idx; + } + } + } + + // cache pointer to symbol table + + // Get section header table + Elf32_Shdr * s = ELFADDR(Elf32_Shdr, iElfFile, iElfFile->e_shoff); + // Index of section header for section header string table + TInt stIdx = iElfFile->e_shstrndx; + TInt symIdx = -1; + // Section name string table + char * stringtable = ELFADDR(char, iElfFile, s[stIdx].sh_offset); + // the index at which we find '.symtab' is the index of the symtab section + for (TInt idx = 0; idx < iElfFile->e_shnum; idx++) + { + if (idx != stIdx) + { + if (!strcmp(&stringtable[s[idx].sh_name], ".symtab")) + { + symIdx = idx; + break; + } + } + } + if (symIdx == -1) return EFalse; + + // save section header table + iSectionHeaderTable = s; + // save the index + iSymIdx = symIdx; + // here's the symbol table + iSymTab = ELFADDR(Elf32_Sym, iElfFile, s[symIdx].sh_offset); + return ETrue; + } + +TBool ELFFile::InitDllData(void) + { + if (!iDynamicSegmentHdr) + { +#if defined(_DEBUG) + Print(EWarning, "Image '%s' has no import/export data.\n", iFileName); +#endif + return ETrue; + } + iDllData = new ELFDllData(this); + if (!iDllData) + { + Print(EPeError, "Out of memory allocating DLL data\n"); + return EFalse; + } + + Elf32_Dyn * dyn = ELFADDR(Elf32_Dyn, iElfFile, iDynamicSegmentHdr->p_offset); + TInt idx = 0; + TInt soNameOffset = 0; + while(dyn[idx].d_tag != DT_NULL) // best to make it explicit + { + switch (dyn[idx].d_tag) + { + case DT_HASH: + iDllData->iHashTable = ELFADDR(Elf32_HashTable, dyn, dyn[idx].d_val); + break; + case DT_STRTAB: + iDllData->iDynStrTab = ELFADDR(char, dyn, dyn[idx].d_val); + break; + case DT_SYMTAB: + iDllData->iDynSymTab = ELFADDR(Elf32_Sym, dyn, dyn[idx].d_val); + break; + case DT_RELA: + iDllData->iRela = ELFADDR(Elf32_Rela, dyn, dyn[idx].d_val); + break; + case DT_RELASZ: + iDllData->iRelaSz = dyn[idx].d_val; + break; + case DT_RELAENT: + iDllData->iRelaSz = dyn[idx].d_val; + break; + case DT_STRSZ: + iDllData->iDynStrTabSize = dyn[idx].d_val; + break; + case DT_ARM_SYMTABSZ_21: //For RVCT2.1 + //iDllData->iDynSymTabSize = dyn[idx].d_val; + case DT_ARM_SYMTABSZ: + /* This is same as DT_ARM_SYMTABSZ_21, but for RVCT 2.2 + * The tag value has been changed for RVC2.2 from RVCT2.1. + * We just ignore this. i.e., we get the symbol table size + * from the nchain field of the hash table as noted in section + * 3.2.2.2 of the BPABI. + */ + break; + case DT_SYMENT: + iDllData->iSymSize = dyn[idx].d_val; + break; + case DT_SONAME: + soNameOffset = dyn[idx].d_val; + break; + case DT_REL: + iDllData->iRel = ELFADDR(Elf32_Rel, dyn, dyn[idx].d_val); + break; + case DT_RELSZ: + iDllData->iRelSz = dyn[idx].d_val; + break; + case DT_RELENT: + iDllData->iRelEnt = dyn[idx].d_val; + break; + case DT_NEEDED: + iDllData->AddToDependency(dyn[idx].d_val); + break; + case DT_PLTRELSZ: + case DT_PLTGOT: + case DT_INIT: + case DT_FINI: + case DT_RPATH: + case DT_SYMBOLIC: + case DT_PLTREL: + case DT_DEBUG: + case DT_TEXTREL: + case DT_JMPREL: + case DT_BIND_NOW: + break; + default: + Print(EPeError,"Unrecognized Dyn Array tag in image '%s'.\n", iFileName); + return EFalse; + } + idx++; + } + return iDllData->Init(); + } + + +void ELFFile::Close() +// +// close the ELF file +// + { + HFile::Close(iFileHandle); + } + + + +TInt ELFFile::NumberOfImports() const +// +// Count the total number of imports for this image +// + { + return iDllData->NumberOfImports(); + } + +TInt ELFFile::NumberOfImportDlls() const +// +// Count the number of referenced Dlls +// + { + return iDllData->NumberOfImportDlls(); + } + +TInt ELFFile::NumberOfExports() const +// +// Count the number of exported symbols +// + { + return iDllData->NumberOfExports(); + } + +TInt ELFFile::NumberOfCodeRelocs() + { + return iDllData->NumberOfCodeRelocs(); + } + +TInt ELFFile::NumberOfDataRelocs() + { + return iDllData->NumberOfDataRelocs(); + } + +Elf32_Phdr * ELFFile::GetSegmentFromAddr(Elf32_Addr addr) + { + TInt nphdrs = iElfFile->e_phnum; + for (TInt idx = 0; idx < nphdrs; idx++) + { + // take advantage of unsignedness + if ((addr - iPhdr[idx].p_vaddr) < iPhdr[idx].p_memsz) return &iPhdr[idx]; + } + return NULL; + } + + +TInt ELFFile::NumberOfRelocs() + { + return iDllData->NumberOfRelocs(); + } + +TUint16 ELFFile::GetRelocType(Elf32_Rel *aReloc) + { + // We work out the type by figuring out the segment of the reloc + TInt segmentIdx = ELF32_R_SYM(aReloc->r_info); + + // check to see if its a reserved or special index. + if ((!segmentIdx) || ((segmentIdx >= SHN_LORESERVE) && (segmentIdx <= SHN_HIRESERVE))) + // up until now these have been treated as KInferredRelocType, so lets continue... + return KInferredRelocType; + + // need to see if this section is executable or writable + if (iPhdr[segmentIdx-1].p_flags & PF_X) + return KTextRelocType; + if (iPhdr[segmentIdx-1].p_flags & PF_W) + return KDataRelocType; + // perhaps we should error here. + return KInferredRelocType; + } + +TBool ELFFile::GetRelocs(Elf32_Rel **aCodeRelocs, Elf32_Rel **aDataRelocs) + { + return iDllData->GetRelocs(aCodeRelocs, aDataRelocs); + } + +TUint ELFFile::GetCodeSize() + { + return iCodeSegmentHdr->p_filesz; + } + +TBool ELFFile::HasInitialisedData() + { + return iDataSegmentHdr != NULL && iDataSegmentHdr->p_filesz != 0; + } + +TUint ELFFile::GetDataSize() + { + return iDataSegmentHdr != NULL ? iDataSegmentHdr->p_filesz : 0; + } + +TBool ELFFile::HasBssData() + { + return iDataSegmentHdr != NULL && (iDataSegmentHdr->p_memsz - iDataSegmentHdr->p_filesz) != 0; + } + +TUint ELFFile::GetBssSize() + { + return iDataSegmentHdr != NULL ? iDataSegmentHdr->p_memsz - iDataSegmentHdr->p_filesz: 0; + } + + + + + + +TBool ELFFile::IsValidFileHeader(Elf32_Ehdr * iElfFile) + { + if (!(iElfFile->e_ident[EI_MAG0] == ELFMAG0 && + iElfFile->e_ident[EI_MAG1] == ELFMAG1 && + iElfFile->e_ident[EI_MAG2] == ELFMAG2 && + iElfFile->e_ident[EI_MAG3] == ELFMAG3)) + { + Print(EPeError,"Invalid ELF magic.\n"); + return EFalse; + } + + if (iElfFile->e_ident[EI_CLASS] != ELFCLASS32) + { + Print(EPeError,"File is not a 32 bit object file.\n"); + return EFalse; + } + if (iElfFile->e_ident[EI_DATA] != ELFDATA2LSB) + { + Print(EPeError,"File data encoding is not Little Endian.\n"); + return EFalse; + } + + if (iElfFile->e_machine != EM_ARM) + { + Print(EPeError,"File does not target ARM/THUMB processors.\n"); + return EFalse; + } + + if (!(iElfFile->e_type == ET_EXEC || iElfFile->e_type == ET_DYN)) + { + Print(EPeError,"File is neither an executable nor a shared object\n"); + return EFalse; + } + + return ETrue; + } + + +// Get details of the next import to fix-up in the current file. Fill in the name of the dll +//it is imported from, the ordinal number and the address to write back to. +#define ORDINAL_DONE 0x40000000 + + +// The following static functions are passed an array of PE files to operate on + +Elf32_Sym * ELFFile::FindSymbol(const char* aName) + { + Elf32_Shdr * s = ELFADDR(Elf32_Shdr, iElfFile, iElfFile->e_shoff); + TInt symIdx = iSymIdx; + Elf32_Sym * sym = iSymTab; + TInt nSyms = s[symIdx].sh_size / s[symIdx].sh_entsize; + char * symStringtable = ELFADDR(char, iElfFile, s[s[symIdx].sh_link].sh_offset); + for (TInt jdx = 0; jdx < nSyms; jdx++) + { + if (!strcmp(&symStringtable[sym[jdx].st_name], (char *)aName)) + return &sym[jdx]; + } + return (Elf32_Sym *)0; + } + +TBool ELFFile::SymbolPresent(const char* aName) + { + return (FindSymbol(aName) != 0); + } + +TBool ELFFile::GetExceptionIndexInfo(TUint32 &aOffset) + { + Elf32_Sym * exidxBase = FindSymbol(".ARM.exidx$$Base"); + Elf32_Sym * exidxLimit = FindSymbol(".ARM.exidx$$Limit"); + if (exidxBase && exidxLimit && (exidxLimit->st_value - exidxBase->st_value)) + { + Elf32_Sym * aED = FindSymbol("Symbian$$CPP$$Exception$$Descriptor"); + if (aED) + { + // Set bottom bit so 0 in header slot means an old binary. + // The decriptor is always aligned on a 4 byte boundary. + aOffset = (aED->st_value - iLinkedBase) | 0x00000001; + return ETrue; + } + else + { + Print(EPeError,"Executable has exception table but no exception descriptor\n"); + exit(666); + } + } + return EFalse; + } + +TBool ELFFile::SetUpLookupTable() +{ + if(!iDllData->CreateSymLookupTable() ) { + Print(EPeError,"Failed to create named symbol lookup information\n"); + return FALSE; + } + if(!iDllData->CreateDependency()){ + Print(EPeError,"Failed to create dependency ordering for named symbol lookup\n"); + return FALSE; + } + + iDllData->SetExportSymInfo(); + return TRUE; +} + +void ELFFile::GetExportSymInfoHeader(E32EpocExpSymInfoHdr& aSymInfoHdr) +{ + iDllData->GetExportSymInfoHeader(aSymInfoHdr); +} + +void ELFFile::SetLookupTblBase(TInt aBaseOffset) +{ + iDllData->SetLookupTblBase(aBaseOffset); +} + +TInt ELFFile::GetLookupTblSize() +{ + return iDllData->GetLookupTblSize(); +} + +TUint ELFFile::GetSymLookupSection(char* aBuff) +{ + return iDllData->GetSymLookupSection(aBuff); +} +