diff --git a/lldb/source/Plugins/Process/Linux/Perf.h b/lldb/source/Plugins/Process/Linux/Perf.h --- a/lldb/source/Plugins/Process/Linux/Perf.h +++ b/lldb/source/Plugins/Process/Linux/Perf.h @@ -22,6 +22,21 @@ #include #include +struct perf_event_mmap_page_custom { + int cap_user_time; + int cap_user_time_zero; + uint32_t time_mult; + uint16_t time_shift; + uint64_t time_zero; + + //uint64_t aux_head; + //int aux_offset; + //unsigned long aux_size; + //uint64_t data_head; + //int data_offset; + //unsigned long data_size; +}; + namespace lldb_private { namespace process_linux { namespace resource_handle { @@ -142,7 +157,7 @@ /// \param[in] num_data_pages /// Number of pages in the data buffer to mmap, must be a power of 2. /// A value of 0 is useful for "dummy" events that only want to access - /// the metadata, \a perf_event_mmap_page, or the aux buffer. + /// the metadata, \a perf_event_mmap_page_custom, or the aux buffer. /// /// \param[in] num_aux_pages /// Number of pages in the aux buffer to mmap, must be a power of 2. @@ -171,8 +186,8 @@ /// otherwise a failure might happen. /// /// \return - /// The data section's \a perf_event_mmap_page. - perf_event_mmap_page &GetMetadataPage() const; + /// The data section's \a perf_event_mmap_page_custom. + perf_event_mmap_page_custom &GetMetadataPage() const; /// Get the data buffer from the data section's mmap buffer. /// @@ -278,7 +293,7 @@ /// \param[in] num_data_pages /// Number of pages in the data buffer to mmap, must be a power of 2. /// A value of 0 is useful for "dummy" events that only want to access - /// the metadata, \a perf_event_mmap_page, or the aux buffer. + /// the metadata, \a perf_event_mmap_page_custom, or the aux buffer. /// /// \param[in] data_buffer_write /// Whether to mmap the data buffer with WRITE permissions. This changes @@ -317,7 +332,7 @@ CreateContextSwitchTracePerfEvent(lldb::cpu_id_t cpu_id, const PerfEvent *parent_perf_event = nullptr); -/// Load \a PerfTscConversionParameters from \a perf_event_mmap_page, if +/// Load \a PerfTscConversionParameters from \a perf_event_mmap_page_custom, if /// available. llvm::Expected LoadPerfTscConversionParameters(); diff --git a/lldb/source/Plugins/Process/Linux/Perf.cpp b/lldb/source/Plugins/Process/Linux/Perf.cpp --- a/lldb/source/Plugins/Process/Linux/Perf.cpp +++ b/lldb/source/Plugins/Process/Linux/Perf.cpp @@ -42,7 +42,7 @@ /*data_buffer_write=*/false)) return std::move(mmap_err); - perf_event_mmap_page &mmap_metada = perf_event->GetMetadataPage(); + perf_event_mmap_page_custom &mmap_metada = perf_event->GetMetadataPage(); if (mmap_metada.cap_user_time && mmap_metada.cap_user_time_zero) { return LinuxPerfZeroTscConversion{ mmap_metada.time_mult, mmap_metada.time_shift, {mmap_metada.time_zero}}; @@ -128,19 +128,22 @@ if (num_aux_pages == 0) return Error::success(); - perf_event_mmap_page &metadata_page = GetMetadataPage(); + return llvm::createStringError( + llvm::inconvertibleErrorCode(), "foo"); - metadata_page.aux_offset = - metadata_page.data_offset + metadata_page.data_size; - metadata_page.aux_size = num_aux_pages * getpagesize(); - - if (Expected mmap_aux = - DoMmap(nullptr, metadata_page.aux_size, PROT_READ, MAP_SHARED, - metadata_page.aux_offset, "aux buffer")) { - m_aux_base = std::move(mmap_aux.get()); - return Error::success(); - } else - return mmap_aux.takeError(); +// perf_event_mmap_page_custom &metadata_page = GetMetadataPage(); +// +// metadata_page.aux_offset = +// metadata_page.data_offset + metadata_page.data_size; +// metadata_page.aux_size = num_aux_pages * getpagesize(); +// +// if (Expected mmap_aux = +// DoMmap(nullptr, metadata_page.aux_size, PROT_READ, MAP_SHARED, +// metadata_page.aux_offset, "aux buffer")) { +// m_aux_base = std::move(mmap_aux.get()); +// return Error::success(); +// } else +// return mmap_aux.takeError(); } llvm::Error PerfEvent::MmapMetadataAndBuffers(size_t num_data_pages, @@ -165,21 +168,24 @@ long PerfEvent::GetFd() const { return *(m_fd.get()); } -perf_event_mmap_page &PerfEvent::GetMetadataPage() const { - return *reinterpret_cast(m_metadata_data_base.get()); +perf_event_mmap_page_custom &PerfEvent::GetMetadataPage() const { + return *reinterpret_cast(m_metadata_data_base.get()); } ArrayRef PerfEvent::GetDataBuffer() const { - perf_event_mmap_page &mmap_metadata = GetMetadataPage(); - return {reinterpret_cast(m_metadata_data_base.get()) + - mmap_metadata.data_offset, - static_cast(mmap_metadata.data_size)}; + // TODO: assert that this isn't called! + return {}; +// perf_event_mmap_page_custom &mmap_metadata = GetMetadataPage(); +// return {reinterpret_cast(m_metadata_data_base.get()) + +// mmap_metadata.data_offset, +// static_cast(mmap_metadata.data_size)}; } ArrayRef PerfEvent::GetAuxBuffer() const { - perf_event_mmap_page &mmap_metadata = GetMetadataPage(); - return {reinterpret_cast(m_aux_base.get()), - static_cast(mmap_metadata.aux_size)}; + return {}; +// perf_event_mmap_page_custom &mmap_metadata = GetMetadataPage(); +// return {reinterpret_cast(m_aux_base.get()), +// static_cast(mmap_metadata.aux_size)}; } Expected> PerfEvent::GetReadOnlyDataBuffer() { @@ -188,7 +194,7 @@ // this piece of code updates some pointers. See more about data_tail // in https://man7.org/linux/man-pages/man2/perf_event_open.2.html. - bool was_enabled = m_enabled; + //bool was_enabled = m_enabled; if (Error err = DisableWithIoctl()) return std::move(err); @@ -199,31 +205,33 @@ * and we don't need to care about it, whereas the data_head keeps * increasing and needs to be wrapped by modulus operator */ - perf_event_mmap_page &mmap_metadata = GetMetadataPage(); - - ArrayRef data = GetDataBuffer(); - uint64_t data_head = mmap_metadata.data_head; - uint64_t data_size = mmap_metadata.data_size; - std::vector output; - output.reserve(data.size()); - - if (data_head > data_size) { - uint64_t actual_data_head = data_head % data_size; - // The buffer has wrapped, so we first the oldest chunk of data - output.insert(output.end(), data.begin() + actual_data_head, data.end()); - // And we we read the most recent chunk of data - output.insert(output.end(), data.begin(), data.begin() + actual_data_head); - } else { - // There's been no wrapping, so we just read linearly - output.insert(output.end(), data.begin(), data.begin() + data_head); - } - - if (was_enabled) { - if (Error err = EnableWithIoctl()) - return std::move(err); - } - - return output; + return llvm::createStringError( + llvm::inconvertibleErrorCode(), "foo"); +// perf_event_mmap_page_custom &mmap_metadata = GetMetadataPage(); +// +// ArrayRef data = GetDataBuffer(); +// uint64_t data_head = mmap_metadata.data_head; +// uint64_t data_size = mmap_metadata.data_size; +// std::vector output; +// output.reserve(data.size()); +// +// if (data_head > data_size) { +// uint64_t actual_data_head = data_head % data_size; +// // The buffer has wrapped, so we first the oldest chunk of data +// output.insert(output.end(), data.begin() + actual_data_head, data.end()); +// // And we we read the most recent chunk of data +// output.insert(output.end(), data.begin(), data.begin() + actual_data_head); +// } else { +// // There's been no wrapping, so we just read linearly +// output.insert(output.end(), data.begin(), data.begin() + data_head); +// } +// +// if (was_enabled) { +// if (Error err = EnableWithIoctl()) +// return std::move(err); +// } +// +// return output; } Expected> PerfEvent::GetReadOnlyAuxBuffer() { @@ -232,38 +240,41 @@ // this piece of code updates some pointers. See more about aux_tail // in https://man7.org/linux/man-pages/man2/perf_event_open.2.html. - bool was_enabled = m_enabled; + //bool was_enabled = m_enabled; if (Error err = DisableWithIoctl()) return std::move(err); - perf_event_mmap_page &mmap_metadata = GetMetadataPage(); - - ArrayRef data = GetAuxBuffer(); - uint64_t aux_head = mmap_metadata.aux_head; - std::vector output; - output.reserve(data.size()); - - /** - * When configured as ring buffer, the aux buffer keeps wrapping around - * the buffer and its not possible to detect how many times the buffer - * wrapped. Initially the buffer is filled with zeros,as shown below - * so in order to get complete buffer we first copy firstpartsize, followed - * by any left over part from beginning to aux_head - * - * aux_offset [d,d,d,d,d,d,d,d,0,0,0,0,0,0,0,0,0,0,0] aux_size - * aux_head->||<- firstpartsize ->| - * - * */ - - output.insert(output.end(), data.begin() + aux_head, data.end()); - output.insert(output.end(), data.begin(), data.begin() + aux_head); - - if (was_enabled) { - if (Error err = EnableWithIoctl()) - return std::move(err); - } + return llvm::createStringError( + llvm::inconvertibleErrorCode(), "foo"); - return output; +// perf_event_mmap_page_custom &mmap_metadata = GetMetadataPage(); +// +// ArrayRef data = GetAuxBuffer(); +// uint64_t aux_head = mmap_metadata.aux_head; +// std::vector output; +// output.reserve(data.size()); +// +// /** +// * When configured as ring buffer, the aux buffer keeps wrapping around +// * the buffer and its not possible to detect how many times the buffer +// * wrapped. Initially the buffer is filled with zeros,as shown below +// * so in order to get complete buffer we first copy firstpartsize, followed +// * by any left over part from beginning to aux_head +// * +// * aux_offset [d,d,d,d,d,d,d,d,0,0,0,0,0,0,0,0,0,0,0] aux_size +// * aux_head->||<- firstpartsize ->| +// * +// * */ +// +// output.insert(output.end(), data.begin() + aux_head, data.end()); +// output.insert(output.end(), data.begin(), data.begin() + aux_head); +// +// if (was_enabled) { +// if (Error err = EnableWithIoctl()) +// return std::move(err); +// } +// +// return output; } Error PerfEvent::DisableWithIoctl() { @@ -295,11 +306,13 @@ } size_t PerfEvent::GetEffectiveDataBufferSize() const { - perf_event_mmap_page &mmap_metadata = GetMetadataPage(); - if (mmap_metadata.data_head < mmap_metadata.data_size) - return mmap_metadata.data_head; - else - return mmap_metadata.data_size; // The buffer has wrapped. + // TODO: assert not called! + return 0; +// perf_event_mmap_page_custom &mmap_metadata = GetMetadataPage(); +// if (mmap_metadata.data_head < mmap_metadata.data_size) +// return mmap_metadata.data_head; +// else +// return mmap_metadata.data_size; // The buffer has wrapped. } Expected