agent/src/os/bsd/ps_proc.c

Mon, 28 Oct 2013 21:41:48 +0400

author
dsamersoff
date
Mon, 28 Oct 2013 21:41:48 +0400
changeset 6031
1a04de1aaedb
parent 4599
2394a89e89f4
child 6876
710a3c8b516e
permissions
-rw-r--r--

8026950: Nits in agent ps_proc.c file breaks compilation of open hotspot
Summary: Fixed two compilation-breaking nits
Reviewed-by: sla, dholmes

never@3156 1 /*
rbackman@4599 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
never@3156 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
never@3156 4 *
never@3156 5 * This code is free software; you can redistribute it and/or modify it
never@3156 6 * under the terms of the GNU General Public License version 2 only, as
never@3156 7 * published by the Free Software Foundation.
never@3156 8 *
never@3156 9 * This code is distributed in the hope that it will be useful, but WITHOUT
never@3156 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
never@3156 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
never@3156 12 * version 2 for more details (a copy is included in the LICENSE file that
never@3156 13 * accompanied this code).
never@3156 14 *
never@3156 15 * You should have received a copy of the GNU General Public License version
never@3156 16 * 2 along with this work; if not, write to the Free Software Foundation,
never@3156 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
never@3156 18 *
never@3156 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
never@3156 20 * or visit www.oracle.com if you need additional information or have any
never@3156 21 * questions.
never@3156 22 *
never@3156 23 */
never@3156 24
never@3156 25 #include <limits.h>
never@3156 26 #include <stdio.h>
never@3156 27 #include <stdlib.h>
never@3156 28 #include <string.h>
never@3156 29 #include <errno.h>
never@3156 30 #include <sys/types.h>
never@3156 31 #include <sys/wait.h>
never@3156 32 #include <sys/ptrace.h>
never@3156 33 #include <sys/param.h>
never@3156 34 #include <sys/user.h>
never@3156 35 #include <elf.h>
never@3156 36 #include <sys/elf_common.h>
never@3156 37 #include <sys/link_elf.h>
never@3156 38 #include <libutil.h>
never@3156 39 #include "libproc_impl.h"
never@3156 40 #include "elfmacros.h"
never@3156 41
never@3156 42 // This file has the libproc implementation specific to live process
never@3156 43 // For core files, refer to ps_core.c
never@3156 44
never@3156 45 static inline uintptr_t align(uintptr_t ptr, size_t size) {
never@3156 46 return (ptr & ~(size - 1));
never@3156 47 }
never@3156 48
never@3156 49 // ---------------------------------------------
never@3156 50 // ptrace functions
never@3156 51 // ---------------------------------------------
never@3156 52
never@3156 53 // read "size" bytes of data from "addr" within the target process.
never@3156 54 // unlike the standard ptrace() function, process_read_data() can handle
never@3156 55 // unaligned address - alignment check, if required, should be done
never@3156 56 // before calling process_read_data.
never@3156 57
never@3156 58 static bool process_read_data(struct ps_prochandle* ph, uintptr_t addr, char *buf, size_t size) {
never@3156 59 int rslt;
never@3156 60 size_t i, words;
never@3156 61 uintptr_t end_addr = addr + size;
never@3156 62 uintptr_t aligned_addr = align(addr, sizeof(int));
never@3156 63
never@3156 64 if (aligned_addr != addr) {
never@3156 65 char *ptr = (char *)&rslt;
never@3156 66 errno = 0;
never@3156 67 rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0);
never@3156 68 if (errno) {
never@3156 69 print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr);
never@3156 70 return false;
never@3156 71 }
never@3156 72 for (; aligned_addr != addr; aligned_addr++, ptr++);
never@3156 73 for (; ((intptr_t)aligned_addr % sizeof(int)) && aligned_addr < end_addr;
never@3156 74 aligned_addr++)
never@3156 75 *(buf++) = *(ptr++);
never@3156 76 }
never@3156 77
never@3156 78 words = (end_addr - aligned_addr) / sizeof(int);
never@3156 79
never@3156 80 // assert((intptr_t)aligned_addr % sizeof(int) == 0);
never@3156 81 for (i = 0; i < words; i++) {
never@3156 82 errno = 0;
never@3156 83 rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0);
never@3156 84 if (errno) {
never@3156 85 print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr);
never@3156 86 return false;
never@3156 87 }
never@3156 88 *(int *)buf = rslt;
never@3156 89 buf += sizeof(int);
never@3156 90 aligned_addr += sizeof(int);
never@3156 91 }
never@3156 92
never@3156 93 if (aligned_addr != end_addr) {
never@3156 94 char *ptr = (char *)&rslt;
never@3156 95 errno = 0;
never@3156 96 rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0);
never@3156 97 if (errno) {
never@3156 98 print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr);
never@3156 99 return false;
never@3156 100 }
never@3156 101 for (; aligned_addr != end_addr; aligned_addr++)
never@3156 102 *(buf++) = *(ptr++);
never@3156 103 }
never@3156 104 return true;
never@3156 105 }
never@3156 106
never@3156 107 // null implementation for write
never@3156 108 static bool process_write_data(struct ps_prochandle* ph,
never@3156 109 uintptr_t addr, const char *buf , size_t size) {
never@3156 110 return false;
never@3156 111 }
never@3156 112
never@3156 113 // "user" should be a pointer to a reg
never@3156 114 static bool process_get_lwp_regs(struct ps_prochandle* ph, pid_t pid, struct reg *user) {
never@3156 115 // we have already attached to all thread 'pid's, just use ptrace call
never@3156 116 // to get regset now. Note that we don't cache regset upfront for processes.
never@3156 117 if (ptrace(PT_GETREGS, pid, (caddr_t) user, 0) < 0) {
never@3156 118 print_debug("ptrace(PTRACE_GETREGS, ...) failed for lwp %d\n", pid);
never@3156 119 return false;
never@3156 120 }
never@3156 121 return true;
never@3156 122 }
never@3156 123
never@3156 124 // fill in ptrace_lwpinfo for lid
never@3156 125 static bool process_get_lwp_info(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo) {
never@3156 126 errno = 0;
never@3156 127 ptrace(PT_LWPINFO, lwp_id, linfo, sizeof(struct ptrace_lwpinfo));
never@3156 128
never@3156 129 return (errno == 0)? true: false;
never@3156 130 }
never@3156 131
rbackman@4599 132 static bool ptrace_continue(pid_t pid, int signal) {
rbackman@4599 133 // pass the signal to the process so we don't swallow it
dsamersoff@6031 134 if (ptrace(PT_CONTINUE, pid, NULL, signal) < 0) {
rbackman@4599 135 print_debug("ptrace(PTRACE_CONT, ..) failed for %d\n", pid);
rbackman@4599 136 return false;
rbackman@4599 137 }
rbackman@4599 138 return true;
rbackman@4599 139 }
rbackman@4599 140
rbackman@4599 141 // waits until the ATTACH has stopped the process
rbackman@4599 142 // by signal SIGSTOP
rbackman@4599 143 static bool ptrace_waitpid(pid_t pid) {
rbackman@4599 144 int ret;
rbackman@4599 145 int status;
rbackman@4599 146 do {
rbackman@4599 147 // Wait for debuggee to stop.
rbackman@4599 148 ret = waitpid(pid, &status, 0);
rbackman@4599 149 if (ret >= 0) {
rbackman@4599 150 if (WIFSTOPPED(status)) {
rbackman@4599 151 // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP
rbackman@4599 152 // will still be pending and delivered when the process is DETACHED and the process
rbackman@4599 153 // will go to sleep.
rbackman@4599 154 if (WSTOPSIG(status) == SIGSTOP) {
rbackman@4599 155 // Debuggee stopped by SIGSTOP.
rbackman@4599 156 return true;
rbackman@4599 157 }
rbackman@4599 158 if (!ptrace_continue(pid, WSTOPSIG(status))) {
rbackman@4599 159 print_error("Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status));
rbackman@4599 160 return false;
rbackman@4599 161 }
rbackman@4599 162 } else {
rbackman@4599 163 print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
rbackman@4599 164 return false;
rbackman@4599 165 }
rbackman@4599 166 } else {
rbackman@4599 167 switch (errno) {
rbackman@4599 168 case EINTR:
rbackman@4599 169 continue;
rbackman@4599 170 break;
rbackman@4599 171 case ECHILD:
rbackman@4599 172 print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
rbackman@4599 173 break;
rbackman@4599 174 case EINVAL:
rbackman@4599 175 print_debug("waitpid() failed. Invalid options argument.\n");
rbackman@4599 176 break;
rbackman@4599 177 default:
rbackman@4599 178 print_debug("waitpid() failed. Unexpected error %d\n",errno);
rbackman@4599 179 }
rbackman@4599 180 return false;
rbackman@4599 181 }
rbackman@4599 182 } while(true);
rbackman@4599 183 }
rbackman@4599 184
never@3156 185 // attach to a process/thread specified by "pid"
never@3156 186 static bool ptrace_attach(pid_t pid) {
never@3156 187 if (ptrace(PT_ATTACH, pid, NULL, 0) < 0) {
never@3156 188 print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid);
never@3156 189 return false;
never@3156 190 } else {
rbackman@4599 191 return ptrace_waitpid(pid);
never@3156 192 }
never@3156 193 }
never@3156 194
never@3156 195 // -------------------------------------------------------
never@3156 196 // functions for obtaining library information
never@3156 197 // -------------------------------------------------------
never@3156 198
never@3156 199 // callback for read_thread_info
never@3156 200 static bool add_new_thread(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
never@3156 201 return add_thread_info(ph, pthread_id, lwp_id) != NULL;
never@3156 202 }
never@3156 203
never@3156 204 #if defined(__FreeBSD__) && __FreeBSD_version < 701000
never@3156 205 /*
never@3156 206 * TEXT_START_ADDR from binutils/ld/emulparams/<arch_spec>.sh
never@3156 207 * Not the most robust but good enough.
never@3156 208 */
never@3156 209
never@3156 210 #if defined(amd64) || defined(x86_64)
never@3156 211 #define TEXT_START_ADDR 0x400000
never@3156 212 #elif defined(i386)
never@3156 213 #define TEXT_START_ADDR 0x8048000
never@3156 214 #else
never@3156 215 #error TEXT_START_ADDR not defined
never@3156 216 #endif
never@3156 217
never@3156 218 #define BUF_SIZE (PATH_MAX + NAME_MAX + 1)
never@3156 219
never@3156 220 uintptr_t linkmap_addr(struct ps_prochandle *ph) {
never@3156 221 uintptr_t ehdr_addr, phdr_addr, dyn_addr, dmap_addr, lmap_addr;
never@3156 222 ELF_EHDR ehdr;
never@3156 223 ELF_PHDR *phdrs, *phdr;
never@3156 224 ELF_DYN *dyns, *dyn;
never@3156 225 struct r_debug dmap;
never@3156 226 unsigned long hdrs_size;
never@3156 227 unsigned int i;
never@3156 228
never@3156 229 /* read ELF_EHDR at TEXT_START_ADDR and validate */
never@3156 230
never@3156 231 ehdr_addr = (uintptr_t)TEXT_START_ADDR;
never@3156 232
never@3156 233 if (process_read_data(ph, ehdr_addr, (char *)&ehdr, sizeof(ehdr)) != true) {
never@3156 234 print_debug("process_read_data failed for ehdr_addr %p\n", ehdr_addr);
never@3156 235 return (0);
never@3156 236 }
never@3156 237
never@3156 238 if (!IS_ELF(ehdr) ||
never@3156 239 ehdr.e_ident[EI_CLASS] != ELF_TARG_CLASS ||
never@3156 240 ehdr.e_ident[EI_DATA] != ELF_TARG_DATA ||
never@3156 241 ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
never@3156 242 ehdr.e_phentsize != sizeof(ELF_PHDR) ||
never@3156 243 ehdr.e_version != ELF_TARG_VER ||
never@3156 244 ehdr.e_machine != ELF_TARG_MACH) {
never@3156 245 print_debug("not an ELF_EHDR at %p\n", ehdr_addr);
never@3156 246 return (0);
never@3156 247 }
never@3156 248
never@3156 249 /* allocate space for all ELF_PHDR's and read */
never@3156 250
never@3156 251 phdr_addr = ehdr_addr + ehdr.e_phoff;
never@3156 252 hdrs_size = ehdr.e_phnum * sizeof(ELF_PHDR);
never@3156 253
never@3156 254 if ((phdrs = malloc(hdrs_size)) == NULL)
never@3156 255 return (0);
never@3156 256
never@3156 257 if (process_read_data(ph, phdr_addr, (char *)phdrs, hdrs_size) != true) {
never@3156 258 print_debug("process_read_data failed for phdr_addr %p\n", phdr_addr);
never@3156 259 return (0);
never@3156 260 }
never@3156 261
never@3156 262 /* find PT_DYNAMIC section */
never@3156 263
never@3156 264 for (i = 0, phdr = phdrs; i < ehdr.e_phnum; i++, phdr++) {
never@3156 265 if (phdr->p_type == PT_DYNAMIC)
never@3156 266 break;
never@3156 267 }
never@3156 268
never@3156 269 if (i >= ehdr.e_phnum) {
never@3156 270 print_debug("PT_DYNAMIC section not found!\n");
never@3156 271 free(phdrs);
never@3156 272 return (0);
never@3156 273 }
never@3156 274
never@3156 275 /* allocate space and read in ELF_DYN headers */
never@3156 276
never@3156 277 dyn_addr = phdr->p_vaddr;
never@3156 278 hdrs_size = phdr->p_memsz;
never@3156 279 free(phdrs);
never@3156 280
never@3156 281 if ((dyns = malloc(hdrs_size)) == NULL)
never@3156 282 return (0);
never@3156 283
never@3156 284 if (process_read_data(ph, dyn_addr, (char *)dyns, hdrs_size) != true) {
never@3156 285 print_debug("process_read_data failed for dyn_addr %p\n", dyn_addr);
never@3156 286 free(dyns);
never@3156 287 return (0);
never@3156 288 }
never@3156 289
never@3156 290 /* find DT_DEBUG */
never@3156 291
never@3156 292 dyn = dyns;
never@3156 293 while (dyn->d_tag != DT_DEBUG && dyn->d_tag != DT_NULL) {
never@3156 294 dyn++;
never@3156 295 }
never@3156 296
never@3156 297 if (dyn->d_tag != DT_DEBUG) {
never@3156 298 print_debug("failed to find DT_DEBUG\n");
never@3156 299 free(dyns);
never@3156 300 return (0);
never@3156 301 }
never@3156 302
never@3156 303 /* read struct r_debug into dmap */
never@3156 304
never@3156 305 dmap_addr = (uintptr_t)dyn->d_un.d_ptr;
never@3156 306 free(dyns);
never@3156 307
never@3156 308 if (process_read_data(ph, dmap_addr, (char *)&dmap, sizeof(dmap)) != true) {
never@3156 309 print_debug("process_read_data failed for dmap_addr %p\n", dmap_addr);
never@3156 310 return (0);
never@3156 311 }
never@3156 312
never@3156 313 lmap_addr = (uintptr_t)dmap.r_map;
never@3156 314
never@3156 315 return (lmap_addr);
never@3156 316 }
never@3156 317 #endif // __FreeBSD__ && __FreeBSD_version < 701000
never@3156 318
never@3156 319 static bool read_lib_info(struct ps_prochandle* ph) {
never@3156 320 #if defined(__FreeBSD__) && __FreeBSD_version >= 701000
never@3156 321 struct kinfo_vmentry *freep, *kve;
never@3156 322 int i, cnt;
never@3156 323
never@3156 324 freep = kinfo_getvmmap(ph->pid, &cnt);
never@3156 325 if (freep == NULL) {
never@3156 326 print_debug("can't get vm map for pid\n", ph->pid);
never@3156 327 return false;
never@3156 328 }
never@3156 329
never@3156 330 for (i = 0; i < cnt; i++) {
never@3156 331 kve = &freep[i];
never@3156 332 if ((kve->kve_flags & KVME_FLAG_COW) &&
never@3156 333 kve->kve_path != NULL &&
never@3156 334 strlen(kve->kve_path) > 0) {
never@3156 335
never@3156 336 if (find_lib(ph, kve->kve_path) == false) {
never@3156 337 lib_info* lib;
never@3156 338 if ((lib = add_lib_info(ph, kve->kve_path,
never@3156 339 (uintptr_t) kve->kve_start)) == NULL)
never@3156 340 continue; // ignore, add_lib_info prints error
never@3156 341
never@3156 342 // we don't need to keep the library open, symtab is already
never@3156 343 // built. Only for core dump we need to keep the fd open.
never@3156 344 close(lib->fd);
never@3156 345 lib->fd = -1;
never@3156 346 }
never@3156 347 }
never@3156 348 }
never@3156 349
never@3156 350 free(freep);
never@3156 351
never@3156 352 return true;
never@3156 353 #else
never@3156 354 char *l_name;
never@3156 355 struct link_map *lmap;
never@3156 356 uintptr_t lmap_addr;
never@3156 357
never@3156 358 if ((l_name = malloc(BUF_SIZE)) == NULL)
never@3156 359 return false;
never@3156 360
never@3156 361 if ((lmap = malloc(sizeof(*lmap))) == NULL) {
never@3156 362 free(l_name);
never@3156 363 return false;
never@3156 364 }
never@3156 365
never@3156 366 lmap_addr = linkmap_addr(ph);
never@3156 367
never@3156 368 if (lmap_addr == 0) {
never@3156 369 free(l_name);
never@3156 370 free(lmap);
never@3156 371 return false;
never@3156 372 }
never@3156 373
never@3156 374 do {
never@3156 375 if (process_read_data(ph, lmap_addr, (char *)lmap, sizeof(*lmap)) != true) {
never@3156 376 print_debug("process_read_data failed for lmap_addr %p\n", lmap_addr);
never@3156 377 free (l_name);
never@3156 378 free (lmap);
never@3156 379 return false;
never@3156 380 }
never@3156 381
never@3156 382 if (process_read_data(ph, (uintptr_t)lmap->l_name, l_name,
never@3156 383 BUF_SIZE) != true) {
never@3156 384 print_debug("process_read_data failed for lmap->l_name %p\n",
never@3156 385 lmap->l_name);
never@3156 386 free (l_name);
never@3156 387 free (lmap);
never@3156 388 return false;
never@3156 389 }
never@3156 390
never@3156 391 if (find_lib(ph, l_name) == false) {
never@3156 392 lib_info* lib;
never@3156 393 if ((lib = add_lib_info(ph, l_name,
never@3156 394 (uintptr_t) lmap->l_addr)) == NULL)
never@3156 395 continue; // ignore, add_lib_info prints error
never@3156 396
never@3156 397 // we don't need to keep the library open, symtab is already
never@3156 398 // built. Only for core dump we need to keep the fd open.
never@3156 399 close(lib->fd);
never@3156 400 lib->fd = -1;
never@3156 401 }
never@3156 402 lmap_addr = (uintptr_t)lmap->l_next;
never@3156 403 } while (lmap->l_next != NULL);
never@3156 404
never@3156 405 free (l_name);
never@3156 406 free (lmap);
never@3156 407
never@3156 408 return true;
never@3156 409 #endif
never@3156 410 }
never@3156 411
never@3156 412 // detach a given pid
never@3156 413 static bool ptrace_detach(pid_t pid) {
never@3156 414 if (pid && ptrace(PT_DETACH, pid, (caddr_t)1, 0) < 0) {
never@3156 415 print_debug("ptrace(PTRACE_DETACH, ..) failed for %d\n", pid);
never@3156 416 return false;
never@3156 417 } else {
never@3156 418 return true;
never@3156 419 }
never@3156 420 }
never@3156 421
never@3156 422 static void process_cleanup(struct ps_prochandle* ph) {
never@3156 423 ptrace_detach(ph->pid);
never@3156 424 }
never@3156 425
never@3156 426 static ps_prochandle_ops process_ops = {
never@3156 427 .release= process_cleanup,
never@3156 428 .p_pread= process_read_data,
never@3156 429 .p_pwrite= process_write_data,
never@3156 430 .get_lwp_regs= process_get_lwp_regs,
never@3156 431 .get_lwp_info= process_get_lwp_info
never@3156 432 };
never@3156 433
never@3156 434 // attach to the process. One and only one exposed stuff
never@3156 435 struct ps_prochandle* Pgrab(pid_t pid) {
never@3156 436 struct ps_prochandle* ph = NULL;
never@3156 437
never@3156 438 if ( (ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle))) == NULL) {
never@3156 439 print_debug("can't allocate memory for ps_prochandle\n");
never@3156 440 return NULL;
never@3156 441 }
never@3156 442
never@3156 443 if (ptrace_attach(pid) != true) {
never@3156 444 free(ph);
never@3156 445 return NULL;
never@3156 446 }
never@3156 447
never@3156 448 // initialize ps_prochandle
never@3156 449 ph->pid = pid;
never@3156 450
never@3156 451 // initialize vtable
never@3156 452 ph->ops = &process_ops;
never@3156 453
never@3156 454 // read library info and symbol tables, must do this before attaching threads,
never@3156 455 // as the symbols in the pthread library will be used to figure out
never@3156 456 // the list of threads within the same process.
never@3156 457 if (read_lib_info(ph) != true) {
never@3156 458 ptrace_detach(pid);
never@3156 459 free(ph);
never@3156 460 return NULL;
never@3156 461 }
never@3156 462
never@3156 463 // read thread info
never@3156 464 read_thread_info(ph, add_new_thread);
never@3156 465
never@3156 466 return ph;
never@3156 467 }

mercurial