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 bool 56 Disassembler::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 187 Disassembler::Instruction::Instruction() 188 { 189 } 190 191 Disassembler::Instruction::~Instruction() 192 { 193 } 194 195 196 Disassembler::InstructionList::InstructionList() : 197 m_instructions() 198 { 199 } 200 201 Disassembler::InstructionList::~InstructionList() 202 { 203 } 204 205 size_t 206 Disassembler::InstructionList::GetSize() const 207 { 208 return m_instructions.size(); 209 } 210 211 212 Disassembler::Instruction * 213 Disassembler::InstructionList::GetInstructionAtIndex (uint32_t idx) 214 { 215 if (idx < m_instructions.size()) 216 return m_instructions[idx].get(); 217 return NULL; 218 } 219 220 const Disassembler::Instruction * 221 Disassembler::InstructionList::GetInstructionAtIndex (uint32_t idx) const 222 { 223 if (idx < m_instructions.size()) 224 return m_instructions[idx].get(); 225 return NULL; 226 } 227 228 void 229 Disassembler::InstructionList::Clear() 230 { 231 m_instructions.clear(); 232 } 233 234 void 235 Disassembler::InstructionList::AppendInstruction (Instruction::shared_ptr &inst_sp) 236 { 237 if (inst_sp) 238 m_instructions.push_back(inst_sp); 239 } 240 241 242 size_t 243 Disassembler::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 //---------------------------------------------------------------------- 274 Disassembler::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 //---------------------------------------------------------------------- 285 Disassembler::~Disassembler() 286 { 287 } 288 289 Disassembler::InstructionList & 290 Disassembler::GetInstructionList () 291 { 292 return m_instruction_list; 293 } 294 295 const Disassembler::InstructionList & 296 Disassembler::GetInstructionList () const 297 { 298 return m_instruction_list; 299 } 300