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_hexagon.cpp
35265 views
1
//===-- xray_hexagon.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 hexagon-specific routines (32-bit).
12
//
13
//===----------------------------------------------------------------------===//
14
#include "sanitizer_common/sanitizer_common.h"
15
#include "xray_defs.h"
16
#include "xray_interface_internal.h"
17
#include <assert.h>
18
#include <atomic>
19
20
namespace __xray {
21
22
// The machine codes for some instructions used in runtime patching.
23
enum PatchOpcodes : uint32_t {
24
PO_JUMPI_14 = 0x5800c00a, // jump #0x014 (PC + 0x014)
25
PO_CALLR_R6 = 0x50a6c000, // indirect call: callr r6
26
PO_TFR_IMM = 0x78000000, // transfer immed
27
// ICLASS 0x7 - S2-type A-type
28
PO_IMMEXT = 0x00000000, // constant extender
29
};
30
31
enum PacketWordParseBits : uint32_t {
32
PP_DUPLEX = 0x00 << 14,
33
PP_NOT_END = 0x01 << 14,
34
PP_PACKET_END = 0x03 << 14,
35
};
36
37
enum RegNum : uint32_t {
38
RN_R6 = 0x6,
39
RN_R7 = 0x7,
40
};
41
42
inline static uint32_t
43
encodeExtendedTransferImmediate(uint32_t Imm, RegNum DestReg,
44
bool PacketEnd = false) XRAY_NEVER_INSTRUMENT {
45
static const uint32_t REG_MASK = 0x1f;
46
assert((DestReg & (~REG_MASK)) == 0);
47
// The constant-extended register transfer encodes the 6 least
48
// significant bits of the effective constant:
49
Imm = Imm & 0x03f;
50
const PacketWordParseBits ParseBits = PacketEnd ? PP_PACKET_END : PP_NOT_END;
51
52
return PO_TFR_IMM | ParseBits | (Imm << 5) | (DestReg & REG_MASK);
53
}
54
55
inline static uint32_t
56
encodeConstantExtender(uint32_t Imm) XRAY_NEVER_INSTRUMENT {
57
// Bits Name Description
58
// ----- ------- ------------------------------------------
59
// 31:28 ICLASS Instruction class = 0000
60
// 27:16 high High 12 bits of 26-bit constant extension
61
// 15:14 Parse Parse bits
62
// 13:0 low Low 14 bits of 26-bit constant extension
63
static const uint32_t IMM_MASK_LOW = 0x03fff;
64
static const uint32_t IMM_MASK_HIGH = 0x00fff << 14;
65
66
// The extender encodes the 26 most significant bits of the effective
67
// constant:
68
Imm = Imm >> 6;
69
70
const uint32_t high = (Imm & IMM_MASK_HIGH) << 16;
71
const uint32_t low = Imm & IMM_MASK_LOW;
72
73
return PO_IMMEXT | high | PP_NOT_END | low;
74
}
75
76
static void WriteInstFlushCache(void *Addr, uint32_t NewInstruction) {
77
asm volatile("icinva(%[inst_addr])\n\t"
78
"isync\n\t"
79
"memw(%[inst_addr]) = %[new_inst]\n\t"
80
"dccleaninva(%[inst_addr])\n\t"
81
"syncht\n\t"
82
:
83
: [ inst_addr ] "r"(Addr), [ new_inst ] "r"(NewInstruction)
84
: "memory");
85
}
86
87
inline static bool patchSled(const bool Enable, const uint32_t FuncId,
88
const XRaySledEntry &Sled,
89
void (*TracingHook)()) XRAY_NEVER_INSTRUMENT {
90
// When |Enable| == true,
91
// We replace the following compile-time stub (sled):
92
//
93
// .L_xray_sled_N:
94
// <xray_sled_base>:
95
// { jump .Ltmp0 }
96
// { nop
97
// nop
98
// nop
99
// nop }
100
// .Ltmp0:
101
102
// With the following runtime patch:
103
//
104
// xray_sled_n (32-bit):
105
//
106
// <xray_sled_n>:
107
// { immext(#...) // upper 26-bits of func id
108
// r7 = ##... // lower 6-bits of func id
109
// immext(#...) // upper 26-bits of trampoline
110
// r6 = ##... } // lower 6 bits of trampoline
111
// { callr r6 }
112
//
113
// When |Enable|==false, we set back the first instruction in the sled to be
114
// { jump .Ltmp0 }
115
116
uint32_t *FirstAddress = reinterpret_cast<uint32_t *>(Sled.address());
117
if (Enable) {
118
uint32_t *CurAddress = FirstAddress + 1;
119
*CurAddress = encodeExtendedTransferImmediate(FuncId, RN_R7);
120
CurAddress++;
121
*CurAddress = encodeConstantExtender(reinterpret_cast<uint32_t>(TracingHook));
122
CurAddress++;
123
*CurAddress =
124
encodeExtendedTransferImmediate(reinterpret_cast<uint32_t>(TracingHook), RN_R6, true);
125
CurAddress++;
126
127
*CurAddress = uint32_t(PO_CALLR_R6);
128
129
WriteInstFlushCache(FirstAddress, uint32_t(encodeConstantExtender(FuncId)));
130
} else {
131
WriteInstFlushCache(FirstAddress, uint32_t(PatchOpcodes::PO_JUMPI_14));
132
}
133
return true;
134
}
135
136
bool patchFunctionEntry(const bool Enable, const uint32_t FuncId,
137
const XRaySledEntry &Sled,
138
void (*Trampoline)()) XRAY_NEVER_INSTRUMENT {
139
return patchSled(Enable, FuncId, Sled, Trampoline);
140
}
141
142
bool patchFunctionExit(const bool Enable, const uint32_t FuncId,
143
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
144
return patchSled(Enable, FuncId, Sled, __xray_FunctionExit);
145
}
146
147
bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId,
148
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
149
return patchSled(Enable, FuncId, Sled, __xray_FunctionExit);
150
}
151
152
bool patchCustomEvent(const bool Enable, const uint32_t FuncId,
153
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
154
// FIXME: Implement in hexagon?
155
return false;
156
}
157
158
bool patchTypedEvent(const bool Enable, const uint32_t FuncId,
159
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
160
// FIXME: Implement in hexagon?
161
return false;
162
}
163
164
} // namespace __xray
165
166
extern "C" void __xray_ArgLoggerEntry() XRAY_NEVER_INSTRUMENT {
167
// FIXME: this will have to be implemented in the trampoline assembly file
168
}
169
170