diff options
Diffstat (limited to 'tester/covoar/ObjdumpProcessor.cc')
-rw-r--r-- | tester/covoar/ObjdumpProcessor.cc | 284 |
1 files changed, 160 insertions, 124 deletions
diff --git a/tester/covoar/ObjdumpProcessor.cc b/tester/covoar/ObjdumpProcessor.cc index c910046..0aef978 100644 --- a/tester/covoar/ObjdumpProcessor.cc +++ b/tester/covoar/ObjdumpProcessor.cc @@ -13,6 +13,8 @@ #include <string.h> #include <algorithm> #include <string> +#include <fstream> +#include <iomanip> #include "ObjdumpProcessor.h" #include "CoverageMap.h" @@ -36,73 +38,81 @@ namespace Coverage { ) { // Find the symbol's coverage map. try { - CoverageMapBase& coverageMap = executableInfo->findCoverageMap(symbolName); + CoverageMapBase& coverageMap = + executableInfo->findCoverageMap( symbolName ); uint32_t firstInstructionAddress = UINT32_MAX; // Find the address of the first instruction. - for (auto& line : instructions) { - if (line.isInstruction) { + for ( auto& line : instructions ) { + if ( line.isInstruction ) { firstInstructionAddress = line.address; break; } } - if (firstInstructionAddress == UINT32_MAX) { + if ( firstInstructionAddress == UINT32_MAX ) { std::ostringstream what; what << "Could not find first instruction address for symbol " - << symbolName << " in " << executableInfo->getFileName(); + << symbolName << " in " << executableInfo->getFileName(); throw rld::error( what, "Coverage::finalizeSymbol" ); } - int rangeIndex = -1; + int rangeIndex = -1; uint32_t lowAddress = UINT32_MAX; do { rangeIndex++; - lowAddress = coverageMap.getLowAddressOfRange(rangeIndex); - } while (firstInstructionAddress != lowAddress); + lowAddress = coverageMap.getLowAddressOfRange( rangeIndex ); + } while ( firstInstructionAddress != lowAddress ); - uint32_t sizeWithoutNops = coverageMap.getSizeOfRange(rangeIndex); - uint32_t size = sizeWithoutNops; - uint32_t highAddress = lowAddress + size - 1; + uint32_t sizeWithoutNops = coverageMap.getSizeOfRange( rangeIndex ); + uint32_t size = sizeWithoutNops; + uint32_t highAddress = lowAddress + size - 1; uint32_t computedHighAddress = highAddress; // Find the high address as reported by the address of the last NOP // instruction. This ensures that NOPs get marked as executed later. - for (auto instruction = instructions.rbegin(); - instruction != instructions.rend(); - instruction++) { - if (instruction->isInstruction) { - if (instruction->isNop) { + for ( + auto instruction = instructions.rbegin(); + instruction != instructions.rend(); + instruction++ + ) { + if ( instruction->isInstruction ) { + if ( instruction->isNop ) { computedHighAddress = instruction->address + instruction->nopSize; } + break; } } - if (highAddress != computedHighAddress) { - std::cerr << "Function's high address differs between DWARF and objdump: " - << symbolName << " (0x" << std::hex << highAddress << " and 0x" - << computedHighAddress - 1 << ")" << std::dec << std::endl; + if ( highAddress != computedHighAddress ) { + std::cerr << "Function's high address differs between DWARF and " + << "objdump: " << symbolName << " (0x" << std::hex + << highAddress << " and 0x" + << computedHighAddress - 1 << ")" << std::dec << std::endl; + size = computedHighAddress - lowAddress; } // If there are NOT already saved instructions, save them. SymbolInformation* symbolInfo = symbolsToAnalyze.find( symbolName ); - if (symbolInfo->instructions.empty()) { - symbolInfo->sourceFile = executableInfo; - symbolInfo->baseAddress = lowAddress; + if ( symbolInfo->instructions.empty() ) { + symbolInfo->sourceFile = executableInfo; + symbolInfo->baseAddress = lowAddress; symbolInfo->instructions = instructions; } // Add the symbol to this executable's symbol table. SymbolTable* theSymbolTable = executableInfo->getSymbolTable(); theSymbolTable->addSymbol( - symbolName, lowAddress, highAddress - lowAddress + 1 + symbolName, + lowAddress, + highAddress - lowAddress + 1 ); // Mark the start of each instruction in the coverage map. - for (auto& instruction : instructions) { + for ( auto& instruction : instructions ) { coverageMap.setIsStartOfInstruction( instruction.address ); } @@ -114,16 +124,16 @@ namespace Coverage { sizeWithoutNops, verbose ); - } catch (const ExecutableInfo::CoverageMapNotFoundError& e) { + } catch ( const ExecutableInfo::CoverageMapNotFoundError& e ) { // Allow execution to continue even if a coverage map could not be // found. std::cerr << "Coverage map not found for symbol " << e.what() - << std::endl; + << std::endl; } } ObjdumpProcessor::ObjdumpProcessor( - DesiredSymbols& symbolsToAnalyze, + DesiredSymbols& symbolsToAnalyze, std::shared_ptr<Target::TargetBase>& targetInfo ): symbolsToAnalyze_m( symbolsToAnalyze ), targetInfo_m( targetInfo ) @@ -139,14 +149,14 @@ namespace Coverage { ) { #define METHOD "ERROR: ObjdumpProcessor::determineLoadAddress - " - FILE* loadAddressFile = NULL; - char* cStatus; - uint32_t offset; - char inputBuffer[MAX_LINE_LENGTH]; + std::ifstream loadAddressFile; + uint32_t offset; + char inputBuffer[ MAX_LINE_LENGTH ]; // This method should only be call for a dynamic library. - if (!theExecutable->hasDynamicLibrary()) + if ( !theExecutable->hasDynamicLibrary() ) { return 0; + } std::string dlinfoName = theExecutable->getFileName(); uint32_t address; @@ -155,8 +165,8 @@ namespace Coverage { dlinfoName += ".dlinfo"; // Read load address. - loadAddressFile = ::fopen( dlinfoName.c_str(), "r" ); - if (!loadAddressFile) { + loadAddressFile.open( dlinfoName ); + if ( !loadAddressFile.is_open() ) { std::ostringstream what; what << "Unable to open " << dlinfoName; throw rld::error( what, METHOD ); @@ -166,23 +176,26 @@ namespace Coverage { while ( 1 ) { // Get a line. - cStatus = ::fgets( inputBuffer, MAX_LINE_LENGTH, loadAddressFile ); - if (cStatus == NULL) { - ::fclose( loadAddressFile ); + loadAddressFile.getline( inputBuffer, MAX_LINE_LENGTH ); + if ( loadAddressFile.fail() && loadAddressFile.is_open() ) { + loadAddressFile.close(); std::ostringstream what; what << "library " << Library << " not found in " << dlinfoName; throw rld::error( what, METHOD ); } + sscanf( inputBuffer, "%s %x", inLibName, &offset ); std::string tmp = inLibName; if ( tmp.find( Library ) != tmp.npos ) { - // fprintf( stderr, "%s - 0x%08x\n", inLibName, offset ); + // std::cerr << inLibName << " - 0x" + // << std::setfill( '0' ) << std::setw( 8 ) << std::hex + // << offset << std::endl + // << std::dec << std::setfill( ' ' ); address = offset; break; } } - ::fclose( loadAddressFile ); return address; #undef METHOD @@ -195,23 +208,21 @@ namespace Coverage { stderr, "ERROR: ObjdumpProcessor::IsBranch - unknown architecture\n" ); - assert(0); + assert( 0 ); return false; } return targetInfo_m->isBranch( instruction ); } - bool ObjdumpProcessor::isBranchLine( - const char* const line - ) + bool ObjdumpProcessor::isBranchLine( const std::string& line ) { if ( !targetInfo_m ) { fprintf( stderr, "ERROR: ObjdumpProcessor::isBranchLine - unknown architecture\n" ); - assert(0); + assert( 0 ); return false; } @@ -219,11 +230,11 @@ namespace Coverage { } bool ObjdumpProcessor::isNop( - const char* const line, - int& size + const std::string& line, + int& size ) { - if ( !targetInfo_m ){ + if ( !targetInfo_m ) { fprintf( stderr, "ERROR: ObjdumpProcessor::isNop - unknown architecture\n" @@ -236,21 +247,32 @@ namespace Coverage { } void ObjdumpProcessor::getFile( - std::string fileName, + std::string fileName, rld::process::tempfile& objdumpFile, rld::process::tempfile& err - ) + ) { rld::process::status status; - rld::process::arg_container args = { targetInfo_m->getObjdump(), - "-Cda", "--section=.text", "--source", - fileName }; + rld::process::arg_container args = { + targetInfo_m->getObjdump(), + "-Cda", + "--section=.text", + "--source", + fileName + }; + try { - status = rld::process::execute( targetInfo_m->getObjdump(), - args, objdumpFile.name(), err.name() ); - if ( (status.type != rld::process::status::normal) - || (status.code != 0) ) { + status = rld::process::execute( + targetInfo_m->getObjdump(), + args, + objdumpFile.name(), + err.name() + ); + if ( + ( status.type != rld::process::status::normal ) || + ( status.code != 0 ) + ) { throw rld::error( "Objdump error", "generating objdump" ); } } catch( rld::error& err ) @@ -269,12 +291,12 @@ namespace Coverage { objdumpFile_t::iterator itr; itr = find ( objdumpList.begin(), objdumpList.end(), address ); - if (itr == objdumpList.end()) { + if ( itr == objdumpList.end() ) { return 0; } itr++; - if (itr == objdumpList.end()) { + if ( itr == objdumpList.end() ) { return 0; } @@ -283,21 +305,22 @@ namespace Coverage { } void ObjdumpProcessor::loadAddressTable ( - ExecutableInfo* const executableInformation, - rld::process::tempfile& objdumpFile, - rld::process::tempfile& err + ExecutableInfo* const executableInformation, + rld::process::tempfile& objdumpFile, + rld::process::tempfile& err ) { - int items; - uint32_t offset; - char terminator; - std::string line; + int items; + uint32_t offset; + char terminator; + std::string line; // Obtain the objdump file. - if ( !executableInformation->hasDynamicLibrary() ) + if ( !executableInformation->hasDynamicLibrary() ) { getFile( executableInformation->getFileName(), objdumpFile, err ); - else + } else { getFile( executableInformation->getLibraryName(), objdumpFile, err ); + } // Process all lines from the objdump file. while ( true ) { @@ -309,14 +332,10 @@ namespace Coverage { } // See if it is the dump of an instruction. - items = sscanf( - line.c_str(), - "%x%c", - &offset, &terminator - ); + items = sscanf( line.c_str(), "%x%c", &offset, &terminator ); // If it looks like an instruction ... - if ((items == 2) && (terminator == ':')) { + if ( ( items == 2 ) && ( terminator == ':' ) ) { objdumpList.push_back( executableInformation->getLoadAddress() + offset ); @@ -325,42 +344,43 @@ namespace Coverage { } void ObjdumpProcessor::load( - ExecutableInfo* const executableInformation, - rld::process::tempfile& objdumpFile, - rld::process::tempfile& err, - bool verbose + ExecutableInfo* const executableInformation, + rld::process::tempfile& objdumpFile, + rld::process::tempfile& err, + bool verbose ) { - std::string currentSymbol = ""; - uint32_t instructionOffset; - int items; - int found; - objdumpLine_t lineInfo; - uint32_t offset; - bool processSymbol = false; - char symbol[ MAX_LINE_LENGTH ]; - char terminator1; - char terminatorOne; - char terminator2; - objdumpLines_t theInstructions; - char instruction[ MAX_LINE_LENGTH ]; - char ID[ MAX_LINE_LENGTH ]; - std::string call = ""; - std::string jumpTableID = ""; - std::string line = ""; + std::string currentSymbol = ""; + uint32_t instructionOffset; + int items; + int found; + objdumpLine_t lineInfo; + uint32_t offset; + bool processSymbol = false; + char symbol[ MAX_LINE_LENGTH ]; + char terminator1; + char terminatorOne; + char terminator2; + objdumpLines_t theInstructions; + char instruction[ MAX_LINE_LENGTH ]; + char ID[ MAX_LINE_LENGTH ]; + std::string call = ""; + std::string jumpTableID = ""; + std::string line = ""; // Obtain the objdump file. - if ( !executableInformation->hasDynamicLibrary() ) + if ( !executableInformation->hasDynamicLibrary() ) { getFile( executableInformation->getFileName(), objdumpFile, err ); - else + } else { getFile( executableInformation->getLibraryName(), objdumpFile, err ); + } while ( true ) { // Get the line. objdumpFile.read_line( line ); if ( line.empty() ) { // If we are currently processing a symbol, finalize it. - if (processSymbol) { + if ( processSymbol ) { finalizeSymbol( executableInformation, currentSymbol, @@ -368,23 +388,23 @@ namespace Coverage { verbose, symbolsToAnalyze_m ); - fprintf( - stderr, - "WARNING: ObjdumpProcessor::load - analysis of symbol %s \n" - " may be incorrect. It was the last symbol in %s\n" - " and the length of its last instruction is assumed " - " to be one.\n", - currentSymbol.c_str(), - executableInformation->getFileName().c_str() - ); + + std::cerr << "WARNING: ObjdumpProcessor::load - analysis of symbol " + << currentSymbol << std::endl + << " may be incorrect. It was the last symbol in " + << executableInformation->getFileName() << std::endl + << " and the length of its last instruction" + << " is assumed to be one." + << std::endl; } + objdumpFile.close(); break; } // Remove any extra line break - if (line.back() == '\n') { - line.erase(line.end() - 1); + if ( line.back() == '\n' ) { + line.erase( line.end() - 1 ); } lineInfo.line = line; @@ -402,22 +422,28 @@ namespace Coverage { items = sscanf( line.c_str(), "%x <%[^>]>%c", - &offset, symbol, &terminator1 + &offset, + symbol, + &terminator1 ); // See if it is a jump table. found = sscanf( line.c_str(), "%x%c\t%*[^\t]%c%s %*x %*[^+]%s", - &instructionOffset, &terminatorOne, &terminator2, instruction, ID + &instructionOffset, + &terminatorOne, + &terminator2, + instruction, + ID ); call = instruction; jumpTableID = ID; // If all items found, we are at the beginning of a symbol's objdump. - if ((items == 3) && (terminator1 == ':')) { + if ( ( items == 3 ) && ( terminator1 == ':' ) ) { // If we are currently processing a symbol, finalize it. - if (processSymbol) { + if ( processSymbol ) { finalizeSymbol( executableInformation, currentSymbol, @@ -442,24 +468,27 @@ namespace Coverage { // When this happens, the compiler will generate a function with a // ".part.n" suffix. For our purposes, this generated function part is // equivalent to the original function and should be treated as such. - char *periodIndex = strstr(symbol, "."); - if (periodIndex != NULL) { + char *periodIndex = strstr( symbol, "." ); + if ( periodIndex != NULL ) { *periodIndex = 0; } // See if the new symbol is one that we care about. - if (symbolsToAnalyze_m.isDesired( symbol )) { + if ( symbolsToAnalyze_m.isDesired( symbol ) ) { currentSymbol = symbol; processSymbol = true; theInstructions.push_back( lineInfo ); } } // If it looks like a jump table, finalize the symbol. - else if ( (found == 5) && (terminatorOne == ':') && (terminator2 == '\t') - && (call.find( "call" ) != std::string::npos) - && (jumpTableID.find( "+0x" ) != std::string::npos) - && processSymbol ) - { + else if ( + ( found == 5 ) && + ( terminatorOne == ':' ) && + ( terminator2 == '\t' ) && + ( call.find( "call" ) != std::string::npos ) && + ( jumpTableID.find( "+0x" ) != std::string::npos ) && + processSymbol + ) { // If we are currently processing a symbol, finalize it. if ( processSymbol ) { finalizeSymbol( @@ -470,19 +499,26 @@ namespace Coverage { symbolsToAnalyze_m ); } + processSymbol = false; } - else if (processSymbol) { + else if ( processSymbol ) { // See if it is the dump of an instruction. items = sscanf( line.c_str(), "%x%c\t%*[^\t]%c", - &instructionOffset, &terminator1, &terminator2 + &instructionOffset, + &terminator1, + &terminator2 ); // If it looks like an instruction ... - if ((items == 3) && (terminator1 == ':') && (terminator2 == '\t')) { + if ( + ( items == 3 ) && + ( terminator1 == ':' ) && + ( terminator2 == '\t' ) + ) { // update the line's information, save it and ... lineInfo.address = executableInformation->getLoadAddress() + instructionOffset; |