Compile gdbserver for Android(gdb 7.1) - xianjimli/misc GitHub Wiki
前几天发现Prebuild的gdbserver在我们的平台上无法运行,只好自己去编译。按照网上的方法编译不过去,虽然折腾半天之后编译成功了,但是运行时只能看到一个线程。后来研究了一下代码,发现里面确实是有问题的:
td_ta_thr_iter是用来获取进程中线程的方法,在Android的实现在bionic/libthread_db/libthread_db.c里,它的实现很简单,遍历/proc/%d/task/目录即可。
td_err_e
td_ta_thr_iter(td_thragent_t const * agent, td_thr_iter_f * func, void * cookie,
td_thr_state_e state, int32_t prio, sigset_t * sigmask, uint32_t user_flags)
{
td_err_e err = TD_OK;
char path[32];
DIR * dir;
struct dirent * entry;
td_thrhandle_t handle;
snprintf(path, sizeof(path), "/proc/%d/task/", agent->pid);
dir = opendir(path);
if (!dir) {
return TD_NOEVENT;
}
handle.pid = agent->pid;
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
handle.tid = atoi(entry->d_name);
err = func(&handle, cookie);
if (err) {
break;
}
}
closedir(dir);
return err;
}
这里的agent->pid是在td_ta_new里初始化的,它从proc_handle->pid而来。
td_err_e
td_ta_new(struct ps_prochandle const * proc_handle, td_thragent_t ** agent_out)
{
td_thragent_t * agent;
agent = (td_thragent_t *)malloc(sizeof(td_thragent_t));
if (!agent) {
return TD_MALLOC;
}
agent->pid = proc_handle->pid;
*agent_out = agent;
return TD_OK;
}
问题是在调用tdb.td_ta_new_p时,proc_handle->pid根本就没有初始化,所以找不到进程中的线程。为了解决这个问题,我只强制把agent->pid设置为被调试的进程ID。
/* Attempt to open a connection to the thread library. */
err = tdb.td_ta_new_p (&tdb.proc_handle, &tdb.thread_agent);
if (err != TD_OK)
{
if (debug_threads)
fprintf (stderr, "td_ta_new(): %s\n", thread_db_err_str (err));
return 0;
}
//Li XianJing td_ta_new use tdb.proc_handle.pid to initialize tdb.thread_agent->pid,
//but tdb.proc_handle.pid is unknown, so I assign signal_pid to tdb.thread_agent->pid directly.
tdb.thread_agent->pid = signal_pid;
另外就是链接libthread_db.so的问题,无论用dlopen的方式或者还是编译链接都不行。我只好静态链接libthread_db.a,最后还要加几个空函数才能编译过去。