1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
//===-- xray_powerpc64.cpp --------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is a part of XRay, a dynamic runtime instrumentation system.
//
// Implementation of powerpc64 and powerpc64le routines.
//
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_common.h"
#include "xray_defs.h"
#include "xray_interface_internal.h"
#include "xray_utils.h"
#include <atomic>
#include <cassert>
#include <cstring>
#ifndef __LITTLE_ENDIAN__
#error powerpc64 big endian is not supported for now.
#endif
namespace {
constexpr unsigned long long JumpOverInstNum = 7;
void clearCache(void *Addr, size_t Len) {
const size_t LineSize = 32;
const intptr_t Mask = ~(LineSize - 1);
const intptr_t StartLine = ((intptr_t)Addr) & Mask;
const intptr_t EndLine = ((intptr_t)Addr + Len + LineSize - 1) & Mask;
for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
asm volatile("dcbf 0, %0" : : "r"(Line));
asm volatile("sync");
for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
asm volatile("icbi 0, %0" : : "r"(Line));
asm volatile("isync");
}
} // namespace
extern "C" void __clear_cache(void *start, void *end);
namespace __xray {
bool patchFunctionEntry(const bool Enable, uint32_t FuncId,
const XRaySledEntry &Sled,
const XRayTrampolines &Trampolines,
bool LogArgs) XRAY_NEVER_INSTRUMENT {
// TODO: Trampoline addresses are currently inserted at compile-time, using
// __xray_FunctionEntry and __xray_FunctionExit only.
// To support DSO instrumentation, trampolines have to be written during
// patching (see implementation on X86_64, e.g.).
const uint64_t Address = Sled.address();
if (Enable) {
// lis 0, FuncId[16..32]
// li 0, FuncId[0..15]
*reinterpret_cast<uint64_t *>(Address) =
(0x3c000000ull + (FuncId >> 16)) +
((0x60000000ull + (FuncId & 0xffff)) << 32);
} else {
// b +JumpOverInstNum instructions.
*reinterpret_cast<uint32_t *>(Address) =
0x48000000ull + (JumpOverInstNum << 2);
}
clearCache(reinterpret_cast<void *>(Address), 8);
return true;
}
bool patchFunctionExit(
const bool Enable, uint32_t FuncId, const XRaySledEntry &Sled,
const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT {
// TODO: Trampoline addresses are currently inserted at compile-time, using
// __xray_FunctionEntry and __xray_FunctionExit only.
// To support DSO instrumentation, trampolines have to be written during
// patching (see implementation on X86_64, e.g.).
const uint64_t Address = Sled.address();
if (Enable) {
// lis 0, FuncId[16..32]
// li 0, FuncId[0..15]
*reinterpret_cast<uint64_t *>(Address) =
(0x3c000000ull + (FuncId >> 16)) +
((0x60000000ull + (FuncId & 0xffff)) << 32);
} else {
// Copy the blr/b instruction after JumpOverInstNum instructions.
*reinterpret_cast<uint32_t *>(Address) =
*(reinterpret_cast<uint32_t *>(Address) + JumpOverInstNum);
}
clearCache(reinterpret_cast<void *>(Address), 8);
return true;
}
bool patchFunctionTailExit(
const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled,
const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT {
return patchFunctionExit(Enable, FuncId, Sled, Trampolines);
}
// FIXME: Maybe implement this better?
bool probeRequiredCPUFeatures() XRAY_NEVER_INSTRUMENT { return true; }
bool patchCustomEvent(const bool Enable, const uint32_t FuncId,
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
// FIXME: Implement in powerpc64?
return false;
}
bool patchTypedEvent(const bool Enable, const uint32_t FuncId,
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
// FIXME: Implement in powerpc64?
return false;
}
} // namespace __xray
extern "C" void __xray_ArgLoggerEntry() XRAY_NEVER_INSTRUMENT {
// FIXME: this will have to be implemented in the trampoline assembly file
}
extern "C" void __xray_FunctionTailExit() XRAY_NEVER_INSTRUMENT {
// For PowerPC, calls to __xray_FunctionEntry and __xray_FunctionExit
// are statically inserted into the sled. Tail exits are handled like normal
// function exits. This trampoline is therefore not implemented.
// This stub is placed here to avoid linking issues.
}
|