@arms/rum-reactnative 0.1.2 → 0.1.3-beta.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 (172) hide show
  1. package/README.md +79 -1
  2. package/RumSdkReactnative.podspec +28 -0
  3. package/android/build.gradle +83 -0
  4. package/android/gradle.properties +6 -0
  5. package/android/src/main/AndroidManifest.xml +13 -0
  6. package/android/src/main/java/com/rumsdkreactnative/RumSdkReactnativeModule.kt +512 -0
  7. package/android/src/main/java/com/rumsdkreactnative/RumSdkReactnativePackage.kt +33 -0
  8. package/android/src/main/java/com/rumsdkreactnative/crash/CrashContextManager.kt +157 -0
  9. package/android/src/main/java/com/rumsdkreactnative/crash/CrashHandler.kt +444 -0
  10. package/android/src/main/java/com/rumsdkreactnative/crash/CrashInitProvider.kt +50 -0
  11. package/android/src/main/java/com/rumsdkreactnative/crash/NdkCrashHandler.kt +66 -0
  12. package/android/src/main/jni/CMakeLists.txt +21 -0
  13. package/android/src/main/jni/rum_backtrace.c +144 -0
  14. package/android/src/main/jni/rum_crash_handler.c +200 -0
  15. package/android/src/main/jni/rum_crash_writer.c +442 -0
  16. package/android/src/main/jni/rum_module_info.c +316 -0
  17. package/android/src/main/jni/rum_module_info.h +54 -0
  18. package/android/src/main/jni/rum_test_crash.cpp +55 -0
  19. package/app.plugin.js +11 -0
  20. package/docs/ReactNative SDK/351/205/215/347/275/256/345/217/202/350/200/203.md" +671 -0
  21. package/docs/SDK /347/211/210/346/234/254/350/257/264/346/230/216.md" +12 -0
  22. package/docs//346/216/245/345/205/245ReactNative/345/272/224/347/224/250.md +238 -0
  23. package/ios/PrivacyInfo.xcprivacy +93 -0
  24. package/ios/RumCrashReporter.h +38 -0
  25. package/ios/RumCrashReporter.mm +861 -0
  26. package/ios/RumSdkReactnative.h +5 -0
  27. package/ios/RumSdkReactnative.mm +291 -0
  28. package/ios/fishhook/fishhook.c +264 -0
  29. package/ios/fishhook/fishhook.h +76 -0
  30. package/lib/commonjs/NativeRumSdkReactnative.js +50 -0
  31. package/lib/commonjs/collector/action/index.js +108 -0
  32. package/lib/commonjs/collector/exception/crash.js +148 -0
  33. package/lib/commonjs/collector/exception/index.js +238 -0
  34. package/lib/commonjs/collector/index.js +42 -0
  35. package/lib/commonjs/collector/resource/api.js +286 -0
  36. package/lib/commonjs/collector/view/perf.js +79 -0
  37. package/lib/commonjs/collector/view/pv.js +88 -0
  38. package/lib/commonjs/expoConfigPlugin.js +37 -0
  39. package/lib/commonjs/index.js +29 -0
  40. package/lib/commonjs/package.json +1 -0
  41. package/lib/commonjs/plugin.js +47 -0
  42. package/lib/commonjs/processor/default-processor.js +27 -0
  43. package/lib/commonjs/processor/session-processor.js +47 -0
  44. package/lib/commonjs/reporter/index.js +148 -0
  45. package/lib/commonjs/reporter/monitor-reporter.js +43 -0
  46. package/lib/commonjs/shell.js +91 -0
  47. package/lib/commonjs/types/client.js +6 -0
  48. package/lib/commonjs/types/crash.js +37 -0
  49. package/lib/commonjs/types/index.js +2 -0
  50. package/lib/commonjs/utils/action.js +305 -0
  51. package/lib/commonjs/utils/api.js +83 -0
  52. package/lib/commonjs/utils/base.js +95 -0
  53. package/lib/commonjs/utils/crash.js +146 -0
  54. package/lib/commonjs/utils/platform.js +162 -0
  55. package/lib/commonjs/utils/session.js +158 -0
  56. package/lib/commonjs/utils/url.js +59 -0
  57. package/lib/commonjs/utils/view.js +93 -0
  58. package/lib/module/NativeRumSdkReactnative.js +47 -0
  59. package/lib/module/collector/action/index.js +45 -10
  60. package/lib/module/collector/exception/crash.js +143 -0
  61. package/lib/module/collector/exception/index.js +144 -46
  62. package/lib/module/collector/index.js +8 -0
  63. package/lib/module/collector/resource/api.js +6 -6
  64. package/lib/module/collector/view/pv.js +11 -0
  65. package/lib/module/expoConfigPlugin.js +33 -0
  66. package/lib/module/index.js +1 -0
  67. package/lib/module/processor/session-processor.js +22 -0
  68. package/lib/module/reporter/index.js +102 -16
  69. package/lib/module/reporter/monitor-reporter.js +38 -0
  70. package/lib/module/shell.js +11 -7
  71. package/lib/module/types/crash.js +33 -0
  72. package/lib/module/utils/action.js +299 -0
  73. package/lib/module/utils/crash.js +141 -0
  74. package/lib/module/utils/platform.js +124 -72
  75. package/lib/module/utils/session.js +23 -4
  76. package/lib/typescript/commonjs/package.json +1 -0
  77. package/lib/typescript/commonjs/src/NativeRumSdkReactnative.d.ts +49 -0
  78. package/lib/typescript/{src → commonjs/src}/collector/action/index.d.ts +6 -0
  79. package/lib/typescript/commonjs/src/collector/exception/crash.d.ts +28 -0
  80. package/lib/typescript/{src → commonjs/src}/collector/exception/index.d.ts +7 -0
  81. package/lib/typescript/commonjs/src/collector/index.d.ts +6 -0
  82. package/lib/typescript/commonjs/src/expoConfigPlugin.d.ts +28 -0
  83. package/lib/typescript/commonjs/src/index.d.ts +6 -0
  84. package/lib/typescript/{src → commonjs/src}/processor/session-processor.d.ts +2 -0
  85. package/lib/typescript/{src → commonjs/src}/reporter/index.d.ts +3 -1
  86. package/lib/typescript/commonjs/src/reporter/monitor-reporter.d.ts +8 -0
  87. package/lib/typescript/{src → commonjs/src}/shell.d.ts +11 -0
  88. package/lib/typescript/commonjs/src/types/crash.d.ts +95 -0
  89. package/lib/typescript/commonjs/src/utils/action.d.ts +63 -0
  90. package/lib/typescript/commonjs/src/utils/crash.d.ts +12 -0
  91. package/lib/typescript/commonjs/src/utils/platform.d.ts +22 -0
  92. package/lib/typescript/{src → commonjs/src}/utils/session.d.ts +4 -0
  93. package/lib/typescript/module/src/NativeRumSdkReactnative.d.ts +49 -0
  94. package/lib/typescript/module/src/collector/action/index.d.ts +21 -0
  95. package/lib/typescript/module/src/collector/exception/crash.d.ts +28 -0
  96. package/lib/typescript/module/src/collector/exception/index.d.ts +32 -0
  97. package/lib/typescript/module/src/collector/index.d.ts +6 -0
  98. package/lib/typescript/module/src/collector/resource/api.d.ts +21 -0
  99. package/lib/typescript/module/src/collector/view/perf.d.ts +1 -0
  100. package/lib/typescript/module/src/collector/view/pv.d.ts +16 -0
  101. package/lib/typescript/module/src/expoConfigPlugin.d.ts +28 -0
  102. package/lib/typescript/module/src/index.d.ts +6 -0
  103. package/lib/typescript/module/src/plugin.d.ts +3 -0
  104. package/lib/typescript/module/src/processor/default-processor.d.ts +6 -0
  105. package/lib/typescript/module/src/processor/session-processor.d.ts +11 -0
  106. package/lib/typescript/module/src/reporter/index.d.ts +18 -0
  107. package/lib/typescript/module/src/reporter/monitor-reporter.d.ts +8 -0
  108. package/lib/typescript/module/src/shell.d.ts +57 -0
  109. package/lib/typescript/module/src/types/client.d.ts +27 -0
  110. package/lib/typescript/module/src/types/crash.d.ts +95 -0
  111. package/lib/typescript/module/src/types/index.d.ts +118 -0
  112. package/lib/typescript/module/src/utils/action.d.ts +63 -0
  113. package/lib/typescript/module/src/utils/api.d.ts +59 -0
  114. package/lib/typescript/module/src/utils/base.d.ts +8 -0
  115. package/lib/typescript/module/src/utils/crash.d.ts +12 -0
  116. package/lib/typescript/module/src/utils/platform.d.ts +22 -0
  117. package/lib/typescript/module/src/utils/session.d.ts +41 -0
  118. package/lib/typescript/module/src/utils/url.d.ts +17 -0
  119. package/lib/typescript/module/src/utils/view.d.ts +13 -0
  120. package/package.json +51 -28
  121. package/lib/module/collector/action/index.js.map +0 -1
  122. package/lib/module/collector/exception/index.js.map +0 -1
  123. package/lib/module/collector/resource/api.js.map +0 -1
  124. package/lib/module/collector/view/perf.js.map +0 -1
  125. package/lib/module/collector/view/pv.js.map +0 -1
  126. package/lib/module/index.js.map +0 -1
  127. package/lib/module/plugin.js.map +0 -1
  128. package/lib/module/processor/default-processor.js.map +0 -1
  129. package/lib/module/processor/session-processor.js.map +0 -1
  130. package/lib/module/reporter/index.js.map +0 -1
  131. package/lib/module/shell.js.map +0 -1
  132. package/lib/module/types/client.js.map +0 -1
  133. package/lib/module/types/index.js.map +0 -1
  134. package/lib/module/utils/api.js.map +0 -1
  135. package/lib/module/utils/base.js.map +0 -1
  136. package/lib/module/utils/platform.js.map +0 -1
  137. package/lib/module/utils/session.js.map +0 -1
  138. package/lib/module/utils/url.js.map +0 -1
  139. package/lib/module/utils/view.js.map +0 -1
  140. package/lib/typescript/src/collector/action/index.d.ts.map +0 -1
  141. package/lib/typescript/src/collector/exception/index.d.ts.map +0 -1
  142. package/lib/typescript/src/collector/resource/api.d.ts.map +0 -1
  143. package/lib/typescript/src/collector/view/perf.d.ts.map +0 -1
  144. package/lib/typescript/src/collector/view/pv.d.ts.map +0 -1
  145. package/lib/typescript/src/index.d.ts +0 -4
  146. package/lib/typescript/src/index.d.ts.map +0 -1
  147. package/lib/typescript/src/plugin.d.ts.map +0 -1
  148. package/lib/typescript/src/processor/default-processor.d.ts.map +0 -1
  149. package/lib/typescript/src/processor/session-processor.d.ts.map +0 -1
  150. package/lib/typescript/src/reporter/index.d.ts.map +0 -1
  151. package/lib/typescript/src/shell.d.ts.map +0 -1
  152. package/lib/typescript/src/types/client.d.ts.map +0 -1
  153. package/lib/typescript/src/types/index.d.ts.map +0 -1
  154. package/lib/typescript/src/utils/api.d.ts.map +0 -1
  155. package/lib/typescript/src/utils/base.d.ts.map +0 -1
  156. package/lib/typescript/src/utils/platform.d.ts +0 -15
  157. package/lib/typescript/src/utils/platform.d.ts.map +0 -1
  158. package/lib/typescript/src/utils/session.d.ts.map +0 -1
  159. package/lib/typescript/src/utils/url.d.ts.map +0 -1
  160. package/lib/typescript/src/utils/view.d.ts.map +0 -1
  161. /package/lib/typescript/{src → commonjs/src}/collector/resource/api.d.ts +0 -0
  162. /package/lib/typescript/{src → commonjs/src}/collector/view/perf.d.ts +0 -0
  163. /package/lib/typescript/{src → commonjs/src}/collector/view/pv.d.ts +0 -0
  164. /package/lib/typescript/{src → commonjs/src}/plugin.d.ts +0 -0
  165. /package/lib/typescript/{src → commonjs/src}/processor/default-processor.d.ts +0 -0
  166. /package/lib/typescript/{src → commonjs/src}/types/client.d.ts +0 -0
  167. /package/lib/typescript/{src → commonjs/src}/types/index.d.ts +0 -0
  168. /package/lib/typescript/{src → commonjs/src}/utils/api.d.ts +0 -0
  169. /package/lib/typescript/{src → commonjs/src}/utils/base.d.ts +0 -0
  170. /package/lib/typescript/{src → commonjs/src}/utils/url.d.ts +0 -0
  171. /package/lib/typescript/{src → commonjs/src}/utils/view.d.ts +0 -0
  172. /package/lib/typescript/{package.json → module/package.json} +0 -0
