jruby-async-profiler 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.gitmodules +3 -0
  4. data/Gemfile +4 -0
  5. data/README.md +35 -0
  6. data/Rakefile +2 -0
  7. data/bin/console +14 -0
  8. data/bin/setup +8 -0
  9. data/ext/Rakefile +6 -0
  10. data/ext/async-profiler/.gitattributes +1 -0
  11. data/ext/async-profiler/.gitignore +6 -0
  12. data/ext/async-profiler/.travis.yml +11 -0
  13. data/ext/async-profiler/CHANGELOG.md +107 -0
  14. data/ext/async-profiler/JavaHome.class +0 -0
  15. data/ext/async-profiler/LICENSE +201 -0
  16. data/ext/async-profiler/Makefile +66 -0
  17. data/ext/async-profiler/README.md +487 -0
  18. data/ext/async-profiler/demo/SwingSet2.svg +2247 -0
  19. data/ext/async-profiler/docs/cddl1.txt +358 -0
  20. data/ext/async-profiler/profiler.sh +240 -0
  21. data/ext/async-profiler/src/allocTracer.cpp +155 -0
  22. data/ext/async-profiler/src/allocTracer.h +74 -0
  23. data/ext/async-profiler/src/arch.h +69 -0
  24. data/ext/async-profiler/src/arguments.cpp +265 -0
  25. data/ext/async-profiler/src/arguments.h +152 -0
  26. data/ext/async-profiler/src/codeCache.cpp +128 -0
  27. data/ext/async-profiler/src/codeCache.h +99 -0
  28. data/ext/async-profiler/src/engine.cpp +50 -0
  29. data/ext/async-profiler/src/engine.h +38 -0
  30. data/ext/async-profiler/src/flameGraph.cpp +770 -0
  31. data/ext/async-profiler/src/flameGraph.h +118 -0
  32. data/ext/async-profiler/src/flightRecorder.cpp +727 -0
  33. data/ext/async-profiler/src/flightRecorder.h +39 -0
  34. data/ext/async-profiler/src/frameName.cpp +189 -0
  35. data/ext/async-profiler/src/frameName.h +56 -0
  36. data/ext/async-profiler/src/itimer.cpp +49 -0
  37. data/ext/async-profiler/src/itimer.h +43 -0
  38. data/ext/async-profiler/src/jattach/jattach.c +437 -0
  39. data/ext/async-profiler/src/java/one/profiler/AsyncProfiler.java +160 -0
  40. data/ext/async-profiler/src/java/one/profiler/AsyncProfilerMXBean.java +43 -0
  41. data/ext/async-profiler/src/java/one/profiler/Counter.java +25 -0
  42. data/ext/async-profiler/src/java/one/profiler/Events.java +28 -0
  43. data/ext/async-profiler/src/javaApi.cpp +124 -0
  44. data/ext/async-profiler/src/lockTracer.cpp +161 -0
  45. data/ext/async-profiler/src/lockTracer.h +55 -0
  46. data/ext/async-profiler/src/mutex.cpp +33 -0
  47. data/ext/async-profiler/src/mutex.h +49 -0
  48. data/ext/async-profiler/src/os.h +45 -0
  49. data/ext/async-profiler/src/os_linux.cpp +129 -0
  50. data/ext/async-profiler/src/os_macos.cpp +115 -0
  51. data/ext/async-profiler/src/perfEvents.h +60 -0
  52. data/ext/async-profiler/src/perfEvents_linux.cpp +550 -0
  53. data/ext/async-profiler/src/perfEvents_macos.cpp +64 -0
  54. data/ext/async-profiler/src/profiler.cpp +952 -0
  55. data/ext/async-profiler/src/profiler.h +238 -0
  56. data/ext/async-profiler/src/spinLock.h +66 -0
  57. data/ext/async-profiler/src/stackFrame.h +57 -0
  58. data/ext/async-profiler/src/stackFrame_aarch64.cpp +75 -0
  59. data/ext/async-profiler/src/stackFrame_arm.cpp +58 -0
  60. data/ext/async-profiler/src/stackFrame_i386.cpp +82 -0
  61. data/ext/async-profiler/src/stackFrame_x64.cpp +113 -0
  62. data/ext/async-profiler/src/symbols.h +37 -0
  63. data/ext/async-profiler/src/symbols_linux.cpp +354 -0
  64. data/ext/async-profiler/src/symbols_macos.cpp +156 -0
  65. data/ext/async-profiler/src/vmEntry.cpp +173 -0
  66. data/ext/async-profiler/src/vmEntry.h +105 -0
  67. data/ext/async-profiler/src/vmStructs.cpp +104 -0
  68. data/ext/async-profiler/src/vmStructs.h +112 -0
  69. data/ext/async-profiler/src/wallClock.cpp +96 -0
  70. data/ext/async-profiler/src/wallClock.h +56 -0
  71. data/ext/async-profiler/test/AllocatingTarget.java +26 -0
  72. data/ext/async-profiler/test/LoadLibraryTest.java +21 -0
  73. data/ext/async-profiler/test/Target.java +31 -0
  74. data/ext/async-profiler/test/ThreadsTarget.java +35 -0
  75. data/ext/async-profiler/test/alloc-smoke-test.sh +36 -0
  76. data/ext/async-profiler/test/load-library-test.sh +35 -0
  77. data/ext/async-profiler/test/smoke-test.sh +37 -0
  78. data/ext/async-profiler/test/thread-smoke-test.sh +32 -0
  79. data/jruby-async-profiler.gemspec +32 -0
  80. data/lib/jruby/async/profiler.rb +10 -0
  81. data/lib/jruby/async/profiler/version.rb +7 -0
  82. metadata +155 -0
