summaryrefslogtreecommitdiff
path: root/libunwindstack/include
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2020-09-23 15:51:46 -0700
committerChristopher Ferris <cferris@google.com>2020-09-24 18:46:23 -0700
commit1d2a2a492f49beded338c91be01a6bd39478deaf (patch)
treeefd610ed831aa7c61ebdf0772c444212e60d4995 /libunwindstack/include
parentfb162c7404514efe0b553d9b44ebff574df4d167 (diff)
downloadunwinding-1d2a2a492f49beded338c91be01a6bd39478deaf.tar.gz
Add arch member into Unwinder object.
This simplifies some of the logic and removes the need to pass an Arch value to functions that should already know about the arch it is operating on. Includes fixes for debuggerd/libbacktrace. Added new unit tests to cover new cases. Test: All unit tests pass. Test: Faked unwinder failing to verify debuggerd error messages display Test: properly in backtrace and tombstone. Change-Id: I439fcae0695befcfb1cb4c0a786cc74949d33425
Diffstat (limited to 'libunwindstack/include')
-rw-r--r--libunwindstack/include/unwindstack/Arch.h47
-rw-r--r--libunwindstack/include/unwindstack/Elf.h11
-rw-r--r--libunwindstack/include/unwindstack/Error.h21
-rw-r--r--libunwindstack/include/unwindstack/Regs.h7
-rw-r--r--libunwindstack/include/unwindstack/Unwinder.h42
5 files changed, 106 insertions, 22 deletions
diff --git a/libunwindstack/include/unwindstack/Arch.h b/libunwindstack/include/unwindstack/Arch.h
new file mode 100644
index 0000000..7060004
--- /dev/null
+++ b/libunwindstack/include/unwindstack/Arch.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 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 _LIBUNWINDSTACK_ARCH_H
+#define _LIBUNWINDSTACK_ARCH_H
+
+#include <stddef.h>
+
+namespace unwindstack {
+
+enum ArchEnum : uint8_t {
+ ARCH_UNKNOWN = 0,
+ ARCH_ARM,
+ ARCH_ARM64,
+ ARCH_X86,
+ ARCH_X86_64,
+ ARCH_MIPS,
+ ARCH_MIPS64,
+};
+
+static inline bool ArchIs32Bit(ArchEnum arch) {
+ switch (arch) {
+ case ARCH_ARM:
+ case ARCH_X86:
+ case ARCH_MIPS:
+ return true;
+ default:
+ return false;
+ }
+}
+
+} // namespace unwindstack
+
+#endif // _LIBUNWINDSTACK_ARCH_H
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h
index 472ed92..97614b1 100644
--- a/libunwindstack/include/unwindstack/Elf.h
+++ b/libunwindstack/include/unwindstack/Elf.h
@@ -25,6 +25,7 @@
#include <unordered_map>
#include <utility>
+#include <unwindstack/Arch.h>
#include <unwindstack/ElfInterface.h>
#include <unwindstack/Memory.h>
@@ -38,16 +39,6 @@ namespace unwindstack {
struct MapInfo;
class Regs;
-enum ArchEnum : uint8_t {
- ARCH_UNKNOWN = 0,
- ARCH_ARM,
- ARCH_ARM64,
- ARCH_X86,
- ARCH_X86_64,
- ARCH_MIPS,
- ARCH_MIPS64,
-};
-
class Elf {
public:
Elf(Memory* memory) : memory_(memory) {}
diff --git a/libunwindstack/include/unwindstack/Error.h b/libunwindstack/include/unwindstack/Error.h
index 66fefe7..0be4572 100644
--- a/libunwindstack/include/unwindstack/Error.h
+++ b/libunwindstack/include/unwindstack/Error.h
@@ -39,6 +39,27 @@ enum ErrorCode : uint8_t {
ERROR_INVALID_ELF, // Unwind in an invalid elf.
};
+static inline const char* GetErrorCodeString(ErrorCode error) {
+ switch (error) {
+ case ERROR_NONE:
+ return "None";
+ case ERROR_MEMORY_INVALID:
+ return "Memory Invalid";
+ case ERROR_UNWIND_INFO:
+ return "Unwind Info";
+ case ERROR_UNSUPPORTED:
+ return "Unsupported";
+ case ERROR_INVALID_MAP:
+ return "Invalid Map";
+ case ERROR_MAX_FRAMES_EXCEEDED:
+ return "Maximum Frames Exceeded";
+ case ERROR_REPEATED_FRAME:
+ return "Repeated Frame";
+ case ERROR_INVALID_ELF:
+ return "Invalid Elf";
+ }
+}
+
struct ErrorData {
ErrorCode code;
uint64_t address; // Only valid when code is ERROR_MEMORY_INVALID.
diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h
index 5f42565..1a2a704 100644
--- a/libunwindstack/include/unwindstack/Regs.h
+++ b/libunwindstack/include/unwindstack/Regs.h
@@ -24,11 +24,12 @@
#include <string>
#include <vector>
+#include <unwindstack/Arch.h>
+
namespace unwindstack {
// Forward declarations.
class Elf;
-enum ArchEnum : uint8_t;
class Memory;
class Regs {
@@ -52,7 +53,7 @@ class Regs {
virtual ArchEnum Arch() = 0;
- virtual bool Is32Bit() = 0;
+ bool Is32Bit() { return ArchIs32Bit(Arch()); }
virtual void* RawData() = 0;
virtual uint64_t pc() = 0;
@@ -96,8 +97,6 @@ class RegsImpl : public Regs {
: Regs(total_regs, return_loc), regs_(total_regs) {}
virtual ~RegsImpl() = default;
- bool Is32Bit() override { return sizeof(AddressType) == sizeof(uint32_t); }
-
inline AddressType& operator[](size_t reg) { return regs_[reg]; }
void* RawData() override { return regs_.data(); }
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h
index 3df8aad..b274c4c 100644
--- a/libunwindstack/include/unwindstack/Unwinder.h
+++ b/libunwindstack/include/unwindstack/Unwinder.h
@@ -24,6 +24,7 @@
#include <string>
#include <vector>
+#include <unwindstack/Arch.h>
#include <unwindstack/DexFiles.h>
#include <unwindstack/Error.h>
#include <unwindstack/JitDebug.h>
@@ -35,7 +36,6 @@ namespace unwindstack {
// Forward declarations.
class Elf;
-enum ArchEnum : uint8_t;
struct FrameData {
size_t num;
@@ -64,7 +64,11 @@ struct FrameData {
class Unwinder {
public:
Unwinder(size_t max_frames, Maps* maps, Regs* regs, std::shared_ptr<Memory> process_memory)
- : max_frames_(max_frames), maps_(maps), regs_(regs), process_memory_(process_memory) {
+ : max_frames_(max_frames),
+ maps_(maps),
+ regs_(regs),
+ process_memory_(process_memory),
+ arch_(regs->Arch()) {
frames_.reserve(max_frames);
}
Unwinder(size_t max_frames, Maps* maps, std::shared_ptr<Memory> process_memory)
@@ -74,8 +78,8 @@ class Unwinder {
virtual ~Unwinder() = default;
- void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr,
- const std::vector<std::string>* map_suffixes_to_ignore = nullptr);
+ virtual void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr,
+ const std::vector<std::string>* map_suffixes_to_ignore = nullptr);
size_t NumFrames() const { return frames_.size(); }
@@ -90,9 +94,14 @@ class Unwinder {
std::string FormatFrame(size_t frame_num) const;
std::string FormatFrame(const FrameData& frame) const;
- void SetJitDebug(JitDebug* jit_debug, ArchEnum arch);
+ void SetArch(ArchEnum arch) { arch_ = arch; };
+
+ void SetJitDebug(JitDebug* jit_debug);
- void SetRegs(Regs* regs) { regs_ = regs; }
+ void SetRegs(Regs* regs) {
+ regs_ = regs;
+ arch_ = regs_ != nullptr ? regs->Arch() : ARCH_UNKNOWN;
+ }
Maps* GetMaps() { return maps_; }
std::shared_ptr<Memory>& GetProcessMemory() { return process_memory_; }
@@ -107,11 +116,12 @@ class Unwinder {
void SetDisplayBuildID(bool display_build_id) { display_build_id_ = display_build_id; }
- void SetDexFiles(DexFiles* dex_files, ArchEnum arch);
+ void SetDexFiles(DexFiles* dex_files);
bool elf_from_memory_not_file() { return elf_from_memory_not_file_; }
ErrorCode LastErrorCode() { return last_error_.code; }
+ const char* LastErrorCodeString() { return GetErrorCodeString(last_error_.code); }
uint64_t LastErrorAddress() { return last_error_.address; }
uint64_t warnings() { return warnings_; }
@@ -126,6 +136,15 @@ class Unwinder {
protected:
Unwinder(size_t max_frames) : max_frames_(max_frames) { frames_.reserve(max_frames); }
+ Unwinder(size_t max_frames, ArchEnum arch) : max_frames_(max_frames), arch_(arch) {
+ frames_.reserve(max_frames);
+ }
+
+ void ClearErrors() {
+ warnings_ = WARNING_NONE;
+ last_error_.code = ERROR_NONE;
+ last_error_.address = 0;
+ }
void FillInDexFrame();
FrameData* FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t pc_adjustment);
@@ -145,20 +164,27 @@ class Unwinder {
bool elf_from_memory_not_file_ = false;
ErrorData last_error_;
uint64_t warnings_;
+ ArchEnum arch_ = ARCH_UNKNOWN;
};
class UnwinderFromPid : public Unwinder {
public:
UnwinderFromPid(size_t max_frames, pid_t pid) : Unwinder(max_frames), pid_(pid) {}
+ UnwinderFromPid(size_t max_frames, pid_t pid, ArchEnum arch)
+ : Unwinder(max_frames, arch), pid_(pid) {}
virtual ~UnwinderFromPid() = default;
- bool Init(ArchEnum arch);
+ bool Init();
+
+ void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr,
+ const std::vector<std::string>* map_suffixes_to_ignore = nullptr) override;
private:
pid_t pid_;
std::unique_ptr<Maps> maps_ptr_;
std::unique_ptr<JitDebug> jit_debug_ptr_;
std::unique_ptr<DexFiles> dex_files_ptr_;
+ bool initted_ = false;
};
} // namespace unwindstack