Path: blob/main/contrib/llvm-project/compiler-rt/lib/xray/xray_hexagon.cpp
35265 views
//===-- xray_hexagon.cpp --------------------------------------*- C++ ---*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file is a part of XRay, a dynamic runtime instrumentation system.9//10// Implementation of hexagon-specific routines (32-bit).11//12//===----------------------------------------------------------------------===//13#include "sanitizer_common/sanitizer_common.h"14#include "xray_defs.h"15#include "xray_interface_internal.h"16#include <assert.h>17#include <atomic>1819namespace __xray {2021// The machine codes for some instructions used in runtime patching.22enum PatchOpcodes : uint32_t {23PO_JUMPI_14 = 0x5800c00a, // jump #0x014 (PC + 0x014)24PO_CALLR_R6 = 0x50a6c000, // indirect call: callr r625PO_TFR_IMM = 0x78000000, // transfer immed26// ICLASS 0x7 - S2-type A-type27PO_IMMEXT = 0x00000000, // constant extender28};2930enum PacketWordParseBits : uint32_t {31PP_DUPLEX = 0x00 << 14,32PP_NOT_END = 0x01 << 14,33PP_PACKET_END = 0x03 << 14,34};3536enum RegNum : uint32_t {37RN_R6 = 0x6,38RN_R7 = 0x7,39};4041inline static uint32_t42encodeExtendedTransferImmediate(uint32_t Imm, RegNum DestReg,43bool PacketEnd = false) XRAY_NEVER_INSTRUMENT {44static const uint32_t REG_MASK = 0x1f;45assert((DestReg & (~REG_MASK)) == 0);46// The constant-extended register transfer encodes the 6 least47// significant bits of the effective constant:48Imm = Imm & 0x03f;49const PacketWordParseBits ParseBits = PacketEnd ? PP_PACKET_END : PP_NOT_END;5051return PO_TFR_IMM | ParseBits | (Imm << 5) | (DestReg & REG_MASK);52}5354inline static uint32_t55encodeConstantExtender(uint32_t Imm) XRAY_NEVER_INSTRUMENT {56// Bits Name Description57// ----- ------- ------------------------------------------58// 31:28 ICLASS Instruction class = 000059// 27:16 high High 12 bits of 26-bit constant extension60// 15:14 Parse Parse bits61// 13:0 low Low 14 bits of 26-bit constant extension62static const uint32_t IMM_MASK_LOW = 0x03fff;63static const uint32_t IMM_MASK_HIGH = 0x00fff << 14;6465// The extender encodes the 26 most significant bits of the effective66// constant:67Imm = Imm >> 6;6869const uint32_t high = (Imm & IMM_MASK_HIGH) << 16;70const uint32_t low = Imm & IMM_MASK_LOW;7172return PO_IMMEXT | high | PP_NOT_END | low;73}7475static void WriteInstFlushCache(void *Addr, uint32_t NewInstruction) {76asm volatile("icinva(%[inst_addr])\n\t"77"isync\n\t"78"memw(%[inst_addr]) = %[new_inst]\n\t"79"dccleaninva(%[inst_addr])\n\t"80"syncht\n\t"81:82: [ inst_addr ] "r"(Addr), [ new_inst ] "r"(NewInstruction)83: "memory");84}8586inline static bool patchSled(const bool Enable, const uint32_t FuncId,87const XRaySledEntry &Sled,88void (*TracingHook)()) XRAY_NEVER_INSTRUMENT {89// When |Enable| == true,90// We replace the following compile-time stub (sled):91//92// .L_xray_sled_N:93// <xray_sled_base>:94// { jump .Ltmp0 }95// { nop96// nop97// nop98// nop }99// .Ltmp0:100101// With the following runtime patch:102//103// xray_sled_n (32-bit):104//105// <xray_sled_n>:106// { immext(#...) // upper 26-bits of func id107// r7 = ##... // lower 6-bits of func id108// immext(#...) // upper 26-bits of trampoline109// r6 = ##... } // lower 6 bits of trampoline110// { callr r6 }111//112// When |Enable|==false, we set back the first instruction in the sled to be113// { jump .Ltmp0 }114115uint32_t *FirstAddress = reinterpret_cast<uint32_t *>(Sled.address());116if (Enable) {117uint32_t *CurAddress = FirstAddress + 1;118*CurAddress = encodeExtendedTransferImmediate(FuncId, RN_R7);119CurAddress++;120*CurAddress = encodeConstantExtender(reinterpret_cast<uint32_t>(TracingHook));121CurAddress++;122*CurAddress =123encodeExtendedTransferImmediate(reinterpret_cast<uint32_t>(TracingHook), RN_R6, true);124CurAddress++;125126*CurAddress = uint32_t(PO_CALLR_R6);127128WriteInstFlushCache(FirstAddress, uint32_t(encodeConstantExtender(FuncId)));129} else {130WriteInstFlushCache(FirstAddress, uint32_t(PatchOpcodes::PO_JUMPI_14));131}132return true;133}134135bool patchFunctionEntry(const bool Enable, const uint32_t FuncId,136const XRaySledEntry &Sled,137void (*Trampoline)()) XRAY_NEVER_INSTRUMENT {138return patchSled(Enable, FuncId, Sled, Trampoline);139}140141bool patchFunctionExit(const bool Enable, const uint32_t FuncId,142const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {143return patchSled(Enable, FuncId, Sled, __xray_FunctionExit);144}145146bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId,147const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {148return patchSled(Enable, FuncId, Sled, __xray_FunctionExit);149}150151bool patchCustomEvent(const bool Enable, const uint32_t FuncId,152const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {153// FIXME: Implement in hexagon?154return false;155}156157bool patchTypedEvent(const bool Enable, const uint32_t FuncId,158const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {159// FIXME: Implement in hexagon?160return false;161}162163} // namespace __xray164165extern "C" void __xray_ArgLoggerEntry() XRAY_NEVER_INSTRUMENT {166// FIXME: this will have to be implemented in the trampoline assembly file167}168169170