Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/compiler-rt/lib/xray/xray_mips64.cpp
35265 views
1
//===-- xray_mips64.cpp -----------------------------------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file is a part of XRay, a dynamic runtime instrumentation system.
10
//
11
// Implementation of MIPS64-specific routines.
12
//
13
//===----------------------------------------------------------------------===//
14
#include "sanitizer_common/sanitizer_common.h"
15
#include "xray_defs.h"
16
#include "xray_interface_internal.h"
17
#include <atomic>
18
19
namespace __xray {
20
21
// The machine codes for some instructions used in runtime patching.
22
enum PatchOpcodes : uint32_t {
23
PO_DADDIU = 0x64000000, // daddiu rt, rs, imm
24
PO_SD = 0xFC000000, // sd rt, base(offset)
25
PO_LUI = 0x3C000000, // lui rt, imm
26
PO_ORI = 0x34000000, // ori rt, rs, imm
27
PO_DSLL = 0x00000038, // dsll rd, rt, sa
28
PO_JALR = 0x00000009, // jalr rs
29
PO_LD = 0xDC000000, // ld rt, base(offset)
30
PO_B60 = 0x1000000f, // b #60
31
PO_NOP = 0x0, // nop
32
};
33
34
enum RegNum : uint32_t {
35
RN_T0 = 0xC,
36
RN_T9 = 0x19,
37
RN_RA = 0x1F,
38
RN_SP = 0x1D,
39
};
40
41
inline static uint32_t encodeInstruction(uint32_t Opcode, uint32_t Rs,
42
uint32_t Rt,
43
uint32_t Imm) XRAY_NEVER_INSTRUMENT {
44
return (Opcode | Rs << 21 | Rt << 16 | Imm);
45
}
46
47
inline static uint32_t
48
encodeSpecialInstruction(uint32_t Opcode, uint32_t Rs, uint32_t Rt, uint32_t Rd,
49
uint32_t Imm) XRAY_NEVER_INSTRUMENT {
50
return (Rs << 21 | Rt << 16 | Rd << 11 | Imm << 6 | Opcode);
51
}
52
53
inline static bool patchSled(const bool Enable, const uint32_t FuncId,
54
const XRaySledEntry &Sled,
55
void (*TracingHook)()) XRAY_NEVER_INSTRUMENT {
56
// When |Enable| == true,
57
// We replace the following compile-time stub (sled):
58
//
59
// xray_sled_n:
60
// B .tmpN
61
// 15 NOPs (60 bytes)
62
// .tmpN
63
//
64
// With the following runtime patch:
65
//
66
// xray_sled_n (64-bit):
67
// daddiu sp, sp, -16 ;create stack frame
68
// nop
69
// sd ra, 8(sp) ;save return address
70
// sd t9, 0(sp) ;save register t9
71
// lui t9, %highest(__xray_FunctionEntry/Exit)
72
// ori t9, t9, %higher(__xray_FunctionEntry/Exit)
73
// dsll t9, t9, 16
74
// ori t9, t9, %hi(__xray_FunctionEntry/Exit)
75
// dsll t9, t9, 16
76
// ori t9, t9, %lo(__xray_FunctionEntry/Exit)
77
// lui t0, %hi(function_id)
78
// jalr t9 ;call Tracing hook
79
// ori t0, t0, %lo(function_id) ;pass function id (delay slot)
80
// ld t9, 0(sp) ;restore register t9
81
// ld ra, 8(sp) ;restore return address
82
// daddiu sp, sp, 16 ;delete stack frame
83
//
84
// Replacement of the first 4-byte instruction should be the last and atomic
85
// operation, so that the user code which reaches the sled concurrently
86
// either jumps over the whole sled, or executes the whole sled when the
87
// latter is ready.
88
//
89
// When |Enable|==false, we set back the first instruction in the sled to be
90
// B #60
91
92
uint32_t *Address = reinterpret_cast<uint32_t *>(Sled.address());
93
if (Enable) {
94
uint32_t LoTracingHookAddr =
95
reinterpret_cast<int64_t>(TracingHook) & 0xffff;
96
uint32_t HiTracingHookAddr =
97
(reinterpret_cast<int64_t>(TracingHook) >> 16) & 0xffff;
98
uint32_t HigherTracingHookAddr =
99
(reinterpret_cast<int64_t>(TracingHook) >> 32) & 0xffff;
100
uint32_t HighestTracingHookAddr =
101
(reinterpret_cast<int64_t>(TracingHook) >> 48) & 0xffff;
102
uint32_t LoFunctionID = FuncId & 0xffff;
103
uint32_t HiFunctionID = (FuncId >> 16) & 0xffff;
104
Address[2] = encodeInstruction(PatchOpcodes::PO_SD, RegNum::RN_SP,
105
RegNum::RN_RA, 0x8);
106
Address[3] = encodeInstruction(PatchOpcodes::PO_SD, RegNum::RN_SP,
107
RegNum::RN_T9, 0x0);
108
Address[4] = encodeInstruction(PatchOpcodes::PO_LUI, 0x0, RegNum::RN_T9,
109
HighestTracingHookAddr);
110
Address[5] = encodeInstruction(PatchOpcodes::PO_ORI, RegNum::RN_T9,
111
RegNum::RN_T9, HigherTracingHookAddr);
112
Address[6] = encodeSpecialInstruction(PatchOpcodes::PO_DSLL, 0x0,
113
RegNum::RN_T9, RegNum::RN_T9, 0x10);
114
Address[7] = encodeInstruction(PatchOpcodes::PO_ORI, RegNum::RN_T9,
115
RegNum::RN_T9, HiTracingHookAddr);
116
Address[8] = encodeSpecialInstruction(PatchOpcodes::PO_DSLL, 0x0,
117
RegNum::RN_T9, RegNum::RN_T9, 0x10);
118
Address[9] = encodeInstruction(PatchOpcodes::PO_ORI, RegNum::RN_T9,
119
RegNum::RN_T9, LoTracingHookAddr);
120
Address[10] = encodeInstruction(PatchOpcodes::PO_LUI, 0x0, RegNum::RN_T0,
121
HiFunctionID);
122
Address[11] = encodeSpecialInstruction(PatchOpcodes::PO_JALR, RegNum::RN_T9,
123
0x0, RegNum::RN_RA, 0X0);
124
Address[12] = encodeInstruction(PatchOpcodes::PO_ORI, RegNum::RN_T0,
125
RegNum::RN_T0, LoFunctionID);
126
Address[13] = encodeInstruction(PatchOpcodes::PO_LD, RegNum::RN_SP,
127
RegNum::RN_T9, 0x0);
128
Address[14] = encodeInstruction(PatchOpcodes::PO_LD, RegNum::RN_SP,
129
RegNum::RN_RA, 0x8);
130
Address[15] = encodeInstruction(PatchOpcodes::PO_DADDIU, RegNum::RN_SP,
131
RegNum::RN_SP, 0x10);
132
uint32_t CreateStackSpace = encodeInstruction(
133
PatchOpcodes::PO_DADDIU, RegNum::RN_SP, RegNum::RN_SP, 0xfff0);
134
std::atomic_store_explicit(
135
reinterpret_cast<std::atomic<uint32_t> *>(Address), CreateStackSpace,
136
std::memory_order_release);
137
} else {
138
std::atomic_store_explicit(
139
reinterpret_cast<std::atomic<uint32_t> *>(Address),
140
uint32_t(PatchOpcodes::PO_B60), std::memory_order_release);
141
}
142
return true;
143
}
144
145
bool patchFunctionEntry(const bool Enable, const uint32_t FuncId,
146
const XRaySledEntry &Sled,
147
void (*Trampoline)()) XRAY_NEVER_INSTRUMENT {
148
return patchSled(Enable, FuncId, Sled, Trampoline);
149
}
150
151
bool patchFunctionExit(const bool Enable, const uint32_t FuncId,
152
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
153
return patchSled(Enable, FuncId, Sled, __xray_FunctionExit);
154
}
155
156
bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId,
157
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
158
// FIXME: In the future we'd need to distinguish between non-tail exits and
159
// tail exits for better information preservation.
160
return patchSled(Enable, FuncId, Sled, __xray_FunctionExit);
161
}
162
163
bool patchCustomEvent(const bool Enable, const uint32_t FuncId,
164
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
165
// FIXME: Implement in mips64?
166
return false;
167
}
168
169
bool patchTypedEvent(const bool Enable, const uint32_t FuncId,
170
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
171
// FIXME: Implement in mips64?
172
return false;
173
}
174
} // namespace __xray
175
176
extern "C" void __xray_ArgLoggerEntry() XRAY_NEVER_INSTRUMENT {
177
// FIXME: this will have to be implemented in the trampoline assembly file
178
}
179
180