diff options
author | Justin Hibbits <jrh29@alumni.cwru.edu> | 2014-10-31 02:34:28 +0000 |
---|---|---|
committer | Justin Hibbits <jrh29@alumni.cwru.edu> | 2014-10-31 02:34:28 +0000 |
commit | 6256a0ea8fdd051e0f76ac422c353e4ac2b05d35 (patch) | |
tree | 2bbb7c0671150f55c774eb4eee50656e5891d978 /lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp | |
parent | 1e2cf0dd4bd7c76fc5a7862e42e2bac2da451fc7 (diff) | |
download | bcm5719-llvm-6256a0ea8fdd051e0f76ac422c353e4ac2b05d35.tar.gz bcm5719-llvm-6256a0ea8fdd051e0f76ac422c353e4ac2b05d35.zip |
First cut of PowerPC(64) support in LLDB.
Summary:
This adds preliminary support for PowerPC/PowerPC64, for FreeBSD. There are
some issues still:
* Breakpoints don't work well on powerpc64.
* Shared libraries don't yet get loaded for a 32-bit process on powerpc64 host.
* Backtraces don't work. This is due to PowerPC ABI using a backchain pointer
in memory, instead of a dedicated frame pointer register for the backchain.
* Breakpoints on functions without debug info may not work correctly for 32-bit
powerpc.
Reviewers: emaste, tfiala, jingham, clayborg
Reviewed By: clayborg
Subscribers: emaste, lldb-commits
Differential Revision: http://reviews.llvm.org/D5988
llvm-svn: 220944
Diffstat (limited to 'lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp')
-rw-r--r-- | lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp new file mode 100644 index 00000000000..a9477d58351 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp @@ -0,0 +1,273 @@ +//===-- RegisterContextPOSIX_powerpc.cpp -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <cstring> +#include <errno.h> +#include <stdint.h> + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Host/Endian.h" +#include "llvm/Support/Compiler.h" + +#include "RegisterContextPOSIX_powerpc.h" +#include "Plugins/Process/elf-core/ProcessElfCore.h" + +using namespace lldb_private; +using namespace lldb; + +static const +uint32_t g_gpr_regnums[] = +{ + gpr_r0_powerpc, + gpr_r1_powerpc, + gpr_r2_powerpc, + gpr_r3_powerpc, + gpr_r4_powerpc, + gpr_r5_powerpc, + gpr_r6_powerpc, + gpr_r7_powerpc, + gpr_r8_powerpc, + gpr_r9_powerpc, + gpr_r10_powerpc, + gpr_r11_powerpc, + gpr_r12_powerpc, + gpr_r13_powerpc, + gpr_r14_powerpc, + gpr_r15_powerpc, + gpr_r16_powerpc, + gpr_r17_powerpc, + gpr_r18_powerpc, + gpr_r19_powerpc, + gpr_r20_powerpc, + gpr_r21_powerpc, + gpr_r22_powerpc, + gpr_r23_powerpc, + gpr_r24_powerpc, + gpr_r25_powerpc, + gpr_r26_powerpc, + gpr_r27_powerpc, + gpr_r28_powerpc, + gpr_r29_powerpc, + gpr_r30_powerpc, + gpr_r31_powerpc, + gpr_lr_powerpc, + gpr_cr_powerpc, + gpr_xer_powerpc, + gpr_ctr_powerpc, + gpr_pc_powerpc, +}; + +static const +uint32_t g_fpr_regnums[] = +{ + fpr_f0_powerpc, + fpr_f1_powerpc, + fpr_f2_powerpc, + fpr_f3_powerpc, + fpr_f4_powerpc, + fpr_f5_powerpc, + fpr_f6_powerpc, + fpr_f7_powerpc, + fpr_f8_powerpc, + fpr_f9_powerpc, + fpr_f10_powerpc, + fpr_f11_powerpc, + fpr_f12_powerpc, + fpr_f13_powerpc, + fpr_f14_powerpc, + fpr_f15_powerpc, + fpr_f16_powerpc, + fpr_f17_powerpc, + fpr_f18_powerpc, + fpr_f19_powerpc, + fpr_f20_powerpc, + fpr_f21_powerpc, + fpr_f22_powerpc, + fpr_f23_powerpc, + fpr_f24_powerpc, + fpr_f25_powerpc, + fpr_f26_powerpc, + fpr_f27_powerpc, + fpr_f28_powerpc, + fpr_f29_powerpc, + fpr_f30_powerpc, + fpr_f31_powerpc, + fpr_fpscr_powerpc, +}; + +// Number of register sets provided by this context. +enum +{ + k_num_register_sets = 2 +}; + +static const RegisterSet +g_reg_sets_powerpc[k_num_register_sets] = +{ + { "General Purpose Registers", "gpr", k_num_gpr_registers_powerpc, g_gpr_regnums }, + { "Floating Point Registers", "fpr", k_num_fpr_registers_powerpc, g_fpr_regnums }, +}; + +bool RegisterContextPOSIX_powerpc::IsGPR(unsigned reg) +{ + return reg <= k_num_gpr_registers_powerpc; // GPR's come first. +} + +bool +RegisterContextPOSIX_powerpc::IsFPR(unsigned reg) +{ + // XXX + return (reg >= k_first_fpr) && (reg <= k_last_fpr); +} + +RegisterContextPOSIX_powerpc::RegisterContextPOSIX_powerpc(Thread &thread, + uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info) + : RegisterContext(thread, concrete_frame_idx) +{ + m_register_info_ap.reset(register_info); + + // elf-core yet to support ReadFPR() + ProcessSP base = CalculateProcess(); + if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) + return; +} + +RegisterContextPOSIX_powerpc::~RegisterContextPOSIX_powerpc() +{ +} + +void +RegisterContextPOSIX_powerpc::Invalidate() +{ +} + +void +RegisterContextPOSIX_powerpc::InvalidateAllRegisters() +{ +} + +unsigned +RegisterContextPOSIX_powerpc::GetRegisterOffset(unsigned reg) +{ + assert(reg < k_num_registers_powerpc && "Invalid register number."); + return GetRegisterInfo()[reg].byte_offset; +} + +unsigned +RegisterContextPOSIX_powerpc::GetRegisterSize(unsigned reg) +{ + assert(reg < k_num_registers_powerpc && "Invalid register number."); + return GetRegisterInfo()[reg].byte_size; +} + +size_t +RegisterContextPOSIX_powerpc::GetRegisterCount() +{ + size_t num_registers = k_num_registers_powerpc; + return num_registers; +} + +size_t +RegisterContextPOSIX_powerpc::GetGPRSize() +{ + return m_register_info_ap->GetGPRSize(); +} + +const RegisterInfo * +RegisterContextPOSIX_powerpc::GetRegisterInfo() +{ + // Commonly, this method is overridden and g_register_infos is copied and specialized. + // So, use GetRegisterInfo() rather than g_register_infos in this scope. + return m_register_info_ap->GetRegisterInfo (); +} + +const RegisterInfo * +RegisterContextPOSIX_powerpc::GetRegisterInfoAtIndex(size_t reg) +{ + if (reg < k_num_registers_powerpc) + return &GetRegisterInfo()[reg]; + else + return NULL; +} + +size_t +RegisterContextPOSIX_powerpc::GetRegisterSetCount() +{ + size_t sets = 0; + for (size_t set = 0; set < k_num_register_sets; ++set) + { + if (IsRegisterSetAvailable(set)) + ++sets; + } + + return sets; +} + +const RegisterSet * +RegisterContextPOSIX_powerpc::GetRegisterSet(size_t set) +{ + if (IsRegisterSetAvailable(set)) + return &g_reg_sets_powerpc[set]; + else + return NULL; +} + +const char * +RegisterContextPOSIX_powerpc::GetRegisterName(unsigned reg) +{ + assert(reg < k_num_registers_powerpc && "Invalid register offset."); + return GetRegisterInfo()[reg].name; +} + +lldb::ByteOrder +RegisterContextPOSIX_powerpc::GetByteOrder() +{ + // Get the target process whose privileged thread was used for the register read. + lldb::ByteOrder byte_order = eByteOrderInvalid; + Process *process = CalculateProcess().get(); + + if (process) + byte_order = process->GetByteOrder(); + return byte_order; +} + +bool +RegisterContextPOSIX_powerpc::IsRegisterSetAvailable(size_t set_index) +{ + size_t num_sets = k_num_register_sets; + + return (set_index < num_sets); +} + +// Used when parsing DWARF and EH frame information and any other +// object file sections that contain register numbers in them. +uint32_t +RegisterContextPOSIX_powerpc::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) +{ + const uint32_t num_regs = GetRegisterCount(); + + assert (kind < kNumRegisterKinds); + for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) + { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx); + + if (reg_info->kinds[kind] == num) + return reg_idx; + } + + return LLDB_INVALID_REGNUM; +} + |