blob: def662777d61b1b704da6f1adb55d03d94a46641 [file] [log] [blame]
Ahmed Bougachaad1084d2013-05-24 00:39:57 +00001//===-- lib/MC/MCExternalSymbolizer.cpp - External symbolizer ---*- 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 "llvm/MC/MCExternalSymbolizer.h"
11#include "llvm/MC/MCContext.h"
12#include "llvm/MC/MCExpr.h"
13#include "llvm/MC/MCInst.h"
14#include "llvm/Support/raw_ostream.h"
15#include <cstring>
16
17using namespace llvm;
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.
31bool 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
42 if (!GetOpInfo ||
43 !GetOpInfo(DisInfo, Address, Offset, InstSize, 1, &SymbolicOp)) {
44 // Clear SymbolicOp.Value from above and also all other fields.
45 std::memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1));
46 if (!SymbolLookUp)
47 return false;
48 uint64_t ReferenceType;
49 if (IsBranch)
50 ReferenceType = LLVMDisassembler_ReferenceType_In_Branch;
51 else
52 ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
53 const char *ReferenceName;
54 const char *Name = SymbolLookUp(DisInfo, Value, &ReferenceType, Address,
55 &ReferenceName);
56 if (Name) {
57 SymbolicOp.AddSymbol.Name = Name;
58 SymbolicOp.AddSymbol.Present = true;
Kevin Enderbyf16c8c52014-01-06 22:08:08 +000059 // If Name is a C++ symbol name put the human readable name in a comment.
60 if(ReferenceType == LLVMDisassembler_ReferenceType_DeMangled_Name)
61 cStream << ReferenceName;
Ahmed Bougachaad1084d2013-05-24 00:39:57 +000062 }
63 // For branches always create an MCExpr so it gets printed as hex address.
64 else if (IsBranch) {
65 SymbolicOp.Value = Value;
66 }
67 if(ReferenceType == LLVMDisassembler_ReferenceType_Out_SymbolStub)
68 cStream << "symbol stub for: " << ReferenceName;
Kevin Enderby3c5ac812013-11-01 00:00:07 +000069 else if(ReferenceType == LLVMDisassembler_ReferenceType_Out_Objc_Message)
70 cStream << "Objc message: " << ReferenceName;
Ahmed Bougachaad1084d2013-05-24 00:39:57 +000071 if (!Name && !IsBranch)
72 return false;
73 }
74
75 const MCExpr *Add = NULL;
76 if (SymbolicOp.AddSymbol.Present) {
77 if (SymbolicOp.AddSymbol.Name) {
78 StringRef Name(SymbolicOp.AddSymbol.Name);
79 MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name);
80 Add = MCSymbolRefExpr::Create(Sym, Ctx);
81 } else {
82 Add = MCConstantExpr::Create((int)SymbolicOp.AddSymbol.Value, Ctx);
83 }
84 }
85
86 const MCExpr *Sub = NULL;
87 if (SymbolicOp.SubtractSymbol.Present) {
88 if (SymbolicOp.SubtractSymbol.Name) {
89 StringRef Name(SymbolicOp.SubtractSymbol.Name);
90 MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name);
91 Sub = MCSymbolRefExpr::Create(Sym, Ctx);
92 } else {
93 Sub = MCConstantExpr::Create((int)SymbolicOp.SubtractSymbol.Value, Ctx);
94 }
95 }
96
97 const MCExpr *Off = NULL;
98 if (SymbolicOp.Value != 0)
99 Off = MCConstantExpr::Create(SymbolicOp.Value, Ctx);
100
101 const MCExpr *Expr;
102 if (Sub) {
103 const MCExpr *LHS;
104 if (Add)
105 LHS = MCBinaryExpr::CreateSub(Add, Sub, Ctx);
106 else
107 LHS = MCUnaryExpr::CreateMinus(Sub, Ctx);
108 if (Off != 0)
109 Expr = MCBinaryExpr::CreateAdd(LHS, Off, Ctx);
110 else
111 Expr = LHS;
112 } else if (Add) {
113 if (Off != 0)
114 Expr = MCBinaryExpr::CreateAdd(Add, Off, Ctx);
115 else
116 Expr = Add;
117 } else {
118 if (Off != 0)
119 Expr = Off;
120 else
121 Expr = MCConstantExpr::Create(0, Ctx);
122 }
123
124 Expr = RelInfo->createExprForCAPIVariantKind(Expr, SymbolicOp.VariantKind);
125 if (!Expr)
126 return false;
127
128 MI.addOperand(MCOperand::CreateExpr(Expr));
129 return true;
130}
131
132// This function tries to add a comment as to what is being referenced by a load
133// instruction with the base register that is the Pc. These can often be values
134// in a literal pool near the Address of the instruction. The Address of the
135// instruction and its immediate Value are used as a possible literal pool entry.
136// The SymbolLookUp call back will return the name of a symbol referenced by the
137// literal pool's entry if the referenced address is that of a symbol. Or it
138// will return a pointer to a literal 'C' string if the referenced address of
139// the literal pool's entry is an address into a section with C string literals.
Kevin Enderby3c5ac812013-11-01 00:00:07 +0000140// Or if the reference is to an Objective-C data structure it will return a
141// specific reference type for it and a string.
Ahmed Bougachaad1084d2013-05-24 00:39:57 +0000142void MCExternalSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream,
143 int64_t Value,
144 uint64_t Address) {
145 if (SymbolLookUp) {
146 uint64_t ReferenceType = LLVMDisassembler_ReferenceType_In_PCrel_Load;
147 const char *ReferenceName;
148 (void)SymbolLookUp(DisInfo, Value, &ReferenceType, Address, &ReferenceName);
Kevin Enderby3c5ac812013-11-01 00:00:07 +0000149 if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr)
150 cStream << "literal pool symbol address: " << ReferenceName;
151 else if(ReferenceType ==
152 LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr)
153 cStream << "literal pool for: \"" << ReferenceName << "\"";
154 else if(ReferenceType ==
155 LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref)
156 cStream << "Objc cfstring ref: @\"" << ReferenceName << "\"";
157 else if(ReferenceType ==
158 LLVMDisassembler_ReferenceType_Out_Objc_Message)
159 cStream << "Objc message: " << ReferenceName;
160 else if(ReferenceType ==
161 LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref)
162 cStream << "Objc message ref: " << ReferenceName;
163 else if(ReferenceType ==
164 LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref)
165 cStream << "Objc selector ref: " << ReferenceName;
166 else if(ReferenceType ==
167 LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref)
168 cStream << "Objc class ref: " << ReferenceName;
Ahmed Bougachaad1084d2013-05-24 00:39:57 +0000169 }
170}
Quentin Colombetf4828052013-05-24 22:51:52 +0000171
172namespace llvm {
173MCSymbolizer *createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo,
174 LLVMSymbolLookupCallback SymbolLookUp,
175 void *DisInfo,
176 MCContext *Ctx,
177 MCRelocationInfo *RelInfo) {
178 assert(Ctx != 0 && "No MCContext given for symbolic disassembly");
179
180 OwningPtr<MCRelocationInfo> RelInfoOwingPtr(RelInfo);
181 return new MCExternalSymbolizer(*Ctx, RelInfoOwingPtr, GetOpInfo,
182 SymbolLookUp, DisInfo);
183}
184}