summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
blob: ba0e0522059102ab31c5fbf424bc159b6b91bbd9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
//===-- RegisterContextLLDB.h --------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef lldb_RegisterContextLLDB_h_
#define lldb_RegisterContextLLDB_h_

#include <vector>

#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Symbol/SymbolContext.h"

class RegisterContextLLDB : public lldb_private::RegisterContext
{
public:
    RegisterContextLLDB (lldb_private::Thread &thread,
                         const lldb::RegisterContextSP& next_frame,
                         lldb_private::SymbolContext& sym_ctx,
                         uint32_t frame_number);

    ///
    // pure virtual functions from the base class that we must implement
    ///

    virtual
    ~RegisterContextLLDB () { }

    virtual void
    InvalidateAllRegisters ();

    virtual size_t
    GetRegisterCount ();

    virtual const lldb::RegisterInfo *
    GetRegisterInfoAtIndex (uint32_t reg);

    virtual size_t
    GetRegisterSetCount ();

    virtual const lldb::RegisterSet *
    GetRegisterSet (uint32_t reg_set);

    virtual bool
    ReadRegisterBytes (uint32_t reg, lldb_private::DataExtractor &data);

    virtual bool
    ReadAllRegisterValues (lldb::DataBufferSP &data_sp);

    virtual bool
    WriteRegisterBytes (uint32_t reg, lldb_private::DataExtractor &data, uint32_t data_offset = 0);

    virtual bool
    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);

    virtual uint32_t
    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);

    bool
    IsValid () const;

    bool
    GetCFA (lldb::addr_t& cfa);

    bool
    GetStartPC (lldb::addr_t& start_pc);

    bool
    ReadPC (lldb::addr_t& start_pc);

private:

    enum FrameType
    {
        eNormalFrame,
        eSigtrampFrame,
        eDebuggerFrame,  // a debugger inferior function call frame; we get caller's registers from debugger
        eNotAValidFrame  // this frame is invalid for some reason - most likely it is past the top (end) of the stack
    };

    enum RegisterLocationTypes
    {
        eRegisterNotSaved = 0,          // register was not preserved by callee.  If volatile reg, is unavailable
        eRegisterSavedAtMemoryLocation, // register is saved at a specific word of target mem (target_memory_location)
        eRegisterInRegister,            // register is available in a (possible other) register (register_number)
        eRegisterSavedAtHostMemoryLocation, // register is saved at a word in lldb's address space
        eRegisterValueInferred          // register val was computed (and is in register_value)
    };

    struct RegisterLocation
    {
        int type;
        union
        {
            lldb::addr_t target_memory_location;
            uint32_t     register_number;       // in eRegisterKindLLDB register numbering system
            void*        host_memory_location;
            uint64_t     register_value;        // eRegisterValueInferred - e.g. stack pointer == cfa + offset
        } location;
    };


    // Indicates whether this frame is frame zero -- the currently
    // executing frame -- or not.  If it is not frame zero, m_next_frame's
    // shared pointer holds a pointer to the RegisterContextLLDB
    // object "below" this frame, i.e. this frame called m_next_frame's
    // function.
    bool
    IsFrameZero () const;

    void 
    InitializeZerothFrame ();

    void 
    InitializeNonZerothFrame();

    // Provide a location for where THIS function saved the CALLER's register value
    // Or a frame "below" this one saved it, i.e. a function called by this one, preserved a register that this
    // function didn't modify/use.
    //
    // The RegisterLocation type may be set to eRegisterNotAvailable -- this will happen for a volatile register 
    // being queried mid-stack.  Instead of floating frame 0's contents of that register up the stack (which may
    // or may not be the value of that reg when the function was executing), we won't return any value.
    //
    // If a non-volatile register (a "preserved" register) is requested mid-stack and no frames "below" the requested
    // stack have saved the register anywhere, it is safe to assume that frame 0's register values are still the same
    // as the requesting frame's.
    //
    bool
    SavedLocationForRegister (uint32_t lldb_regnum, RegisterLocation &regloc);

    bool
    ReadRegisterBytesFromRegisterLocation (uint32_t regnum, RegisterLocation regloc, lldb_private::DataExtractor &data);

    bool
    WriteRegisterBytesToRegisterLocation (uint32_t regnum, RegisterLocation regloc, lldb_private::DataExtractor &data, uint32_t data_offset);

    // Get the contents of a general purpose (address-size) register for this frame 
    // (usually retrieved from the m_next_frame)
    // m_base_reg_ectx and m_next_frame should both be initialized appropriately before calling.
    bool
    ReadGPRValue (int register_kind, uint32_t regnum, lldb::addr_t &value);

    lldb_private::UnwindPlan *
    GetFastUnwindPlanForFrame ();

    lldb_private::UnwindPlan *
    GetFullUnwindPlanForFrame ();

    lldb_private::Thread& m_thread;
    lldb::RegisterContextSP m_next_frame;

    ///
    // The following tell us how to retrieve the CALLER's register values (ie the "previous" frame, aka the frame above)
    // i.e. where THIS frame saved them
    ///

    lldb_private::UnwindPlan *m_fast_unwind_plan;  // may be NULL
    lldb_private::UnwindPlan *m_full_unwind_plan;
    bool m_all_registers_available;               // Can we retrieve all regs or just nonvolatile regs?
    int m_frame_type;                             // enum FrameType

    lldb::addr_t m_cfa;
    lldb_private::Address m_start_pc;
    lldb_private::Address m_current_pc;

    int m_current_offset;                         // how far into the function we've executed; -1 if unknown
                                                  // 0 if no instructions have been executed yet.

    int m_current_offset_backed_up_one;           // how far into the function we've executed; -1 if unknown
                                                  // 0 if no instructions have been executed yet.
                                                  // On architectures where the return address on the stack points
                                                  // to the instruction after the CALL, this value will have 1 
                                                  // subtracted from it.  Else a function that ends in a CALL will
                                                  // have an offset pointing into the next function's address range.
                                                  // m_current_pc has the actual address of the "current" pc.

    lldb_private::SymbolContext& m_sym_ctx;
    bool m_sym_ctx_valid;                         // if ResolveSymbolContextForAddress fails, don't try to use m_sym_ctx

    uint32_t m_frame_number;                      // What stack frame level this frame is - used for debug logging

    std::map<uint32_t, RegisterLocation> m_registers; // where to find reg values for this frame

    //------------------------------------------------------------------
    // For RegisterContextLLDB only
    //------------------------------------------------------------------

    DISALLOW_COPY_AND_ASSIGN (RegisterContextLLDB);
};

#endif  // lldb_RegisterContextLLDB_h_
OpenPOWER on IntegriCloud