diff options
| author | Ed Maste <emaste@FreeBSD.org> | 2015-02-06 21:38:51 +0000 | 
|---|---|---|
| committer | Ed Maste <emaste@FreeBSD.org> | 2015-02-06 21:38:51 +0000 | 
| commit | 205afe679855a4ce8149cdaa94d3f0868ce796dc (patch) | |
| tree | 09bc83f73246ee3c7a779605cd0122093d2a8a19 /source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp | |
| parent | 0cac4ca3916ac24ab6139d03cbfd18db9e715bfe (diff) | |
Notes
Diffstat (limited to 'source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp')
| -rw-r--r-- | source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp | 273 | 
1 files changed, 273 insertions, 0 deletions
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp new file mode 100644 index 0000000000000..a9477d583517f --- /dev/null +++ b/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; +} +  | 