@@ -0,0 +1,238 @@
1
+ /*
2
+ * Copyright 2016 Andrei Pangin
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #ifndef _PROFILER_H
18
+ #define _PROFILER_H
19
+
20
+ #include <iostream>
21
+ #include <map>
22
+ #include <time.h>
23
+ #include "arch.h"
24
+ #include "arguments.h"
25
+ #include "engine.h"
26
+ #include "flightRecorder.h"
27
+ #include "mutex.h"
28
+ #include "spinLock.h"
29
+ #include "codeCache.h"
30
+ #include "vmEntry.h"
31
+
32
+
33
+ const char FULL_VERSION_STRING[] =
34
+ "Async-profiler " PROFILER_VERSION " built on " __DATE__ "\n"
35
+ "Copyright 2019 Andrei Pangin\n";
36
+
37
+ const int MAX_CALLTRACES = 65536;
38
+ const int MAX_NATIVE_FRAMES = 128;
39
+ const int RESERVED_FRAMES = 4;
40
+ const int MAX_NATIVE_LIBS = 2048;
41
+ const int CONCURRENCY_LEVEL = 16;
42
+
43
+
44
+ static inline int cmp64(u64 a, u64 b) {
45
+ return a > b ? 1 : a == b ? 0 : -1;
46
+ }
47
+
48
+
49
+ union CallTraceBuffer {
50
+ ASGCT_CallFrame _asgct_frames[1];
51
+ jvmtiFrameInfo _jvmti_frames[1];
52
+ };
53
+
54
+
55
+ class CallTraceSample {
56
+ private:
57
+ u64 _samples;
58
+ u64 _counter;
59
+ int _start_frame; // Offset in frame buffer
60
+ int _num_frames;
61
+
62
+ public:
63
+ static int comparator(const void* s1, const void* s2) {
64
+ return cmp64((*(CallTraceSample**)s2)->_counter, (*(CallTraceSample**)s1)->_counter);
65
+ }
66
+
67
+ friend class Profiler;
68
+ friend class Recording;
69
+ };
70
+
71
+ class MethodSample {
72
+ private:
73
+ u64 _samples;
74
+ u64 _counter;
75
+ ASGCT_CallFrame _method;
76
+
77
+ public:
78
+ static int comparator(const void* s1, const void* s2) {
79
+ return cmp64((*(MethodSample**)s2)->_counter, (*(MethodSample**)s1)->_counter);
80
+ }
81
+
82
+ friend class Profiler;
83
+ };
84
+
85
+
86
+ typedef jboolean JNICALL (*NativeLoadLibraryFunc)(JNIEnv*, jobject, jstring, jboolean);
87
+
88
+ enum State {
89
+ IDLE,
90
+ RUNNING,
91
+ TERMINATED
92
+ };
93
+
94
+ class Profiler {
95
+ private:
96
+ Mutex _state_lock;
97
+ State _state;
98
+ Mutex _thread_names_lock;
99
+ std::map<int, std::string> _thread_names;
100
+ FlightRecorder _jfr;
101
+ Engine* _engine;
102
+ time_t _start_time;
103
+
104
+ u64 _total_samples;
105
+ u64 _total_counter;
106
+ u64 _failures[ASGCT_FAILURE_TYPES];
107
+ u64 _hashes[MAX_CALLTRACES];
108
+ CallTraceSample _traces[MAX_CALLTRACES];
109
+ MethodSample _methods[MAX_CALLTRACES];
110
+
111
+ SpinLock _locks[CONCURRENCY_LEVEL];
112
+ CallTraceBuffer* _calltrace_buffer[CONCURRENCY_LEVEL];
113
+ ASGCT_CallFrame* _frame_buffer;
114
+ int _frame_buffer_size;
115
+ int _max_stack_depth;
116
+ volatile int _frame_buffer_index;
117
+ bool _frame_buffer_overflow;
118
+ bool _threads;
119
+ bool _sync_walk;
120
+ volatile bool _thread_events_state;
121
+
122
+ SpinLock _jit_lock;
123
+ const void* _jit_min_address;
124
+ const void* _jit_max_address;
125
+ CodeCache _java_methods;
126
+ NativeCodeCache _runtime_stubs;
127
+ NativeCodeCache* _native_libs[MAX_NATIVE_LIBS];
128
+ volatile int _native_lib_count;
129
+
130
+ JNINativeMethod _load_method;
131
+ NativeLoadLibraryFunc _original_NativeLibrary_load;
132
+ static jboolean JNICALL NativeLibraryLoadTrap(JNIEnv* env, jobject self, jstring name, jboolean builtin);
133
+ void bindNativeLibraryLoad(NativeLoadLibraryFunc entry);
134
+
135
+ void* (*_ThreadLocalStorage_thread)();
136
+ jvmtiError (*_JvmtiEnv_GetStackTrace)(void* self, void* thread, jint start_depth, jint max_frame_count,
137
+ jvmtiFrameInfo* frame_buffer, jint* count_ptr);
138
+
139
+ void addJavaMethod(const void* address, int length, jmethodID method);
140
+ void removeJavaMethod(const void* address, jmethodID method);
141
+ void addRuntimeStub(const void* address, int length, const char* name);
142
+ void updateJitRange(const void* min_address, const void* max_address);
143
+
144
+ const char* asgctError(int code);
145
+ const char* findNativeMethod(const void* address);
146
+ int getNativeTrace(void* ucontext, ASGCT_CallFrame* frames, int tid, bool* stopped_at_java_frame);
147
+ int getJavaTraceAsync(void* ucontext, ASGCT_CallFrame* frames, int max_depth);
148
+ int getJavaTraceJvmti(jvmtiFrameInfo* jvmti_frames, ASGCT_CallFrame* frames, int max_depth);
149
+ int makeEventFrame(ASGCT_CallFrame* frames, jint event_type, jmethodID event);
150
+ bool fillTopFrame(const void* pc, ASGCT_CallFrame* frame);
151
+ bool addressInCode(const void* pc);
152
+ u64 hashCallTrace(int num_frames, ASGCT_CallFrame* frames);
153
+ int storeCallTrace(int num_frames, ASGCT_CallFrame* frames, u64 counter);
154
+ void copyToFrameBuffer(int num_frames, ASGCT_CallFrame* frames, CallTraceSample* trace);
155
+ u64 hashMethod(jmethodID method);
156
+ void storeMethod(jmethodID method, jint bci, u64 counter);
157
+ void initJvmtiFunctions(NativeCodeCache* libjvm);
158
+ void setThreadName(int tid, const char* name);
159
+ void updateThreadName(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread);
160
+ void updateAllThreadNames();
161
+ Engine* selectEngine(const char* event_name);
162
+
163
+ public:
164
+ static Profiler _instance;
165
+
166
+ Profiler() :
167
+ _state(IDLE),
168
+ _jfr(),
169
+ _frame_buffer(NULL),
170
+ _frame_buffer_size(0),
171
+ _max_stack_depth(0),
172
+ _thread_events_state(JVMTI_DISABLE),
173
+ _jit_lock(),
174
+ _jit_min_address((const void*)-1),
175
+ _jit_max_address((const void*)0),
176
+ _java_methods(),
177
+ _runtime_stubs("[stubs]"),
178
+ _native_lib_count(0),
179
+ _original_NativeLibrary_load(NULL),
180
+ _ThreadLocalStorage_thread(NULL),
181
+ _JvmtiEnv_GetStackTrace(NULL) {
182
+
183
+ for (int i = 0; i < CONCURRENCY_LEVEL; i++) {
184
+ _calltrace_buffer[i] = NULL;
185
+ }
186
+ }
187
+
188
+ u64 total_samples() { return _total_samples; }
189
+ u64 total_counter() { return _total_counter; }
190
+ time_t uptime() { return time(NULL) - _start_time; }
191
+
192
+ void run(Arguments& args);
193
+ void runInternal(Arguments& args, std::ostream& out);
194
+ void shutdown(Arguments& args);
195
+ Error start(Arguments& args, bool reset);
196
+ Error stop();
197
+ void switchThreadEvents(jvmtiEventMode mode);
198
+ void dumpSummary(std::ostream& out);
199
+ void dumpCollapsed(std::ostream& out, Arguments& args);
200
+ void dumpFlameGraph(std::ostream& out, Arguments& args, bool tree);
201
+ void dumpTraces(std::ostream& out, Arguments& args);
202
+ void dumpFlat(std::ostream& out, Arguments& args);
203
+ void recordSample(void* ucontext, u64 counter, jint event_type, jmethodID event);
204
+ NativeCodeCache* jvmLibrary();
205
+ const void* findSymbol(const char* name);
206
+
207
+ // CompiledMethodLoad is also needed to enable DebugNonSafepoints info by default
208
+ static void JNICALL CompiledMethodLoad(jvmtiEnv* jvmti, jmethodID method,
209
+ jint code_size, const void* code_addr,
210
+ jint map_length, const jvmtiAddrLocationMap* map,
211
+ const void* compile_info) {
212
+ _instance.addJavaMethod(code_addr, code_size, method);
213
+ }
214
+
215
+ static void JNICALL CompiledMethodUnload(jvmtiEnv* jvmti, jmethodID method,
216
+ const void* code_addr) {
217
+ _instance.removeJavaMethod(code_addr, method);
218
+ }
219
+
220
+ static void JNICALL DynamicCodeGenerated(jvmtiEnv* jvmti, const char* name,
221
+ const void* address, jint length) {
222
+ _instance.addRuntimeStub(address, length, name);
223
+ }
224
+
225
+ static void JNICALL ThreadStart(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) {
226
+ _instance.updateThreadName(jvmti, jni, thread);
227
+ _instance._engine->onThreadStart();
228
+ }
229
+
230
+ static void JNICALL ThreadEnd(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) {
231
+ _instance.updateThreadName(jvmti, jni, thread);
232
+ _instance._engine->onThreadEnd();
233
+ }
234
+
235
+ friend class Recording;
236
+ };
237
+
238
+ #endif // _PROFILER_H
@@ -0,0 +1,66 @@
1
+ /*
2
+ * Copyright 2017 Andrei Pangin
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #ifndef _SPINLOCK_H
18
+ #define _SPINLOCK_H
19
+
20
+ #include "arch.h"
21
+
22
+
23
+ // Cannot use regular mutexes inside signal handler.
24
+ // This lock is based on CAS busy loop. GCC atomic builtins imply full barrier.
25
+ class SpinLock {
26
+ private:
27
+ // 0 - unlocked
28
+ // 1 - exclusive lock
29
+ // <0 - shared lock
30
+ volatile int _lock;
31
+
32
+ public:
33
+ SpinLock() : _lock(0) {
34
+ }
35
+
36
+ void reset() {
37
+ _lock = 0;
38
+ }
39
+
40
+ bool tryLock() {
41
+ return __sync_bool_compare_and_swap(&_lock, 0, 1);
42
+ }
43
+
44
+ void lock() {
45
+ while (!tryLock()) {
46
+ spinPause();
47
+ }
48
+ }
49
+
50
+ void unlock() {
51
+ __sync_fetch_and_sub(&_lock, 1);
52
+ }
53
+
54
+ void lockShared() {
55
+ int value;
56
+ while ((value = _lock) == 1 || !__sync_bool_compare_and_swap(&_lock, value, value - 1)) {
57
+ spinPause();
58
+ }
59
+ }
60
+
61
+ void unlockShared() {
62
+ __sync_fetch_and_add(&_lock, 1);
63
+ }
64
+ };
65
+
66
+ #endif // _SPINLOCK_H
@@ -0,0 +1,57 @@
1
+ /*
2
+ * Copyright 2017 Andrei Pangin
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #ifndef _STACKFRAME_H
18
+ #define _STACKFRAME_H
19
+
20
+ #include <stdint.h>
21
+ #include <ucontext.h>
22
+
23
+
24
+ class StackFrame {
25
+ private:
26
+ ucontext_t* _ucontext;
27
+
28
+ uintptr_t stackAt(int slot) {
29
+ return ((uintptr_t*)sp())[slot];
30
+ }
31
+
32
+ public:
33
+ StackFrame(void* ucontext) {
34
+ _ucontext = (ucontext_t*)ucontext;
35
+ }
36
+
37
+ void restore(uintptr_t saved_pc, uintptr_t saved_sp, uintptr_t saved_fp) {
38
+ pc() = saved_pc;
39
+ sp() = saved_sp;
40
+ fp() = saved_fp;
41
+ }
42
+
43
+ uintptr_t& pc();
44
+ uintptr_t& sp();
45
+ uintptr_t& fp();
46
+
47
+ uintptr_t arg0();
48
+ uintptr_t arg1();
49
+ uintptr_t arg2();
50
+ uintptr_t arg3();
51
+
52
+ void ret();
53
+
54
+ bool pop(bool trust_frame_pointer);
55
+ };
56
+
57
+ #endif // _STACKFRAME_H
@@ -0,0 +1,75 @@
1
+ /*
2
+ * Copyright 2017 Andrei Pangin
3
+ * Copyright 2017 BellSoft LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ *
17
+ * Author: Dmitry Samersoff
18
+ */
19
+
20
+ #if defined(__aarch64__)
21
+
22
+ #include "stackFrame.h"
23
+
24
+
25
+ #define REG_FP 29
26
+ #define REG_LR 30
27
+
28
+ uintptr_t& StackFrame::pc() {
29
+ return (uintptr_t&)_ucontext->uc_mcontext.pc;
30
+ }
31
+
32
+ uintptr_t& StackFrame::sp() {
33
+ return (uintptr_t&)_ucontext->uc_mcontext.sp;
34
+ }
35
+
36
+ uintptr_t& StackFrame::fp() {
37
+ return (uintptr_t&)_ucontext->uc_mcontext.regs[REG_FP];
38
+ }
39
+
40
+ uintptr_t StackFrame::arg0() {
41
+ return (uintptr_t)_ucontext->uc_mcontext.regs[0];
42
+ }
43
+
44
+ uintptr_t StackFrame::arg1() {
45
+ return (uintptr_t)_ucontext->uc_mcontext.regs[1];
46
+ }
47
+
48
+ uintptr_t StackFrame::arg2() {
49
+ return (uintptr_t)_ucontext->uc_mcontext.regs[2];
50
+ }
51
+
52
+ uintptr_t StackFrame::arg3() {
53
+ return (uintptr_t)_ucontext->uc_mcontext.regs[3];
54
+ }
55
+
56
+ void StackFrame::ret() {
57
+ _ucontext->uc_mcontext.pc = _ucontext->uc_mcontext.regs[REG_LR];
58
+ }
59
+
60
+ bool StackFrame::pop(bool trust_frame_pointer) {
61
+ if (fp() == sp()) {
62
+ // Expected frame layout:
63
+ // sp 000000nnnnnnnnnn [stack]
64
+ // sp+8 000000nnnnnnnnnn [link]
65
+ fp() = stackAt(0);
66
+ pc() = stackAt(1);
67
+ sp() += 16;
68
+ } else {
69
+ // Hope LR holds correct value
70
+ pc() = _ucontext->uc_mcontext.regs[REG_LR];
71
+ }
72
+ return true;
73
+ }
74
+
75
+ #endif // defined(__aarch64__)
@@ -0,0 +1,58 @@
1
+ /*
2
+ * Copyright 2017 Andrei Pangin
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #if defined(__arm__) || defined(__thumb__)
18
+
19
+ #include "stackFrame.h"
20
+
21
+
22
+ uintptr_t& StackFrame::pc() {
23
+ return (uintptr_t&)_ucontext->uc_mcontext.arm_pc;
24
+ }
25
+
26
+ uintptr_t& StackFrame::sp() {
27
+ return (uintptr_t&)_ucontext->uc_mcontext.arm_sp;
28
+ }
29
+
30
+ uintptr_t& StackFrame::fp() {
31
+ return (uintptr_t&)_ucontext->uc_mcontext.arm_fp;
32
+ }
33
+
34
+ uintptr_t StackFrame::arg0() {
35
+ return (uintptr_t)_ucontext->uc_mcontext.arm_r0;
36
+ }
37
+
38
+ uintptr_t StackFrame::arg1() {
39
+ return (uintptr_t)_ucontext->uc_mcontext.arm_r1;
40
+ }
41
+
42
+ uintptr_t StackFrame::arg2() {
43
+ return (uintptr_t)_ucontext->uc_mcontext.arm_r2;
44
+ }
45
+
46
+ uintptr_t StackFrame::arg3() {
47
+ return (uintptr_t)_ucontext->uc_mcontext.arm_r3;
48
+ }
49
+
50
+ void StackFrame::ret() {
51
+ _ucontext->uc_mcontext.arm_pc = _ucontext->uc_mcontext.arm_lr;
52
+ }
53
+
54
+ bool StackFrame::pop(bool trust_frame_pointer) {
55
+ return false;
56
+ }
57
+
58
+ #endif // defined(__arm__) || defined(__thumb__)