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 const uint64_t Address = Sled.address(); 56 if (Enable) { 57 // lis 0, FuncId[16..32] 58 // li 0, FuncId[0..15] 59 *reinterpret_cast<uint64_t *>(Address) = 60 (0x3c000000ull + (FuncId >> 16)) + 61 ((0x60000000ull + (FuncId & 0xffff)) << 32); 62 } else { 63 // b +JumpOverInstNum instructions. 64 *reinterpret_cast<uint32_t *>(Address) = 65 0x48000000ull + (JumpOverInstNum << 2); 66 } 67 clearCache(reinterpret_cast<void *>(Address), 8); 68 return true; 69 } 70 71 bool patchFunctionExit(const bool Enable, uint32_t FuncId, 72 const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { 73 const uint64_t Address = Sled.address(); 74 if (Enable) { 75 // lis 0, FuncId[16..32] 76 // li 0, FuncId[0..15] 77 *reinterpret_cast<uint64_t *>(Address) = 78 (0x3c000000ull + (FuncId >> 16)) + 79 ((0x60000000ull + (FuncId & 0xffff)) << 32); 80 } else { 81 // Copy the blr/b instruction after JumpOverInstNum instructions. 82 *reinterpret_cast<uint32_t *>(Address) = 83 *(reinterpret_cast<uint32_t *>(Address) + JumpOverInstNum); 84 } 85 clearCache(reinterpret_cast<void *>(Address), 8); 86 return true; 87 } 88 89 bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId, 90 const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { 91 return patchFunctionExit(Enable, FuncId, Sled); 92 } 93 94 // FIXME: Maybe implement this better? 95 bool probeRequiredCPUFeatures() XRAY_NEVER_INSTRUMENT { return true; } 96 97 bool patchCustomEvent(const bool Enable, const uint32_t FuncId, 98 const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { 99 // FIXME: Implement in powerpc64? 100 return false; 101 } 102 103 bool patchTypedEvent(const bool Enable, const uint32_t FuncId, 104 const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { 105 // FIXME: Implement in powerpc64? 106 return false; 107 } 108 109 } // namespace __xray 110 111 extern "C" void __xray_ArgLoggerEntry() XRAY_NEVER_INSTRUMENT { 112 // FIXME: this will have to be implemented in the trampoline assembly file 113 } 114