annotate agent/src/os/linux/ps_proc.c @ 3011:f00918f35c7f

inlining and runtime interface related changes: added codeSize() and compilerStorage() to RiMethod HotSpotMethodResolved uses reflective methods instead of vmIds and survives compilations HotSpotResolvedType.isInitialized not represented as field (can change) inlining stores graphs into method objects and reuses them
author Lukas Stadler <lukas.stadler@jku.at>
date Thu, 16 Jun 2011 20:36:17 +0200
parents 0a8e0d4345b3
children 2394a89e89f4
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
2042
0a8e0d4345b3 7010068: Update all 2010 Oracle-changed OpenJDK files to have the proper copyright dates - first pass
trims
parents: 1990
diff changeset
2 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 196
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 196
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 196
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 #include <stdio.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
26 #include <stdlib.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
27 #include <string.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
28 #include <errno.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
29 #include <sys/ptrace.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
30 #include "libproc_impl.h"
a61af66fc99e Initial load
duke
parents:
diff changeset
31
a61af66fc99e Initial load
duke
parents:
diff changeset
32 #if defined(x86_64) && !defined(amd64)
a61af66fc99e Initial load
duke
parents:
diff changeset
33 #define amd64 1
a61af66fc99e Initial load
duke
parents:
diff changeset
34 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
35
a61af66fc99e Initial load
duke
parents:
diff changeset
36 #ifndef __WALL
a61af66fc99e Initial load
duke
parents:
diff changeset
37 #define __WALL 0x40000000 // Copied from /usr/include/linux/wait.h
a61af66fc99e Initial load
duke
parents:
diff changeset
38 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
39
a61af66fc99e Initial load
duke
parents:
diff changeset
40 // This file has the libproc implementation specific to live process
a61af66fc99e Initial load
duke
parents:
diff changeset
41 // For core files, refer to ps_core.c
a61af66fc99e Initial load
duke
parents:
diff changeset
42
a61af66fc99e Initial load
duke
parents:
diff changeset
43 static inline uintptr_t align(uintptr_t ptr, size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
44 return (ptr & ~(size - 1));
a61af66fc99e Initial load
duke
parents:
diff changeset
45 }
a61af66fc99e Initial load
duke
parents:
diff changeset
46
a61af66fc99e Initial load
duke
parents:
diff changeset
47 // ---------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
48 // ptrace functions
a61af66fc99e Initial load
duke
parents:
diff changeset
49 // ---------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
50
a61af66fc99e Initial load
duke
parents:
diff changeset
51 // read "size" bytes of data from "addr" within the target process.
a61af66fc99e Initial load
duke
parents:
diff changeset
52 // unlike the standard ptrace() function, process_read_data() can handle
a61af66fc99e Initial load
duke
parents:
diff changeset
53 // unaligned address - alignment check, if required, should be done
a61af66fc99e Initial load
duke
parents:
diff changeset
54 // before calling process_read_data.
a61af66fc99e Initial load
duke
parents:
diff changeset
55
a61af66fc99e Initial load
duke
parents:
diff changeset
56 static bool process_read_data(struct ps_prochandle* ph, uintptr_t addr, char *buf, size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
57 long rslt;
a61af66fc99e Initial load
duke
parents:
diff changeset
58 size_t i, words;
a61af66fc99e Initial load
duke
parents:
diff changeset
59 uintptr_t end_addr = addr + size;
a61af66fc99e Initial load
duke
parents:
diff changeset
60 uintptr_t aligned_addr = align(addr, sizeof(long));
a61af66fc99e Initial load
duke
parents:
diff changeset
61
a61af66fc99e Initial load
duke
parents:
diff changeset
62 if (aligned_addr != addr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
63 char *ptr = (char *)&rslt;
a61af66fc99e Initial load
duke
parents:
diff changeset
64 errno = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
65 rslt = ptrace(PTRACE_PEEKDATA, ph->pid, aligned_addr, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
66 if (errno) {
a61af66fc99e Initial load
duke
parents:
diff changeset
67 print_debug("ptrace(PTRACE_PEEKDATA, ..) failed for %d bytes @ %lx\n", size, addr);
a61af66fc99e Initial load
duke
parents:
diff changeset
68 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
69 }
a61af66fc99e Initial load
duke
parents:
diff changeset
70 for (; aligned_addr != addr; aligned_addr++, ptr++);
a61af66fc99e Initial load
duke
parents:
diff changeset
71 for (; ((intptr_t)aligned_addr % sizeof(long)) && aligned_addr < end_addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
72 aligned_addr++)
a61af66fc99e Initial load
duke
parents:
diff changeset
73 *(buf++) = *(ptr++);
a61af66fc99e Initial load
duke
parents:
diff changeset
74 }
a61af66fc99e Initial load
duke
parents:
diff changeset
75
a61af66fc99e Initial load
duke
parents:
diff changeset
76 words = (end_addr - aligned_addr) / sizeof(long);
a61af66fc99e Initial load
duke
parents:
diff changeset
77
a61af66fc99e Initial load
duke
parents:
diff changeset
78 // assert((intptr_t)aligned_addr % sizeof(long) == 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
79 for (i = 0; i < words; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
80 errno = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
81 rslt = ptrace(PTRACE_PEEKDATA, ph->pid, aligned_addr, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
82 if (errno) {
a61af66fc99e Initial load
duke
parents:
diff changeset
83 print_debug("ptrace(PTRACE_PEEKDATA, ..) failed for %d bytes @ %lx\n", size, addr);
a61af66fc99e Initial load
duke
parents:
diff changeset
84 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
85 }
a61af66fc99e Initial load
duke
parents:
diff changeset
86 *(long *)buf = rslt;
a61af66fc99e Initial load
duke
parents:
diff changeset
87 buf += sizeof(long);
a61af66fc99e Initial load
duke
parents:
diff changeset
88 aligned_addr += sizeof(long);
a61af66fc99e Initial load
duke
parents:
diff changeset
89 }
a61af66fc99e Initial load
duke
parents:
diff changeset
90
a61af66fc99e Initial load
duke
parents:
diff changeset
91 if (aligned_addr != end_addr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
92 char *ptr = (char *)&rslt;
a61af66fc99e Initial load
duke
parents:
diff changeset
93 errno = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
94 rslt = ptrace(PTRACE_PEEKDATA, ph->pid, aligned_addr, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
95 if (errno) {
a61af66fc99e Initial load
duke
parents:
diff changeset
96 print_debug("ptrace(PTRACE_PEEKDATA, ..) failed for %d bytes @ %lx\n", size, addr);
a61af66fc99e Initial load
duke
parents:
diff changeset
97 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
98 }
a61af66fc99e Initial load
duke
parents:
diff changeset
99 for (; aligned_addr != end_addr; aligned_addr++)
a61af66fc99e Initial load
duke
parents:
diff changeset
100 *(buf++) = *(ptr++);
a61af66fc99e Initial load
duke
parents:
diff changeset
101 }
a61af66fc99e Initial load
duke
parents:
diff changeset
102 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
103 }
a61af66fc99e Initial load
duke
parents:
diff changeset
104
a61af66fc99e Initial load
duke
parents:
diff changeset
105 // null implementation for write
a61af66fc99e Initial load
duke
parents:
diff changeset
106 static bool process_write_data(struct ps_prochandle* ph,
a61af66fc99e Initial load
duke
parents:
diff changeset
107 uintptr_t addr, const char *buf , size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
108 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
109 }
a61af66fc99e Initial load
duke
parents:
diff changeset
110
a61af66fc99e Initial load
duke
parents:
diff changeset
111 // "user" should be a pointer to a user_regs_struct
a61af66fc99e Initial load
duke
parents:
diff changeset
112 static bool process_get_lwp_regs(struct ps_prochandle* ph, pid_t pid, struct user_regs_struct *user) {
a61af66fc99e Initial load
duke
parents:
diff changeset
113 // we have already attached to all thread 'pid's, just use ptrace call
a61af66fc99e Initial load
duke
parents:
diff changeset
114 // to get regset now. Note that we don't cache regset upfront for processes.
a61af66fc99e Initial load
duke
parents:
diff changeset
115 // Linux on x86 and sparc are different. On x86 ptrace(PTRACE_GETREGS, ...)
a61af66fc99e Initial load
duke
parents:
diff changeset
116 // uses pointer from 4th argument and ignores 3rd argument. On sparc it uses
a61af66fc99e Initial load
duke
parents:
diff changeset
117 // pointer from 3rd argument and ignores 4th argument
a61af66fc99e Initial load
duke
parents:
diff changeset
118 #if defined(sparc) || defined(sparcv9)
a61af66fc99e Initial load
duke
parents:
diff changeset
119 #define ptrace_getregs(request, pid, addr, data) ptrace(request, pid, addr, data)
a61af66fc99e Initial load
duke
parents:
diff changeset
120 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
121 #define ptrace_getregs(request, pid, addr, data) ptrace(request, pid, data, addr)
a61af66fc99e Initial load
duke
parents:
diff changeset
122 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
123
1990
401fbd7ff77c 7003789: PTRACE_GETREGS problems with SA on Linux.
kevinw
parents: 1681
diff changeset
124 #if defined(_LP64) && defined(PTRACE_GETREGS64)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
125 #define PTRACE_GETREGS_REQ PTRACE_GETREGS64
1990
401fbd7ff77c 7003789: PTRACE_GETREGS problems with SA on Linux.
kevinw
parents: 1681
diff changeset
126 #elif defined(PTRACE_GETREGS)
401fbd7ff77c 7003789: PTRACE_GETREGS problems with SA on Linux.
kevinw
parents: 1681
diff changeset
127 #define PTRACE_GETREGS_REQ PTRACE_GETREGS
401fbd7ff77c 7003789: PTRACE_GETREGS problems with SA on Linux.
kevinw
parents: 1681
diff changeset
128 #elif defined(PT_GETREGS)
401fbd7ff77c 7003789: PTRACE_GETREGS problems with SA on Linux.
kevinw
parents: 1681
diff changeset
129 #define PTRACE_GETREGS_REQ PT_GETREGS
0
a61af66fc99e Initial load
duke
parents:
diff changeset
130 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
131
a61af66fc99e Initial load
duke
parents:
diff changeset
132 #ifdef PTRACE_GETREGS_REQ
a61af66fc99e Initial load
duke
parents:
diff changeset
133 if (ptrace_getregs(PTRACE_GETREGS_REQ, pid, user, NULL) < 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
134 print_debug("ptrace(PTRACE_GETREGS, ...) failed for lwp %d\n", pid);
a61af66fc99e Initial load
duke
parents:
diff changeset
135 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
136 }
a61af66fc99e Initial load
duke
parents:
diff changeset
137 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
138 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
139 print_debug("ptrace(PTRACE_GETREGS, ...) not supported\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
140 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
141 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
142
a61af66fc99e Initial load
duke
parents:
diff changeset
143 }
a61af66fc99e Initial load
duke
parents:
diff changeset
144
a61af66fc99e Initial load
duke
parents:
diff changeset
145 // attach to a process/thread specified by "pid"
a61af66fc99e Initial load
duke
parents:
diff changeset
146 static bool ptrace_attach(pid_t pid) {
a61af66fc99e Initial load
duke
parents:
diff changeset
147 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
148 print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid);
a61af66fc99e Initial load
duke
parents:
diff changeset
149 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
150 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
151 int ret;
a61af66fc99e Initial load
duke
parents:
diff changeset
152 int status;
a61af66fc99e Initial load
duke
parents:
diff changeset
153 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
154 // Wait for debuggee to stop.
a61af66fc99e Initial load
duke
parents:
diff changeset
155 ret = waitpid(pid, &status, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
156 if (ret == -1 && errno == ECHILD) {
a61af66fc99e Initial load
duke
parents:
diff changeset
157 // try cloned process.
a61af66fc99e Initial load
duke
parents:
diff changeset
158 ret = waitpid(pid, &status, __WALL);
a61af66fc99e Initial load
duke
parents:
diff changeset
159 }
a61af66fc99e Initial load
duke
parents:
diff changeset
160 if (ret >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
161 if (WIFSTOPPED(status)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
162 // Debuggee stopped.
a61af66fc99e Initial load
duke
parents:
diff changeset
163 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
164 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
165 print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
a61af66fc99e Initial load
duke
parents:
diff changeset
166 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
167 }
a61af66fc99e Initial load
duke
parents:
diff changeset
168 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
169 switch (errno) {
a61af66fc99e Initial load
duke
parents:
diff changeset
170 case EINTR:
a61af66fc99e Initial load
duke
parents:
diff changeset
171 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
172 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
173 case ECHILD:
a61af66fc99e Initial load
duke
parents:
diff changeset
174 print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
a61af66fc99e Initial load
duke
parents:
diff changeset
175 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
176 case EINVAL:
a61af66fc99e Initial load
duke
parents:
diff changeset
177 print_debug("waitpid() failed. Invalid options argument.\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
178 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
179 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
180 print_debug("waitpid() failed. Unexpected error %d\n",errno);
a61af66fc99e Initial load
duke
parents:
diff changeset
181 }
a61af66fc99e Initial load
duke
parents:
diff changeset
182 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
183 }
a61af66fc99e Initial load
duke
parents:
diff changeset
184 } while(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
185 }
a61af66fc99e Initial load
duke
parents:
diff changeset
186 }
a61af66fc99e Initial load
duke
parents:
diff changeset
187
a61af66fc99e Initial load
duke
parents:
diff changeset
188 // -------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
189 // functions for obtaining library information
a61af66fc99e Initial load
duke
parents:
diff changeset
190 // -------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
191
a61af66fc99e Initial load
duke
parents:
diff changeset
192 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
193 * splits a string _str_ into substrings with delimiter _delim_ by replacing old * delimiters with _new_delim_ (ideally, '\0'). the address of each substring
a61af66fc99e Initial load
duke
parents:
diff changeset
194 * is stored in array _ptrs_ as the return value. the maximum capacity of _ptrs_ * array is specified by parameter _n_.
a61af66fc99e Initial load
duke
parents:
diff changeset
195 * RETURN VALUE: total number of substrings (always <= _n_)
a61af66fc99e Initial load
duke
parents:
diff changeset
196 * NOTE: string _str_ is modified if _delim_!=_new_delim_
a61af66fc99e Initial load
duke
parents:
diff changeset
197 */
a61af66fc99e Initial load
duke
parents:
diff changeset
198 static int split_n_str(char * str, int n, char ** ptrs, char delim, char new_delim)
a61af66fc99e Initial load
duke
parents:
diff changeset
199 {
a61af66fc99e Initial load
duke
parents:
diff changeset
200 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
201 for(i = 0; i < n; i++) ptrs[i] = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
202 if (str == NULL || n < 1 ) return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
203
a61af66fc99e Initial load
duke
parents:
diff changeset
204 i = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
205
a61af66fc99e Initial load
duke
parents:
diff changeset
206 // skipping leading blanks
a61af66fc99e Initial load
duke
parents:
diff changeset
207 while(*str&&*str==delim) str++;
a61af66fc99e Initial load
duke
parents:
diff changeset
208
a61af66fc99e Initial load
duke
parents:
diff changeset
209 while(*str&&i<n){
a61af66fc99e Initial load
duke
parents:
diff changeset
210 ptrs[i++] = str;
a61af66fc99e Initial load
duke
parents:
diff changeset
211 while(*str&&*str!=delim) str++;
a61af66fc99e Initial load
duke
parents:
diff changeset
212 while(*str&&*str==delim) *(str++) = new_delim;
a61af66fc99e Initial load
duke
parents:
diff changeset
213 }
a61af66fc99e Initial load
duke
parents:
diff changeset
214
a61af66fc99e Initial load
duke
parents:
diff changeset
215 return i;
a61af66fc99e Initial load
duke
parents:
diff changeset
216 }
a61af66fc99e Initial load
duke
parents:
diff changeset
217
a61af66fc99e Initial load
duke
parents:
diff changeset
218 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
219 * fgets without storing '\n' at the end of the string
a61af66fc99e Initial load
duke
parents:
diff changeset
220 */
a61af66fc99e Initial load
duke
parents:
diff changeset
221 static char * fgets_no_cr(char * buf, int n, FILE *fp)
a61af66fc99e Initial load
duke
parents:
diff changeset
222 {
a61af66fc99e Initial load
duke
parents:
diff changeset
223 char * rslt = fgets(buf, n, fp);
a61af66fc99e Initial load
duke
parents:
diff changeset
224 if (rslt && buf && *buf){
a61af66fc99e Initial load
duke
parents:
diff changeset
225 char *p = strchr(buf, '\0');
a61af66fc99e Initial load
duke
parents:
diff changeset
226 if (*--p=='\n') *p='\0';
a61af66fc99e Initial load
duke
parents:
diff changeset
227 }
a61af66fc99e Initial load
duke
parents:
diff changeset
228 return rslt;
a61af66fc99e Initial load
duke
parents:
diff changeset
229 }
a61af66fc99e Initial load
duke
parents:
diff changeset
230
a61af66fc99e Initial load
duke
parents:
diff changeset
231 // callback for read_thread_info
a61af66fc99e Initial load
duke
parents:
diff changeset
232 static bool add_new_thread(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
233 return add_thread_info(ph, pthread_id, lwp_id) != NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
234 }
a61af66fc99e Initial load
duke
parents:
diff changeset
235
a61af66fc99e Initial load
duke
parents:
diff changeset
236 static bool read_lib_info(struct ps_prochandle* ph) {
a61af66fc99e Initial load
duke
parents:
diff changeset
237 char fname[32];
a61af66fc99e Initial load
duke
parents:
diff changeset
238 char buf[256];
a61af66fc99e Initial load
duke
parents:
diff changeset
239 FILE *fp = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
240
a61af66fc99e Initial load
duke
parents:
diff changeset
241 sprintf(fname, "/proc/%d/maps", ph->pid);
a61af66fc99e Initial load
duke
parents:
diff changeset
242 fp = fopen(fname, "r");
a61af66fc99e Initial load
duke
parents:
diff changeset
243 if (fp == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
244 print_debug("can't open /proc/%d/maps file\n", ph->pid);
a61af66fc99e Initial load
duke
parents:
diff changeset
245 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
246 }
a61af66fc99e Initial load
duke
parents:
diff changeset
247
a61af66fc99e Initial load
duke
parents:
diff changeset
248 while(fgets_no_cr(buf, 256, fp)){
a61af66fc99e Initial load
duke
parents:
diff changeset
249 char * word[6];
a61af66fc99e Initial load
duke
parents:
diff changeset
250 int nwords = split_n_str(buf, 6, word, ' ', '\0');
a61af66fc99e Initial load
duke
parents:
diff changeset
251 if (nwords > 5 && find_lib(ph, word[5]) == false) {
a61af66fc99e Initial load
duke
parents:
diff changeset
252 intptr_t base;
a61af66fc99e Initial load
duke
parents:
diff changeset
253 lib_info* lib;
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1552
diff changeset
254 #ifdef _LP64
0
a61af66fc99e Initial load
duke
parents:
diff changeset
255 sscanf(word[0], "%lx", &base);
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1552
diff changeset
256 #else
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1552
diff changeset
257 sscanf(word[0], "%x", &base);
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1552
diff changeset
258 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
259 if ((lib = add_lib_info(ph, word[5], (uintptr_t)base)) == NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
260 continue; // ignore, add_lib_info prints error
a61af66fc99e Initial load
duke
parents:
diff changeset
261
a61af66fc99e Initial load
duke
parents:
diff changeset
262 // we don't need to keep the library open, symtab is already
a61af66fc99e Initial load
duke
parents:
diff changeset
263 // built. Only for core dump we need to keep the fd open.
a61af66fc99e Initial load
duke
parents:
diff changeset
264 close(lib->fd);
a61af66fc99e Initial load
duke
parents:
diff changeset
265 lib->fd = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
266 }
a61af66fc99e Initial load
duke
parents:
diff changeset
267 }
a61af66fc99e Initial load
duke
parents:
diff changeset
268 fclose(fp);
a61af66fc99e Initial load
duke
parents:
diff changeset
269 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
270 }
a61af66fc99e Initial load
duke
parents:
diff changeset
271
a61af66fc99e Initial load
duke
parents:
diff changeset
272 // detach a given pid
a61af66fc99e Initial load
duke
parents:
diff changeset
273 static bool ptrace_detach(pid_t pid) {
a61af66fc99e Initial load
duke
parents:
diff changeset
274 if (pid && ptrace(PTRACE_DETACH, pid, NULL, NULL) < 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
275 print_debug("ptrace(PTRACE_DETACH, ..) failed for %d\n", pid);
a61af66fc99e Initial load
duke
parents:
diff changeset
276 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
277 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
278 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
279 }
a61af66fc99e Initial load
duke
parents:
diff changeset
280 }
a61af66fc99e Initial load
duke
parents:
diff changeset
281
a61af66fc99e Initial load
duke
parents:
diff changeset
282 // detach all pids of a ps_prochandle
a61af66fc99e Initial load
duke
parents:
diff changeset
283 static void detach_all_pids(struct ps_prochandle* ph) {
a61af66fc99e Initial load
duke
parents:
diff changeset
284 thread_info* thr = ph->threads;
a61af66fc99e Initial load
duke
parents:
diff changeset
285 while (thr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
286 ptrace_detach(thr->lwp_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
287 thr = thr->next;
a61af66fc99e Initial load
duke
parents:
diff changeset
288 }
a61af66fc99e Initial load
duke
parents:
diff changeset
289 }
a61af66fc99e Initial load
duke
parents:
diff changeset
290
a61af66fc99e Initial load
duke
parents:
diff changeset
291 static void process_cleanup(struct ps_prochandle* ph) {
a61af66fc99e Initial load
duke
parents:
diff changeset
292 detach_all_pids(ph);
a61af66fc99e Initial load
duke
parents:
diff changeset
293 }
a61af66fc99e Initial load
duke
parents:
diff changeset
294
a61af66fc99e Initial load
duke
parents:
diff changeset
295 static ps_prochandle_ops process_ops = {
50
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
296 .release= process_cleanup,
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
297 .p_pread= process_read_data,
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
298 .p_pwrite= process_write_data,
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
299 .get_lwp_regs= process_get_lwp_regs
0
a61af66fc99e Initial load
duke
parents:
diff changeset
300 };
a61af66fc99e Initial load
duke
parents:
diff changeset
301
a61af66fc99e Initial load
duke
parents:
diff changeset
302 // attach to the process. One and only one exposed stuff
a61af66fc99e Initial load
duke
parents:
diff changeset
303 struct ps_prochandle* Pgrab(pid_t pid) {
a61af66fc99e Initial load
duke
parents:
diff changeset
304 struct ps_prochandle* ph = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
305 thread_info* thr = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
306
a61af66fc99e Initial load
duke
parents:
diff changeset
307 if ( (ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle))) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
308 print_debug("can't allocate memory for ps_prochandle\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
309 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
310 }
a61af66fc99e Initial load
duke
parents:
diff changeset
311
a61af66fc99e Initial load
duke
parents:
diff changeset
312 if (ptrace_attach(pid) != true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
313 free(ph);
a61af66fc99e Initial load
duke
parents:
diff changeset
314 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
315 }
a61af66fc99e Initial load
duke
parents:
diff changeset
316
a61af66fc99e Initial load
duke
parents:
diff changeset
317 // initialize ps_prochandle
a61af66fc99e Initial load
duke
parents:
diff changeset
318 ph->pid = pid;
a61af66fc99e Initial load
duke
parents:
diff changeset
319
a61af66fc99e Initial load
duke
parents:
diff changeset
320 // initialize vtable
a61af66fc99e Initial load
duke
parents:
diff changeset
321 ph->ops = &process_ops;
a61af66fc99e Initial load
duke
parents:
diff changeset
322
a61af66fc99e Initial load
duke
parents:
diff changeset
323 // read library info and symbol tables, must do this before attaching threads,
a61af66fc99e Initial load
duke
parents:
diff changeset
324 // as the symbols in the pthread library will be used to figure out
a61af66fc99e Initial load
duke
parents:
diff changeset
325 // the list of threads within the same process.
a61af66fc99e Initial load
duke
parents:
diff changeset
326 read_lib_info(ph);
a61af66fc99e Initial load
duke
parents:
diff changeset
327
a61af66fc99e Initial load
duke
parents:
diff changeset
328 // read thread info
a61af66fc99e Initial load
duke
parents:
diff changeset
329 read_thread_info(ph, add_new_thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
330
a61af66fc99e Initial load
duke
parents:
diff changeset
331 // attach to the threads
a61af66fc99e Initial load
duke
parents:
diff changeset
332 thr = ph->threads;
a61af66fc99e Initial load
duke
parents:
diff changeset
333 while (thr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
334 // don't attach to the main thread again
a61af66fc99e Initial load
duke
parents:
diff changeset
335 if (ph->pid != thr->lwp_id && ptrace_attach(thr->lwp_id) != true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
336 // even if one attach fails, we get return NULL
a61af66fc99e Initial load
duke
parents:
diff changeset
337 Prelease(ph);
a61af66fc99e Initial load
duke
parents:
diff changeset
338 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
339 }
a61af66fc99e Initial load
duke
parents:
diff changeset
340 thr = thr->next;
a61af66fc99e Initial load
duke
parents:
diff changeset
341 }
a61af66fc99e Initial load
duke
parents:
diff changeset
342 return ph;
a61af66fc99e Initial load
duke
parents:
diff changeset
343 }