/*
* 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 <boost/regex.hpp>
#include "symbolprocessunit.h"
#include "e32image.h"
#include "symbolgenerator.h"
#include "h_utl.h"
#define MAX_LINE 65535
#if defined(__LINUX__)
#define PATH_SEPARATOR '/'
#else
#define PATH_SEPARATOR '\\'
#endif
void SymbolProcessUnit::ProcessEntry(const TPlacedEntry& aEntry)
{
if(aEntry.iFileName == "")
return;
else if(aEntry.iExecutable)
ProcessExecutableFile(aEntry.iFileName);
else
ProcessDataFile(aEntry.iFileName);
}
// CommenRomSymbolProcessUnit start
void CommenRomSymbolProcessUnit::FlushStdOut(ostream& aOut)
{
for(int i = 0; i < (int) iStdoutLog.size(); i++)
{
aOut << iStdoutLog[i];
}
}
void CommenRomSymbolProcessUnit::FlushSymbolContent(ostream &aOut)
{
for(int i = 0; i < (int) iSymbolContentLog.size(); i++)
{
aOut << iSymbolContentLog[i];
}
}
void CommenRomSymbolProcessUnit::ResetContentLog()
{
iStdoutLog.clear();
iSymbolContentLog.clear();
}
void CommenRomSymbolProcessUnit::ProcessEntry(const TPlacedEntry& aEntry)
{
iPlacedEntry = aEntry;
SymbolProcessUnit::ProcessEntry(aEntry);
}
void CommenRomSymbolProcessUnit::ProcessExecutableFile(const string& aFile)
{
ResetContentLog();
char str[MAX_LINE];
string outString;
outString = "\nFrom ";
outString += aFile + "\n\n";
iSymbolContentLog.push_back(outString);
string mapFile2 = aFile+".map";
size_t dot = aFile.rfind('.');
string mapFile = aFile.substr(0,dot)+".map";
ifstream fMap;
fMap.open(mapFile2.c_str());
if(!fMap.is_open()) {
fMap.open(mapFile.c_str());
}
if(!fMap.is_open()) {
sprintf(str, "\nWarning: Can't open \"%s\" or \"%s\"\n",mapFile2.c_str(),mapFile.c_str());
iStdoutLog.push_back(str);
memset(str,0,sizeof(str));
sprintf(str, "%08x %04x ", (unsigned int)iPlacedEntry.iCodeAddress, (unsigned int)iPlacedEntry.iTotalSize);
outString = str;
outString += aFile.substr(aFile.rfind(PATH_SEPARATOR)+1)+"\n";
iSymbolContentLog.push_back(outString);
}
else {
if(!fMap.good()) fMap.clear();
char buffer[100];
fMap.getline(buffer, 100);
boost::regex regARMV5("ARM Linker", boost::regex::icase);
boost::regex regGCCEoARMV4("Archive member included", boost::regex::icase);
boost::cmatch what;
if(regex_search(buffer, what, regARMV5)) {
ProcessArmv5File(aFile, fMap);
}
else if(regex_search(buffer, what, regGCCEoARMV4)) {
ProcessGcceOrArm4File(aFile, fMap);
}
else {
fMap.seekg(0, ios_base::beg);
ProcessX86File(aFile, fMap);
}
}
}
void CommenRomSymbolProcessUnit::ProcessDataFile(const string& aFile)
{
ResetContentLog();
char str[MAX_LINE];
memset(str,0,sizeof(str));
string basename = aFile.substr(aFile.rfind(PATH_SEPARATOR)+1);
sprintf(str, "\nFrom %s\n\n%08x 0000 %s\n", aFile.c_str(), (unsigned int) iPlacedEntry.iDataAddress, basename.c_str());
iSymbolContentLog.push_back(str);
}
struct ArmSymbolInfo {
string name ;
TUint size ;
string section ;
};
typedef multimap<TUint32,ArmSymbolInfo> ArmSymMap ;
#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++;
}
}
void CommenRomSymbolProcessUnit::ProcessArmv5File(const string& aFile, ifstream& aMap)
{
string symName ;
ArmSymMap symbols ;
vector<char*> words ;
ArmSymbolInfo info;
char* lineStart ;
char buffer[MAX_LINE];
while(aMap.good() && (!aMap.eof())){
*buffer = 0;
aMap.getline(buffer,MAX_LINE);
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 = iPlacedEntry.iFileName.length();
while(aMap.good() && (!aMap.eof())){
*buffer = 0;
aMap.getline(buffer,MAX_LINE);
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 + iPlacedEntry.iTextSize)) {
romAddr = thisAddr - textSectAddr + iPlacedEntry.iCodeAddress ;
}
else if ( iPlacedEntry.iDataAddress &&
( thisAddr >= dataSectAddr && thisAddr <= (dataSectAddr + iPlacedEntry.iTextSize))) {
romAddr = thisAddr-dataSectAddr + iPlacedEntry.iDataBssLinearBase;
}
else if ( iPlacedEntry.iDataBssLinearBase &&
( thisAddr >= dataSectAddr && thisAddr <= (dataSectAddr+ iPlacedEntry.iTotalDataSize))) {
romAddr = thisAddr - dataSectAddr + iPlacedEntry.iDataBssLinearBase;
}
else {
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) ;
iStdoutLog.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",iPlacedEntry.iFileName.c_str());
iStdoutLog.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));
}
for (vector<pair<int,char*> >::iterator i = lines.begin() ; i < lines.end(); i ++ ) {
char* line = i->second;
iSymbolContentLog.push_back(line);
delete[] line;
}
}
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 ;
}
}
void CommenRomSymbolProcessUnit::ProcessGcceOrArm4File(const string& aFile, ifstream& aMap)
{
char* lineStart;
vector<char*> words ;
char buffer[MAX_LINE];
while(aMap.good() && (!aMap.eof())){
aMap.getline(buffer,MAX_LINE);
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 = iPlacedEntry.iFileName.length() + 60;
char* msg = new char[allocBytes];
snprintf(msg,allocBytes,"\nError: Can't get .text section info for \"%s\"\r\n",iPlacedEntry.iFileName.c_str());
iStdoutLog.push_back(msg);
return;
}
map<TUint32,string> symbols ;
TUint32 stubHex = 0;
//Slurp symbols 'til the end of the text section
while(aMap.good() && (!aMap.eof())){
aMap.getline(buffer,MAX_LINE);
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 + iPlacedEntry.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 ++ ;
}
vector<pair<int,char*> >::iterator i;
for ( i = lines.begin() ; i < lines.end(); i ++ ) {
char* line = i->second ;
iSymbolContentLog.push_back(line);
delete []line ;
}
}
void CommenRomSymbolProcessUnit::ProcessX86File(const string& aFile, ifstream& aMap)
{
char buffer[MAX_LINE];
char* lineStart;
while(aMap.good() && (!aMap.eof())){
aMap.getline(buffer,MAX_LINE);
lineStart = buffer ;
SKIP_WS(lineStart);
if( 0 == strncmp(lineStart,"Address",7)) {
break ;
}
}
aMap.getline(buffer,MAX_LINE);
string lastName ;
TUint32 lastAddr = 0;
size_t allocBytes ;
vector<pair<int, char*> >lines ;
while(aMap.good() && (!aMap.eof())){
aMap.getline(buffer,MAX_LINE);
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 + iPlacedEntry.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));
}
}
vector<pair<int,char*> >::iterator it;
for ( it = lines.begin() ; it < lines.end(); it ++ ) {
char* line = it->second ;
iSymbolContentLog.push_back(line);
delete []line ;
}
if(!lastName.empty()){
allocBytes = lastName.length() + 40 ;
char* outputLine = new char[allocBytes];
unsigned int romAddr = lastAddr + iPlacedEntry.iCodeAddress;
snprintf(outputLine,allocBytes,"%08x 0000 %s\r\n",romAddr,lastName.c_str());
iSymbolContentLog.push_back(outputLine);
delete []outputLine ;
}
}
// CommenRomSymbolProcessUnit end
// CommenRofsSymbolProcessUnit start
void CommenRofsSymbolProcessUnit::ProcessExecutableFile(const string& aFile)
{
ResetContentLog();
char str[MAX_LINE];
string outString;
outString = "\nFrom ";
outString += aFile + "\n\n";
iSymbolContentLog.push_back(outString);
string mapFile2 = aFile+".map";
size_t dot = aFile.rfind('.');
string mapFile = aFile.substr(0,dot)+".map";
ifstream fMap;
fMap.open(mapFile2.c_str());
if(!fMap.is_open()) {
fMap.open(mapFile.c_str());
}
if(!fMap.is_open()) {
sprintf(str, "%s\nWarning: Can't open \"%s\" or \"%s\"\n",aFile.c_str(),mapFile2.c_str(),mapFile.c_str());
iStdoutLog.push_back(str);
int binSize = GetSizeFromBinFile(aFile);
memset(str,0,sizeof(str));
sprintf(str,"%04x", binSize);
outString = "00000000 ";
outString += str;
outString += " ";
outString += aFile.substr(aFile.rfind(PATH_SEPARATOR)+1)+"\n";
iSymbolContentLog.push_back(outString);
}
else {
if(!fMap.good()) fMap.clear();
boost::regex regARMV5("ARMV5", boost::regex::icase);
boost::regex regGCCEoARMV4("(GCCE|ARMV4)", boost::regex::icase);
boost::cmatch what;
if(regex_search(aFile, what, regARMV5)) {
ProcessArmv5File(aFile, fMap);
}
else if(regex_search(aFile, what, regGCCEoARMV4)) {
ProcessGcceOrArm4File(aFile, fMap);
}
else {
sprintf(str, "\nWarning: cannot determine linker type used to create %s\n",aFile.c_str());
iStdoutLog.push_back(str);
outString = "00000000 0000 ";
outString += aFile.substr(aFile.rfind(PATH_SEPARATOR)+1)+"\n";
iSymbolContentLog.push_back(outString);
}
}
}
void CommenRofsSymbolProcessUnit::ProcessDataFile(const string& aFile)
{
ResetContentLog();
string line = "\nFrom "+aFile+"\n\n00000000 0000 "+aFile.substr(aFile.rfind(PATH_SEPARATOR)+1)+"\n";
iSymbolContentLog.push_back(line);
}
void CommenRofsSymbolProcessUnit::FlushStdOut(ostream& aOut)
{
for(int i = 0; i < (int) iStdoutLog.size(); i++)
{
aOut << iStdoutLog[i];
}
}
void CommenRofsSymbolProcessUnit::FlushSymbolContent(ostream &aOut)
{
for(int i = 0; i < (int) iSymbolContentLog.size(); i++)
{
aOut << iSymbolContentLog[i];
}
}
void CommenRofsSymbolProcessUnit::ResetContentLog()
{
iStdoutLog.clear();
iSymbolContentLog.clear();
}
void CommenRofsSymbolProcessUnit::ProcessArmv5File( const string& fileName, ifstream& aMap ){
aMap.seekg (0, ios::beg);
char str[MAX_LINE];
char outbuffer[MAX_LINE];
string outString;
aMap.getline(str,MAX_LINE);
boost::cmatch what;
boost::regex reg("^ARM Linker");
if(!regex_search(str, what, reg)) {
sprintf(outbuffer, "\nWarning: expecting %s to be generated by ARM linker\n", fileName.c_str());
iStdoutLog.push_back(outbuffer);
outString = "00000000 0000 "+fileName.substr(fileName.rfind(PATH_SEPARATOR)+1)+"\n";
iSymbolContentLog.push_back(outString);
}
reg.assign("Global Symbols");
while(aMap.getline(str,MAX_LINE)) {
if(regex_search(str, what, reg)) {
break;
}
}
reg.assign("^\\s*(.+)\\s*0x(\\S+)\\s+[^\\d]*(\\d+)\\s+(.*)$");
string sSym,sTmp,sSection;
unsigned int addr,size,baseOffset = 0;
map<unsigned int,string> syms;
char symString[MAX_LINE];
while(aMap.getline(str,MAX_LINE)) {
if(regex_search(str, what, reg)) {
sSym.assign(what[1].first,what[1].second-what[1].first);
sTmp.assign(what[2].first,what[2].second-what[2].first);
addr = strtol(sTmp.c_str(), NULL, 16);
sTmp.assign(what[3].first,what[3].second-what[3].first);
size = strtol(sTmp.c_str(), NULL, 10);
sSection.assign(what[4].first,what[4].second-what[4].first);
if(sSection.find("(StubCode)") != string::npos)
size = 8;
if(addr > 0) {
memset(symString,0,sizeof(symString));
sprintf(symString,"%04x ",size);
outString = symString;
outString += sSym+" ";
outString += sSection;
if(baseOffset == 0)
baseOffset = addr;
unsigned int k = addr - baseOffset;
if( (syms.find(k) == syms.end()) || size != 0)
syms[k] = outString;
}
// end of addr>0
}
// end of regex_search
}
map<unsigned int,string>::iterator it;
for(it = syms.begin(); it != syms.end(); it++) {
memset(str,0,sizeof(str));
sprintf(str,"%08x",it->first);
outString = str;
outString += " ";
outString += it->second+"\n";
iSymbolContentLog.push_back(outString);
}
}
void CommenRofsSymbolProcessUnit::ProcessGcceOrArm4File( const string& fileName, ifstream& aMap ){
aMap.seekg (0, ios_base::beg);
char str[MAX_LINE];
char outbuffer[MAX_LINE];
aMap.getline(str,MAX_LINE);
boost::cmatch what;
boost::regex reg("^\\.text\\s+");
while(aMap.getline(str,MAX_LINE)) {
if(regex_search(str, what, reg)) {
break;
}
}
reg.assign("^\\.text\\s+(\\w+)\\s+\\w+");
if(!regex_search(str, what, reg)) {
sprintf(outbuffer, "ERROR: Can't get .text section info for \"%s\"\n",fileName.c_str());
iStdoutLog.push_back(outbuffer);
}
else {
string sTmp, sLibFile;
sTmp.assign(what[1].first,what[1].second-what[1].first);
unsigned int imgText = strtol(sTmp.c_str(), NULL, 16);
reg.assign("^LONG 0x.*", boost::regex::icase);
boost::cmatch what1;
boost::regex reg1("^\\s(\\.text)?\\s+(0x\\w+)\\s+(0x\\w+)\\s+(.*)$", boost::regex::icase);
boost::regex reg2("^\\s+(\\w+)\\s\\s+([a-zA-Z_].+)", boost::regex::icase);
boost::regex reg3(".*lib\\(.*d\\d*s_?\\d{5}.o\\)$", boost::regex::icase);
map<unsigned int,string> syms;
unsigned int addr, len, stubhex;
while(aMap.getline(str,MAX_LINE)) {
if(strlen(str) == 0)
break;
else if(regex_search(str, what, reg1)) {
sLibFile.assign(what[4].first,what[4].second-what[4].first);
if(!regex_search(sLibFile, what1, reg)) {
sTmp.assign(what[2].first,what[2].second-what[2].first);
addr = strtol(sTmp.c_str(), NULL, 16);
sTmp.assign(what[3].first,what[3].second-what[3].first);
len = strtol(sTmp.c_str(), NULL, 16);
syms[addr+len] = "";
if(regex_search(sLibFile, what, reg3)) {
stubhex = addr;
}
}
}
else if(regex_search(str, what, reg2)) {
sTmp.assign(what[1].first,what[1].second-what[1].first);
addr = strtol(sTmp.c_str(), NULL, 16);
sTmp.assign(what[2].first,what[2].second-what[2].first);
syms[addr] = (addr == stubhex)? ("stub "+sTmp) : sTmp;
}
}
map<unsigned int,string>::iterator it = syms.begin();
map<unsigned int,string>::iterator itp = it++;
string outString;
for(; it != syms.end(); itp = it++) {
if(itp->second != "") {
memset(str,0,sizeof(str));
sprintf(str,"%08x %04x ",(itp->first-imgText), (it->first-itp->first));
outString = str;
outString += it->second+"\n";
iSymbolContentLog.push_back(outString);
}
}
}
}
// CommenRofsSymbolProcessUnit end
int SymbolProcessUnit::GetSizeFromBinFile( const string& fileName ){
TInt ret = 0;
//char outbuffer[MAX_LINE];
ifstream aIf(fileName.c_str(), ios_base::binary);
if( !aIf.is_open() ) {
printf("Warning: Cannot open file %s\n", fileName.c_str());
//iStdoutLog.push_back(outbuffer);
}
else {
E32ImageFile e32Image;
TUint32 aSz;
aIf.seekg(0,ios_base::end);
aSz = aIf.tellg();
e32Image.Adjust(aSz);
e32Image.iFileSize = aSz;
aIf.seekg(0,ios_base::beg);
aIf >> e32Image;
ret = e32Image.iOrigHdr->iCodeSize;
}
return ret;
}
// for BSym
void BsymRofsSymbolProcessUnit::ProcessEntry(const TPlacedEntry& aEntry)
{
SymbolProcessUnit::ProcessEntry(aEntry);
if(aEntry.iFileName == "")
return;
else if(aEntry.iExecutable)
ProcessExecutableFile(aEntry.iFileName);
else
ProcessDataFile(aEntry.iFileName);
iMapFileInfo.iDbgUnitPCEntry.iPCName = aEntry.iFileName;
iMapFileInfo.iDbgUnitPCEntry.iDevName = aEntry.iDevFileName;
}
void BsymRofsSymbolProcessUnit::ProcessExecutableFile(const string& aFile)
{
ResetContentLog();
char str[MAX_LINE];
string mapFile2 = aFile+".map";
size_t dot = aFile.rfind('.');
string mapFile = aFile.substr(0,dot)+".map";
ifstream fMap;
fMap.open(mapFile2.c_str());
if(!fMap.is_open()) {
fMap.open(mapFile.c_str());
}
if(!fMap.is_open()) {
sprintf(str, "%s\nWarning: Can't open \"%s\" or \"%s\"\n",aFile.c_str(),mapFile2.c_str(),mapFile.c_str());
iStdoutLog.push_back(str);
int binSize = GetSizeFromBinFile(aFile);
TSymbolPCEntry tmpEntry;
tmpEntry.iSymbolEntry.iAddress = 0;
tmpEntry.iSymbolEntry.iLength = binSize;
tmpEntry.iName = aFile.substr(aFile.rfind(PATH_SEPARATOR)+1);
iMapFileInfo.iSymbolPCEntrySet.push_back(tmpEntry);
iMapFileInfo.iDbgUnitPCEntry.iDbgUnitEntry.iDataSymbolCount++;
}
else {
if(!fMap.good()) fMap.clear();
boost::regex regARMV5("ARMV5", boost::regex::icase);
boost::regex regGCCEoARMV4("(GCCE|ARMV4)", boost::regex::icase);
boost::cmatch what;
if(regex_search(aFile, what, regARMV5)) {
ProcessArmv5File(aFile, fMap);
}
else if(regex_search(aFile, what, regGCCEoARMV4)) {
ProcessGcceOrArm4File(aFile, fMap);
}
else {
sprintf(str, "\nWarning: cannot determine linker type used to create %s\n",aFile.c_str());
iStdoutLog.push_back(str);
TSymbolPCEntry tmpEntry;
tmpEntry.iSymbolEntry.iAddress = 0;
tmpEntry.iSymbolEntry.iLength = 0;
tmpEntry.iName = aFile.substr(aFile.rfind(PATH_SEPARATOR)+1);
iMapFileInfo.iSymbolPCEntrySet.push_back(tmpEntry);
iMapFileInfo.iDbgUnitPCEntry.iDbgUnitEntry.iDataSymbolCount++;
}
}
}
void BsymRofsSymbolProcessUnit::ProcessDataFile(const string& aFile)
{
ResetContentLog();
TSymbolPCEntry tmpEntry;
tmpEntry.iSymbolEntry.iAddress = 0;
tmpEntry.iSymbolEntry.iLength = 0;
tmpEntry.iName = aFile.substr(aFile.rfind(PATH_SEPARATOR)+1);
iMapFileInfo.iSymbolPCEntrySet.push_back(tmpEntry);
iMapFileInfo.iDbgUnitPCEntry.iDbgUnitEntry.iDataSymbolCount++;
}
void BsymRofsSymbolProcessUnit::FlushStdOut(ostream& aOut)
{
for(int i = 0; i < (int) iStdoutLog.size(); i++)
{
aOut << iStdoutLog[i];
}
}
void BsymRofsSymbolProcessUnit::FlushSymbolContent(ostream &aOut)
{
iSymbolGeneratorPtr->AppendMapFileInfo(iMapFileInfo);
}
void BsymRofsSymbolProcessUnit::ResetContentLog()
{
iStdoutLog.clear();
iMapFileInfo.iDbgUnitPCEntry.iPCName = "";
iMapFileInfo.iDbgUnitPCEntry.iDevName = "";
iMapFileInfo.iDbgUnitPCEntry.iDbgUnitEntry.Reset();
iMapFileInfo.iSymbolPCEntrySet.clear();
}
void BsymRofsSymbolProcessUnit::ProcessArmv5File( const string& fileName, ifstream& aMap ){
aMap.seekg (0, ios::beg);
char str[MAX_LINE];
char outbuffer[MAX_LINE];
aMap.getline(str,MAX_LINE);
boost::cmatch what;
boost::regex reg("^ARM Linker");
if(!regex_search(str, what, reg)) {
sprintf(outbuffer, "\nWarning: expecting %s to be generated by ARM linker\n", fileName.c_str());
iStdoutLog.push_back(outbuffer);
return;
}
reg.assign("Global Symbols");
boost::regex bss_search("^\\s*\\.bss\\s*0x(\\S+)\\s*.*$");
bool hasValue = false;
string bssStart;
TUint32 bssSection = 0;
while(aMap.getline(str,MAX_LINE)) {
if(!hasValue && regex_search(str, what, bss_search))
{
hasValue = true;
bssStart.assign(what[1].first,what[1].second-what[1].first);
}
if(regex_search(str, what, reg)) {
break;
}
}
if(!bssStart.empty())
{
bssSection = strtol(bssStart.c_str(), NULL, 16);
}
reg.assign("^\\s*(.+)\\s*0x(\\S+)\\s+[^\\d]*(\\d+)\\s+(.*)$");
string sSym,sTmp,sSection,scopeName, symName;
boost::regex regScope("^\\s*(\\w+)\\s*::\\s*(.*)$");
unsigned int addr,size,baseOffset = 0;
map<unsigned int, TSymbolPCEntry> syms;
TUint32 dataStart = 0x400000;
while(aMap.getline(str,MAX_LINE)) {
if(regex_search(str, what, reg)) {
sSym.assign(what[1].first,what[1].second-what[1].first);
sTmp.assign(what[2].first,what[2].second-what[2].first);
addr = strtol(sTmp.c_str(), NULL, 16);
sTmp.assign(what[3].first,what[3].second-what[3].first);
size = strtol(sTmp.c_str(), NULL, 10);
sSection.assign(what[4].first,what[4].second-what[4].first);
if(sSection.find("(StubCode)") != string::npos)
size = 8;
if(addr > 0) {
if(baseOffset == 0)
baseOffset = addr;
unsigned int k = addr - baseOffset;
if( (syms.find(k) == syms.end()) || size != 0)
{
TSymbolPCEntry tmpEntry;
if(regex_search(sSym, what, regScope))
{
scopeName.assign(what[1].first, what[1].second-what[1].first);
symName.assign(what[2].first, what[2].second-what[2].first);
tmpEntry.iScopeName = scopeName;
tmpEntry.iName = symName;
tmpEntry.iSecName = sSection;
}
else
{
tmpEntry.iScopeName = "";
tmpEntry.iName = sSym;
tmpEntry.iSecName = sSection;
}
tmpEntry.iSymbolEntry.iAddress = k;
tmpEntry.iSymbolEntry.iLength = size;
syms[k]=tmpEntry;
}
}
// end of addr>0
}
// end of regex_search
}
map<unsigned int, TSymbolPCEntry>::iterator it;
for(it = syms.begin(); it != syms.end(); it++) {
unsigned int addr = it->first;
if(addr < dataStart)
{
iMapFileInfo.iDbgUnitPCEntry.iDbgUnitEntry.iCodeSymbolCount++;
}
else
{
if(bssSection > 0 && addr >= bssSection)
{
iMapFileInfo.iDbgUnitPCEntry.iDbgUnitEntry.iBssSymbolCount++;
}
else
{
iMapFileInfo.iDbgUnitPCEntry.iDbgUnitEntry.iDataSymbolCount++;
}
}
iMapFileInfo.iSymbolPCEntrySet.push_back(it->second);
}
}
void BsymRofsSymbolProcessUnit::ProcessGcceOrArm4File( const string& fileName, ifstream& aMap ){
aMap.seekg (0, ios_base::beg);
char str[MAX_LINE];
char outbuffer[MAX_LINE];
aMap.getline(str,MAX_LINE);
boost::cmatch what;
boost::regex reg("^\\.text\\s+");
while(aMap.getline(str,MAX_LINE)) {
if(regex_search(str, what, reg)) {
break;
}
}
reg.assign("^\\.text\\s+(\\w+)\\s+\\w+");
if(!regex_search(str, what, reg)) {
sprintf(outbuffer, "ERROR: Can't get .text section info for \"%s\"\n",fileName.c_str());
iStdoutLog.push_back(outbuffer);
}
else {
string sTmp, sLibFile;
sTmp.assign(what[1].first,what[1].second-what[1].first);
unsigned int imgText = strtol(sTmp.c_str(), NULL, 16);
reg.assign("^LONG 0x.*", boost::regex::icase);
boost::cmatch what1;
boost::regex reg1("^\\s(\\.text)?\\s+(0x\\w+)\\s+(0x\\w+)\\s+(.*)$", boost::regex::icase);
boost::regex reg2("^\\s+(\\w+)\\s\\s+([a-zA-Z_].+)", boost::regex::icase);
boost::regex reg3(".*lib\\(.*d\\d*s_?\\d{5}.o\\)$", boost::regex::icase);
map<unsigned int,string> syms;
unsigned int addr, len, stubhex;
while(aMap.getline(str,MAX_LINE)) {
if(strlen(str) == 0)
break;
else if(regex_search(str, what, reg1)) {
sLibFile.assign(what[4].first,what[4].second-what[4].first);
if(!regex_search(sLibFile, what1, reg)) {
sTmp.assign(what[2].first,what[2].second-what[2].first);
addr = strtol(sTmp.c_str(), NULL, 16);
sTmp.assign(what[3].first,what[3].second-what[3].first);
len = strtol(sTmp.c_str(), NULL, 16);
syms[addr+len] = "";
if(regex_search(sLibFile, what, reg3)) {
stubhex = addr;
}
}
}
else if(regex_search(str, what, reg2)) {
sTmp.assign(what[1].first,what[1].second-what[1].first);
addr = strtol(sTmp.c_str(), NULL, 16);
sTmp.assign(what[2].first,what[2].second-what[2].first);
syms[addr] = (addr == stubhex)? ("stub "+sTmp) : sTmp;
}
}
map<unsigned int,string>::iterator it = syms.begin();
map<unsigned int,string>::iterator itp = it++;
TSymbolPCEntry tmpSymbolEntry;
for(; it != syms.end(); itp = it++) {
if(itp->second != "") {
tmpSymbolEntry.iSymbolEntry.iAddress = itp->first-imgText;
tmpSymbolEntry.iSymbolEntry.iLength = it->first-itp->first;
tmpSymbolEntry.iName = it->second;
iMapFileInfo.iDbgUnitPCEntry.iDbgUnitEntry.iCodeSymbolCount++;
iMapFileInfo.iSymbolPCEntrySet.push_back(tmpSymbolEntry);
}
}
}
}