admin 管理员组文章数量: 1184232
2024年1月18日发(作者:webapp的优缺点)
1
2
3
4
5
6
7
extern
"C"Elf32_Addr __linker_init(void* raw_args) {
…
Elf32_Addr start_address = __linker_init_post_relocation(args, linker_addr);
set_soinfo_pool_protection(PROT_READ);
// Return the address that the calling assembly stub should jump to.
returnstart_address;} 1
2
3
4
5
staticElf32_Addr __linker_init_post_relocation(KernelArgumentBlock& args, Elf32_Addr linker_base) {
...
debuggerd_init();
...}bioniclinkerDebugger.c 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
voiddebugger_init(){
struct sigaction act;
memset(&act,
0, sizeof(act));
_sigaction = debugger_signal_handler;
_flags = SA_RESTART | SA_SIGINFO;
sigemptyset(&_mask);
sigaction(SIGILL, &act, NULL);
sigaction(SIGABRT, &act, NULL);
sigaction(SIGBUS, &act, NULL);
sigaction(SIGFPE, &act, NULL);
sigaction(SIGSEGV, &act, NULL);
sigaction(SIGSTKFLT, &act, NULL);
sigaction(SIGPIPE, &act, NULL);}
18
19* local socket but we need to tell it our tid. It
20* is paranoid and will verify that we are giving a tid
21* that's actually in our process
22*/
23int
ret;
24
debugger_msg_t msg; 25
= DEBUGGER_ACTION_CRASH; 26
= tid; 27
RETRY_ON_EINTR(ret, write(s, &msg, sizeof(msg))); 28
if(ret == sizeof(msg)) { 29
/* if the write failed, there is no point to read on 30
* the file descriptor. */ 31
RETRY_ON_EINTR(ret, read(s, &tid,
321
)); 33
intsavedErrno = errno; 34
notify_gdb_of_libraries(); 35
errno = savedErrno; 36
} 37
38
if 39(ret <
0) { 40
/* read or write failed -- broken connection? */ 41
format_buffer(msgbuf, sizeof(msgbuf), 42
"Failed while talking to debuggerd: %s" 43, strerror(errno));
44__libc_android_log_write(ANDROID_LOG_FATAL,
"libc", msgbuf); 45
} 46
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
close(s);
}
else{
/* socket failed; maybe process ran out of fds */
format_buffer(msgbuf, sizeof(msgbuf),
"Unable to open connection to debuggerd: %s", strerror(errno));
__libc_android_log_write(ANDROID_LOG_FATAL,
"libc", msgbuf);
}
/* remove our net so we fault for real when we return */
signal(n, SIG_DFL);
/*
* These signals are not re-thrown when we resume. This means that
* crashing due to (say) SIGPIPE doesn't work the way you'd expect it
* to. We work around this by throwing them manually. We don't want
* to do this for *all* signals because it'll screw up the address for
* faults like SIGSEGV.
*/
switch(n) {
caseSIGABRT:
caseSIGFPE:
caseSIGPIPE:
caseSIGSTKFLT:
(void
10
switch 11(signum) {
12case
SIGILL: signame =
"SIGILL" 13;
break; 14
case 15SIGABRT: signame =
"SIGABRT";
16break
; 17
caseSIGBUS: signame =
18"SIGBUS"
;
break 19;
20case
SIGFPE: signame =
"SIGFPE" 21;
break; 22
case 23SIGSEGV: signame =
"SIGSEGV";
24break
; 25
caseSIGSTKFLT: signame =
26"SIGSTKFLT"
;
break 27;
28case
SIGPIPE: signame =
"SIGPIPE" 29;
break; 30
default: signame =
"";
break;
}
if(prctl(PR_GET_NAME, (unsigned
long)threadname,
0,
0,
0) !=
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
* debuggerd crashes can't be reported to debuggerd. Reset all of the
* crash handlers.
*/
signal(SIGILL, SIG_DFL);
signal(SIGABRT, SIG_DFL);
signal(SIGBUS, SIG_DFL);
signal(SIGFPE, SIG_DFL);
signal(SIGSEGV, SIG_DFL);
signal(SIGPIPE, SIG_IGN);
signal(SIGSTKFLT, SIG_DFL);
logsocket = socket_local_client("logd",
ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_DGRAM);
if(logsocket <
0) {
logsocket = -1;
}
else{
fcntl(logsocket, F_SETFD, FD_CLOEXEC);
}
_handler = SIG_DFL;
sigemptyset(&_mask);
sigaddset(&_mask,SIGCHLD);
_flags = SA_NOCLDWAIT;
sigaction(SIGCHLD, &act,
0);
37
38
s = socket_local_server(DEBUGGER_SOCKET_NAME,
ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); 39
40if
(s <
0 41)
return1 42;
43fcntl(s, F_SETFD, FD_CLOEXEC);
44
45LOG(
"debuggerd: "__DATE__
46" "
__TIME__
"n" 47);
48
49//check corefile limit.
50(
void)check_corefile_limit(); 51
52
for 53(;;) {
54struct sockaddr addr;
55socklen_t alen;
56int
fd; 57
alen = sizeof(addr); 58
XLOG("waiting for connectionn" 59);
fd = accept(s, &addr, &alen);
if(fd <
0) {
XLOG("accept failed: %sn", strerror(errno));
continue;
17
18
19
20
*
* The PTRACE_ATTACH sends a SIGSTOP to the target process, but it
* won't necessarily have stopped by the time ptrace() returns. (We
* currently assume it does.) We write to the file descriptor to
* ensure that it can run as soon as we call PTRACE_CONT below. 21
* See details in bionic/libc/linker/debugger.c, in function 22
* debugger_signal_handler(). 23
*/ 24
if 25(ptrace(PTRACE_ATTACH, ,
0,
260
)) { 27
LOG("ptrace attach failed: %sn" 28, strerror(errno));
29}
else{ 30
bool detach_failed =
31false
; 32
bool attach_gdb = should_attach_gdb(&request); 33
if(TEMP_FAILURE_RETRY(write(fd,
34"0"
,
1 35)) !=
1) { 36
LOG( 37"failed responding to client: %sn"
, strerror(errno)); 38
}
else 39{
40char
* tombstone_path = NULL; 41
42
if( == DEBUGGER_ACTION_CRASH) { 43
close(fd); 44
fd = -
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
fd = -1;
}
inttotal_sleep_time_usec =
0;
for(;;) {
intsignal = wait_for_signal(, &total_sleep_time_usec);
if(signal <
0) {
break;
}
switch(signal) {
caseSIGSTOP:
if( == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
XLOG("stopped -- dumping to tombstonen");
tombstone_path = engrave_tombstone(, ,
signal,
true,
true, &detach_failed,
&total_sleep_time_usec);
}
elseif( == DEBUGGER_ACTION_DUMP_BACKTRACE) {
XLOG("stopped -- dumping to fdn");
dump_backtrace(fd, , , &detach_failed,
73&total_sleep_time_usec);
74}
else{ 75
XLOG( 76"stopped -- continuingn"
); 77
status = ptrace(PTRACE_CONT, ,
0 78,
0); 79
if 80(status) {
81LOG(
"ptrace continue failed: %sn", strerror(errno)); 82
} 83
continue 84;
/* loop again */ 85
} 86
break; 87
88
case 89SIGILL:
90case
SIGABRT: 91
caseSIGBUS: 92
case 93SIGFPE:
94case
SIGSEGV: 95
caseSIGSTKFLT: { 96
XLOG( 97"stopped -- fatal signaln"
); 98
/* 99
* Send a SIGSTOP to the process to make all of
* the non-signaled threads stop moving. Without
100
101
102
103
104
105
106
107
* this we get a lot of "ptrace detach failed:
* No such process".
*/
kill(, SIGSTOP);
/* don't dump sibling threads when attaching to GDB because it
* makes the process less reliable, */
tombstone_path = engrave_tombstone(, ,
108
signal, !attach_gdb,
false 109, &detach_failed,
110&total_sleep_time_usec);
111break
; 112
} 113
114
caseSIGPIPE: 115
LOG( 116"socket-client process stopped due to SIGPIPE! n"
); 117
break; 118
119
default 120:
121XLOG(
"stopped -- unexpected signaln"); 122
LOG( 123"process stopped due to unexpected signal %dn"
, signal); 124
break; 125
} 126
break 127;
128}
129
130
if( == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
131
if(tombstone_path) { 132
write(fd, tombstone_path, strlen(tombstone_path)); 133
} 134
close(fd); 135
fd = - 1361
; 137
} 138
free(tombstone_path); 139
} 140
141
XLOG("detachingn" 142);
143if
(attach_gdb) { 144
/* stop the process so we can debug */ 145
kill(, SIGSTOP); 146
147
/* detach so we can attach gdbserver */ 148
if(ptrace(PTRACE_DETACH, ,
1490
,
0 150)) {
LOG("ptrace detach from %d failed: %sn", , strerror(errno));
detach_failed =
true;
}
/*
* if is set, its value indicates if we should wait
* for user action for the crashing process.
* in this case, we log a message and turn the debug LED on
* waiting for a gdb connection (for instance)
*/
wait_for_user_action();
}
else{
/* just detach */
if(ptrace(PTRACE_DETACH, ,
0,
0)) {
LOG("ptrace detach from %d failed: %sn", , strerror(errno));
detach_failed =
true;
}
}
/* resume stopped process (so it can crash in peace). */
kill(, SIGCONT);
/* If we didn't successfully detach, we're still the parent, and the
* actual parent won't receive a death notification via wait(2). At this point
* there's not much we can do about that. */
if(detach_failed) {
LOG("debuggerd committing suicide to free the zombie!n");
kill(getpid(), SIGKILL);
}
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
pollfds[0].fd = fd;
pollfds[0].events = POLLIN;
pollfds[0].revents =
0;
status = TEMP_FAILURE_RETRY(poll(pollfds,
1,
3000));
if(status !=
1) {
LOG("timed out reading tidn");
return-1;
}
debugger_msg_t msg;
status = TEMP_FAILURE_RETRY(read(fd, &msg, sizeof(msg)));
if(status <
0) {
LOG("read failure? %sn", strerror(errno));
return-1;
}
if(status != sizeof(msg)) {
LOG("invalid crash request of size %dn", status);
return
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
return-1;
}
out_request->action = ;
out_request->tid = ;
out_request->pid = ;
out_request->uid = ;
out_request->gid = ;
if( == DEBUGGER_ACTION_CRASH) {
/* Ensure that the tid reported by the crashing process is valid. */
charbuf[64];
struct stat s;
snprintf(buf, sizeof buf,
"/proc/%d/task/%d", out_request->pid, out_request->tid);
if(stat(buf, &s)) {
LOG("tid %d does not exist in pid %d. ignoring debug requestn",
out_request->tid, out_request->pid);
return-1;
}
}
elseif( ==
0
|| ( == AID_SYSTEM && == DEBUGGER_ACTION_DUMP_BACKTRACE)) {
/* Only root or system can ask us to attach to any process and dump it explicitly.
* However, system is only allowed to collect backtraces but cannot dump tombstones. */
status = get_process_info(out_request->tid, &out_request->pid,
&out_request->uid, &out_request->gid);
if(status <
0) {
LOG("tid %d does not exist. ignoring explicit dump requestn",
out_request->tid);
return-1;
}
}
else{
/* No one else is not allowed to dump arbitrary processes. */
return-1;
}
return0;} 从socket中读取client端进程的pid uid gid 1
getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len); 轮询socket句柄
1
2
3
4
5
struct pollfd pollfds[1];pollfds[0].fd = fd;pollfds[0].events = POLLIN;pollfds[0].revents =
0;status = TEMP_FAILURE_RETRY(poll(pollfds,
1,
3000)); 从socket上读取debugger_msg_t结构体 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
debugger_msg_t msg;status = TEMP_FAILURE_RETRY(read(fd, &msg, sizeof(msg)));if(status <
0) {
LOG("read failure? %sn", strerror(errno));
return-1;}if(status != sizeof(msg)) {
LOG("invalid crash request of size %dn", status);
return-1;}out_request->action = ;out_request->tid = ;out_request->pid = ;out_request->uid = ;out_request->gid = ; 如果debugger_msg_t中设置的action为DEBUGGER_ACTION_CRASH,说明是crash的C/C++进程发来的请求,则判断传进来的tid是否有效。
28
} 29
break; 30
case 31SIGILL:
32case
SIGABRT: 33
caseSIGBUS: 34
case 35SIGFPE:
36case
SIGSEGV: 37
caseSIGSTKFLT: { 38
XLOG( 39"stopped -- fatal signaln"
); 40
kill(, SIGSTOP); 41
tombstone_path = engrave_tombstone(, ,
signal, !attach_gdb,
false, &detach_failed,
&total_sleep_time_usec);
break;
}
caseSIGPIPE:
LOG("socket-client process stopped due to SIGPIPE! n");
break;
default:
XLOG("stopped -- unexpected signaln");
LOG("process stopped due to unexpected signal %dn", signal);
14char
task_path[64 15];
16snprintf(task_path, sizeof(task_path),
"/proc/%d/task", pid); 17
DIR* d = opendir(task_path); 18
if 19(d) {
20struct dirent debuf;
21struct dirent *de;
22while
(!readdir_r(d, &debuf, &de) && de) { 23
if(!strcmp(de->d_name,
24"."
) || !strcmp(de->d_name,
".." 25)) {
26continue
; 27
} 28
29
char* end; 30
pid_t new_tid = strtoul(de->d_name, &end,
3110
); 32
if(*end || new_tid == tid) { 33
continue 34;
35}
dump_thread(&log, new_tid, context,
false, detach_failed, total_sleep_time_usec);
}
closedir(d);
}
return1;
}
}
if(!have_tid) {
usage();
return1;
}
returndo_explicit_dump(tid, dump_backtrace);}通过do_explicit_dump函数dump出指定进程的栈信息等
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
staticintdo_explicit_dump(pid_t tid, bool dump_backtrace) {
fprintf(stdout,
"Sending request to dump task %d.n", tid);
if(dump_backtrace) {
fflush(stdout);
if(dump_backtrace_to_file(tid, fileno(stdout)) <
0) {
fputs("Error dumping backtrace.n", stderr);
return1;
}
}
else{
chartombstone_path[PATH_MAX];
if(dump_tombstone(tid, tombstone_path, sizeof(tombstone_path)) <
0) {
fputs("Error dumping tombstone.n", stderr);
版权声明:本文标题:Androiddebuggerd源码分析 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/b/1705563654a490117.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
更多相关文章
svchost.exe大解析:掌握Windows操作系统的运行关键
svchost.exe 是 Windows 系统的 核心服务宿主进程,并非独立程序,而是负责承载多个系统服务(如自动更新、网络连接等;以 DLL 形式存在)的“容器”,正常情况下会在任务管理器中显示多个实例,属
从SVCHOST到SWF:探析其背后的合作与支持关系
你是否经常在你电脑看到很多 svchost.exe进程呢?有的人电脑有6个svchost.exe进程、有的人电脑更多的svchost.exe进程。例如我的电脑就有5个svchost.exe程序。一般来说Wind
走近svchost.exe与hkcmd.exe:揭秘这两个进程的幕后操作
进程文件: Svchost.exe Svchost.exe文件存在于“%system root%system32”(例如C:Windowssystem32)目录下,它是Windows NT核心的重
Linux高手进阶课:用netstat和ps找出并释放被占用的端口
运行软件或程序时,有时会出现以下问题、导致运行失败: Web server failed to start. Port 8080 was already in use. 表示8080端口被占用,程序启动失败。
一招解决8092端口占用难题:确保Flash中心流畅运行
端口占用处理 项目启动报端口正在使用 09:25:12.866 [restartedMain]ERROR org.springframework.boot.diagnostics.LoggingFailureAnalys
摆脱技术难题:快速解决RBCShellExternal带来的烦扰
迅雷影音被自动安装后,已经卸载,但是每天还是会定时弹出“影音资讯”弹窗,如下图,让人烦得很,下面操作可以让你摆脱烦恼:C盘直接搜索KKTIP会发现在路径C:UsersPublicVideo LegendRBC
电脑故障排查指南:识别并解决DLLHOST.EXE相关的Adobe Flash Player问题
dllhost.exe 是 Windows 系统的核心进程之一,主要作用是管理和运行系统中的 COM+ 组件,属于正常且必要的系统进程。 1. 正常 dllhost.exe 的核心信息 进程定位:它
Java程序问题解决高手必备:dump文件生成与解析攻略
为啥需要内存文件 服务器CPU,内存占用空间飙升,或者GC频繁,首先需要排除的就是内存泄露,即内存中没有的对象的空间没有被及时回收导致的。而检测内存泄露就需要看哪种类在内存占了较多份额,从而定位到代码,然后修改。
这SVCHOST.exe吃CPU吃得厉害,怎么处理才对?能强行终结吗?
svchost.exe是什么意思? svchost.exe是Windows操作系统中一个非常重要且合法的核心进程,它的名字是Service Host(服务宿主)的缩写。简单来说,它是动态链接库(DLL)中运行的服务的通
巧用ClipBoardSvcGroup,让SWF内容在Adobe Flash Player上焕发生机的实践指南
转载 本文转载自,防止原站挂了。作者:ZwelL 1. 多个服务共享一个Svchost.exe进程利与弊 windows 系统服务分为独立进程和共享进程两种,在windows NT时只有服务器
深入探究svchost.exe:了解Windows后台运行的奥秘
svchost是微软Windows操作系统中的系统文件程序,这个程序对系统的正常运行是非常重要,而且是不能被结束的,许多服务通过注入到该程序中启动,所以会有多个该文件的进程。推荐:《编程视频》svchost.e
深入探究:SVCHOST.EXE在电脑中的角色和重要性
网上有很多关于是什么进程,svchost.exe是什么病毒,svchost.exe占用cpu100%或占用大量内存,svchost.exe有十几个,svchost.exe偷偷连网很象木马的问题,本文提供关于svchost.exe
深入浅出:解析Android中的App与桌面进程的不同之处
安卓 有三类工作和三种进程 动作 RemoteView 纯静态 UI渲染 读取本地静态数据、一些同步的计算逻辑、views.setTextViewText()等普通 KotlinJava
在Linux系统中让Chromium浏览器像服务一样稳定运行的方法分享
前言:很多时候,有些程序需要开机自启动,有很多种方式可以实现,我这里写了俩种方式,一是桌面进程,二是守护进程。 一、桌面进程示例 1.文件需是xxx.desktop命名,路径需在~.config下 ~.confi
一键搞定!教你如何在Linux上自动启动Chromium桌面应用程序
前言:很多时候,有些程序需要开机自启动,有很多种方式可以实现,我这里写了俩种方式,一是桌面进程,二是守护进程。 一、桌面进程示例 1.文件需是xxx.desktop命名,路径需在~.config下 ~.confi
微信登陆不求人!用wxshareutils轻松搞定
微信分享Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.wx_fxlogo);图标Wx
一文精通Redis读写之道:避开穿透风险,提升性能的旁路技巧
一、Redis三种常用的缓存读写策略 Redis有三种读写策略分别是:旁路缓存模式策略、读写穿透策略、异步缓存写入策略。 这三种缓存读写策略各有优势,不存在最佳,需要我们根据实际的业务场景选择最合适的。 二、旁路缓存模式(Cache
从经典到智能:Web演进之路与未来趋势探析
大家好,今天想和大家深度拆解我们每天高频接触,却鲜少深究的「Web 世界」。从最初仅能承载文字与图片的静态页面,到如今集沉浸式交互、智能服务、全端适配于一体的复杂应用生态,Web 的发展历程,本质上是一部「技术迭代适配用户需求」的浓缩
Windows-mscorsvw.exe
mscorsvw.exe是 Microsoft .NET Framework(微软.NET框架)的核心系统进程,全称为 Microsoft .NET Runtime Optimizat
【学习笔记】Android进程调度及优化_processstate foreground visible
1.ADJ算法 1.1 ADJ级别 ADJ级别定义在 com.android.server.am.ProcessList.java中,oom_adj划分为16级,分别如下所示(Android 1
发表评论