imgtools/imglib/symbolutil/symbolgenerator.cpp
changeset 695 46ca13b54f56
child 714 e5a58c351011
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imgtools/imglib/symbolutil/symbolgenerator.cpp	Wed Nov 17 16:47:32 2010 +0800
@@ -0,0 +1,384 @@
+/*
+* 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 <vector>
+#include <boost/regex.hpp>
+#define MAX_LINE 65535
+#include "symbolgenerator.h"
+#include "e32image.h"
+#include "h_utl.h"
+
+#if defined(__LINUX__)
+#define PATH_SEPARATOR '/'
+#else
+#define PATH_SEPARATOR '\\'
+#endif
+extern TInt gThreadNum;
+extern TBool gGenBsymbols;
+
+boost::mutex SymbolGenerator::iMutexSingleton;
+SymbolGenerator* SymbolGenerator::iInst = NULL;
+SymbolGenerator* SymbolGenerator::GetInstance(){
+    iMutexSingleton.lock();
+    if(iInst == NULL) {
+        iInst = new SymbolGenerator();
+    }
+    iMutexSingleton.unlock();
+    return iInst;
+}
+void SymbolGenerator::Release() {
+    if(iInst != NULL) {
+        iInst->join();
+    }
+    iMutexSingleton.lock();
+    if(iInst != NULL) {
+        delete iInst;
+        iInst = NULL;
+    }
+    iMutexSingleton.unlock();
+}
+void SymbolGenerator::SetSymbolFileName( const string& fileName ){
+    if(iSymFile.is_open())
+        iSymFile.close();
+    if(gGenBsymbols)
+    {
+    	string s = fileName.substr(0,fileName.rfind('.'))+".bsym";
+    	if(iImageType == ERofsImage)
+    	{
+    		printf("* Writing %s - ROFS BSymbol file\n", s.c_str());
+    	}
+    	else
+    	{
+    		printf("* Writing %s - ROM BSymbol file\n", s.c_str());
+    	}
+    	iSymFile.open(s.c_str(), ios_base::binary);
+    }
+    else
+    {
+    	string s = fileName.substr(0,fileName.rfind('.'))+".symbol";
+    	if(iImageType == ERofsImage)
+    	{
+    		printf("* Writing %s - ROFS Symbol file\n", s.c_str());
+    	}
+    	else
+    	{
+    		printf("* Writing %s - ROM Symbol file\n", s.c_str());
+    	}
+    iSymFile.open(s.c_str());
+    }
+	   
+}
+void SymbolGenerator::AddFile( const string& fileName, bool isExecutable ){
+    iMutex.lock();
+    iQueueFiles.push(TPlacedEntry(fileName, "" , isExecutable));
+    iMutex.unlock();
+    iCond.notify_all();
+}
+
+void SymbolGenerator::AddEntry(const TPlacedEntry& aEntry)
+{
+    iMutex.lock();
+    iQueueFiles.push(aEntry);
+    iMutex.unlock();
+    iCond.notify_all();
+}
+
+void SymbolGenerator::SetFinished() 
+{ 
+
+	iFinished = true; 
+	iCond.notify_all();
+}
+TPlacedEntry SymbolGenerator::GetNextPlacedEntry()
+{
+	TPlacedEntry pe("", "", false);
+	if(1)
+	{
+		boost::mutex::scoped_lock lock(iMutex);
+		while(!iFinished && iQueueFiles.empty())
+			iCond.wait(lock);
+		if(!iQueueFiles.empty())
+		{
+			pe = iQueueFiles.front();
+			iQueueFiles.pop();
+        	}
+    	}
+	return pe;
+}
+void SymbolGenerator::thrd_func(){
+    	boost::thread_group threads;
+	SymbolWorker worker;
+    	for(int i=0; i < gThreadNum; i++)
+    	{
+    		threads.create_thread(worker);
+    	}
+    	threads.join_all();
+	SymbolGenerator::GetInstance()->FlushSymbolFileContent();
+        }
+SymbolGenerator::SymbolGenerator() : boost::thread(thrd_func),iFinished(false) {
+	if(gGenBsymbols)
+	{
+		iSymbolType = ESymBsym;
+	}
+	else
+	{
+		iSymbolType = ESymCommon;
+	}
+    }
+SymbolGenerator::~SymbolGenerator(){
+    if(joinable())
+        join();
+    iSymFile.flush();
+    iSymFile.close();
+}
+void SymbolGenerator::FlushSymbolFileContent()
+{
+    if(iSymbolType == ESymCommon)
+    {
+	return;
+    }
+    TBsymHeader tmpBsymHeader;
+    memset(&tmpBsymHeader, 0, sizeof(tmpBsymHeader));
+    tmpBsymHeader.iMagic[0] = 'B';
+    tmpBsymHeader.iMagic[1] = 'S';
+    tmpBsymHeader.iMagic[2] = 'Y';
+    tmpBsymHeader.iMagic[3] = 'M';
+    tmpBsymHeader.iMajorVer[0] = BsymMajorVer >> 8;
+    tmpBsymHeader.iMajorVer[1] = BsymMajorVer & 0xff;
+    tmpBsymHeader.iMinorVer[0] = BsymMinorVer >> 8;
+    tmpBsymHeader.iMinorVer[1] = BsymMinorVer & 0xff;
+    if(ByteOrderUtil::IsLittleEndian())
+    {
+	    tmpBsymHeader.iEndiannessFlag = 0;
+    }
+    else
+    {
+	    tmpBsymHeader.iEndiannessFlag = 1;
+    }
+    tmpBsymHeader.iCompressionFlag = 1;
+    //count the space for TDbgUnitEntries and TSymbolEntries
+    int fileCount = iMapFileInfoSet.size();
+    TUint32 sizeNeeded = fileCount * sizeof(TDbgUnitEntry);
+    for(int i = 0; i < fileCount; i++)
+    {
+    	sizeNeeded += iMapFileInfoSet[i].iSymbolPCEntrySet.size() * sizeof(TSymbolEntry);
+    }
+    //write string to the temporary memory area
+    MemoryWriter mWriter;
+    mWriter.SetOffset(sizeNeeded);
+    mWriter.SetStringTableStart(sizeNeeded);
+    mWriter.AddEmptyString();
+
+    //first to prepare the file info entries TDbgUnitEntry
+    TUint32 startSymbolIndex = 0;
+    for(int i = 0; i < fileCount; i++)
+    {
+    	iMapFileInfoSet[i].iDbgUnitPCEntry.iDbgUnitEntry.iStartSymbolIndex = startSymbolIndex;
+    	iMapFileInfoSet[i].iDbgUnitPCEntry.iDbgUnitEntry.iPCNameOffset = mWriter.AddString(iMapFileInfoSet[i].iDbgUnitPCEntry.iPCName);
+    	iMapFileInfoSet[i].iDbgUnitPCEntry.iDbgUnitEntry.iDevNameOffset = mWriter.AddString(iMapFileInfoSet[i].iDbgUnitPCEntry.iDevName);
+    	startSymbolIndex += iMapFileInfoSet[i].iSymbolPCEntrySet.size();
+    }
+    //second to layout the symbols unit for the mapfile
+    for(int i = 0; i < fileCount; i++)
+    {
+        int symbolcount = iMapFileInfoSet[i].iSymbolPCEntrySet.size();
+        for(int j =0; j< symbolcount; j++)
+        {
+        	iMapFileInfoSet[i].iSymbolPCEntrySet[j].iSymbolEntry.iScopeNameOffset = mWriter.AddScopeName(iMapFileInfoSet[i].iSymbolPCEntrySet[j].iScopeName);
+        	iMapFileInfoSet[i].iSymbolPCEntrySet[j].iSymbolEntry.iNameOffset = mWriter.AddString(iMapFileInfoSet[i].iSymbolPCEntrySet[j].iName);
+        	iMapFileInfoSet[i].iSymbolPCEntrySet[j].iSymbolEntry.iSecNameOffset = mWriter.AddString(iMapFileInfoSet[i].iSymbolPCEntrySet[j].iSecName);
+        }
+    }
+
+    //write out the BSym file content
+    char* pstart = mWriter.GetDataPointer();
+    //write out the map file info
+    int unitlen = sizeof(TDbgUnitEntry);
+    for(int i = 0; i < fileCount; i++)
+    {
+    	memcpy(pstart, &iMapFileInfoSet[i].iDbgUnitPCEntry.iDbgUnitEntry, unitlen);
+    	pstart += unitlen;
+    }
+    //wirte out the symbol unit info
+    unitlen = sizeof(TSymbolEntry);
+    for(int i = 0; i < fileCount; i++)
+    {
+    	int symbolcount = iMapFileInfoSet[i].iSymbolPCEntrySet.size();
+    	for(int j =0; j < symbolcount; j++)
+    	{
+    		memcpy(pstart, &iMapFileInfoSet[i].iSymbolPCEntrySet[j].iSymbolEntry, unitlen);
+    		pstart += unitlen;
+    	}
+    }
+    //write out the memory out to the symbol file
+
+    int totalPages = (mWriter.GetOffset() + ( BSYM_PAGE_SIZE -1)) / 4096;
+    TUint32 compressInfoLength = sizeof(TCompressedHeaderInfo) + sizeof(TPageInfo)*(totalPages -1);
+    char* tmpBuffer = new char[compressInfoLength];
+    TCompressedHeaderInfo * pCompressedHeaderInfo = (TCompressedHeaderInfo *) tmpBuffer;
+    pCompressedHeaderInfo->iPageSize = BSYM_PAGE_SIZE;
+    pCompressedHeaderInfo->iTotalPageNumber = totalPages;
+    TPageInfo* tmpPage = &pCompressedHeaderInfo->iPages[0];
+    for(int i = 0; i < totalPages; i++)
+    {
+	    tmpPage->iPageStartOffset = i * BSYM_PAGE_SIZE;
+	    if(tmpPage->iPageStartOffset + BSYM_PAGE_SIZE < mWriter.GetOffset())
+	    {
+	    	tmpPage->iPageDataSize = BSYM_PAGE_SIZE;
+	    }
+	    else
+	    {
+		tmpPage->iPageDataSize = mWriter.GetOffset() - tmpPage->iPageStartOffset;
+	    }
+	    tmpPage++;
+    }
+
+    //prepare the TBsymHeader, TDbgUnitEntry and TSymbolEntry to the memory
+    tmpBsymHeader.iDbgUnitOffset = sizeof(TBsymHeader) + compressInfoLength;
+    tmpBsymHeader.iDbgUnitCount = fileCount;
+    tmpBsymHeader.iSymbolOffset = fileCount*sizeof(TDbgUnitEntry);
+    tmpBsymHeader.iSymbolCount = startSymbolIndex;
+    tmpBsymHeader.iStringTableOffset = mWriter.GetStringTableStart();
+    tmpBsymHeader.iStringTableBytes = mWriter.GetOffset() - tmpBsymHeader.iStringTableOffset;
+    tmpBsymHeader.iUncompressSize = mWriter.GetOffset();
+    //start the compress threads
+    Print(EAlways, "Start compress for Bsymbol file\n");
+    PageCompressWorker compressWorker(pCompressedHeaderInfo, mWriter.GetDataPointer());
+    boost::thread_group threads;
+    for(int i=0; i < gThreadNum; i++)
+    {
+	    threads.create_thread(compressWorker);
+    }
+    threads.join_all();
+    Print(EAlways, "Complete compress for Bsymbol file\n");
+    //pack all the pages together
+    tmpPage = &pCompressedHeaderInfo->iPages[0];
+    TPageInfo* prePage = NULL;
+    char* pchar = mWriter.GetDataPointer();
+    for(int i=0; i < totalPages -1; i++)
+    {
+	    prePage = tmpPage;
+	    tmpPage++;
+	    memcpy(pchar + prePage->iPageStartOffset + prePage->iPageDataSize, pchar + tmpPage->iPageStartOffset, tmpPage->iPageDataSize);
+	    tmpPage->iPageStartOffset = prePage->iPageStartOffset + prePage->iPageDataSize;
+
+    }
+    tmpBsymHeader.iCompressedSize = tmpPage->iPageStartOffset + tmpPage->iPageDataSize;
+    mWriter.SetOffset(tmpBsymHeader.iCompressedSize);
+    tmpBsymHeader.iCompressInfoOffset = sizeof(TBsymHeader);
+
+    iSymFile.write((char*)&tmpBsymHeader, sizeof(TBsymHeader));
+    iSymFile.write((char*)pCompressedHeaderInfo, compressInfoLength);
+    iSymFile.write(mWriter.GetDataPointer(), mWriter.GetOffset());
+    delete[] tmpBuffer;
+    for(int i = 0; i < fileCount; i++)
+    {
+    	iMapFileInfoSet[i].iSymbolPCEntrySet.clear();
+    }
+    iMapFileInfoSet.clear();
+}
+
+SymbolWorker::SymbolWorker()
+{
+}
+SymbolWorker::~SymbolWorker()
+{
+    }
+void SymbolWorker::operator()()
+{
+	SymbolProcessUnit* aSymbolProcessUnit;
+	SymbolGenerator* symbolgenerator = SymbolGenerator::GetInstance();
+	if(symbolgenerator->GetImageType() == ERomImage)
+	{
+		aSymbolProcessUnit = new CommenRomSymbolProcessUnit();
+	}
+	else
+	{
+		if(gGenBsymbols)
+		{
+			aSymbolProcessUnit = new BsymRofsSymbolProcessUnit(symbolgenerator);
+		}
+		else
+		{
+			aSymbolProcessUnit = new CommenRofsSymbolProcessUnit();
+		}
+	}
+
+	while(1)
+	{
+		if(symbolgenerator->HasFinished() && symbolgenerator->IsEmpty())
+		{
+			break;
+                }
+		TPlacedEntry pe = symbolgenerator->GetNextPlacedEntry();
+		if(pe.iFileName.empty())
+			continue;
+
+		aSymbolProcessUnit->ProcessEntry(pe);
+
+		symbolgenerator->LockOutput();
+		aSymbolProcessUnit->FlushStdOut(cout);
+		aSymbolProcessUnit->FlushSymbolContent(symbolgenerator->GetOutputFileStream());
+		symbolgenerator->UnlockOutput();
+	}
+	delete aSymbolProcessUnit;
+}
+TCompressedHeaderInfo* PageCompressWorker::pHeaderInfo = NULL;
+int PageCompressWorker::currentPage = 0;
+boost::mutex PageCompressWorker::m_mutex;
+int PageCompressWorker::m_error = 0;
+char* PageCompressWorker::iChar = NULL;
+
+PageCompressWorker::PageCompressWorker(TCompressedHeaderInfo* aHeaderInfo, char* aChar) 
+{
+	pHeaderInfo = aHeaderInfo;
+	iChar = aChar;
+}
+
+PageCompressWorker::~PageCompressWorker() {}
+void PageCompressWorker::operator()()
+{
+	int tobecompress = 0;
+	CBytePair bpe;
+	while(1)
+	{
+		m_mutex.lock();
+		tobecompress =currentPage;
+		currentPage++;
+		m_mutex.unlock();
+		if(tobecompress >= (int) pHeaderInfo->iTotalPageNumber)
+			break;
+		TPageInfo* current = &pHeaderInfo->iPages[0] + tobecompress;
+		TUint8* in = (TUint8*)(iChar + current->iPageStartOffset);
+		TUint8* out = in;
+		TInt outSize = BytePairCompress(out, in, current->iPageDataSize, &bpe);
+		if(outSize == KErrTooBig)
+		{
+			outSize = BSYM_PAGE_SIZE;
+		}
+		if(outSize < 0)
+		{
+			m_mutex.lock();
+			m_error = -1;
+			m_mutex.unlock();
+			break;
+		}
+		current->iPageDataSize = outSize;
+	}
+	
+}
+