# This file is part of ltrace. # Copyright (C) 2014 Petr Machata, Red Hat Inc. # Copyright (C) 2006 Yao Qi , IBM Corporation # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA # Objectives: Verify that Ltrace can trace all the system calls in # execution. Note that this test is necessarily noisy. Dynamic # linker adds a bunch of system calls of its own. set empty [ltraceCompile {} [ltraceSource c { int main (void) { return 0; } }]] set bin [ltraceCompile {} [ltraceSource c { #include #include #include #include #include #include int main () { FILE* fp; char s[]="system_calls"; char buffer[1024]; struct stat state; fp = fopen ("system_calls.tmp", "w"); if (fp == NULL) { printf("Can not create system_calls.tmp\n"); exit (0); } fwrite(s, sizeof(s), 1, fp); fseek (fp, 0, SEEK_CUR); fread(buffer, sizeof(s), 1, fp); fclose(fp); getcwd (buffer, sizeof buffer); chdir ("."); symlink ("system_calls.tmp", "system_calls.link"); remove("system_calls.link"); rename ("system_calls.tmp", "system_calls.tmp1"); stat ("system_calls.tmp", &state); access ("system_calls.tmp", R_OK); remove("system_calls.tmp1"); mkdir ("system_call_mkdir", 0777); rmdir ("system_call_mkdir"); return 0; } }]] proc Calls {logfile} { set fp [open $logfile] set ret {} while {[gets $fp line] >= 0} { if [regexp -- {^[a-zA-Z0-9]*@SYS} $line] { set call [lindex [split $line @] 0] dict incr ret $call } } close $fp return $ret } proc GetDefault {d key def} { if {[dict exists $d $key]} { return [dict get $d $key] } else { return $def } } proc Diff {d1 d2} { set keys [lsort -unique [concat [dict keys $d1] [dict keys $d2]]] set ret {} foreach key $keys { set n1 [GetDefault $d1 $key 0] set n2 [GetDefault $d2 $key 0] set sum [expr $n1 - $n2] if {[expr $sum != 0]} { dict set ret $key $sum } } return $ret } proc Match {d patterns} { foreach line $patterns { set pattern [lindex $line 0] set op [lindex $line 1] set expect [lindex $line 2] set count 0 foreach key [dict keys $d] { if [regexp -- $pattern $key] { incr count [dict get $d $key] } } set msgMain "$pattern was recorded $count times" if {[eval expr $count $op $expect]} { pass $msgMain } else { fail "$msgMain, expected $op $expect" } } } Match [Diff [Calls [ltraceRun -L -S -- $bin]] \ [Calls [ltraceRun -L -S -- $empty]]] { { {^write$} == 1 } { {^unlink(at)?$} >= 2 } { {^open(at)?$} == 1 } { {^(new|f)?stat(64)?$} == 1 } { {^close$} == 1 } { {^getcwd$} == 1 } { {^chdir$} == 1 } { {^symlink(at)?$} == 1 } { {^f?access(at)?$} == 1 } { {^rename(at)?$} == 1 } { {^mkdir(at)?$} == 1 } } ltraceDone