UnwindAssemblyInstEmulation.cpp revision 0fef968c843be422d6facc2e8d54d8471eee88ed
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;
7475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            // Initialize the CFA with a known value. In the 32 bit case
75888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            // it will be 0x80000000, and in the 64 bit case 0x8000000000000000.
76888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            // We use the address byte size to be safe for any future addresss sizes
7775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            m_inst_emulator_ap->GetRegisterInfo (unwind_plan.GetRegisterKind(),
7875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                                 unwind_plan.GetInitialCFARegister(),
7975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                                 m_cfa_reg_info);
8075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
8175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            m_fp_is_cfa = false;
8275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            m_register_values.clear();
8375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            m_pushed_regs.clear();
8475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
85061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton            m_initial_sp = (1ull << ((addr_byte_size * 8) - 1));
862f085c6ca2895663687dca704589478ff040b849Greg Clayton            RegisterValue cfa_reg_value;
872f085c6ca2895663687dca704589478ff040b849Greg Clayton            cfa_reg_value.SetUInt (m_initial_sp, m_cfa_reg_info.byte_size);
882f085c6ca2895663687dca704589478ff040b849Greg Clayton            SetRegisterValue (m_cfa_reg_info, cfa_reg_value);
89888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
90888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            const InstructionList &inst_list = disasm_sp->GetInstructionList ();
91888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            const size_t num_instructions = inst_list.GetSize();
923063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            if (num_instructions > 0)
93888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            {
943063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                Instruction *inst = inst_list.GetInstructionAtIndex (0).get();
953063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                const addr_t base_addr = inst->GetAddress().GetFileAddress();
9675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                // Initialize the current row with the one row that was created
9775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                // from the CreateFunctionEntryUnwind call above...
9875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                m_curr_row = unwind_plan.GetLastRow();
99888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
1003063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                for (size_t idx=0; idx<num_instructions; ++idx)
1013063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                {
1023063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    inst = inst_list.GetInstructionAtIndex (idx).get();
1033063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    if (inst)
1043063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    {
10575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
1062d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda                        if (log && log->GetVerbose ())
10775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        {
10875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            StreamString strm;
1090fef968c843be422d6facc2e8d54d8471eee88edGreg Clayton                            inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL);
11075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            log->PutCString (strm.GetData());
11175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        }
1123063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
1133063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        m_inst_emulator_ap->SetInstruction (inst->GetOpcode(),
1143063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                                                            inst->GetAddress(),
115567e7f3ba16eb48cb9fd6a2f26f2f7269eb6983cGreg Clayton                                                            exe_ctx.GetTargetPtr());
1163063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
1173063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        m_inst_emulator_ap->EvaluateInstruction (eEmulateInstructionOptionIgnoreConditions);
11875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
11975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        if (unwind_plan.GetLastRow() != m_curr_row)
12075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        {
12175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            // Be sure to not edit the offset unless our row has changed
12275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            // so that the "!=" call above doesn't trigger every time
12375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            m_curr_row.SetOffset (inst->GetAddress().GetFileAddress() + inst->GetOpcode().GetByteSize() - base_addr);
12475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            // Append the new row
12575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            unwind_plan.AppendRow (m_curr_row);
12675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        }
1273063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    }
128888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                }
129888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            }
130888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        }
13175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
1322d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda        if (log && log->GetVerbose ())
13375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        {
13475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            StreamString strm;
135f4124deeb9532044a38c0774ced872f2709347daGreg Clayton            lldb::addr_t base_addr = range.GetBaseAddress().GetLoadAddress(thread.CalculateTarget().get());
13675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            strm.Printf ("Resulting unwind rows for [0x%llx - 0x%llx):", base_addr, base_addr + range.GetByteSize());
13775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            unwind_plan.Dump(strm, &thread, base_addr);
13875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            log->PutCString (strm.GetData());
13975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        }
14075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        return unwind_plan.GetRowCount() > 0;
141888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    }
142f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return false;
143f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
144f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
145f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonbool
146888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::GetFastUnwindPlan (AddressRange& func,
147888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                Thread& thread,
148888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                UnwindPlan &unwind_plan)
149f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
150f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return false;
151f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
152f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
153f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonbool
154888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::FirstNonPrologueInsn (AddressRange& func,
155f4124deeb9532044a38c0774ced872f2709347daGreg Clayton                                                   const ExecutionContext &exe_ctx,
156888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                   Address& first_non_prologue_insn)
157f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
158f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return false;
159f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
160f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
1618badcb2503ed2e2884a48f66099c1d48494817f4Greg ClaytonUnwindAssembly *
162f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::CreateInstance (const ArchSpec &arch)
163f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
164061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    std::auto_ptr<EmulateInstruction> inst_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypePrologueEpilogue, NULL));
165888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    // Make sure that all prologue instructions are handled
166888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    if (inst_emulator_ap.get())
167888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        return new UnwindAssemblyInstEmulation (arch, inst_emulator_ap.release());
168f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return NULL;
169f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
170f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
171f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
172f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//------------------------------------------------------------------
173f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton// PluginInterface protocol in UnwindAssemblyParser_x86
174f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//------------------------------------------------------------------
175f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
176f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonconst char *
177f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetPluginName()
178f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
179f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return "UnwindAssemblyInstEmulation";
180f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
181f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
182f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonconst char *
183f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetShortPluginName()
184f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
185f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return "unwindassembly.inst-emulation";
186f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
187f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
188f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
189f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonuint32_t
190f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetPluginVersion()
191f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
192f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return 1;
193f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
194f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
195f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonvoid
196f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::Initialize()
197f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
198f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    PluginManager::RegisterPlugin (GetPluginNameStatic(),
199f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton                                   GetPluginDescriptionStatic(),
200f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton                                   CreateInstance);
201f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
202f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
203f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonvoid
204f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::Terminate()
205f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
206f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    PluginManager::UnregisterPlugin (CreateInstance);
207f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
208f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
209f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
210f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonconst char *
211f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetPluginNameStatic()
212f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
213f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return "UnwindAssemblyInstEmulation";
214f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
215f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
216f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonconst char *
217f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetPluginDescriptionStatic()
218f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
219f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return "Instruction emulation based unwind information.";
220f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
221888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
222888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
223c07d451bb046e47215bd73fda0235362cc6b1a47Greg Claytonuint64_t
224061b79dbf1fefaf157d414747e98a463a0f32edaGreg ClaytonUnwindAssemblyInstEmulation::MakeRegisterKindValuePair (const RegisterInfo &reg_info)
225c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton{
226c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    uint32_t reg_kind, reg_num;
227061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    if (EmulateInstruction::GetBestRegisterKindAndNumber (&reg_info, reg_kind, reg_num))
228c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton        return (uint64_t)reg_kind << 24 | reg_num;
229c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    return 0ull;
230c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton}
231c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton
232c07d451bb046e47215bd73fda0235362cc6b1a47Greg Claytonvoid
233061b79dbf1fefaf157d414747e98a463a0f32edaGreg ClaytonUnwindAssemblyInstEmulation::SetRegisterValue (const RegisterInfo &reg_info, const RegisterValue &reg_value)
234c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton{
235c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    m_register_values[MakeRegisterKindValuePair (reg_info)] = reg_value;
236c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton}
237c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton
238061b79dbf1fefaf157d414747e98a463a0f32edaGreg Claytonbool
239061b79dbf1fefaf157d414747e98a463a0f32edaGreg ClaytonUnwindAssemblyInstEmulation::GetRegisterValue (const RegisterInfo &reg_info, RegisterValue &reg_value)
240c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton{
241c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    const uint64_t reg_id = MakeRegisterKindValuePair (reg_info);
242c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    RegisterValueMap::const_iterator pos = m_register_values.find(reg_id);
243c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    if (pos != m_register_values.end())
244061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    {
245061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton        reg_value = pos->second;
246061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton        return true; // We had a real value that comes from an opcode that wrote
247061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton                     // to it...
248061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    }
249061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    // We are making up a value that is recognizable...
250061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    reg_value.SetUInt(reg_id, reg_info.byte_size);
251061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    return false;
252c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton}
253c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton
254888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
255888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Claytonsize_t
256888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::ReadMemory (EmulateInstruction *instruction,
257888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         void *baton,
258888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         const EmulateInstruction::Context &context,
259888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         lldb::addr_t addr,
260888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         void *dst,
261888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         size_t dst_len)
262888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton{
26375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
26475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
2652d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda    if (log && log->GetVerbose ())
26675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    {
26775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        StreamString strm;
26875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        strm.Printf ("UnwindAssemblyInstEmulation::ReadMemory    (addr = 0x%16.16llx, dst = %p, dst_len = %zu, context = ",
26975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                     addr,
27075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                     dst,
27175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                     dst_len);
27275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        context.Dump(strm, instruction);
27375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        log->PutCString (strm.GetData ());
27475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    }
275888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    return dst_len;
276888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton}
277888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
278888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Claytonsize_t
279888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction,
280888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          void *baton,
281888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          const EmulateInstruction::Context &context,
282888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          lldb::addr_t addr,
283888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          const void *dst,
284888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          size_t dst_len)
285888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton{
28675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    if (baton && dst && dst_len)
28775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        return ((UnwindAssemblyInstEmulation *)baton)->WriteMemory (instruction, context, addr, dst, dst_len);
28875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    return 0;
28975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton}
29075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
29175906e4ec98af3717e415727a8d663a4e246bb4fGreg Claytonsize_t
29275906e4ec98af3717e415727a8d663a4e246bb4fGreg ClaytonUnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction,
29375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                          const EmulateInstruction::Context &context,
29475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                          lldb::addr_t addr,
29575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                          const void *dst,
29675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                          size_t dst_len)
29775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton{
298888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    DataExtractor data (dst,
299888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                        dst_len,
300888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                        instruction->GetArchitecture ().GetByteOrder(),
301888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                        instruction->GetArchitecture ().GetAddressByteSize());
302888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
30375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
30475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
3052d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda    if (log && log->GetVerbose ())
30675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    {
30775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        StreamString strm;
30875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
30975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        strm.PutCString ("UnwindAssemblyInstEmulation::WriteMemory   (");
31075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        data.Dump(&strm, 0, eFormatBytes, 1, dst_len, UINT32_MAX, addr, 0, 0);
31175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        strm.PutCString (", context = ");
31275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        context.Dump(strm, instruction);
31375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        log->PutCString (strm.GetData());
31475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    }
3153063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
31675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    const bool can_replace = true;
31775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    const bool cant_replace = false;
31875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
3193063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton    switch (context.type)
3203063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton    {
321061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton        default:
3223063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextInvalid:
3233063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextReadOpcode:
3243063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextImmediate:
3253063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAdjustBaseRegister:
3263063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextRegisterPlusOffset:
3273063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAdjustPC:
3283063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextRegisterStore:
3293063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextRegisterLoad:
3303063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextRelativeBranchImmediate:
3313063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAbsoluteBranchRegister:
3323063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextSupervisorCall:
3333063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextTableBranchReadMemory:
3343063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextWriteRegisterRandomBits:
3353063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextWriteMemoryRandomBits:
3363063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextArithmetic:
3373063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAdvancePC:
3383063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextReturnFromException:
3393063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextPopRegisterOffStack:
3403063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAdjustStackPointer:
3413063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            break;
3423063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
3433063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextPushRegisterOnStack:
3443063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            {
34575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                uint32_t reg_num = LLDB_INVALID_REGNUM;
34675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                bool is_return_address_reg = false;
34775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind();
34875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                if (context.info_type == EmulateInstruction::eInfoTypeRegisterToRegisterPlusOffset)
34975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                {
35075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                    reg_num = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[unwind_reg_kind];
35175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                    if (context.info.RegisterToRegisterPlusOffset.data_reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_RA)
35275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        is_return_address_reg = true;
35375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                }
35475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                else
35575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                {
35675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                    assert (!"unhandled case, add code to handle this!");
35775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                }
35875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
35975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                if (reg_num != LLDB_INVALID_REGNUM)
36075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                {
36175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                    if (m_pushed_regs.find (reg_num) == m_pushed_regs.end())
3623063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    {
36375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        m_pushed_regs[reg_num] = addr;
36475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        const int32_t offset = addr - m_initial_sp;
36575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        m_curr_row.SetRegisterLocationToAtCFAPlusOffset (reg_num, offset, cant_replace);
36675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        if (is_return_address_reg)
36775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        {
36875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            // This push was pushing the return address register,
36975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            // so this is also how we will unwind the PC...
37075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            RegisterInfo pc_reg_info;
37175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            if (instruction->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info))
37275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            {
37375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                uint32_t pc_reg_num = pc_reg_info.kinds[unwind_reg_kind];
37475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                if (pc_reg_num != LLDB_INVALID_REGNUM)
37575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                    m_curr_row.SetRegisterLocationToAtCFAPlusOffset (pc_reg_num, offset, can_replace);
37675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            }
37775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        }
3783063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    }
37975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                }
3803063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            }
3813063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            break;
3823063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
3833063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton    }
3843063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
385888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    return dst_len;
386888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton}
387888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
388888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Claytonbool
389888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::ReadRegister (EmulateInstruction *instruction,
390888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                           void *baton,
391061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton                                           const RegisterInfo *reg_info,
392061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton                                           RegisterValue &reg_value)
393888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton{
39475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
395061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    if (baton && reg_info)
39675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        return ((UnwindAssemblyInstEmulation *)baton)->ReadRegister (instruction, reg_info, reg_value);
39775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    return false;
39875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton}
39975906e4ec98af3717e415727a8d663a4e246bb4fGreg Claytonbool
40075906e4ec98af3717e415727a8d663a4e246bb4fGreg ClaytonUnwindAssemblyInstEmulation::ReadRegister (EmulateInstruction *instruction,
40175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                           const RegisterInfo *reg_info,
40275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                           RegisterValue &reg_value)
40375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton{
40475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    bool synthetic = GetRegisterValue (*reg_info, reg_value);
405888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
40675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
40775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
4082d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda    if (log && log->GetVerbose ())
40975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    {
41075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
41175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        StreamString strm;
412061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton        strm.Printf ("UnwindAssemblyInstEmulation::ReadRegister  (name = \"%s\") => synthetic_value = %i, value = ", reg_info->name, synthetic);
413997b1e82f098a8b748b490d1ae6d0bbe597a59d5Greg Clayton        reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
41475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        log->PutCString(strm.GetData());
415061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    }
416888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    return true;
417888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton}
418888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
419888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Claytonbool
420888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
421888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                            void *baton,
422888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                            const EmulateInstruction::Context &context,
423061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton                                            const RegisterInfo *reg_info,
424061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton                                            const RegisterValue &reg_value)
425888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton{
42675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    if (baton && reg_info)
42775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        return ((UnwindAssemblyInstEmulation *)baton)->WriteRegister (instruction, context, reg_info, reg_value);
42875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    return false;
42975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton}
43075906e4ec98af3717e415727a8d663a4e246bb4fGreg Claytonbool
43175906e4ec98af3717e415727a8d663a4e246bb4fGreg ClaytonUnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
43275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                            const EmulateInstruction::Context &context,
43375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                            const RegisterInfo *reg_info,
43475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                            const RegisterValue &reg_value)
43575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton{
43675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
437061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton
4382d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda    if (log && log->GetVerbose ())
43975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    {
44075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
44175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        StreamString strm;
44275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        strm.Printf ("UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ", reg_info->name);
443997b1e82f098a8b748b490d1ae6d0bbe597a59d5Greg Clayton        reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
44475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        strm.PutCString (", context = ");
44575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        context.Dump(strm, instruction);
44675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        log->PutCString(strm.GetData());
44775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    }
448c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton
44975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    const bool must_replace = true;
45075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    SetRegisterValue (*reg_info, reg_value);
451888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
452888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    switch (context.type)
453888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    {
454061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton        default:
455888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextInvalid:
456888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextReadOpcode:
457888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextImmediate:
458888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAdjustBaseRegister:
459888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextRegisterPlusOffset:
460888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAdjustPC:
461888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextRegisterStore:
462888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextRegisterLoad:
463888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextRelativeBranchImmediate:
464888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAbsoluteBranchRegister:
465888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextSupervisorCall:
466888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextTableBranchReadMemory:
467888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextWriteRegisterRandomBits:
468888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextWriteMemoryRandomBits:
469c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton        case EmulateInstruction::eContextArithmetic:
470888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAdvancePC:
471888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextReturnFromException:
472888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextPushRegisterOnStack:
47375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//            {
47475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
47575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                if (reg_num != LLDB_INVALID_REGNUM)
47675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                {
47775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                    const bool can_replace_only_if_unspecified = true;
47875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//
47975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                    m_curr_row.SetRegisterLocationToUndefined (reg_num,
48075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                                                               can_replace_only_if_unspecified,
48175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                                                               can_replace_only_if_unspecified);
48275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                }
48375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//            }
484888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            break;
4853063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
486888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextPopRegisterOffStack:
4873063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            {
48875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
48975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                if (reg_num != LLDB_INVALID_REGNUM)
4903063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                {
49175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                    m_curr_row.SetRegisterLocationToSame (reg_num, must_replace);
4923063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                }
4933063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            }
494888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            break;
495888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
49675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        case EmulateInstruction::eContextSetFramePointer:
49775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            if (!m_fp_is_cfa)
49875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            {
49975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                m_fp_is_cfa = true;
50075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                m_cfa_reg_info = *reg_info;
50175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                const uint32_t cfa_reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
50275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                assert (cfa_reg_num != LLDB_INVALID_REGNUM);
50375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                m_curr_row.SetCFARegister(cfa_reg_num);
50475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                m_curr_row.SetCFAOffset(m_initial_sp - reg_value.GetAsUInt64());
50575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            }
50675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            break;
50775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
508888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAdjustStackPointer:
50975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            // If we have created a frame using the frame pointer, don't follow
51075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            // subsequent adjustments to the stack pointer.
51175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            if (!m_fp_is_cfa)
51275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            {
51375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                m_curr_row.SetCFAOffset (m_initial_sp - reg_value.GetAsUInt64());
51475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            }
515888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            break;
516888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    }
517888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    return true;
518888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton}
519888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
520888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
521