brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.8 KiB · 1c07bb0 Raw
174 lines · cpp
1//===-- xray_hexagon.cpp --------------------------------------*- C++ ---*-===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of XRay, a dynamic runtime instrumentation system.10//11// Implementation of hexagon-specific routines (32-bit).12//13//===----------------------------------------------------------------------===//14#include "sanitizer_common/sanitizer_common.h"15#include "xray_defs.h"16#include "xray_interface_internal.h"17#include <assert.h>18#include <atomic>19 20namespace __xray {21 22// The machine codes for some instructions used in runtime patching.23enum PatchOpcodes : uint32_t {24  PO_JUMPI_14 = 0x5800c00a, // jump #0x014 (PC + 0x014)25  PO_CALLR_R6 = 0x50a6c000, // indirect call: callr r626  PO_TFR_IMM = 0x78000000,  // transfer immed27                            // ICLASS 0x7 - S2-type A-type28  PO_IMMEXT = 0x00000000, // constant extender29};30 31enum PacketWordParseBits : uint32_t {32  PP_DUPLEX = 0x00 << 14,33  PP_NOT_END = 0x01 << 14,34  PP_PACKET_END = 0x03 << 14,35};36 37enum RegNum : uint32_t {38  RN_R6 = 0x6,39  RN_R7 = 0x7,40};41 42inline static uint32_t43encodeExtendedTransferImmediate(uint32_t Imm, RegNum DestReg,44                                bool PacketEnd = false) XRAY_NEVER_INSTRUMENT {45  static const uint32_t REG_MASK = 0x1f;46  assert((DestReg & (~REG_MASK)) == 0);47  // The constant-extended register transfer encodes the 6 least48  // significant bits of the effective constant:49  Imm = Imm & 0x03f;50  const PacketWordParseBits ParseBits = PacketEnd ? PP_PACKET_END : PP_NOT_END;51 52  return PO_TFR_IMM | ParseBits | (Imm << 5) | (DestReg & REG_MASK);53}54 55inline static uint32_t56encodeConstantExtender(uint32_t Imm) XRAY_NEVER_INSTRUMENT {57  // Bits   Name      Description58  // -----  -------   ------------------------------------------59  // 31:28  ICLASS    Instruction class = 000060  // 27:16  high      High 12 bits of 26-bit constant extension61  // 15:14  Parse     Parse bits62  // 13:0   low       Low 14 bits of 26-bit constant extension63  static const uint32_t IMM_MASK_LOW = 0x03fff;64  static const uint32_t IMM_MASK_HIGH = 0x00fff << 14;65 66  // The extender encodes the 26 most significant bits of the effective67  // constant:68  Imm = Imm >> 6;69 70  const uint32_t high = (Imm & IMM_MASK_HIGH) << 16;71  const uint32_t low = Imm & IMM_MASK_LOW;72 73  return PO_IMMEXT | high | PP_NOT_END | low;74}75 76static void WriteInstFlushCache(void *Addr, uint32_t NewInstruction) {77  asm volatile("icinva(%[inst_addr])\n\t"78               "isync\n\t"79               "memw(%[inst_addr]) = %[new_inst]\n\t"80               "dccleaninva(%[inst_addr])\n\t"81               "syncht\n\t"82               :83               : [ inst_addr ] "r"(Addr), [ new_inst ] "r"(NewInstruction)84               : "memory");85}86 87inline static bool patchSled(const bool Enable, const uint32_t FuncId,88                             const XRaySledEntry &Sled,89                             void (*TracingHook)()) XRAY_NEVER_INSTRUMENT {90  // When |Enable| == true,91  // We replace the following compile-time stub (sled):92  //93  // .L_xray_sled_N:94  // <xray_sled_base>:95  // {  jump .Ltmp0 }96  // {  nop97  //    nop98  //    nop99  //    nop }100  // .Ltmp0:101 102  // With the following runtime patch:103  //104  // xray_sled_n (32-bit):105  //106  // <xray_sled_n>:107  // {  immext(#...) // upper 26-bits of func id108  //    r7 = ##...   // lower  6-bits of func id109  //    immext(#...) // upper 26-bits of trampoline110  //    r6 = ##... }  // lower 6 bits of trampoline111  // {  callr r6 }112  //113  // When |Enable|==false, we set back the first instruction in the sled to be114  // {  jump .Ltmp0 }115 116  uint32_t *FirstAddress = reinterpret_cast<uint32_t *>(Sled.address());117  if (Enable) {118    uint32_t *CurAddress = FirstAddress + 1;119    *CurAddress = encodeExtendedTransferImmediate(FuncId, RN_R7);120    CurAddress++;121    *CurAddress = encodeConstantExtender(reinterpret_cast<uint32_t>(TracingHook));122    CurAddress++;123    *CurAddress =124        encodeExtendedTransferImmediate(reinterpret_cast<uint32_t>(TracingHook), RN_R6, true);125    CurAddress++;126 127    *CurAddress = uint32_t(PO_CALLR_R6);128 129    WriteInstFlushCache(FirstAddress, uint32_t(encodeConstantExtender(FuncId)));130  } else {131    WriteInstFlushCache(FirstAddress, uint32_t(PatchOpcodes::PO_JUMPI_14));132  }133  return true;134}135 136bool patchFunctionEntry(const bool Enable, const uint32_t FuncId,137                        const XRaySledEntry &Sled,138                        const XRayTrampolines &Trampolines,139                        bool LogArgs) XRAY_NEVER_INSTRUMENT {140  auto Trampoline =141      LogArgs ? Trampolines.LogArgsTrampoline : Trampolines.EntryTrampoline;142  return patchSled(Enable, FuncId, Sled, Trampoline);143}144 145bool patchFunctionExit(146    const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled,147    const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT {148  return patchSled(Enable, FuncId, Sled, Trampolines.ExitTrampoline);149}150 151bool patchFunctionTailExit(152    const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled,153    const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT {154  return patchSled(Enable, FuncId, Sled, Trampolines.TailExitTrampoline);155}156 157bool patchCustomEvent(const bool Enable, const uint32_t FuncId,158                      const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {159  // FIXME: Implement in hexagon?160  return false;161}162 163bool patchTypedEvent(const bool Enable, const uint32_t FuncId,164                     const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {165  // FIXME: Implement in hexagon?166  return false;167}168 169} // namespace __xray170 171extern "C" void __xray_ArgLoggerEntry() XRAY_NEVER_INSTRUMENT {172  // FIXME: this will have to be implemented in the trampoline assembly file173}174