summaryrefslogtreecommitdiff
path: root/libunwindstack/include/unwindstack/AndroidUnwinder.h
diff options
context:
space:
mode:
Diffstat (limited to 'libunwindstack/include/unwindstack/AndroidUnwinder.h')
-rw-r--r--libunwindstack/include/unwindstack/AndroidUnwinder.h161
1 files changed, 161 insertions, 0 deletions
diff --git a/libunwindstack/include/unwindstack/AndroidUnwinder.h b/libunwindstack/include/unwindstack/AndroidUnwinder.h
new file mode 100644
index 0000000..de5579d
--- /dev/null
+++ b/libunwindstack/include/unwindstack/AndroidUnwinder.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <memory>
+#include <mutex>
+#include <optional>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <unwindstack/Arch.h>
+#include <unwindstack/DexFiles.h>
+#include <unwindstack/Error.h>
+#include <unwindstack/JitDebug.h>
+#include <unwindstack/Maps.h>
+#include <unwindstack/Memory.h>
+#include <unwindstack/Regs.h>
+#include <unwindstack/SharedString.h>
+#include <unwindstack/Unwinder.h>
+
+namespace unwindstack {
+
+struct AndroidUnwinderData {
+ AndroidUnwinderData() = default;
+ explicit AndroidUnwinderData(const size_t max_frames) : max_frames(max_frames) {}
+ explicit AndroidUnwinderData(const bool show_all_frames) : show_all_frames(show_all_frames) {}
+
+ void DemangleFunctionNames();
+
+ std::string GetErrorString();
+
+ std::vector<FrameData> frames;
+ ErrorData error;
+ std::optional<std::unique_ptr<Regs>> saved_initial_regs;
+ const std::optional<size_t> max_frames;
+ const bool show_all_frames = false;
+};
+
+class AndroidUnwinder {
+ public:
+ AndroidUnwinder(pid_t pid) : pid_(pid) {}
+ AndroidUnwinder(pid_t pid, std::shared_ptr<Memory>& memory)
+ : pid_(pid), process_memory_(memory) {}
+ AndroidUnwinder(pid_t pid, ArchEnum arch) : pid_(pid), arch_(arch) {}
+ AndroidUnwinder(pid_t pid, const std::vector<std::string> initial_map_names_to_skip)
+ : pid_(pid), initial_map_names_to_skip_(std::move(initial_map_names_to_skip)) {}
+ AndroidUnwinder(pid_t pid, const std::vector<std::string> initial_map_names_to_skip,
+ const std::vector<std::string> map_suffixes_to_ignore)
+ : pid_(pid),
+ initial_map_names_to_skip_(std::move(initial_map_names_to_skip)),
+ map_suffixes_to_ignore_(std::move(map_suffixes_to_ignore)) {}
+ virtual ~AndroidUnwinder() = default;
+
+ bool Initialize(ErrorData& error);
+
+ std::shared_ptr<Memory>& GetProcessMemory() { return process_memory_; }
+ unwindstack::Maps* GetMaps() { return maps_.get(); }
+
+ const JitDebug& GetJitDebug() { return *jit_debug_.get(); }
+ const DexFiles& GetDexFiles() { return *dex_files_.get(); }
+
+ std::string FormatFrame(const FrameData& frame) const;
+
+ bool Unwind(AndroidUnwinderData& data);
+ bool Unwind(std::optional<pid_t> tid, AndroidUnwinderData& data);
+ bool Unwind(void* ucontext, AndroidUnwinderData& data);
+ bool Unwind(Regs* initial_regs, AndroidUnwinderData& data);
+
+ FrameData BuildFrameFromPcOnly(uint64_t pc);
+
+ static AndroidUnwinder* Create(pid_t pid);
+
+ protected:
+ virtual bool InternalInitialize(ErrorData& error) = 0;
+
+ virtual bool InternalUnwind(std::optional<pid_t> tid, AndroidUnwinderData& data) = 0;
+
+ pid_t pid_;
+
+ size_t max_frames_ = kMaxNumFrames;
+ std::vector<std::string> initial_map_names_to_skip_;
+ std::vector<std::string> map_suffixes_to_ignore_;
+ std::once_flag initialize_;
+
+ ArchEnum arch_ = ARCH_UNKNOWN;
+
+ std::shared_ptr<Maps> maps_;
+ std::shared_ptr<Memory> process_memory_;
+ std::unique_ptr<JitDebug> jit_debug_;
+ std::unique_ptr<DexFiles> dex_files_;
+
+ static constexpr size_t kMaxNumFrames = 512;
+};
+
+class AndroidLocalUnwinder : public AndroidUnwinder {
+ public:
+ AndroidLocalUnwinder() : AndroidUnwinder(getpid()) {
+ initial_map_names_to_skip_.emplace_back(kUnwindstackLib);
+ }
+ AndroidLocalUnwinder(std::shared_ptr<Memory>& process_memory)
+ : AndroidUnwinder(getpid(), process_memory) {
+ initial_map_names_to_skip_.emplace_back(kUnwindstackLib);
+ }
+ AndroidLocalUnwinder(const std::vector<std::string>& initial_map_names_to_skip)
+ : AndroidUnwinder(getpid(), initial_map_names_to_skip) {
+ initial_map_names_to_skip_.emplace_back(kUnwindstackLib);
+ }
+ AndroidLocalUnwinder(const std::vector<std::string>& initial_map_names_to_skip,
+ const std::vector<std::string>& map_suffixes_to_ignore)
+ : AndroidUnwinder(getpid(), initial_map_names_to_skip, map_suffixes_to_ignore) {
+ initial_map_names_to_skip_.emplace_back(kUnwindstackLib);
+ }
+ virtual ~AndroidLocalUnwinder() = default;
+
+ protected:
+ static constexpr const char* kUnwindstackLib = "libunwindstack.so";
+
+ bool InternalInitialize(ErrorData& error) override;
+
+ bool InternalUnwind(std::optional<pid_t> tid, AndroidUnwinderData& data) override;
+};
+
+class AndroidRemoteUnwinder : public AndroidUnwinder {
+ public:
+ AndroidRemoteUnwinder(pid_t pid) : AndroidUnwinder(pid) {}
+ AndroidRemoteUnwinder(pid_t pid, std::shared_ptr<Memory>& process_memory)
+ : AndroidUnwinder(pid, process_memory) {}
+ AndroidRemoteUnwinder(pid_t pid, ArchEnum arch) : AndroidUnwinder(pid, arch) {}
+ AndroidRemoteUnwinder(pid_t pid, const std::vector<std::string> initial_map_names_to_skip)
+ : AndroidUnwinder(pid, initial_map_names_to_skip) {}
+ AndroidRemoteUnwinder(pid_t pid, const std::vector<std::string> initial_map_names_to_skip,
+ const std::vector<std::string> map_suffixes_to_ignore)
+ : AndroidUnwinder(pid, initial_map_names_to_skip, map_suffixes_to_ignore) {}
+ virtual ~AndroidRemoteUnwinder() = default;
+
+ protected:
+ bool InternalInitialize(ErrorData& error) override;
+
+ bool InternalUnwind(std::optional<pid_t> tid, AndroidUnwinderData& data) override;
+};
+
+} // namespace unwindstack