Introduce sentry for crash data collection

This commit is contained in:
Mark Roszko
2022-04-02 01:21:55 +00:00
parent 0625e20fc0
commit f0f33ef1d3
2266 changed files with 514726 additions and 0 deletions
@@ -0,0 +1,44 @@
/*
* 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,
};
static inline bool ArchIs32Bit(ArchEnum arch) {
switch (arch) {
case ARCH_ARM:
case ARCH_X86:
return true;
default:
return false;
}
}
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_ARCH_H
@@ -0,0 +1,79 @@
/*
* Copyright (C) 2018 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_DEX_FILES_H
#define _LIBUNWINDSTACK_DEX_FILES_H
#include <stdint.h>
#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
#include <vector>
#include <unwindstack/Global.h>
#include <unwindstack/Memory.h>
namespace unwindstack {
// Forward declarations.
class DexFile;
class Maps;
struct MapInfo;
enum ArchEnum : uint8_t;
class DexFiles : public Global {
public:
explicit DexFiles(std::shared_ptr<Memory>& memory);
DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs);
virtual ~DexFiles();
DexFile* GetDexFile(uint64_t dex_file_offset, MapInfo* info);
void GetMethodInformation(Maps* maps, MapInfo* info, uint64_t dex_pc, std::string* method_name,
uint64_t* method_offset);
private:
void Init(Maps* maps);
bool GetAddr(size_t index, uint64_t* addr);
uint64_t ReadEntryPtr32(uint64_t addr);
uint64_t ReadEntryPtr64(uint64_t addr);
bool ReadEntry32();
bool ReadEntry64();
bool ReadVariableData(uint64_t ptr_offset) override;
void ProcessArch() override;
std::mutex lock_;
bool initialized_ = false;
std::unordered_map<uint64_t, std::unique_ptr<DexFile>> files_;
uint64_t entry_addr_ = 0;
uint64_t (DexFiles::*read_entry_ptr_func_)(uint64_t) = nullptr;
bool (DexFiles::*read_entry_func_)() = nullptr;
std::vector<uint64_t> addrs_;
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_DEX_FILES_H
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2016 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_DWARF_ERROR_H
#define _LIBUNWINDSTACK_DWARF_ERROR_H
#include <stdint.h>
namespace unwindstack {
enum DwarfErrorCode : uint8_t {
DWARF_ERROR_NONE,
DWARF_ERROR_MEMORY_INVALID,
DWARF_ERROR_ILLEGAL_VALUE,
DWARF_ERROR_ILLEGAL_STATE,
DWARF_ERROR_STACK_INDEX_NOT_VALID,
DWARF_ERROR_NOT_IMPLEMENTED,
DWARF_ERROR_TOO_MANY_ITERATIONS,
DWARF_ERROR_CFA_NOT_DEFINED,
DWARF_ERROR_UNSUPPORTED_VERSION,
DWARF_ERROR_NO_FDES,
};
struct DwarfErrorData {
DwarfErrorCode code;
uint64_t address;
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_DWARF_ERROR_H
@@ -0,0 +1,54 @@
/*
* Copyright (C) 2016 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_DWARF_LOCATION_H
#define _LIBUNWINDSTACK_DWARF_LOCATION_H
#include <stdint.h>
#include <unordered_map>
namespace unwindstack {
struct DwarfCie;
enum DwarfLocationEnum : uint8_t {
DWARF_LOCATION_INVALID = 0,
DWARF_LOCATION_UNDEFINED,
DWARF_LOCATION_OFFSET,
DWARF_LOCATION_VAL_OFFSET,
DWARF_LOCATION_REGISTER,
DWARF_LOCATION_EXPRESSION,
DWARF_LOCATION_VAL_EXPRESSION,
DWARF_LOCATION_PSEUDO_REGISTER,
};
struct DwarfLocation {
DwarfLocationEnum type;
uint64_t values[2];
};
struct DwarfLocations : public std::unordered_map<uint32_t, DwarfLocation> {
const DwarfCie* cie;
// The range of PCs where the locations are valid (end is exclusive).
uint64_t pc_start = 0;
uint64_t pc_end = 0;
};
typedef DwarfLocations dwarf_loc_regs_t;
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_DWARF_LOCATION_H
@@ -0,0 +1,76 @@
/*
* Copyright (C) 2016 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_DWARF_MEMORY_H
#define _LIBUNWINDSTACK_DWARF_MEMORY_H
#include <stdint.h>
namespace unwindstack {
// Forward declarations.
class Memory;
class DwarfMemory {
public:
DwarfMemory(Memory* memory) : memory_(memory) {}
virtual ~DwarfMemory() = default;
bool ReadBytes(void* dst, size_t num_bytes);
template <typename SignedType>
bool ReadSigned(uint64_t* value);
bool ReadULEB128(uint64_t* value);
bool ReadSLEB128(int64_t* value);
template <typename AddressType>
size_t GetEncodedSize(uint8_t encoding);
bool AdjustEncodedValue(uint8_t encoding, uint64_t* value);
template <typename AddressType>
bool ReadEncodedValue(uint8_t encoding, uint64_t* value);
uint64_t cur_offset() { return cur_offset_; }
void set_cur_offset(uint64_t cur_offset) { cur_offset_ = cur_offset; }
void set_pc_offset(int64_t offset) { pc_offset_ = offset; }
void clear_pc_offset() { pc_offset_ = INT64_MAX; }
void set_data_offset(uint64_t offset) { data_offset_ = offset; }
void clear_data_offset() { data_offset_ = static_cast<uint64_t>(-1); }
void set_func_offset(uint64_t offset) { func_offset_ = offset; }
void clear_func_offset() { func_offset_ = static_cast<uint64_t>(-1); }
void set_text_offset(uint64_t offset) { text_offset_ = offset; }
void clear_text_offset() { text_offset_ = static_cast<uint64_t>(-1); }
private:
Memory* memory_;
uint64_t cur_offset_ = 0;
int64_t pc_offset_ = INT64_MAX;
uint64_t data_offset_ = static_cast<uint64_t>(-1);
uint64_t func_offset_ = static_cast<uint64_t>(-1);
uint64_t text_offset_ = static_cast<uint64_t>(-1);
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_DWARF_MEMORY_H
@@ -0,0 +1,177 @@
/*
* Copyright (C) 2016 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_DWARF_SECTION_H
#define _LIBUNWINDSTACK_DWARF_SECTION_H
#include <stdint.h>
#include <iterator>
#include <map>
#include <unordered_map>
#include <unwindstack/DwarfError.h>
#include <unwindstack/DwarfLocation.h>
#include <unwindstack/DwarfMemory.h>
#include <unwindstack/DwarfStructs.h>
namespace unwindstack {
// Forward declarations.
enum ArchEnum : uint8_t;
class Memory;
class Regs;
template <typename AddressType>
struct RegsInfo;
class DwarfSection {
public:
DwarfSection(Memory* memory);
virtual ~DwarfSection() = default;
class iterator : public std::iterator<std::bidirectional_iterator_tag, DwarfFde*> {
public:
iterator(DwarfSection* section, size_t index) : index_(index) {
section->GetFdes(&fdes_);
if (index_ == static_cast<size_t>(-1)) {
index_ = fdes_.size();
}
}
iterator& operator++() {
index_++;
return *this;
}
iterator& operator++(int increment) {
index_ += increment;
return *this;
}
iterator& operator--() {
index_--;
return *this;
}
iterator& operator--(int decrement) {
index_ -= decrement;
return *this;
}
bool operator==(const iterator& rhs) { return this->index_ == rhs.index_; }
bool operator!=(const iterator& rhs) { return this->index_ != rhs.index_; }
const DwarfFde* operator*() {
if (index_ > fdes_.size()) return nullptr;
return fdes_[index_];
}
private:
std::vector<const DwarfFde*> fdes_;
size_t index_ = 0;
};
iterator begin() { return iterator(this, 0); }
iterator end() { return iterator(this, static_cast<size_t>(-1)); }
DwarfErrorCode LastErrorCode() { return last_error_.code; }
uint64_t LastErrorAddress() { return last_error_.address; }
virtual bool Init(uint64_t offset, uint64_t size, int64_t section_bias) = 0;
virtual bool Eval(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*) = 0;
virtual bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde, ArchEnum arch) = 0;
virtual void GetFdes(std::vector<const DwarfFde*>* fdes) = 0;
virtual const DwarfFde* GetFdeFromPc(uint64_t pc) = 0;
virtual bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs,
ArchEnum arch) = 0;
virtual uint64_t GetCieOffsetFromFde32(uint32_t pointer) = 0;
virtual uint64_t GetCieOffsetFromFde64(uint64_t pointer) = 0;
virtual uint64_t AdjustPcFromFde(uint64_t pc) = 0;
bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished, bool* is_signal_frame);
protected:
DwarfMemory memory_;
DwarfErrorData last_error_{DWARF_ERROR_NONE, 0};
uint32_t cie32_value_ = 0;
uint64_t cie64_value_ = 0;
std::unordered_map<uint64_t, DwarfFde> fde_entries_;
std::unordered_map<uint64_t, DwarfCie> cie_entries_;
std::unordered_map<uint64_t, dwarf_loc_regs_t> cie_loc_regs_;
std::map<uint64_t, dwarf_loc_regs_t> loc_regs_; // Single row indexed by pc_end.
};
template <typename AddressType>
class DwarfSectionImpl : public DwarfSection {
public:
DwarfSectionImpl(Memory* memory) : DwarfSection(memory) {}
virtual ~DwarfSectionImpl() = default;
bool Init(uint64_t offset, uint64_t size, int64_t section_bias) override;
const DwarfCie* GetCieFromOffset(uint64_t offset);
const DwarfFde* GetFdeFromOffset(uint64_t offset);
const DwarfFde* GetFdeFromPc(uint64_t pc) override;
void GetFdes(std::vector<const DwarfFde*>* fdes) override;
bool EvalRegister(const DwarfLocation* loc, uint32_t reg, AddressType* reg_ptr, void* info);
bool Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs,
Regs* regs, bool* finished) override;
bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs,
ArchEnum arch) override;
bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde, ArchEnum arch) override;
protected:
bool GetNextCieOrFde(const DwarfFde** fde_entry);
bool FillInCieHeader(DwarfCie* cie);
bool FillInCie(DwarfCie* cie);
bool FillInFdeHeader(DwarfFde* fde);
bool FillInFde(DwarfFde* fde);
bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value,
RegsInfo<AddressType>* regs_info, bool* is_dex_pc);
void InsertFde(const DwarfFde* fde);
int64_t section_bias_ = 0;
uint64_t entries_offset_ = 0;
uint64_t entries_end_ = 0;
uint64_t next_entries_offset_ = 0;
uint64_t pc_offset_ = 0;
std::map<uint64_t, std::pair<uint64_t, const DwarfFde*>> fdes_;
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_DWARF_SECTION_H
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2016 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_DWARF_STRUCTS_H
#define _LIBUNWINDSTACK_DWARF_STRUCTS_H
#include <stdint.h>
#include <vector>
namespace unwindstack {
struct DwarfCie {
uint8_t version = 0;
uint8_t fde_address_encoding = 0;
uint8_t lsda_encoding = 0;
uint8_t segment_size = 0;
std::vector<char> augmentation_string;
uint64_t personality_handler = 0;
uint64_t cfa_instructions_offset = 0;
uint64_t cfa_instructions_end = 0;
uint64_t code_alignment_factor = 0;
int64_t data_alignment_factor = 0;
uint64_t return_address_register = 0;
bool is_signal_frame = false;
};
struct DwarfFde {
uint64_t cie_offset = 0;
uint64_t cfa_instructions_offset = 0;
uint64_t cfa_instructions_end = 0;
uint64_t pc_start = 0;
uint64_t pc_end = 0;
uint64_t lsda_address = 0;
const DwarfCie* cie = nullptr;
};
constexpr uint16_t CFA_REG = static_cast<uint16_t>(-1);
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_DWARF_STRUCTS_H
@@ -0,0 +1,130 @@
/*
* Copyright (C) 2016 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_ELF_H
#define _LIBUNWINDSTACK_ELF_H
#include <stddef.h>
#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
#include <utility>
#include <unwindstack/Arch.h>
#include <unwindstack/ElfInterface.h>
#include <unwindstack/Memory.h>
#if !defined(EM_AARCH64)
#define EM_AARCH64 183
#endif
namespace unwindstack {
// Forward declaration.
struct MapInfo;
class Regs;
class Elf {
public:
Elf(Memory* memory) : memory_(memory) {}
virtual ~Elf() = default;
bool Init();
void InitGnuDebugdata();
void Invalidate();
std::string GetSoname();
bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset);
bool GetGlobalVariableOffset(const std::string& name, uint64_t* memory_offset);
uint64_t GetRelPc(uint64_t pc, const MapInfo* map_info);
bool StepIfSignalHandler(uint64_t rel_pc, Regs* regs, Memory* process_memory);
bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished,
bool* is_signal_frame);
ElfInterface* CreateInterfaceFromMemory(Memory* memory);
std::string GetBuildID();
int64_t GetLoadBias() { return load_bias_; }
bool IsValidPc(uint64_t pc);
void GetLastError(ErrorData* data);
ErrorCode GetLastErrorCode();
uint64_t GetLastErrorAddress();
bool valid() { return valid_; }
uint32_t machine_type() { return machine_type_; }
uint8_t class_type() { return class_type_; }
ArchEnum arch() { return arch_; }
Memory* memory() { return memory_.get(); }
ElfInterface* interface() { return interface_.get(); }
ElfInterface* gnu_debugdata_interface() { return gnu_debugdata_interface_.get(); }
static bool IsValidElf(Memory* memory);
static bool GetInfo(Memory* memory, uint64_t* size);
static int64_t GetLoadBias(Memory* memory);
static std::string GetBuildID(Memory* memory);
static void SetCachingEnabled(bool enable);
static bool CachingEnabled() { return cache_enabled_; }
static void CacheLock();
static void CacheUnlock();
static void CacheAdd(MapInfo* info);
static bool CacheGet(MapInfo* info);
static bool CacheAfterCreateMemory(MapInfo* info);
protected:
bool valid_ = false;
int64_t load_bias_ = 0;
std::unique_ptr<ElfInterface> interface_;
std::unique_ptr<Memory> memory_;
uint32_t machine_type_;
uint8_t class_type_;
ArchEnum arch_;
// Protect calls that can modify internal state of the interface object.
std::mutex lock_;
std::unique_ptr<Memory> gnu_debugdata_memory_;
std::unique_ptr<ElfInterface> gnu_debugdata_interface_;
static bool cache_enabled_;
static std::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>* cache_;
static std::mutex* cache_lock_;
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_ELF_H
@@ -0,0 +1,223 @@
/*
* Copyright (C) 2016 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_ELF_INTERFACE_H
#define _LIBUNWINDSTACK_ELF_INTERFACE_H
#include <elf.h>
#include <stdint.h>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <unwindstack/DwarfSection.h>
#include <unwindstack/Error.h>
namespace unwindstack {
// Forward declarations.
class Memory;
class Regs;
class Symbols;
struct LoadInfo {
uint64_t offset;
uint64_t table_offset;
size_t table_size;
};
enum : uint8_t {
SONAME_UNKNOWN = 0,
SONAME_VALID,
SONAME_INVALID,
};
struct ElfTypes32 {
using AddressType = uint32_t;
using Dyn = Elf32_Dyn;
using Ehdr = Elf32_Ehdr;
using Nhdr = Elf32_Nhdr;
using Phdr = Elf32_Phdr;
using Shdr = Elf32_Shdr;
using Sym = Elf32_Sym;
};
struct ElfTypes64 {
using AddressType = uint64_t;
using Dyn = Elf64_Dyn;
using Ehdr = Elf64_Ehdr;
using Nhdr = Elf64_Nhdr;
using Phdr = Elf64_Phdr;
using Shdr = Elf64_Shdr;
using Sym = Elf64_Sym;
};
class ElfInterface {
public:
ElfInterface(Memory* memory) : memory_(memory) {}
virtual ~ElfInterface();
virtual bool Init(int64_t* load_bias) = 0;
virtual void InitHeaders() = 0;
virtual std::string GetSoname() = 0;
virtual bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* offset) = 0;
virtual bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) = 0;
virtual std::string GetBuildID() = 0;
virtual bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished,
bool* is_signal_frame);
virtual bool IsValidPc(uint64_t pc);
Memory* CreateGnuDebugdataMemory();
Memory* memory() { return memory_; }
const std::unordered_map<uint64_t, LoadInfo>& pt_loads() { return pt_loads_; }
void SetGnuDebugdataInterface(ElfInterface* interface) { gnu_debugdata_interface_ = interface; }
uint64_t dynamic_offset() { return dynamic_offset_; }
uint64_t dynamic_vaddr_start() { return dynamic_vaddr_start_; }
uint64_t dynamic_vaddr_end() { return dynamic_vaddr_end_; }
uint64_t data_offset() { return data_offset_; }
uint64_t data_vaddr_start() { return data_vaddr_start_; }
uint64_t data_vaddr_end() { return data_vaddr_end_; }
uint64_t eh_frame_hdr_offset() { return eh_frame_hdr_offset_; }
int64_t eh_frame_hdr_section_bias() { return eh_frame_hdr_section_bias_; }
uint64_t eh_frame_hdr_size() { return eh_frame_hdr_size_; }
uint64_t eh_frame_offset() { return eh_frame_offset_; }
int64_t eh_frame_section_bias() { return eh_frame_section_bias_; }
uint64_t eh_frame_size() { return eh_frame_size_; }
uint64_t debug_frame_offset() { return debug_frame_offset_; }
int64_t debug_frame_section_bias() { return debug_frame_section_bias_; }
uint64_t debug_frame_size() { return debug_frame_size_; }
uint64_t gnu_debugdata_offset() { return gnu_debugdata_offset_; }
uint64_t gnu_debugdata_size() { return gnu_debugdata_size_; }
uint64_t gnu_build_id_offset() { return gnu_build_id_offset_; }
uint64_t gnu_build_id_size() { return gnu_build_id_size_; }
DwarfSection* eh_frame() { return eh_frame_.get(); }
DwarfSection* debug_frame() { return debug_frame_.get(); }
const ErrorData& last_error() { return last_error_; }
ErrorCode LastErrorCode() { return last_error_.code; }
uint64_t LastErrorAddress() { return last_error_.address; }
template <typename EhdrType, typename PhdrType>
static int64_t GetLoadBias(Memory* memory);
template <typename EhdrType, typename ShdrType, typename NhdrType>
static std::string ReadBuildIDFromMemory(Memory* memory);
protected:
virtual void HandleUnknownType(uint32_t, uint64_t, uint64_t) {}
Memory* memory_;
std::unordered_map<uint64_t, LoadInfo> pt_loads_;
// Stored elf data.
uint64_t dynamic_offset_ = 0;
uint64_t dynamic_vaddr_start_ = 0;
uint64_t dynamic_vaddr_end_ = 0;
uint64_t data_offset_ = 0;
uint64_t data_vaddr_start_ = 0;
uint64_t data_vaddr_end_ = 0;
uint64_t eh_frame_hdr_offset_ = 0;
int64_t eh_frame_hdr_section_bias_ = 0;
uint64_t eh_frame_hdr_size_ = 0;
uint64_t eh_frame_offset_ = 0;
int64_t eh_frame_section_bias_ = 0;
uint64_t eh_frame_size_ = 0;
uint64_t debug_frame_offset_ = 0;
int64_t debug_frame_section_bias_ = 0;
uint64_t debug_frame_size_ = 0;
uint64_t gnu_debugdata_offset_ = 0;
uint64_t gnu_debugdata_size_ = 0;
uint64_t gnu_build_id_offset_ = 0;
uint64_t gnu_build_id_size_ = 0;
uint8_t soname_type_ = SONAME_UNKNOWN;
std::string soname_;
ErrorData last_error_{ERROR_NONE, 0};
std::unique_ptr<DwarfSection> eh_frame_;
std::unique_ptr<DwarfSection> debug_frame_;
// The Elf object owns the gnu_debugdata interface object.
ElfInterface* gnu_debugdata_interface_ = nullptr;
std::vector<Symbols*> symbols_;
std::vector<std::pair<uint64_t, uint64_t>> strtabs_;
};
template <typename ElfTypes>
class ElfInterfaceImpl : public ElfInterface {
public:
using AddressType = typename ElfTypes::AddressType;
using DynType = typename ElfTypes::Dyn;
using EhdrType = typename ElfTypes::Ehdr;
using NhdrType = typename ElfTypes::Nhdr;
using PhdrType = typename ElfTypes::Phdr;
using ShdrType = typename ElfTypes::Shdr;
using SymType = typename ElfTypes::Sym;
ElfInterfaceImpl(Memory* memory) : ElfInterface(memory) {}
virtual ~ElfInterfaceImpl() = default;
bool Init(int64_t* load_bias) override { return ReadAllHeaders(load_bias); }
void InitHeaders() override;
std::string GetSoname() override;
bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override;
bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) override;
std::string GetBuildID() override { return ReadBuildID(); }
static void GetMaxSize(Memory* memory, uint64_t* size);
protected:
bool ReadAllHeaders(int64_t* load_bias);
void ReadProgramHeaders(const EhdrType& ehdr, int64_t* load_bias);
void ReadSectionHeaders(const EhdrType& ehdr);
std::string ReadBuildID();
};
using ElfInterface32 = ElfInterfaceImpl<ElfTypes32>;
using ElfInterface64 = ElfInterfaceImpl<ElfTypes64>;
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_ELF_INTERFACE_H
@@ -0,0 +1,81 @@
/*
* Copyright (C) 2018 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_ERROR_H
#define _LIBUNWINDSTACK_ERROR_H
#include <stdint.h>
namespace unwindstack {
// A bit map of warnings, multiple warnings can be set at the same time.
enum WarningCode : uint64_t {
WARNING_NONE = 0,
WARNING_DEX_PC_NOT_IN_MAP = 0x1, // A dex pc was found, but it doesn't exist
// in any valid map.
};
enum ErrorCode : uint8_t {
ERROR_NONE, // No error.
ERROR_MEMORY_INVALID, // Memory read failed.
ERROR_UNWIND_INFO, // Unable to use unwind information to unwind.
ERROR_UNSUPPORTED, // Encountered unsupported feature.
ERROR_INVALID_MAP, // Unwind in an invalid map.
ERROR_MAX_FRAMES_EXCEEDED, // The number of frames exceed the total allowed.
ERROR_REPEATED_FRAME, // The last frame has the same pc/sp as the next.
ERROR_INVALID_ELF, // Unwind in an invalid elf.
ERROR_THREAD_DOES_NOT_EXIST, // Attempt to unwind a local thread that does
// not exist.
ERROR_THREAD_TIMEOUT, // Timeout trying to unwind a local thread.
ERROR_SYSTEM_CALL, // System call failed while unwinding.
};
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";
case ERROR_THREAD_DOES_NOT_EXIST:
return "Thread Does Not Exist";
case ERROR_THREAD_TIMEOUT:
return "Thread Timeout";
case ERROR_SYSTEM_CALL:
return "System Call Failed";
}
}
struct ErrorData {
ErrorCode code;
uint64_t address; // Only valid when code is ERROR_MEMORY_INVALID.
// Indicates the failing address.
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_ERROR_H
@@ -0,0 +1,63 @@
/*
* Copyright (C) 2018 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_GLOBAL_H
#define _LIBUNWINDSTACK_GLOBAL_H
#include <stdint.h>
#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
#include <vector>
#include <unwindstack/Elf.h>
#include <unwindstack/Memory.h>
namespace unwindstack {
// Forward declarations.
class Maps;
struct MapInfo;
class Global {
public:
explicit Global(std::shared_ptr<Memory>& memory);
Global(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs);
virtual ~Global() = default;
void SetArch(ArchEnum arch);
ArchEnum arch() { return arch_; }
protected:
bool Searchable(const std::string& name);
void FindAndReadVariable(Maps* maps, const char* variable);
virtual bool ReadVariableData(uint64_t offset) = 0;
virtual void ProcessArch() = 0;
ArchEnum arch_ = ARCH_UNKNOWN;
std::shared_ptr<Memory> memory_;
std::vector<std::string> search_libs_;
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_GLOBAL_H
@@ -0,0 +1,71 @@
/*
* Copyright (C) 2017 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_JIT_DEBUG_H
#define _LIBUNWINDSTACK_JIT_DEBUG_H
#include <stdint.h>
#include <memory>
#include <mutex>
#include <string>
#include <vector>
#include <unwindstack/Global.h>
#include <unwindstack/Memory.h>
namespace unwindstack {
// Forward declarations.
class Elf;
class Maps;
enum ArchEnum : uint8_t;
class JitDebug : public Global {
public:
explicit JitDebug(std::shared_ptr<Memory>& memory);
JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs);
virtual ~JitDebug();
Elf* GetElf(Maps* maps, uint64_t pc);
private:
void Init(Maps* maps);
uint64_t (JitDebug::*read_descriptor_func_)(uint64_t) = nullptr;
uint64_t (JitDebug::*read_entry_func_)(uint64_t*, uint64_t*) = nullptr;
uint64_t ReadDescriptor32(uint64_t);
uint64_t ReadDescriptor64(uint64_t);
uint64_t ReadEntry32Pack(uint64_t* start, uint64_t* size);
uint64_t ReadEntry32Pad(uint64_t* start, uint64_t* size);
uint64_t ReadEntry64(uint64_t* start, uint64_t* size);
bool ReadVariableData(uint64_t ptr_offset) override;
void ProcessArch() override;
uint64_t entry_addr_ = 0;
bool initialized_ = false;
std::vector<Elf*> elf_list_;
std::mutex lock_;
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_JIT_DEBUG_H
@@ -0,0 +1,86 @@
/*
* Copyright (C) 2018 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_LOCAL_UNWINDER_H
#define _LIBUNWINDSTACK_LOCAL_UNWINDER_H
#include <pthread.h>
#include <stdint.h>
#include <sys/types.h>
#include <memory>
#include <string>
#include <vector>
#include <unwindstack/Error.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>
namespace unwindstack {
// Forward declarations.
class Elf;
struct MapInfo;
struct LocalFrameData {
LocalFrameData(MapInfo* map_info, uint64_t pc, uint64_t rel_pc, const std::string& function_name,
uint64_t function_offset)
: map_info(map_info),
pc(pc),
rel_pc(rel_pc),
function_name(function_name),
function_offset(function_offset) {}
MapInfo* map_info;
uint64_t pc;
uint64_t rel_pc;
std::string function_name;
uint64_t function_offset;
};
// This is a specialized class that should only be used for doing local unwinds.
// The Unwind call can be made as multiple times on the same object, and it can
// be called by multiple threads at the same time.
// It is designed to be used in debugging circumstances to get a stack trace
// as fast as possible.
class LocalUnwinder {
public:
LocalUnwinder() = default;
LocalUnwinder(const std::vector<std::string>& skip_libraries) : skip_libraries_(skip_libraries) {}
~LocalUnwinder() = default;
bool Init();
bool Unwind(std::vector<LocalFrameData>* frame_info, size_t max_frames);
bool ShouldSkipLibrary(const std::string& map_name);
MapInfo* GetMapInfo(uint64_t pc);
ErrorCode LastErrorCode() { return last_error_.code; }
uint64_t LastErrorAddress() { return last_error_.address; }
private:
pthread_rwlock_t maps_rwlock_;
std::unique_ptr<LocalUpdatableMaps> maps_ = nullptr;
std::shared_ptr<Memory> process_memory_;
std::vector<std::string> skip_libraries_;
ErrorData last_error_;
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_LOCAL_UNWINDER_H
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2016 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_LOG_H
#define _LIBUNWINDSTACK_LOG_H
#include <stdint.h>
namespace unwindstack {
void log_to_stdout(bool enable);
void log(uint8_t indent, const char* format, ...);
void log_async_safe(const char* format, ...);
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_LOG_H
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2017 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_MACHINE_ARM_H
#define _LIBUNWINDSTACK_MACHINE_ARM_H
#include <stdint.h>
namespace unwindstack {
enum ArmReg : uint16_t {
ARM_REG_R0 = 0,
ARM_REG_R1,
ARM_REG_R2,
ARM_REG_R3,
ARM_REG_R4,
ARM_REG_R5,
ARM_REG_R6,
ARM_REG_R7,
ARM_REG_R8,
ARM_REG_R9,
ARM_REG_R10,
ARM_REG_R11,
ARM_REG_R12,
ARM_REG_R13,
ARM_REG_R14,
ARM_REG_R15,
ARM_REG_LAST,
ARM_REG_SP = ARM_REG_R13,
ARM_REG_LR = ARM_REG_R14,
ARM_REG_PC = ARM_REG_R15,
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_MACHINE_ARM_H
@@ -0,0 +1,74 @@
/*
* Copyright (C) 2017 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_MACHINE_ARM64_H
#define _LIBUNWINDSTACK_MACHINE_ARM64_H
#include <stdint.h>
namespace unwindstack {
enum Arm64Reg : uint16_t {
ARM64_REG_R0 = 0,
ARM64_REG_R1,
ARM64_REG_R2,
ARM64_REG_R3,
ARM64_REG_R4,
ARM64_REG_R5,
ARM64_REG_R6,
ARM64_REG_R7,
ARM64_REG_R8,
ARM64_REG_R9,
ARM64_REG_R10,
ARM64_REG_R11,
ARM64_REG_R12,
ARM64_REG_R13,
ARM64_REG_R14,
ARM64_REG_R15,
ARM64_REG_R16,
ARM64_REG_R17,
ARM64_REG_R18,
ARM64_REG_R19,
ARM64_REG_R20,
ARM64_REG_R21,
ARM64_REG_R22,
ARM64_REG_R23,
ARM64_REG_R24,
ARM64_REG_R25,
ARM64_REG_R26,
ARM64_REG_R27,
ARM64_REG_R28,
ARM64_REG_R29,
ARM64_REG_R30,
ARM64_REG_R31,
ARM64_REG_PC,
ARM64_REG_PSTATE,
ARM64_REG_LAST,
ARM64_REG_SP = ARM64_REG_R31,
ARM64_REG_LR = ARM64_REG_R30,
// Pseudo registers. These are not machine registers.
// AARCH64 Return address signed state pseudo-register
ARM64_PREG_RA_SIGN_STATE = 34,
ARM64_PREG_FIRST = ARM64_PREG_RA_SIGN_STATE,
ARM64_PREG_LAST,
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_MACHINE_ARM64_H
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2017 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_MACHINE_X86_H
#define _LIBUNWINDSTACK_MACHINE_X86_H
#include <stdint.h>
namespace unwindstack {
// Matches the numbers for the registers as generated by compilers.
// If this is changed, then unwinding will fail.
enum X86Reg : uint16_t {
X86_REG_EAX = 0,
X86_REG_ECX = 1,
X86_REG_EDX = 2,
X86_REG_EBX = 3,
X86_REG_ESP = 4,
X86_REG_EBP = 5,
X86_REG_ESI = 6,
X86_REG_EDI = 7,
X86_REG_EIP = 8,
X86_REG_EFL = 9,
X86_REG_CS = 10,
X86_REG_SS = 11,
X86_REG_DS = 12,
X86_REG_ES = 13,
X86_REG_FS = 14,
X86_REG_GS = 15,
X86_REG_LAST,
X86_REG_SP = X86_REG_ESP,
X86_REG_PC = X86_REG_EIP,
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_MACHINE_X86_H
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2017 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_MACHINE_X86_64_H
#define _LIBUNWINDSTACK_MACHINE_X86_64_H
#include <stdint.h>
namespace unwindstack {
// Matches the numbers for the registers as generated by compilers.
// If this is changed, then unwinding will fail.
enum X86_64Reg : uint16_t {
X86_64_REG_RAX = 0,
X86_64_REG_RDX = 1,
X86_64_REG_RCX = 2,
X86_64_REG_RBX = 3,
X86_64_REG_RSI = 4,
X86_64_REG_RDI = 5,
X86_64_REG_RBP = 6,
X86_64_REG_RSP = 7,
X86_64_REG_R8 = 8,
X86_64_REG_R9 = 9,
X86_64_REG_R10 = 10,
X86_64_REG_R11 = 11,
X86_64_REG_R12 = 12,
X86_64_REG_R13 = 13,
X86_64_REG_R14 = 14,
X86_64_REG_R15 = 15,
X86_64_REG_RIP = 16,
X86_64_REG_LAST,
X86_64_REG_SP = X86_64_REG_RSP,
X86_64_REG_PC = X86_64_REG_RIP,
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_MACHINE_X86_64_H
@@ -0,0 +1,132 @@
/*
* Copyright (C) 2016 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_MAP_INFO_H
#define _LIBUNWINDSTACK_MAP_INFO_H
#include <stdint.h>
#include <atomic>
#include <memory>
#include <mutex>
#include <string>
#include <unwindstack/Elf.h>
namespace unwindstack {
class MemoryFileAtOffset;
struct MapInfo {
MapInfo(MapInfo* prev_map, MapInfo* prev_real_map, uint64_t start, uint64_t end, uint64_t offset,
uint64_t flags, const char* name)
: start(start),
end(end),
offset(offset),
flags(flags),
name(name),
prev_map(prev_map),
prev_real_map(prev_real_map),
load_bias(INT64_MAX),
build_id(0) {
if (prev_real_map != nullptr) prev_real_map->next_real_map = this;
}
MapInfo(MapInfo* prev_map, MapInfo* prev_real_map, uint64_t start, uint64_t end, uint64_t offset,
uint64_t flags, const std::string& name)
: start(start),
end(end),
offset(offset),
flags(flags),
name(name),
prev_map(prev_map),
prev_real_map(prev_real_map),
load_bias(INT64_MAX),
build_id(0) {
if (prev_real_map != nullptr) prev_real_map->next_real_map = this;
}
~MapInfo();
uint64_t start = 0;
uint64_t end = 0;
uint64_t offset = 0;
uint16_t flags = 0;
std::string name;
std::shared_ptr<Elf> elf;
// The offset of the beginning of this mapping to the beginning of the
// ELF file.
// elf_offset == offset - elf_start_offset.
// This value is only non-zero if the offset is non-zero but there is
// no elf signature found at that offset.
uint64_t elf_offset = 0;
// This value is the offset into the file of the map in memory that is the
// start of the elf. This is not equal to offset when the linker splits
// shared libraries into a read-only and read-execute map.
uint64_t elf_start_offset = 0;
MapInfo* prev_map = nullptr;
// This is the previous map that is not empty with a 0 offset. For
// example, this set of maps:
// 1000-2000 r--p 000000 00:00 0 libc.so
// 2000-3000 ---p 000000 00:00 0 libc.so
// 3000-4000 r-xp 003000 00:00 0 libc.so
// The last map's prev_map would point to the 2000-3000 map, while the
// prev_real_map would point to the 1000-2000 map.
MapInfo* prev_real_map = nullptr;
// Same as above but set to point to the next map.
MapInfo* next_real_map = nullptr;
std::atomic_int64_t load_bias;
// This is a pointer to a new'd std::string.
// Using an atomic value means that we don't need to lock and will
// make it easier to move to a fine grained lock in the future.
std::atomic<std::string*> build_id;
// Set to true if the elf file data is coming from memory.
bool memory_backed_elf = false;
// This function guarantees it will never return nullptr.
Elf* GetElf(const std::shared_ptr<Memory>& process_memory, ArchEnum expected_arch);
uint64_t GetLoadBias(const std::shared_ptr<Memory>& process_memory);
Memory* CreateMemory(const std::shared_ptr<Memory>& process_memory);
bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset);
// Returns the raw build id read from the elf data.
const std::string& GetBuildID();
// Returns the printable version of the build id (hex dump of raw data).
std::string GetPrintableBuildID();
inline bool IsBlank() { return offset == 0 && flags == 0 && name.empty(); }
private:
MapInfo(const MapInfo&) = delete;
void operator=(const MapInfo&) = delete;
Memory* GetFileMemory();
bool InitFileMemoryFromPreviousReadOnlyMap(MemoryFileAtOffset* memory);
// Protect the creation of the elf object.
std::mutex mutex_;
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_MAP_INFO_H
@@ -0,0 +1,136 @@
/*
* Copyright (C) 2016 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_MAPS_H
#define _LIBUNWINDSTACK_MAPS_H
#include <sys/types.h>
#include <unistd.h>
#include <memory>
#include <string>
#include <vector>
#include <unwindstack/MapInfo.h>
namespace unwindstack {
// Special flag to indicate a map is in /dev/. However, a map in
// /dev/ashmem/... does not set this flag.
static constexpr int MAPS_FLAGS_DEVICE_MAP = 0x8000;
// Special flag to indicate that this map represents an elf file
// created by ART for use with the gdb jit debug interface.
// This should only ever appear in offline maps data.
static constexpr int MAPS_FLAGS_JIT_SYMFILE_MAP = 0x4000;
class Maps {
public:
virtual ~Maps() = default;
Maps() = default;
// Maps are not copyable but movable, because they own pointers to MapInfo
// objects.
Maps(const Maps&) = delete;
Maps& operator=(const Maps&) = delete;
Maps(Maps&&) = default;
Maps& operator=(Maps&&) = default;
MapInfo* Find(uint64_t pc);
virtual bool Parse();
virtual const std::string GetMapsFile() const { return ""; }
void Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, const std::string& name,
uint64_t load_bias);
void Sort();
typedef std::vector<std::unique_ptr<MapInfo>>::iterator iterator;
iterator begin() { return maps_.begin(); }
iterator end() { return maps_.end(); }
typedef std::vector<std::unique_ptr<MapInfo>>::const_iterator const_iterator;
const_iterator begin() const { return maps_.begin(); }
const_iterator end() const { return maps_.end(); }
size_t Total() { return maps_.size(); }
MapInfo* Get(size_t index) {
if (index >= maps_.size()) return nullptr;
return maps_[index].get();
}
protected:
std::vector<std::unique_ptr<MapInfo>> maps_;
};
class RemoteMaps : public Maps {
public:
RemoteMaps(pid_t pid) : pid_(pid) {}
virtual ~RemoteMaps() = default;
virtual const std::string GetMapsFile() const override;
private:
pid_t pid_;
};
class LocalMaps : public RemoteMaps {
public:
LocalMaps() : RemoteMaps(getpid()) {}
virtual ~LocalMaps() = default;
};
class LocalUpdatableMaps : public Maps {
public:
LocalUpdatableMaps() : Maps() {}
virtual ~LocalUpdatableMaps() = default;
bool Reparse();
const std::string GetMapsFile() const override;
protected:
std::vector<std::unique_ptr<MapInfo>> saved_maps_;
};
class BufferMaps : public Maps {
public:
BufferMaps(const char* buffer) : buffer_(buffer) {}
virtual ~BufferMaps() = default;
bool Parse() override;
private:
const char* buffer_;
};
class FileMaps : public Maps {
public:
FileMaps(const std::string& file) : file_(file) {}
virtual ~FileMaps() = default;
const std::string GetMapsFile() const override { return file_; }
protected:
const std::string file_;
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_MAPS_H
@@ -0,0 +1,62 @@
/*
* Copyright (C) 2016 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_MEMORY_H
#define _LIBUNWINDSTACK_MEMORY_H
#include <stdint.h>
#include <sys/types.h>
#include <unistd.h>
#include <memory>
#include <string>
namespace unwindstack {
class Memory {
public:
Memory() = default;
virtual ~Memory() = default;
static std::shared_ptr<Memory> CreateProcessMemory(pid_t pid);
static std::shared_ptr<Memory> CreateProcessMemoryCached(pid_t pid);
static std::shared_ptr<Memory> CreateOfflineMemory(const uint8_t* data, uint64_t start,
uint64_t end);
static std::unique_ptr<Memory> CreateFileMemory(const std::string& path, uint64_t offset);
virtual bool ReadString(uint64_t addr, std::string* dst, size_t max_read);
virtual void Clear() {}
virtual bool IsLocal() const { return false; }
virtual size_t Read(uint64_t addr, void* dst, size_t size) = 0;
virtual long ReadTag(uint64_t) { return -1; }
bool ReadFully(uint64_t addr, void* dst, size_t size);
inline bool Read32(uint64_t addr, uint32_t* dst) {
return ReadFully(addr, dst, sizeof(uint32_t));
}
inline bool Read64(uint64_t addr, uint64_t* dst) {
return ReadFully(addr, dst, sizeof(uint64_t));
}
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_MEMORY_H
@@ -0,0 +1,118 @@
/*
* Copyright (C) 2016 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_REGS_H
#define _LIBUNWINDSTACK_REGS_H
#include <stdint.h>
#include <unistd.h>
#include <functional>
#include <string>
#include <vector>
#include <unwindstack/Arch.h>
namespace unwindstack {
// Forward declarations.
class Elf;
class Memory;
class Regs {
public:
enum LocationEnum : uint8_t {
LOCATION_UNKNOWN = 0,
LOCATION_REGISTER,
LOCATION_SP_OFFSET,
};
struct Location {
Location(LocationEnum type, int16_t value) : type(type), value(value) {}
LocationEnum type;
int16_t value;
};
Regs(uint16_t total_regs, const Location& return_loc)
: total_regs_(total_regs), return_loc_(return_loc) {}
virtual ~Regs() = default;
virtual ArchEnum Arch() = 0;
bool Is32Bit() { return ArchIs32Bit(Arch()); }
virtual void* RawData() = 0;
virtual uint64_t pc() = 0;
virtual uint64_t sp() = 0;
virtual void set_pc(uint64_t pc) = 0;
virtual void set_sp(uint64_t sp) = 0;
uint64_t dex_pc() { return dex_pc_; }
void set_dex_pc(uint64_t dex_pc) { dex_pc_ = dex_pc; }
virtual void ResetPseudoRegisters() {}
virtual bool SetPseudoRegister(uint16_t, uint64_t) { return false; }
virtual bool GetPseudoRegister(uint16_t, uint64_t*) { return false; }
virtual bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) = 0;
virtual bool SetPcFromReturnAddress(Memory* process_memory) = 0;
virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) = 0;
uint16_t total_regs() { return total_regs_; }
virtual Regs* Clone() = 0;
static ArchEnum CurrentArch();
static Regs* RemoteGet(pid_t pid);
static Regs* CreateFromUcontext(ArchEnum arch, void* ucontext);
static Regs* CreateFromLocal();
protected:
uint16_t total_regs_;
Location return_loc_;
uint64_t dex_pc_ = 0;
};
template <typename AddressType>
class RegsImpl : public Regs {
public:
RegsImpl(uint16_t total_regs, Location return_loc)
: Regs(total_regs, return_loc), regs_(total_regs) {}
virtual ~RegsImpl() = default;
inline AddressType& operator[](size_t reg) { return regs_[reg]; }
void* RawData() override { return regs_.data(); }
virtual void IterateRegisters(std::function<void(const char*, uint64_t)> fn) override {
for (size_t i = 0; i < regs_.size(); ++i) {
fn(std::to_string(i).c_str(), regs_[i]);
}
}
protected:
std::vector<AddressType> regs_;
};
uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf, ArchEnum arch);
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_REGS_H
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2016 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_REGS_ARM_H
#define _LIBUNWINDSTACK_REGS_ARM_H
#include <stdint.h>
#include <functional>
#include <unwindstack/Elf.h>
#include <unwindstack/Regs.h>
namespace unwindstack {
// Forward declarations.
class Memory;
class RegsArm : public RegsImpl<uint32_t> {
public:
RegsArm();
virtual ~RegsArm() = default;
ArchEnum Arch() override final;
bool SetPcFromReturnAddress(Memory* process_memory) override;
bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
uint64_t pc() override;
uint64_t sp() override;
void set_pc(uint64_t pc) override;
void set_sp(uint64_t sp) override;
Regs* Clone() override final;
static Regs* Read(void* data);
static Regs* CreateFromUcontext(void* ucontext);
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_REGS_ARM_H
@@ -0,0 +1,75 @@
/*
* Copyright (C) 2016 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_REGS_ARM64_H
#define _LIBUNWINDSTACK_REGS_ARM64_H
#include <stdint.h>
#include <functional>
#include <unwindstack/Elf.h>
#include <unwindstack/MachineArm64.h>
#include <unwindstack/Regs.h>
namespace unwindstack {
// Forward declarations.
class Memory;
class RegsArm64 : public RegsImpl<uint64_t> {
public:
RegsArm64();
virtual ~RegsArm64() = default;
ArchEnum Arch() override final;
bool SetPcFromReturnAddress(Memory* process_memory) override;
bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
uint64_t pc() override;
uint64_t sp() override;
void set_pc(uint64_t pc) override;
void set_sp(uint64_t sp) override;
void ResetPseudoRegisters() override;
bool SetPseudoRegister(uint16_t id, uint64_t value) override;
bool GetPseudoRegister(uint16_t id, uint64_t* value) override;
bool IsRASigned();
void SetPACMask(uint64_t mask);
Regs* Clone() override final;
static Regs* Read(void* data);
static Regs* CreateFromUcontext(void* ucontext);
protected:
uint64_t pseudo_regs_[Arm64Reg::ARM64_PREG_LAST - Arm64Reg::ARM64_PREG_FIRST];
uint64_t pac_mask_;
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_REGS_ARM64_H
@@ -0,0 +1,97 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _LIBUNWINDSTACK_REGS_GET_LOCAL_H
#define _LIBUNWINDSTACK_REGS_GET_LOCAL_H
namespace unwindstack {
#if defined(__arm__)
inline __attribute__((__always_inline__)) void AsmGetRegs(void* reg_data) {
asm volatile(
".align 2\n"
"bx pc\n"
"nop\n"
".code 32\n"
"stmia %[base], {r0-r12}\n"
"add r2, %[base], #52\n"
"mov r3, r13\n"
"mov r4, r14\n"
"mov r5, r15\n"
"stmia r2, {r3-r5}\n"
"orr %[base], pc, #1\n"
"bx %[base]\n"
: [ base ] "+r"(reg_data)
:
: "r2", "r3", "r4", "r5", "memory");
}
#elif defined(__aarch64__)
inline __attribute__((__always_inline__)) void AsmGetRegs(void* reg_data) {
asm volatile(
"1:\n"
"stp x0, x1, [%[base], #0]\n"
"stp x2, x3, [%[base], #16]\n"
"stp x4, x5, [%[base], #32]\n"
"stp x6, x7, [%[base], #48]\n"
"stp x8, x9, [%[base], #64]\n"
"stp x10, x11, [%[base], #80]\n"
"stp x12, x13, [%[base], #96]\n"
"stp x14, x15, [%[base], #112]\n"
"stp x16, x17, [%[base], #128]\n"
"stp x18, x19, [%[base], #144]\n"
"stp x20, x21, [%[base], #160]\n"
"stp x22, x23, [%[base], #176]\n"
"stp x24, x25, [%[base], #192]\n"
"stp x26, x27, [%[base], #208]\n"
"stp x28, x29, [%[base], #224]\n"
"str x30, [%[base], #240]\n"
"mov x12, sp\n"
"adr x13, 1b\n"
"stp x12, x13, [%[base], #248]\n"
: [base] "+r"(reg_data)
:
: "x12", "x13", "memory");
}
#elif defined(__i386__) || defined(__x86_64__)
extern "C" void AsmGetRegs(void* regs);
#endif
inline __attribute__((__always_inline__)) void RegsGetLocal(Regs* regs) {
AsmGetRegs(regs->RawData());
}
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_REGS_GET_LOCAL_H
@@ -0,0 +1,63 @@
/*
* Copyright (C) 2016 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_REGS_X86_H
#define _LIBUNWINDSTACK_REGS_X86_H
#include <stdint.h>
#include <functional>
#include <unwindstack/Elf.h>
#include <unwindstack/Regs.h>
namespace unwindstack {
// Forward declarations.
class Memory;
struct x86_ucontext_t;
class RegsX86 : public RegsImpl<uint32_t> {
public:
RegsX86();
virtual ~RegsX86() = default;
ArchEnum Arch() override final;
bool SetPcFromReturnAddress(Memory* process_memory) override;
bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
void SetFromUcontext(x86_ucontext_t* ucontext);
void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
uint64_t pc() override;
uint64_t sp() override;
void set_pc(uint64_t pc) override;
void set_sp(uint64_t sp) override;
Regs* Clone() override final;
static Regs* Read(void* data);
static Regs* CreateFromUcontext(void* ucontext);
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_REGS_X86_H
@@ -0,0 +1,63 @@
/*
* Copyright (C) 2016 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_REGS_X86_64_H
#define _LIBUNWINDSTACK_REGS_X86_64_H
#include <stdint.h>
#include <functional>
#include <unwindstack/Elf.h>
#include <unwindstack/Regs.h>
namespace unwindstack {
// Forward declarations.
class Memory;
struct x86_64_ucontext_t;
class RegsX86_64 : public RegsImpl<uint64_t> {
public:
RegsX86_64();
virtual ~RegsX86_64() = default;
ArchEnum Arch() override final;
bool SetPcFromReturnAddress(Memory* process_memory) override;
bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
void SetFromUcontext(x86_64_ucontext_t* ucontext);
void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
uint64_t pc() override;
uint64_t sp() override;
void set_pc(uint64_t pc) override;
void set_sp(uint64_t sp) override;
Regs* Clone() override final;
static Regs* Read(void* data);
static Regs* CreateFromUcontext(void* ucontext);
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_REGS_X86_64_H
@@ -0,0 +1,63 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _LIBUNWINDSTACK_UCONTEXT_ARM_H
#define _LIBUNWINDSTACK_UCONTEXT_ARM_H
#include <stdint.h>
#include <unwindstack/MachineArm.h>
namespace unwindstack {
struct arm_stack_t {
uint32_t ss_sp; // void __user*
int32_t ss_flags; // int
uint32_t ss_size; // size_t
};
struct arm_mcontext_t {
uint32_t trap_no; // unsigned long
uint32_t error_code; // unsigned long
uint32_t oldmask; // unsigned long
uint32_t regs[ARM_REG_LAST]; // unsigned long
uint32_t cpsr; // unsigned long
uint32_t fault_address; // unsigned long
};
struct arm_ucontext_t {
uint32_t uc_flags; // unsigned long
uint32_t uc_link; // struct ucontext*
arm_stack_t uc_stack;
arm_mcontext_t uc_mcontext;
// Nothing else is used, so don't define it.
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_UCONTEXT_ARM_H
@@ -0,0 +1,69 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _LIBUNWINDSTACK_UCONTEXT_ARM64_H
#define _LIBUNWINDSTACK_UCONTEXT_ARM64_H
#include <stdint.h>
#include <unwindstack/MachineArm64.h>
namespace unwindstack {
struct arm64_stack_t {
uint64_t ss_sp; // void __user*
int32_t ss_flags; // int
uint64_t ss_size; // size_t
};
struct arm64_sigset_t {
uint64_t sig; // unsigned long
};
struct arm64_mcontext_t {
uint64_t fault_address; // __u64
uint64_t regs[ARM64_REG_LAST]; // __u64
uint64_t pstate; // __u64
// Nothing else is used, so don't define it.
};
struct arm64_ucontext_t {
uint64_t uc_flags; // unsigned long
uint64_t uc_link; // struct ucontext*
arm64_stack_t uc_stack;
arm64_sigset_t uc_sigmask;
// The kernel adds extra padding after uc_sigmask to match glibc sigset_t on ARM64.
char __padding[128 - sizeof(arm64_sigset_t)];
// The full structure requires 16 byte alignment, but our partial structure
// doesn't, so force the alignment.
arm64_mcontext_t uc_mcontext __attribute__((aligned(16)));
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_UCONTEXT_ARM64_H
@@ -0,0 +1,77 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _LIBUNWINDSTACK_UCONTEXT_X86_H
#define _LIBUNWINDSTACK_UCONTEXT_X86_H
#include <stdint.h>
#include <unwindstack/MachineX86.h>
namespace unwindstack {
struct x86_stack_t {
uint32_t ss_sp; // void __user*
int32_t ss_flags; // int
uint32_t ss_size; // size_t
};
struct x86_mcontext_t {
uint32_t gs;
uint32_t fs;
uint32_t es;
uint32_t ds;
uint32_t edi;
uint32_t esi;
uint32_t ebp;
uint32_t esp;
uint32_t ebx;
uint32_t edx;
uint32_t ecx;
uint32_t eax;
uint32_t trapno;
uint32_t err;
uint32_t eip;
uint32_t cs;
uint32_t efl;
uint32_t uesp;
uint32_t ss;
// Only care about the registers, skip everything else.
};
struct x86_ucontext_t {
uint32_t uc_flags; // unsigned long
uint32_t uc_link; // struct ucontext*
x86_stack_t uc_stack;
x86_mcontext_t uc_mcontext;
// Nothing else is used, so don't define it.
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_UCONTEXT_X86_H
@@ -0,0 +1,82 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _LIBUNWINDSTACK_UCONTEXT_X86_64_H
#define _LIBUNWINDSTACK_UCONTEXT_X86_64_H
#include <stdint.h>
#include <unwindstack/MachineX86_64.h>
namespace unwindstack {
struct x86_64_stack_t {
uint64_t ss_sp; // void __user*
int32_t ss_flags; // int
int32_t pad;
uint64_t ss_size; // size_t
};
struct x86_64_mcontext_t {
uint64_t r8;
uint64_t r9;
uint64_t r10;
uint64_t r11;
uint64_t r12;
uint64_t r13;
uint64_t r14;
uint64_t r15;
uint64_t rdi;
uint64_t rsi;
uint64_t rbp;
uint64_t rbx;
uint64_t rdx;
uint64_t rax;
uint64_t rcx;
uint64_t rsp;
uint64_t rip;
uint64_t efl;
uint64_t csgsfs;
uint64_t err;
uint64_t trapno;
uint64_t oldmask;
uint64_t cr2;
// Only care about the registers, skip everything else.
};
struct x86_64_ucontext_t {
uint64_t uc_flags; // unsigned long
uint64_t uc_link; // struct ucontext*
x86_64_stack_t uc_stack;
x86_64_mcontext_t uc_mcontext;
// Nothing else is used, so don't define it.
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_UCONTEXT_X86_64_H
@@ -0,0 +1,207 @@
/*
* Copyright (C) 2017 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_UNWINDER_H
#define _LIBUNWINDSTACK_UNWINDER_H
#include <stdint.h>
#include <sys/types.h>
#include <memory>
#include <string>
#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>
namespace unwindstack {
// Forward declarations.
class Elf;
class ThreadEntry;
struct FrameData {
size_t num;
uint64_t rel_pc;
uint64_t pc;
uint64_t sp;
std::string function_name;
uint64_t function_offset = 0;
std::string map_name;
// The offset from the first map representing the frame. When there are
// two maps (read-only and read-execute) this will be the offset from
// the read-only map. When there is only one map, this will be the
// same as the actual offset of the map and match map_exact_offset.
uint64_t map_elf_start_offset = 0;
// The actual offset from the map where the pc lies.
uint64_t map_exact_offset = 0;
uint64_t map_start = 0;
uint64_t map_end = 0;
uint64_t map_load_bias = 0;
int map_flags = 0;
};
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),
arch_(regs->Arch()) {}
Unwinder(size_t max_frames, Maps* maps, std::shared_ptr<Memory> process_memory)
: max_frames_(max_frames), maps_(maps), process_memory_(process_memory) {}
virtual ~Unwinder() = default;
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(); }
// Returns frames after unwinding.
// Intentionally mutable (which can be used to swap in reserved memory before unwinding).
std::vector<FrameData>& frames() { return frames_; }
std::vector<FrameData> ConsumeFrames() {
std::vector<FrameData> frames = std::move(frames_);
frames_.clear();
return frames;
}
std::string FormatFrame(size_t frame_num) const;
std::string FormatFrame(const FrameData& frame) const;
void SetArch(ArchEnum arch) { arch_ = arch; };
void SetJitDebug(JitDebug* jit_debug);
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_; }
// Disabling the resolving of names results in the function name being
// set to an empty string and the function offset being set to zero.
void SetResolveNames(bool resolve) { resolve_names_ = resolve; }
// Enable/disable soname printing the soname for a map name if the elf is
// embedded in a file. This is enabled by default.
// NOTE: This does nothing unless resolving names is enabled.
void SetEmbeddedSoname(bool embedded_soname) { embedded_soname_ = embedded_soname; }
void SetDisplayBuildID(bool display_build_id) { display_build_id_ = display_build_id; }
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_; }
// Builds a frame for symbolization using the maps from this unwinder. The
// constructed frame contains just enough information to be used to symbolize
// frames collected by frame-pointer unwinding that's done outside of
// libunwindstack. This is used by tombstoned to symbolize frame pointer-based
// stack traces that are collected by tools such as GWP-ASan and MTE.
static FrameData BuildFrameFromPcOnly(uint64_t pc, ArchEnum arch, Maps* maps, JitDebug* jit_debug,
std::shared_ptr<Memory> process_memory, bool resolve_names);
FrameData BuildFrameFromPcOnly(uint64_t pc);
protected:
Unwinder(size_t max_frames) : max_frames_(max_frames) {}
Unwinder(size_t max_frames, ArchEnum arch) : max_frames_(max_frames), arch_(arch) {}
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);
size_t max_frames_;
Maps* maps_;
Regs* regs_;
std::vector<FrameData> frames_;
std::shared_ptr<Memory> process_memory_;
JitDebug* jit_debug_ = nullptr;
DexFiles* dex_files_ = nullptr;
bool resolve_names_ = true;
bool embedded_soname_ = true;
bool display_build_id_ = false;
// True if at least one elf file is coming from memory and not the related
// file. This is only true if there is an actual file backing up the elf.
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();
void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr,
const std::vector<std::string>* map_suffixes_to_ignore = nullptr) override;
protected:
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;
};
class ThreadUnwinder : public UnwinderFromPid {
public:
explicit ThreadUnwinder(size_t max_frames);
ThreadUnwinder(size_t max_frames, const ThreadUnwinder* unwinder);
virtual ~ThreadUnwinder() = default;
void SetObjects(ThreadUnwinder* unwinder);
void Unwind(const std::vector<std::string>*, const std::vector<std::string>*) override {}
void UnwindWithSignal(int signal, pid_t tid,
const std::vector<std::string>* initial_map_names_to_skip = nullptr,
const std::vector<std::string>* map_suffixes_to_ignore = nullptr);
protected:
ThreadEntry* SendSignalToThread(int signal, pid_t tid);
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_UNWINDER_H
@@ -0,0 +1,40 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _LIBUNWINDSTACK_USER_ARM_H
#define _LIBUNWINDSTACK_USER_ARM_H
namespace unwindstack {
struct arm_user_regs {
uint32_t regs[18];
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_USER_ARM_H
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _LIBUNWINDSTACK_USER_ARM64_H
#define _LIBUNWINDSTACK_USER_ARM64_H
namespace unwindstack {
struct arm64_user_regs {
uint64_t regs[31];
uint64_t sp;
uint64_t pc;
uint64_t pstate;
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_USER_ARM64_H
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _LIBUNWINDSTACK_USER_X86_H
#define _LIBUNWINDSTACK_USER_X86_H
namespace unwindstack {
struct x86_user_regs {
uint32_t ebx;
uint32_t ecx;
uint32_t edx;
uint32_t esi;
uint32_t edi;
uint32_t ebp;
uint32_t eax;
uint32_t xds;
uint32_t xes;
uint32_t xfs;
uint32_t xgs;
uint32_t orig_eax;
uint32_t eip;
uint32_t xcs;
uint32_t eflags;
uint32_t esp;
uint32_t xss;
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_USER_X86_H
@@ -0,0 +1,66 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _LIBUNWINDSTACK_USER_X86_64_H
#define _LIBUNWINDSTACK_USER_X86_64_H
namespace unwindstack {
struct x86_64_user_regs {
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
uint64_t rbp;
uint64_t rbx;
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
uint64_t rax;
uint64_t rcx;
uint64_t rdx;
uint64_t rsi;
uint64_t rdi;
uint64_t orig_rax;
uint64_t rip;
uint64_t cs;
uint64_t eflags;
uint64_t rsp;
uint64_t ss;
uint64_t fs_base;
uint64_t gs_base;
uint64_t ds;
uint64_t es;
uint64_t fs;
uint64_t gs;
};
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_USER_X86_64_H