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