summaryrefslogtreecommitdiff
path: root/libunwindstack/utils/OfflineUnwindUtils.h
diff options
context:
space:
mode:
Diffstat (limited to 'libunwindstack/utils/OfflineUnwindUtils.h')
-rw-r--r--libunwindstack/utils/OfflineUnwindUtils.h103
1 files changed, 82 insertions, 21 deletions
diff --git a/libunwindstack/utils/OfflineUnwindUtils.h b/libunwindstack/utils/OfflineUnwindUtils.h
index 928ac5c..75bfd38 100644
--- a/libunwindstack/utils/OfflineUnwindUtils.h
+++ b/libunwindstack/utils/OfflineUnwindUtils.h
@@ -17,10 +17,17 @@
#ifndef _LIBUNWINDSTACK_UTILS_OFFLINE_UNWIND_UTILS_H
#define _LIBUNWINDSTACK_UTILS_OFFLINE_UNWIND_UTILS_H
+#include <cstddef>
#include <filesystem>
#include <memory>
#include <string>
+#include <unordered_map>
+#include <vector>
+#include <unwindstack/Arch.h>
+#include <unwindstack/JitDebug.h>
+#include <unwindstack/Memory.h>
+#include <unwindstack/Regs.h>
#include <unwindstack/Unwinder.h>
#include "MemoryOffline.h"
@@ -64,40 +71,97 @@
//
// See b/192012600 for additional information regarding Offline Unwind Benchmarks.
namespace unwindstack {
+
std::string GetOfflineFilesDirectory();
std::string DumpFrames(const Unwinder& unwinder);
-bool AddMemory(std::string file_name, MemoryOfflineParts* parts, std::string& error_msg);
+bool AddMemory(std::string file_name, MemoryOfflineParts* parts, std::string* error_msg);
+
+// An `UnwindSample` encapsulates the information necessary to perform an offline unwind for a
+// single offline sample/snapshot.
+struct UnwindSample {
+ std::string offline_files_path;
+ std::string map_buffer;
+ std::unique_ptr<Regs> regs;
+ std::unique_ptr<Maps> maps;
+ std::shared_ptr<Memory> process_memory;
+ std::unique_ptr<JitDebug> jit_debug;
+};
+// Enum that indicates how `UnwindSample::process_memory` of `OfflineUnwindUtils::samples_`
+// should be initialized.
+enum class ProcessMemoryFlag {
+ kNone = 0,
+ kIncludeJitMemory,
+ kNoMemory,
+};
+
+// The `OfflineUnwindUtils` class helps perform offline unwinds by handling the creation of the
+// `Regs`, `Maps`, and `Memory` objects needed for unwinding.
+//
+// `OfflineUnwindUtils` assists in two unwind use cases:
+// 1. Single unwinds: unwind from a single sample/snapshot (one set of offline unwind files).
+// 2. Consecutive/Multiple unwinds: unwind from a multiple samples/snapshots.
+//
+// `Init` contains two overloads for these two unwind cases. Other than `Init` and
+// `ReturnToCurrentWorkingDirectory`, the remainder of the public API includes a `sample_name`
+// parameter to indicate which sample/snapshot we are referencing. Specifying this value is
+// REQUIRED for the multiple unwind use case. However, in the single use case, the caller has
+// the choice of either providing the sample name or using the default value.
class OfflineUnwindUtils {
public:
- Regs* GetRegs() { return regs_.get(); }
+ // If the sample name passed to Get* is an invalid sample, nullptr is returned.
+ Regs* GetRegs(const std::string& sample_name = kSingleSample) const;
+
+ Maps* GetMaps(const std::string& sample_name = kSingleSample) const;
+
+ std::shared_ptr<Memory> GetProcessMemory(const std::string& sample_name = kSingleSample) const;
- Maps* GetMaps() { return maps_.get(); }
+ JitDebug* GetJitDebug(const std::string& sample_name = kSingleSample) const;
- std::shared_ptr<Memory> GetProcessMemory() { return process_memory_; }
+ const std::string* GetOfflineFilesPath(const std::string& sample_name = kSingleSample) const;
- std::string GetOfflineDirectory() { return offline_dir_; }
+ // Notes:
+ // * If the caller sets elements of `set_maps` to false or `memory_types` to
+ // kNoMemory, they are responsible for calling `CreateMaps` or `CreateProcessMemory` before
+ // expecting `GetMaps` or `GetProcessMemory` to return anything but nullptr.
+ // * Pass offline_files_dirs by value because we move each string to create the samples_ elements.
+ bool Init(std::vector<std::string> offline_files_dirs, const std::vector<ArchEnum>& archs,
+ std::string* error_msg, const std::vector<ProcessMemoryFlag>& memory_flags,
+ const std::vector<bool>& set_maps);
- bool Init(const std::string& offline_files_dir, ArchEnum arch, std::string& error_msg,
- bool add_stack = true, bool set_maps = true);
+ bool Init(std::string offline_files_dir, ArchEnum arch, std::string* error_msg,
+ ProcessMemoryFlag memory_flag = ProcessMemoryFlag::kNone, bool set_maps = true);
- bool ResetMaps(std::string& error_msg);
+ // This must be called explicitly for the multiple unwind use case sometime before
+ // Unwinder::Unwind is called. This is required because the Unwinder must init each
+ // ELF object with a MemoryFileAtOffset memory object. Because the maps.txt provides a relative
+ // path to the ELF files, we must be in the directory of the maps.txt when unwinding.
+ //
+ // Note: Init performs the check that this sample directory exists. If Init fails,
+ // `initted_` is not set to true and this function will return false.
+ bool ChangeToSampleDirectory(std::string* error_msg,
+ const std::string& initial_sample_name = kSingleSample) const;
- bool SetProcessMemory(std::string& error_msg);
+ void ReturnToCurrentWorkingDirectory() {
+ if (!cwd_.empty()) std::filesystem::current_path(cwd_);
+ }
- bool SetJitProcessMemory(std::string& error_msg);
+ bool CreateMaps(std::string* error_msg, const std::string& sample_name = kSingleSample);
- void ReturnToCurrentWorkingDirectory() { std::filesystem::current_path(cwd_); }
+ bool CreateProcessMemory(std::string* error_msg, const std::string& sample_name = kSingleSample);
private:
- bool SetRegs(ArchEnum arch, std::string& error_msg);
+ static constexpr char kSingleSample[] = "";
+
+ bool CreateRegs(ArchEnum arch, std::string* error_msg,
+ const std::string& sample_name = kSingleSample);
+
+ // Needed to support using the default value `kSingleSample` for the single unwind use case.
+ const std::string& GetAdjustedSampleName(const std::string& sample_name) const;
- template <typename AddressType>
- bool ReadRegs(RegsImpl<AddressType>* regs,
- const std::unordered_map<std::string, uint32_t>& name_to_reg,
- std::string& error_msg);
+ bool IsValidUnwindSample(const std::string& sample_name, std::string* error_msg) const;
static std::unordered_map<std::string, uint32_t> arm_regs_;
static std::unordered_map<std::string, uint32_t> arm64_regs_;
@@ -105,11 +169,8 @@ class OfflineUnwindUtils {
static std::unordered_map<std::string, uint32_t> x86_64_regs_;
std::string cwd_;
- std::string offline_dir_;
- std::string map_buffer_;
- std::unique_ptr<Regs> regs_;
- std::unique_ptr<Maps> maps_;
- std::shared_ptr<Memory> process_memory_;
+ std::unordered_map<std::string, UnwindSample> samples_;
+ bool initted_ = false;
};
} // namespace unwindstack