Home | History | Annotate | Line # | Download | only in xray
      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