MCExternalSymbolizer.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. //===-- MCExternalSymbolizer.cpp - External symbolizer --------------------===//
  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. #include "llvm/MC/MCExternalSymbolizer.h"
  10. #include "llvm/MC/MCContext.h"
  11. #include "llvm/MC/MCExpr.h"
  12. #include "llvm/MC/MCInst.h"
  13. #include "llvm/Support/raw_ostream.h"
  14. #include <cstring>
  15. using namespace llvm;
  16. namespace llvm {
  17. class Triple;
  18. }
  19. // This function tries to add a symbolic operand in place of the immediate
  20. // Value in the MCInst. The immediate Value has had any PC adjustment made by
  21. // the caller. If the instruction is a branch instruction then IsBranch is true,
  22. // else false. If the getOpInfo() function was set as part of the
  23. // setupForSymbolicDisassembly() call then that function is called to get any
  24. // symbolic information at the Address for this instruction. If that returns
  25. // non-zero then the symbolic information it returns is used to create an MCExpr
  26. // and that is added as an operand to the MCInst. If getOpInfo() returns zero
  27. // and IsBranch is true then a symbol look up for Value is done and if a symbol
  28. // is found an MCExpr is created with that, else an MCExpr with Value is
  29. // created. This function returns true if it adds an operand to the MCInst and
  30. // false otherwise.
  31. bool MCExternalSymbolizer::tryAddingSymbolicOperand(MCInst &MI,
  32. raw_ostream &cStream,
  33. int64_t Value,
  34. uint64_t Address,
  35. bool IsBranch,
  36. uint64_t Offset,
  37. uint64_t InstSize) {
  38. struct LLVMOpInfo1 SymbolicOp;
  39. std::memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1));
  40. SymbolicOp.Value = Value;
  41. if (!GetOpInfo ||
  42. !GetOpInfo(DisInfo, Address, Offset, InstSize, 1, &SymbolicOp)) {
  43. // Clear SymbolicOp.Value from above and also all other fields.
  44. std::memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1));
  45. // At this point, GetOpInfo() did not find any relocation information about
  46. // this operand and we are left to use the SymbolLookUp() call back to guess
  47. // if the Value is the address of a symbol. In the case this is a branch
  48. // that always makes sense to guess. But in the case of an immediate it is
  49. // a bit more questionable if it is an address of a symbol or some other
  50. // reference. So if the immediate Value comes from a width of 1 byte,
  51. // InstSize, we will not guess it is an address of a symbol. Because in
  52. // object files assembled starting at address 0 this usually leads to
  53. // incorrect symbolication.
  54. if (!SymbolLookUp || (InstSize == 1 && !IsBranch))
  55. return false;
  56. uint64_t ReferenceType;
  57. if (IsBranch)
  58. ReferenceType = LLVMDisassembler_ReferenceType_In_Branch;
  59. else
  60. ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  61. const char *ReferenceName;
  62. const char *Name = SymbolLookUp(DisInfo, Value, &ReferenceType, Address,
  63. &ReferenceName);
  64. if (Name) {
  65. SymbolicOp.AddSymbol.Name = Name;
  66. SymbolicOp.AddSymbol.Present = true;
  67. // If Name is a C++ symbol name put the human readable name in a comment.
  68. if(ReferenceType == LLVMDisassembler_ReferenceType_DeMangled_Name)
  69. cStream << ReferenceName;
  70. }
  71. // For branches always create an MCExpr so it gets printed as hex address.
  72. else if (IsBranch) {
  73. SymbolicOp.Value = Value;
  74. }
  75. if(ReferenceType == LLVMDisassembler_ReferenceType_Out_SymbolStub)
  76. cStream << "symbol stub for: " << ReferenceName;
  77. else if(ReferenceType == LLVMDisassembler_ReferenceType_Out_Objc_Message)
  78. cStream << "Objc message: " << ReferenceName;
  79. if (!Name && !IsBranch)
  80. return false;
  81. }
  82. const MCExpr *Add = nullptr;
  83. if (SymbolicOp.AddSymbol.Present) {
  84. if (SymbolicOp.AddSymbol.Name) {
  85. StringRef Name(SymbolicOp.AddSymbol.Name);
  86. MCSymbol *Sym = Ctx.getOrCreateSymbol(Name);
  87. Add = MCSymbolRefExpr::create(Sym, Ctx);
  88. } else {
  89. Add = MCConstantExpr::create((int)SymbolicOp.AddSymbol.Value, Ctx);
  90. }
  91. }
  92. const MCExpr *Sub = nullptr;
  93. if (SymbolicOp.SubtractSymbol.Present) {
  94. if (SymbolicOp.SubtractSymbol.Name) {
  95. StringRef Name(SymbolicOp.SubtractSymbol.Name);
  96. MCSymbol *Sym = Ctx.getOrCreateSymbol(Name);
  97. Sub = MCSymbolRefExpr::create(Sym, Ctx);
  98. } else {
  99. Sub = MCConstantExpr::create((int)SymbolicOp.SubtractSymbol.Value, Ctx);
  100. }
  101. }
  102. const MCExpr *Off = nullptr;
  103. if (SymbolicOp.Value != 0)
  104. Off = MCConstantExpr::create(SymbolicOp.Value, Ctx);
  105. const MCExpr *Expr;
  106. if (Sub) {
  107. const MCExpr *LHS;
  108. if (Add)
  109. LHS = MCBinaryExpr::createSub(Add, Sub, Ctx);
  110. else
  111. LHS = MCUnaryExpr::createMinus(Sub, Ctx);
  112. if (Off)
  113. Expr = MCBinaryExpr::createAdd(LHS, Off, Ctx);
  114. else
  115. Expr = LHS;
  116. } else if (Add) {
  117. if (Off)
  118. Expr = MCBinaryExpr::createAdd(Add, Off, Ctx);
  119. else
  120. Expr = Add;
  121. } else {
  122. if (Off)
  123. Expr = Off;
  124. else
  125. Expr = MCConstantExpr::create(0, Ctx);
  126. }
  127. Expr = RelInfo->createExprForCAPIVariantKind(Expr, SymbolicOp.VariantKind);
  128. if (!Expr)
  129. return false;
  130. MI.addOperand(MCOperand::createExpr(Expr));
  131. return true;
  132. }
  133. // This function tries to add a comment as to what is being referenced by a load
  134. // instruction with the base register that is the Pc. These can often be values
  135. // in a literal pool near the Address of the instruction. The Address of the
  136. // instruction and its immediate Value are used as a possible literal pool entry.
  137. // The SymbolLookUp call back will return the name of a symbol referenced by the
  138. // literal pool's entry if the referenced address is that of a symbol. Or it
  139. // will return a pointer to a literal 'C' string if the referenced address of
  140. // the literal pool's entry is an address into a section with C string literals.
  141. // Or if the reference is to an Objective-C data structure it will return a
  142. // specific reference type for it and a string.
  143. void MCExternalSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream,
  144. int64_t Value,
  145. uint64_t Address) {
  146. if (SymbolLookUp) {
  147. uint64_t ReferenceType = LLVMDisassembler_ReferenceType_In_PCrel_Load;
  148. const char *ReferenceName;
  149. (void)SymbolLookUp(DisInfo, Value, &ReferenceType, Address, &ReferenceName);
  150. if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr)
  151. cStream << "literal pool symbol address: " << ReferenceName;
  152. else if(ReferenceType ==
  153. LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr) {
  154. cStream << "literal pool for: \"";
  155. cStream.write_escaped(ReferenceName);
  156. cStream << "\"";
  157. }
  158. else if(ReferenceType ==
  159. LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref)
  160. cStream << "Objc cfstring ref: @\"" << ReferenceName << "\"";
  161. else if(ReferenceType ==
  162. LLVMDisassembler_ReferenceType_Out_Objc_Message)
  163. cStream << "Objc message: " << ReferenceName;
  164. else if(ReferenceType ==
  165. LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref)
  166. cStream << "Objc message ref: " << ReferenceName;
  167. else if(ReferenceType ==
  168. LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref)
  169. cStream << "Objc selector ref: " << ReferenceName;
  170. else if(ReferenceType ==
  171. LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref)
  172. cStream << "Objc class ref: " << ReferenceName;
  173. }
  174. }
  175. namespace llvm {
  176. MCSymbolizer *createMCSymbolizer(const Triple &TT, LLVMOpInfoCallback GetOpInfo,
  177. LLVMSymbolLookupCallback SymbolLookUp,
  178. void *DisInfo, MCContext *Ctx,
  179. std::unique_ptr<MCRelocationInfo> &&RelInfo) {
  180. assert(Ctx && "No MCContext given for symbolic disassembly");
  181. return new MCExternalSymbolizer(*Ctx, std::move(RelInfo), GetOpInfo,
  182. SymbolLookUp, DisInfo);
  183. }
  184. }