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