Android——coredump 配置
撰寫不易,轉載需註明出處:http://blog.csdn.net/jscese/article/details/46699117本文來自 【jscese】的部落格!
kernel支援:
由linux支援,程式崩潰時記錄儲存堆疊空間,暫存器等相關內容,保留致命現場資料,便於分析查詢根源。
編譯項:
Symbol: COREDUMP [=y]
Type : boolean
Prompt: Enable core dump support
Location:
(1) -> Userspace binary formats
Defined at fs/Kconfig.binfmt:182
/kernel/signal.c中的訊號處理函式:get_signal_to_deliver中有這麼一段:
if (sig_kernel_coredump(signr)) {
if (print_fatal_signals)
print_fatal_signal(info->si_signo);
proc_coredump_connector(current);
/*
* If it was able to dump core, this kills all
* other threads in the group and synchronizes with
* their demise. If we lost the race with another
* thread getting here, it set group_exit_code
* first and our do_group_exit call below will use
* that value and ignore the one we pass it.
*/
do_coredump(info);
}
展開巨集如下:
(((signr) < 32) && ((1UL << ((signr) - 1)) & ((\
(1UL << ((3) - 1)) | (1UL << ((4) - 1)) | \
(1UL << ((5) - 1)) | (1UL << ((6) - 1)) | \
(1UL << ((8) - 1)) | (1UL << ((11) - 1)) | \
(1UL << ((10) - 1)) | (1UL << ((12) - 1)) | \
(1UL << ((24) - 1)) | (1UL << ((25) - 1)) | \
(1UL << ((7) - 1))
可對照signal列表檢視,
do_coredump函式實現在/fs/coredump.c
void do_coredump(siginfo_t *siginfo)
{
...
struct mm_struct *mm = current->mm;
struct linux_binfmt * binfmt;
...
struct coredump_params cprm = {
.siginfo = siginfo,
.regs = signal_pt_regs(),
.limit = rlimit(RLIMIT_CORE), //獲取當前程式的rlimit
/*
* We must use the same mm->flags while dumping core to avoid
* inconsistency of bit flags, since this flag is not protected
* by any locks.
*/
.mm_flags = mm->flags,
};
...
binfmt = mm->binfmt;
...
if (cprm.limit < binfmt->min_coredump) //判斷rlimit 必須大於定的一個最小值:
goto fail_unlock;
...
}
這個最小值定義在binfmt_elf.c中
static struct linux_binfmt elf_format = {
.module = THIS_MODULE,
.load_binary = load_elf_binary,
.load_shlib = load_elf_library,
.core_dump = elf_core_dump,
.min_coredump = ELF_EXEC_PAGESIZE,
};
#define ELF_EXEC_PAGESIZE 4096
kernel中的就先記錄這些準備資訊,如有需要可再深入檢視coredump時抓取儲存的細節
Android native 層面配置
上patch:
diff --git a/init.{ro.hardware}.rc b/init.{ro.hardware}.rc
index 8571839..a161071 100755
--- a/init.{ro.hardware}.rc
+++ b/init.ro.hardware.rc
@@ -106,6 +106,10 @@ on fs
mount debugfs none /sys/kernel/debug
+ # config coredump
+ mkdir /data/coredump 0777 system system
+ checkenable /data/coredump/enable
+ # end
diff --git a/init/builtins.c b/init/builtins.c
index 81f9b2c..c21a192 100755
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -949,3 +949,60 @@ int do_wait(int nargs, char **args)
} else
return -1;
}
+
+/*(jiangbin: command check enable from file;operation )*/
+int do_checkenable(int nargs, char **args) {
+
+ int fd,len;
+ char buf[10];
+
+
+ ERROR("do_checkenable in init");
+ if (nargs == 2) {
+
+ if((fd = open(args[1], O_RDONLY|O_CREAT, 0664)) < 0)
+ {
+ return -1;
+ }
+
+ len = read(fd, buf, sizeof buf);
+ if (len < 0) {
+ close (fd);
+ return -1;
+ }
+ close (fd);
+ buf[len] = '\0';
+ if(atoi(buf)==1) /*is enable*/
+ {
+ if(strcmp(args[1],"/data/coredump/enable")==0)
+ {
+ struct rlimit coredump;
+ memset(&coredump, 0, sizeof(struct rlimit));
+ coredump.rlim_cur = RLIM_INFINITY;
+ coredump.rlim_max = RLIM_INFINITY;
+ if(setrlimit(RLIMIT_CORE, &coredump)==0)
+ {
+ NOTICE("in init command do_checkenable coredump cur==%lu , max==%lu pid==%lu\n",coredump.rlim_cur,coredump.rlim_max, getpid());
+ }else
+ {
+ ERROR("setrlimit unlimit fail");
+ return -1;
+ }
+ int iret=0;
+ iret=write_file("/proc/sys/kernel/core_pattern","/data/coredump/core.%e.%p.%s");
+ iret=write_file("/proc/sys/fs/suid_dumpable","1");
+ return iret;
+
+
+ }
+
+ }
+
+
+ return 0;
+
+ }
+ return -1;
+
+}
+/*end*/
diff --git a/init/init_parser.c b/init/init_parser.c
old mode 100644
new mode 100755
index 6466db2..569b910
--- a/init/init_parser.c
+++ b/init/init_parser.c
@@ -89,6 +89,7 @@ static int lookup_keyword(const char *s)
if (!strcmp(s, "hown")) return K_chown;
if (!strcmp(s, "hmod")) return K_chmod;
if (!strcmp(s, "ritical")) return K_critical;
+ if (!strcmp(s, "heckenable")) return K_checkenable;/*jiangbin add for checkenable*/
break;
case 'd':
if (!strcmp(s, "isabled")) return K_disabled;
diff --git a/init/keywords.h b/init/keywords.h
old mode 100644
new mode 100755
index 2d97e5b..cf8792d
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -41,6 +41,7 @@ int do_loglevel(int nargs, char **args);
int do_load_persist_props(int nargs, char **args);
int do_load_all_props(int nargs, char **args);
int do_wait(int nargs, char **args);
+int do_checkenable(int nargs, char **args);
#define __MAKE_KEYWORD_ENUM__
#define KEYWORD(symbol, flags, nargs, func) K_##symbol,
enum {
@@ -104,6 +105,7 @@ enum {
KEYWORD(load_persist_props, COMMAND, 0, do_load_persist_props)
KEYWORD(load_all_props, COMMAND, 0, do_load_all_props)
KEYWORD(ioprio, OPTION, 0, 0)
+ KEYWORD(checkenable, COMMAND, 1, do_checkenable)
#ifdef __MAKE_KEYWORD_ENUM__
KEYWORD_COUNT,
};
作為開關新增了一個checkenable command 方便修改操作.
最終生成core檔案 /data/coredump/core.%e.%p.%s 含義:
%p 出Core程式的PID
%u 出Core程式的UID
%s 造成Core的signal號
%t 出Core的時間,從1970-01-0100:00:00開始的秒數
%e 出Core程式對應的可執行檔名
可使用ulimit -c 檢視
Android Application 層配置:
按道理init程式按照上面那樣設定之後,它的子程式zygote應該也是具備coredump能力的,自然fork的app程式也是
但是發現在zygote fork程式之後進行的:
private static void callPostForkChildHooks(int debugFlags, String instructionSet) {
long startTime = SystemClock.elapsedRealtime();
VM_HOOKS.postForkChild(debugFlags, instructionSet);
checkTime(startTime, "Zygote.callPostForkChildHooks");
}
中呼叫到 dalvik.system.ZygoteHooks 中進一步初始化
libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
native:
/art/runtime/native/dalvik_system_ZygoteHooks.cc
呼叫邏輯不多描述其中會進入這個函式:
static void EnableDebugger() {
// To let a non-privileged gdbserver attach to this
// process, we must set our dumpable flag.
#if defined(HAVE_PRCTL)
if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
PLOG(ERROR) << "prctl(PR_SET_DUMPABLE) failed for pid " << getpid();
}
#endif
// We don't want core dumps, though, so set the core dump size to 0.
rlimit rl;
rl.rlim_cur = 0;
rl.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_CORE, &rl) == -1) {
PLOG(ERROR) << "setrlimit(RLIMIT_CORE) failed for pid " << getpid();
}
}
所以zygote fork出來的process 最後都是current rlimit_core 為0
導致無法coredump
解決辦法patch如下:
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
old mode 100644
new mode 100755
index 4f5e08b..f9782c3
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -35,6 +35,7 @@
#include <sys/utsname.h>
#include <sys/wait.h>
+#include <cutils/properties.h>
#include <cutils/fs.h>
#include <cutils/multiuser.h>
@@ -165,6 +166,26 @@ static void SetGids(JNIEnv* env, jintArray javaGids) {
}
}
- delete se_name;
+
+/*actions_code(jiangbin:native interface to setrlimit for app process:coredump)*/
+static void Zygote_nativesetrlimit()
+{
+ struct rlimit coredump;
+ memset(&coredump, 0, sizeof(struct rlimit));
+ coredump.rlim_cur = RLIM_INFINITY;
+ coredump.rlim_max = RLIM_INFINITY;
+ if(setrlimit(RLIMIT_CORE, &coredump)==0)
+ {
+ ALOGD("in zygotejni setunlimit cur==%lu , max==%lu pid==%lu\n",coredump.rlim_cur,coredump.rlim_max, getpid());
+ }else
+ {
+ ALOGE("setrlimit unlimit fail in zygotejni");
+ }
+}
+/*end*/
+
+
+
// Sets the resource limits via setrlimit(2) for the values in the
// two-dimensional array of integers that's passed in. The second dimension
// contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is
@@ -577,6 +598,17 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
ALOGE("Error calling post fork hooks.");
RuntimeAbort(env);
}
+
+ /*actions_code(jiangbin:to setrlimit for app process:coredump after PostForkChildHooks)*/
+ char propcoredump[PROPERTY_VALUE_MAX];
+ property_get("persist.sys.zygotedump", propcoredump, "");
+ if(strstr(propcoredump,se_name_c_str)!=NULL)
+ {
+ Zygote_nativesetrlimit();
+ }
+ /*end*/
+ delete se_name;
+
} else if (pid > 0) {
// the parent process
}
同樣留有開關用於控制~
下篇記錄 coredump 檔案解析流程
相關文章
- 2、coredump檔案的配置
- 詳解coredump
- coredump檔案的使用
- tacmd[203] no segmentation fault(coredump)ACMSegmentation
- Segmentation fault (coredump)的解決Segmentation
- gdb除錯coredump檔案除錯
- coredump檔案生成,以及GDB工具使用
- linux下gdb如何處理coredump錯誤Linux
- netca 啟動時報錯(Segmentation fault(coredump))Segmentation
- 使用 gdb 檢視 coredump 檔案的 backtrace
- Android APN配置Android
- Android 多渠道配置Android
- Android Studio配置Android
- C++ lambda 引用捕獲臨時物件引發 coredump 的案例C++物件
- Android 多渠道打包配置Android
- Android 馬甲包配置Android
- android gradle配置指南AndroidGradle
- Android Studio - 基本配置Android
- Percona 8.0.30中"show engine innodb status"導致coredump排查及分析
- 【Android】Android Studio啟動配置gradleAndroidGradle
- Android kotlin中配置protobufAndroidKotlin
- Android Studio 高階配置Android
- 配置你的 Android StudioAndroid
- Android SDK Manager 更新代理配置Android
- Android開發:在Eclipse中配置Android環境AndroidEclipse
- Android基礎 寫給新手的Android環境配置Android
- android studio配置ndk開發Android
- Android Gradle進階配置指南AndroidGradle
- Android儲存(3)– 裝置配置Android
- Android JNI開發系列之配置Android
- Android 代理自動配置PAC研究Android
- gradle android基本配置詳解GradleAndroid
- Android Jenkins引數化配置AndroidJenkins
- Ubuntu 下配置使用Android adbUbuntuAndroid
- Android Studio終極配置方案Android
- Android獲取手機配置資訊Android
- Android外掛DSL配置文件Android
- Android的安裝和配置【Z】Android