Mercurial > hg > graal-jvmci-8
comparison agent/src/os/bsd/libproc_impl.c @ 8750:39432a1cefdd
8003348: SA can not read core file on OS
Summary: Macosx uses Mach-O file format for binary files, not ELF format. Currently SA works on core files on other platforms, t his change enables SA work on core file generated on Darwin.
Reviewed-by: sla, sspitsyn
Contributed-by: yumin.qi@oracle.com
author | minqi |
---|---|
date | Thu, 14 Mar 2013 00:33:08 -0700 |
parents | 2394a89e89f4 |
children |
comparison
equal
deleted
inserted
replaced
8719:c8b31b461e1a | 8750:39432a1cefdd |
---|---|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 * or visit www.oracle.com if you need additional information or have any | 20 * or visit www.oracle.com if you need additional information or have any |
21 * questions. | 21 * questions. |
22 * | 22 * |
23 */ | 23 */ |
24 #include <stdarg.h> | |
25 #include <stdio.h> | |
26 #include <stdlib.h> | |
27 #include <string.h> | |
28 #include <fcntl.h> | |
29 #include <thread_db.h> | |
30 #include "libproc_impl.h" | 24 #include "libproc_impl.h" |
31 | 25 |
32 static const char* alt_root = NULL; | 26 static const char* alt_root = NULL; |
33 static int alt_root_len = -1; | 27 static int alt_root_len = -1; |
34 | 28 |
35 #define SA_ALTROOT "SA_ALTROOT" | 29 #define SA_ALTROOT "SA_ALTROOT" |
36 | 30 |
31 off_t ltell(int fd) { | |
32 return lseek(fd, 0, SEEK_CUR); | |
33 } | |
34 | |
37 static void init_alt_root() { | 35 static void init_alt_root() { |
38 if (alt_root_len == -1) { | 36 if (alt_root_len == -1) { |
39 alt_root = getenv(SA_ALTROOT); | 37 alt_root = getenv(SA_ALTROOT); |
40 if (alt_root) { | 38 if (alt_root) { |
41 alt_root_len = strlen(alt_root); | 39 alt_root_len = strlen(alt_root); |
42 } else { | 40 } else { |
43 alt_root_len = 0; | 41 alt_root_len = 0; |
44 } | 42 } |
45 } | 43 } |
46 } | 44 } |
47 | 45 |
48 int pathmap_open(const char* name) { | 46 int pathmap_open(const char* name) { |
49 int fd; | 47 int fd; |
50 char alt_path[PATH_MAX + 1]; | 48 char alt_path[PATH_MAX + 1]; |
51 | 49 |
52 init_alt_root(); | 50 init_alt_root(); |
53 fd = open(name, O_RDONLY); | 51 |
54 if (fd >= 0) { | 52 if (alt_root_len > 0) { |
53 strcpy(alt_path, alt_root); | |
54 strcat(alt_path, name); | |
55 fd = open(alt_path, O_RDONLY); | |
56 if (fd >= 0) { | |
57 print_debug("path %s substituted for %s\n", alt_path, name); | |
55 return fd; | 58 return fd; |
56 } | 59 } |
57 | 60 |
58 if (alt_root_len > 0) { | 61 if (strrchr(name, '/')) { |
59 strcpy(alt_path, alt_root); | 62 strcpy(alt_path, alt_root); |
60 strcat(alt_path, name); | 63 strcat(alt_path, strrchr(name, '/')); |
61 fd = open(alt_path, O_RDONLY); | 64 fd = open(alt_path, O_RDONLY); |
62 if (fd >= 0) { | 65 if (fd >= 0) { |
63 print_debug("path %s substituted for %s\n", alt_path, name); | 66 print_debug("path %s substituted for %s\n", alt_path, name); |
64 return fd; | 67 return fd; |
65 } | 68 } |
66 | 69 } |
67 if (strrchr(name, '/')) { | 70 } else { |
68 strcpy(alt_path, alt_root); | 71 fd = open(name, O_RDONLY); |
69 strcat(alt_path, strrchr(name, '/')); | 72 if (fd >= 0) { |
70 fd = open(alt_path, O_RDONLY); | 73 return fd; |
71 if (fd >= 0) { | 74 } |
72 print_debug("path %s substituted for %s\n", alt_path, name); | 75 } |
73 return fd; | 76 return -1; |
74 } | |
75 } | |
76 } | |
77 | |
78 return -1; | |
79 } | 77 } |
80 | 78 |
81 static bool _libsaproc_debug; | 79 static bool _libsaproc_debug; |
82 | 80 |
83 void print_debug(const char* format,...) { | 81 void print_debug(const char* format,...) { |
84 if (_libsaproc_debug) { | 82 if (_libsaproc_debug) { |
85 va_list alist; | 83 va_list alist; |
86 | 84 |
87 va_start(alist, format); | 85 va_start(alist, format); |
88 fputs("libsaproc DEBUG: ", stderr); | 86 fputs("libsaproc DEBUG: ", stderr); |
89 vfprintf(stderr, format, alist); | 87 vfprintf(stderr, format, alist); |
90 va_end(alist); | 88 va_end(alist); |
91 } | 89 } |
92 } | 90 } |
93 | 91 |
94 void print_error(const char* format,...) { | 92 void print_error(const char* format,...) { |
95 va_list alist; | 93 va_list alist; |
96 va_start(alist, format); | 94 va_start(alist, format); |
98 vfprintf(stderr, format, alist); | 96 vfprintf(stderr, format, alist); |
99 va_end(alist); | 97 va_end(alist); |
100 } | 98 } |
101 | 99 |
102 bool is_debug() { | 100 bool is_debug() { |
103 return _libsaproc_debug; | 101 return _libsaproc_debug; |
104 } | 102 } |
103 | |
104 #ifdef __APPLE__ | |
105 // get arch offset in file | |
106 bool get_arch_off(int fd, cpu_type_t cputype, off_t *offset) { | |
107 struct fat_header fatheader; | |
108 struct fat_arch fatarch; | |
109 off_t img_start = 0; | |
110 | |
111 off_t pos = ltell(fd); | |
112 if (read(fd, (void *)&fatheader, sizeof(struct fat_header)) != sizeof(struct fat_header)) { | |
113 return false; | |
114 } | |
115 if (fatheader.magic == FAT_CIGAM) { | |
116 int i; | |
117 for (i = 0; i < ntohl(fatheader.nfat_arch); i++) { | |
118 if (read(fd, (void *)&fatarch, sizeof(struct fat_arch)) != sizeof(struct fat_arch)) { | |
119 return false; | |
120 } | |
121 if (ntohl(fatarch.cputype) == cputype) { | |
122 print_debug("fat offset=%x\n", ntohl(fatarch.offset)); | |
123 img_start = ntohl(fatarch.offset); | |
124 break; | |
125 } | |
126 } | |
127 if (img_start == 0) { | |
128 return false; | |
129 } | |
130 } | |
131 lseek(fd, pos, SEEK_SET); | |
132 *offset = img_start; | |
133 return true; | |
134 } | |
135 | |
136 bool is_macho_file(int fd) { | |
137 mach_header_64 fhdr; | |
138 off_t x86_64_off; | |
139 | |
140 if (fd < 0) { | |
141 print_debug("Invalid file handle passed to is_macho_file\n"); | |
142 return false; | |
143 } | |
144 | |
145 off_t pos = ltell(fd); | |
146 // check fat header | |
147 if (!get_arch_off(fd, CPU_TYPE_X86_64, &x86_64_off)) { | |
148 print_debug("failed to get fat header\n"); | |
149 return false; | |
150 } | |
151 lseek(fd, x86_64_off, SEEK_SET); | |
152 if (read(fd, (void *)&fhdr, sizeof(mach_header_64)) != sizeof(mach_header_64)) { | |
153 return false; | |
154 } | |
155 lseek(fd, pos, SEEK_SET); // restore | |
156 print_debug("fhdr.magic %x\n", fhdr.magic); | |
157 return (fhdr.magic == MH_MAGIC_64 || fhdr.magic == MH_CIGAM_64); | |
158 } | |
159 | |
160 #endif //__APPLE__ | |
105 | 161 |
106 // initialize libproc | 162 // initialize libproc |
107 bool init_libproc(bool debug) { | 163 bool init_libproc(bool debug) { |
108 // init debug mode | |
109 _libsaproc_debug = debug; | 164 _libsaproc_debug = debug; |
110 | 165 #ifndef __APPLE__ |
111 // initialize the thread_db library | 166 // initialize the thread_db library |
112 if (td_init() != TD_OK) { | 167 if (td_init() != TD_OK) { |
113 print_debug("libthread_db's td_init failed\n"); | 168 print_debug("libthread_db's td_init failed\n"); |
114 return false; | 169 return false; |
115 } | 170 } |
116 | 171 #endif // __APPLE__ |
117 return true; | 172 return true; |
118 } | 173 } |
119 | 174 |
120 static void destroy_lib_info(struct ps_prochandle* ph) { | 175 void destroy_lib_info(struct ps_prochandle* ph) { |
121 lib_info* lib = ph->libs; | 176 lib_info* lib = ph->libs; |
122 while (lib) { | 177 while (lib) { |
123 lib_info *next = lib->next; | 178 lib_info* next = lib->next; |
124 if (lib->symtab) { | 179 if (lib->symtab) { |
125 destroy_symtab(lib->symtab); | 180 destroy_symtab(lib->symtab); |
126 } | 181 } |
127 free(lib); | 182 free(lib); |
128 lib = next; | 183 lib = next; |
129 } | 184 } |
130 } | 185 } |
131 | 186 |
132 static void destroy_thread_info(struct ps_prochandle* ph) { | 187 void destroy_thread_info(struct ps_prochandle* ph) { |
133 thread_info* thr = ph->threads; | 188 sa_thread_info* thr = ph->threads; |
134 while (thr) { | 189 while (thr) { |
135 thread_info *next = thr->next; | 190 sa_thread_info* n = thr->next; |
136 free(thr); | 191 free(thr); |
137 thr = next; | 192 thr = n; |
138 } | 193 } |
139 } | 194 } |
140 | |
141 // ps_prochandle cleanup | |
142 | 195 |
143 // ps_prochandle cleanup | 196 // ps_prochandle cleanup |
144 void Prelease(struct ps_prochandle* ph) { | 197 void Prelease(struct ps_prochandle* ph) { |
145 // do the "derived class" clean-up first | 198 // do the "derived class" clean-up first |
146 ph->ops->release(ph); | 199 ph->ops->release(ph); |
147 destroy_lib_info(ph); | 200 destroy_lib_info(ph); |
148 destroy_thread_info(ph); | 201 destroy_thread_info(ph); |
149 free(ph); | 202 free(ph); |
150 } | 203 } |
151 | 204 |
152 lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base) { | 205 lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base) { |
153 return add_lib_info_fd(ph, libname, -1, base); | 206 return add_lib_info_fd(ph, libname, -1, base); |
154 } | 207 } |
155 | 208 |
156 lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) { | 209 lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) { |
157 lib_info* newlib; | 210 lib_info* newlib; |
158 | 211 print_debug("add_lib_info_fd %s\n", libname); |
159 if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) { | 212 |
160 print_debug("can't allocate memory for lib_info\n"); | 213 if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) { |
161 return NULL; | 214 print_debug("can't allocate memory for lib_info\n"); |
162 } | 215 return NULL; |
163 | 216 } |
164 strncpy(newlib->name, libname, sizeof(newlib->name)); | 217 |
165 newlib->base = base; | 218 strncpy(newlib->name, libname, sizeof(newlib->name)); |
166 | 219 newlib->base = base; |
167 if (fd == -1) { | 220 |
168 if ( (newlib->fd = pathmap_open(newlib->name)) < 0) { | 221 if (fd == -1) { |
169 print_debug("can't open shared object %s\n", newlib->name); | 222 if ( (newlib->fd = pathmap_open(newlib->name)) < 0) { |
170 free(newlib); | 223 print_debug("can't open shared object %s\n", newlib->name); |
171 return NULL; | |
172 } | |
173 } else { | |
174 newlib->fd = fd; | |
175 } | |
176 | |
177 // check whether we have got an ELF file. /proc/<pid>/map | |
178 // gives out all file mappings and not just shared objects | |
179 if (is_elf_file(newlib->fd) == false) { | |
180 close(newlib->fd); | |
181 free(newlib); | 224 free(newlib); |
182 return NULL; | 225 return NULL; |
183 } | 226 } |
184 | 227 } else { |
185 newlib->symtab = build_symtab(newlib->fd); | 228 newlib->fd = fd; |
186 if (newlib->symtab == NULL) { | 229 } |
187 print_debug("symbol table build failed for %s\n", newlib->name); | 230 |
188 } | 231 #ifdef __APPLE__ |
189 else { | 232 // check whether we have got an Macho file. |
190 print_debug("built symbol table for %s\n", newlib->name); | 233 if (is_macho_file(newlib->fd) == false) { |
191 } | 234 close(newlib->fd); |
192 | 235 free(newlib); |
193 // even if symbol table building fails, we add the lib_info. | 236 print_debug("not a mach-o file\n"); |
194 // This is because we may need to read from the ELF file for core file | 237 return NULL; |
195 // address read functionality. lookup_symbol checks for NULL symtab. | 238 } |
196 if (ph->libs) { | 239 #else |
197 ph->lib_tail->next = newlib; | 240 // check whether we have got an ELF file. /proc/<pid>/map |
198 ph->lib_tail = newlib; | 241 // gives out all file mappings and not just shared objects |
199 } else { | 242 if (is_elf_file(newlib->fd) == false) { |
200 ph->libs = ph->lib_tail = newlib; | 243 close(newlib->fd); |
201 } | 244 free(newlib); |
202 ph->num_libs++; | 245 return NULL; |
203 | 246 } |
204 return newlib; | 247 #endif // __APPLE__ |
248 | |
249 newlib->symtab = build_symtab(newlib->fd); | |
250 if (newlib->symtab == NULL) { | |
251 print_debug("symbol table build failed for %s\n", newlib->name); | |
252 } else { | |
253 print_debug("built symbol table for %s\n", newlib->name); | |
254 } | |
255 | |
256 // even if symbol table building fails, we add the lib_info. | |
257 // This is because we may need to read from the ELF file or MachO file for core file | |
258 // address read functionality. lookup_symbol checks for NULL symtab. | |
259 if (ph->libs) { | |
260 ph->lib_tail->next = newlib; | |
261 ph->lib_tail = newlib; | |
262 } else { | |
263 ph->libs = ph->lib_tail = newlib; | |
264 } | |
265 ph->num_libs++; | |
266 return newlib; | |
205 } | 267 } |
206 | 268 |
207 // lookup for a specific symbol | 269 // lookup for a specific symbol |
208 uintptr_t lookup_symbol(struct ps_prochandle* ph, const char* object_name, | 270 uintptr_t lookup_symbol(struct ps_prochandle* ph, const char* object_name, |
209 const char* sym_name) { | 271 const char* sym_name) { |
210 // ignore object_name. search in all libraries | 272 // ignore object_name. search in all libraries |
211 // FIXME: what should we do with object_name?? The library names are obtained | 273 // FIXME: what should we do with object_name?? The library names are obtained |
212 // by parsing /proc/<pid>/maps, which may not be the same as object_name. | 274 // by parsing /proc/<pid>/maps, which may not be the same as object_name. |
213 // What we need is a utility to map object_name to real file name, something | 275 // What we need is a utility to map object_name to real file name, something |
214 // dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For | 276 // dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For |
215 // now, we just ignore object_name and do a global search for the symbol. | 277 // now, we just ignore object_name and do a global search for the symbol. |
216 | 278 |
217 lib_info* lib = ph->libs; | 279 lib_info* lib = ph->libs; |
218 while (lib) { | 280 while (lib) { |
219 if (lib->symtab) { | 281 if (lib->symtab) { |
220 uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL); | 282 uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL); |
221 if (res) return res; | 283 if (res) return res; |
222 } | 284 } |
223 lib = lib->next; | 285 lib = lib->next; |
224 } | 286 } |
225 | 287 |
226 print_debug("lookup failed for symbol '%s' in obj '%s'\n", | 288 print_debug("lookup failed for symbol '%s' in obj '%s'\n", |
227 sym_name, object_name); | 289 sym_name, object_name); |
228 return (uintptr_t) NULL; | 290 return (uintptr_t) NULL; |
229 } | 291 } |
230 | |
231 | 292 |
232 const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset) { | 293 const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset) { |
233 const char* res = NULL; | 294 const char* res = NULL; |
234 lib_info* lib = ph->libs; | 295 lib_info* lib = ph->libs; |
235 while (lib) { | 296 while (lib) { |
236 if (lib->symtab && addr >= lib->base) { | 297 if (lib->symtab && addr >= lib->base) { |
237 res = nearest_symbol(lib->symtab, addr - lib->base, poffset); | 298 res = nearest_symbol(lib->symtab, addr - lib->base, poffset); |
238 if (res) return res; | 299 if (res) return res; |
239 } | 300 } |
240 lib = lib->next; | 301 lib = lib->next; |
241 } | 302 } |
242 return NULL; | 303 return NULL; |
243 } | 304 } |
244 | 305 |
245 // add a thread to ps_prochandle | 306 // add a thread to ps_prochandle |
246 thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) { | 307 sa_thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) { |
247 thread_info* newthr; | 308 sa_thread_info* newthr; |
248 if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) { | 309 if ( (newthr = (sa_thread_info*) calloc(1, sizeof(sa_thread_info))) == NULL) { |
249 print_debug("can't allocate memory for thread_info\n"); | 310 print_debug("can't allocate memory for thread_info\n"); |
250 return NULL; | 311 return NULL; |
251 } | 312 } |
252 | 313 |
253 // initialize thread info | 314 // initialize thread info |
254 newthr->pthread_id = pthread_id; | 315 newthr->pthread_id = pthread_id; |
255 newthr->lwp_id = lwp_id; | 316 newthr->lwp_id = lwp_id; |
256 | 317 |
257 // add new thread to the list | 318 // add new thread to the list |
258 newthr->next = ph->threads; | 319 newthr->next = ph->threads; |
259 ph->threads = newthr; | 320 ph->threads = newthr; |
260 ph->num_threads++; | 321 ph->num_threads++; |
261 return newthr; | 322 return newthr; |
262 } | 323 } |
263 | 324 |
264 | 325 #ifndef __APPLE__ |
265 // struct used for client data from thread_db callback | 326 // struct used for client data from thread_db callback |
266 struct thread_db_client_data { | 327 struct thread_db_client_data { |
267 struct ps_prochandle* ph; | 328 struct ps_prochandle* ph; |
268 thread_info_callback callback; | 329 thread_info_callback callback; |
269 }; | 330 }; |
270 | 331 |
271 // callback function for libthread_db | 332 // callback function for libthread_db |
272 static int thread_db_callback(const td_thrhandle_t *th_p, void *data) { | 333 static int thread_db_callback(const td_thrhandle_t *th_p, void *data) { |
273 struct thread_db_client_data* ptr = (struct thread_db_client_data*) data; | 334 struct thread_db_client_data* ptr = (struct thread_db_client_data*) data; |
312 // delete thread agent | 373 // delete thread agent |
313 td_ta_delete(thread_agent); | 374 td_ta_delete(thread_agent); |
314 return true; | 375 return true; |
315 } | 376 } |
316 | 377 |
378 #endif // __APPLE__ | |
317 | 379 |
318 // get number of threads | 380 // get number of threads |
319 int get_num_threads(struct ps_prochandle* ph) { | 381 int get_num_threads(struct ps_prochandle* ph) { |
320 return ph->num_threads; | 382 return ph->num_threads; |
321 } | 383 } |
322 | 384 |
323 // get lwp_id of n'th thread | 385 // get lwp_id of n'th thread |
324 lwpid_t get_lwp_id(struct ps_prochandle* ph, int index) { | 386 lwpid_t get_lwp_id(struct ps_prochandle* ph, int index) { |
325 int count = 0; | 387 int count = 0; |
326 thread_info* thr = ph->threads; | 388 sa_thread_info* thr = ph->threads; |
327 while (thr) { | 389 while (thr) { |
328 if (count == index) { | 390 if (count == index) { |
329 return thr->lwp_id; | 391 return thr->lwp_id; |
330 } | 392 } |
331 count++; | 393 count++; |
332 thr = thr->next; | 394 thr = thr->next; |
333 } | 395 } |
334 return -1; | 396 return 0; |
335 } | 397 } |
398 | |
399 #ifdef __APPLE__ | |
400 // set lwp_id of n'th thread | |
401 bool set_lwp_id(struct ps_prochandle* ph, int index, lwpid_t lwpid) { | |
402 int count = 0; | |
403 sa_thread_info* thr = ph->threads; | |
404 while (thr) { | |
405 if (count == index) { | |
406 thr->lwp_id = lwpid; | |
407 return true; | |
408 } | |
409 count++; | |
410 thr = thr->next; | |
411 } | |
412 return false; | |
413 } | |
414 | |
415 // get regs of n-th thread, only used in fillThreads the first time called | |
416 bool get_nth_lwp_regs(struct ps_prochandle* ph, int index, struct reg* regs) { | |
417 int count = 0; | |
418 sa_thread_info* thr = ph->threads; | |
419 while (thr) { | |
420 if (count == index) { | |
421 break; | |
422 } | |
423 count++; | |
424 thr = thr->next; | |
425 } | |
426 if (thr != NULL) { | |
427 memcpy(regs, &thr->regs, sizeof(struct reg)); | |
428 return true; | |
429 } | |
430 return false; | |
431 } | |
432 | |
433 #endif // __APPLE__ | |
336 | 434 |
337 // get regs for a given lwp | 435 // get regs for a given lwp |
338 bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, struct reg* regs) { | 436 bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, struct reg* regs) { |
339 return ph->ops->get_lwp_regs(ph, lwp_id, regs); | 437 return ph->ops->get_lwp_regs(ph, lwp_id, regs); |
340 } | 438 } |
341 | 439 |
342 // get number of shared objects | 440 // get number of shared objects |
343 int get_num_libs(struct ps_prochandle* ph) { | 441 int get_num_libs(struct ps_prochandle* ph) { |
344 return ph->num_libs; | 442 return ph->num_libs; |
345 } | 443 } |
346 | 444 |
347 // get name of n'th solib | 445 // get name of n'th solib |
348 const char* get_lib_name(struct ps_prochandle* ph, int index) { | 446 const char* get_lib_name(struct ps_prochandle* ph, int index) { |
349 int count = 0; | 447 int count = 0; |
350 lib_info* lib = ph->libs; | 448 lib_info* lib = ph->libs; |
351 while (lib) { | 449 while (lib) { |
352 if (count == index) { | 450 if (count == index) { |
353 return lib->name; | 451 return lib->name; |
354 } | 452 } |
355 count++; | 453 count++; |
356 lib = lib->next; | 454 lib = lib->next; |
357 } | 455 } |
358 return NULL; | 456 return NULL; |
359 } | 457 } |
360 | 458 |
361 // get base address of a lib | 459 // get base address of a lib |
362 uintptr_t get_lib_base(struct ps_prochandle* ph, int index) { | 460 uintptr_t get_lib_base(struct ps_prochandle* ph, int index) { |
363 int count = 0; | 461 int count = 0; |
364 lib_info* lib = ph->libs; | 462 lib_info* lib = ph->libs; |
365 while (lib) { | 463 while (lib) { |
366 if (count == index) { | 464 if (count == index) { |
367 return lib->base; | 465 return lib->base; |
368 } | 466 } |
369 count++; | 467 count++; |
370 lib = lib->next; | 468 lib = lib->next; |
371 } | 469 } |
372 return (uintptr_t)NULL; | 470 return (uintptr_t)NULL; |
373 } | 471 } |
374 | 472 |
375 bool find_lib(struct ps_prochandle* ph, const char *lib_name) { | 473 bool find_lib(struct ps_prochandle* ph, const char *lib_name) { |
376 lib_info *p = ph->libs; | 474 lib_info *p = ph->libs; |
377 while (p) { | 475 while (p) { |
423 va_start(alist, format); | 521 va_start(alist, format); |
424 vfprintf(stderr, format, alist); | 522 vfprintf(stderr, format, alist); |
425 va_end(alist); | 523 va_end(alist); |
426 } | 524 } |
427 | 525 |
526 #ifndef __APPLE__ | |
428 // ------------------------------------------------------------------------ | 527 // ------------------------------------------------------------------------ |
429 // Functions below this point are not yet implemented. They are here only | 528 // Functions below this point are not yet implemented. They are here only |
430 // to make the linker happy. | 529 // to make the linker happy. |
431 | 530 |
432 ps_err_e ps_lsetfpregs(struct ps_prochandle *ph, lwpid_t lid, const prfpregset_t *fpregs) { | 531 ps_err_e ps_lsetfpregs(struct ps_prochandle *ph, lwpid_t lid, const prfpregset_t *fpregs) { |
456 | 555 |
457 ps_err_e ps_pcontinue(struct ps_prochandle *ph) { | 556 ps_err_e ps_pcontinue(struct ps_prochandle *ph) { |
458 print_debug("ps_pcontinue not implemented\n"); | 557 print_debug("ps_pcontinue not implemented\n"); |
459 return PS_OK; | 558 return PS_OK; |
460 } | 559 } |
560 #endif // __APPLE__ |