jruby-async-profiler 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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__)