LLVM  3.7.0
Disassembler.cpp
Go to the documentation of this file.
1 //===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface ---------===//
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 "Disassembler.h"
11 #include "llvm-c/Disassembler.h"
12 #include "llvm/MC/MCAsmInfo.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCDisassembler.h"
15 #include "llvm/MC/MCInst.h"
16 #include "llvm/MC/MCInstPrinter.h"
17 #include "llvm/MC/MCInstrInfo.h"
18 #include "llvm/MC/MCRegisterInfo.h"
21 #include "llvm/MC/MCSymbolizer.h"
25 
26 using namespace llvm;
27 
28 // LLVMCreateDisasm() creates a disassembler for the TripleName. Symbolic
29 // disassembly is supported by passing a block of information in the DisInfo
30 // parameter and specifying the TagType and callback functions as described in
31 // the header llvm-c/Disassembler.h . The pointer to the block and the
32 // functions can all be passed as NULL. If successful, this returns a
33 // disassembler context. If not, it returns NULL.
34 //
36 LLVMCreateDisasmCPUFeatures(const char *TT, const char *CPU,
37  const char *Features, void *DisInfo, int TagType,
38  LLVMOpInfoCallback GetOpInfo,
39  LLVMSymbolLookupCallback SymbolLookUp) {
40  // Get the target.
41  std::string Error;
42  const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error);
43  if (!TheTarget)
44  return nullptr;
45 
46  const MCRegisterInfo *MRI = TheTarget->createMCRegInfo(TT);
47  if (!MRI)
48  return nullptr;
49 
50  // Get the assembler info needed to setup the MCContext.
51  const MCAsmInfo *MAI = TheTarget->createMCAsmInfo(*MRI, TT);
52  if (!MAI)
53  return nullptr;
54 
55  const MCInstrInfo *MII = TheTarget->createMCInstrInfo();
56  if (!MII)
57  return nullptr;
58 
59  const MCSubtargetInfo *STI =
60  TheTarget->createMCSubtargetInfo(TT, CPU, Features);
61  if (!STI)
62  return nullptr;
63 
64  // Set up the MCContext for creating symbols and MCExpr's.
65  MCContext *Ctx = new MCContext(MAI, MRI, nullptr);
66  if (!Ctx)
67  return nullptr;
68 
69  // Set up disassembler.
70  MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI, *Ctx);
71  if (!DisAsm)
72  return nullptr;
73 
74  std::unique_ptr<MCRelocationInfo> RelInfo(
75  TheTarget->createMCRelocationInfo(TT, *Ctx));
76  if (!RelInfo)
77  return nullptr;
78 
79  std::unique_ptr<MCSymbolizer> Symbolizer(TheTarget->createMCSymbolizer(
80  TT, GetOpInfo, SymbolLookUp, DisInfo, Ctx, std::move(RelInfo)));
81  DisAsm->setSymbolizer(std::move(Symbolizer));
82 
83  // Set up the instruction printer.
84  int AsmPrinterVariant = MAI->getAssemblerDialect();
85  MCInstPrinter *IP = TheTarget->createMCInstPrinter(
86  Triple(TT), AsmPrinterVariant, *MAI, *MII, *MRI);
87  if (!IP)
88  return nullptr;
89 
90  LLVMDisasmContext *DC =
91  new LLVMDisasmContext(TT, DisInfo, TagType, GetOpInfo, SymbolLookUp,
92  TheTarget, MAI, MRI, STI, MII, Ctx, DisAsm, IP);
93  if (!DC)
94  return nullptr;
95 
96  DC->setCPU(CPU);
97  return DC;
98 }
99 
101 LLVMCreateDisasmCPU(const char *TT, const char *CPU, void *DisInfo, int TagType,
102  LLVMOpInfoCallback GetOpInfo,
103  LLVMSymbolLookupCallback SymbolLookUp) {
104  return LLVMCreateDisasmCPUFeatures(TT, CPU, "", DisInfo, TagType, GetOpInfo,
105  SymbolLookUp);
106 }
107 
108 LLVMDisasmContextRef LLVMCreateDisasm(const char *TT, void *DisInfo,
109  int TagType, LLVMOpInfoCallback GetOpInfo,
110  LLVMSymbolLookupCallback SymbolLookUp) {
111  return LLVMCreateDisasmCPUFeatures(TT, "", "", DisInfo, TagType, GetOpInfo,
112  SymbolLookUp);
113 }
114 
115 //
116 // LLVMDisasmDispose() disposes of the disassembler specified by the context.
117 //
120  delete DC;
121 }
122 
123 /// \brief Emits the comments that are stored in \p DC comment stream.
124 /// Each comment in the comment stream must end with a newline.
126  formatted_raw_ostream &FormattedOS) {
127  // Flush the stream before taking its content.
128  DC->CommentStream.flush();
129  StringRef Comments = DC->CommentsToEmit.str();
130  // Get the default information for printing a comment.
131  const MCAsmInfo *MAI = DC->getAsmInfo();
132  const char *CommentBegin = MAI->getCommentString();
133  unsigned CommentColumn = MAI->getCommentColumn();
134  bool IsFirst = true;
135  while (!Comments.empty()) {
136  if (!IsFirst)
137  FormattedOS << '\n';
138  // Emit a line of comments.
139  FormattedOS.PadToColumn(CommentColumn);
140  size_t Position = Comments.find('\n');
141  FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
142  // Move after the newline character.
143  Comments = Comments.substr(Position+1);
144  IsFirst = false;
145  }
146  FormattedOS.flush();
147 
148  // Tell the comment stream that the vector changed underneath it.
149  DC->CommentsToEmit.clear();
150  DC->CommentStream.resync();
151 }
152 
153 /// \brief Gets latency information for \p Inst from the itinerary
154 /// scheduling model, based on \p DC information.
155 /// \return The maximum expected latency over all the operands or -1
156 /// if no information is available.
157 static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
158  const int NoInformationAvailable = -1;
159 
160  // Check if we have a CPU to get the itinerary information.
161  if (DC->getCPU().empty())
162  return NoInformationAvailable;
163 
164  // Get itinerary information.
165  const MCSubtargetInfo *STI = DC->getSubtargetInfo();
167  // Get the scheduling class of the requested instruction.
168  const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
169  unsigned SCClass = Desc.getSchedClass();
170 
171  int Latency = 0;
172  for (unsigned OpIdx = 0, OpIdxEnd = Inst.getNumOperands(); OpIdx != OpIdxEnd;
173  ++OpIdx)
174  Latency = std::max(Latency, IID.getOperandCycle(SCClass, OpIdx));
175 
176  return Latency;
177 }
178 
179 /// \brief Gets latency information for \p Inst, based on \p DC information.
180 /// \return The maximum expected latency over all the definitions or -1
181 /// if no information is available.
182 static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
183  // Try to compute scheduling information.
184  const MCSubtargetInfo *STI = DC->getSubtargetInfo();
185  const MCSchedModel SCModel = STI->getSchedModel();
186  const int NoInformationAvailable = -1;
187 
188  // Check if we have a scheduling model for instructions.
189  if (!SCModel.hasInstrSchedModel())
190  // Try to fall back to the itinerary model if the scheduling model doesn't
191  // have a scheduling table. Note the default does not have a table.
192  return getItineraryLatency(DC, Inst);
193 
194  // Get the scheduling class of the requested instruction.
195  const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
196  unsigned SCClass = Desc.getSchedClass();
197  const MCSchedClassDesc *SCDesc = SCModel.getSchedClassDesc(SCClass);
198  // Resolving the variant SchedClass requires an MI to pass to
199  // SubTargetInfo::resolveSchedClass.
200  if (!SCDesc || !SCDesc->isValid() || SCDesc->isVariant())
201  return NoInformationAvailable;
202 
203  // Compute output latency.
204  int Latency = 0;
205  for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries;
206  DefIdx != DefEnd; ++DefIdx) {
207  // Lookup the definition's write latency in SubtargetInfo.
208  const MCWriteLatencyEntry *WLEntry = STI->getWriteLatencyEntry(SCDesc,
209  DefIdx);
210  Latency = std::max(Latency, WLEntry->Cycles);
211  }
212 
213  return Latency;
214 }
215 
216 
217 /// \brief Emits latency information in DC->CommentStream for \p Inst, based
218 /// on the information available in \p DC.
219 static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
220  int Latency = getLatency(DC, Inst);
221 
222  // Report only interesting latencies.
223  if (Latency < 2)
224  return;
225 
226  DC->CommentStream << "Latency: " << Latency << '\n';
227 }
228 
229 //
230 // LLVMDisasmInstruction() disassembles a single instruction using the
231 // disassembler context specified in the parameter DC. The bytes of the
232 // instruction are specified in the parameter Bytes, and contains at least
233 // BytesSize number of bytes. The instruction is at the address specified by
234 // the PC parameter. If a valid instruction can be disassembled its string is
235 // returned indirectly in OutString which whos size is specified in the
236 // parameter OutStringSize. This function returns the number of bytes in the
237 // instruction or zero if there was no valid instruction. If this function
238 // returns zero the caller will have to pick how many bytes they want to step
239 // over by printing a .byte, .long etc. to continue.
240 //
241 size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes,
242  uint64_t BytesSize, uint64_t PC, char *OutString,
243  size_t OutStringSize){
245  // Wrap the pointer to the Bytes, BytesSize and PC in a MemoryObject.
246  ArrayRef<uint8_t> Data(Bytes, BytesSize);
247 
248  uint64_t Size;
249  MCInst Inst;
250  const MCDisassembler *DisAsm = DC->getDisAsm();
251  MCInstPrinter *IP = DC->getIP();
253  SmallVector<char, 64> InsnStr;
254  raw_svector_ostream Annotations(InsnStr);
255  S = DisAsm->getInstruction(Inst, Size, Data, PC,
256  /*REMOVE*/ nulls(), Annotations);
257  switch (S) {
260  // FIXME: Do something different for soft failure modes?
261  return 0;
262 
264  Annotations.flush();
265  StringRef AnnotationsStr = Annotations.str();
266 
267  SmallVector<char, 64> InsnStr;
268  raw_svector_ostream OS(InsnStr);
269  formatted_raw_ostream FormattedOS(OS);
270  IP->printInst(&Inst, FormattedOS, AnnotationsStr, *DC->getSubtargetInfo());
271 
273  emitLatency(DC, Inst);
274 
275  emitComments(DC, FormattedOS);
276  OS.flush();
277 
278  assert(OutStringSize != 0 && "Output buffer cannot be zero size");
279  size_t OutputSize = std::min(OutStringSize-1, InsnStr.size());
280  std::memcpy(OutString, InsnStr.data(), OutputSize);
281  OutString[OutputSize] = '\0'; // Terminate string.
282 
283  return Size;
284  }
285  }
286  llvm_unreachable("Invalid DecodeStatus!");
287 }
288 
289 //
290 // LLVMSetDisasmOptions() sets the disassembler's options. It returns 1 if it
291 // can set all the Options and 0 otherwise.
292 //
293 int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){
294  if (Options & LLVMDisassembler_Option_UseMarkup){
296  MCInstPrinter *IP = DC->getIP();
297  IP->setUseMarkup(1);
298  DC->addOptions(LLVMDisassembler_Option_UseMarkup);
299  Options &= ~LLVMDisassembler_Option_UseMarkup;
300  }
303  MCInstPrinter *IP = DC->getIP();
304  IP->setPrintImmHex(1);
305  DC->addOptions(LLVMDisassembler_Option_PrintImmHex);
306  Options &= ~LLVMDisassembler_Option_PrintImmHex;
307  }
310  // Try to set up the new instruction printer.
311  const MCAsmInfo *MAI = DC->getAsmInfo();
312  const MCInstrInfo *MII = DC->getInstrInfo();
313  const MCRegisterInfo *MRI = DC->getRegisterInfo();
314  int AsmPrinterVariant = MAI->getAssemblerDialect();
315  AsmPrinterVariant = AsmPrinterVariant == 0 ? 1 : 0;
317  Triple(DC->getTripleName()), AsmPrinterVariant, *MAI, *MII, *MRI);
318  if (IP) {
319  DC->setIP(IP);
320  DC->addOptions(LLVMDisassembler_Option_AsmPrinterVariant);
321  Options &= ~LLVMDisassembler_Option_AsmPrinterVariant;
322  }
323  }
326  MCInstPrinter *IP = DC->getIP();
328  DC->addOptions(LLVMDisassembler_Option_SetInstrComments);
329  Options &= ~LLVMDisassembler_Option_SetInstrComments;
330  }
331  if (Options & LLVMDisassembler_Option_PrintLatency) {
333  DC->addOptions(LLVMDisassembler_Option_PrintLatency);
334  Options &= ~LLVMDisassembler_Option_PrintLatency;
335  }
336  return (Options == 0);
337 }
MCDisassembler * createMCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) const
unsigned getAssemblerDialect() const
Definition: MCAsmInfo.h:465
#define LLVMDisassembler_Option_SetInstrComments
const MCRegisterInfo * getRegisterInfo() const
InstrItineraryData getInstrItineraryForCPU(StringRef CPU) const
getInstrItineraryForCPU - Get scheduling itinerary of a CPU.
virtual void printInst(const MCInst *MI, raw_ostream &OS, StringRef Annot, const MCSubtargetInfo &STI)=0
Print the specified MCInst to the specified raw_ostream.
LLVMDisasmContextRef LLVMCreateDisasm(const char *TT, void *DisInfo, int TagType, LLVMOpInfoCallback GetOpInfo, LLVMSymbolLookupCallback SymbolLookUp)
Create a disassembler for the TripleName.
DecodeStatus
Ternary decode status.
formatted_raw_ostream - A raw_ostream that wraps another one and keeps track of line and column posit...
Superclass for all disassemblers.
const char *(* LLVMSymbolLookupCallback)(void *DisInfo, uint64_t ReferenceValue, uint64_t *ReferenceType, uint64_t ReferencePC, const char **ReferenceName)
The type for the symbol lookup function.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:240
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:138
MCRegisterInfo * createMCRegInfo(StringRef TT) const
createMCRegInfo - Create a MCRegisterInfo implementation.
const FeatureBitset Features
StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:405
static void emitComments(LLVMDisasmContext *DC, formatted_raw_ostream &FormattedOS)
Emits the comments that are stored in DC comment stream.
void setPrintImmHex(bool Value)
Definition: MCInstPrinter.h:90
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:488
const std::string & getTripleName() const
void setSymbolizer(std::unique_ptr< MCSymbolizer > Symzer)
Set Symzer as the current symbolizer.
#define LLVMDisassembler_Option_UseMarkup
static const Target * lookupTarget(const std::string &Triple, std::string &Error)
lookupTarget - Lookup a target based on a target triple.
LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *TT, const char *CPU, void *DisInfo, int TagType, LLVMOpInfoCallback GetOpInfo, LLVMSymbolLookupCallback SymbolLookUp)
Create a disassembler for the TripleName and a specific CPU.
MCInstrInfo * createMCInstrInfo() const
createMCInstrInfo - Create a MCInstrInfo implementation.
const MCDisassembler * getDisAsm() const
MCSubtargetInfo * createMCSubtargetInfo(StringRef TheTriple, StringRef CPU, StringRef Features) const
createMCSubtargetInfo - Create a MCSubtargetInfo implementation.
int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const
Return the cycle for the given class and operand.
const MCSubtargetInfo * getSubtargetInfo() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:98
unsigned getCommentColumn() const
This indicates the column (zero-based) at which asm comments should be printed.
Definition: MCAsmInfo.h:443
Number of individual test Apply this number of consecutive mutations to each input exit after the first new interesting input is found the minimized corpus is saved into the first input directory Number of jobs to run If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst)
Emits latency information in DC->CommentStream for Inst, based on the information available in DC...
const MCSchedModel & getSchedModel() const
Get the machine model for this subtarget's CPU.
Context object for machine code objects.
Definition: MCContext.h:48
formatted_raw_ostream & PadToColumn(unsigned NewCol)
PadToColumn - Align the output to some column number.
void * LLVMDisasmContextRef
An opaque reference to a disassembler context.
Itinerary data supplied by a subtarget to be used by a target.
bool isValid() const
Definition: MCSchedule.h:118
static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst)
Gets latency information for Inst, based on DC information.
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:150
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition: MCAsmInfo.h:58
MCAsmInfo * createMCAsmInfo(const MCRegisterInfo &MRI, StringRef TheTriple) const
createMCAsmInfo - Create a MCAsmInfo implementation for the specified target triple.
unsigned NumWriteLatencyEntries
Definition: MCSchedule.h:114
void resync()
This is called when the SmallVector we're appending to is changed outside of the raw_svector_ostream'...
Summarize the scheduling resources required for an instruction of a particular scheduling class...
Definition: MCSchedule.h:101
void setCommentStream(raw_ostream &OS)
Specify a stream to emit comments to.
Definition: MCInstPrinter.h:69
#define LLVMDisassembler_Option_PrintImmHex
const MCWriteLatencyEntry * getWriteLatencyEntry(const MCSchedClassDesc *SC, unsigned DefIdx) const
bool hasInstrSchedModel() const
Does this machine model include instruction-level scheduling.
Definition: MCSchedule.h:203
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:24
MCRelocationInfo * createMCRelocationInfo(StringRef TT, MCContext &Ctx) const
createMCRelocationInfo - Create a target specific MCRelocationInfo.
const MCSchedClassDesc * getSchedClassDesc(unsigned SchedClassIdx) const
Definition: MCSchedule.h:220
MCInstPrinter * createMCInstPrinter(const Triple &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI) const
static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst)
Gets latency information for Inst from the itinerary scheduling model, based on DC information...
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Definition: MCInstrInfo.h:45
bool isVariant() const
Definition: MCSchedule.h:121
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
Specify the latency in cpu cycles for a particular scheduling class and def index.
Definition: MCSchedule.h:69
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:861
MCSymbolizer * createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo, LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo, MCContext *Ctx, std::unique_ptr< MCRelocationInfo > &&RelInfo) const
createMCSymbolizer - Create a target specific MCSymbolizer.
const MCInstrInfo * getInstrInfo() const
LLVMDisasmContextRef LLVMCreateDisasmCPUFeatures(const char *TT, const char *CPU, const char *Features, void *DisInfo, int TagType, LLVMOpInfoCallback GetOpInfo, LLVMSymbolLookupCallback SymbolLookUp)
Create a disassembler for the TripleName, a specific CPU and specific feature string.
unsigned getOpcode() const
Definition: MCInst.h:159
Target - Wrapper for Target specific information.
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:267
void setUseMarkup(bool Value)
Definition: MCInstPrinter.h:83
size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes, uint64_t BytesSize, uint64_t PC, char *OutString, size_t OutStringSize)
Disassemble a single instruction using the disassembler context specified in the parameter DC...
int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options)
Set the disassembler's options.
#define LLVMDisassembler_Option_AsmPrinterVariant
StringRef str()
Flushes the stream contents to the target vector and return a StringRef for the vector contents...
unsigned getSchedClass() const
Return the scheduling class for this instruction.
Definition: MCInstrDesc.h:528
This is an instance of a target assembly language printer that converts an MCInst to valid target ass...
Definition: MCInstPrinter.h:38
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:134
unsigned getNumOperands() const
Definition: MCInst.h:166
void LLVMDisasmDispose(LLVMDisasmContextRef DCR)
Dispose of a disassembler context.
MCSubtargetInfo - Generic base class for all target subtargets.
raw_ostream & nulls()
This returns a reference to a raw_ostream which simply discards output.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
virtual DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, ArrayRef< uint8_t > Bytes, uint64_t Address, raw_ostream &VStream, raw_ostream &CStream) const =0
Returns the disassembly of a single instruction.
int(* LLVMOpInfoCallback)(void *DisInfo, uint64_t PC, uint64_t Offset, uint64_t Size, int TagType, void *TagBuf)
The type for the operand information call back function.
Machine model for scheduling, bundling, and heuristics.
Definition: MCSchedule.h:136
const char * getCommentString() const
Definition: MCAsmInfo.h:445
bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:110
#define LLVMDisassembler_Option_PrintLatency