blob: 61a57ef3fcdd872bd0ea90718e254fec3073f3a4 [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"
Sean Callanan4740a732016-09-06 04:48:36 +000034#include "lldb/Core/Log.h"
Greg Clayton1f746072012-08-29 21:13:06 +000035#include "lldb/Core/Module.h"
Sean Callanan95e5c632012-02-17 00:53:45 +000036#include "lldb/Core/Stream.h"
37#include "lldb/Symbol/SymbolContext.h"
38#include "lldb/Target/ExecutionContext.h"
39#include "lldb/Target/Process.h"
40#include "lldb/Target/RegisterContext.h"
Greg Claytond5944cd2013-12-06 01:12:00 +000041#include "lldb/Target/SectionLoadList.h"
Sean Callanan95e5c632012-02-17 00:53:45 +000042#include "lldb/Target/Target.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000043#include "lldb/Target/StackFrame.h"
Sean Callanan95e5c632012-02-17 00:53:45 +000044
Virgile Bellob2f1fb22013-08-23 12:44:05 +000045#include "lldb/Core/RegularExpression.h"
Sean Callanan95e5c632012-02-17 00:53:45 +000046
47using namespace lldb;
48using namespace lldb_private;
49
50class InstructionLLVMC : public lldb_private::Instruction
51{
52public:
53 InstructionLLVMC (DisassemblerLLVMC &disasm,
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +000054 const lldb_private::Address &address,
Greg Claytonc8e0c242012-04-13 00:07:34 +000055 AddressClass addr_class) :
Greg Clayton3faf47c2013-03-28 23:42:53 +000056 Instruction (address, addr_class),
Greg Clayton4a9d83a2016-06-07 22:56:40 +000057 m_disasm_wp (std::static_pointer_cast<DisassemblerLLVMC>(disasm.shared_from_this())),
Greg Clayton3faf47c2013-03-28 23:42:53 +000058 m_does_branch (eLazyBoolCalculate),
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +000059 m_has_delay_slot (eLazyBoolCalculate),
Sean Callanan4740a732016-09-06 04:48:36 +000060 m_is_call (eLazyBoolCalculate),
Greg Clayton3faf47c2013-03-28 23:42:53 +000061 m_is_valid (false),
62 m_using_file_addr (false)
Sean Callanan95e5c632012-02-17 00:53:45 +000063 {
64 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +000065
Eugene Zelenko45a40142015-10-22 21:24:37 +000066 ~InstructionLLVMC() override = default;
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +000067
Eugene Zelenko45a40142015-10-22 21:24:37 +000068 bool
69 DoesBranch() override
Sean Callanan95e5c632012-02-17 00:53:45 +000070 {
Jim Ingham32ce20c2013-03-13 01:55:16 +000071 if (m_does_branch == eLazyBoolCalculate)
72 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +000073 std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
74 if (disasm_sp)
Jim Ingham32ce20c2013-03-13 01:55:16 +000075 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +000076 disasm_sp->Lock(this, NULL);
77 DataExtractor data;
78 if (m_opcode.GetData(data))
Jim Ingham32ce20c2013-03-13 01:55:16 +000079 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +000080 bool is_alternate_isa;
81 lldb::addr_t pc = m_address.GetFileAddress();
82
83 DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
84 const uint8_t *opcode_data = data.GetDataStart();
85 const size_t opcode_data_len = data.GetByteSize();
86 llvm::MCInst inst;
87 const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
88 opcode_data_len,
89 pc,
90 inst);
91 // Be conservative, if we didn't understand the instruction, say it might branch...
92 if (inst_size == 0)
Jim Ingham32ce20c2013-03-13 01:55:16 +000093 m_does_branch = eLazyBoolYes;
94 else
Greg Clayton4a9d83a2016-06-07 22:56:40 +000095 {
96 const bool can_branch = mc_disasm_ptr->CanBranch(inst);
97 if (can_branch)
98 m_does_branch = eLazyBoolYes;
99 else
100 m_does_branch = eLazyBoolNo;
101 }
Jim Ingham32ce20c2013-03-13 01:55:16 +0000102 }
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000103 disasm_sp->Unlock();
Jim Ingham32ce20c2013-03-13 01:55:16 +0000104 }
Jim Ingham32ce20c2013-03-13 01:55:16 +0000105 }
Sean Callanan7725a462012-03-02 23:22:53 +0000106 return m_does_branch == eLazyBoolYes;
Sean Callanan95e5c632012-02-17 00:53:45 +0000107 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000108
Eugene Zelenko45a40142015-10-22 21:24:37 +0000109 bool
110 HasDelaySlot() override
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +0000111 {
112 if (m_has_delay_slot == eLazyBoolCalculate)
113 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000114 std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
115 if (disasm_sp)
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +0000116 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000117 disasm_sp->Lock(this, NULL);
118 DataExtractor data;
119 if (m_opcode.GetData(data))
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +0000120 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000121 bool is_alternate_isa;
122 lldb::addr_t pc = m_address.GetFileAddress();
123
124 DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
125 const uint8_t *opcode_data = data.GetDataStart();
126 const size_t opcode_data_len = data.GetByteSize();
127 llvm::MCInst inst;
128 const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
129 opcode_data_len,
130 pc,
131 inst);
132 // if we didn't understand the instruction, say it doesn't have a delay slot...
133 if (inst_size == 0)
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +0000134 m_has_delay_slot = eLazyBoolNo;
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000135 else
136 {
137 const bool has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst);
138 if (has_delay_slot)
139 m_has_delay_slot = eLazyBoolYes;
140 else
141 m_has_delay_slot = eLazyBoolNo;
142 }
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +0000143 }
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000144 disasm_sp->Unlock();
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +0000145 }
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +0000146 }
147 return m_has_delay_slot == eLazyBoolYes;
148 }
149
Jim Ingham32ce20c2013-03-13 01:55:16 +0000150 DisassemblerLLVMC::LLVMCDisassembler *
151 GetDisasmToUse (bool &is_alternate_isa)
152 {
Jim Ingham32ce20c2013-03-13 01:55:16 +0000153 is_alternate_isa = false;
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000154 std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
155 if (disasm_sp)
Jim Ingham32ce20c2013-03-13 01:55:16 +0000156 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000157 if (disasm_sp->m_alternate_disasm_ap.get() != NULL)
Jim Ingham32ce20c2013-03-13 01:55:16 +0000158 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000159 const AddressClass address_class = GetAddressClass ();
160
161 if (address_class == eAddressClassCodeAlternateISA)
162 {
163 is_alternate_isa = true;
164 return disasm_sp->m_alternate_disasm_ap.get();
165 }
Jim Ingham32ce20c2013-03-13 01:55:16 +0000166 }
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000167 return disasm_sp->m_disasm_ap.get();
Jim Ingham32ce20c2013-03-13 01:55:16 +0000168 }
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000169 return nullptr;
Jim Ingham32ce20c2013-03-13 01:55:16 +0000170 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000171
Eugene Zelenko45a40142015-10-22 21:24:37 +0000172 size_t
173 Decode(const lldb_private::Disassembler &disassembler,
174 const lldb_private::DataExtractor &data,
175 lldb::offset_t data_offset) override
Sean Callanan95e5c632012-02-17 00:53:45 +0000176 {
Greg Claytonba812f42012-05-10 02:52:23 +0000177 // All we have to do is read the opcode which can be easy for some
Michael Sartaincc791bb2013-07-11 16:40:56 +0000178 // architectures
Greg Claytonba812f42012-05-10 02:52:23 +0000179 bool got_op = false;
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000180 std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
181 if (disasm_sp)
Greg Claytonba812f42012-05-10 02:52:23 +0000182 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000183 const ArchSpec &arch = disasm_sp->GetArchitecture();
184 const lldb::ByteOrder byte_order = data.GetByteOrder();
Ed Maste90359962013-12-09 19:45:33 +0000185
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000186 const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize();
187 const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize();
188 if (min_op_byte_size == max_op_byte_size)
Greg Claytonba812f42012-05-10 02:52:23 +0000189 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000190 // Fixed size instructions, just read that amount of data.
191 if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size))
192 return false;
Greg Claytonba812f42012-05-10 02:52:23 +0000193
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000194 switch (min_op_byte_size)
Greg Claytonba812f42012-05-10 02:52:23 +0000195 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000196 case 1:
197 m_opcode.SetOpcode8 (data.GetU8 (&data_offset), byte_order);
198 got_op = true;
199 break;
200
201 case 2:
202 m_opcode.SetOpcode16 (data.GetU16 (&data_offset), byte_order);
203 got_op = true;
204 break;
205
206 case 4:
207 m_opcode.SetOpcode32 (data.GetU32 (&data_offset), byte_order);
208 got_op = true;
209 break;
210
211 case 8:
212 m_opcode.SetOpcode64 (data.GetU64 (&data_offset), byte_order);
213 got_op = true;
214 break;
215
216 default:
217 m_opcode.SetOpcodeBytes(data.PeekData(data_offset, min_op_byte_size), min_op_byte_size);
218 got_op = true;
219 break;
220 }
221 }
222 if (!got_op)
223 {
224 bool is_alternate_isa = false;
225 DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
226
227 const llvm::Triple::ArchType machine = arch.GetMachine();
228 if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb)
229 {
230 if (machine == llvm::Triple::thumb || is_alternate_isa)
Greg Claytonba812f42012-05-10 02:52:23 +0000231 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000232 uint32_t thumb_opcode = data.GetU16(&data_offset);
233 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
234 {
235 m_opcode.SetOpcode16 (thumb_opcode, byte_order);
236 m_is_valid = true;
237 }
238 else
239 {
240 thumb_opcode <<= 16;
241 thumb_opcode |= data.GetU16(&data_offset);
242 m_opcode.SetOpcode16_2 (thumb_opcode, byte_order);
243 m_is_valid = true;
244 }
Greg Claytonba812f42012-05-10 02:52:23 +0000245 }
246 else
247 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000248 m_opcode.SetOpcode32 (data.GetU32(&data_offset), byte_order);
Greg Claytonba812f42012-05-10 02:52:23 +0000249 m_is_valid = true;
250 }
251 }
252 else
253 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000254 // The opcode isn't evenly sized, so we need to actually use the llvm
255 // disassembler to parse it and get the size.
256 uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (data_offset, 1));
257 const size_t opcode_data_len = data.BytesLeft(data_offset);
258 const addr_t pc = m_address.GetFileAddress();
259 llvm::MCInst inst;
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000260
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000261 disasm_sp->Lock(this, NULL);
262 const size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data,
263 opcode_data_len,
264 pc,
265 inst);
266 disasm_sp->Unlock();
267 if (inst_size == 0)
268 m_opcode.Clear();
269 else
270 {
271 m_opcode.SetOpcodeBytes(opcode_data, inst_size);
272 m_is_valid = true;
273 }
Greg Claytonba812f42012-05-10 02:52:23 +0000274 }
275 }
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000276 return m_opcode.GetByteSize();
Greg Claytonba812f42012-05-10 02:52:23 +0000277 }
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000278 return 0;
Sean Callanan95e5c632012-02-17 00:53:45 +0000279 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000280
Sean Callanan95e5c632012-02-17 00:53:45 +0000281 void
Greg Claytonba812f42012-05-10 02:52:23 +0000282 AppendComment (std::string &description)
Sean Callanan95e5c632012-02-17 00:53:45 +0000283 {
Greg Claytonba812f42012-05-10 02:52:23 +0000284 if (m_comment.empty())
285 m_comment.swap (description);
Sean Callanan95e5c632012-02-17 00:53:45 +0000286 else
Greg Claytonba812f42012-05-10 02:52:23 +0000287 {
288 m_comment.append(", ");
289 m_comment.append(description);
290 }
Sean Callanan95e5c632012-02-17 00:53:45 +0000291 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000292
Eugene Zelenko45a40142015-10-22 21:24:37 +0000293 void
294 CalculateMnemonicOperandsAndComment(const lldb_private::ExecutionContext *exe_ctx) override
Sean Callanan95e5c632012-02-17 00:53:45 +0000295 {
Greg Claytonba812f42012-05-10 02:52:23 +0000296 DataExtractor data;
297 const AddressClass address_class = GetAddressClass ();
298
Sean Callanancd4ae1a2012-08-07 01:44:58 +0000299 if (m_opcode.GetData(data))
Greg Claytonba812f42012-05-10 02:52:23 +0000300 {
Sean Callanand38f4d22015-12-11 19:10:04 +0000301 std::string out_string;
302 std::string comment_string;
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000303
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000304 std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
305 if (disasm_sp)
Greg Claytonba812f42012-05-10 02:52:23 +0000306 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000307 DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr;
Daniel Malead79ae052013-08-07 21:54:09 +0000308
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000309 if (address_class == eAddressClassCodeAlternateISA)
310 mc_disasm_ptr = disasm_sp->m_alternate_disasm_ap.get();
311 else
312 mc_disasm_ptr = disasm_sp->m_disasm_ap.get();
313
314 lldb::addr_t pc = m_address.GetFileAddress();
315 m_using_file_addr = true;
316
317 const bool data_from_file = disasm_sp->m_data_from_file;
318 bool use_hex_immediates = true;
319 Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC;
320
321 if (exe_ctx)
322 {
323 Target *target = exe_ctx->GetTargetPtr();
324 if (target)
Greg Clayton3faf47c2013-03-28 23:42:53 +0000325 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000326 use_hex_immediates = target->GetUseHexImmediates();
327 hex_style = target->GetHexImmediateStyle();
328
329 if (!data_from_file)
Greg Clayton3faf47c2013-03-28 23:42:53 +0000330 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000331 const lldb::addr_t load_addr = m_address.GetLoadAddress(target);
332 if (load_addr != LLDB_INVALID_ADDRESS)
333 {
334 pc = load_addr;
335 m_using_file_addr = false;
336 }
Greg Clayton3faf47c2013-03-28 23:42:53 +0000337 }
338 }
339 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000340
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000341 disasm_sp->Lock(this, exe_ctx);
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000342
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000343 const uint8_t *opcode_data = data.GetDataStart();
344 const size_t opcode_data_len = data.GetByteSize();
345 llvm::MCInst inst;
346 size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
347 opcode_data_len,
348 pc,
349 inst);
Daniel Malead79ae052013-08-07 21:54:09 +0000350
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000351 if (inst_size > 0)
Sean Callanand38f4d22015-12-11 19:10:04 +0000352 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000353 mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style);
354 mc_disasm_ptr->PrintMCInst(inst, out_string, comment_string);
355
356 if (!comment_string.empty())
357 {
358 AppendComment(comment_string);
359 }
Sean Callanand38f4d22015-12-11 19:10:04 +0000360 }
Daniel Malead79ae052013-08-07 21:54:09 +0000361
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000362 disasm_sp->Unlock();
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000363
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000364 if (inst_size == 0)
Greg Claytonba812f42012-05-10 02:52:23 +0000365 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000366 m_comment.assign ("unknown opcode");
367 inst_size = m_opcode.GetByteSize();
368 StreamString mnemonic_strm;
369 lldb::offset_t offset = 0;
370 lldb::ByteOrder byte_order = data.GetByteOrder();
371 switch (inst_size)
372 {
373 case 1:
374 {
375 const uint8_t uval8 = data.GetU8 (&offset);
376 m_opcode.SetOpcode8 (uval8, byte_order);
377 m_opcode_name.assign (".byte");
378 mnemonic_strm.Printf("0x%2.2x", uval8);
379 }
380 break;
381 case 2:
382 {
383 const uint16_t uval16 = data.GetU16(&offset);
384 m_opcode.SetOpcode16(uval16, byte_order);
385 m_opcode_name.assign (".short");
386 mnemonic_strm.Printf("0x%4.4x", uval16);
387 }
388 break;
389 case 4:
390 {
391 const uint32_t uval32 = data.GetU32(&offset);
392 m_opcode.SetOpcode32(uval32, byte_order);
393 m_opcode_name.assign (".long");
394 mnemonic_strm.Printf("0x%8.8x", uval32);
395 }
396 break;
397 case 8:
398 {
399 const uint64_t uval64 = data.GetU64(&offset);
400 m_opcode.SetOpcode64(uval64, byte_order);
401 m_opcode_name.assign (".quad");
402 mnemonic_strm.Printf("0x%16.16" PRIx64, uval64);
403 }
404 break;
405 default:
406 if (inst_size == 0)
Greg Claytonba812f42012-05-10 02:52:23 +0000407 return;
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000408 else
409 {
410 const uint8_t *bytes = data.PeekData(offset, inst_size);
411 if (bytes == NULL)
412 return;
413 m_opcode_name.assign (".byte");
414 m_opcode.SetOpcodeBytes(bytes, inst_size);
415 mnemonic_strm.Printf("0x%2.2x", bytes[0]);
416 for (uint32_t i=1; i<inst_size; ++i)
417 mnemonic_strm.Printf(" 0x%2.2x", bytes[i]);
418 }
419 break;
420 }
421 m_mnemonics.swap(mnemonic_strm.GetString());
422 return;
Greg Claytonba812f42012-05-10 02:52:23 +0000423 }
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000424 else
Greg Claytonba812f42012-05-10 02:52:23 +0000425 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000426 if (m_does_branch == eLazyBoolCalculate)
427 {
428 const bool can_branch = mc_disasm_ptr->CanBranch(inst);
429 if (can_branch)
430 m_does_branch = eLazyBoolYes;
431 else
432 m_does_branch = eLazyBoolNo;
Jim Ingham0f063ba2013-03-02 00:26:47 +0000433
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000434 }
Greg Claytonba812f42012-05-10 02:52:23 +0000435 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000436
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000437 static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?");
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000438
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000439 RegularExpression::Match matches(3);
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000440
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000441 if (s_regex.Execute(out_string.c_str(), &matches))
442 {
443 matches.GetMatchAtIndex(out_string.c_str(), 1, m_opcode_name);
444 matches.GetMatchAtIndex(out_string.c_str(), 2, m_mnemonics);
445 }
Greg Claytonba812f42012-05-10 02:52:23 +0000446 }
447 }
Sean Callanan95e5c632012-02-17 00:53:45 +0000448 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000449
Sean Callanan95e5c632012-02-17 00:53:45 +0000450 bool
Greg Clayton3faf47c2013-03-28 23:42:53 +0000451 IsValid () const
Sean Callanan95e5c632012-02-17 00:53:45 +0000452 {
453 return m_is_valid;
454 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000455
Greg Clayton3faf47c2013-03-28 23:42:53 +0000456 bool
457 UsingFileAddress() const
458 {
459 return m_using_file_addr;
460 }
Sean Callanan95e5c632012-02-17 00:53:45 +0000461 size_t
Greg Clayton3faf47c2013-03-28 23:42:53 +0000462 GetByteSize () const
Sean Callanan95e5c632012-02-17 00:53:45 +0000463 {
464 return m_opcode.GetByteSize();
465 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +0000466
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000467 std::shared_ptr<DisassemblerLLVMC>
468 GetDisassembler ()
Greg Clayton3faf47c2013-03-28 23:42:53 +0000469 {
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000470 return m_disasm_wp.lock();
Greg Clayton3faf47c2013-03-28 23:42:53 +0000471 }
Sean Callanan4740a732016-09-06 04:48:36 +0000472
473 static llvm::StringRef::const_iterator
474 ConsumeWhitespace(llvm::StringRef::const_iterator osi, llvm::StringRef::const_iterator ose)
475 {
476 while (osi != ose)
477 {
478 switch (*osi) {
479 default:
480 return osi;
481 case ' ': case '\t':
482 break;
483 }
484 ++osi;
485 }
486
487 return osi;
488 }
489
490 static std::pair<bool, llvm::StringRef::const_iterator>
491 ConsumeChar(llvm::StringRef::const_iterator osi, const char c, llvm::StringRef::const_iterator ose)
492 {
493 bool found = false;
494
495 osi = ConsumeWhitespace(osi, ose);
496 if (osi != ose && *osi == c)
497 {
498 found = true;
499 ++osi;
500 }
501
502 return std::make_pair(found, osi);
503 }
504
505 static std::pair<Operand, llvm::StringRef::const_iterator>
506 ParseRegisterName(llvm::StringRef::const_iterator osi, llvm::StringRef::const_iterator ose)
507 {
508 Operand ret;
509 ret.m_type = Operand::Type::Register;
510 std::string str;
511
512 osi = ConsumeWhitespace(osi, ose);
513
514 while (osi != ose)
515 {
516 if (*osi >= '0' && *osi <= '9')
517 {
518 if (str.empty())
519 {
520 return std::make_pair(Operand(), osi);
521 }
522 else
523 {
524 str.push_back(*osi);
525 }
526 }
527 else if (*osi >= 'a' && *osi <= 'z')
528 {
529 str.push_back(*osi);
530 }
531 else
532 {
533 switch (*osi)
534 {
535 default:
536 if (str.empty())
537 {
538 return std::make_pair(Operand(), osi);
539 }
540 else
541 {
542 ret.m_register = ConstString(str);
543 return std::make_pair(ret, osi);
544 }
545 case '%':
546 if (!str.empty())
547 {
548 return std::make_pair(Operand(), osi);
549 }
550 break;
551 }
552 }
553 ++osi;
554 }
555
556 ret.m_register = ConstString(str);
557 return std::make_pair(ret, osi);
558 }
559
560 static std::pair<Operand, llvm::StringRef::const_iterator>
561 ParseImmediate(llvm::StringRef::const_iterator osi, llvm::StringRef::const_iterator ose)
562 {
563 Operand ret;
564 ret.m_type = Operand::Type::Immediate;
565 std::string str;
566 bool is_hex = false;
567
568 osi = ConsumeWhitespace(osi, ose);
569
570 while (osi != ose)
571 {
572 if (*osi >= '0' && *osi <= '9')
573 {
574 str.push_back(*osi);
575 }
576 else if (*osi >= 'a' && *osi <= 'f')
577 {
578 if (is_hex)
579 {
580 str.push_back(*osi);
581 }
582 else
583 {
584 return std::make_pair(Operand(), osi);
585 }
586 }
587 else
588 {
589 switch (*osi)
590 {
591 default:
592 if (str.empty())
593 {
594 return std::make_pair(Operand(), osi);
595 }
596 else
597 {
598 ret.m_immediate = std::stoull(str, nullptr, 0);
599 return std::make_pair(ret, osi);
600 }
601 case 'x':
602 if (!str.compare("0"))
603 {
604 is_hex = true;
605 str.push_back(*osi);
606 }
607 else
608 {
609 return std::make_pair(Operand(), osi);
610 }
611 break;
612 case '#': case '$':
613 if (!str.empty())
614 {
615 return std::make_pair(Operand(), osi);
616 }
617 break;
618 case '-':
619 if (str.empty())
620 {
621 ret.m_negative = true;
622 }
623 else
624 {
625 return std::make_pair(Operand(), osi);
626 }
627 }
628 }
629 ++osi;
630 }
631
632 ret.m_immediate = std::stoull(str, nullptr, 0);
633 return std::make_pair(ret, osi);
634 }
635
636 // -0x5(%rax,%rax,2)
637 static std::pair<Operand, llvm::StringRef::const_iterator>
638 ParseIntelIndexedAccess (llvm::StringRef::const_iterator osi, llvm::StringRef::const_iterator ose)
639 {
640 std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator = ParseImmediate(osi, ose);
641 if (offset_and_iterator.first.IsValid())
642 {
643 osi = offset_and_iterator.second;
644 }
645
646 bool found = false;
647 std::tie(found, osi) = ConsumeChar(osi, '(', ose);
648 if (!found)
649 {
650 return std::make_pair(Operand(), osi);
651 }
652
653 std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = ParseRegisterName(osi, ose);
654 if (base_and_iterator.first.IsValid())
655 {
656 osi = base_and_iterator.second;
657 }
658 else
659 {
660 return std::make_pair(Operand(), osi);
661 }
662
663 std::tie(found, osi) = ConsumeChar(osi, ',', ose);
664 if (!found)
665 {
666 return std::make_pair(Operand(), osi);
667 }
668
669 std::pair<Operand, llvm::StringRef::const_iterator> index_and_iterator = ParseRegisterName(osi, ose);
670 if (index_and_iterator.first.IsValid())
671 {
672 osi = index_and_iterator.second;
673 }
674 else
675 {
676 return std::make_pair(Operand(), osi);
677 }
678
679 std::tie(found, osi) = ConsumeChar(osi, ',', ose);
680 if (!found)
681 {
682 return std::make_pair(Operand(), osi);
683 }
684
685 std::pair<Operand, llvm::StringRef::const_iterator> multiplier_and_iterator = ParseImmediate(osi, ose);
686 if (index_and_iterator.first.IsValid())
687 {
688 osi = index_and_iterator.second;
689 }
690 else
691 {
692 return std::make_pair(Operand(), osi);
693 }
694
695 std::tie(found, osi) = ConsumeChar(osi, ')', ose);
696 if (!found)
697 {
698 return std::make_pair(Operand(), osi);
699 }
700
701 Operand product;
702 product.m_type = Operand::Type::Product;
703 product.m_children.push_back(index_and_iterator.first);
704 product.m_children.push_back(multiplier_and_iterator.first);
705
706 Operand index;
707 index.m_type = Operand::Type::Sum;
708 index.m_children.push_back(base_and_iterator.first);
709 index.m_children.push_back(product);
710
711 if (offset_and_iterator.first.IsValid())
712 {
713 Operand offset;
714 offset.m_type = Operand::Type::Sum;
715 offset.m_children.push_back(offset_and_iterator.first);
716 offset.m_children.push_back(index);
717
718 Operand deref;
719 deref.m_type = Operand::Type::Dereference;
720 deref.m_children.push_back(offset);
721 return std::make_pair(deref, osi);
722 }
723 else
724 {
725 Operand deref;
726 deref.m_type = Operand::Type::Dereference;
727 deref.m_children.push_back(index);
728 return std::make_pair(deref, osi);
729 }
730 }
731
732 // -0x10(%rbp)
733 static std::pair<Operand, llvm::StringRef::const_iterator>
734 ParseIntelDerefAccess (llvm::StringRef::const_iterator osi, llvm::StringRef::const_iterator ose)
735 {
736 std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator = ParseImmediate(osi, ose);
737 if (offset_and_iterator.first.IsValid())
738 {
739 osi = offset_and_iterator.second;
740 }
741
742 bool found = false;
743 std::tie(found, osi) = ConsumeChar(osi, '(', ose);
744 if (!found)
745 {
746 return std::make_pair(Operand(), osi);
747 }
748
749 std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = ParseRegisterName(osi, ose);
750 if (base_and_iterator.first.IsValid())
751 {
752 osi = base_and_iterator.second;
753 }
754 else
755 {
756 return std::make_pair(Operand(), osi);
757 }
758
759 std::tie(found, osi) = ConsumeChar(osi, ')', ose);
760 if (!found)
761 {
762 return std::make_pair(Operand(), osi);
763 }
764
765 if (offset_and_iterator.first.IsValid())
766 {
767 Operand offset;
768 offset.m_type = Operand::Type::Sum;
769 offset.m_children.push_back(offset_and_iterator.first);
770 offset.m_children.push_back(base_and_iterator.first);
771
772 Operand deref;
773 deref.m_type = Operand::Type::Dereference;
774 deref.m_children.push_back(offset);
775 return std::make_pair(deref, osi);
776 }
777 else
778 {
779 Operand deref;
780 deref.m_type = Operand::Type::Dereference;
781 deref.m_children.push_back(base_and_iterator.first);
782 return std::make_pair(deref, osi);
783 }
784 }
785
786 // [sp, #8]!
787 static std::pair<Operand, llvm::StringRef::const_iterator>
788 ParseARMOffsetAccess (llvm::StringRef::const_iterator osi, llvm::StringRef::const_iterator ose)
789 {
790 bool found = false;
791 std::tie(found, osi) = ConsumeChar(osi, '[', ose);
792 if (!found)
793 {
794 return std::make_pair(Operand(), osi);
795 }
796
797 std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = ParseRegisterName(osi, ose);
798 if (base_and_iterator.first.IsValid())
799 {
800 osi = base_and_iterator.second;
801 }
802 else
803 {
804 return std::make_pair(Operand(), osi);
805 }
806
807 std::tie(found, osi) = ConsumeChar(osi, ',', ose);
808 if (!found)
809 {
810 return std::make_pair(Operand(), osi);
811 }
812
813 std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator = ParseImmediate(osi, ose);
814 if (offset_and_iterator.first.IsValid())
815 {
816 osi = offset_and_iterator.second;
817 }
818
819 std::tie(found, osi) = ConsumeChar(osi, ']', ose);
820 if (!found)
821 {
822 return std::make_pair(Operand(), osi);
823 }
824
825 Operand offset;
826 offset.m_type = Operand::Type::Sum;
827 offset.m_children.push_back(offset_and_iterator.first);
828 offset.m_children.push_back(base_and_iterator.first);
829
830 Operand deref;
831 deref.m_type = Operand::Type::Dereference;
832 deref.m_children.push_back(offset);
833 return std::make_pair(deref, osi);
834 }
835
836 // [sp]
837 static std::pair<Operand, llvm::StringRef::const_iterator>
838 ParseARMDerefAccess (llvm::StringRef::const_iterator osi, llvm::StringRef::const_iterator ose)
839 {
840 bool found = false;
841 std::tie(found, osi) = ConsumeChar(osi, '[', ose);
842 if (!found)
843 {
844 return std::make_pair(Operand(), osi);
845 }
846
847 std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = ParseRegisterName(osi, ose);
848 if (base_and_iterator.first.IsValid())
849 {
850 osi = base_and_iterator.second;
851 }
852 else
853 {
854 return std::make_pair(Operand(), osi);
855 }
856
857 std::tie(found, osi) = ConsumeChar(osi, ']', ose);
858 if (!found)
859 {
860 return std::make_pair(Operand(), osi);
861 }
862
863 Operand deref;
864 deref.m_type = Operand::Type::Dereference;
865 deref.m_children.push_back(base_and_iterator.first);
866 return std::make_pair(deref, osi);
867 }
868
869 static void
870 DumpOperand(const Operand &op, Stream &s)
871 {
872 switch (op.m_type)
873 {
874 case Operand::Type::Dereference:
875 s.PutCString("*");
876 DumpOperand(op.m_children[0], s);
877 break;
878 case Operand::Type::Immediate:
879 if (op.m_negative)
880 {
881 s.PutCString("-");
882 }
883 s.PutCString(std::to_string(op.m_immediate).c_str());
884 break;
885 case Operand::Type::Invalid:
886 s.PutCString("Invalid");
887 break;
888 case Operand::Type::Product:
889 s.PutCString("(");
890 DumpOperand(op.m_children[0], s);
891 s.PutCString("*");
892 DumpOperand(op.m_children[1], s);
893 s.PutCString(")");
894 break;
895 case Operand::Type::Register:
896 s.PutCString(op.m_register.AsCString());
897 break;
898 case Operand::Type::Sum:
899 s.PutCString("(");
900 DumpOperand(op.m_children[0], s);
901 s.PutCString("+");
902 DumpOperand(op.m_children[1], s);
903 s.PutCString(")");
904 break;
905 }
906 }
907
908 bool
909 ParseOperands (llvm::SmallVectorImpl<Instruction::Operand> &operands) override
910 {
911 const char *operands_string = GetOperands(nullptr);
912
913 if (!operands_string)
914 {
915 return false;
916 }
917
918 llvm::StringRef operands_ref(operands_string);
919
920 llvm::StringRef::const_iterator osi = operands_ref.begin();
921 llvm::StringRef::const_iterator ose = operands_ref.end();
922
923 while (osi != ose)
924 {
925 Operand operand;
926 llvm::StringRef::const_iterator iter;
927
928 if ((std::tie(operand, iter) = ParseIntelIndexedAccess(osi, ose), operand.IsValid()) ||
929 (std::tie(operand, iter) = ParseIntelDerefAccess(osi, ose), operand.IsValid()) ||
930 (std::tie(operand, iter) = ParseARMOffsetAccess(osi, ose), operand.IsValid()) ||
931 (std::tie(operand, iter) = ParseARMDerefAccess(osi, ose), operand.IsValid()) ||
932 (std::tie(operand, iter) = ParseRegisterName(osi, ose), operand.IsValid()) ||
933 (std::tie(operand, iter) = ParseImmediate(osi, ose), operand.IsValid()))
934 {
935 osi = iter;
936 operands.push_back(operand);
937 }
938 else
939 {
940 return false;
941 }
942
943 std::pair<bool, llvm::StringRef::const_iterator> found_and_iter = ConsumeChar(osi, ',', ose);
944 if (found_and_iter.first)
945 {
946 osi = found_and_iter.second;
947 }
948
949 osi = ConsumeWhitespace(osi, ose);
950 }
951
952 DisassemblerSP disasm_sp = m_disasm_wp.lock();
953
954 if (disasm_sp && operands.size() > 1)
955 {
956 // TODO tie this into the MC Disassembler's notion of clobbers.
957 switch (disasm_sp->GetArchitecture().GetMachine())
958 {
959 default:
960 break;
961 case llvm::Triple::x86:
962 case llvm::Triple::x86_64:
963 operands[operands.size() - 1].m_clobbered = true;
964 break;
965 case llvm::Triple::arm:
966 operands[0].m_clobbered = true;
967 break;
968 }
969 }
970
971 if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS))
972 {
973 StreamString ss;
974
975 ss.Printf("[%s] expands to %zu operands:\n", operands_string, operands.size());
976 for (const Operand &operand : operands) {
977 ss.PutCString(" ");
978 DumpOperand(operand, ss);
979 ss.PutCString("\n");
980 }
981
982 log->PutCString(ss.GetData());
983 }
984
985 return true;
986 }
987
988 bool
989 IsCall () override
990 {
991 if (m_is_call == eLazyBoolCalculate)
992 {
993 std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
994 if (disasm_sp)
995 {
996 disasm_sp->Lock(this, NULL);
997 DataExtractor data;
998 if (m_opcode.GetData(data))
999 {
1000 bool is_alternate_isa;
1001 lldb::addr_t pc = m_address.GetFileAddress();
1002
1003 DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
1004 const uint8_t *opcode_data = data.GetDataStart();
1005 const size_t opcode_data_len = data.GetByteSize();
1006 llvm::MCInst inst;
1007 const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
1008 opcode_data_len,
1009 pc,
1010 inst);
1011 if (inst_size == 0)
1012 {
1013 m_is_call = eLazyBoolNo;
1014 }
1015 else
1016 {
1017 if (mc_disasm_ptr->IsCall(inst))
1018 m_is_call = eLazyBoolYes;
1019 else
1020 m_is_call = eLazyBoolNo;
1021 }
1022 }
1023 disasm_sp->Unlock();
1024 }
1025 }
1026 return m_is_call == eLazyBoolYes;
1027 }
1028
Sean Callanan95e5c632012-02-17 00:53:45 +00001029protected:
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001030
Greg Clayton4a9d83a2016-06-07 22:56:40 +00001031 std::weak_ptr<DisassemblerLLVMC> m_disasm_wp;
Sean Callanan7725a462012-03-02 23:22:53 +00001032 LazyBool m_does_branch;
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +00001033 LazyBool m_has_delay_slot;
Sean Callanan4740a732016-09-06 04:48:36 +00001034 LazyBool m_is_call;
Greg Clayton3faf47c2013-03-28 23:42:53 +00001035 bool m_is_valid;
1036 bool m_using_file_addr;
Sean Callanan95e5c632012-02-17 00:53:45 +00001037};
1038
Jaydeep Patil501a7812015-07-16 03:51:55 +00001039DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, const char *cpu, const char *features_str, unsigned flavor, DisassemblerLLVMC &owner):
Jim Ingham0f063ba2013-03-02 00:26:47 +00001040 m_is_valid(true)
1041{
1042 std::string Error;
1043 const llvm::Target *curr_target = llvm::TargetRegistry::lookupTarget(triple, Error);
1044 if (!curr_target)
1045 {
1046 m_is_valid = false;
1047 return;
1048 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001049
Jim Ingham0f063ba2013-03-02 00:26:47 +00001050 m_instr_info_ap.reset(curr_target->createMCInstrInfo());
1051 m_reg_info_ap.reset (curr_target->createMCRegInfo(triple));
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001052
Mohit K. Bhakkad276a9302015-06-18 06:03:27 +00001053 m_subtarget_info_ap.reset(curr_target->createMCSubtargetInfo(triple, cpu,
Jim Ingham0f063ba2013-03-02 00:26:47 +00001054 features_str));
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001055
Jean-Daniel Dupasc6f26f82013-12-29 20:17:26 +00001056 std::unique_ptr<llvm::MCRegisterInfo> reg_info(curr_target->createMCRegInfo(triple));
1057 m_asm_info_ap.reset(curr_target->createMCAsmInfo(*reg_info, triple));
Sylvestre Ledru7a89d6f2013-05-13 13:41:13 +00001058
Jim Ingham0f063ba2013-03-02 00:26:47 +00001059 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)
1060 {
Matt Kopec787d1622013-03-12 17:45:38 +00001061 m_is_valid = false;
Jim Ingham0f063ba2013-03-02 00:26:47 +00001062 return;
1063 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001064
Bill Wendlingd63d0a82013-06-18 07:50:43 +00001065 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 +00001066
Sylvestre Ledru5ac35ae2014-04-15 12:07:25 +00001067 m_disasm_ap.reset(curr_target->createMCDisassembler(*m_subtarget_info_ap.get(), *m_context_ap.get()));
Ashok Thirumurthi78059352013-05-24 15:55:54 +00001068 if (m_disasm_ap.get() && m_context_ap.get())
Jim Ingham0f063ba2013-03-02 00:26:47 +00001069 {
Ahmed Charles8f926ad2014-03-07 04:45:22 +00001070 std::unique_ptr<llvm::MCRelocationInfo> RelInfo(curr_target->createMCRelocationInfo(triple, *m_context_ap.get()));
Ashok Thirumurthi78059352013-05-24 15:55:54 +00001071 if (!RelInfo)
1072 {
1073 m_is_valid = false;
1074 return;
1075 }
Jason Molenda64a68d62014-05-17 00:27:44 +00001076 std::unique_ptr<llvm::MCSymbolizer> symbolizer_up(curr_target->createMCSymbolizer(triple, NULL,
1077 DisassemblerLLVMC::SymbolLookupCallback,
1078 (void *) &owner,
Chandler Carruth215d9392015-01-19 03:07:25 +00001079 m_context_ap.get(), std::move(RelInfo)));
Jason Molenda64a68d62014-05-17 00:27:44 +00001080 m_disasm_ap->setSymbolizer(std::move(symbolizer_up));
Greg Clayton3434b572014-04-14 21:33:38 +00001081
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001082
Jim Ingham0f063ba2013-03-02 00:26:47 +00001083 unsigned asm_printer_variant;
1084 if (flavor == ~0U)
1085 asm_printer_variant = m_asm_info_ap->getAssemblerDialect();
1086 else
1087 {
1088 asm_printer_variant = flavor;
1089 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001090
Daniel Sanders32764b52015-09-15 16:33:17 +00001091 m_instr_printer_ap.reset(curr_target->createMCInstPrinter(llvm::Triple{triple},
Chaoren Lin2d6105c2015-03-31 00:59:13 +00001092 asm_printer_variant,
Jim Ingham0f063ba2013-03-02 00:26:47 +00001093 *m_asm_info_ap.get(),
1094 *m_instr_info_ap.get(),
Chaoren Lin2d6105c2015-03-31 00:59:13 +00001095 *m_reg_info_ap.get()));
Jim Ingham0f063ba2013-03-02 00:26:47 +00001096 if (m_instr_printer_ap.get() == NULL)
1097 {
1098 m_disasm_ap.reset();
1099 m_is_valid = false;
1100 }
1101 }
1102 else
1103 m_is_valid = false;
1104}
1105
Eugene Zelenko45a40142015-10-22 21:24:37 +00001106DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler() = default;
Eugene Zelenko8dd3fdb2015-10-21 01:42:15 +00001107
Jim Ingham0f063ba2013-03-02 00:26:47 +00001108uint64_t
Greg Clayton3faf47c2013-03-28 23:42:53 +00001109DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data,
1110 size_t opcode_data_len,
1111 lldb::addr_t pc,
1112 llvm::MCInst &mc_inst)
Jim Ingham0f063ba2013-03-02 00:26:47 +00001113{
Rafael Espindola434df0a2014-11-12 02:04:31 +00001114 llvm::ArrayRef<uint8_t> data(opcode_data, opcode_data_len);
Jim Ingham0f063ba2013-03-02 00:26:47 +00001115 llvm::MCDisassembler::DecodeStatus status;
1116
1117 uint64_t new_inst_size;
1118 status = m_disasm_ap->getInstruction(mc_inst,
1119 new_inst_size,
Rafael Espindola434df0a2014-11-12 02:04:31 +00001120 data,
Jim Ingham0f063ba2013-03-02 00:26:47 +00001121 pc,
1122 llvm::nulls(),
1123 llvm::nulls());
1124 if (status == llvm::MCDisassembler::Success)
1125 return new_inst_size;
1126 else
1127 return 0;
1128}
1129
Sean Callanand38f4d22015-12-11 19:10:04 +00001130void
Greg Clayton3faf47c2013-03-28 23:42:53 +00001131DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst (llvm::MCInst &mc_inst,
Sean Callanand38f4d22015-12-11 19:10:04 +00001132 std::string &inst_string,
1133 std::string &comments_string)
Jim Ingham0f063ba2013-03-02 00:26:47 +00001134{
Sean Callanand38f4d22015-12-11 19:10:04 +00001135 llvm::raw_string_ostream inst_stream(inst_string);
1136 llvm::raw_string_ostream comments_stream(comments_string);
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001137
Sean Callanand38f4d22015-12-11 19:10:04 +00001138 m_instr_printer_ap->setCommentStream(comments_stream);
1139 m_instr_printer_ap->printInst (&mc_inst, inst_stream, llvm::StringRef(), *m_subtarget_info_ap);
1140 m_instr_printer_ap->setCommentStream(llvm::nulls());
1141 comments_stream.flush();
1142
1143 static std::string g_newlines("\r\n");
1144
1145 for (size_t newline_pos = 0; (newline_pos = comments_string.find_first_of(g_newlines, newline_pos)) != comments_string.npos; /**/)
1146 {
1147 comments_string.replace(comments_string.begin() + newline_pos, comments_string.begin() + newline_pos + 1, 1, ' ');
1148 }
Jim Ingham0f063ba2013-03-02 00:26:47 +00001149}
1150
Daniel Malead79ae052013-08-07 21:54:09 +00001151void
1152DisassemblerLLVMC::LLVMCDisassembler::SetStyle (bool use_hex_immed, HexImmediateStyle hex_style)
1153{
1154 m_instr_printer_ap->setPrintImmHex(use_hex_immed);
1155 switch(hex_style)
1156 {
Oleksiy Vyalov37ff6c42015-06-08 17:10:27 +00001157 case eHexStyleC: m_instr_printer_ap->setPrintHexStyle(llvm::HexStyle::C); break;
1158 case eHexStyleAsm: m_instr_printer_ap->setPrintHexStyle(llvm::HexStyle::Asm); break;
Daniel Malead79ae052013-08-07 21:54:09 +00001159 }
1160}
1161
Jim Ingham0f063ba2013-03-02 00:26:47 +00001162bool
1163DisassemblerLLVMC::LLVMCDisassembler::CanBranch (llvm::MCInst &mc_inst)
1164{
1165 return m_instr_info_ap->get(mc_inst.getOpcode()).mayAffectControlFlow(mc_inst, *m_reg_info_ap.get());
1166}
1167
1168bool
Bhushan D. Attarde7f3daed2015-08-26 06:04:54 +00001169DisassemblerLLVMC::LLVMCDisassembler::HasDelaySlot (llvm::MCInst &mc_inst)
1170{
1171 return m_instr_info_ap->get(mc_inst.getOpcode()).hasDelaySlot();
1172}
1173
Sean Callanan4740a732016-09-06 04:48:36 +00001174bool
1175DisassemblerLLVMC::LLVMCDisassembler::IsCall (llvm::MCInst &mc_inst)
1176{
1177 return m_instr_info_ap->get(mc_inst.getOpcode()).isCall();
1178}
1179
Jim Ingham0f063ba2013-03-02 00:26:47 +00001180DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_string) :
1181 Disassembler(arch, flavor_string),
Greg Claytonba812f42012-05-10 02:52:23 +00001182 m_exe_ctx (NULL),
Greg Clayton3faf47c2013-03-28 23:42:53 +00001183 m_inst (NULL),
1184 m_data_from_file (false)
Sean Callanan95e5c632012-02-17 00:53:45 +00001185{
Jim Ingham0f063ba2013-03-02 00:26:47 +00001186 if (!FlavorValidForArchSpec (arch, m_flavor.c_str()))
1187 {
1188 m_flavor.assign("default");
1189 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001190
Jim Ingham0f063ba2013-03-02 00:26:47 +00001191 unsigned flavor = ~0U;
Tamas Berghammerff417ef2015-09-02 13:24:50 +00001192 llvm::Triple triple = arch.GetTriple();
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001193
Jim Ingham0f063ba2013-03-02 00:26:47 +00001194 // So far the only supported flavor is "intel" on x86. The base class will set this
1195 // correctly coming in.
Tamas Berghammerff417ef2015-09-02 13:24:50 +00001196 if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64)
Jim Ingham0f063ba2013-03-02 00:26:47 +00001197 {
1198 if (m_flavor == "intel")
1199 {
1200 flavor = 1;
1201 }
1202 else if (m_flavor == "att")
1203 {
1204 flavor = 0;
1205 }
1206 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001207
Jason Molenda01aa5342013-07-22 22:11:53 +00001208 ArchSpec thumb_arch(arch);
Tamas Berghammerc17469b2015-09-02 13:31:18 +00001209 if (triple.getArch() == llvm::Triple::arm)
Sean Callanan95e5c632012-02-17 00:53:45 +00001210 {
Greg Claytona80ea122013-05-03 01:05:04 +00001211 std::string thumb_arch_name (thumb_arch.GetTriple().getArchName().str());
1212 // Replace "arm" with "thumb" so we get all thumb variants correct
1213 if (thumb_arch_name.size() > 3)
1214 {
1215 thumb_arch_name.erase(0,3);
1216 thumb_arch_name.insert(0, "thumb");
1217 }
1218 else
1219 {
Tamas Berghammer45dbfa12016-03-02 12:42:43 +00001220 thumb_arch_name = "thumbv8.2a";
Greg Claytona80ea122013-05-03 01:05:04 +00001221 }
1222 thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name.c_str()));
Jason Molenda01aa5342013-07-22 22:11:53 +00001223 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001224
Tamas Berghammerff417ef2015-09-02 13:24:50 +00001225 // If no sub architecture specified then use the most recent arm architecture so the
1226 // disassembler will return all instruction. Without it we will see a lot of unknow opcode
1227 // in case the code uses instructions which are not available in the oldest arm version
1228 // (used when no sub architecture is specified)
1229 if (triple.getArch() == llvm::Triple::arm && triple.getSubArch() == llvm::Triple::NoSubArch)
Tamas Berghammer45dbfa12016-03-02 12:42:43 +00001230 triple.setArchName("armv8.2a");
Tamas Berghammerff417ef2015-09-02 13:24:50 +00001231
1232 const char *triple_str = triple.getTriple().c_str();
1233
Jason Molenda583b1a82016-04-05 05:01:30 +00001234 // ARM Cortex M0-M7 devices only execute thumb instructions
1235 if (arch.IsAlwaysThumbInstructions ())
Jason Molenda01aa5342013-07-22 22:11:53 +00001236 {
Tamas Berghammerff417ef2015-09-02 13:24:50 +00001237 triple_str = thumb_arch.GetTriple().getTriple().c_str();
Jason Molenda01aa5342013-07-22 22:11:53 +00001238 }
1239
Mohit K. Bhakkad276a9302015-06-18 06:03:27 +00001240 const char *cpu = "";
1241
1242 switch (arch.GetCore())
1243 {
1244 case ArchSpec::eCore_mips32:
1245 case ArchSpec::eCore_mips32el:
1246 cpu = "mips32"; break;
1247 case ArchSpec::eCore_mips32r2:
1248 case ArchSpec::eCore_mips32r2el:
1249 cpu = "mips32r2"; break;
1250 case ArchSpec::eCore_mips32r3:
1251 case ArchSpec::eCore_mips32r3el:
1252 cpu = "mips32r3"; break;
1253 case ArchSpec::eCore_mips32r5:
1254 case ArchSpec::eCore_mips32r5el:
1255 cpu = "mips32r5"; break;
1256 case ArchSpec::eCore_mips32r6:
1257 case ArchSpec::eCore_mips32r6el:
1258 cpu = "mips32r6"; break;
1259 case ArchSpec::eCore_mips64:
1260 case ArchSpec::eCore_mips64el:
1261 cpu = "mips64"; break;
1262 case ArchSpec::eCore_mips64r2:
1263 case ArchSpec::eCore_mips64r2el:
1264 cpu = "mips64r2"; break;
1265 case ArchSpec::eCore_mips64r3:
1266 case ArchSpec::eCore_mips64r3el:
1267 cpu = "mips64r3"; break;
1268 case ArchSpec::eCore_mips64r5:
1269 case ArchSpec::eCore_mips64r5el:
1270 cpu = "mips64r5"; break;
1271 case ArchSpec::eCore_mips64r6:
1272 case ArchSpec::eCore_mips64r6el:
1273 cpu = "mips64r6"; break;
1274 default:
1275 cpu = ""; break;
1276 }
Jaydeep Patil501a7812015-07-16 03:51:55 +00001277
1278 std::string features_str = "";
Tamas Berghammerff417ef2015-09-02 13:24:50 +00001279 if (triple.getArch() == llvm::Triple::mips || triple.getArch() == llvm::Triple::mipsel
1280 || triple.getArch() == llvm::Triple::mips64 || triple.getArch() == llvm::Triple::mips64el)
Jaydeep Patil501a7812015-07-16 03:51:55 +00001281 {
1282 uint32_t arch_flags = arch.GetFlags ();
1283 if (arch_flags & ArchSpec::eMIPSAse_msa)
1284 features_str += "+msa,";
1285 if (arch_flags & ArchSpec::eMIPSAse_dsp)
1286 features_str += "+dsp,";
1287 if (arch_flags & ArchSpec::eMIPSAse_dspr2)
1288 features_str += "+dspr2,";
Jaydeep Patil501a7812015-07-16 03:51:55 +00001289 }
Mohit K. Bhakkad276a9302015-06-18 06:03:27 +00001290
Tamas Berghammerff417ef2015-09-02 13:24:50 +00001291 m_disasm_ap.reset (new LLVMCDisassembler(triple_str, cpu, features_str.c_str(), flavor, *this));
Jason Molenda01aa5342013-07-22 22:11:53 +00001292 if (!m_disasm_ap->IsValid())
1293 {
1294 // We use m_disasm_ap.get() to tell whether we are valid or not, so if this isn't good for some reason,
1295 // we reset it, and then we won't be valid and FindPlugin will fail and we won't get used.
1296 m_disasm_ap.reset();
1297 }
1298
Jaydeep Patil44d07fc2015-09-22 06:36:56 +00001299 llvm::Triple::ArchType llvm_arch = triple.getArch();
1300
Jason Molenda01aa5342013-07-22 22:11:53 +00001301 // For arm CPUs that can execute arm or thumb instructions, also create a thumb instruction disassembler.
Jaydeep Patil44d07fc2015-09-22 06:36:56 +00001302 if (llvm_arch == llvm::Triple::arm)
Jason Molenda01aa5342013-07-22 22:11:53 +00001303 {
Greg Claytonba812f42012-05-10 02:52:23 +00001304 std::string thumb_triple(thumb_arch.GetTriple().getTriple());
Jaydeep Patil501a7812015-07-16 03:51:55 +00001305 m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), "", "", flavor, *this));
Jim Ingham0f063ba2013-03-02 00:26:47 +00001306 if (!m_alternate_disasm_ap->IsValid())
1307 {
1308 m_disasm_ap.reset();
1309 m_alternate_disasm_ap.reset();
1310 }
Sean Callanan95e5c632012-02-17 00:53:45 +00001311 }
Jaydeep Patil44d07fc2015-09-22 06:36:56 +00001312 else if (llvm_arch == llvm::Triple::mips
1313 || llvm_arch == llvm::Triple::mipsel
1314 || llvm_arch == llvm::Triple::mips64
1315 || llvm_arch == llvm::Triple::mips64el)
1316 {
1317 /* Create alternate disassembler for MIPS16 and microMIPS */
1318 uint32_t arch_flags = arch.GetFlags ();
1319 if (arch_flags & ArchSpec::eMIPSAse_mips16)
1320 features_str += "+mips16,";
1321 else if (arch_flags & ArchSpec::eMIPSAse_micromips)
1322 features_str += "+micromips,";
1323
1324 m_alternate_disasm_ap.reset(new LLVMCDisassembler (triple_str, cpu, features_str.c_str(), flavor, *this));
1325 if (!m_alternate_disasm_ap->IsValid())
1326 {
1327 m_disasm_ap.reset();
1328 m_alternate_disasm_ap.reset();
1329 }
1330 }
Sean Callanan95e5c632012-02-17 00:53:45 +00001331}
1332
Eugene Zelenko45a40142015-10-22 21:24:37 +00001333DisassemblerLLVMC::~DisassemblerLLVMC() = default;
1334
1335Disassembler *
1336DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor)
Eugene Zelenko8dd3fdb2015-10-21 01:42:15 +00001337{
Eugene Zelenko45a40142015-10-22 21:24:37 +00001338 if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch)
1339 {
1340 std::unique_ptr<DisassemblerLLVMC> disasm_ap (new DisassemblerLLVMC(arch, flavor));
1341
1342 if (disasm_ap.get() && disasm_ap->IsValid())
1343 return disasm_ap.release();
1344 }
1345 return NULL;
Eugene Zelenko8dd3fdb2015-10-21 01:42:15 +00001346}
1347
Sean Callanan95e5c632012-02-17 00:53:45 +00001348size_t
1349DisassemblerLLVMC::DecodeInstructions (const Address &base_addr,
1350 const DataExtractor& data,
Greg Claytonc7bece562013-01-25 18:06:21 +00001351 lldb::offset_t data_offset,
1352 size_t num_instructions,
Greg Clayton3faf47c2013-03-28 23:42:53 +00001353 bool append,
1354 bool data_from_file)
Sean Callanan95e5c632012-02-17 00:53:45 +00001355{
1356 if (!append)
1357 m_instruction_list.Clear();
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001358
Sean Callanan95e5c632012-02-17 00:53:45 +00001359 if (!IsValid())
1360 return 0;
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001361
Greg Clayton3faf47c2013-03-28 23:42:53 +00001362 m_data_from_file = data_from_file;
Sean Callanan95e5c632012-02-17 00:53:45 +00001363 uint32_t data_cursor = data_offset;
Greg Claytonba812f42012-05-10 02:52:23 +00001364 const size_t data_byte_size = data.GetByteSize();
Sean Callanan95e5c632012-02-17 00:53:45 +00001365 uint32_t instructions_parsed = 0;
Greg Claytonba812f42012-05-10 02:52:23 +00001366 Address inst_addr(base_addr);
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001367
Greg Claytonba812f42012-05-10 02:52:23 +00001368 while (data_cursor < data_byte_size && instructions_parsed < num_instructions)
Sean Callanan95e5c632012-02-17 00:53:45 +00001369 {
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001370
Greg Claytonba812f42012-05-10 02:52:23 +00001371 AddressClass address_class = eAddressClassCode;
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001372
Jim Ingham0f063ba2013-03-02 00:26:47 +00001373 if (m_alternate_disasm_ap.get() != NULL)
Greg Claytonba812f42012-05-10 02:52:23 +00001374 address_class = inst_addr.GetAddressClass ();
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001375
Sean Callanan95e5c632012-02-17 00:53:45 +00001376 InstructionSP inst_sp(new InstructionLLVMC(*this,
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001377 inst_addr,
Sean Callanan95e5c632012-02-17 00:53:45 +00001378 address_class));
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001379
Sean Callanan95e5c632012-02-17 00:53:45 +00001380 if (!inst_sp)
Greg Claytonba812f42012-05-10 02:52:23 +00001381 break;
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001382
Sean Callanan95e5c632012-02-17 00:53:45 +00001383 uint32_t inst_size = inst_sp->Decode(*this, data, data_cursor);
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001384
Greg Claytonba812f42012-05-10 02:52:23 +00001385 if (inst_size == 0)
1386 break;
1387
Sean Callanan95e5c632012-02-17 00:53:45 +00001388 m_instruction_list.Append(inst_sp);
Sean Callanan95e5c632012-02-17 00:53:45 +00001389 data_cursor += inst_size;
Greg Claytonba812f42012-05-10 02:52:23 +00001390 inst_addr.Slide(inst_size);
Sean Callanan95e5c632012-02-17 00:53:45 +00001391 instructions_parsed++;
1392 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001393
Sean Callanan95e5c632012-02-17 00:53:45 +00001394 return data_cursor - data_offset;
1395}
1396
1397void
1398DisassemblerLLVMC::Initialize()
1399{
1400 PluginManager::RegisterPlugin (GetPluginNameStatic(),
Jason Molendaa3329782014-03-29 18:54:20 +00001401 "Disassembler that uses LLVM MC to disassemble i386, x86_64, ARM, and ARM64.",
Sean Callanan95e5c632012-02-17 00:53:45 +00001402 CreateInstance);
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001403
Sean Callanan95e5c632012-02-17 00:53:45 +00001404 llvm::InitializeAllTargetInfos();
1405 llvm::InitializeAllTargetMCs();
1406 llvm::InitializeAllAsmParsers();
1407 llvm::InitializeAllDisassemblers();
1408}
1409
1410void
1411DisassemblerLLVMC::Terminate()
1412{
1413 PluginManager::UnregisterPlugin (CreateInstance);
1414}
1415
1416
Greg Clayton57abc5d2013-05-10 21:47:16 +00001417ConstString
Sean Callanan95e5c632012-02-17 00:53:45 +00001418DisassemblerLLVMC::GetPluginNameStatic()
1419{
Greg Clayton57abc5d2013-05-10 21:47:16 +00001420 static ConstString g_name("llvm-mc");
1421 return g_name;
Sean Callanan95e5c632012-02-17 00:53:45 +00001422}
1423
Greg Claytonba812f42012-05-10 02:52:23 +00001424int DisassemblerLLVMC::OpInfoCallback (void *disassembler,
1425 uint64_t pc,
1426 uint64_t offset,
1427 uint64_t size,
1428 int tag_type,
1429 void *tag_bug)
Sean Callanan95e5c632012-02-17 00:53:45 +00001430{
Greg Claytonba812f42012-05-10 02:52:23 +00001431 return static_cast<DisassemblerLLVMC*>(disassembler)->OpInfo (pc,
1432 offset,
1433 size,
1434 tag_type,
1435 tag_bug);
Sean Callanan95e5c632012-02-17 00:53:45 +00001436}
1437
Greg Claytonba812f42012-05-10 02:52:23 +00001438const char *DisassemblerLLVMC::SymbolLookupCallback (void *disassembler,
1439 uint64_t value,
1440 uint64_t *type,
1441 uint64_t pc,
1442 const char **name)
Sean Callanan95e5c632012-02-17 00:53:45 +00001443{
Greg Claytonba812f42012-05-10 02:52:23 +00001444 return static_cast<DisassemblerLLVMC*>(disassembler)->SymbolLookup(value,
1445 type,
1446 pc,
1447 name);
Sean Callanan95e5c632012-02-17 00:53:45 +00001448}
1449
Eugene Zelenko45a40142015-10-22 21:24:37 +00001450bool
1451DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor)
1452{
1453 llvm::Triple triple = arch.GetTriple();
1454 if (flavor == NULL || strcmp (flavor, "default") == 0)
1455 return true;
1456
1457 if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64)
1458 {
1459 if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0)
1460 return true;
1461 else
1462 return false;
1463 }
1464 else
1465 return false;
1466}
1467
Sean Callanan95e5c632012-02-17 00:53:45 +00001468int DisassemblerLLVMC::OpInfo (uint64_t PC,
1469 uint64_t Offset,
1470 uint64_t Size,
Greg Claytonba812f42012-05-10 02:52:23 +00001471 int tag_type,
1472 void *tag_bug)
Sean Callanan95e5c632012-02-17 00:53:45 +00001473{
Greg Claytonba812f42012-05-10 02:52:23 +00001474 switch (tag_type)
Sean Callanan95e5c632012-02-17 00:53:45 +00001475 {
1476 default:
1477 break;
1478 case 1:
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001479 memset (tag_bug, 0, sizeof(::LLVMOpInfo1));
Sean Callanan95e5c632012-02-17 00:53:45 +00001480 break;
1481 }
1482 return 0;
1483}
1484
Greg Claytonba812f42012-05-10 02:52:23 +00001485const char *DisassemblerLLVMC::SymbolLookup (uint64_t value,
1486 uint64_t *type_ptr,
1487 uint64_t pc,
1488 const char **name)
Sean Callanan95e5c632012-02-17 00:53:45 +00001489{
Greg Claytonba812f42012-05-10 02:52:23 +00001490 if (*type_ptr)
1491 {
1492 if (m_exe_ctx && m_inst)
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001493 {
Greg Claytonba812f42012-05-10 02:52:23 +00001494 //std::string remove_this_prior_to_checkin;
Greg Claytonba812f42012-05-10 02:52:23 +00001495 Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : NULL;
Greg Clayton3faf47c2013-03-28 23:42:53 +00001496 Address value_so_addr;
Jason Molendac980fa92015-02-13 23:24:21 +00001497 Address pc_so_addr;
Greg Clayton3faf47c2013-03-28 23:42:53 +00001498 if (m_inst->UsingFileAddress())
Greg Claytonba812f42012-05-10 02:52:23 +00001499 {
1500 ModuleSP module_sp(m_inst->GetAddress().GetModule());
1501 if (module_sp)
Jason Molendac980fa92015-02-13 23:24:21 +00001502 {
Greg Clayton3faf47c2013-03-28 23:42:53 +00001503 module_sp->ResolveFileAddress(value, value_so_addr);
Jason Molendac980fa92015-02-13 23:24:21 +00001504 module_sp->ResolveFileAddress(pc, pc_so_addr);
1505 }
Greg Claytonba812f42012-05-10 02:52:23 +00001506 }
Greg Clayton3faf47c2013-03-28 23:42:53 +00001507 else if (target && !target->GetSectionLoadList().IsEmpty())
1508 {
1509 target->GetSectionLoadList().ResolveLoadAddress(value, value_so_addr);
Jason Molendac980fa92015-02-13 23:24:21 +00001510 target->GetSectionLoadList().ResolveLoadAddress(pc, pc_so_addr);
1511 }
1512
1513 SymbolContext sym_ctx;
1514 const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
1515 if (pc_so_addr.IsValid() && pc_so_addr.GetModule())
1516 {
1517 pc_so_addr.GetModule()->ResolveSymbolContextForAddress (pc_so_addr, resolve_scope, sym_ctx);
Greg Clayton3faf47c2013-03-28 23:42:53 +00001518 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001519
Greg Clayton3faf47c2013-03-28 23:42:53 +00001520 if (value_so_addr.IsValid() && value_so_addr.GetSection())
Sean Callanan95e5c632012-02-17 00:53:45 +00001521 {
Sean Callanan95e5c632012-02-17 00:53:45 +00001522 StreamString ss;
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001523
Jason Molendac980fa92015-02-13 23:24:21 +00001524 bool format_omitting_current_func_name = false;
1525 if (sym_ctx.symbol || sym_ctx.function)
1526 {
1527 AddressRange range;
1528 if (sym_ctx.GetAddressRange (resolve_scope, 0, false, range)
1529 && range.GetBaseAddress().IsValid()
1530 && range.ContainsLoadAddress (value_so_addr, target))
1531 {
1532 format_omitting_current_func_name = true;
1533 }
1534 }
1535
1536 // If the "value" address (the target address we're symbolicating)
1537 // is inside the same SymbolContext as the current instruction pc
1538 // (pc_so_addr), don't print the full function name - just print it
1539 // with DumpStyleNoFunctionName style, e.g. "<+36>".
1540 if (format_omitting_current_func_name)
1541 {
1542 value_so_addr.Dump (&ss,
1543 target,
1544 Address::DumpStyleNoFunctionName,
1545 Address::DumpStyleSectionNameOffset);
1546 }
1547 else
1548 {
1549 value_so_addr.Dump (&ss,
1550 target,
1551 Address::DumpStyleResolvedDescriptionNoFunctionArguments,
1552 Address::DumpStyleSectionNameOffset);
1553 }
Sylvestre Ledrua3e4ceb2014-04-15 12:08:57 +00001554
Sean Callanan745af462012-03-22 20:04:23 +00001555 if (!ss.GetString().empty())
Greg Claytonba812f42012-05-10 02:52:23 +00001556 {
Jason Molendaaff1b352014-10-10 23:07:36 +00001557 // If Address::Dump returned a multi-line description, most commonly seen when we
1558 // have multiple levels of inlined functions at an address, only show the first line.
1559 std::string &str(ss.GetString());
1560 size_t first_eol_char = str.find_first_of ("\r\n");
1561 if (first_eol_char != std::string::npos)
1562 {
1563 str.erase (first_eol_char);
1564 }
Greg Claytonba812f42012-05-10 02:52:23 +00001565 m_inst->AppendComment(ss.GetString());
1566 }
Sean Callanan95e5c632012-02-17 00:53:45 +00001567 }
1568 }
1569 }
Greg Claytonba812f42012-05-10 02:52:23 +00001570
1571 *type_ptr = LLVMDisassembler_ReferenceType_InOut_None;
1572 *name = NULL;
1573 return NULL;
Sean Callanan95e5c632012-02-17 00:53:45 +00001574}
1575
1576//------------------------------------------------------------------
1577// PluginInterface protocol
1578//------------------------------------------------------------------
Greg Clayton57abc5d2013-05-10 21:47:16 +00001579ConstString
Sean Callanan95e5c632012-02-17 00:53:45 +00001580DisassemblerLLVMC::GetPluginName()
1581{
Sean Callanan95e5c632012-02-17 00:53:45 +00001582 return GetPluginNameStatic();
1583}
1584
1585uint32_t
1586DisassemblerLLVMC::GetPluginVersion()
1587{
1588 return 1;
1589}