Coverage Report

Created: 2017-10-03 07:32

/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
}