1 //===-- xray_powerpc64.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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of XRay, a dynamic runtime instrumentation system. 10 // 11 // Implementation of powerpc64 and powerpc64le routines. 12 // 13 //===----------------------------------------------------------------------===// 14 #include "sanitizer_common/sanitizer_common.h" 15 #include "xray_defs.h" 16 #include "xray_interface_internal.h" 17 #include "xray_utils.h" 18 #include <atomic> 19 #include <cassert> 20 #include <cstring> 21 22 #ifndef __LITTLE_ENDIAN__ 23 #error powerpc64 big endian is not supported for now. 24 #endif 25 26 namespace { 27 28 constexpr unsigned long long JumpOverInstNum = 7; 29 30 void clearCache(void *Addr, size_t Len) { 31 const size_t LineSize = 32; 32 33 const intptr_t Mask = ~(LineSize - 1); 34 const intptr_t StartLine = ((intptr_t)Addr) & Mask; 35 const intptr_t EndLine = ((intptr_t)Addr + Len + LineSize - 1) & Mask; 36 37 for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) 38 asm volatile("dcbf 0, %0" : : "r"(Line)); 39 asm volatile("sync"); 40 41 for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) 42 asm volatile("icbi 0, %0" : : "r"(Line)); 43 asm volatile("isync"); 44 } 45 46 } // namespace 47 48 extern "C" void __clear_cache(void *start, void *end); 49 50 namespace __xray { 51 52 bool patchFunctionEntry(const bool Enable, uint32_t FuncId, 53 const XRaySledEntry &Sled, 54 void (*Trampoline)()) XRAY_NEVER_INSTRUMENT { 55 if (Enable) { 56 // lis 0, FuncId[16..32] 57 // li 0, FuncId[0..15] 58 *reinterpret_cast<uint64_t *>(Sled.Address) = 59 (0x3c000000ull + (FuncId >> 16)) + 60 ((0x60000000ull + (FuncId & 0xffff)) << 32); 61 } else { 62 // b +JumpOverInstNum instructions. 63 *reinterpret_cast<uint32_t *>(Sled.Address) = 64 0x48000000ull + (JumpOverInstNum << 2); 65 } 66 clearCache(reinterpret_cast<void *>(Sled.Address), 8); 67 return true; 68 } 69 70 bool patchFunctionExit(const bool Enable, uint32_t FuncId, 71 const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { 72 if (Enable) { 73 // lis 0, FuncId[16..32] 74 // li 0, FuncId[0..15] 75 *reinterpret_cast<uint64_t *>(Sled.Address) = 76 (0x3c000000ull + (FuncId >> 16)) + 77 ((0x60000000ull + (FuncId & 0xffff)) << 32); 78 } else { 79 // Copy the blr/b instruction after JumpOverInstNum instructions. 80 *reinterpret_cast<uint32_t *>(Sled.Address) = 81 *(reinterpret_cast<uint32_t *>(Sled.Address) + JumpOverInstNum); 82 } 83 clearCache(reinterpret_cast<void *>(Sled.Address), 8); 84 return true; 85 } 86 87 bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId, 88 const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { 89 return patchFunctionExit(Enable, FuncId, Sled); 90 } 91 92 // FIXME: Maybe implement this better? 93 bool probeRequiredCPUFeatures() XRAY_NEVER_INSTRUMENT { return true; } 94 95 bool patchCustomEvent(const bool Enable, const uint32_t FuncId, 96 const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { 97 // FIXME: Implement in powerpc64? 98 return false; 99 } 100 101 bool patchTypedEvent(const bool Enable, const uint32_t FuncId, 102 const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { 103 // FIXME: Implement in powerpc64? 104 return false; 105 } 106 107 } // namespace __xray 108 109 extern "C" void __xray_ArgLoggerEntry() XRAY_NEVER_INSTRUMENT { 110 // FIXME: this will have to be implemented in the trampoline assembly file 111 } 112