1/*- 2 * Copyright (c) 2003-2008 Joseph Koshy 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD$"); 29 30#include <sys/types.h> 31#include <sys/cpuset.h> 32#include <sys/event.h> 33#include <sys/param.h> 34#include <sys/socket.h> 35#include <sys/stat.h> 36#include <sys/module.h> 37#include <sys/pmc.h> 38 39#include <assert.h> 40#include <ctype.h> 41#include <err.h> 42#include <errno.h> 43#include <fcntl.h> 44#include <limits.h> 45#include <netdb.h> 46#include <pmc.h> 47#include <pmclog.h> 48#include <signal.h> 49#include <stdio.h> 50#include <stdlib.h> 51#include <string.h> 52#include <strings.h> 53#include <sysexits.h> 54#include <unistd.h> 55 56#include "libpmcstat.h" 57 58/* 59 * Associate an AOUT image with a process. 60 */ 61 62void 63pmcstat_process_aout_exec(struct pmcstat_process *pp, 64 struct pmcstat_image *image, uintfptr_t entryaddr) 65{ 66 (void) pp; 67 (void) image; 68 (void) entryaddr; 69 /* TODO Implement a.out handling */ 70} 71 72/* 73 * Associate an ELF image with a process. 74 */ 75 76void 77pmcstat_process_elf_exec(struct pmcstat_process *pp, 78 struct pmcstat_image *image, uintfptr_t entryaddr, 79 struct pmcstat_args *args, struct pmc_plugins *plugins, 80 struct pmcstat_stats *pmcstat_stats) 81{ 82 uintmax_t libstart; 83 struct pmcstat_image *rtldimage; 84 85 assert(image->pi_type == PMCSTAT_IMAGE_ELF32 || 86 image->pi_type == PMCSTAT_IMAGE_ELF64); 87 88 /* Create a map entry for the base executable. */ 89 pmcstat_image_link(pp, image, image->pi_vaddr); 90 91 /* 92 * For dynamically linked executables we need to determine 93 * where the dynamic linker was mapped to for this process, 94 * Subsequent executable objects that are mapped in by the 95 * dynamic linker will be tracked by log events of type 96 * PMCLOG_TYPE_MAP_IN. 97 */ 98 99 if (image->pi_isdynamic) { 100 101 /* 102 * The runtime loader gets loaded just after the maximum 103 * possible heap address. Like so: 104 * 105 * [ TEXT DATA BSS HEAP -->*RTLD SHLIBS <--STACK] 106 * ^ ^ 107 * 0 VM_MAXUSER_ADDRESS 108 109 * 110 * The exact address where the loader gets mapped in 111 * will vary according to the size of the executable 112 * and the limits on the size of the process'es data 113 * segment at the time of exec(). The entry address 114 * recorded at process exec time corresponds to the 115 * 'start' address inside the dynamic linker. From 116 * this we can figure out the address where the 117 * runtime loader's file object had been mapped to. 118 */ 119 rtldimage = pmcstat_image_from_path(image->pi_dynlinkerpath, 120 0, args, plugins); 121 if (rtldimage == NULL) { 122 warnx("WARNING: Cannot find image for \"%s\".", 123 pmcstat_string_unintern(image->pi_dynlinkerpath)); 124 pmcstat_stats->ps_exec_errors++; 125 return; 126 } 127 128 if (rtldimage->pi_type == PMCSTAT_IMAGE_UNKNOWN) 129 pmcstat_image_get_elf_params(rtldimage, args); 130 131 if (rtldimage->pi_type != PMCSTAT_IMAGE_ELF32 && 132 rtldimage->pi_type != PMCSTAT_IMAGE_ELF64) { 133 warnx("WARNING: rtld not an ELF object \"%s\".", 134 pmcstat_string_unintern(image->pi_dynlinkerpath)); 135 return; 136 } 137 138 libstart = entryaddr - rtldimage->pi_entry; 139 pmcstat_image_link(pp, rtldimage, libstart); 140 } 141} 142 143/* 144 * Associate an image and a process. 145 */ 146 147void 148pmcstat_process_exec(struct pmcstat_process *pp, 149 pmcstat_interned_string path, uintfptr_t entryaddr, 150 struct pmcstat_args *args, struct pmc_plugins *plugins, 151 struct pmcstat_stats *pmcstat_stats) 152{ 153 struct pmcstat_image *image; 154 155 if ((image = pmcstat_image_from_path(path, 0, 156 args, plugins)) == NULL) { 157 pmcstat_stats->ps_exec_errors++; 158 return; 159 } 160 161 if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN) 162 pmcstat_image_determine_type(image, args); 163 164 assert(image->pi_type != PMCSTAT_IMAGE_UNKNOWN); 165 166 switch (image->pi_type) { 167 case PMCSTAT_IMAGE_ELF32: 168 case PMCSTAT_IMAGE_ELF64: 169 pmcstat_stats->ps_exec_elf++; 170 pmcstat_process_elf_exec(pp, image, entryaddr, 171 args, plugins, pmcstat_stats); 172 break; 173 174 case PMCSTAT_IMAGE_AOUT: 175 pmcstat_stats->ps_exec_aout++; 176 pmcstat_process_aout_exec(pp, image, entryaddr); 177 break; 178 179 case PMCSTAT_IMAGE_INDETERMINABLE: 180 pmcstat_stats->ps_exec_indeterminable++; 181 break; 182 183 default: 184 err(EX_SOFTWARE, 185 "ERROR: Unsupported executable type for \"%s\"", 186 pmcstat_string_unintern(path)); 187 } 188} 189 190/* 191 * Find the map entry associated with process 'p' at PC value 'pc'. 192 */ 193 194struct pmcstat_pcmap * 195pmcstat_process_find_map(struct pmcstat_process *p, uintfptr_t pc) 196{ 197 struct pmcstat_pcmap *ppm; 198 199 TAILQ_FOREACH(ppm, &p->pp_map, ppm_next) { 200 if (pc >= ppm->ppm_lowpc && pc < ppm->ppm_highpc) 201 return (ppm); 202 if (pc < ppm->ppm_lowpc) 203 return (NULL); 204 } 205 206 return (NULL); 207} 208 209/* 210 * Find the process descriptor corresponding to a PID. If 'allocate' 211 * is zero, we return a NULL if a pid descriptor could not be found or 212 * a process descriptor process. If 'allocate' is non-zero, then we 213 * will attempt to allocate a fresh process descriptor. Zombie 214 * process descriptors are only removed if a fresh allocation for the 215 * same PID is requested. 216 */ 217 218struct pmcstat_process * 219pmcstat_process_lookup(pid_t pid, int allocate) 220{ 221 uint32_t hash; 222 struct pmcstat_pcmap *ppm, *ppmtmp; 223 struct pmcstat_process *pp, *pptmp; 224 225 hash = (uint32_t) pid & PMCSTAT_HASH_MASK; /* simplicity wins */ 226 227 LIST_FOREACH_SAFE(pp, &pmcstat_process_hash[hash], pp_next, pptmp) 228 if (pp->pp_pid == pid) { 229 /* Found a descriptor, check and process zombies */ 230 if (allocate && pp->pp_isactive == 0) { 231 /* remove maps */ 232 TAILQ_FOREACH_SAFE(ppm, &pp->pp_map, ppm_next, 233 ppmtmp) { 234 TAILQ_REMOVE(&pp->pp_map, ppm, 235 ppm_next); 236 free(ppm); 237 } 238 /* remove process entry */ 239 LIST_REMOVE(pp, pp_next); 240 free(pp); 241 break; 242 } 243 return (pp); 244 } 245 246 if (!allocate) 247 return (NULL); 248 249 if ((pp = malloc(sizeof(*pp))) == NULL) 250 err(EX_OSERR, "ERROR: Cannot allocate pid descriptor"); 251 252 pp->pp_pid = pid; 253 pp->pp_isactive = 1; 254 255 TAILQ_INIT(&pp->pp_map); 256 257 LIST_INSERT_HEAD(&pmcstat_process_hash[hash], pp, pp_next); 258 return (pp); 259} 260 261void 262pmcstat_create_process(int *pmcstat_sockpair, struct pmcstat_args *args, 263 int pmcstat_kq) 264{ 265 char token; 266 pid_t pid; 267 struct kevent kev; 268 struct pmcstat_target *pt; 269 270 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pmcstat_sockpair) < 0) 271 err(EX_OSERR, "ERROR: cannot create socket pair"); 272 273 switch (pid = fork()) { 274 case -1: 275 err(EX_OSERR, "ERROR: cannot fork"); 276 /*NOTREACHED*/ 277 278 case 0: /* child */ 279 (void) close(pmcstat_sockpair[PARENTSOCKET]); 280 281 /* Write a token to tell our parent we've started executing. */ 282 if (write(pmcstat_sockpair[CHILDSOCKET], "+", 1) != 1) 283 err(EX_OSERR, "ERROR (child): cannot write token"); 284 285 /* Wait for our parent to signal us to start. */ 286 if (read(pmcstat_sockpair[CHILDSOCKET], &token, 1) < 0) 287 err(EX_OSERR, "ERROR (child): cannot read token"); 288 (void) close(pmcstat_sockpair[CHILDSOCKET]); 289 290 /* exec() the program requested */ 291 execvp(*args->pa_argv, args->pa_argv); 292 /* and if that fails, notify the parent */ 293 kill(getppid(), SIGCHLD); 294 err(EX_OSERR, "ERROR: execvp \"%s\" failed", *args->pa_argv); 295 /*NOTREACHED*/ 296 297 default: /* parent */ 298 (void) close(pmcstat_sockpair[CHILDSOCKET]); 299 break; 300 } 301 302 /* Ask to be notified via a kevent when the target process exits. */ 303 EV_SET(&kev, pid, EVFILT_PROC, EV_ADD | EV_ONESHOT, NOTE_EXIT, 0, 304 NULL); 305 if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0) 306 err(EX_OSERR, "ERROR: cannot monitor child process %d", pid); 307 308 if ((pt = malloc(sizeof(*pt))) == NULL) 309 errx(EX_SOFTWARE, "ERROR: Out of memory."); 310 311 pt->pt_pid = pid; 312 SLIST_INSERT_HEAD(&args->pa_targets, pt, pt_next); 313 314 /* Wait for the child to signal that its ready to go. */ 315 if (read(pmcstat_sockpair[PARENTSOCKET], &token, 1) < 0) 316 err(EX_OSERR, "ERROR (parent): cannot read token"); 317 318 return; 319} 320 321/* 322 * Do process profiling 323 * 324 * If a pid was specified, attach each allocated PMC to the target 325 * process. Otherwise, fork a child and attach the PMCs to the child, 326 * and have the child exec() the target program. 327 */ 328 329void 330pmcstat_start_process(int *pmcstat_sockpair) 331{ 332 /* Signal the child to proceed. */ 333 if (write(pmcstat_sockpair[PARENTSOCKET], "!", 1) != 1) 334 err(EX_OSERR, "ERROR (parent): write of token failed"); 335 336 (void) close(pmcstat_sockpair[PARENTSOCKET]); 337} 338 339void 340pmcstat_attach_pmcs(struct pmcstat_args *args) 341{ 342 struct pmcstat_ev *ev; 343 struct pmcstat_target *pt; 344 int count; 345 346 /* Attach all process PMCs to target processes. */ 347 count = 0; 348 STAILQ_FOREACH(ev, &args->pa_events, ev_next) { 349 if (PMC_IS_SYSTEM_MODE(ev->ev_mode)) 350 continue; 351 SLIST_FOREACH(pt, &args->pa_targets, pt_next) { 352 if (pmc_attach(ev->ev_pmcid, pt->pt_pid) == 0) 353 count++; 354 else if (errno != ESRCH) 355 err(EX_OSERR, 356"ERROR: cannot attach pmc \"%s\" to process %d", 357 ev->ev_name, (int)pt->pt_pid); 358 } 359 } 360 361 if (count == 0) 362 errx(EX_DATAERR, "ERROR: No processes were attached to."); 363} 364