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