@arms/rum-reactnative 0.1.3-beta.0 → 0.1.3-beta.1
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.
- package/android/src/main/jni/rum_crash_writer.c +13 -19
- package/android/src/main/jni/rum_module_info.c +39 -0
- package/android/src/main/jni/rum_module_info.h +4 -0
- package/lib/commonjs/utils/crash.js +3 -0
- package/lib/commonjs/utils/platform.js +1 -1
- package/lib/module/utils/crash.js +3 -0
- package/lib/module/utils/platform.js +1 -1
- package/package.json +1 -1
|
@@ -191,7 +191,7 @@ static void emit_frame(int fd, char *buf, size_t *pos,
|
|
|
191
191
|
|
|
192
192
|
int si = rum_module_index_for_addr(addr);
|
|
193
193
|
if (si >= 0) {
|
|
194
|
-
uintptr_t base =
|
|
194
|
+
uintptr_t base = rum_module_base_for_seg(si);
|
|
195
195
|
|
|
196
196
|
// 记录被引用模块的 image_addr(去重),供 binary_images 过滤
|
|
197
197
|
if (base != 0 && *referenced_count < MAX_REFERENCED_MODULES) {
|
|
@@ -316,6 +316,9 @@ void rum_write_crash(int fd, int signum, siginfo_t *info, ucontext_t *uc,
|
|
|
316
316
|
|
|
317
317
|
// 解析 /proc/self/maps(async-signal-safe),为帧提供模块归属与相对偏移
|
|
318
318
|
rum_modules_parse();
|
|
319
|
+
// 构建去重模块列表,供 emit_frame 获取模块级基址和 binary_images 枚举使用。
|
|
320
|
+
// 必须在 frames 循环前调用,确保 rum_module_base_for_seg() 能查到模块。
|
|
321
|
+
int mod_count = rum_module_build_distinct();
|
|
319
322
|
|
|
320
323
|
// binary_images 按需过滤:仅保留被栈帧引用的模块。
|
|
321
324
|
// 参照 Sentry 实践,服务端符号化时忽略未被任何栈帧引用的模块,
|
|
@@ -328,36 +331,28 @@ void rum_write_crash(int fd, int signum, siginfo_t *info, ucontext_t *uc,
|
|
|
328
331
|
// "frames":[{"address","library","image_addr","offset"}, ...]
|
|
329
332
|
// library/offset 供后端结合 binary_images 的 build_id 精确符号化
|
|
330
333
|
//
|
|
331
|
-
//
|
|
332
|
-
//
|
|
333
|
-
//
|
|
334
|
-
//
|
|
335
|
-
//
|
|
334
|
+
// NDK 信号处理器最多采集 MAX_FRAMES(512) 帧。frame_count 达到
|
|
335
|
+
// TRUNCATION_THRESHOLD(512) 时说明实际栈可能更长(已达到采集上限),
|
|
336
|
+
// 此时全部输出 512 帧 + 尾部标记帧(omitted_count=-1 表示实际总帧数
|
|
337
|
+
// 未知),不做双侧截断——因为 NDK 只能获取前 512 帧,前 256 + 后 256
|
|
338
|
+
// 恰好覆盖全部 512 帧,中间无省略,插入中间标记帧会造成冗余。
|
|
336
339
|
// frame_count < TRUNCATION_THRESHOLD 时全部输出,不截断。
|
|
337
340
|
// 所有操作仅为栈上数组读写与整数比较,符合 async-signal-safe。
|
|
338
341
|
buf_append(fd, buf, &pos, ",\"frames\":[");
|
|
339
|
-
int
|
|
342
|
+
int needs_tail_marker = (frame_count >= TRUNCATION_THRESHOLD);
|
|
340
343
|
int first = 1;
|
|
341
344
|
|
|
342
|
-
int
|
|
343
|
-
for (int i = 0; i < head_count; i++) {
|
|
345
|
+
for (int i = 0; i < frame_count; i++) {
|
|
344
346
|
emit_frame(fd, buf, &pos, (uintptr_t)frames[i],
|
|
345
347
|
referenced_addrs, &referenced_count, &first);
|
|
346
348
|
}
|
|
347
349
|
|
|
348
|
-
if (
|
|
349
|
-
//
|
|
350
|
+
if (needs_tail_marker) {
|
|
351
|
+
// 尾部标记帧(omitted_count=-1 表示实际总帧数未知)
|
|
350
352
|
if (!first) {
|
|
351
353
|
buf_append(fd, buf, &pos, ",");
|
|
352
354
|
}
|
|
353
355
|
buf_append(fd, buf, &pos, "{\"truncated\":true,\"omitted_count\":-1}");
|
|
354
|
-
first = 0;
|
|
355
|
-
|
|
356
|
-
int tail_start = frame_count - FRAMES_PER_SIDE;
|
|
357
|
-
for (int i = tail_start; i < frame_count; i++) {
|
|
358
|
-
emit_frame(fd, buf, &pos, (uintptr_t)frames[i],
|
|
359
|
-
referenced_addrs, &referenced_count, &first);
|
|
360
|
-
}
|
|
361
356
|
}
|
|
362
357
|
buf_append(fd, buf, &pos, "]");
|
|
363
358
|
|
|
@@ -375,7 +370,6 @@ void rum_write_crash(int fd, int signum, siginfo_t *info, ucontext_t *uc,
|
|
|
375
370
|
// 仅上报带 GNU build-id 的 file-backed 模块(build-id 等价于 iOS image uuid,
|
|
376
371
|
// 用于后端精确匹配符号文件)。
|
|
377
372
|
buf_append(fd, buf, &pos, ",\"binary_images\":[");
|
|
378
|
-
int mod_count = rum_module_build_distinct();
|
|
379
373
|
int emitted = 0;
|
|
380
374
|
char bid[BUILD_ID_HEX_CAP];
|
|
381
375
|
for (int m = 0; m < mod_count; m++) {
|
|
@@ -152,6 +152,27 @@ uintptr_t rum_seg_load_base(int seg_index) {
|
|
|
152
152
|
return g_segs[seg_index].start - g_segs[seg_index].offset;
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
uintptr_t rum_module_base_for_seg(int seg_index) {
|
|
156
|
+
if (seg_index < 0 || seg_index >= g_seg_count) {
|
|
157
|
+
return 0;
|
|
158
|
+
}
|
|
159
|
+
// 查找该段所属模块(同路径),返回模块级基址(image_addr)。
|
|
160
|
+
// 与 binary_images 的 rum_module_image_addr() 一致,确保 emit_frame
|
|
161
|
+
// 收集的 referenced_addrs 与 binary_images 过滤比较的基址相同。
|
|
162
|
+
// 若 rum_module_build_distinct() 尚未调用(g_mod_count == 0),
|
|
163
|
+
// 回退到段级基址。
|
|
164
|
+
const char *path = g_segs[seg_index].path;
|
|
165
|
+
int path_len = g_segs[seg_index].path_len;
|
|
166
|
+
for (int m = 0; m < g_mod_count; m++) {
|
|
167
|
+
if (g_mods[m].path_len == path_len &&
|
|
168
|
+
memcmp(g_mods[m].path, path, (size_t)path_len) == 0) {
|
|
169
|
+
return g_mods[m].image_addr;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Fallback: 段级基址
|
|
173
|
+
return g_segs[seg_index].start - g_segs[seg_index].offset;
|
|
174
|
+
}
|
|
175
|
+
|
|
155
176
|
const char *rum_seg_path(int seg_index, int *out_len) {
|
|
156
177
|
if (seg_index < 0 || seg_index >= g_seg_count) {
|
|
157
178
|
if (out_len) *out_len = 0;
|
|
@@ -296,6 +317,24 @@ int rum_module_build_id_hex(uintptr_t load_base, char *out, int out_cap) {
|
|
|
296
317
|
const unsigned char *name = note + sizeof(ElfW(Nhdr));
|
|
297
318
|
const unsigned char *desc = name + ((namesz + 3u) & ~3u);
|
|
298
319
|
|
|
320
|
+
// 边界检查:确保 name 区域不超出 note section。
|
|
321
|
+
// 损坏的 namesz 可导致 name 指针越界,memcmp 读取未映射内存
|
|
322
|
+
// 触发二次 SIGSEGV。
|
|
323
|
+
if (name + namesz > note_end) {
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// 边界检查:desc 起始地址(含对齐填充)不得超出 note section。
|
|
328
|
+
if (desc > note_end) {
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// 边界检查:将 descsz clamp 到实际可用范围,防止 desc[b] 循环
|
|
333
|
+
// 读取超出 note section 的内存,触发二次 SIGSEGV。
|
|
334
|
+
if (desc + descsz > note_end) {
|
|
335
|
+
descsz = (uint32_t)(note_end - desc);
|
|
336
|
+
}
|
|
337
|
+
|
|
299
338
|
if (type == NT_GNU_BUILD_ID && namesz == 4 &&
|
|
300
339
|
memcmp(name, "GNU", 4) == 0) {
|
|
301
340
|
static const char hexc[] = "0123456789abcdef";
|
|
@@ -24,6 +24,10 @@ int rum_module_index_for_addr(uintptr_t addr);
|
|
|
24
24
|
/** 段的加载基址(= start - file_offset)。索引非法返回 0。 */
|
|
25
25
|
uintptr_t rum_seg_load_base(int seg_index);
|
|
26
26
|
|
|
27
|
+
/** 段所属模块的加载基址(模块级 image_addr,与 binary_images 一致)。
|
|
28
|
+
* 需在 rum_module_build_distinct() 之后调用;未构建时回退到段级基址。 */
|
|
29
|
+
uintptr_t rum_module_base_for_seg(int seg_index);
|
|
30
|
+
|
|
27
31
|
/** 段对应的模块路径(指向内部缓冲,非 null 结尾)。out_len 输出长度。 */
|
|
28
32
|
const char *rum_seg_path(int seg_index, int *out_len);
|
|
29
33
|
|
|
@@ -119,6 +119,9 @@ function formatStack(frames) {
|
|
|
119
119
|
// 截断标记帧:双侧截断时插入的中间标记
|
|
120
120
|
if (frame.truncated) {
|
|
121
121
|
const count = frame.omitted_count ?? -1;
|
|
122
|
+
if (count < 0) {
|
|
123
|
+
return `#${index} ... frames omitted (unknown count) ...`;
|
|
124
|
+
}
|
|
122
125
|
return `#${index} ... ${count} frames omitted ...`;
|
|
123
126
|
}
|
|
124
127
|
const library = frame.library || '<unknown>';
|
|
@@ -14,7 +14,7 @@ var _rumCore = require("@arms/rum-core");
|
|
|
14
14
|
var _reactNative = require("react-native");
|
|
15
15
|
var _NativeRumSdkReactnative = _interopRequireDefault(require("../NativeRumSdkReactnative"));
|
|
16
16
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
17
|
-
const _pkg = {"version":"0.1.3-beta.
|
|
17
|
+
const _pkg = {"version":"0.1.3-beta.1"};
|
|
18
18
|
const VERSION = exports.VERSION = _pkg.version;
|
|
19
19
|
|
|
20
20
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -114,6 +114,9 @@ function formatStack(frames) {
|
|
|
114
114
|
// 截断标记帧:双侧截断时插入的中间标记
|
|
115
115
|
if (frame.truncated) {
|
|
116
116
|
const count = frame.omitted_count ?? -1;
|
|
117
|
+
if (count < 0) {
|
|
118
|
+
return `#${index} ... frames omitted (unknown count) ...`;
|
|
119
|
+
}
|
|
117
120
|
return `#${index} ... ${count} frames omitted ...`;
|
|
118
121
|
}
|
|
119
122
|
const library = frame.library || '<unknown>';
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { AppType } from '@arms/rum-core';
|
|
4
4
|
import { Dimensions, Platform } from 'react-native';
|
|
5
5
|
import NativeRumSdkReactnative from "../NativeRumSdkReactnative.js";
|
|
6
|
-
const _pkg = {"version":"0.1.3-beta.
|
|
6
|
+
const _pkg = {"version":"0.1.3-beta.1"};
|
|
7
7
|
export const VERSION = _pkg.version;
|
|
8
8
|
|
|
9
9
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
package/package.json
CHANGED