1*30fdc8d8SChris Lattner //===-- Disassembler.cpp ----------------------------------------*- C++ -*-===//
2*30fdc8d8SChris Lattner //
3*30fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
4*30fdc8d8SChris Lattner //
5*30fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
6*30fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
7*30fdc8d8SChris Lattner //
8*30fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
9*30fdc8d8SChris Lattner 
10*30fdc8d8SChris Lattner #include "lldb/Core/Disassembler.h"
11*30fdc8d8SChris Lattner 
12*30fdc8d8SChris Lattner // C Includes
13*30fdc8d8SChris Lattner // C++ Includes
14*30fdc8d8SChris Lattner // Other libraries and framework includes
15*30fdc8d8SChris Lattner // Project includes
16*30fdc8d8SChris Lattner #include "lldb/lldb-private.h"
17*30fdc8d8SChris Lattner #include "lldb/Core/Error.h"
18*30fdc8d8SChris Lattner #include "lldb/Core/DataBufferHeap.h"
19*30fdc8d8SChris Lattner #include "lldb/Core/DataExtractor.h"
20*30fdc8d8SChris Lattner #include "lldb/Core/Debugger.h"
21*30fdc8d8SChris Lattner #include "lldb/Core/Module.h"
22*30fdc8d8SChris Lattner #include "lldb/Core/PluginManager.h"
23*30fdc8d8SChris Lattner #include "lldb/Core/Timer.h"
24*30fdc8d8SChris Lattner #include "lldb/Symbol/ObjectFile.h"
25*30fdc8d8SChris Lattner #include "lldb/Target/ExecutionContext.h"
26*30fdc8d8SChris Lattner #include "lldb/Target/Process.h"
27*30fdc8d8SChris Lattner #include "lldb/Target/StackFrame.h"
28*30fdc8d8SChris Lattner #include "lldb/Target/Target.h"
29*30fdc8d8SChris Lattner 
30*30fdc8d8SChris Lattner #define DEFAULT_DISASM_BYTE_SIZE 32
31*30fdc8d8SChris Lattner 
32*30fdc8d8SChris Lattner using namespace lldb;
33*30fdc8d8SChris Lattner using namespace lldb_private;
34*30fdc8d8SChris Lattner 
35*30fdc8d8SChris Lattner 
36*30fdc8d8SChris Lattner Disassembler*
37*30fdc8d8SChris Lattner Disassembler::FindPlugin (const ArchSpec &arch)
38*30fdc8d8SChris Lattner {
39*30fdc8d8SChris Lattner     Timer scoped_timer (__PRETTY_FUNCTION__,
40*30fdc8d8SChris Lattner                         "Disassembler::FindPlugin (arch = %s)",
41*30fdc8d8SChris Lattner                         arch.AsCString());
42*30fdc8d8SChris Lattner 
43*30fdc8d8SChris Lattner     std::auto_ptr<Disassembler> disassembler_ap;
44*30fdc8d8SChris Lattner     DisassemblerCreateInstance create_callback;
45*30fdc8d8SChris Lattner     for (uint32_t idx = 0; (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(idx)) != NULL; ++idx)
46*30fdc8d8SChris Lattner     {
47*30fdc8d8SChris Lattner         disassembler_ap.reset (create_callback(arch));
48*30fdc8d8SChris Lattner 
49*30fdc8d8SChris Lattner         if (disassembler_ap.get())
50*30fdc8d8SChris Lattner             return disassembler_ap.release();
51*30fdc8d8SChris Lattner     }
52*30fdc8d8SChris Lattner     return NULL;
53*30fdc8d8SChris Lattner }
54*30fdc8d8SChris Lattner 
55*30fdc8d8SChris Lattner bool
56*30fdc8d8SChris Lattner Disassembler::Disassemble
57*30fdc8d8SChris Lattner (
58*30fdc8d8SChris Lattner     const ArchSpec &arch,
59*30fdc8d8SChris Lattner     const ExecutionContext &exe_ctx,
60*30fdc8d8SChris Lattner     uint32_t mixed_context_lines,
61*30fdc8d8SChris Lattner     Stream &strm
62*30fdc8d8SChris Lattner )
63*30fdc8d8SChris Lattner {
64*30fdc8d8SChris Lattner     Disassembler *disassembler = Disassembler::FindPlugin(arch);
65*30fdc8d8SChris Lattner 
66*30fdc8d8SChris Lattner     if (disassembler)
67*30fdc8d8SChris Lattner     {
68*30fdc8d8SChris Lattner         lldb::addr_t addr = LLDB_INVALID_ADDRESS;
69*30fdc8d8SChris Lattner         size_t byte_size = 0;
70*30fdc8d8SChris Lattner         if (exe_ctx.frame)
71*30fdc8d8SChris Lattner         {
72*30fdc8d8SChris Lattner             SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
73*30fdc8d8SChris Lattner             if (sc.function)
74*30fdc8d8SChris Lattner             {
75*30fdc8d8SChris Lattner                 addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(exe_ctx.process);
76*30fdc8d8SChris Lattner                 if (addr != LLDB_INVALID_ADDRESS)
77*30fdc8d8SChris Lattner                     byte_size = sc.function->GetAddressRange().GetByteSize();
78*30fdc8d8SChris Lattner             }
79*30fdc8d8SChris Lattner             else if (sc.symbol && sc.symbol->GetAddressRangePtr())
80*30fdc8d8SChris Lattner             {
81*30fdc8d8SChris Lattner                 addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress().GetLoadAddress(exe_ctx.process);
82*30fdc8d8SChris Lattner                 if (addr != LLDB_INVALID_ADDRESS)
83*30fdc8d8SChris Lattner                 {
84*30fdc8d8SChris Lattner                     byte_size = sc.symbol->GetAddressRangePtr()->GetByteSize();
85*30fdc8d8SChris Lattner                     if (byte_size == 0)
86*30fdc8d8SChris Lattner                         byte_size = DEFAULT_DISASM_BYTE_SIZE;
87*30fdc8d8SChris Lattner                 }
88*30fdc8d8SChris Lattner             }
89*30fdc8d8SChris Lattner             else
90*30fdc8d8SChris Lattner             {
91*30fdc8d8SChris Lattner                 addr = exe_ctx.frame->GetPC().GetLoadAddress(exe_ctx.process);
92*30fdc8d8SChris Lattner                 if (addr != LLDB_INVALID_ADDRESS)
93*30fdc8d8SChris Lattner                     byte_size = DEFAULT_DISASM_BYTE_SIZE;
94*30fdc8d8SChris Lattner             }
95*30fdc8d8SChris Lattner         }
96*30fdc8d8SChris Lattner 
97*30fdc8d8SChris Lattner         if (byte_size)
98*30fdc8d8SChris Lattner         {
99*30fdc8d8SChris Lattner             DataExtractor data;
100*30fdc8d8SChris Lattner             size_t bytes_disassembled = disassembler->ParseInstructions (&exe_ctx, eAddressTypeLoad, addr, byte_size, data);
101*30fdc8d8SChris Lattner             if (bytes_disassembled == 0)
102*30fdc8d8SChris Lattner             {
103*30fdc8d8SChris Lattner                 return false;
104*30fdc8d8SChris Lattner             }
105*30fdc8d8SChris Lattner             else
106*30fdc8d8SChris Lattner             {
107*30fdc8d8SChris Lattner                 // We got some things disassembled...
108*30fdc8d8SChris Lattner                 size_t num_instructions = disassembler->GetInstructionList().GetSize();
109*30fdc8d8SChris Lattner                 uint32_t offset = 0;
110*30fdc8d8SChris Lattner                 SymbolContext sc;
111*30fdc8d8SChris Lattner                 SymbolContext prev_sc;
112*30fdc8d8SChris Lattner                 AddressRange sc_range;
113*30fdc8d8SChris Lattner                 if (mixed_context_lines)
114*30fdc8d8SChris Lattner                     strm.IndentMore ();
115*30fdc8d8SChris Lattner 
116*30fdc8d8SChris Lattner                 for (size_t i=0; i<num_instructions; ++i)
117*30fdc8d8SChris Lattner                 {
118*30fdc8d8SChris Lattner                     Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
119*30fdc8d8SChris Lattner                     if (inst)
120*30fdc8d8SChris Lattner                     {
121*30fdc8d8SChris Lattner                         lldb::addr_t curr_addr = addr + offset;
122*30fdc8d8SChris Lattner                         if (mixed_context_lines)
123*30fdc8d8SChris Lattner                         {
124*30fdc8d8SChris Lattner                             if (!sc_range.ContainsLoadAddress (curr_addr, exe_ctx.process))
125*30fdc8d8SChris Lattner                             {
126*30fdc8d8SChris Lattner                                 prev_sc = sc;
127*30fdc8d8SChris Lattner                                 Address curr_so_addr;
128*30fdc8d8SChris Lattner                                 Process *process = exe_ctx.process;
129*30fdc8d8SChris Lattner                                 if (process && process->ResolveLoadAddress (curr_addr, curr_so_addr))
130*30fdc8d8SChris Lattner                                 {
131*30fdc8d8SChris Lattner                                     if (curr_so_addr.GetSection())
132*30fdc8d8SChris Lattner                                     {
133*30fdc8d8SChris Lattner                                         Module *module = curr_so_addr.GetSection()->GetModule();
134*30fdc8d8SChris Lattner                                         uint32_t resolved_mask = module->ResolveSymbolContextForAddress(curr_so_addr, eSymbolContextEverything, sc);
135*30fdc8d8SChris Lattner                                         if (resolved_mask)
136*30fdc8d8SChris Lattner                                         {
137*30fdc8d8SChris Lattner                                             sc.GetAddressRange (eSymbolContextEverything, sc_range);
138*30fdc8d8SChris Lattner                                             if (sc != prev_sc)
139*30fdc8d8SChris Lattner                                             {
140*30fdc8d8SChris Lattner                                                 if (offset != 0)
141*30fdc8d8SChris Lattner                                                     strm.EOL();
142*30fdc8d8SChris Lattner 
143*30fdc8d8SChris Lattner                                                 sc.DumpStopContext(&strm, process, curr_so_addr);
144*30fdc8d8SChris Lattner 
145*30fdc8d8SChris Lattner                                                 if (sc.comp_unit && sc.line_entry.IsValid())
146*30fdc8d8SChris Lattner                                                 {
147*30fdc8d8SChris Lattner                                                     Debugger::GetSharedInstance().GetSourceManager().DisplaySourceLinesWithLineNumbers (
148*30fdc8d8SChris Lattner                                                             sc.line_entry.file,
149*30fdc8d8SChris Lattner                                                             sc.line_entry.line,
150*30fdc8d8SChris Lattner                                                             mixed_context_lines,
151*30fdc8d8SChris Lattner                                                             mixed_context_lines,
152*30fdc8d8SChris Lattner                                                             mixed_context_lines ? "->" : "",
153*30fdc8d8SChris Lattner                                                             &strm);
154*30fdc8d8SChris Lattner                                                 }
155*30fdc8d8SChris Lattner                                             }
156*30fdc8d8SChris Lattner                                         }
157*30fdc8d8SChris Lattner                                     }
158*30fdc8d8SChris Lattner                                 }
159*30fdc8d8SChris Lattner                             }
160*30fdc8d8SChris Lattner                         }
161*30fdc8d8SChris Lattner                         if (mixed_context_lines)
162*30fdc8d8SChris Lattner                             strm.IndentMore ();
163*30fdc8d8SChris Lattner                         strm.Indent();
164*30fdc8d8SChris Lattner                         size_t inst_byte_size = inst->GetByteSize();
165*30fdc8d8SChris Lattner                         //inst->Dump(&strm, curr_addr, &data, offset);  // Do dump opcode bytes
166*30fdc8d8SChris Lattner                         inst->Dump(&strm, curr_addr, NULL, offset, exe_ctx, false); // Don't dump opcode bytes
167*30fdc8d8SChris Lattner                         strm.EOL();
168*30fdc8d8SChris Lattner                         offset += inst_byte_size;
169*30fdc8d8SChris Lattner                         if (mixed_context_lines)
170*30fdc8d8SChris Lattner                             strm.IndentLess ();
171*30fdc8d8SChris Lattner                     }
172*30fdc8d8SChris Lattner                     else
173*30fdc8d8SChris Lattner                     {
174*30fdc8d8SChris Lattner                         break;
175*30fdc8d8SChris Lattner                     }
176*30fdc8d8SChris Lattner                 }
177*30fdc8d8SChris Lattner                 if (mixed_context_lines)
178*30fdc8d8SChris Lattner                     strm.IndentLess ();
179*30fdc8d8SChris Lattner 
180*30fdc8d8SChris Lattner             }
181*30fdc8d8SChris Lattner         }
182*30fdc8d8SChris Lattner         return true;
183*30fdc8d8SChris Lattner     }
184*30fdc8d8SChris Lattner     return false;
185*30fdc8d8SChris Lattner }
186*30fdc8d8SChris Lattner 
187*30fdc8d8SChris Lattner Disassembler::Instruction::Instruction()
188*30fdc8d8SChris Lattner {
189*30fdc8d8SChris Lattner }
190*30fdc8d8SChris Lattner 
191*30fdc8d8SChris Lattner Disassembler::Instruction::~Instruction()
192*30fdc8d8SChris Lattner {
193*30fdc8d8SChris Lattner }
194*30fdc8d8SChris Lattner 
195*30fdc8d8SChris Lattner 
196*30fdc8d8SChris Lattner Disassembler::InstructionList::InstructionList() :
197*30fdc8d8SChris Lattner     m_instructions()
198*30fdc8d8SChris Lattner {
199*30fdc8d8SChris Lattner }
200*30fdc8d8SChris Lattner 
201*30fdc8d8SChris Lattner Disassembler::InstructionList::~InstructionList()
202*30fdc8d8SChris Lattner {
203*30fdc8d8SChris Lattner }
204*30fdc8d8SChris Lattner 
205*30fdc8d8SChris Lattner size_t
206*30fdc8d8SChris Lattner Disassembler::InstructionList::GetSize() const
207*30fdc8d8SChris Lattner {
208*30fdc8d8SChris Lattner     return m_instructions.size();
209*30fdc8d8SChris Lattner }
210*30fdc8d8SChris Lattner 
211*30fdc8d8SChris Lattner 
212*30fdc8d8SChris Lattner Disassembler::Instruction *
213*30fdc8d8SChris Lattner Disassembler::InstructionList::GetInstructionAtIndex (uint32_t idx)
214*30fdc8d8SChris Lattner {
215*30fdc8d8SChris Lattner     if (idx < m_instructions.size())
216*30fdc8d8SChris Lattner         return m_instructions[idx].get();
217*30fdc8d8SChris Lattner     return NULL;
218*30fdc8d8SChris Lattner }
219*30fdc8d8SChris Lattner 
220*30fdc8d8SChris Lattner const Disassembler::Instruction *
221*30fdc8d8SChris Lattner Disassembler::InstructionList::GetInstructionAtIndex (uint32_t idx) const
222*30fdc8d8SChris Lattner {
223*30fdc8d8SChris Lattner     if (idx < m_instructions.size())
224*30fdc8d8SChris Lattner         return m_instructions[idx].get();
225*30fdc8d8SChris Lattner     return NULL;
226*30fdc8d8SChris Lattner }
227*30fdc8d8SChris Lattner 
228*30fdc8d8SChris Lattner void
229*30fdc8d8SChris Lattner Disassembler::InstructionList::Clear()
230*30fdc8d8SChris Lattner {
231*30fdc8d8SChris Lattner   m_instructions.clear();
232*30fdc8d8SChris Lattner }
233*30fdc8d8SChris Lattner 
234*30fdc8d8SChris Lattner void
235*30fdc8d8SChris Lattner Disassembler::InstructionList::AppendInstruction (Instruction::shared_ptr &inst_sp)
236*30fdc8d8SChris Lattner {
237*30fdc8d8SChris Lattner     if (inst_sp)
238*30fdc8d8SChris Lattner         m_instructions.push_back(inst_sp);
239*30fdc8d8SChris Lattner }
240*30fdc8d8SChris Lattner 
241*30fdc8d8SChris Lattner 
242*30fdc8d8SChris Lattner size_t
243*30fdc8d8SChris Lattner Disassembler::ParseInstructions
244*30fdc8d8SChris Lattner (
245*30fdc8d8SChris Lattner     const ExecutionContext *exe_ctx,
246*30fdc8d8SChris Lattner     lldb::AddressType addr_type,
247*30fdc8d8SChris Lattner     lldb::addr_t addr,
248*30fdc8d8SChris Lattner     size_t byte_size,
249*30fdc8d8SChris Lattner     DataExtractor& data
250*30fdc8d8SChris Lattner )
251*30fdc8d8SChris Lattner {
252*30fdc8d8SChris Lattner     Process *process = exe_ctx->process;
253*30fdc8d8SChris Lattner 
254*30fdc8d8SChris Lattner     if (process == NULL)
255*30fdc8d8SChris Lattner         return 0;
256*30fdc8d8SChris Lattner 
257*30fdc8d8SChris Lattner     DataBufferSP data_sp(new DataBufferHeap (byte_size, '\0'));
258*30fdc8d8SChris Lattner 
259*30fdc8d8SChris Lattner     Error error;
260*30fdc8d8SChris Lattner     if (process->GetTarget().ReadMemory (addr_type, addr, data_sp->GetBytes(), data_sp->GetByteSize(), error, NULL))
261*30fdc8d8SChris Lattner     {
262*30fdc8d8SChris Lattner         data.SetData(data_sp);
263*30fdc8d8SChris Lattner         data.SetByteOrder(process->GetByteOrder());
264*30fdc8d8SChris Lattner         data.SetAddressByteSize(process->GetAddressByteSize());
265*30fdc8d8SChris Lattner         return ParseInstructions (data, 0, UINT32_MAX, addr);
266*30fdc8d8SChris Lattner     }
267*30fdc8d8SChris Lattner 
268*30fdc8d8SChris Lattner     return 0;
269*30fdc8d8SChris Lattner }
270*30fdc8d8SChris Lattner 
271*30fdc8d8SChris Lattner //----------------------------------------------------------------------
272*30fdc8d8SChris Lattner // Disassembler copy constructor
273*30fdc8d8SChris Lattner //----------------------------------------------------------------------
274*30fdc8d8SChris Lattner Disassembler::Disassembler(const ArchSpec& arch) :
275*30fdc8d8SChris Lattner     m_arch (arch),
276*30fdc8d8SChris Lattner     m_instruction_list(),
277*30fdc8d8SChris Lattner     m_base_addr(LLDB_INVALID_ADDRESS)
278*30fdc8d8SChris Lattner {
279*30fdc8d8SChris Lattner 
280*30fdc8d8SChris Lattner }
281*30fdc8d8SChris Lattner 
282*30fdc8d8SChris Lattner //----------------------------------------------------------------------
283*30fdc8d8SChris Lattner // Destructor
284*30fdc8d8SChris Lattner //----------------------------------------------------------------------
285*30fdc8d8SChris Lattner Disassembler::~Disassembler()
286*30fdc8d8SChris Lattner {
287*30fdc8d8SChris Lattner }
288*30fdc8d8SChris Lattner 
289*30fdc8d8SChris Lattner Disassembler::InstructionList &
290*30fdc8d8SChris Lattner Disassembler::GetInstructionList ()
291*30fdc8d8SChris Lattner {
292*30fdc8d8SChris Lattner     return m_instruction_list;
293*30fdc8d8SChris Lattner }
294*30fdc8d8SChris Lattner 
295*30fdc8d8SChris Lattner const Disassembler::InstructionList &
296*30fdc8d8SChris Lattner Disassembler::GetInstructionList () const
297*30fdc8d8SChris Lattner {
298*30fdc8d8SChris Lattner     return m_instruction_list;
299*30fdc8d8SChris Lattner }
300