Home | History | Annotate | Download | only in libthread_db
      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