tools/elf4rom/src/elfsymboltablemanager.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 <libelf.h>
       
    20 #include <map>
       
    21 
       
    22 #include "elfsymboltablemanager.h"
       
    23 
       
    24 void ElfFileSymbolFragments::AddSymbolTable(String & aPath, size_t aOffset, size_t aSize, size_t aFirstGlobal){
       
    25 	iPath = aPath;
       
    26 	// drop the inital 'undefined' symbol
       
    27 	iSymbolTableOffset = aOffset + sizeof(Elf32_Sym);
       
    28 	iSymbolTableSize = aSize - sizeof(Elf32_Sym);
       
    29 	iFirstGlobal = aFirstGlobal - 1;
       
    30 }
       
    31 
       
    32 void ElfFileSymbolFragments::AddStringTable(String & aPath, size_t aOffset, size_t aSize){
       
    33 	iPath = aPath;
       
    34 	// drop the inital "\0"
       
    35 	iStringTableOffset = aOffset + 1;
       
    36 	iStringTableSize = aSize - 1;
       
    37 }
       
    38 
       
    39 size_t ElfFileSymbolFragments::LookupSection(size_t ndx){
       
    40 	SectionNumberMap::iterator aMapping = iSectionNumberMap.begin();
       
    41 	SectionNumberMap::iterator end = iSectionNumberMap.end();
       
    42 	while (aMapping != end) {
       
    43 		if (aMapping->iOld == ndx) 
       
    44 			return aMapping->iNew;
       
    45 		aMapping++;
       
    46 	}
       
    47 	return ndx;
       
    48 }
       
    49 
       
    50 int ElfFileSymbolFragments::LookupVaddrAddend(size_t ndx){
       
    51 	SectionVaddrAddendMap::iterator aMapping = iSectionVaddrAddendMap.begin();
       
    52 	SectionVaddrAddendMap::iterator end = iSectionVaddrAddendMap.end();
       
    53 	while (aMapping != end) {
       
    54 		if (aMapping->iSectionNumber == ndx) 
       
    55 			return aMapping->iAddend;
       
    56 		aMapping++;
       
    57 	}
       
    58 	return 0;
       
    59 }
       
    60 
       
    61 size_t ElfSymTabStringTable::Size(){
       
    62 	return iElfSymbolTableManager.GetSymTabStringsSectionSize();
       
    63 }
       
    64 
       
    65 void ElfSymbolTableManager::Finalize(SectionNumberMap & aSectionNumberMap, SectionVaddrAddendMap & aSectionVaddrAddendMap ){
       
    66 	iCurrentFragment.SetSectionNumberMap(aSectionNumberMap);
       
    67 	iCurrentFragment.SetSectionVaddrAddendMap(aSectionVaddrAddendMap);
       
    68 	iCurrentFragment.Validate();
       
    69 	iSymbolFragments.push_back(iCurrentFragment);
       
    70 	iCurrentFragment.Reset();
       
    71 }
       
    72 
       
    73 // TODO: This could be done more efficiently and with out the use of the ElfStringTable object.
       
    74 void ElfSymbolTableManager::GetFileFragmentData(FileFragmentData & aFileFragmentData ){
       
    75 	size_t symTabSize = GetSymTabSectionSize(); 
       
    76 	iData = new char[symTabSize];
       
    77 	Elf32_Sym * syms = (Elf32_Sym *)iData;
       
    78 
       
    79 	
       
    80 	// set up UNDEF symbol
       
    81 	syms[0].st_info = 0;
       
    82 	syms[0].st_name = 0;
       
    83 	syms[0].st_other = 0;
       
    84 	syms[0].st_shndx = 0;
       
    85 	syms[0].st_size = 0;
       
    86 	syms[0].st_value = 0;
       
    87 
       
    88 	// set up 'cursors' into final symbol table so we put locals first 
       
    89 	// and globals at the end
       
    90 	Elf32_Sym * lsym = &syms[1];
       
    91 	size_t firstGlobal = GetFirstNonLocalIndex();
       
    92 	Elf32_Sym * gsym = &syms[firstGlobal];
       
    93 	Elf32_Sym * lsymLim = gsym;
       
    94 	iStringTable.AllocateInitialNullString();
       
    95 	
       
    96 	SymbolFragmentList::iterator aFrag = iSymbolFragments.begin();
       
    97 	SymbolFragmentList::iterator end = iSymbolFragments.end();
       
    98 	while (aFrag != end) {
       
    99 		//InputFile aFile((char *)(aFrag->GetPath().c_str()));
       
   100 		InputFile aFile(aFrag->GetPath());
       
   101 		aFile.SetOffset(aFrag->GetSymbolTableOffset());
       
   102 		size_t symSize = aFrag->GetSymbolTableSize();
       
   103 		size_t limit = symSize / sizeof(Elf32_Sym);
       
   104 		char * symtabData = aFile.GetData(symSize);
       
   105 		Elf32_Sym * symtab = (Elf32_Sym *)symtabData;
       
   106 		aFile.SetOffset(aFrag->GetStringTableOffset());
       
   107 		char * strtabx = aFile.GetData(aFrag->GetStringTableSize());
       
   108 		// set strtab back one to 'add' "\0" back in so indexs works with addition.
       
   109 		char * strtab = strtabx - 1;
       
   110 		size_t firstNonLocal = aFrag->GetFirstGlobal();
       
   111 		
       
   112 		typedef std::map<size_t, size_t> SymbolNdxMap;
       
   113 		SymbolNdxMap symNdxMap;
       
   114 		
       
   115 		for (size_t i = 0; i < limit; i++){
       
   116 			size_t strndx = symtab[i].st_name;
       
   117 			
       
   118 			if (strndx != 0) {
       
   119 				// see if we've already seen this index
       
   120 				SymbolNdxMap::iterator res = symNdxMap.find(strndx);
       
   121 				size_t newndx;
       
   122 				if (res != symNdxMap.end()){
       
   123 					newndx = res->second;
       
   124 					symtab[i].st_name = newndx;	
       
   125 				} else {
       
   126 					char * name = &strtab[strndx];
       
   127 					newndx = iStringTable.AddString(name);
       
   128 					symNdxMap[strndx] = symtab[i].st_name = newndx;
       
   129 				}
       
   130 			}
       
   131 			
       
   132 			if (!(symtab[i].st_value || symtab[i].st_size)){
       
   133 				symtab[i].st_shndx = SHN_UNDEF;
       
   134 			} else {
       
   135 				size_t oldNdx = symtab[i].st_shndx;
       
   136 				
       
   137 				// retrieve new section index
       
   138 				size_t newscnndx = aFrag->LookupSection(oldNdx);
       
   139 				// retrieve the vaddr adjustment to add to the symbol's value
       
   140 				int addend = aFrag->LookupVaddrAddend(oldNdx);
       
   141 				symtab[i].st_shndx = newscnndx;
       
   142 				symtab[i].st_value += addend;
       
   143 			}
       
   144 			if (i < firstNonLocal){
       
   145 				assert(lsym < lsymLim);
       
   146 				*(lsym++) = symtab[i];
       
   147 			} else {
       
   148 				*(gsym++) = symtab[i];
       
   149 			}
       
   150 		}
       
   151 		
       
   152 		delete [] symtabData;
       
   153 		delete strtabx;
       
   154 		
       
   155 		aFrag++;
       
   156 	}
       
   157 	SetFileFragmentData(aFileFragmentData, symTabSize, reinterpret_cast<char *>(iData));
       
   158 }
       
   159 
       
   160 
       
   161 size_t ElfSymbolTableManager::Size(){
       
   162 	return GetSymTabSectionSize();
       
   163 }
       
   164 
       
   165 void ElfSymbolTableManager::DeleteFileFragmentData(){
       
   166 	char * d = iData;
       
   167 	iData = NULL;
       
   168 	delete [] d;
       
   169 }
       
   170 
       
   171 void ElfSymbolTableManager::AddData(OutputFile & aOutputFile){
       
   172 	const FileFragment & aSectionFrag = iOutputFile.GetFileFragment(this);	
       
   173 	SetOffset(aSectionFrag.GetOffset());
       
   174 }
       
   175 
       
   176 void ElfSymbolTableManager::AddSymbolTable(){
       
   177 	// The sym table section needs to record the index of its associated
       
   178 	// string table in its link field and record the index of the first non-local
       
   179 	// symbol in its info field
       
   180 	int symTabSize = GetSymTabSectionSize(); 
       
   181 	size_t firstNonLocal = GetFirstNonLocalIndex();
       
   182 	size_t nextSectionIndex = iElfSectionManager.NumSections();
       
   183 	
       
   184 	ElfSectionElfData * aSymTabSectionData = new ElfSectionElfData(*this);
       
   185 	Elf32_Shdr symTabShdr;
       
   186 	symTabShdr.sh_name = 0; // for now.
       
   187 	symTabShdr.sh_type = SHT_SYMTAB;
       
   188 	symTabShdr.sh_flags = 0;
       
   189 	symTabShdr.sh_addr = 0;
       
   190 	symTabShdr.sh_offset = 0; // for now
       
   191 	symTabShdr.sh_size = symTabSize; // for now.
       
   192 	// symTabShdr will be @ index nextSectionIndex so the .strtab will 
       
   193 	// be @ nextSectionIndex +1
       
   194 	symTabShdr.sh_link = nextSectionIndex + 1;
       
   195 	symTabShdr.sh_info = firstNonLocal;
       
   196 	symTabShdr.sh_addralign = 4;
       
   197 	symTabShdr.sh_entsize = sizeof(Elf32_Sym);
       
   198 	
       
   199 	ElfSection aSymTabSection(aSymTabSectionData, ".symtab", symTabShdr);
       
   200 	iElfSectionManager.AddSection(aSymTabSection);
       
   201 
       
   202 
       
   203 	ElfSectionElfData * aStringTableSectionData = new ElfSectionElfData(iStringTable);
       
   204 	Elf32_Shdr shdr;
       
   205 	shdr.sh_name = 0; // for now.
       
   206 	shdr.sh_type = SHT_STRTAB;
       
   207 	shdr.sh_flags = 0;
       
   208 	shdr.sh_addr = 0;
       
   209 	shdr.sh_offset = 0; // for now
       
   210 	shdr.sh_size = GetSymTabStringsSectionSize();
       
   211 	shdr.sh_link = 0;
       
   212 	shdr.sh_info = 0;
       
   213 	shdr.sh_addralign = 0;
       
   214 	shdr.sh_entsize = 0;
       
   215 	ElfSection aStringTableSection(aStringTableSectionData, ".strtab", shdr);
       
   216 	iElfSectionManager.AddSection(aStringTableSection);
       
   217 
       
   218 }
       
   219 
       
   220 size_t ElfSymbolTableManager::GetSymTabSectionSize(){
       
   221 	int symTabSize = sizeof(Elf32_Sym); // add the 'undefined' symbols
       
   222 	
       
   223 	SymbolFragmentList::iterator aFrag = iSymbolFragments.begin();
       
   224 	SymbolFragmentList::iterator end = iSymbolFragments.end();
       
   225 	while (aFrag != end) {
       
   226 		symTabSize += aFrag->GetSymbolTableSize();
       
   227 		aFrag++;
       
   228 	}
       
   229 	return symTabSize;
       
   230 }
       
   231 
       
   232 size_t ElfSymbolTableManager::GetSymTabStringsSectionSize(){
       
   233 	
       
   234 	if (iSymbolStringTableSizeValid)
       
   235 		return iSymbolStringTableSize;
       
   236 	
       
   237 	int stringsSize = 1; // add the leading "\0"
       
   238 	
       
   239 	SymbolFragmentList::iterator aFrag = iSymbolFragments.begin();
       
   240 	SymbolFragmentList::iterator end = iSymbolFragments.end();
       
   241 	while (aFrag != end) {
       
   242 		stringsSize += aFrag->GetStringTableSize();
       
   243 		aFrag++;
       
   244 	}
       
   245 	iSymbolStringTableSizeValid = true;
       
   246 	return iSymbolStringTableSize = stringsSize;
       
   247 }
       
   248 
       
   249 size_t ElfSymbolTableManager::GetFirstNonLocalIndex(){
       
   250 	int ndx = 1; // add the 'undefined' symbols
       
   251 	
       
   252 	SymbolFragmentList::iterator aFrag = iSymbolFragments.begin();
       
   253 	SymbolFragmentList::iterator end = iSymbolFragments.end();
       
   254 	while (aFrag != end) {
       
   255 		ndx += aFrag->GetFirstGlobal();
       
   256 		aFrag++;
       
   257 	}
       
   258 	return ndx;
       
   259 }