@@ -16,6 +16,7 @@ limitations under the License.
1616
1717#include " debuggercontroller.h"
1818#include < thread>
19+ #include < fstream>
1920#include " lowlevelilinstruction.h"
2021#include " mediumlevelilinstruction.h"
2122#include " highlevelilinstruction.h"
@@ -2918,31 +2919,158 @@ bool DebuggerController::RunCodeCoverageAnalysis()
29182919
29192920 LogInfo (" Starting TTD code coverage analysis..." );
29202921
2921- // Iterate through all functions and their instruction addresses
2922+ // Get all instruction addresses from all functions
2923+ std::set<uint64_t > allInstructionAddresses;
29222924 for (auto func : bv->GetAnalysisFunctionList ())
29232925 {
2924- uint64_t funcStart = func->GetStart ();
2925- uint64_t funcEnd = func->GetHighestAddress ();
2926-
2927- // Query TTD for execute access at each instruction address
2928- auto events = GetTTDMemoryAccessForAddress (funcStart, funcEnd, TTDMemoryExecute);
2929-
2930- for (const auto & event : events)
2926+ for (auto block : func->GetBasicBlocks ())
2927+ {
2928+ uint64_t addr = block->GetStart ();
2929+ uint64_t end = block->GetEnd ();
2930+ while (addr < end)
2931+ {
2932+ allInstructionAddresses.insert (addr);
2933+ size_t instrLen = func->GetArchitecture ()->GetInstructionLength (bv, addr);
2934+ if (instrLen == 0 )
2935+ instrLen = 1 ; // Fallback to avoid infinite loop
2936+ addr += instrLen;
2937+ }
2938+ }
2939+ }
2940+
2941+ LogInfo (" Analyzing {} instruction addresses for execution traces..." , allInstructionAddresses.size ());
2942+
2943+ // Query TTD for execute access covering the entire executable range
2944+ uint64_t minAddr = *allInstructionAddresses.begin ();
2945+ uint64_t maxAddr = *allInstructionAddresses.rbegin ();
2946+
2947+ auto events = GetTTDMemoryAccessForAddress (minAddr, maxAddr - minAddr + 16 , TTDMemoryExecute);
2948+
2949+ for (const auto & event : events)
2950+ {
2951+ if (event.accessType == TTDMemoryExecute)
29312952 {
2932- if (event.accessType == TTDMemoryExecute)
2953+ // Only count instruction addresses that we actually care about
2954+ if (allInstructionAddresses.find (event.instructionAddress ) != allInstructionAddresses.end ())
29332955 {
29342956 m_executedInstructions.insert (event.instructionAddress );
29352957 }
29362958 }
29372959 }
29382960
29392961 m_codeCoverageAnalysisRun = true ;
2940- LogInfo (" TTD code coverage analysis completed. Found {} executed instructions." , m_executedInstructions.size ());
2962+ LogInfo (" TTD code coverage analysis completed. Found {} executed instructions out of {} total." ,
2963+ m_executedInstructions.size (), allInstructionAddresses.size ());
29412964
29422965 return true ;
29432966}
29442967
29452968
2969+ size_t DebuggerController::GetExecutedInstructionCount () const
2970+ {
2971+ return m_executedInstructions.size ();
2972+ }
2973+
2974+
2975+ bool DebuggerController::SaveCodeCoverageToFile (const std::string& filePath) const
2976+ {
2977+ if (!m_codeCoverageAnalysisRun)
2978+ {
2979+ LogError (" No code coverage analysis has been run" );
2980+ return false ;
2981+ }
2982+
2983+ try
2984+ {
2985+ std::ofstream file (filePath, std::ios::binary);
2986+ if (!file.is_open ())
2987+ {
2988+ LogError (" Failed to open file for writing: {}" , filePath);
2989+ return false ;
2990+ }
2991+
2992+ // Write header
2993+ uint32_t magic = 0x54544443 ; // "TTDC" - TTD Coverage
2994+ uint32_t version = 1 ;
2995+ size_t count = m_executedInstructions.size ();
2996+
2997+ file.write (reinterpret_cast <const char *>(&magic), sizeof (magic));
2998+ file.write (reinterpret_cast <const char *>(&version), sizeof (version));
2999+ file.write (reinterpret_cast <const char *>(&count), sizeof (count));
3000+
3001+ // Write addresses
3002+ for (uint64_t addr : m_executedInstructions)
3003+ {
3004+ file.write (reinterpret_cast <const char *>(&addr), sizeof (addr));
3005+ }
3006+
3007+ file.close ();
3008+ LogInfo (" Saved {} executed instruction addresses to {}" , count, filePath);
3009+ return true ;
3010+ }
3011+ catch (const std::exception& e)
3012+ {
3013+ LogError (" Error saving code coverage: {}" , e.what ());
3014+ return false ;
3015+ }
3016+ }
3017+
3018+
3019+ bool DebuggerController::LoadCodeCoverageFromFile (const std::string& filePath)
3020+ {
3021+ try
3022+ {
3023+ std::ifstream file (filePath, std::ios::binary);
3024+ if (!file.is_open ())
3025+ {
3026+ LogError (" Failed to open file for reading: {}" , filePath);
3027+ return false ;
3028+ }
3029+
3030+ // Read header
3031+ uint32_t magic, version;
3032+ size_t count;
3033+
3034+ file.read (reinterpret_cast <char *>(&magic), sizeof (magic));
3035+ if (magic != 0x54544443 )
3036+ {
3037+ LogError (" Invalid file format (magic number mismatch)" );
3038+ return false ;
3039+ }
3040+
3041+ file.read (reinterpret_cast <char *>(&version), sizeof (version));
3042+ if (version != 1 )
3043+ {
3044+ LogError (" Unsupported file version: {}" , version);
3045+ return false ;
3046+ }
3047+
3048+ file.read (reinterpret_cast <char *>(&count), sizeof (count));
3049+
3050+ // Clear existing data and read addresses
3051+ m_executedInstructions.clear ();
3052+
3053+ for (size_t i = 0 ; i < count; i++)
3054+ {
3055+ uint64_t addr;
3056+ file.read (reinterpret_cast <char *>(&addr), sizeof (addr));
3057+ m_executedInstructions.insert (addr);
3058+ }
3059+
3060+ file.close ();
3061+ m_codeCoverageAnalysisRun = true ;
3062+
3063+ LogInfo (" Loaded {} executed instruction addresses from {}" , count, filePath);
3064+ return true ;
3065+ }
3066+ catch (const std::exception& e)
3067+ {
3068+ LogError (" Error loading code coverage: {}" , e.what ());
3069+ return false ;
3070+ }
3071+ }
3072+
3073+
29463074void DebuggerController::OnRebased (BinaryView* oldView, BinaryView* newView)
29473075{
29483076 m_data = newView;
0 commit comments