--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bintools/elftools/elftran/elf_dlld.cpp Tue Oct 27 16:36:35 2009 +0000
@@ -0,0 +1,954 @@
+/*
+* 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 <string.h>
+#include <stdlib.h>
+#include <e32std.h>
+#include <elfdefs.h>
+#include "elfdll.h"
+#include "elffile.h"
+#include <h_utl.h>
+#include <e32ldr.h>
+
+ELFFile::ELFDllData::ELFDllData(ELFFile * f)
+ :
+ iElfFile(f),
+
+ iDynStrTab(0),
+ iDynStrTabSize(0),
+ iDynSymTab(0),
+
+ iSymSize(0),
+ iRela(0),
+ iRelaSz(0),
+ iRelaEnt(0),
+
+ iRel(0),
+ iRelSz(0),
+ iRelEnt(0),
+
+ iHashTable(0),
+
+ iNamedExportSymbolHead(0),
+ iNamedExportCount(0),
+
+ iSymStringTableSize(0),
+ iStringNameOffset(0),
+
+ iDepRecords(0),
+ iDepRecordsTail(0),
+
+ iNeededDllNames(0),
+ iNeededDllNamesTail(0),
+
+ iOrdZeroRec(0),
+
+ iNamedLookupEnabled(0),
+
+ iDllHead(0),
+ iDllTail(0),
+
+ iNumberOfImports(0),
+ iNumberOfExports(0),
+ iNumberOfImportDlls(0),
+
+ iStringTableSize(0),
+
+ iNumberOfRelocs(0),
+ iNumberOfCodeRelocs(0),
+ iNumberOfDataRelocs(0)
+ {
+ }
+
+ELFFile::ELFDllData::~ELFDllData()
+ {
+ delete iOrdZeroRec;
+ delete iDepRecords;
+ delete iNeededDllNames;
+ }
+
+TBool ELFFile::ELFDllData::Init()
+ {
+ // process imported symbols
+ // There will be at least one relocation (assumed to be Elf32_Rel) for each such symbol.
+ // S iterate over relocations looking for DLL symbols and add them to the record of
+ // of import info.
+ TInt nrelocs = iRelSz/iRelEnt;
+ TInt SrcSegIdx = -1;
+ TInt errors = 0;
+
+ for (TInt idx = 0; idx < nrelocs; idx++)
+ {
+ Elf32_Rel * rel = &iRel[idx];
+ TUint relType = ELF32_R_TYPE(rel->r_info);
+
+ if (relType == R_ARM_ABS32)
+ {
+ TInt symIdx = ELF32_R_SYM(rel->r_info);
+ Elf32_Sym * sym = &iDynSymTab[symIdx];
+ DllSymbol * dllSym = DllSymbolP(sym);
+ if (dllSym)
+ {
+ dllSym->iRel = rel;
+ dllSym->iSegment = iElfFile->GetSegment(SrcSegIdx);
+ if (!AddSymbol(dllSym)) return EFalse;
+ }
+ else errors++;
+ }
+ else if (relType == R_ARM_RABS32)
+ {
+ iNumberOfRelocs++;
+ if (iElfFile->CodeSegmentP(SrcSegIdx)) iNumberOfCodeRelocs++;
+ else iNumberOfDataRelocs++;
+ }
+ else if (relType == R_ARM_RBASE)
+ {
+ SrcSegIdx = ELF32_R_SYM(rel->r_info);
+ if (SrcSegIdx) SrcSegIdx--;
+ }
+ else
+ {
+ // Gives error with all other Relocation types..
+ TInt symIdx = ELF32_R_SYM(rel->r_info);
+ Elf32_Sym * s = &iDynSymTab[symIdx];
+ char * symName = ELFADDR(char,iDynStrTab,s->st_name);
+ Print(EPeError, "Unresolved symbol: %s\n", symName);
+ errors++;
+ }
+ }
+ // Set up export info
+ if (InitExportInfo())
+ {
+ TText * sym = (TText *)"_E32Startup";
+ // If _E32Startup is defined then this is not a DLL
+ iImageIsDll = !iElfFile->SymbolPresent(sym);
+ }
+ if (errors > 0) return EFalse;
+ return ETrue;
+ }
+
+TBool ELFFile::ELFDllData::ParseDllSymbol(Elf32_Sym * s, char *& dll, TUint& len, TInt& ord)
+ {
+ char * sym = ELFADDR(char,iDynStrTab,s->st_name);
+ if (!strncmp(sym, DLLSYMPREFIX, strlen(DLLSYMPREFIX)))
+ {
+ dll = sym + strlen(DLLSYMPREFIX);
+ TUint lim = strlen(dll);
+ TUint index = strcspn(dll, DLLSYMPREFIX0);
+ if ((index + strlen(DLLSYMSUFFIX)) < lim)
+ {
+ len = index;
+ char * dllSuffix = dll+index;
+ char * match = DLLSYMSUFFIX;
+ int suflen = strlen(DLLSYMSUFFIX);
+ if (!strncmp(dllSuffix, match, suflen))
+ {
+ char * ordString = dll+index+suflen;
+ char * final;
+ TUint X = strtoul(ordString, &final, ORDBASE);
+ if (ordString != final)
+ {
+ ord = (TInt)X;
+ return ETrue;
+ }
+
+ }
+ }
+ }
+ dll = 0;
+ len = 0;
+ ord = -1;
+ return EFalse;
+ }
+
+ELFFile::ELFDllData::DllSymbol * ELFFile::ELFDllData::DllSymbolP(Elf32_Sym * s)
+ {
+ char * dllName;
+ TUint nameLen;
+ TInt symOrd;
+ if (ParseDllSymbol(s, dllName, nameLen, symOrd))
+ {
+ DllSymbol * ds = new DllSymbol(dllName, nameLen, symOrd);
+ if (ds) return ds;
+ Print(EPeError, "Out of memory.\n");
+ return NULL;
+ }
+ // If we get here its not a valid 'dll symbol' and so it is an unresolved symbol
+ char * sym = ELFADDR(char,iDynStrTab,s->st_name);
+ Print(EPeError, "Unresolved symbol: %s\n", sym);
+ return NULL;
+ }
+
+TBool ELFFile::ELFDllData::AddSymbol(ELFFile::ELFDllData::DllSymbol * s)
+ {
+ DllRec * aDll = NULL;
+
+ for (DllRec * r = iDllHead; r != NULL; r = r->iNext)
+ {
+ if (!strncmp(s->iDll, r->iName, s->iLen))
+ {
+ aDll = r;
+ break;
+ }
+ }
+ if (aDll)
+ {
+ iNumberOfImports++;
+ aDll->AddSymbol(s);
+ return ETrue;
+ }
+ else
+ {
+ aDll = new DllRec(s->iDll, s->iLen, s);
+ if (aDll)
+ {
+ if (!iDllHead)
+ {
+ iDllHead = iDllTail = aDll;
+ }
+ else
+ {
+ iDllTail->iNext = aDll;
+ iDllTail = aDll;
+ }
+ iStringTableSize += (s->iLen + 1);
+ iNumberOfImportDlls++;
+ iNumberOfImports++;
+ return ETrue;
+ }
+ else
+ {
+ Print(EPeError, "Out of memory.\n");
+ return EFalse;
+ }
+ }
+ }
+
+void ELFFile::ELFDllData::DllRec::AddSymbol(ELFFile::ELFDllData::DllSymbol * s)
+ {
+ nImports++;
+ iTail->iNext = s;
+ iTail = s;
+ }
+
+static unsigned long elf_hash(const unsigned char *name)
+ {
+ unsigned long h, g;
+ for (h = 0; *name != 0; ++name)
+ {
+ h = (h << 4) + *name;
+ g = h & 0xf0000000;
+ if (g != 0) h ^= g >> 24;
+ h &= ~g;
+ }
+ return h;
+ }
+
+Elf32_Word ELFFile::ELFDllData::FindSymbolIndex(TText * s)
+ {
+ TUint h = elf_hash(s);
+ TUint nb = iHashTable[0].nBuckets;
+ TUint probe = h%nb;
+ Elf32_Sword * bucket = ELFADDR(Elf32_Sword, iHashTable, sizeof(Elf32_HashTable));
+ Elf32_Sword * chain = ELFADDR(Elf32_Sword, bucket, nb * sizeof(Elf32_Sword));
+ Elf32_Sword idx = bucket[probe];
+
+ do
+ {
+ if (!strcmp(ELFADDR(char, iDynStrTab, iDynSymTab[idx].st_name), (char *)s)) return idx;
+ idx = chain[idx];
+ } while (idx > 0);
+ if (idx == 0) idx = -1;
+ return idx;
+ }
+
+TBool ELFFile::ELFDllData::InitExportInfo()
+ {
+ memset(&iSymInfoHdr, 0, sizeof(iSymInfoHdr));
+ TText * exp = (TText *)EXPORTTABLENAME;
+ if ( int(iExportTableSymIdx = FindSymbolIndex(exp)) != -1 )
+ {
+ TText * exps = (TText *)EXPORTTABLESIZENAME;
+ iExportTableSizeSymIdx = FindSymbolIndex(exps);
+ //TUint offset = iDynSymTab[iExportTableSizeSymIdx].st_value - (TUint)code;
+ Elf32_Word * pNumberOfExports = iElfFile->CodePtrFromAddr(iDynSymTab[iExportTableSizeSymIdx].st_value);
+ iNumberOfExports = * pNumberOfExports;
+ iImageIsDll = ETrue;
+ return ETrue;
+ }
+ else iImageIsDll = EFalse;
+ return EFalse;
+ }
+
+TInt ELFFile::ELFDllData::NumberOfImports(void)
+ {
+ return iNumberOfImports;
+ }
+
+TInt ELFFile::ELFDllData::NumberOfExports(void)
+ {
+ return iNumberOfExports;
+ }
+
+TInt ELFFile::ELFDllData::NumberOfImportDlls(void)
+ {
+ return iNumberOfImportDlls;
+ }
+
+TInt ELFFile::ELFDllData::NumberOfRelocs()
+ {
+ return iNumberOfRelocs;
+ }
+
+char * ELFFile::ELFDllData::CreateImportSection(TInt &aSize)
+ {
+ if (!iNumberOfImports)
+ {
+ aSize = 0;
+ return 0;
+ }
+
+ TInt byteSize = sizeof(E32ImportSection) +
+ (sizeof(E32ImportBlock) * iNumberOfImportDlls) +
+ (sizeof(TUint) * iNumberOfImports) +
+ iStringTableSize;
+ if(iNamedLookupEnabled)
+ {
+ // 0th ordinal of each DLL imported from.
+ byteSize += (sizeof(TUint) * iNumberOfImportDlls);
+ }
+ char * newSection = new char[byteSize];
+
+ if (!newSection)
+ {
+ Print(EPeError, "Failed to allocate new import section.\n");
+ aSize = 0;
+ return 0;
+ }
+
+ ((E32ImportSection *)newSection)->iSize = byteSize;
+
+ // used to point to current ImportBlock
+ E32ImportBlock * bp = ELFADDR(E32ImportBlock, newSection, sizeof(E32ImportSection));
+ // used to point to current import relocation entry
+ TUint * rp;
+ // used to point to current location in string table
+ char * sp = ELFADDR(char, newSection, (byteSize - iStringTableSize));
+ OrdZeroRecord *aDep = iDepRecords;
+
+ for (DllRec * dll = iDllHead; dll != NULL ; dll = dll->iNext, bp = (E32ImportBlock *)rp )
+ {
+ // set up the offset from E32ImportBlock.iOffsetOfDllName to the
+ // corresponding string table location
+ bp->iOffsetOfDllName = (sp - (char *)newSection);
+ bp->iNumberOfImports = dll->nImports;
+ if(iNamedLookupEnabled)
+ {
+ bp->iNumberOfImports++;
+ }
+
+ // copy the DLL name to the string table
+ memcpy(sp , dll->iName, dll->iLen);
+ sp[dll->iLen] = 0;
+ sp = sp + dll->iLen + 1;
+
+ // sort out the import 'relocs'
+ rp = ELFADDR(TUint, bp, sizeof(E32ImportBlock));
+
+ for (DllSymbol * sym = dll->iHead; sym != NULL; sym = sym->iNext, rp++)
+ {
+ Elf32_Phdr * segment = sym->iSegment;
+ Elf32_Addr segBase = segment->p_vaddr;
+
+ // sanity check: segment should be the code segment
+ if (!iElfFile->CodeSegmentP(segment))
+ {
+ Print(EPeError, "Import relocation does not refer to code segment.\n");
+ aSize = 0;
+ return 0;
+ }
+
+ // This field is misnamed because it is actually given as a virtual address in
+ // dynamic relocations
+ Elf32_Addr dynOffset = sym->iRel->r_offset;
+ //So this is the 'real' offset of the reloc in the segment in which it occurs
+ Elf32_Addr segOffset = dynOffset - segBase;
+ TUint * relocAddr = ELFADDR(TUint, iElfFile->ELFFileBase(), (segment->p_offset + segOffset));
+ // The only non-zero reloc vals we expect are for vtables.
+ // We store there reloc offset in the top 16 bits of the 'reloc info'.
+ // NB the ELF reloc values should only ever be multiples of 4. So we could optimize here,
+ // but we won't.
+ TUint relocVal = *relocAddr;
+ TUint importOrdinal = sym->iOrd;
+ if (relocVal > 0xFFFF)
+ Print(EPeError, "ELF relocation exceeds E32Image limit of 64K.\n");
+ if (importOrdinal > 0xFFFF)
+ Print(EPeError, "Import ordinal exceeds E32Image limit of 64K.\n");
+
+ *rp = segOffset;
+
+ // eek !! surgery on the code segment....
+ *relocAddr = (relocVal<<16) | importOrdinal;
+ }
+
+ if(iNamedLookupEnabled)
+ {
+ aDep = FindDependency(dll->iName, dll->iLen);
+ if( aDep )
+ {
+ *rp = aDep->iOffset;
+ rp++;
+ }
+ }
+ }
+
+ aSize = byteSize;
+ return newSection;
+ }
+
+TUint ELFFile::ELFDllData::GetExportTableOffset(void)
+ {
+ Elf32_Sym * et = &iDynSymTab[iExportTableSymIdx];
+ Elf32_Phdr * segment = iElfFile->GetSegment(et->st_shndx - 1);
+
+ return et->st_value - segment->p_vaddr;
+ }
+
+TBool ELFFile::ELFDllData::GetRelocs(Elf32_Rel **aCodeRelocs, Elf32_Rel **aDataRelocs)
+ //
+ // load the relocs from the reloc section into relocation and relocsection arrays
+ //
+ {
+ TInt nrelocs = iRelSz/iRelEnt;
+
+ TInt SrcSegIdx = -1;
+
+ TInt cidx = 0;
+ TInt didx = 0;
+
+ for (TInt idx = 0; idx < nrelocs; idx++)
+ {
+ Elf32_Rel * rel = &iRel[idx];
+
+ if (ELF32_R_TYPE(rel->r_info) == R_ARM_RABS32)
+ {
+ if (iElfFile->CodeSegmentP(SrcSegIdx))
+ aCodeRelocs[cidx++]=rel;
+ else if (iElfFile->DataSegmentP(SrcSegIdx))
+ aDataRelocs[didx++]=rel;
+ }
+ else if (ELF32_R_TYPE(rel->r_info) == R_ARM_RBASE)
+ {
+ SrcSegIdx = ELF32_R_SYM(rel->r_info);
+ if (!(iElfFile->CodeSegmentP(SrcSegIdx-1) || iElfFile->DataSegmentP(SrcSegIdx-1)))
+ {
+ Print(EPeError, "Source segment for relocations is neither Code or Data.\n");
+ return EFalse;
+ }
+ SrcSegIdx--;
+ }
+ }
+
+ if(!iNamedLookupEnabled)
+ return ETrue;
+
+ // Add the 0th ordinal of this binary - The relocation info is already setup.
+ aCodeRelocs[cidx++] = &iOrdZeroRec->iReloc;
+
+ // add relocation entries for each of the symbols
+ NamedExportSymbol *aSym = iNamedExportSymbolHead;
+ while(aSym)
+ {
+ // The symbol name info is part of the code section hence all relocations
+ // are collected as part of Code relocations.
+ aCodeRelocs[cidx++] = &aSym->iReloc;
+ aSym = aSym->Next();
+ }
+
+ // Since we have added a few relocations, lets make sure
+ // they are still sorted on addresses they refer to.
+
+ //Sorting the code relocs
+ TInt aIdx1, aIdx2;
+ Elf32_Rel *aTmp;
+ for (aIdx1 = 0; aIdx1 < cidx; aIdx1++) {
+ for (aIdx2 = aIdx1; aIdx2 < cidx; aIdx2++) {
+ if(aCodeRelocs[aIdx1]->r_offset > aCodeRelocs[aIdx2]->r_offset) {
+ aTmp = aCodeRelocs[aIdx2];
+ aCodeRelocs[aIdx2] = aCodeRelocs[aIdx1];
+ aCodeRelocs[aIdx1] = aTmp;
+ }
+ }
+ }
+
+ //Sorting the data relocs
+ for (aIdx1 = 0; aIdx1 < didx; aIdx1++) {
+ for (aIdx2 = aIdx1; aIdx2 < didx; aIdx2++) {
+ if(aDataRelocs[aIdx1]->r_offset > aDataRelocs[aIdx2]->r_offset) {
+ aTmp = aDataRelocs[aIdx2];
+ aDataRelocs[aIdx2] = aDataRelocs[aIdx1];
+ aDataRelocs[aIdx1] = aTmp;
+ }
+ }
+ }
+
+ return ETrue;
+ }
+
+NamedExportSymbol::NamedExportSymbol(char* aName, Elf32_Addr aValue) : \
+ iSymbolName(aName), iValue(aValue), iNext(NULL)
+{
+}
+
+TBool ELFFile::ELFDllData::CreateSymLookupTable()
+{
+ if( !SetupSymbolValues() )
+ return FALSE;
+
+ if( !SetupSymbolNames() )
+ return FALSE;
+
+ return TRUE;
+}
+
+TBool ELFFile::ELFDllData::SetupSymbolValues()
+{
+ NamedExportSymbol *aSym, *aPrevSym;
+
+ if( int(iExportTableSymIdx) == -1 || int(iExportTableSizeSymIdx) == -1)
+ return FALSE;
+
+ // Fetch the 'export table' symbol from the dynamic symbol table.
+ Elf32_Sym *aElfExpTbl = &iDynSymTab[iExportTableSymIdx];
+
+ // Fetch the 'export table size' symbol from the dynamic symbol table.
+ Elf32_Sym *aElfExpTblSz = &iDynSymTab[iExportTableSizeSymIdx];
+
+ if((aElfExpTbl->st_value - aElfExpTblSz->st_value) != 4)
+ {
+ // Check that the word prior to the export table is not the export table size
+ // This is to make sure that there is space for the 0th ordinal and
+ // we dont overwrite the 'export table size' entry.
+ iNamedLookupEnabled = 1;
+ }
+ else
+ return FALSE;
+
+ // Fetch the export table contents
+ Elf32_Word * aExpEntries = iElfFile->CodePtrFromAddr(aElfExpTbl->st_value);
+
+ if(!aExpEntries)
+ return FALSE;
+
+ aSym = aPrevSym = NULL;
+ TInt idx;
+ // Create symbols corresponding to export table entries.
+ for(idx = 0; idx < iNumberOfExports; idx++)
+ {
+ //Symbols marked Absent are ignored.
+ if( aExpEntries[idx] == iElfFile->iEntryPoint)
+ continue;
+
+ aSym = new NamedExportSymbol(0, aExpEntries[idx]);
+ iNamedExportCount++;
+ if(aPrevSym)
+ {
+ aPrevSym->Next(aSym);
+ }
+ else
+ {
+ iNamedExportSymbolHead = aSym;
+ }
+
+ aPrevSym = aSym;
+ }
+
+ return TRUE;
+}
+
+TBool ELFFile::ELFDllData::SetupSymbolNames()
+{
+ char *aSymName = NULL;
+ NamedExportSymbol *aSym;
+ TUint aDynSymbolTblCount = iHashTable->nChains;
+ TInt aCount = 0;
+ TInt aCodeSegIdx = iElfFile->CodeSegmentIndex() + 1;
+ TInt aDataSegIdx = iElfFile->DataSegmentIndex() + 1;
+
+ // Traverse the dynamic symbol table
+ for(TUint idx = 0; idx < aDynSymbolTblCount; idx++)
+ {
+ //Consider only the the defined symbols
+ if( ELF32_ST_TYPE(iDynSymTab[idx].st_info) == STT_OBJECT ||
+ ELF32_ST_TYPE(iDynSymTab[idx].st_info) == STT_FUNC )
+ {
+ aSym = iNamedExportSymbolHead;
+ while(aSym)
+ {
+ // Name already set
+ if(aSym->Name())
+ {
+ aSym = aSym->Next();
+ continue;
+ }
+ Elf32_Addr aAddr = aSym->Value();
+
+ // If the exported symbol and the dynamic symbol table entry have the
+ // same values, setup the name
+ if(iDynSymTab[idx].st_value == aAddr)
+ {
+ aSymName = ELFADDR(char, iDynStrTab, iDynSymTab[idx].st_name);
+ aSym->Name(aSymName);
+
+ if(iElfFile->CodeSegmentP (iElfFile->GetSegmentFromAddr(aAddr)) ) {
+ aSym->iReloc.r_info = aCodeSegIdx << 8 | R_ARM_RABS32;
+ aSym->iSymRelocType = KTextRelocType;
+ }
+ else {
+ aSym->iReloc.r_info = aDataSegIdx << 8 | R_ARM_RABS32;
+ aSym->iSymRelocType = KDataRelocType;
+ }
+
+ iNumberOfCodeRelocs++;
+ iNumberOfRelocs++;
+
+ // The offset to the name is always 4 byte aligned.
+ iStringNameOffset = iSymStringTableSize >> 2;
+ aSym->NameOffset( iSymStringTableSize );
+ // These are NULL-terminated strings
+ iSymStringTableSize += (strlen(aSymName) + 1);
+ iSymStringTableSize = ALIGN4(iSymStringTableSize);
+
+ aCount++;
+ break;
+ }
+ aSym = aSym->Next();
+ }
+ }
+ }
+
+ if(aCount != iNamedExportCount)
+ return FALSE;
+
+ // Sort symbols on their names...
+ if(iNamedExportCount > 1)
+ {
+ NamedExportSymbol **aTmpStart = &iNamedExportSymbolHead;
+ Sort(aTmpStart, iNamedExportSymbolHead);
+ }
+
+ return TRUE;
+}
+
+void ELFFile::ELFDllData::SetLookupTblBase(TInt aBaseOffset)
+{
+ Elf32_Addr aBaseAddr = iElfFile->iLinkedBase + iElfFile->GetCodeSize();
+
+ Elf32_Addr aAddr;
+
+ // setup relocations of each of the exported symbols.
+ aAddr = aBaseAddr + iSymInfoHdr.iSymbolTblOffset;
+ NamedExportSymbol *aSym = iNamedExportSymbolHead;
+ while(aSym)
+ {
+ aSym->iReloc.r_offset = aAddr;
+ aAddr += sizeof(Elf32_Addr);
+ aSym = aSym->Next();
+ }
+
+ // setup relocations for the 0th ordinal of this binary.
+
+ iOrdZeroRec = new OrdZeroRecord(0);
+ Elf32_Sym * et = &iDynSymTab[iExportTableSymIdx];
+ iOrdZeroRec->iReloc.r_offset = et->st_value - 4; // The word prior ro the first entry
+ // of the export table is the 0th ordinal entry.
+
+ //At the 0th ordinal, write the address of the start of symbol info
+ TUint32 aZeroOrdOff = et->st_value - 4 - iElfFile->iLinkedBase;
+ aZeroOrdOff += (iElfFile->GetSegment(et->st_shndx - 1))->p_offset;
+ TUint32 *aZeroOrdLocation = ELFADDR(TUint32, iElfFile->ELFFileBase(), aZeroOrdOff);
+ *aZeroOrdLocation = aBaseAddr;
+
+ iOrdZeroRec->iReloc.r_info = ELF32_R_INFO(et->st_shndx, R_ARM_RABS32);
+ iNumberOfCodeRelocs++;
+ iNumberOfRelocs++;
+
+ TInt aOffset = aBaseOffset + iSymInfoHdr.iDepDllZeroOrdTableOffset;
+
+ OrdZeroRecord *aDepRecord = iDepRecords;
+
+ while( aDepRecord )
+ {
+ // Setup the offset - This offset (relative code segment) is filled in the
+ // import table to point to this dependency record.
+ aDepRecord->iOffset = aOffset;
+
+ aOffset += 4;
+ aDepRecord = aDepRecord->iNext;
+ }
+}
+
+TBool ELFFile::ELFDllData::AddToDependency(TUint aOff)
+{
+ // Add the name found in DT_NEEDED into a list.
+ // The dynamic string table might not have been found in dynamic table yet.
+ // So store the offset (wrt base of dynamic string table) for now.
+ NeededDLLsList *aNeeded = new NeededDLLsList(aOff);
+ if(!aNeeded)
+ return FALSE;
+
+ if ( iNeededDllNames ) {
+ iNeededDllNamesTail->iNext= aNeeded;
+ iNeededDllNamesTail = aNeeded;
+ }
+ else {
+ iNeededDllNames = iNeededDllNamesTail = aNeeded;
+ }
+
+ return TRUE;
+}
+
+TBool ELFFile::ELFDllData::CreateDependency()
+{
+ OrdZeroRecord *aDep;
+ NeededDLLsList *aNeeded = iNeededDllNames;
+ char *aDllName = NULL;
+ DllRec *aRec;
+ TInt aNeededFound;
+
+ for(aNeededFound = 0; (aNeededFound < iNumberOfImportDlls) && aNeeded;)
+ {
+ aRec = 0;
+ while(aNeeded) {
+ aDllName = iDynStrTab + aNeeded->iOffset;
+ // aNeeded is just a guess that this binary might be dependent on aDllName
+ // Search through the import table to find if the guess was correct.
+ aRec = SearchImports(aDllName);
+ if(aRec && FindDependency(aRec->iName, aRec->iLen) == NULL) {
+ // Check if aDllName is listed in import table and it
+ // not added already in the depedency records.
+ aNeededFound++;
+ break;
+ }
+ // Bad guess...go to the next aNeeded
+ aNeeded = aNeeded->iNext;
+ }
+
+ if( !aRec )
+ return FALSE;
+
+ aDep = new OrdZeroRecord(aDllName);
+ if(!iDepRecords)
+ {
+ iDepRecords = iDepRecordsTail = aDep;
+ }
+ else
+ {
+ iDepRecordsTail->iNext = aDep;
+ iDepRecordsTail = aDep;
+ }
+ aNeeded = aNeeded->iNext;
+ }
+
+ return (aNeededFound == iNumberOfImportDlls);
+}
+
+ELFFile::ELFDllData::DllRec* ELFFile::ELFDllData::SearchImports(char *aName)
+{
+ DllRec *aRec = iDllHead;
+ while (aRec)
+ {
+ if(strncmp(aRec->iName, aName, aRec->iLen) == 0)
+ return aRec;
+ aRec = aRec->iNext;
+ }
+ return NULL;
+}
+
+OrdZeroRecord* ELFFile::ELFDllData::FindDependency(char* aName, TUint aLen)
+{
+ OrdZeroRecord* aDep = iDepRecords;
+ while(aDep)
+ {
+ if(strncmp(aName, aDep->iName, aLen) == 0)
+ return aDep;
+ aDep = aDep->iNext;
+ }
+ return NULL;
+}
+
+void ELFFile::ELFDllData::GetExportSymInfoHeader(E32EpocExpSymInfoHdr& aSymInfoHdr)
+{
+ memcpy(&aSymInfoHdr, &iSymInfoHdr, sizeof(E32EpocExpSymInfoHdr));
+}
+
+void ELFFile::ELFDllData::SetExportSymInfo()
+{
+ iSymInfoHdr.iSymCount = (TUint16)iNamedExportCount;
+ iSymInfoHdr.iSymbolTblOffset = sizeof(E32EpocExpSymInfoHdr);
+ iSymInfoHdr.iStringTableSz = iSymStringTableSize;
+ TInt aSymTabSz;
+ if( iStringNameOffset > 0xffff){
+ iSymInfoHdr.iFlags = KNameLookupOffsetFlag32; // Flag indicating 32 bit offsets
+ // for symbol names
+ aSymTabSz = iNamedExportCount* sizeof(TUint32);// symbol addresses
+ aSymTabSz += iNamedExportCount* sizeof(TUint32);// symbol name 32-bit offsets
+ }
+ else
+ {
+ iSymInfoHdr.iFlags &= ~KNameLookupOffsetFlag32;// Flag indicating 16-bit offsets
+ // for symbol names
+ aSymTabSz = iNamedExportCount* sizeof(TUint32); // symbol addresses
+ aSymTabSz += iNamedExportCount* sizeof(TUint16);// symbol name 16-bit offsets
+ aSymTabSz = ALIGN4(aSymTabSz);
+ }
+ iSymInfoHdr.iStringTableOffset = iSymInfoHdr.iSymbolTblOffset + aSymTabSz;
+ iSymInfoHdr.iDllCount = iNumberOfImportDlls;
+ iSymInfoHdr.iDepDllZeroOrdTableOffset = iSymInfoHdr.iStringTableOffset + \
+ iSymInfoHdr.iStringTableSz;
+
+ iSymInfoHdr.iSize = iSymInfoHdr.iDepDllZeroOrdTableOffset + \
+ iSymInfoHdr.iDllCount * sizeof(Elf32_Addr);
+}
+
+TUint ELFFile::ELFDllData::GetSymLookupSection(char* aBuff)
+{
+ if( !iNamedLookupEnabled)
+ return 0;
+
+ memcpy(aBuff, &iSymInfoHdr, sizeof(iSymInfoHdr));
+
+ // Name offsets start after the end of symbol addresses.
+ TUint32 aNameOffsetStart = iSymInfoHdr.iSymbolTblOffset + \
+ iNamedExportCount* sizeof(TUint32);
+
+ TUint32 *aAddrPtr = (TUint32*)(aBuff + iSymInfoHdr.iSymbolTblOffset);
+ TUint32 aStringTabOff = 0;
+ char *aStringTab = aBuff + iSymInfoHdr.iStringTableOffset;//Start of the string table.
+ NamedExportSymbol *aSym = iNamedExportSymbolHead;
+ while(aSym)
+ {
+ *aAddrPtr = aSym->Value();
+ aStringTabOff = aSym->NameOffset(); // Get the offset of symbol name (which is wrt
+ // string table base).
+ if( iSymInfoHdr.iFlags & KNameLookupOffsetFlag32 )
+ {
+ TUint32 *aNameOffPtr = (TUint32*)(aBuff + aNameOffsetStart);
+ *aNameOffPtr = (aStringTabOff >> 2);//write the offset of the name
+ strcpy(aStringTab + aStringTabOff, aSym->Name());//write the symbol name
+ aNameOffsetStart +=4;
+ }
+ else
+ {
+ TUint16 *aNameOffPtr = (TUint16*)(aBuff + aNameOffsetStart);
+ *aNameOffPtr = (TUint16)(aStringTabOff >> 2);//write the offset of the name
+ strcpy(aStringTab + aStringTabOff, aSym->Name());//write the symbol name
+ aNameOffsetStart +=2;
+ }
+ aAddrPtr++;
+ aSym = aSym->Next();
+ }
+
+ OrdZeroRecord *aRec = iDepRecords;
+ TUint32* aDepsTable = (TUint32*)(aBuff + iSymInfoHdr.iDepDllZeroOrdTableOffset);
+ while(aRec)
+ {
+ *aDepsTable++ = 0;
+ aRec = aRec->iNext;
+ }
+ return iSymInfoHdr.iSize;
+}
+
+void ELFFile::ELFDllData::Sort(NamedExportSymbol** aDstList, NamedExportSymbol* aSrcList)
+{
+ NamedExportSymbol *aSym = aSrcList;
+ NamedExportSymbol **aSymbols = new NamedExportSymbol*[iNamedExportCount];
+
+ TInt pos;
+ for (pos = 0; pos < iNamedExportCount; pos++) {
+ aSymbols[pos] = aSym;
+ aSym = aSym->Next();
+ }
+
+ NamedExportSymbol **aResult = new NamedExportSymbol*[iNamedExportCount];
+ MergeSort(aResult, aSymbols);
+ iNamedExportSymbolHead = aResult[0];
+ for (pos = 0; pos < iNamedExportCount; pos++) {
+ aSym = aResult[pos];
+ if( pos == iNamedExportCount-1)
+ aSym->Next(NULL);
+ else
+ aSym->Next(aResult[pos+1]);
+ }
+ *aDstList = aResult[0];
+ delete [] aResult;
+ delete [] aSymbols;
+}
+
+void ELFFile::ELFDllData::MergeSort(NamedExportSymbol** aDstList, NamedExportSymbol** aSrcList)
+{
+ MergeSort(aDstList, aSrcList, 0, iNamedExportCount);
+}
+
+void ELFFile::ELFDllData::MergeSort(NamedExportSymbol** aDstList, NamedExportSymbol** aSrcList, \
+ TUint aLeft, TUint aRight)
+{
+ if( (aRight - aLeft) <= 1)
+ return;
+
+ TUint aSize = aRight - aLeft;
+ TUint aCenter = aLeft + aSize/2;
+
+ MergeSort(aDstList, aSrcList, aLeft, aCenter);
+ MergeSort(aDstList, aSrcList, aCenter, aRight);
+
+ TUint aLPos, aRPos, aCnt;
+ aLPos = aLeft;
+ aRPos = aCenter;
+ for(aCnt = 0; aCnt < aSize; aCnt++)
+ {
+ if( (aLPos < aCenter) &&
+ (aRPos == aRight || (strcmp(aSrcList[aLPos]->Name(), aSrcList[aRPos]->Name()) < 0) )
+ )
+ {
+ // Compare the left half with the right and add the lesser one.
+ // The comparision is done on the topmost element on each half.
+ // if aRPos is past the last element of the right half, the left element has
+ // nothing to compare with. Just add it to the result list.
+ aDstList[aCnt] = aSrcList[aLPos];
+ aLPos++;
+ }
+ else
+ {
+ // Add the greater one into the list.
+ // if aLPos is past the element at the center, it anyway belongs to the
+ // right half. Add it to the result list.
+ aDstList[aCnt] = aSrcList[aRPos];
+ aRPos++;
+ }
+ }
+
+ // Once the sublist is sorted, put it back to the source list
+ // so that the parent has its left and right sublists are sorted.
+ for(aCnt = 0; aCnt < aSize; aCnt++)
+ {
+ aSrcList[aLeft+aCnt] = aDstList[aCnt];
+ }
+}
+