xref: /aosp_15_r20/external/elfutils/libdwfl/linux-pid-attach.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Get Dwarf Frame state for target live PID process.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2013, 2014, 2015, 2018 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker    This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker 
5*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
6*7304104dSAndroid Build Coastguard Worker    it under the terms of either
7*7304104dSAndroid Build Coastguard Worker 
8*7304104dSAndroid Build Coastguard Worker      * the GNU Lesser General Public License as published by the Free
9*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 3 of the License, or (at
10*7304104dSAndroid Build Coastguard Worker        your option) any later version
11*7304104dSAndroid Build Coastguard Worker 
12*7304104dSAndroid Build Coastguard Worker    or
13*7304104dSAndroid Build Coastguard Worker 
14*7304104dSAndroid Build Coastguard Worker      * the GNU General Public License as published by the Free
15*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 2 of the License, or (at
16*7304104dSAndroid Build Coastguard Worker        your option) any later version
17*7304104dSAndroid Build Coastguard Worker 
18*7304104dSAndroid Build Coastguard Worker    or both in parallel, as here.
19*7304104dSAndroid Build Coastguard Worker 
20*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
21*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
22*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23*7304104dSAndroid Build Coastguard Worker    General Public License for more details.
24*7304104dSAndroid Build Coastguard Worker 
25*7304104dSAndroid Build Coastguard Worker    You should have received copies of the GNU General Public License and
26*7304104dSAndroid Build Coastguard Worker    the GNU Lesser General Public License along with this program.  If
27*7304104dSAndroid Build Coastguard Worker    not, see <http://www.gnu.org/licenses/>.  */
28*7304104dSAndroid Build Coastguard Worker 
29*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
30*7304104dSAndroid Build Coastguard Worker # include <config.h>
31*7304104dSAndroid Build Coastguard Worker #endif
32*7304104dSAndroid Build Coastguard Worker 
33*7304104dSAndroid Build Coastguard Worker #include <system.h>
34*7304104dSAndroid Build Coastguard Worker 
35*7304104dSAndroid Build Coastguard Worker #include "libelfP.h"
36*7304104dSAndroid Build Coastguard Worker #include "libdwflP.h"
37*7304104dSAndroid Build Coastguard Worker #include <sys/types.h>
38*7304104dSAndroid Build Coastguard Worker #include <sys/stat.h>
39*7304104dSAndroid Build Coastguard Worker #include <fcntl.h>
40*7304104dSAndroid Build Coastguard Worker #include <dirent.h>
41*7304104dSAndroid Build Coastguard Worker 
42*7304104dSAndroid Build Coastguard Worker #ifdef __linux__
43*7304104dSAndroid Build Coastguard Worker 
44*7304104dSAndroid Build Coastguard Worker #include <sys/uio.h>
45*7304104dSAndroid Build Coastguard Worker #include <sys/ptrace.h>
46*7304104dSAndroid Build Coastguard Worker #include <sys/syscall.h>
47*7304104dSAndroid Build Coastguard Worker #include <sys/wait.h>
48*7304104dSAndroid Build Coastguard Worker 
49*7304104dSAndroid Build Coastguard Worker static bool
linux_proc_pid_is_stopped(pid_t pid)50*7304104dSAndroid Build Coastguard Worker linux_proc_pid_is_stopped (pid_t pid)
51*7304104dSAndroid Build Coastguard Worker {
52*7304104dSAndroid Build Coastguard Worker   char buffer[64];
53*7304104dSAndroid Build Coastguard Worker   FILE *procfile;
54*7304104dSAndroid Build Coastguard Worker   bool retval, have_state;
55*7304104dSAndroid Build Coastguard Worker 
56*7304104dSAndroid Build Coastguard Worker   snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
57*7304104dSAndroid Build Coastguard Worker   procfile = fopen (buffer, "r");
58*7304104dSAndroid Build Coastguard Worker   if (procfile == NULL)
59*7304104dSAndroid Build Coastguard Worker     return false;
60*7304104dSAndroid Build Coastguard Worker 
61*7304104dSAndroid Build Coastguard Worker   have_state = false;
62*7304104dSAndroid Build Coastguard Worker   while (fgets (buffer, sizeof (buffer), procfile) != NULL)
63*7304104dSAndroid Build Coastguard Worker     if (startswith (buffer, "State:"))
64*7304104dSAndroid Build Coastguard Worker       {
65*7304104dSAndroid Build Coastguard Worker 	have_state = true;
66*7304104dSAndroid Build Coastguard Worker 	break;
67*7304104dSAndroid Build Coastguard Worker       }
68*7304104dSAndroid Build Coastguard Worker   retval = (have_state && strstr (buffer, "T (stopped)") != NULL);
69*7304104dSAndroid Build Coastguard Worker   fclose (procfile);
70*7304104dSAndroid Build Coastguard Worker   return retval;
71*7304104dSAndroid Build Coastguard Worker }
72*7304104dSAndroid Build Coastguard Worker 
73*7304104dSAndroid Build Coastguard Worker bool
74*7304104dSAndroid Build Coastguard Worker internal_function
__libdwfl_ptrace_attach(pid_t tid,bool * tid_was_stoppedp)75*7304104dSAndroid Build Coastguard Worker __libdwfl_ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
76*7304104dSAndroid Build Coastguard Worker {
77*7304104dSAndroid Build Coastguard Worker   if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
78*7304104dSAndroid Build Coastguard Worker     {
79*7304104dSAndroid Build Coastguard Worker       __libdwfl_seterrno (DWFL_E_ERRNO);
80*7304104dSAndroid Build Coastguard Worker       return false;
81*7304104dSAndroid Build Coastguard Worker     }
82*7304104dSAndroid Build Coastguard Worker   *tid_was_stoppedp = linux_proc_pid_is_stopped (tid);
83*7304104dSAndroid Build Coastguard Worker   if (*tid_was_stoppedp)
84*7304104dSAndroid Build Coastguard Worker     {
85*7304104dSAndroid Build Coastguard Worker       /* Make sure there is a SIGSTOP signal pending even when the process is
86*7304104dSAndroid Build Coastguard Worker 	 already State: T (stopped).  Older kernels might fail to generate
87*7304104dSAndroid Build Coastguard Worker 	 a SIGSTOP notification in that case in response to our PTRACE_ATTACH
88*7304104dSAndroid Build Coastguard Worker 	 above.  Which would make the waitpid below wait forever.  So emulate
89*7304104dSAndroid Build Coastguard Worker 	 it.  Since there can only be one SIGSTOP notification pending this is
90*7304104dSAndroid Build Coastguard Worker 	 safe.  See also gdb/linux-nat.c linux_nat_post_attach_wait.  */
91*7304104dSAndroid Build Coastguard Worker       syscall (__NR_tkill, tid, SIGSTOP);
92*7304104dSAndroid Build Coastguard Worker       ptrace (PTRACE_CONT, tid, NULL, NULL);
93*7304104dSAndroid Build Coastguard Worker     }
94*7304104dSAndroid Build Coastguard Worker   for (;;)
95*7304104dSAndroid Build Coastguard Worker     {
96*7304104dSAndroid Build Coastguard Worker       int status;
97*7304104dSAndroid Build Coastguard Worker       if (waitpid (tid, &status, __WALL) != tid || !WIFSTOPPED (status))
98*7304104dSAndroid Build Coastguard Worker 	{
99*7304104dSAndroid Build Coastguard Worker 	  int saved_errno = errno;
100*7304104dSAndroid Build Coastguard Worker 	  ptrace (PTRACE_DETACH, tid, NULL, NULL);
101*7304104dSAndroid Build Coastguard Worker 	  errno = saved_errno;
102*7304104dSAndroid Build Coastguard Worker 	  __libdwfl_seterrno (DWFL_E_ERRNO);
103*7304104dSAndroid Build Coastguard Worker 	  return false;
104*7304104dSAndroid Build Coastguard Worker 	}
105*7304104dSAndroid Build Coastguard Worker       if (WSTOPSIG (status) == SIGSTOP)
106*7304104dSAndroid Build Coastguard Worker 	break;
107*7304104dSAndroid Build Coastguard Worker       if (ptrace (PTRACE_CONT, tid, NULL,
108*7304104dSAndroid Build Coastguard Worker 		  (void *) (uintptr_t) WSTOPSIG (status)) != 0)
109*7304104dSAndroid Build Coastguard Worker 	{
110*7304104dSAndroid Build Coastguard Worker 	  int saved_errno = errno;
111*7304104dSAndroid Build Coastguard Worker 	  ptrace (PTRACE_DETACH, tid, NULL, NULL);
112*7304104dSAndroid Build Coastguard Worker 	  errno = saved_errno;
113*7304104dSAndroid Build Coastguard Worker 	  __libdwfl_seterrno (DWFL_E_ERRNO);
114*7304104dSAndroid Build Coastguard Worker 	  return false;
115*7304104dSAndroid Build Coastguard Worker 	}
116*7304104dSAndroid Build Coastguard Worker     }
117*7304104dSAndroid Build Coastguard Worker   return true;
118*7304104dSAndroid Build Coastguard Worker }
119*7304104dSAndroid Build Coastguard Worker 
120*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_PROCESS_VM_READV
121*7304104dSAndroid Build Coastguard Worker /* Note that the result word size depends on the architecture word size.
122*7304104dSAndroid Build Coastguard Worker    That is sizeof long. */
123*7304104dSAndroid Build Coastguard Worker static bool
read_cached_memory(struct __libdwfl_pid_arg * pid_arg,Dwarf_Addr addr,Dwarf_Word * result)124*7304104dSAndroid Build Coastguard Worker read_cached_memory (struct __libdwfl_pid_arg *pid_arg,
125*7304104dSAndroid Build Coastguard Worker 		    Dwarf_Addr addr, Dwarf_Word *result)
126*7304104dSAndroid Build Coastguard Worker {
127*7304104dSAndroid Build Coastguard Worker   /* Let the ptrace fallback deal with the corner case of the address
128*7304104dSAndroid Build Coastguard Worker      possibly crossing a page boundary.  */
129*7304104dSAndroid Build Coastguard Worker   if ((addr & ((Dwarf_Addr)__LIBDWFL_REMOTE_MEM_CACHE_SIZE - 1))
130*7304104dSAndroid Build Coastguard Worker       > (Dwarf_Addr)__LIBDWFL_REMOTE_MEM_CACHE_SIZE - sizeof (unsigned long))
131*7304104dSAndroid Build Coastguard Worker     return false;
132*7304104dSAndroid Build Coastguard Worker 
133*7304104dSAndroid Build Coastguard Worker   struct __libdwfl_remote_mem_cache *mem_cache = pid_arg->mem_cache;
134*7304104dSAndroid Build Coastguard Worker   if (mem_cache == NULL)
135*7304104dSAndroid Build Coastguard Worker     {
136*7304104dSAndroid Build Coastguard Worker       size_t mem_cache_size = sizeof (struct __libdwfl_remote_mem_cache);
137*7304104dSAndroid Build Coastguard Worker       mem_cache = malloc (mem_cache_size);
138*7304104dSAndroid Build Coastguard Worker       if (mem_cache == NULL)
139*7304104dSAndroid Build Coastguard Worker 	return false;
140*7304104dSAndroid Build Coastguard Worker 
141*7304104dSAndroid Build Coastguard Worker       mem_cache->addr = 0;
142*7304104dSAndroid Build Coastguard Worker       mem_cache->len = 0;
143*7304104dSAndroid Build Coastguard Worker       pid_arg->mem_cache = mem_cache;
144*7304104dSAndroid Build Coastguard Worker     }
145*7304104dSAndroid Build Coastguard Worker 
146*7304104dSAndroid Build Coastguard Worker   unsigned char *d;
147*7304104dSAndroid Build Coastguard Worker   if (addr >= mem_cache->addr && addr - mem_cache->addr < mem_cache->len)
148*7304104dSAndroid Build Coastguard Worker     {
149*7304104dSAndroid Build Coastguard Worker       d = &mem_cache->buf[addr - mem_cache->addr];
150*7304104dSAndroid Build Coastguard Worker       if ((((uintptr_t) d) & (sizeof (unsigned long) - 1)) == 0)
151*7304104dSAndroid Build Coastguard Worker 	*result = *(unsigned long *) d;
152*7304104dSAndroid Build Coastguard Worker       else
153*7304104dSAndroid Build Coastguard Worker 	memcpy (result, d, sizeof (unsigned long));
154*7304104dSAndroid Build Coastguard Worker       return true;
155*7304104dSAndroid Build Coastguard Worker     }
156*7304104dSAndroid Build Coastguard Worker 
157*7304104dSAndroid Build Coastguard Worker   struct iovec local, remote;
158*7304104dSAndroid Build Coastguard Worker   mem_cache->addr = addr & ~((Dwarf_Addr)__LIBDWFL_REMOTE_MEM_CACHE_SIZE - 1);
159*7304104dSAndroid Build Coastguard Worker   local.iov_base = mem_cache->buf;
160*7304104dSAndroid Build Coastguard Worker   local.iov_len = __LIBDWFL_REMOTE_MEM_CACHE_SIZE;
161*7304104dSAndroid Build Coastguard Worker   remote.iov_base = (void *) (uintptr_t) mem_cache->addr;
162*7304104dSAndroid Build Coastguard Worker   remote.iov_len = __LIBDWFL_REMOTE_MEM_CACHE_SIZE;
163*7304104dSAndroid Build Coastguard Worker 
164*7304104dSAndroid Build Coastguard Worker   ssize_t res = process_vm_readv (pid_arg->tid_attached,
165*7304104dSAndroid Build Coastguard Worker 				  &local, 1, &remote, 1, 0);
166*7304104dSAndroid Build Coastguard Worker   if (res != __LIBDWFL_REMOTE_MEM_CACHE_SIZE)
167*7304104dSAndroid Build Coastguard Worker     {
168*7304104dSAndroid Build Coastguard Worker       mem_cache->len = 0;
169*7304104dSAndroid Build Coastguard Worker       return false;
170*7304104dSAndroid Build Coastguard Worker     }
171*7304104dSAndroid Build Coastguard Worker 
172*7304104dSAndroid Build Coastguard Worker   mem_cache->len = res;
173*7304104dSAndroid Build Coastguard Worker   d = &mem_cache->buf[addr - mem_cache->addr];
174*7304104dSAndroid Build Coastguard Worker   if ((((uintptr_t) d) & (sizeof (unsigned long) - 1)) == 0)
175*7304104dSAndroid Build Coastguard Worker     *result = *(unsigned long *) d;
176*7304104dSAndroid Build Coastguard Worker   else
177*7304104dSAndroid Build Coastguard Worker     memcpy (result, d, sizeof (unsigned long));
178*7304104dSAndroid Build Coastguard Worker   return true;
179*7304104dSAndroid Build Coastguard Worker }
180*7304104dSAndroid Build Coastguard Worker #endif /* HAVE_PROCESS_VM_READV */
181*7304104dSAndroid Build Coastguard Worker 
182*7304104dSAndroid Build Coastguard Worker static void
clear_cached_memory(struct __libdwfl_pid_arg * pid_arg)183*7304104dSAndroid Build Coastguard Worker clear_cached_memory (struct __libdwfl_pid_arg *pid_arg)
184*7304104dSAndroid Build Coastguard Worker {
185*7304104dSAndroid Build Coastguard Worker   struct __libdwfl_remote_mem_cache *mem_cache = pid_arg->mem_cache;
186*7304104dSAndroid Build Coastguard Worker   if (mem_cache != NULL)
187*7304104dSAndroid Build Coastguard Worker     mem_cache->len = 0;
188*7304104dSAndroid Build Coastguard Worker }
189*7304104dSAndroid Build Coastguard Worker 
190*7304104dSAndroid Build Coastguard Worker /* Note that the result word size depends on the architecture word size.
191*7304104dSAndroid Build Coastguard Worker    That is sizeof long. */
192*7304104dSAndroid Build Coastguard Worker static bool
pid_memory_read(Dwfl * dwfl,Dwarf_Addr addr,Dwarf_Word * result,void * arg)193*7304104dSAndroid Build Coastguard Worker pid_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, void *arg)
194*7304104dSAndroid Build Coastguard Worker {
195*7304104dSAndroid Build Coastguard Worker   struct __libdwfl_pid_arg *pid_arg = arg;
196*7304104dSAndroid Build Coastguard Worker   pid_t tid = pid_arg->tid_attached;
197*7304104dSAndroid Build Coastguard Worker   Dwfl_Process *process = dwfl->process;
198*7304104dSAndroid Build Coastguard Worker   assert (tid > 0);
199*7304104dSAndroid Build Coastguard Worker 
200*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_PROCESS_VM_READV
201*7304104dSAndroid Build Coastguard Worker   if (read_cached_memory (pid_arg, addr, result))
202*7304104dSAndroid Build Coastguard Worker     {
203*7304104dSAndroid Build Coastguard Worker #if SIZEOF_LONG == 8
204*7304104dSAndroid Build Coastguard Worker # if BYTE_ORDER == BIG_ENDIAN
205*7304104dSAndroid Build Coastguard Worker       if (ebl_get_elfclass (process->ebl) == ELFCLASS32)
206*7304104dSAndroid Build Coastguard Worker 	*result >>= 32;
207*7304104dSAndroid Build Coastguard Worker # endif
208*7304104dSAndroid Build Coastguard Worker #endif
209*7304104dSAndroid Build Coastguard Worker     return true;
210*7304104dSAndroid Build Coastguard Worker     }
211*7304104dSAndroid Build Coastguard Worker #endif
212*7304104dSAndroid Build Coastguard Worker 
213*7304104dSAndroid Build Coastguard Worker   if (ebl_get_elfclass (process->ebl) == ELFCLASS64)
214*7304104dSAndroid Build Coastguard Worker     {
215*7304104dSAndroid Build Coastguard Worker #if SIZEOF_LONG == 8
216*7304104dSAndroid Build Coastguard Worker       errno = 0;
217*7304104dSAndroid Build Coastguard Worker       *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
218*7304104dSAndroid Build Coastguard Worker       return errno == 0;
219*7304104dSAndroid Build Coastguard Worker #else /* SIZEOF_LONG != 8 */
220*7304104dSAndroid Build Coastguard Worker       /* This should not happen.  */
221*7304104dSAndroid Build Coastguard Worker       return false;
222*7304104dSAndroid Build Coastguard Worker #endif /* SIZEOF_LONG != 8 */
223*7304104dSAndroid Build Coastguard Worker     }
224*7304104dSAndroid Build Coastguard Worker #if SIZEOF_LONG == 8
225*7304104dSAndroid Build Coastguard Worker   /* We do not care about reads unaliged to 4 bytes boundary.
226*7304104dSAndroid Build Coastguard Worker      But 0x...ffc read of 8 bytes could overrun a page.  */
227*7304104dSAndroid Build Coastguard Worker   bool lowered = (addr & 4) != 0;
228*7304104dSAndroid Build Coastguard Worker   if (lowered)
229*7304104dSAndroid Build Coastguard Worker     addr -= 4;
230*7304104dSAndroid Build Coastguard Worker #endif /* SIZEOF_LONG == 8 */
231*7304104dSAndroid Build Coastguard Worker   errno = 0;
232*7304104dSAndroid Build Coastguard Worker   *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
233*7304104dSAndroid Build Coastguard Worker   if (errno != 0)
234*7304104dSAndroid Build Coastguard Worker     return false;
235*7304104dSAndroid Build Coastguard Worker #if SIZEOF_LONG == 8
236*7304104dSAndroid Build Coastguard Worker # if BYTE_ORDER == BIG_ENDIAN
237*7304104dSAndroid Build Coastguard Worker   if (! lowered)
238*7304104dSAndroid Build Coastguard Worker     *result >>= 32;
239*7304104dSAndroid Build Coastguard Worker # else
240*7304104dSAndroid Build Coastguard Worker   if (lowered)
241*7304104dSAndroid Build Coastguard Worker     *result >>= 32;
242*7304104dSAndroid Build Coastguard Worker # endif
243*7304104dSAndroid Build Coastguard Worker #endif /* SIZEOF_LONG == 8 */
244*7304104dSAndroid Build Coastguard Worker   *result &= 0xffffffff;
245*7304104dSAndroid Build Coastguard Worker   return true;
246*7304104dSAndroid Build Coastguard Worker }
247*7304104dSAndroid Build Coastguard Worker 
248*7304104dSAndroid Build Coastguard Worker static pid_t
pid_next_thread(Dwfl * dwfl,void * dwfl_arg,void ** thread_argp)249*7304104dSAndroid Build Coastguard Worker pid_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
250*7304104dSAndroid Build Coastguard Worker 		 void **thread_argp)
251*7304104dSAndroid Build Coastguard Worker {
252*7304104dSAndroid Build Coastguard Worker   struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
253*7304104dSAndroid Build Coastguard Worker   struct dirent *dirent;
254*7304104dSAndroid Build Coastguard Worker   /* Start fresh on first traversal. */
255*7304104dSAndroid Build Coastguard Worker   if (*thread_argp == NULL)
256*7304104dSAndroid Build Coastguard Worker     rewinddir (pid_arg->dir);
257*7304104dSAndroid Build Coastguard Worker   do
258*7304104dSAndroid Build Coastguard Worker     {
259*7304104dSAndroid Build Coastguard Worker       errno = 0;
260*7304104dSAndroid Build Coastguard Worker       dirent = readdir (pid_arg->dir);
261*7304104dSAndroid Build Coastguard Worker       if (dirent == NULL)
262*7304104dSAndroid Build Coastguard Worker 	{
263*7304104dSAndroid Build Coastguard Worker 	  if (errno != 0)
264*7304104dSAndroid Build Coastguard Worker 	    {
265*7304104dSAndroid Build Coastguard Worker 	      __libdwfl_seterrno (DWFL_E_ERRNO);
266*7304104dSAndroid Build Coastguard Worker 	      return -1;
267*7304104dSAndroid Build Coastguard Worker 	    }
268*7304104dSAndroid Build Coastguard Worker 	  return 0;
269*7304104dSAndroid Build Coastguard Worker 	}
270*7304104dSAndroid Build Coastguard Worker     }
271*7304104dSAndroid Build Coastguard Worker   while (strcmp (dirent->d_name, ".") == 0
272*7304104dSAndroid Build Coastguard Worker 	 || strcmp (dirent->d_name, "..") == 0);
273*7304104dSAndroid Build Coastguard Worker   char *end;
274*7304104dSAndroid Build Coastguard Worker   errno = 0;
275*7304104dSAndroid Build Coastguard Worker   long tidl = strtol (dirent->d_name, &end, 10);
276*7304104dSAndroid Build Coastguard Worker   if (errno != 0)
277*7304104dSAndroid Build Coastguard Worker     {
278*7304104dSAndroid Build Coastguard Worker       __libdwfl_seterrno (DWFL_E_ERRNO);
279*7304104dSAndroid Build Coastguard Worker       return -1;
280*7304104dSAndroid Build Coastguard Worker     }
281*7304104dSAndroid Build Coastguard Worker   pid_t tid = tidl;
282*7304104dSAndroid Build Coastguard Worker   if (tidl <= 0 || (end && *end) || tid != tidl)
283*7304104dSAndroid Build Coastguard Worker     {
284*7304104dSAndroid Build Coastguard Worker       __libdwfl_seterrno (DWFL_E_PARSE_PROC);
285*7304104dSAndroid Build Coastguard Worker       return -1;
286*7304104dSAndroid Build Coastguard Worker     }
287*7304104dSAndroid Build Coastguard Worker   *thread_argp = dwfl_arg;
288*7304104dSAndroid Build Coastguard Worker   return tid;
289*7304104dSAndroid Build Coastguard Worker }
290*7304104dSAndroid Build Coastguard Worker 
291*7304104dSAndroid Build Coastguard Worker /* Just checks that the thread id exists.  */
292*7304104dSAndroid Build Coastguard Worker static bool
pid_getthread(Dwfl * dwfl,pid_t tid,void * dwfl_arg,void ** thread_argp)293*7304104dSAndroid Build Coastguard Worker pid_getthread (Dwfl *dwfl __attribute__ ((unused)), pid_t tid,
294*7304104dSAndroid Build Coastguard Worker 	       void *dwfl_arg, void **thread_argp)
295*7304104dSAndroid Build Coastguard Worker {
296*7304104dSAndroid Build Coastguard Worker   *thread_argp = dwfl_arg;
297*7304104dSAndroid Build Coastguard Worker   if (kill (tid, 0) < 0)
298*7304104dSAndroid Build Coastguard Worker     {
299*7304104dSAndroid Build Coastguard Worker       __libdwfl_seterrno (DWFL_E_ERRNO);
300*7304104dSAndroid Build Coastguard Worker       return false;
301*7304104dSAndroid Build Coastguard Worker     }
302*7304104dSAndroid Build Coastguard Worker   return true;
303*7304104dSAndroid Build Coastguard Worker }
304*7304104dSAndroid Build Coastguard Worker 
305*7304104dSAndroid Build Coastguard Worker /* Implement the ebl_set_initial_registers_tid setfunc callback.  */
306*7304104dSAndroid Build Coastguard Worker 
307*7304104dSAndroid Build Coastguard Worker static bool
pid_thread_state_registers_cb(int firstreg,unsigned nregs,const Dwarf_Word * regs,void * arg)308*7304104dSAndroid Build Coastguard Worker pid_thread_state_registers_cb (int firstreg, unsigned nregs,
309*7304104dSAndroid Build Coastguard Worker 			       const Dwarf_Word *regs, void *arg)
310*7304104dSAndroid Build Coastguard Worker {
311*7304104dSAndroid Build Coastguard Worker   Dwfl_Thread *thread = (Dwfl_Thread *) arg;
312*7304104dSAndroid Build Coastguard Worker   if (firstreg < 0)
313*7304104dSAndroid Build Coastguard Worker     {
314*7304104dSAndroid Build Coastguard Worker       assert (firstreg == -1);
315*7304104dSAndroid Build Coastguard Worker       assert (nregs == 1);
316*7304104dSAndroid Build Coastguard Worker       INTUSE(dwfl_thread_state_register_pc) (thread, *regs);
317*7304104dSAndroid Build Coastguard Worker       return true;
318*7304104dSAndroid Build Coastguard Worker     }
319*7304104dSAndroid Build Coastguard Worker   assert (nregs > 0);
320*7304104dSAndroid Build Coastguard Worker   return INTUSE(dwfl_thread_state_registers) (thread, firstreg, nregs, regs);
321*7304104dSAndroid Build Coastguard Worker }
322*7304104dSAndroid Build Coastguard Worker 
323*7304104dSAndroid Build Coastguard Worker static bool
pid_set_initial_registers(Dwfl_Thread * thread,void * thread_arg)324*7304104dSAndroid Build Coastguard Worker pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
325*7304104dSAndroid Build Coastguard Worker {
326*7304104dSAndroid Build Coastguard Worker   struct __libdwfl_pid_arg *pid_arg = thread_arg;
327*7304104dSAndroid Build Coastguard Worker   assert (pid_arg->tid_attached == 0);
328*7304104dSAndroid Build Coastguard Worker   pid_t tid = INTUSE(dwfl_thread_tid) (thread);
329*7304104dSAndroid Build Coastguard Worker   if (! pid_arg->assume_ptrace_stopped
330*7304104dSAndroid Build Coastguard Worker       && ! __libdwfl_ptrace_attach (tid, &pid_arg->tid_was_stopped))
331*7304104dSAndroid Build Coastguard Worker     return false;
332*7304104dSAndroid Build Coastguard Worker   pid_arg->tid_attached = tid;
333*7304104dSAndroid Build Coastguard Worker   Dwfl_Process *process = thread->process;
334*7304104dSAndroid Build Coastguard Worker   Ebl *ebl = process->ebl;
335*7304104dSAndroid Build Coastguard Worker   return ebl_set_initial_registers_tid (ebl, tid,
336*7304104dSAndroid Build Coastguard Worker 					pid_thread_state_registers_cb, thread);
337*7304104dSAndroid Build Coastguard Worker }
338*7304104dSAndroid Build Coastguard Worker 
339*7304104dSAndroid Build Coastguard Worker static void
pid_detach(Dwfl * dwfl,void * dwfl_arg)340*7304104dSAndroid Build Coastguard Worker pid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
341*7304104dSAndroid Build Coastguard Worker {
342*7304104dSAndroid Build Coastguard Worker   struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
343*7304104dSAndroid Build Coastguard Worker   elf_end (pid_arg->elf);
344*7304104dSAndroid Build Coastguard Worker   free (pid_arg->mem_cache);
345*7304104dSAndroid Build Coastguard Worker   close (pid_arg->elf_fd);
346*7304104dSAndroid Build Coastguard Worker   closedir (pid_arg->dir);
347*7304104dSAndroid Build Coastguard Worker   free (pid_arg);
348*7304104dSAndroid Build Coastguard Worker }
349*7304104dSAndroid Build Coastguard Worker 
350*7304104dSAndroid Build Coastguard Worker void
351*7304104dSAndroid Build Coastguard Worker internal_function
__libdwfl_ptrace_detach(pid_t tid,bool tid_was_stopped)352*7304104dSAndroid Build Coastguard Worker __libdwfl_ptrace_detach (pid_t tid, bool tid_was_stopped)
353*7304104dSAndroid Build Coastguard Worker {
354*7304104dSAndroid Build Coastguard Worker   /* This handling is needed only on older Linux kernels such as
355*7304104dSAndroid Build Coastguard Worker      2.6.32-358.23.2.el6.ppc64.  Later kernels such as
356*7304104dSAndroid Build Coastguard Worker      3.11.7-200.fc19.x86_64 remember the T (stopped) state
357*7304104dSAndroid Build Coastguard Worker      themselves and no longer need to pass SIGSTOP during
358*7304104dSAndroid Build Coastguard Worker      PTRACE_DETACH.  */
359*7304104dSAndroid Build Coastguard Worker   ptrace (PTRACE_DETACH, tid, NULL,
360*7304104dSAndroid Build Coastguard Worker 	  (void *) (intptr_t) (tid_was_stopped ? SIGSTOP : 0));
361*7304104dSAndroid Build Coastguard Worker }
362*7304104dSAndroid Build Coastguard Worker 
363*7304104dSAndroid Build Coastguard Worker static void
pid_thread_detach(Dwfl_Thread * thread,void * thread_arg)364*7304104dSAndroid Build Coastguard Worker pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
365*7304104dSAndroid Build Coastguard Worker {
366*7304104dSAndroid Build Coastguard Worker   struct __libdwfl_pid_arg *pid_arg = thread_arg;
367*7304104dSAndroid Build Coastguard Worker   pid_t tid = INTUSE(dwfl_thread_tid) (thread);
368*7304104dSAndroid Build Coastguard Worker   assert (pid_arg->tid_attached == tid);
369*7304104dSAndroid Build Coastguard Worker   pid_arg->tid_attached = 0;
370*7304104dSAndroid Build Coastguard Worker   clear_cached_memory (pid_arg);
371*7304104dSAndroid Build Coastguard Worker   if (! pid_arg->assume_ptrace_stopped)
372*7304104dSAndroid Build Coastguard Worker     __libdwfl_ptrace_detach (tid, pid_arg->tid_was_stopped);
373*7304104dSAndroid Build Coastguard Worker }
374*7304104dSAndroid Build Coastguard Worker 
375*7304104dSAndroid Build Coastguard Worker static const Dwfl_Thread_Callbacks pid_thread_callbacks =
376*7304104dSAndroid Build Coastguard Worker {
377*7304104dSAndroid Build Coastguard Worker   pid_next_thread,
378*7304104dSAndroid Build Coastguard Worker   pid_getthread,
379*7304104dSAndroid Build Coastguard Worker   pid_memory_read,
380*7304104dSAndroid Build Coastguard Worker   pid_set_initial_registers,
381*7304104dSAndroid Build Coastguard Worker   pid_detach,
382*7304104dSAndroid Build Coastguard Worker   pid_thread_detach,
383*7304104dSAndroid Build Coastguard Worker };
384*7304104dSAndroid Build Coastguard Worker 
385*7304104dSAndroid Build Coastguard Worker int
dwfl_linux_proc_attach(Dwfl * dwfl,pid_t pid,bool assume_ptrace_stopped)386*7304104dSAndroid Build Coastguard Worker dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
387*7304104dSAndroid Build Coastguard Worker {
388*7304104dSAndroid Build Coastguard Worker   char buffer[36];
389*7304104dSAndroid Build Coastguard Worker   FILE *procfile;
390*7304104dSAndroid Build Coastguard Worker   int err = 0; /* The errno to return and set for dwfl->attcherr.  */
391*7304104dSAndroid Build Coastguard Worker 
392*7304104dSAndroid Build Coastguard Worker   /* Make sure to report the actual PID (thread group leader) to
393*7304104dSAndroid Build Coastguard Worker      dwfl_attach_state.  */
394*7304104dSAndroid Build Coastguard Worker   snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
395*7304104dSAndroid Build Coastguard Worker   procfile = fopen (buffer, "r");
396*7304104dSAndroid Build Coastguard Worker   if (procfile == NULL)
397*7304104dSAndroid Build Coastguard Worker     {
398*7304104dSAndroid Build Coastguard Worker       err = errno;
399*7304104dSAndroid Build Coastguard Worker     fail:
400*7304104dSAndroid Build Coastguard Worker       if (dwfl->process == NULL && dwfl->attacherr == DWFL_E_NOERROR)
401*7304104dSAndroid Build Coastguard Worker 	{
402*7304104dSAndroid Build Coastguard Worker 	  errno = err;
403*7304104dSAndroid Build Coastguard Worker 	  dwfl->attacherr = __libdwfl_canon_error (DWFL_E_ERRNO);
404*7304104dSAndroid Build Coastguard Worker 	}
405*7304104dSAndroid Build Coastguard Worker       return err;
406*7304104dSAndroid Build Coastguard Worker     }
407*7304104dSAndroid Build Coastguard Worker 
408*7304104dSAndroid Build Coastguard Worker   char *line = NULL;
409*7304104dSAndroid Build Coastguard Worker   size_t linelen = 0;
410*7304104dSAndroid Build Coastguard Worker   while (getline (&line, &linelen, procfile) >= 0)
411*7304104dSAndroid Build Coastguard Worker     if (startswith (line, "Tgid:"))
412*7304104dSAndroid Build Coastguard Worker       {
413*7304104dSAndroid Build Coastguard Worker 	errno = 0;
414*7304104dSAndroid Build Coastguard Worker 	char *endptr;
415*7304104dSAndroid Build Coastguard Worker 	long val = strtol (&line[5], &endptr, 10);
416*7304104dSAndroid Build Coastguard Worker 	if ((errno == ERANGE && val == LONG_MAX)
417*7304104dSAndroid Build Coastguard Worker 	    || *endptr != '\n' || val < 0 || val != (pid_t) val)
418*7304104dSAndroid Build Coastguard Worker 	  pid = 0;
419*7304104dSAndroid Build Coastguard Worker 	else
420*7304104dSAndroid Build Coastguard Worker 	  pid = (pid_t) val;
421*7304104dSAndroid Build Coastguard Worker 	break;
422*7304104dSAndroid Build Coastguard Worker       }
423*7304104dSAndroid Build Coastguard Worker   free (line);
424*7304104dSAndroid Build Coastguard Worker   fclose (procfile);
425*7304104dSAndroid Build Coastguard Worker 
426*7304104dSAndroid Build Coastguard Worker   if (pid == 0)
427*7304104dSAndroid Build Coastguard Worker     {
428*7304104dSAndroid Build Coastguard Worker       err = ESRCH;
429*7304104dSAndroid Build Coastguard Worker       goto fail;
430*7304104dSAndroid Build Coastguard Worker     }
431*7304104dSAndroid Build Coastguard Worker 
432*7304104dSAndroid Build Coastguard Worker   char name[64];
433*7304104dSAndroid Build Coastguard Worker   int i = snprintf (name, sizeof (name), "/proc/%ld/task", (long) pid);
434*7304104dSAndroid Build Coastguard Worker   if (i <= 0 || i >= (ssize_t) sizeof (name) - 1)
435*7304104dSAndroid Build Coastguard Worker     {
436*7304104dSAndroid Build Coastguard Worker       errno = -ENOMEM;
437*7304104dSAndroid Build Coastguard Worker       goto fail;
438*7304104dSAndroid Build Coastguard Worker     }
439*7304104dSAndroid Build Coastguard Worker   DIR *dir = opendir (name);
440*7304104dSAndroid Build Coastguard Worker   if (dir == NULL)
441*7304104dSAndroid Build Coastguard Worker     {
442*7304104dSAndroid Build Coastguard Worker       err = errno;
443*7304104dSAndroid Build Coastguard Worker       goto fail;
444*7304104dSAndroid Build Coastguard Worker     }
445*7304104dSAndroid Build Coastguard Worker 
446*7304104dSAndroid Build Coastguard Worker   Elf *elf;
447*7304104dSAndroid Build Coastguard Worker   i = snprintf (name, sizeof (name), "/proc/%ld/exe", (long) pid);
448*7304104dSAndroid Build Coastguard Worker   assert (i > 0 && i < (ssize_t) sizeof (name) - 1);
449*7304104dSAndroid Build Coastguard Worker   int elf_fd = open (name, O_RDONLY);
450*7304104dSAndroid Build Coastguard Worker   if (elf_fd >= 0)
451*7304104dSAndroid Build Coastguard Worker     {
452*7304104dSAndroid Build Coastguard Worker       elf = elf_begin (elf_fd, ELF_C_READ_MMAP, NULL);
453*7304104dSAndroid Build Coastguard Worker       if (elf == NULL)
454*7304104dSAndroid Build Coastguard Worker 	{
455*7304104dSAndroid Build Coastguard Worker 	  /* Just ignore, dwfl_attach_state will fall back to trying
456*7304104dSAndroid Build Coastguard Worker 	     to associate the Dwfl with one of the existing DWfl_Module
457*7304104dSAndroid Build Coastguard Worker 	     ELF images (to know the machine/class backend to use).  */
458*7304104dSAndroid Build Coastguard Worker 	  close (elf_fd);
459*7304104dSAndroid Build Coastguard Worker 	  elf_fd = -1;
460*7304104dSAndroid Build Coastguard Worker 	}
461*7304104dSAndroid Build Coastguard Worker     }
462*7304104dSAndroid Build Coastguard Worker   else
463*7304104dSAndroid Build Coastguard Worker     elf = NULL;
464*7304104dSAndroid Build Coastguard Worker   struct __libdwfl_pid_arg *pid_arg = malloc (sizeof *pid_arg);
465*7304104dSAndroid Build Coastguard Worker   if (pid_arg == NULL)
466*7304104dSAndroid Build Coastguard Worker     {
467*7304104dSAndroid Build Coastguard Worker       elf_end (elf);
468*7304104dSAndroid Build Coastguard Worker       close (elf_fd);
469*7304104dSAndroid Build Coastguard Worker       closedir (dir);
470*7304104dSAndroid Build Coastguard Worker       err = ENOMEM;
471*7304104dSAndroid Build Coastguard Worker       goto fail;
472*7304104dSAndroid Build Coastguard Worker     }
473*7304104dSAndroid Build Coastguard Worker   pid_arg->dir = dir;
474*7304104dSAndroid Build Coastguard Worker   pid_arg->elf = elf;
475*7304104dSAndroid Build Coastguard Worker   pid_arg->elf_fd = elf_fd;
476*7304104dSAndroid Build Coastguard Worker   pid_arg->mem_cache = NULL;
477*7304104dSAndroid Build Coastguard Worker   pid_arg->tid_attached = 0;
478*7304104dSAndroid Build Coastguard Worker   pid_arg->assume_ptrace_stopped = assume_ptrace_stopped;
479*7304104dSAndroid Build Coastguard Worker   if (! INTUSE(dwfl_attach_state) (dwfl, elf, pid, &pid_thread_callbacks,
480*7304104dSAndroid Build Coastguard Worker 				   pid_arg))
481*7304104dSAndroid Build Coastguard Worker     {
482*7304104dSAndroid Build Coastguard Worker       elf_end (elf);
483*7304104dSAndroid Build Coastguard Worker       close (elf_fd);
484*7304104dSAndroid Build Coastguard Worker       closedir (dir);
485*7304104dSAndroid Build Coastguard Worker       free (pid_arg);
486*7304104dSAndroid Build Coastguard Worker       return -1;
487*7304104dSAndroid Build Coastguard Worker     }
488*7304104dSAndroid Build Coastguard Worker   return 0;
489*7304104dSAndroid Build Coastguard Worker }
INTDEF(dwfl_linux_proc_attach)490*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_linux_proc_attach)
491*7304104dSAndroid Build Coastguard Worker 
492*7304104dSAndroid Build Coastguard Worker struct __libdwfl_pid_arg *
493*7304104dSAndroid Build Coastguard Worker internal_function
494*7304104dSAndroid Build Coastguard Worker __libdwfl_get_pid_arg (Dwfl *dwfl)
495*7304104dSAndroid Build Coastguard Worker {
496*7304104dSAndroid Build Coastguard Worker   if (dwfl != NULL && dwfl->process != NULL
497*7304104dSAndroid Build Coastguard Worker       && dwfl->process->callbacks == &pid_thread_callbacks)
498*7304104dSAndroid Build Coastguard Worker     return (struct __libdwfl_pid_arg *) dwfl->process->callbacks_arg;
499*7304104dSAndroid Build Coastguard Worker 
500*7304104dSAndroid Build Coastguard Worker   return NULL;
501*7304104dSAndroid Build Coastguard Worker }
502*7304104dSAndroid Build Coastguard Worker 
503*7304104dSAndroid Build Coastguard Worker #else	/* __linux__ */
504*7304104dSAndroid Build Coastguard Worker 
505*7304104dSAndroid Build Coastguard Worker bool
506*7304104dSAndroid Build Coastguard Worker internal_function
__libdwfl_ptrace_attach(pid_t tid,bool * tid_was_stoppedp)507*7304104dSAndroid Build Coastguard Worker __libdwfl_ptrace_attach (pid_t tid __attribute__ ((unused)),
508*7304104dSAndroid Build Coastguard Worker 			 bool *tid_was_stoppedp __attribute__ ((unused)))
509*7304104dSAndroid Build Coastguard Worker {
510*7304104dSAndroid Build Coastguard Worker   errno = ENOSYS;
511*7304104dSAndroid Build Coastguard Worker   __libdwfl_seterrno (DWFL_E_ERRNO);
512*7304104dSAndroid Build Coastguard Worker   return false;
513*7304104dSAndroid Build Coastguard Worker }
514*7304104dSAndroid Build Coastguard Worker 
515*7304104dSAndroid Build Coastguard Worker void
516*7304104dSAndroid Build Coastguard Worker internal_function
__libdwfl_ptrace_detach(pid_t tid,bool tid_was_stopped)517*7304104dSAndroid Build Coastguard Worker __libdwfl_ptrace_detach (pid_t tid __attribute__ ((unused)),
518*7304104dSAndroid Build Coastguard Worker 			 bool tid_was_stopped __attribute__ ((unused)))
519*7304104dSAndroid Build Coastguard Worker {
520*7304104dSAndroid Build Coastguard Worker }
521*7304104dSAndroid Build Coastguard Worker 
522*7304104dSAndroid Build Coastguard Worker int
dwfl_linux_proc_attach(Dwfl * dwfl,pid_t pid,bool assume_ptrace_stopped)523*7304104dSAndroid Build Coastguard Worker dwfl_linux_proc_attach (Dwfl *dwfl __attribute__ ((unused)),
524*7304104dSAndroid Build Coastguard Worker 			pid_t pid __attribute__ ((unused)),
525*7304104dSAndroid Build Coastguard Worker 			bool assume_ptrace_stopped __attribute__ ((unused)))
526*7304104dSAndroid Build Coastguard Worker {
527*7304104dSAndroid Build Coastguard Worker   return ENOSYS;
528*7304104dSAndroid Build Coastguard Worker }
INTDEF(dwfl_linux_proc_attach)529*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_linux_proc_attach)
530*7304104dSAndroid Build Coastguard Worker 
531*7304104dSAndroid Build Coastguard Worker struct __libdwfl_pid_arg *
532*7304104dSAndroid Build Coastguard Worker internal_function
533*7304104dSAndroid Build Coastguard Worker __libdwfl_get_pid_arg (Dwfl *dwfl __attribute__ ((unused)))
534*7304104dSAndroid Build Coastguard Worker {
535*7304104dSAndroid Build Coastguard Worker   return NULL;
536*7304104dSAndroid Build Coastguard Worker }
537*7304104dSAndroid Build Coastguard Worker 
538*7304104dSAndroid Build Coastguard Worker #endif /* ! __linux __ */
539*7304104dSAndroid Build Coastguard Worker 
540