在项目中,需要使用到Breakpad作为crash的coredump工具,希望breakpad能以静态或动态库的方式集成到项目中来,但是,在研究中发现,breakpad在每个平台上都有一个特有的工程,且生成出来的文件,每个平台都不一样。
Breakpad Mac项目简介
路径在:breakpad/src/client/mac ,使用xcode打开Breakpad.xcodeproj后,看到以下内容:
可以看出,整个项目是的核心就是输出一个breakpad.framework。根据文章https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/mac_breakpad_starter_guide.md中可知,这种方式是直接使用objective-c的调用方式,而我们需要使用一个跨平台c++的调用方式。
调用方法
#include "client/mac/handler/exception_handler.h"
static google_breakpad::ExceptionHandler* g_ExceptionHandler = nullptr;
static bool OnMinidumpGenerated(const char* dump_dir,const char* minidump_id,void* context, bool succeeded) {
printf("Dump path: %s\n", dump_dir);
return succeeded;
}
g_ExceptionHandler = new google_breakpad::ExceptionHandler(path,
NULL,
OnMinidumpGenerated,
NULL,
true,
NULL);
通过 include 文件可以知道,breakpad的调用方式,我们可以参照 https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/linux_starter_guide.md 写一个程序,然后编译会发现,程序需要构造函数ExceptionHandler,那么必然,在libbreakpad.a中需要exception_handler.cc,然而exception_handler.cc又依赖于minidump_generator.cc,通过编译器就可以找出mac依赖的文件。
CMakeFiles.txt
当然,如果需要多个源文件依赖,最好是有一个构建工具,那么这里使用的是cmake,依赖的文件如下:
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/client/mac/handler/exception_handler.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/client/mac/handler/minidump_generator.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/client/mac/handler/dynamic_images.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/common/mac/string_utilities.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/client/minidump_file_writer.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/client/mac/handler/breakpad_nlist_64.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/common/mac/file_id.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/common/mac/macho_id.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/common/mac/macho_walker.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/common/mac/macho_utilities.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/common/md5.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/common/string_conversion.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/common/convert_UTF.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/common/mac/MachIPC.mm"
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/client/mac/crash_generation/crash_generation_client.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/common/mac/bootstrap_compat.cc"
iOS平台PROTECTED_ALLOCATION的问题
参考src/client/mac/handler/exception_handler.cc中的代码可以看出来(如下:),当平台是mac的时候,breakpad会使用内存池的方式来分配内存(不知道为啥)。但是这样会导致普通调用出错。所以,在CmakeLists.txt中添加,让breakpad按照macOS的方式运行。
ADD_DEFINITIONS(-DUSE_PROTECTED_ALLOCATIONS=0)
iOS和macOS都会在debugger的时候产生dump文件
在iOS和macOS中,程序运行起来,debugger attatch到程序中是时候,那么那么breakpad就会收到一个exception。而breakpad会认为他是一个crash,因此会停止程序,生成当前的dump文件。
解决这个问题的的方式是探测当前的系统pid的某个类型,代码如下,代码是通过/src/client/ios/Breakpad.mm中修改所得。
static bool IsDebuggerActive() {
bool result = false;
pid_t pid = getpid();
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
int mibSize = sizeof(mib) / sizeof(int);
size_t actualSize;
if (sysctl(mib, mibSize, NULL, &actualSize, NULL, 0) == 0) {
struct kinfo_proc* info = (struct kinfo_proc*)malloc(actualSize);
if (info) {
// This comes from looking at the Darwin xnu Kernel
if (sysctl(mib, mibSize, info, &actualSize, NULL, 0) == 0)
result = (info->kp_proc.p_flag & P_TRACED) ? true : false;
free(info);
}
}
return result;
}