admin 管理员组文章数量: 887042
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.freenas.com.cn/jishu/1705563654h490117.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
更多相关文章
1+X云计算中级习题
1+X云计算中级习题
linux中df命令的作用
linux中df命令的作用
如何解决windows系统错误1079:此服务的帐户不同于运行于同一进程上的其他服务的帐户
防火墙出现无法启动的情况时,可以参考如下操作方式 操作地址 另,在操作完成之后重新启动防火墙服务时如若还有错误,还应进行如下操作: 1、单击开始&a
服务器开机提示系统初始化失败,Win7开机提示"交互式登录进程初始化失败"怎么解决...
Win7系统虽然稳定,安全,但是在运行过程中有遇到一些故障问题,这不有位用户说Win7旗舰版开机突然跳出提示"交互式登录进程初始化失败"的提示窗口&
linux交互式进程初始化失败怎么办,win7系统开机提示"交互式登录进程初始化失败"怎么办?...
可以说,现实操作中的很多问题都会造成win7系统无法开机,无法开机出现的错误提示也是很多的,例如之前咱们介绍过的黑屏、白屏、蓝屏以及各种各样其他的提示,
操作系统 进程调度-银行家算法实验报告
实验要求 一、 实验目的 死锁会引起计算机工作僵死,因此操作系统中必须防止。本实验的目的在于让学生独立的使用高级语言编写和调试一个系统动态分配资源的简单模拟程序,了解死锁产生的条件和原因&
当你启动服务器出现系统出错。 发生系统错误 1067。 进程意外终止。
解决办法: 如下图将my-small中的内容复制给my的文件中即可 然后在管理员的命令中输入net start Mysql 即可,注意MySQL是服务器名,填写自己的服务器
浏览器原理 01 # Chrome架构:仅仅打开了1个页面,为什么有4个进程?
说明 浏览器工作原理与实践专栏学习笔记 进程和线程 什么是并行处理:计算机中的并行处理就是同一时刻处理多个任务 线程是不能单独存在的,它是由进程来启动和管理的。 进程 一个进程就是一个程序
逼近Windows限制:单个进程最大线&系统最大进程
首先讨论线程限制,因为每个活动进程至少有一个线程(终止的进程,但是由另一个进程拥有的句柄保持引用),所以进程的限制直接受到限制线程的上限的影响。 与一些UNIX变体不同&am
windows系统查看进程端口号的命令
查看进程端口号 1、查看windows所有端口进程 netstat -ano 命令提示符窗口:2、查询指定的端口占用 netstat -aon|findstr “端口” 显示列表中的PID
CC++ 判断进程是否存在
这段代码实现了一个函数getProcess,用于检查指定名称的进程是否存在。它通过遍历系统中的所有进程,对比输入的进程名(不区分大小写)与快照中的进程名
磁盘管理、进程管理、文件系统、软硬链接详细文档
项目技术操作文档项目名称:存储管理、进程管理 项目需求:1、在企业服务器上安装新硬盘,对磁盘进行分区、格式化、挂载处理2、根据企业服务器数据业务的不同,
Windows查看端口和进程
windows: 通过任务管理器查看进程信息 通过控制台查看进程信息 taskkill杀死进程 Linux: ps -ef 查看所有进程信息 kill 32029 使用k
操作系统课设之Windows 进程管理
前言 课程设计开始了,实验很有意思,写博客总结学到的知识 白嫖容易,创作不易,学到东西才是真 本文原创,创作不易
windows 系统 system 进程占用80端口
windows 系统 system 进程占用80端口 目录 一丶概述介绍 1.端口 二丶需求分析 1.Windows出现系统端口占用 三丶问题解决一丶概述介绍 1.端口 "端口"是英文por
windows下绑定线程(进程)到指定的CPU核心 http:blog.csdn.netbeyond_cnarticledetails15813361
windows下绑定线程(进程)到指定的CPU核心 2013-11-13 15:15 4423人阅读 评论(1) 收藏 举报 分类: 操作系统(
发表评论