1 //===- bolt/Target/X86/X86MCSymbolizer.cpp --------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "X86MCSymbolizer.h"
10 #include "MCTargetDesc/X86BaseInfo.h"
11 #include "bolt/Core/BinaryContext.h"
12 #include "bolt/Core/BinaryFunction.h"
13 #include "bolt/Core/MCPlusBuilder.h"
14 #include "bolt/Core/Relocation.h"
15 #include "llvm/MC/MCInst.h"
16 #include "llvm/MC/MCRegisterInfo.h"
17 
18 #define DEBUG_TYPE "bolt-symbolizer"
19 
20 namespace llvm {
21 namespace bolt {
22 
23 X86MCSymbolizer::~X86MCSymbolizer() {}
24 
25 bool X86MCSymbolizer::tryAddingSymbolicOperand(
26     MCInst &Inst, raw_ostream &CStream, int64_t Value, uint64_t InstAddress,
27     bool IsBranch, uint64_t ImmOffset, uint64_t ImmSize, uint64_t InstSize) {
28   if (IsBranch)
29     return false;
30 
31   // Ignore implicit operands.
32   if (ImmSize == 0)
33     return false;
34 
35   BinaryContext &BC = Function.getBinaryContext();
36   MCContext *Ctx = BC.Ctx.get();
37 
38   if (BC.MIB->isBranch(Inst) || BC.MIB->isCall(Inst))
39     return false;
40 
41   /// Add symbolic operand to the instruction with an optional addend.
42   auto addOperand = [&](const MCSymbol *Symbol, uint64_t Addend) {
43     const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, *Ctx);
44     if (Addend)
45       Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Addend, *Ctx),
46                                      *Ctx);
47     Inst.addOperand(MCOperand::createExpr(Expr));
48   };
49 
50   // Check for relocations against the operand.
51   const uint64_t InstOffset = InstAddress - Function.getAddress();
52   if (const Relocation *Relocation =
53           Function.getRelocationAt(InstOffset + ImmOffset)) {
54     uint64_t SymbolValue = Relocation->Value - Relocation->Addend;
55     if (Relocation->isPCRelative())
56       SymbolValue += InstAddress + ImmOffset;
57 
58     // Process reference to the symbol.
59     BC.handleAddressRef(SymbolValue, Function, Relocation->isPCRelative());
60 
61     uint64_t Addend = Relocation->Addend;
62     // Real addend for pc-relative targets is adjusted with a delta from
63     // the relocation placement to the next instruction.
64     if (Relocation->isPCRelative())
65       Addend += InstOffset + InstSize - Relocation->Offset;
66 
67     addOperand(Relocation->Symbol, Addend);
68 
69     return true;
70   }
71 
72   // Check if the operand being added is a displacement part of a compound
73   // memory operand that uses PC-relative addressing. If it is, try to symbolize
74   // it without relocations.
75   const int MemOp = BC.MIB->getMemoryOperandNo(Inst);
76   if (MemOp == -1)
77     return false;
78 
79   const unsigned DispOp = MemOp + X86::AddrDisp;
80   if (Inst.getNumOperands() != DispOp)
81     return false;
82 
83   const MCOperand &Base = Inst.getOperand(MemOp + X86::AddrBaseReg);
84   if (Base.getReg() != BC.MRI->getProgramCounter())
85     return false;
86 
87   const MCOperand &Scale = Inst.getOperand(MemOp + X86::AddrScaleAmt);
88   const MCOperand &Index = Inst.getOperand(MemOp + X86::AddrIndexReg);
89   if (Scale.getImm() != 0 && Index.getReg() != MCRegister::NoRegister)
90     return false;
91 
92   const MCSymbol *TargetSymbol;
93   uint64_t TargetOffset;
94   std::tie(TargetSymbol, TargetOffset) =
95       BC.handleAddressRef(Value, Function, /*IsPCRel*/ true);
96 
97   addOperand(TargetSymbol, TargetOffset);
98 
99   return true;
100 }
101 
102 void X86MCSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &CStream,
103                                                       int64_t Value,
104                                                       uint64_t Address) {}
105 
106 } // namespace bolt
107 } // namespace llvm
108