diff -r c3fbb20e86f0 -r 46ca13b54f56 imgtools/imglib/symbolutil/symbolgenerator.cpp --- /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 +#include +#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; + } + +} +