1# This file is part of ltrace. 2# Copyright (C) 2014 Petr Machata, Red Hat Inc. 3# Copyright (C) 2006 Yao Qi <qiyao@cn.ibm.com>, IBM Corporation 4# 5# This program is free software; you can redistribute it and/or 6# modify it under the terms of the GNU General Public License as 7# published by the Free Software Foundation; either version 2 of the 8# License, or (at your option) any later version. 9# 10# This program is distributed in the hope that it will be useful, but 11# WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13# General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program; if not, write to the Free Software 17# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 18# 02110-1301 USA 19 20# Objectives: Verify that Ltrace can trace all the system calls in 21# execution. Note that this test is necessarily noisy. Dynamic 22# linker adds a bunch of system calls of its own. 23 24set empty [ltraceCompile {} [ltraceSource c { 25 int main (void) { return 0; } 26}]] 27 28set bin [ltraceCompile {} [ltraceSource c { 29 #include <stdio.h> 30 #include <unistd.h> 31 #include <sys/syscall.h> 32 #include <sys/stat.h> 33 #include <errno.h> 34 #include <stdlib.h> 35 36 int 37 main () 38 { 39 FILE* fp; 40 char s[]="system_calls"; 41 char buffer[1024]; 42 struct stat state; 43 44 fp = fopen ("system_calls.tmp", "w"); 45 if (fp == NULL) 46 { 47 printf("Can not create system_calls.tmp\n"); 48 exit (0); 49 } 50 fwrite(s, sizeof(s), 1, fp); 51 fseek (fp, 0, SEEK_CUR); 52 fread(buffer, sizeof(s), 1, fp); 53 fclose(fp); 54 55 getcwd (buffer, sizeof buffer); 56 chdir ("."); 57 symlink ("system_calls.tmp", "system_calls.link"); 58 remove("system_calls.link"); 59 rename ("system_calls.tmp", "system_calls.tmp1"); 60 stat ("system_calls.tmp", &state); 61 access ("system_calls.tmp", R_OK); 62 remove("system_calls.tmp1"); 63 64 mkdir ("system_call_mkdir", 0777); 65 rmdir ("system_call_mkdir"); 66 67 return 0; 68 } 69}]] 70 71proc Calls {logfile} { 72 set fp [open $logfile] 73 set ret {} 74 75 while {[gets $fp line] >= 0} { 76 if [regexp -- {^[a-zA-Z0-9]*@SYS} $line] { 77 set call [lindex [split $line @] 0] 78 dict incr ret $call 79 } 80 } 81 82 close $fp 83 return $ret 84} 85 86proc GetDefault {d key def} { 87 if {[dict exists $d $key]} { 88 return [dict get $d $key] 89 } else { 90 return $def 91 } 92} 93 94proc Diff {d1 d2} { 95 set keys [lsort -unique [concat [dict keys $d1] [dict keys $d2]]] 96 set ret {} 97 foreach key $keys { 98 set n1 [GetDefault $d1 $key 0] 99 set n2 [GetDefault $d2 $key 0] 100 set sum [expr $n1 - $n2] 101 if {[expr $sum != 0]} { 102 dict set ret $key $sum 103 } 104 } 105 return $ret 106} 107 108proc Match {d patterns} { 109 foreach line $patterns { 110 set pattern [lindex $line 0] 111 set op [lindex $line 1] 112 set expect [lindex $line 2] 113 114 set count 0 115 foreach key [dict keys $d] { 116 if [regexp -- $pattern $key] { 117 incr count [dict get $d $key] 118 } 119 } 120 121 set msgMain "$pattern was recorded $count times" 122 123 if {[eval expr $count $op $expect]} { 124 pass $msgMain 125 } else { 126 fail "$msgMain, expected $op $expect" 127 } 128 } 129} 130 131Match [Diff [Calls [ltraceRun -L -S -- $bin]] \ 132 [Calls [ltraceRun -L -S -- $empty]]] { 133 { {^write$} == 1 } 134 { {^unlink(at)?$} >= 2 } 135 { {^open(at)?$} == 1 } 136 { {^(new|f)?stat(64)?$} == 1 } 137 { {^close$} == 1 } 138 { {^getcwd$} == 1 } 139 { {^chdir$} == 1 } 140 { {^symlink(at)?$} == 1 } 141 { {^f?access(at)?$} == 1 } 142 { {^rename(at)?$} == 1 } 143 { {^mkdir(at)?$} == 1 } 144} 145 146ltraceDone 147