blob: 5ddcd727bc0d65bf927cc90d3820a18e26d19940 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- DisassemblerLLVM.cpp ------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "DisassemblerLLVM.h"
11
12#include "llvm-c/EnhancedDisassembly.h"
13
14#include "lldb/Core/Address.h"
15#include "lldb/Core/DataExtractor.h"
16#include "lldb/Core/Disassembler.h"
17#include "lldb/Core/Module.h"
18#include "lldb/Core/PluginManager.h"
19#include "lldb/Core/Stream.h"
20#include "lldb/Core/StreamString.h"
21#include "lldb/Symbol/SymbolContext.h"
22
23#include "lldb/Target/ExecutionContext.h"
24#include "lldb/Target/Process.h"
25#include "lldb/Target/RegisterContext.h"
26#include "lldb/Target/Target.h"
27
Greg Claytonb01000f2011-01-17 03:46:26 +000028#include <assert.h>
Chris Lattner24943d22010-06-08 16:52:24 +000029
30using namespace lldb;
31using namespace lldb_private;
32
33
Greg Claytonb1888f22011-03-19 01:12:21 +000034static int
Greg Clayton7bc39082011-03-24 23:53:38 +000035DataExtractorByteReader (uint8_t *byte, uint64_t address, void *arg)
Chris Lattner24943d22010-06-08 16:52:24 +000036{
37 DataExtractor &extractor = *((DataExtractor *)arg);
38
39 if (extractor.ValidOffset(address))
40 {
41 *byte = *(extractor.GetDataStart() + address);
42 return 0;
43 }
44 else
45 {
46 return -1;
47 }
48}
49
50namespace {
51 struct RegisterReaderArg {
52 const lldb::addr_t instructionPointer;
53 const EDDisassemblerRef disassembler;
54
55 RegisterReaderArg(lldb::addr_t ip,
56 EDDisassemblerRef dis) :
57 instructionPointer(ip),
58 disassembler(dis)
59 {
60 }
61 };
62}
63
64static int IPRegisterReader(uint64_t *value, unsigned regID, void* arg)
65{
66 uint64_t instructionPointer = ((RegisterReaderArg*)arg)->instructionPointer;
67 EDDisassemblerRef disassembler = ((RegisterReaderArg*)arg)->disassembler;
68
Greg Claytonb1888f22011-03-19 01:12:21 +000069 if (EDRegisterIsProgramCounter(disassembler, regID)) {
Chris Lattner24943d22010-06-08 16:52:24 +000070 *value = instructionPointer;
71 return 0;
72 }
73
74 return -1;
75}
76
Caroline Ticeaf591802011-04-05 23:22:54 +000077InstructionLLVM::InstructionLLVM (const Address &addr,
78 AddressClass addr_class,
Greg Claytonabe0fed2011-04-18 08:33:37 +000079 EDDisassemblerRef disassembler,
80 bool force_raw) :
Greg Clayton889fbd02011-03-26 19:14:58 +000081 Instruction (addr, addr_class),
Greg Claytonabe0fed2011-04-18 08:33:37 +000082 m_disassembler (disassembler),
83 m_force_raw (force_raw)
Chris Lattner24943d22010-06-08 16:52:24 +000084{
85}
86
Caroline Ticeaf591802011-04-05 23:22:54 +000087InstructionLLVM::~InstructionLLVM()
Chris Lattner24943d22010-06-08 16:52:24 +000088{
89}
90
91static void
92PadString(Stream *s, const std::string &str, size_t width)
93{
94 int diff = width - str.length();
95
96 if (diff > 0)
97 s->Printf("%s%*.*s", str.c_str(), diff, diff, "");
98 else
99 s->Printf("%s ", str.c_str());
100}
101
102void
Caroline Ticeaf591802011-04-05 23:22:54 +0000103InstructionLLVM::Dump
Chris Lattner24943d22010-06-08 16:52:24 +0000104(
105 Stream *s,
Greg Clayton889fbd02011-03-26 19:14:58 +0000106 uint32_t max_opcode_byte_size,
Greg Clayton5c4c7462010-10-06 03:09:58 +0000107 bool show_address,
Greg Clayton149731c2011-03-25 18:03:16 +0000108 bool show_bytes,
Greg Clayton5c4c7462010-10-06 03:09:58 +0000109 const lldb_private::ExecutionContext* exe_ctx,
Chris Lattner24943d22010-06-08 16:52:24 +0000110 bool raw
111)
112{
113 const size_t opcodeColumnWidth = 7;
114 const size_t operandColumnWidth = 25;
115
Greg Clayton5c4c7462010-10-06 03:09:58 +0000116 ExecutionContextScope *exe_scope = NULL;
117 if (exe_ctx)
118 exe_scope = exe_ctx->GetBestExecutionContextScope();
119
Chris Lattner24943d22010-06-08 16:52:24 +0000120 // If we have an address, print it out
Sean Callanan91557b02010-11-10 01:38:28 +0000121 if (GetAddress().IsValid() && show_address)
Greg Clayton70436352010-06-30 23:03:03 +0000122 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000123 if (GetAddress().Dump (s,
124 exe_scope,
125 Address::DumpStyleLoadAddress,
126 Address::DumpStyleModuleWithFileAddress,
127 0))
Greg Clayton70436352010-06-30 23:03:03 +0000128 s->PutCString(": ");
129 }
Chris Lattner24943d22010-06-08 16:52:24 +0000130
131 // If we are supposed to show bytes, "bytes" will be non-NULL.
Greg Clayton149731c2011-03-25 18:03:16 +0000132 if (show_bytes)
Chris Lattner24943d22010-06-08 16:52:24 +0000133 {
Greg Clayton149731c2011-03-25 18:03:16 +0000134 if (m_opcode.GetType() == Opcode::eTypeBytes)
Chris Lattner24943d22010-06-08 16:52:24 +0000135 {
Greg Clayton149731c2011-03-25 18:03:16 +0000136 // x86_64 and i386 are the only ones that use bytes right now so
137 // pad out the byte dump to be able to always show 15 bytes (3 chars each)
138 // plus a space
Greg Clayton889fbd02011-03-26 19:14:58 +0000139 if (max_opcode_byte_size > 0)
140 m_opcode.Dump (s, max_opcode_byte_size * 3 + 1);
141 else
142 m_opcode.Dump (s, 15 * 3 + 1);
Greg Clayton149731c2011-03-25 18:03:16 +0000143 }
144 else
145 {
146 // Else, we have ARM which can show up to a uint32_t 0x00000000 (10 spaces)
147 // plus two for padding...
Greg Clayton889fbd02011-03-26 19:14:58 +0000148 if (max_opcode_byte_size > 0)
149 m_opcode.Dump (s, max_opcode_byte_size * 3 + 1);
150 else
151 m_opcode.Dump (s, 12);
Chris Lattner24943d22010-06-08 16:52:24 +0000152 }
153 }
154
Greg Claytonf15996e2011-04-07 22:46:35 +0000155 int numTokens = -1;
156
157 if (!raw)
Greg Claytonabe0fed2011-04-18 08:33:37 +0000158 raw = m_force_raw;
159
160 if (!raw)
Greg Claytonf15996e2011-04-07 22:46:35 +0000161 numTokens = EDNumTokens(m_inst);
Chris Lattner24943d22010-06-08 16:52:24 +0000162
163 int currentOpIndex = -1;
164
Greg Claytonf15996e2011-04-07 22:46:35 +0000165 bool printTokenized = false;
166
167 if (numTokens != -1 && !raw)
Sean Callanan8541f2f2010-07-23 02:19:15 +0000168 {
169 addr_t base_addr = LLDB_INVALID_ADDRESS;
Greg Claytonf15996e2011-04-07 22:46:35 +0000170
171 RegisterReaderArg rra(base_addr + EDInstByteSize(m_inst), m_disassembler);
172
Greg Clayton5c4c7462010-10-06 03:09:58 +0000173 if (exe_ctx && exe_ctx->target && !exe_ctx->target->GetSectionLoadList().IsEmpty())
174 base_addr = GetAddress().GetLoadAddress (exe_ctx->target);
Sean Callanan8541f2f2010-07-23 02:19:15 +0000175 if (base_addr == LLDB_INVALID_ADDRESS)
Greg Clayton5c4c7462010-10-06 03:09:58 +0000176 base_addr = GetAddress().GetFileAddress ();
Greg Claytonf15996e2011-04-07 22:46:35 +0000177
Chris Lattner24943d22010-06-08 16:52:24 +0000178 printTokenized = true;
179
180 // Handle the opcode column.
181
182 StreamString opcode;
183
184 int tokenIndex = 0;
185
186 EDTokenRef token;
187 const char *tokenStr;
188
189 if (EDGetToken(&token, m_inst, tokenIndex))
190 printTokenized = false;
191
192 if (!printTokenized || !EDTokenIsOpcode(token))
193 printTokenized = false;
194
195 if (!printTokenized || EDGetTokenString(&tokenStr, token))
196 printTokenized = false;
197
198 // Put the token string into our opcode string
199 opcode.PutCString(tokenStr);
200
201 // If anything follows, it probably starts with some whitespace. Skip it.
202
203 tokenIndex++;
204
205 if (printTokenized && tokenIndex < numTokens)
206 {
207 if(!printTokenized || EDGetToken(&token, m_inst, tokenIndex))
208 printTokenized = false;
209
210 if(!printTokenized || !EDTokenIsWhitespace(token))
211 printTokenized = false;
212 }
213
214 tokenIndex++;
215
216 // Handle the operands and the comment.
217
218 StreamString operands;
219 StreamString comment;
220
221 if (printTokenized)
222 {
223 bool show_token;
224
225 for (; tokenIndex < numTokens; ++tokenIndex)
226 {
227 if (EDGetToken(&token, m_inst, tokenIndex))
228 return;
229
230 if (raw)
231 {
232 show_token = true;
233 }
234 else
235 {
236 int operandIndex = EDOperandIndexForToken(token);
237
238 if (operandIndex >= 0)
239 {
240 if (operandIndex != currentOpIndex)
241 {
242 show_token = true;
243
244 currentOpIndex = operandIndex;
245 EDOperandRef operand;
246
247 if (!EDGetOperand(&operand, m_inst, currentOpIndex))
248 {
249 if (EDOperandIsMemory(operand))
250 {
251 uint64_t operand_value;
252
Greg Claytonf15996e2011-04-07 22:46:35 +0000253 if (!EDEvaluateOperand(&operand_value, operand, IPRegisterReader, &rra))
Chris Lattner24943d22010-06-08 16:52:24 +0000254 {
255 if (EDInstIsBranch(m_inst))
256 {
257 operands.Printf("0x%llx ", operand_value);
258 show_token = false;
259 }
260 else
261 {
262 // Put the address value into the comment
263 comment.Printf("0x%llx ", operand_value);
264 }
265
266 lldb_private::Address so_addr;
Greg Clayton5c4c7462010-10-06 03:09:58 +0000267 if (exe_ctx && exe_ctx->target && !exe_ctx->target->GetSectionLoadList().IsEmpty())
Chris Lattner24943d22010-06-08 16:52:24 +0000268 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000269 if (exe_ctx->target->GetSectionLoadList().ResolveLoadAddress (operand_value, so_addr))
Greg Claytoncf7f1ad2010-07-01 01:26:43 +0000270 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
Greg Clayton70436352010-06-30 23:03:03 +0000271 }
Greg Clayton5c4c7462010-10-06 03:09:58 +0000272 else
Greg Clayton70436352010-06-30 23:03:03 +0000273 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000274 Module *module = GetAddress().GetModule();
Greg Clayton70436352010-06-30 23:03:03 +0000275 if (module)
Chris Lattner24943d22010-06-08 16:52:24 +0000276 {
Greg Clayton70436352010-06-30 23:03:03 +0000277 if (module->ResolveFileAddress (operand_value, so_addr))
Greg Claytoncf7f1ad2010-07-01 01:26:43 +0000278 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
Chris Lattner24943d22010-06-08 16:52:24 +0000279 }
280 }
Greg Clayton70436352010-06-30 23:03:03 +0000281
Chris Lattner24943d22010-06-08 16:52:24 +0000282 } // EDEvaluateOperand
283 } // EDOperandIsMemory
284 } // EDGetOperand
285 } // operandIndex != currentOpIndex
286 } // operandIndex >= 0
287 } // else(raw)
288
289 if (show_token)
290 {
291 if(EDGetTokenString(&tokenStr, token))
292 {
293 printTokenized = false;
294 break;
295 }
296
297 operands.PutCString(tokenStr);
298 }
299 } // for (tokenIndex)
300
301 if (printTokenized)
302 {
303 if (operands.GetString().empty())
304 {
305 s->PutCString(opcode.GetString().c_str());
306 }
307 else
308 {
309 PadString(s, opcode.GetString(), opcodeColumnWidth);
310
311 if (comment.GetString().empty())
312 {
313 s->PutCString(operands.GetString().c_str());
314 }
315 else
316 {
317 PadString(s, operands.GetString(), operandColumnWidth);
318
319 s->PutCString("; ");
320 s->PutCString(comment.GetString().c_str());
321 } // else (comment.GetString().empty())
322 } // else (operands.GetString().empty())
323 } // printTokenized
324 } // for (tokenIndex)
325 } // numTokens != -1
326
327 if (!printTokenized)
328 {
329 const char *str;
330
331 if (EDGetInstString(&str, m_inst))
332 return;
333 else
Greg Claytonf15996e2011-04-07 22:46:35 +0000334 s->Write(str, strlen(str) - 1);
Chris Lattner24943d22010-06-08 16:52:24 +0000335 }
336}
337
338bool
Caroline Ticeaf591802011-04-05 23:22:54 +0000339InstructionLLVM::DoesBranch() const
Chris Lattner24943d22010-06-08 16:52:24 +0000340{
341 return EDInstIsBranch(m_inst);
342}
343
344size_t
Caroline Ticeaf591802011-04-05 23:22:54 +0000345InstructionLLVM::Decode (const Disassembler &disassembler,
346 const lldb_private::DataExtractor &data,
347 uint32_t data_offset)
Chris Lattner24943d22010-06-08 16:52:24 +0000348{
349 if (EDCreateInsts(&m_inst, 1, m_disassembler, DataExtractorByteReader, data_offset, (void*)(&data)))
Greg Clayton7bc39082011-03-24 23:53:38 +0000350 {
351 const int byte_size = EDInstByteSize(m_inst);
352 uint32_t offset = data_offset;
353 // Make a copy of the opcode in m_opcode
354 switch (disassembler.GetArchitecture().GetMachine())
355 {
356 case llvm::Triple::x86:
357 case llvm::Triple::x86_64:
358 m_opcode.SetOpcodeBytes (data.PeekData (data_offset, byte_size), byte_size);
359 break;
360
361 case llvm::Triple::arm:
Greg Clayton7bc39082011-03-24 23:53:38 +0000362 case llvm::Triple::thumb:
Greg Clayton149731c2011-03-25 18:03:16 +0000363 switch (byte_size)
364 {
365 case 2:
366 m_opcode.SetOpcode16 (data.GetU16 (&offset));
367 break;
368
369 case 4:
Greg Clayton7bc39082011-03-24 23:53:38 +0000370 m_opcode.SetOpcode32 (data.GetU32 (&offset));
Greg Clayton149731c2011-03-25 18:03:16 +0000371 break;
372
373 default:
374 assert (!"Invalid ARM opcode size");
375 break;
376 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000377 break;
378
379 default:
380 assert (!"This shouldn't happen since we control the architecture we allow DisassemblerLLVM to be created for");
381 break;
382 }
383 return byte_size;
384 }
Chris Lattner24943d22010-06-08 16:52:24 +0000385 else
386 return 0;
387}
388
Chris Lattner24943d22010-06-08 16:52:24 +0000389static inline EDAssemblySyntax_t
Greg Claytoncf015052010-06-11 03:25:34 +0000390SyntaxForArchSpec (const ArchSpec &arch)
Chris Lattner24943d22010-06-08 16:52:24 +0000391{
Greg Clayton940b1032011-02-23 00:35:02 +0000392 switch (arch.GetMachine ())
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000393 {
Greg Clayton940b1032011-02-23 00:35:02 +0000394 case llvm::Triple::x86:
395 case llvm::Triple::x86_64:
Chris Lattner24943d22010-06-08 16:52:24 +0000396 return kEDAssemblySyntaxX86ATT;
Sean Callanand151c8a2011-03-09 01:02:51 +0000397 case llvm::Triple::arm:
Greg Clayton889fbd02011-03-26 19:14:58 +0000398 case llvm::Triple::thumb:
Sean Callanand151c8a2011-03-09 01:02:51 +0000399 return kEDAssemblySyntaxARMUAL;
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000400 default:
401 break;
402 }
Greg Claytoncf015052010-06-11 03:25:34 +0000403 return (EDAssemblySyntax_t)0; // default
Chris Lattner24943d22010-06-08 16:52:24 +0000404}
405
406Disassembler *
407DisassemblerLLVM::CreateInstance(const ArchSpec &arch)
408{
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000409 std::auto_ptr<DisassemblerLLVM> disasm_ap (new DisassemblerLLVM(arch));
410
Caroline Tice080bf612011-04-05 18:46:00 +0000411 if (disasm_ap.get() && disasm_ap->IsValid())
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000412 return disasm_ap.release();
Chris Lattner24943d22010-06-08 16:52:24 +0000413
Greg Claytoncf015052010-06-11 03:25:34 +0000414 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000415}
416
417DisassemblerLLVM::DisassemblerLLVM(const ArchSpec &arch) :
Greg Claytonb01000f2011-01-17 03:46:26 +0000418 Disassembler (arch),
Greg Claytonb1888f22011-03-19 01:12:21 +0000419 m_disassembler (NULL),
420 m_disassembler_thumb (NULL) // For ARM only
Chris Lattner24943d22010-06-08 16:52:24 +0000421{
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000422 const std::string &arch_triple = arch.GetTriple().str();
423 if (!arch_triple.empty())
Greg Claytoncf015052010-06-11 03:25:34 +0000424 {
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000425 if (EDGetDisassembler(&m_disassembler, arch_triple.c_str(), SyntaxForArchSpec (arch)))
426 m_disassembler = NULL;
Greg Claytonb1888f22011-03-19 01:12:21 +0000427 llvm::Triple::ArchType llvm_arch = arch.GetTriple().getArch();
Greg Clayton889fbd02011-03-26 19:14:58 +0000428 // Don't have the lldb::Triple::thumb architecture here. If someone specifies
429 // "thumb" as the architecture, we want a thumb only disassembler. But if any
430 // architecture starting with "arm" if specified, we want to auto detect the
431 // arm/thumb code automatically using the AddressClass from section offset
432 // addresses.
Greg Claytonb1888f22011-03-19 01:12:21 +0000433 if (llvm_arch == llvm::Triple::arm)
434 {
435 if (EDGetDisassembler(&m_disassembler_thumb, "thumb-apple-darwin", kEDAssemblySyntaxARMUAL))
436 m_disassembler_thumb = NULL;
437 }
Greg Claytoncf015052010-06-11 03:25:34 +0000438 }
Chris Lattner24943d22010-06-08 16:52:24 +0000439}
440
441DisassemblerLLVM::~DisassemblerLLVM()
442{
443}
444
445size_t
Greg Clayton70436352010-06-30 23:03:03 +0000446DisassemblerLLVM::DecodeInstructions
Chris Lattner24943d22010-06-08 16:52:24 +0000447(
Greg Clayton5c4c7462010-10-06 03:09:58 +0000448 const Address &base_addr,
Chris Lattner24943d22010-06-08 16:52:24 +0000449 const DataExtractor& data,
450 uint32_t data_offset,
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000451 uint32_t num_instructions,
452 bool append
Chris Lattner24943d22010-06-08 16:52:24 +0000453)
454{
Greg Claytonb01000f2011-01-17 03:46:26 +0000455 if (m_disassembler == NULL)
456 return 0;
457
Chris Lattner24943d22010-06-08 16:52:24 +0000458 size_t total_inst_byte_size = 0;
459
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000460 if (!append)
461 m_instruction_list.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000462
463 while (data.ValidOffset(data_offset) && num_instructions)
464 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000465 Address inst_addr (base_addr);
466 inst_addr.Slide(data_offset);
Greg Claytonb1888f22011-03-19 01:12:21 +0000467
468 bool use_thumb = false;
469 // If we have a thumb disassembler, then we have an ARM architecture
470 // so we need to check what the instruction address class is to make
471 // sure we shouldn't be disassembling as thumb...
Greg Clayton889fbd02011-03-26 19:14:58 +0000472 AddressClass inst_address_class = eAddressClassInvalid;
Greg Claytonb1888f22011-03-19 01:12:21 +0000473 if (m_disassembler_thumb)
474 {
Greg Clayton889fbd02011-03-26 19:14:58 +0000475 inst_address_class = inst_addr.GetAddressClass ();
476 if (inst_address_class == eAddressClassCodeAlternateISA)
Greg Claytonb1888f22011-03-19 01:12:21 +0000477 use_thumb = true;
478 }
Greg Claytonabe0fed2011-04-18 08:33:37 +0000479 bool force_raw = false;
480 switch (m_arch.GetMachine())
481 {
482 case llvm::Triple::arm:
483 case llvm::Triple::thumb:
484 force_raw = true;
485 break;
486 default:
487 break;
488 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000489 InstructionSP inst_sp (new InstructionLLVM (inst_addr,
Greg Clayton889fbd02011-03-26 19:14:58 +0000490 inst_address_class,
Greg Claytonabe0fed2011-04-18 08:33:37 +0000491 use_thumb ? m_disassembler_thumb : m_disassembler,
492 force_raw));
Chris Lattner24943d22010-06-08 16:52:24 +0000493
Greg Clayton889fbd02011-03-26 19:14:58 +0000494 size_t inst_byte_size = inst_sp->Decode (*this, data, data_offset);
Chris Lattner24943d22010-06-08 16:52:24 +0000495
496 if (inst_byte_size == 0)
497 break;
498
Greg Clayton5c4c7462010-10-06 03:09:58 +0000499 m_instruction_list.Append (inst_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000500
501 total_inst_byte_size += inst_byte_size;
502 data_offset += inst_byte_size;
503 num_instructions--;
504 }
505
506 return total_inst_byte_size;
507}
508
509void
510DisassemblerLLVM::Initialize()
511{
512 PluginManager::RegisterPlugin (GetPluginNameStatic(),
513 GetPluginDescriptionStatic(),
514 CreateInstance);
515}
516
517void
518DisassemblerLLVM::Terminate()
519{
520 PluginManager::UnregisterPlugin (CreateInstance);
521}
522
523
524const char *
525DisassemblerLLVM::GetPluginNameStatic()
526{
Greg Clayton149731c2011-03-25 18:03:16 +0000527 return "llvm";
Chris Lattner24943d22010-06-08 16:52:24 +0000528}
529
530const char *
531DisassemblerLLVM::GetPluginDescriptionStatic()
532{
Greg Clayton149731c2011-03-25 18:03:16 +0000533 return "Disassembler that uses LLVM opcode tables to disassemble i386, x86_64 and ARM.";
Chris Lattner24943d22010-06-08 16:52:24 +0000534}
535
536//------------------------------------------------------------------
537// PluginInterface protocol
538//------------------------------------------------------------------
539const char *
540DisassemblerLLVM::GetPluginName()
541{
542 return "DisassemblerLLVM";
543}
544
545const char *
546DisassemblerLLVM::GetShortPluginName()
547{
548 return GetPluginNameStatic();
549}
550
551uint32_t
552DisassemblerLLVM::GetPluginVersion()
553{
554 return 1;
555}
556