-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathstackFrame_aarch64.cpp
More file actions
140 lines (117 loc) · 3.85 KB
/
Copy pathstackFrame_aarch64.cpp
File metadata and controls
140 lines (117 loc) · 3.85 KB
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
132
133
134
135
136
137
138
139
140
/*
* Copyright The async-profiler authors
* Copyright 2026 Datadog, Inc
* SPDX-License-Identifier: Apache-2.0
*/
#ifdef __aarch64__
#include <errno.h>
#include <string.h>
#include <sys/syscall.h>
#include "stackFrame.h"
#include "safeAccess.h"
#include "counters.h"
#ifdef __APPLE__
# define REG(l, m) _ucontext->uc_mcontext->__ss.__##m
#else
# define REG(l, m) _ucontext->uc_mcontext.l
#endif
uintptr_t& StackFrame::pc() {
return (uintptr_t&)REG(pc, pc);
}
uintptr_t& StackFrame::sp() {
return (uintptr_t&)REG(sp, sp);
}
uintptr_t& StackFrame::fp() {
return (uintptr_t&)REG(regs[29], fp);
}
uintptr_t& StackFrame::retval() {
return (uintptr_t&)REG(regs[0], x[0]);
}
uintptr_t StackFrame::link() const {
return (uintptr_t)REG(regs[30], lr);
}
uintptr_t StackFrame::arg0() const {
return (uintptr_t)REG(regs[0], x[0]);
}
uintptr_t StackFrame::arg1() const {
return (uintptr_t)REG(regs[1], x[1]);
}
uintptr_t StackFrame::arg2() const {
return (uintptr_t)REG(regs[2], x[2]);
}
uintptr_t StackFrame::arg3() const {
return (uintptr_t)REG(regs[3], x[3]);
}
uintptr_t StackFrame::jarg0() const {
return arg1();
}
uintptr_t StackFrame::method() const {
return (uintptr_t)REG(regs[12], x[12]);
}
uintptr_t StackFrame::senderSP() const {
return (uintptr_t)REG(regs[19], x[19]);
}
void StackFrame::ret() {
pc() = link();
}
NOSANALIGSANITIZE void StackFrame::adjustSP(const void* entry, const void* pc, uintptr_t& sp) {
instruction_t* ip = (instruction_t*)pc;
if (ip > entry && (ip[-1] == 0xa9bf27ff || (ip[-1] == 0xd63f0100 && ip[-2] == 0xa9bf27ff))) {
// When calling a leaf native from Java, JVM puts a dummy frame link onto the stack,
// thus breaking the invariant: sender_sp == current_sp + frame_size.
// Since JDK 21, there are more instructions between `blr` and `add`,
// ignore them now for the sake of simplicity.
// stp xzr, x9, [sp, #-16]!
// blr x8
// ...
// add sp, sp, #0x10
sp += 16;
}
}
bool StackFrame::skipFaultInstruction() {
return false;
}
NOSANALIGSANITIZE bool StackFrame::checkInterruptedSyscall() {
#ifdef __APPLE__
// We are not interested in syscalls that do not check error code, e.g. semaphore_wait_trap
if (*(instruction_t*)pc() == 0xd65f03c0) {
return true;
}
// If carry flag is set, the error code is in low byte of x0
if (REG(pstate, cpsr) & (1 << 29)) {
return (retval() & 0xff) == EINTR || (retval() & 0xff) == ETIMEDOUT;
} else {
return retval() == (uintptr_t)-EINTR;
}
#else
if (retval() == (uintptr_t)-EINTR) {
// Workaround for JDK-8237858: restart the interrupted poll / epoll_wait manually
uintptr_t nr = (uintptr_t)REG(regs[8], x[8]);
if (nr == SYS_ppoll || (nr == SYS_epoll_pwait && (int)arg3() == -1)) {
// Check against unreadable page for the loop below
const uintptr_t max_distance = 24;
if ((pc() & 0xfff) < max_distance && SafeAccess::load32((int32_t*)(pc() - max_distance)) == 0) {
return true;
}
// Try to restore the original value of x0 saved in another register
for (uintptr_t prev_pc = pc() - 4; pc() - prev_pc <= max_distance; prev_pc -= 4) {
instruction_t insn = *(instruction_t*)prev_pc;
unsigned int reg = (insn >> 16) & 31;
if ((insn & 0xffe0ffff) == 0xaa0003e0 && reg >= 6) {
// mov x0, reg
REG(regs[0], x[0]) = REG(regs[reg], x[reg]);
pc() -= sizeof(instruction_t);
break;
}
}
}
return true;
}
return false;
#endif
}
bool StackFrame::isSyscall(instruction_t* pc) {
// svc #0 or svc #80
return (*pc & 0xffffefff) == 0xd4000001;
}
#endif // __aarch64__