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 62 void 63 pmcstat_process_aout_exec(struct pmcstat_process *pp, 64 struct pmcstat_image *image, uintptr_t baseaddr) 65 { 66 (void) pp; 67 (void) image; 68 (void) baseaddr; 69 /* TODO Implement a.out handling */ 70 } 71 72 /* 73 * Associate an ELF image with a process. 74 */ 75 76 void 77 pmcstat_process_elf_exec(struct pmcstat_process *pp, 78 struct pmcstat_image *image, uintptr_t baseaddr, uintptr_t dynaddr, 79 struct pmcstat_args *args, struct pmc_plugins *plugins, 80 struct pmcstat_stats *pmcstat_stats) 81 { 82 struct pmcstat_image *rtldimage; 83 84 assert(image->pi_type == PMCSTAT_IMAGE_ELF32 || 85 image->pi_type == PMCSTAT_IMAGE_ELF64); 86 87 /* 88 * The exact address where the executable gets mapped in will vary for 89 * PIEs. The dynamic address recorded at process exec time corresponds 90 * to the address where the executable's file object had been mapped to. 91 */ 92 pmcstat_image_link(pp, image, image->pi_vaddr + dynaddr); 93 94 /* 95 * For dynamically linked executables we need to determine 96 * where the dynamic linker was mapped to for this process, 97 * Subsequent executable objects that are mapped in by the 98 * dynamic linker will be tracked by log events of type 99 * PMCLOG_TYPE_MAP_IN. 100 */ 101 102 if (image->pi_isdynamic) { 103 104 /* 105 * The runtime loader gets loaded just after the maximum 106 * possible heap address. Like so: 107 * 108 * [ TEXT DATA BSS HEAP -->*RTLD SHLIBS <--STACK] 109 * ^ ^ 110 * 0 VM_MAXUSER_ADDRESS 111 * 112 * The exact address where the loader gets mapped in 113 * will vary according to the size of the executable 114 * and the limits on the size of the process'es data 115 * segment at the time of exec(). The base address 116 * recorded at process exec time corresponds to the 117 * address where the runtime loader's file object had 118 * been mapped to. 119 */ 120 rtldimage = pmcstat_image_from_path(image->pi_dynlinkerpath, 121 0, args, plugins); 122 if (rtldimage == NULL) { 123 warnx("WARNING: Cannot find image for \"%s\".", 124 pmcstat_string_unintern(image->pi_dynlinkerpath)); 125 pmcstat_stats->ps_exec_errors++; 126 return; 127 } 128 129 if (rtldimage->pi_type == PMCSTAT_IMAGE_UNKNOWN) 130 pmcstat_image_get_elf_params(rtldimage, args); 131 132 if (rtldimage->pi_type != PMCSTAT_IMAGE_ELF32 && 133 rtldimage->pi_type != PMCSTAT_IMAGE_ELF64) { 134 warnx("WARNING: rtld not an ELF object \"%s\".", 135 pmcstat_string_unintern(image->pi_dynlinkerpath)); 136 return; 137 } 138 139 pmcstat_image_link(pp, rtldimage, baseaddr); 140 } 141 } 142 143 /* 144 * Associate an image and a process. 145 */ 146 147 void 148 pmcstat_process_exec(struct pmcstat_process *pp, 149 pmcstat_interned_string path, uintptr_t baseaddr, uintptr_t dynaddr, 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, baseaddr, dynaddr, 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, baseaddr); 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 194 struct pmcstat_pcmap * 195 pmcstat_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 218 struct pmcstat_process * 219 pmcstat_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 261 void 262 pmcstat_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 329 void 330 pmcstat_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 339 void 340 pmcstat_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