UnwindAssemblyInstEmulation.cpp revision 68fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7
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//-----------------------------------------------------------------------------------------------
337fad24a9fd7226016b28fef78930501a1bef898cJason Molenda//  UnwindAssemblyInstEmulation 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            m_inst_emulator_ap->GetRegisterInfo (unwind_plan.GetRegisterKind(),
7575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                                 unwind_plan.GetInitialCFARegister(),
7675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                                 m_cfa_reg_info);
7775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
7875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            m_fp_is_cfa = false;
7975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            m_register_values.clear();
8075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            m_pushed_regs.clear();
8175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
827fad24a9fd7226016b28fef78930501a1bef898cJason Molenda            // Initialize the CFA with a known value. In the 32 bit case
837fad24a9fd7226016b28fef78930501a1bef898cJason Molenda            // it will be 0x80000000, and in the 64 bit case 0x8000000000000000.
847fad24a9fd7226016b28fef78930501a1bef898cJason Molenda            // We use the address byte size to be safe for any future addresss sizes
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);
8968fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda
90888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            const InstructionList &inst_list = disasm_sp->GetInstructionList ();
91888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            const size_t num_instructions = inst_list.GetSize();
9268fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda
9368fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda            UnwindPlan::RowSP prologue_completed_row;
9468fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda
953063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            if (num_instructions > 0)
96888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            {
973063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                Instruction *inst = inst_list.GetInstructionAtIndex (0).get();
983063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                const addr_t base_addr = inst->GetAddress().GetFileAddress();
9975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                // Initialize the current row with the one row that was created
10075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                // from the CreateFunctionEntryUnwind call above...
10168fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda                UnwindPlan::RowSP last_row = unwind_plan.GetLastRow();
10268fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda                UnwindPlan::Row *newrow = new UnwindPlan::Row;
10368fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda                if (last_row.get())
10468fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda                    *newrow = *last_row.get();
10568fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda                m_curr_row.reset(newrow);
106888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
1073063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                for (size_t idx=0; idx<num_instructions; ++idx)
1083063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                {
1093063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    inst = inst_list.GetInstructionAtIndex (idx).get();
1103063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    if (inst)
1113063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    {
1122d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda                        if (log && log->GetVerbose ())
11375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        {
11475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            StreamString strm;
1150fef968c843be422d6facc2e8d54d8471eee88edGreg Clayton                            inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL);
11675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            log->PutCString (strm.GetData());
11775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        }
1183063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
1193063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        m_inst_emulator_ap->SetInstruction (inst->GetOpcode(),
1203063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                                                            inst->GetAddress(),
121567e7f3ba16eb48cb9fd6a2f26f2f7269eb6983cGreg Clayton                                                            exe_ctx.GetTargetPtr());
1223063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
1233063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        m_inst_emulator_ap->EvaluateInstruction (eEmulateInstructionOptionIgnoreConditions);
12475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
12575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        if (unwind_plan.GetLastRow() != m_curr_row)
12675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        {
12775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            // Be sure to not edit the offset unless our row has changed
12875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            // so that the "!=" call above doesn't trigger every time
12968fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda                            m_curr_row->SetOffset (inst->GetAddress().GetFileAddress() + inst->GetOpcode().GetByteSize() - base_addr);
13075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            // Append the new row
13175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            unwind_plan.AppendRow (m_curr_row);
13268fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda
13368fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda                            UnwindPlan::Row *newrow = new UnwindPlan::Row;
13468fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda                            *newrow = *m_curr_row.get();
13568fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda                            m_curr_row.reset(newrow);
13675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        }
1373063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    }
138888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                }
139888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            }
140888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        }
14175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
1422d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda        if (log && log->GetVerbose ())
14375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        {
14475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            StreamString strm;
145f4124deeb9532044a38c0774ced872f2709347daGreg Clayton            lldb::addr_t base_addr = range.GetBaseAddress().GetLoadAddress(thread.CalculateTarget().get());
14675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            strm.Printf ("Resulting unwind rows for [0x%llx - 0x%llx):", base_addr, base_addr + range.GetByteSize());
14775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            unwind_plan.Dump(strm, &thread, base_addr);
14875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            log->PutCString (strm.GetData());
14975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        }
15075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        return unwind_plan.GetRowCount() > 0;
151888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    }
152f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return false;
153f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
154f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
155f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonbool
156888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::GetFastUnwindPlan (AddressRange& func,
157888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                Thread& thread,
158888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                UnwindPlan &unwind_plan)
159f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
160f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return false;
161f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
162f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
163f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonbool
164888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::FirstNonPrologueInsn (AddressRange& func,
165f4124deeb9532044a38c0774ced872f2709347daGreg Clayton                                                   const ExecutionContext &exe_ctx,
166888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                   Address& first_non_prologue_insn)
167f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
168f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return false;
169f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
170f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
1718badcb2503ed2e2884a48f66099c1d48494817f4Greg ClaytonUnwindAssembly *
172f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::CreateInstance (const ArchSpec &arch)
173f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
174061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    std::auto_ptr<EmulateInstruction> inst_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypePrologueEpilogue, NULL));
175888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    // Make sure that all prologue instructions are handled
176888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    if (inst_emulator_ap.get())
177888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        return new UnwindAssemblyInstEmulation (arch, inst_emulator_ap.release());
178f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return NULL;
179f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
180f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
181f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
182f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//------------------------------------------------------------------
183f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton// PluginInterface protocol in UnwindAssemblyParser_x86
184f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//------------------------------------------------------------------
185f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
186f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonconst char *
187f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetPluginName()
188f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
189f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return "UnwindAssemblyInstEmulation";
190f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
191f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
192f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonconst char *
193f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetShortPluginName()
194f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
195f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return "unwindassembly.inst-emulation";
196f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
197f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
198f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
199f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonuint32_t
200f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetPluginVersion()
201f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
202f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return 1;
203f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
204f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
205f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonvoid
206f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::Initialize()
207f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
208f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    PluginManager::RegisterPlugin (GetPluginNameStatic(),
209f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton                                   GetPluginDescriptionStatic(),
210f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton                                   CreateInstance);
211f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
212f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
213f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonvoid
214f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::Terminate()
215f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
216f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    PluginManager::UnregisterPlugin (CreateInstance);
217f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
218f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
219f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
220f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonconst char *
221f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetPluginNameStatic()
222f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
223f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return "UnwindAssemblyInstEmulation";
224f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
225f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
226f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonconst char *
227f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetPluginDescriptionStatic()
228f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
229f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return "Instruction emulation based unwind information.";
230f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
231888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
232888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
233c07d451bb046e47215bd73fda0235362cc6b1a47Greg Claytonuint64_t
234061b79dbf1fefaf157d414747e98a463a0f32edaGreg ClaytonUnwindAssemblyInstEmulation::MakeRegisterKindValuePair (const RegisterInfo &reg_info)
235c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton{
236c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    uint32_t reg_kind, reg_num;
237061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    if (EmulateInstruction::GetBestRegisterKindAndNumber (&reg_info, reg_kind, reg_num))
238c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton        return (uint64_t)reg_kind << 24 | reg_num;
239c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    return 0ull;
240c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton}
241c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton
242c07d451bb046e47215bd73fda0235362cc6b1a47Greg Claytonvoid
243061b79dbf1fefaf157d414747e98a463a0f32edaGreg ClaytonUnwindAssemblyInstEmulation::SetRegisterValue (const RegisterInfo &reg_info, const RegisterValue &reg_value)
244c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton{
245c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    m_register_values[MakeRegisterKindValuePair (reg_info)] = reg_value;
246c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton}
247c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton
248061b79dbf1fefaf157d414747e98a463a0f32edaGreg Claytonbool
249061b79dbf1fefaf157d414747e98a463a0f32edaGreg ClaytonUnwindAssemblyInstEmulation::GetRegisterValue (const RegisterInfo &reg_info, RegisterValue &reg_value)
250c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton{
251c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    const uint64_t reg_id = MakeRegisterKindValuePair (reg_info);
252c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    RegisterValueMap::const_iterator pos = m_register_values.find(reg_id);
253c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    if (pos != m_register_values.end())
254061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    {
255061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton        reg_value = pos->second;
256061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton        return true; // We had a real value that comes from an opcode that wrote
257061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton                     // to it...
258061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    }
259061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    // We are making up a value that is recognizable...
260061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    reg_value.SetUInt(reg_id, reg_info.byte_size);
261061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    return false;
262c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton}
263c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton
264888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
265888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Claytonsize_t
266888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::ReadMemory (EmulateInstruction *instruction,
267888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         void *baton,
268888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         const EmulateInstruction::Context &context,
269888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         lldb::addr_t addr,
270888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         void *dst,
271888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         size_t dst_len)
272888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton{
27375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
27475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
2752d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda    if (log && log->GetVerbose ())
27675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    {
27775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        StreamString strm;
27875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        strm.Printf ("UnwindAssemblyInstEmulation::ReadMemory    (addr = 0x%16.16llx, dst = %p, dst_len = %zu, context = ",
27975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                     addr,
28075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                     dst,
28175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                     dst_len);
28275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        context.Dump(strm, instruction);
28375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        log->PutCString (strm.GetData ());
28475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    }
285888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    return dst_len;
286888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton}
287888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
288888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Claytonsize_t
289888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction,
290888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          void *baton,
291888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          const EmulateInstruction::Context &context,
292888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          lldb::addr_t addr,
293888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          const void *dst,
294888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          size_t dst_len)
295888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton{
29675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    if (baton && dst && dst_len)
29775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        return ((UnwindAssemblyInstEmulation *)baton)->WriteMemory (instruction, context, addr, dst, dst_len);
29875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    return 0;
29975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton}
30075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
30175906e4ec98af3717e415727a8d663a4e246bb4fGreg Claytonsize_t
30275906e4ec98af3717e415727a8d663a4e246bb4fGreg ClaytonUnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction,
30375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                          const EmulateInstruction::Context &context,
30475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                          lldb::addr_t addr,
30575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                          const void *dst,
30675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                          size_t dst_len)
30775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton{
308888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    DataExtractor data (dst,
309888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                        dst_len,
310888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                        instruction->GetArchitecture ().GetByteOrder(),
311888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                        instruction->GetArchitecture ().GetAddressByteSize());
312888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
31375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
31475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
3152d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda    if (log && log->GetVerbose ())
31675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    {
31775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        StreamString strm;
31875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
31975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        strm.PutCString ("UnwindAssemblyInstEmulation::WriteMemory   (");
32075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        data.Dump(&strm, 0, eFormatBytes, 1, dst_len, UINT32_MAX, addr, 0, 0);
32175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        strm.PutCString (", context = ");
32275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        context.Dump(strm, instruction);
32375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        log->PutCString (strm.GetData());
32475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    }
3253063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
32675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    const bool can_replace = true;
32775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    const bool cant_replace = false;
32875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
3293063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton    switch (context.type)
3303063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton    {
331061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton        default:
3323063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextInvalid:
3333063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextReadOpcode:
3343063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextImmediate:
3353063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAdjustBaseRegister:
3363063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextRegisterPlusOffset:
3373063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAdjustPC:
3383063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextRegisterStore:
3393063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextRegisterLoad:
3403063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextRelativeBranchImmediate:
3413063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAbsoluteBranchRegister:
3423063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextSupervisorCall:
3433063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextTableBranchReadMemory:
3443063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextWriteRegisterRandomBits:
3453063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextWriteMemoryRandomBits:
3463063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextArithmetic:
3473063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAdvancePC:
3483063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextReturnFromException:
3493063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextPopRegisterOffStack:
3503063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAdjustStackPointer:
3513063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            break;
3523063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
3533063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextPushRegisterOnStack:
3543063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            {
35575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                uint32_t reg_num = LLDB_INVALID_REGNUM;
35675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                bool is_return_address_reg = false;
35775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind();
35875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                if (context.info_type == EmulateInstruction::eInfoTypeRegisterToRegisterPlusOffset)
35975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                {
36075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                    reg_num = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[unwind_reg_kind];
36175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                    if (context.info.RegisterToRegisterPlusOffset.data_reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_RA)
36275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        is_return_address_reg = true;
36375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                }
36475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                else
36575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                {
36675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                    assert (!"unhandled case, add code to handle this!");
36775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                }
36875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
36975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                if (reg_num != LLDB_INVALID_REGNUM)
37075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                {
37175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                    if (m_pushed_regs.find (reg_num) == m_pushed_regs.end())
3723063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    {
37375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        m_pushed_regs[reg_num] = addr;
37475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        const int32_t offset = addr - m_initial_sp;
37568fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda                        m_curr_row->SetRegisterLocationToAtCFAPlusOffset (reg_num, offset, cant_replace);
37675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        if (is_return_address_reg)
37775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        {
37875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            // This push was pushing the return address register,
37975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            // so this is also how we will unwind the PC...
38075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            RegisterInfo pc_reg_info;
38175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            if (instruction->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info))
38275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            {
38375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                uint32_t pc_reg_num = pc_reg_info.kinds[unwind_reg_kind];
38475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                if (pc_reg_num != LLDB_INVALID_REGNUM)
38568fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda                                    m_curr_row->SetRegisterLocationToAtCFAPlusOffset (pc_reg_num, offset, can_replace);
38675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                            }
38775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                        }
3883063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    }
38975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                }
3903063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            }
3913063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            break;
3923063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
3933063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton    }
3943063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
395888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    return dst_len;
396888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton}
397888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
398888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Claytonbool
399888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::ReadRegister (EmulateInstruction *instruction,
400888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                           void *baton,
401061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton                                           const RegisterInfo *reg_info,
402061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton                                           RegisterValue &reg_value)
403888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton{
40475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
405061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    if (baton && reg_info)
40675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        return ((UnwindAssemblyInstEmulation *)baton)->ReadRegister (instruction, reg_info, reg_value);
40775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    return false;
40875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton}
40975906e4ec98af3717e415727a8d663a4e246bb4fGreg Claytonbool
41075906e4ec98af3717e415727a8d663a4e246bb4fGreg ClaytonUnwindAssemblyInstEmulation::ReadRegister (EmulateInstruction *instruction,
41175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                           const RegisterInfo *reg_info,
41275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                           RegisterValue &reg_value)
41375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton{
41475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    bool synthetic = GetRegisterValue (*reg_info, reg_value);
415888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
41675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
41775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
4182d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda    if (log && log->GetVerbose ())
41975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    {
42075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
42175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        StreamString strm;
422061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton        strm.Printf ("UnwindAssemblyInstEmulation::ReadRegister  (name = \"%s\") => synthetic_value = %i, value = ", reg_info->name, synthetic);
423997b1e82f098a8b748b490d1ae6d0bbe597a59d5Greg Clayton        reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
42475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        log->PutCString(strm.GetData());
425061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton    }
426888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    return true;
427888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton}
428888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
429888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Claytonbool
430888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
431888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                            void *baton,
432888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                            const EmulateInstruction::Context &context,
433061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton                                            const RegisterInfo *reg_info,
434061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton                                            const RegisterValue &reg_value)
435888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton{
43675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    if (baton && reg_info)
43775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        return ((UnwindAssemblyInstEmulation *)baton)->WriteRegister (instruction, context, reg_info, reg_value);
43875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    return false;
43975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton}
44075906e4ec98af3717e415727a8d663a4e246bb4fGreg Claytonbool
44175906e4ec98af3717e415727a8d663a4e246bb4fGreg ClaytonUnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
44275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                            const EmulateInstruction::Context &context,
44375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                            const RegisterInfo *reg_info,
44475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                                            const RegisterValue &reg_value)
44575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton{
44675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
447061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton
4482d9b29b4bdc88d319761cac07f1692eef95c2a72Jason Molenda    if (log && log->GetVerbose ())
44975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    {
45075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
45175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        StreamString strm;
45275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        strm.Printf ("UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ", reg_info->name);
453997b1e82f098a8b748b490d1ae6d0bbe597a59d5Greg Clayton        reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
45475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        strm.PutCString (", context = ");
45575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        context.Dump(strm, instruction);
45675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        log->PutCString(strm.GetData());
45775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    }
458c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton
45975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    const bool must_replace = true;
46075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton    SetRegisterValue (*reg_info, reg_value);
461888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
462888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    switch (context.type)
463888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    {
464061b79dbf1fefaf157d414747e98a463a0f32edaGreg Clayton        default:
465888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextInvalid:
466888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextReadOpcode:
467888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextImmediate:
468888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAdjustBaseRegister:
469888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextRegisterPlusOffset:
470888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAdjustPC:
471888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextRegisterStore:
472888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextRegisterLoad:
473888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextRelativeBranchImmediate:
474888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAbsoluteBranchRegister:
475888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextSupervisorCall:
476888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextTableBranchReadMemory:
477888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextWriteRegisterRandomBits:
478888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextWriteMemoryRandomBits:
479c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton        case EmulateInstruction::eContextArithmetic:
480888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAdvancePC:
481888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextReturnFromException:
482888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextPushRegisterOnStack:
48375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//            {
48475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
48575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                if (reg_num != LLDB_INVALID_REGNUM)
48675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                {
48775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                    const bool can_replace_only_if_unspecified = true;
48875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//
48975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                    m_curr_row.SetRegisterLocationToUndefined (reg_num,
49075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                                                               can_replace_only_if_unspecified,
49175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                                                               can_replace_only_if_unspecified);
49275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//                }
49375906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton//            }
494888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            break;
4953063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
496888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextPopRegisterOffStack:
4973063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            {
49875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
49975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                if (reg_num != LLDB_INVALID_REGNUM)
5003063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                {
50168fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda                    m_curr_row->SetRegisterLocationToSame (reg_num, must_replace);
5023063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                }
5033063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            }
504888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            break;
505888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
50675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        case EmulateInstruction::eContextSetFramePointer:
50775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            if (!m_fp_is_cfa)
50875906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            {
50975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                m_fp_is_cfa = true;
51075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                m_cfa_reg_info = *reg_info;
51175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                const uint32_t cfa_reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
51275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton                assert (cfa_reg_num != LLDB_INVALID_REGNUM);
51368fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda                m_curr_row->SetCFARegister(cfa_reg_num);
51468fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda                m_curr_row->SetCFAOffset(m_initial_sp - reg_value.GetAsUInt64());
51575906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            }
51675906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            break;
51775906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton
518888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAdjustStackPointer:
51975906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            // If we have created a frame using the frame pointer, don't follow
52075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            // subsequent adjustments to the stack pointer.
52175906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            if (!m_fp_is_cfa)
52275906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            {
52368fa4ec4361d1ea5a78a8a7eba2b8015e3dd68f7Jason Molenda                m_curr_row->SetCFAOffset (m_initial_sp - reg_value.GetAsUInt64());
52475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton            }
525888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            break;
526888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    }
527888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    return true;
528888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton}
529888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
530888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
531