1 //===-- IntelPTMultiCoreTrace.cpp -----------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "IntelPTMultiCoreTrace.h" 10 11 #include "Procfs.h" 12 13 using namespace lldb; 14 using namespace lldb_private; 15 using namespace process_linux; 16 using namespace llvm; 17 18 static bool IsTotalBufferLimitReached(ArrayRef<core_id_t> cores, 19 const TraceIntelPTStartRequest &request) { 20 uint64_t required = cores.size() * request.trace_buffer_size; 21 uint64_t limit = request.process_buffer_size_limit.getValueOr( 22 std::numeric_limits<uint64_t>::max()); 23 return required > limit; 24 } 25 26 static Error IncludePerfEventParanoidMessageInError(Error &&error) { 27 return createStringError( 28 inconvertibleErrorCode(), 29 "%s\nYou might need to rerun as sudo or to set " 30 "/proc/sys/kernel/perf_event_paranoid to a value of 0 or -1.", 31 toString(std::move(error)).c_str()); 32 } 33 34 Expected<IntelPTMultiCoreTraceUP> IntelPTMultiCoreTrace::StartOnAllCores( 35 const TraceIntelPTStartRequest &request) { 36 Expected<ArrayRef<core_id_t>> core_ids = GetAvailableLogicalCoreIDs(); 37 if (!core_ids) 38 return core_ids.takeError(); 39 40 if (IsTotalBufferLimitReached(*core_ids, request)) 41 return createStringError( 42 inconvertibleErrorCode(), 43 "The process can't be traced because the process trace size limit " 44 "has been reached. Consider retracing with a higher limit."); 45 46 llvm::DenseMap<core_id_t, IntelPTSingleBufferTraceUP> buffers; 47 for (core_id_t core_id : *core_ids) { 48 if (Expected<IntelPTSingleBufferTraceUP> core_trace = 49 IntelPTSingleBufferTrace::Start(request, /*tid=*/None, core_id)) 50 buffers.try_emplace(core_id, std::move(*core_trace)); 51 else 52 return IncludePerfEventParanoidMessageInError(core_trace.takeError()); 53 } 54 55 return IntelPTMultiCoreTraceUP(new IntelPTMultiCoreTrace(std::move(buffers))); 56 } 57 58 void IntelPTMultiCoreTrace::ForEachCore( 59 std::function<void(core_id_t core_id, 60 const IntelPTSingleBufferTrace &core_trace)> 61 callback) { 62 for (auto &it : m_traces_per_core) 63 callback(it.first, *it.second); 64 } 65