1 //===-- 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 32 using namespace lldb; 33 using namespace lldb_private; 34 35 36 Disassembler* 37 Disassembler::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 55 56 57 size_t 58 Disassembler::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 89 bool 90 Disassembler::Disassemble 91 ( 92 Debugger &debugger, 93 const ArchSpec &arch, 94 const ExecutionContext &exe_ctx, 95 const ConstString &name, 96 Module *module, 97 uint32_t num_mixed_context_lines, 98 bool show_bytes, 99 Stream &strm 100 ) 101 { 102 if (exe_ctx.target == NULL && name) 103 return false; 104 105 SymbolContextList sc_list; 106 107 if (module) 108 { 109 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)) 120 { 121 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 131 bool 132 Disassembler::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) 156 { 157 if (process && process->IsAlive()) 158 { 159 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()); 164 } 165 } 166 167 168 DataExtractor data; 169 size_t bytes_disassembled = disassembler->ParseInstructions (&exe_ctx, range, data); 170 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; 182 if (num_mixed_context_lines) 183 strm.IndentMore (); 184 185 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 193 for (size_t i=0; i<num_instructions; ++i) 194 { 195 Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i); 196 if (inst) 197 { 198 addr_t file_addr = addr.GetFileAddress(); 199 if (addr_section == NULL || addr_section->ContainsFileAddress (file_addr) == false) 200 { 201 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) 216 { 217 if (prev_sc.function != sc.function || prev_sc.symbol != sc.symbol) 218 { 219 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) 236 { 237 if (offset != 0) 238 strm.EOL(); 239 240 sc.DumpStopContext(&strm, process, addr); 241 242 if (sc.comp_unit && sc.line_entry.IsValid()) 243 { 244 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); 250 } 251 } 252 } 253 } 254 else 255 { 256 sc.Clear(); 257 } 258 } 259 if (num_mixed_context_lines) 260 strm.IndentMore (); 261 strm.Indent(); 262 size_t inst_byte_size = inst->GetByteSize(); 263 inst->Dump(&strm, &addr, show_bytes ? &data : NULL, offset, exe_ctx, show_bytes); 264 strm.EOL(); 265 offset += inst_byte_size; 266 267 addr.SetOffset (addr.GetOffset() + inst_byte_size); 268 269 if (num_mixed_context_lines) 270 strm.IndentLess (); 271 } 272 else 273 { 274 break; 275 } 276 } 277 if (num_mixed_context_lines) 278 strm.IndentLess (); 279 280 } 281 } 282 return true; 283 } 284 return false; 285 } 286 287 288 bool 289 Disassembler::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 323 Disassembler::Instruction::Instruction() 324 { 325 } 326 327 Disassembler::Instruction::~Instruction() 328 { 329 } 330 331 332 Disassembler::InstructionList::InstructionList() : 333 m_instructions() 334 { 335 } 336 337 Disassembler::InstructionList::~InstructionList() 338 { 339 } 340 341 size_t 342 Disassembler::InstructionList::GetSize() const 343 { 344 return m_instructions.size(); 345 } 346 347 348 Disassembler::Instruction * 349 Disassembler::InstructionList::GetInstructionAtIndex (uint32_t idx) 350 { 351 if (idx < m_instructions.size()) 352 return m_instructions[idx].get(); 353 return NULL; 354 } 355 356 const Disassembler::Instruction * 357 Disassembler::InstructionList::GetInstructionAtIndex (uint32_t idx) const 358 { 359 if (idx < m_instructions.size()) 360 return m_instructions[idx].get(); 361 return NULL; 362 } 363 364 void 365 Disassembler::InstructionList::Clear() 366 { 367 m_instructions.clear(); 368 } 369 370 void 371 Disassembler::InstructionList::AppendInstruction (Instruction::shared_ptr &inst_sp) 372 { 373 if (inst_sp) 374 m_instructions.push_back(inst_sp); 375 } 376 377 378 size_t 379 Disassembler::ParseInstructions 380 ( 381 const ExecutionContext *exe_ctx, 382 const AddressRange &range, 383 DataExtractor& data 384 ) 385 { 386 Target *target = exe_ctx->target; 387 388 const addr_t byte_size = range.GetByteSize(); 389 if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid()) 390 return 0; 391 392 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0'); 393 DataBufferSP data_sp(heap_buffer); 394 395 Error error; 396 const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(), heap_buffer->GetBytes(), heap_buffer->GetByteSize(), error); 397 398 if (bytes_read > 0) 399 { 400 if (bytes_read != heap_buffer->GetByteSize()) 401 heap_buffer->SetByteSize (bytes_read); 402 403 data.SetData(data_sp); 404 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); 415 } 416 417 return 0; 418 } 419 420 //---------------------------------------------------------------------- 421 // Disassembler copy constructor 422 //---------------------------------------------------------------------- 423 Disassembler::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 //---------------------------------------------------------------------- 434 Disassembler::~Disassembler() 435 { 436 } 437 438 Disassembler::InstructionList & 439 Disassembler::GetInstructionList () 440 { 441 return m_instruction_list; 442 } 443 444 const Disassembler::InstructionList & 445 Disassembler::GetInstructionList () const 446 { 447 return m_instruction_list; 448 } 449