| //===-- xray_interface_internal.h -------------------------------*- 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 the API functions. See also include/xray/xray_interface.h. |
| // |
| //===----------------------------------------------------------------------===// |
| #ifndef XRAY_INTERFACE_INTERNAL_H |
| #define XRAY_INTERFACE_INTERNAL_H |
| |
| #include "sanitizer_common/sanitizer_platform.h" |
| #include "xray/xray_interface.h" |
| #include <cstddef> |
| #include <cstdint> |
| #include <utility> |
| |
| extern "C" { |
| // The following functions have to be defined in assembler, on a per-platform |
| // basis. See xray_trampoline_*.S files for implementations. |
| extern void __xray_FunctionEntry(); |
| extern void __xray_FunctionExit(); |
| extern void __xray_FunctionTailExit(); |
| extern void __xray_ArgLoggerEntry(); |
| extern void __xray_CustomEvent(); |
| extern void __xray_TypedEvent(); |
| } |
| |
| extern "C" { |
| |
| struct XRaySledEntry { |
| #if SANITIZER_WORDSIZE == 64 |
| uint64_t Address; |
| uint64_t Function; |
| unsigned char Kind; |
| unsigned char AlwaysInstrument; |
| unsigned char Version; |
| unsigned char Padding[13]; // Need 32 bytes |
| uint64_t function() const { |
| // The target address is relative to the location of the Function variable. |
| return reinterpret_cast<uint64_t>(&Function) + Function; |
| } |
| uint64_t address() const { |
| // The target address is relative to the location of the Address variable. |
| return reinterpret_cast<uint64_t>(&Address) + Address; |
| } |
| #elif SANITIZER_WORDSIZE == 32 |
| uint32_t Address; |
| uint32_t Function; |
| unsigned char Kind; |
| unsigned char AlwaysInstrument; |
| unsigned char Version; |
| unsigned char Padding[5]; // Need 16 bytes |
| uint32_t function() const { |
| // The target address is relative to the location of the Function variable. |
| return reinterpret_cast<uint32_t>(&Function) + Function; |
| } |
| uint32_t address() const { |
| // The target address is relative to the location of the Address variable. |
| return reinterpret_cast<uint32_t>(&Address) + Address; |
| } |
| #else |
| #error "Unsupported word size." |
| #endif |
| }; |
| |
| struct XRayFunctionSledIndex { |
| const XRaySledEntry *Begin; |
| size_t Size; |
| // For an entry in the xray_fn_idx section, the address is relative to the |
| // location of the Begin variable. |
| const XRaySledEntry *fromPCRelative() const { |
| return reinterpret_cast<const XRaySledEntry *>(uintptr_t(&Begin) + |
| uintptr_t(Begin)); |
| } |
| }; |
| |
| struct XRayTrampolines { |
| void (*EntryTrampoline)(); |
| void (*ExitTrampoline)(); |
| void (*TailExitTrampoline)(); |
| void (*LogArgsTrampoline)(); |
| |
| XRayTrampolines() { |
| // These resolve to the definitions in the respective executable or DSO. |
| EntryTrampoline = __xray_FunctionEntry; |
| ExitTrampoline = __xray_FunctionExit; |
| TailExitTrampoline = __xray_FunctionTailExit; |
| LogArgsTrampoline = __xray_ArgLoggerEntry; |
| } |
| }; |
| |
| extern int32_t __xray_register_dso(const XRaySledEntry *SledsBegin, |
| const XRaySledEntry *SledsEnd, |
| const XRayFunctionSledIndex *FnIndexBegin, |
| const XRayFunctionSledIndex *FnIndexEnd, |
| XRayTrampolines Trampolines); |
| |
| extern bool __xray_deregister_dso(int32_t ObjId); |
| } |
| |
| namespace __xray { |
| |
| constexpr uint32_t XRayNFnBits = 24; |
| constexpr uint32_t XRayNObjBits = 8; |
| |
| constexpr uint32_t XRayFnBitMask = 0x00FFFFFF; |
| constexpr uint32_t XRayObjBitMask = 0xFF000000; |
| |
| constexpr size_t XRayMaxFunctions = 1 << XRayNFnBits; |
| constexpr size_t XRayMaxObjects = 1 << XRayNObjBits; |
| |
| inline int32_t MakePackedId(int32_t FnId, int32_t ObjId) { |
| return ((ObjId << XRayNFnBits) & XRayObjBitMask) | (FnId & XRayFnBitMask); |
| } |
| |
| inline std::pair<int32_t, int32_t> UnpackId(int32_t PackedId) { |
| uint32_t ObjId = (PackedId & XRayObjBitMask) >> XRayNFnBits; |
| uint32_t FnId = PackedId & XRayFnBitMask; |
| return {ObjId, FnId}; |
| } |
| |
| struct XRaySledMap { |
| const XRaySledEntry *Sleds; |
| size_t Entries; |
| const XRayFunctionSledIndex *SledsIndex; |
| size_t Functions; |
| XRayTrampolines Trampolines; |
| bool FromDSO; |
| bool Loaded; |
| }; |
| |
| bool patchFunctionEntry(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled, |
| const XRayTrampolines &Trampolines, bool LogArgs); |
| bool patchFunctionExit(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled, |
| const XRayTrampolines &Trampolines); |
| bool patchFunctionTailExit(bool Enable, uint32_t FuncId, |
| const XRaySledEntry &Sled, |
| const XRayTrampolines &Trampolines); |
| bool patchCustomEvent(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled); |
| bool patchTypedEvent(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled); |
| |
| } // namespace __xray |
| |
| #endif |