xref: /freebsd/contrib/llvm-project/compiler-rt/lib/xray/xray_s390x.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===-- xray_s390x.cpp ------------------------------------------*- C++ -*-===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric // This file is a part of XRay, a dynamic runtime instrumentation system.
10*700637cbSDimitry Andric //
11*700637cbSDimitry Andric // Implementation of s390x routines.
12*700637cbSDimitry Andric //
13*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
14*700637cbSDimitry Andric #include "sanitizer_common/sanitizer_common.h"
15*700637cbSDimitry Andric #include "xray_defs.h"
16*700637cbSDimitry Andric #include "xray_interface_internal.h"
17*700637cbSDimitry Andric #include <cassert>
18*700637cbSDimitry Andric #include <cstring>
19*700637cbSDimitry Andric 
patchFunctionEntry(const bool Enable,const uint32_t FuncId,const XRaySledEntry & Sled,const XRayTrampolines & Trampolines,bool LogArgs)20*700637cbSDimitry Andric bool __xray::patchFunctionEntry(const bool Enable, const uint32_t FuncId,
21*700637cbSDimitry Andric                                 const XRaySledEntry &Sled,
22*700637cbSDimitry Andric                                 const XRayTrampolines &Trampolines,
23*700637cbSDimitry Andric                                 bool LogArgs) XRAY_NEVER_INSTRUMENT {
24*700637cbSDimitry Andric   uint32_t *Address = reinterpret_cast<uint32_t *>(Sled.address());
25*700637cbSDimitry Andric   // TODO: Trampoline addresses are currently inserted at compile-time, using
26*700637cbSDimitry Andric   //       __xray_FunctionEntry and __xray_FunctionExit only.
27*700637cbSDimitry Andric   //       To support DSO instrumentation, trampolines have to be written during
28*700637cbSDimitry Andric   //       patching (see implementation on X86_64, e.g.).
29*700637cbSDimitry Andric   if (Enable) {
30*700637cbSDimitry Andric     // The resulting code is:
31*700637cbSDimitry Andric     //   stmg    %r2, %r15, 16(%r15)
32*700637cbSDimitry Andric     //   llilf   %2, FuncID
33*700637cbSDimitry Andric     //   brasl   %r14, __xray_FunctionEntry@GOT
34*700637cbSDimitry Andric     // The FuncId and the stmg instruction must be written.
35*700637cbSDimitry Andric 
36*700637cbSDimitry Andric     // Write FuncId into llilf.
37*700637cbSDimitry Andric     Address[2] = FuncId;
38*700637cbSDimitry Andric     // Write last part of stmg.
39*700637cbSDimitry Andric     reinterpret_cast<uint16_t *>(Address)[2] = 0x24;
40*700637cbSDimitry Andric     // Write first part of stmg.
41*700637cbSDimitry Andric     Address[0] = 0xeb2ff010;
42*700637cbSDimitry Andric   } else {
43*700637cbSDimitry Andric     // j +16 instructions.
44*700637cbSDimitry Andric     Address[0] = 0xa7f4000b;
45*700637cbSDimitry Andric   }
46*700637cbSDimitry Andric   return true;
47*700637cbSDimitry Andric }
48*700637cbSDimitry Andric 
patchFunctionExit(const bool Enable,const uint32_t FuncId,const XRaySledEntry & Sled,const XRayTrampolines & Trampolines)49*700637cbSDimitry Andric bool __xray::patchFunctionExit(
50*700637cbSDimitry Andric     const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled,
51*700637cbSDimitry Andric     const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT {
52*700637cbSDimitry Andric   uint32_t *Address = reinterpret_cast<uint32_t *>(Sled.address());
53*700637cbSDimitry Andric   // TODO: Trampoline addresses are currently inserted at compile-time, using
54*700637cbSDimitry Andric   //       __xray_FunctionEntry and __xray_FunctionExit only.
55*700637cbSDimitry Andric   //       To support DSO instrumentation, trampolines have to be written during
56*700637cbSDimitry Andric   //       patching (see implementation on X86_64, e.g.).
57*700637cbSDimitry Andric   if (Enable) {
58*700637cbSDimitry Andric     // The resulting code is:
59*700637cbSDimitry Andric     //   stmg    %r2, %r15, 24(%r15)
60*700637cbSDimitry Andric     //   llilf   %2,FuncID
61*700637cbSDimitry Andric     //   j       __xray_FunctionEntry@GOT
62*700637cbSDimitry Andric     // The FuncId and the stmg instruction must be written.
63*700637cbSDimitry Andric 
64*700637cbSDimitry Andric     // Write FuncId into llilf.
65*700637cbSDimitry Andric     Address[2] = FuncId;
66*700637cbSDimitry Andric     // Write last part of of stmg.
67*700637cbSDimitry Andric     reinterpret_cast<uint16_t *>(Address)[2] = 0x24;
68*700637cbSDimitry Andric     // Write first part of stmg.
69*700637cbSDimitry Andric     Address[0] = 0xeb2ff010;
70*700637cbSDimitry Andric   } else {
71*700637cbSDimitry Andric     // br %14 instruction.
72*700637cbSDimitry Andric     reinterpret_cast<uint16_t *>(Address)[0] = 0x07fe;
73*700637cbSDimitry Andric   }
74*700637cbSDimitry Andric   return true;
75*700637cbSDimitry Andric }
76*700637cbSDimitry Andric 
patchFunctionTailExit(const bool Enable,const uint32_t FuncId,const XRaySledEntry & Sled,const XRayTrampolines & Trampolines)77*700637cbSDimitry Andric bool __xray::patchFunctionTailExit(
78*700637cbSDimitry Andric     const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled,
79*700637cbSDimitry Andric     const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT {
80*700637cbSDimitry Andric   return patchFunctionExit(Enable, FuncId, Sled, Trampolines);
81*700637cbSDimitry Andric }
82*700637cbSDimitry Andric 
patchCustomEvent(const bool Enable,const uint32_t FuncId,const XRaySledEntry & Sled)83*700637cbSDimitry Andric bool __xray::patchCustomEvent(const bool Enable, const uint32_t FuncId,
84*700637cbSDimitry Andric                               const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
85*700637cbSDimitry Andric   // TODO Implement.
86*700637cbSDimitry Andric   return false;
87*700637cbSDimitry Andric }
88*700637cbSDimitry Andric 
patchTypedEvent(const bool Enable,const uint32_t FuncId,const XRaySledEntry & Sled)89*700637cbSDimitry Andric bool __xray::patchTypedEvent(const bool Enable, const uint32_t FuncId,
90*700637cbSDimitry Andric                              const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
91*700637cbSDimitry Andric   // TODO Implement.
92*700637cbSDimitry Andric   return false;
93*700637cbSDimitry Andric }
94*700637cbSDimitry Andric 
__xray_ArgLoggerEntry()95*700637cbSDimitry Andric extern "C" void __xray_ArgLoggerEntry() XRAY_NEVER_INSTRUMENT {
96*700637cbSDimitry Andric   // TODO this will have to be implemented in the trampoline assembly file.
97*700637cbSDimitry Andric }
98*700637cbSDimitry Andric 
__xray_FunctionTailExit()99*700637cbSDimitry Andric extern "C" void __xray_FunctionTailExit() XRAY_NEVER_INSTRUMENT {
100*700637cbSDimitry Andric   // For PowerPC, calls to __xray_FunctionEntry and __xray_FunctionExit
101*700637cbSDimitry Andric   // are statically inserted into the sled. Tail exits are handled like normal
102*700637cbSDimitry Andric   // function exits. This trampoline is therefore not implemented.
103*700637cbSDimitry Andric   // This stub is placed here to avoid linking issues.
104*700637cbSDimitry Andric }
105