UnwindAssemblyInstEmulation.cpp revision 3063c95c54ac0303287c34f9f5af7ba7b6b8f0bc
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"
19f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton#include "lldb/Core/PluginManager.h"
20888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton#include "lldb/Core/StreamFile.h"
21f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton#include "lldb/Target/ExecutionContext.h"
22f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton#include "lldb/Target/Process.h"
23f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton#include "lldb/Target/Thread.h"
24f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton#include "lldb/Target/Target.h"
25f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
26f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonusing namespace lldb;
27f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonusing namespace lldb_private;
28f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
29f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
30f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
31f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//-----------------------------------------------------------------------------------------------
32f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//  UnwindAssemblyParser_x86 method definitions
33f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//-----------------------------------------------------------------------------------------------
34f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
35f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonbool
36888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& range,
37888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                                   Thread& thread,
38888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                                   UnwindPlan& unwind_plan)
39f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
40888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton#if 0
41888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    UnwindPlan::Row row;
42888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    UnwindPlan::Row::RegisterLocation regloc;
43888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
44888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    m_unwind_plan_sp->SetRegisterKind (eRegisterKindGeneric);
45888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    row.SetCFARegister (LLDB_REGNUM_GENERIC_FP);
46888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    row.SetCFAOffset (2 * 8);
47888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    row.SetOffset (0);
48888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
49888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    regloc.SetAtCFAPlusOffset (2 * -8);
50888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    row.SetRegisterInfo (LLDB_REGNUM_GENERIC_FP, regloc);
51888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    regloc.SetAtCFAPlusOffset (1 * -8);
52888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    row.SetRegisterInfo (LLDB_REGNUM_GENERIC_PC, regloc);
53888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    regloc.SetIsCFAPlusOffset (0);
54888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    row.SetRegisterInfo (LLDB_REGNUM_GENERIC_SP, regloc);
55888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
56888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    m_unwind_plan_sp->AppendRow (row);
57888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    m_unwind_plan_sp->SetSourceName ("x86_64 architectural default");
58888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton#endif
59888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
60888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    if (range.GetByteSize() > 0 &&
61888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        range.GetBaseAddress().IsValid() &&
62888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        m_inst_emulator_ap.get())
63888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    {
64888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton#if  0
65888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        Target &target = thread.GetProcess().GetTarget();
66888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        const ArchSpec &target_arch = target.GetArchitecture();
67888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        bool prefer_file_cache = true;
68888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        Error error;
69888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        DataBufferHeap data_buffer (range.GetByteSize(), 0);
70888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        if (target.ReadMemory (range.GetBaseAddress(),
71888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                               prefer_file_cache,
72888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                               data_buffer.GetBytes(),
73888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                               data_buffer.GetByteSize(),
74888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                               error) == data_buffer.GetByteSize())
75888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        {
76888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            DataExtractor data (data_buffer.GetBytes(),
77888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                data_buffer.GetByteSize(),
78888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                target_arch.GetByteOrder(),
79888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                target_arch.GetAddressByteSize());
80888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        }
81888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton#endif
82888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        StreamFile strm (stdout, false);
83888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
84888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        ExecutionContext exe_ctx;
85888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        thread.CalculateExecutionContext(exe_ctx);
86888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        DisassemblerSP disasm_sp (Disassembler::DisassembleRange (m_arch,
87888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                                  NULL,
88888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                                  exe_ctx,
89888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                                  range));
90888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        if (disasm_sp)
91888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        {
92888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
93888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            m_range_ptr = ⦥
94888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            m_thread_ptr = &thread;
95888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            m_unwind_plan_ptr = &unwind_plan;
96888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
97888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            const uint32_t addr_byte_size = m_arch.GetAddressByteSize();
98888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            const bool show_address = true;
99888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            const bool show_bytes = true;
100888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            const bool raw = false;
101888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            // Initialize the stack pointer with a known value. In the 32 bit case
102888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            // it will be 0x80000000, and in the 64 bit case 0x8000000000000000.
103888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            // We use the address byte size to be safe for any future addresss sizes
104c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton            RegisterInfo sp_reg_info;
105c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton            m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp_reg_info);
106c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton            SetRegisterValue(sp_reg_info, (1ull << ((addr_byte_size * 8) - 1)));
107888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
108888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            const InstructionList &inst_list = disasm_sp->GetInstructionList ();
109888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            const size_t num_instructions = inst_list.GetSize();
1103063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            if (num_instructions > 0)
111888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            {
1123063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                Instruction *inst = inst_list.GetInstructionAtIndex (0).get();
1133063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                const addr_t base_addr = inst->GetAddress().GetFileAddress();
114888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
1153063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                for (size_t idx=0; idx<num_instructions; ++idx)
1163063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                {
1173063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    inst = inst_list.GetInstructionAtIndex (idx).get();
1183063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    if (inst)
1193063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    {
1203063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        m_curr_row.Clear();
1213063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, &exe_ctx, raw);
1223063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        strm.EOL();
1233063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
1243063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        m_inst_emulator_ap->SetInstruction (inst->GetOpcode(),
1253063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                                                            inst->GetAddress(),
1263063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                                                            exe_ctx.target);
1273063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        m_curr_row.SetOffset (inst->GetAddress().GetFileAddress() + inst->GetOpcode().GetByteSize() - base_addr);
1283063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
1293063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        m_inst_emulator_ap->EvaluateInstruction (eEmulateInstructionOptionIgnoreConditions);
1303063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    }
131888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                }
132888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            }
133888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        }
134888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    }
135f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return false;
136f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
137f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
138f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonbool
139888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::GetFastUnwindPlan (AddressRange& func,
140888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                Thread& thread,
141888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                UnwindPlan &unwind_plan)
142f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
143f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return false;
144f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
145f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
146f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonbool
147888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::FirstNonPrologueInsn (AddressRange& func,
148888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                   Target& target,
149888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                   Thread* thread,
150888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                                   Address& first_non_prologue_insn)
151f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
152f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return false;
153f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
154f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
1558badcb2503ed2e2884a48f66099c1d48494817f4Greg ClaytonUnwindAssembly *
156f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::CreateInstance (const ArchSpec &arch)
157f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
158888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    std::auto_ptr<lldb_private::EmulateInstruction> inst_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypePrologueEpilogue, NULL));
159888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    // Make sure that all prologue instructions are handled
160888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    if (inst_emulator_ap.get())
161888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        return new UnwindAssemblyInstEmulation (arch, inst_emulator_ap.release());
162f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return NULL;
163f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
164f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
165f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
166f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//------------------------------------------------------------------
167f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton// PluginInterface protocol in UnwindAssemblyParser_x86
168f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton//------------------------------------------------------------------
169f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
170f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonconst char *
171f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetPluginName()
172f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
173f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return "UnwindAssemblyInstEmulation";
174f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
175f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
176f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonconst char *
177f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetShortPluginName()
178f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
179f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return "unwindassembly.inst-emulation";
180f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
181f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
182f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
183f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonuint32_t
184f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetPluginVersion()
185f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
186f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return 1;
187f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
188f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
189f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonvoid
190f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::Initialize()
191f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
192f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    PluginManager::RegisterPlugin (GetPluginNameStatic(),
193f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton                                   GetPluginDescriptionStatic(),
194f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton                                   CreateInstance);
195f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
196f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
197f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonvoid
198f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::Terminate()
199f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
200f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    PluginManager::UnregisterPlugin (CreateInstance);
201f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
202f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
203f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
204f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonconst char *
205f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetPluginNameStatic()
206f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
207f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return "UnwindAssemblyInstEmulation";
208f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
209f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton
210f6e287a873007543f3b419a71546ab8f007be90bGreg Claytonconst char *
211f6e287a873007543f3b419a71546ab8f007be90bGreg ClaytonUnwindAssemblyInstEmulation::GetPluginDescriptionStatic()
212f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton{
213f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton    return "Instruction emulation based unwind information.";
214f6e287a873007543f3b419a71546ab8f007be90bGreg Clayton}
215888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
216888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
217c07d451bb046e47215bd73fda0235362cc6b1a47Greg Claytonuint64_t
218c07d451bb046e47215bd73fda0235362cc6b1a47Greg ClaytonUnwindAssemblyInstEmulation::MakeRegisterKindValuePair (const lldb_private::RegisterInfo &reg_info)
219c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton{
220c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    uint32_t reg_kind, reg_num;
221c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    if (EmulateInstruction::GetBestRegisterKindAndNumber (reg_info, reg_kind, reg_num))
222c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton        return (uint64_t)reg_kind << 24 | reg_num;
223c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    return 0ull;
224c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton}
225c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton
226c07d451bb046e47215bd73fda0235362cc6b1a47Greg Claytonvoid
227c07d451bb046e47215bd73fda0235362cc6b1a47Greg ClaytonUnwindAssemblyInstEmulation::SetRegisterValue (const lldb_private::RegisterInfo &reg_info, uint64_t reg_value)
228c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton{
229c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    m_register_values[MakeRegisterKindValuePair (reg_info)] = reg_value;
230c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton}
231c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton
232c07d451bb046e47215bd73fda0235362cc6b1a47Greg Claytonuint64_t
233c07d451bb046e47215bd73fda0235362cc6b1a47Greg ClaytonUnwindAssemblyInstEmulation::GetRegisterValue (const lldb_private::RegisterInfo &reg_info)
234c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton{
235c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    const uint64_t reg_id = MakeRegisterKindValuePair (reg_info);
236c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    RegisterValueMap::const_iterator pos = m_register_values.find(reg_id);
237c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    if (pos != m_register_values.end())
238c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton        return pos->second;
239c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    return MakeRegisterKindValuePair (reg_info);
240c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton}
241c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton
242888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
243888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Claytonsize_t
244888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::ReadMemory (EmulateInstruction *instruction,
245888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         void *baton,
246888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         const EmulateInstruction::Context &context,
247888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         lldb::addr_t addr,
248888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         void *dst,
249888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                         size_t dst_len)
250888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton{
251888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    //UnwindAssemblyInstEmulation *inst_emulator = (UnwindAssemblyInstEmulation *)baton;
252c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    printf ("UnwindAssemblyInstEmulation::ReadMemory    (addr = 0x%16.16llx, dst = %p, dst_len = %zu, context = ",
253888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            addr,
254888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            dst,
255888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            dst_len);
256c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    context.Dump(stdout, instruction);
257888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    return dst_len;
258888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton}
259888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
260888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Claytonsize_t
261888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction,
262888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          void *baton,
263888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          const EmulateInstruction::Context &context,
264888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          lldb::addr_t addr,
265888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          const void *dst,
266888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                          size_t dst_len)
267888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton{
2683063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton    UnwindAssemblyInstEmulation *inst_emulator = (UnwindAssemblyInstEmulation *)baton;
269888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
270888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    DataExtractor data (dst,
271888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                        dst_len,
272888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                        instruction->GetArchitecture ().GetByteOrder(),
273888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                        instruction->GetArchitecture ().GetAddressByteSize());
274888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    StreamFile strm(stdout, false);
275888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
276c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    strm.PutCString ("UnwindAssemblyInstEmulation::WriteMemory   (");
277888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    data.Dump(&strm, 0, eFormatBytes, 1, dst_len, UINT32_MAX, addr, 0, 0);
278c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    strm.PutCString (", context = ");
279c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    context.Dump(stdout, instruction);
2803063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
2813063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton    switch (context.type)
2823063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton    {
2833063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextInvalid:
2843063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextReadOpcode:
2853063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextImmediate:
2863063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAdjustBaseRegister:
2873063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextRegisterPlusOffset:
2883063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAdjustPC:
2893063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextRegisterStore:
2903063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextRegisterLoad:
2913063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextRelativeBranchImmediate:
2923063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAbsoluteBranchRegister:
2933063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextSupervisorCall:
2943063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextTableBranchReadMemory:
2953063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextWriteRegisterRandomBits:
2963063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextWriteMemoryRandomBits:
2973063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextArithmetic:
2983063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAdvancePC:
2993063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextReturnFromException:
3003063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextPopRegisterOffStack:
3013063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextAdjustStackPointer:
3023063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            break;
3033063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
3043063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton        case EmulateInstruction::eContextPushRegisterOnStack:
3053063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            switch (context.info_type)
3063063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            {
3073063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                case EmulateInstruction::eInfoTypeRegisterToRegisterPlusOffset:
3083063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    {
3093063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        UnwindPlan::Row::RegisterLocation regloc;
3103063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        const uint32_t dwarf_reg_num = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[eRegisterKindDWARF];
3113063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        const addr_t reg_cfa_offset = inst_emulator->m_curr_row.GetCFAOffset() + context.info.RegisterToRegisterPlusOffset.offset;
3123063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        regloc.SetIsCFAPlusOffset (reg_cfa_offset);
3133063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        inst_emulator->m_curr_row.SetRegisterInfo (dwarf_reg_num, regloc);
3143063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    }
3153063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    break;
3163063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
3173063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                default:
3183063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    assert (!"unhandled case, add code to handle this!");
3193063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    break;
3203063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            }
3213063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            break;
3223063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
3233063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            break;
3243063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
3253063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton    }
3263063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
327888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    return dst_len;
328888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton}
329888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
330888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Claytonbool
331888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::ReadRegister (EmulateInstruction *instruction,
332888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                           void *baton,
333c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton                                           const RegisterInfo &reg_info,
334888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                           uint64_t &reg_value)
335888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton{
336888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    UnwindAssemblyInstEmulation *inst_emulator = (UnwindAssemblyInstEmulation *)baton;
337c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    reg_value = inst_emulator->GetRegisterValue (reg_info);
338888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
339c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    printf ("UnwindAssemblyInstEmulation::ReadRegister  (name = \"%s\") => value = 0x%16.16llx\n", reg_info.name, reg_value);
340888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
341888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    return true;
342888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton}
343888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
344888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Claytonbool
345888a7334344778d1a4edbd58b5852ae4d53ffed9Greg ClaytonUnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
346888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                            void *baton,
347888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                            const EmulateInstruction::Context &context,
348c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton                                            const RegisterInfo &reg_info,
349888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton                                            uint64_t reg_value)
350888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton{
351888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    UnwindAssemblyInstEmulation *inst_emulator = (UnwindAssemblyInstEmulation *)baton;
352888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
353c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    printf ("UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = 0x%16.16llx, context =",
354c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton            reg_info.name,
355c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton            reg_value);
356c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    context.Dump(stdout, instruction);
357c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton
358c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton    inst_emulator->SetRegisterValue (reg_info, reg_value);
359888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
360888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    switch (context.type)
361888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    {
362888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextInvalid:
363888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextReadOpcode:
364888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextImmediate:
365888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAdjustBaseRegister:
366888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextRegisterPlusOffset:
367888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAdjustPC:
368888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextRegisterStore:
369888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextRegisterLoad:
370888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextRelativeBranchImmediate:
371888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAbsoluteBranchRegister:
372888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextSupervisorCall:
373888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextTableBranchReadMemory:
374888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextWriteRegisterRandomBits:
375888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextWriteMemoryRandomBits:
376c07d451bb046e47215bd73fda0235362cc6b1a47Greg Clayton        case EmulateInstruction::eContextArithmetic:
377888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAdvancePC:
378888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextReturnFromException:
379888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextPushRegisterOnStack:
380888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            break;
3813063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
382888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextPopRegisterOffStack:
3833063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            {
3843063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                switch (context.info_type)
3853063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                {
3863063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    case EmulateInstruction::eInfoTypeRegisterPlusOffset:
3873063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        {
3883063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                            const uint32_t dwarf_reg_num = reg_info.kinds[eRegisterKindDWARF];
3893063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                            UnwindPlan::Row::RegisterLocation regloc;
3903063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                            regloc.SetSame();
3913063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                            inst_emulator->m_curr_row.SetRegisterInfo (dwarf_reg_num, regloc);
3923063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        }
3933063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        break;
3943063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
3953063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    default:
3963063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        assert (!"unhandled case, add code to handle this!");
3973063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                        break;
3983063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                }
3993063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            }
400888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            break;
401888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
402888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton        case EmulateInstruction::eContextAdjustStackPointer:
4033063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            switch (context.info_type)
4043063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            {
4053063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                case EmulateInstruction::eInfoTypeImmediateSigned:
4063063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    inst_emulator->m_curr_row.SetCFAOffset (inst_emulator->m_curr_row.GetCFAOffset() + context.info.signed_immediate);
4073063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    break;
4083063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton
4093063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                default:
4103063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    assert (!"unhandled case, add code to handle this!");
4113063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton                    break;
4123063c95c54ac0303287c34f9f5af7ba7b6b8f0bcGreg Clayton            }
413888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton            break;
414888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    }
415888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton    return true;
416888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton}
417888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
418888a7334344778d1a4edbd58b5852ae4d53ffed9Greg Clayton
419