annotate agent/src/os/linux/libproc_impl.c @ 3237:399aa66d375e

Fixed a bug in which the valueEquals method was misused. The method does only check the equality of the node data and not full GVN equality by taking inputs and successors into account.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Wed, 27 Jul 2011 14:16:38 -0700
parents 0a8e0d4345b3
children 54d3535a6dd3
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: 1552
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: 1294
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1294
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: 1294
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 #include <stdarg.h>
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 <fcntl.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
29 #include <thread_db.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 static const char* alt_root = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
33 static int alt_root_len = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
34
a61af66fc99e Initial load
duke
parents:
diff changeset
35 #define SA_ALTROOT "SA_ALTROOT"
a61af66fc99e Initial load
duke
parents:
diff changeset
36
a61af66fc99e Initial load
duke
parents:
diff changeset
37 static void init_alt_root() {
a61af66fc99e Initial load
duke
parents:
diff changeset
38 if (alt_root_len == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
39 alt_root = getenv(SA_ALTROOT);
a61af66fc99e Initial load
duke
parents:
diff changeset
40 if (alt_root) {
a61af66fc99e Initial load
duke
parents:
diff changeset
41 alt_root_len = strlen(alt_root);
a61af66fc99e Initial load
duke
parents:
diff changeset
42 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
43 alt_root_len = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
44 }
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 int pathmap_open(const char* name) {
a61af66fc99e Initial load
duke
parents:
diff changeset
49 int fd;
a61af66fc99e Initial load
duke
parents:
diff changeset
50 char alt_path[PATH_MAX + 1];
a61af66fc99e Initial load
duke
parents:
diff changeset
51
a61af66fc99e Initial load
duke
parents:
diff changeset
52 init_alt_root();
a61af66fc99e Initial load
duke
parents:
diff changeset
53 fd = open(name, O_RDONLY);
a61af66fc99e Initial load
duke
parents:
diff changeset
54 if (fd >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
55 return fd;
a61af66fc99e Initial load
duke
parents:
diff changeset
56 }
a61af66fc99e Initial load
duke
parents:
diff changeset
57
a61af66fc99e Initial load
duke
parents:
diff changeset
58 if (alt_root_len > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
59 strcpy(alt_path, alt_root);
a61af66fc99e Initial load
duke
parents:
diff changeset
60 strcat(alt_path, name);
a61af66fc99e Initial load
duke
parents:
diff changeset
61 fd = open(alt_path, O_RDONLY);
a61af66fc99e Initial load
duke
parents:
diff changeset
62 if (fd >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
63 print_debug("path %s substituted for %s\n", alt_path, name);
a61af66fc99e Initial load
duke
parents:
diff changeset
64 return fd;
a61af66fc99e Initial load
duke
parents:
diff changeset
65 }
a61af66fc99e Initial load
duke
parents:
diff changeset
66
a61af66fc99e Initial load
duke
parents:
diff changeset
67 if (strrchr(name, '/')) {
a61af66fc99e Initial load
duke
parents:
diff changeset
68 strcpy(alt_path, alt_root);
a61af66fc99e Initial load
duke
parents:
diff changeset
69 strcat(alt_path, strrchr(name, '/'));
a61af66fc99e Initial load
duke
parents:
diff changeset
70 fd = open(alt_path, O_RDONLY);
a61af66fc99e Initial load
duke
parents:
diff changeset
71 if (fd >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
72 print_debug("path %s substituted for %s\n", alt_path, name);
a61af66fc99e Initial load
duke
parents:
diff changeset
73 return fd;
a61af66fc99e Initial load
duke
parents:
diff changeset
74 }
a61af66fc99e Initial load
duke
parents:
diff changeset
75 }
a61af66fc99e Initial load
duke
parents:
diff changeset
76 }
a61af66fc99e Initial load
duke
parents:
diff changeset
77
a61af66fc99e Initial load
duke
parents:
diff changeset
78 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
79 }
a61af66fc99e Initial load
duke
parents:
diff changeset
80
a61af66fc99e Initial load
duke
parents:
diff changeset
81 static bool _libsaproc_debug;
a61af66fc99e Initial load
duke
parents:
diff changeset
82
a61af66fc99e Initial load
duke
parents:
diff changeset
83 void print_debug(const char* format,...) {
a61af66fc99e Initial load
duke
parents:
diff changeset
84 if (_libsaproc_debug) {
a61af66fc99e Initial load
duke
parents:
diff changeset
85 va_list alist;
a61af66fc99e Initial load
duke
parents:
diff changeset
86
a61af66fc99e Initial load
duke
parents:
diff changeset
87 va_start(alist, format);
a61af66fc99e Initial load
duke
parents:
diff changeset
88 fputs("libsaproc DEBUG: ", stderr);
a61af66fc99e Initial load
duke
parents:
diff changeset
89 vfprintf(stderr, format, alist);
a61af66fc99e Initial load
duke
parents:
diff changeset
90 va_end(alist);
a61af66fc99e Initial load
duke
parents:
diff changeset
91 }
a61af66fc99e Initial load
duke
parents:
diff changeset
92 }
a61af66fc99e Initial load
duke
parents:
diff changeset
93
a61af66fc99e Initial load
duke
parents:
diff changeset
94 bool is_debug() {
a61af66fc99e Initial load
duke
parents:
diff changeset
95 return _libsaproc_debug;
a61af66fc99e Initial load
duke
parents:
diff changeset
96 }
a61af66fc99e Initial load
duke
parents:
diff changeset
97
a61af66fc99e Initial load
duke
parents:
diff changeset
98 // initialize libproc
a61af66fc99e Initial load
duke
parents:
diff changeset
99 bool init_libproc(bool debug) {
a61af66fc99e Initial load
duke
parents:
diff changeset
100 // init debug mode
a61af66fc99e Initial load
duke
parents:
diff changeset
101 _libsaproc_debug = debug;
a61af66fc99e Initial load
duke
parents:
diff changeset
102
a61af66fc99e Initial load
duke
parents:
diff changeset
103 // initialize the thread_db library
a61af66fc99e Initial load
duke
parents:
diff changeset
104 if (td_init() != TD_OK) {
a61af66fc99e Initial load
duke
parents:
diff changeset
105 print_debug("libthread_db's td_init failed\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
106 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
107 }
a61af66fc99e Initial load
duke
parents:
diff changeset
108
a61af66fc99e Initial load
duke
parents:
diff changeset
109 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
110 }
a61af66fc99e Initial load
duke
parents:
diff changeset
111
a61af66fc99e Initial load
duke
parents:
diff changeset
112 static void destroy_lib_info(struct ps_prochandle* ph) {
a61af66fc99e Initial load
duke
parents:
diff changeset
113 lib_info* lib = ph->libs;
a61af66fc99e Initial load
duke
parents:
diff changeset
114 while (lib) {
a61af66fc99e Initial load
duke
parents:
diff changeset
115 lib_info *next = lib->next;
a61af66fc99e Initial load
duke
parents:
diff changeset
116 if (lib->symtab) {
a61af66fc99e Initial load
duke
parents:
diff changeset
117 destroy_symtab(lib->symtab);
a61af66fc99e Initial load
duke
parents:
diff changeset
118 }
a61af66fc99e Initial load
duke
parents:
diff changeset
119 free(lib);
a61af66fc99e Initial load
duke
parents:
diff changeset
120 lib = next;
a61af66fc99e Initial load
duke
parents:
diff changeset
121 }
a61af66fc99e Initial load
duke
parents:
diff changeset
122 }
a61af66fc99e Initial load
duke
parents:
diff changeset
123
a61af66fc99e Initial load
duke
parents:
diff changeset
124 static void destroy_thread_info(struct ps_prochandle* ph) {
a61af66fc99e Initial load
duke
parents:
diff changeset
125 thread_info* thr = ph->threads;
a61af66fc99e Initial load
duke
parents:
diff changeset
126 while (thr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
127 thread_info *next = thr->next;
a61af66fc99e Initial load
duke
parents:
diff changeset
128 free(thr);
a61af66fc99e Initial load
duke
parents:
diff changeset
129 thr = next;
a61af66fc99e Initial load
duke
parents:
diff changeset
130 }
a61af66fc99e Initial load
duke
parents:
diff changeset
131 }
a61af66fc99e Initial load
duke
parents:
diff changeset
132
a61af66fc99e Initial load
duke
parents:
diff changeset
133 // ps_prochandle cleanup
a61af66fc99e Initial load
duke
parents:
diff changeset
134
a61af66fc99e Initial load
duke
parents:
diff changeset
135 // ps_prochandle cleanup
a61af66fc99e Initial load
duke
parents:
diff changeset
136 void Prelease(struct ps_prochandle* ph) {
a61af66fc99e Initial load
duke
parents:
diff changeset
137 // do the "derived class" clean-up first
a61af66fc99e Initial load
duke
parents:
diff changeset
138 ph->ops->release(ph);
a61af66fc99e Initial load
duke
parents:
diff changeset
139 destroy_lib_info(ph);
a61af66fc99e Initial load
duke
parents:
diff changeset
140 destroy_thread_info(ph);
a61af66fc99e Initial load
duke
parents:
diff changeset
141 free(ph);
a61af66fc99e Initial load
duke
parents:
diff changeset
142 }
a61af66fc99e Initial load
duke
parents:
diff changeset
143
a61af66fc99e Initial load
duke
parents:
diff changeset
144 lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base) {
a61af66fc99e Initial load
duke
parents:
diff changeset
145 return add_lib_info_fd(ph, libname, -1, base);
a61af66fc99e Initial load
duke
parents:
diff changeset
146 }
a61af66fc99e Initial load
duke
parents:
diff changeset
147
a61af66fc99e Initial load
duke
parents:
diff changeset
148 lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) {
a61af66fc99e Initial load
duke
parents:
diff changeset
149 lib_info* newlib;
a61af66fc99e Initial load
duke
parents:
diff changeset
150
a61af66fc99e Initial load
duke
parents:
diff changeset
151 if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
152 print_debug("can't allocate memory for lib_info\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
153 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
154 }
a61af66fc99e Initial load
duke
parents:
diff changeset
155
a61af66fc99e Initial load
duke
parents:
diff changeset
156 strncpy(newlib->name, libname, sizeof(newlib->name));
a61af66fc99e Initial load
duke
parents:
diff changeset
157 newlib->base = base;
a61af66fc99e Initial load
duke
parents:
diff changeset
158
a61af66fc99e Initial load
duke
parents:
diff changeset
159 if (fd == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
160 if ( (newlib->fd = pathmap_open(newlib->name)) < 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
161 print_debug("can't open shared object %s\n", newlib->name);
a61af66fc99e Initial load
duke
parents:
diff changeset
162 free(newlib);
a61af66fc99e Initial load
duke
parents:
diff changeset
163 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
164 }
a61af66fc99e Initial load
duke
parents:
diff changeset
165 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
166 newlib->fd = fd;
a61af66fc99e Initial load
duke
parents:
diff changeset
167 }
a61af66fc99e Initial load
duke
parents:
diff changeset
168
a61af66fc99e Initial load
duke
parents:
diff changeset
169 // check whether we have got an ELF file. /proc/<pid>/map
a61af66fc99e Initial load
duke
parents:
diff changeset
170 // gives out all file mappings and not just shared objects
a61af66fc99e Initial load
duke
parents:
diff changeset
171 if (is_elf_file(newlib->fd) == false) {
a61af66fc99e Initial load
duke
parents:
diff changeset
172 close(newlib->fd);
a61af66fc99e Initial load
duke
parents:
diff changeset
173 free(newlib);
a61af66fc99e Initial load
duke
parents:
diff changeset
174 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
175 }
a61af66fc99e Initial load
duke
parents:
diff changeset
176
1294
7de45b5044c3 6932270: Allow Java's ELF symtab reader to use separate debuginfo files
never
parents: 0
diff changeset
177 newlib->symtab = build_symtab(newlib->fd, libname);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
178 if (newlib->symtab == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
179 print_debug("symbol table build failed for %s\n", newlib->name);
a61af66fc99e Initial load
duke
parents:
diff changeset
180 }
a61af66fc99e Initial load
duke
parents:
diff changeset
181
a61af66fc99e Initial load
duke
parents:
diff changeset
182 // even if symbol table building fails, we add the lib_info.
a61af66fc99e Initial load
duke
parents:
diff changeset
183 // This is because we may need to read from the ELF file for core file
a61af66fc99e Initial load
duke
parents:
diff changeset
184 // address read functionality. lookup_symbol checks for NULL symtab.
a61af66fc99e Initial load
duke
parents:
diff changeset
185 if (ph->libs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
186 ph->lib_tail->next = newlib;
a61af66fc99e Initial load
duke
parents:
diff changeset
187 ph->lib_tail = newlib;
a61af66fc99e Initial load
duke
parents:
diff changeset
188 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
189 ph->libs = ph->lib_tail = newlib;
a61af66fc99e Initial load
duke
parents:
diff changeset
190 }
a61af66fc99e Initial load
duke
parents:
diff changeset
191 ph->num_libs++;
a61af66fc99e Initial load
duke
parents:
diff changeset
192
a61af66fc99e Initial load
duke
parents:
diff changeset
193 return newlib;
a61af66fc99e Initial load
duke
parents:
diff changeset
194 }
a61af66fc99e Initial load
duke
parents:
diff changeset
195
a61af66fc99e Initial load
duke
parents:
diff changeset
196 // lookup for a specific symbol
a61af66fc99e Initial load
duke
parents:
diff changeset
197 uintptr_t lookup_symbol(struct ps_prochandle* ph, const char* object_name,
a61af66fc99e Initial load
duke
parents:
diff changeset
198 const char* sym_name) {
a61af66fc99e Initial load
duke
parents:
diff changeset
199 // ignore object_name. search in all libraries
a61af66fc99e Initial load
duke
parents:
diff changeset
200 // FIXME: what should we do with object_name?? The library names are obtained
a61af66fc99e Initial load
duke
parents:
diff changeset
201 // by parsing /proc/<pid>/maps, which may not be the same as object_name.
a61af66fc99e Initial load
duke
parents:
diff changeset
202 // What we need is a utility to map object_name to real file name, something
a61af66fc99e Initial load
duke
parents:
diff changeset
203 // dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For
a61af66fc99e Initial load
duke
parents:
diff changeset
204 // now, we just ignore object_name and do a global search for the symbol.
a61af66fc99e Initial load
duke
parents:
diff changeset
205
a61af66fc99e Initial load
duke
parents:
diff changeset
206 lib_info* lib = ph->libs;
a61af66fc99e Initial load
duke
parents:
diff changeset
207 while (lib) {
a61af66fc99e Initial load
duke
parents:
diff changeset
208 if (lib->symtab) {
a61af66fc99e Initial load
duke
parents:
diff changeset
209 uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
210 if (res) return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
211 }
a61af66fc99e Initial load
duke
parents:
diff changeset
212 lib = lib->next;
a61af66fc99e Initial load
duke
parents:
diff changeset
213 }
a61af66fc99e Initial load
duke
parents:
diff changeset
214
a61af66fc99e Initial load
duke
parents:
diff changeset
215 print_debug("lookup failed for symbol '%s' in obj '%s'\n",
a61af66fc99e Initial load
duke
parents:
diff changeset
216 sym_name, object_name);
a61af66fc99e Initial load
duke
parents:
diff changeset
217 return (uintptr_t) NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
218 }
a61af66fc99e Initial load
duke
parents:
diff changeset
219
a61af66fc99e Initial load
duke
parents:
diff changeset
220
a61af66fc99e Initial load
duke
parents:
diff changeset
221 const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset) {
a61af66fc99e Initial load
duke
parents:
diff changeset
222 const char* res = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
223 lib_info* lib = ph->libs;
a61af66fc99e Initial load
duke
parents:
diff changeset
224 while (lib) {
a61af66fc99e Initial load
duke
parents:
diff changeset
225 if (lib->symtab && addr >= lib->base) {
a61af66fc99e Initial load
duke
parents:
diff changeset
226 res = nearest_symbol(lib->symtab, addr - lib->base, poffset);
a61af66fc99e Initial load
duke
parents:
diff changeset
227 if (res) return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
228 }
a61af66fc99e Initial load
duke
parents:
diff changeset
229 lib = lib->next;
a61af66fc99e Initial load
duke
parents:
diff changeset
230 }
a61af66fc99e Initial load
duke
parents:
diff changeset
231 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
232 }
a61af66fc99e Initial load
duke
parents:
diff changeset
233
a61af66fc99e Initial load
duke
parents:
diff changeset
234 // add a thread to ps_prochandle
a61af66fc99e Initial load
duke
parents:
diff changeset
235 thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
236 thread_info* newthr;
a61af66fc99e Initial load
duke
parents:
diff changeset
237 if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
238 print_debug("can't allocate memory for thread_info\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
239 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
240 }
a61af66fc99e Initial load
duke
parents:
diff changeset
241
a61af66fc99e Initial load
duke
parents:
diff changeset
242 // initialize thread info
a61af66fc99e Initial load
duke
parents:
diff changeset
243 newthr->pthread_id = pthread_id;
a61af66fc99e Initial load
duke
parents:
diff changeset
244 newthr->lwp_id = lwp_id;
a61af66fc99e Initial load
duke
parents:
diff changeset
245
a61af66fc99e Initial load
duke
parents:
diff changeset
246 // add new thread to the list
a61af66fc99e Initial load
duke
parents:
diff changeset
247 newthr->next = ph->threads;
a61af66fc99e Initial load
duke
parents:
diff changeset
248 ph->threads = newthr;
a61af66fc99e Initial load
duke
parents:
diff changeset
249 ph->num_threads++;
a61af66fc99e Initial load
duke
parents:
diff changeset
250 return newthr;
a61af66fc99e Initial load
duke
parents:
diff changeset
251 }
a61af66fc99e Initial load
duke
parents:
diff changeset
252
a61af66fc99e Initial load
duke
parents:
diff changeset
253
a61af66fc99e Initial load
duke
parents:
diff changeset
254 // struct used for client data from thread_db callback
a61af66fc99e Initial load
duke
parents:
diff changeset
255 struct thread_db_client_data {
a61af66fc99e Initial load
duke
parents:
diff changeset
256 struct ps_prochandle* ph;
a61af66fc99e Initial load
duke
parents:
diff changeset
257 thread_info_callback callback;
a61af66fc99e Initial load
duke
parents:
diff changeset
258 };
a61af66fc99e Initial load
duke
parents:
diff changeset
259
a61af66fc99e Initial load
duke
parents:
diff changeset
260 // callback function for libthread_db
a61af66fc99e Initial load
duke
parents:
diff changeset
261 static int thread_db_callback(const td_thrhandle_t *th_p, void *data) {
a61af66fc99e Initial load
duke
parents:
diff changeset
262 struct thread_db_client_data* ptr = (struct thread_db_client_data*) data;
a61af66fc99e Initial load
duke
parents:
diff changeset
263 td_thrinfo_t ti;
a61af66fc99e Initial load
duke
parents:
diff changeset
264 td_err_e err;
a61af66fc99e Initial load
duke
parents:
diff changeset
265
a61af66fc99e Initial load
duke
parents:
diff changeset
266 memset(&ti, 0, sizeof(ti));
a61af66fc99e Initial load
duke
parents:
diff changeset
267 err = td_thr_get_info(th_p, &ti);
a61af66fc99e Initial load
duke
parents:
diff changeset
268 if (err != TD_OK) {
a61af66fc99e Initial load
duke
parents:
diff changeset
269 print_debug("libthread_db : td_thr_get_info failed, can't get thread info\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
270 return err;
a61af66fc99e Initial load
duke
parents:
diff changeset
271 }
a61af66fc99e Initial load
duke
parents:
diff changeset
272
a61af66fc99e Initial load
duke
parents:
diff changeset
273 print_debug("thread_db : pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid);
a61af66fc99e Initial load
duke
parents:
diff changeset
274
a61af66fc99e Initial load
duke
parents:
diff changeset
275 if (ptr->callback(ptr->ph, ti.ti_tid, ti.ti_lid) != true)
a61af66fc99e Initial load
duke
parents:
diff changeset
276 return TD_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
277
a61af66fc99e Initial load
duke
parents:
diff changeset
278 return TD_OK;
a61af66fc99e Initial load
duke
parents:
diff changeset
279 }
a61af66fc99e Initial load
duke
parents:
diff changeset
280
a61af66fc99e Initial load
duke
parents:
diff changeset
281 // read thread_info using libthread_db
a61af66fc99e Initial load
duke
parents:
diff changeset
282 bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb) {
a61af66fc99e Initial load
duke
parents:
diff changeset
283 struct thread_db_client_data mydata;
a61af66fc99e Initial load
duke
parents:
diff changeset
284 td_thragent_t* thread_agent = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
285 if (td_ta_new(ph, &thread_agent) != TD_OK) {
a61af66fc99e Initial load
duke
parents:
diff changeset
286 print_debug("can't create libthread_db agent\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
287 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
288 }
a61af66fc99e Initial load
duke
parents:
diff changeset
289
a61af66fc99e Initial load
duke
parents:
diff changeset
290 mydata.ph = ph;
a61af66fc99e Initial load
duke
parents:
diff changeset
291 mydata.callback = cb;
a61af66fc99e Initial load
duke
parents:
diff changeset
292
a61af66fc99e Initial load
duke
parents:
diff changeset
293 // we use libthread_db iterator to iterate thru list of threads.
a61af66fc99e Initial load
duke
parents:
diff changeset
294 if (td_ta_thr_iter(thread_agent, thread_db_callback, &mydata,
a61af66fc99e Initial load
duke
parents:
diff changeset
295 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
a61af66fc99e Initial load
duke
parents:
diff changeset
296 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS) != TD_OK) {
a61af66fc99e Initial load
duke
parents:
diff changeset
297 td_ta_delete(thread_agent);
a61af66fc99e Initial load
duke
parents:
diff changeset
298 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
299 }
a61af66fc99e Initial load
duke
parents:
diff changeset
300
a61af66fc99e Initial load
duke
parents:
diff changeset
301 // delete thread agent
a61af66fc99e Initial load
duke
parents:
diff changeset
302 td_ta_delete(thread_agent);
a61af66fc99e Initial load
duke
parents:
diff changeset
303 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
304 }
a61af66fc99e Initial load
duke
parents:
diff changeset
305
a61af66fc99e Initial load
duke
parents:
diff changeset
306
a61af66fc99e Initial load
duke
parents:
diff changeset
307 // get number of threads
a61af66fc99e Initial load
duke
parents:
diff changeset
308 int get_num_threads(struct ps_prochandle* ph) {
a61af66fc99e Initial load
duke
parents:
diff changeset
309 return ph->num_threads;
a61af66fc99e Initial load
duke
parents:
diff changeset
310 }
a61af66fc99e Initial load
duke
parents:
diff changeset
311
a61af66fc99e Initial load
duke
parents:
diff changeset
312 // get lwp_id of n'th thread
a61af66fc99e Initial load
duke
parents:
diff changeset
313 lwpid_t get_lwp_id(struct ps_prochandle* ph, int index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
314 int count = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
315 thread_info* thr = ph->threads;
a61af66fc99e Initial load
duke
parents:
diff changeset
316 while (thr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
317 if (count == index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
318 return thr->lwp_id;
a61af66fc99e Initial load
duke
parents:
diff changeset
319 }
a61af66fc99e Initial load
duke
parents:
diff changeset
320 count++;
a61af66fc99e Initial load
duke
parents:
diff changeset
321 thr = thr->next;
a61af66fc99e Initial load
duke
parents:
diff changeset
322 }
a61af66fc99e Initial load
duke
parents:
diff changeset
323 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
324 }
a61af66fc99e Initial load
duke
parents:
diff changeset
325
a61af66fc99e Initial load
duke
parents:
diff changeset
326 // get regs for a given lwp
a61af66fc99e Initial load
duke
parents:
diff changeset
327 bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, struct user_regs_struct* regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
328 return ph->ops->get_lwp_regs(ph, lwp_id, regs);
a61af66fc99e Initial load
duke
parents:
diff changeset
329 }
a61af66fc99e Initial load
duke
parents:
diff changeset
330
a61af66fc99e Initial load
duke
parents:
diff changeset
331 // get number of shared objects
a61af66fc99e Initial load
duke
parents:
diff changeset
332 int get_num_libs(struct ps_prochandle* ph) {
a61af66fc99e Initial load
duke
parents:
diff changeset
333 return ph->num_libs;
a61af66fc99e Initial load
duke
parents:
diff changeset
334 }
a61af66fc99e Initial load
duke
parents:
diff changeset
335
a61af66fc99e Initial load
duke
parents:
diff changeset
336 // get name of n'th solib
a61af66fc99e Initial load
duke
parents:
diff changeset
337 const char* get_lib_name(struct ps_prochandle* ph, int index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
338 int count = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
339 lib_info* lib = ph->libs;
a61af66fc99e Initial load
duke
parents:
diff changeset
340 while (lib) {
a61af66fc99e Initial load
duke
parents:
diff changeset
341 if (count == index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
342 return lib->name;
a61af66fc99e Initial load
duke
parents:
diff changeset
343 }
a61af66fc99e Initial load
duke
parents:
diff changeset
344 count++;
a61af66fc99e Initial load
duke
parents:
diff changeset
345 lib = lib->next;
a61af66fc99e Initial load
duke
parents:
diff changeset
346 }
a61af66fc99e Initial load
duke
parents:
diff changeset
347 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
348 }
a61af66fc99e Initial load
duke
parents:
diff changeset
349
a61af66fc99e Initial load
duke
parents:
diff changeset
350 // get base address of a lib
a61af66fc99e Initial load
duke
parents:
diff changeset
351 uintptr_t get_lib_base(struct ps_prochandle* ph, int index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
352 int count = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
353 lib_info* lib = ph->libs;
a61af66fc99e Initial load
duke
parents:
diff changeset
354 while (lib) {
a61af66fc99e Initial load
duke
parents:
diff changeset
355 if (count == index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
356 return lib->base;
a61af66fc99e Initial load
duke
parents:
diff changeset
357 }
a61af66fc99e Initial load
duke
parents:
diff changeset
358 count++;
a61af66fc99e Initial load
duke
parents:
diff changeset
359 lib = lib->next;
a61af66fc99e Initial load
duke
parents:
diff changeset
360 }
a61af66fc99e Initial load
duke
parents:
diff changeset
361 return (uintptr_t)NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
362 }
a61af66fc99e Initial load
duke
parents:
diff changeset
363
a61af66fc99e Initial load
duke
parents:
diff changeset
364 bool find_lib(struct ps_prochandle* ph, const char *lib_name) {
a61af66fc99e Initial load
duke
parents:
diff changeset
365 lib_info *p = ph->libs;
a61af66fc99e Initial load
duke
parents:
diff changeset
366 while (p) {
a61af66fc99e Initial load
duke
parents:
diff changeset
367 if (strcmp(p->name, lib_name) == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
368 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
369 }
a61af66fc99e Initial load
duke
parents:
diff changeset
370 p = p->next;
a61af66fc99e Initial load
duke
parents:
diff changeset
371 }
a61af66fc99e Initial load
duke
parents:
diff changeset
372 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
373 }
a61af66fc99e Initial load
duke
parents:
diff changeset
374
a61af66fc99e Initial load
duke
parents:
diff changeset
375 //--------------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
376 // proc service functions
a61af66fc99e Initial load
duke
parents:
diff changeset
377
a61af66fc99e Initial load
duke
parents:
diff changeset
378 // get process id
a61af66fc99e Initial load
duke
parents:
diff changeset
379 pid_t ps_getpid(struct ps_prochandle *ph) {
a61af66fc99e Initial load
duke
parents:
diff changeset
380 return ph->pid;
a61af66fc99e Initial load
duke
parents:
diff changeset
381 }
a61af66fc99e Initial load
duke
parents:
diff changeset
382
a61af66fc99e Initial load
duke
parents:
diff changeset
383 // ps_pglobal_lookup() looks up the symbol sym_name in the symbol table
a61af66fc99e Initial load
duke
parents:
diff changeset
384 // of the load object object_name in the target process identified by ph.
a61af66fc99e Initial load
duke
parents:
diff changeset
385 // It returns the symbol's value as an address in the target process in
a61af66fc99e Initial load
duke
parents:
diff changeset
386 // *sym_addr.
a61af66fc99e Initial load
duke
parents:
diff changeset
387
a61af66fc99e Initial load
duke
parents:
diff changeset
388 ps_err_e ps_pglobal_lookup(struct ps_prochandle *ph, const char *object_name,
a61af66fc99e Initial load
duke
parents:
diff changeset
389 const char *sym_name, psaddr_t *sym_addr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
390 *sym_addr = (psaddr_t) lookup_symbol(ph, object_name, sym_name);
a61af66fc99e Initial load
duke
parents:
diff changeset
391 return (*sym_addr ? PS_OK : PS_NOSYM);
a61af66fc99e Initial load
duke
parents:
diff changeset
392 }
a61af66fc99e Initial load
duke
parents:
diff changeset
393
a61af66fc99e Initial load
duke
parents:
diff changeset
394 // read "size" bytes info "buf" from address "addr"
a61af66fc99e Initial load
duke
parents:
diff changeset
395 ps_err_e ps_pdread(struct ps_prochandle *ph, psaddr_t addr,
a61af66fc99e Initial load
duke
parents:
diff changeset
396 void *buf, size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
397 return ph->ops->p_pread(ph, (uintptr_t) addr, buf, size)? PS_OK: PS_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
398 }
a61af66fc99e Initial load
duke
parents:
diff changeset
399
a61af66fc99e Initial load
duke
parents:
diff changeset
400 // write "size" bytes of data to debuggee at address "addr"
a61af66fc99e Initial load
duke
parents:
diff changeset
401 ps_err_e ps_pdwrite(struct ps_prochandle *ph, psaddr_t addr,
a61af66fc99e Initial load
duke
parents:
diff changeset
402 const void *buf, size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
403 return ph->ops->p_pwrite(ph, (uintptr_t)addr, buf, size)? PS_OK: PS_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
404 }
a61af66fc99e Initial load
duke
parents:
diff changeset
405
a61af66fc99e Initial load
duke
parents:
diff changeset
406 // ------------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
407 // Functions below this point are not yet implemented. They are here only
a61af66fc99e Initial load
duke
parents:
diff changeset
408 // to make the linker happy.
a61af66fc99e Initial load
duke
parents:
diff changeset
409
a61af66fc99e Initial load
duke
parents:
diff changeset
410 ps_err_e ps_lsetfpregs(struct ps_prochandle *ph, lwpid_t lid, const prfpregset_t *fpregs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
411 print_debug("ps_lsetfpregs not implemented\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
412 return PS_OK;
a61af66fc99e Initial load
duke
parents:
diff changeset
413 }
a61af66fc99e Initial load
duke
parents:
diff changeset
414
a61af66fc99e Initial load
duke
parents:
diff changeset
415 ps_err_e ps_lsetregs(struct ps_prochandle *ph, lwpid_t lid, const prgregset_t gregset) {
a61af66fc99e Initial load
duke
parents:
diff changeset
416 print_debug("ps_lsetregs not implemented\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
417 return PS_OK;
a61af66fc99e Initial load
duke
parents:
diff changeset
418 }
a61af66fc99e Initial load
duke
parents:
diff changeset
419
a61af66fc99e Initial load
duke
parents:
diff changeset
420 ps_err_e ps_lgetfpregs(struct ps_prochandle *ph, lwpid_t lid, prfpregset_t *fpregs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
421 print_debug("ps_lgetfpregs not implemented\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
422 return PS_OK;
a61af66fc99e Initial load
duke
parents:
diff changeset
423 }
a61af66fc99e Initial load
duke
parents:
diff changeset
424
a61af66fc99e Initial load
duke
parents:
diff changeset
425 ps_err_e ps_lgetregs(struct ps_prochandle *ph, lwpid_t lid, prgregset_t gregset) {
a61af66fc99e Initial load
duke
parents:
diff changeset
426 print_debug("ps_lgetfpregs not implemented\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
427 return PS_OK;
a61af66fc99e Initial load
duke
parents:
diff changeset
428 }
a61af66fc99e Initial load
duke
parents:
diff changeset
429
a61af66fc99e Initial load
duke
parents:
diff changeset
430 // new libthread_db of NPTL seem to require this symbol
a61af66fc99e Initial load
duke
parents:
diff changeset
431 ps_err_e ps_get_thread_area() {
a61af66fc99e Initial load
duke
parents:
diff changeset
432 print_debug("ps_get_thread_area not implemented\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
433 return PS_OK;
a61af66fc99e Initial load
duke
parents:
diff changeset
434 }