summaryrefslogtreecommitdiffstats
path: root/tester/covoar/ObjdumpProcessor.cc
diff options
context:
space:
mode:
authorAlex White <alex.white@oarcorp.com>2021-02-24 16:53:43 -0600
committerJoel Sherrill <joel@rtems.org>2021-03-30 13:15:58 -0500
commite5c985eba0822b9c1356c85617ea687cfdac379b (patch)
treecc12abe5b8fb9acf3027b10e19d89aaa032be124 /tester/covoar/ObjdumpProcessor.cc
parenttester: Add coverage variants for a few BSPs (diff)
downloadrtems-tools-e5c985eba0822b9c1356c85617ea687cfdac379b.tar.bz2
covoar: Fix NOP execution marking
Some NOP instructions were not being marked as executed because they are located at the end of uncovered ranges. This has been fixed.
Diffstat (limited to 'tester/covoar/ObjdumpProcessor.cc')
-rw-r--r--tester/covoar/ObjdumpProcessor.cc105
1 files changed, 79 insertions, 26 deletions
diff --git a/tester/covoar/ObjdumpProcessor.cc b/tester/covoar/ObjdumpProcessor.cc
index 56ee219..05a50f1 100644
--- a/tester/covoar/ObjdumpProcessor.cc
+++ b/tester/covoar/ObjdumpProcessor.cc
@@ -32,35 +32,88 @@ namespace Coverage {
ObjdumpProcessor::objdumpLines_t instructions
) {
// Find the symbol's coverage map.
- CoverageMapBase& coverageMap = executableInfo->findCoverageMap( symbolName );
-
- uint32_t lowAddress = coverageMap.getFirstLowAddress();
- uint32_t size = coverageMap.getSize();
- uint32_t highAddress = lowAddress + size - 1;
-
- // If there are NOT already saved instructions, save them.
- SymbolInformation* symbolInfo = SymbolsToAnalyze->find( symbolName );
- if (symbolInfo->instructions.empty()) {
- symbolInfo->sourceFile = executableInfo;
- symbolInfo->baseAddress = lowAddress;
- symbolInfo->instructions = instructions;
- }
+ try {
+ CoverageMapBase& coverageMap = executableInfo->findCoverageMap(symbolName);
- // Add the symbol to this executable's symbol table.
- SymbolTable* theSymbolTable = executableInfo->getSymbolTable();
- theSymbolTable->addSymbol(
- symbolName, lowAddress, highAddress - lowAddress + 1
- );
+ uint32_t firstInstructionAddress = UINT32_MAX;
- // Mark the start of each instruction in the coverage map.
- for (auto& instruction : instructions) {
- coverageMap.setIsStartOfInstruction( instruction.address );
- }
+ // Find the address of the first instruction.
+ for (auto& line : instructions) {
+ if (line.isInstruction) {
+ firstInstructionAddress = line.address;
+ break;
+ }
+ }
+
+ if (firstInstructionAddress == UINT32_MAX) {
+ std::ostringstream what;
+ what << "Could not find first instruction address for symbol "
+ << symbolName << " in " << executableInfo->getFileName();
+ throw rld::error( what, "Coverage::finalizeSymbol" );
+ }
+
+ int rangeIndex;
+ uint32_t lowAddress = UINT32_MAX;
+ for (rangeIndex = 0;
+ firstInstructionAddress != lowAddress;
+ rangeIndex++) {
+ lowAddress = coverageMap.getLowAddressOfRange(rangeIndex);
+ }
+
+ 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) {
+ 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;
+ size = computedHighAddress - lowAddress;
+ }
- // Create a unified coverage map for the symbol.
- SymbolsToAnalyze->createCoverageMap(
- executableInfo->getFileName().c_str(), symbolName, size
- );
+ // If there are NOT already saved instructions, save them.
+ SymbolInformation* symbolInfo = SymbolsToAnalyze->find( symbolName );
+ 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
+ );
+
+ // Mark the start of each instruction in the coverage map.
+ for (auto& instruction : instructions) {
+ coverageMap.setIsStartOfInstruction( instruction.address );
+ }
+
+ // Create a unified coverage map for the symbol.
+ SymbolsToAnalyze->createCoverageMap(
+ executableInfo->getFileName().c_str(), symbolName, size, sizeWithoutNops
+ );
+ } 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;
+ }
}
ObjdumpProcessor::ObjdumpProcessor()