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