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. 29 char const** td_symbol_list(void) { 30 static char const* symbols[] = { NULL }; 31 return symbols; 32 } 33 34 // 35 // Thread agents. 36 // 37 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 52 td_err_e td_ta_delete(td_thragent_t* ta) { 53 free(ta); 54 return TD_OK; 55 } 56 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 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 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 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 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. 129 td_err_e td_ta_set_event(td_thragent_t const* agent, td_thr_events_t* events) { 130 abort(); 131 } 132 td_err_e td_ta_event_getmsg(td_thragent_t const* agent, td_event_msg_t* event) { 133 abort(); 134 } 135 td_err_e td_thr_event_enable(const td_thrhandle_t* handle, int event) { 136 abort(); 137 } 138 td_err_e td_ta_clear_event(const td_thragent_t* ta_arg, td_thr_events_t* event) { 139 abort(); 140 } 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