blob: a8eceb74ff9903e6ac4ff460deed26579f6f1786 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Disassembler.cpp ----------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Core/Disassembler.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/lldb-private.h"
17#include "lldb/Core/Error.h"
18#include "lldb/Core/DataBufferHeap.h"
19#include "lldb/Core/DataExtractor.h"
20#include "lldb/Core/Debugger.h"
21#include "lldb/Core/Module.h"
22#include "lldb/Core/PluginManager.h"
23#include "lldb/Core/Timer.h"
24#include "lldb/Symbol/ObjectFile.h"
25#include "lldb/Target/ExecutionContext.h"
26#include "lldb/Target/Process.h"
27#include "lldb/Target/StackFrame.h"
28#include "lldb/Target/Target.h"
29
30#define DEFAULT_DISASM_BYTE_SIZE 32
31
32using namespace lldb;
33using namespace lldb_private;
34
35
36Disassembler*
37Disassembler::FindPlugin (const ArchSpec &arch)
38{
39 Timer scoped_timer (__PRETTY_FUNCTION__,
40 "Disassembler::FindPlugin (arch = %s)",
41 arch.AsCString());
42
43 std::auto_ptr<Disassembler> disassembler_ap;
44 DisassemblerCreateInstance create_callback;
45 for (uint32_t idx = 0; (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(idx)) != NULL; ++idx)
46 {
47 disassembler_ap.reset (create_callback(arch));
48
49 if (disassembler_ap.get())
50 return disassembler_ap.release();
51 }
52 return NULL;
53}
54
Greg Claytondda4f7b2010-06-30 23:03:03 +000055
56
57size_t
58Disassembler::Disassemble
59(
60 Debugger &debugger,
61 const ArchSpec &arch,
62 const ExecutionContext &exe_ctx,
63 SymbolContextList &sc_list,
64 uint32_t num_mixed_context_lines,
65 bool show_bytes,
66 Stream &strm
67)
68{
69 size_t success_count = 0;
70 const size_t count = sc_list.GetSize();
71 SymbolContext sc;
72 AddressRange range;
73 for (size_t i=0; i<count; ++i)
74 {
75 if (sc_list.GetContextAtIndex(i, sc) == false)
76 break;
77 if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range))
78 {
79 if (Disassemble (debugger, arch, exe_ctx, range, num_mixed_context_lines, show_bytes, strm))
80 {
81 ++success_count;
82 strm.EOL();
83 }
84 }
85 }
86 return success_count;
87}
88
Chris Lattner30fdc8d2010-06-08 16:52:24 +000089bool
90Disassembler::Disassemble
91(
Greg Clayton66111032010-06-23 01:19:29 +000092 Debugger &debugger,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000093 const ArchSpec &arch,
94 const ExecutionContext &exe_ctx,
Greg Claytondda4f7b2010-06-30 23:03:03 +000095 const ConstString &name,
96 Module *module,
97 uint32_t num_mixed_context_lines,
98 bool show_bytes,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000099 Stream &strm
100)
101{
Greg Claytondda4f7b2010-06-30 23:03:03 +0000102 if (exe_ctx.target == NULL && name)
103 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000104
Greg Claytondda4f7b2010-06-30 23:03:03 +0000105 SymbolContextList sc_list;
106
107 if (module)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000108 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000109 if (!module->FindFunctions (name,
110 eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeMethod | eFunctionNameTypeSelector,
111 true,
112 sc_list))
113 return false;
114 }
115 else
116 {
117 if (exe_ctx.target->GetImages().FindFunctions (name,
118 eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeMethod | eFunctionNameTypeSelector,
119 sc_list))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000120 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000121 return Disassemble (debugger, arch, exe_ctx, sc_list, num_mixed_context_lines, show_bytes, strm);
122 }
123 else if (exe_ctx.target->GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeCode, sc_list))
124 {
125 return Disassemble (debugger, arch, exe_ctx, sc_list, num_mixed_context_lines, show_bytes, strm);
126 }
127 }
128 return false;
129}
130
131bool
132Disassembler::Disassemble
133(
134 Debugger &debugger,
135 const ArchSpec &arch,
136 const ExecutionContext &exe_ctx,
137 const AddressRange &disasm_range,
138 uint32_t num_mixed_context_lines,
139 bool show_bytes,
140 Stream &strm
141)
142{
143 if (disasm_range.GetByteSize())
144 {
145 Disassembler *disassembler = Disassembler::FindPlugin(arch);
146
147 if (disassembler)
148 {
149 AddressRange range(disasm_range);
150
151 Process *process = exe_ctx.process;
152
153 // If we weren't passed in a section offset address range,
154 // try and resolve it to something
155 if (range.GetBaseAddress().IsSectionOffset() == false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000156 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000157 if (process && process->IsAlive())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000158 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000159 process->ResolveLoadAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress());
160 }
161 else if (exe_ctx.target)
162 {
163 exe_ctx.target->GetImages().ResolveFileAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000164 }
165 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000166
Greg Claytondda4f7b2010-06-30 23:03:03 +0000167
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000168 DataExtractor data;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000169 size_t bytes_disassembled = disassembler->ParseInstructions (&exe_ctx, range, data);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000170 if (bytes_disassembled == 0)
171 {
172 return false;
173 }
174 else
175 {
176 // We got some things disassembled...
177 size_t num_instructions = disassembler->GetInstructionList().GetSize();
178 uint32_t offset = 0;
179 SymbolContext sc;
180 SymbolContext prev_sc;
181 AddressRange sc_range;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000182 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000183 strm.IndentMore ();
184
Greg Claytondda4f7b2010-06-30 23:03:03 +0000185
186 Address addr(range.GetBaseAddress());
187
188 // We extract the section to make sure we don't transition out
189 // of the current section when disassembling
190 const Section *addr_section = addr.GetSection();
191 Module *range_module = range.GetBaseAddress().GetModule();
192
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000193 for (size_t i=0; i<num_instructions; ++i)
194 {
195 Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
196 if (inst)
197 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000198 addr_t file_addr = addr.GetFileAddress();
199 if (addr_section == NULL || addr_section->ContainsFileAddress (file_addr) == false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000200 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000201 if (range_module)
202 range_module->ResolveFileAddress (file_addr, addr);
203 else if (exe_ctx.target)
204 exe_ctx.target->GetImages().ResolveFileAddress (file_addr, addr);
205
206 addr_section = addr.GetSection();
207 }
208
209 prev_sc = sc;
210
211 if (addr_section)
212 {
213 Module *module = addr_section->GetModule();
214 uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
215 if (resolved_mask)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000216 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000217 if (prev_sc.function != sc.function || prev_sc.symbol != sc.symbol)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000218 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000219 if (prev_sc.function || prev_sc.symbol)
220 strm.EOL();
221
222 strm << sc.module_sp->GetFileSpec().GetFilename();
223
224 if (sc.function)
225 strm << '`' << sc.function->GetMangled().GetName();
226 else if (sc.symbol)
227 strm << '`' << sc.symbol->GetMangled().GetName();
228 strm << ":\n";
229 }
230
231 if (num_mixed_context_lines && !sc_range.ContainsFileAddress (addr))
232 {
233 sc.GetAddressRange (eSymbolContextEverything, sc_range);
234
235 if (sc != prev_sc)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000236 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000237 if (offset != 0)
238 strm.EOL();
239
240 sc.DumpStopContext(&strm, process, addr);
241
242 if (sc.comp_unit && sc.line_entry.IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000243 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000244 debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
245 sc.line_entry.line,
246 num_mixed_context_lines,
247 num_mixed_context_lines,
248 num_mixed_context_lines ? "->" : "",
249 &strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000250 }
251 }
252 }
253 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000254 else
255 {
256 sc.Clear();
257 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000258 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000259 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000260 strm.IndentMore ();
261 strm.Indent();
262 size_t inst_byte_size = inst->GetByteSize();
Greg Claytondda4f7b2010-06-30 23:03:03 +0000263 inst->Dump(&strm, &addr, show_bytes ? &data : NULL, offset, exe_ctx, show_bytes);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000264 strm.EOL();
265 offset += inst_byte_size;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000266
267 addr.SetOffset (addr.GetOffset() + inst_byte_size);
268
269 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000270 strm.IndentLess ();
271 }
272 else
273 {
274 break;
275 }
276 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000277 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000278 strm.IndentLess ();
279
280 }
281 }
282 return true;
283 }
284 return false;
285}
286
Greg Claytondda4f7b2010-06-30 23:03:03 +0000287
288bool
289Disassembler::Disassemble
290(
291 Debugger &debugger,
292 const ArchSpec &arch,
293 const ExecutionContext &exe_ctx,
294 uint32_t num_mixed_context_lines,
295 bool show_bytes,
296 Stream &strm
297)
298{
299 AddressRange range;
300 if (exe_ctx.frame)
301 {
302 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
303 if (sc.function)
304 {
305 range = sc.function->GetAddressRange();
306 }
307 else if (sc.symbol && sc.symbol->GetAddressRangePtr())
308 {
309 range = *sc.symbol->GetAddressRangePtr();
310 }
311 else
312 {
313 range.GetBaseAddress() = exe_ctx.frame->GetPC();
314 }
315
316 if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
317 range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
318 }
319
320 return Disassemble(debugger, arch, exe_ctx, range, num_mixed_context_lines, show_bytes, strm);
321}
322
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000323Disassembler::Instruction::Instruction()
324{
325}
326
327Disassembler::Instruction::~Instruction()
328{
329}
330
331
332Disassembler::InstructionList::InstructionList() :
333 m_instructions()
334{
335}
336
337Disassembler::InstructionList::~InstructionList()
338{
339}
340
341size_t
342Disassembler::InstructionList::GetSize() const
343{
344 return m_instructions.size();
345}
346
347
348Disassembler::Instruction *
349Disassembler::InstructionList::GetInstructionAtIndex (uint32_t idx)
350{
351 if (idx < m_instructions.size())
352 return m_instructions[idx].get();
353 return NULL;
354}
355
356const Disassembler::Instruction *
357Disassembler::InstructionList::GetInstructionAtIndex (uint32_t idx) const
358{
359 if (idx < m_instructions.size())
360 return m_instructions[idx].get();
361 return NULL;
362}
363
364void
365Disassembler::InstructionList::Clear()
366{
367 m_instructions.clear();
368}
369
370void
371Disassembler::InstructionList::AppendInstruction (Instruction::shared_ptr &inst_sp)
372{
373 if (inst_sp)
374 m_instructions.push_back(inst_sp);
375}
376
377
378size_t
379Disassembler::ParseInstructions
380(
381 const ExecutionContext *exe_ctx,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000382 const AddressRange &range,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000383 DataExtractor& data
384)
385{
Greg Claytondda4f7b2010-06-30 23:03:03 +0000386 Target *target = exe_ctx->target;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000387
Greg Claytondda4f7b2010-06-30 23:03:03 +0000388 const addr_t byte_size = range.GetByteSize();
389 if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000390 return 0;
391
Greg Claytondda4f7b2010-06-30 23:03:03 +0000392 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
393 DataBufferSP data_sp(heap_buffer);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000394
395 Error error;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000396 const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(), heap_buffer->GetBytes(), heap_buffer->GetByteSize(), error);
397
398 if (bytes_read > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000399 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000400 if (bytes_read != heap_buffer->GetByteSize())
401 heap_buffer->SetByteSize (bytes_read);
402
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000403 data.SetData(data_sp);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000404 if (exe_ctx->process)
405 {
406 data.SetByteOrder(exe_ctx->process->GetByteOrder());
407 data.SetAddressByteSize(exe_ctx->process->GetAddressByteSize());
408 }
409 else
410 {
411 data.SetByteOrder(target->GetArchitecture().GetDefaultEndian());
412 data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
413 }
414 return DecodeInstructions (data, 0, UINT32_MAX);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000415 }
416
417 return 0;
418}
419
420//----------------------------------------------------------------------
421// Disassembler copy constructor
422//----------------------------------------------------------------------
423Disassembler::Disassembler(const ArchSpec& arch) :
424 m_arch (arch),
425 m_instruction_list(),
426 m_base_addr(LLDB_INVALID_ADDRESS)
427{
428
429}
430
431//----------------------------------------------------------------------
432// Destructor
433//----------------------------------------------------------------------
434Disassembler::~Disassembler()
435{
436}
437
438Disassembler::InstructionList &
439Disassembler::GetInstructionList ()
440{
441 return m_instruction_list;
442}
443
444const Disassembler::InstructionList &
445Disassembler::GetInstructionList () const
446{
447 return m_instruction_list;
448}