diff -r 1af5c1be89f8 -r 92d87f2e53c2 tools/elf4rom/src/elfsymboltablemanager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/elf4rom/src/elfsymboltablemanager.cpp Fri Jan 15 09:07:44 2010 +0000 @@ -0,0 +1,259 @@ +/* +* 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 . +*/ + +#include +#include + +#include "elfsymboltablemanager.h" + +void ElfFileSymbolFragments::AddSymbolTable(String & aPath, size_t aOffset, size_t aSize, size_t aFirstGlobal){ + iPath = aPath; + // drop the inital 'undefined' symbol + iSymbolTableOffset = aOffset + sizeof(Elf32_Sym); + iSymbolTableSize = aSize - sizeof(Elf32_Sym); + iFirstGlobal = aFirstGlobal - 1; +} + +void ElfFileSymbolFragments::AddStringTable(String & aPath, size_t aOffset, size_t aSize){ + iPath = aPath; + // drop the inital "\0" + iStringTableOffset = aOffset + 1; + iStringTableSize = aSize - 1; +} + +size_t ElfFileSymbolFragments::LookupSection(size_t ndx){ + SectionNumberMap::iterator aMapping = iSectionNumberMap.begin(); + SectionNumberMap::iterator end = iSectionNumberMap.end(); + while (aMapping != end) { + if (aMapping->iOld == ndx) + return aMapping->iNew; + aMapping++; + } + return ndx; +} + +int ElfFileSymbolFragments::LookupVaddrAddend(size_t ndx){ + SectionVaddrAddendMap::iterator aMapping = iSectionVaddrAddendMap.begin(); + SectionVaddrAddendMap::iterator end = iSectionVaddrAddendMap.end(); + while (aMapping != end) { + if (aMapping->iSectionNumber == ndx) + return aMapping->iAddend; + aMapping++; + } + return 0; +} + +size_t ElfSymTabStringTable::Size(){ + return iElfSymbolTableManager.GetSymTabStringsSectionSize(); +} + +void ElfSymbolTableManager::Finalize(SectionNumberMap & aSectionNumberMap, SectionVaddrAddendMap & aSectionVaddrAddendMap ){ + iCurrentFragment.SetSectionNumberMap(aSectionNumberMap); + iCurrentFragment.SetSectionVaddrAddendMap(aSectionVaddrAddendMap); + iCurrentFragment.Validate(); + iSymbolFragments.push_back(iCurrentFragment); + iCurrentFragment.Reset(); +} + +// TODO: This could be done more efficiently and with out the use of the ElfStringTable object. +void ElfSymbolTableManager::GetFileFragmentData(FileFragmentData & aFileFragmentData ){ + size_t symTabSize = GetSymTabSectionSize(); + iData = new char[symTabSize]; + Elf32_Sym * syms = (Elf32_Sym *)iData; + + + // set up UNDEF symbol + syms[0].st_info = 0; + syms[0].st_name = 0; + syms[0].st_other = 0; + syms[0].st_shndx = 0; + syms[0].st_size = 0; + syms[0].st_value = 0; + + // set up 'cursors' into final symbol table so we put locals first + // and globals at the end + Elf32_Sym * lsym = &syms[1]; + size_t firstGlobal = GetFirstNonLocalIndex(); + Elf32_Sym * gsym = &syms[firstGlobal]; + Elf32_Sym * lsymLim = gsym; + iStringTable.AllocateInitialNullString(); + + SymbolFragmentList::iterator aFrag = iSymbolFragments.begin(); + SymbolFragmentList::iterator end = iSymbolFragments.end(); + while (aFrag != end) { + //InputFile aFile((char *)(aFrag->GetPath().c_str())); + InputFile aFile(aFrag->GetPath()); + aFile.SetOffset(aFrag->GetSymbolTableOffset()); + size_t symSize = aFrag->GetSymbolTableSize(); + size_t limit = symSize / sizeof(Elf32_Sym); + char * symtabData = aFile.GetData(symSize); + Elf32_Sym * symtab = (Elf32_Sym *)symtabData; + aFile.SetOffset(aFrag->GetStringTableOffset()); + char * strtabx = aFile.GetData(aFrag->GetStringTableSize()); + // set strtab back one to 'add' "\0" back in so indexs works with addition. + char * strtab = strtabx - 1; + size_t firstNonLocal = aFrag->GetFirstGlobal(); + + typedef std::map SymbolNdxMap; + SymbolNdxMap symNdxMap; + + for (size_t i = 0; i < limit; i++){ + size_t strndx = symtab[i].st_name; + + if (strndx != 0) { + // see if we've already seen this index + SymbolNdxMap::iterator res = symNdxMap.find(strndx); + size_t newndx; + if (res != symNdxMap.end()){ + newndx = res->second; + symtab[i].st_name = newndx; + } else { + char * name = &strtab[strndx]; + newndx = iStringTable.AddString(name); + symNdxMap[strndx] = symtab[i].st_name = newndx; + } + } + + if (!(symtab[i].st_value || symtab[i].st_size)){ + symtab[i].st_shndx = SHN_UNDEF; + } else { + size_t oldNdx = symtab[i].st_shndx; + + // retrieve new section index + size_t newscnndx = aFrag->LookupSection(oldNdx); + // retrieve the vaddr adjustment to add to the symbol's value + int addend = aFrag->LookupVaddrAddend(oldNdx); + symtab[i].st_shndx = newscnndx; + symtab[i].st_value += addend; + } + if (i < firstNonLocal){ + assert(lsym < lsymLim); + *(lsym++) = symtab[i]; + } else { + *(gsym++) = symtab[i]; + } + } + + delete [] symtabData; + delete strtabx; + + aFrag++; + } + SetFileFragmentData(aFileFragmentData, symTabSize, reinterpret_cast(iData)); +} + + +size_t ElfSymbolTableManager::Size(){ + return GetSymTabSectionSize(); +} + +void ElfSymbolTableManager::DeleteFileFragmentData(){ + char * d = iData; + iData = NULL; + delete [] d; +} + +void ElfSymbolTableManager::AddData(OutputFile & aOutputFile){ + const FileFragment & aSectionFrag = iOutputFile.GetFileFragment(this); + SetOffset(aSectionFrag.GetOffset()); +} + +void ElfSymbolTableManager::AddSymbolTable(){ + // The sym table section needs to record the index of its associated + // string table in its link field and record the index of the first non-local + // symbol in its info field + int symTabSize = GetSymTabSectionSize(); + size_t firstNonLocal = GetFirstNonLocalIndex(); + size_t nextSectionIndex = iElfSectionManager.NumSections(); + + ElfSectionElfData * aSymTabSectionData = new ElfSectionElfData(*this); + Elf32_Shdr symTabShdr; + symTabShdr.sh_name = 0; // for now. + symTabShdr.sh_type = SHT_SYMTAB; + symTabShdr.sh_flags = 0; + symTabShdr.sh_addr = 0; + symTabShdr.sh_offset = 0; // for now + symTabShdr.sh_size = symTabSize; // for now. + // symTabShdr will be @ index nextSectionIndex so the .strtab will + // be @ nextSectionIndex +1 + symTabShdr.sh_link = nextSectionIndex + 1; + symTabShdr.sh_info = firstNonLocal; + symTabShdr.sh_addralign = 4; + symTabShdr.sh_entsize = sizeof(Elf32_Sym); + + ElfSection aSymTabSection(aSymTabSectionData, ".symtab", symTabShdr); + iElfSectionManager.AddSection(aSymTabSection); + + + ElfSectionElfData * aStringTableSectionData = new ElfSectionElfData(iStringTable); + Elf32_Shdr shdr; + shdr.sh_name = 0; // for now. + shdr.sh_type = SHT_STRTAB; + shdr.sh_flags = 0; + shdr.sh_addr = 0; + shdr.sh_offset = 0; // for now + shdr.sh_size = GetSymTabStringsSectionSize(); + shdr.sh_link = 0; + shdr.sh_info = 0; + shdr.sh_addralign = 0; + shdr.sh_entsize = 0; + ElfSection aStringTableSection(aStringTableSectionData, ".strtab", shdr); + iElfSectionManager.AddSection(aStringTableSection); + +} + +size_t ElfSymbolTableManager::GetSymTabSectionSize(){ + int symTabSize = sizeof(Elf32_Sym); // add the 'undefined' symbols + + SymbolFragmentList::iterator aFrag = iSymbolFragments.begin(); + SymbolFragmentList::iterator end = iSymbolFragments.end(); + while (aFrag != end) { + symTabSize += aFrag->GetSymbolTableSize(); + aFrag++; + } + return symTabSize; +} + +size_t ElfSymbolTableManager::GetSymTabStringsSectionSize(){ + + if (iSymbolStringTableSizeValid) + return iSymbolStringTableSize; + + int stringsSize = 1; // add the leading "\0" + + SymbolFragmentList::iterator aFrag = iSymbolFragments.begin(); + SymbolFragmentList::iterator end = iSymbolFragments.end(); + while (aFrag != end) { + stringsSize += aFrag->GetStringTableSize(); + aFrag++; + } + iSymbolStringTableSizeValid = true; + return iSymbolStringTableSize = stringsSize; +} + +size_t ElfSymbolTableManager::GetFirstNonLocalIndex(){ + int ndx = 1; // add the 'undefined' symbols + + SymbolFragmentList::iterator aFrag = iSymbolFragments.begin(); + SymbolFragmentList::iterator end = iSymbolFragments.end(); + while (aFrag != end) { + ndx += aFrag->GetFirstGlobal(); + aFrag++; + } + return ndx; +}