Tencent / matrix

Matrix is a plugin style, non-invasive APM system developed by WeChat.
Other
11.6k stars 1.88k forks source link

将主APP抽离成多个动态库之后 is_stack_frames_should_skip 会忽略动态库中的 mmap #383

Open tripleCC opened 5 years ago

tripleCC commented 5 years ago

is_stack_frames_should_skip 判断逻辑有个疑问

bool is_stack_frames_should_skip(uintptr_t *frames, int32_t count, uint64_t malloc_size, uint32_t type_flags)
{
    // skip allocation events from mapped_file
    if (type_flags & memory_logging_type_mapped_file_or_shared_mem) {
        if (mmap_func_info.vm_str == 0) {
            Dl_info info = {0};
            dladdr((const void *)frames[0], &info);
            if (strcmp(info.dli_sname, "mmap") == 0) {
                mmap_func_info.vm_str = frames[0];
            }
        }
        if (mmap_func_info.vm_str == frames[0]) {
            if (frames[1] >= app_image_info.vm_str && frames[1] < app_image_info.vm_end) {
                return false;
            } else {
                return true;
            }
        }
    }

    if (malloc_size >= skip_min_malloc_size) {
        return false;
    }

    // check whether there's any symbol not in this APP
    for (int i = MIN(count - 3, skip_max_stack_depth); i >= 1; --i) {
        if (frames[i] >= app_image_info.vm_str && frames[i] < app_image_info.vm_end) {
            return false;
        }
    }

    // skip this stack
    return true;
}

判断用的 app_image_info 结构记录的是主 image 的,主 image 依赖的所以动态库在下面这个语句中会返回 true :

// // 如果是调用 mmap 是在主 app image 里面,则不忽略 (这里有个问题,如果把主 app 抽离成多个动态库,那么这些动态库的 mmap 也会被忽略)
if (mmap_func_info.vm_str == frames[0]) { 
    if (frames[1] >= app_image_info.vm_str && frames[1] < app_image_info.vm_end) {
        return false;
    } else {
        return true;
    }
}

这个是否应该把 is_app_image 为 true 的 这些动态库也一并计入?

chzhij5 commented 4 years ago

@tripleCC 代码看了下是处理的, 看一下这个的实现 :

https://github.com/Tencent/matrix/blob/8e80e452d7100be9e67d4f6d9678aa4bcf88b73c/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/StackFrames/dyld_image_info.cpp#L80

static dyld_image_info app_image_info = {0}; // Infos of all app images including embeded frameworks

凡是二进制的路径包含了 app 包名,默认都是 app 里的二进制,然后 app_image_info 的起始地址和结束地址拿这几个库的地址范围取 MIN 和 MAX。

tripleCC commented 4 years ago

@tripleCC 代码看了下是处理的, 看一下这个的实现 :

https://github.com/Tencent/matrix/blob/8e80e452d7100be9e67d4f6d9678aa4bcf88b73c/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/StackFrames/dyld_image_info.cpp#L80

static dyld_image_info app_image_info = {0}; // Infos of all app images including embeded frameworks

凡是二进制的路径包含了 app 包名,默认都是 app 里的二进制,然后 app_image_info 的起始地址和结束地址拿这几个库的地址范围取 MIN 和 MAX。

嗯,看到了,不过部分系统库的地址可能会出现在 app_image_info 的起始地址和结束地址之间,如果这样处理,是否会把系统库的 mmap 也算进去。

MatrixDemo 0x10a39a000        主 image
libBacktraceRecording.dylib 0x10a673000  系统的
ynamic.framework/Dynamic 0x10a8df000 自定义动态库
chzhij5 commented 4 years ago

@tripleCC 代码看了下是处理的, 看一下这个的实现 : https://github.com/Tencent/matrix/blob/8e80e452d7100be9e67d4f6d9678aa4bcf88b73c/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/StackFrames/dyld_image_info.cpp#L80

static dyld_image_info app_image_info = {0}; // Infos of all app images including embeded frameworks 凡是二进制的路径包含了 app 包名,默认都是 app 里的二进制,然后 app_image_info 的起始地址和结束地址拿这几个库的地址范围取 MIN 和 MAX。

嗯,看到了,不过部分系统库的地址可能会出现在 app_image_info 的起始地址和结束地址之间,如果这样处理,是否会把系统库的 mmap 也算进去。

MatrixDemo 0x10a39a000        主 image
libBacktraceRecording.dylib 0x10a673000  系统的
ynamic.framework/Dynamic 0x10a8df000 自定义动态库

确实简单处理了,得想想有没有更好的做法。