| #ifndef RR_REMOTE_CODE_PTR_H_ |
| #define RR_REMOTE_CODE_PTR_H_ |
| |
| #include <cstddef> |
| #include <iostream> |
| |
| #include "kernel_abi.h" |
| |
| namespace rr { |
| |
| /* |
| * A pointer to code in the tracee address space. Convertible to a |
| * remote_ptr<void>. |
| */ |
| class remote_code_ptr { |
| public: |
| remote_code_ptr() : ptr(0) {} |
| remote_code_ptr(uintptr_t ptr) : ptr(ptr) {} |
| remote_code_ptr(std::nullptr_t) : ptr(0) {} |
| |
| bool operator==(const remote_code_ptr& other) const { |
| return ptr == other.ptr; |
| } |
| bool operator!=(const remote_code_ptr& other) const { |
| return ptr != other.ptr; |
| } |
| bool operator<=(const remote_code_ptr& other) const { |
| return ptr <= other.ptr; |
| } |
| bool operator>=(const remote_code_ptr& other) const { |
| return ptr >= other.ptr; |
| } |
| bool operator<(const remote_code_ptr& other) const { return ptr < other.ptr; } |
| bool operator>(const remote_code_ptr& other) const { return ptr > other.ptr; } |
| // XXXkhuey this will have to get smarter once we have ARM. |
| remote_code_ptr operator+(intptr_t delta) const { |
| return remote_code_ptr(ptr + delta); |
| } |
| remote_code_ptr operator-(intptr_t delta) const { |
| return remote_code_ptr(ptr - delta); |
| } |
| intptr_t operator-(remote_code_ptr other) const { return ptr - other.ptr; } |
| |
| remote_code_ptr decrement_by_syscall_insn_length(SupportedArch arch) const { |
| return remote_code_ptr(ptr - rr::syscall_instruction_length(arch)); |
| } |
| remote_code_ptr increment_by_syscall_insn_length(SupportedArch arch) const { |
| return remote_code_ptr(ptr + rr::syscall_instruction_length(arch)); |
| } |
| remote_code_ptr undo_executed_bkpt(SupportedArch arch) { |
| switch (arch) { |
| case x86: |
| case x86_64: |
| return decrement_by_bkpt_insn_length_private(arch); |
| case aarch64: |
| // On aarch64 executed breakpoint instructions do not increment the pc |
| return *this; |
| default: |
| DEBUG_ASSERT(0 && "Unknown architecture"); |
| __builtin_unreachable(); |
| } |
| } |
| remote_code_ptr advance_past_executed_bkpt(SupportedArch arch) { |
| switch (arch) { |
| case x86: |
| case x86_64: |
| return *this; |
| case aarch64: |
| // On aarch64 executed breakpoint instructions do not increment the pc |
| return increment_by_bkpt_insn_length(arch); |
| default: |
| DEBUG_ASSERT(0 && "Unknown architecture"); |
| __builtin_unreachable(); |
| } |
| } |
| remote_code_ptr increment_by_bkpt_insn_length(SupportedArch arch) const { |
| return remote_code_ptr(ptr + rr::bkpt_instruction_length(arch)); |
| } |
| remote_code_ptr increment_by_movrm_insn_length(SupportedArch arch) const { |
| return remote_code_ptr(ptr + rr::movrm_instruction_length(arch)); |
| } |
| remote_code_ptr decrement_by_vsyscall_entry_length(SupportedArch arch) const { |
| return remote_code_ptr(ptr - rr::vsyscall_entry_length(arch)); |
| } |
| |
| template <typename T> remote_ptr<T> to_data_ptr() const { |
| return remote_ptr<T>(to_data_ptr_value()); |
| } |
| |
| // Return the pointer in a form suitable for storing in a register. Only |
| // intended for use by Registers and the operator << |
| uintptr_t register_value() const { return ptr; } |
| |
| bool is_null() const { return !ptr; } |
| explicit operator bool() const { return ptr != 0; } |
| |
| private: |
| // Private to avoid accidentally using this instead of undo_executed_bkpt. |
| // You probably want that one. |
| remote_code_ptr decrement_by_bkpt_insn_length_private(SupportedArch arch) const { |
| return remote_code_ptr(ptr - rr::bkpt_instruction_length(arch)); |
| } |
| |
| // Return the integer value for this pointer viewed as a data pointer. |
| // A no-op on Intel architectures, will mask off the thumb bit on ARM. |
| uintptr_t to_data_ptr_value() const { return ptr; } |
| |
| uintptr_t ptr; |
| }; |
| |
| std::ostream& operator<<(std::ostream& stream, remote_code_ptr p); |
| |
| } // namespace rr |
| |
| namespace std { |
| |
| template <> struct hash<rr::remote_code_ptr> { |
| size_t operator()(const rr::remote_code_ptr& ptr) const { |
| return hash<uintptr_t>()(ptr.register_value()); |
| } |
| }; |
| |
| } // namespace std |
| |
| #endif // RR_REMOTE_CODE_PTR_H_ |