RegisterContextPOSIXProcessMonitor_powerpc.cpp revision 285101
168313Srnordier//===-- RegisterContextPOSIXProcessMonitor_powerpc.h ------------*- C++ -*-===//
268313Srnordier//
368313Srnordier//                     The LLVM Compiler Infrastructure
468313Srnordier//
568313Srnordier// This file is distributed under the University of Illinois Open Source
668313Srnordier// License. See LICENSE.TXT for details.
768313Srnordier//
868313Srnordier//===---------------------------------------------------------------------===//
968313Srnordier
1068313Srnordier#include "lldb/Core/DataBufferHeap.h"
1168313Srnordier#include "lldb/Core/RegisterValue.h"
1268313Srnordier#include "lldb/Target/Thread.h"
1368313Srnordier
1468313Srnordier#include "RegisterContextPOSIX_powerpc.h"
1568313Srnordier#include "ProcessPOSIX.h"
1668313Srnordier#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
1768313Srnordier#include "ProcessMonitor.h"
1868313Srnordier
1968313Srnordierusing namespace lldb_private;
2068313Srnordierusing namespace lldb;
2168313Srnordier
2268313Srnordier#define REG_CONTEXT_SIZE (GetGPRSize())
2368313Srnordier
2468313SrnordierRegisterContextPOSIXProcessMonitor_powerpc::RegisterContextPOSIXProcessMonitor_powerpc(Thread &thread,
2568313Srnordier                                                                                     uint32_t concrete_frame_idx,
2668313Srnordier                                                                                     lldb_private::RegisterInfoInterface *register_info)
2768313Srnordier    : RegisterContextPOSIX_powerpc(thread, concrete_frame_idx, register_info)
2868313Srnordier{
2968313Srnordier}
3068313Srnordier
3168313SrnordierProcessMonitor &
3268313SrnordierRegisterContextPOSIXProcessMonitor_powerpc::GetMonitor()
3368313Srnordier{
3468313Srnordier    ProcessSP base = CalculateProcess();
3568313Srnordier    ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
3668313Srnordier    return process->GetMonitor();
3768313Srnordier}
3868313Srnordier
3968313Srnordierbool
4068313SrnordierRegisterContextPOSIXProcessMonitor_powerpc::ReadGPR()
4168313Srnordier{
4268313Srnordier    ProcessMonitor &monitor = GetMonitor();
4368313Srnordier    return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
4468313Srnordier}
4568313Srnordier
4668313Srnordierbool
4768313SrnordierRegisterContextPOSIXProcessMonitor_powerpc::ReadFPR()
4868313Srnordier{
4968313Srnordier    ProcessMonitor &monitor = GetMonitor();
5068313Srnordier    return monitor.ReadFPR(m_thread.GetID(), &m_fpr_powerpc, sizeof(m_fpr_powerpc));
5168313Srnordier}
5268313Srnordier
5368313Srnordierbool
5468313SrnordierRegisterContextPOSIXProcessMonitor_powerpc::ReadVMX()
5568313Srnordier{
5668313Srnordier    // XXX: Need a way to read/write process VMX registers with ptrace.
5768313Srnordier    return false;
5868313Srnordier}
5968313Srnordier
6068313Srnordierbool
6168313SrnordierRegisterContextPOSIXProcessMonitor_powerpc::WriteGPR()
6268313Srnordier{
6368313Srnordier    ProcessMonitor &monitor = GetMonitor();
6468313Srnordier    return monitor.WriteGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
6568313Srnordier}
6668313Srnordier
6768313Srnordierbool
6868313SrnordierRegisterContextPOSIXProcessMonitor_powerpc::WriteFPR()
6968313Srnordier{
7068313Srnordier    ProcessMonitor &monitor = GetMonitor();
7168313Srnordier    return monitor.WriteFPR(m_thread.GetID(), &m_fpr_powerpc, sizeof(m_fpr_powerpc));
7268313Srnordier}
7368313Srnordier
7468313Srnordierbool
7568313SrnordierRegisterContextPOSIXProcessMonitor_powerpc::WriteVMX()
7668313Srnordier{
7768313Srnordier    // XXX: Need a way to read/write process VMX registers with ptrace.
7868313Srnordier    return false;
7968313Srnordier}
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