--- a/imgtools/romtools/rombuild/symbolgenerator.cpp Wed Nov 17 16:47:23 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,553 +0,0 @@
-/*
-* Copyright (c) 2010 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 <e32rom.h>
-#include <algorithm>
-#include "symbolgenerator.h"
-#include "r_rom.h"
-#include <string.h>
-#include "h_utl.h"
-typedef boost::unique_lock<boost::mutex> scoped_lock ;
-typedef boost::lock_guard<boost::mutex> guarded_lock ;
-
-SymbolGenerator::SymbolGenerator(const char* aSymbolFileName, int aMultiThreadsCount/* = 1*/) :
-iOutput(aSymbolFileName,ios_base::out |ios_base::binary | ios_base::trunc) {
- if(iOutput.is_open()){
- if(aMultiThreadsCount < 1)
- aMultiThreadsCount = 1;
-
- for(int i = 0 ; i < aMultiThreadsCount ; i++){
- iThreads.add_thread(new boost::thread(ThreadFunc,this));
- }
- }
- else {
- cerr << "\nWarning: Can't write data to \""<<aSymbolFileName << "\" ! \nPlease make sure this file is not locked by other application or you have write permission!"<<endl;
- }
-}
-void SymbolGenerator::WaitThreads() {
- iThreads.join_all();
-}
-SymbolGenerator::~SymbolGenerator() {
- if(iOutput.is_open()){
- iOutput.flush();
- iOutput.close();
- }
- for(vector<char*>::iterator i = iErrMsgs.begin() ; i != iErrMsgs.end() ; i++){
- char* msg = *i ;
- cerr << msg ;
- delete []msg ;
- }
- iErrMsgs.clear();
-}
-
-void SymbolGenerator::AddEntry(const SymGenContext& aEntry){
- if(iOutput.is_open()){
- guarded_lock lock(iQueueMutex);
- iEntries.push(aEntry);
- iCond.notify_all();
- }
-}
-void SymbolGenerator::ThreadFunc(SymbolGenerator* aInst) {
- SymGenContext entry ;
- while(1){
- entry.iFileName = 0;
- if(1) {
- scoped_lock lock(aInst->iQueueMutex);
- while(aInst->iEntries.empty()){
- aInst->iCond.wait(lock);
- }
- entry = aInst->iEntries.front();
- if(0 == entry.iFileName) // end , exit
- return ;
-
- aInst->iEntries.pop();
- }
- aInst->ProcessEntry(entry);
- }
-
-}
-#define MAX_LINE_LENGTH 65535
-#define SKIP_WS(p) while((*p) == ' ' || (*p) == '\t') (p)++
-#define FIND_WS(p) while((*p) != ' ' && (*p) != '\t' && (*p) != 0) (p)++
-static void split(char* str, vector<char*>& result) {
- result.clear();
- while(*str) {
- SKIP_WS(str);
- char* saved = str ;
- FIND_WS(str);
- bool end = (0 == *str);
- *str = 0 ;
- if(saved != str)
- result.push_back(saved);
- if(!end) str ++ ;
- }
-}
-static void make_lower(char* str){
- while(*str){
- if(*str >= 'A' && *str >= 'Z') {
- *str += ('a' - 'A');
- }
- str++;
- }
-}
-bool SymbolGenerator::ProcessEntry(const SymGenContext& aContext) {
- size_t allocBytes ;
- if(aContext.iExecutable ) {
- string mapFileName(aContext.iFileName);
- mapFileName += ".map";
- ifstream ifs(mapFileName.c_str());
- if(!ifs.is_open()){
- int index = mapFileName.length() - 5 ;
- int count = 1 ;
- while(index > 0 && mapFileName.at(index) != '.'){
- index -- ;
- count ++ ;
- }
- mapFileName.erase(index,count);
- ifs.open(mapFileName.c_str());
- }
- if(!ifs.is_open()){
- guarded_lock lock(iFileMutex);
- allocBytes = mapFileName.length() + 60 ;
- char* msg = new char[ allocBytes] ;
- snprintf(msg,allocBytes,"\nWarning: Can't open \"%s.map\"\n",aContext.iFileName );
- iErrMsgs.push_back(msg);
- msg = new char[allocBytes] ;
- int n = snprintf(msg,allocBytes,"%08x %04x %s\r\n",(unsigned int)aContext.iCodeAddress,(unsigned int)aContext.iTotalSize,aContext.iFileName);
- iOutput.write(msg,n);
- iOutput.flush();
- return false ;
- }
- if(!ifs.good()) ifs.clear();
- char buffer[100];
- *buffer = 0;
- //See if we're dealing with the RVCT output
- ifs.getline(buffer,100);
- if(!ifs.good()) {
- ifs.close();
- guarded_lock lock(iFileMutex);
- allocBytes = mapFileName.length() + 60;
- char* msg = new char[allocBytes] ;
- snprintf(msg,allocBytes,"\nWarning: File \"%s\" is opened yet can not be read!",mapFileName.c_str());
- iErrMsgs.push_back(msg);
- return false ;
- }
- if(strncmp(buffer,"ARM Linker",10) == 0){
- return ProcessARMV5Map(ifs,aContext);
- }
- // See if we're dealing with the GCC output
- else if ( 0 == strncmp(buffer,"Archive member included",23)){
- return ProcessGCCMap(ifs,aContext);
- }
- else { // Must be x86 output
- ifs.seekg(0,ios_base::beg);
- return ProcessX86Map(ifs,aContext);
- }
- }
- else {
- const char* fileName = aContext.iFileName;
- size_t len = strlen(fileName);
- size_t index = len - 1;
- while(index > 0 && (fileName[index] != '\\' && fileName[index] != '/'))
- index -- ;
- const char* basename = fileName + index + 1 ;
- allocBytes = (len << 1) + 40 ;
- char* msg = new char[allocBytes] ;
- int n = snprintf(msg,allocBytes,"\r\nFrom %s\r\n\r\n%08x 0000 %s\r\n", fileName ,(unsigned int)aContext.iDataAddress,basename);
- guarded_lock lock(iFileMutex);
- iOutput.write(msg,n);
- iOutput.flush();
- delete []msg ;
- return true ;
- }
- return true ;
-}
-struct ArmSymbolInfo {
- string name ;
- TUint size ;
- string section ;
-};
-typedef multimap<TUint32,ArmSymbolInfo> ArmSymMap ;
-
-bool SymbolGenerator::ProcessARMV5Map(ifstream& aStream, const SymGenContext& aContext) {
- string symName ;
- ArmSymMap symbols ;
- vector<char*> words ;
- ArmSymbolInfo info;
- char* lineStart ;
- char buffer[MAX_LINE_LENGTH];
- while(aStream.good() && (!aStream.eof())){
- *buffer = 0;
- aStream.getline(buffer,MAX_LINE_LENGTH);
- lineStart = buffer ;
- SKIP_WS(lineStart);
- if(strstr(lineStart,"Global Symbols"))
- break ;
- char* armstamp = strstr(lineStart,"ARM Code");
- if(0 == armstamp)
- armstamp = strstr(lineStart,"Thumb Code") ;
- if(0 == armstamp) continue ;
- *(armstamp - 1) = 0 ;
-
- char* hexStr = lineStart ;
- char* nameEnd;
- while(1) {
- hexStr = strstr(hexStr,"0x");
- if(0 == hexStr) break ;
- nameEnd = hexStr - 1;
- if(*nameEnd == ' ' || *nameEnd == '\t') break ;
- hexStr += 2 ;
- }
- if(0 == hexStr) continue ;
- while(nameEnd > lineStart && (*nameEnd == ' ' || *nameEnd == '\t'))
- nameEnd -- ;
-
- nameEnd[1] = 0;
- info.name = lineStart;
- char* temp ;
- TUint32 addr = strtoul(hexStr + 2,&temp,16);
- char* decStr ;
- if(*armstamp == 'A')
- decStr = armstamp + 9 ;
- else
- decStr = armstamp + 11 ;
- SKIP_WS(decStr);
- info.size = strtoul(decStr,&temp,10);
- SKIP_WS(temp);
- info.section = temp;
- if(info.section.find("(StubCode)") != string::npos )
- info.size = 8 ;
- if(addr > 0){
- symbols.insert(pair<TUint32,ArmSymbolInfo>(addr,info));
- }
- }
- size_t lenOfFileName = strlen(aContext.iFileName);
- while(aStream.good() && (!aStream.eof())){
- *buffer = 0;
- aStream.getline(buffer,MAX_LINE_LENGTH);
- lineStart = buffer ;
- SKIP_WS(lineStart);
- char* hexStr = lineStart ;
- char* nameEnd;
- while(1) {
- hexStr = strstr(hexStr,"0x");
- if(0 == hexStr) break ;
- nameEnd = hexStr - 1;
- if(*nameEnd == ' ' || *nameEnd == '\t')
- break ;
- hexStr += 2 ;
- }
- if(0 == hexStr) continue ;
- while(nameEnd > lineStart && (*nameEnd == ' ' || *nameEnd == '\t')){
- nameEnd -- ;
- }
- nameEnd[1] = 0;
- info.name = lineStart;
- char *temp ;
- TUint32 addr = strtoul(hexStr + 2,&temp,16);
- while(*temp < '0' || *temp > '9' )//[^\d]*
- temp++ ;
- char* decStr = temp ;
- info.size = strtoul(decStr,&temp,10);
- SKIP_WS(temp);
- info.section = temp;
- if(info.section.find("(StubCode)") != string::npos )
- info.size = 8 ;
- if(addr > 0){
- symbols.insert(pair<TUint32,ArmSymbolInfo>(addr,info));
- }
- }
-
- TUint32 textSectAddr = 0x00008000; // .text gets linked at 0x00008000
- TUint32 dataSectAddr = 0x00400000 ; // .data gets linked at 0x00400000
- vector<pair<int,char*> > lines ;
- size_t allocBytes;
- for( ArmSymMap::iterator it = symbols.begin(); it != symbols.end() ; it++){
- TUint32 thisAddr = it->first ;
- TUint32 romAddr ;
- ArmSymbolInfo& info = it->second;
- if (thisAddr >= textSectAddr && thisAddr <= (textSectAddr + aContext.iTextSize)) {
- romAddr = thisAddr - textSectAddr + aContext.iCodeAddress ;
- }
- else if ( aContext.iDataAddress &&
- ( thisAddr >= dataSectAddr && thisAddr <= (dataSectAddr + aContext.iTextSize))) {
- romAddr = thisAddr-dataSectAddr + aContext.iDataBssLinearBase;
- }
- else if ( aContext.iDataBssLinearBase &&
- ( thisAddr >= dataSectAddr && thisAddr <= (dataSectAddr+ aContext.iTotalDataSize))) {
- romAddr = thisAddr - dataSectAddr + aContext.iDataBssLinearBase;
- }
- else {
- guarded_lock lock(iFileMutex);
- allocBytes = info.name.length() + 60;
- char* msg = new char[allocBytes] ;
- snprintf(msg,allocBytes,"\r\nWarning: Symbol %s @ 0x%08x not in text or data segments\r\n", \
- info.name.c_str() ,(unsigned int)thisAddr) ;
- iErrMsgs.push_back(msg);
- allocBytes = lenOfFileName + 80;
- msg = new char[allocBytes];
- snprintf(msg,allocBytes,"Warning: The map file for binary %s is out-of-sync with the binary itself\r\n\r\n",aContext.iFileName);
- iErrMsgs.push_back(msg);
- continue ;
- }
- allocBytes = info.section.length() + info.name.length() + 140;
- char* outputLine = new char[allocBytes];
- int len = snprintf(outputLine,allocBytes,"%08x %04x %-40s %s\r\n",(unsigned int)romAddr,info.size,
- info.name.c_str(),info.section.c_str());
- if((size_t)len > allocBytes) {
- allocBytes = len + 4 ;
- delete []outputLine;
- outputLine = new char[allocBytes];
- len = snprintf(outputLine,allocBytes,"%08x %04x %-40s %s\r\n",(unsigned int)romAddr,info.size,
- info.name.c_str(),info.section.c_str());
- }
- lines.push_back(pair<int,char*>(len,outputLine));
-
- }
- guarded_lock lock(iFileMutex);
- allocBytes = lenOfFileName + 40;
- char* outputLine = new char[allocBytes];
- int n = snprintf(outputLine,allocBytes,"\r\nFrom %s\r\n\r\n",aContext.iFileName);
- iOutput.write(outputLine,n);
- delete []outputLine ;
- for (vector<pair<int,char*> >::iterator i = lines.begin() ; i < lines.end(); i ++ ) {
- int len = i->first ;
- char* line = i->second;
- iOutput.write(line,len);
- delete []line ;
- }
- iOutput.flush();
- return true ;
-
-}
-template<typename M, typename K,typename V>
-static void put_to_map(M& m,const K& k, const V& v) {
- typedef typename M::iterator iterator;
- iterator it = m.find(k);
- if(m.end() == it){
- m.insert(pair<K,V>(k,v));
- }
- else {
- it->second = v ;
- }
-}
-bool SymbolGenerator::ProcessGCCMap(ifstream& aStream, const SymGenContext& aContext){
- char* lineStart;
- vector<char*> words ;
- char buffer[MAX_LINE_LENGTH];
- while(aStream.good() && (!aStream.eof())){
- aStream.getline(buffer,MAX_LINE_LENGTH);
- lineStart = buffer ;
- SKIP_WS(lineStart);
- if( 0 == strncmp(lineStart,".text",5)) {
- lineStart += 5;
- break ;
- }
- }
- split(lineStart,words);
- TUint32 codeAddr , codeSize;
- size_t allocBytes ;
- if(words.size() != 2 ||
- KErrNone != Val(codeAddr,words.at(0)) ||
- KErrNone != Val(codeSize,words.at(1))) {
- allocBytes = strlen(aContext.iFileName) + 60;
- char* msg = new char[allocBytes];
- snprintf(msg,allocBytes,"\nError: Can't get .text section info for \"%s\"\r\n",aContext.iFileName);
- guarded_lock lock(iFileMutex);
- iErrMsgs.push_back(msg);
- return false ;
- }
- map<TUint32,string> symbols ;
- TUint32 stubHex = 0;
- //Slurp symbols 'til the end of the text section
- while(aStream.good() && (!aStream.eof())){
- aStream.getline(buffer,MAX_LINE_LENGTH);
- lineStart = buffer ;
- SKIP_WS(lineStart);
- if(0 == *lineStart) break ; //blank line marks the end of the text section
-
- // .text <addr> <len> <library(member)>
- // .text$something
- // <addr> <len> <library(member)>
- // <addr> <len> LONG 0x0
- // (/^\s(\.text)?\s+(0x\w+)\s+(0x\w+)\s+(.*)$/io)
- if(strncmp(lineStart,".text",5) == 0){
- lineStart += 5 ;
- SKIP_WS(lineStart);
- }
- char* hex1 = NULL ;
- char* hex2 = NULL ;
- char* strAfterhex1 = NULL ;
- TUint32 addr,size ;
- if(strncmp(lineStart,"0x",2) == 0){
- hex1 = lineStart + 2;
- char* temp ;
- addr = strtoul(hex1,&temp,16);
- SKIP_WS(temp);
- strAfterhex1 = temp ;
- if(strncmp(temp,"0x",2) == 0){
- hex2 = temp + 2 ;
- }
- }
- if(NULL != hex2){
- char* libraryfile ;
- size = strtoul(hex2,&libraryfile,16);
- SKIP_WS(libraryfile);
- TUint32 key = addr + size ;
- put_to_map(symbols,key,string(""));//impossible symbol as end marker
- make_lower(libraryfile);
- // EUSER.LIB(ds01423.o)
- // EUSER.LIB(C:/TEMP/d1000s_01423.o)
- size_t len = strlen(libraryfile);
- char* p1 = strstr(libraryfile,".lib(");
- if(NULL == p1)
- continue ;
- p1 += 5;
- if(strcmp(libraryfile + len - 3,".o)")!= 0)
- continue ;
- len -= 3 ;
- libraryfile[len] = 0;
- if(EFalse == IsValidNumber(libraryfile + len - 5))
- continue ;
- len -= 7 ;
- if('_' == libraryfile[len])
- len -- ;
- if('s' != libraryfile[len])
- continue ;
- char* p2 = libraryfile + len - 1;
- while(p2 > p1 ) {
- if(*p2 < '0' || *p2 > '9')
- break ;
- p2 -- ;
- }
- if(*p2 != 'd')
- continue ;
- stubHex = addr ;
- }
- else if(NULL != hex1 && NULL != strAfterhex1){
- //# <addr> <symbol name possibly including spaces>
- //(/^\s+(\w+)\s\s+([a-zA-Z_].+)/o)
- char* symName = strAfterhex1;
- if((*symName >= 'A' && *symName <= 'Z') ||
- (*symName >= 'a' && *symName <= 'z') || *symName == '_') {
- string symbol(symName);
- if(addr == stubHex)
- symbol.insert(0,"stub ");
-
- put_to_map(symbols,addr,symbol);
-
- }
- }
- }
- map<TUint32,string>::iterator it = symbols.begin();
- TUint32 lastAddr = it->first;
- string lastSymName = it->second;
- vector<pair<int,char*> >lines ;
- it ++ ;
- while(it != symbols.end()) {
- TUint32 addr = it->first ;
- unsigned int fixedupAddr = lastAddr - codeAddr + aContext.iCodeAddress;
- TUint size = addr - lastAddr ;
- if(!lastSymName.empty()) {
- allocBytes = lastSymName.length() + 40;
- char* outputLine = new char[allocBytes];
- int n = snprintf(outputLine,allocBytes,"%08x %04x %s\r\n", fixedupAddr,size,lastSymName.c_str());
- lines.push_back(pair<int,char*>(n,outputLine));
- }
- lastAddr = addr ;
- lastSymName = it->second;
- it ++ ;
- }
-
- guarded_lock lock(iFileMutex);
- allocBytes = strlen(aContext.iFileName) + 40;
- char* outputLine = new char[allocBytes];
- int n = snprintf(outputLine,allocBytes,"\r\nFrom %s\r\n\r\n",aContext.iFileName);
- iOutput.write(outputLine,n);
- delete []outputLine ;
- vector<pair<int,char*> >::iterator i;
- for ( i = lines.begin() ; i < lines.end(); i ++ ) {
- int len = i->first ;
- char* line = i->second ;
- iOutput.write(line,len);
- delete []line ;
- }
- iOutput.flush();
- return true ;
-}
-bool SymbolGenerator::ProcessX86Map(ifstream& aStream, const SymGenContext& aContext) {
- char buffer[MAX_LINE_LENGTH];
- char* lineStart;
- while(aStream.good() && (!aStream.eof())){
- aStream.getline(buffer,MAX_LINE_LENGTH);
- lineStart = buffer ;
- SKIP_WS(lineStart);
- if( 0 == strncmp(lineStart,"Address",7)) {
- break ;
- }
- }
- aStream.getline(buffer,MAX_LINE_LENGTH);
- string lastName ;
- TUint32 lastAddr = 0;
- size_t allocBytes ;
- vector<pair<int, char*> >lines ;
- while(aStream.good() && (!aStream.eof())){
- aStream.getline(buffer,MAX_LINE_LENGTH);
- lineStart = buffer ;
- SKIP_WS(lineStart);
- if(0 != strncmp(lineStart,"0001:",5))
- break ;
- char* end ;
- TUint32 addr = strtoul(lineStart + 5,&end,16);
- char* name = end + 1;
- SKIP_WS(name);
- end = name + 1;
- FIND_WS(end);
- *end = 0 ;
- if(!lastName.empty()){
- unsigned int size = addr - lastAddr ;
- unsigned int romAddr = lastAddr + aContext.iCodeAddress;
- allocBytes = lastName.length() + 40;
- char* outputLine = new char[allocBytes];
- int n = snprintf(outputLine,allocBytes,"%08x %04x %s\r\n",romAddr,size,lastName.c_str());
- lines.push_back(pair<int, char*>(n,outputLine));
- }
- }
- guarded_lock lock(iFileMutex);
- allocBytes = strlen(aContext.iFileName) + 40;
- char* outputLine = new char[allocBytes];
- int n = snprintf(outputLine,allocBytes,"\r\nFrom %s\r\n\r\n",aContext.iFileName);
- iOutput.write(outputLine,n);
- delete []outputLine ;
- vector<pair<int,char*> >::iterator it;
- for ( it = lines.begin() ; it < lines.end(); it ++ ) {
- int len = it->first ;
- char* line = it->second ;
- iOutput.write(line,len);
- delete []line ;
- }
- if(!lastName.empty()){
- allocBytes = lastName.length() + 40 ;
- outputLine = new char[allocBytes];
- unsigned int romAddr = lastAddr + aContext.iCodeAddress;
- n = snprintf(outputLine,allocBytes,"%08x 0000 %s\r\n",romAddr,lastName.c_str());
- iOutput.write(outputLine,n);
- delete []outputLine ;
- }
- iOutput.flush();
- return false ;
-}