[trace][intelpt] Support system-wide tracing [2] - Add a dummy --per-core-tracing option
This updates the documentation of the gdb-remote protocol, as well as the help messages, to include the new --per-core-tracing option. Differential Revision: https://reviews.llvm.org/D124640
This commit is contained in:
parent
67d0bc27c0
commit
b8d1776fc5
|
@ -283,7 +283,7 @@ read packet: {"name":<name>, "description":<description>}/E<error code>;AAAAAAAA
|
||||||
// Tracing technology name, e.g. intel-pt, arm-coresight.
|
// Tracing technology name, e.g. intel-pt, arm-coresight.
|
||||||
//
|
//
|
||||||
// /* thread tracing only */
|
// /* thread tracing only */
|
||||||
// "tids": [<decimal integer>],
|
// "tids"?: [<decimal integer>],
|
||||||
// Individual threads to trace.
|
// Individual threads to trace.
|
||||||
//
|
//
|
||||||
// ... other parameters specific to the provided tracing type
|
// ... other parameters specific to the provided tracing type
|
||||||
|
@ -298,16 +298,25 @@ read packet: {"name":<name>, "description":<description>}/E<error code>;AAAAAAAA
|
||||||
// INTEL-PT
|
// INTEL-PT
|
||||||
// intel-pt supports both "thread tracing" and "process tracing".
|
// intel-pt supports both "thread tracing" and "process tracing".
|
||||||
//
|
//
|
||||||
// "Process tracing" is implemented by tracing each thread individually, but
|
// "Process tracing" is implemented in two different ways. If the
|
||||||
// managed by the same "process trace" instance.
|
// "perCoreTracing" option is false, then each thread is traced individually
|
||||||
// Each actual thread trace, either from "process tracing" or "thread tracing",
|
// but managed by the same "process trace" instance. This means that the
|
||||||
|
// amount of trace buffers used is proportional to the number of running
|
||||||
|
// threads. This is the recommended option unless the number of threads is
|
||||||
|
// huge. If "perCoreTracing" is true, then each cpu core is traced invidually
|
||||||
|
// instead of each thread, which uses a fixed number of trace buffers, but
|
||||||
|
// might result in less data available for less frequent threads. See
|
||||||
|
// "perCoreTracing" below for more information.
|
||||||
|
//
|
||||||
|
// Each actual trace buffer, either from "process tracing" or "thread tracing",
|
||||||
// is stored in an in-memory circular buffer, which keeps the most recent data.
|
// is stored in an in-memory circular buffer, which keeps the most recent data.
|
||||||
//
|
//
|
||||||
// Additional params in the input schema:
|
// Additional params in the input schema:
|
||||||
// {
|
// {
|
||||||
// "threadBufferSize": <decimal integer>,
|
// "traceBufferSize": <decimal integer>,
|
||||||
// Trace buffer size per thread in bytes. It must be a power of 2
|
// Size in bytes used by each individual per-thread or per-core trace
|
||||||
// greater than or equal to 4096 (2^12) bytes.
|
// buffer. It must be a power of 2 greater than or equal to 4096 (2^12)
|
||||||
|
// bytes.
|
||||||
//
|
//
|
||||||
// "enableTsc": <boolean>,
|
// "enableTsc": <boolean>,
|
||||||
// Whether to enable TSC timestamps or not. This is supported on
|
// Whether to enable TSC timestamps or not. This is supported on
|
||||||
|
@ -342,15 +351,35 @@ read packet: {"name":<name>, "description":<description>}/E<error code>;AAAAAAAA
|
||||||
// 0 if supported.
|
// 0 if supported.
|
||||||
//
|
//
|
||||||
// /* process tracing only */
|
// /* process tracing only */
|
||||||
|
// "perCoreTracing": <boolean>
|
||||||
|
// Instead of having an individual trace buffer per thread, this option
|
||||||
|
// triggers the collection on a per cpu core basis. This effectively
|
||||||
|
// traces the entire activity on all cores. At decoding time, in order
|
||||||
|
// to correctly associate a decoded instruction with a thread, the
|
||||||
|
// context switch trace of each core is needed, as well as a record per
|
||||||
|
// cpu indicating which thread was running on each core when tracing
|
||||||
|
// started. These secondary traces are correlated with the intel-pt
|
||||||
|
// trace by comparing TSC timestamps.
|
||||||
|
//
|
||||||
|
// This option forces the capture of TSC timestamps (see "enableTsc").
|
||||||
|
//
|
||||||
|
// Note: This option can't be used simulatenously with any other trace
|
||||||
|
// sessions because of its system-wide nature.
|
||||||
|
//
|
||||||
|
// /* process tracing only */
|
||||||
// "processBufferSizeLimit": <decimal integer>,
|
// "processBufferSizeLimit": <decimal integer>,
|
||||||
// Maximum total buffer size per process in bytes.
|
// Maximum total buffer size per process in bytes.
|
||||||
// This limit applies to the sum of the sizes of all trace buffers for
|
// This limit applies to the sum of the sizes of all trace buffers for
|
||||||
// the current process, excluding the ones started with "thread tracing".
|
// the current process, excluding the ones started with "thread tracing".
|
||||||
//
|
//
|
||||||
// Whenever a thread is attempted to be traced due to "process tracing"
|
// If "perCoreTracing" is false, whenever a thread is attempted to be
|
||||||
// and the limit would be reached, the process is stopped with a
|
// traced due to "process tracing" and the limit would be reached, the
|
||||||
// "tracing" reason along with a meaningful description, so that the
|
// process is stopped with a "tracing" reason along with a meaningful
|
||||||
// user can retrace the process if needed.
|
// description, so that the user can retrace the process if needed.
|
||||||
|
//
|
||||||
|
// If "perCoreTracing" is true, then starting the system-wide trace
|
||||||
|
// session fails if all the individual per-core trace buffers require
|
||||||
|
// in total more memory that the limit impossed by this parameter.
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Notes:
|
// Notes:
|
||||||
|
|
|
@ -28,20 +28,23 @@ struct IntelPTDataKinds {
|
||||||
/// \{
|
/// \{
|
||||||
struct TraceIntelPTStartRequest : TraceStartRequest {
|
struct TraceIntelPTStartRequest : TraceStartRequest {
|
||||||
/// Size in bytes to use for each thread's trace buffer.
|
/// Size in bytes to use for each thread's trace buffer.
|
||||||
int64_t threadBufferSize;
|
int64_t trace_buffer_size;
|
||||||
|
|
||||||
/// Whether to enable TSC
|
/// Whether to enable TSC
|
||||||
bool enableTsc;
|
bool enable_tsc;
|
||||||
|
|
||||||
/// PSB packet period
|
/// PSB packet period
|
||||||
llvm::Optional<int64_t> psbPeriod;
|
llvm::Optional<int64_t> psb_period;
|
||||||
|
|
||||||
/// Required when doing "process tracing".
|
/// Required when doing "process tracing".
|
||||||
///
|
///
|
||||||
/// Limit in bytes on all the thread traces started by this "process trace"
|
/// Limit in bytes on all the thread traces started by this "process trace"
|
||||||
/// instance. When a thread is about to be traced and the limit would be hit,
|
/// instance. When a thread is about to be traced and the limit would be hit,
|
||||||
/// then a "tracing" stop event is triggered.
|
/// then a "tracing" stop event is triggered.
|
||||||
llvm::Optional<int64_t> processBufferSizeLimit;
|
llvm::Optional<int64_t> process_buffer_size_limit;
|
||||||
|
|
||||||
|
/// Whether to have a trace buffer per thread or per cpu core.
|
||||||
|
llvm::Optional<bool> per_core_tracing;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool fromJSON(const llvm::json::Value &value, TraceIntelPTStartRequest &packet,
|
bool fromJSON(const llvm::json::Value &value, TraceIntelPTStartRequest &packet,
|
||||||
|
|
|
@ -45,37 +45,38 @@ class TraceIntelPTTestCaseBase(TestBase):
|
||||||
else:
|
else:
|
||||||
self.assertSuccess(sberror)
|
self.assertSuccess(sberror)
|
||||||
|
|
||||||
def createConfiguration(self, threadBufferSize=None,
|
def createConfiguration(self, traceBufferSize=None,
|
||||||
processBufferSizeLimit=None, enableTsc=False,
|
processBufferSizeLimit=None, enableTsc=False,
|
||||||
psbPeriod=None):
|
psbPeriod=None, perCoreTracing=False):
|
||||||
obj = {}
|
obj = {}
|
||||||
if processBufferSizeLimit is not None:
|
if processBufferSizeLimit is not None:
|
||||||
obj["processBufferSizeLimit"] = processBufferSizeLimit
|
obj["processBufferSizeLimit"] = processBufferSizeLimit
|
||||||
if threadBufferSize is not None:
|
if traceBufferSize is not None:
|
||||||
obj["threadBufferSize"] = threadBufferSize
|
obj["traceBufferSize"] = traceBufferSize
|
||||||
if psbPeriod is not None:
|
if psbPeriod is not None:
|
||||||
obj["psbPeriod"] = psbPeriod
|
obj["psbPeriod"] = psbPeriod
|
||||||
obj["enableTsc"] = enableTsc
|
obj["enableTsc"] = enableTsc
|
||||||
|
obj["perCoreTracing"] = perCoreTracing
|
||||||
|
|
||||||
configuration = lldb.SBStructuredData()
|
configuration = lldb.SBStructuredData()
|
||||||
configuration.SetFromJSON(json.dumps(obj))
|
configuration.SetFromJSON(json.dumps(obj))
|
||||||
return configuration
|
return configuration
|
||||||
|
|
||||||
def traceStartThread(self, thread=None, error=False, substrs=None,
|
def traceStartThread(self, thread=None, error=False, substrs=None,
|
||||||
threadBufferSize=None, enableTsc=False, psbPeriod=None):
|
traceBufferSize=None, enableTsc=False, psbPeriod=None):
|
||||||
if self.USE_SB_API:
|
if self.USE_SB_API:
|
||||||
trace = self.getTraceOrCreate()
|
trace = self.getTraceOrCreate()
|
||||||
thread = thread if thread is not None else self.thread()
|
thread = thread if thread is not None else self.thread()
|
||||||
configuration = self.createConfiguration(
|
configuration = self.createConfiguration(
|
||||||
threadBufferSize=threadBufferSize, enableTsc=enableTsc,
|
traceBufferSize=traceBufferSize, enableTsc=enableTsc,
|
||||||
psbPeriod=psbPeriod)
|
psbPeriod=psbPeriod)
|
||||||
self.assertSBError(trace.Start(thread, configuration), error)
|
self.assertSBError(trace.Start(thread, configuration), error)
|
||||||
else:
|
else:
|
||||||
command = "thread trace start"
|
command = "thread trace start"
|
||||||
if thread is not None:
|
if thread is not None:
|
||||||
command += " " + str(thread.GetIndexID())
|
command += " " + str(thread.GetIndexID())
|
||||||
if threadBufferSize is not None:
|
if traceBufferSize is not None:
|
||||||
command += " -s " + str(threadBufferSize)
|
command += " -s " + str(traceBufferSize)
|
||||||
if enableTsc:
|
if enableTsc:
|
||||||
command += " --tsc"
|
command += " --tsc"
|
||||||
if psbPeriod is not None:
|
if psbPeriod is not None:
|
||||||
|
@ -83,12 +84,13 @@ class TraceIntelPTTestCaseBase(TestBase):
|
||||||
self.expect(command, error=error, substrs=substrs)
|
self.expect(command, error=error, substrs=substrs)
|
||||||
|
|
||||||
def traceStartProcess(self, processBufferSizeLimit=None, error=False,
|
def traceStartProcess(self, processBufferSizeLimit=None, error=False,
|
||||||
substrs=None, enableTsc=False, psbPeriod=None):
|
substrs=None, enableTsc=False, psbPeriod=None,
|
||||||
|
perCoreTracing=False):
|
||||||
if self.USE_SB_API:
|
if self.USE_SB_API:
|
||||||
trace = self.getTraceOrCreate()
|
trace = self.getTraceOrCreate()
|
||||||
configuration = self.createConfiguration(
|
configuration = self.createConfiguration(
|
||||||
processBufferSizeLimit=processBufferSizeLimit, enableTsc=enableTsc,
|
processBufferSizeLimit=processBufferSizeLimit, enableTsc=enableTsc,
|
||||||
psbPeriod=psbPeriod)
|
psbPeriod=psbPeriod, perCoreTracing=perCoreTracing)
|
||||||
self.assertSBError(trace.Start(configuration), error=error)
|
self.assertSBError(trace.Start(configuration), error=error)
|
||||||
else:
|
else:
|
||||||
command = "process trace start"
|
command = "process trace start"
|
||||||
|
@ -98,6 +100,8 @@ class TraceIntelPTTestCaseBase(TestBase):
|
||||||
command += " --tsc"
|
command += " --tsc"
|
||||||
if psbPeriod is not None:
|
if psbPeriod is not None:
|
||||||
command += " --psb-period " + str(psbPeriod)
|
command += " --psb-period " + str(psbPeriod)
|
||||||
|
if perCoreTracing:
|
||||||
|
command += " --per-core-tracing"
|
||||||
self.expect(command, error=error, substrs=substrs)
|
self.expect(command, error=error, substrs=substrs)
|
||||||
|
|
||||||
def traceStopProcess(self):
|
def traceStopProcess(self):
|
||||||
|
|
|
@ -443,8 +443,8 @@ Error IntelPTThreadTraceCollection::TraceStart(
|
||||||
"Thread %" PRIu64 " already traced", tid);
|
"Thread %" PRIu64 " already traced", tid);
|
||||||
|
|
||||||
Expected<IntelPTThreadTraceUP> trace_up = IntelPTThreadTrace::Create(
|
Expected<IntelPTThreadTraceUP> trace_up = IntelPTThreadTrace::Create(
|
||||||
m_pid, tid, request.threadBufferSize, request.enableTsc,
|
m_pid, tid, request.trace_buffer_size, request.enable_tsc,
|
||||||
request.psbPeriod.map([](int64_t period) { return (size_t)period; }));
|
request.psb_period.map([](int64_t period) { return (size_t)period; }));
|
||||||
if (!trace_up)
|
if (!trace_up)
|
||||||
return trace_up.takeError();
|
return trace_up.takeError();
|
||||||
|
|
||||||
|
@ -490,8 +490,9 @@ Error IntelPTProcessTrace::TraceStop(lldb::tid_t tid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Error IntelPTProcessTrace::TraceStart(lldb::tid_t tid) {
|
Error IntelPTProcessTrace::TraceStart(lldb::tid_t tid) {
|
||||||
if (m_thread_traces.GetTotalBufferSize() + m_tracing_params.threadBufferSize >
|
if (m_thread_traces.GetTotalBufferSize() +
|
||||||
static_cast<size_t>(*m_tracing_params.processBufferSizeLimit))
|
m_tracing_params.trace_buffer_size >
|
||||||
|
static_cast<size_t>(*m_tracing_params.process_buffer_size_limit))
|
||||||
return createStringError(
|
return createStringError(
|
||||||
inconvertibleErrorCode(),
|
inconvertibleErrorCode(),
|
||||||
"Thread %" PRIu64 " can't be traced as the process trace size limit "
|
"Thread %" PRIu64 " can't be traced as the process trace size limit "
|
||||||
|
@ -548,6 +549,10 @@ Error IntelPTCollector::TraceStart(
|
||||||
inconvertibleErrorCode(),
|
inconvertibleErrorCode(),
|
||||||
"Process currently traced. Stop process tracing first");
|
"Process currently traced. Stop process tracing first");
|
||||||
}
|
}
|
||||||
|
if (request.per_core_tracing.getValueOr(false)) {
|
||||||
|
return createStringError(inconvertibleErrorCode(),
|
||||||
|
"Per-core tracing is not supported.");
|
||||||
|
}
|
||||||
m_process_trace = IntelPTProcessTrace(m_pid, request);
|
m_process_trace = IntelPTProcessTrace(m_pid, request);
|
||||||
|
|
||||||
Error error = Error::success();
|
Error error = Error::success();
|
||||||
|
|
|
@ -32,13 +32,13 @@ Status CommandObjectThreadTraceStartIntelPT::CommandOptions::SetOptionValue(
|
||||||
|
|
||||||
switch (short_option) {
|
switch (short_option) {
|
||||||
case 's': {
|
case 's': {
|
||||||
int64_t thread_buffer_size;
|
int64_t trace_buffer_size;
|
||||||
if (option_arg.empty() || option_arg.getAsInteger(0, thread_buffer_size) ||
|
if (option_arg.empty() || option_arg.getAsInteger(0, trace_buffer_size) ||
|
||||||
thread_buffer_size < 0)
|
trace_buffer_size < 0)
|
||||||
error.SetErrorStringWithFormat("invalid integer value for option '%s'",
|
error.SetErrorStringWithFormat("invalid integer value for option '%s'",
|
||||||
option_arg.str().c_str());
|
option_arg.str().c_str());
|
||||||
else
|
else
|
||||||
m_thread_buffer_size = thread_buffer_size;
|
m_trace_buffer_size = trace_buffer_size;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 't': {
|
case 't': {
|
||||||
|
@ -63,7 +63,7 @@ Status CommandObjectThreadTraceStartIntelPT::CommandOptions::SetOptionValue(
|
||||||
|
|
||||||
void CommandObjectThreadTraceStartIntelPT::CommandOptions::
|
void CommandObjectThreadTraceStartIntelPT::CommandOptions::
|
||||||
OptionParsingStarting(ExecutionContext *execution_context) {
|
OptionParsingStarting(ExecutionContext *execution_context) {
|
||||||
m_thread_buffer_size = kDefaultThreadBufferSize;
|
m_trace_buffer_size = kDefaultTraceBufferSize;
|
||||||
m_enable_tsc = kDefaultEnableTscValue;
|
m_enable_tsc = kDefaultEnableTscValue;
|
||||||
m_psb_period = kDefaultPsbPeriod;
|
m_psb_period = kDefaultPsbPeriod;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ CommandObjectThreadTraceStartIntelPT::CommandOptions::GetDefinitions() {
|
||||||
bool CommandObjectThreadTraceStartIntelPT::DoExecuteOnThreads(
|
bool CommandObjectThreadTraceStartIntelPT::DoExecuteOnThreads(
|
||||||
Args &command, CommandReturnObject &result,
|
Args &command, CommandReturnObject &result,
|
||||||
llvm::ArrayRef<lldb::tid_t> tids) {
|
llvm::ArrayRef<lldb::tid_t> tids) {
|
||||||
if (Error err = m_trace.Start(tids, m_options.m_thread_buffer_size,
|
if (Error err = m_trace.Start(tids, m_options.m_trace_buffer_size,
|
||||||
m_options.m_enable_tsc, m_options.m_psb_period))
|
m_options.m_enable_tsc, m_options.m_psb_period))
|
||||||
result.SetError(Status(std::move(err)));
|
result.SetError(Status(std::move(err)));
|
||||||
else
|
else
|
||||||
|
@ -98,13 +98,13 @@ Status CommandObjectProcessTraceStartIntelPT::CommandOptions::SetOptionValue(
|
||||||
|
|
||||||
switch (short_option) {
|
switch (short_option) {
|
||||||
case 's': {
|
case 's': {
|
||||||
int64_t thread_buffer_size;
|
int64_t trace_buffer_size;
|
||||||
if (option_arg.empty() || option_arg.getAsInteger(0, thread_buffer_size) ||
|
if (option_arg.empty() || option_arg.getAsInteger(0, trace_buffer_size) ||
|
||||||
thread_buffer_size < 0)
|
trace_buffer_size < 0)
|
||||||
error.SetErrorStringWithFormat("invalid integer value for option '%s'",
|
error.SetErrorStringWithFormat("invalid integer value for option '%s'",
|
||||||
option_arg.str().c_str());
|
option_arg.str().c_str());
|
||||||
else
|
else
|
||||||
m_thread_buffer_size = thread_buffer_size;
|
m_trace_buffer_size = trace_buffer_size;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'l': {
|
case 'l': {
|
||||||
|
@ -122,6 +122,10 @@ Status CommandObjectProcessTraceStartIntelPT::CommandOptions::SetOptionValue(
|
||||||
m_enable_tsc = true;
|
m_enable_tsc = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'c': {
|
||||||
|
m_per_core_tracing = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'p': {
|
case 'p': {
|
||||||
int64_t psb_period;
|
int64_t psb_period;
|
||||||
if (option_arg.empty() || option_arg.getAsInteger(0, psb_period) ||
|
if (option_arg.empty() || option_arg.getAsInteger(0, psb_period) ||
|
||||||
|
@ -140,10 +144,11 @@ Status CommandObjectProcessTraceStartIntelPT::CommandOptions::SetOptionValue(
|
||||||
|
|
||||||
void CommandObjectProcessTraceStartIntelPT::CommandOptions::
|
void CommandObjectProcessTraceStartIntelPT::CommandOptions::
|
||||||
OptionParsingStarting(ExecutionContext *execution_context) {
|
OptionParsingStarting(ExecutionContext *execution_context) {
|
||||||
m_thread_buffer_size = kDefaultThreadBufferSize;
|
m_trace_buffer_size = kDefaultTraceBufferSize;
|
||||||
m_process_buffer_size_limit = kDefaultProcessBufferSizeLimit;
|
m_process_buffer_size_limit = kDefaultProcessBufferSizeLimit;
|
||||||
m_enable_tsc = kDefaultEnableTscValue;
|
m_enable_tsc = kDefaultEnableTscValue;
|
||||||
m_psb_period = kDefaultPsbPeriod;
|
m_psb_period = kDefaultPsbPeriod;
|
||||||
|
m_per_core_tracing = kDefaultPerCoreTracing;
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::ArrayRef<OptionDefinition>
|
llvm::ArrayRef<OptionDefinition>
|
||||||
|
@ -153,9 +158,10 @@ CommandObjectProcessTraceStartIntelPT::CommandOptions::GetDefinitions() {
|
||||||
|
|
||||||
bool CommandObjectProcessTraceStartIntelPT::DoExecute(
|
bool CommandObjectProcessTraceStartIntelPT::DoExecute(
|
||||||
Args &command, CommandReturnObject &result) {
|
Args &command, CommandReturnObject &result) {
|
||||||
if (Error err = m_trace.Start(m_options.m_thread_buffer_size,
|
if (Error err = m_trace.Start(m_options.m_trace_buffer_size,
|
||||||
m_options.m_process_buffer_size_limit,
|
m_options.m_process_buffer_size_limit,
|
||||||
m_options.m_enable_tsc, m_options.m_psb_period))
|
m_options.m_enable_tsc, m_options.m_psb_period,
|
||||||
|
m_options.m_per_core_tracing))
|
||||||
result.SetError(Status(std::move(err)));
|
result.SetError(Status(std::move(err)));
|
||||||
else
|
else
|
||||||
result.SetStatus(eReturnStatusSuccessFinishResult);
|
result.SetStatus(eReturnStatusSuccessFinishResult);
|
||||||
|
|
|
@ -31,7 +31,7 @@ public:
|
||||||
|
|
||||||
llvm::ArrayRef<OptionDefinition> GetDefinitions() override;
|
llvm::ArrayRef<OptionDefinition> GetDefinitions() override;
|
||||||
|
|
||||||
size_t m_thread_buffer_size;
|
size_t m_trace_buffer_size;
|
||||||
bool m_enable_tsc;
|
bool m_enable_tsc;
|
||||||
llvm::Optional<size_t> m_psb_period;
|
llvm::Optional<size_t> m_psb_period;
|
||||||
};
|
};
|
||||||
|
@ -74,10 +74,11 @@ public:
|
||||||
|
|
||||||
llvm::ArrayRef<OptionDefinition> GetDefinitions() override;
|
llvm::ArrayRef<OptionDefinition> GetDefinitions() override;
|
||||||
|
|
||||||
size_t m_thread_buffer_size;
|
size_t m_trace_buffer_size;
|
||||||
size_t m_process_buffer_size_limit;
|
size_t m_process_buffer_size_limit;
|
||||||
bool m_enable_tsc;
|
bool m_enable_tsc;
|
||||||
llvm::Optional<size_t> m_psb_period;
|
llvm::Optional<size_t> m_psb_period;
|
||||||
|
bool m_per_core_tracing;
|
||||||
};
|
};
|
||||||
|
|
||||||
CommandObjectProcessTraceStartIntelPT(TraceIntelPT &trace,
|
CommandObjectProcessTraceStartIntelPT(TraceIntelPT &trace,
|
||||||
|
@ -85,10 +86,14 @@ public:
|
||||||
: CommandObjectParsed(
|
: CommandObjectParsed(
|
||||||
interpreter, "process trace start",
|
interpreter, "process trace start",
|
||||||
"Start tracing this process with intel-pt, including future "
|
"Start tracing this process with intel-pt, including future "
|
||||||
"threads. "
|
"threads. If --per-core-tracing is not provided, this traces each "
|
||||||
"This is implemented by tracing each thread independently. "
|
"thread independently, thus using a trace buffer per thread. "
|
||||||
"Threads traced with the \"thread trace start\" command are left "
|
"Threads traced with the \"thread trace start\" command are left "
|
||||||
"unaffected ant not retraced.",
|
"unaffected ant not retraced. This is the recommended option "
|
||||||
|
"unless the number of threads is huge. If --per-core-tracing is "
|
||||||
|
"passed, each cpu core is traced instead of each thread, which "
|
||||||
|
"uses a fixed number of trace buffers, but might result in less "
|
||||||
|
"data available for less frequent threads.",
|
||||||
"process trace start [<intel-pt-options>]",
|
"process trace start [<intel-pt-options>]",
|
||||||
lldb::eCommandRequiresProcess | lldb::eCommandTryTargetAPILock |
|
lldb::eCommandRequiresProcess | lldb::eCommandTryTargetAPILock |
|
||||||
lldb::eCommandProcessMustBeLaunched |
|
lldb::eCommandProcessMustBeLaunched |
|
||||||
|
|
|
@ -271,101 +271,79 @@ bool TraceIntelPT::IsTraced(lldb::tid_t tid) {
|
||||||
// documentation file. Similarly, it should match the CLI help messages of the
|
// documentation file. Similarly, it should match the CLI help messages of the
|
||||||
// TraceIntelPTOptions.td file.
|
// TraceIntelPTOptions.td file.
|
||||||
const char *TraceIntelPT::GetStartConfigurationHelp() {
|
const char *TraceIntelPT::GetStartConfigurationHelp() {
|
||||||
return R"(Parameters:
|
static Optional<std::string> message;
|
||||||
|
if (!message) {
|
||||||
|
message.emplace(formatv(R"(Parameters:
|
||||||
|
|
||||||
Note: If a parameter is not specified, a default value will be used.
|
See the jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt for a
|
||||||
|
description of each parameter below.
|
||||||
|
|
||||||
- int threadBufferSize (defaults to 4096 bytes):
|
- int traceBufferSize (defaults to {0} bytes):
|
||||||
[process and thread tracing]
|
[process and thread tracing]
|
||||||
Trace size in bytes per thread. It must be a power of 2 greater
|
|
||||||
than or equal to 4096 (2^12). The trace is circular keeping the
|
|
||||||
the most recent data.
|
|
||||||
|
|
||||||
- boolean enableTsc (default to false):
|
- boolean enableTsc (default to {1}):
|
||||||
[process and thread tracing]
|
[process and thread tracing]
|
||||||
Whether to use enable TSC timestamps or not. This is supported on
|
|
||||||
all devices that support intel-pt.
|
|
||||||
|
|
||||||
- psbPeriod (defaults to null):
|
- int psbPeriod (defaults to {2}):
|
||||||
[process and thread tracing]
|
[process and thread tracing]
|
||||||
This value defines the period in which PSB packets will be generated.
|
|
||||||
A PSB packet is a synchronization packet that contains a TSC
|
|
||||||
timestamp and the current absolute instruction pointer.
|
|
||||||
|
|
||||||
This parameter can only be used if
|
- boolean perCoreTracing (default to {3}):
|
||||||
|
|
||||||
/sys/bus/event_source/devices/intel_pt/caps/psb_cyc
|
|
||||||
|
|
||||||
is 1. Otherwise, the PSB period will be defined by the processor.
|
|
||||||
|
|
||||||
If supported, valid values for this period can be found in
|
|
||||||
|
|
||||||
/sys/bus/event_source/devices/intel_pt/caps/psb_periods
|
|
||||||
|
|
||||||
which contains a hexadecimal number, whose bits represent
|
|
||||||
valid values e.g. if bit 2 is set, then value 2 is valid.
|
|
||||||
|
|
||||||
The psb_period value is converted to the approximate number of
|
|
||||||
raw trace bytes between PSB packets as:
|
|
||||||
|
|
||||||
2 ^ (value + 11)
|
|
||||||
|
|
||||||
e.g. value 3 means 16KiB between PSB packets. Defaults to 0 if
|
|
||||||
supported.
|
|
||||||
|
|
||||||
- int processBufferSizeLimit (defaults to 500 MB):
|
|
||||||
[process tracing only]
|
[process tracing only]
|
||||||
Maximum total trace size per process in bytes. This limit applies
|
|
||||||
to the sum of the sizes of all thread traces of this process,
|
- int processBufferSizeLimit (defaults to {4} MiB):
|
||||||
excluding the ones created explicitly with "thread tracing".
|
[process tracing only])",
|
||||||
Whenever a thread is attempted to be traced due to this command
|
kDefaultTraceBufferSize, kDefaultEnableTscValue,
|
||||||
and the limit would be reached, the process is stopped with a
|
kDefaultPsbPeriod, kDefaultPerCoreTracing,
|
||||||
"processor trace" reason, so that the user can retrace the process
|
kDefaultProcessBufferSizeLimit / 1024 / 1024));
|
||||||
if needed.)";
|
}
|
||||||
|
return message->c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error TraceIntelPT::Start(size_t thread_buffer_size,
|
Error TraceIntelPT::Start(size_t trace_buffer_size,
|
||||||
size_t total_buffer_size_limit, bool enable_tsc,
|
size_t total_buffer_size_limit, bool enable_tsc,
|
||||||
Optional<size_t> psb_period) {
|
Optional<size_t> psb_period, bool per_core_tracing) {
|
||||||
TraceIntelPTStartRequest request;
|
TraceIntelPTStartRequest request;
|
||||||
request.threadBufferSize = thread_buffer_size;
|
request.trace_buffer_size = trace_buffer_size;
|
||||||
request.processBufferSizeLimit = total_buffer_size_limit;
|
request.process_buffer_size_limit = total_buffer_size_limit;
|
||||||
request.enableTsc = enable_tsc;
|
request.enable_tsc = enable_tsc;
|
||||||
request.psbPeriod = psb_period.map([](size_t val) { return (int64_t)val; });
|
request.psb_period = psb_period.map([](size_t val) { return (int64_t)val; });
|
||||||
request.type = GetPluginName().str();
|
request.type = GetPluginName().str();
|
||||||
|
request.per_core_tracing = per_core_tracing;
|
||||||
return Trace::Start(toJSON(request));
|
return Trace::Start(toJSON(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
Error TraceIntelPT::Start(StructuredData::ObjectSP configuration) {
|
Error TraceIntelPT::Start(StructuredData::ObjectSP configuration) {
|
||||||
size_t thread_buffer_size = kDefaultThreadBufferSize;
|
size_t trace_buffer_size = kDefaultTraceBufferSize;
|
||||||
size_t process_buffer_size_limit = kDefaultProcessBufferSizeLimit;
|
size_t process_buffer_size_limit = kDefaultProcessBufferSizeLimit;
|
||||||
bool enable_tsc = kDefaultEnableTscValue;
|
bool enable_tsc = kDefaultEnableTscValue;
|
||||||
Optional<size_t> psb_period = kDefaultPsbPeriod;
|
Optional<size_t> psb_period = kDefaultPsbPeriod;
|
||||||
|
bool per_core_tracing = kDefaultPerCoreTracing;
|
||||||
|
|
||||||
if (configuration) {
|
if (configuration) {
|
||||||
if (StructuredData::Dictionary *dict = configuration->GetAsDictionary()) {
|
if (StructuredData::Dictionary *dict = configuration->GetAsDictionary()) {
|
||||||
dict->GetValueForKeyAsInteger("threadBufferSize", thread_buffer_size);
|
dict->GetValueForKeyAsInteger("traceBufferSize", trace_buffer_size);
|
||||||
dict->GetValueForKeyAsInteger("processBufferSizeLimit",
|
dict->GetValueForKeyAsInteger("processBufferSizeLimit",
|
||||||
process_buffer_size_limit);
|
process_buffer_size_limit);
|
||||||
dict->GetValueForKeyAsBoolean("enableTsc", enable_tsc);
|
dict->GetValueForKeyAsBoolean("enableTsc", enable_tsc);
|
||||||
dict->GetValueForKeyAsInteger("psbPeriod", psb_period);
|
dict->GetValueForKeyAsInteger("psbPeriod", psb_period);
|
||||||
|
dict->GetValueForKeyAsBoolean("perCoreTracing", per_core_tracing);
|
||||||
} else {
|
} else {
|
||||||
return createStringError(inconvertibleErrorCode(),
|
return createStringError(inconvertibleErrorCode(),
|
||||||
"configuration object is not a dictionary");
|
"configuration object is not a dictionary");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Start(thread_buffer_size, process_buffer_size_limit, enable_tsc,
|
return Start(trace_buffer_size, process_buffer_size_limit, enable_tsc,
|
||||||
psb_period);
|
psb_period, per_core_tracing);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids,
|
llvm::Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids,
|
||||||
size_t thread_buffer_size, bool enable_tsc,
|
size_t trace_buffer_size, bool enable_tsc,
|
||||||
Optional<size_t> psb_period) {
|
Optional<size_t> psb_period) {
|
||||||
TraceIntelPTStartRequest request;
|
TraceIntelPTStartRequest request;
|
||||||
request.threadBufferSize = thread_buffer_size;
|
request.trace_buffer_size = trace_buffer_size;
|
||||||
request.enableTsc = enable_tsc;
|
request.enable_tsc = enable_tsc;
|
||||||
request.psbPeriod = psb_period.map([](size_t val) { return (int64_t)val; });
|
request.psb_period = psb_period.map([](size_t val) { return (int64_t)val; });
|
||||||
request.type = GetPluginName().str();
|
request.type = GetPluginName().str();
|
||||||
request.tids.emplace();
|
request.tids.emplace();
|
||||||
for (lldb::tid_t tid : tids)
|
for (lldb::tid_t tid : tids)
|
||||||
|
@ -375,13 +353,13 @@ llvm::Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids,
|
||||||
|
|
||||||
Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids,
|
Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids,
|
||||||
StructuredData::ObjectSP configuration) {
|
StructuredData::ObjectSP configuration) {
|
||||||
size_t thread_buffer_size = kDefaultThreadBufferSize;
|
size_t trace_buffer_size = kDefaultTraceBufferSize;
|
||||||
bool enable_tsc = kDefaultEnableTscValue;
|
bool enable_tsc = kDefaultEnableTscValue;
|
||||||
Optional<size_t> psb_period = kDefaultPsbPeriod;
|
Optional<size_t> psb_period = kDefaultPsbPeriod;
|
||||||
|
|
||||||
if (configuration) {
|
if (configuration) {
|
||||||
if (StructuredData::Dictionary *dict = configuration->GetAsDictionary()) {
|
if (StructuredData::Dictionary *dict = configuration->GetAsDictionary()) {
|
||||||
dict->GetValueForKeyAsInteger("threadBufferSize", thread_buffer_size);
|
dict->GetValueForKeyAsInteger("traceBufferSize", trace_buffer_size);
|
||||||
dict->GetValueForKeyAsBoolean("enableTsc", enable_tsc);
|
dict->GetValueForKeyAsBoolean("enableTsc", enable_tsc);
|
||||||
dict->GetValueForKeyAsInteger("psbPeriod", psb_period);
|
dict->GetValueForKeyAsInteger("psbPeriod", psb_period);
|
||||||
} else {
|
} else {
|
||||||
|
@ -390,7 +368,7 @@ Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Start(tids, thread_buffer_size, enable_tsc, psb_period);
|
return Start(tids, trace_buffer_size, enable_tsc, psb_period);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error TraceIntelPT::OnThreadBufferRead(lldb::tid_t tid,
|
Error TraceIntelPT::OnThreadBufferRead(lldb::tid_t tid,
|
||||||
|
|
|
@ -84,27 +84,31 @@ public:
|
||||||
|
|
||||||
/// Start tracing a live process.
|
/// Start tracing a live process.
|
||||||
///
|
///
|
||||||
/// \param[in] thread_buffer_size
|
/// More information on the parameters below can be found in the
|
||||||
|
/// jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt.
|
||||||
|
///
|
||||||
|
/// \param[in] trace_buffer_size
|
||||||
/// Trace size per thread in bytes.
|
/// Trace size per thread in bytes.
|
||||||
///
|
///
|
||||||
/// \param[in] total_buffer_size_limit
|
/// \param[in] total_buffer_size_limit
|
||||||
/// Maximum total trace size per process in bytes.
|
/// Maximum total trace size per process in bytes.
|
||||||
/// More information in TraceIntelPT::GetStartConfigurationHelp().
|
|
||||||
///
|
///
|
||||||
/// \param[in] enable_tsc
|
/// \param[in] enable_tsc
|
||||||
/// Whether to use enable TSC timestamps or not.
|
/// Whether to use enable TSC timestamps or not.
|
||||||
/// More information in TraceIntelPT::GetStartConfigurationHelp().
|
|
||||||
///
|
///
|
||||||
/// \param[in] psb_period
|
/// \param[in] psb_period
|
||||||
///
|
|
||||||
/// This value defines the period in which PSB packets will be generated.
|
/// This value defines the period in which PSB packets will be generated.
|
||||||
/// More information in TraceIntelPT::GetStartConfigurationHelp();
|
///
|
||||||
|
/// \param[in] per_core_tracing
|
||||||
|
/// This value defines whether to have a trace buffer per thread or per
|
||||||
|
/// cpu core.
|
||||||
///
|
///
|
||||||
/// \return
|
/// \return
|
||||||
/// \a llvm::Error::success if the operation was successful, or
|
/// \a llvm::Error::success if the operation was successful, or
|
||||||
/// \a llvm::Error otherwise.
|
/// \a llvm::Error otherwise.
|
||||||
llvm::Error Start(size_t thread_buffer_size, size_t total_buffer_size_limit,
|
llvm::Error Start(size_t trace_buffer_size, size_t total_buffer_size_limit,
|
||||||
bool enable_tsc, llvm::Optional<size_t> psb_period);
|
bool enable_tsc, llvm::Optional<size_t> psb_period,
|
||||||
|
bool m_per_core_tracing);
|
||||||
|
|
||||||
/// \copydoc Trace::Start
|
/// \copydoc Trace::Start
|
||||||
llvm::Error Start(StructuredData::ObjectSP configuration =
|
llvm::Error Start(StructuredData::ObjectSP configuration =
|
||||||
|
@ -112,25 +116,25 @@ public:
|
||||||
|
|
||||||
/// Start tracing live threads.
|
/// Start tracing live threads.
|
||||||
///
|
///
|
||||||
|
/// More information on the parameters below can be found in the
|
||||||
|
/// jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt.
|
||||||
|
///
|
||||||
/// \param[in] tids
|
/// \param[in] tids
|
||||||
/// Threads to trace.
|
/// Threads to trace.
|
||||||
///
|
///
|
||||||
/// \param[in] thread_buffer_size
|
/// \param[in] trace_buffer_size
|
||||||
/// Trace size per thread in bytes.
|
/// Trace size per thread or per core in bytes.
|
||||||
///
|
///
|
||||||
/// \param[in] enable_tsc
|
/// \param[in] enable_tsc
|
||||||
/// Whether to use enable TSC timestamps or not.
|
/// Whether to use enable TSC timestamps or not.
|
||||||
/// More information in TraceIntelPT::GetStartConfigurationHelp().
|
|
||||||
///
|
///
|
||||||
/// \param[in] psb_period
|
/// \param[in] psb_period
|
||||||
///
|
|
||||||
/// This value defines the period in which PSB packets will be generated.
|
/// This value defines the period in which PSB packets will be generated.
|
||||||
/// More information in TraceIntelPT::GetStartConfigurationHelp().
|
|
||||||
///
|
///
|
||||||
/// \return
|
/// \return
|
||||||
/// \a llvm::Error::success if the operation was successful, or
|
/// \a llvm::Error::success if the operation was successful, or
|
||||||
/// \a llvm::Error otherwise.
|
/// \a llvm::Error otherwise.
|
||||||
llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, size_t thread_buffer_size,
|
llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, size_t trace_buffer_size,
|
||||||
bool enable_tsc, llvm::Optional<size_t> psb_period);
|
bool enable_tsc, llvm::Optional<size_t> psb_period);
|
||||||
|
|
||||||
/// \copydoc Trace::Start
|
/// \copydoc Trace::Start
|
||||||
|
|
|
@ -16,10 +16,11 @@
|
||||||
namespace lldb_private {
|
namespace lldb_private {
|
||||||
namespace trace_intel_pt {
|
namespace trace_intel_pt {
|
||||||
|
|
||||||
const size_t kDefaultThreadBufferSize = 4 * 1024; // 4KB
|
const size_t kDefaultTraceBufferSize = 4 * 1024; // 4KB
|
||||||
const size_t kDefaultProcessBufferSizeLimit = 5 * 1024 * 1024; // 500MB
|
const size_t kDefaultProcessBufferSizeLimit = 5 * 1024 * 1024; // 500MB
|
||||||
const bool kDefaultEnableTscValue = false;
|
const bool kDefaultEnableTscValue = false;
|
||||||
const llvm::Optional<size_t> kDefaultPsbPeriod = llvm::None;
|
const llvm::Optional<size_t> kDefaultPsbPeriod = llvm::None;
|
||||||
|
const bool kDefaultPerCoreTracing = false;
|
||||||
|
|
||||||
} // namespace trace_intel_pt
|
} // namespace trace_intel_pt
|
||||||
} // namespace lldb_private
|
} // namespace lldb_private
|
||||||
|
|
|
@ -35,12 +35,24 @@ let Command = "thread trace start intel pt" in {
|
||||||
}
|
}
|
||||||
|
|
||||||
let Command = "process trace start intel pt" in {
|
let Command = "process trace start intel pt" in {
|
||||||
def process_trace_start_intel_pt_thread_size: Option<"thread-size", "s">,
|
def process_trace_start_intel_pt_buffer_size: Option<"buffer-size", "s">,
|
||||||
Group<1>,
|
Group<1>,
|
||||||
Arg<"Value">,
|
Arg<"Value">,
|
||||||
Desc<"Trace size in bytes per thread. It must be a power of 2 greater "
|
Desc<"Size in bytes used by each individual per-thread or per-core trace "
|
||||||
"than or equal to 4096 (2^12). The trace is circular keeping "
|
"buffer. It must be a power of 2 greater than or equal to 4096 (2^12) "
|
||||||
"the most recent data. Defaults to 4096 bytes.">;
|
"bytes.">;
|
||||||
|
def process_trace_start_intel_pt_per_core_tracing:
|
||||||
|
Option<"per-core-tracing", "c">,
|
||||||
|
Group<1>,
|
||||||
|
Desc<"Instead of having an individual trace buffer per thread, which uses "
|
||||||
|
"a number trace buffers proportional to the number of running "
|
||||||
|
"threads, this option triggers the collection on a per cpu core "
|
||||||
|
"basis. This effectively traces the entire activity on all cores "
|
||||||
|
"using a limited amount of trace buffers regardless of the number of "
|
||||||
|
"threads. This might cause data loss for less frequent threads. This "
|
||||||
|
"option forces the capture of TSC timestamps (see --tsc). Also, this "
|
||||||
|
"option can't be used simulatenously with any other trace sessions "
|
||||||
|
"because of its system-wide nature.">;
|
||||||
def process_trace_start_intel_pt_process_size_limit: Option<"total-size-limit", "l">,
|
def process_trace_start_intel_pt_process_size_limit: Option<"total-size-limit", "l">,
|
||||||
Group<1>,
|
Group<1>,
|
||||||
Arg<"Value">,
|
Arg<"Value">,
|
||||||
|
|
|
@ -20,29 +20,27 @@ bool fromJSON(const json::Value &value, TraceIntelPTStartRequest &packet,
|
||||||
Path path) {
|
Path path) {
|
||||||
ObjectMapper o(value, path);
|
ObjectMapper o(value, path);
|
||||||
if (!o || !fromJSON(value, (TraceStartRequest &)packet, path) ||
|
if (!o || !fromJSON(value, (TraceStartRequest &)packet, path) ||
|
||||||
!o.map("enableTsc", packet.enableTsc) ||
|
!o.map("enableTsc", packet.enable_tsc) ||
|
||||||
!o.map("psbPeriod", packet.psbPeriod) ||
|
!o.map("psbPeriod", packet.psb_period) ||
|
||||||
!o.map("threadBufferSize", packet.threadBufferSize) ||
|
!o.map("traceBufferSize", packet.trace_buffer_size))
|
||||||
!o.map("processBufferSizeLimit", packet.processBufferSizeLimit))
|
|
||||||
return false;
|
|
||||||
if (packet.tids && packet.processBufferSizeLimit) {
|
|
||||||
path.report("processBufferSizeLimit must be provided");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!packet.tids && !packet.processBufferSizeLimit) {
|
|
||||||
path.report("processBufferSizeLimit must not be provided");
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (packet.IsProcessTracing()) {
|
||||||
|
if (!o.map("processBufferSizeLimit", packet.process_buffer_size_limit) ||
|
||||||
|
!o.map("perCoreTracing", packet.per_core_tracing))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
json::Value toJSON(const TraceIntelPTStartRequest &packet) {
|
json::Value toJSON(const TraceIntelPTStartRequest &packet) {
|
||||||
json::Value base = toJSON((const TraceStartRequest &)packet);
|
json::Value base = toJSON((const TraceStartRequest &)packet);
|
||||||
base.getAsObject()->try_emplace("threadBufferSize", packet.threadBufferSize);
|
json::Object &obj = *base.getAsObject();
|
||||||
base.getAsObject()->try_emplace("processBufferSizeLimit",
|
obj.try_emplace("traceBufferSize", packet.trace_buffer_size);
|
||||||
packet.processBufferSizeLimit);
|
obj.try_emplace("processBufferSizeLimit", packet.process_buffer_size_limit);
|
||||||
base.getAsObject()->try_emplace("psbPeriod", packet.psbPeriod);
|
obj.try_emplace("psbPeriod", packet.psb_period);
|
||||||
base.getAsObject()->try_emplace("enableTsc", packet.enableTsc);
|
obj.try_emplace("enableTsc", packet.enable_tsc);
|
||||||
|
obj.try_emplace("perCoreTracing", packet.per_core_tracing);
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,18 +35,18 @@ class TestTraceStartStop(TraceIntelPTTestCaseBase):
|
||||||
self.expect("r")
|
self.expect("r")
|
||||||
|
|
||||||
self.traceStartThread(
|
self.traceStartThread(
|
||||||
error=True, threadBufferSize=2000,
|
error=True, traceBufferSize=2000,
|
||||||
substrs=["The trace buffer size must be a power of 2", "It was 2000"])
|
substrs=["The trace buffer size must be a power of 2", "It was 2000"])
|
||||||
|
|
||||||
self.traceStartThread(
|
self.traceStartThread(
|
||||||
error=True, threadBufferSize=5000,
|
error=True, traceBufferSize=5000,
|
||||||
substrs=["The trace buffer size must be a power of 2", "It was 5000"])
|
substrs=["The trace buffer size must be a power of 2", "It was 5000"])
|
||||||
|
|
||||||
self.traceStartThread(
|
self.traceStartThread(
|
||||||
error=True, threadBufferSize=0,
|
error=True, traceBufferSize=0,
|
||||||
substrs=["The trace buffer size must be a power of 2", "It was 0"])
|
substrs=["The trace buffer size must be a power of 2", "It was 0"])
|
||||||
|
|
||||||
self.traceStartThread(threadBufferSize=1048576)
|
self.traceStartThread(traceBufferSize=1048576)
|
||||||
|
|
||||||
@skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
|
@skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
|
||||||
def testSBAPIHelp(self):
|
def testSBAPIHelp(self):
|
||||||
|
@ -55,7 +55,7 @@ class TestTraceStartStop(TraceIntelPTTestCaseBase):
|
||||||
self.expect("r")
|
self.expect("r")
|
||||||
|
|
||||||
help = self.getTraceOrCreate().GetStartConfigurationHelp()
|
help = self.getTraceOrCreate().GetStartConfigurationHelp()
|
||||||
self.assertIn("threadBufferSize", help)
|
self.assertIn("traceBufferSize", help)
|
||||||
self.assertIn("processBufferSizeLimit", help)
|
self.assertIn("processBufferSizeLimit", help)
|
||||||
|
|
||||||
@skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
|
@skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
|
||||||
|
|
|
@ -152,3 +152,17 @@ class TestTraceStartStopMultipleThreads(TraceIntelPTTestCaseBase):
|
||||||
self.expect("c", substrs=['Thread', "can't be traced"])
|
self.expect("c", substrs=['Thread', "can't be traced"])
|
||||||
|
|
||||||
self.traceStopProcess()
|
self.traceStopProcess()
|
||||||
|
|
||||||
|
@skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
|
||||||
|
@testSBAPIAndCommands
|
||||||
|
def testStartPerCoreSession(self):
|
||||||
|
self.build()
|
||||||
|
exe = self.getBuildArtifact("a.out")
|
||||||
|
self.dbg.CreateTarget(exe)
|
||||||
|
|
||||||
|
self.expect("b main")
|
||||||
|
self.expect("r")
|
||||||
|
|
||||||
|
self.traceStartProcess(
|
||||||
|
error=True, perCoreTracing=True,
|
||||||
|
substrs=["Per-core tracing is not supported"])
|
||||||
|
|
Loading…
Reference in New Issue