LCOV - code coverage report
Current view: top level - lib/Target/AArch64/Disassembler - AArch64ExternalSymbolizer.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 79 100 79.0 %
Date: 2017-09-14 15:23:50 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- AArch64ExternalSymbolizer.cpp - Symbolizer for AArch64 ---*- 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 "AArch64ExternalSymbolizer.h"
      11             : #include "AArch64Subtarget.h"
      12             : #include "MCTargetDesc/AArch64AddressingModes.h"
      13             : #include "Utils/AArch64BaseInfo.h"
      14             : #include "llvm/MC/MCContext.h"
      15             : #include "llvm/MC/MCExpr.h"
      16             : #include "llvm/MC/MCInst.h"
      17             : #include "llvm/Support/Format.h"
      18             : #include "llvm/Support/raw_ostream.h"
      19             : 
      20             : using namespace llvm;
      21             : 
      22             : #define DEBUG_TYPE "aarch64-disassembler"
      23             : 
      24             : static MCSymbolRefExpr::VariantKind
      25             : getVariant(uint64_t LLVMDisassembler_VariantKind) {
      26          17 :   switch (LLVMDisassembler_VariantKind) {
      27             :   case LLVMDisassembler_VariantKind_None:
      28             :     return MCSymbolRefExpr::VK_None;
      29             :   case LLVMDisassembler_VariantKind_ARM64_PAGE:
      30             :     return MCSymbolRefExpr::VK_PAGE;
      31             :   case LLVMDisassembler_VariantKind_ARM64_PAGEOFF:
      32             :     return MCSymbolRefExpr::VK_PAGEOFF;
      33             :   case LLVMDisassembler_VariantKind_ARM64_GOTPAGE:
      34             :     return MCSymbolRefExpr::VK_GOTPAGE;
      35             :   case LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF:
      36             :     return MCSymbolRefExpr::VK_GOTPAGEOFF;
      37           0 :   case LLVMDisassembler_VariantKind_ARM64_TLVP:
      38             :   case LLVMDisassembler_VariantKind_ARM64_TLVOFF:
      39             :   default:
      40           0 :     llvm_unreachable("bad LLVMDisassembler_VariantKind");
      41             :   }
      42             : }
      43             : 
      44             : /// tryAddingSymbolicOperand - tryAddingSymbolicOperand trys to add a symbolic
      45             : /// operand in place of the immediate Value in the MCInst.  The immediate
      46             : /// Value has not had any PC adjustment made by the caller. If the instruction
      47             : /// is a branch that adds the PC to the immediate Value then isBranch is
      48             : /// Success, else Fail. If GetOpInfo is non-null, then it is called to get any
      49             : /// symbolic information at the Address for this instrution.  If that returns
      50             : /// non-zero then the symbolic information it returns is used to create an
      51             : /// MCExpr and that is added as an operand to the MCInst.  If GetOpInfo()
      52             : /// returns zero and isBranch is Success then a symbol look up for
      53             : /// Address + Value is done and if a symbol is found an MCExpr is created with
      54             : /// that, else an MCExpr with Address + Value is created.  If GetOpInfo()
      55             : /// returns zero and isBranch is Fail then the Opcode of the MCInst is
      56             : /// tested and for ADRP an other instructions that help to load of pointers
      57             : /// a symbol look up is done to see it is returns a specific reference type
      58             : /// to add to the comment stream.  This function returns Success if it adds
      59             : /// an operand to the MCInst and Fail otherwise.
      60          64 : bool AArch64ExternalSymbolizer::tryAddingSymbolicOperand(
      61             :     MCInst &MI, raw_ostream &CommentStream, int64_t Value, uint64_t Address,
      62             :     bool IsBranch, uint64_t Offset, uint64_t InstSize) {
      63             :   // FIXME: This method shares a lot of code with
      64             :   //        MCExternalSymbolizer::tryAddingSymbolicOperand. It may be possible
      65             :   //        refactor the MCExternalSymbolizer interface to allow more of this
      66             :   //        implementation to be shared.
      67             :   //
      68             :   struct LLVMOpInfo1 SymbolicOp;
      69          64 :   memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1));
      70          64 :   SymbolicOp.Value = Value;
      71             :   uint64_t ReferenceType;
      72             :   const char *ReferenceName;
      73         128 :   if (!GetOpInfo ||
      74          64 :       !GetOpInfo(DisInfo, Address, 0 /* Offset */, InstSize, 1, &SymbolicOp)) {
      75          48 :     if (IsBranch) {
      76           5 :       ReferenceType = LLVMDisassembler_ReferenceType_In_Branch;
      77           5 :       const char *Name = SymbolLookUp(DisInfo, Address + Value, &ReferenceType,
      78           5 :                                       Address, &ReferenceName);
      79           5 :       if (Name) {
      80           1 :         SymbolicOp.AddSymbol.Name = Name;
      81           1 :         SymbolicOp.AddSymbol.Present = true;
      82           1 :         SymbolicOp.Value = 0;
      83             :       } else {
      84           4 :         SymbolicOp.Value = Address + Value;
      85             :       }
      86           5 :       if (ReferenceType == LLVMDisassembler_ReferenceType_Out_SymbolStub)
      87           2 :         CommentStream << "symbol stub for: " << ReferenceName;
      88           3 :       else if (ReferenceType ==
      89             :                LLVMDisassembler_ReferenceType_Out_Objc_Message)
      90           2 :         CommentStream << "Objc message: " << ReferenceName;
      91          43 :     } else if (MI.getOpcode() == AArch64::ADRP) {
      92           6 :         ReferenceType = LLVMDisassembler_ReferenceType_In_ARM64_ADRP;
      93             :         // otool expects the fully encoded ADRP instruction to be passed in as
      94             :         // the value here, so reconstruct it:
      95           6 :         const MCRegisterInfo &MCRI = *Ctx.getRegisterInfo();
      96           6 :         uint32_t EncodedInst = 0x90000000;
      97           6 :         EncodedInst |= (Value & 0x3) << 29; // immlo
      98           6 :         EncodedInst |= ((Value >> 2) & 0x7FFFF) << 5; // immhi
      99          12 :         EncodedInst |= MCRI.getEncodingValue(MI.getOperand(0).getReg()); // reg
     100           6 :         SymbolLookUp(DisInfo, EncodedInst, &ReferenceType, Address,
     101             :                      &ReferenceName);
     102          12 :         CommentStream << format("0x%llx",
     103           6 :                                 0xfffffffffffff000LL & (Address + Value));
     104          57 :     } else if (MI.getOpcode() == AArch64::ADDXri ||
     105          32 :                MI.getOpcode() == AArch64::LDRXui ||
     106          61 :                MI.getOpcode() == AArch64::LDRXl ||
     107          12 :                MI.getOpcode() == AArch64::ADR) {
     108          25 :       if (MI.getOpcode() == AArch64::ADDXri)
     109          17 :         ReferenceType = LLVMDisassembler_ReferenceType_In_ARM64_ADDXri;
     110           8 :       else if (MI.getOpcode() == AArch64::LDRXui)
     111           8 :         ReferenceType = LLVMDisassembler_ReferenceType_In_ARM64_LDRXui;
     112          25 :       if (MI.getOpcode() == AArch64::LDRXl) {
     113           0 :         ReferenceType = LLVMDisassembler_ReferenceType_In_ARM64_LDRXl;
     114           0 :         SymbolLookUp(DisInfo, Address + Value, &ReferenceType, Address,
     115             :                      &ReferenceName);
     116          25 :       } else if (MI.getOpcode() == AArch64::ADR) {
     117           0 :         ReferenceType = LLVMDisassembler_ReferenceType_In_ARM64_ADR;
     118           0 :         SymbolLookUp(DisInfo, Address + Value, &ReferenceType, Address,
     119             :                             &ReferenceName);
     120             :       } else {
     121          25 :         const MCRegisterInfo &MCRI = *Ctx.getRegisterInfo();
     122             :         // otool expects the fully encoded ADD/LDR instruction to be passed in
     123             :         // as the value here, so reconstruct it:
     124             :         unsigned EncodedInst =
     125          25 :           MI.getOpcode() == AArch64::ADDXri ? 0x91000000: 0xF9400000;
     126          25 :         EncodedInst |= Value << 10; // imm12 [+ shift:2 for ADD]
     127          25 :         EncodedInst |=
     128          50 :           MCRI.getEncodingValue(MI.getOperand(1).getReg()) << 5; // Rn
     129          50 :         EncodedInst |= MCRI.getEncodingValue(MI.getOperand(0).getReg()); // Rd
     130             : 
     131          25 :         SymbolLookUp(DisInfo, EncodedInst, &ReferenceType, Address,
     132             :                      &ReferenceName);
     133             :       }
     134          25 :       if (ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr)
     135           0 :         CommentStream << "literal pool symbol address: " << ReferenceName;
     136          25 :       else if (ReferenceType ==
     137             :                LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr) {
     138           1 :         CommentStream << "literal pool for: \"";
     139           2 :         CommentStream.write_escaped(ReferenceName);
     140           1 :         CommentStream << "\"";
     141          24 :       } else if (ReferenceType ==
     142             :                LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref)
     143           1 :         CommentStream << "Objc cfstring ref: @\"" << ReferenceName << "\"";
     144          23 :       else if (ReferenceType ==
     145             :                LLVMDisassembler_ReferenceType_Out_Objc_Message)
     146           0 :         CommentStream << "Objc message: " << ReferenceName;
     147          23 :       else if (ReferenceType ==
     148             :                LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref)
     149           0 :         CommentStream << "Objc message ref: " << ReferenceName;
     150          23 :       else if (ReferenceType ==
     151             :                LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref)
     152           2 :         CommentStream << "Objc selector ref: " << ReferenceName;
     153          21 :       else if (ReferenceType ==
     154             :                LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref)
     155           2 :         CommentStream << "Objc class ref: " << ReferenceName;
     156             :       // For these instructions, the SymbolLookUp() above is just to get the
     157             :       // ReferenceType and ReferenceName.  We want to make sure not to
     158             :       // fall through so we don't build an MCExpr to leave the disassembly
     159             :       // of the immediate values of these instructions to the InstPrinter.
     160             :       return false;
     161             :     } else {
     162             :       return false;
     163             :     }
     164             :   }
     165             : 
     166          27 :   const MCExpr *Add = nullptr;
     167          27 :   if (SymbolicOp.AddSymbol.Present) {
     168          17 :     if (SymbolicOp.AddSymbol.Name) {
     169          34 :       StringRef Name(SymbolicOp.AddSymbol.Name);
     170          34 :       MCSymbol *Sym = Ctx.getOrCreateSymbol(Name);
     171          17 :       MCSymbolRefExpr::VariantKind Variant = getVariant(SymbolicOp.VariantKind);
     172             :       if (Variant != MCSymbolRefExpr::VK_None)
     173          12 :         Add = MCSymbolRefExpr::create(Sym, Variant, Ctx);
     174             :       else
     175          10 :         Add = MCSymbolRefExpr::create(Sym, Ctx);
     176             :     } else {
     177           0 :       Add = MCConstantExpr::create(SymbolicOp.AddSymbol.Value, Ctx);
     178             :     }
     179             :   }
     180             : 
     181          27 :   const MCExpr *Sub = nullptr;
     182          27 :   if (SymbolicOp.SubtractSymbol.Present) {
     183           0 :     if (SymbolicOp.SubtractSymbol.Name) {
     184           0 :       StringRef Name(SymbolicOp.SubtractSymbol.Name);
     185           0 :       MCSymbol *Sym = Ctx.getOrCreateSymbol(Name);
     186           0 :       Sub = MCSymbolRefExpr::create(Sym, Ctx);
     187             :     } else {
     188           0 :       Sub = MCConstantExpr::create(SymbolicOp.SubtractSymbol.Value, Ctx);
     189             :     }
     190             :   }
     191             : 
     192          27 :   const MCExpr *Off = nullptr;
     193          27 :   if (SymbolicOp.Value != 0)
     194           9 :     Off = MCConstantExpr::create(SymbolicOp.Value, Ctx);
     195             : 
     196             :   const MCExpr *Expr;
     197          27 :   if (Sub) {
     198             :     const MCExpr *LHS;
     199           0 :     if (Add)
     200           0 :       LHS = MCBinaryExpr::createSub(Add, Sub, Ctx);
     201             :     else
     202           0 :       LHS = MCUnaryExpr::createMinus(Sub, Ctx);
     203           0 :     if (Off)
     204           0 :       Expr = MCBinaryExpr::createAdd(LHS, Off, Ctx);
     205             :     else
     206             :       Expr = LHS;
     207          27 :   } else if (Add) {
     208          17 :     if (Off)
     209           0 :       Expr = MCBinaryExpr::createAdd(Add, Off, Ctx);
     210             :     else
     211             :       Expr = Add;
     212             :   } else {
     213          10 :     if (Off)
     214             :       Expr = Off;
     215             :     else
     216           1 :       Expr = MCConstantExpr::create(0, Ctx);
     217             :   }
     218             : 
     219          54 :   MI.addOperand(MCOperand::createExpr(Expr));
     220             : 
     221          27 :   return true;
     222             : }

Generated by: LCOV version 1.13