diff -r 22486c9c7b15 -r 378360dbbdba imgtools/romtools/rombuild/symbolgenerator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imgtools/romtools/rombuild/symbolgenerator.cpp Wed Jun 30 11:35:58 2010 +0800 @@ -0,0 +1,536 @@ +#include +#include +#include "symbolgenerator.h" +#include "r_rom.h" +#include +#include "h_utl.h" +typedef boost::unique_lock scoped_lock ; +typedef boost::lock_guard 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 \""<::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& 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 ArmSymMap ; + +bool SymbolGenerator::ProcessARMV5Map(ifstream& aStream, const SymGenContext& aContext) { + string symName ; + ArmSymMap symbols ; + vector 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(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(addr,info)); + } + } + + TUint32 textSectAddr = 0x00008000; // .text gets linked at 0x00008000 + TUint32 dataSectAddr = 0x00400000 ; // .data gets linked at 0x00400000 + vector > 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(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 >::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 +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)); + } + else { + it->second = v ; + } +} +bool SymbolGenerator::ProcessGCCMap(ifstream& aStream, const SymGenContext& aContext){ + char* lineStart; + vector 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 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 + // .text$something + // + // 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){ + //# + //(/^\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::iterator it = symbols.begin(); + TUint32 lastAddr = it->first; + string lastSymName = it->second; + vector >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(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 >::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 >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(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 >::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 ; +}