<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Mar 2, 2021 at 10:23 AM Gedare Bloom <<a href="mailto:gedare@rtems.org">gedare@rtems.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Mon, Mar 1, 2021 at 1:02 PM Alex White <<a href="mailto:alexanderjwhite@gmail.com" target="_blank">alexanderjwhite@gmail.com</a>> wrote:<br>
><br>
> Some NOP instructions were not being marked as executed because they<br>
> are located at the end of uncovered ranges. This has been fixed.<br>
> ---<br>
> tester/covoar/CoverageMapBase.cc | 10 +++<br>
> tester/covoar/CoverageMapBase.h | 4 ++<br>
> tester/covoar/DesiredSymbols.cc | 38 ++++++++--<br>
> tester/covoar/DesiredSymbols.h | 10 ++-<br>
> tester/covoar/ObjdumpProcessor.cc | 112 +++++++++++++++++++++++-------<br>
> 5 files changed, 139 insertions(+), 35 deletions(-)<br>
><br>
> diff --git a/tester/covoar/CoverageMapBase.cc b/tester/covoar/CoverageMapBase.cc<br>
> index ad0080d..6ca5cf7 100644<br>
> --- a/tester/covoar/CoverageMapBase.cc<br>
> +++ b/tester/covoar/CoverageMapBase.cc<br>
> @@ -142,6 +142,11 @@ namespace Coverage {<br>
> return size;<br>
> }<br>
><br>
> + uint32_t CoverageMapBase::getSizeOfRange( size_t index ) const<br>
> + {<br>
> + return Ranges.at(index).size();<br>
> + }<br>
> +<br>
> bool CoverageMapBase::getBeginningOfInstruction(<br>
> uint32_t address,<br>
> uint32_t* beginning<br>
> @@ -178,6 +183,11 @@ namespace Coverage {<br>
> return Ranges.front().lowAddress;<br>
> }<br>
><br>
> + uint32_t CoverageMapBase::getLowAddressOfRange( size_t index ) const<br>
> + {<br>
> + return Ranges.at(index).lowAddress;<br>
> + }<br>
> +<br>
> bool CoverageMapBase::getRange( uint32_t address, AddressRange& range ) const<br>
> {<br>
> for ( auto r : Ranges ) {<br>
> diff --git a/tester/covoar/CoverageMapBase.h b/tester/covoar/CoverageMapBase.h<br>
> index 6ad76d3..a58c696 100644<br>
> --- a/tester/covoar/CoverageMapBase.h<br>
> +++ b/tester/covoar/CoverageMapBase.h<br>
> @@ -156,6 +156,8 @@ namespace Coverage {<br>
> */<br>
> int32_t getFirstLowAddress() const;<br>
><br>
> + uint32_t getLowAddressOfRange( size_t index ) const;<br>
> +<br>
> /*!<br>
> * This method returns true and sets the address range if<br>
> * the address falls with the bounds of an address range<br>
> @@ -177,6 +179,8 @@ namespace Coverage {<br>
> */<br>
> uint32_t getSize() const;<br>
><br>
> + uint32_t getSizeOfRange( size_t index ) const;<br>
> +<br>
> /*!<br>
> * This method returns the address of the beginning of the<br>
> * instruction that contains the specified address.<br>
> diff --git a/tester/covoar/DesiredSymbols.cc b/tester/covoar/DesiredSymbols.cc<br>
> index b9a5bb7..c97b25c 100644<br>
> --- a/tester/covoar/DesiredSymbols.cc<br>
> +++ b/tester/covoar/DesiredSymbols.cc<br>
> @@ -142,7 +142,7 @@ namespace Coverage {<br>
> CoverageMapBase* theCoverageMap = s.second.unifiedCoverageMap;<br>
> if (theCoverageMap)<br>
> {<br>
> - // Increment the total sizeInBytes byt the bytes in the symbol<br>
> + // Increment the total sizeInBytes by the bytes in the symbol<br>
> stats.sizeInBytes += s.second.stats.sizeInBytes;<br>
><br>
> // Now scan through the coverage map of this symbol.<br>
> @@ -202,6 +202,26 @@ namespace Coverage {<br>
> uint32_t count;<br>
><br>
> // Mark NOPs as executed<br>
> + a = s.second.stats.sizeInBytes - 1;<br>
> + count = 0;<br>
> + while (a > 0) {<br>
> + if (theCoverageMap->isStartOfInstruction( a )) {<br>
You can merge this if conditional into the while expression.<br>
<br>
while (a > 0 && !theCoverageMap->isStartOfInstruction( a )) {<br>
is equivalent<br></blockquote><div><br></div><div>Yes. But harder to debug when something goes wrong. We spent a</div><div>surprising amount of time in this loop. :(</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
> + break;<br>
> + }<br>
> +<br>
> + count++;<br>
> +<br>
> + if (theCoverageMap->isNop( a )) {<br>
> + for (la = a; la < (a + count); la++) {<br>
> + theCoverageMap->setWasExecuted( la );<br>
> + }<br>
> +<br>
> + count = 0;<br>
> + }<br>
> +<br>
> + a--;<br>
> + }<br>
> +<br>
> endAddress = s.second.stats.sizeInBytes - 1;<br>
> a = 0;<br>
> while (a < endAddress) {<br>
> @@ -223,12 +243,13 @@ namespace Coverage {<br>
> ha++;<br>
> if ( ha >= endAddress )<br>
> break;<br>
> - } while ( !theCoverageMap->isStartOfInstruction( ha ) );<br>
> + } while ( !theCoverageMap->isStartOfInstruction( ha ) ||<br>
> + theCoverageMap->isNop( ha ) );<br>
> a = ha;<br>
> }<br>
><br>
> // Now scan through the coverage map of this symbol.<br>
> - endAddress = s.second.stats.sizeInBytes - 1;<br>
> + endAddress = s.second.stats.sizeInBytesWithoutNops - 1;<br>
> a = 0;<br>
> while (a <= endAddress) {<br>
> // If an address was NOT executed, find consecutive unexecuted<br>
> @@ -316,7 +337,8 @@ namespace Coverage {<br>
> void DesiredSymbols::createCoverageMap(<br>
> const std::string& exefileName,<br>
> const std::string& symbolName,<br>
> - uint32_t size<br>
> + uint32_t size,<br>
> + uint32_t sizeWithoutNops<br>
> )<br>
> {<br>
> CoverageMapBase* aCoverageMap;<br>
> @@ -354,9 +376,10 @@ namespace Coverage {<br>
> << '/' << size << ')'<br>
> << std::endl;<br>
><br>
> - if ( itr->second.stats.sizeInBytes < size )<br>
> + if ( itr->second.stats.sizeInBytes < size ) {<br>
> itr->second.stats.sizeInBytes = size;<br>
> - else<br>
> + itr->second.stats.sizeInBytesWithoutNops = sizeWithoutNops;<br>
> + } else<br>
> size = itr->second.stats.sizeInBytes;<br>
> }<br>
> }<br>
> @@ -376,6 +399,7 @@ namespace Coverage {<br>
> );<br>
> itr->second.unifiedCoverageMap = aCoverageMap;<br>
> itr->second.stats.sizeInBytes = size;<br>
> + itr->second.stats.sizeInBytesWithoutNops = sizeWithoutNops;<br>
> }<br>
> }<br>
><br>
> @@ -479,7 +503,7 @@ namespace Coverage {<br>
> // are the same size.<br>
> // Changed from ERROR msg to INFO, because size mismatch is not<br>
> // treated as error anymore. 2015-07-20<br>
> - uint32_t dMapSize = sinfo.stats.sizeInBytes;<br>
> + uint32_t dMapSize = sinfo.stats.sizeInBytesWithoutNops;<br>
> uint32_t sBaseAddress = sourceCoverageMap->getFirstLowAddress();<br>
> uint32_t sMapSize = sourceCoverageMap->getSize();<br>
> if (dMapSize != 0 && dMapSize != sMapSize) {<br>
> diff --git a/tester/covoar/DesiredSymbols.h b/tester/covoar/DesiredSymbols.h<br>
> index 5c45af8..fb3efd6 100644<br>
> --- a/tester/covoar/DesiredSymbols.h<br>
> +++ b/tester/covoar/DesiredSymbols.h<br>
> @@ -57,7 +57,12 @@ namespace Coverage {<br>
> uint32_t sizeInBytes;<br>
><br>
> /*!<br>
> - * This member contains the size in Bytes.<br>
> + * This member contains the size in Bytes not accounting for NOPs.<br>
> + */<br>
> + uint32_t sizeInBytesWithoutNops;<br>
> +<br>
> + /*!<br>
> + * This member contains the size in instructions.<br>
> */<br>
> uint32_t sizeInInstructions;<br>
><br>
> @@ -227,7 +232,8 @@ namespace Coverage {<br>
> void createCoverageMap(<br>
> const std::string& exefileName,<br>
> const std::string& symbolName,<br>
> - uint32_t size<br>
> + uint32_t size,<br>
> + uint32_t sizeWithoutNops<br>
> );<br>
><br>
> /*!<br>
> diff --git a/tester/covoar/ObjdumpProcessor.cc b/tester/covoar/ObjdumpProcessor.cc<br>
> index 56ee219..bf39fe9 100644<br>
> --- a/tester/covoar/ObjdumpProcessor.cc<br>
> +++ b/tester/covoar/ObjdumpProcessor.cc<br>
> @@ -32,35 +32,95 @@ namespace Coverage {<br>
> ObjdumpProcessor::objdumpLines_t instructions<br>
> ) {<br>
> // Find the symbol's coverage map.<br>
> - CoverageMapBase& coverageMap = executableInfo->findCoverageMap( symbolName );<br>
> -<br>
> - uint32_t lowAddress = coverageMap.getFirstLowAddress();<br>
> - uint32_t size = coverageMap.getSize();<br>
> - uint32_t highAddress = lowAddress + size - 1;<br>
> -<br>
> - // If there are NOT already saved instructions, save them.<br>
> - SymbolInformation* symbolInfo = SymbolsToAnalyze->find( symbolName );<br>
> - if (symbolInfo->instructions.empty()) {<br>
> - symbolInfo->sourceFile = executableInfo;<br>
> - symbolInfo->baseAddress = lowAddress;<br>
> - symbolInfo->instructions = instructions;<br>
> - }<br>
> + try {<br>
> + CoverageMapBase& coverageMap = executableInfo->findCoverageMap(symbolName);<br>
><br>
> - // Add the symbol to this executable's symbol table.<br>
> - SymbolTable* theSymbolTable = executableInfo->getSymbolTable();<br>
> - theSymbolTable->addSymbol(<br>
> - symbolName, lowAddress, highAddress - lowAddress + 1<br>
> - );<br>
> + uint32_t firstInstructionAddress = -1;<br>
I don't really like this with -1 in an unsigned number. Beside which,<br>
will this stuff using uint32_t break in a 64-bit address space?<br></blockquote><div><br></div><div>There could be problems on a 64-bit target if the address space for the</div><div>program doesn't fall within the first 4GB. On the aarch64, even the </div><div>Couverture traces still output 32-bit addresses. We were surprised.</div><div><br></div><div>Change -1 to the max constant for uint32_t. which should be UINT32_MAX</div><div><br></div><div>Add changing uint32_t to a private target address type to the list</div><div>of things to do and then we can look at making it 64-bit easier.</div><div>I have a bad feeling this will be a sweep until itself which shouldn't</div><div>be mixed with this set.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
><br>
> - // Mark the start of each instruction in the coverage map.<br>
> - for (auto& instruction : instructions) {<br>
> - coverageMap.setIsStartOfInstruction( instruction.address );<br>
> - }<br>
> + // Find the address of the first instruction.<br>
> + for (auto& line : instructions) {<br>
> + if (!line.isInstruction) {<br>
> + continue;<br>
> + }<br>
> +<br>
> + firstInstructionAddress = line.address;<br>
> + break;<br>
> + }<br>
There has to be a more elegant way to write this loop.<br>
<br>
> +<br>
> + if (firstInstructionAddress == (uint32_t)-1) {<br>
> + std::ostringstream what;<br>
> + what << "Could not find first instruction address for symbol "<br>
> + << symbolName << " in " << executableInfo->getFileName();<br>
> + throw rld::error( what, "Coverage::finalizeSymbol" );<br>
> + }<br>
> +<br>
> + bool inRange = false;<br>
> + int rangeIndex = 0;<br>
> + uint32_t lowAddress = -1;<br>
> + while (!inRange) {<br>
inRange is always false.<br>
<br>
> + lowAddress = coverageMap.getLowAddressOfRange(rangeIndex);<br>
> +<br>
> + if (firstInstructionAddress == lowAddress) {<br>
> + break;<br>
> + }<br>
> +<br>
> + rangeIndex++;<br>
> + }<br>
><br>
> - // Create a unified coverage map for the symbol.<br>
> - SymbolsToAnalyze->createCoverageMap(<br>
> - executableInfo->getFileName().c_str(), symbolName, size<br>
> - );<br>
> + uint32_t sizeWithoutNops = coverageMap.getSizeOfRange(rangeIndex);<br>
> + uint32_t size = sizeWithoutNops;<br>
> + uint32_t highAddress = lowAddress + size - 1;<br>
> + uint32_t computedHighAddress = highAddress;<br>
> +<br>
> + // Find the high address as reported by the address of the last NOP<br>
> + // instruction. This ensures that NOPs get marked as executed later.<br>
> + for (auto instruction = instructions.rbegin();<br>
> + instruction != instructions.rend();<br>
> + instruction++) {<br>
> + if (instruction->isInstruction) {<br>
> + if (instruction->isNop) {<br>
> + computedHighAddress = instruction->address + instruction->nopSize;<br>
> + }<br>
> + break;<br>
> + }<br>
> + }<br>
<br>
The complexity of this method suggests it might be a good idea to refactor it.<br></blockquote><div><br></div><div>Alex .. Add this to the list of todo's. Not worth holding this up for. </div><div><br></div><div>We need a baseline working version to make improvements to. It had</div><div>bitrotted quite considerably. </div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
> +<br>
> + if (highAddress != computedHighAddress) {<br>
> + fprintf(<br>
why not using C++ way of printing?<br></blockquote><div><br></div><div>Originally covoar used C IO exclusively. Apparently all hasn't been swept out.</div><div><br></div><div>Go ahead and change this.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
> + stderr,<br>
> + "Function's high address differs between DWARF and objdump: "<br>
> + "%s (0x%x and 0x%x)\n",<br>
> + symbolName.c_str(), highAddress, computedHighAddress - 1<br>
> + );<br>
> + size = computedHighAddress - lowAddress;<br>
> + }<br>
> +<br>
> + // If there are NOT already saved instructions, save them.<br>
> + SymbolInformation* symbolInfo = SymbolsToAnalyze->find( symbolName );<br>
> + if (symbolInfo->instructions.empty()) {<br>
> + symbolInfo->sourceFile = executableInfo;<br>
> + symbolInfo->baseAddress = lowAddress;<br>
> + symbolInfo->instructions = instructions;<br>
> + }<br>
> +<br>
> + // Add the symbol to this executable's symbol table.<br>
> + SymbolTable* theSymbolTable = executableInfo->getSymbolTable();<br>
> + theSymbolTable->addSymbol(<br>
> + symbolName, lowAddress, highAddress - lowAddress + 1<br>
> + );<br>
> +<br>
> + // Mark the start of each instruction in the coverage map.<br>
> + for (auto& instruction : instructions) {<br>
> + coverageMap.setIsStartOfInstruction( instruction.address );<br>
> + }<br>
> +<br>
> + // Create a unified coverage map for the symbol.<br>
> + SymbolsToAnalyze->createCoverageMap(<br>
> + executableInfo->getFileName().c_str(), symbolName, size, sizeWithoutNops<br>
> + );<br>
> + } catch (rld::error& e) {<br>
> + throw rld::error( e.what, "Coverage::finalizeSymbol" );<br>
> + }<br>
> }<br>
><br>
> ObjdumpProcessor::ObjdumpProcessor()<br>
> --<br>
> 2.27.0<br>
><br>
> _______________________________________________<br>
> devel mailing list<br>
> <a href="mailto:devel@rtems.org" target="_blank">devel@rtems.org</a><br>
> <a href="http://lists.rtems.org/mailman/listinfo/devel" rel="noreferrer" target="_blank">http://lists.rtems.org/mailman/listinfo/devel</a><br>
_______________________________________________<br>
devel mailing list<br>
<a href="mailto:devel@rtems.org" target="_blank">devel@rtems.org</a><br>
<a href="http://lists.rtems.org/mailman/listinfo/devel" rel="noreferrer" target="_blank">http://lists.rtems.org/mailman/listinfo/devel</a><br>
</blockquote></div></div>