@@ -0,0 +1,316 @@
1
+ #include "rum_module_info.h"
2
+
3
+ #include <unistd.h>
4
+ #include <fcntl.h>
5
+ #include <string.h>
6
+ #include <elf.h>
7
+ #include <link.h>
8
+
9
+ /*
10
+ * async-signal-safe 的 /proc/self/maps 解析与 ELF build-id 提取。
11
+ *
12
+ * 约束:不分配内存、不加锁、不使用 stdio / sscanf。仅用 open/read/close/memcmp
13
+ * 及手写解析,可在 signal handler 中安全调用。
14
+ */
15
+
16
+ #ifndef NT_GNU_BUILD_ID
17
+ #define NT_GNU_BUILD_ID 3
18
+ #endif
19
+
20
+ #define RUM_MAPS_RAW_CAP (256 * 1024) // maps 原始文本缓冲(超出部分截断)
21
+ #define RUM_MAX_SEGS 512 // 最多解析段数
22
+ #define RUM_MAX_MODULES 256 // 去重后最多模块数
23
+
24
+ typedef struct {
25
+ uintptr_t start;
26
+ uintptr_t end;
27
+ uintptr_t offset;
28
+ const char *path; // 指向 g_maps_raw,非 null 结尾
29
+ int path_len;
30
+ } rum_seg_t;
31
+
32
+ typedef struct {
33
+ uintptr_t image_addr; // ELF 基址(= start - file_offset)
34
+ uintptr_t image_size; // 覆盖所有段的镜像大小
35
+ const char *path;
36
+ int path_len;
37
+ } rum_mod_t;
38
+
39
+ static char g_maps_raw[RUM_MAPS_RAW_CAP];
40
+ static size_t g_maps_len;
41
+
42
+ static rum_seg_t g_segs[RUM_MAX_SEGS];
43
+ static int g_seg_count;
44
+ static int g_parsed;
45
+
46
+ static rum_mod_t g_mods[RUM_MAX_MODULES];
47
+ static int g_mod_count;
48
+
49
+ static int is_hex(char c) {
50
+ return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
51
+ (c >= 'A' && c <= 'F');
52
+ }
53
+
54
+ static uintptr_t hex_val(char c) {
55
+ if (c >= '0' && c <= '9') return (uintptr_t)(c - '0');
56
+ if (c >= 'a' && c <= 'f') return (uintptr_t)(c - 'a' + 10);
57
+ if (c >= 'A' && c <= 'F') return (uintptr_t)(c - 'A' + 10);
58
+ return 0;
59
+ }
60
+
61
+ int rum_modules_parse(void) {
62
+ if (g_parsed) {
63
+ return g_seg_count;
64
+ }
65
+ g_parsed = 1;
66
+ g_seg_count = 0;
67
+
68
+ int fd = open("/proc/self/maps", O_RDONLY);
69
+ if (fd < 0) {
70
+ return 0;
71
+ }
72
+
73
+ size_t total = 0;
74
+ while (total < sizeof(g_maps_raw)) {
75
+ ssize_t n = read(fd, g_maps_raw + total, sizeof(g_maps_raw) - total);
76
+ if (n <= 0) {
77
+ break;
78
+ }
79
+ total += (size_t)n;
80
+ }
81
+ close(fd);
82
+ g_maps_len = total;
83
+
84
+ size_t i = 0;
85
+ while (i < g_maps_len && g_seg_count < RUM_MAX_SEGS) {
86
+ uintptr_t start = 0, end = 0, offset = 0;
87
+
88
+ // start hex
89
+ while (i < g_maps_len && is_hex(g_maps_raw[i])) {
90
+ start = start * 16 + hex_val(g_maps_raw[i]);
91
+ i++;
92
+ }
93
+ if (i < g_maps_len && g_maps_raw[i] == '-') {
94
+ i++;
95
+ }
96
+ // end hex
97
+ while (i < g_maps_len && is_hex(g_maps_raw[i])) {
98
+ end = end * 16 + hex_val(g_maps_raw[i]);
99
+ i++;
100
+ }
101
+ // space + perms 字段(跳过)
102
+ while (i < g_maps_len && g_maps_raw[i] == ' ') i++;
103
+ while (i < g_maps_len && g_maps_raw[i] != ' ' && g_maps_raw[i] != '\n') i++;
104
+ // space + offset hex
105
+ while (i < g_maps_len && g_maps_raw[i] == ' ') i++;
106
+ while (i < g_maps_len && is_hex(g_maps_raw[i])) {
107
+ offset = offset * 16 + hex_val(g_maps_raw[i]);
108
+ i++;
109
+ }
110
+ // dev 字段(跳过)
111
+ while (i < g_maps_len && g_maps_raw[i] == ' ') i++;
112
+ while (i < g_maps_len && g_maps_raw[i] != ' ' && g_maps_raw[i] != '\n') i++;
113
+ // inode 字段(跳过)
114
+ while (i < g_maps_len && g_maps_raw[i] == ' ') i++;
115
+ while (i < g_maps_len && g_maps_raw[i] != ' ' && g_maps_raw[i] != '\n') i++;
116
+ // 空白 + pathname 直到行尾
117
+ while (i < g_maps_len && g_maps_raw[i] == ' ') i++;
118
+ size_t path_start = i;
119
+ while (i < g_maps_len && g_maps_raw[i] != '\n') i++;
120
+ size_t path_end = i;
121
+ if (i < g_maps_len && g_maps_raw[i] == '\n') {
122
+ i++;
123
+ }
124
+
125
+ // 仅保留以 '/' 开头的 file-backed 段(跳过 [anon] / [stack] 等)
126
+ if (path_end > path_start && g_maps_raw[path_start] == '/') {
127
+ rum_seg_t *s = &g_segs[g_seg_count++];
128
+ s->start = start;
129
+ s->end = end;
130
+ s->offset = offset;
131
+ s->path = &g_maps_raw[path_start];
132
+ s->path_len = (int)(path_end - path_start);
133
+ }
134
+ }
135
+
136
+ return g_seg_count;
137
+ }
138
+
139
+ int rum_module_index_for_addr(uintptr_t addr) {
140
+ for (int i = 0; i < g_seg_count; i++) {
141
+ if (addr >= g_segs[i].start && addr < g_segs[i].end) {
142
+ return i;
143
+ }
144
+ }
145
+ return -1;
146
+ }
147
+
148
+ uintptr_t rum_seg_load_base(int seg_index) {
149
+ if (seg_index < 0 || seg_index >= g_seg_count) {
150
+ return 0;
151
+ }
152
+ return g_segs[seg_index].start - g_segs[seg_index].offset;
153
+ }
154
+
155
+ const char *rum_seg_path(int seg_index, int *out_len) {
156
+ if (seg_index < 0 || seg_index >= g_seg_count) {
157
+ if (out_len) *out_len = 0;
158
+ return NULL;
159
+ }
160
+ if (out_len) *out_len = g_segs[seg_index].path_len;
161
+ return g_segs[seg_index].path;
162
+ }
163
+
164
+ int rum_module_build_distinct(void) {
165
+ g_mod_count = 0;
166
+ for (int s = 0; s < g_seg_count; s++) {
167
+ uintptr_t base = g_segs[s].start - g_segs[s].offset;
168
+
169
+ int found = -1;
170
+ for (int m = 0; m < g_mod_count; m++) {
171
+ if (g_mods[m].path_len == g_segs[s].path_len &&
172
+ memcmp(g_mods[m].path, g_segs[s].path,
173
+ (size_t)g_segs[s].path_len) == 0) {
174
+ found = m;
175
+ break;
176
+ }
177
+ }
178
+
179
+ if (found < 0) {
180
+ if (g_mod_count >= RUM_MAX_MODULES) {
181
+ continue;
182
+ }
183
+ found = g_mod_count++;
184
+ g_mods[found].path = g_segs[s].path;
185
+ g_mods[found].path_len = g_segs[s].path_len;
186
+ g_mods[found].image_addr = base;
187
+ g_mods[found].image_size = g_segs[s].end - base;
188
+ } else {
189
+ if (base < g_mods[found].image_addr) {
190
+ g_mods[found].image_addr = base;
191
+ }
192
+ uintptr_t span = g_segs[s].end - g_mods[found].image_addr;
193
+ if (span > g_mods[found].image_size) {
194
+ g_mods[found].image_size = span;
195
+ }
196
+ }
197
+ }
198
+ return g_mod_count;
199
+ }
200
+
201
+ uintptr_t rum_module_image_addr(int mod_index) {
202
+ if (mod_index < 0 || mod_index >= g_mod_count) {
203
+ return 0;
204
+ }
205
+ return g_mods[mod_index].image_addr;
206
+ }
207
+
208
+ uintptr_t rum_module_image_size(int mod_index) {
209
+ if (mod_index < 0 || mod_index >= g_mod_count) {
210
+ return 0;
211
+ }
212
+ return g_mods[mod_index].image_size;
213
+ }
214
+
215
+ const char *rum_module_name(int mod_index, int *out_len) {
216
+ if (mod_index < 0 || mod_index >= g_mod_count) {
217
+ if (out_len) *out_len = 0;
218
+ return NULL;
219
+ }
220
+ if (out_len) *out_len = g_mods[mod_index].path_len;
221
+ return g_mods[mod_index].path;
222
+ }
223
+
224
+ int rum_module_build_id_hex(uintptr_t load_base, char *out, int out_cap) {
225
+ if (load_base == 0 || out == NULL || out_cap <= 0) {
226
+ return 0;
227
+ }
228
+
229
+ // 验证 load_base 落在已映射的段范围内。
230
+ // load_base = start - offset 可能指向未映射的内存区域(例如段 file_offset
231
+ // 不为零时,start - offset 可能落在该段之前的空洞中)。直接读取该地址
232
+ // 会触发二次 SIGSEGV,导致信号处理器重入保护将信号设为 SIG_DFL 后进程
233
+ // 立即终止,缓冲区中的崩溃数据从未刷新到磁盘。
234
+ // rum_module_index_for_addr() 仅做静态数组遍历比较,async-signal-safe。
235
+ if (rum_module_index_for_addr(load_base) < 0) {
236
+ return 0;
237
+ }
238
+
239
+ const unsigned char *base = (const unsigned char *)load_base;
240
+ // 校验 ELF magic(双重防御:即使地址已映射,也需确认指向 ELF 头)
241
+ if (base[0] != 0x7f || base[1] != 'E' || base[2] != 'L' ||
242
+ base[3] != 'F') {
243
+ return 0;
244
+ }
245
+
246
+ const ElfW(Ehdr) *ehdr = (const ElfW(Ehdr) *)base;
247
+
248
+ // 校验 e_phnum 上限,防止损坏的值导致循环越界。
249
+ // 正常 ELF 的程序头表条目数极少超过几十个,256 是宽松上限。
250
+ if (ehdr->e_phnum > 256) {
251
+ return 0;
252
+ }
253
+
254
+ const ElfW(Phdr) *phdr = (const ElfW(Phdr) *)(base + ehdr->e_phoff);
255
+
256
+ // 验证 phdr 起始地址在已映射段范围内。
257
+ // 如果 e_phoff 被损坏导致 phdr 指向未映射内存,读取 phdr[i] 会触发
258
+ // 二次 SIGSEGV。rum_module_index_for_addr() 仅遍历静态数组做整数比较,
259
+ // async-signal-safe。
260
+ if (rum_module_index_for_addr((uintptr_t)phdr) < 0) {
261
+ return 0;
262
+ }
263
+
264
+ for (int i = 0; i < ehdr->e_phnum; i++) {
265
+ if (phdr[i].p_type != PT_NOTE) {
266
+ continue;
267
+ }
268
+ // 对 PIE / 共享库,PT_NOTE 内容运行时地址 = base + p_vaddr
269
+ const unsigned char *note = base + phdr[i].p_vaddr;
270
+ const unsigned char *note_end = note + phdr[i].p_memsz;
271
+
272
+ // 验证 note section 起始地址在已映射段范围内。
273
+ // p_vaddr 可能指向模块文件中未被映射到内存的区域(如 SHT_NOTE
274
+ // 类型段在某些构建配置下不在可加载段内),直接读取同样会触发二次
275
+ // SIGSEGV。
276
+ if (rum_module_index_for_addr((uintptr_t)note) < 0) {
277
+ continue;
278
+ }
279
+
280
+ // 验证 note section 末尾地址也在已映射段范围内。
281
+ // 如果 note 数据跨越映射段末尾页边界,读取 nhdr->n_namesz、name、
282
+ // desc[b] 等可能触发二次 SIGSEGV。p_memsz 为 0 时跳过该段。
283
+ if (phdr[i].p_memsz == 0) {
284
+ continue;
285
+ }
286
+ if (rum_module_index_for_addr((uintptr_t)(note_end - 1)) < 0) {
287
+ continue;
288
+ }
289
+
290
+ while (note + sizeof(ElfW(Nhdr)) <= note_end) {
291
+ const ElfW(Nhdr) *nhdr = (const ElfW(Nhdr) *)note;
292
+ uint32_t namesz = nhdr->n_namesz;
293
+ uint32_t descsz = nhdr->n_descsz;
294
+ uint32_t type = nhdr->n_type;
295
+
296
+ const unsigned char *name = note + sizeof(ElfW(Nhdr));
297
+ const unsigned char *desc = name + ((namesz + 3u) & ~3u);
298
+
299
+ if (type == NT_GNU_BUILD_ID && namesz == 4 &&
300
+ memcmp(name, "GNU", 4) == 0) {
301
+ static const char hexc[] = "0123456789abcdef";
302
+ int written = 0;
303
+ for (uint32_t b = 0;
304
+ b < descsz && written + 2 <= out_cap; b++) {
305
+ out[written++] = hexc[(desc[b] >> 4) & 0xF];
306
+ out[written++] = hexc[desc[b] & 0xF];
307
+ }
308
+ return written;
309
+ }
310
+
311
+ note = desc + ((descsz + 3u) & ~3u);
312
+ }
313
+ }
314
+
315
+ return 0;
316
+ }
@@ -0,0 +1,54 @@
1
+ #ifndef RUM_MODULE_INFO_H
2
+ #define RUM_MODULE_INFO_H
3
+
4
+ #include <stdint.h>
5
+ #include <stddef.h>
6
+
7
+ /*
8
+ * 已加载模块信息(async-signal-safe)。
9
+ *
10
+ * 在信号处理器中解析 /proc/self/maps,为崩溃栈帧提供:
11
+ * - 每帧所属模块(library 名)与模块内相对偏移(供后端符号化);
12
+ * - binary_images 列表:每个 .so 的 GNU build-id、加载基址、大小
13
+ * (build-id 用于后端精确匹配符号文件,等价于 iOS 的 image uuid)。
14
+ *
15
+ * 所有函数均不分配内存、不加锁,可在 signal handler 中调用。
16
+ */
17
+
18
+ /** 解析 /proc/self/maps 到内部静态表(幂等)。返回段数量。 */
19
+ int rum_modules_parse(void);
20
+
21
+ /** 返回包含 addr 的段索引,未命中返回 -1。 */
22
+ int rum_module_index_for_addr(uintptr_t addr);
23
+
24
+ /** 段的加载基址(= start - file_offset)。索引非法返回 0。 */
25
+ uintptr_t rum_seg_load_base(int seg_index);
26
+
27
+ /** 段对应的模块路径(指向内部缓冲,非 null 结尾)。out_len 输出长度。 */
28
+ const char *rum_seg_path(int seg_index, int *out_len);
29
+
30
+ /**
31
+ * 构建去重后的 file-backed 模块列表(按路径去重)。返回模块数量。
32
+ * 必须在 rum_modules_parse() 之后调用。
33
+ */
34
+ int rum_module_build_distinct(void);
35
+
36
+ /** 去重模块的加载基址。 */
37
+ uintptr_t rum_module_image_addr(int mod_index);
38
+
39
+ /** 去重模块的镜像大小(覆盖所有段的范围)。 */
40
+ uintptr_t rum_module_image_size(int mod_index);
41
+
42
+ /** 去重模块的路径(指向内部缓冲,非 null 结尾)。 */
43
+ const char *rum_module_name(int mod_index, int *out_len);
44
+
45
+ /**
46
+ * 提取模块的 GNU build-id 并写入 out(小写 hex,不含 null)。
47
+ * @param load_base 模块加载基址(ELF header 所在地址)
48
+ * @param out 输出缓冲
49
+ * @param out_cap 输出缓冲容量
50
+ * @return 写入的 hex 字符数;无 build-id 或读取失败返回 0。
51
+ */
52
+ int rum_module_build_id_hex(uintptr_t load_base, char *out, int out_cap);
53
+
54
+ #endif // RUM_MODULE_INFO_H
@@ -0,0 +1,55 @@
1
+ #include <jni.h>
2
+ #include <stdlib.h>
3
+ #include <signal.h>
4
+ #include <stdexcept>
5
+
6
+ // 无限递归触发栈溢出
7
+ static void infinite_recursion(void) {
8
+ volatile char buf[4096];
9
+ buf[0] = 0;
10
+ infinite_recursion();
11
+ }
12
+
13
+ extern "C" {
14
+
15
+ JNIEXPORT void JNICALL
16
+ Java_com_rumsdkreactnative_RumSdkReactnativeModule_nativeTriggerCrash(
17
+ JNIEnv *env, jobject thiz, jint type) {
18
+ (void)env;
19
+ (void)thiz;
20
+
21
+ switch (type) {
22
+ case 0: {
23
+ // SIGSEGV - null pointer dereference
24
+ volatile int *p = NULL;
25
+ *p = 42;
26
+ break;
27
+ }
28
+ case 1: {
29
+ // SIGABRT
30
+ abort();
31
+ break;
32
+ }
33
+ case 2: {
34
+ // SIGFPE - division by zero
35
+ volatile int x = 0;
36
+ volatile int y = 1 / x;
37
+ (void)y;
38
+ break;
39
+ }
40
+ case 3: {
41
+ // Unhandled C++ exception
42
+ throw std::runtime_error("RUM SDK Test: Unhandled C++ Exception");
43
+ break;
44
+ }
45
+ case 4: {
46
+ // Stack overflow
47
+ infinite_recursion();
48
+ break;
49
+ }
50
+ default:
51
+ break;
52
+ }
53
+ }
54
+
55
+ } // extern "C"
package/app.plugin.js ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Expo config plugin entry point.
3
+ *
4
+ * Discovered automatically by `expo prebuild` / EAS Build when this package is listed
5
+ * in the consumer's app.config `plugins` array:
6
+ * plugins: [['@arms/rum-reactnative', { endpoint: '...', env: 'prod' }]]
7
+ *
8
+ * Delegates to the built CommonJS module (lib/commonjs/expoConfigPlugin.js).
9
+ */
10
+ const mod = require('./lib/commonjs/expoConfigPlugin');
11
+ module.exports = mod.default || mod;