blob: 91a4253b72e52724123b319ea100a8f03784a6df [file] [log] [blame]
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PERF_READER_H_
#define SRC_TRACE_PROCESSOR_IMPORTERS_PERF_READER_H_
#include <stdint.h>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <optional>
#include <string>
#include <type_traits>
#include <vector>
#include "perfetto/ext/base/string_view.h"
#include "perfetto/trace_processor/trace_blob_view.h"
#include "src/trace_processor/importers/perf/perf_event.h"
namespace perfetto::trace_processor::perf_importer {
// Helper to read various types of data fields contained in a TraceBlobView.
// All methods return a boolean indicating whether the read was successful. A
// false value means there was not enough data in the underlying buffer to
// satisfy the read.
class Reader {
public:
explicit Reader(TraceBlobView tbv)
: buffer_(tbv.blob()),
current_(tbv.data()),
end_(current_ + tbv.size()) {}
// Data left to be read. The value returned here decrements as read or skip
// methods are called.
size_t size_left() const { return static_cast<size_t>(end_ - current_); }
bool ReadStringView(base::StringView& str, size_t size) {
if (size_left() < size) {
return false;
}
str = base::StringView(reinterpret_cast<const char*>(current_), size);
current_ += size;
return true;
}
bool ReadPerfEventAttr(perf_event_attr& attr, size_t attr_size) {
const size_t bytes_to_read = std::min(attr_size, sizeof(attr));
const size_t bytes_to_skip = attr_size - bytes_to_read;
static_assert(std::has_unique_object_representations_v<perf_event_attr>);
if (size_left() < bytes_to_read + bytes_to_skip) {
return false;
}
memset(&attr, 0, sizeof(attr));
return Read(&attr, bytes_to_read) && Skip(bytes_to_skip);
}
bool ReadBlob(TraceBlobView& blob, uint32_t size) {
if (size_left() < size) {
return false;
}
blob = TraceBlobView(buffer_, static_cast<size_t>(end_ - current_), size);
current_ += size;
return true;
}
bool ReadStringUntilEndOrNull(std::string& out) {
const uint8_t* ptr = current_;
while (ptr != end_ && *ptr != 0) {
++ptr;
}
out = std::string(reinterpret_cast<const char*>(current_),
static_cast<size_t>(ptr - current_));
current_ = ptr;
return true;
}
template <typename T>
bool Read(T& obj) {
static_assert(std::has_unique_object_representations_v<T>);
return Read(&obj, sizeof(T));
}
bool Read(void* dest, size_t size) {
if (size_left() < size) {
return false;
}
memcpy(dest, current_, size);
current_ += size;
return true;
}
bool Skip(size_t size) {
if (size_left() < size) {
return false;
}
current_ += size;
return true;
}
template <typename T>
bool Skip() {
return Skip(sizeof(T));
}
// Reads consecutive values and stores them in the given vector. Reads as many
// entries as the current vector size.
template <typename T>
bool ReadVector(std::vector<T>& vec) {
static_assert(std::has_unique_object_representations_v<T>);
size_t size = sizeof(T) * vec.size();
if (size_left() < size) {
return false;
}
memcpy(vec.data(), current_, size);
current_ += size;
return true;
}
// Convenience helper for reading values and storing them in an optional<>
// wrapper.
template <typename T>
bool ReadOptional(std::optional<T>& obj) {
T val;
if (!Read(val)) {
return false;
}
obj = val;
return true;
}
// Reads a null terminated string.
bool ReadCString(std::string& out) {
for (const uint8_t* ptr = current_; ptr != end_; ++ptr) {
if (*ptr == 0) {
out = std::string(reinterpret_cast<const char*>(current_),
static_cast<size_t>(ptr - current_));
current_ = ptr;
return true;
}
}
return false;
}
private:
RefPtr<TraceBlob> buffer_;
const uint8_t* current_;
const uint8_t* end_;
};
} // namespace perfetto::trace_processor::perf_importer
#endif // SRC_TRACE_PROCESSOR_IMPORTERS_PERF_READER_H_