1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <dirent.h>
18 #include <stdint.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <sys/ptrace.h>
23 #include <thread_db.h>
24 #include <unistd.h>
25 
26 extern pid_t ps_getpid(struct ps_prochandle*);
27 
28 // We don't have any symbols to cache.
td_symbol_list(void)29 char const** td_symbol_list(void) {
30     static char const* symbols[] = { NULL };
31     return symbols;
32 }
33 
34 //
35 // Thread agents.
36 //
37 
td_ta_new(struct ps_prochandle * proc_handle,td_thragent_t ** agent_out)38 td_err_e td_ta_new(struct ps_prochandle* proc_handle, td_thragent_t** agent_out) {
39     td_thragent_t* agent = (td_thragent_t*) calloc(1, sizeof(td_thragent_t));
40     if (!agent) {
41         return TD_MALLOC;
42     }
43 
44     agent->pid = ps_getpid(proc_handle);
45     agent->ph = proc_handle;
46     *agent_out = agent;
47 
48     return TD_OK;
49 }
50 
51 
td_ta_delete(td_thragent_t * ta)52 td_err_e td_ta_delete(td_thragent_t* ta) {
53     free(ta);
54     return TD_OK;
55 }
56 
td_ta_map_lwp2thr(td_thragent_t const * agent,lwpid_t lwpid,td_thrhandle_t * th)57 td_err_e td_ta_map_lwp2thr(td_thragent_t const* agent, lwpid_t lwpid, td_thrhandle_t* th) {
58     th->pid = ps_getpid(agent->ph);
59     th->tid = lwpid;
60     return TD_OK;
61 }
62 
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)63 td_err_e td_ta_thr_iter(td_thragent_t const* agent,
64                         td_thr_iter_f* func,
65                         void* cookie,
66                         td_thr_state_e state,
67                         int32_t prio,
68                         sigset_t* sigmask,
69                         uint32_t user_flags) {
70     td_err_e err = TD_OK;
71     char path[32];
72     DIR * dir;
73     struct dirent * entry;
74     td_thrhandle_t handle;
75 
76     snprintf(path, sizeof(path), "/proc/%d/task/", agent->pid);
77     dir = opendir(path);
78     if (!dir) {
79         return TD_NOEVENT;
80     }
81 
82     handle.pid = agent->pid;
83     while ((entry = readdir(dir)) != NULL) {
84         if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
85             continue;
86         }
87         handle.tid = atoi(entry->d_name);
88         if (func(&handle, cookie) != 0) {
89 	    err = TD_DBERR;
90             break;
91         }
92     }
93 
94     closedir(dir);
95 
96     return err;
97 }
98 
99 //
100 // Threads.
101 //
102 
td_thr_get_info(td_thrhandle_t const * handle,td_thrinfo_t * info)103 td_err_e td_thr_get_info(td_thrhandle_t const* handle, td_thrinfo_t* info) {
104     info->ti_tid = handle->tid;
105     info->ti_lid = handle->tid; // Our pthreads uses kernel ids for tids
106     info->ti_state = TD_THR_SLEEP; /* XXX this needs to be read from /proc/<pid>/task/<tid>.
107                                       This is only used to see if the thread is a zombie or not */
108     return TD_OK;
109 }
110 
111 //
112 // TLS.
113 //
114 
td_thr_tlsbase(const td_thrhandle_t * unused1,unsigned long int unused2,psaddr_t * unused3)115 td_err_e td_thr_tlsbase(const td_thrhandle_t* unused1, unsigned long int unused2, psaddr_t* unused3) {
116   return TD_NOAPLIC; // TODO: fix this if/when we support ELF TLS.
117 }
118 
td_thr_tls_get_addr(const td_thrhandle_t * unused1,psaddr_t unused2,size_t unused3,psaddr_t * unused4)119 td_err_e td_thr_tls_get_addr(const td_thrhandle_t* unused1, psaddr_t unused2, size_t unused3, psaddr_t* unused4) {
120   return TD_NOAPLIC; // TODO: fix this if/when we support ELF TLS.
121 }
122 
123 //
124 // Thread events.
125 //
126 
127 // Thread events are no longer used by gdb >= 7.0.
128 // Because we link gdbserver statically, though, we need dummy definitions.
td_ta_set_event(td_thragent_t const * agent,td_thr_events_t * events)129 td_err_e td_ta_set_event(td_thragent_t const* agent, td_thr_events_t* events) {
130     abort();
131 }
td_ta_event_getmsg(td_thragent_t const * agent,td_event_msg_t * event)132 td_err_e td_ta_event_getmsg(td_thragent_t const* agent, td_event_msg_t* event) {
133     abort();
134 }
td_thr_event_enable(const td_thrhandle_t * handle,int event)135 td_err_e td_thr_event_enable(const td_thrhandle_t* handle, int event) {
136     abort();
137 }
td_ta_clear_event(const td_thragent_t * ta_arg,td_thr_events_t * event)138 td_err_e td_ta_clear_event(const td_thragent_t* ta_arg, td_thr_events_t* event) {
139     abort();
140 }
td_ta_event_addr(td_thragent_t const * agent,td_event_e event,td_notify_t * notify_out)141 td_err_e td_ta_event_addr(td_thragent_t const* agent, td_event_e event, td_notify_t* notify_out) {
142     abort();
143 }
144