RegisterContextPOSIXProcessMonitor_powerpc.cpp revision 296417
1//===-- RegisterContextPOSIXProcessMonitor_powerpc.h ------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===---------------------------------------------------------------------===//
9
10#include "lldb/Core/DataBufferHeap.h"
11#include "lldb/Core/RegisterValue.h"
12#include "lldb/Target/Thread.h"
13
14#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
15#include "ProcessFreeBSD.h"
16#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
17#include "ProcessMonitor.h"
18
19using namespace lldb_private;
20using namespace lldb;
21
22#define REG_CONTEXT_SIZE (GetGPRSize())
23
24RegisterContextPOSIXProcessMonitor_powerpc::RegisterContextPOSIXProcessMonitor_powerpc(Thread &thread,
25                                                                                     uint32_t concrete_frame_idx,
26                                                                                     lldb_private::RegisterInfoInterface *register_info)
27    : RegisterContextPOSIX_powerpc(thread, concrete_frame_idx, register_info)
28{
29}
30
31ProcessMonitor &
32RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor()
33{
34    ProcessSP base = CalculateProcess();
35    ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get());
36    return process->GetMonitor();
37}
38
39bool
40RegisterContextPOSIXProcessMonitor_powerpc::ReadGPR()
41{
42    ProcessMonitor &monitor = GetMonitor();
43    return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
44}
45
46bool
47RegisterContextPOSIXProcessMonitor_powerpc::ReadFPR()
48{
49    ProcessMonitor &monitor = GetMonitor();
50    return monitor.ReadFPR(m_thread.GetID(), &m_fpr_powerpc, sizeof(m_fpr_powerpc));
51}
52
53bool
54RegisterContextPOSIXProcessMonitor_powerpc::ReadVMX()
55{
56    // XXX: Need a way to read/write process VMX registers with ptrace.
57    return false;
58}
59
60bool
61RegisterContextPOSIXProcessMonitor_powerpc::WriteGPR()
62{
63    ProcessMonitor &monitor = GetMonitor();
64    return monitor.WriteGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
65}
66
67bool
68RegisterContextPOSIXProcessMonitor_powerpc::WriteFPR()
69{
70    ProcessMonitor &monitor = GetMonitor();
71    return monitor.WriteFPR(m_thread.GetID(), &m_fpr_powerpc, sizeof(m_fpr_powerpc));
72}
73
74bool
75RegisterContextPOSIXProcessMonitor_powerpc::WriteVMX()
76{
77    // XXX: Need a way to read/write process VMX registers with ptrace.
78    return false;
79}
80
81bool
82RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(const unsigned reg,
83                                                        RegisterValue &value)
84{
85    ProcessMonitor &monitor = GetMonitor();
86    return monitor.ReadRegisterValue(m_thread.GetID(),
87                                     GetRegisterOffset(reg),
88                                     GetRegisterName(reg),
89                                     GetRegisterSize(reg),
90                                     value);
91}
92
93bool
94RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(const unsigned reg,
95                                                         const RegisterValue &value)
96{
97    unsigned reg_to_write = reg;
98    RegisterValue value_to_write = value;
99
100    // Check if this is a subregister of a full register.
101    const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
102    if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
103    {
104        RegisterValue full_value;
105        uint32_t full_reg = reg_info->invalidate_regs[0];
106        const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
107
108        // Read the full register.
109        if (ReadRegister(full_reg_info, full_value))
110        {
111            Error error;
112            ByteOrder byte_order = GetByteOrder();
113            uint8_t dst[RegisterValue::kMaxRegisterByteSize];
114
115            // Get the bytes for the full register.
116            const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
117                                                                   dst,
118                                                                   sizeof(dst),
119                                                                   byte_order,
120                                                                   error);
121            if (error.Success() && dest_size)
122            {
123                uint8_t src[RegisterValue::kMaxRegisterByteSize];
124
125                // Get the bytes for the source data.
126                const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
127                if (error.Success() && src_size && (src_size < dest_size))
128                {
129                    // Copy the src bytes to the destination.
130                    memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
131                    // Set this full register as the value to write.
132                    value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
133                    value_to_write.SetType(full_reg_info);
134                    reg_to_write = full_reg;
135                }
136            }
137        }
138    }
139
140    ProcessMonitor &monitor = GetMonitor();
141    // Account for the fact that 32-bit targets on powerpc64 really use 64-bit
142    // registers in ptrace, but expose here 32-bit registers with a higher
143    // offset.
144    uint64_t offset = GetRegisterOffset(reg_to_write);
145    offset &= ~(sizeof(uintptr_t) - 1);
146    return monitor.WriteRegisterValue(m_thread.GetID(),
147                                      offset,
148                                      GetRegisterName(reg_to_write),
149                                      value_to_write);
150}
151
152bool
153RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
154{
155    if (!reg_info)
156        return false;
157
158    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
159
160    if (IsFPR(reg))
161    {
162        if (!ReadFPR())
163            return false;
164        uint8_t *src = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset;
165        value.SetUInt64(*(uint64_t*)src);
166    }
167    else if (IsGPR(reg))
168    {
169        bool success = ReadRegister(reg, value);
170
171        if (success)
172        {
173            // If our return byte size was greater than the return value reg size, then
174            // use the type specified by reg_info rather than the uint64_t default
175            if (value.GetByteSize() > reg_info->byte_size)
176                value.SetType(reg_info);
177        }
178        return success;
179    }
180
181    return false;
182}
183
184bool
185RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
186{
187    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
188
189    if (IsGPR(reg))
190    {
191        return WriteRegister(reg, value);
192    }
193    else if (IsFPR(reg))
194    {
195        assert (reg_info->byte_offset < sizeof(m_fpr_powerpc));
196        uint8_t *dst = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset;
197        *(uint64_t *)dst = value.GetAsUInt64();
198        return WriteFPR();
199    }
200
201    return false;
202}
203
204bool
205RegisterContextPOSIXProcessMonitor_powerpc::ReadAllRegisterValues(DataBufferSP &data_sp)
206{
207    bool success = false;
208    data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
209    if (data_sp && ReadGPR () && ReadFPR ())
210    {
211        uint8_t *dst = data_sp->GetBytes();
212        success = dst != 0;
213
214        if (success)
215        {
216            ::memcpy (dst, &m_gpr_powerpc, GetGPRSize());
217            dst += GetGPRSize();
218        }
219    }
220    return success;
221}
222
223bool
224RegisterContextPOSIXProcessMonitor_powerpc::WriteAllRegisterValues(const DataBufferSP &data_sp)
225{
226    bool success = false;
227    if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
228    {
229        uint8_t *src = data_sp->GetBytes();
230        if (src)
231        {
232            ::memcpy (&m_gpr_powerpc, src, GetGPRSize());
233
234            if (WriteGPR())
235            {
236                src += GetGPRSize();
237                ::memcpy (&m_fpr_powerpc, src, sizeof(m_fpr_powerpc));
238
239                success = WriteFPR();
240            }
241        }
242    }
243    return success;
244}
245
246uint32_t
247RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpoint(addr_t addr, size_t size,
248                                              bool read, bool write)
249{
250    const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
251    uint32_t hw_index;
252
253    for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
254    {
255        if (IsWatchpointVacant(hw_index))
256            return SetHardwareWatchpointWithIndex(addr, size,
257                                                  read, write,
258                                                  hw_index);
259    }
260
261    return LLDB_INVALID_INDEX32;
262}
263
264bool
265RegisterContextPOSIXProcessMonitor_powerpc::ClearHardwareWatchpoint(uint32_t hw_index)
266{
267    return false;
268}
269
270bool
271RegisterContextPOSIXProcessMonitor_powerpc::HardwareSingleStep(bool enable)
272{
273    return false;
274}
275
276bool
277RegisterContextPOSIXProcessMonitor_powerpc::UpdateAfterBreakpoint()
278{
279    lldb::addr_t pc;
280
281    if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
282        return false;
283
284    return true;
285}
286
287unsigned
288RegisterContextPOSIXProcessMonitor_powerpc::GetRegisterIndexFromOffset(unsigned offset)
289{
290    unsigned reg;
291    for (reg = 0; reg < k_num_registers_powerpc; reg++)
292    {
293        if (GetRegisterInfo()[reg].byte_offset == offset)
294            break;
295    }
296    assert(reg < k_num_registers_powerpc && "Invalid register offset.");
297    return reg;
298}
299
300bool
301RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointHit(uint32_t hw_index)
302{
303    return false;
304}
305
306bool
307RegisterContextPOSIXProcessMonitor_powerpc::ClearWatchpointHits()
308{
309    return false;
310}
311
312addr_t
313RegisterContextPOSIXProcessMonitor_powerpc::GetWatchpointAddress(uint32_t hw_index)
314{
315    return LLDB_INVALID_ADDRESS;
316}
317
318bool
319RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointVacant(uint32_t hw_index)
320{
321    return false;
322}
323
324bool
325RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
326                                                       bool read, bool write,
327                                                       uint32_t hw_index)
328{
329    return false;
330}
331
332uint32_t
333RegisterContextPOSIXProcessMonitor_powerpc::NumSupportedHardwareWatchpoints()
334{
335    return 0;
336}
337
338