UnwindAssemblyInstEmulation.cpp revision 2d9b29b4bdc88d319761cac07f1692eef95c2a72
1f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//===-- UnwindAssemblyInstEmulation.cpp --------------------------*- C++ -*-===//
2f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//
3f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//                     The LLVM Compiler Infrastructure
4f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//
5f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton// This file is distributed under the University of Illinois Open Source
6f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton// License. See LICENSE.TXT for details.
7f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//
8f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//===----------------------------------------------------------------------===//
9f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
10f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton#include "UnwindAssemblyInstEmulation.h"
11f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
12f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton#include "llvm-c/EnhancedDisassembly.h"
13f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
14f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton#include "lldb/Core/Address.h"
15f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton#include "lldb/Core/ArchSpec.h"
16888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton#include "lldb/Core/DataBufferHeap.h"
17888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton#include "lldb/Core/Disassembler.h"
18888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton#include "lldb/Core/Error.h"
1975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton#include "lldb/Core/Log.h"
20f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton#include "lldb/Core/PluginManager.h"
2175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton#include "lldb/Core/StreamString.h"
22f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton#include "lldb/Target/ExecutionContext.h"
23f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton#include "lldb/Target/Process.h"
24f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton#include "lldb/Target/Thread.h"
25f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton#include "lldb/Target/Target.h"
26f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
27f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonusing namespace lldb;
28f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonusing namespace lldb_private;
29f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
30f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
31f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
32f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//-----------------------------------------------------------------------------------------------
33f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//  UnwindAssemblyParser_x86 method definitions
34f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//-----------------------------------------------------------------------------------------------
35f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
36f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonbool
37888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& range,
38888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                                   Thread& thread,
39888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                                   UnwindPlan& unwind_plan)
40f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
41888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    if (range.GetByteSize() > 0 &&
42888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        range.GetBaseAddress().IsValid() &&
43888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        m_inst_emulator_ap.get())
44888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    {
4575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
4675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        // The the instruction emulation subclass setup the unwind plan for the
4775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        // first instruction.
4875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        m_inst_emulator_ap->CreateFunctionEntryUnwind (unwind_plan);
4975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
5075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        // CreateFunctionEntryUnwind should have created the first row. If it
5175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        // doesn't, then we are done.
5275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        if (unwind_plan.GetRowCount() == 0)
5375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            return false;
54888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
55888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        ExecutionContext exe_ctx;
56888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        thread.CalculateExecutionContext(exe_ctx);
57888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        DisassemblerSP disasm_sp (Disassembler::DisassembleRange (m_arch,
58888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                                  NULL,
59888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                                  exe_ctx,
60888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                                  range));
6175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
6275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
6375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
64888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        if (disasm_sp)
65888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        {
66888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
67888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            m_range_ptr = ⦥
68888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            m_thread_ptr = &thread;
69888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            m_unwind_plan_ptr = &unwind_plan;
70888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
71888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            const uint32_t addr_byte_size = m_arch.GetAddressByteSize();
72888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            const bool show_address = true;
73888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            const bool show_bytes = true;
74888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            const bool raw = false;
7575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            // Initialize the CFA with a known value. In the 32 bit case
76888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            // it will be 0x80000000, and in the 64 bit case 0x8000000000000000.
77888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            // We use the address byte size to be safe for any future addresss sizes
7875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            m_inst_emulator_ap->GetRegisterInfo (unwind_plan.GetRegisterKind(),
7975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                                 unwind_plan.GetInitialCFARegister(),
8075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                                 m_cfa_reg_info);
8175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
8275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            m_fp_is_cfa = false;
8375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            m_register_values.clear();
8475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            m_pushed_regs.clear();
8575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
86061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton            m_initial_sp = (1ull << ((addr_byte_size * 8) - 1));
872f085c6ca2895663687dca704589478ff040b849Greg Clayton            RegisterValue cfa_reg_value;
882f085c6ca2895663687dca704589478ff040b849Greg Clayton            cfa_reg_value.SetUInt (m_initial_sp, m_cfa_reg_info.byte_size);
892f085c6ca2895663687dca704589478ff040b849Greg Clayton            SetRegisterValue (m_cfa_reg_info, cfa_reg_value);
90888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
91888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            const InstructionList &inst_list = disasm_sp->GetInstructionList ();
92888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            const size_t num_instructions = inst_list.GetSize();
933063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            if (num_instructions > 0)
94888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            {
953063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                Instruction *inst = inst_list.GetInstructionAtIndex (0).get();
963063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                const addr_t base_addr = inst->GetAddress().GetFileAddress();
9775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                // Initialize the current row with the one row that was created
9875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                // from the CreateFunctionEntryUnwind call above...
9975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                m_curr_row = unwind_plan.GetLastRow();
100888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
1013063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                for (size_t idx=0; idx<num_instructions; ++idx)
1023063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                {
1033063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    inst = inst_list.GetInstructionAtIndex (idx).get();
1043063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    if (inst)
1053063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    {
10675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
1072d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda                        if (log && log->GetVerbose ())
10875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        {
10975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            StreamString strm;
11075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, &exe_ctx, raw);
11175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            log->PutCString (strm.GetData());
11275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        }
1133063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
1143063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        m_inst_emulator_ap->SetInstruction (inst->GetOpcode(),
1153063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                                                            inst->GetAddress(),
116567e7f3ba16eb48cb9fd6a2f26f2f7269eb6983cGreg Clayton                                                            exe_ctx.GetTargetPtr());
1173063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
1183063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        m_inst_emulator_ap->EvaluateInstruction (eEmulateInstructionOptionIgnoreConditions);
11975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
12075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        if (unwind_plan.GetLastRow() != m_curr_row)
12175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        {
12275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            // Be sure to not edit the offset unless our row has changed
12375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            // so that the "!=" call above doesn't trigger every time
12475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            m_curr_row.SetOffset (inst->GetAddress().GetFileAddress() + inst->GetOpcode().GetByteSize() - base_addr);
12575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            // Append the new row
12675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            unwind_plan.AppendRow (m_curr_row);
12775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        }
1283063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    }
129888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                }
130888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            }
131888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        }
13275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
1332d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda        if (log && log->GetVerbose ())
13475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        {
13575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            StreamString strm;
13675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            lldb::addr_t base_addr = range.GetBaseAddress().GetLoadAddress(&thread.GetProcess().GetTarget());
13775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            strm.Printf ("Resulting unwind rows for [0x%llx - 0x%llx):", base_addr, base_addr + range.GetByteSize());
13875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            unwind_plan.Dump(strm, &thread, base_addr);
13975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            log->PutCString (strm.GetData());
14075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        }
14175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        return unwind_plan.GetRowCount() > 0;
142888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    }
143f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return false;
144f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
145f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
146f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonbool
147888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::GetFastUnwindPlan (AddressRange& func,
148888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                Thread& thread,
149888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                UnwindPlan &unwind_plan)
150f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
151f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return false;
152f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
153f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
154f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonbool
155888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::FirstNonPrologueInsn (AddressRange& func,
156888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                   Target& target,
157888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                   Thread* thread,
158888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                   Address& first_non_prologue_insn)
159f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
160f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return false;
161f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
162f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
1638badcb2503ed2e2884a48f66099c1d48494817f4Greg ClaytonUnwindAssembly *
164f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::CreateInstance (const ArchSpec &arch)
165f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
166061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    std::auto_ptr<EmulateInstruction> inst_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypePrologueEpilogue, NULL));
167888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    // Make sure that all prologue instructions are handled
168888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    if (inst_emulator_ap.get())
169888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        return new UnwindAssemblyInstEmulation (arch, inst_emulator_ap.release());
170f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return NULL;
171f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
172f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
173f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
174f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//------------------------------------------------------------------
175f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton// PluginInterface protocol in UnwindAssemblyParser_x86
176f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//------------------------------------------------------------------
177f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
178f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonconst char *
179f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetPluginName()
180f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
181f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return "UnwindAssemblyInstEmulation";
182f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
183f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
184f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonconst char *
185f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetShortPluginName()
186f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
187f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return "unwindassembly.inst-emulation";
188f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
189f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
190f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
191f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonuint32_t
192f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetPluginVersion()
193f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
194f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return 1;
195f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
196f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
197f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonvoid
198f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::Initialize()
199f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
200f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    PluginManager::RegisterPlugin (GetPluginNameStatic(),
201f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton                                   GetPluginDescriptionStatic(),
202f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton                                   CreateInstance);
203f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
204f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
205f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonvoid
206f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::Terminate()
207f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
208f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    PluginManager::UnregisterPlugin (CreateInstance);
209f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
210f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
211f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
212f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonconst char *
213f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetPluginNameStatic()
214f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
215f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return "UnwindAssemblyInstEmulation";
216f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
217f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
218f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonconst char *
219f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetPluginDescriptionStatic()
220f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
221f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return "Instruction emulation based unwind information.";
222f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
223888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
224888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
225c07d451bb046e47215bd73fda0235362cc6b1a47Greg Claytonuint64_t
226061b79dbf1fefaf157d414747e98a463a0f32edaGreg ClaytonUnwindAssemblyInstEmulation::MakeRegisterKindValuePair (const RegisterInfo &reg_info)
227c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton{
228c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    uint32_t reg_kind, reg_num;
229061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    if (EmulateInstruction::GetBestRegisterKindAndNumber (&reg_info, reg_kind, reg_num))
230c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton        return (uint64_t)reg_kind << 24 | reg_num;
231c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    return 0ull;
232c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton}
233c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton
234c07d451bb046e47215bd73fda0235362cc6b1a47Greg Claytonvoid
235061b79dbf1fefaf157d414747e98a463a0f32edaGreg ClaytonUnwindAssemblyInstEmulation::SetRegisterValue (const RegisterInfo &reg_info, const RegisterValue &reg_value)
236c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton{
237c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    m_register_values[MakeRegisterKindValuePair (reg_info)] = reg_value;
238c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton}
239c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton
240061b79dbf1fefaf157d414747e98a463a0f32edaGreg Claytonbool
241061b79dbf1fefaf157d414747e98a463a0f32edaGreg ClaytonUnwindAssemblyInstEmulation::GetRegisterValue (const RegisterInfo &reg_info, RegisterValue &reg_value)
242c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton{
243c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    const uint64_t reg_id = MakeRegisterKindValuePair (reg_info);
244c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    RegisterValueMap::const_iterator pos = m_register_values.find(reg_id);
245c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    if (pos != m_register_values.end())
246061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    {
247061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton        reg_value = pos->second;
248061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton        return true; // We had a real value that comes from an opcode that wrote
249061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton                     // to it...
250061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    }
251061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    // We are making up a value that is recognizable...
252061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    reg_value.SetUInt(reg_id, reg_info.byte_size);
253061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    return false;
254c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton}
255c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton
256888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
257888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Claytonsize_t
258888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::ReadMemory (EmulateInstruction *instruction,
259888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         void *baton,
260888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         const EmulateInstruction::Context &context,
261888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         lldb::addr_t addr,
262888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         void *dst,
263888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         size_t dst_len)
264888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton{
26575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
26675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
2672d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda    if (log && log->GetVerbose ())
26875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    {
26975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        StreamString strm;
27075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        strm.Printf ("UnwindAssemblyInstEmulation::ReadMemory    (addr = 0x%16.16llx, dst = %p, dst_len = %zu, context = ",
27175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                     addr,
27275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                     dst,
27375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                     dst_len);
27475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        context.Dump(strm, instruction);
27575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        log->PutCString (strm.GetData ());
27675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    }
277888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    return dst_len;
278888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton}
279888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
280888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Claytonsize_t
281888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction,
282888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          void *baton,
283888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          const EmulateInstruction::Context &context,
284888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          lldb::addr_t addr,
285888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          const void *dst,
286888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          size_t dst_len)
287888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton{
28875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    if (baton && dst && dst_len)
28975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        return ((UnwindAssemblyInstEmulation *)baton)->WriteMemory (instruction, context, addr, dst, dst_len);
29075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    return 0;
29175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton}
29275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
29375906e4ec98af3717e415727a8d663a4e246bb4fGreg Claytonsize_t
29475906e4ec98af3717e415727a8d663a4e246bb4fGreg ClaytonUnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction,
29575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                          const EmulateInstruction::Context &context,
29675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                          lldb::addr_t addr,
29775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                          const void *dst,
29875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                          size_t dst_len)
29975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton{
300888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    DataExtractor data (dst,
301888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                        dst_len,
302888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                        instruction->GetArchitecture ().GetByteOrder(),
303888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                        instruction->GetArchitecture ().GetAddressByteSize());
304888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
30575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
30675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
3072d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda    if (log && log->GetVerbose ())
30875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    {
30975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        StreamString strm;
31075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
31175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        strm.PutCString ("UnwindAssemblyInstEmulation::WriteMemory   (");
31275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        data.Dump(&strm, 0, eFormatBytes, 1, dst_len, UINT32_MAX, addr, 0, 0);
31375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        strm.PutCString (", context = ");
31475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        context.Dump(strm, instruction);
31575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        log->PutCString (strm.GetData());
31675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    }
3173063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
31875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    const bool can_replace = true;
31975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    const bool cant_replace = false;
32075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
3213063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton    switch (context.type)
3223063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton    {
323061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton        default:
3243063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextInvalid:
3253063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextReadOpcode:
3263063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextImmediate:
3273063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAdjustBaseRegister:
3283063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextRegisterPlusOffset:
3293063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAdjustPC:
3303063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextRegisterStore:
3313063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextRegisterLoad:
3323063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextRelativeBranchImmediate:
3333063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAbsoluteBranchRegister:
3343063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextSupervisorCall:
3353063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextTableBranchReadMemory:
3363063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextWriteRegisterRandomBits:
3373063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextWriteMemoryRandomBits:
3383063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextArithmetic:
3393063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAdvancePC:
3403063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextReturnFromException:
3413063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextPopRegisterOffStack:
3423063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAdjustStackPointer:
3433063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            break;
3443063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
3453063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextPushRegisterOnStack:
3463063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            {
34775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                uint32_t reg_num = LLDB_INVALID_REGNUM;
34875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                bool is_return_address_reg = false;
34975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind();
35075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                if (context.info_type == EmulateInstruction::eInfoTypeRegisterToRegisterPlusOffset)
35175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                {
35275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                    reg_num = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[unwind_reg_kind];
35375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                    if (context.info.RegisterToRegisterPlusOffset.data_reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_RA)
35475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        is_return_address_reg = true;
35575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                }
35675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                else
35775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                {
35875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                    assert (!"unhandled case, add code to handle this!");
35975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                }
36075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
36175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                if (reg_num != LLDB_INVALID_REGNUM)
36275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                {
36375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                    if (m_pushed_regs.find (reg_num) == m_pushed_regs.end())
3643063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    {
36575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        m_pushed_regs[reg_num] = addr;
36675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        const int32_t offset = addr - m_initial_sp;
36775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        m_curr_row.SetRegisterLocationToAtCFAPlusOffset (reg_num, offset, cant_replace);
36875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        if (is_return_address_reg)
36975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        {
37075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            // This push was pushing the return address register,
37175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            // so this is also how we will unwind the PC...
37275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            RegisterInfo pc_reg_info;
37375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            if (instruction->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info))
37475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            {
37575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                uint32_t pc_reg_num = pc_reg_info.kinds[unwind_reg_kind];
37675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                if (pc_reg_num != LLDB_INVALID_REGNUM)
37775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                    m_curr_row.SetRegisterLocationToAtCFAPlusOffset (pc_reg_num, offset, can_replace);
37875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            }
37975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        }
3803063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    }
38175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                }
3823063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            }
3833063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            break;
3843063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
3853063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton    }
3863063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
387888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    return dst_len;
388888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton}
389888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
390888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Claytonbool
391888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::ReadRegister (EmulateInstruction *instruction,
392888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                           void *baton,
393061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton                                           const RegisterInfo *reg_info,
394061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton                                           RegisterValue &reg_value)
395888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton{
39675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
397061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    if (baton && reg_info)
39875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        return ((UnwindAssemblyInstEmulation *)baton)->ReadRegister (instruction, reg_info, reg_value);
39975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    return false;
40075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton}
40175906e4ec98af3717e415727a8d663a4e246bb4fGreg Claytonbool
40275906e4ec98af3717e415727a8d663a4e246bb4fGreg ClaytonUnwindAssemblyInstEmulation::ReadRegister (EmulateInstruction *instruction,
40375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                           const RegisterInfo *reg_info,
40475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                           RegisterValue &reg_value)
40575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton{
40675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    bool synthetic = GetRegisterValue (*reg_info, reg_value);
407888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
40875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
40975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
4102d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda    if (log && log->GetVerbose ())
41175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    {
41275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
41375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        StreamString strm;
414061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton        strm.Printf ("UnwindAssemblyInstEmulation::ReadRegister  (name = \"%s\") => synthetic_value = %i, value = ", reg_info->name, synthetic);
415997b1e82f098a8b748b490d1ae6d0bbe597a59d5Greg Clayton        reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
41675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        log->PutCString(strm.GetData());
417061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    }
418888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    return true;
419888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton}
420888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
421888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Claytonbool
422888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
423888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                            void *baton,
424888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                            const EmulateInstruction::Context &context,
425061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton                                            const RegisterInfo *reg_info,
426061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton                                            const RegisterValue &reg_value)
427888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton{
42875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    if (baton && reg_info)
42975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        return ((UnwindAssemblyInstEmulation *)baton)->WriteRegister (instruction, context, reg_info, reg_value);
43075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    return false;
43175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton}
43275906e4ec98af3717e415727a8d663a4e246bb4fGreg Claytonbool
43375906e4ec98af3717e415727a8d663a4e246bb4fGreg ClaytonUnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
43475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                            const EmulateInstruction::Context &context,
43575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                            const RegisterInfo *reg_info,
43675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                            const RegisterValue &reg_value)
43775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton{
43875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
439061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton
4402d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda    if (log && log->GetVerbose ())
44175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    {
44275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
44375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        StreamString strm;
44475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        strm.Printf ("UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ", reg_info->name);
445997b1e82f098a8b748b490d1ae6d0bbe597a59d5Greg Clayton        reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
44675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        strm.PutCString (", context = ");
44775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        context.Dump(strm, instruction);
44875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        log->PutCString(strm.GetData());
44975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    }
450c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton
45175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    const bool must_replace = true;
45275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    SetRegisterValue (*reg_info, reg_value);
453888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
454888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    switch (context.type)
455888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    {
456061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton        default:
457888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextInvalid:
458888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextReadOpcode:
459888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextImmediate:
460888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAdjustBaseRegister:
461888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextRegisterPlusOffset:
462888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAdjustPC:
463888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextRegisterStore:
464888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextRegisterLoad:
465888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextRelativeBranchImmediate:
466888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAbsoluteBranchRegister:
467888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextSupervisorCall:
468888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextTableBranchReadMemory:
469888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextWriteRegisterRandomBits:
470888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextWriteMemoryRandomBits:
471c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton        case EmulateInstruction::eContextArithmetic:
472888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAdvancePC:
473888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextReturnFromException:
474888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextPushRegisterOnStack:
47575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//            {
47675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
47775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                if (reg_num != LLDB_INVALID_REGNUM)
47875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                {
47975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                    const bool can_replace_only_if_unspecified = true;
48075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//
48175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                    m_curr_row.SetRegisterLocationToUndefined (reg_num,
48275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                                                               can_replace_only_if_unspecified,
48375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                                                               can_replace_only_if_unspecified);
48475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                }
48575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//            }
486888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            break;
4873063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
488888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextPopRegisterOffStack:
4893063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            {
49075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
49175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                if (reg_num != LLDB_INVALID_REGNUM)
4923063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                {
49375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                    m_curr_row.SetRegisterLocationToSame (reg_num, must_replace);
4943063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                }
4953063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            }
496888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            break;
497888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
49875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        case EmulateInstruction::eContextSetFramePointer:
49975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            if (!m_fp_is_cfa)
50075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            {
50175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                m_fp_is_cfa = true;
50275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                m_cfa_reg_info = *reg_info;
50375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                const uint32_t cfa_reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
50475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                assert (cfa_reg_num != LLDB_INVALID_REGNUM);
50575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                m_curr_row.SetCFARegister(cfa_reg_num);
50675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                m_curr_row.SetCFAOffset(m_initial_sp - reg_value.GetAsUInt64());
50775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            }
50875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            break;
50975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
510888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAdjustStackPointer:
51175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            // If we have created a frame using the frame pointer, don't follow
51275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            // subsequent adjustments to the stack pointer.
51375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            if (!m_fp_is_cfa)
51475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            {
51575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                m_curr_row.SetCFAOffset (m_initial_sp - reg_value.GetAsUInt64());
51675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            }
517888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            break;
518888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    }
519888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    return true;
520888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton}
521888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
522888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
523