summaryrefslogtreecommitdiffstats
path: root/tester/covoar/ObjdumpProcessor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tester/covoar/ObjdumpProcessor.cc')
-rw-r--r--tester/covoar/ObjdumpProcessor.cc284
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;