Introduce sentry for crash data collection
This commit is contained in:
+44
@@ -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
|
||||
+79
@@ -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
|
||||
+44
@@ -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
|
||||
+54
@@ -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
|
||||
+76
@@ -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
|
||||
+177
@@ -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
|
||||
+55
@@ -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
|
||||
+130
@@ -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
|
||||
+223
@@ -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
|
||||
+81
@@ -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
|
||||
+63
@@ -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
|
||||
+71
@@ -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
|
||||
+86
@@ -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
|
||||
+30
@@ -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
|
||||
+50
@@ -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
|
||||
+74
@@ -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
|
||||
+51
@@ -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
|
||||
+52
@@ -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
|
||||
+132
@@ -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
|
||||
+136
@@ -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
|
||||
+62
@@ -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
|
||||
+118
@@ -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
|
||||
+60
@@ -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
|
||||
+75
@@ -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
|
||||
+97
@@ -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
|
||||
+63
@@ -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
|
||||
+63
@@ -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
|
||||
+63
@@ -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
|
||||
+69
@@ -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
|
||||
+77
@@ -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
|
||||
+82
@@ -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
|
||||
+207
@@ -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
|
||||
+40
@@ -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
|
||||
+43
@@ -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
|
||||
+56
@@ -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
|
||||
+66
@@ -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
|
||||
Reference in New Issue
Block a user