blob: 4d24cf1ab6de37a9210dafa01f677c6a50c9aa75 [file] [log] [blame]
Sean Callanan95e5c632012-02-17 00:53:45 +00001//===-- DisassemblerLLVMC.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
Eugene Zelenko45a40142015-10-22 21:24:37 +000010// C Includes
11// C++ Includes
12// Project includes
Sean Callanan95e5c632012-02-17 00:53:45 +000013#include "llvm-c/Disassembler.h"
Benjamin Kramer79dad1d2016-01-26 16:45:00 +000014#include "llvm/ADT/SmallString.h"
Jim Ingham0f063ba2013-03-02 00:26:47 +000015#include "llvm/MC/MCAsmInfo.h"
16#include "llvm/MC/MCContext.h"
Benjamin Kramer79dad1d2016-01-26 16:45:00 +000017#include "llvm/MC/MCDisassembler/MCDisassembler.h"
18#include "llvm/MC/MCDisassembler/MCExternalSymbolizer.h"
19#include "llvm/MC/MCDisassembler/MCRelocationInfo.h"
Jim Ingham0f063ba2013-03-02 00:26:47 +000020#include "llvm/MC/MCInst.h"
21#include "llvm/MC/MCInstPrinter.h"
22#include "llvm/MC/MCInstrInfo.h"
23#include "llvm/MC/MCRegisterInfo.h"
24#include "llvm/MC/MCSubtargetInfo.h"
25#include "llvm/Support/ErrorHandling.h"
Jim Ingham0f063ba2013-03-02 00:26:47 +000026#include "llvm/Support/TargetRegistry.h"
Sean Callanan95e5c632012-02-17 00:53:45 +000027#include "llvm/Support/TargetSelect.h"
Jim Ingham0f063ba2013-03-02 00:26:47 +000028
Eugene Zelenko45a40142015-10-22 21:24:37 +000029// Other libraries and framework includes
30#include "DisassemblerLLVMC.h"
Sean Callanan95e5c632012-02-17 00:53:45 +000031
32#include "lldb/Core/Address.h"
33#include "lldb/Core/DataExtractor.h"
Greg Clayton1f746072012-08-29 21:13:06 +000034#include "lldb/Core/Module.h"
Sean Callanan95e5c632012-02-17 00:53:45 +000035#include "lldb/Core/Stream.h"
36#include "lldb/Symbol/SymbolContext.h"
37#include "lldb/Target/ExecutionContext.h"
38#include "lldb/Target/Process.h"
39#include "lldb/Target/RegisterContext.h"
Greg Claytond5944cd2013-12-06 01:12:00 +000040#include "lldb/Target/SectionLoadList.h"
Sean Callanan95e5c632012-02-17 00:53:45 +000041#include "lldb/Target/Target.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000042#include "lldb/Target/StackFrame.h"
Sean Callanan95e5c632012-02-17 00:53:45 +000043
Virgile Bellob2f1fb22013-08-23 12:44:05 +000044#include "lldb/Core/RegularExpression.h"
Sean Callanan95e5c632012-02-17 00:53:45 +000045
46using namespace lldb;
47using namespace lldb_private;
48
49class InstructionLLVMC : public lldb_private::Instruction
50{
51public:
52 InstructionLLVMC (DisassemblerLLVMC &disasm,
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +000053 const lldb_private::Address &address,
Greg Claytonc8e0c242012-04-13 00:07:34 +000054 AddressClass addr_class) :
Greg Clayton3faf47c2013-03-28 23:42:53 +000055 Instruction (address, addr_class),
Greg Clayton4a9d83a2016-06-07 22:56:40 +000056 m_disasm_wp (std::static_pointer_cast<DisassemblerLLVMC>(disasm.shared_from_this())),
Greg Clayton3faf47c2013-03-28 23:42:53 +000057 m_does_branch (eLazyBoolCalculate),
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +000058 m_has_delay_slot (eLazyBoolCalculate),
Greg Clayton3faf47c2013-03-28 23:42:53 +000059 m_is_valid (false),
60 m_using_file_addr (false)
Sean Callanan95e5c632012-02-17 00:53:45 +000061 {
62 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +000063
Eugene Zelenko45a40142015-10-22 21:24:37 +000064 ~InstructionLLVMC() override = default;
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +000065
Eugene Zelenko45a40142015-10-22 21:24:37 +000066 bool
67 DoesBranch() override
Sean Callanan95e5c632012-02-17 00:53:45 +000068 {
Jim Ingham32ce20c2013-03-13 01:55:16 +000069 if (m_does_branch == eLazyBoolCalculate)
70 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +000071 std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
72 if (disasm_sp)
Jim Ingham32ce20c2013-03-13 01:55:16 +000073 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +000074 disasm_sp->Lock(this, NULL);
75 DataExtractor data;
76 if (m_opcode.GetData(data))
Jim Ingham32ce20c2013-03-13 01:55:16 +000077 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +000078 bool is_alternate_isa;
79 lldb::addr_t pc = m_address.GetFileAddress();
80
81 DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
82 const uint8_t *opcode_data = data.GetDataStart();
83 const size_t opcode_data_len = data.GetByteSize();
84 llvm::MCInst inst;
85 const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
86 opcode_data_len,
87 pc,
88 inst);
89 // Be conservative, if we didn't understand the instruction, say it might branch...
90 if (inst_size == 0)
Jim Ingham32ce20c2013-03-13 01:55:16 +000091 m_does_branch = eLazyBoolYes;
92 else
Greg Clayton4a9d83a2016-06-07 22:56:40 +000093 {
94 const bool can_branch = mc_disasm_ptr->CanBranch(inst);
95 if (can_branch)
96 m_does_branch = eLazyBoolYes;
97 else
98 m_does_branch = eLazyBoolNo;
99 }
Jim Ingham32ce20c2013-03-13 01:55:16 +0000100 }
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000101 disasm_sp->Unlock();
Jim Ingham32ce20c2013-03-13 01:55:16 +0000102 }
Jim Ingham32ce20c2013-03-13 01:55:16 +0000103 }
Sean Callanan7725a462012-03-02 23:22:53 +0000104 return m_does_branch == eLazyBoolYes;
Sean Callanan95e5c632012-02-17 00:53:45 +0000105 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000106
Eugene Zelenko45a40142015-10-22 21:24:37 +0000107 bool
108 HasDelaySlot() override
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +0000109 {
110 if (m_has_delay_slot == eLazyBoolCalculate)
111 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000112 std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
113 if (disasm_sp)
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +0000114 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000115 disasm_sp->Lock(this, NULL);
116 DataExtractor data;
117 if (m_opcode.GetData(data))
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +0000118 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000119 bool is_alternate_isa;
120 lldb::addr_t pc = m_address.GetFileAddress();
121
122 DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
123 const uint8_t *opcode_data = data.GetDataStart();
124 const size_t opcode_data_len = data.GetByteSize();
125 llvm::MCInst inst;
126 const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
127 opcode_data_len,
128 pc,
129 inst);
130 // if we didn't understand the instruction, say it doesn't have a delay slot...
131 if (inst_size == 0)
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +0000132 m_has_delay_slot = eLazyBoolNo;
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000133 else
134 {
135 const bool has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst);
136 if (has_delay_slot)
137 m_has_delay_slot = eLazyBoolYes;
138 else
139 m_has_delay_slot = eLazyBoolNo;
140 }
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +0000141 }
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000142 disasm_sp->Unlock();
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +0000143 }
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +0000144 }
145 return m_has_delay_slot == eLazyBoolYes;
146 }
147
Jim Ingham32ce20c2013-03-13 01:55:16 +0000148 DisassemblerLLVMC::LLVMCDisassembler *
149 GetDisasmToUse (bool &is_alternate_isa)
150 {
Jim Ingham32ce20c2013-03-13 01:55:16 +0000151 is_alternate_isa = false;
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000152 std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
153 if (disasm_sp)
Jim Ingham32ce20c2013-03-13 01:55:16 +0000154 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000155 if (disasm_sp->m_alternate_disasm_ap.get() != NULL)
Jim Ingham32ce20c2013-03-13 01:55:16 +0000156 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000157 const AddressClass address_class = GetAddressClass ();
158
159 if (address_class == eAddressClassCodeAlternateISA)
160 {
161 is_alternate_isa = true;
162 return disasm_sp->m_alternate_disasm_ap.get();
163 }
Jim Ingham32ce20c2013-03-13 01:55:16 +0000164 }
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000165 return disasm_sp->m_disasm_ap.get();
Jim Ingham32ce20c2013-03-13 01:55:16 +0000166 }
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000167 return nullptr;
Jim Ingham32ce20c2013-03-13 01:55:16 +0000168 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000169
Eugene Zelenko45a40142015-10-22 21:24:37 +0000170 size_t
171 Decode(const lldb_private::Disassembler &disassembler,
172 const lldb_private::DataExtractor &data,
173 lldb::offset_t data_offset) override
Sean Callanan95e5c632012-02-17 00:53:45 +0000174 {
Greg Claytonba812f42012-05-10 02:52:23 +0000175 // All we have to do is read the opcode which can be easy for some
Michael Sartaincc791bb2013-07-11 16:40:56 +0000176 // architectures
Greg Claytonba812f42012-05-10 02:52:23 +0000177 bool got_op = false;
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000178 std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
179 if (disasm_sp)
Greg Claytonba812f42012-05-10 02:52:23 +0000180 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000181 const ArchSpec &arch = disasm_sp->GetArchitecture();
182 const lldb::ByteOrder byte_order = data.GetByteOrder();
Ed Maste90359962013-12-09 19:45:33 +0000183
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000184 const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize();
185 const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize();
186 if (min_op_byte_size == max_op_byte_size)
Greg Claytonba812f42012-05-10 02:52:23 +0000187 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000188 // Fixed size instructions, just read that amount of data.
189 if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size))
190 return false;
Greg Claytonba812f42012-05-10 02:52:23 +0000191
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000192 switch (min_op_byte_size)
Greg Claytonba812f42012-05-10 02:52:23 +0000193 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000194 case 1:
195 m_opcode.SetOpcode8 (data.GetU8 (&data_offset), byte_order);
196 got_op = true;
197 break;
198
199 case 2:
200 m_opcode.SetOpcode16 (data.GetU16 (&data_offset), byte_order);
201 got_op = true;
202 break;
203
204 case 4:
205 m_opcode.SetOpcode32 (data.GetU32 (&data_offset), byte_order);
206 got_op = true;
207 break;
208
209 case 8:
210 m_opcode.SetOpcode64 (data.GetU64 (&data_offset), byte_order);
211 got_op = true;
212 break;
213
214 default:
215 m_opcode.SetOpcodeBytes(data.PeekData(data_offset, min_op_byte_size), min_op_byte_size);
216 got_op = true;
217 break;
218 }
219 }
220 if (!got_op)
221 {
222 bool is_alternate_isa = false;
223 DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
224
225 const llvm::Triple::ArchType machine = arch.GetMachine();
226 if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb)
227 {
228 if (machine == llvm::Triple::thumb || is_alternate_isa)
Greg Claytonba812f42012-05-10 02:52:23 +0000229 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000230 uint32_t thumb_opcode = data.GetU16(&data_offset);
231 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
232 {
233 m_opcode.SetOpcode16 (thumb_opcode, byte_order);
234 m_is_valid = true;
235 }
236 else
237 {
238 thumb_opcode <<= 16;
239 thumb_opcode |= data.GetU16(&data_offset);
240 m_opcode.SetOpcode16_2 (thumb_opcode, byte_order);
241 m_is_valid = true;
242 }
Greg Claytonba812f42012-05-10 02:52:23 +0000243 }
244 else
245 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000246 m_opcode.SetOpcode32 (data.GetU32(&data_offset), byte_order);
Greg Claytonba812f42012-05-10 02:52:23 +0000247 m_is_valid = true;
248 }
249 }
250 else
251 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000252 // The opcode isn't evenly sized, so we need to actually use the llvm
253 // disassembler to parse it and get the size.
254 uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (data_offset, 1));
255 const size_t opcode_data_len = data.BytesLeft(data_offset);
256 const addr_t pc = m_address.GetFileAddress();
257 llvm::MCInst inst;
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000258
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000259 disasm_sp->Lock(this, NULL);
260 const size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data,
261 opcode_data_len,
262 pc,
263 inst);
264 disasm_sp->Unlock();
265 if (inst_size == 0)
266 m_opcode.Clear();
267 else
268 {
269 m_opcode.SetOpcodeBytes(opcode_data, inst_size);
270 m_is_valid = true;
271 }
Greg Claytonba812f42012-05-10 02:52:23 +0000272 }
273 }
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000274 return m_opcode.GetByteSize();
Greg Claytonba812f42012-05-10 02:52:23 +0000275 }
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000276 return 0;
Sean Callanan95e5c632012-02-17 00:53:45 +0000277 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000278
Sean Callanan95e5c632012-02-17 00:53:45 +0000279 void
Greg Claytonba812f42012-05-10 02:52:23 +0000280 AppendComment (std::string &description)
Sean Callanan95e5c632012-02-17 00:53:45 +0000281 {
Greg Claytonba812f42012-05-10 02:52:23 +0000282 if (m_comment.empty())
283 m_comment.swap (description);
Sean Callanan95e5c632012-02-17 00:53:45 +0000284 else
Greg Claytonba812f42012-05-10 02:52:23 +0000285 {
286 m_comment.append(", ");
287 m_comment.append(description);
288 }
Sean Callanan95e5c632012-02-17 00:53:45 +0000289 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000290
Eugene Zelenko45a40142015-10-22 21:24:37 +0000291 void
292 CalculateMnemonicOperandsAndComment(const lldb_private::ExecutionContext *exe_ctx) override
Sean Callanan95e5c632012-02-17 00:53:45 +0000293 {
Greg Claytonba812f42012-05-10 02:52:23 +0000294 DataExtractor data;
295 const AddressClass address_class = GetAddressClass ();
296
Sean Callanancd4ae1a2012-08-07 01:44:58 +0000297 if (m_opcode.GetData(data))
Greg Claytonba812f42012-05-10 02:52:23 +0000298 {
Sean Callanand38f4d22015-12-11 19:10:04 +0000299 std::string out_string;
300 std::string comment_string;
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000301
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000302 std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
303 if (disasm_sp)
Greg Claytonba812f42012-05-10 02:52:23 +0000304 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000305 DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr;
Daniel Malead79ae052013-08-07 21:54:09 +0000306
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000307 if (address_class == eAddressClassCodeAlternateISA)
308 mc_disasm_ptr = disasm_sp->m_alternate_disasm_ap.get();
309 else
310 mc_disasm_ptr = disasm_sp->m_disasm_ap.get();
311
312 lldb::addr_t pc = m_address.GetFileAddress();
313 m_using_file_addr = true;
314
315 const bool data_from_file = disasm_sp->m_data_from_file;
316 bool use_hex_immediates = true;
317 Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC;
318
319 if (exe_ctx)
320 {
321 Target *target = exe_ctx->GetTargetPtr();
322 if (target)
Greg Clayton3faf47c2013-03-28 23:42:53 +0000323 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000324 use_hex_immediates = target->GetUseHexImmediates();
325 hex_style = target->GetHexImmediateStyle();
326
327 if (!data_from_file)
Greg Clayton3faf47c2013-03-28 23:42:53 +0000328 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000329 const lldb::addr_t load_addr = m_address.GetLoadAddress(target);
330 if (load_addr != LLDB_INVALID_ADDRESS)
331 {
332 pc = load_addr;
333 m_using_file_addr = false;
334 }
Greg Clayton3faf47c2013-03-28 23:42:53 +0000335 }
336 }
337 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000338
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000339 disasm_sp->Lock(this, exe_ctx);
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000340
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000341 const uint8_t *opcode_data = data.GetDataStart();
342 const size_t opcode_data_len = data.GetByteSize();
343 llvm::MCInst inst;
344 size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
345 opcode_data_len,
346 pc,
347 inst);
Daniel Malead79ae052013-08-07 21:54:09 +0000348
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000349 if (inst_size > 0)
Sean Callanand38f4d22015-12-11 19:10:04 +0000350 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000351 mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style);
352 mc_disasm_ptr->PrintMCInst(inst, out_string, comment_string);
353
354 if (!comment_string.empty())
355 {
356 AppendComment(comment_string);
357 }
Sean Callanand38f4d22015-12-11 19:10:04 +0000358 }
Daniel Malead79ae052013-08-07 21:54:09 +0000359
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000360 disasm_sp->Unlock();
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000361
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000362 if (inst_size == 0)
Greg Claytonba812f42012-05-10 02:52:23 +0000363 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000364 m_comment.assign ("unknown opcode");
365 inst_size = m_opcode.GetByteSize();
366 StreamString mnemonic_strm;
367 lldb::offset_t offset = 0;
368 lldb::ByteOrder byte_order = data.GetByteOrder();
369 switch (inst_size)
370 {
371 case 1:
372 {
373 const uint8_t uval8 = data.GetU8 (&offset);
374 m_opcode.SetOpcode8 (uval8, byte_order);
375 m_opcode_name.assign (".byte");
376 mnemonic_strm.Printf("0x%2.2x", uval8);
377 }
378 break;
379 case 2:
380 {
381 const uint16_t uval16 = data.GetU16(&offset);
382 m_opcode.SetOpcode16(uval16, byte_order);
383 m_opcode_name.assign (".short");
384 mnemonic_strm.Printf("0x%4.4x", uval16);
385 }
386 break;
387 case 4:
388 {
389 const uint32_t uval32 = data.GetU32(&offset);
390 m_opcode.SetOpcode32(uval32, byte_order);
391 m_opcode_name.assign (".long");
392 mnemonic_strm.Printf("0x%8.8x", uval32);
393 }
394 break;
395 case 8:
396 {
397 const uint64_t uval64 = data.GetU64(&offset);
398 m_opcode.SetOpcode64(uval64, byte_order);
399 m_opcode_name.assign (".quad");
400 mnemonic_strm.Printf("0x%16.16" PRIx64, uval64);
401 }
402 break;
403 default:
404 if (inst_size == 0)
Greg Claytonba812f42012-05-10 02:52:23 +0000405 return;
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000406 else
407 {
408 const uint8_t *bytes = data.PeekData(offset, inst_size);
409 if (bytes == NULL)
410 return;
411 m_opcode_name.assign (".byte");
412 m_opcode.SetOpcodeBytes(bytes, inst_size);
413 mnemonic_strm.Printf("0x%2.2x", bytes[0]);
414 for (uint32_t i=1; i<inst_size; ++i)
415 mnemonic_strm.Printf(" 0x%2.2x", bytes[i]);
416 }
417 break;
418 }
419 m_mnemonics.swap(mnemonic_strm.GetString());
420 return;
Greg Claytonba812f42012-05-10 02:52:23 +0000421 }
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000422 else
Greg Claytonba812f42012-05-10 02:52:23 +0000423 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000424 if (m_does_branch == eLazyBoolCalculate)
425 {
426 const bool can_branch = mc_disasm_ptr->CanBranch(inst);
427 if (can_branch)
428 m_does_branch = eLazyBoolYes;
429 else
430 m_does_branch = eLazyBoolNo;
Jim Ingham0f063ba2013-03-02 00:26:47 +0000431
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000432 }
Greg Claytonba812f42012-05-10 02:52:23 +0000433 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000434
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000435 static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?");
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000436
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000437 RegularExpression::Match matches(3);
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000438
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000439 if (s_regex.Execute(out_string.c_str(), &matches))
440 {
441 matches.GetMatchAtIndex(out_string.c_str(), 1, m_opcode_name);
442 matches.GetMatchAtIndex(out_string.c_str(), 2, m_mnemonics);
443 }
Greg Claytonba812f42012-05-10 02:52:23 +0000444 }
445 }
Sean Callanan95e5c632012-02-17 00:53:45 +0000446 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000447
Sean Callanan95e5c632012-02-17 00:53:45 +0000448 bool
Greg Clayton3faf47c2013-03-28 23:42:53 +0000449 IsValid () const
Sean Callanan95e5c632012-02-17 00:53:45 +0000450 {
451 return m_is_valid;
452 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000453
Greg Clayton3faf47c2013-03-28 23:42:53 +0000454 bool
455 UsingFileAddress() const
456 {
457 return m_using_file_addr;
458 }
Sean Callanan95e5c632012-02-17 00:53:45 +0000459 size_t
Greg Clayton3faf47c2013-03-28 23:42:53 +0000460 GetByteSize () const
Sean Callanan95e5c632012-02-17 00:53:45 +0000461 {
462 return m_opcode.GetByteSize();
463 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000464
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000465 std::shared_ptr<DisassemblerLLVMC>
466 GetDisassembler ()
Greg Clayton3faf47c2013-03-28 23:42:53 +0000467 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000468 return m_disasm_wp.lock();
Greg Clayton3faf47c2013-03-28 23:42:53 +0000469 }
Sean Callanan95e5c632012-02-17 00:53:45 +0000470protected:
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000471
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000472 std::weak_ptr<DisassemblerLLVMC> m_disasm_wp;
Sean Callanan7725a462012-03-02 23:22:53 +0000473 LazyBool m_does_branch;
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +0000474 LazyBool m_has_delay_slot;
Greg Clayton3faf47c2013-03-28 23:42:53 +0000475 bool m_is_valid;
476 bool m_using_file_addr;
Sean Callanan95e5c632012-02-17 00:53:45 +0000477};
478
Jaydeep Patil501a7812015-07-16 03:51:55 +0000479DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, const char *cpu, const char *features_str, unsigned flavor, DisassemblerLLVMC &owner):
Jim Ingham0f063ba2013-03-02 00:26:47 +0000480 m_is_valid(true)
481{
482 std::string Error;
483 const llvm::Target *curr_target = llvm::TargetRegistry::lookupTarget(triple, Error);
484 if (!curr_target)
485 {
486 m_is_valid = false;
487 return;
488 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000489
Jim Ingham0f063ba2013-03-02 00:26:47 +0000490 m_instr_info_ap.reset(curr_target->createMCInstrInfo());
491 m_reg_info_ap.reset (curr_target->createMCRegInfo(triple));
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000492
Mohit K. Bhakkad276a9302015-06-18 06:03:27 +0000493 m_subtarget_info_ap.reset(curr_target->createMCSubtargetInfo(triple, cpu,
Jim Ingham0f063ba2013-03-02 00:26:47 +0000494 features_str));
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000495
Jean-Daniel Dupasc6f26f82013-12-29 20:17:26 +0000496 std::unique_ptr<llvm::MCRegisterInfo> reg_info(curr_target->createMCRegInfo(triple));
497 m_asm_info_ap.reset(curr_target->createMCAsmInfo(*reg_info, triple));
Sylvestre Ledru7a89d6f2013-05-13 13:41:13 +0000498
Jim Ingham0f063ba2013-03-02 00:26:47 +0000499 if (m_instr_info_ap.get() == NULL || m_reg_info_ap.get() == NULL || m_subtarget_info_ap.get() == NULL || m_asm_info_ap.get() == NULL)
500 {
Matt Kopec787d1622013-03-12 17:45:38 +0000501 m_is_valid = false;
Jim Ingham0f063ba2013-03-02 00:26:47 +0000502 return;
503 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000504
Bill Wendlingd63d0a82013-06-18 07:50:43 +0000505 m_context_ap.reset(new llvm::MCContext(m_asm_info_ap.get(), m_reg_info_ap.get(), 0));
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000506
Sylvestre Ledru5ac35ae2014-04-15 12:07:25 +0000507 m_disasm_ap.reset(curr_target->createMCDisassembler(*m_subtarget_info_ap.get(), *m_context_ap.get()));
Ashok Thirumurthi78059352013-05-24 15:55:54 +0000508 if (m_disasm_ap.get() && m_context_ap.get())
Jim Ingham0f063ba2013-03-02 00:26:47 +0000509 {
Ahmed Charles8f926ad2014-03-07 04:45:22 +0000510 std::unique_ptr<llvm::MCRelocationInfo> RelInfo(curr_target->createMCRelocationInfo(triple, *m_context_ap.get()));
Ashok Thirumurthi78059352013-05-24 15:55:54 +0000511 if (!RelInfo)
512 {
513 m_is_valid = false;
514 return;
515 }
Jason Molenda64a68d62014-05-17 00:27:44 +0000516 std::unique_ptr<llvm::MCSymbolizer> symbolizer_up(curr_target->createMCSymbolizer(triple, NULL,
517 DisassemblerLLVMC::SymbolLookupCallback,
518 (void *) &owner,
Chandler Carruth215d9392015-01-19 03:07:25 +0000519 m_context_ap.get(), std::move(RelInfo)));
Jason Molenda64a68d62014-05-17 00:27:44 +0000520 m_disasm_ap->setSymbolizer(std::move(symbolizer_up));
Greg Clayton3434b572014-04-14 21:33:38 +0000521
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000522
Jim Ingham0f063ba2013-03-02 00:26:47 +0000523 unsigned asm_printer_variant;
524 if (flavor == ~0U)
525 asm_printer_variant = m_asm_info_ap->getAssemblerDialect();
526 else
527 {
528 asm_printer_variant = flavor;
529 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000530
Daniel Sanders32764b52015-09-15 16:33:17 +0000531 m_instr_printer_ap.reset(curr_target->createMCInstPrinter(llvm::Triple{triple},
Chaoren Lin2d6105c2015-03-31 00:59:13 +0000532 asm_printer_variant,
Jim Ingham0f063ba2013-03-02 00:26:47 +0000533 *m_asm_info_ap.get(),
534 *m_instr_info_ap.get(),
Chaoren Lin2d6105c2015-03-31 00:59:13 +0000535 *m_reg_info_ap.get()));
Jim Ingham0f063ba2013-03-02 00:26:47 +0000536 if (m_instr_printer_ap.get() == NULL)
537 {
538 m_disasm_ap.reset();
539 m_is_valid = false;
540 }
541 }
542 else
543 m_is_valid = false;
544}
545
Eugene Zelenko45a40142015-10-22 21:24:37 +0000546DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler() = default;
Eugene Zelenko8dd3fdb2015-10-21 01:42:15 +0000547
Jim Ingham0f063ba2013-03-02 00:26:47 +0000548uint64_t
Greg Clayton3faf47c2013-03-28 23:42:53 +0000549DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data,
550 size_t opcode_data_len,
551 lldb::addr_t pc,
552 llvm::MCInst &mc_inst)
Jim Ingham0f063ba2013-03-02 00:26:47 +0000553{
Rafael Espindola434df0a2014-11-12 02:04:31 +0000554 llvm::ArrayRef<uint8_t> data(opcode_data, opcode_data_len);
Jim Ingham0f063ba2013-03-02 00:26:47 +0000555 llvm::MCDisassembler::DecodeStatus status;
556
557 uint64_t new_inst_size;
558 status = m_disasm_ap->getInstruction(mc_inst,
559 new_inst_size,
Rafael Espindola434df0a2014-11-12 02:04:31 +0000560 data,
Jim Ingham0f063ba2013-03-02 00:26:47 +0000561 pc,
562 llvm::nulls(),
563 llvm::nulls());
564 if (status == llvm::MCDisassembler::Success)
565 return new_inst_size;
566 else
567 return 0;
568}
569
Sean Callanand38f4d22015-12-11 19:10:04 +0000570void
Greg Clayton3faf47c2013-03-28 23:42:53 +0000571DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst (llvm::MCInst &mc_inst,
Sean Callanand38f4d22015-12-11 19:10:04 +0000572 std::string &inst_string,
573 std::string &comments_string)
Jim Ingham0f063ba2013-03-02 00:26:47 +0000574{
Sean Callanand38f4d22015-12-11 19:10:04 +0000575 llvm::raw_string_ostream inst_stream(inst_string);
576 llvm::raw_string_ostream comments_stream(comments_string);
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000577
Sean Callanand38f4d22015-12-11 19:10:04 +0000578 m_instr_printer_ap->setCommentStream(comments_stream);
579 m_instr_printer_ap->printInst (&mc_inst, inst_stream, llvm::StringRef(), *m_subtarget_info_ap);
580 m_instr_printer_ap->setCommentStream(llvm::nulls());
581 comments_stream.flush();
582
583 static std::string g_newlines("\r\n");
584
585 for (size_t newline_pos = 0; (newline_pos = comments_string.find_first_of(g_newlines, newline_pos)) != comments_string.npos; /**/)
586 {
587 comments_string.replace(comments_string.begin() + newline_pos, comments_string.begin() + newline_pos + 1, 1, ' ');
588 }
Jim Ingham0f063ba2013-03-02 00:26:47 +0000589}
590
Daniel Malead79ae052013-08-07 21:54:09 +0000591void
592DisassemblerLLVMC::LLVMCDisassembler::SetStyle (bool use_hex_immed, HexImmediateStyle hex_style)
593{
594 m_instr_printer_ap->setPrintImmHex(use_hex_immed);
595 switch(hex_style)
596 {
Oleksiy Vyalov37ff6c42015-06-08 17:10:27 +0000597 case eHexStyleC: m_instr_printer_ap->setPrintHexStyle(llvm::HexStyle::C); break;
598 case eHexStyleAsm: m_instr_printer_ap->setPrintHexStyle(llvm::HexStyle::Asm); break;
Daniel Malead79ae052013-08-07 21:54:09 +0000599 }
600}
601
Jim Ingham0f063ba2013-03-02 00:26:47 +0000602bool
603DisassemblerLLVMC::LLVMCDisassembler::CanBranch (llvm::MCInst &mc_inst)
604{
605 return m_instr_info_ap->get(mc_inst.getOpcode()).mayAffectControlFlow(mc_inst, *m_reg_info_ap.get());
606}
607
608bool
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +0000609DisassemblerLLVMC::LLVMCDisassembler::HasDelaySlot (llvm::MCInst &mc_inst)
610{
611 return m_instr_info_ap->get(mc_inst.getOpcode()).hasDelaySlot();
612}
613
Jim Ingham0f063ba2013-03-02 00:26:47 +0000614DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_string) :
615 Disassembler(arch, flavor_string),
Greg Claytonba812f42012-05-10 02:52:23 +0000616 m_exe_ctx (NULL),
Greg Clayton3faf47c2013-03-28 23:42:53 +0000617 m_inst (NULL),
618 m_data_from_file (false)
Sean Callanan95e5c632012-02-17 00:53:45 +0000619{
Jim Ingham0f063ba2013-03-02 00:26:47 +0000620 if (!FlavorValidForArchSpec (arch, m_flavor.c_str()))
621 {
622 m_flavor.assign("default");
623 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000624
Jim Ingham0f063ba2013-03-02 00:26:47 +0000625 unsigned flavor = ~0U;
Tamas Berghammerff417ef2015-09-02 13:24:50 +0000626 llvm::Triple triple = arch.GetTriple();
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000627
Jim Ingham0f063ba2013-03-02 00:26:47 +0000628 // So far the only supported flavor is "intel" on x86. The base class will set this
629 // correctly coming in.
Tamas Berghammerff417ef2015-09-02 13:24:50 +0000630 if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64)
Jim Ingham0f063ba2013-03-02 00:26:47 +0000631 {
632 if (m_flavor == "intel")
633 {
634 flavor = 1;
635 }
636 else if (m_flavor == "att")
637 {
638 flavor = 0;
639 }
640 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000641
Jason Molenda01aa5342013-07-22 22:11:53 +0000642 ArchSpec thumb_arch(arch);
Tamas Berghammerc17469b2015-09-02 13:31:18 +0000643 if (triple.getArch() == llvm::Triple::arm)
Sean Callanan95e5c632012-02-17 00:53:45 +0000644 {
Greg Claytona80ea122013-05-03 01:05:04 +0000645 std::string thumb_arch_name (thumb_arch.GetTriple().getArchName().str());
646 // Replace "arm" with "thumb" so we get all thumb variants correct
647 if (thumb_arch_name.size() > 3)
648 {
649 thumb_arch_name.erase(0,3);
650 thumb_arch_name.insert(0, "thumb");
651 }
652 else
653 {
Tamas Berghammer45dbfa12016-03-02 12:42:43 +0000654 thumb_arch_name = "thumbv8.2a";
Greg Claytona80ea122013-05-03 01:05:04 +0000655 }
656 thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name.c_str()));
Jason Molenda01aa5342013-07-22 22:11:53 +0000657 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000658
Tamas Berghammerff417ef2015-09-02 13:24:50 +0000659 // If no sub architecture specified then use the most recent arm architecture so the
660 // disassembler will return all instruction. Without it we will see a lot of unknow opcode
661 // in case the code uses instructions which are not available in the oldest arm version
662 // (used when no sub architecture is specified)
663 if (triple.getArch() == llvm::Triple::arm && triple.getSubArch() == llvm::Triple::NoSubArch)
Tamas Berghammer45dbfa12016-03-02 12:42:43 +0000664 triple.setArchName("armv8.2a");
Tamas Berghammerff417ef2015-09-02 13:24:50 +0000665
666 const char *triple_str = triple.getTriple().c_str();
667
Jason Molenda583b1a82016-04-05 05:01:30 +0000668 // ARM Cortex M0-M7 devices only execute thumb instructions
669 if (arch.IsAlwaysThumbInstructions ())
Jason Molenda01aa5342013-07-22 22:11:53 +0000670 {
Tamas Berghammerff417ef2015-09-02 13:24:50 +0000671 triple_str = thumb_arch.GetTriple().getTriple().c_str();
Jason Molenda01aa5342013-07-22 22:11:53 +0000672 }
673
Mohit K. Bhakkad276a9302015-06-18 06:03:27 +0000674 const char *cpu = "";
675
676 switch (arch.GetCore())
677 {
678 case ArchSpec::eCore_mips32:
679 case ArchSpec::eCore_mips32el:
680 cpu = "mips32"; break;
681 case ArchSpec::eCore_mips32r2:
682 case ArchSpec::eCore_mips32r2el:
683 cpu = "mips32r2"; break;
684 case ArchSpec::eCore_mips32r3:
685 case ArchSpec::eCore_mips32r3el:
686 cpu = "mips32r3"; break;
687 case ArchSpec::eCore_mips32r5:
688 case ArchSpec::eCore_mips32r5el:
689 cpu = "mips32r5"; break;
690 case ArchSpec::eCore_mips32r6:
691 case ArchSpec::eCore_mips32r6el:
692 cpu = "mips32r6"; break;
693 case ArchSpec::eCore_mips64:
694 case ArchSpec::eCore_mips64el:
695 cpu = "mips64"; break;
696 case ArchSpec::eCore_mips64r2:
697 case ArchSpec::eCore_mips64r2el:
698 cpu = "mips64r2"; break;
699 case ArchSpec::eCore_mips64r3:
700 case ArchSpec::eCore_mips64r3el:
701 cpu = "mips64r3"; break;
702 case ArchSpec::eCore_mips64r5:
703 case ArchSpec::eCore_mips64r5el:
704 cpu = "mips64r5"; break;
705 case ArchSpec::eCore_mips64r6:
706 case ArchSpec::eCore_mips64r6el:
707 cpu = "mips64r6"; break;
708 default:
709 cpu = ""; break;
710 }
Jaydeep Patil501a7812015-07-16 03:51:55 +0000711
712 std::string features_str = "";
Tamas Berghammerff417ef2015-09-02 13:24:50 +0000713 if (triple.getArch() == llvm::Triple::mips || triple.getArch() == llvm::Triple::mipsel
714 || triple.getArch() == llvm::Triple::mips64 || triple.getArch() == llvm::Triple::mips64el)
Jaydeep Patil501a7812015-07-16 03:51:55 +0000715 {
716 uint32_t arch_flags = arch.GetFlags ();
717 if (arch_flags & ArchSpec::eMIPSAse_msa)
718 features_str += "+msa,";
719 if (arch_flags & ArchSpec::eMIPSAse_dsp)
720 features_str += "+dsp,";
721 if (arch_flags & ArchSpec::eMIPSAse_dspr2)
722 features_str += "+dspr2,";
Jaydeep Patil501a7812015-07-16 03:51:55 +0000723 }
Mohit K. Bhakkad276a9302015-06-18 06:03:27 +0000724
Tamas Berghammerff417ef2015-09-02 13:24:50 +0000725 m_disasm_ap.reset (new LLVMCDisassembler(triple_str, cpu, features_str.c_str(), flavor, *this));
Jason Molenda01aa5342013-07-22 22:11:53 +0000726 if (!m_disasm_ap->IsValid())
727 {
728 // We use m_disasm_ap.get() to tell whether we are valid or not, so if this isn't good for some reason,
729 // we reset it, and then we won't be valid and FindPlugin will fail and we won't get used.
730 m_disasm_ap.reset();
731 }
732
Jaydeep Patil44d07fc2015-09-22 06:36:56 +0000733 llvm::Triple::ArchType llvm_arch = triple.getArch();
734
Jason Molenda01aa5342013-07-22 22:11:53 +0000735 // For arm CPUs that can execute arm or thumb instructions, also create a thumb instruction disassembler.
Jaydeep Patil44d07fc2015-09-22 06:36:56 +0000736 if (llvm_arch == llvm::Triple::arm)
Jason Molenda01aa5342013-07-22 22:11:53 +0000737 {
Greg Claytonba812f42012-05-10 02:52:23 +0000738 std::string thumb_triple(thumb_arch.GetTriple().getTriple());
Jaydeep Patil501a7812015-07-16 03:51:55 +0000739 m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), "", "", flavor, *this));
Jim Ingham0f063ba2013-03-02 00:26:47 +0000740 if (!m_alternate_disasm_ap->IsValid())
741 {
742 m_disasm_ap.reset();
743 m_alternate_disasm_ap.reset();
744 }
Sean Callanan95e5c632012-02-17 00:53:45 +0000745 }
Jaydeep Patil44d07fc2015-09-22 06:36:56 +0000746 else if (llvm_arch == llvm::Triple::mips
747 || llvm_arch == llvm::Triple::mipsel
748 || llvm_arch == llvm::Triple::mips64
749 || llvm_arch == llvm::Triple::mips64el)
750 {
751 /* Create alternate disassembler for MIPS16 and microMIPS */
752 uint32_t arch_flags = arch.GetFlags ();
753 if (arch_flags & ArchSpec::eMIPSAse_mips16)
754 features_str += "+mips16,";
755 else if (arch_flags & ArchSpec::eMIPSAse_micromips)
756 features_str += "+micromips,";
757
758 m_alternate_disasm_ap.reset(new LLVMCDisassembler (triple_str, cpu, features_str.c_str(), flavor, *this));
759 if (!m_alternate_disasm_ap->IsValid())
760 {
761 m_disasm_ap.reset();
762 m_alternate_disasm_ap.reset();
763 }
764 }
Sean Callanan95e5c632012-02-17 00:53:45 +0000765}
766
Eugene Zelenko45a40142015-10-22 21:24:37 +0000767DisassemblerLLVMC::~DisassemblerLLVMC() = default;
768
769Disassembler *
770DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor)
Eugene Zelenko8dd3fdb2015-10-21 01:42:15 +0000771{
Eugene Zelenko45a40142015-10-22 21:24:37 +0000772 if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch)
773 {
774 std::unique_ptr<DisassemblerLLVMC> disasm_ap (new DisassemblerLLVMC(arch, flavor));
775
776 if (disasm_ap.get() && disasm_ap->IsValid())
777 return disasm_ap.release();
778 }
779 return NULL;
Eugene Zelenko8dd3fdb2015-10-21 01:42:15 +0000780}
781
Sean Callanan95e5c632012-02-17 00:53:45 +0000782size_t
783DisassemblerLLVMC::DecodeInstructions (const Address &base_addr,
784 const DataExtractor& data,
Greg Claytonc7bece562013-01-25 18:06:21 +0000785 lldb::offset_t data_offset,
786 size_t num_instructions,
Greg Clayton3faf47c2013-03-28 23:42:53 +0000787 bool append,
788 bool data_from_file)
Sean Callanan95e5c632012-02-17 00:53:45 +0000789{
790 if (!append)
791 m_instruction_list.Clear();
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000792
Sean Callanan95e5c632012-02-17 00:53:45 +0000793 if (!IsValid())
794 return 0;
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000795
Greg Clayton3faf47c2013-03-28 23:42:53 +0000796 m_data_from_file = data_from_file;
Sean Callanan95e5c632012-02-17 00:53:45 +0000797 uint32_t data_cursor = data_offset;
Greg Claytonba812f42012-05-10 02:52:23 +0000798 const size_t data_byte_size = data.GetByteSize();
Sean Callanan95e5c632012-02-17 00:53:45 +0000799 uint32_t instructions_parsed = 0;
Greg Claytonba812f42012-05-10 02:52:23 +0000800 Address inst_addr(base_addr);
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000801
Greg Claytonba812f42012-05-10 02:52:23 +0000802 while (data_cursor < data_byte_size && instructions_parsed < num_instructions)
Sean Callanan95e5c632012-02-17 00:53:45 +0000803 {
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000804
Greg Claytonba812f42012-05-10 02:52:23 +0000805 AddressClass address_class = eAddressClassCode;
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000806
Jim Ingham0f063ba2013-03-02 00:26:47 +0000807 if (m_alternate_disasm_ap.get() != NULL)
Greg Claytonba812f42012-05-10 02:52:23 +0000808 address_class = inst_addr.GetAddressClass ();
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000809
Sean Callanan95e5c632012-02-17 00:53:45 +0000810 InstructionSP inst_sp(new InstructionLLVMC(*this,
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000811 inst_addr,
Sean Callanan95e5c632012-02-17 00:53:45 +0000812 address_class));
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000813
Sean Callanan95e5c632012-02-17 00:53:45 +0000814 if (!inst_sp)
Greg Claytonba812f42012-05-10 02:52:23 +0000815 break;
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000816
Sean Callanan95e5c632012-02-17 00:53:45 +0000817 uint32_t inst_size = inst_sp->Decode(*this, data, data_cursor);
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000818
Greg Claytonba812f42012-05-10 02:52:23 +0000819 if (inst_size == 0)
820 break;
821
Sean Callanan95e5c632012-02-17 00:53:45 +0000822 m_instruction_list.Append(inst_sp);
Sean Callanan95e5c632012-02-17 00:53:45 +0000823 data_cursor += inst_size;
Greg Claytonba812f42012-05-10 02:52:23 +0000824 inst_addr.Slide(inst_size);
Sean Callanan95e5c632012-02-17 00:53:45 +0000825 instructions_parsed++;
826 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000827
Sean Callanan95e5c632012-02-17 00:53:45 +0000828 return data_cursor - data_offset;
829}
830
831void
832DisassemblerLLVMC::Initialize()
833{
834 PluginManager::RegisterPlugin (GetPluginNameStatic(),
Jason Molendaa3329782014-03-29 18:54:20 +0000835 "Disassembler that uses LLVM MC to disassemble i386, x86_64, ARM, and ARM64.",
Sean Callanan95e5c632012-02-17 00:53:45 +0000836 CreateInstance);
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000837
Sean Callanan95e5c632012-02-17 00:53:45 +0000838 llvm::InitializeAllTargetInfos();
839 llvm::InitializeAllTargetMCs();
840 llvm::InitializeAllAsmParsers();
841 llvm::InitializeAllDisassemblers();
842}
843
844void
845DisassemblerLLVMC::Terminate()
846{
847 PluginManager::UnregisterPlugin (CreateInstance);
848}
849
850
Greg Clayton57abc5d2013-05-10 21:47:16 +0000851ConstString
Sean Callanan95e5c632012-02-17 00:53:45 +0000852DisassemblerLLVMC::GetPluginNameStatic()
853{
Greg Clayton57abc5d2013-05-10 21:47:16 +0000854 static ConstString g_name("llvm-mc");
855 return g_name;
Sean Callanan95e5c632012-02-17 00:53:45 +0000856}
857
Greg Claytonba812f42012-05-10 02:52:23 +0000858int DisassemblerLLVMC::OpInfoCallback (void *disassembler,
859 uint64_t pc,
860 uint64_t offset,
861 uint64_t size,
862 int tag_type,
863 void *tag_bug)
Sean Callanan95e5c632012-02-17 00:53:45 +0000864{
Greg Claytonba812f42012-05-10 02:52:23 +0000865 return static_cast<DisassemblerLLVMC*>(disassembler)->OpInfo (pc,
866 offset,
867 size,
868 tag_type,
869 tag_bug);
Sean Callanan95e5c632012-02-17 00:53:45 +0000870}
871
Greg Claytonba812f42012-05-10 02:52:23 +0000872const char *DisassemblerLLVMC::SymbolLookupCallback (void *disassembler,
873 uint64_t value,
874 uint64_t *type,
875 uint64_t pc,
876 const char **name)
Sean Callanan95e5c632012-02-17 00:53:45 +0000877{
Greg Claytonba812f42012-05-10 02:52:23 +0000878 return static_cast<DisassemblerLLVMC*>(disassembler)->SymbolLookup(value,
879 type,
880 pc,
881 name);
Sean Callanan95e5c632012-02-17 00:53:45 +0000882}
883
Eugene Zelenko45a40142015-10-22 21:24:37 +0000884bool
885DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor)
886{
887 llvm::Triple triple = arch.GetTriple();
888 if (flavor == NULL || strcmp (flavor, "default") == 0)
889 return true;
890
891 if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64)
892 {
893 if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0)
894 return true;
895 else
896 return false;
897 }
898 else
899 return false;
900}
901
Sean Callanan95e5c632012-02-17 00:53:45 +0000902int DisassemblerLLVMC::OpInfo (uint64_t PC,
903 uint64_t Offset,
904 uint64_t Size,
Greg Claytonba812f42012-05-10 02:52:23 +0000905 int tag_type,
906 void *tag_bug)
Sean Callanan95e5c632012-02-17 00:53:45 +0000907{
Greg Claytonba812f42012-05-10 02:52:23 +0000908 switch (tag_type)
Sean Callanan95e5c632012-02-17 00:53:45 +0000909 {
910 default:
911 break;
912 case 1:
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000913 memset (tag_bug, 0, sizeof(::LLVMOpInfo1));
Sean Callanan95e5c632012-02-17 00:53:45 +0000914 break;
915 }
916 return 0;
917}
918
Greg Claytonba812f42012-05-10 02:52:23 +0000919const char *DisassemblerLLVMC::SymbolLookup (uint64_t value,
920 uint64_t *type_ptr,
921 uint64_t pc,
922 const char **name)
Sean Callanan95e5c632012-02-17 00:53:45 +0000923{
Greg Claytonba812f42012-05-10 02:52:23 +0000924 if (*type_ptr)
925 {
926 if (m_exe_ctx && m_inst)
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000927 {
Greg Claytonba812f42012-05-10 02:52:23 +0000928 //std::string remove_this_prior_to_checkin;
Greg Claytonba812f42012-05-10 02:52:23 +0000929 Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : NULL;
Greg Clayton3faf47c2013-03-28 23:42:53 +0000930 Address value_so_addr;
Jason Molendac980fa92015-02-13 23:24:21 +0000931 Address pc_so_addr;
Greg Clayton3faf47c2013-03-28 23:42:53 +0000932 if (m_inst->UsingFileAddress())
Greg Claytonba812f42012-05-10 02:52:23 +0000933 {
934 ModuleSP module_sp(m_inst->GetAddress().GetModule());
935 if (module_sp)
Jason Molendac980fa92015-02-13 23:24:21 +0000936 {
Greg Clayton3faf47c2013-03-28 23:42:53 +0000937 module_sp->ResolveFileAddress(value, value_so_addr);
Jason Molendac980fa92015-02-13 23:24:21 +0000938 module_sp->ResolveFileAddress(pc, pc_so_addr);
939 }
Greg Claytonba812f42012-05-10 02:52:23 +0000940 }
Greg Clayton3faf47c2013-03-28 23:42:53 +0000941 else if (target && !target->GetSectionLoadList().IsEmpty())
942 {
943 target->GetSectionLoadList().ResolveLoadAddress(value, value_so_addr);
Jason Molendac980fa92015-02-13 23:24:21 +0000944 target->GetSectionLoadList().ResolveLoadAddress(pc, pc_so_addr);
945 }
946
947 SymbolContext sym_ctx;
948 const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
949 if (pc_so_addr.IsValid() && pc_so_addr.GetModule())
950 {
951 pc_so_addr.GetModule()->ResolveSymbolContextForAddress (pc_so_addr, resolve_scope, sym_ctx);
Greg Clayton3faf47c2013-03-28 23:42:53 +0000952 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000953
Greg Clayton3faf47c2013-03-28 23:42:53 +0000954 if (value_so_addr.IsValid() && value_so_addr.GetSection())
Sean Callanan95e5c632012-02-17 00:53:45 +0000955 {
Sean Callanan95e5c632012-02-17 00:53:45 +0000956 StreamString ss;
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000957
Jason Molendac980fa92015-02-13 23:24:21 +0000958 bool format_omitting_current_func_name = false;
959 if (sym_ctx.symbol || sym_ctx.function)
960 {
961 AddressRange range;
962 if (sym_ctx.GetAddressRange (resolve_scope, 0, false, range)
963 && range.GetBaseAddress().IsValid()
964 && range.ContainsLoadAddress (value_so_addr, target))
965 {
966 format_omitting_current_func_name = true;
967 }
968 }
969
970 // If the "value" address (the target address we're symbolicating)
971 // is inside the same SymbolContext as the current instruction pc
972 // (pc_so_addr), don't print the full function name - just print it
973 // with DumpStyleNoFunctionName style, e.g. "<+36>".
974 if (format_omitting_current_func_name)
975 {
976 value_so_addr.Dump (&ss,
977 target,
978 Address::DumpStyleNoFunctionName,
979 Address::DumpStyleSectionNameOffset);
980 }
981 else
982 {
983 value_so_addr.Dump (&ss,
984 target,
985 Address::DumpStyleResolvedDescriptionNoFunctionArguments,
986 Address::DumpStyleSectionNameOffset);
987 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000988
Sean Callanan745af462012-03-22 20:04:23 +0000989 if (!ss.GetString().empty())
Greg Claytonba812f42012-05-10 02:52:23 +0000990 {
Jason Molendaaff1b352014-10-10 23:07:36 +0000991 // If Address::Dump returned a multi-line description, most commonly seen when we
992 // have multiple levels of inlined functions at an address, only show the first line.
993 std::string &str(ss.GetString());
994 size_t first_eol_char = str.find_first_of ("\r\n");
995 if (first_eol_char != std::string::npos)
996 {
997 str.erase (first_eol_char);
998 }
Greg Claytonba812f42012-05-10 02:52:23 +0000999 m_inst->AppendComment(ss.GetString());
1000 }
Sean Callanan95e5c632012-02-17 00:53:45 +00001001 }
1002 }
1003 }
Greg Claytonba812f42012-05-10 02:52:23 +00001004
1005 *type_ptr = LLVMDisassembler_ReferenceType_InOut_None;
1006 *name = NULL;
1007 return NULL;
Sean Callanan95e5c632012-02-17 00:53:45 +00001008}
1009
1010//------------------------------------------------------------------
1011// PluginInterface protocol
1012//------------------------------------------------------------------
Greg Clayton57abc5d2013-05-10 21:47:16 +00001013ConstString
Sean Callanan95e5c632012-02-17 00:53:45 +00001014DisassemblerLLVMC::GetPluginName()
1015{
Sean Callanan95e5c632012-02-17 00:53:45 +00001016 return GetPluginNameStatic();
1017}
1018
1019uint32_t
1020DisassemblerLLVMC::GetPluginVersion()
1021{
1022 return 1;
1023}