Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/agent/src/os/bsd/ps_proc.c
38833 views
/*1* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include <limits.h>25#include <stdio.h>26#include <stdlib.h>27#include <string.h>28#include <errno.h>29#include <sys/types.h>30#include <sys/wait.h>31#include <sys/ptrace.h>32#include <sys/param.h>33#include <sys/user.h>34#include <elf.h>35#include <sys/elf_common.h>36#include <sys/link_elf.h>37#include <libutil.h>38#include "libproc_impl.h"39#include "elfmacros.h"4041// This file has the libproc implementation specific to live process42// For core files, refer to ps_core.c4344static inline uintptr_t align(uintptr_t ptr, size_t size) {45return (ptr & ~(size - 1));46}4748// ---------------------------------------------49// ptrace functions50// ---------------------------------------------5152// read "size" bytes of data from "addr" within the target process.53// unlike the standard ptrace() function, process_read_data() can handle54// unaligned address - alignment check, if required, should be done55// before calling process_read_data.5657static bool process_read_data(struct ps_prochandle* ph, uintptr_t addr, char *buf, size_t size) {58int rslt;59size_t i, words;60uintptr_t end_addr = addr + size;61uintptr_t aligned_addr = align(addr, sizeof(int));6263if (aligned_addr != addr) {64char *ptr = (char *)&rslt;65errno = 0;66rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0);67if (errno) {68print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr);69return false;70}71for (; aligned_addr != addr; aligned_addr++, ptr++);72for (; ((intptr_t)aligned_addr % sizeof(int)) && aligned_addr < end_addr;73aligned_addr++)74*(buf++) = *(ptr++);75}7677words = (end_addr - aligned_addr) / sizeof(int);7879// assert((intptr_t)aligned_addr % sizeof(int) == 0);80for (i = 0; i < words; i++) {81errno = 0;82rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0);83if (errno) {84print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr);85return false;86}87*(int *)buf = rslt;88buf += sizeof(int);89aligned_addr += sizeof(int);90}9192if (aligned_addr != end_addr) {93char *ptr = (char *)&rslt;94errno = 0;95rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0);96if (errno) {97print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr);98return false;99}100for (; aligned_addr != end_addr; aligned_addr++)101*(buf++) = *(ptr++);102}103return true;104}105106// null implementation for write107static bool process_write_data(struct ps_prochandle* ph,108uintptr_t addr, const char *buf , size_t size) {109return false;110}111112// "user" should be a pointer to a reg113static bool process_get_lwp_regs(struct ps_prochandle* ph, pid_t pid, struct reg *user) {114// we have already attached to all thread 'pid's, just use ptrace call115// to get regset now. Note that we don't cache regset upfront for processes.116if (ptrace(PT_GETREGS, pid, (caddr_t) user, 0) < 0) {117print_debug("ptrace(PTRACE_GETREGS, ...) failed for lwp %d\n", pid);118return false;119}120return true;121}122123// fill in ptrace_lwpinfo for lid124static bool process_get_lwp_info(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo) {125errno = 0;126ptrace(PT_LWPINFO, lwp_id, linfo, sizeof(struct ptrace_lwpinfo));127128return (errno == 0)? true: false;129}130131static bool ptrace_continue(pid_t pid, int signal) {132// pass the signal to the process so we don't swallow it133if (ptrace(PT_CONTINUE, pid, NULL, signal) < 0) {134print_debug("ptrace(PTRACE_CONT, ..) failed for %d\n", pid);135return false;136}137return true;138}139140// waits until the ATTACH has stopped the process141// by signal SIGSTOP142static bool ptrace_waitpid(pid_t pid) {143int ret;144int status;145do {146// Wait for debuggee to stop.147ret = waitpid(pid, &status, 0);148if (ret >= 0) {149if (WIFSTOPPED(status)) {150// Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP151// will still be pending and delivered when the process is DETACHED and the process152// will go to sleep.153if (WSTOPSIG(status) == SIGSTOP) {154// Debuggee stopped by SIGSTOP.155return true;156}157if (!ptrace_continue(pid, WSTOPSIG(status))) {158print_error("Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status));159return false;160}161} else {162print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);163return false;164}165} else {166switch (errno) {167case EINTR:168continue;169break;170case ECHILD:171print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);172break;173case EINVAL:174print_debug("waitpid() failed. Invalid options argument.\n");175break;176default:177print_debug("waitpid() failed. Unexpected error %d\n",errno);178}179return false;180}181} while(true);182}183184// attach to a process/thread specified by "pid"185static bool ptrace_attach(pid_t pid) {186if (ptrace(PT_ATTACH, pid, NULL, 0) < 0) {187print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid);188return false;189} else {190return ptrace_waitpid(pid);191}192}193194// -------------------------------------------------------195// functions for obtaining library information196// -------------------------------------------------------197198// callback for read_thread_info199static bool add_new_thread(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {200return add_thread_info(ph, pthread_id, lwp_id) != NULL;201}202203#if defined(__FreeBSD__) && __FreeBSD_version < 701000204/*205* TEXT_START_ADDR from binutils/ld/emulparams/<arch_spec>.sh206* Not the most robust but good enough.207*/208209#if defined(amd64) || defined(x86_64)210#define TEXT_START_ADDR 0x400000211#elif defined(i386)212#define TEXT_START_ADDR 0x8048000213#else214#error TEXT_START_ADDR not defined215#endif216217#define BUF_SIZE (PATH_MAX + NAME_MAX + 1)218219uintptr_t linkmap_addr(struct ps_prochandle *ph) {220uintptr_t ehdr_addr, phdr_addr, dyn_addr, dmap_addr, lmap_addr;221ELF_EHDR ehdr;222ELF_PHDR *phdrs, *phdr;223ELF_DYN *dyns, *dyn;224struct r_debug dmap;225unsigned long hdrs_size;226unsigned int i;227228/* read ELF_EHDR at TEXT_START_ADDR and validate */229230ehdr_addr = (uintptr_t)TEXT_START_ADDR;231232if (process_read_data(ph, ehdr_addr, (char *)&ehdr, sizeof(ehdr)) != true) {233print_debug("process_read_data failed for ehdr_addr %p\n", ehdr_addr);234return (0);235}236237if (!IS_ELF(ehdr) ||238ehdr.e_ident[EI_CLASS] != ELF_TARG_CLASS ||239ehdr.e_ident[EI_DATA] != ELF_TARG_DATA ||240ehdr.e_ident[EI_VERSION] != EV_CURRENT ||241ehdr.e_phentsize != sizeof(ELF_PHDR) ||242ehdr.e_version != ELF_TARG_VER ||243ehdr.e_machine != ELF_TARG_MACH) {244print_debug("not an ELF_EHDR at %p\n", ehdr_addr);245return (0);246}247248/* allocate space for all ELF_PHDR's and read */249250phdr_addr = ehdr_addr + ehdr.e_phoff;251hdrs_size = ehdr.e_phnum * sizeof(ELF_PHDR);252253if ((phdrs = malloc(hdrs_size)) == NULL)254return (0);255256if (process_read_data(ph, phdr_addr, (char *)phdrs, hdrs_size) != true) {257print_debug("process_read_data failed for phdr_addr %p\n", phdr_addr);258return (0);259}260261/* find PT_DYNAMIC section */262263for (i = 0, phdr = phdrs; i < ehdr.e_phnum; i++, phdr++) {264if (phdr->p_type == PT_DYNAMIC)265break;266}267268if (i >= ehdr.e_phnum) {269print_debug("PT_DYNAMIC section not found!\n");270free(phdrs);271return (0);272}273274/* allocate space and read in ELF_DYN headers */275276dyn_addr = phdr->p_vaddr;277hdrs_size = phdr->p_memsz;278free(phdrs);279280if ((dyns = malloc(hdrs_size)) == NULL)281return (0);282283if (process_read_data(ph, dyn_addr, (char *)dyns, hdrs_size) != true) {284print_debug("process_read_data failed for dyn_addr %p\n", dyn_addr);285free(dyns);286return (0);287}288289/* find DT_DEBUG */290291dyn = dyns;292while (dyn->d_tag != DT_DEBUG && dyn->d_tag != DT_NULL) {293dyn++;294}295296if (dyn->d_tag != DT_DEBUG) {297print_debug("failed to find DT_DEBUG\n");298free(dyns);299return (0);300}301302/* read struct r_debug into dmap */303304dmap_addr = (uintptr_t)dyn->d_un.d_ptr;305free(dyns);306307if (process_read_data(ph, dmap_addr, (char *)&dmap, sizeof(dmap)) != true) {308print_debug("process_read_data failed for dmap_addr %p\n", dmap_addr);309return (0);310}311312lmap_addr = (uintptr_t)dmap.r_map;313314return (lmap_addr);315}316#endif // __FreeBSD__ && __FreeBSD_version < 701000317318static bool read_lib_info(struct ps_prochandle* ph) {319#if defined(__FreeBSD__) && __FreeBSD_version >= 701000320struct kinfo_vmentry *freep, *kve;321int i, cnt;322323freep = kinfo_getvmmap(ph->pid, &cnt);324if (freep == NULL) {325print_debug("can't get vm map for pid\n", ph->pid);326return false;327}328329for (i = 0; i < cnt; i++) {330kve = &freep[i];331if ((kve->kve_flags & KVME_FLAG_COW) &&332kve->kve_path != NULL &&333strlen(kve->kve_path) > 0) {334335if (find_lib(ph, kve->kve_path) == false) {336lib_info* lib;337if ((lib = add_lib_info(ph, kve->kve_path,338(uintptr_t) kve->kve_start)) == NULL)339continue; // ignore, add_lib_info prints error340341// we don't need to keep the library open, symtab is already342// built. Only for core dump we need to keep the fd open.343close(lib->fd);344lib->fd = -1;345}346}347}348349free(freep);350351return true;352#else353char *l_name;354struct link_map *lmap;355uintptr_t lmap_addr;356357if ((l_name = malloc(BUF_SIZE)) == NULL)358return false;359360if ((lmap = malloc(sizeof(*lmap))) == NULL) {361free(l_name);362return false;363}364365lmap_addr = linkmap_addr(ph);366367if (lmap_addr == 0) {368free(l_name);369free(lmap);370return false;371}372373do {374if (process_read_data(ph, lmap_addr, (char *)lmap, sizeof(*lmap)) != true) {375print_debug("process_read_data failed for lmap_addr %p\n", lmap_addr);376free (l_name);377free (lmap);378return false;379}380381if (process_read_data(ph, (uintptr_t)lmap->l_name, l_name,382BUF_SIZE) != true) {383print_debug("process_read_data failed for lmap->l_name %p\n",384lmap->l_name);385free (l_name);386free (lmap);387return false;388}389390if (find_lib(ph, l_name) == false) {391lib_info* lib;392if ((lib = add_lib_info(ph, l_name,393(uintptr_t) lmap->l_addr)) == NULL)394continue; // ignore, add_lib_info prints error395396// we don't need to keep the library open, symtab is already397// built. Only for core dump we need to keep the fd open.398close(lib->fd);399lib->fd = -1;400}401lmap_addr = (uintptr_t)lmap->l_next;402} while (lmap->l_next != NULL);403404free (l_name);405free (lmap);406407return true;408#endif409}410411// detach a given pid412static bool ptrace_detach(pid_t pid) {413if (pid && ptrace(PT_DETACH, pid, (caddr_t)1, 0) < 0) {414print_debug("ptrace(PTRACE_DETACH, ..) failed for %d\n", pid);415return false;416} else {417return true;418}419}420421static void process_cleanup(struct ps_prochandle* ph) {422ptrace_detach(ph->pid);423}424425static ps_prochandle_ops process_ops = {426.release= process_cleanup,427.p_pread= process_read_data,428.p_pwrite= process_write_data,429.get_lwp_regs= process_get_lwp_regs,430.get_lwp_info= process_get_lwp_info431};432433// attach to the process. One and only one exposed stuff434struct ps_prochandle* Pgrab(pid_t pid) {435struct ps_prochandle* ph = NULL;436437if ( (ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle))) == NULL) {438print_debug("can't allocate memory for ps_prochandle\n");439return NULL;440}441442if (ptrace_attach(pid) != true) {443free(ph);444return NULL;445}446447// initialize ps_prochandle448ph->pid = pid;449450// initialize vtable451ph->ops = &process_ops;452453// read library info and symbol tables, must do this before attaching threads,454// as the symbols in the pthread library will be used to figure out455// the list of threads within the same process.456if (read_lib_info(ph) != true) {457ptrace_detach(pid);458free(ph);459return NULL;460}461462// read thread info463read_thread_info(ph, add_new_thread);464465return ph;466}467468469