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