wallace created this revision. wallace added reviewers: clayborg, kusmour. Herald added subscribers: lldb-commits, mgorny. Herald added a project: LLDB. wallace requested review of this revision. Herald added a subscriber: JDevlieghere.
Depends on D85070 <https://reviews.llvm.org/D85070>. I don't think PTDecoder is structured very well, and the name is also misleading, and it doesn't just "decode". Given that the Python API generation has been broken for a long time and that one of my recent patches fix it, I assume there's no problem in changing the API, as there has been no users. A first fundamental change I want to do is to stop having PTDecoder as a top level class that receives an SBProcess for any action it needs to do. The existing way requires a good amount of boilerplate code here and there with little to no benefit. Instead, I'm renaming it into SBPTProcess. I think the SB is consistent with the LLDB SB API, and this class now directly manages one SBProcess. This means that whenever you want to trace or decode an SBProcess, you create a SBPTProcess class, which is easier to reason about in an OOP way. I've updated the test accordingly, and I've noticed that the code is now much simpler, with less faiture points and checks. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D85158 Files: lldb/test/API/tools/intel-features/intel-pt/test/TestIntelPTSimpleBinary.py lldb/tools/intel-features/intel-pt/include/intel-pt/API/PTDecoder.h lldb/tools/intel-features/intel-pt/include/intel-pt/API/SBPTProcess.h lldb/tools/intel-features/intel-pt/include/intel-pt/API/cli-wrapper-pt.h lldb/tools/intel-features/intel-pt/include/intel-pt/Core/Decoder.h lldb/tools/intel-features/intel-pt/include/intel-pt/Core/PTProcess.h lldb/tools/intel-features/intel-pt/interface/PTDecoder.i lldb/tools/intel-features/intel-pt/interface/SBPTProcess.i lldb/tools/intel-features/intel-pt/source/API/CMakeLists.txt lldb/tools/intel-features/intel-pt/source/API/PTDecoder.cpp lldb/tools/intel-features/intel-pt/source/API/SBPTProcess.cpp lldb/tools/intel-features/intel-pt/source/API/cli-wrapper-pt.cpp lldb/tools/intel-features/intel-pt/source/Core/CMakeLists.txt lldb/tools/intel-features/intel-pt/source/Core/Decoder.cpp lldb/tools/intel-features/intel-pt/source/Core/PTProcess.cpp lldb/tools/intel-features/scripts/lldb-intel-features.swig
Index: lldb/tools/intel-features/scripts/lldb-intel-features.swig =================================================================== --- lldb/tools/intel-features/scripts/lldb-intel-features.swig +++ lldb/tools/intel-features/scripts/lldb-intel-features.swig @@ -20,7 +20,7 @@ %{ #include "lldb/lldb-public.h" -#include "intel-pt/API/PTDecoder.h" +#include "intel-pt/API/SBPTProcess.h" using namespace intelpt; %} @@ -31,4 +31,4 @@ %include "python-typemaps.txt" /* Feature specific python interface files*/ -%include "../intel-pt/interface/PTDecoder.i" +%include "../intel-pt/interface/SBPTProcess.i" Index: lldb/tools/intel-features/intel-pt/source/Core/PTProcess.cpp =================================================================== --- lldb/tools/intel-features/intel-pt/source/Core/PTProcess.cpp +++ lldb/tools/intel-features/intel-pt/source/Core/PTProcess.cpp @@ -1,4 +1,4 @@ -//===-- Decoder.cpp ---------------------------------------------*- C++ -*-===// +//===-- PTProcess.cpp -------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "intel-pt/Core/Decoder.h" +#include "intel-pt/Core/PTProcess.h" // C/C++ Includes #include <cinttypes> @@ -18,77 +18,37 @@ using namespace intelpt_private; -// This function removes entries of all the processes/threads which were once +// This function removes entries of all the threads which were once // registered in the class but are not alive anymore because they died or // finished executing. -void Decoder::RemoveDeadProcessesAndThreads(lldb::SBProcess &sbprocess) { - lldb::SBTarget sbtarget = sbprocess.GetTarget(); - lldb::SBDebugger sbdebugger = sbtarget.GetDebugger(); - uint32_t num_targets = sbdebugger.GetNumTargets(); - - auto itr_process = m_mapProcessUID_mapThreadID_TraceInfo.begin(); - while (itr_process != m_mapProcessUID_mapThreadID_TraceInfo.end()) { - bool process_found = false; - lldb::SBTarget target; - lldb::SBProcess process; - for (uint32_t i = 0; i < num_targets; i++) { - target = sbdebugger.GetTargetAtIndex(i); - process = target.GetProcess(); - if (process.GetUniqueID() == itr_process->first) { - process_found = true; - break; - } - } - - // Remove the process's entry if it was not found in SBDebugger - if (!process_found) { - itr_process = m_mapProcessUID_mapThreadID_TraceInfo.erase(itr_process); +void PTProcess::RemoveDeadThreads() { + auto itr_thread = m_mapThreadID_TraceInfo.begin(); + while (itr_thread != m_mapThreadID_TraceInfo.end()) { + if (itr_thread->first == LLDB_INVALID_THREAD_ID) { + ++itr_thread; continue; } - // If the state of the process is exited or detached then remove process's - // entry. If not then remove entry for all those registered threads of this - // process that are not alive anymore. - lldb::StateType state = process.GetState(); - if ((state == lldb::StateType::eStateDetached) || - (state == lldb::StateType::eStateExited)) - itr_process = m_mapProcessUID_mapThreadID_TraceInfo.erase(itr_process); - else { - auto itr_thread = itr_process->second.begin(); - while (itr_thread != itr_process->second.end()) { - if (itr_thread->first == LLDB_INVALID_THREAD_ID) { - ++itr_thread; - continue; - } - - lldb::SBThread thread = process.GetThreadByID(itr_thread->first); - if (!thread.IsValid()) - itr_thread = itr_process->second.erase(itr_thread); - else - ++itr_thread; - } - ++itr_process; - } + lldb::SBThread thread = m_process.GetThreadByID(itr_thread->first); + if (!thread.IsValid()) + itr_thread = m_mapThreadID_TraceInfo.erase(itr_thread); + else + ++itr_thread; } } -void Decoder::StartProcessorTrace(lldb::SBProcess &sbprocess, - lldb::SBTraceOptions &sbtraceoptions, - lldb::SBError &sberror) { +void PTProcess::StartProcessorTrace(lldb::SBTraceOptions &sbtraceoptions, + lldb::SBError &sberror) { sberror.Clear(); - CheckDebuggerID(sbprocess, sberror); - if (!sberror.Success()) - return; - std::lock_guard<std::mutex> guard( - m_mapProcessUID_mapThreadID_TraceInfo_mutex); - RemoveDeadProcessesAndThreads(sbprocess); + std::lock_guard<std::mutex> guard(m_mapThreadID_TraceInfo_mutex); + RemoveDeadThreads(); if (sbtraceoptions.getType() != lldb::TraceType::eTraceTypeProcessorTrace) { sberror.SetErrorStringWithFormat("SBTraceOptions::TraceType not set to " "eTraceTypeProcessorTrace; ProcessID = " "%" PRIu64, - sbprocess.GetProcessID()); + m_process.GetProcessID()); return; } lldb::SBStructuredData sbstructdata = sbtraceoptions.getTraceParams(sberror); @@ -116,7 +76,7 @@ std::size_t pos = trace_tech_value.find((const char *)string_value, 0, bytes_written); - if ((pos == std::string::npos)) { + if (pos == std::string::npos) { sberror.SetErrorStringWithFormat( "key \"%s\" not set to \"%s\" in custom trace parameters", trace_tech_key, trace_tech_value.c_str()); @@ -125,55 +85,40 @@ // Start Tracing lldb::SBError error; - uint32_t unique_id = sbprocess.GetUniqueID(); lldb::tid_t tid = sbtraceoptions.getThreadID(); - lldb::SBTrace trace = sbprocess.StartTrace(sbtraceoptions, error); + lldb::SBTrace trace = m_process.StartTrace(sbtraceoptions, error); if (!error.Success()) { if (tid == LLDB_INVALID_THREAD_ID) sberror.SetErrorStringWithFormat("%s; ProcessID = %" PRIu64, error.GetCString(), - sbprocess.GetProcessID()); + m_process.GetProcessID()); else sberror.SetErrorStringWithFormat( "%s; thread_id = %" PRIu64 ", ProcessID = %" PRIu64, - error.GetCString(), tid, sbprocess.GetProcessID()); + error.GetCString(), tid, m_process.GetProcessID()); return; } - MapThreadID_TraceInfo &mapThreadID_TraceInfo = - m_mapProcessUID_mapThreadID_TraceInfo[unique_id]; - ThreadTraceInfo &trace_info = mapThreadID_TraceInfo[tid]; + ThreadTraceInfo &trace_info = m_mapThreadID_TraceInfo[tid]; trace_info.SetUniqueTraceInstance(trace); - trace_info.SetStopID(sbprocess.GetStopID()); + trace_info.SetStopID(m_process.GetStopID()); } -void Decoder::StopProcessorTrace(lldb::SBProcess &sbprocess, - lldb::SBError &sberror, lldb::tid_t tid) { +void PTProcess::StopProcessorTrace(lldb::SBError &sberror, lldb::tid_t tid) { sberror.Clear(); - CheckDebuggerID(sbprocess, sberror); if (!sberror.Success()) { return; } - std::lock_guard<std::mutex> guard( - m_mapProcessUID_mapThreadID_TraceInfo_mutex); - RemoveDeadProcessesAndThreads(sbprocess); - - uint32_t unique_id = sbprocess.GetUniqueID(); - auto itr_process = m_mapProcessUID_mapThreadID_TraceInfo.find(unique_id); - if (itr_process == m_mapProcessUID_mapThreadID_TraceInfo.end()) { - sberror.SetErrorStringWithFormat( - "tracing not active for this process; ProcessID = %" PRIu64, - sbprocess.GetProcessID()); - return; - } + std::lock_guard<std::mutex> guard(m_mapThreadID_TraceInfo_mutex); + RemoveDeadThreads(); lldb::SBError error; if (tid == LLDB_INVALID_THREAD_ID) { // This implies to stop tracing on the whole process lldb::user_id_t id_to_be_ignored = LLDB_INVALID_UID; - auto itr_thread = itr_process->second.begin(); - while (itr_thread != itr_process->second.end()) { + auto itr_thread = m_mapThreadID_TraceInfo.begin(); + while (itr_thread != m_mapThreadID_TraceInfo.end()) { // In the case when user started trace on the entire process and then // registered newly spawned threads of this process in the class later, // these newly spawned threads will have same trace id. If we stopped @@ -194,7 +139,7 @@ sberror.SetErrorStringWithFormat( "%s; thread id=%" PRIu64 ", ProcessID = %" PRIu64, error_string.c_str(), itr_thread->first, - sbprocess.GetProcessID()); + m_process.GetProcessID()); return; } } @@ -202,9 +147,8 @@ if (itr_thread->first == LLDB_INVALID_THREAD_ID) id_to_be_ignored = lldb_pt_user_id; } - itr_thread = itr_process->second.erase(itr_thread); + itr_thread = m_mapThreadID_TraceInfo.erase(itr_thread); } - m_mapProcessUID_mapThreadID_TraceInfo.erase(itr_process); } else { // This implies to stop tracing on a single thread. // if 'tid' is registered in the class then get the trace id and stop trace @@ -215,20 +159,19 @@ // the trace id of the process trace instance and stop trace on this thread. // If tracing was never started on the entire process then return error // because there is no way tracing is active on 'tid'. - MapThreadID_TraceInfo &mapThreadID_TraceInfo = itr_process->second; lldb::SBTrace trace; - auto itr = mapThreadID_TraceInfo.find(tid); - if (itr != mapThreadID_TraceInfo.end()) { + auto itr = m_mapThreadID_TraceInfo.find(tid); + if (itr != m_mapThreadID_TraceInfo.end()) { trace = itr->second.GetUniqueTraceInstance(); } else { - auto itr = mapThreadID_TraceInfo.find(LLDB_INVALID_THREAD_ID); - if (itr != mapThreadID_TraceInfo.end()) { + auto itr = m_mapThreadID_TraceInfo.find(LLDB_INVALID_THREAD_ID); + if (itr != m_mapThreadID_TraceInfo.end()) { trace = itr->second.GetUniqueTraceInstance(); } else { sberror.SetErrorStringWithFormat( "tracing not active for this thread; thread id=%" PRIu64 ", ProcessID = %" PRIu64, - tid, sbprocess.GetProcessID()); + tid, m_process.GetProcessID()); return; } } @@ -239,18 +182,18 @@ std::string error_string(error.GetCString()); sberror.SetErrorStringWithFormat( "%s; thread id=%" PRIu64 ", ProcessID = %" PRIu64, - error_string.c_str(), tid, sbprocess.GetProcessID()); + error_string.c_str(), tid, m_process.GetProcessID()); if (error_string.find("tracing not active") == std::string::npos) return; } // Delete the entry of 'tid' from this class (if any) - mapThreadID_TraceInfo.erase(tid); + m_mapThreadID_TraceInfo.erase(tid); } } -void Decoder::ReadTraceDataAndImageInfo(lldb::SBProcess &sbprocess, - lldb::tid_t tid, lldb::SBError &sberror, - ThreadTraceInfo &threadTraceInfo) { +void PTProcess::ReadTraceDataAndImageInfo(lldb::tid_t tid, + lldb::SBError &sberror, + ThreadTraceInfo &threadTraceInfo) { // Allocate trace data buffer and parse cpu info for 'tid' if it is registered // for the first time in class lldb::SBTrace &trace = threadTraceInfo.GetUniqueTraceInstance(); @@ -263,14 +206,14 @@ if (!error.Success()) { sberror.SetErrorStringWithFormat("%s; ProcessID = %" PRIu64, error.GetCString(), - sbprocess.GetProcessID()); + m_process.GetProcessID()); return; } if (traceoptions.getType() != lldb::TraceType::eTraceTypeProcessorTrace) { sberror.SetErrorStringWithFormat("invalid TraceType received from LLDB " "for this thread; thread id=%" PRIu64 ", ProcessID = %" PRIu64, - tid, sbprocess.GetProcessID()); + tid, m_process.GetProcessID()); return; } @@ -290,23 +233,21 @@ if (!error.Success()) { sberror.SetErrorStringWithFormat( "%s; thread_id = %" PRIu64 ", ProcessID = %" PRIu64, - error.GetCString(), tid, sbprocess.GetProcessID()); + error.GetCString(), tid, m_process.GetProcessID()); return; } std::fill(pt_buffer.begin() + bytes_written, pt_buffer.end(), 0); // Get information of all the modules of the inferior - lldb::SBTarget sbtarget = sbprocess.GetTarget(); ReadExecuteSectionInfos &readExecuteSectionInfos = threadTraceInfo.GetReadExecuteSectionInfos(); - GetTargetModulesInfo(sbtarget, readExecuteSectionInfos, sberror); + GetTargetModulesInfo(readExecuteSectionInfos, sberror); if (!sberror.Success()) return; } -void Decoder::DecodeProcessorTrace(lldb::SBProcess &sbprocess, lldb::tid_t tid, - lldb::SBError &sberror, - ThreadTraceInfo &threadTraceInfo) { +void PTProcess::DecodeProcessorTrace(lldb::tid_t tid, lldb::SBError &sberror, + ThreadTraceInfo &threadTraceInfo) { // Initialize instruction decoder struct pt_insn_decoder *decoder = nullptr; struct pt_config config; @@ -329,15 +270,9 @@ // Raw trace decoding requires information of Read & Execute sections of each // module of the inferior. This function updates internal state of the class to // store this information. -void Decoder::GetTargetModulesInfo( - lldb::SBTarget &sbtarget, ReadExecuteSectionInfos &readExecuteSectionInfos, - lldb::SBError &sberror) { - if (!sbtarget.IsValid()) { - sberror.SetErrorStringWithFormat("Can't get target's modules info from " - "LLDB; process has an invalid target"); - return; - } - +void PTProcess::GetTargetModulesInfo( + ReadExecuteSectionInfos &readExecuteSectionInfos, lldb::SBError &sberror) { + lldb::SBTarget sbtarget = m_process.GetTarget(); lldb::SBFileSpec target_file_spec = sbtarget.GetExecutable(); if (!target_file_spec.IsValid()) { sberror.SetErrorStringWithFormat("Target has an invalid file spec"); @@ -416,8 +351,8 @@ // is running. This function gets the Trace Configuration from LLDB, parses it // for cpu model, family, stepping and vendor id info and updates the internal // state of the class to store this information. -void Decoder::ParseCPUInfo(CPUInfo &pt_cpu, lldb::SBStructuredData &s, - lldb::SBError &sberror) { +void PTProcess::ParseCPUInfo(CPUInfo &pt_cpu, lldb::SBStructuredData &s, + lldb::SBError &sberror) { lldb::SBStructuredData custom_trace_params = s.GetValueForKey("intel-pt"); if (!custom_trace_params.IsValid()) { sberror.SetErrorStringWithFormat("lldb couldn't provide cpuinfo"); @@ -505,7 +440,7 @@ // structure with inferior's memory image information. pt_config structure is // initialized with trace buffer and cpu info of the inferior before storing it // in trace decoder. -void Decoder::InitializePTInstDecoder( +void PTProcess::InitializePTInstDecoder( struct pt_insn_decoder **decoder, struct pt_config *config, const CPUInfo &pt_cpu, Buffer &pt_buffer, const ReadExecuteSectionInfos &readExecuteSectionInfos, @@ -564,7 +499,7 @@ } } -void Decoder::AppendErrorWithOffsetToInstructionList( +void PTProcess::AppendErrorWithOffsetToInstructionList( int errcode, uint64_t decoder_offset, Instructions &instruction_list, lldb::SBError &sberror) { sberror.SetErrorStringWithFormat( @@ -574,16 +509,17 @@ instruction_list.emplace_back(sberror.GetCString()); } -void Decoder::AppendErrorWithoutOffsetToInstructionList( +void PTProcess::AppendErrorWithoutOffsetToInstructionList( int errcode, Instructions &instruction_list, lldb::SBError &sberror) { sberror.SetErrorStringWithFormat("processor trace decoding library: \"%s\"", pt_errstr(pt_errcode(errcode))); instruction_list.emplace_back(sberror.GetCString()); } -int Decoder::AppendErrorToInstructionList(int errcode, pt_insn_decoder *decoder, - Instructions &instruction_list, - lldb::SBError &sberror) { +int PTProcess::AppendErrorToInstructionList(int errcode, + pt_insn_decoder *decoder, + Instructions &instruction_list, + lldb::SBError &sberror) { uint64_t decoder_offset = 0; int errcode_off = pt_insn_get_offset(decoder, &decoder_offset); if (errcode_off < 0) { @@ -596,9 +532,9 @@ return 0; } -int Decoder::HandlePTInstructionEvents(pt_insn_decoder *decoder, int errcode, - Instructions &instruction_list, - lldb::SBError &sberror) { +int PTProcess::HandlePTInstructionEvents(pt_insn_decoder *decoder, int errcode, + Instructions &instruction_list, + lldb::SBError &sberror) { while (errcode & pts_event_pending) { pt_event event; errcode = pt_insn_event(decoder, &event, sizeof(event)); @@ -620,9 +556,9 @@ } // Start actual decoding of raw trace -void Decoder::DecodeTrace(struct pt_insn_decoder *decoder, - Instructions &instruction_list, - lldb::SBError &sberror) { +void PTProcess::DecodeTrace(struct pt_insn_decoder *decoder, + Instructions &instruction_list, + lldb::SBError &sberror) { uint64_t decoder_offset = 0; while (1) { @@ -710,8 +646,8 @@ } // Function to diagnose and indicate errors during raw trace decoding -void Decoder::Diagnose(struct pt_insn_decoder *decoder, int decode_error, - lldb::SBError &sberror, const struct pt_insn *insn) { +void PTProcess::Diagnose(struct pt_insn_decoder *decoder, int decode_error, + lldb::SBError &sberror, const struct pt_insn *insn) { int errcode; uint64_t offset; @@ -740,23 +676,16 @@ } } -void Decoder::GetInstructionLogAtOffset(lldb::SBProcess &sbprocess, - lldb::tid_t tid, uint32_t offset, - uint32_t count, - InstructionList &result_list, - lldb::SBError &sberror) { +void PTProcess::GetInstructionLogAtOffset(lldb::tid_t tid, uint32_t offset, + uint32_t count, + InstructionList &result_list, + lldb::SBError &sberror) { sberror.Clear(); - CheckDebuggerID(sbprocess, sberror); - if (!sberror.Success()) { - return; - } - - std::lock_guard<std::mutex> guard( - m_mapProcessUID_mapThreadID_TraceInfo_mutex); - RemoveDeadProcessesAndThreads(sbprocess); + std::lock_guard<std::mutex> guard(m_mapThreadID_TraceInfo_mutex); + RemoveDeadThreads(); ThreadTraceInfo *threadTraceInfo = nullptr; - FetchAndDecode(sbprocess, tid, sberror, &threadTraceInfo); + FetchAndDecode(tid, sberror, &threadTraceInfo); if (!sberror.Success()) { return; } @@ -774,7 +703,7 @@ sberror.SetErrorStringWithFormat( "Instruction Log not available for offset=%" PRIu32 " and count=%" PRIu32 ", ProcessID = %" PRIu64, - offset, count, sbprocess.GetProcessID()); + offset, count, m_process.GetProcessID()); return; } @@ -791,21 +720,18 @@ } } -void Decoder::GetProcessorTraceInfo(lldb::SBProcess &sbprocess, lldb::tid_t tid, - TraceOptions &options, - lldb::SBError &sberror) { +void PTProcess::GetProcessorTraceInfo(lldb::tid_t tid, TraceOptions &options, + lldb::SBError &sberror) { sberror.Clear(); - CheckDebuggerID(sbprocess, sberror); if (!sberror.Success()) { return; } - std::lock_guard<std::mutex> guard( - m_mapProcessUID_mapThreadID_TraceInfo_mutex); - RemoveDeadProcessesAndThreads(sbprocess); + std::lock_guard<std::mutex> guard(m_mapThreadID_TraceInfo_mutex); + RemoveDeadThreads(); ThreadTraceInfo *threadTraceInfo = nullptr; - FetchAndDecode(sbprocess, tid, sberror, &threadTraceInfo); + FetchAndDecode(tid, sberror, &threadTraceInfo); if (!sberror.Success()) { return; } @@ -823,22 +749,18 @@ if (!error.Success()) { std::string error_string(error.GetCString()); if (error_string.find("tracing not active") != std::string::npos) { - uint32_t unique_id = sbprocess.GetUniqueID(); - auto itr_process = m_mapProcessUID_mapThreadID_TraceInfo.find(unique_id); - if (itr_process == m_mapProcessUID_mapThreadID_TraceInfo.end()) - return; - itr_process->second.erase(tid); + m_mapThreadID_TraceInfo.erase(tid); } sberror.SetErrorStringWithFormat("%s; ProcessID = %" PRIu64, error_string.c_str(), - sbprocess.GetProcessID()); + m_process.GetProcessID()); return; } if (traceoptions.getType() != lldb::TraceType::eTraceTypeProcessorTrace) { sberror.SetErrorStringWithFormat("invalid TraceType received from LLDB " "for this thread; thread id=%" PRIu64 ", ProcessID = %" PRIu64, - tid, sbprocess.GetProcessID()); + tid, m_process.GetProcessID()); return; } options.setType(traceoptions.getType()); @@ -851,24 +773,13 @@ options.setInstructionLogSize(threadTraceInfo->GetInstructionLog().size()); } -void Decoder::FetchAndDecode(lldb::SBProcess &sbprocess, lldb::tid_t tid, - lldb::SBError &sberror, - ThreadTraceInfo **threadTraceInfo) { - // Return with error if 'sbprocess' is not registered in the class - uint32_t unique_id = sbprocess.GetUniqueID(); - auto itr_process = m_mapProcessUID_mapThreadID_TraceInfo.find(unique_id); - if (itr_process == m_mapProcessUID_mapThreadID_TraceInfo.end()) { - sberror.SetErrorStringWithFormat( - "tracing not active for this process; ProcessID = %" PRIu64, - sbprocess.GetProcessID()); - return; - } - +void PTProcess::FetchAndDecode(lldb::tid_t tid, lldb::SBError &sberror, + ThreadTraceInfo **threadTraceInfo) { if (tid == LLDB_INVALID_THREAD_ID) { sberror.SetErrorStringWithFormat( "invalid thread id provided; thread_id = %" PRIu64 ", ProcessID = %" PRIu64, - tid, sbprocess.GetProcessID()); + tid, m_process.GetProcessID()); return; } @@ -881,85 +792,50 @@ return; } - MapThreadID_TraceInfo &mapThreadID_TraceInfo = itr_process->second; - auto itr_thread = mapThreadID_TraceInfo.find(tid); - if (itr_thread != mapThreadID_TraceInfo.end()) { - if (itr_thread->second.GetStopID() == sbprocess.GetStopID()) { + auto itr_thread = m_mapThreadID_TraceInfo.find(tid); + if (itr_thread != m_mapThreadID_TraceInfo.end()) { + if (itr_thread->second.GetStopID() == m_process.GetStopID()) { *threadTraceInfo = &(itr_thread->second); return; } - itr_thread->second.SetStopID(sbprocess.GetStopID()); + itr_thread->second.SetStopID(m_process.GetStopID()); } else { // Implies 'tid' is not registered in the class. If tracing was never // started on the entire process then return an error. Else try to register // this thread and proceed with reading and decoding trace. lldb::SBError error; - itr_thread = mapThreadID_TraceInfo.find(LLDB_INVALID_THREAD_ID); - if (itr_thread == mapThreadID_TraceInfo.end()) { + itr_thread = m_mapThreadID_TraceInfo.find(LLDB_INVALID_THREAD_ID); + if (itr_thread == m_mapThreadID_TraceInfo.end()) { sberror.SetErrorStringWithFormat( "tracing not active for this thread; ProcessID = %" PRIu64, - sbprocess.GetProcessID()); + m_process.GetProcessID()); return; } lldb::SBTrace &trace = itr_thread->second.GetUniqueTraceInstance(); - ThreadTraceInfo &trace_info = mapThreadID_TraceInfo[tid]; + ThreadTraceInfo &trace_info = m_mapThreadID_TraceInfo[tid]; trace_info.SetUniqueTraceInstance(trace); - trace_info.SetStopID(sbprocess.GetStopID()); - itr_thread = mapThreadID_TraceInfo.find(tid); + trace_info.SetStopID(m_process.GetStopID()); + itr_thread = m_mapThreadID_TraceInfo.find(tid); } // Get raw trace data and inferior image from LLDB for the registered thread - ReadTraceDataAndImageInfo(sbprocess, tid, sberror, itr_thread->second); + ReadTraceDataAndImageInfo(tid, sberror, itr_thread->second); if (!sberror.Success()) { std::string error_string(sberror.GetCString()); if (error_string.find("tracing not active") != std::string::npos) - mapThreadID_TraceInfo.erase(itr_thread); + m_mapThreadID_TraceInfo.erase(itr_thread); return; } // Decode raw trace data - DecodeProcessorTrace(sbprocess, tid, sberror, itr_thread->second); + DecodeProcessorTrace(tid, sberror, itr_thread->second); if (!sberror.Success()) { return; } *threadTraceInfo = &(itr_thread->second); } -// This function checks whether the provided SBProcess instance belongs to same -// SBDebugger with which this tool instance is associated. -void Decoder::CheckDebuggerID(lldb::SBProcess &sbprocess, - lldb::SBError &sberror) { - if (!sbprocess.IsValid()) { - sberror.SetErrorStringWithFormat("invalid process instance"); - return; - } - - lldb::SBTarget sbtarget = sbprocess.GetTarget(); - if (!sbtarget.IsValid()) { - sberror.SetErrorStringWithFormat( - "process contains an invalid target; ProcessID = %" PRIu64, - sbprocess.GetProcessID()); - return; - } - - lldb::SBDebugger sbdebugger = sbtarget.GetDebugger(); - if (!sbdebugger.IsValid()) { - sberror.SetErrorStringWithFormat("process's target contains an invalid " - "debugger instance; ProcessID = %" PRIu64, - sbprocess.GetProcessID()); - return; - } - - if (sbdebugger.GetID() != m_debugger_user_id) { - sberror.SetErrorStringWithFormat( - "process belongs to a different SBDebugger instance than the one for " - "which the tool is instantiated; ProcessID = %" PRIu64, - sbprocess.GetProcessID()); - return; - } -} - -lldb::SBTraceOptions Decoder::GetDefaultTraceOptions() { +lldb::SBTraceOptions PTProcess::GetDefaultTraceOptions() { lldb::SBTraceOptions trace_opts; trace_opts.setThreadID(LLDB_INVALID_THREAD_ID); trace_opts.setType(lldb::TraceType::eTraceTypeProcessorTrace); Index: lldb/tools/intel-features/intel-pt/source/Core/CMakeLists.txt =================================================================== --- lldb/tools/intel-features/intel-pt/source/Core/CMakeLists.txt +++ lldb/tools/intel-features/intel-pt/source/Core/CMakeLists.txt @@ -21,7 +21,7 @@ endif() add_lldb_library(lldbIntelPTCore - Decoder.cpp + PTProcess.cpp LINK_LIBS ${LIBIPT_LIBRARY} Index: lldb/tools/intel-features/intel-pt/source/API/cli-wrapper-pt.cpp =================================================================== --- lldb/tools/intel-features/intel-pt/source/API/cli-wrapper-pt.cpp +++ lldb/tools/intel-features/intel-pt/source/API/cli-wrapper-pt.cpp @@ -4,7 +4,7 @@ // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // -// CLI Wrapper of PTDecoder Tool to enable it to be used through LLDB's CLI. The +// CLI Wrapper of PTProcess Tool to enable it to be used through LLDB's CLI. The // wrapper provides a new command called processor-trace with 4 child // subcommands as follows: // processor-trace start @@ -17,10 +17,11 @@ #include <cerrno> #include <cinttypes> #include <cstring> +#include <map> #include <string> #include <vector> -#include "intel-pt/API/PTDecoder.h" +#include "intel-pt/API/SBPTProcess.h" #include "intel-pt/API/cli-wrapper-pt.h" #include "lldb/API/SBCommandInterpreter.h" #include "lldb/API/SBCommandReturnObject.h" @@ -31,9 +32,11 @@ #include "lldb/API/SBTarget.h" #include "lldb/API/SBThread.h" -static bool GetProcess(lldb::SBDebugger &debugger, - lldb::SBCommandReturnObject &result, - lldb::SBProcess &process) { +static bool GetPTProcess(lldb::SBDebugger &debugger, + lldb::SBCommandReturnObject &result, + lldb::SBProcess &process, + intelpt::SBPTProcess &ptprocess) { + static std::map<uint32_t, intelpt::SBPTProcess> puid_ptprocess_map; if (!debugger.IsValid()) { result.Printf("error: invalid debugger\n"); result.SetStatus(lldb::eReturnStatusFailed); @@ -56,6 +59,14 @@ result.SetStatus(lldb::eReturnStatusFailed); return false; } + uint32_t uid = process.GetUniqueID(); + auto it = puid_ptprocess_map.find(uid); + if (it != puid_ptprocess_map.end()) + ptprocess = it->second; + else { + ptprocess = intelpt::SBPTProcess(process); + puid_ptprocess_map[uid] = ptprocess; + } return true; } @@ -123,8 +134,7 @@ class ProcessorTraceStart : public lldb::SBCommandPluginInterface { public: - ProcessorTraceStart(std::shared_ptr<intelpt::PTDecoder> &pt_decoder) - : SBCommandPluginInterface(), pt_decoder_sp(pt_decoder) {} + ProcessorTraceStart() : SBCommandPluginInterface() {} ~ProcessorTraceStart() {} @@ -132,12 +142,13 @@ lldb::SBCommandReturnObject &result) { lldb::SBProcess process; lldb::SBThread thread; - if (!GetProcess(debugger, result, process)) + intelpt::SBPTProcess ptprocess; + if (!GetPTProcess(debugger, result, process, ptprocess)) return false; // Default initialize API's arguments lldb::SBTraceOptions lldb_SBTraceOptions = - intelpt::PTDecoder::GetDefaultTraceOptions(); + intelpt::SBPTProcess::GetDefaultTraceOptions(); uint32_t trace_buffer_size = lldb_SBTraceOptions.getTraceBufferSize(); lldb::tid_t thread_id; @@ -175,7 +186,7 @@ // Start trace lldb::SBError error; - pt_decoder_sp->StartProcessorTrace(process, lldb_SBTraceOptions, error); + ptprocess.StartProcessorTrace(lldb_SBTraceOptions, error); if (!error.Success()) { result.Printf("error: %s\n", error.GetCString()); result.SetStatus(lldb::eReturnStatusFailed); @@ -186,14 +197,12 @@ } private: - std::shared_ptr<intelpt::PTDecoder> pt_decoder_sp; const uint32_t m_max_trace_buff_size = 0x3fff; }; class ProcessorTraceInfo : public lldb::SBCommandPluginInterface { public: - ProcessorTraceInfo(std::shared_ptr<intelpt::PTDecoder> &pt_decoder) - : SBCommandPluginInterface(), pt_decoder_sp(pt_decoder) {} + ProcessorTraceInfo() : SBCommandPluginInterface() {} ~ProcessorTraceInfo() {} @@ -201,7 +210,8 @@ lldb::SBCommandReturnObject &result) { lldb::SBProcess process; lldb::SBThread thread; - if (!GetProcess(debugger, result, process)) + intelpt::SBPTProcess ptprocess; + if (!GetPTProcess(debugger, result, process, ptprocess)) return false; lldb::tid_t thread_id; @@ -247,7 +257,7 @@ thread_id = thread.GetThreadID(); intelpt::PTTraceOptions options; - pt_decoder_sp->GetProcessorTraceInfo(process, thread_id, options, error); + ptprocess.GetProcessorTraceInfo(thread_id, options, error); if (!error.Success()) { res.Printf("thread #%" PRIu32 ": tid=%" PRIu64 ", error: %s", thread.GetIndexID(), thread_id, error.GetCString()); @@ -283,15 +293,11 @@ result.SetStatus(lldb::eReturnStatusSuccessFinishResult); return true; } - -private: - std::shared_ptr<intelpt::PTDecoder> pt_decoder_sp; }; class ProcessorTraceShowInstrLog : public lldb::SBCommandPluginInterface { public: - ProcessorTraceShowInstrLog(std::shared_ptr<intelpt::PTDecoder> &pt_decoder) - : SBCommandPluginInterface(), pt_decoder_sp(pt_decoder) {} + ProcessorTraceShowInstrLog() : SBCommandPluginInterface() {} ~ProcessorTraceShowInstrLog() {} @@ -299,7 +305,8 @@ lldb::SBCommandReturnObject &result) { lldb::SBProcess process; lldb::SBThread thread; - if (!GetProcess(debugger, result, process)) + intelpt::SBPTProcess ptprocess; + if (!GetPTProcess(debugger, result, process, ptprocess)) return false; // Default initialize API's arguments @@ -364,8 +371,8 @@ // Get the instruction log intelpt::PTInstructionList insn_list; - pt_decoder_sp->GetInstructionLogAtOffset(process, thread_id, offset, - count, insn_list, error); + ptprocess.GetInstructionLogAtOffset(thread_id, offset, count, insn_list, + error); if (!error.Success()) { res.Printf("thread #%" PRIu32 ": tid=%" PRIu64 ", error: %s", thread.GetIndexID(), thread_id, error.GetCString()); @@ -424,14 +431,12 @@ } private: - std::shared_ptr<intelpt::PTDecoder> pt_decoder_sp; const uint32_t m_default_count = 10; }; class ProcessorTraceStop : public lldb::SBCommandPluginInterface { public: - ProcessorTraceStop(std::shared_ptr<intelpt::PTDecoder> &pt_decoder) - : SBCommandPluginInterface(), pt_decoder_sp(pt_decoder) {} + ProcessorTraceStop() : SBCommandPluginInterface() {} ~ProcessorTraceStop() {} @@ -439,7 +444,8 @@ lldb::SBCommandReturnObject &result) { lldb::SBProcess process; lldb::SBThread thread; - if (!GetProcess(debugger, result, process)) + intelpt::SBPTProcess ptprocess; + if (!GetPTProcess(debugger, result, process, ptprocess)) return false; lldb::tid_t thread_id; @@ -466,7 +472,7 @@ // Stop trace lldb::SBError error; - pt_decoder_sp->StopProcessorTrace(process, error, thread_id); + ptprocess.StopProcessorTrace(error, thread_id); if (!error.Success()) { result.Printf("error: %s\n", error.GetCString()); result.SetStatus(lldb::eReturnStatusFailed); @@ -475,9 +481,6 @@ result.SetStatus(lldb::eReturnStatusSuccessFinishResult); return true; } - -private: - std::shared_ptr<intelpt::PTDecoder> pt_decoder_sp; }; bool PTPluginInitialize(lldb::SBDebugger &debugger) { @@ -485,11 +488,7 @@ lldb::SBCommand proc_trace = interpreter.AddMultiwordCommand( "processor-trace", "Intel(R) Processor Trace for thread/process"); - std::shared_ptr<intelpt::PTDecoder> PTDecoderSP( - new intelpt::PTDecoder(debugger)); - - lldb::SBCommandPluginInterface *proc_trace_start = - new ProcessorTraceStart(PTDecoderSP); + lldb::SBCommandPluginInterface *proc_trace_start = new ProcessorTraceStart(); const char *help_proc_trace_start = "start Intel(R) Processor Trace on a " "specific thread or on the whole process"; const char *syntax_proc_trace_start = @@ -506,8 +505,7 @@ proc_trace.AddCommand("start", proc_trace_start, help_proc_trace_start, syntax_proc_trace_start); - lldb::SBCommandPluginInterface *proc_trace_stop = - new ProcessorTraceStop(PTDecoderSP); + lldb::SBCommandPluginInterface *proc_trace_stop = new ProcessorTraceStop(); const char *help_proc_trace_stop = "stop Intel(R) Processor Trace on a specific thread or on whole process"; const char *syntax_proc_trace_stop = @@ -522,7 +520,7 @@ syntax_proc_trace_stop); lldb::SBCommandPluginInterface *proc_trace_show_instr_log = - new ProcessorTraceShowInstrLog(PTDecoderSP); + new ProcessorTraceShowInstrLog(); const char *help_proc_trace_show_instr_log = "display a log of assembly instructions executed for a specific thread " "or for the whole process.\n" @@ -551,8 +549,7 @@ help_proc_trace_show_instr_log, syntax_proc_trace_show_instr_log); - lldb::SBCommandPluginInterface *proc_trace_options = - new ProcessorTraceInfo(PTDecoderSP); + lldb::SBCommandPluginInterface *proc_trace_options = new ProcessorTraceInfo(); const char *help_proc_trace_show_options = "display all the information regarding Intel(R) Processor Trace for a " "specific thread or for the whole process.\n" Index: lldb/tools/intel-features/intel-pt/source/API/SBPTProcess.cpp =================================================================== --- lldb/tools/intel-features/intel-pt/source/API/SBPTProcess.cpp +++ lldb/tools/intel-features/intel-pt/source/API/SBPTProcess.cpp @@ -1,4 +1,4 @@ -//===-- PTDecoder.cpp -------------------------------------------*- C++ -*-===// +//===-- SBPTProcess.cpp -----------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "intel-pt/API/PTDecoder.h" -#include "intel-pt/Core/Decoder.h" +#include "intel-pt/API/SBPTProcess.h" +#include "intel-pt/Core/PTProcess.h" using namespace intelpt; using namespace intelpt_private; @@ -85,69 +85,67 @@ m_opaque_sp = ptr; } -// PTDecoder class member functions definitions -PTDecoder::PTDecoder(lldb::SBDebugger &sbdebugger) - : m_opaque_sp(new intelpt_private::Decoder(sbdebugger)) {} +// SBPTProcess class member functions definitions +SBPTProcess::SBPTProcess(lldb::SBProcess &process) + : m_opaque_sp(new intelpt_private::PTProcess(process)) {} -void PTDecoder::StartProcessorTrace(lldb::SBProcess &sbprocess, - lldb::SBTraceOptions &sbtraceoptions, - lldb::SBError &sberror) { +SBPTProcess::SBPTProcess() : m_opaque_sp(nullptr) {} + +void SBPTProcess::StartProcessorTrace(lldb::SBTraceOptions &sbtraceoptions, + lldb::SBError &sberror) { if (m_opaque_sp == nullptr) { - sberror.SetErrorStringWithFormat("invalid PTDecoder instance"); + sberror.SetErrorStringWithFormat("invalid SBPTProcess instance"); return; } - m_opaque_sp->StartProcessorTrace(sbprocess, sbtraceoptions, sberror); + m_opaque_sp->StartProcessorTrace(sbtraceoptions, sberror); } -void PTDecoder::StopProcessorTrace(lldb::SBProcess &sbprocess, - lldb::SBError &sberror, lldb::tid_t tid) { +void SBPTProcess::StopProcessorTrace(lldb::SBError &sberror, lldb::tid_t tid) { if (m_opaque_sp == nullptr) { - sberror.SetErrorStringWithFormat("invalid PTDecoder instance"); + sberror.SetErrorStringWithFormat("invalid SBPTProcess instance"); return; } - m_opaque_sp->StopProcessorTrace(sbprocess, sberror, tid); + m_opaque_sp->StopProcessorTrace(sberror, tid); } -void PTDecoder::GetInstructionLogAtOffset(lldb::SBProcess &sbprocess, - lldb::tid_t tid, uint32_t offset, - uint32_t count, - PTInstructionList &result_list, - lldb::SBError &sberror) { +void SBPTProcess::GetInstructionLogAtOffset(lldb::tid_t tid, uint32_t offset, + uint32_t count, + PTInstructionList &result_list, + lldb::SBError &sberror) { if (m_opaque_sp == nullptr) { - sberror.SetErrorStringWithFormat("invalid PTDecoder instance"); + sberror.SetErrorStringWithFormat("invalid SBPTProcess instance"); return; } std::shared_ptr<intelpt_private::InstructionList> insn_list_ptr( new InstructionList()); - m_opaque_sp->GetInstructionLogAtOffset(sbprocess, tid, offset, count, - *insn_list_ptr, sberror); + m_opaque_sp->GetInstructionLogAtOffset(tid, offset, count, *insn_list_ptr, + sberror); if (!sberror.Success()) return; result_list.SetSP(insn_list_ptr); } -void PTDecoder::GetProcessorTraceInfo(lldb::SBProcess &sbprocess, - lldb::tid_t tid, PTTraceOptions &options, - lldb::SBError &sberror) { +void SBPTProcess::GetProcessorTraceInfo(lldb::tid_t tid, + PTTraceOptions &options, + lldb::SBError &sberror) { if (m_opaque_sp == nullptr) { - sberror.SetErrorStringWithFormat("invalid PTDecoder instance"); + sberror.SetErrorStringWithFormat("invalid SBPTProcess instance"); return; } std::shared_ptr<intelpt_private::TraceOptions> trace_options_ptr( new TraceOptions()); - m_opaque_sp->GetProcessorTraceInfo(sbprocess, tid, *trace_options_ptr, - sberror); + m_opaque_sp->GetProcessorTraceInfo(tid, *trace_options_ptr, sberror); if (!sberror.Success()) return; options.SetSP(trace_options_ptr); } -lldb::SBTraceOptions PTDecoder::GetDefaultTraceOptions() { - return Decoder::GetDefaultTraceOptions(); +lldb::SBTraceOptions SBPTProcess::GetDefaultTraceOptions() { + return PTProcess::GetDefaultTraceOptions(); } Index: lldb/tools/intel-features/intel-pt/source/API/CMakeLists.txt =================================================================== --- lldb/tools/intel-features/intel-pt/source/API/CMakeLists.txt +++ lldb/tools/intel-features/intel-pt/source/API/CMakeLists.txt @@ -1,5 +1,5 @@ add_lldb_library(lldbIntelPT - PTDecoder.cpp + SBPTProcess.cpp cli-wrapper-pt.cpp LINK_LIBS Index: lldb/tools/intel-features/intel-pt/interface/SBPTProcess.i =================================================================== --- lldb/tools/intel-features/intel-pt/interface/SBPTProcess.i +++ lldb/tools/intel-features/intel-pt/interface/SBPTProcess.i @@ -7,4 +7,4 @@ %include "lldb/API/SBDefines.h" -%include "intel-pt/API/PTDecoder.h" +%include "intel-pt/API/SBPTProcess.h" Index: lldb/tools/intel-features/intel-pt/include/intel-pt/Core/PTProcess.h =================================================================== --- lldb/tools/intel-features/intel-pt/include/intel-pt/Core/PTProcess.h +++ lldb/tools/intel-features/intel-pt/include/intel-pt/Core/PTProcess.h @@ -1,4 +1,4 @@ -//===-- Decoder.h -----------------------------------------------*- C++ -*-===// +//===-- PTProcess.h ---------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_INTEL_PT_CORE_DECODER_H -#define LLDB_INTEL_PT_CORE_DECODER_H +#ifndef LLDB_INTEL_PT_CORE_PT_PROCESS_H +#define LLDB_INTEL_PT_CORE_PT_PROCESS_H // C/C++ Includes #include <map> @@ -133,9 +133,9 @@ uint32_t m_insn_log_size; }; -/// \class Decoder +/// \class PTProcess /// This class makes use of Intel(R) Processor Trace hardware feature -/// (implememted inside LLDB) to gather trace data for an inferior (being +/// (implemented inside LLDB) to gather trace data for an process (being /// debugged with LLDB) to provide meaningful information out of it. /// /// Currently the meaningful information comprises of the execution flow @@ -145,31 +145,28 @@ /// - stop the trace for a thread/process, /// - get the execution flow (assembly instructions) for a thread and /// - get trace specific information for a thread -class Decoder { +class PTProcess { public: typedef std::vector<Instruction> Instructions; - Decoder(lldb::SBDebugger &sbdebugger) - : m_mapProcessUID_mapThreadID_TraceInfo_mutex(), - m_mapProcessUID_mapThreadID_TraceInfo(), - m_debugger_user_id(sbdebugger.GetID()) {} + PTProcess(lldb::SBProcess &process) + : m_mapThreadID_TraceInfo_mutex(), m_mapThreadID_TraceInfo(), + m_process(process) {} - ~Decoder() {} + ~PTProcess() {} - void StartProcessorTrace(lldb::SBProcess &sbprocess, - lldb::SBTraceOptions &sbtraceoptions, + void StartProcessorTrace(lldb::SBTraceOptions &sbtraceoptions, lldb::SBError &sberror); - void StopProcessorTrace(lldb::SBProcess &sbprocess, lldb::SBError &sberror, + void StopProcessorTrace(lldb::SBError &sberror, lldb::tid_t tid = LLDB_INVALID_THREAD_ID); - void GetInstructionLogAtOffset(lldb::SBProcess &sbprocess, lldb::tid_t tid, - uint32_t offset, uint32_t count, - InstructionList &result_list, + void GetInstructionLogAtOffset(lldb::tid_t tid, uint32_t offset, + uint32_t count, InstructionList &result_list, lldb::SBError &sberror); - void GetProcessorTraceInfo(lldb::SBProcess &sbprocess, lldb::tid_t tid, - TraceOptions &traceinfo, lldb::SBError &sberror); + void GetProcessorTraceInfo(lldb::tid_t tid, TraceOptions &traceinfo, + lldb::SBError &sberror); static lldb::SBTraceOptions GetDefaultTraceOptions(); @@ -195,12 +192,8 @@ typedef struct pt_cpu CPUInfo; typedef std::vector<ReadExecuteSectionInfo> ReadExecuteSectionInfos; - // Check whether the provided SBProcess belongs to the same SBDebugger with - // which Decoder class instance was constructed. - void CheckDebuggerID(lldb::SBProcess &sbprocess, lldb::SBError &sberror); - - // Function to remove entries of finished processes/threads in the class - void RemoveDeadProcessesAndThreads(lldb::SBProcess &sbprocess); + // Function to remove entries of finished threads in the class + void RemoveDeadThreads(); // Parse cpu information from trace configuration received from LLDB void ParseCPUInfo(CPUInfo &pt_cpu, lldb::SBStructuredData &s, @@ -213,27 +206,23 @@ /// - fetches trace and other necessary information from LLDB (using /// ReadTraceDataAndImageInfo()) and decodes the trace (using /// DecodeProcessorTrace()) - void FetchAndDecode(lldb::SBProcess &sbprocess, lldb::tid_t tid, - lldb::SBError &sberror, + void FetchAndDecode(lldb::tid_t tid, lldb::SBError &sberror, ThreadTraceInfo **threadTraceInfo); // Helper function of FetchAndDecode() to get raw trace data and memory image // info of inferior from LLDB - void ReadTraceDataAndImageInfo(lldb::SBProcess &sbprocess, lldb::tid_t tid, - lldb::SBError &sberror, + void ReadTraceDataAndImageInfo(lldb::tid_t tid, lldb::SBError &sberror, ThreadTraceInfo &threadTraceInfo); // Helper function of FetchAndDecode() to initialize raw trace decoder and // start trace decoding - void DecodeProcessorTrace(lldb::SBProcess &sbprocess, lldb::tid_t tid, - lldb::SBError &sberror, + void DecodeProcessorTrace(lldb::tid_t tid, lldb::SBError &sberror, ThreadTraceInfo &threadTraceInfo); // Helper function of ReadTraceDataAndImageInfo() function for gathering // inferior's memory image info along with all dynamic libraries linked with // it - void GetTargetModulesInfo(lldb::SBTarget &sbtarget, - ReadExecuteSectionInfos &readExecuteSectionInfos, + void GetTargetModulesInfo(ReadExecuteSectionInfos &readExecuteSectionInfos, lldb::SBError &sberror); /// Helper functions of DecodeProcessorTrace() function for: @@ -298,8 +287,6 @@ void SetUniqueTraceInstance(lldb::SBTrace &trace) { m_trace = trace; } - friend class Decoder; - private: Buffer m_pt_buffer; // raw trace buffer ReadExecuteSectionInfos @@ -310,18 +297,15 @@ Instructions m_instruction_log; // complete instruction log }; - typedef std::map<lldb::user_id_t, ThreadTraceInfo> MapThreadID_TraceInfo; - typedef std::map<uint32_t, MapThreadID_TraceInfo> - MapProcessUID_MapThreadID_TraceInfo; - - std::mutex m_mapProcessUID_mapThreadID_TraceInfo_mutex; - MapProcessUID_MapThreadID_TraceInfo - m_mapProcessUID_mapThreadID_TraceInfo; // to store trace information for - // each process and its associated - // threads - lldb::user_id_t m_debugger_user_id; // SBDebugger instance which is associated - // to this Decoder instance + // typedef std::map<lldb::user_id_t, ThreadTraceInfo> MapThreadID_TraceInfo; + // typedef std::map<uint32_t, MapThreadID_TraceInfo> + // MapProcessUID_MapThreadID_TraceInfo; + + std::mutex m_mapThreadID_TraceInfo_mutex; + std::map<lldb::tid_t, ThreadTraceInfo> m_mapThreadID_TraceInfo; + + lldb::SBProcess m_process; }; } // namespace intelpt_private -#endif // LLDB_INTEL_PT_CORE_DECODER_H +#endif // LLDB_INTEL_PT_CORE_PT_PROCESS_H Index: lldb/tools/intel-features/intel-pt/include/intel-pt/API/cli-wrapper-pt.h =================================================================== --- lldb/tools/intel-features/intel-pt/include/intel-pt/API/cli-wrapper-pt.h +++ lldb/tools/intel-features/intel-pt/include/intel-pt/API/cli-wrapper-pt.h @@ -4,7 +4,7 @@ // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // -// CLI Wrapper of PTDecoder Tool to enable it to be used through LLDB's CLI. +// CLI Wrapper of PTProcess Tool to enable it to be used through LLDB's CLI. //===----------------------------------------------------------------------===// #include "lldb/API/SBDebugger.h" Index: lldb/tools/intel-features/intel-pt/include/intel-pt/API/SBPTProcess.h =================================================================== --- lldb/tools/intel-features/intel-pt/include/intel-pt/API/SBPTProcess.h +++ lldb/tools/intel-features/intel-pt/include/intel-pt/API/SBPTProcess.h @@ -1,4 +1,4 @@ -//===-- PTDecoder.h ---------------------------------------------*- C++ -*-===// +//===-- SBPTProcess.h ------------------------------------*- C++ -*--------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_INTEL_PT_API_PT_DECODER_H -#define LLDB_INTEL_PT_API_PT_DECODER_H +#ifndef LLDB_INTEL_PT_API_SB_PT_PROCESS_H +#define LLDB_INTEL_PT_API_SB_PT_PROCESS_H // C/C++ Includes #include <vector> @@ -24,7 +24,7 @@ class Instruction; class InstructionList; class TraceOptions; -class Decoder; +class PTProcess; } // namespace intelpt_private namespace intelpt { @@ -89,7 +89,7 @@ void Clear(); private: - friend class PTDecoder; + friend class SBPTProcess; void SetSP(const std::shared_ptr<intelpt_private::InstructionList> &ptr); @@ -119,14 +119,14 @@ lldb::SBStructuredData GetTraceParams(lldb::SBError &error); private: - friend class PTDecoder; + friend class SBPTProcess; void SetSP(const std::shared_ptr<intelpt_private::TraceOptions> &ptr); std::shared_ptr<intelpt_private::TraceOptions> m_opaque_sp; }; -/// \class PTDecoder +/// \class PTProcess /// This class makes use of Intel(R) Processor Trace hardware feature /// (implememted inside LLDB) to gather trace data for an inferior (being /// debugged with LLDB) to provide meaningful information out of it. @@ -138,17 +138,15 @@ /// - stop the trace for a thread/process, /// - get the execution flow (assembly instructions) for a thread and /// - get trace specific information for a thread -class PTDecoder { +class SBPTProcess { public: - PTDecoder(lldb::SBDebugger &sbdebugger); + SBPTProcess(lldb::SBProcess &process); + + SBPTProcess(); /// Start Intel(R) Processor Trace on a thread or complete process with /// Intel(R) Processor Trace specific configuration options /// - /// \param[in] sbprocess - /// A valid process on which this operation will be performed. An error is - /// returned in case of an invalid process. - /// /// \param[in] sbtraceoptions /// Contains thread id information and configuration options: /// @@ -180,16 +178,11 @@ /// /// \param[out] sberror /// An error with the failure reason if API fails. Else success. - void StartProcessorTrace(lldb::SBProcess &sbprocess, - lldb::SBTraceOptions &sbtraceoptions, + void StartProcessorTrace(lldb::SBTraceOptions &sbtraceoptions, lldb::SBError &sberror); /// Stop Intel(R) Processor Trace on a thread or complete process. /// - /// \param[in] sbprocess - /// A valid process on which this operation will be performed. An error is - /// returned in case of an invalid process. - /// /// \param[in] tid /// Case 1: To stop tracing a single thread, provide a valid thread id. If /// sbprocess doesn't contain the thread tid, error will be returned. @@ -198,16 +191,12 @@ /// /// \param[out] sberror /// An error with the failure reason if API fails. Else success. - void StopProcessorTrace(lldb::SBProcess &sbprocess, lldb::SBError &sberror, + void StopProcessorTrace(lldb::SBError &sberror, lldb::tid_t tid = LLDB_INVALID_THREAD_ID); /// Get instruction log containing the execution flow for a thread of a /// process in terms of assembly instructions executed. /// - /// \param[in] sbprocess - /// A valid process on which this operation will be performed. An error is - /// returned in case of an invalid process. - /// /// \param[in] tid /// A valid thread id of the thread for which instruction log is desired. /// If sbprocess doesn't contain the thread tid, error will be returned. @@ -234,19 +223,14 @@ /// /// \param[out] sberror /// An error with the failure reason if API fails. Else success. - void GetInstructionLogAtOffset(lldb::SBProcess &sbprocess, lldb::tid_t tid, - uint32_t offset, uint32_t count, - PTInstructionList &result_list, + void GetInstructionLogAtOffset(lldb::tid_t tid, uint32_t offset, + uint32_t count, PTInstructionList &result_list, lldb::SBError &sberror); /// Get Intel(R) Processor Trace specific information for a thread of a /// process. The information contains the actual configuration options with /// which the trace was started for this thread. /// - /// \param[in] sbprocess - /// A valid process on which this operation will be performed. An error is - /// returned in case of an invalid process. - /// /// \param[in] tid /// A valid thread id of the thread for which the trace specific /// information is required. If sbprocess doesn't contain the thread tid, @@ -259,12 +243,12 @@ /// /// \param[out] sberror /// An error with the failure reason if API fails. Else success. - void GetProcessorTraceInfo(lldb::SBProcess &sbprocess, lldb::tid_t tid, - PTTraceOptions &options, lldb::SBError &sberror); + void GetProcessorTraceInfo(lldb::tid_t tid, PTTraceOptions &options, + lldb::SBError &sberror); /// Get an instance of an \a lldb::SBTraceOptions object with a default /// configuration for tracing with Intel(R) Processor Trace. This object - /// is ready to be passed as argument to \a PTDecoder::StartProcessorTrace. + /// is ready to be passed as argument to \a SBPTProcess::StartProcessorTrace. /// /// The default configuration sets 4096 bytes as trace buffer size per thread. /// Besides, this configuration traces all the running threads of the target @@ -276,8 +260,8 @@ static lldb::SBTraceOptions GetDefaultTraceOptions(); private: - std::shared_ptr<intelpt_private::Decoder> m_opaque_sp; + std::shared_ptr<intelpt_private::PTProcess> m_opaque_sp; }; } // namespace intelpt -#endif // LLDB_INTEL_PT_API_PT_DECODER_H +#endif // LLDB_INTEL_PT_API_SB_PT_PROCESS_H Index: lldb/test/API/tools/intel-features/intel-pt/test/TestIntelPTSimpleBinary.py =================================================================== --- lldb/test/API/tools/intel-features/intel-pt/test/TestIntelPTSimpleBinary.py +++ lldb/test/API/tools/intel-features/intel-pt/test/TestIntelPTSimpleBinary.py @@ -95,19 +95,19 @@ # We will start tracing from main lldbutil.run_to_name_breakpoint(self, "main", exe_name=exe) - decoder = lldbIntelFeatures.PTDecoder(self.dbg) - target = self.dbg.GetSelectedTarget() process = target.GetProcess() tid = process.GetProcessID() + ptprocess = lldbIntelFeatures.SBPTProcess(process) + # We configure the tracing options - trace_opts = lldbIntelFeatures.PTDecoder.GetDefaultTraceOptions() + trace_opts = lldbIntelFeatures.SBPTProcess.GetDefaultTraceOptions() trace_opts.setThreadID(tid) # We start tracing error = lldb.SBError() - decoder.StartProcessorTrace(process, trace_opts, error) + ptprocess.StartProcessorTrace(trace_opts, error) self.assertSuccess(error) # We check the trace after the for loop @@ -117,8 +117,8 @@ # We'll check repeteadly until the trace is available def getInstructions(): instruction_list = lldbIntelFeatures.PTInstructionList() - decoder.GetInstructionLogAtOffset( - process, tid, offset=99, count=100, result_list=instruction_list, sberror=error) + ptprocess.GetInstructionLogAtOffset( + tid, offset=99, count=100, result_list=instruction_list, sberror=error) if error.Fail() or instruction_list.GetSize() == 0: return None return instruction_list @@ -133,5 +133,5 @@ self.assertIn(self.find_start_address_of_function(target, "fun"), addresses) # We assert stopping the trace works - decoder.StopProcessorTrace(process, error, tid) + ptprocess.StopProcessorTrace(error, tid) self.assertSuccess(error)
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits