blob: 570ff7262258cbc15deb31922b0663946a2a5fa8 [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
55bool
56Disassembler::Disassemble
57(
58 const ArchSpec &arch,
59 const ExecutionContext &exe_ctx,
60 uint32_t mixed_context_lines,
61 Stream &strm
62)
63{
64 Disassembler *disassembler = Disassembler::FindPlugin(arch);
65
66 if (disassembler)
67 {
68 lldb::addr_t addr = LLDB_INVALID_ADDRESS;
69 size_t byte_size = 0;
70 if (exe_ctx.frame)
71 {
72 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
73 if (sc.function)
74 {
75 addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(exe_ctx.process);
76 if (addr != LLDB_INVALID_ADDRESS)
77 byte_size = sc.function->GetAddressRange().GetByteSize();
78 }
79 else if (sc.symbol && sc.symbol->GetAddressRangePtr())
80 {
81 addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress().GetLoadAddress(exe_ctx.process);
82 if (addr != LLDB_INVALID_ADDRESS)
83 {
84 byte_size = sc.symbol->GetAddressRangePtr()->GetByteSize();
85 if (byte_size == 0)
86 byte_size = DEFAULT_DISASM_BYTE_SIZE;
87 }
88 }
89 else
90 {
91 addr = exe_ctx.frame->GetPC().GetLoadAddress(exe_ctx.process);
92 if (addr != LLDB_INVALID_ADDRESS)
93 byte_size = DEFAULT_DISASM_BYTE_SIZE;
94 }
95 }
96
97 if (byte_size)
98 {
99 DataExtractor data;
100 size_t bytes_disassembled = disassembler->ParseInstructions (&exe_ctx, eAddressTypeLoad, addr, byte_size, data);
101 if (bytes_disassembled == 0)
102 {
103 return false;
104 }
105 else
106 {
107 // We got some things disassembled...
108 size_t num_instructions = disassembler->GetInstructionList().GetSize();
109 uint32_t offset = 0;
110 SymbolContext sc;
111 SymbolContext prev_sc;
112 AddressRange sc_range;
113 if (mixed_context_lines)
114 strm.IndentMore ();
115
116 for (size_t i=0; i<num_instructions; ++i)
117 {
118 Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
119 if (inst)
120 {
121 lldb::addr_t curr_addr = addr + offset;
122 if (mixed_context_lines)
123 {
124 if (!sc_range.ContainsLoadAddress (curr_addr, exe_ctx.process))
125 {
126 prev_sc = sc;
127 Address curr_so_addr;
128 Process *process = exe_ctx.process;
129 if (process && process->ResolveLoadAddress (curr_addr, curr_so_addr))
130 {
131 if (curr_so_addr.GetSection())
132 {
133 Module *module = curr_so_addr.GetSection()->GetModule();
134 uint32_t resolved_mask = module->ResolveSymbolContextForAddress(curr_so_addr, eSymbolContextEverything, sc);
135 if (resolved_mask)
136 {
137 sc.GetAddressRange (eSymbolContextEverything, sc_range);
138 if (sc != prev_sc)
139 {
140 if (offset != 0)
141 strm.EOL();
142
143 sc.DumpStopContext(&strm, process, curr_so_addr);
144
145 if (sc.comp_unit && sc.line_entry.IsValid())
146 {
147 Debugger::GetSharedInstance().GetSourceManager().DisplaySourceLinesWithLineNumbers (
148 sc.line_entry.file,
149 sc.line_entry.line,
150 mixed_context_lines,
151 mixed_context_lines,
152 mixed_context_lines ? "->" : "",
153 &strm);
154 }
155 }
156 }
157 }
158 }
159 }
160 }
161 if (mixed_context_lines)
162 strm.IndentMore ();
163 strm.Indent();
164 size_t inst_byte_size = inst->GetByteSize();
165 //inst->Dump(&strm, curr_addr, &data, offset); // Do dump opcode bytes
166 inst->Dump(&strm, curr_addr, NULL, offset, exe_ctx, false); // Don't dump opcode bytes
167 strm.EOL();
168 offset += inst_byte_size;
169 if (mixed_context_lines)
170 strm.IndentLess ();
171 }
172 else
173 {
174 break;
175 }
176 }
177 if (mixed_context_lines)
178 strm.IndentLess ();
179
180 }
181 }
182 return true;
183 }
184 return false;
185}
186
187Disassembler::Instruction::Instruction()
188{
189}
190
191Disassembler::Instruction::~Instruction()
192{
193}
194
195
196Disassembler::InstructionList::InstructionList() :
197 m_instructions()
198{
199}
200
201Disassembler::InstructionList::~InstructionList()
202{
203}
204
205size_t
206Disassembler::InstructionList::GetSize() const
207{
208 return m_instructions.size();
209}
210
211
212Disassembler::Instruction *
213Disassembler::InstructionList::GetInstructionAtIndex (uint32_t idx)
214{
215 if (idx < m_instructions.size())
216 return m_instructions[idx].get();
217 return NULL;
218}
219
220const Disassembler::Instruction *
221Disassembler::InstructionList::GetInstructionAtIndex (uint32_t idx) const
222{
223 if (idx < m_instructions.size())
224 return m_instructions[idx].get();
225 return NULL;
226}
227
228void
229Disassembler::InstructionList::Clear()
230{
231 m_instructions.clear();
232}
233
234void
235Disassembler::InstructionList::AppendInstruction (Instruction::shared_ptr &inst_sp)
236{
237 if (inst_sp)
238 m_instructions.push_back(inst_sp);
239}
240
241
242size_t
243Disassembler::ParseInstructions
244(
245 const ExecutionContext *exe_ctx,
246 lldb::AddressType addr_type,
247 lldb::addr_t addr,
248 size_t byte_size,
249 DataExtractor& data
250)
251{
252 Process *process = exe_ctx->process;
253
254 if (process == NULL)
255 return 0;
256
257 DataBufferSP data_sp(new DataBufferHeap (byte_size, '\0'));
258
259 Error error;
260 if (process->GetTarget().ReadMemory (addr_type, addr, data_sp->GetBytes(), data_sp->GetByteSize(), error, NULL))
261 {
262 data.SetData(data_sp);
263 data.SetByteOrder(process->GetByteOrder());
264 data.SetAddressByteSize(process->GetAddressByteSize());
265 return ParseInstructions (data, 0, UINT32_MAX, addr);
266 }
267
268 return 0;
269}
270
271//----------------------------------------------------------------------
272// Disassembler copy constructor
273//----------------------------------------------------------------------
274Disassembler::Disassembler(const ArchSpec& arch) :
275 m_arch (arch),
276 m_instruction_list(),
277 m_base_addr(LLDB_INVALID_ADDRESS)
278{
279
280}
281
282//----------------------------------------------------------------------
283// Destructor
284//----------------------------------------------------------------------
285Disassembler::~Disassembler()
286{
287}
288
289Disassembler::InstructionList &
290Disassembler::GetInstructionList ()
291{
292 return m_instruction_list;
293}
294
295const Disassembler::InstructionList &
296Disassembler::GetInstructionList () const
297{
298 return m_instruction_list;
299}