strace.c revision 05f325199a6cf36c92560d5a08b56652502705c2
176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/* 276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> 376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> 476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> 54dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl> 676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * All rights reserved. 776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Redistribution and use in source and binary forms, with or without 976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * modification, are permitted provided that the following conditions 1076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * are met: 1176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 1. Redistributions of source code must retain the above copyright 1276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * notice, this list of conditions and the following disclaimer. 1376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 2. Redistributions in binary form must reproduce the above copyright 1476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * notice, this list of conditions and the following disclaimer in the 1576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * documentation and/or other materials provided with the distribution. 1676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 3. The name of the author may not be used to endorse or promote products 1776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * derived from this software without specific prior written permission. 1876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 1976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 3076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 3176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include "defs.h" 323454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko#include <stdarg.h> 3376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h> 3476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h> 3576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/resource.h> 3676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/wait.h> 3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stat.h> 3876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h> 3976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h> 4070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath#include <dirent.h> 41f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko#include <sys/utsname.h> 428470374cba7df0e70653d95c4f336a4082c68d82Denys Vlasenko#if defined(IA64) 437b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h> 447b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif 45a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko/* In some libc, these aren't declared. Do it ourself: */ 4696d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkoextern char **environ; 47418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern int optind; 48418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern char *optarg; 4996d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko 50a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko 51a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko#if defined __NR_tkill 52a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig)) 53a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko#else 54a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko /* kill() may choose arbitrarily the target task of the process group 55a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko while we later wait on a that specific TID. PID process waits become 56a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko TID task specific waits for a process under ptrace(2). */ 57978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko# warning "tkill(2) not available, risk of strace hangs!" 58a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko# define my_tkill(tid, sig) kill((tid), (sig)) 59a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko#endif 60a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko 615c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko/* Glue for systems without a MMU that cannot provide fork() */ 625c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#if !defined(HAVE_FORK) 635c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko# undef NOMMU_SYSTEM 645c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko# define NOMMU_SYSTEM 1 655c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#endif 665c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#if NOMMU_SYSTEM 675c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko# define fork() vfork() 685c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#endif 695c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko 70a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkocflag_t cflag = CFLAG_NONE; 71a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkounsigned int followfork = 0; 72f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenkounsigned int ptrace_setoptions = 0; 73a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkounsigned int xflag = 0; 748d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenkobool need_fork_exec_workarounds = 0; 75a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool debug_flag = 0; 76a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool Tflag = 0; 77a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool qflag = 0; 783454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/* Which WSTOPSIG(status) value marks syscall traps? */ 7975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic unsigned int syscall_trap_sig = SIGTRAP; 80a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic unsigned int tflag = 0; 81a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic bool iflag = 0; 82a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic bool rflag = 0; 83a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic bool print_pid_pfx = 0; 84b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko 85b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko/* -I n */ 86b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenkoenum { 87b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko INTR_NOT_SET = 0, 88b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko INTR_ANYWHERE = 1, /* don't block/ignore any signals */ 89b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko INTR_WHILE_WAIT = 2, /* block fatal signals while decoding syscall. default */ 90b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko INTR_NEVER = 3, /* block fatal signals. default if '-o FILE PROG' */ 91b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko INTR_BLOCK_TSTP_TOO = 4, /* block fatal signals and SIGTSTP (^Z) */ 92b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko NUM_INTR_OPTS 93b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko}; 94b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenkostatic int opt_intr; 95b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko/* We play with signal mask only if this mode is active: */ 96b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko#define interactive (opt_intr == INTR_WHILE_WAIT) 97b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko 98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/* 99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option. 100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice. 101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's, 102ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process 103ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild 104ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID. 105ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases 106ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals, 107ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between, 108ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link. 109ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 110ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0; 11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1125c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#if USE_SEIZE 11331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP; 11431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define use_seize (post_attach_sigstop == 0) 11531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#else 11631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP 11731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define use_seize 0 11831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif 11931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko 12017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */ 121a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool not_failing_only = 0; 12217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig 1238a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* Show path associated with fd arguments */ 124a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool show_fd_path = 0; 1258a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards 1268a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* are we filtering traces based on paths? */ 127a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool tracing_paths = 0; 1288a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards 12961e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenkostatic bool detach_on_execve = 0; 13061e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenkostatic bool skip_startup_execve = 0; 13161e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko 132a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0; 133a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0; 13475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic int strace_tracer_pid = 0; 135eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath 136b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL; 137ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic uid_t run_uid; 138ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic gid_t run_gid; 13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 140a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkounsigned int max_strlen = DEFAULT_STRLEN; 141ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levinstatic int acolumn = DEFAULT_ACOLUMN; 142102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenkostatic char *acolumn_spaces; 1436764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko 144b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL; 1456764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko/* If -ff, points to stderr. Else, it's our common output log */ 1466764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenkostatic FILE *shared_log; 1476764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko 148000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenkostruct tcb *printing_tcp = NULL; 1496764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenkostatic struct tcb *current_tcp; 1506764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko 151ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic struct tcb **tcbtab; 1522b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic unsigned int nprocs, tcbtabsize; 153ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic const char *progname; 15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 155eec8d5d6b028665a73169fda96e4e873cb8351f0Denys Vlasenkounsigned os_release; /* generated from uname()'s u.release */ 156f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko 1574c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenkostatic int detach(struct tcb *tcp); 158e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int trace(void); 159e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void cleanup(void); 160e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void interrupt(int sig); 16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set; 16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T 16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted; 165a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko#else 16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted; 167a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko#endif 16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1692c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko#ifndef HAVE_STRERROR 1702c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko 1712c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko#if !HAVE_DECL_SYS_ERRLIST 1722c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenkoextern int sys_nerr; 1732c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenkoextern char *sys_errlist[]; 174a6d91ded3f2d5401e09a9c2fa442aabfbfe593a8Denys Vlasenko#endif 1752c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko 1762c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenkoconst char * 1772c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenkostrerror(int err_no) 1782c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko{ 1792c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko static char buf[sizeof("Unknown error %d") + sizeof(int)*3]; 1802c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko 1812c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko if (err_no < 1 || err_no >= sys_nerr) { 1822c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko sprintf(buf, "Unknown error %d", err_no); 1832c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko return buf; 1842c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko } 1852c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko return sys_errlist[err_no]; 1862c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko} 1872c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko 1882c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko#endif /* HAVE_STERRROR */ 1892c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko 19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 191cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenkousage(FILE *ofp, int exitval) 19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(ofp, "\ 194c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenkousage: strace [-CdffhiqrtttTvVxxy] [-I n] [-e expr]...\n\ 195c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko [-a column] [-o file] [-s strsize] [-P path]...\n\ 196c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]\n\ 197c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko or: strace -c[df] [-I n] [-e expr]... [-O overhead] [-S sortby]\n\ 198c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]\n\ 19976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\ 200c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko-C -- like -c but also print regular output\n\ 2013e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko-d -- enable debug output to stderr\n\ 202b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\ 20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\ 20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\ 20576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\ 20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\ 207cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-T -- print time spent in each syscall\n\ 208cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\ 20976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\ 2108a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-y -- print paths associated with file descriptor arguments\n\ 211c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko-h -- print help message, -V -- print version\n\ 21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\ 21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\ 21438e79bbb25bca8b79ae2866b93c4ddf26dea2b13Denys Vlasenko options: trace, abbrev, verbose, raw, signal, read, write\n\ 215c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko-I interruptible --\n\ 216c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko 1: no signals are blocked\n\ 217c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko 2: fatal signals are blocked while decoding syscall (default)\n\ 218c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko 3: fatal signals are always blocked (default if '-o FILE PROG')\n\ 219c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko 4: fatal signals and SIGTSTP (^Z) are always blocked\n\ 220c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\ 22176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\ 22276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\ 22376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\ 22476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\ 22576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\ 22676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\ 227de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\ 228de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\ 2298a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-P path -- trace accesses to path\n\ 23061e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko" 23138e79bbb25bca8b79ae2866b93c4ddf26dea2b13Denys Vlasenko/* ancient, no one should use it 23238e79bbb25bca8b79ae2866b93c4ddf26dea2b13Denys Vlasenko-F -- attempt to follow vforks (deprecated, use -f)\n\ 23338e79bbb25bca8b79ae2866b93c4ddf26dea2b13Denys Vlasenko */ 23461e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko/* this is broken, so don't document it 23517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\ 23661e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko */ 23761e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko/* experimental, don't document it yet (option letter may change in the future!) 23861e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko-b -- detach on successful execve\n\ 23961e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko */ 240de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY); 24176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(exitval); 24276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 24376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 24475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void) __attribute__ ((noreturn)); 24575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void) 24675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{ 24775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko if (strace_tracer_pid == getpid()) { 24875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko cflag = 0; 24975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko cleanup(); 25075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko } 25175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko exit(1); 25275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko} 25375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko 25475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void verror_msg(int err_no, const char *fmt, va_list p) 2553454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{ 25682bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko char *msg; 25782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko 25844d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin fflush(NULL); 25982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko 26082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko /* We want to print entire message with single fprintf to ensure 26182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko * message integrity if stderr is shared with other programs. 26282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko * Thus we use vasprintf + single fprintf. 26382bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko */ 26482bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko msg = NULL; 265cfad543087d98c5313fd7f006c0de69a1d87dc8eDenys Vlasenko if (vasprintf(&msg, fmt, p) >= 0) { 26682bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko if (err_no) 26782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no)); 26882bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko else 26982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko fprintf(stderr, "%s: %s\n", progname, msg); 27082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko free(msg); 27182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko } else { 27282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko /* malloc in vasprintf failed, try it without malloc */ 27382bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko fprintf(stderr, "%s: ", progname); 27482bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko vfprintf(stderr, fmt, p); 27582bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko if (err_no) 27682bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko fprintf(stderr, ": %s\n", strerror(err_no)); 27782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko else 27882bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko putc('\n', stderr); 27982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko } 28082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko /* We don't switch stderr to buffered, thus fprintf(stderr) 28182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko * always flushes its output and this is not necessary: */ 28282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko /* fflush(stderr); */ 28375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko} 28475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko 28575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg(const char *fmt, ...) 28675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{ 28775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_list p; 28875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_start(p, fmt); 28975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko verror_msg(0, fmt, p); 2903454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko va_end(p); 29175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko} 2923454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 29375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg_and_die(const char *fmt, ...) 29475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{ 29575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_list p; 29675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_start(p, fmt); 29775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko verror_msg(0, fmt, p); 29875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko die(); 29975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko} 30075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko 30175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg(const char *fmt, ...) 30275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{ 30375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_list p; 30475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_start(p, fmt); 30575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko verror_msg(errno, fmt, p); 30675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_end(p); 30775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko} 30875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko 30975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg_and_die(const char *fmt, ...) 31075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{ 31175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_list p; 31275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_start(p, fmt); 31375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko verror_msg(errno, fmt, p); 31475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko die(); 3153454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko} 3163454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 3171d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenkovoid die_out_of_memory(void) 3181d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko{ 3191d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko static bool recursed = 0; 3201d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko if (recursed) 3211d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko exit(1); 3221d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko recursed = 1; 3231d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko error_msg_and_die("Out of memory"); 3241d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko} 3251d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko 326ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levinstatic void 327ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levinerror_opt_arg(int opt, const char *arg) 328ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin{ 329ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin error_msg_and_die("Invalid -%c argument: '%s'", opt, arg); 330ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin} 331ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin 3325c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#if USE_SEIZE 33331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic int 33431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkoptrace_attach_or_seize(int pid) 33531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko{ 33631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko int r; 33731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (!use_seize) 33831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko return ptrace(PTRACE_ATTACH, pid, 0, 0); 33926bc0606d96d05d30ba263939a0451889340a64cDenys Vlasenko r = ptrace(PTRACE_SEIZE, pid, 0, 0); 34031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (r) 34131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko return r; 34231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko r = ptrace(PTRACE_INTERRUPT, pid, 0, 0); 34331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko return r; 34431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko} 34531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#else 34631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0) 34731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif 34831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko 349852f98a3824f6b8359df744af5772306410341abDenys Vlasenko/* 350852f98a3824f6b8359df744af5772306410341abDenys Vlasenko * Used when we want to unblock stopped traced process. 351852f98a3824f6b8359df744af5772306410341abDenys Vlasenko * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL. 352852f98a3824f6b8359df744af5772306410341abDenys Vlasenko * Returns 0 on success or if error was ESRCH 353852f98a3824f6b8359df744af5772306410341abDenys Vlasenko * (presumably process was killed while we talk to it). 354852f98a3824f6b8359df744af5772306410341abDenys Vlasenko * Otherwise prints error message and returns -1. 355852f98a3824f6b8359df744af5772306410341abDenys Vlasenko */ 356852f98a3824f6b8359df744af5772306410341abDenys Vlasenkostatic int 357852f98a3824f6b8359df744af5772306410341abDenys Vlasenkoptrace_restart(int op, struct tcb *tcp, int sig) 358852f98a3824f6b8359df744af5772306410341abDenys Vlasenko{ 359852f98a3824f6b8359df744af5772306410341abDenys Vlasenko int err; 360852f98a3824f6b8359df744af5772306410341abDenys Vlasenko const char *msg; 361852f98a3824f6b8359df744af5772306410341abDenys Vlasenko 362852f98a3824f6b8359df744af5772306410341abDenys Vlasenko errno = 0; 363852f98a3824f6b8359df744af5772306410341abDenys Vlasenko ptrace(op, tcp->pid, (void *) 0, (long) sig); 364852f98a3824f6b8359df744af5772306410341abDenys Vlasenko err = errno; 365235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko if (!err) 366852f98a3824f6b8359df744af5772306410341abDenys Vlasenko return 0; 367852f98a3824f6b8359df744af5772306410341abDenys Vlasenko 368852f98a3824f6b8359df744af5772306410341abDenys Vlasenko msg = "SYSCALL"; 369852f98a3824f6b8359df744af5772306410341abDenys Vlasenko if (op == PTRACE_CONT) 370852f98a3824f6b8359df744af5772306410341abDenys Vlasenko msg = "CONT"; 371852f98a3824f6b8359df744af5772306410341abDenys Vlasenko if (op == PTRACE_DETACH) 372852f98a3824f6b8359df744af5772306410341abDenys Vlasenko msg = "DETACH"; 373852f98a3824f6b8359df744af5772306410341abDenys Vlasenko#ifdef PTRACE_LISTEN 374852f98a3824f6b8359df744af5772306410341abDenys Vlasenko if (op == PTRACE_LISTEN) 375852f98a3824f6b8359df744af5772306410341abDenys Vlasenko msg = "LISTEN"; 376852f98a3824f6b8359df744af5772306410341abDenys Vlasenko#endif 377235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko /* 378235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko * Why curcol != 0? Otherwise sometimes we get this: 379235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko * 380235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko * 10252 kill(10253, SIGKILL) = 0 381235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko * <ptrace(SYSCALL,10252):No such process>10253 ...next decode... 382235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko * 383235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko * 10252 died after we retrieved syscall exit data, 384235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko * but before we tried to restart it. Log looks ugly. 385235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko */ 3866764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko if (current_tcp && current_tcp->curcol != 0) { 387235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko tprintf(" <ptrace(%s):%s>\n", msg, strerror(err)); 388235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko line_ended(); 389235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko } 390235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko if (err == ESRCH) 391235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko return 0; 392235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko errno = err; 393852f98a3824f6b8359df744af5772306410341abDenys Vlasenko perror_msg("ptrace(PTRACE_%s,pid:%d,sig:%d)", msg, tcp->pid, sig); 394852f98a3824f6b8359df744af5772306410341abDenys Vlasenko return -1; 395852f98a3824f6b8359df744af5772306410341abDenys Vlasenko} 396852f98a3824f6b8359df744af5772306410341abDenys Vlasenko 3971f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenkostatic void 39810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd) 39910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 4001f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko int flags, newflags; 4011f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko 4021f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko flags = fcntl(fd, F_GETFD); 4031f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko if (flags < 0) { 4041f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko /* Can happen only if fd is bad. 4051f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko * Should never happen: if it does, we have a bug 4061f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko * in the caller. Therefore we just abort 4071f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko * instead of propagating the error. 4081f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko */ 4091f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko perror_msg_and_die("fcntl(%d, F_GETFD)", fd); 41010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 41110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 41210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin newflags = flags | FD_CLOEXEC; 41310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (flags == newflags) 4141f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko return; 41510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 4161f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko fcntl(fd, F_SETFD, newflags); /* never fails */ 41710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 41810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 41975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenkostatic void kill_save_errno(pid_t pid, int sig) 42075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko{ 42175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko int saved_errno = errno; 42275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko 42375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko (void) kill(pid, sig); 42475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko errno = saved_errno; 42575fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko} 42675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko 427800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko/* 428800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * When strace is setuid executable, we have to swap uids 429800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * before and after filesystem and process management operations. 430800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko */ 431800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic void 432800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkoswap_uid(void) 433800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko{ 434800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko int euid = geteuid(), uid = getuid(); 435800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 436800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (euid != uid && setreuid(euid, uid) < 0) { 437800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko perror_msg_and_die("setreuid"); 438800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 439800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko} 440800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 441800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#if _LFS64_LARGEFILE 442800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko# define fopen_for_output fopen64 443800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#else 444800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko# define fopen_for_output fopen 445800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#endif 446800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 447800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic FILE * 448800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostrace_fopen(const char *path) 449800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko{ 450800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko FILE *fp; 451800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 452800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko swap_uid(); 453800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko fp = fopen_for_output(path, "w"); 454800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (!fp) 455800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko perror_msg_and_die("Can't fopen '%s'", path); 456800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko swap_uid(); 457800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko set_cloexec_flag(fileno(fp)); 458800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko return fp; 459800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko} 460800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 461800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic int popen_pid = 0; 462800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 463800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#ifndef _PATH_BSHELL 464800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko# define _PATH_BSHELL "/bin/sh" 465800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#endif 466800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 467800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko/* 468800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * We cannot use standard popen(3) here because we have to distinguish 469800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * popen child process from other processes we trace, and standard popen(3) 470800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * does not export its child's pid. 471800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko */ 472800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic FILE * 473800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostrace_popen(const char *command) 474800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko{ 475800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko FILE *fp; 476800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko int fds[2]; 477800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 478800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko swap_uid(); 479800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (pipe(fds) < 0) 480800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko perror_msg_and_die("pipe"); 481800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 482800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko set_cloexec_flag(fds[1]); /* never fails */ 483800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 484800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko popen_pid = vfork(); 485800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (popen_pid == -1) 486800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko perror_msg_and_die("vfork"); 487800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 488800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (popen_pid == 0) { 489800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko /* child */ 490800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko close(fds[1]); 491800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (fds[0] != 0) { 492800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (dup2(fds[0], 0)) 493800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko perror_msg_and_die("dup2"); 494800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko close(fds[0]); 495800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 496800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko execl(_PATH_BSHELL, "sh", "-c", command, NULL); 497800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL); 498800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 499800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 500800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko /* parent */ 501800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko close(fds[0]); 502800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko swap_uid(); 503800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko fp = fdopen(fds[1], "w"); 504800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (!fp) 505800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko die_out_of_memory(); 506800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko return fp; 507800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko} 508800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 5092e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid 5102e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkotprintf(const char *fmt, ...) 5112e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{ 5122e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko va_list args; 5132e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko 5142e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko va_start(args, fmt); 5156764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko if (current_tcp) { 5166e4f3c1fa41851cb72230432db4be8e0c2993c7dDenys Vlasenko int n = strace_vfprintf(current_tcp->outf, fmt, args); 5172e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko if (n < 0) { 5186764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko if (current_tcp->outf != stderr) 5199a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin perror_msg("%s", outfname); 5202e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko } else 5216764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko current_tcp->curcol += n; 5222e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko } 5232e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko va_end(args); 5242e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko} 5252e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko 5262e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid 5272e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkotprints(const char *str) 5282e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{ 5296764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko if (current_tcp) { 530142aee0a593ea9b42aa98347d998176b8a4e2489Denys Vlasenko int n = fputs_unlocked(str, current_tcp->outf); 5312e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko if (n >= 0) { 5326764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko current_tcp->curcol += strlen(str); 5332e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko return; 5342e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko } 5356764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko if (current_tcp->outf != stderr) 5369a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin perror_msg("%s", outfname); 5372e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko } 5382e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko} 5392e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko 5402e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid 5417de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenkoline_ended(void) 5427de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko{ 5436764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko if (current_tcp) { 5446764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko current_tcp->curcol = 0; 5456764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko fflush(current_tcp->outf); 5466764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko } 5476764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko if (printing_tcp) { 5486764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko printing_tcp->curcol = 0; 5496764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko printing_tcp = NULL; 5506764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko } 5517de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko} 5527de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko 5537de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenkovoid 5542e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkoprintleader(struct tcb *tcp) 5552e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{ 5567de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko /* If -ff, "previous tcb we printed" is always the same as current, 5577de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko * because we have per-tcb output files. 5587de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko */ 5597de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko if (followfork >= 2) 5607de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko printing_tcp = tcp; 5617de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko 5622e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko if (printing_tcp) { 5636764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko current_tcp = printing_tcp; 5647de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko if (printing_tcp->curcol != 0 && (followfork < 2 || printing_tcp == tcp)) { 5657de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko /* 5667de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko * case 1: we have a shared log (i.e. not -ff), and last line 5677de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko * wasn't finished (same or different tcb, doesn't matter). 5687de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko * case 2: split log, we are the same tcb, but our last line 5697de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko * didn't finish ("SIGKILL nuked us after syscall entry" etc). 5707de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko */ 5712e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko tprints(" <unfinished ...>\n"); 5727de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko printing_tcp->curcol = 0; 5732e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko } 5742e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko } 5752e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko 5762e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko printing_tcp = tcp; 5776764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko current_tcp = tcp; 5786764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko current_tcp->curcol = 0; 5792e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko 5802e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko if (print_pid_pfx) 5812e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko tprintf("%-5d ", tcp->pid); 5822e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko else if (nprocs > 1 && !outfname) 5832e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko tprintf("[pid %5u] ", tcp->pid); 5842e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko 5852e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko if (tflag) { 5862e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko char str[sizeof("HH:MM:SS")]; 5872e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko struct timeval tv, dtv; 5882e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko static struct timeval otv; 5892e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko 5902e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko gettimeofday(&tv, NULL); 5912e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko if (rflag) { 5922e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko if (otv.tv_sec == 0) 5932e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko otv = tv; 5942e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko tv_sub(&dtv, &tv, &otv); 5952e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko tprintf("%6ld.%06ld ", 5962e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko (long) dtv.tv_sec, (long) dtv.tv_usec); 5972e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko otv = tv; 5982e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko } 5992e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko else if (tflag > 2) { 6002e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko tprintf("%ld.%06ld ", 6012e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko (long) tv.tv_sec, (long) tv.tv_usec); 6022e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko } 6032e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko else { 6042e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko time_t local = tv.tv_sec; 6052e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko strftime(str, sizeof(str), "%T", localtime(&local)); 6062e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko if (tflag > 1) 6072e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko tprintf("%s.%06ld ", str, (long) tv.tv_usec); 6082e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko else 6092e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko tprintf("%s ", str); 6102e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko } 6112e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko } 6122e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko if (iflag) 6132e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko printcall(tcp); 6142e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko} 6152e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko 6162e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid 6172e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkotabto(void) 6182e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{ 6196764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko if (current_tcp->curcol < acolumn) 6206764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko tprints(acolumn_spaces + current_tcp->curcol); 6212e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko} 6222e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko 6233db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko/* Should be only called directly *after successful attach* to a tracee. 6243db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko * Otherwise, "strace -oFILE -ff -p<nonexistant_pid>" 6253db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko * may create bogus empty FILE.<nonexistant_pid>, and then die. 6263db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko */ 62710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void 628800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkonewoutf(struct tcb *tcp) 62910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 6306764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko tcp->outf = shared_log; /* if not -ff mode, the same file is for all */ 6313db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko if (followfork >= 2) { 632800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko char name[520 + sizeof(int) * 3]; 633800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko sprintf(name, "%.512s.%u", outfname, tcp->pid); 634800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko tcp->outf = strace_fopen(name); 63510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 63610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 63710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 638800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic void 639800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkoexpand_tcbtab(void) 640800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko{ 641800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko /* Allocate some more TCBs and expand the table. 642800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko We don't want to relocate the TCBs because our 643800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko callers have pointers and it would be a pain. 644800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko So tcbtab is a table of pointers. Since we never 645800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko free the TCBs, we allocate a single chunk of many. */ 646800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko int i = tcbtabsize; 647800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0])); 648800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0])); 649800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (!newtab || !newtcbs) 650800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko die_out_of_memory(); 651800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko tcbtabsize *= 2; 652800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko tcbtab = newtab; 653800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko while (i < tcbtabsize) 654800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko tcbtab[i++] = newtcbs++; 655800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko} 6564bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath 657800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic struct tcb * 6583db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenkoalloctcb(int pid) 65910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 660800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko int i; 661800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko struct tcb *tcp; 66210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 663800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (nprocs == tcbtabsize) 664800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko expand_tcbtab(); 665800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 666800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko for (i = 0; i < tcbtabsize; i++) { 667800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko tcp = tcbtab[i]; 668800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if ((tcp->flags & TCB_INUSE) == 0) { 669800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko memset(tcp, 0, sizeof(*tcp)); 670800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko tcp->pid = pid; 671800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko tcp->flags = TCB_INUSE; 672800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#if SUPPORTED_PERSONALITIES > 1 673800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko tcp->currpers = current_personality; 674800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#endif 675800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko nprocs++; 676800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (debug_flag) 677800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs); 678800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko return tcp; 679800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 680800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 6813db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko error_msg_and_die("bug in alloctcb"); 68210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 68310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 684800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic void 685800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkodroptcb(struct tcb *tcp) 686800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko{ 687800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (tcp->pid == 0) 688800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko return; 68910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 690800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko nprocs--; 691800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (debug_flag) 692800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs); 69310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 694800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (tcp->outf) { 6958511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko if (followfork >= 2) { 696800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (tcp->curcol != 0) 697800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko fprintf(tcp->outf, " <detached ...>\n"); 698800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko fclose(tcp->outf); 699800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } else { 700800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (printing_tcp == tcp && tcp->curcol != 0) 701800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko fprintf(tcp->outf, " <detached ...>\n"); 702800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko fflush(tcp->outf); 703800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 704800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 705800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 7066764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko if (current_tcp == tcp) 7076764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko current_tcp = NULL; 708800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (printing_tcp == tcp) 709800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko printing_tcp = NULL; 710800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 711800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko memset(tcp, 0, sizeof(*tcp)); 712800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko} 713800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 714800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko/* detach traced process; continue with sig 715800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * Never call DETACH twice on the same process as both unattached and 716800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * attached-unstopped processes give the same ESRCH. For unattached process we 717800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * would SIGSTOP it and wait for its SIGSTOP notification forever. 71810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */ 719800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic int 720800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkodetach(struct tcb *tcp) 72110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 722800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko int error; 723800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko int status, sigstop_expected; 72410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 725800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (tcp->flags & TCB_BPTSET) 726800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko clearbpt(tcp); 72710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 728800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko /* 729800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * Linux wrongly insists the child be stopped 730800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * before detaching. Arghh. We go through hoops 731800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * to make a clean break of things. 732800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko */ 733800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#if defined(SPARC) 734978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko# undef PTRACE_DETACH 735978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko# define PTRACE_DETACH PTRACE_SUNDETACH 736800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#endif 73710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 738800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko error = 0; 739800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko sigstop_expected = 0; 740800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (tcp->flags & TCB_ATTACHED) { 741800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko /* 742800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * We attached but possibly didn't see the expected SIGSTOP. 743800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * We must catch exactly one as otherwise the detached process 744800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * would be left stopped (process state T). 745800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko */ 746800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP); 747800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0); 748800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (error == 0) { 749800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko /* On a clear day, you can see forever. */ 750800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 751800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko else if (errno != ESRCH) { 752800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko /* Shouldn't happen. */ 7539a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin perror_msg("%s", "detach: ptrace(PTRACE_DETACH, ...)"); 754800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 755800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko else if (my_tkill(tcp->pid, 0) < 0) { 756800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (errno != ESRCH) 7579a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin perror_msg("%s", "detach: checking sanity"); 758800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 759800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) { 760800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (errno != ESRCH) 7619a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin perror_msg("%s", "detach: stopping child"); 762800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 763800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko else 764800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko sigstop_expected = 1; 765800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 76610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 767800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (sigstop_expected) { 768800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko for (;;) { 769800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#ifdef __WALL 770800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (waitpid(tcp->pid, &status, __WALL) < 0) { 771800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (errno == ECHILD) /* Already gone. */ 772800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko break; 773800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (errno != EINVAL) { 7749a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin perror_msg("%s", "detach: waiting"); 775800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko break; 776800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 777800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#endif /* __WALL */ 778800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko /* No __WALL here. */ 779800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (waitpid(tcp->pid, &status, 0) < 0) { 780800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (errno != ECHILD) { 7819a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin perror_msg("%s", "detach: waiting"); 782800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko break; 783800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 784800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#ifdef __WCLONE 785800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko /* If no processes, try clones. */ 786800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (waitpid(tcp->pid, &status, __WCLONE) < 0) { 787800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (errno != ECHILD) 7889a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin perror_msg("%s", "detach: waiting"); 789800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko break; 790800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 791800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#endif /* __WCLONE */ 792800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 793800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#ifdef __WALL 794800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 795800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#endif 796800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (!WIFSTOPPED(status)) { 797800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko /* Au revoir, mon ami. */ 798800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko break; 799800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 800800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (WSTOPSIG(status) == SIGSTOP) { 801800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko ptrace_restart(PTRACE_DETACH, tcp, 0); 802800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko break; 803800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko } 804800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko error = ptrace_restart(PTRACE_CONT, tcp, 805800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko WSTOPSIG(status) == syscall_trap_sig ? 0 806800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko : WSTOPSIG(status)); 807800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (error < 0) 808800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko break; 80910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 81010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 8117dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko 812800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko if (!qflag && (tcp->flags & TCB_ATTACHED)) 813800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko fprintf(stderr, "Process %u detached\n", tcp->pid); 81410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 815800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko droptcb(tcp); 816800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko 817800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko return error; 81810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 81910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 820558e5127fb68a7ab5c5ba6d8e976efd77e396cc2Denys Vlasenkostatic void 821558e5127fb68a7ab5c5ba6d8e976efd77e396cc2Denys Vlasenkoprocess_opt_p_list(char *opt) 822e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko{ 823e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko while (*opt) { 824e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko /* 825e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`". 826e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko * pidof uses space as delim, pgrep uses newline. :( 827e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko */ 828e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko int pid; 829e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko char *delim = opt + strcspn(opt, ", \n\t"); 830e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko char c = *delim; 831e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko 832e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko *delim = '\0'; 833ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin pid = string_to_uint(opt); 834e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko if (pid <= 0) { 835ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin error_msg_and_die("Invalid process id: '%s'", opt); 836e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko } 837e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko if (pid == strace_tracer_pid) { 838ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin error_msg_and_die("I'm sorry, I can't let you do that, Dave."); 839e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko } 840e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko *delim = c; 8413db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko alloctcb(pid); 842e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko if (c == '\0') 843e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko break; 844e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko opt = delim + 1; 845e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko } 846e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko} 847e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko 84802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void 84902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void) 85002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{ 85102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int tcbi; 85202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct tcb *tcp; 85302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 85402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 85502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Block user interruptions as we would leave the traced 85602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * process stopped (process state T) if we would terminate in 8572e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko * between PTRACE_ATTACH and wait4() on SIGSTOP. 858b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko * We rely on cleanup() from this point on. 85902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 86002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interactive) 86102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigprocmask(SIG_BLOCK, &blocked_set, NULL); 86202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 863ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (daemonized_tracer) { 864ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko pid_t pid = fork(); 865ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pid < 0) { 866014ca3a53cb24d8e12e87f43a880efc52940a8beDenys Vlasenko perror_msg_and_die("fork"); 867ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 868ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pid) { /* parent */ 869ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 87075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko * Wait for grandchild to attach to straced process 87175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko * (grandparent). Grandchild SIGKILLs us after it attached. 87275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko * Grandparent's wait() is unblocked by our death, 873ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * it proceeds to exec the straced program. 874ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 875ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko pause(); 876ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko _exit(0); /* paranoia */ 877ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 87875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko /* grandchild */ 87975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko /* We will be the tracer process. Remember our new pid: */ 88075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko strace_tracer_pid = getpid(); 881ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 882ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 88302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath for (tcbi = 0; tcbi < tcbtabsize; tcbi++) { 88402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp = tcbtab[tcbi]; 88544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko 88675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko if (!(tcp->flags & TCB_INUSE)) 88775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko continue; 88875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko 889d116a7338645af45090aecc331701e999148d284Denys Vlasenko /* Is this a process we should attach to, but not yet attached? */ 89075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko if (tcp->flags & TCB_ATTACHED) 89175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko continue; /* no, we already attached it */ 892d116a7338645af45090aecc331701e999148d284Denys Vlasenko 893ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (followfork && !daemonized_tracer) { 8947a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3]; 89502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath DIR *dir; 89602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 89702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sprintf(procdir, "/proc/%d/task", tcp->pid); 89802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath dir = opendir(procdir); 89902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (dir != NULL) { 90002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath unsigned int ntid = 0, nerr = 0; 90102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct dirent *de; 902381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko 90302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath while ((de = readdir(dir)) != NULL) { 904381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko struct tcb *cur_tcp; 905381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko int tid; 906381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko 9077a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko if (de->d_fileno == 0) 90802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 909ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin /* we trust /proc filesystem */ 91002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tid = atoi(de->d_name); 91102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (tid <= 0) 91202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 91302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ++ntid; 91431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (ptrace_attach_or_seize(tid) < 0) { 91502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ++nerr; 916a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko if (debug_flag) 917f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko fprintf(stderr, "attach to pid %d failed\n", tid); 918381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko continue; 919f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko } 920a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko if (debug_flag) 921381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko fprintf(stderr, "attach to pid %d succeeded\n", tid); 922381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko cur_tcp = tcp; 923381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko if (tid != tcp->pid) 924381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko cur_tcp = alloctcb(tid); 92531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop; 9263db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko newoutf(cur_tcp); 92702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 92802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath closedir(dir); 929381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko if (interactive) { 930381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko sigprocmask(SIG_SETMASK, &empty_set, NULL); 931381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko if (interrupted) 932381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko goto ret; 933381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko sigprocmask(SIG_BLOCK, &blocked_set, NULL); 934381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko } 9357a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko ntid -= nerr; 9367a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko if (ntid == 0) { 9379a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin perror_msg("%s", "attach: ptrace(PTRACE_ATTACH, ...)"); 93802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath droptcb(tcp); 93902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 94002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 94102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!qflag) { 9427a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko fprintf(stderr, ntid > 1 9433db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko? "Process %u attached with %u threads\n" 9443db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko: "Process %u attached\n", 94544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko tcp->pid, ntid); 94602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 94775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko if (!(tcp->flags & TCB_ATTACHED)) { 948f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko /* -p PID, we failed to attach to PID itself 949f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko * but did attach to some of its sibling threads. 950f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko * Drop PID's tcp. 951f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko */ 952f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko droptcb(tcp); 953f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko } 95402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 9557a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko } /* if (opendir worked) */ 9567a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko } /* if (-f) */ 95731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (ptrace_attach_or_seize(tcp->pid) < 0) { 9589a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin perror_msg("%s", "attach: ptrace(PTRACE_ATTACH, ...)"); 95902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath droptcb(tcp); 96002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 96102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 96275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop; 9633db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko newoutf(tcp); 964a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko if (debug_flag) 965f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid); 966ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 967ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (daemonized_tracer) { 968ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 969ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Make parent go away. 970ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Also makes grandparent's wait() unblock. 971ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 972ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko kill(getppid(), SIGKILL); 973ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 974ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 97502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!qflag) 97602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, 9779c3861d3177f3bfb12b24890fd118bcb77066abbDenys Vlasenko "Process %u attached\n", 97802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->pid); 979f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko } /* for each tcbtab[] */ 98002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 98144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko ret: 98202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interactive) 98302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigprocmask(SIG_SETMASK, &empty_set, NULL); 98402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath} 98502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 986f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko/* Stack-o-phobic exec helper, in the hope to work around 987f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * NOMMU + "daemonized tracer" difficulty. 988f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko */ 989f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenkostruct exec_params { 990f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko int fd_to_close; 991f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko uid_t run_euid; 992f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko gid_t run_egid; 993f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko char **argv; 994f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko char *pathname; 995f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko}; 996f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenkostatic struct exec_params params_for_tracee; 997f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenkostatic void __attribute__ ((noinline, noreturn)) 998f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenkoexec_or_die(void) 999f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko{ 1000f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko struct exec_params *params = ¶ms_for_tracee; 1001f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko 1002f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko if (params->fd_to_close >= 0) 1003f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko close(params->fd_to_close); 1004f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko if (!daemonized_tracer && !use_seize) { 1005f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) { 1006f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)"); 1007f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko } 1008f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko } 1009f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko 1010f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko if (username != NULL) { 1011f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko /* 1012f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * It is important to set groups before we 1013f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * lose privileges on setuid. 1014f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko */ 1015f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko if (initgroups(username, run_gid) < 0) { 1016f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko perror_msg_and_die("initgroups"); 1017f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko } 1018f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko if (setregid(run_gid, params->run_egid) < 0) { 1019f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko perror_msg_and_die("setregid"); 1020f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko } 1021f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko if (setreuid(run_uid, params->run_euid) < 0) { 1022f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko perror_msg_and_die("setreuid"); 1023f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko } 1024f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko } 1025f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko else if (geteuid() != 0) 1026f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko if (setreuid(run_uid, run_uid) < 0) { 1027f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko perror_msg_and_die("setreuid"); 1028f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko } 1029f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko 1030f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko if (!daemonized_tracer) { 1031f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko /* 1032f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * Induce a ptrace stop. Tracer (our parent) 1033f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * will resume us with PTRACE_SYSCALL and display 1034f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * the immediately following execve syscall. 1035f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * Can't do this on NOMMU systems, we are after 1036f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * vfork: parent is blocked, stopping would deadlock. 1037f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko */ 1038f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko if (!NOMMU_SYSTEM) 1039f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko kill(getpid(), SIGSTOP); 1040f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko } else { 1041f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko alarm(3); 1042f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko /* we depend on SIGCHLD set to SIG_DFL by init code */ 1043f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko /* if it happens to be SIG_IGN'ed, wait won't block */ 1044f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko wait(NULL); 1045f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko alarm(0); 1046f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko } 1047f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko 1048f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko execv(params->pathname, params->argv); 1049f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko perror_msg_and_die("exec"); 1050f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko} 1051f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko 105202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void 10531201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostartup_child(char **argv) 105402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{ 105502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct stat statbuf; 105602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath const char *filename; 105702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath char pathname[MAXPATHLEN]; 1058f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko int pid; 105902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct tcb *tcp; 106002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 106102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath filename = argv[0]; 106202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (strchr(filename, '/')) { 106302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (strlen(filename) > sizeof pathname - 1) { 106402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath errno = ENAMETOOLONG; 1065cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("exec"); 106602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 106702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname, filename); 106802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 106902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC 107002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 107102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Debuggers customarily check the current directory 107202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * first regardless of the path but doing that gives 107302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * security geeks a panic attack. 107402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 107502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (stat(filename, &statbuf) == 0) 107602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname, filename); 107702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */ 107802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else { 107930145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin const char *path; 108002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int m, n, len; 108102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 108202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath for (path = getenv("PATH"); path && *path; path += m) { 10834f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko const char *colon = strchr(path, ':'); 10844f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko if (colon) { 10854f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko n = colon - path; 108602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath m = n + 1; 108702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 108802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 108902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath m = n = strlen(path); 109002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (n == 0) { 109102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!getcwd(pathname, MAXPATHLEN)) 109202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 109302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath len = strlen(pathname); 109402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 109502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (n > sizeof pathname - 1) 109602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 109702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else { 109802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strncpy(pathname, path, n); 109902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath len = n; 110002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 110102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (len && pathname[len - 1] != '/') 110202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath pathname[len++] = '/'; 110302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname + len, filename); 110402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (stat(pathname, &statbuf) == 0 && 110502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* Accept only regular files 110602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath with some execute bits set. 110702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath XXX not perfect, might still fail */ 110802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath S_ISREG(statbuf.st_mode) && 110902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath (statbuf.st_mode & 0111)) 111002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath break; 111102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 111202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 111302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (stat(pathname, &statbuf) < 0) { 1114cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("Can't stat '%s'", filename); 111502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 1116f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko 1117f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko params_for_tracee.fd_to_close = (shared_log != stderr) ? fileno(shared_log) : -1; 1118f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko params_for_tracee.run_euid = (statbuf.st_mode & S_ISUID) ? statbuf.st_uid : run_uid; 1119f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko params_for_tracee.run_egid = (statbuf.st_mode & S_ISGID) ? statbuf.st_gid : run_gid; 1120f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko params_for_tracee.argv = argv; 1121f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko /* 1122f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * On NOMMU, can be safely freed only after execve in tracee. 1123f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * It's hard to know when that happens, so we just leak it. 1124f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko */ 112505f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko params_for_tracee.pathname = NOMMU_SYSTEM ? strdup(pathname) : pathname; 1126f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko 1127a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin strace_child = pid = fork(); 1128ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pid < 0) { 1129cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("fork"); 1130ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 1131f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko if ((pid != 0 && daemonized_tracer) 1132f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko || (pid == 0 && !daemonized_tracer) 1133ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko ) { 1134f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko /* We are to become the tracee. Two cases: 1135f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * -D: we are parent 1136f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * not -D: we are child 1137f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko */ 1138f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko exec_or_die(); 113902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 1140ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 11412e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko /* We are the tracer */ 114275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko 11432e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko if (!daemonized_tracer) { 114431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (!use_seize) { 114531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko /* child did PTRACE_TRACEME, nothing to do in parent */ 114631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko } else { 11475c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko if (!NOMMU_SYSTEM) { 114831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko /* Wait until child stopped itself */ 114931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko int status; 115031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko while (waitpid(pid, &status, WSTOPPED) < 0) { 115131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (errno == EINTR) 115231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko continue; 115331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko perror_msg_and_die("waitpid"); 115431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko } 115531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) { 115675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko kill_save_errno(pid, SIGKILL); 115731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko perror_msg_and_die("Unexpected wait status %x", status); 115831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko } 115905f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko skip_startup_execve = 1; 116031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko } 11615c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko /* Else: NOMMU case, we have no way to sync. 116231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko * Just attach to it as soon as possible. 116331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko * This means that we may miss a few first syscalls... 116431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko */ 116531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko 116631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (ptrace_attach_or_seize(pid)) { 116775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko kill_save_errno(pid, SIGKILL); 116831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko perror_msg_and_die("Can't attach to %d", pid); 116931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko } 11705c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko if (!NOMMU_SYSTEM) 117131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko kill(pid, SIGCONT); 117231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko } 11732e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko tcp = alloctcb(pid); 11745c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko if (!NOMMU_SYSTEM) 117575fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop; 1176f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko else 117775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP; 11783db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko newoutf(tcp); 11792e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko } 11802e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko else { 118105f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko /* With -D, we are *child* here, IOW: different pid. Fetch it: */ 11822e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko strace_tracer_pid = getpid(); 11832e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko /* The tracee is our parent: */ 11842e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko pid = getppid(); 1185f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko alloctcb(pid); 1186f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko /* attaching will be done later, by startup_attach */ 11873db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko /* note: we don't do newoutf(tcp) here either! */ 118805f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko skip_startup_execve = 1; 11895c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko 1190f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko /* NOMMU BUG! -D mode is active, we (child) return, 1191f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * and we will scribble over parent's stack! 1192f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * When parent later unpauses, it segfaults. 1193f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * 1194f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * We work around it 1195f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * (1) by declaring exec_or_die() NORETURN, 1196f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * hopefully compiler will just jump to it 1197f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * instead of call (won't push anything to stack), 1198f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * (2) by trying very hard in exec_or_die() 1199f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * to not use any stack, 1200f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * (3) having a really big (MAXPATHLEN) stack object 1201f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * in this function, which creates a "buffer" between 1202f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * child's and parent's stack pointers. 1203f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * This may save us if (1) and (2) failed 1204f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * and compiler decided to use stack in exec_or_die() anyway 1205f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * (happens on i386 because of stack parameter passing). 120605f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko * 120705f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko * A cleaner solution is to use makecontext + setcontext 120805f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko * to create a genuine separate stack and execute on it. 1209f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko */ 1210ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 121102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath} 121202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 1213b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao/* 1214b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * Test whether the kernel support PTRACE_O_TRACECLONE et al options. 1215b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it, 1216b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * and then see which options are supported by the kernel. 1217b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao */ 12188d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenkostatic int 12193454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_followfork(void) 1220b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao{ 12212fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin int pid, expected_grandchild = 0, found_grandchild = 0; 12222fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin const unsigned int test_options = PTRACE_O_TRACECLONE | 12232fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin PTRACE_O_TRACEFORK | 12242fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin PTRACE_O_TRACEVFORK; 1225b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao 122605f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko /* Need fork for test. NOMMU has no forks */ 122705f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko if (NOMMU_SYSTEM) 122805f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko goto worked; /* be bold, and pretend that test succeeded */ 122905f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko 12305d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko pid = fork(); 12315d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko if (pid < 0) 123204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg_and_die("fork"); 12335d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko if (pid == 0) { 123404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin pid = getpid(); 123531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) 123604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", 123704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__); 12384c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko kill_save_errno(pid, SIGSTOP); 123904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (fork() < 0) 124004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg_and_die("fork"); 124104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin _exit(0); 1242b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao } 1243b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin 1244b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin while (1) { 1245b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin int status, tracee_pid; 1246b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin 124704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin errno = 0; 1248b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin tracee_pid = wait(&status); 124904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (tracee_pid <= 0) { 1250b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin if (errno == EINTR) 1251b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin continue; 12524c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko if (errno == ECHILD) 1253b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao break; 125404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(pid, SIGKILL); 125504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg_and_die("%s: unexpected wait result %d", 125604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__, tracee_pid); 125704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin } 125804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (WIFEXITED(status)) { 125904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (WEXITSTATUS(status)) { 126004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (tracee_pid != pid) 126104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(pid, SIGKILL); 126204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin error_msg_and_die("%s: unexpected exit status %u", 126304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__, WEXITSTATUS(status)); 126404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin } 126504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin continue; 126604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin } 126704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (WIFSIGNALED(status)) { 126804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (tracee_pid != pid) 126904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(pid, SIGKILL); 127004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin error_msg_and_die("%s: unexpected signal %u", 127104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__, WTERMSIG(status)); 127204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin } 127304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (!WIFSTOPPED(status)) { 127404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (tracee_pid != pid) 127504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(tracee_pid, SIGKILL); 12764c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko kill_save_errno(pid, SIGKILL); 127704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin error_msg_and_die("%s: unexpected wait status %x", 127804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__, status); 1279b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin } 1280b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin if (tracee_pid != pid) { 12812fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin found_grandchild = tracee_pid; 128204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) { 128304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(tracee_pid, SIGKILL); 128404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(pid, SIGKILL); 128504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg_and_die("PTRACE_CONT doesn't work"); 128604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin } 128704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin continue; 1288b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin } 128904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin switch (WSTOPSIG(status)) { 129004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin case SIGSTOP: 129104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0 129204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin && errno != EINVAL && errno != EIO) 129304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg("PTRACE_SETOPTIONS"); 129404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin break; 129504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin case SIGTRAP: 129604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (status >> 16 == PTRACE_EVENT_FORK) { 129704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin long msg = 0; 12982fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin 129904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (ptrace(PTRACE_GETEVENTMSG, pid, 130004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin NULL, (long) &msg) == 0) 130104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin expected_grandchild = msg; 1302b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao } 130304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin break; 130404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin } 130504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) { 130604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(pid, SIGKILL); 130704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg_and_die("PTRACE_SYSCALL doesn't work"); 1308b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao } 1309b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao } 131004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (expected_grandchild && expected_grandchild == found_grandchild) { 131105f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko worked: 1312f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko ptrace_setoptions |= test_options; 1313a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko if (debug_flag) 131404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin fprintf(stderr, "ptrace_setoptions = %#x\n", 131504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin ptrace_setoptions); 13168d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko return 0; 131704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin } 131804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin error_msg("Test for PTRACE_O_TRACECLONE failed, " 131904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin "giving up using this feature."); 13208d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko return 1; 1321b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao} 13223454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 13233454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/* 13243454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Test whether the kernel support PTRACE_O_TRACESYSGOOD. 13253454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it, 13263454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and then see whether it will stop with (SIGTRAP | 0x80). 13273454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * 13283454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Use of this option enables correct handling of user-generated SIGTRAPs, 13293454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and SIGTRAPs generated by special instructions such as int3 on x86: 13303454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * _start: .globl _start 13313454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * int3 13323454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * movl $42, %ebx 13333454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * movl $1, %eax 13343454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * int $0x80 13353454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S") 13363454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko */ 13378d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenkostatic int 13383454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_for_all(void) 13393454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{ 134004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin const unsigned int test_options = PTRACE_O_TRACESYSGOOD | 134104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin PTRACE_O_TRACEEXEC; 13423454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko int pid; 13433454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko int it_worked = 0; 13443454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 134505f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko /* Need fork for test. NOMMU has no forks */ 13465c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko if (NOMMU_SYSTEM) 134705f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko goto worked; /* be bold, and pretend that test succeeded */ 13487ff5ed932568a8049c3ca134da374f64c3e255ceMike Frysinger 13493454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko pid = fork(); 13503454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (pid < 0) 135175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko perror_msg_and_die("fork"); 13523454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 13533454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (pid == 0) { 13543454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko pid = getpid(); 13553454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) 135675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko /* Note: exits with exitcode 1 */ 135704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", 135804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__); 13593454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko kill(pid, SIGSTOP); 13603454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko _exit(0); /* parent should see entry into this syscall */ 13613454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 13623454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 13633454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko while (1) { 13643454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko int status, tracee_pid; 13653454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 13663454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko errno = 0; 13673454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko tracee_pid = wait(&status); 13683454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (tracee_pid <= 0) { 13693454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (errno == EINTR) 13703454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko continue; 137104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(pid, SIGKILL); 137204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg_and_die("%s: unexpected wait result %d", 137304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__, tracee_pid); 137475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko } 137575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko if (WIFEXITED(status)) { 137675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko if (WEXITSTATUS(status) == 0) 137775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko break; 137804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin error_msg_and_die("%s: unexpected exit status %u", 137904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__, WEXITSTATUS(status)); 138004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin } 138104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (WIFSIGNALED(status)) { 138204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin error_msg_and_die("%s: unexpected signal %u", 138304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__, WTERMSIG(status)); 13843454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 13853454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (!WIFSTOPPED(status)) { 13863454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko kill(pid, SIGKILL); 138704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin error_msg_and_die("%s: unexpected wait status %x", 138804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__, status); 13893454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 13903454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (WSTOPSIG(status) == SIGSTOP) { 13913454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko /* 13923454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * We don't check "options aren't accepted" error. 13933454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * If it happens, we'll never get (SIGTRAP | 0x80), 13943454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and thus will decide to not use the option. 13953454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * IOW: the outcome of the test will be correct. 13963454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko */ 139704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0 139804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin && errno != EINVAL && errno != EIO) 139904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg("PTRACE_SETOPTIONS"); 14003454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 14013454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (WSTOPSIG(status) == (SIGTRAP | 0x80)) { 14023454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko it_worked = 1; 14033454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 14043454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) { 140504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(pid, SIGKILL); 140675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko perror_msg_and_die("PTRACE_SYSCALL doesn't work"); 14073454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 14083454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 14093454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 14103454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (it_worked) { 141105f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko worked: 141275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko syscall_trap_sig = (SIGTRAP | 0x80); 1413f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko ptrace_setoptions |= test_options; 1414a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko if (debug_flag) 1415f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko fprintf(stderr, "ptrace_setoptions = %#x\n", 1416f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko ptrace_setoptions); 14178d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko return 0; 14183454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 14193454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 142004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin error_msg("Test for PTRACE_O_TRACESYSGOOD failed, " 142104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin "giving up using this feature."); 14228d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko return 1; 14233454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko} 142431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko 14255c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#if USE_SEIZE 142631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic void 142731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkotest_ptrace_seize(void) 142831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko{ 142931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko int pid; 143031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko 143105f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko /* Need fork for test. NOMMU has no forks */ 14325c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko if (NOMMU_SYSTEM) { 14335c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko post_attach_sigstop = 0; /* this sets use_seize to 1 */ 14345c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko return; 14355c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko } 14365c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko 143731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko pid = fork(); 143831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (pid < 0) 143931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko perror_msg_and_die("fork"); 144031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko 144131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (pid == 0) { 144231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko pause(); 144331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko _exit(0); 144431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko } 144531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko 144631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After 144731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko * attaching tracee continues to run unless a trap condition occurs. 144831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko * PTRACE_SEIZE doesn't affect signal or group stop state. 144931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko */ 145026bc0606d96d05d30ba263939a0451889340a64cDenys Vlasenko if (ptrace(PTRACE_SEIZE, pid, 0, 0) == 0) { 145131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko post_attach_sigstop = 0; /* this sets use_seize to 1 */ 1452a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko } else if (debug_flag) { 145331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko fprintf(stderr, "PTRACE_SEIZE doesn't work\n"); 145431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko } 145531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko 145631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko kill(pid, SIGKILL); 145731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko 145831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko while (1) { 145931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko int status, tracee_pid; 146031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko 146131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko errno = 0; 146231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko tracee_pid = waitpid(pid, &status, 0); 146331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (tracee_pid <= 0) { 146431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (errno == EINTR) 146531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko continue; 146631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko perror_msg_and_die("%s: unexpected wait result %d", 146731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko __func__, tracee_pid); 146831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko } 146931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (WIFSIGNALED(status)) { 147031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko return; 147131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko } 147231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko error_msg_and_die("%s: unexpected wait status %x", 147331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko __func__, status); 147431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko } 147531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko} 1476978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko#else /* !USE_SEIZE */ 1477978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko# define test_ptrace_seize() ((void)0) 1478978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko#endif 147931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko 14806e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenkostatic unsigned 1481f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenkoget_os_release(void) 1482f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko{ 14836e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko unsigned rel; 14846e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko const char *p; 1485f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko struct utsname u; 1486f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko if (uname(&u) < 0) 1487f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko perror_msg_and_die("uname"); 14886e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko /* u.release has this form: "3.2.9[-some-garbage]" */ 14896e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko rel = 0; 14906e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko p = u.release; 14916e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko for (;;) { 14926e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko if (!(*p >= '0' && *p <= '9')) 14936e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko error_msg_and_die("Bad OS release string: '%s'", u.release); 14946e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko /* Note: this open-codes KERNEL_VERSION(): */ 14956e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko rel = (rel << 8) | atoi(p); 14966e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko if (rel >= KERNEL_VERSION(1,0,0)) 14976e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko break; 14986e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko while (*p >= '0' && *p <= '9') 14996e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko p++; 15000dbc80de895c25769791b7726022a274695eec31Dmitry V. Levin if (*p != '.') { 15010dbc80de895c25769791b7726022a274695eec31Dmitry V. Levin if (rel >= KERNEL_VERSION(0,1,0)) { 15020dbc80de895c25769791b7726022a274695eec31Dmitry V. Levin /* "X.Y-something" means "X.Y.0" */ 15030dbc80de895c25769791b7726022a274695eec31Dmitry V. Levin rel <<= 8; 15040dbc80de895c25769791b7726022a274695eec31Dmitry V. Levin break; 15050dbc80de895c25769791b7726022a274695eec31Dmitry V. Levin } 15066e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko error_msg_and_die("Bad OS release string: '%s'", u.release); 15070dbc80de895c25769791b7726022a274695eec31Dmitry V. Levin } 15086e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko p++; 15096e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko } 15106e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko return rel; 1511f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko} 1512f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko 1513ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko/* 1514ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * Initialization part of main() was eating much stack (~0.5k), 1515ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * which was unused after init. 1516ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * We can reuse it if we move init code into a separate function. 1517ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * 1518ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * Don't want main() to inline us and defeat the reason 1519ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * we have a separate function. 1520ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko */ 1521ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkostatic void __attribute__ ((noinline)) 1522ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkoinit(int argc, char *argv[]) 152376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 152476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 1525ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin int c, i; 152606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin int optF = 0; 152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct sigaction sa; 152876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 152908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin progname = argv[0] ? argv[0] : "strace"; 153008b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin 1531a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko /* Make sure SIGCHLD has the default action so that waitpid 1532a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko definitely works without losing track of children. The user 1533a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko should not have given us a bogus state to inherit, but he might 1534a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko have. Arguably we should detect SIG_IGN here and pass it on 1535a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko to children, but probably noone really needs that. */ 1536a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko signal(SIGCHLD, SIG_DFL); 1537a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko 153875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko strace_tracer_pid = getpid(); 153975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko 15406e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko os_release = get_os_release(); 1541f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko 1542ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath /* Allocate the initial tcbtab. */ 1543ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcbtabsize = argc; /* Surely enough for all -p args. */ 15444f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0])); 15451d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko if (!tcbtab) 15461d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko die_out_of_memory(); 15474f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko tcp = calloc(tcbtabsize, sizeof(*tcp)); 15481d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko if (!tcp) 15491d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko die_out_of_memory(); 15504f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko for (c = 0; c < tcbtabsize; c++) 15514f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko tcbtab[c] = tcp++; 1552ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath 15536764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko shared_log = stderr; 1554138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath set_sortby(DEFAULT_SORTBY); 1555138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath set_personality(DEFAULT_PERSONALITY); 155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("trace=all"); 155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=all"); 155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("verbose=all"); 155974ec14f968a418691b851cbbfeb0269174c64b08Denys Vlasenko#if DEFAULT_QUAL_FLAGS != (QUAL_TRACE | QUAL_ABBREV | QUAL_VERBOSE) 156074ec14f968a418691b851cbbfeb0269174c64b08Denys Vlasenko# error Bug in DEFAULT_QUAL_FLAGS 156174ec14f968a418691b851cbbfeb0269174c64b08Denys Vlasenko#endif 156276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("signal=all"); 156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while ((c = getopt(argc, argv, 156461e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko "+bcCdfFhiqrtTvVxyz" 1565ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko "D" 1566b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) { 156776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (c) { 156861e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko case 'b': 156961e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko detach_on_execve = 1; 157061e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko break; 157176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'c': 1572e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag == CFLAG_BOTH) { 1573c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko error_msg_and_die("-c and -C are mutually exclusive"); 1574e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin } 1575e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin cflag = CFLAG_ONLY_STATS; 1576e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin break; 1577e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin case 'C': 1578e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag == CFLAG_ONLY_STATS) { 1579c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko error_msg_and_die("-c and -C are mutually exclusive"); 1580e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin } 1581e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin cflag = CFLAG_BOTH; 158276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 158376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'd': 1584a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko debug_flag = 1; 158576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 1586ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko case 'D': 1587ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko daemonized_tracer = 1; 1588ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko break; 158941c48227a86a176da333f713d5047240885f25ccRoland McGrath case 'F': 159006350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin optF = 1; 159106350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin break; 159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'f': 159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman followfork++; 159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'h': 159676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stdout, 0); 159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'i': 1599a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko iflag = 1; 160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'q': 1602a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko qflag = 1; 160376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'r': 1605a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko rflag = 1; 1606a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko /* fall through to tflag++ */ 160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 't': 160876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tflag++; 160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'T': 1611a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko Tflag = 1; 161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'x': 161476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman xflag++; 161576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 16168a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards case 'y': 16178a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards show_fd_path = 1; 16188a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards break; 161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'v': 162076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=none"); 162176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'V': 16239c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath printf("%s -- version %s\n", PACKAGE_NAME, VERSION); 162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(0); 162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 162617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig case 'z': 162717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig not_failing_only = 1; 162817f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig break; 162976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'a': 1630ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin acolumn = string_to_uint(optarg); 1631102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko if (acolumn < 0) 1632ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin error_opt_arg(c, optarg); 163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'e': 163576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify(optarg); 163676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'o': 163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outfname = strdup(optarg); 163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'O': 1641ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin i = string_to_uint(optarg); 1642ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin if (i < 0) 1643ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin error_opt_arg(c, optarg); 1644ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin set_overhead(i); 164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'p': 1647e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko process_opt_p_list(optarg); 164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 16498a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards case 'P': 16508a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards tracing_paths = 1; 16518a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards if (pathtrace_select(optarg)) { 1652cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("Failed to select path '%s'", optarg); 16538a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards } 16548a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards break; 165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 's': 1656ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin i = string_to_uint(optarg); 1657ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin if (i < 0) 1658ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin error_opt_arg(c, optarg); 1659ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin max_strlen = i; 166076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'S': 166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_sortby(optarg); 166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 166476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'u': 166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman username = strdup(optarg); 166676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 1667de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath case 'E': 16681d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko if (putenv(optarg) < 0) 16691d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko die_out_of_memory(); 1670de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath break; 1671b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko case 'I': 1672ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin opt_intr = string_to_uint(optarg); 1673ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) 1674ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin error_opt_arg(c, optarg); 1675b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko break; 167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stderr, 1); 167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 168076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1681837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko argv += optind; 1682837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko /* argc -= optind; - no need, argc is not used below */ 168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1684102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko acolumn_spaces = malloc(acolumn + 1); 1685102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko if (!acolumn_spaces) 16861d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko die_out_of_memory(); 1687102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko memset(acolumn_spaces, ' ', acolumn); 1688102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko acolumn_spaces[acolumn] = '\0'; 1689102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko 1690837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko /* Must have PROG [ARGS], or -p PID. Not both. */ 1691fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko if (!argv[0] == !nprocs) 1692ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath usage(stderr, 1); 1693ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath 1694fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko if (nprocs != 0 && daemonized_tracer) { 1695c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko error_msg_and_die("-D and -p are mutually exclusive"); 1696d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao } 1697d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao 169806350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin if (!followfork) 169906350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin followfork = optF; 170006350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin 17013db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko if (followfork >= 2 && cflag) { 1702c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko error_msg_and_die("(-c or -C) and -ff are mutually exclusive"); 1703cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath } 1704cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath 170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* See if they want to run as another user. */ 170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (username != NULL) { 170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct passwd *pent; 170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (getuid() != 0 || geteuid() != 0) { 1710cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("You must be root to use the -u option"); 171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 17125d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko pent = getpwnam(username); 17135d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko if (pent == NULL) { 1714cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("Cannot find user '%s'", username); 171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = pent->pw_uid; 171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = pent->pw_gid; 171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = getuid(); 172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = getgid(); 172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 17248d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko /* 17258d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko * On any reasonably recent Linux kernel (circa about 2.5.46) 17268d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko * need_fork_exec_workarounds should stay 0 after these tests: 17278d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko */ 17288d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko /*need_fork_exec_workarounds = 0; - already is */ 172904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (followfork) 17308d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko need_fork_exec_workarounds = test_ptrace_setoptions_followfork(); 17318d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko need_fork_exec_workarounds |= test_ptrace_setoptions_for_all(); 173231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko test_ptrace_seize(); 17338044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin 173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Check if they want to redirect the output. */ 173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (outfname) { 173637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath /* See if they want to pipe the output. */ 173737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (outfname[0] == '|' || outfname[0] == '!') { 173837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath /* 173937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath * We can't do the <outfname>.PID funny business 174037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath * when using popen, so prohibit it. 174137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath */ 17423db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko if (followfork >= 2) 17437dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko error_msg_and_die("Piping the output and -ff are mutually exclusive"); 17446764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko shared_log = strace_popen(outfname + 1); 174554b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman } 17463db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko else if (followfork < 2) 17476764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko shared_log = strace_fopen(outfname); 1748328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko } else { 1749328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko /* -ff without -o FILE is the same as single -f */ 17503db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko if (followfork >= 2) 1751328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko followfork = 1; 175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1754cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko if (!outfname || outfname[0] == '|' || outfname[0] == '!') { 1755a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko char *buf = malloc(BUFSIZ); 1756a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko if (!buf) 1757a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko die_out_of_memory(); 17586764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko setvbuf(shared_log, buf, _IOLBF, BUFSIZ); 1759cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko } 1760837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko if (outfname && argv[0]) { 1761b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko if (!opt_intr) 1762b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko opt_intr = INTR_NEVER; 176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag = 1; 1764369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath } 1765b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko if (!opt_intr) 1766b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko opt_intr = INTR_WHILE_WAIT; 1767b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko 1768b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko /* argv[0] -pPID -oFILE Default interactive setting 1769b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko * yes 0 0 INTR_WHILE_WAIT 1770b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko * no 1 0 INTR_WHILE_WAIT 1771b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko * yes 0 1 INTR_NEVER 1772b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko * no 1 1 INTR_WHILE_WAIT 177354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath */ 177454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 17755c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko sigemptyset(&empty_set); 17765c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko sigemptyset(&blocked_set); 17775c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko 1778f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko /* startup_child() must be called before the signal handlers get 1779f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * installed below as they are inherited into the spawned process. 1780f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * Also we do not need to be protected by them as during interruption 1781f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * in the startup_child() mode we kill the spawned process anyway. 1782f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko */ 178361e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko if (argv[0]) { 1784837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko startup_child(argv); 178561e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko } 178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = SIG_IGN; 178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 1790b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */ 1791b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */ 1792b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko if (opt_intr != INTR_ANYWHERE) { 1793b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko if (opt_intr == INTR_BLOCK_TSTP_TOO) 1794b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */ 1795b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko /* 1796b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko * In interactive mode (if no -o OUTFILE, or -p PID is used), 1797b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko * fatal signals are blocked while syscall stop is processed, 1798b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko * and acted on in between, when waiting for new syscall stops. 1799b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko * In non-interactive mode, signals are ignored. 1800b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko */ 1801b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko if (opt_intr == INTR_WHILE_WAIT) { 1802b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko sigaddset(&blocked_set, SIGHUP); 1803b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko sigaddset(&blocked_set, SIGINT); 1804b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko sigaddset(&blocked_set, SIGQUIT); 1805b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko sigaddset(&blocked_set, SIGPIPE); 1806b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko sigaddset(&blocked_set, SIGTERM); 1807b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko sa.sa_handler = interrupt; 1808b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko } 1809b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko /* SIG_IGN, or set handler for these */ 1810b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko sigaction(SIGHUP, &sa, NULL); 1811b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko sigaction(SIGINT, &sa, NULL); 1812b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko sigaction(SIGQUIT, &sa, NULL); 1813b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko sigaction(SIGPIPE, &sa, NULL); 1814b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko sigaction(SIGTERM, &sa, NULL); 181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1816fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko if (nprocs != 0 || daemonized_tracer) 181702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath startup_attach(); 181802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 1819fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko /* Do we want pids printed in our -o OUTFILE? 1820fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko * -ff: no (every pid has its own file); or 1821fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko * -f: yes (there can be more pids in the future); or 1822fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko * -p PID1,PID2: yes (there are already more than one pid) 1823fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko */ 1824fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1)); 182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1827eebb04d4ae8bf4b08a041f5ea442ca24c90692c2Denys Vlasenkostatic struct tcb * 182854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathpid2tcb(int pid) 182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 183154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath 183254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath if (pid <= 0) 183354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath return NULL; 183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1835ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 183654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath struct tcb *tcp = tcbtab[i]; 183754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath if (tcp->pid == pid && (tcp->flags & TCB_INUSE)) 183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 184054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath 184176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 18451201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkocleanup(void) 184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 18493521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko int fatal_sig; 18503521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko 18513521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko /* 'interrupted' is a volatile object, fetch it only once */ 18523521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko fatal_sig = interrupted; 18533521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko if (!fatal_sig) 18543521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko fatal_sig = SIGTERM; 185576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1856ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1857ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[i]; 185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE)) 185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 1860a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko if (debug_flag) 186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "cleanup: looking at pid %u\n", tcp->pid); 18637de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko if (tcp->flags & TCB_STRACE_CHILD) { 186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGCONT); 1865a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko kill(tcp->pid, fatal_sig); 186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 18677de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko detach(tcp); 186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) 18706764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko call_summary(shared_log); 187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 18741201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkointerrupt(int sig) 187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 1876a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko interrupted = sig; 187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 18801201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotrace(void) 188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct rusage ru; 188326d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko struct rusage *rup = cflag ? &ru : NULL; 1884978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko#ifdef __WALL 1885eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath static int wait4_options = __WALL; 1886978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko#endif 188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1888eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath while (nprocs != 0) { 1889f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko int pid; 1890f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko int wait_errno; 1891f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko int status, sig; 189231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko int stopped; 1893f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko struct tcb *tcp; 1894f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko unsigned event; 1895f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko 1896222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko if (interrupted) 1897eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath return 0; 1898eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (interactive) 1899eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath sigprocmask(SIG_SETMASK, &empty_set, NULL); 1900978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko#ifdef __WALL 190126d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko pid = wait4(-1, &status, wait4_options, rup); 19025bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) { 19032f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman /* this kernel does not support __WALL */ 19042f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman wait4_options &= ~__WALL; 190526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko pid = wait4(-1, &status, wait4_options, rup); 19062f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 19075bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) { 19082f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman /* most likely a "cloned" process */ 190926d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko pid = wait4(-1, &status, __WCLONE, rup); 191026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko if (pid < 0) { 1911cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg("wait4(__WCLONE) failed"); 19122f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 19132f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 1914978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko#else 191526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko pid = wait4(-1, &status, 0, rup); 1916978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko#endif /* __WALL */ 191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman wait_errno = errno; 1918eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (interactive) 1919eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath sigprocmask(SIG_BLOCK, &blocked_set, NULL); 192076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 192126d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko if (pid < 0) { 1922eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath switch (wait_errno) { 1923eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath case EINTR: 192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 1925eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath case ECHILD: 192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * We would like to verify this case 192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * but sometimes a race in Solbourne's 192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * version of SunOS sometimes reports 193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * ECHILD before sending us SIGCHILD. 193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 1932eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath return 0; 1933eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath default: 1934eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath errno = wait_errno; 19354c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko perror_msg("wait"); 1936eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath return -1; 193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 193910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (pid == popen_pid) { 194010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (WIFEXITED(status) || WIFSIGNALED(status)) 19417dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko popen_pid = 0; 194210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin continue; 194310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 1944f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko 1945f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko event = ((unsigned)status >> 16); 1946a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko if (debug_flag) { 19471d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16]; 194867559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko char evbuf[sizeof(",PTRACE_EVENT_?? (%u)") + sizeof(int)*3 /*paranoia:*/ + 16]; 19491d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko strcpy(buf, "???"); 19501d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko if (WIFSIGNALED(status)) 19511d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef WCOREDUMP 19521d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko sprintf(buf, "WIFSIGNALED,%ssig=%s", 19531d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko WCOREDUMP(status) ? "core," : "", 19541d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko signame(WTERMSIG(status))); 19551d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#else 19561d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko sprintf(buf, "WIFSIGNALED,sig=%s", 19571d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko signame(WTERMSIG(status))); 19581d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif 19591d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko if (WIFEXITED(status)) 19601d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status)); 19611d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko if (WIFSTOPPED(status)) 19621d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status))); 19635bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#ifdef WIFCONTINUED 19641d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko if (WIFCONTINUED(status)) 19651d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko strcpy(buf, "WIFCONTINUED"); 19665bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#endif 196767559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko evbuf[0] = '\0'; 196867559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko if (event != 0) { 196967559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko static const char *const event_names[] = { 197067559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko [PTRACE_EVENT_CLONE] = "CLONE", 197167559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko [PTRACE_EVENT_FORK] = "FORK", 197267559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko [PTRACE_EVENT_VFORK] = "VFORK", 197367559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE", 197467559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko [PTRACE_EVENT_EXEC] = "EXEC", 197567559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko [PTRACE_EVENT_EXIT] = "EXIT", 197667559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko }; 197767559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko const char *e; 197867559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko if (event < ARRAY_SIZE(event_names)) 197967559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko e = event_names[event]; 198067559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko else { 198167559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko sprintf(buf, "?? (%u)", event); 198267559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko e = buf; 198367559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko } 198467559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko sprintf(evbuf, ",PTRACE_EVENT_%s", e); 198567559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko } 198667559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko fprintf(stderr, " [wait(0x%04x) = %u] %s%s\n", status, pid, buf, evbuf); 19871d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko } 198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1989f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko /* Look up 'pid' in our table. */ 19905d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko tcp = pid2tcb(pid); 1991f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko 19928511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko if (!tcp) { 19938511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko if (followfork) { 19948511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko tcp = alloctcb(pid); 19958511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop; 19968511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko newoutf(tcp); 19978511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko if (!qflag) 19988511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko fprintf(stderr, "Process %d attached\n", 19998511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko pid); 20008511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko } else { 20018511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko /* This can happen if a clone call used 20028511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko CLONE_PTRACE itself. */ 20038511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko if (WIFSTOPPED(status)) 20048511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko ptrace(PTRACE_CONT, pid, (char *) 0, 0); 20058511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko error_msg_and_die("Unknown pid: %u", pid); 20068511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko } 20078511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko } 20088511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko 2009ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko clear_regs(); 2010ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko if (WIFSTOPPED(status)) 2011ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko get_regs(pid); 2012ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko 2013f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko /* Under Linux, execve changes pid to thread leader's pid, 2014f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko * and we see this changed pid on EVENT_EXEC and later, 2015f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko * execve sysexit. Leader "disappears" without exit 2016f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko * notification. Let user know that, drop leader's tcb, 2017f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko * and fix up pid in execve thread's tcb. 2018f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko * Effectively, execve thread's tcb replaces leader's tcb. 2019f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko * 2020f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko * BTW, leader is 'stuck undead' (doesn't report WIFEXITED 2021f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko * on exit syscall) in multithreaded programs exactly 2022f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko * in order to handle this case. 2023f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko * 2024f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0. 2025f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko * On 2.6 and earlier, it can return garbage. 2026f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko */ 20276e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko if (event == PTRACE_EVENT_EXEC && os_release >= KERNEL_VERSION(3,0,0)) { 20286764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko FILE *fp; 20298511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko struct tcb *execve_thread; 2030f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko long old_pid = 0; 20318511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko 20328511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) < 0) 20338511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko goto dont_switch_tcbs; 20348511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko if (old_pid <= 0 || old_pid == pid) 20358511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko goto dont_switch_tcbs; 20368511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko execve_thread = pid2tcb(old_pid); 20378511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko /* It should be !NULL, but I feel paranoid */ 20388511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko if (!execve_thread) 20398511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko goto dont_switch_tcbs; 20408511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko 20418511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko if (execve_thread->curcol != 0) { 20428511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko /* 20438511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko * One case we are here is -ff: 20448511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko * try "strace -oLOG -ff test/threaded_execve" 20458511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko */ 20468511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid); 20476764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko /*execve_thread->curcol = 0; - no need, see code below */ 20488511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko } 20498511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko /* Swap output FILEs (needed for -ff) */ 20506764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko fp = execve_thread->outf; 20516764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko execve_thread->outf = tcp->outf; 20526764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko tcp->outf = fp; 20538511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko /* And their column positions */ 20546764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko execve_thread->curcol = tcp->curcol; 20556764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko tcp->curcol = 0; 20568511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko /* Drop leader, but close execve'd thread outfile (if -ff) */ 20578511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko droptcb(tcp); 20588511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko /* Switch to the thread, reusing leader's outfile and pid */ 20598511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko tcp = execve_thread; 20608511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko tcp->pid = pid; 20618511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko if (cflag != CFLAG_ONLY_STATS) { 20628511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko printleader(tcp); 20638511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko tprintf("+++ superseded by execve in pid %lu +++\n", old_pid); 20648511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko line_ended(); 20658511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko tcp->flags |= TCB_REPRINT; 2066f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko } 2067f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko } 20688511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko dont_switch_tcbs: 2069f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko 207061e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko if (event == PTRACE_EVENT_EXEC && detach_on_execve) { 207161e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko if (!skip_startup_execve) 207261e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko detach(tcp); 207361e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko /* This was initial execve for "strace PROG". Skip. */ 207461e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko skip_startup_execve = 0; 207561e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko } 207661e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko 20777de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko /* Set current output file */ 20786764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko current_tcp = tcp; 20797de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko 208013d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko if (cflag) { 208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime); 208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime = ru.ru_stime; 208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2084eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath 208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFSIGNALED(status)) { 2086a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin if (pid == strace_child) 2087a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code = 0x100 | WTERMSIG(status); 2088e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag != CFLAG_ONLY_STATS 2089a9fe13c9437707fa132fde4e51a20d88381e7430Denys Vlasenko && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) 2090a9fe13c9437707fa132fde4e51a20d88381e7430Denys Vlasenko ) { 209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 209213d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#ifdef WCOREDUMP 2093000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko tprintf("+++ killed by %s %s+++\n", 20942efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath signame(WTERMSIG(status)), 209513d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko WCOREDUMP(status) ? "(core dumped) " : ""); 209613d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#else 2097000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko tprintf("+++ killed by %s +++\n", 209813d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko signame(WTERMSIG(status))); 20992efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif 21007de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko line_ended(); 210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFEXITED(status)) { 2106a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin if (pid == strace_child) 2107a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code = WEXITSTATUS(status); 2108b5e0908a173cc8005ed73fa5c0eab59d03baa7f3Denys Vlasenko if (cflag != CFLAG_ONLY_STATS) { 210919cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko printleader(tcp); 2110000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko tprintf("+++ exited with %d +++\n", WEXITSTATUS(status)); 21117de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko line_ended(); 211219cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko } 211376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 211476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 211576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 211676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "PANIC: pid %u not stopped\n", pid); 211876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2122f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko /* Is this the very first time we see this tracee stopped? */ 2123f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko if (tcp->flags & TCB_STARTUP) { 2124a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko if (debug_flag) 2125f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid); 212676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_STARTUP; 212702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (tcp->flags & TCB_BPTSET) { 212876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 212902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * One example is a breakpoint inherited from 21302ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko * parent through fork(). 213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 21326cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko if (clearbpt(tcp) < 0) { 21336cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko /* Pretty fatal */ 213476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 213676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 213876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 213944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko if (ptrace_setoptions) { 2140a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko if (debug_flag) 214144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid); 214244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) { 214344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko if (errno != ESRCH) { 214444f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko /* Should never happen, really */ 214544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko perror_msg_and_die("PTRACE_SETOPTIONS"); 21463454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 21473454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 21483454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 2149f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko } 2150f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko 215131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko sig = WSTOPSIG(status); 215231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko 2153f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko if (event != 0) { 215431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko /* Ptrace event */ 21555c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#if USE_SEIZE 215626bc0606d96d05d30ba263939a0451889340a64cDenys Vlasenko if (event == PTRACE_EVENT_STOP) { 21576703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko /* 21586703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko * PTRACE_INTERRUPT-stop or group-stop. 21596703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko * PTRACE_INTERRUPT-stop has sig == SIGTRAP here. 21606703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko */ 216131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (sig == SIGSTOP 216231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko || sig == SIGTSTP 216331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko || sig == SIGTTIN 216431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko || sig == SIGTTOU 216531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko ) { 216631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko stopped = 1; 216731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko goto show_stopsig; 216831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko } 216931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko } 217031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif 2171f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko goto restart_tracee_with_sig_0; 2172f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko } 2173f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko 2174f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko /* Is this post-attach SIGSTOP? 2175f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko * Interestingly, the process may stop 2176f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko * with STOPSIG equal to some other signal 2177f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko * than SIGSTOP if we happend to attach 2178f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko * just before the process takes a signal. 2179f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko */ 2180f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) { 2181a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko if (debug_flag) 2182f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid); 2183f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP; 21846cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko goto restart_tracee_with_sig_0; 218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 21876cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko if (sig != syscall_trap_sig) { 218831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko siginfo_t si; 218931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko 219031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko /* Nonzero (true) if tracee is stopped by signal 219131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko * (as opposed to "tracee received signal"). 2192a44f9696e45f5bb51c6ec37c0ef95dc2cdfd4c8aDenys Vlasenko * TODO: shouldn't we check for errno == EINVAL too? 2193a44f9696e45f5bb51c6ec37c0ef95dc2cdfd4c8aDenys Vlasenko * We can get ESRCH instead, you know... 219431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko */ 219531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0); 21965c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#if USE_SEIZE 219731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko show_stopsig: 21986703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko#endif 2199e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag != CFLAG_ONLY_STATS 2200a9fe13c9437707fa132fde4e51a20d88381e7430Denys Vlasenko && (qual_flags[sig] & QUAL_SIGNAL) 2201a9fe13c9437707fa132fde4e51a20d88381e7430Denys Vlasenko ) { 2202c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) 22036b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin long pc = 0; 22046b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin long psr = 0; 22057b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 2206932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko upeek(tcp, PT_CR_IPSR, &psr); 2207932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko upeek(tcp, PT_CR_IIP, &pc); 22087b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 22096b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PSR_RI 41 22107b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman pc += (psr >> PSR_RI) & 0x3; 22116b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR " @ %lx" 22122ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG , pc 22136b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin#else 22142ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_STR "" 22152ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG /* nothing */ 22167b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif 221776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 221831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (!stopped) { 22192c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko tprintf("--- %s ", signame(sig)); 22206b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin printsiginfo(&si, verbose(tcp)); 22212c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko tprintf(PC_FORMAT_STR " ---\n" 22226b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin PC_FORMAT_ARG); 22236b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin } else 22242c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko tprintf("--- stopped by %s" PC_FORMAT_STR " ---\n", 22256cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko signame(sig) 22266b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin PC_FORMAT_ARG); 22277de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko line_ended(); 222876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 222931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko 223031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (!stopped) 223131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko /* It's signal-delivery-stop. Inject the signal */ 223231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko goto restart_tracee; 223331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko 223431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko /* It's group-stop */ 22355c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#if USE_SEIZE 223631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (use_seize) { 223731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko /* 223831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko * This ends ptrace-stop, but does *not* end group-stop. 223931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko * This makes stopping signals work properly on straced process 224031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko * (that is, process really stops. It used to continue to run). 224131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko */ 224231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) { 224331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko cleanup(); 224431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko return -1; 224531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko } 224631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko continue; 224731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko } 224831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko /* We don't have PTRACE_LISTEN support... */ 224931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif 22506cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko goto restart_tracee; 225176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 22522ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko 22532ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko /* We handled quick cases, we are permitted to interrupt now. */ 225402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interrupted) 225502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath return 0; 22562ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko 22572ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko /* This should be syscall entry or exit. 22582ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko * (Or it still can be that pesky post-execve SIGTRAP!) 22592ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko * Handle it. 22602ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko */ 2261235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko if (trace_syscall(tcp) < 0) { 2262235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko /* ptrace() failed in trace_syscall(). 2263eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * Likely a result of process disappearing mid-flight. 2264235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko * Observed case: exit_group() or SIGKILL terminating 2265f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko * all processes in thread group. 22667de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko * We assume that ptrace error was caused by process death. 2267f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko * We used to detach(tcp) here, but since we no longer 2268f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko * implement "detach before death" policy/hack, 2269f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko * we can let this process to report its death to us 2270f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko * normally, via WIFEXITED or WIFSIGNALED wait status. 2271f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko */ 227276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 227376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 22746cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee_with_sig_0: 22756cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko sig = 0; 22766cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee: 22776cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) { 227876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 227976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 228076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 228176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 228276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 228376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 2284ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko 2285ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkoint 2286ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkomain(int argc, char *argv[]) 2287ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko{ 2288ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko init(argc, argv); 2289ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko 2290ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko /* Run main tracing loop */ 2291ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko if (trace() < 0) 2292ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko return 1; 2293ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko 2294ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko cleanup(); 2295ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko fflush(NULL); 2296cf53436f737c0273028503186fc0f837c7191085Dmitry V. Levin if (shared_log != stderr) 2297cf53436f737c0273028503186fc0f837c7191085Dmitry V. Levin fclose(shared_log); 2298cf53436f737c0273028503186fc0f837c7191085Dmitry V. Levin if (popen_pid) { 2299cf53436f737c0273028503186fc0f837c7191085Dmitry V. Levin while (waitpid(popen_pid, NULL, 0) < 0 && errno == EINTR) 2300cf53436f737c0273028503186fc0f837c7191085Dmitry V. Levin ; 2301cf53436f737c0273028503186fc0f837c7191085Dmitry V. Levin } 2302ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko if (exit_code > 0xff) { 2303ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko /* Avoid potential core file clobbering. */ 2304ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko struct rlimit rlim = {0, 0}; 2305ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko setrlimit(RLIMIT_CORE, &rlim); 2306ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko 2307ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko /* Child was killed by a signal, mimic that. */ 2308ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko exit_code &= 0xff; 2309ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko signal(exit_code, SIG_DFL); 2310ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko raise(exit_code); 2311ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko /* Paranoia - what if this signal is not fatal? 2312ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko Exit with 128 + signo then. */ 2313ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko exit_code += 128; 2314ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko } 2315ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko 2316ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko return exit_code; 2317ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko} 2318