pax_global_header00006660000000000000000000000064121743042720014514gustar00rootroot0000000000000052 comment=e58138572ebddac9498b93c76770eeca7d45e3b1 systemtap-2.3/000077500000000000000000000000001217430427200134115ustar00rootroot00000000000000systemtap-2.3/.gitignore000066400000000000000000000005721217430427200154050ustar00rootroot00000000000000*~ #* *# .#* autom4te.* cscope.files cscope*out gmon.out config.h config.log config.status .deps loc2c-test run-stap run-staprun stamp-h1 stap staprun/staprun testresults staprun/stapio stap_merge CVS .checkstyle .cproject .metadata .project .settings .autotools SNAPSHOT *.o git_version.h Makefile build-elfutils include-elfutils lib-elfutils stamp-elfutils dtrace stappaths.7 systemtap-2.3/.mailmap000066400000000000000000000040641217430427200150360ustar00rootroot00000000000000# Early history did not include userid->full-name mappings, so we do # that explicitly here. Ananth N Mavinakayanahalli Anil Keshavamurthy bibo mao Brad Chen Charles Spirakis Dave Brolley Dave Nomura David Smith David J. Wilder Denys Vlasenko Don Domingo Elliott Baron Eugene Teo Frank Ch. Eigler Frederic Turgis Graydon Hoare Hien Nguyen Jim Keniston Josh Stone Kai Meyer Kent Sebastian Kevin Stafford K.Prasad Li Guanglei Mark McLoughlin Martin Hunt Masami Hiramatsu Maynard Johnson Michael Behm Mike Mason Prasanna S Panchamukhi Prerna Saxena Rajan Arora Roland McGrath Rusty Lynch Shaohua Li Srikar Dronamraju Srinivasa DS Thang Nguyen Tom Zanussi Wenji Huang William Cohen Zhaolei Zhaolei # Normalize a few git commit names too Anithra Janakiraman Breno Leitao Bryn M. Reeves Dave Nomura Don Domingo K.Prasad K.Prasad Kent Sebastian Maran Pakkirisamy Mark Wielaard Negreanu Marius Adrian Negreanu Marius Adrian Prerna Saxena Przemysław Pawełczyk Przemysław Pawełczyk Srinivasa DS Wenji Huang Wenji Huang William Cohen William Cohen Rayson Ho Rayson Ho systemtap-2.3/.tx/000077500000000000000000000000001217430427200141225ustar00rootroot00000000000000systemtap-2.3/.tx/config000066400000000000000000000002661217430427200153160ustar00rootroot00000000000000[main] host = https://www.transifex.net [systemtap.systemtappot] file_filter = po/.po source_file = po/systemtap.pot source_lang = en trans.fr = po/fr.po trans.pl = po/pl.po systemtap-2.3/ABOUT-NLS000066400000000000000000002671331217430427200146540ustar00rootroot000000000000001 Notes on the Free Translation Project *************************************** Free software is going international! The Free Translation Project is a way to get maintainers of free software, translators, and users all together, so that free software will gradually become able to speak many languages. A few packages already provide translations for their messages. If you found this `ABOUT-NLS' file inside a distribution, you may assume that the distributed package does use GNU `gettext' internally, itself available at your nearest GNU archive site. But you do _not_ need to install GNU `gettext' prior to configuring, installing or using this package with messages translated. Installers will find here some useful hints. These notes also explain how users should proceed for getting the programs to use the available translations. They tell how people wanting to contribute and work on translations can contact the appropriate team. 1.1 INSTALL Matters =================== Some packages are "localizable" when properly installed; the programs they contain can be made to speak your own native language. Most such packages use GNU `gettext'. Other packages have their own ways to internationalization, predating GNU `gettext'. By default, this package will be installed to allow translation of messages. It will automatically detect whether the system already provides the GNU `gettext' functions. Installers may use special options at configuration time for changing the default behaviour. The command: ./configure --disable-nls will _totally_ disable translation of messages. When you already have GNU `gettext' installed on your system and run configure without an option for your new package, `configure' will probably detect the previously built and installed `libintl' library and will decide to use it. If not, you may have to to use the `--with-libintl-prefix' option to tell `configure' where to look for it. Internationalized packages usually have many `po/LL.po' files, where LL gives an ISO 639 two-letter code identifying the language. Unless translations have been forbidden at `configure' time by using the `--disable-nls' switch, all available translations are installed together with the package. However, the environment variable `LINGUAS' may be set, prior to configuration, to limit the installed set. `LINGUAS' should then contain a space separated list of two-letter codes, stating which languages are allowed. 1.2 Using This Package ====================== As a user, if your language has been installed for this package, you only have to set the `LANG' environment variable to the appropriate `LL_CC' combination. If you happen to have the `LC_ALL' or some other `LC_xxx' environment variables set, you should unset them before setting `LANG', otherwise the setting of `LANG' will not have the desired effect. Here `LL' is an ISO 639 two-letter language code, and `CC' is an ISO 3166 two-letter country code. For example, let's suppose that you speak German and live in Germany. At the shell prompt, merely execute `setenv LANG de_DE' (in `csh'), `export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). This can be done from your `.login' or `.profile' file, once and for all. You might think that the country code specification is redundant. But in fact, some languages have dialects in different countries. For example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The country code serves to distinguish the dialects. The locale naming convention of `LL_CC', with `LL' denoting the language and `CC' denoting the country, is the one use on systems based on GNU libc. On other systems, some variations of this scheme are used, such as `LL' or `LL_CC.ENCODING'. You can get the list of locales supported by your system for your language by running the command `locale -a | grep '^LL''. Not all programs have translations for all languages. By default, an English message is shown in place of a nonexistent translation. If you understand other languages, you can set up a priority list of languages. This is done through a different environment variable, called `LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' for the purpose of message handling, but you still need to have `LANG' set to the primary language; this is required by other parts of the system libraries. For example, some Swedish users who would rather read translations in German than English for when Swedish is not available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. Special advice for Norwegian users: The language code for Norwegian bokma*l changed from `no' to `nb' recently (in 2003). During the transition period, while some message catalogs for this language are installed under `nb' and some older ones under `no', it's recommended for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and older translations are used. In the `LANGUAGE' environment variable, but not in the `LANG' environment variable, `LL_CC' combinations can be abbreviated as `LL' to denote the language's main dialect. For example, `de' is equivalent to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' (Portuguese as spoken in Portugal) in this context. 1.3 Translating Teams ===================== For the Free Translation Project to be a success, we need interested people who like their own language and write it well, and who are also able to synergize with other translators speaking the same language. Each translation team has its own mailing list. The up-to-date list of teams can be found at the Free Translation Project's homepage, `http://translationproject.org/', in the "Teams" area. If you'd like to volunteer to _work_ at translating messages, you should become a member of the translating team for your own language. The subscribing address is _not_ the same as the list itself, it has `-request' appended. For example, speakers of Swedish can send a message to `sv-request@li.org', having this message body: subscribe Keep in mind that team members are expected to participate _actively_ in translations, or at solving translational difficulties, rather than merely lurking around. If your team does not exist yet and you want to start one, or if you are unsure about what to do or how to get started, please write to `coordinator@translationproject.org' to reach the coordinator for all translator teams. The English team is special. It works at improving and uniformizing the terminology in use. Proven linguistic skills are praised more than programming skills, here. 1.4 Available Packages ====================== Languages are not equally supported in all packages. The following matrix shows the current state of internationalization, as of June 2010. The matrix shows, in regard of each package, for which languages PO files have been submitted to translation coordination, with a translation percentage of at least 50%. Ready PO files af am an ar as ast az be be@latin bg bn_IN bs ca +--------------------------------------------------+ a2ps | [] [] | aegis | | ant-phone | | anubis | | aspell | [] [] | bash | | bfd | | bibshelf | [] | binutils | | bison | | bison-runtime | [] | bluez-pin | [] [] | bombono-dvd | | buzztard | | cflow | | clisp | | coreutils | [] [] | cpio | | cppi | | cpplib | [] | cryptsetup | | dfarc | | dialog | [] [] | dico | | diffutils | [] | dink | | doodle | | e2fsprogs | [] | enscript | [] | exif | | fetchmail | [] | findutils | [] | flex | [] | freedink | | gas | | gawk | [] [] | gcal | [] | gcc | | gettext-examples | [] [] [] [] | gettext-runtime | [] [] | gettext-tools | [] [] | gip | [] | gjay | | gliv | [] | glunarclock | [] [] | gnubiff | | gnucash | [] | gnuedu | | gnulib | | gnunet | | gnunet-gtk | | gnutls | | gold | | gpe-aerial | | gpe-beam | | gpe-bluetooth | | gpe-calendar | | gpe-clock | [] | gpe-conf | | gpe-contacts | | gpe-edit | | gpe-filemanager | | gpe-go | | gpe-login | | gpe-ownerinfo | [] | gpe-package | | gpe-sketchbook | | gpe-su | [] | gpe-taskmanager | [] | gpe-timesheet | [] | gpe-today | [] | gpe-todo | | gphoto2 | | gprof | [] | gpsdrive | | gramadoir | | grep | | grub | [] [] | gsasl | | gss | | gst-plugins-bad | [] | gst-plugins-base | [] | gst-plugins-good | [] | gst-plugins-ugly | [] | gstreamer | [] [] [] | gtick | | gtkam | [] | gtkorphan | [] | gtkspell | [] [] [] | gutenprint | | hello | [] | help2man | | hylafax | | idutils | | indent | [] [] | iso_15924 | | iso_3166 | [] [] [] [] [] [] [] | iso_3166_2 | | iso_4217 | | iso_639 | [] [] [] [] | iso_639_3 | | jwhois | | kbd | | keytouch | [] | keytouch-editor | | keytouch-keyboa... | [] | klavaro | [] | latrine | | ld | [] | leafpad | [] [] | libc | [] [] | libexif | () | libextractor | | libgnutls | | libgpewidget | | libgpg-error | | libgphoto2 | | libgphoto2_port | | libgsasl | | libiconv | [] | libidn | | lifelines | | liferea | [] [] | lilypond | | linkdr | [] | lordsawar | | lprng | | lynx | [] | m4 | | mailfromd | | mailutils | | make | | man-db | | man-db-manpages | | minicom | | mkisofs | | myserver | | nano | [] [] | opcodes | | parted | | pies | | popt | | psmisc | | pspp | [] | pwdutils | | radius | [] | recode | [] [] | rosegarden | | rpm | | rush | | sarg | | screem | | scrollkeeper | [] [] [] | sed | [] [] | sharutils | [] [] | shishi | | skencil | | solfege | | solfege-manual | | soundtracker | | sp | | sysstat | | tar | [] | texinfo | | tin | | unicode-han-tra... | | unicode-transla... | | util-linux-ng | [] | vice | | vmm | | vorbis-tools | | wastesedge | | wdiff | | wget | [] [] | wyslij-po | | xchat | [] [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] | +--------------------------------------------------+ af am an ar as ast az be be@latin bg bn_IN bs ca 6 0 1 2 3 19 1 10 3 28 3 1 38 crh cs da de el en en_GB en_ZA eo es et eu fa +-------------------------------------------------+ a2ps | [] [] [] [] [] [] [] | aegis | [] [] [] | ant-phone | [] () | anubis | [] [] | aspell | [] [] [] [] [] | bash | [] [] [] | bfd | [] | bibshelf | [] [] [] | binutils | [] | bison | [] [] | bison-runtime | [] [] [] [] | bluez-pin | [] [] [] [] [] [] | bombono-dvd | [] | buzztard | [] [] [] | cflow | [] [] | clisp | [] [] [] [] | coreutils | [] [] [] [] | cpio | | cppi | | cpplib | [] [] [] | cryptsetup | [] | dfarc | [] [] [] | dialog | [] [] [] [] [] | dico | | diffutils | [] [] [] [] [] [] | dink | [] [] [] | doodle | [] | e2fsprogs | [] [] [] | enscript | [] [] [] | exif | () [] [] | fetchmail | [] [] () [] [] [] | findutils | [] [] [] | flex | [] [] | freedink | [] [] [] | gas | [] | gawk | [] [] [] | gcal | [] | gcc | [] [] | gettext-examples | [] [] [] [] | gettext-runtime | [] [] [] [] | gettext-tools | [] [] [] | gip | [] [] [] [] | gjay | [] | gliv | [] [] [] | glunarclock | [] [] | gnubiff | () | gnucash | [] () () () () | gnuedu | [] [] | gnulib | [] [] | gnunet | | gnunet-gtk | [] | gnutls | [] [] | gold | [] | gpe-aerial | [] [] [] [] | gpe-beam | [] [] [] [] | gpe-bluetooth | [] [] | gpe-calendar | [] | gpe-clock | [] [] [] [] | gpe-conf | [] [] [] | gpe-contacts | [] [] [] | gpe-edit | [] [] | gpe-filemanager | [] [] [] | gpe-go | [] [] [] [] | gpe-login | [] [] | gpe-ownerinfo | [] [] [] [] | gpe-package | [] [] [] | gpe-sketchbook | [] [] [] [] | gpe-su | [] [] [] [] | gpe-taskmanager | [] [] [] [] | gpe-timesheet | [] [] [] [] | gpe-today | [] [] [] [] | gpe-todo | [] [] [] | gphoto2 | [] [] () [] [] [] | gprof | [] [] [] | gpsdrive | [] [] [] | gramadoir | [] [] [] | grep | [] | grub | [] [] | gsasl | [] | gss | | gst-plugins-bad | [] [] [] [] [] | gst-plugins-base | [] [] [] [] [] | gst-plugins-good | [] [] [] [] [] [] | gst-plugins-ugly | [] [] [] [] [] [] | gstreamer | [] [] [] [] [] | gtick | [] () [] | gtkam | [] [] () [] [] | gtkorphan | [] [] [] [] | gtkspell | [] [] [] [] [] [] [] | gutenprint | [] [] [] | hello | [] [] [] [] | help2man | [] | hylafax | [] [] | idutils | [] [] | indent | [] [] [] [] [] [] [] | iso_15924 | [] () [] [] | iso_3166 | [] [] [] [] () [] [] [] () | iso_3166_2 | () | iso_4217 | [] [] [] () [] [] | iso_639 | [] [] [] [] () [] [] | iso_639_3 | [] | jwhois | [] | kbd | [] [] [] [] [] | keytouch | [] [] | keytouch-editor | [] [] | keytouch-keyboa... | [] | klavaro | [] [] [] [] | latrine | [] () | ld | [] [] | leafpad | [] [] [] [] [] [] | libc | [] [] [] [] | libexif | [] [] () | libextractor | | libgnutls | [] | libgpewidget | [] [] | libgpg-error | [] [] | libgphoto2 | [] () | libgphoto2_port | [] () [] | libgsasl | | libiconv | [] [] [] [] [] | libidn | [] [] [] | lifelines | [] () | liferea | [] [] [] [] [] | lilypond | [] [] [] | linkdr | [] [] [] | lordsawar | [] | lprng | | lynx | [] [] [] [] | m4 | [] [] [] [] | mailfromd | | mailutils | [] | make | [] [] [] | man-db | | man-db-manpages | | minicom | [] [] [] [] | mkisofs | | myserver | | nano | [] [] [] | opcodes | [] [] | parted | [] [] | pies | | popt | [] [] [] [] [] | psmisc | [] [] [] | pspp | [] | pwdutils | [] | radius | [] | recode | [] [] [] [] [] [] | rosegarden | () () () | rpm | [] [] [] | rush | | sarg | | screem | | scrollkeeper | [] [] [] [] [] | sed | [] [] [] [] [] [] | sharutils | [] [] [] [] | shishi | | skencil | [] () [] | solfege | [] [] [] | solfege-manual | [] [] | soundtracker | [] [] [] | sp | [] | sysstat | [] [] [] | tar | [] [] [] [] | texinfo | [] [] [] | tin | [] [] | unicode-han-tra... | | unicode-transla... | | util-linux-ng | [] [] [] [] | vice | () () | vmm | [] | vorbis-tools | [] [] | wastesedge | [] | wdiff | [] [] | wget | [] [] [] | wyslij-po | | xchat | [] [] [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] [] [] [] | +-------------------------------------------------+ crh cs da de el en en_GB en_ZA eo es et eu fa 5 64 105 117 18 1 8 0 28 89 18 19 0 fi fr ga gl gu he hi hr hu hy id is it ja ka kn +----------------------------------------------------+ a2ps | [] [] [] [] | aegis | [] [] | ant-phone | [] [] | anubis | [] [] [] [] | aspell | [] [] [] [] | bash | [] [] [] [] | bfd | [] [] [] | bibshelf | [] [] [] [] [] | binutils | [] [] [] | bison | [] [] [] [] | bison-runtime | [] [] [] [] [] [] | bluez-pin | [] [] [] [] [] [] [] [] | bombono-dvd | [] | buzztard | [] | cflow | [] [] [] | clisp | [] | coreutils | [] [] [] [] [] | cpio | [] [] [] [] | cppi | [] [] | cpplib | [] [] [] | cryptsetup | [] [] [] | dfarc | [] [] [] | dialog | [] [] [] [] [] [] [] | dico | | diffutils | [] [] [] [] [] [] [] [] [] | dink | [] | doodle | [] [] | e2fsprogs | [] [] | enscript | [] [] [] [] | exif | [] [] [] [] [] [] | fetchmail | [] [] [] [] | findutils | [] [] [] [] [] [] | flex | [] [] [] | freedink | [] [] [] | gas | [] [] | gawk | [] [] [] [] () [] | gcal | [] | gcc | [] | gettext-examples | [] [] [] [] [] [] [] | gettext-runtime | [] [] [] [] [] [] | gettext-tools | [] [] [] [] | gip | [] [] [] [] [] [] | gjay | [] | gliv | [] () | glunarclock | [] [] [] [] | gnubiff | () [] () | gnucash | () () () () () [] | gnuedu | [] [] | gnulib | [] [] [] [] [] [] | gnunet | | gnunet-gtk | [] | gnutls | [] [] | gold | [] [] | gpe-aerial | [] [] [] | gpe-beam | [] [] [] [] | gpe-bluetooth | [] [] [] [] | gpe-calendar | [] [] | gpe-clock | [] [] [] [] [] | gpe-conf | [] [] [] [] | gpe-contacts | [] [] [] [] | gpe-edit | [] [] [] | gpe-filemanager | [] [] [] [] | gpe-go | [] [] [] [] [] | gpe-login | [] [] [] | gpe-ownerinfo | [] [] [] [] [] | gpe-package | [] [] [] | gpe-sketchbook | [] [] [] [] | gpe-su | [] [] [] [] [] [] | gpe-taskmanager | [] [] [] [] [] | gpe-timesheet | [] [] [] [] [] | gpe-today | [] [] [] [] [] [] [] | gpe-todo | [] [] [] | gphoto2 | [] [] [] [] [] [] | gprof | [] [] [] [] | gpsdrive | [] [] [] | gramadoir | [] [] [] | grep | [] [] | grub | [] [] [] [] | gsasl | [] [] [] [] [] | gss | [] [] [] [] [] | gst-plugins-bad | [] [] [] [] [] [] | gst-plugins-base | [] [] [] [] [] [] | gst-plugins-good | [] [] [] [] [] [] | gst-plugins-ugly | [] [] [] [] [] [] | gstreamer | [] [] [] [] [] | gtick | [] [] [] [] [] | gtkam | [] [] [] [] [] | gtkorphan | [] [] [] | gtkspell | [] [] [] [] [] [] [] [] [] | gutenprint | [] [] [] [] | hello | [] [] [] | help2man | [] [] | hylafax | [] | idutils | [] [] [] [] [] [] | indent | [] [] [] [] [] [] [] [] | iso_15924 | [] () [] [] | iso_3166 | [] () [] [] [] [] [] [] [] [] [] [] | iso_3166_2 | () [] [] [] | iso_4217 | [] () [] [] [] [] | iso_639 | [] () [] [] [] [] [] [] [] | iso_639_3 | () [] [] | jwhois | [] [] [] [] [] | kbd | [] [] | keytouch | [] [] [] [] [] [] | keytouch-editor | [] [] [] [] [] | keytouch-keyboa... | [] [] [] [] [] | klavaro | [] [] | latrine | [] [] [] | ld | [] [] [] [] | leafpad | [] [] [] [] [] [] [] () | libc | [] [] [] [] [] | libexif | [] | libextractor | | libgnutls | [] [] | libgpewidget | [] [] [] [] | libgpg-error | [] [] | libgphoto2 | [] [] [] | libgphoto2_port | [] [] [] | libgsasl | [] [] [] [] [] | libiconv | [] [] [] [] [] [] | libidn | [] [] [] [] | lifelines | () | liferea | [] [] [] [] | lilypond | [] [] | linkdr | [] [] [] [] [] | lordsawar | | lprng | [] | lynx | [] [] [] [] [] | m4 | [] [] [] [] [] [] | mailfromd | | mailutils | [] [] | make | [] [] [] [] [] [] [] [] [] | man-db | [] [] | man-db-manpages | [] | minicom | [] [] [] [] [] | mkisofs | [] [] [] [] | myserver | | nano | [] [] [] [] [] [] | opcodes | [] [] [] [] | parted | [] [] [] [] | pies | | popt | [] [] [] [] [] [] [] [] [] | psmisc | [] [] [] | pspp | | pwdutils | [] [] | radius | [] [] | recode | [] [] [] [] [] [] [] [] | rosegarden | () () () () () | rpm | [] [] | rush | | sarg | [] | screem | [] [] | scrollkeeper | [] [] [] [] | sed | [] [] [] [] [] [] [] [] | sharutils | [] [] [] [] [] [] [] | shishi | [] | skencil | [] | solfege | [] [] [] [] | solfege-manual | [] [] | soundtracker | [] [] | sp | [] () | sysstat | [] [] [] [] [] | tar | [] [] [] [] [] [] [] | texinfo | [] [] [] [] | tin | [] | unicode-han-tra... | | unicode-transla... | [] [] | util-linux-ng | [] [] [] [] [] [] | vice | () () () | vmm | [] | vorbis-tools | [] | wastesedge | () () | wdiff | [] | wget | [] [] [] [] [] [] [] [] | wyslij-po | [] [] [] | xchat | [] [] [] [] [] [] [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] [] [] | +----------------------------------------------------+ fi fr ga gl gu he hi hr hu hy id is it ja ka kn 105 121 53 20 4 8 3 5 53 2 120 5 84 67 0 4 ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne +-----------------------------------------------+ a2ps | [] | aegis | | ant-phone | | anubis | [] [] | aspell | [] | bash | | bfd | | bibshelf | [] [] | binutils | | bison | [] | bison-runtime | [] [] [] [] [] | bluez-pin | [] [] [] [] [] | bombono-dvd | | buzztard | | cflow | | clisp | | coreutils | [] | cpio | | cppi | | cpplib | | cryptsetup | | dfarc | [] | dialog | [] [] [] [] [] | dico | | diffutils | [] [] | dink | | doodle | | e2fsprogs | | enscript | | exif | [] | fetchmail | | findutils | | flex | | freedink | [] | gas | | gawk | | gcal | | gcc | | gettext-examples | [] [] [] [] | gettext-runtime | [] | gettext-tools | [] | gip | [] [] | gjay | | gliv | | glunarclock | [] | gnubiff | | gnucash | () () () () | gnuedu | | gnulib | | gnunet | | gnunet-gtk | | gnutls | [] | gold | | gpe-aerial | [] | gpe-beam | [] | gpe-bluetooth | [] [] | gpe-calendar | [] | gpe-clock | [] [] [] [] [] | gpe-conf | [] [] | gpe-contacts | [] [] | gpe-edit | [] | gpe-filemanager | [] [] | gpe-go | [] [] [] | gpe-login | [] | gpe-ownerinfo | [] [] | gpe-package | [] [] | gpe-sketchbook | [] [] | gpe-su | [] [] [] [] [] [] | gpe-taskmanager | [] [] [] [] [] [] | gpe-timesheet | [] [] | gpe-today | [] [] [] [] | gpe-todo | [] [] | gphoto2 | | gprof | [] | gpsdrive | | gramadoir | | grep | | grub | | gsasl | | gss | | gst-plugins-bad | [] [] [] [] | gst-plugins-base | [] [] | gst-plugins-good | [] [] | gst-plugins-ugly | [] [] [] [] [] | gstreamer | | gtick | | gtkam | [] | gtkorphan | [] [] | gtkspell | [] [] [] [] [] [] [] | gutenprint | | hello | [] [] [] | help2man | | hylafax | | idutils | | indent | | iso_15924 | [] [] | iso_3166 | [] [] () [] [] [] [] [] | iso_3166_2 | | iso_4217 | [] [] | iso_639 | [] [] | iso_639_3 | [] | jwhois | [] | kbd | | keytouch | [] | keytouch-editor | [] | keytouch-keyboa... | [] | klavaro | [] | latrine | [] | ld | | leafpad | [] [] [] | libc | [] | libexif | | libextractor | | libgnutls | [] | libgpewidget | [] [] | libgpg-error | | libgphoto2 | | libgphoto2_port | | libgsasl | | libiconv | | libidn | | lifelines | | liferea | | lilypond | | linkdr | | lordsawar | | lprng | | lynx | | m4 | | mailfromd | | mailutils | | make | [] | man-db | | man-db-manpages | | minicom | [] | mkisofs | | myserver | | nano | [] [] | opcodes | | parted | | pies | | popt | [] [] [] | psmisc | | pspp | | pwdutils | | radius | | recode | | rosegarden | | rpm | | rush | | sarg | | screem | | scrollkeeper | [] [] | sed | | sharutils | | shishi | | skencil | | solfege | [] | solfege-manual | | soundtracker | | sp | | sysstat | [] | tar | [] | texinfo | [] | tin | | unicode-han-tra... | | unicode-transla... | | util-linux-ng | | vice | | vmm | | vorbis-tools | | wastesedge | | wdiff | | wget | [] | wyslij-po | | xchat | [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] | +-----------------------------------------------+ ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne 20 5 10 1 13 48 4 2 2 4 24 10 20 3 1 nl nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr +---------------------------------------------------+ a2ps | [] [] [] [] [] [] [] [] | aegis | [] [] [] | ant-phone | [] [] | anubis | [] [] [] | aspell | [] [] [] [] [] | bash | [] [] | bfd | [] | bibshelf | [] [] | binutils | [] [] | bison | [] [] [] | bison-runtime | [] [] [] [] [] [] [] | bluez-pin | [] [] [] [] [] [] [] [] | bombono-dvd | [] () | buzztard | [] [] | cflow | [] | clisp | [] [] | coreutils | [] [] [] [] [] [] | cpio | [] [] [] | cppi | [] | cpplib | [] | cryptsetup | [] | dfarc | [] | dialog | [] [] [] [] | dico | [] | diffutils | [] [] [] [] [] [] | dink | () | doodle | [] [] | e2fsprogs | [] [] | enscript | [] [] [] [] [] | exif | [] [] [] () [] | fetchmail | [] [] [] [] | findutils | [] [] [] [] [] | flex | [] [] [] [] [] | freedink | [] [] | gas | | gawk | [] [] [] [] | gcal | | gcc | [] | gettext-examples | [] [] [] [] [] [] [] [] | gettext-runtime | [] [] [] [] [] [] [] [] [] | gettext-tools | [] [] [] [] [] [] | gip | [] [] [] [] [] | gjay | | gliv | [] [] [] [] [] [] | glunarclock | [] [] [] [] [] | gnubiff | [] () | gnucash | [] () () () | gnuedu | [] | gnulib | [] [] [] [] | gnunet | | gnunet-gtk | | gnutls | [] [] | gold | | gpe-aerial | [] [] [] [] [] [] [] | gpe-beam | [] [] [] [] [] [] [] | gpe-bluetooth | [] [] | gpe-calendar | [] [] [] [] | gpe-clock | [] [] [] [] [] [] [] [] | gpe-conf | [] [] [] [] [] [] [] | gpe-contacts | [] [] [] [] [] | gpe-edit | [] [] [] | gpe-filemanager | [] [] [] | gpe-go | [] [] [] [] [] [] [] [] | gpe-login | [] [] | gpe-ownerinfo | [] [] [] [] [] [] [] [] | gpe-package | [] [] | gpe-sketchbook | [] [] [] [] [] [] [] | gpe-su | [] [] [] [] [] [] [] [] | gpe-taskmanager | [] [] [] [] [] [] [] [] | gpe-timesheet | [] [] [] [] [] [] [] [] | gpe-today | [] [] [] [] [] [] [] [] | gpe-todo | [] [] [] [] [] | gphoto2 | [] [] [] [] [] [] [] [] | gprof | [] [] [] | gpsdrive | [] [] | gramadoir | [] [] | grep | [] [] [] [] | grub | [] [] [] | gsasl | [] [] [] [] | gss | [] [] [] | gst-plugins-bad | [] [] [] [] [] [] | gst-plugins-base | [] [] [] [] [] | gst-plugins-good | [] [] [] [] [] | gst-plugins-ugly | [] [] [] [] [] [] | gstreamer | [] [] [] [] [] | gtick | [] [] [] | gtkam | [] [] [] [] [] [] | gtkorphan | [] | gtkspell | [] [] [] [] [] [] [] [] [] [] | gutenprint | [] [] | hello | [] [] [] [] | help2man | [] [] | hylafax | [] | idutils | [] [] [] [] [] | indent | [] [] [] [] [] [] [] | iso_15924 | [] [] [] [] | iso_3166 | [] [] [] [] [] () [] [] [] [] [] [] [] [] | iso_3166_2 | [] [] [] | iso_4217 | [] [] [] [] [] [] [] [] | iso_639 | [] [] [] [] [] [] [] [] [] | iso_639_3 | [] [] | jwhois | [] [] [] [] | kbd | [] [] [] | keytouch | [] [] [] | keytouch-editor | [] [] [] | keytouch-keyboa... | [] [] [] | klavaro | [] [] | latrine | [] [] | ld | | leafpad | [] [] [] [] [] [] [] [] [] | libc | [] [] [] [] | libexif | [] [] () [] | libextractor | | libgnutls | [] [] | libgpewidget | [] [] [] | libgpg-error | [] [] | libgphoto2 | [] [] | libgphoto2_port | [] [] [] [] [] | libgsasl | [] [] [] [] [] | libiconv | [] [] [] [] [] | libidn | [] [] | lifelines | [] [] | liferea | [] [] [] [] [] () () [] | lilypond | [] | linkdr | [] [] [] | lordsawar | | lprng | [] | lynx | [] [] [] | m4 | [] [] [] [] [] | mailfromd | [] | mailutils | [] | make | [] [] [] [] | man-db | [] [] [] | man-db-manpages | [] [] [] | minicom | [] [] [] [] | mkisofs | [] [] [] | myserver | | nano | [] [] [] [] | opcodes | [] [] | parted | [] [] [] [] | pies | [] | popt | [] [] [] [] | psmisc | [] [] [] | pspp | [] [] | pwdutils | [] | radius | [] [] [] | recode | [] [] [] [] [] [] [] [] | rosegarden | () () | rpm | [] [] [] | rush | [] [] | sarg | | screem | | scrollkeeper | [] [] [] [] [] [] [] [] | sed | [] [] [] [] [] [] [] [] [] | sharutils | [] [] [] [] | shishi | [] | skencil | [] [] | solfege | [] [] [] [] | solfege-manual | [] [] [] | soundtracker | [] | sp | | sysstat | [] [] [] [] | tar | [] [] [] [] | texinfo | [] [] [] [] | tin | [] | unicode-han-tra... | | unicode-transla... | | util-linux-ng | [] [] [] [] [] | vice | [] | vmm | [] | vorbis-tools | [] [] | wastesedge | [] | wdiff | [] [] | wget | [] [] [] [] [] [] [] | wyslij-po | [] [] [] | xchat | [] [] [] [] [] [] [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] | +---------------------------------------------------+ nl nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr 135 10 4 7 105 1 29 62 47 91 3 54 46 9 37 sv sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW +---------------------------------------------------+ a2ps | [] [] [] [] [] | 27 aegis | [] | 9 ant-phone | [] [] [] [] | 9 anubis | [] [] [] [] | 15 aspell | [] [] [] | 20 bash | [] [] [] | 12 bfd | [] | 6 bibshelf | [] [] [] | 16 binutils | [] [] | 8 bison | [] [] | 12 bison-runtime | [] [] [] [] [] [] | 29 bluez-pin | [] [] [] [] [] [] [] [] | 37 bombono-dvd | [] | 4 buzztard | [] | 7 cflow | [] [] [] | 9 clisp | | 10 coreutils | [] [] [] [] | 22 cpio | [] [] [] [] [] [] | 13 cppi | [] [] | 5 cpplib | [] [] [] [] [] [] | 14 cryptsetup | [] [] | 7 dfarc | [] | 9 dialog | [] [] [] [] [] [] [] | 30 dico | [] | 2 diffutils | [] [] [] [] [] [] | 30 dink | | 4 doodle | [] [] | 7 e2fsprogs | [] [] [] | 11 enscript | [] [] [] [] | 17 exif | [] [] [] | 16 fetchmail | [] [] [] | 17 findutils | [] [] [] [] [] | 20 flex | [] [] [] [] | 15 freedink | [] | 10 gas | [] | 4 gawk | [] [] [] [] | 18 gcal | [] [] | 5 gcc | [] [] [] | 7 gettext-examples | [] [] [] [] [] [] [] | 34 gettext-runtime | [] [] [] [] [] [] [] | 29 gettext-tools | [] [] [] [] [] [] | 22 gip | [] [] [] [] | 22 gjay | [] | 3 gliv | [] [] [] | 14 glunarclock | [] [] [] [] [] | 19 gnubiff | [] [] | 4 gnucash | () [] () [] () | 10 gnuedu | [] [] | 7 gnulib | [] [] [] [] | 16 gnunet | [] | 1 gnunet-gtk | [] [] [] | 5 gnutls | [] [] [] | 10 gold | [] | 4 gpe-aerial | [] [] [] | 18 gpe-beam | [] [] [] | 19 gpe-bluetooth | [] [] [] | 13 gpe-calendar | [] [] [] [] | 12 gpe-clock | [] [] [] [] [] | 28 gpe-conf | [] [] [] [] | 20 gpe-contacts | [] [] [] | 17 gpe-edit | [] [] [] | 12 gpe-filemanager | [] [] [] [] | 16 gpe-go | [] [] [] [] [] | 25 gpe-login | [] [] [] | 11 gpe-ownerinfo | [] [] [] [] [] | 25 gpe-package | [] [] [] | 13 gpe-sketchbook | [] [] [] | 20 gpe-su | [] [] [] [] [] | 30 gpe-taskmanager | [] [] [] [] [] | 29 gpe-timesheet | [] [] [] [] [] | 25 gpe-today | [] [] [] [] [] [] | 30 gpe-todo | [] [] [] [] | 17 gphoto2 | [] [] [] [] [] | 24 gprof | [] [] [] | 15 gpsdrive | [] [] [] | 11 gramadoir | [] [] [] | 11 grep | [] [] [] | 10 grub | [] [] [] | 14 gsasl | [] [] [] [] | 14 gss | [] [] [] | 11 gst-plugins-bad | [] [] [] [] | 26 gst-plugins-base | [] [] [] [] [] | 24 gst-plugins-good | [] [] [] [] | 24 gst-plugins-ugly | [] [] [] [] [] | 29 gstreamer | [] [] [] [] | 22 gtick | [] [] [] | 13 gtkam | [] [] [] | 20 gtkorphan | [] [] [] | 14 gtkspell | [] [] [] [] [] [] [] [] [] | 45 gutenprint | [] | 10 hello | [] [] [] [] [] [] | 21 help2man | [] [] | 7 hylafax | [] | 5 idutils | [] [] [] [] | 17 indent | [] [] [] [] [] [] | 30 iso_15924 | () [] () [] [] | 16 iso_3166 | [] [] () [] [] () [] [] [] () | 53 iso_3166_2 | () [] () [] | 9 iso_4217 | [] () [] [] () [] [] | 26 iso_639 | [] [] [] () [] () [] [] [] [] | 38 iso_639_3 | [] () | 8 jwhois | [] [] [] [] [] | 16 kbd | [] [] [] [] [] | 15 keytouch | [] [] [] | 16 keytouch-editor | [] [] [] | 14 keytouch-keyboa... | [] [] [] | 14 klavaro | [] | 11 latrine | [] [] [] | 10 ld | [] [] [] [] | 11 leafpad | [] [] [] [] [] [] | 33 libc | [] [] [] [] [] | 21 libexif | [] () | 7 libextractor | [] | 1 libgnutls | [] [] [] | 9 libgpewidget | [] [] [] | 14 libgpg-error | [] [] [] | 9 libgphoto2 | [] [] | 8 libgphoto2_port | [] [] [] [] | 14 libgsasl | [] [] [] | 13 libiconv | [] [] [] [] | 21 libidn | () [] [] | 11 lifelines | [] | 4 liferea | [] [] [] | 21 lilypond | [] | 7 linkdr | [] [] [] [] [] | 17 lordsawar | | 1 lprng | [] | 3 lynx | [] [] [] [] | 17 m4 | [] [] [] [] | 19 mailfromd | [] [] | 3 mailutils | [] | 5 make | [] [] [] [] | 21 man-db | [] [] [] | 8 man-db-manpages | | 4 minicom | [] [] | 16 mkisofs | [] [] | 9 myserver | | 0 nano | [] [] [] [] | 21 opcodes | [] [] [] | 11 parted | [] [] [] [] [] | 15 pies | [] [] | 3 popt | [] [] [] [] [] [] | 27 psmisc | [] [] | 11 pspp | | 4 pwdutils | [] [] | 6 radius | [] [] | 9 recode | [] [] [] [] | 28 rosegarden | () | 0 rpm | [] [] [] | 11 rush | [] [] | 4 sarg | | 1 screem | [] | 3 scrollkeeper | [] [] [] [] [] | 27 sed | [] [] [] [] [] | 30 sharutils | [] [] [] [] [] | 22 shishi | [] | 3 skencil | [] [] | 7 solfege | [] [] [] [] | 16 solfege-manual | [] | 8 soundtracker | [] [] [] | 9 sp | [] | 3 sysstat | [] [] | 15 tar | [] [] [] [] [] [] | 23 texinfo | [] [] [] [] [] | 17 tin | | 4 unicode-han-tra... | | 0 unicode-transla... | | 2 util-linux-ng | [] [] [] [] | 20 vice | () () | 1 vmm | [] | 4 vorbis-tools | [] | 6 wastesedge | | 2 wdiff | [] [] | 7 wget | [] [] [] [] [] | 26 wyslij-po | [] [] | 8 xchat | [] [] [] [] [] [] | 36 xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] | 63 xkeyboard-config | [] [] [] | 22 +---------------------------------------------------+ 85 teams sv sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW 178 domains 119 1 3 3 0 10 65 51 155 17 98 7 41 2618 Some counters in the preceding matrix are higher than the number of visible blocks let us expect. This is because a few extra PO files are used for implementing regional variants of languages, or language dialects. For a PO file in the matrix above to be effective, the package to which it applies should also have been internationalized and distributed as such by its maintainer. There might be an observable lag between the mere existence a PO file and its wide availability in a distribution. If June 2010 seems to be old, you may fetch a more recent copy of this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date matrix with full percentage details can be found at `http://translationproject.org/extra/matrix.html'. 1.5 Using `gettext' in new packages =================================== If you are writing a freely available program and want to internationalize it you are welcome to use GNU `gettext' in your package. Of course you have to respect the GNU Library General Public License which covers the use of the GNU `gettext' library. This means in particular that even non-free programs can use `libintl' as a shared library, whereas only free software can use `libintl' as a static library or use modified versions of `libintl'. Once the sources are changed appropriately and the setup can handle the use of `gettext' the only thing missing are the translations. The Free Translation Project is also available for packages which are not developed inside the GNU project. Therefore the information given above applies also for every other Free Software Project. Contact `coordinator@translationproject.org' to make the `.pot' files available to the translation teams. systemtap-2.3/AUTHORS000066400000000000000000000034431217430427200144650ustar00rootroot00000000000000Adrien Kunysz Alexander Lochmann Alexander Y. Fomichev Alfred Landrum Ananth N Mavinakayanahalli Andre Detsch Andreas Müller Anil Keshavamurthy Anithra Janakiraman Anton Vorontsov Atsushi Tsuji Breno Leitao Bryn M. Reeves Casey Dahlin Charles Spirakis Charley Wang Chris Meek Dan Horak Daniel Migault Daniel Tschan Dave Brolley Dave Nomura David J. Wilder David Smith Dennis Gilmore Diego Elio Pettenò Don Domingo Elliott Baron Erick Tryzelaar Eugene Teo Eugeniy Meshcheryakov Fabio Olive Leite Felix Lin Frank Ch. Eigler Frederic Turgis Fredrik Östman Grant Edwards Graydon Hoare Han Pingtian Hien Nguyen James Bottomley Jan Kratochvil Jeff Moyer Jim Keniston Jiri Horky Jiri Slaby JoeLynn Keniston Jonathan Lebon Josh Stone Jóhann B. Guðmundsson K.Prasad Kai Meyer Kapileshwar Singh (KP) Keiichi KII Kent Sebastian Kevin Stafford Kim van der Riet Kiran Prakesh Lars R. Damerow Li Guanglei Lubomir Rintel Lukas Berk Lukas Czerner Lukáš Hejtmánek Mahesh J Salgaonkar Malte Nuhn Maran Pakkirisamy Marc Milgram Mark McLoughlin Mark Wielaard Martin Hunt Martin Lazar Masami Hiramatsu Masanari Iida Maynard Johnson Michael Meeks Mike Mason Nathan Scott Negreanu Marius Adrian Nitin A Kamble Nobuhiro Tachino Otavio Pontes Peter Feiner Peter Robinson Petr Muller Phil Muldoon Prerna Saxena Przemysław Pawełczyk Rajan Arora Rajasekhar Duddu Raphaël Beamonte Rayson Ho Rich Megginson Robb Romans Robin Lee Roland Grunberg Roland McGrath Rüdiger Sonderfeld Serguei Makarov Shaohua Li Srikar Dronamraju Srinivasa DS Stan Cox Steve Dickson Sunzen Wang Thang Nguyen Theodore Ts'o Tim Moore Timo Juhani Lindfors Tom Callaway Tom Tromey Tom Zanussi Tomoki Sekiyama Tony Jones Torsten Polle Varun Chandramohan Wade Farnsworth Wenji Huang William Cohen Yang Wen Yichun Zhang (agentzh) Yoshihide Sonoda Zhaolei Zifei Tong ch huang systemtap-2.3/AUTHORS.sh000077500000000000000000000004651217430427200151020ustar00rootroot00000000000000#! /bin/sh # Create the AUTHORS file, by searching the git history. # Run as "AUTHORS.sh" to get complete history # Run with "AUTHORS.sh commitish..commitish" for history between tags # shortlog will canonicalize the names using the file .mailmap git shortlog -s ${1-} | cut -b8- # strip the commit counts systemtap-2.3/COPYING000066400000000000000000000432541217430427200144540ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. systemtap-2.3/HACKING000066400000000000000000000164511217430427200144070ustar00rootroot00000000000000This text describes contribution procedures to systemtap. Please read and understand them before jumping in. Discussions take place on the mailing list. - general Submissions should be in an easy-to-read diff/patch form, unless this is inappropriate due to size, relevance, or fraction of novel content. They should be accompanied by an explanation. The relevant test suites should be run before and after your changes, and regressions avoided, explained, or corrected. Established contributors may be considered for direct GIT write access. Other contributors should simply pack up the goods into a plain text email message to the mailing list. - obvious changes Trivial, obvious patches may be posted or committed without other formalities. - copyright You must designate the appropriate copyright holder for your contribution. If not already there, this name should be added by your patch to the copyright header in the affected files. The copyright holder is assumed to agree with the general licensing terms (GPLv2+). - coding style Abide by the general formatting of the code you are modifying. The code base generally follows the GNU standards in usermode code and the Linux kernel standards in runtime code. - commit messages In the git commit message, make the first line a brief (<=50 char) summary of the patch, and leave the second line blank. If you have trouble coming up with a concise summary, consider whether your patch might be better broken into smaller commits. For trivial changes, the summary alone may be sufficient, but most commits should include a paragraph or two giving more details about what the change is and why it is needed. Extra information like bugzilla numbers and mailing-list discussion links are appreciated as a supplement, but they are not a replacement for a real description. - test suites As far as practicable, changes should be accompanied by test cases to prevent future regressions. Tests should be run on at least x86, and ideally also on some 64-bit platform. The test suite is located under /src/testsuite and is based on dejagnu. "make check" runs unprivileged tests only against an uninstalled build tree. "make installcheck" runs all tests against an installed tree. Tests that don't require probe execution should go into new or modified files under the *{ok,ko} directories, which are scanned by corresponding systemtap.pass1-4/*.exp files. The "ko" tests are for expected (deliberate) errors. Tests that execute probes (pass 5) should include their own .exp/.stp files under any other appropriate systemtap.* testsuite subdirectory. To run a particular test or set of tests, do: cd testsuite make check RUNTESTFLAGS=testname.exp or make installcheck RUNTESTFLAGS=testname.exp To disambiguate among multiple tests with the same name, specify the directory as well -- for example: make installcheck RUNTESTFLAGS=systemtap.base/print.exp - translator Translator changes can easily invalidate tapsets and user script code. One must tread carefully and run regression tests rigorously. Both positive and negative polarity (expect-pass / expect-fail) test cases may need to be written to assert a bug fix. Script language changes should be documented in the stap.1 man page and emphasized in the NEWS file. - tapsets Tapset script files should demonstrate effective economy, and avoid conflicts with user and other tapset code. It may be necessary to prefix symbols with the tapset name to ensure systemtap-wide uniqueness. All "external interfaces" expected to be used by user scripts (or perhaps other tapsets) should be documented -- either in stapprobes.3stap if they are built into the language or otherwise somehow essential; or in kernel-doc style comments if they are defined in a tapset (see almost any existing tapset for an example of how this is done); any new tapset should be mentioned in doc/SystemTap_Tapset_Reference/tapsets.tmpl. Major or incompatible changes should be mentioned in the NEWS file; see also the deprecation section below. Internal function, variable, probe identifiers should be prefixed with "_" for extra uniqueness, and not documented in the man pages. Tapsets should come with a tests cases that provide good test coverage. Every alias definition should be tested for pass-2 correctness. Every embedded-C routine should be tested for pass-4 buildability. As they are a security hazard, every tapset embedded-C routine should be pass-5 stress-tested for response to erroneous inputs. This applies doubly to /* unprivileged */ ones. The platforms/architectures against which the tapset was tested should be published, and ideally asserted by code. Embedded-C code should avoid making references to the runtime or other code possibly generated by the translator. Embedded-C code that dereferences pointers should use deref() type functions to check each individual operation if there exists a possibility that the function may be called with invalid pointers or pointer chains. - deprecation Try to remain compatible with existing valid scripts, with respect to changes in the script language or the tapset. Where this is not practicable, preserve the old functionality using the %( systemtap_v %) preprocessor conditional in the tapset and systemtap_session.compatible in the translator. If needed, after several major releases, deprecated functionality may be dropped outright. Note both pending and final deprecation in NEWS and the permanent DEPRECATION section in stap.1. The intent is to protect old scripts for a year or longer. Tapset functions to be deprecated should be kept for at least one major release. For example, if we're in development between versions 1.2 and 1.3, wrap to-be-deprecated tapset functions or probes in %( systemtap_v <= "1.3" %? function foo() {} %) so as to preserve the tapset function during the life of the 1.3 release. Script language changes that cause earlier valid scripts to become invalid should be opt-in (requiring --compatible=NEWVERSION) for at least one major release before becoming default. For example, test strverscmp(s.compatible.c_str(), "1.4") >= 0 in the 1.3 release sources in order to activate the change. - runtime Changes to the runtime can cause problems on different architectures or kernel versions. Luckily, many code mistakes show up easily in the pass-4 tests. - meta Proposed changes to these guidelines should be discussed on the mailing list. - git basics git clone ssh://sourceware.org/git/systemtap.git # OR: use git://sourceware.org/git/systemtap.git then add to .git/config: # [remote "origin"] # pushurl=ssh://sourceware.org/git/systemtap.git # build ; hack hack hack; test git add FILE1 FILE2 # enumerate all modified or new files git status # to confirm that needed local changes are "staged" git commit # to your local repository, add nice commit message git show # to check that the last commit included all changes git pull # to make sure your copy is up to date & merged # last minute rebuild; retest git rebase origin/master # clean git commit of merge history git diff origin/master # final visual check git push # to the central one systemtap-2.3/INSTALL000066400000000000000000000224501217430427200144450ustar00rootroot00000000000000Installation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 6. Often, you can also type `make uninstall' to remove the installed files again. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of the options to `configure', and exit. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. systemtap-2.3/INTERNALS000066400000000000000000000114111217430427200146710ustar00rootroot00000000000000The Systemtap Translator - a tour on the inside Outline: - general principles - main data structures - pass 1: parsing - pass 2: semantic analysis (parts 1, 2, 3) - pass 3: translation (parts 1, 2) - pass 4: compilation - pass 5: run ------------------------------------------------------------------------ Translator general principles - written in standard C++ - mildly O-O, sparing use of C++ features - uses "visitor" concept for type-dependent (virtual) traversal ------------------------------------------------------------------------ Main data structures - abstract syntax tree - family of types and subtypes for language parts: expressions, literals, statements - includes outermost constructs: probes, aliases, functions - an instance of "stapfile" represents an entire script file - each annotated with a token (script source coordinates) - data persists throughout run - session - contains run-time parameters from command line - contains all globals - passed by reference to many functions ------------------------------------------------------------------------ Pass 1 - parsing - hand-written recursive-descent - language specified in man page - reads user-specified script file - also searches path for all <*.stp> files, parses them too - => syntax errors are caught immediately, throughout tapset - now includes baby preprocessor probe kernel. %( kernel_v == "2.6.9" %? inline("foo") %: function("bar") %) { } - enforces guru mode for embedded code %{ C %} ------------------------------------------------------------------------ Pass 2 - semantic analysis - step 1: resolve symbols - code in - want to know all global and per-probe/function local variables - one "vardecl" instance interned per variable - fills in "referent" field in AST for nodes that refer to it - collect "needed" probe/global/function list in session variable - loop over file queue, starting with user script "stapfile" - add to "needed" list this file's globals, functions, probes - resolve any symbols used in this file (function calls, variables) against "needed" list - if not resolved, search through all tapset "stapfile" instances; add to file queue if matched - if still not resolved, create as local scalar, or signal an error ------------------------------------------------------------------------ Pass 2 - semantic analysis - step 2: resolve types - fills in "type" field in AST - iterate along all probes and functions, until convergence - infer types of variables from usage context / operators: a = 5 # a is a pe_long b["foo",a]++ # b is a pe_long array with indexes pe_string and pe_long - loop until no further variable types can be inferred - signal error if any still unresolved ------------------------------------------------------------------------ Pass 2 - semantic analysis - step 3: resolve probes - probe points turned to "derived_probe" instances by code in - derived_probes know how to talk to kernel API for registration/callbacks - aliases get expanded at this point - some probe points ("begin", "end", "timer*") are very simple - dwarf ("kernel*", "module*") implementation very complicated - target-variables "$foo" expanded to getter/setter functions with synthesized embedded-C ------------------------------------------------------------------------ Pass 3 - translation - step 1: data - - we now know all types, all variables - strings are everywhere copied by value (MAXSTRINGLEN bytes) - emit data storage mega-struct "context" for all probes/functions - array instantiated per-CPU, per-nesting-level - can be pretty big static data ------------------------------------------------------------------------ Pass 3 - translation - step 2: code - map script functions to C functions taking a context pointer - map probes to two C functions: - one to interface with the probe point infrastructure (kprobes, kernel timer): reserves per-cpu context - one to implement probe body, just like a script function - emit global startup/shutdown routine to manage orderly registration/deregistration of probes - expressions/statements emitted in "natural" evaluation sequence - emit code to enforce activity-count limits, simple safety tests - global variables protected by locks global k function foo () { k ++ } # write lock around increment probe bar { if (k>5) ... } # read lock around read - same thing for arrays, except foreach/sort take longer-duration locks ------------------------------------------------------------------------ Pass 4 - compilation - - write out C code in a temporary directory - call into kbuild makefile to build module Pass 5 - running - run "staprun" - clean up temporary directory - nothing to it! systemtap-2.3/Makefile.am000066400000000000000000000334151217430427200154530ustar00rootroot00000000000000# Makefile.am --- automake input file for systemtap ## process this file with automake to produce Makefile.in # we don't maintain a ChangeLog, which makes us non-GNU -> foreign AUTOMAKE_OPTIONS = no-dist foreign pkglibexecdir = ${libexecdir}/${PACKAGE} oldincludedir = ${includedir}/sys AM_CPPFLAGS = -DBINDIR='"$(bindir)"' \ -DSYSCONFDIR='"$(sysconfdir)"' \ -DPKGDATADIR='"$(pkgdatadir)"' \ -DPKGLIBDIR='"$(pkglibexecdir)"' \ -DLOCALEDIR='"$(localedir)"' \ -I$(srcdir)/includes -I$(builddir)/includes/sys AM_CFLAGS = -D_GNU_SOURCE -fexceptions -Wall -Werror -Wunused -Wformat=2 -W AM_CXXFLAGS = -Wall -Werror bin_SCRIPTS = stap-report pkglibexec_SCRIPTS = stap-env oldinclude_HEADERS = includes/sys/sdt.h includes/sys/sdt-config.h bin_PROGRAMS = if BUILD_TRANSLATOR bin_PROGRAMS += stap bin_SCRIPTS += dtrace pkglibexec_PROGRAMS = if HAVE_NSS pkglibexec_PROGRAMS += stap-sign-module stap-authorize-cert if BUILD_SERVER pkglibexec_PROGRAMS += stap-serverd stap-gen-cert bin_SCRIPTS += stap-server pkglibexec_SCRIPTS += stap-start-server stap-stop-server endif endif stap_SOURCES = main.cxx session.cxx \ parse.cxx staptree.cxx elaborate.cxx translate.cxx \ tapsets.cxx buildrun.cxx loc2c.c hash.cxx mdfour.c \ cache.cxx util.cxx coveragedb.cxx dwarf_wrappers.cxx \ tapset-been.cxx tapset-procfs.cxx tapset-timers.cxx tapset-netfilter.cxx \ tapset-perfmon.cxx tapset-mark.cxx tapset-itrace.cxx \ tapset-utrace.cxx task_finder.cxx dwflpp.cxx rpm_finder.cxx \ setupdwfl.cxx remote.cxx privilege.cxx cmdline.cxx \ tapset-dynprobe.cxx tapset-method.cxx translator-output.cxx stap_SOURCES += stapregex.cxx stapregex-tree.cxx stapregex-parse.cxx \ stapregex-dfa.cxx noinst_HEADERS = sdt_types.h stap_LDADD = @stap_LIBS@ @sqlite3_LIBS@ @LIBINTL@ -lpthread stap_DEPENDENCIES = endif install: all $(MAKE) $(AM_MAKEFLAGS) install-recursive BUILT_SOURCES = CLEANFILES = # Arrange for git_version.h to be regenerated at every "make". # Code fragment is based upon RadeonHD.am. # The stamp file which is never created ensures that git_version.h is updated # before every build. Having git_version.h in foo_SOURCES ensures a recompile # of foo-bar.c if it is newer than the foo-bar.o file. Using noinst_foo_SOURCES # instead of foo_SOURCES prevents shipping git_version.h in dist tarballs, # which may cause false GIT_FOO readings. BUILT_SOURCES += git_version.stamp CLEANFILES += git_version.h GIT_VERSION_CMD = $(SHELL) $(top_srcdir)/git_version.sh git_version.stamp: @if test -f "$(srcdir)/git_version.h"; then \ if test -f "git_version.h"; then :; \ else \ cp "$(srcdir)/git_version.h" "git_version.h"; \ fi; \ fi $(GIT_VERSION_CMD) -k -s $(top_srcdir) -o git_version.h @if test -s "$(srcdir)/git_version.h"; then \ if cmp "$(srcdir)/git_version.h" "git_version.h"; then :; \ else \ echo "Error: $(srcdir)/git_version.h and git_version.h differ."; \ echo " You probably want to remove the former."; \ exit 1; \ fi; \ fi git_version.h: $(srcdir)/git_version.sh -k --srcdir $(srcdir) -o git_version.h cscope: cd $(srcdir) && \ (echo -q ; git ls-files '*.cxx' '*.c' '*.h' | grep -v '^testsuite' ) > cscope.files && \ cscope -b -q @DYNINST_CXXFLAGS@ PHONIES = if BUILD_TRANSLATOR stap_CFLAGS = $(AM_CFLAGS) @PIECFLAGS@ stap_CXXFLAGS = $(AM_CXXFLAGS) @PIECXXFLAGS@ stap_CPPFLAGS = $(AM_CPPFLAGS) -DSTAP_SDT_V2 stap_LDFLAGS = $(AM_LDFLAGS) @PIELDFLAGS@ if HAVE_AVAHI stap_CXXFLAGS += $(avahi_CFLAGS) stap_CPPFLAGS += $(avahi_CFLAGS) stap_LDADD += $(avahi_LIBS) endif if HAVE_NSS stap_SOURCES += nsscommon.cxx csclient.cxx cscommon.cxx stap_CFLAGS += $(nss_CFLAGS) -DSTAP stap_CXXFLAGS += $(nss_CFLAGS) stap_CPPFLAGS += $(nss_CFLAGS) stap_LDADD += $(nss_LIBS) install-exec-local: install-scripts PHONIES += install-scripts # scripts must be installed before this rule is run install-scripts: install-binSCRIPTS install-pkglibexecSCRIPTS for f in $(bin_SCRIPTS); do \ sed -i -e "s,\$${PKGLIBEXECDIR},$(pkglibexecdir)/," $(DESTDIR)$(bindir)/$$f; \ done for f in $(pkglibexec_SCRIPTS); do \ sed -i -e "/INSTALL-HOOK/d;s,sysconfdir=.*,sysconfdir=$(sysconfdir),;s,pkglibexecdir=.*,pkglibexecdir=$(pkglibexecdir)/,;s,localstatedir=.*,localstatedir=$(localstatedir),;s,\$${PKGLIBEXECDIR},$(pkglibexecdir)/," $(DESTDIR)$(pkglibexecdir)/$$f; \ done endif if BUILD_ELFUTILS stap_CPPFLAGS += -Iinclude-elfutils stap_LDFLAGS += -Llib-elfutils -Wl,-rpath-link,lib-elfutils \ -Wl,--enable-new-dtags,-rpath,$(pkglibdir) BUILT_SOURCES += stamp-elfutils CLEANFILES += stamp-elfutils stamp-elfutils: config.status $(MAKE) $(AM_MAKEFLAGS) -C build-elfutils all bin_PROGRAMS= for dir in libelf libebl libdw libdwfl backends; do \ $(MAKE) $(AM_MAKEFLAGS) -j1 -C build-elfutils/$$dir bin_PROGRAMS= install; \ done $(MAKE) $(AM_MAKEFLAGS) -j1 -C build-elfutils install-pkgincludeHEADERS; touch $@ stap_DEPENDENCIES += lib-elfutils/libdw.so lib-elfutils/libdw.so: stamp-elfutils ; PHONIES += install-elfutils install-elfutils: mkdir -p $(DESTDIR)$(pkglibdir) for file in lib-elfutils/*.so* lib-elfutils/${PACKAGE_NAME}/*.so*; do \ $(INSTALL_PROGRAM) $$file $(DESTDIR)$(pkglibdir); \ done install-exec-local: install-elfutils endif endif CLEANFILES += $(pkglibexec_PROGRAMS) if BUILD_TRANSLATOR if HAVE_NSS stap_sign_module_SOURCES = stap-sign-module.cxx nsscommon.cxx util.cxx stap_sign_module_CPPFLAGS = $(AM_CPPFLAGS) stap_sign_module_CXXFLAGS = $(AM_CXXFLAGS) @PIECXXFLAGS@ $(nss_CFLAGS) stap_sign_module_CFLAGS = $(AM_CFLAGS) @PIECFLAGS@ $(nss_CFLAGS) stap_sign_module_LDFLAGS = $(AM_LDFLAGS) @PIELDFLAGS@ stap_sign_module_LDADD = $(nss_LIBS) stap_authorize_cert_SOURCES = stap-authorize-cert.cxx nsscommon.cxx util.cxx stap_authorize_cert_CPPFLAGS = $(AM_CPPFLAGS) stap_authorize_cert_CXXFLAGS = $(AM_CXXFLAGS) @PIECXXFLAGS@ $(nss_CFLAGS) stap_authorize_cert_CFLAGS = $(AM_CFLAGS) @PIECFLAGS@ $(nss_CFLAGS) stap_authorize_cert_LDFLAGS = $(AM_LDFLAGS) @PIELDFLAGS@ stap_authorize_cert_LDADD = $(nss_LIBS) if BUILD_SERVER stap_serverd_SOURCES = stap-serverd.cxx cscommon.cxx util.cxx privilege.cxx nsscommon.cxx cmdline.cxx stap_serverd_CXXFLAGS = $(AM_CXXFLAGS) @PIECXXFLAGS@ $(nss_CFLAGS) stap_serverd_CFLAGS = $(AM_CFLAGS) @PIECFLAGS@ $(nss_CFLAGS) stap_serverd_LDFLAGS = $(AM_LDFLAGS) @PIELDFLAGS@ stap_serverd_LDADD = $(nss_LIBS) -lpthread if HAVE_AVAHI stap_serverd_CFLAGS += $(avahi_CFLAGS) stap_serverd_CXXFLAGS += $(avahi_CFLAGS) stap_serverd_LDADD += $(avahi_LIBS) endif stap_gen_cert_SOURCES = stap-gen-cert.cxx util.cxx nsscommon.cxx stap_gen_cert_CXXFLAGS = $(AM_CXXFLAGS) @PIECXXFLAGS@ $(nss_CFLAGS) stap_gen_cert_CFLAGS = $(AM_CFLAGS) @PIECFLAGS@ $(nss_CFLAGS) stap_gen_cert_LDFLAGS = $(AM_LDFLAGS) @PIELDFLAGS@ stap_gen_cert_LDADD = $(nss_LIBS) endif endif noinst_PROGRAMS = loc2c-test loc2c_test_SOURCES = loc2c-test.c loc2c.c loc2c_test_CFLAGS = $(stap_CFLAGS) loc2c_test_CPPFLAGS = $(stap_CPPFLAGS) loc2c_test_LDFLAGS = $(stap_LDFLAGS) loc2c_test_LDADD = $(stap_LDADD) endif # crash(8) extension if BUILD_CRASHMOD STAPLOG=staplog.so $(STAPLOG): staplog.c $(CC) $(staplog_CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -shared -rdynamic \ $(AM_LDFLAGS) $(LDFLAGS) -fPIC -o $@ $< all-local: $(STAPLOG) example_index install-exec-local: $(STAPLOG) $(MKDIR_P) $(DESTDIR)$(pkglibdir) $(INSTALL) $(STAPLOG) $(DESTDIR)$(pkglibdir) else all-local: example_index endif # Get extra libs as needed LDADD = EXAMPLE_SOURCE_DIR = $(srcdir)/testsuite/systemtap.examples EXAMPLE_META_FILES = $(EXAMPLE_SOURCE_DIR)/*/*.meta example_index: $(EXAMPLE_SOURCE_DIR)/index.html $(EXAMPLE_SOURCE_DIR)/index.html: $(EXAMPLE_META_FILES) $(EXAMPLE_INDEX_GEN) @echo "The script example index is outdated, run" @echo " cd $(EXAMPLE_SOURCE_DIR) && \\ " @echo " perl examples-index-gen.pl" @echo "to regenerate it." install-data-local: (cd $(srcdir)/runtime; for f in *.[ch]; do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/$$f; done) if HAVE_DYNINST (cd $(srcdir)/runtime/dyninst; find . \( -name '*.[ch]' \) -print \ | while read f; do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/dyninst/$$f; done) endif (cd $(srcdir)/runtime/unwind; find . \( -name '*.[ch]' \) -print \ | while read f; do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/unwind/$$f; done) (cd $(srcdir)/runtime/transport; for f in *.[ch]; \ do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/transport/$$f; done) (cd $(srcdir)/runtime/linux; for f in *.[ch]; \ do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/linux/$$f; done) (cd $(srcdir)/runtime/linux/uprobes; for f in Makefile *.[ch]; \ do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/linux/uprobes/$$f; done) (cd $(srcdir)/runtime/linux/uprobes2; for f in *.[ch]; \ do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/linux/uprobes2/$$f; done) (cd $(srcdir)/tapset; find . \( -name '*.stp' -o -name '*.stpm' -o -name README \) -print \ | while read f; do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/tapset/$$f; done) (cd $(srcdir)/testsuite/systemtap.examples; find . -type f -print \ | egrep -v 'check.exp|ChangeLog|examples-index-gen.pl|html/.*\.tmpl$$' \ | while read f; do if test -x $$f; then \ i_cmd="$(INSTALL_PROGRAM)"; else \ i_cmd="$(INSTALL_DATA)"; fi; \ $$i_cmd -D $$f $(DESTDIR)$(docdir)/examples/$$f; done) test -e $(DESTDIR)$(sysconfdir)/systemtap || mkdir -p $(DESTDIR)$(sysconfdir)/systemtap if BUILD_SERVER test -e $(DESTDIR)$(localstatedir)/run/stap-server || mkdir -p $(DESTDIR)$(localstatedir)/run/stap-server test -e $(DESTDIR)$(localstatedir)/log || mkdir -p $(DESTDIR)$(localstatedir)/log endif TEST_COV_DIR = coverage gcov: find . -name '*.gc*' | xargs rm -f $(MAKE) clean CXXFLAGS="-g -fprofile-arcs -ftest-coverage" CFLAGS="-g -fprofile-arcs -ftest-coverage" all install -sudo $(MAKE) installcheck $${RUNTESTFLAGS+RUNTESTFLAGS=$${RUNTESTFLAGS}} for dir in $(SUBDIRS); do \ (cd $$dir; gcov *.gcno > SUMMARY.gcov 2>&1 || true); \ done find . -name '*.gcov' clean-local: rm -rf ${PACKAGE_TARNAME}-*.tar.gz rm -rf ${PACKAGE_TARNAME}-${PACKAGE_VERSION} rm -rf $(TEST_COV_DIR) rm -rf stap.info rm -rf staplog.so distclean-local: rm -rf build-elfutils include-elfutils lib-elfutils rm -f doc/beginners/en-US doc/beginners/build/en-US/testsuite uninstall-local: rm -rf $(DESTDIR)$(pkgdatadir) rm -rf $(DESTDIR)$(libdir)/$(PACKAGE) -rm -rf $(DESTDIR)$(localstatedir)/cache/$(PACKAGE) @list='$(EXAMPLE_SRC)'; for f in $$list; do p=`basename $$f`; \ echo " rm -f '$(EXAMPLE_INSTALL_DIR)/$$p'"; \ rm -f "$(EXAMPLE_INSTALL_DIR)/$$p"; \ done @list='$(DEMO_SRC)'; for f in $$list; do p=`basename $$f`; \ echo " rm -f '$(DEMO_INSTALL_DIR)/$$p'"; \ rm -f "$(DEMO_INSTALL_DIR)/$$p"; \ done @list='$(SAMPLE_SRC)'; for f in $$list; do p=`basename $$f`; \ echo " rm -f '$(SAMPLE_INSTALL_DIR)/$$p'"; \ rm -f "$(SAMPLE_INSTALL_DIR)/$$p"; \ done rm -rf $(DESTDIR)$(sysconfdir)/systemtap rm -rf $(DESTDIR)$(docdir)/examples if BUILD_SERVER rm -rf $(DESTDIR)$(localstatedir)/run/stap-server rm -f $(DESTDIR)$(localstatedir)/log/stap-server/log endif SUBDIRS = . java stapdyn staprun re2c-migrate doc man po # NB: the gcov target above uses this to enumarate linked binaries' build directories DIST_SUBDIRS = testsuite $(SUBDIRS) EXTRA_DIST = m4/ChangeLog check-local: SRCDIR=`cd $(srcdir); pwd`; \ PWD=`pwd`; \ $(MAKE) -C testsuite check SYSTEMTAP_RUNTIME=$$SRCDIR/runtime SYSTEMTAP_TAPSET=$$SRCDIR/tapset LD_LIBRARY_PATH=$$LD_LIBRARY_PATH$${LD_LIBRARY_PATH:+:}$$PWD/lib-elfutils:$$PWD/lib-elfutils/systemtap SYSTEMTAP_PATH=$$PWD SYSTEMTAP_INCLUDES=$$PWD/includes RUNTESTFLAGS="$(RUNTESTFLAGS)" PKGLIBDIR="$(pkglibexecdir)"; installcheck: if test \! -e $(DESTDIR)$(bindir)/stap; then \ echo $(DESTDIR)$(bindir)/stap doesn\'t exist, run make install; \ exit -1; \ fi; \ if test $(builddir)/stap -nt $(DESTDIR)$(bindir)/stap; then \ echo "$(DESTDIR)$(bindir)/stap is not recent, run make install"; \ exit -1; \ fi; $(MAKE) -C testsuite installcheck RUNTESTFLAGS="$(RUNTESTFLAGS)" PHONIES += runcheck # All the variables are overridden by run-stap, but SYSTEMTAP_RUNTIME # is used by the testsuite scripts themselves. runcheck: testsuite/stap testsuite/dtrace $(MAKE) -C testsuite installcheck RUNTESTFLAGS="$(RUNTESTFLAGS)" \ SYSTEMTAP_PATH="`cd testsuite; pwd`" \ SYSTEMTAP_RUNTIME="`cd $(srcdir)/runtime; pwd`" testsuite/stap: run-stap (echo '#!/bin/sh'; echo "exec `pwd`/run-stap" '$${1+"$$@"}') > $@.new chmod 555 $@.new mv -f $@.new $@ testsuite/dtrace: dtrace (echo '#!/bin/sh'; echo "exec `pwd`/dtrace" '$${1+"$$@"}') > $@.new chmod 555 $@.new mv -f $@.new $@ PHONIES += update-po update-po: (cd $(srcdir); ls -1d *.c *.cxx *.h staprun/*.c staprun/*.h) \ | grep -v loc2c-test.c \ | grep -v config.h \ | grep -v git_version.h \ | grep -v staprun/config.h \ | sort > $(srcdir)/po/POTFILES.in $(MAKE) -C po update-po # Any extra flags, such as: # --define "with_docs 0" # --define "with_bundled_elfutils 1" --define "elfutils_version 0.135" RPMBUILDFLAGS= PHONIES += dist-gzip rpm srpm PHONIES += uprobes install-uprobes uprobes: $(MAKE) -C $(srcdir)/runtime/uprobes clean default install-uprobes: $(MAKE) -C $(DESTDIR)$(pkgdatadir)/runtime/uprobes clean default .PHONY: $(PHONIES) dist-gzip: cd $(srcdir); git status | grep working.directory.clean || (echo "You should commit your changes before 'make rpm'.") (cd $(srcdir); git archive --prefix=systemtap-$(VERSION)/ --format=tar HEAD) | gzip > systemtap-$(VERSION).tar.gz rpm: dist-gzip if [ `id -u` = 0 ]; then echo NOTE: do not run this as root; exit 1; fi mkdir -p `rpm --eval %_specdir` mkdir -p `rpm --eval %_srcrpmdir` mkdir -p `rpm --eval %_rpmdir` mkdir -p `rpm --eval %_builddir` mkdir -p `rpm --eval %_buildroot` rpmbuild --define "_sourcedir $(PWD)/" -ta systemtap-$(VERSION).tar.gz $(RPMBUILDFLAGS) srpm: dist-gzip mkdir -p `rpm --eval %_srcrpmdir` rpmbuild --define "_sourcedir $(PWD)/" -ts systemtap-$(VERSION).tar.gz $(RPMBUILDFLAGS) ACLOCAL_AMFLAGS = -I m4 systemtap-2.3/Makefile.in000066400000000000000000005202621217430427200154650ustar00rootroot00000000000000# Makefile.in generated by automake 1.12.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Makefile.am --- automake input file for systemtap VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = $(am__EXEEXT_1) @BUILD_TRANSLATOR_TRUE@am__append_1 = stap @BUILD_TRANSLATOR_TRUE@am__append_2 = dtrace @BUILD_TRANSLATOR_TRUE@pkglibexec_PROGRAMS = $(am__EXEEXT_2) \ @BUILD_TRANSLATOR_TRUE@ $(am__EXEEXT_3) @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am__append_3 = stap-sign-module stap-authorize-cert @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am__append_4 = stap-serverd stap-gen-cert @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am__append_5 = stap-server @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am__append_6 = stap-start-server stap-stop-server @BUILD_TRANSLATOR_TRUE@@HAVE_AVAHI_TRUE@am__append_7 = $(avahi_CFLAGS) @BUILD_TRANSLATOR_TRUE@@HAVE_AVAHI_TRUE@am__append_8 = $(avahi_CFLAGS) @BUILD_TRANSLATOR_TRUE@@HAVE_AVAHI_TRUE@am__append_9 = $(avahi_LIBS) @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am__append_10 = nsscommon.cxx csclient.cxx cscommon.cxx @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am__append_11 = $(nss_CFLAGS) -DSTAP @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am__append_12 = $(nss_CFLAGS) @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am__append_13 = $(nss_CFLAGS) @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am__append_14 = $(nss_LIBS) @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am__append_15 = install-scripts @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@am__append_16 = -Iinclude-elfutils @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@am__append_17 = -Llib-elfutils -Wl,-rpath-link,lib-elfutils \ @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@ -Wl,--enable-new-dtags,-rpath,$(pkglibdir) @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@am__append_18 = stamp-elfutils @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@am__append_19 = stamp-elfutils @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@am__append_20 = lib-elfutils/libdw.so @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@am__append_21 = install-elfutils @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_AVAHI_TRUE@@HAVE_NSS_TRUE@am__append_22 = $(avahi_CFLAGS) @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_AVAHI_TRUE@@HAVE_NSS_TRUE@am__append_23 = $(avahi_CFLAGS) @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_AVAHI_TRUE@@HAVE_NSS_TRUE@am__append_24 = $(avahi_LIBS) @BUILD_TRANSLATOR_TRUE@noinst_PROGRAMS = loc2c-test$(EXEEXT) subdir = . DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/configure $(am__configure_deps) \ $(srcdir)/config.in $(top_srcdir)/includes/sys/sdt-config.h.in \ $(top_srcdir)/initscript/config.systemtap.in \ $(top_srcdir)/initscript/config.stap-server.in \ $(top_srcdir)/initscript/systemtap.in \ $(top_srcdir)/initscript/stap-server.in $(srcdir)/run-stap.in \ $(srcdir)/dtrace.in depcomp $(am__noinst_HEADERS_DIST) \ $(oldinclude_HEADERS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = includes/sys/sdt-config.h \ initscript/config.systemtap initscript/config.stap-server \ initscript/systemtap initscript/stap-server run-stap dtrace CONFIG_CLEAN_VPATH_FILES = @BUILD_TRANSLATOR_TRUE@am__EXEEXT_1 = stap$(EXEEXT) am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkglibexecdir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkglibexecdir)" \ "$(DESTDIR)$(oldincludedir)" @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am__EXEEXT_2 = stap-sign-module$(EXEEXT) \ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ stap-authorize-cert$(EXEEXT) @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am__EXEEXT_3 = stap-serverd$(EXEEXT) \ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ stap-gen-cert$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) $(pkglibexec_PROGRAMS) @BUILD_TRANSLATOR_TRUE@am_loc2c_test_OBJECTS = \ @BUILD_TRANSLATOR_TRUE@ loc2c_test-loc2c-test.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ loc2c_test-loc2c.$(OBJEXT) loc2c_test_OBJECTS = $(am_loc2c_test_OBJECTS) am__DEPENDENCIES_1 = @BUILD_TRANSLATOR_TRUE@@HAVE_AVAHI_TRUE@am__DEPENDENCIES_2 = \ @BUILD_TRANSLATOR_TRUE@@HAVE_AVAHI_TRUE@ $(am__DEPENDENCIES_1) @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am__DEPENDENCIES_3 = \ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ $(am__DEPENDENCIES_1) @BUILD_TRANSLATOR_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_2) \ @BUILD_TRANSLATOR_TRUE@ $(am__DEPENDENCIES_3) @BUILD_TRANSLATOR_TRUE@loc2c_test_DEPENDENCIES = \ @BUILD_TRANSLATOR_TRUE@ $(am__DEPENDENCIES_4) loc2c_test_LINK = $(CCLD) $(loc2c_test_CFLAGS) $(CFLAGS) \ $(loc2c_test_LDFLAGS) $(LDFLAGS) -o $@ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am__objects_1 = stap-nsscommon.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ stap-csclient.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ stap-cscommon.$(OBJEXT) @BUILD_TRANSLATOR_TRUE@am_stap_OBJECTS = stap-main.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-session.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-parse.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-staptree.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-elaborate.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-translate.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-tapsets.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-buildrun.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-loc2c.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-hash.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-mdfour.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-cache.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-util.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-coveragedb.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-dwarf_wrappers.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-tapset-been.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-tapset-procfs.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-tapset-timers.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-tapset-netfilter.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-tapset-perfmon.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-tapset-mark.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-tapset-itrace.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-tapset-utrace.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-task_finder.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-dwflpp.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-rpm_finder.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-setupdwfl.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-remote.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-privilege.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-cmdline.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-tapset-dynprobe.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-tapset-method.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-translator-output.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-stapregex.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-stapregex-tree.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-stapregex-parse.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ stap-stapregex-dfa.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@ $(am__objects_1) stap_OBJECTS = $(am_stap_OBJECTS) stap_LINK = $(CXXLD) $(stap_CXXFLAGS) $(CXXFLAGS) $(stap_LDFLAGS) \ $(LDFLAGS) -o $@ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am_stap_authorize_cert_OBJECTS = stap_authorize_cert-stap-authorize-cert.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ stap_authorize_cert-nsscommon.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ stap_authorize_cert-util.$(OBJEXT) stap_authorize_cert_OBJECTS = $(am_stap_authorize_cert_OBJECTS) @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_authorize_cert_DEPENDENCIES = \ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ $(am__DEPENDENCIES_1) stap_authorize_cert_LINK = $(CXXLD) $(stap_authorize_cert_CXXFLAGS) \ $(CXXFLAGS) $(stap_authorize_cert_LDFLAGS) $(LDFLAGS) -o $@ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am_stap_gen_cert_OBJECTS = stap_gen_cert-stap-gen-cert.$(OBJEXT) \ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ stap_gen_cert-util.$(OBJEXT) \ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ stap_gen_cert-nsscommon.$(OBJEXT) stap_gen_cert_OBJECTS = $(am_stap_gen_cert_OBJECTS) @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_gen_cert_DEPENDENCIES = $(am__DEPENDENCIES_1) stap_gen_cert_LINK = $(CXXLD) $(stap_gen_cert_CXXFLAGS) $(CXXFLAGS) \ $(stap_gen_cert_LDFLAGS) $(LDFLAGS) -o $@ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am_stap_serverd_OBJECTS = stap_serverd-stap-serverd.$(OBJEXT) \ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ stap_serverd-cscommon.$(OBJEXT) \ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ stap_serverd-util.$(OBJEXT) \ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ stap_serverd-privilege.$(OBJEXT) \ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ stap_serverd-nsscommon.$(OBJEXT) \ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ stap_serverd-cmdline.$(OBJEXT) stap_serverd_OBJECTS = $(am_stap_serverd_OBJECTS) @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_AVAHI_TRUE@@HAVE_NSS_TRUE@am__DEPENDENCIES_5 = $(am__DEPENDENCIES_1) @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_serverd_DEPENDENCIES = $(am__DEPENDENCIES_1) \ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ $(am__DEPENDENCIES_5) stap_serverd_LINK = $(CXXLD) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) \ $(stap_serverd_LDFLAGS) $(LDFLAGS) -o $@ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@am_stap_sign_module_OBJECTS = stap_sign_module-stap-sign-module.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ stap_sign_module-nsscommon.$(OBJEXT) \ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ stap_sign_module-util.$(OBJEXT) stap_sign_module_OBJECTS = $(am_stap_sign_module_OBJECTS) @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_sign_module_DEPENDENCIES = \ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ $(am__DEPENDENCIES_1) stap_sign_module_LINK = $(CXXLD) $(stap_sign_module_CXXFLAGS) \ $(CXXFLAGS) $(stap_sign_module_LDFLAGS) $(LDFLAGS) -o $@ am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } SCRIPTS = $(bin_SCRIPTS) $(pkglibexec_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(loc2c_test_SOURCES) $(stap_SOURCES) \ $(stap_authorize_cert_SOURCES) $(stap_gen_cert_SOURCES) \ $(stap_serverd_SOURCES) $(stap_sign_module_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__noinst_HEADERS_DIST = sdt_types.h HEADERS = $(noinst_HEADERS) $(oldinclude_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ cscope ETAGS = etags CTAGS = ctags CSCOPE = cscope pkglibexecdir = ${libexecdir}/${PACKAGE} ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DATE = @DATE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DYNINST_CXXFLAGS = @DYNINST_CXXFLAGS@ DYNINST_LDFLAGS = @DYNINST_LDFLAGS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_NLS = @ENABLE_NLS@ EXEEXT = @EXEEXT@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ JAVADIR = @JAVADIR@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PIECFLAGS = @PIECFLAGS@ PIECXXFLAGS = @PIECXXFLAGS@ PIELDFLAGS = @PIELDFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POSUB = @POSUB@ PUBLICAN_BRAND = @PUBLICAN_BRAND@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STAP_EXTRA_VERSION = @STAP_EXTRA_VERSION@ STAP_PREFIX = @STAP_PREFIX@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ elfutils_abs_srcdir = @elfutils_abs_srcdir@ exec_prefix = @exec_prefix@ have_dvips = @have_dvips@ have_fop = @have_fop@ have_jar = @have_jar@ have_javac = @have_javac@ have_latex = @have_latex@ have_latex2html = @have_latex2html@ have_ps2pdf = @have_ps2pdf@ have_publican = @have_publican@ have_xmlto = @have_xmlto@ have_xvfb = @have_xvfb@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ nss_CFLAGS = @nss_CFLAGS@ nss_LIBS = @nss_LIBS@ oldincludedir = ${includedir}/sys pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ selinux_CFLAGS = @selinux_CFLAGS@ selinux_LIBS = @selinux_LIBS@ sharedstatedir = @sharedstatedir@ sqlite3_LIBS = @sqlite3_LIBS@ srcdir = @srcdir@ stap_LIBS = @stap_LIBS@ staplog_CPPFLAGS = @staplog_CPPFLAGS@ staprun_LIBS = @staprun_LIBS@ subdirs = @subdirs@ support_section_question = @support_section_question@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # we don't maintain a ChangeLog, which makes us non-GNU -> foreign AUTOMAKE_OPTIONS = no-dist foreign AM_CPPFLAGS = -DBINDIR='"$(bindir)"' \ -DSYSCONFDIR='"$(sysconfdir)"' \ -DPKGDATADIR='"$(pkgdatadir)"' \ -DPKGLIBDIR='"$(pkglibexecdir)"' \ -DLOCALEDIR='"$(localedir)"' \ -I$(srcdir)/includes -I$(builddir)/includes/sys AM_CFLAGS = -D_GNU_SOURCE -fexceptions -Wall -Werror -Wunused -Wformat=2 -W AM_CXXFLAGS = -Wall -Werror bin_SCRIPTS = stap-report $(am__append_2) $(am__append_5) pkglibexec_SCRIPTS = stap-env $(am__append_6) oldinclude_HEADERS = includes/sys/sdt.h includes/sys/sdt-config.h @BUILD_TRANSLATOR_TRUE@stap_SOURCES = main.cxx session.cxx parse.cxx \ @BUILD_TRANSLATOR_TRUE@ staptree.cxx elaborate.cxx \ @BUILD_TRANSLATOR_TRUE@ translate.cxx tapsets.cxx buildrun.cxx \ @BUILD_TRANSLATOR_TRUE@ loc2c.c hash.cxx mdfour.c cache.cxx \ @BUILD_TRANSLATOR_TRUE@ util.cxx coveragedb.cxx \ @BUILD_TRANSLATOR_TRUE@ dwarf_wrappers.cxx tapset-been.cxx \ @BUILD_TRANSLATOR_TRUE@ tapset-procfs.cxx tapset-timers.cxx \ @BUILD_TRANSLATOR_TRUE@ tapset-netfilter.cxx tapset-perfmon.cxx \ @BUILD_TRANSLATOR_TRUE@ tapset-mark.cxx tapset-itrace.cxx \ @BUILD_TRANSLATOR_TRUE@ tapset-utrace.cxx task_finder.cxx \ @BUILD_TRANSLATOR_TRUE@ dwflpp.cxx rpm_finder.cxx setupdwfl.cxx \ @BUILD_TRANSLATOR_TRUE@ remote.cxx privilege.cxx cmdline.cxx \ @BUILD_TRANSLATOR_TRUE@ tapset-dynprobe.cxx tapset-method.cxx \ @BUILD_TRANSLATOR_TRUE@ translator-output.cxx stapregex.cxx \ @BUILD_TRANSLATOR_TRUE@ stapregex-tree.cxx stapregex-parse.cxx \ @BUILD_TRANSLATOR_TRUE@ stapregex-dfa.cxx $(am__append_10) @BUILD_TRANSLATOR_TRUE@noinst_HEADERS = sdt_types.h @BUILD_TRANSLATOR_TRUE@stap_LDADD = @stap_LIBS@ @sqlite3_LIBS@ \ @BUILD_TRANSLATOR_TRUE@ @LIBINTL@ -lpthread $(am__append_9) \ @BUILD_TRANSLATOR_TRUE@ $(am__append_14) @BUILD_TRANSLATOR_TRUE@stap_DEPENDENCIES = $(am__append_20) # Arrange for git_version.h to be regenerated at every "make". # Code fragment is based upon RadeonHD.am. # The stamp file which is never created ensures that git_version.h is updated # before every build. Having git_version.h in foo_SOURCES ensures a recompile # of foo-bar.c if it is newer than the foo-bar.o file. Using noinst_foo_SOURCES # instead of foo_SOURCES prevents shipping git_version.h in dist tarballs, # which may cause false GIT_FOO readings. BUILT_SOURCES = git_version.stamp $(am__append_18) CLEANFILES = git_version.h $(am__append_19) $(pkglibexec_PROGRAMS) GIT_VERSION_CMD = $(SHELL) $(top_srcdir)/git_version.sh PHONIES = $(am__append_15) $(am__append_21) runcheck update-po \ dist-gzip rpm srpm uprobes install-uprobes @BUILD_TRANSLATOR_TRUE@stap_CFLAGS = $(AM_CFLAGS) @PIECFLAGS@ \ @BUILD_TRANSLATOR_TRUE@ $(am__append_11) @BUILD_TRANSLATOR_TRUE@stap_CXXFLAGS = $(AM_CXXFLAGS) @PIECXXFLAGS@ \ @BUILD_TRANSLATOR_TRUE@ $(am__append_7) $(am__append_12) @BUILD_TRANSLATOR_TRUE@stap_CPPFLAGS = $(AM_CPPFLAGS) -DSTAP_SDT_V2 \ @BUILD_TRANSLATOR_TRUE@ $(am__append_8) $(am__append_13) \ @BUILD_TRANSLATOR_TRUE@ $(am__append_16) @BUILD_TRANSLATOR_TRUE@stap_LDFLAGS = $(AM_LDFLAGS) @PIELDFLAGS@ \ @BUILD_TRANSLATOR_TRUE@ $(am__append_17) @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_sign_module_SOURCES = stap-sign-module.cxx nsscommon.cxx util.cxx @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_sign_module_CPPFLAGS = $(AM_CPPFLAGS) @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_sign_module_CXXFLAGS = $(AM_CXXFLAGS) @PIECXXFLAGS@ $(nss_CFLAGS) @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_sign_module_CFLAGS = $(AM_CFLAGS) @PIECFLAGS@ $(nss_CFLAGS) @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_sign_module_LDFLAGS = $(AM_LDFLAGS) @PIELDFLAGS@ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_sign_module_LDADD = $(nss_LIBS) @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_authorize_cert_SOURCES = stap-authorize-cert.cxx nsscommon.cxx util.cxx @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_authorize_cert_CPPFLAGS = $(AM_CPPFLAGS) @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_authorize_cert_CXXFLAGS = $(AM_CXXFLAGS) @PIECXXFLAGS@ $(nss_CFLAGS) @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_authorize_cert_CFLAGS = $(AM_CFLAGS) @PIECFLAGS@ $(nss_CFLAGS) @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_authorize_cert_LDFLAGS = $(AM_LDFLAGS) @PIELDFLAGS@ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_authorize_cert_LDADD = $(nss_LIBS) @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_serverd_SOURCES = stap-serverd.cxx cscommon.cxx util.cxx privilege.cxx nsscommon.cxx cmdline.cxx @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_serverd_CXXFLAGS = $(AM_CXXFLAGS) \ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ @PIECXXFLAGS@ \ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ $(nss_CFLAGS) \ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ $(am__append_23) @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_serverd_CFLAGS = $(AM_CFLAGS) \ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ @PIECFLAGS@ \ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ $(nss_CFLAGS) \ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ $(am__append_22) @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_serverd_LDFLAGS = $(AM_LDFLAGS) @PIELDFLAGS@ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_serverd_LDADD = $(nss_LIBS) \ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ -lpthread \ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ $(am__append_24) @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_gen_cert_SOURCES = stap-gen-cert.cxx util.cxx nsscommon.cxx @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_gen_cert_CXXFLAGS = $(AM_CXXFLAGS) @PIECXXFLAGS@ $(nss_CFLAGS) @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_gen_cert_CFLAGS = $(AM_CFLAGS) @PIECFLAGS@ $(nss_CFLAGS) @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_gen_cert_LDFLAGS = $(AM_LDFLAGS) @PIELDFLAGS@ @BUILD_SERVER_TRUE@@BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@stap_gen_cert_LDADD = $(nss_LIBS) @BUILD_TRANSLATOR_TRUE@loc2c_test_SOURCES = loc2c-test.c loc2c.c @BUILD_TRANSLATOR_TRUE@loc2c_test_CFLAGS = $(stap_CFLAGS) @BUILD_TRANSLATOR_TRUE@loc2c_test_CPPFLAGS = $(stap_CPPFLAGS) @BUILD_TRANSLATOR_TRUE@loc2c_test_LDFLAGS = $(stap_LDFLAGS) @BUILD_TRANSLATOR_TRUE@loc2c_test_LDADD = $(stap_LDADD) # crash(8) extension @BUILD_CRASHMOD_TRUE@STAPLOG = staplog.so # Get extra libs as needed LDADD = EXAMPLE_SOURCE_DIR = $(srcdir)/testsuite/systemtap.examples EXAMPLE_META_FILES = $(EXAMPLE_SOURCE_DIR)/*/*.meta TEST_COV_DIR = coverage SUBDIRS = . java stapdyn staprun re2c-migrate doc man po # NB: the gcov target above uses this to enumarate linked binaries' build directories DIST_SUBDIRS = testsuite $(SUBDIRS) EXTRA_DIST = m4/ChangeLog # Any extra flags, such as: # --define "with_docs 0" # --define "with_bundled_elfutils 1" --define "elfutils_version 0.135" RPMBUILDFLAGS = ACLOCAL_AMFLAGS = -I m4 all: $(BUILT_SOURCES) config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: .SUFFIXES: .c .cxx .o .obj am--refresh: Makefile @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @if test ! -f $@; then rm -f stamp-h1; else :; fi @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi stamp-h1: $(srcdir)/config.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 includes/sys/sdt-config.h: $(top_builddir)/config.status $(top_srcdir)/includes/sys/sdt-config.h.in cd $(top_builddir) && $(SHELL) ./config.status $@ initscript/config.systemtap: $(top_builddir)/config.status $(top_srcdir)/initscript/config.systemtap.in cd $(top_builddir) && $(SHELL) ./config.status $@ initscript/config.stap-server: $(top_builddir)/config.status $(top_srcdir)/initscript/config.stap-server.in cd $(top_builddir) && $(SHELL) ./config.status $@ initscript/systemtap: $(top_builddir)/config.status $(top_srcdir)/initscript/systemtap.in cd $(top_builddir) && $(SHELL) ./config.status $@ initscript/stap-server: $(top_builddir)/config.status $(top_srcdir)/initscript/stap-server.in cd $(top_builddir) && $(SHELL) ./config.status $@ run-stap: $(top_builddir)/config.status $(srcdir)/run-stap.in cd $(top_builddir) && $(SHELL) ./config.status $@ dtrace: $(top_builddir)/config.status $(srcdir)/dtrace.in cd $(top_builddir) && $(SHELL) ./config.status $@ install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) install-pkglibexecPROGRAMS: $(pkglibexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(pkglibexec_PROGRAMS)'; test -n "$(pkglibexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkglibexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(pkglibexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(pkglibexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-pkglibexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(pkglibexec_PROGRAMS)'; test -n "$(pkglibexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(pkglibexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(pkglibexecdir)" && rm -f $$files clean-pkglibexecPROGRAMS: -test -z "$(pkglibexec_PROGRAMS)" || rm -f $(pkglibexec_PROGRAMS) loc2c-test$(EXEEXT): $(loc2c_test_OBJECTS) $(loc2c_test_DEPENDENCIES) $(EXTRA_loc2c_test_DEPENDENCIES) @rm -f loc2c-test$(EXEEXT) $(AM_V_CCLD)$(loc2c_test_LINK) $(loc2c_test_OBJECTS) $(loc2c_test_LDADD) $(LIBS) stap$(EXEEXT): $(stap_OBJECTS) $(stap_DEPENDENCIES) $(EXTRA_stap_DEPENDENCIES) @rm -f stap$(EXEEXT) $(AM_V_CXXLD)$(stap_LINK) $(stap_OBJECTS) $(stap_LDADD) $(LIBS) stap-authorize-cert$(EXEEXT): $(stap_authorize_cert_OBJECTS) $(stap_authorize_cert_DEPENDENCIES) $(EXTRA_stap_authorize_cert_DEPENDENCIES) @rm -f stap-authorize-cert$(EXEEXT) $(AM_V_CXXLD)$(stap_authorize_cert_LINK) $(stap_authorize_cert_OBJECTS) $(stap_authorize_cert_LDADD) $(LIBS) stap-gen-cert$(EXEEXT): $(stap_gen_cert_OBJECTS) $(stap_gen_cert_DEPENDENCIES) $(EXTRA_stap_gen_cert_DEPENDENCIES) @rm -f stap-gen-cert$(EXEEXT) $(AM_V_CXXLD)$(stap_gen_cert_LINK) $(stap_gen_cert_OBJECTS) $(stap_gen_cert_LDADD) $(LIBS) stap-serverd$(EXEEXT): $(stap_serverd_OBJECTS) $(stap_serverd_DEPENDENCIES) $(EXTRA_stap_serverd_DEPENDENCIES) @rm -f stap-serverd$(EXEEXT) $(AM_V_CXXLD)$(stap_serverd_LINK) $(stap_serverd_OBJECTS) $(stap_serverd_LDADD) $(LIBS) stap-sign-module$(EXEEXT): $(stap_sign_module_OBJECTS) $(stap_sign_module_DEPENDENCIES) $(EXTRA_stap_sign_module_DEPENDENCIES) @rm -f stap-sign-module$(EXEEXT) $(AM_V_CXXLD)$(stap_sign_module_LINK) $(stap_sign_module_OBJECTS) $(stap_sign_module_LDADD) $(LIBS) install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) install-pkglibexecSCRIPTS: $(pkglibexec_SCRIPTS) @$(NORMAL_INSTALL) @list='$(pkglibexec_SCRIPTS)'; test -n "$(pkglibexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkglibexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibexecdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(pkglibexecdir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(pkglibexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-pkglibexecSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(pkglibexec_SCRIPTS)'; test -n "$(pkglibexecdir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(pkglibexecdir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loc2c_test-loc2c-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loc2c_test-loc2c.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-buildrun.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-cache.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-cmdline.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-coveragedb.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-csclient.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-cscommon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-dwarf_wrappers.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-dwflpp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-elaborate.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-hash.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-loc2c.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-mdfour.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-nsscommon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-parse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-privilege.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-remote.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-rpm_finder.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-session.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-setupdwfl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-stapregex-dfa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-stapregex-parse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-stapregex-tree.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-stapregex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-staptree.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapset-been.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapset-dynprobe.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapset-itrace.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapset-mark.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapset-method.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapset-netfilter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapset-perfmon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapset-procfs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapset-timers.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapset-utrace.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapsets.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-task_finder.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-translate.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-translator-output.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap_authorize_cert-nsscommon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap_authorize_cert-stap-authorize-cert.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap_authorize_cert-util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap_gen_cert-nsscommon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap_gen_cert-stap-gen-cert.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap_gen_cert-util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap_serverd-cmdline.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap_serverd-cscommon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap_serverd-nsscommon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap_serverd-privilege.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap_serverd-stap-serverd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap_serverd-util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap_sign_module-nsscommon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap_sign_module-stap-sign-module.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap_sign_module-util.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` loc2c_test-loc2c-test.o: loc2c-test.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(loc2c_test_CPPFLAGS) $(CPPFLAGS) $(loc2c_test_CFLAGS) $(CFLAGS) -MT loc2c_test-loc2c-test.o -MD -MP -MF $(DEPDIR)/loc2c_test-loc2c-test.Tpo -c -o loc2c_test-loc2c-test.o `test -f 'loc2c-test.c' || echo '$(srcdir)/'`loc2c-test.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/loc2c_test-loc2c-test.Tpo $(DEPDIR)/loc2c_test-loc2c-test.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='loc2c-test.c' object='loc2c_test-loc2c-test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(loc2c_test_CPPFLAGS) $(CPPFLAGS) $(loc2c_test_CFLAGS) $(CFLAGS) -c -o loc2c_test-loc2c-test.o `test -f 'loc2c-test.c' || echo '$(srcdir)/'`loc2c-test.c loc2c_test-loc2c-test.obj: loc2c-test.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(loc2c_test_CPPFLAGS) $(CPPFLAGS) $(loc2c_test_CFLAGS) $(CFLAGS) -MT loc2c_test-loc2c-test.obj -MD -MP -MF $(DEPDIR)/loc2c_test-loc2c-test.Tpo -c -o loc2c_test-loc2c-test.obj `if test -f 'loc2c-test.c'; then $(CYGPATH_W) 'loc2c-test.c'; else $(CYGPATH_W) '$(srcdir)/loc2c-test.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/loc2c_test-loc2c-test.Tpo $(DEPDIR)/loc2c_test-loc2c-test.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='loc2c-test.c' object='loc2c_test-loc2c-test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(loc2c_test_CPPFLAGS) $(CPPFLAGS) $(loc2c_test_CFLAGS) $(CFLAGS) -c -o loc2c_test-loc2c-test.obj `if test -f 'loc2c-test.c'; then $(CYGPATH_W) 'loc2c-test.c'; else $(CYGPATH_W) '$(srcdir)/loc2c-test.c'; fi` loc2c_test-loc2c.o: loc2c.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(loc2c_test_CPPFLAGS) $(CPPFLAGS) $(loc2c_test_CFLAGS) $(CFLAGS) -MT loc2c_test-loc2c.o -MD -MP -MF $(DEPDIR)/loc2c_test-loc2c.Tpo -c -o loc2c_test-loc2c.o `test -f 'loc2c.c' || echo '$(srcdir)/'`loc2c.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/loc2c_test-loc2c.Tpo $(DEPDIR)/loc2c_test-loc2c.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='loc2c.c' object='loc2c_test-loc2c.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(loc2c_test_CPPFLAGS) $(CPPFLAGS) $(loc2c_test_CFLAGS) $(CFLAGS) -c -o loc2c_test-loc2c.o `test -f 'loc2c.c' || echo '$(srcdir)/'`loc2c.c loc2c_test-loc2c.obj: loc2c.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(loc2c_test_CPPFLAGS) $(CPPFLAGS) $(loc2c_test_CFLAGS) $(CFLAGS) -MT loc2c_test-loc2c.obj -MD -MP -MF $(DEPDIR)/loc2c_test-loc2c.Tpo -c -o loc2c_test-loc2c.obj `if test -f 'loc2c.c'; then $(CYGPATH_W) 'loc2c.c'; else $(CYGPATH_W) '$(srcdir)/loc2c.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/loc2c_test-loc2c.Tpo $(DEPDIR)/loc2c_test-loc2c.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='loc2c.c' object='loc2c_test-loc2c.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(loc2c_test_CPPFLAGS) $(CPPFLAGS) $(loc2c_test_CFLAGS) $(CFLAGS) -c -o loc2c_test-loc2c.obj `if test -f 'loc2c.c'; then $(CYGPATH_W) 'loc2c.c'; else $(CYGPATH_W) '$(srcdir)/loc2c.c'; fi` stap-loc2c.o: loc2c.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CFLAGS) $(CFLAGS) -MT stap-loc2c.o -MD -MP -MF $(DEPDIR)/stap-loc2c.Tpo -c -o stap-loc2c.o `test -f 'loc2c.c' || echo '$(srcdir)/'`loc2c.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-loc2c.Tpo $(DEPDIR)/stap-loc2c.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='loc2c.c' object='stap-loc2c.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CFLAGS) $(CFLAGS) -c -o stap-loc2c.o `test -f 'loc2c.c' || echo '$(srcdir)/'`loc2c.c stap-loc2c.obj: loc2c.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CFLAGS) $(CFLAGS) -MT stap-loc2c.obj -MD -MP -MF $(DEPDIR)/stap-loc2c.Tpo -c -o stap-loc2c.obj `if test -f 'loc2c.c'; then $(CYGPATH_W) 'loc2c.c'; else $(CYGPATH_W) '$(srcdir)/loc2c.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-loc2c.Tpo $(DEPDIR)/stap-loc2c.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='loc2c.c' object='stap-loc2c.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CFLAGS) $(CFLAGS) -c -o stap-loc2c.obj `if test -f 'loc2c.c'; then $(CYGPATH_W) 'loc2c.c'; else $(CYGPATH_W) '$(srcdir)/loc2c.c'; fi` stap-mdfour.o: mdfour.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CFLAGS) $(CFLAGS) -MT stap-mdfour.o -MD -MP -MF $(DEPDIR)/stap-mdfour.Tpo -c -o stap-mdfour.o `test -f 'mdfour.c' || echo '$(srcdir)/'`mdfour.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-mdfour.Tpo $(DEPDIR)/stap-mdfour.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mdfour.c' object='stap-mdfour.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CFLAGS) $(CFLAGS) -c -o stap-mdfour.o `test -f 'mdfour.c' || echo '$(srcdir)/'`mdfour.c stap-mdfour.obj: mdfour.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CFLAGS) $(CFLAGS) -MT stap-mdfour.obj -MD -MP -MF $(DEPDIR)/stap-mdfour.Tpo -c -o stap-mdfour.obj `if test -f 'mdfour.c'; then $(CYGPATH_W) 'mdfour.c'; else $(CYGPATH_W) '$(srcdir)/mdfour.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-mdfour.Tpo $(DEPDIR)/stap-mdfour.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mdfour.c' object='stap-mdfour.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CFLAGS) $(CFLAGS) -c -o stap-mdfour.obj `if test -f 'mdfour.c'; then $(CYGPATH_W) 'mdfour.c'; else $(CYGPATH_W) '$(srcdir)/mdfour.c'; fi` .cxx.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cxx.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` stap-main.o: main.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-main.o -MD -MP -MF $(DEPDIR)/stap-main.Tpo -c -o stap-main.o `test -f 'main.cxx' || echo '$(srcdir)/'`main.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-main.Tpo $(DEPDIR)/stap-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='main.cxx' object='stap-main.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-main.o `test -f 'main.cxx' || echo '$(srcdir)/'`main.cxx stap-main.obj: main.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-main.obj -MD -MP -MF $(DEPDIR)/stap-main.Tpo -c -o stap-main.obj `if test -f 'main.cxx'; then $(CYGPATH_W) 'main.cxx'; else $(CYGPATH_W) '$(srcdir)/main.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-main.Tpo $(DEPDIR)/stap-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='main.cxx' object='stap-main.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-main.obj `if test -f 'main.cxx'; then $(CYGPATH_W) 'main.cxx'; else $(CYGPATH_W) '$(srcdir)/main.cxx'; fi` stap-session.o: session.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-session.o -MD -MP -MF $(DEPDIR)/stap-session.Tpo -c -o stap-session.o `test -f 'session.cxx' || echo '$(srcdir)/'`session.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-session.Tpo $(DEPDIR)/stap-session.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='session.cxx' object='stap-session.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-session.o `test -f 'session.cxx' || echo '$(srcdir)/'`session.cxx stap-session.obj: session.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-session.obj -MD -MP -MF $(DEPDIR)/stap-session.Tpo -c -o stap-session.obj `if test -f 'session.cxx'; then $(CYGPATH_W) 'session.cxx'; else $(CYGPATH_W) '$(srcdir)/session.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-session.Tpo $(DEPDIR)/stap-session.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='session.cxx' object='stap-session.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-session.obj `if test -f 'session.cxx'; then $(CYGPATH_W) 'session.cxx'; else $(CYGPATH_W) '$(srcdir)/session.cxx'; fi` stap-parse.o: parse.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-parse.o -MD -MP -MF $(DEPDIR)/stap-parse.Tpo -c -o stap-parse.o `test -f 'parse.cxx' || echo '$(srcdir)/'`parse.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-parse.Tpo $(DEPDIR)/stap-parse.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='parse.cxx' object='stap-parse.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-parse.o `test -f 'parse.cxx' || echo '$(srcdir)/'`parse.cxx stap-parse.obj: parse.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-parse.obj -MD -MP -MF $(DEPDIR)/stap-parse.Tpo -c -o stap-parse.obj `if test -f 'parse.cxx'; then $(CYGPATH_W) 'parse.cxx'; else $(CYGPATH_W) '$(srcdir)/parse.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-parse.Tpo $(DEPDIR)/stap-parse.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='parse.cxx' object='stap-parse.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-parse.obj `if test -f 'parse.cxx'; then $(CYGPATH_W) 'parse.cxx'; else $(CYGPATH_W) '$(srcdir)/parse.cxx'; fi` stap-staptree.o: staptree.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-staptree.o -MD -MP -MF $(DEPDIR)/stap-staptree.Tpo -c -o stap-staptree.o `test -f 'staptree.cxx' || echo '$(srcdir)/'`staptree.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-staptree.Tpo $(DEPDIR)/stap-staptree.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='staptree.cxx' object='stap-staptree.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-staptree.o `test -f 'staptree.cxx' || echo '$(srcdir)/'`staptree.cxx stap-staptree.obj: staptree.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-staptree.obj -MD -MP -MF $(DEPDIR)/stap-staptree.Tpo -c -o stap-staptree.obj `if test -f 'staptree.cxx'; then $(CYGPATH_W) 'staptree.cxx'; else $(CYGPATH_W) '$(srcdir)/staptree.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-staptree.Tpo $(DEPDIR)/stap-staptree.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='staptree.cxx' object='stap-staptree.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-staptree.obj `if test -f 'staptree.cxx'; then $(CYGPATH_W) 'staptree.cxx'; else $(CYGPATH_W) '$(srcdir)/staptree.cxx'; fi` stap-elaborate.o: elaborate.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-elaborate.o -MD -MP -MF $(DEPDIR)/stap-elaborate.Tpo -c -o stap-elaborate.o `test -f 'elaborate.cxx' || echo '$(srcdir)/'`elaborate.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-elaborate.Tpo $(DEPDIR)/stap-elaborate.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='elaborate.cxx' object='stap-elaborate.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-elaborate.o `test -f 'elaborate.cxx' || echo '$(srcdir)/'`elaborate.cxx stap-elaborate.obj: elaborate.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-elaborate.obj -MD -MP -MF $(DEPDIR)/stap-elaborate.Tpo -c -o stap-elaborate.obj `if test -f 'elaborate.cxx'; then $(CYGPATH_W) 'elaborate.cxx'; else $(CYGPATH_W) '$(srcdir)/elaborate.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-elaborate.Tpo $(DEPDIR)/stap-elaborate.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='elaborate.cxx' object='stap-elaborate.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-elaborate.obj `if test -f 'elaborate.cxx'; then $(CYGPATH_W) 'elaborate.cxx'; else $(CYGPATH_W) '$(srcdir)/elaborate.cxx'; fi` stap-translate.o: translate.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-translate.o -MD -MP -MF $(DEPDIR)/stap-translate.Tpo -c -o stap-translate.o `test -f 'translate.cxx' || echo '$(srcdir)/'`translate.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-translate.Tpo $(DEPDIR)/stap-translate.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='translate.cxx' object='stap-translate.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-translate.o `test -f 'translate.cxx' || echo '$(srcdir)/'`translate.cxx stap-translate.obj: translate.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-translate.obj -MD -MP -MF $(DEPDIR)/stap-translate.Tpo -c -o stap-translate.obj `if test -f 'translate.cxx'; then $(CYGPATH_W) 'translate.cxx'; else $(CYGPATH_W) '$(srcdir)/translate.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-translate.Tpo $(DEPDIR)/stap-translate.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='translate.cxx' object='stap-translate.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-translate.obj `if test -f 'translate.cxx'; then $(CYGPATH_W) 'translate.cxx'; else $(CYGPATH_W) '$(srcdir)/translate.cxx'; fi` stap-tapsets.o: tapsets.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapsets.o -MD -MP -MF $(DEPDIR)/stap-tapsets.Tpo -c -o stap-tapsets.o `test -f 'tapsets.cxx' || echo '$(srcdir)/'`tapsets.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapsets.Tpo $(DEPDIR)/stap-tapsets.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapsets.cxx' object='stap-tapsets.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapsets.o `test -f 'tapsets.cxx' || echo '$(srcdir)/'`tapsets.cxx stap-tapsets.obj: tapsets.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapsets.obj -MD -MP -MF $(DEPDIR)/stap-tapsets.Tpo -c -o stap-tapsets.obj `if test -f 'tapsets.cxx'; then $(CYGPATH_W) 'tapsets.cxx'; else $(CYGPATH_W) '$(srcdir)/tapsets.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapsets.Tpo $(DEPDIR)/stap-tapsets.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapsets.cxx' object='stap-tapsets.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapsets.obj `if test -f 'tapsets.cxx'; then $(CYGPATH_W) 'tapsets.cxx'; else $(CYGPATH_W) '$(srcdir)/tapsets.cxx'; fi` stap-buildrun.o: buildrun.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-buildrun.o -MD -MP -MF $(DEPDIR)/stap-buildrun.Tpo -c -o stap-buildrun.o `test -f 'buildrun.cxx' || echo '$(srcdir)/'`buildrun.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-buildrun.Tpo $(DEPDIR)/stap-buildrun.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='buildrun.cxx' object='stap-buildrun.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-buildrun.o `test -f 'buildrun.cxx' || echo '$(srcdir)/'`buildrun.cxx stap-buildrun.obj: buildrun.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-buildrun.obj -MD -MP -MF $(DEPDIR)/stap-buildrun.Tpo -c -o stap-buildrun.obj `if test -f 'buildrun.cxx'; then $(CYGPATH_W) 'buildrun.cxx'; else $(CYGPATH_W) '$(srcdir)/buildrun.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-buildrun.Tpo $(DEPDIR)/stap-buildrun.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='buildrun.cxx' object='stap-buildrun.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-buildrun.obj `if test -f 'buildrun.cxx'; then $(CYGPATH_W) 'buildrun.cxx'; else $(CYGPATH_W) '$(srcdir)/buildrun.cxx'; fi` stap-hash.o: hash.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-hash.o -MD -MP -MF $(DEPDIR)/stap-hash.Tpo -c -o stap-hash.o `test -f 'hash.cxx' || echo '$(srcdir)/'`hash.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-hash.Tpo $(DEPDIR)/stap-hash.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='hash.cxx' object='stap-hash.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-hash.o `test -f 'hash.cxx' || echo '$(srcdir)/'`hash.cxx stap-hash.obj: hash.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-hash.obj -MD -MP -MF $(DEPDIR)/stap-hash.Tpo -c -o stap-hash.obj `if test -f 'hash.cxx'; then $(CYGPATH_W) 'hash.cxx'; else $(CYGPATH_W) '$(srcdir)/hash.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-hash.Tpo $(DEPDIR)/stap-hash.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='hash.cxx' object='stap-hash.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-hash.obj `if test -f 'hash.cxx'; then $(CYGPATH_W) 'hash.cxx'; else $(CYGPATH_W) '$(srcdir)/hash.cxx'; fi` stap-cache.o: cache.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-cache.o -MD -MP -MF $(DEPDIR)/stap-cache.Tpo -c -o stap-cache.o `test -f 'cache.cxx' || echo '$(srcdir)/'`cache.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-cache.Tpo $(DEPDIR)/stap-cache.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='cache.cxx' object='stap-cache.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-cache.o `test -f 'cache.cxx' || echo '$(srcdir)/'`cache.cxx stap-cache.obj: cache.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-cache.obj -MD -MP -MF $(DEPDIR)/stap-cache.Tpo -c -o stap-cache.obj `if test -f 'cache.cxx'; then $(CYGPATH_W) 'cache.cxx'; else $(CYGPATH_W) '$(srcdir)/cache.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-cache.Tpo $(DEPDIR)/stap-cache.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='cache.cxx' object='stap-cache.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-cache.obj `if test -f 'cache.cxx'; then $(CYGPATH_W) 'cache.cxx'; else $(CYGPATH_W) '$(srcdir)/cache.cxx'; fi` stap-util.o: util.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-util.o -MD -MP -MF $(DEPDIR)/stap-util.Tpo -c -o stap-util.o `test -f 'util.cxx' || echo '$(srcdir)/'`util.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-util.Tpo $(DEPDIR)/stap-util.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='util.cxx' object='stap-util.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-util.o `test -f 'util.cxx' || echo '$(srcdir)/'`util.cxx stap-util.obj: util.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-util.obj -MD -MP -MF $(DEPDIR)/stap-util.Tpo -c -o stap-util.obj `if test -f 'util.cxx'; then $(CYGPATH_W) 'util.cxx'; else $(CYGPATH_W) '$(srcdir)/util.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-util.Tpo $(DEPDIR)/stap-util.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='util.cxx' object='stap-util.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-util.obj `if test -f 'util.cxx'; then $(CYGPATH_W) 'util.cxx'; else $(CYGPATH_W) '$(srcdir)/util.cxx'; fi` stap-coveragedb.o: coveragedb.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-coveragedb.o -MD -MP -MF $(DEPDIR)/stap-coveragedb.Tpo -c -o stap-coveragedb.o `test -f 'coveragedb.cxx' || echo '$(srcdir)/'`coveragedb.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-coveragedb.Tpo $(DEPDIR)/stap-coveragedb.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='coveragedb.cxx' object='stap-coveragedb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-coveragedb.o `test -f 'coveragedb.cxx' || echo '$(srcdir)/'`coveragedb.cxx stap-coveragedb.obj: coveragedb.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-coveragedb.obj -MD -MP -MF $(DEPDIR)/stap-coveragedb.Tpo -c -o stap-coveragedb.obj `if test -f 'coveragedb.cxx'; then $(CYGPATH_W) 'coveragedb.cxx'; else $(CYGPATH_W) '$(srcdir)/coveragedb.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-coveragedb.Tpo $(DEPDIR)/stap-coveragedb.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='coveragedb.cxx' object='stap-coveragedb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-coveragedb.obj `if test -f 'coveragedb.cxx'; then $(CYGPATH_W) 'coveragedb.cxx'; else $(CYGPATH_W) '$(srcdir)/coveragedb.cxx'; fi` stap-dwarf_wrappers.o: dwarf_wrappers.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-dwarf_wrappers.o -MD -MP -MF $(DEPDIR)/stap-dwarf_wrappers.Tpo -c -o stap-dwarf_wrappers.o `test -f 'dwarf_wrappers.cxx' || echo '$(srcdir)/'`dwarf_wrappers.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-dwarf_wrappers.Tpo $(DEPDIR)/stap-dwarf_wrappers.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dwarf_wrappers.cxx' object='stap-dwarf_wrappers.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-dwarf_wrappers.o `test -f 'dwarf_wrappers.cxx' || echo '$(srcdir)/'`dwarf_wrappers.cxx stap-dwarf_wrappers.obj: dwarf_wrappers.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-dwarf_wrappers.obj -MD -MP -MF $(DEPDIR)/stap-dwarf_wrappers.Tpo -c -o stap-dwarf_wrappers.obj `if test -f 'dwarf_wrappers.cxx'; then $(CYGPATH_W) 'dwarf_wrappers.cxx'; else $(CYGPATH_W) '$(srcdir)/dwarf_wrappers.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-dwarf_wrappers.Tpo $(DEPDIR)/stap-dwarf_wrappers.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dwarf_wrappers.cxx' object='stap-dwarf_wrappers.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-dwarf_wrappers.obj `if test -f 'dwarf_wrappers.cxx'; then $(CYGPATH_W) 'dwarf_wrappers.cxx'; else $(CYGPATH_W) '$(srcdir)/dwarf_wrappers.cxx'; fi` stap-tapset-been.o: tapset-been.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-been.o -MD -MP -MF $(DEPDIR)/stap-tapset-been.Tpo -c -o stap-tapset-been.o `test -f 'tapset-been.cxx' || echo '$(srcdir)/'`tapset-been.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-been.Tpo $(DEPDIR)/stap-tapset-been.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-been.cxx' object='stap-tapset-been.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-been.o `test -f 'tapset-been.cxx' || echo '$(srcdir)/'`tapset-been.cxx stap-tapset-been.obj: tapset-been.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-been.obj -MD -MP -MF $(DEPDIR)/stap-tapset-been.Tpo -c -o stap-tapset-been.obj `if test -f 'tapset-been.cxx'; then $(CYGPATH_W) 'tapset-been.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-been.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-been.Tpo $(DEPDIR)/stap-tapset-been.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-been.cxx' object='stap-tapset-been.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-been.obj `if test -f 'tapset-been.cxx'; then $(CYGPATH_W) 'tapset-been.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-been.cxx'; fi` stap-tapset-procfs.o: tapset-procfs.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-procfs.o -MD -MP -MF $(DEPDIR)/stap-tapset-procfs.Tpo -c -o stap-tapset-procfs.o `test -f 'tapset-procfs.cxx' || echo '$(srcdir)/'`tapset-procfs.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-procfs.Tpo $(DEPDIR)/stap-tapset-procfs.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-procfs.cxx' object='stap-tapset-procfs.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-procfs.o `test -f 'tapset-procfs.cxx' || echo '$(srcdir)/'`tapset-procfs.cxx stap-tapset-procfs.obj: tapset-procfs.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-procfs.obj -MD -MP -MF $(DEPDIR)/stap-tapset-procfs.Tpo -c -o stap-tapset-procfs.obj `if test -f 'tapset-procfs.cxx'; then $(CYGPATH_W) 'tapset-procfs.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-procfs.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-procfs.Tpo $(DEPDIR)/stap-tapset-procfs.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-procfs.cxx' object='stap-tapset-procfs.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-procfs.obj `if test -f 'tapset-procfs.cxx'; then $(CYGPATH_W) 'tapset-procfs.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-procfs.cxx'; fi` stap-tapset-timers.o: tapset-timers.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-timers.o -MD -MP -MF $(DEPDIR)/stap-tapset-timers.Tpo -c -o stap-tapset-timers.o `test -f 'tapset-timers.cxx' || echo '$(srcdir)/'`tapset-timers.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-timers.Tpo $(DEPDIR)/stap-tapset-timers.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-timers.cxx' object='stap-tapset-timers.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-timers.o `test -f 'tapset-timers.cxx' || echo '$(srcdir)/'`tapset-timers.cxx stap-tapset-timers.obj: tapset-timers.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-timers.obj -MD -MP -MF $(DEPDIR)/stap-tapset-timers.Tpo -c -o stap-tapset-timers.obj `if test -f 'tapset-timers.cxx'; then $(CYGPATH_W) 'tapset-timers.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-timers.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-timers.Tpo $(DEPDIR)/stap-tapset-timers.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-timers.cxx' object='stap-tapset-timers.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-timers.obj `if test -f 'tapset-timers.cxx'; then $(CYGPATH_W) 'tapset-timers.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-timers.cxx'; fi` stap-tapset-netfilter.o: tapset-netfilter.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-netfilter.o -MD -MP -MF $(DEPDIR)/stap-tapset-netfilter.Tpo -c -o stap-tapset-netfilter.o `test -f 'tapset-netfilter.cxx' || echo '$(srcdir)/'`tapset-netfilter.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-netfilter.Tpo $(DEPDIR)/stap-tapset-netfilter.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-netfilter.cxx' object='stap-tapset-netfilter.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-netfilter.o `test -f 'tapset-netfilter.cxx' || echo '$(srcdir)/'`tapset-netfilter.cxx stap-tapset-netfilter.obj: tapset-netfilter.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-netfilter.obj -MD -MP -MF $(DEPDIR)/stap-tapset-netfilter.Tpo -c -o stap-tapset-netfilter.obj `if test -f 'tapset-netfilter.cxx'; then $(CYGPATH_W) 'tapset-netfilter.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-netfilter.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-netfilter.Tpo $(DEPDIR)/stap-tapset-netfilter.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-netfilter.cxx' object='stap-tapset-netfilter.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-netfilter.obj `if test -f 'tapset-netfilter.cxx'; then $(CYGPATH_W) 'tapset-netfilter.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-netfilter.cxx'; fi` stap-tapset-perfmon.o: tapset-perfmon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-perfmon.o -MD -MP -MF $(DEPDIR)/stap-tapset-perfmon.Tpo -c -o stap-tapset-perfmon.o `test -f 'tapset-perfmon.cxx' || echo '$(srcdir)/'`tapset-perfmon.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-perfmon.Tpo $(DEPDIR)/stap-tapset-perfmon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-perfmon.cxx' object='stap-tapset-perfmon.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-perfmon.o `test -f 'tapset-perfmon.cxx' || echo '$(srcdir)/'`tapset-perfmon.cxx stap-tapset-perfmon.obj: tapset-perfmon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-perfmon.obj -MD -MP -MF $(DEPDIR)/stap-tapset-perfmon.Tpo -c -o stap-tapset-perfmon.obj `if test -f 'tapset-perfmon.cxx'; then $(CYGPATH_W) 'tapset-perfmon.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-perfmon.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-perfmon.Tpo $(DEPDIR)/stap-tapset-perfmon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-perfmon.cxx' object='stap-tapset-perfmon.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-perfmon.obj `if test -f 'tapset-perfmon.cxx'; then $(CYGPATH_W) 'tapset-perfmon.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-perfmon.cxx'; fi` stap-tapset-mark.o: tapset-mark.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-mark.o -MD -MP -MF $(DEPDIR)/stap-tapset-mark.Tpo -c -o stap-tapset-mark.o `test -f 'tapset-mark.cxx' || echo '$(srcdir)/'`tapset-mark.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-mark.Tpo $(DEPDIR)/stap-tapset-mark.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-mark.cxx' object='stap-tapset-mark.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-mark.o `test -f 'tapset-mark.cxx' || echo '$(srcdir)/'`tapset-mark.cxx stap-tapset-mark.obj: tapset-mark.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-mark.obj -MD -MP -MF $(DEPDIR)/stap-tapset-mark.Tpo -c -o stap-tapset-mark.obj `if test -f 'tapset-mark.cxx'; then $(CYGPATH_W) 'tapset-mark.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-mark.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-mark.Tpo $(DEPDIR)/stap-tapset-mark.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-mark.cxx' object='stap-tapset-mark.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-mark.obj `if test -f 'tapset-mark.cxx'; then $(CYGPATH_W) 'tapset-mark.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-mark.cxx'; fi` stap-tapset-itrace.o: tapset-itrace.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-itrace.o -MD -MP -MF $(DEPDIR)/stap-tapset-itrace.Tpo -c -o stap-tapset-itrace.o `test -f 'tapset-itrace.cxx' || echo '$(srcdir)/'`tapset-itrace.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-itrace.Tpo $(DEPDIR)/stap-tapset-itrace.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-itrace.cxx' object='stap-tapset-itrace.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-itrace.o `test -f 'tapset-itrace.cxx' || echo '$(srcdir)/'`tapset-itrace.cxx stap-tapset-itrace.obj: tapset-itrace.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-itrace.obj -MD -MP -MF $(DEPDIR)/stap-tapset-itrace.Tpo -c -o stap-tapset-itrace.obj `if test -f 'tapset-itrace.cxx'; then $(CYGPATH_W) 'tapset-itrace.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-itrace.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-itrace.Tpo $(DEPDIR)/stap-tapset-itrace.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-itrace.cxx' object='stap-tapset-itrace.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-itrace.obj `if test -f 'tapset-itrace.cxx'; then $(CYGPATH_W) 'tapset-itrace.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-itrace.cxx'; fi` stap-tapset-utrace.o: tapset-utrace.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-utrace.o -MD -MP -MF $(DEPDIR)/stap-tapset-utrace.Tpo -c -o stap-tapset-utrace.o `test -f 'tapset-utrace.cxx' || echo '$(srcdir)/'`tapset-utrace.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-utrace.Tpo $(DEPDIR)/stap-tapset-utrace.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-utrace.cxx' object='stap-tapset-utrace.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-utrace.o `test -f 'tapset-utrace.cxx' || echo '$(srcdir)/'`tapset-utrace.cxx stap-tapset-utrace.obj: tapset-utrace.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-utrace.obj -MD -MP -MF $(DEPDIR)/stap-tapset-utrace.Tpo -c -o stap-tapset-utrace.obj `if test -f 'tapset-utrace.cxx'; then $(CYGPATH_W) 'tapset-utrace.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-utrace.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-utrace.Tpo $(DEPDIR)/stap-tapset-utrace.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-utrace.cxx' object='stap-tapset-utrace.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-utrace.obj `if test -f 'tapset-utrace.cxx'; then $(CYGPATH_W) 'tapset-utrace.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-utrace.cxx'; fi` stap-task_finder.o: task_finder.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-task_finder.o -MD -MP -MF $(DEPDIR)/stap-task_finder.Tpo -c -o stap-task_finder.o `test -f 'task_finder.cxx' || echo '$(srcdir)/'`task_finder.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-task_finder.Tpo $(DEPDIR)/stap-task_finder.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='task_finder.cxx' object='stap-task_finder.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-task_finder.o `test -f 'task_finder.cxx' || echo '$(srcdir)/'`task_finder.cxx stap-task_finder.obj: task_finder.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-task_finder.obj -MD -MP -MF $(DEPDIR)/stap-task_finder.Tpo -c -o stap-task_finder.obj `if test -f 'task_finder.cxx'; then $(CYGPATH_W) 'task_finder.cxx'; else $(CYGPATH_W) '$(srcdir)/task_finder.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-task_finder.Tpo $(DEPDIR)/stap-task_finder.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='task_finder.cxx' object='stap-task_finder.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-task_finder.obj `if test -f 'task_finder.cxx'; then $(CYGPATH_W) 'task_finder.cxx'; else $(CYGPATH_W) '$(srcdir)/task_finder.cxx'; fi` stap-dwflpp.o: dwflpp.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-dwflpp.o -MD -MP -MF $(DEPDIR)/stap-dwflpp.Tpo -c -o stap-dwflpp.o `test -f 'dwflpp.cxx' || echo '$(srcdir)/'`dwflpp.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-dwflpp.Tpo $(DEPDIR)/stap-dwflpp.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dwflpp.cxx' object='stap-dwflpp.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-dwflpp.o `test -f 'dwflpp.cxx' || echo '$(srcdir)/'`dwflpp.cxx stap-dwflpp.obj: dwflpp.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-dwflpp.obj -MD -MP -MF $(DEPDIR)/stap-dwflpp.Tpo -c -o stap-dwflpp.obj `if test -f 'dwflpp.cxx'; then $(CYGPATH_W) 'dwflpp.cxx'; else $(CYGPATH_W) '$(srcdir)/dwflpp.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-dwflpp.Tpo $(DEPDIR)/stap-dwflpp.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dwflpp.cxx' object='stap-dwflpp.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-dwflpp.obj `if test -f 'dwflpp.cxx'; then $(CYGPATH_W) 'dwflpp.cxx'; else $(CYGPATH_W) '$(srcdir)/dwflpp.cxx'; fi` stap-rpm_finder.o: rpm_finder.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-rpm_finder.o -MD -MP -MF $(DEPDIR)/stap-rpm_finder.Tpo -c -o stap-rpm_finder.o `test -f 'rpm_finder.cxx' || echo '$(srcdir)/'`rpm_finder.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-rpm_finder.Tpo $(DEPDIR)/stap-rpm_finder.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rpm_finder.cxx' object='stap-rpm_finder.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-rpm_finder.o `test -f 'rpm_finder.cxx' || echo '$(srcdir)/'`rpm_finder.cxx stap-rpm_finder.obj: rpm_finder.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-rpm_finder.obj -MD -MP -MF $(DEPDIR)/stap-rpm_finder.Tpo -c -o stap-rpm_finder.obj `if test -f 'rpm_finder.cxx'; then $(CYGPATH_W) 'rpm_finder.cxx'; else $(CYGPATH_W) '$(srcdir)/rpm_finder.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-rpm_finder.Tpo $(DEPDIR)/stap-rpm_finder.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rpm_finder.cxx' object='stap-rpm_finder.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-rpm_finder.obj `if test -f 'rpm_finder.cxx'; then $(CYGPATH_W) 'rpm_finder.cxx'; else $(CYGPATH_W) '$(srcdir)/rpm_finder.cxx'; fi` stap-setupdwfl.o: setupdwfl.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-setupdwfl.o -MD -MP -MF $(DEPDIR)/stap-setupdwfl.Tpo -c -o stap-setupdwfl.o `test -f 'setupdwfl.cxx' || echo '$(srcdir)/'`setupdwfl.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-setupdwfl.Tpo $(DEPDIR)/stap-setupdwfl.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='setupdwfl.cxx' object='stap-setupdwfl.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-setupdwfl.o `test -f 'setupdwfl.cxx' || echo '$(srcdir)/'`setupdwfl.cxx stap-setupdwfl.obj: setupdwfl.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-setupdwfl.obj -MD -MP -MF $(DEPDIR)/stap-setupdwfl.Tpo -c -o stap-setupdwfl.obj `if test -f 'setupdwfl.cxx'; then $(CYGPATH_W) 'setupdwfl.cxx'; else $(CYGPATH_W) '$(srcdir)/setupdwfl.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-setupdwfl.Tpo $(DEPDIR)/stap-setupdwfl.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='setupdwfl.cxx' object='stap-setupdwfl.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-setupdwfl.obj `if test -f 'setupdwfl.cxx'; then $(CYGPATH_W) 'setupdwfl.cxx'; else $(CYGPATH_W) '$(srcdir)/setupdwfl.cxx'; fi` stap-remote.o: remote.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-remote.o -MD -MP -MF $(DEPDIR)/stap-remote.Tpo -c -o stap-remote.o `test -f 'remote.cxx' || echo '$(srcdir)/'`remote.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-remote.Tpo $(DEPDIR)/stap-remote.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='remote.cxx' object='stap-remote.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-remote.o `test -f 'remote.cxx' || echo '$(srcdir)/'`remote.cxx stap-remote.obj: remote.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-remote.obj -MD -MP -MF $(DEPDIR)/stap-remote.Tpo -c -o stap-remote.obj `if test -f 'remote.cxx'; then $(CYGPATH_W) 'remote.cxx'; else $(CYGPATH_W) '$(srcdir)/remote.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-remote.Tpo $(DEPDIR)/stap-remote.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='remote.cxx' object='stap-remote.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-remote.obj `if test -f 'remote.cxx'; then $(CYGPATH_W) 'remote.cxx'; else $(CYGPATH_W) '$(srcdir)/remote.cxx'; fi` stap-privilege.o: privilege.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-privilege.o -MD -MP -MF $(DEPDIR)/stap-privilege.Tpo -c -o stap-privilege.o `test -f 'privilege.cxx' || echo '$(srcdir)/'`privilege.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-privilege.Tpo $(DEPDIR)/stap-privilege.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='privilege.cxx' object='stap-privilege.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-privilege.o `test -f 'privilege.cxx' || echo '$(srcdir)/'`privilege.cxx stap-privilege.obj: privilege.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-privilege.obj -MD -MP -MF $(DEPDIR)/stap-privilege.Tpo -c -o stap-privilege.obj `if test -f 'privilege.cxx'; then $(CYGPATH_W) 'privilege.cxx'; else $(CYGPATH_W) '$(srcdir)/privilege.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-privilege.Tpo $(DEPDIR)/stap-privilege.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='privilege.cxx' object='stap-privilege.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-privilege.obj `if test -f 'privilege.cxx'; then $(CYGPATH_W) 'privilege.cxx'; else $(CYGPATH_W) '$(srcdir)/privilege.cxx'; fi` stap-cmdline.o: cmdline.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-cmdline.o -MD -MP -MF $(DEPDIR)/stap-cmdline.Tpo -c -o stap-cmdline.o `test -f 'cmdline.cxx' || echo '$(srcdir)/'`cmdline.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-cmdline.Tpo $(DEPDIR)/stap-cmdline.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='cmdline.cxx' object='stap-cmdline.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-cmdline.o `test -f 'cmdline.cxx' || echo '$(srcdir)/'`cmdline.cxx stap-cmdline.obj: cmdline.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-cmdline.obj -MD -MP -MF $(DEPDIR)/stap-cmdline.Tpo -c -o stap-cmdline.obj `if test -f 'cmdline.cxx'; then $(CYGPATH_W) 'cmdline.cxx'; else $(CYGPATH_W) '$(srcdir)/cmdline.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-cmdline.Tpo $(DEPDIR)/stap-cmdline.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='cmdline.cxx' object='stap-cmdline.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-cmdline.obj `if test -f 'cmdline.cxx'; then $(CYGPATH_W) 'cmdline.cxx'; else $(CYGPATH_W) '$(srcdir)/cmdline.cxx'; fi` stap-tapset-dynprobe.o: tapset-dynprobe.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-dynprobe.o -MD -MP -MF $(DEPDIR)/stap-tapset-dynprobe.Tpo -c -o stap-tapset-dynprobe.o `test -f 'tapset-dynprobe.cxx' || echo '$(srcdir)/'`tapset-dynprobe.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-dynprobe.Tpo $(DEPDIR)/stap-tapset-dynprobe.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-dynprobe.cxx' object='stap-tapset-dynprobe.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-dynprobe.o `test -f 'tapset-dynprobe.cxx' || echo '$(srcdir)/'`tapset-dynprobe.cxx stap-tapset-dynprobe.obj: tapset-dynprobe.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-dynprobe.obj -MD -MP -MF $(DEPDIR)/stap-tapset-dynprobe.Tpo -c -o stap-tapset-dynprobe.obj `if test -f 'tapset-dynprobe.cxx'; then $(CYGPATH_W) 'tapset-dynprobe.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-dynprobe.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-dynprobe.Tpo $(DEPDIR)/stap-tapset-dynprobe.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-dynprobe.cxx' object='stap-tapset-dynprobe.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-dynprobe.obj `if test -f 'tapset-dynprobe.cxx'; then $(CYGPATH_W) 'tapset-dynprobe.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-dynprobe.cxx'; fi` stap-tapset-method.o: tapset-method.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-method.o -MD -MP -MF $(DEPDIR)/stap-tapset-method.Tpo -c -o stap-tapset-method.o `test -f 'tapset-method.cxx' || echo '$(srcdir)/'`tapset-method.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-method.Tpo $(DEPDIR)/stap-tapset-method.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-method.cxx' object='stap-tapset-method.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-method.o `test -f 'tapset-method.cxx' || echo '$(srcdir)/'`tapset-method.cxx stap-tapset-method.obj: tapset-method.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-method.obj -MD -MP -MF $(DEPDIR)/stap-tapset-method.Tpo -c -o stap-tapset-method.obj `if test -f 'tapset-method.cxx'; then $(CYGPATH_W) 'tapset-method.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-method.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-tapset-method.Tpo $(DEPDIR)/stap-tapset-method.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tapset-method.cxx' object='stap-tapset-method.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-method.obj `if test -f 'tapset-method.cxx'; then $(CYGPATH_W) 'tapset-method.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-method.cxx'; fi` stap-translator-output.o: translator-output.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-translator-output.o -MD -MP -MF $(DEPDIR)/stap-translator-output.Tpo -c -o stap-translator-output.o `test -f 'translator-output.cxx' || echo '$(srcdir)/'`translator-output.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-translator-output.Tpo $(DEPDIR)/stap-translator-output.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='translator-output.cxx' object='stap-translator-output.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-translator-output.o `test -f 'translator-output.cxx' || echo '$(srcdir)/'`translator-output.cxx stap-translator-output.obj: translator-output.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-translator-output.obj -MD -MP -MF $(DEPDIR)/stap-translator-output.Tpo -c -o stap-translator-output.obj `if test -f 'translator-output.cxx'; then $(CYGPATH_W) 'translator-output.cxx'; else $(CYGPATH_W) '$(srcdir)/translator-output.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-translator-output.Tpo $(DEPDIR)/stap-translator-output.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='translator-output.cxx' object='stap-translator-output.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-translator-output.obj `if test -f 'translator-output.cxx'; then $(CYGPATH_W) 'translator-output.cxx'; else $(CYGPATH_W) '$(srcdir)/translator-output.cxx'; fi` stap-stapregex.o: stapregex.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-stapregex.o -MD -MP -MF $(DEPDIR)/stap-stapregex.Tpo -c -o stap-stapregex.o `test -f 'stapregex.cxx' || echo '$(srcdir)/'`stapregex.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-stapregex.Tpo $(DEPDIR)/stap-stapregex.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stapregex.cxx' object='stap-stapregex.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-stapregex.o `test -f 'stapregex.cxx' || echo '$(srcdir)/'`stapregex.cxx stap-stapregex.obj: stapregex.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-stapregex.obj -MD -MP -MF $(DEPDIR)/stap-stapregex.Tpo -c -o stap-stapregex.obj `if test -f 'stapregex.cxx'; then $(CYGPATH_W) 'stapregex.cxx'; else $(CYGPATH_W) '$(srcdir)/stapregex.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-stapregex.Tpo $(DEPDIR)/stap-stapregex.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stapregex.cxx' object='stap-stapregex.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-stapregex.obj `if test -f 'stapregex.cxx'; then $(CYGPATH_W) 'stapregex.cxx'; else $(CYGPATH_W) '$(srcdir)/stapregex.cxx'; fi` stap-stapregex-tree.o: stapregex-tree.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-stapregex-tree.o -MD -MP -MF $(DEPDIR)/stap-stapregex-tree.Tpo -c -o stap-stapregex-tree.o `test -f 'stapregex-tree.cxx' || echo '$(srcdir)/'`stapregex-tree.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-stapregex-tree.Tpo $(DEPDIR)/stap-stapregex-tree.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stapregex-tree.cxx' object='stap-stapregex-tree.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-stapregex-tree.o `test -f 'stapregex-tree.cxx' || echo '$(srcdir)/'`stapregex-tree.cxx stap-stapregex-tree.obj: stapregex-tree.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-stapregex-tree.obj -MD -MP -MF $(DEPDIR)/stap-stapregex-tree.Tpo -c -o stap-stapregex-tree.obj `if test -f 'stapregex-tree.cxx'; then $(CYGPATH_W) 'stapregex-tree.cxx'; else $(CYGPATH_W) '$(srcdir)/stapregex-tree.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-stapregex-tree.Tpo $(DEPDIR)/stap-stapregex-tree.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stapregex-tree.cxx' object='stap-stapregex-tree.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-stapregex-tree.obj `if test -f 'stapregex-tree.cxx'; then $(CYGPATH_W) 'stapregex-tree.cxx'; else $(CYGPATH_W) '$(srcdir)/stapregex-tree.cxx'; fi` stap-stapregex-parse.o: stapregex-parse.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-stapregex-parse.o -MD -MP -MF $(DEPDIR)/stap-stapregex-parse.Tpo -c -o stap-stapregex-parse.o `test -f 'stapregex-parse.cxx' || echo '$(srcdir)/'`stapregex-parse.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-stapregex-parse.Tpo $(DEPDIR)/stap-stapregex-parse.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stapregex-parse.cxx' object='stap-stapregex-parse.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-stapregex-parse.o `test -f 'stapregex-parse.cxx' || echo '$(srcdir)/'`stapregex-parse.cxx stap-stapregex-parse.obj: stapregex-parse.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-stapregex-parse.obj -MD -MP -MF $(DEPDIR)/stap-stapregex-parse.Tpo -c -o stap-stapregex-parse.obj `if test -f 'stapregex-parse.cxx'; then $(CYGPATH_W) 'stapregex-parse.cxx'; else $(CYGPATH_W) '$(srcdir)/stapregex-parse.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-stapregex-parse.Tpo $(DEPDIR)/stap-stapregex-parse.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stapregex-parse.cxx' object='stap-stapregex-parse.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-stapregex-parse.obj `if test -f 'stapregex-parse.cxx'; then $(CYGPATH_W) 'stapregex-parse.cxx'; else $(CYGPATH_W) '$(srcdir)/stapregex-parse.cxx'; fi` stap-stapregex-dfa.o: stapregex-dfa.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-stapregex-dfa.o -MD -MP -MF $(DEPDIR)/stap-stapregex-dfa.Tpo -c -o stap-stapregex-dfa.o `test -f 'stapregex-dfa.cxx' || echo '$(srcdir)/'`stapregex-dfa.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-stapregex-dfa.Tpo $(DEPDIR)/stap-stapregex-dfa.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stapregex-dfa.cxx' object='stap-stapregex-dfa.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-stapregex-dfa.o `test -f 'stapregex-dfa.cxx' || echo '$(srcdir)/'`stapregex-dfa.cxx stap-stapregex-dfa.obj: stapregex-dfa.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-stapregex-dfa.obj -MD -MP -MF $(DEPDIR)/stap-stapregex-dfa.Tpo -c -o stap-stapregex-dfa.obj `if test -f 'stapregex-dfa.cxx'; then $(CYGPATH_W) 'stapregex-dfa.cxx'; else $(CYGPATH_W) '$(srcdir)/stapregex-dfa.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-stapregex-dfa.Tpo $(DEPDIR)/stap-stapregex-dfa.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stapregex-dfa.cxx' object='stap-stapregex-dfa.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-stapregex-dfa.obj `if test -f 'stapregex-dfa.cxx'; then $(CYGPATH_W) 'stapregex-dfa.cxx'; else $(CYGPATH_W) '$(srcdir)/stapregex-dfa.cxx'; fi` stap-nsscommon.o: nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-nsscommon.o -MD -MP -MF $(DEPDIR)/stap-nsscommon.Tpo -c -o stap-nsscommon.o `test -f 'nsscommon.cxx' || echo '$(srcdir)/'`nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-nsscommon.Tpo $(DEPDIR)/stap-nsscommon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='nsscommon.cxx' object='stap-nsscommon.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-nsscommon.o `test -f 'nsscommon.cxx' || echo '$(srcdir)/'`nsscommon.cxx stap-nsscommon.obj: nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-nsscommon.obj -MD -MP -MF $(DEPDIR)/stap-nsscommon.Tpo -c -o stap-nsscommon.obj `if test -f 'nsscommon.cxx'; then $(CYGPATH_W) 'nsscommon.cxx'; else $(CYGPATH_W) '$(srcdir)/nsscommon.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-nsscommon.Tpo $(DEPDIR)/stap-nsscommon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='nsscommon.cxx' object='stap-nsscommon.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-nsscommon.obj `if test -f 'nsscommon.cxx'; then $(CYGPATH_W) 'nsscommon.cxx'; else $(CYGPATH_W) '$(srcdir)/nsscommon.cxx'; fi` stap-csclient.o: csclient.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-csclient.o -MD -MP -MF $(DEPDIR)/stap-csclient.Tpo -c -o stap-csclient.o `test -f 'csclient.cxx' || echo '$(srcdir)/'`csclient.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-csclient.Tpo $(DEPDIR)/stap-csclient.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='csclient.cxx' object='stap-csclient.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-csclient.o `test -f 'csclient.cxx' || echo '$(srcdir)/'`csclient.cxx stap-csclient.obj: csclient.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-csclient.obj -MD -MP -MF $(DEPDIR)/stap-csclient.Tpo -c -o stap-csclient.obj `if test -f 'csclient.cxx'; then $(CYGPATH_W) 'csclient.cxx'; else $(CYGPATH_W) '$(srcdir)/csclient.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-csclient.Tpo $(DEPDIR)/stap-csclient.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='csclient.cxx' object='stap-csclient.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-csclient.obj `if test -f 'csclient.cxx'; then $(CYGPATH_W) 'csclient.cxx'; else $(CYGPATH_W) '$(srcdir)/csclient.cxx'; fi` stap-cscommon.o: cscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-cscommon.o -MD -MP -MF $(DEPDIR)/stap-cscommon.Tpo -c -o stap-cscommon.o `test -f 'cscommon.cxx' || echo '$(srcdir)/'`cscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-cscommon.Tpo $(DEPDIR)/stap-cscommon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='cscommon.cxx' object='stap-cscommon.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-cscommon.o `test -f 'cscommon.cxx' || echo '$(srcdir)/'`cscommon.cxx stap-cscommon.obj: cscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-cscommon.obj -MD -MP -MF $(DEPDIR)/stap-cscommon.Tpo -c -o stap-cscommon.obj `if test -f 'cscommon.cxx'; then $(CYGPATH_W) 'cscommon.cxx'; else $(CYGPATH_W) '$(srcdir)/cscommon.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap-cscommon.Tpo $(DEPDIR)/stap-cscommon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='cscommon.cxx' object='stap-cscommon.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-cscommon.obj `if test -f 'cscommon.cxx'; then $(CYGPATH_W) 'cscommon.cxx'; else $(CYGPATH_W) '$(srcdir)/cscommon.cxx'; fi` stap_authorize_cert-stap-authorize-cert.o: stap-authorize-cert.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_authorize_cert_CPPFLAGS) $(CPPFLAGS) $(stap_authorize_cert_CXXFLAGS) $(CXXFLAGS) -MT stap_authorize_cert-stap-authorize-cert.o -MD -MP -MF $(DEPDIR)/stap_authorize_cert-stap-authorize-cert.Tpo -c -o stap_authorize_cert-stap-authorize-cert.o `test -f 'stap-authorize-cert.cxx' || echo '$(srcdir)/'`stap-authorize-cert.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_authorize_cert-stap-authorize-cert.Tpo $(DEPDIR)/stap_authorize_cert-stap-authorize-cert.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stap-authorize-cert.cxx' object='stap_authorize_cert-stap-authorize-cert.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_authorize_cert_CPPFLAGS) $(CPPFLAGS) $(stap_authorize_cert_CXXFLAGS) $(CXXFLAGS) -c -o stap_authorize_cert-stap-authorize-cert.o `test -f 'stap-authorize-cert.cxx' || echo '$(srcdir)/'`stap-authorize-cert.cxx stap_authorize_cert-stap-authorize-cert.obj: stap-authorize-cert.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_authorize_cert_CPPFLAGS) $(CPPFLAGS) $(stap_authorize_cert_CXXFLAGS) $(CXXFLAGS) -MT stap_authorize_cert-stap-authorize-cert.obj -MD -MP -MF $(DEPDIR)/stap_authorize_cert-stap-authorize-cert.Tpo -c -o stap_authorize_cert-stap-authorize-cert.obj `if test -f 'stap-authorize-cert.cxx'; then $(CYGPATH_W) 'stap-authorize-cert.cxx'; else $(CYGPATH_W) '$(srcdir)/stap-authorize-cert.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_authorize_cert-stap-authorize-cert.Tpo $(DEPDIR)/stap_authorize_cert-stap-authorize-cert.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stap-authorize-cert.cxx' object='stap_authorize_cert-stap-authorize-cert.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_authorize_cert_CPPFLAGS) $(CPPFLAGS) $(stap_authorize_cert_CXXFLAGS) $(CXXFLAGS) -c -o stap_authorize_cert-stap-authorize-cert.obj `if test -f 'stap-authorize-cert.cxx'; then $(CYGPATH_W) 'stap-authorize-cert.cxx'; else $(CYGPATH_W) '$(srcdir)/stap-authorize-cert.cxx'; fi` stap_authorize_cert-nsscommon.o: nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_authorize_cert_CPPFLAGS) $(CPPFLAGS) $(stap_authorize_cert_CXXFLAGS) $(CXXFLAGS) -MT stap_authorize_cert-nsscommon.o -MD -MP -MF $(DEPDIR)/stap_authorize_cert-nsscommon.Tpo -c -o stap_authorize_cert-nsscommon.o `test -f 'nsscommon.cxx' || echo '$(srcdir)/'`nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_authorize_cert-nsscommon.Tpo $(DEPDIR)/stap_authorize_cert-nsscommon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='nsscommon.cxx' object='stap_authorize_cert-nsscommon.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_authorize_cert_CPPFLAGS) $(CPPFLAGS) $(stap_authorize_cert_CXXFLAGS) $(CXXFLAGS) -c -o stap_authorize_cert-nsscommon.o `test -f 'nsscommon.cxx' || echo '$(srcdir)/'`nsscommon.cxx stap_authorize_cert-nsscommon.obj: nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_authorize_cert_CPPFLAGS) $(CPPFLAGS) $(stap_authorize_cert_CXXFLAGS) $(CXXFLAGS) -MT stap_authorize_cert-nsscommon.obj -MD -MP -MF $(DEPDIR)/stap_authorize_cert-nsscommon.Tpo -c -o stap_authorize_cert-nsscommon.obj `if test -f 'nsscommon.cxx'; then $(CYGPATH_W) 'nsscommon.cxx'; else $(CYGPATH_W) '$(srcdir)/nsscommon.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_authorize_cert-nsscommon.Tpo $(DEPDIR)/stap_authorize_cert-nsscommon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='nsscommon.cxx' object='stap_authorize_cert-nsscommon.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_authorize_cert_CPPFLAGS) $(CPPFLAGS) $(stap_authorize_cert_CXXFLAGS) $(CXXFLAGS) -c -o stap_authorize_cert-nsscommon.obj `if test -f 'nsscommon.cxx'; then $(CYGPATH_W) 'nsscommon.cxx'; else $(CYGPATH_W) '$(srcdir)/nsscommon.cxx'; fi` stap_authorize_cert-util.o: util.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_authorize_cert_CPPFLAGS) $(CPPFLAGS) $(stap_authorize_cert_CXXFLAGS) $(CXXFLAGS) -MT stap_authorize_cert-util.o -MD -MP -MF $(DEPDIR)/stap_authorize_cert-util.Tpo -c -o stap_authorize_cert-util.o `test -f 'util.cxx' || echo '$(srcdir)/'`util.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_authorize_cert-util.Tpo $(DEPDIR)/stap_authorize_cert-util.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='util.cxx' object='stap_authorize_cert-util.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_authorize_cert_CPPFLAGS) $(CPPFLAGS) $(stap_authorize_cert_CXXFLAGS) $(CXXFLAGS) -c -o stap_authorize_cert-util.o `test -f 'util.cxx' || echo '$(srcdir)/'`util.cxx stap_authorize_cert-util.obj: util.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_authorize_cert_CPPFLAGS) $(CPPFLAGS) $(stap_authorize_cert_CXXFLAGS) $(CXXFLAGS) -MT stap_authorize_cert-util.obj -MD -MP -MF $(DEPDIR)/stap_authorize_cert-util.Tpo -c -o stap_authorize_cert-util.obj `if test -f 'util.cxx'; then $(CYGPATH_W) 'util.cxx'; else $(CYGPATH_W) '$(srcdir)/util.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_authorize_cert-util.Tpo $(DEPDIR)/stap_authorize_cert-util.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='util.cxx' object='stap_authorize_cert-util.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_authorize_cert_CPPFLAGS) $(CPPFLAGS) $(stap_authorize_cert_CXXFLAGS) $(CXXFLAGS) -c -o stap_authorize_cert-util.obj `if test -f 'util.cxx'; then $(CYGPATH_W) 'util.cxx'; else $(CYGPATH_W) '$(srcdir)/util.cxx'; fi` stap_gen_cert-stap-gen-cert.o: stap-gen-cert.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_gen_cert_CXXFLAGS) $(CXXFLAGS) -MT stap_gen_cert-stap-gen-cert.o -MD -MP -MF $(DEPDIR)/stap_gen_cert-stap-gen-cert.Tpo -c -o stap_gen_cert-stap-gen-cert.o `test -f 'stap-gen-cert.cxx' || echo '$(srcdir)/'`stap-gen-cert.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_gen_cert-stap-gen-cert.Tpo $(DEPDIR)/stap_gen_cert-stap-gen-cert.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stap-gen-cert.cxx' object='stap_gen_cert-stap-gen-cert.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_gen_cert_CXXFLAGS) $(CXXFLAGS) -c -o stap_gen_cert-stap-gen-cert.o `test -f 'stap-gen-cert.cxx' || echo '$(srcdir)/'`stap-gen-cert.cxx stap_gen_cert-stap-gen-cert.obj: stap-gen-cert.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_gen_cert_CXXFLAGS) $(CXXFLAGS) -MT stap_gen_cert-stap-gen-cert.obj -MD -MP -MF $(DEPDIR)/stap_gen_cert-stap-gen-cert.Tpo -c -o stap_gen_cert-stap-gen-cert.obj `if test -f 'stap-gen-cert.cxx'; then $(CYGPATH_W) 'stap-gen-cert.cxx'; else $(CYGPATH_W) '$(srcdir)/stap-gen-cert.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_gen_cert-stap-gen-cert.Tpo $(DEPDIR)/stap_gen_cert-stap-gen-cert.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stap-gen-cert.cxx' object='stap_gen_cert-stap-gen-cert.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_gen_cert_CXXFLAGS) $(CXXFLAGS) -c -o stap_gen_cert-stap-gen-cert.obj `if test -f 'stap-gen-cert.cxx'; then $(CYGPATH_W) 'stap-gen-cert.cxx'; else $(CYGPATH_W) '$(srcdir)/stap-gen-cert.cxx'; fi` stap_gen_cert-util.o: util.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_gen_cert_CXXFLAGS) $(CXXFLAGS) -MT stap_gen_cert-util.o -MD -MP -MF $(DEPDIR)/stap_gen_cert-util.Tpo -c -o stap_gen_cert-util.o `test -f 'util.cxx' || echo '$(srcdir)/'`util.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_gen_cert-util.Tpo $(DEPDIR)/stap_gen_cert-util.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='util.cxx' object='stap_gen_cert-util.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_gen_cert_CXXFLAGS) $(CXXFLAGS) -c -o stap_gen_cert-util.o `test -f 'util.cxx' || echo '$(srcdir)/'`util.cxx stap_gen_cert-util.obj: util.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_gen_cert_CXXFLAGS) $(CXXFLAGS) -MT stap_gen_cert-util.obj -MD -MP -MF $(DEPDIR)/stap_gen_cert-util.Tpo -c -o stap_gen_cert-util.obj `if test -f 'util.cxx'; then $(CYGPATH_W) 'util.cxx'; else $(CYGPATH_W) '$(srcdir)/util.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_gen_cert-util.Tpo $(DEPDIR)/stap_gen_cert-util.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='util.cxx' object='stap_gen_cert-util.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_gen_cert_CXXFLAGS) $(CXXFLAGS) -c -o stap_gen_cert-util.obj `if test -f 'util.cxx'; then $(CYGPATH_W) 'util.cxx'; else $(CYGPATH_W) '$(srcdir)/util.cxx'; fi` stap_gen_cert-nsscommon.o: nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_gen_cert_CXXFLAGS) $(CXXFLAGS) -MT stap_gen_cert-nsscommon.o -MD -MP -MF $(DEPDIR)/stap_gen_cert-nsscommon.Tpo -c -o stap_gen_cert-nsscommon.o `test -f 'nsscommon.cxx' || echo '$(srcdir)/'`nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_gen_cert-nsscommon.Tpo $(DEPDIR)/stap_gen_cert-nsscommon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='nsscommon.cxx' object='stap_gen_cert-nsscommon.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_gen_cert_CXXFLAGS) $(CXXFLAGS) -c -o stap_gen_cert-nsscommon.o `test -f 'nsscommon.cxx' || echo '$(srcdir)/'`nsscommon.cxx stap_gen_cert-nsscommon.obj: nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_gen_cert_CXXFLAGS) $(CXXFLAGS) -MT stap_gen_cert-nsscommon.obj -MD -MP -MF $(DEPDIR)/stap_gen_cert-nsscommon.Tpo -c -o stap_gen_cert-nsscommon.obj `if test -f 'nsscommon.cxx'; then $(CYGPATH_W) 'nsscommon.cxx'; else $(CYGPATH_W) '$(srcdir)/nsscommon.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_gen_cert-nsscommon.Tpo $(DEPDIR)/stap_gen_cert-nsscommon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='nsscommon.cxx' object='stap_gen_cert-nsscommon.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_gen_cert_CXXFLAGS) $(CXXFLAGS) -c -o stap_gen_cert-nsscommon.obj `if test -f 'nsscommon.cxx'; then $(CYGPATH_W) 'nsscommon.cxx'; else $(CYGPATH_W) '$(srcdir)/nsscommon.cxx'; fi` stap_serverd-stap-serverd.o: stap-serverd.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -MT stap_serverd-stap-serverd.o -MD -MP -MF $(DEPDIR)/stap_serverd-stap-serverd.Tpo -c -o stap_serverd-stap-serverd.o `test -f 'stap-serverd.cxx' || echo '$(srcdir)/'`stap-serverd.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_serverd-stap-serverd.Tpo $(DEPDIR)/stap_serverd-stap-serverd.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stap-serverd.cxx' object='stap_serverd-stap-serverd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -c -o stap_serverd-stap-serverd.o `test -f 'stap-serverd.cxx' || echo '$(srcdir)/'`stap-serverd.cxx stap_serverd-stap-serverd.obj: stap-serverd.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -MT stap_serverd-stap-serverd.obj -MD -MP -MF $(DEPDIR)/stap_serverd-stap-serverd.Tpo -c -o stap_serverd-stap-serverd.obj `if test -f 'stap-serverd.cxx'; then $(CYGPATH_W) 'stap-serverd.cxx'; else $(CYGPATH_W) '$(srcdir)/stap-serverd.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_serverd-stap-serverd.Tpo $(DEPDIR)/stap_serverd-stap-serverd.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stap-serverd.cxx' object='stap_serverd-stap-serverd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -c -o stap_serverd-stap-serverd.obj `if test -f 'stap-serverd.cxx'; then $(CYGPATH_W) 'stap-serverd.cxx'; else $(CYGPATH_W) '$(srcdir)/stap-serverd.cxx'; fi` stap_serverd-cscommon.o: cscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -MT stap_serverd-cscommon.o -MD -MP -MF $(DEPDIR)/stap_serverd-cscommon.Tpo -c -o stap_serverd-cscommon.o `test -f 'cscommon.cxx' || echo '$(srcdir)/'`cscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_serverd-cscommon.Tpo $(DEPDIR)/stap_serverd-cscommon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='cscommon.cxx' object='stap_serverd-cscommon.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -c -o stap_serverd-cscommon.o `test -f 'cscommon.cxx' || echo '$(srcdir)/'`cscommon.cxx stap_serverd-cscommon.obj: cscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -MT stap_serverd-cscommon.obj -MD -MP -MF $(DEPDIR)/stap_serverd-cscommon.Tpo -c -o stap_serverd-cscommon.obj `if test -f 'cscommon.cxx'; then $(CYGPATH_W) 'cscommon.cxx'; else $(CYGPATH_W) '$(srcdir)/cscommon.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_serverd-cscommon.Tpo $(DEPDIR)/stap_serverd-cscommon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='cscommon.cxx' object='stap_serverd-cscommon.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -c -o stap_serverd-cscommon.obj `if test -f 'cscommon.cxx'; then $(CYGPATH_W) 'cscommon.cxx'; else $(CYGPATH_W) '$(srcdir)/cscommon.cxx'; fi` stap_serverd-util.o: util.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -MT stap_serverd-util.o -MD -MP -MF $(DEPDIR)/stap_serverd-util.Tpo -c -o stap_serverd-util.o `test -f 'util.cxx' || echo '$(srcdir)/'`util.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_serverd-util.Tpo $(DEPDIR)/stap_serverd-util.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='util.cxx' object='stap_serverd-util.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -c -o stap_serverd-util.o `test -f 'util.cxx' || echo '$(srcdir)/'`util.cxx stap_serverd-util.obj: util.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -MT stap_serverd-util.obj -MD -MP -MF $(DEPDIR)/stap_serverd-util.Tpo -c -o stap_serverd-util.obj `if test -f 'util.cxx'; then $(CYGPATH_W) 'util.cxx'; else $(CYGPATH_W) '$(srcdir)/util.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_serverd-util.Tpo $(DEPDIR)/stap_serverd-util.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='util.cxx' object='stap_serverd-util.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -c -o stap_serverd-util.obj `if test -f 'util.cxx'; then $(CYGPATH_W) 'util.cxx'; else $(CYGPATH_W) '$(srcdir)/util.cxx'; fi` stap_serverd-privilege.o: privilege.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -MT stap_serverd-privilege.o -MD -MP -MF $(DEPDIR)/stap_serverd-privilege.Tpo -c -o stap_serverd-privilege.o `test -f 'privilege.cxx' || echo '$(srcdir)/'`privilege.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_serverd-privilege.Tpo $(DEPDIR)/stap_serverd-privilege.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='privilege.cxx' object='stap_serverd-privilege.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -c -o stap_serverd-privilege.o `test -f 'privilege.cxx' || echo '$(srcdir)/'`privilege.cxx stap_serverd-privilege.obj: privilege.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -MT stap_serverd-privilege.obj -MD -MP -MF $(DEPDIR)/stap_serverd-privilege.Tpo -c -o stap_serverd-privilege.obj `if test -f 'privilege.cxx'; then $(CYGPATH_W) 'privilege.cxx'; else $(CYGPATH_W) '$(srcdir)/privilege.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_serverd-privilege.Tpo $(DEPDIR)/stap_serverd-privilege.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='privilege.cxx' object='stap_serverd-privilege.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -c -o stap_serverd-privilege.obj `if test -f 'privilege.cxx'; then $(CYGPATH_W) 'privilege.cxx'; else $(CYGPATH_W) '$(srcdir)/privilege.cxx'; fi` stap_serverd-nsscommon.o: nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -MT stap_serverd-nsscommon.o -MD -MP -MF $(DEPDIR)/stap_serverd-nsscommon.Tpo -c -o stap_serverd-nsscommon.o `test -f 'nsscommon.cxx' || echo '$(srcdir)/'`nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_serverd-nsscommon.Tpo $(DEPDIR)/stap_serverd-nsscommon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='nsscommon.cxx' object='stap_serverd-nsscommon.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -c -o stap_serverd-nsscommon.o `test -f 'nsscommon.cxx' || echo '$(srcdir)/'`nsscommon.cxx stap_serverd-nsscommon.obj: nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -MT stap_serverd-nsscommon.obj -MD -MP -MF $(DEPDIR)/stap_serverd-nsscommon.Tpo -c -o stap_serverd-nsscommon.obj `if test -f 'nsscommon.cxx'; then $(CYGPATH_W) 'nsscommon.cxx'; else $(CYGPATH_W) '$(srcdir)/nsscommon.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_serverd-nsscommon.Tpo $(DEPDIR)/stap_serverd-nsscommon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='nsscommon.cxx' object='stap_serverd-nsscommon.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -c -o stap_serverd-nsscommon.obj `if test -f 'nsscommon.cxx'; then $(CYGPATH_W) 'nsscommon.cxx'; else $(CYGPATH_W) '$(srcdir)/nsscommon.cxx'; fi` stap_serverd-cmdline.o: cmdline.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -MT stap_serverd-cmdline.o -MD -MP -MF $(DEPDIR)/stap_serverd-cmdline.Tpo -c -o stap_serverd-cmdline.o `test -f 'cmdline.cxx' || echo '$(srcdir)/'`cmdline.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_serverd-cmdline.Tpo $(DEPDIR)/stap_serverd-cmdline.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='cmdline.cxx' object='stap_serverd-cmdline.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -c -o stap_serverd-cmdline.o `test -f 'cmdline.cxx' || echo '$(srcdir)/'`cmdline.cxx stap_serverd-cmdline.obj: cmdline.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -MT stap_serverd-cmdline.obj -MD -MP -MF $(DEPDIR)/stap_serverd-cmdline.Tpo -c -o stap_serverd-cmdline.obj `if test -f 'cmdline.cxx'; then $(CYGPATH_W) 'cmdline.cxx'; else $(CYGPATH_W) '$(srcdir)/cmdline.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_serverd-cmdline.Tpo $(DEPDIR)/stap_serverd-cmdline.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='cmdline.cxx' object='stap_serverd-cmdline.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_serverd_CXXFLAGS) $(CXXFLAGS) -c -o stap_serverd-cmdline.obj `if test -f 'cmdline.cxx'; then $(CYGPATH_W) 'cmdline.cxx'; else $(CYGPATH_W) '$(srcdir)/cmdline.cxx'; fi` stap_sign_module-stap-sign-module.o: stap-sign-module.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_sign_module_CPPFLAGS) $(CPPFLAGS) $(stap_sign_module_CXXFLAGS) $(CXXFLAGS) -MT stap_sign_module-stap-sign-module.o -MD -MP -MF $(DEPDIR)/stap_sign_module-stap-sign-module.Tpo -c -o stap_sign_module-stap-sign-module.o `test -f 'stap-sign-module.cxx' || echo '$(srcdir)/'`stap-sign-module.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_sign_module-stap-sign-module.Tpo $(DEPDIR)/stap_sign_module-stap-sign-module.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stap-sign-module.cxx' object='stap_sign_module-stap-sign-module.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_sign_module_CPPFLAGS) $(CPPFLAGS) $(stap_sign_module_CXXFLAGS) $(CXXFLAGS) -c -o stap_sign_module-stap-sign-module.o `test -f 'stap-sign-module.cxx' || echo '$(srcdir)/'`stap-sign-module.cxx stap_sign_module-stap-sign-module.obj: stap-sign-module.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_sign_module_CPPFLAGS) $(CPPFLAGS) $(stap_sign_module_CXXFLAGS) $(CXXFLAGS) -MT stap_sign_module-stap-sign-module.obj -MD -MP -MF $(DEPDIR)/stap_sign_module-stap-sign-module.Tpo -c -o stap_sign_module-stap-sign-module.obj `if test -f 'stap-sign-module.cxx'; then $(CYGPATH_W) 'stap-sign-module.cxx'; else $(CYGPATH_W) '$(srcdir)/stap-sign-module.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_sign_module-stap-sign-module.Tpo $(DEPDIR)/stap_sign_module-stap-sign-module.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stap-sign-module.cxx' object='stap_sign_module-stap-sign-module.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_sign_module_CPPFLAGS) $(CPPFLAGS) $(stap_sign_module_CXXFLAGS) $(CXXFLAGS) -c -o stap_sign_module-stap-sign-module.obj `if test -f 'stap-sign-module.cxx'; then $(CYGPATH_W) 'stap-sign-module.cxx'; else $(CYGPATH_W) '$(srcdir)/stap-sign-module.cxx'; fi` stap_sign_module-nsscommon.o: nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_sign_module_CPPFLAGS) $(CPPFLAGS) $(stap_sign_module_CXXFLAGS) $(CXXFLAGS) -MT stap_sign_module-nsscommon.o -MD -MP -MF $(DEPDIR)/stap_sign_module-nsscommon.Tpo -c -o stap_sign_module-nsscommon.o `test -f 'nsscommon.cxx' || echo '$(srcdir)/'`nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_sign_module-nsscommon.Tpo $(DEPDIR)/stap_sign_module-nsscommon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='nsscommon.cxx' object='stap_sign_module-nsscommon.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_sign_module_CPPFLAGS) $(CPPFLAGS) $(stap_sign_module_CXXFLAGS) $(CXXFLAGS) -c -o stap_sign_module-nsscommon.o `test -f 'nsscommon.cxx' || echo '$(srcdir)/'`nsscommon.cxx stap_sign_module-nsscommon.obj: nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_sign_module_CPPFLAGS) $(CPPFLAGS) $(stap_sign_module_CXXFLAGS) $(CXXFLAGS) -MT stap_sign_module-nsscommon.obj -MD -MP -MF $(DEPDIR)/stap_sign_module-nsscommon.Tpo -c -o stap_sign_module-nsscommon.obj `if test -f 'nsscommon.cxx'; then $(CYGPATH_W) 'nsscommon.cxx'; else $(CYGPATH_W) '$(srcdir)/nsscommon.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_sign_module-nsscommon.Tpo $(DEPDIR)/stap_sign_module-nsscommon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='nsscommon.cxx' object='stap_sign_module-nsscommon.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_sign_module_CPPFLAGS) $(CPPFLAGS) $(stap_sign_module_CXXFLAGS) $(CXXFLAGS) -c -o stap_sign_module-nsscommon.obj `if test -f 'nsscommon.cxx'; then $(CYGPATH_W) 'nsscommon.cxx'; else $(CYGPATH_W) '$(srcdir)/nsscommon.cxx'; fi` stap_sign_module-util.o: util.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_sign_module_CPPFLAGS) $(CPPFLAGS) $(stap_sign_module_CXXFLAGS) $(CXXFLAGS) -MT stap_sign_module-util.o -MD -MP -MF $(DEPDIR)/stap_sign_module-util.Tpo -c -o stap_sign_module-util.o `test -f 'util.cxx' || echo '$(srcdir)/'`util.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_sign_module-util.Tpo $(DEPDIR)/stap_sign_module-util.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='util.cxx' object='stap_sign_module-util.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_sign_module_CPPFLAGS) $(CPPFLAGS) $(stap_sign_module_CXXFLAGS) $(CXXFLAGS) -c -o stap_sign_module-util.o `test -f 'util.cxx' || echo '$(srcdir)/'`util.cxx stap_sign_module-util.obj: util.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_sign_module_CPPFLAGS) $(CPPFLAGS) $(stap_sign_module_CXXFLAGS) $(CXXFLAGS) -MT stap_sign_module-util.obj -MD -MP -MF $(DEPDIR)/stap_sign_module-util.Tpo -c -o stap_sign_module-util.obj `if test -f 'util.cxx'; then $(CYGPATH_W) 'util.cxx'; else $(CYGPATH_W) '$(srcdir)/util.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_sign_module-util.Tpo $(DEPDIR)/stap_sign_module-util.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='util.cxx' object='stap_sign_module-util.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_sign_module_CPPFLAGS) $(CPPFLAGS) $(stap_sign_module_CXXFLAGS) $(CXXFLAGS) -c -o stap_sign_module-util.obj `if test -f 'util.cxx'; then $(CYGPATH_W) 'util.cxx'; else $(CYGPATH_W) '$(srcdir)/util.cxx'; fi` install-oldincludeHEADERS: $(oldinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(oldinclude_HEADERS)'; test -n "$(oldincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(oldincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(oldincludedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(oldincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(oldincludedir)" || exit $$?; \ done uninstall-oldincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(oldinclude_HEADERS)'; test -n "$(oldincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(oldincludedir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done cscopelist-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) config.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) config.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) config.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist-recursive cscopelist cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-recursive all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(HEADERS) config.h all-local installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkglibexecdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkglibexecdir)" "$(DESTDIR)$(oldincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) @BUILD_CRASHMOD_FALSE@@BUILD_ELFUTILS_FALSE@@HAVE_NSS_FALSE@install-exec-local: @BUILD_CRASHMOD_FALSE@@BUILD_TRANSLATOR_FALSE@install-exec-local: clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic clean-local \ clean-noinstPROGRAMS clean-pkglibexecPROGRAMS mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-local distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-data-local install-oldincludeHEADERS install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binPROGRAMS install-binSCRIPTS \ install-exec-local install-pkglibexecPROGRAMS \ install-pkglibexecSCRIPTS install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \ uninstall-local uninstall-oldincludeHEADERS \ uninstall-pkglibexecPROGRAMS uninstall-pkglibexecSCRIPTS .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all check \ check-am cscopelist-recursive ctags-recursive install \ install-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am all-local am--refresh check check-am check-local \ clean clean-binPROGRAMS clean-cscope clean-generic clean-local \ clean-noinstPROGRAMS clean-pkglibexecPROGRAMS cscope \ cscopelist cscopelist-recursive ctags ctags-recursive \ distclean distclean-compile distclean-generic distclean-hdr \ distclean-local distclean-tags dvi dvi-am html html-am info \ info-am install install-am install-binPROGRAMS \ install-binSCRIPTS install-data install-data-am \ install-data-local install-dvi install-dvi-am install-exec \ install-exec-am install-exec-local install-html \ install-html-am install-info install-info-am install-man \ install-oldincludeHEADERS install-pdf install-pdf-am \ install-pkglibexecPROGRAMS install-pkglibexecSCRIPTS \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-binSCRIPTS uninstall-local \ uninstall-oldincludeHEADERS uninstall-pkglibexecPROGRAMS \ uninstall-pkglibexecSCRIPTS install: all $(MAKE) $(AM_MAKEFLAGS) install-recursive git_version.stamp: @if test -f "$(srcdir)/git_version.h"; then \ if test -f "git_version.h"; then :; \ else \ cp "$(srcdir)/git_version.h" "git_version.h"; \ fi; \ fi $(GIT_VERSION_CMD) -k -s $(top_srcdir) -o git_version.h @if test -s "$(srcdir)/git_version.h"; then \ if cmp "$(srcdir)/git_version.h" "git_version.h"; then :; \ else \ echo "Error: $(srcdir)/git_version.h and git_version.h differ."; \ echo " You probably want to remove the former."; \ exit 1; \ fi; \ fi git_version.h: $(srcdir)/git_version.sh -k --srcdir $(srcdir) -o git_version.h cscope: cd $(srcdir) && \ (echo -q ; git ls-files '*.cxx' '*.c' '*.h' | grep -v '^testsuite' ) > cscope.files && \ cscope -b -q @DYNINST_CXXFLAGS@ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@install-exec-local: install-scripts # scripts must be installed before this rule is run @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@install-scripts: install-binSCRIPTS install-pkglibexecSCRIPTS @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ for f in $(bin_SCRIPTS); do \ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ sed -i -e "s,\$${PKGLIBEXECDIR},$(pkglibexecdir)/," $(DESTDIR)$(bindir)/$$f; \ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ done @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ for f in $(pkglibexec_SCRIPTS); do \ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ sed -i -e "/INSTALL-HOOK/d;s,sysconfdir=.*,sysconfdir=$(sysconfdir),;s,pkglibexecdir=.*,pkglibexecdir=$(pkglibexecdir)/,;s,localstatedir=.*,localstatedir=$(localstatedir),;s,\$${PKGLIBEXECDIR},$(pkglibexecdir)/," $(DESTDIR)$(pkglibexecdir)/$$f; \ @BUILD_TRANSLATOR_TRUE@@HAVE_NSS_TRUE@ done @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@stamp-elfutils: config.status @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@ $(MAKE) $(AM_MAKEFLAGS) -C build-elfutils all bin_PROGRAMS= @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@ for dir in libelf libebl libdw libdwfl backends; do \ @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@ $(MAKE) $(AM_MAKEFLAGS) -j1 -C build-elfutils/$$dir bin_PROGRAMS= install; \ @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@ done @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@ $(MAKE) $(AM_MAKEFLAGS) -j1 -C build-elfutils install-pkgincludeHEADERS; @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@ touch $@ @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@lib-elfutils/libdw.so: stamp-elfutils ; @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@install-elfutils: @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@ mkdir -p $(DESTDIR)$(pkglibdir) @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@ for file in lib-elfutils/*.so* lib-elfutils/${PACKAGE_NAME}/*.so*; do \ @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@ $(INSTALL_PROGRAM) $$file $(DESTDIR)$(pkglibdir); \ @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@ done @BUILD_ELFUTILS_TRUE@@BUILD_TRANSLATOR_TRUE@install-exec-local: install-elfutils @BUILD_CRASHMOD_TRUE@$(STAPLOG): staplog.c @BUILD_CRASHMOD_TRUE@ $(CC) $(staplog_CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -shared -rdynamic \ @BUILD_CRASHMOD_TRUE@ $(AM_LDFLAGS) $(LDFLAGS) -fPIC -o $@ $< @BUILD_CRASHMOD_TRUE@all-local: $(STAPLOG) example_index @BUILD_CRASHMOD_TRUE@install-exec-local: $(STAPLOG) @BUILD_CRASHMOD_TRUE@ $(MKDIR_P) $(DESTDIR)$(pkglibdir) @BUILD_CRASHMOD_TRUE@ $(INSTALL) $(STAPLOG) $(DESTDIR)$(pkglibdir) @BUILD_CRASHMOD_FALSE@all-local: example_index example_index: $(EXAMPLE_SOURCE_DIR)/index.html $(EXAMPLE_SOURCE_DIR)/index.html: $(EXAMPLE_META_FILES) $(EXAMPLE_INDEX_GEN) @echo "The script example index is outdated, run" @echo " cd $(EXAMPLE_SOURCE_DIR) && \\ " @echo " perl examples-index-gen.pl" @echo "to regenerate it." install-data-local: (cd $(srcdir)/runtime; for f in *.[ch]; do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/$$f; done) @HAVE_DYNINST_TRUE@ (cd $(srcdir)/runtime/dyninst; find . \( -name '*.[ch]' \) -print \ @HAVE_DYNINST_TRUE@ | while read f; do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/dyninst/$$f; done) (cd $(srcdir)/runtime/unwind; find . \( -name '*.[ch]' \) -print \ | while read f; do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/unwind/$$f; done) (cd $(srcdir)/runtime/transport; for f in *.[ch]; \ do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/transport/$$f; done) (cd $(srcdir)/runtime/linux; for f in *.[ch]; \ do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/linux/$$f; done) (cd $(srcdir)/runtime/linux/uprobes; for f in Makefile *.[ch]; \ do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/linux/uprobes/$$f; done) (cd $(srcdir)/runtime/linux/uprobes2; for f in *.[ch]; \ do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/linux/uprobes2/$$f; done) (cd $(srcdir)/tapset; find . \( -name '*.stp' -o -name '*.stpm' -o -name README \) -print \ | while read f; do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/tapset/$$f; done) (cd $(srcdir)/testsuite/systemtap.examples; find . -type f -print \ | egrep -v 'check.exp|ChangeLog|examples-index-gen.pl|html/.*\.tmpl$$' \ | while read f; do if test -x $$f; then \ i_cmd="$(INSTALL_PROGRAM)"; else \ i_cmd="$(INSTALL_DATA)"; fi; \ $$i_cmd -D $$f $(DESTDIR)$(docdir)/examples/$$f; done) test -e $(DESTDIR)$(sysconfdir)/systemtap || mkdir -p $(DESTDIR)$(sysconfdir)/systemtap @BUILD_SERVER_TRUE@ test -e $(DESTDIR)$(localstatedir)/run/stap-server || mkdir -p $(DESTDIR)$(localstatedir)/run/stap-server @BUILD_SERVER_TRUE@ test -e $(DESTDIR)$(localstatedir)/log || mkdir -p $(DESTDIR)$(localstatedir)/log gcov: find . -name '*.gc*' | xargs rm -f $(MAKE) clean CXXFLAGS="-g -fprofile-arcs -ftest-coverage" CFLAGS="-g -fprofile-arcs -ftest-coverage" all install -sudo $(MAKE) installcheck $${RUNTESTFLAGS+RUNTESTFLAGS=$${RUNTESTFLAGS}} for dir in $(SUBDIRS); do \ (cd $$dir; gcov *.gcno > SUMMARY.gcov 2>&1 || true); \ done find . -name '*.gcov' clean-local: rm -rf ${PACKAGE_TARNAME}-*.tar.gz rm -rf ${PACKAGE_TARNAME}-${PACKAGE_VERSION} rm -rf $(TEST_COV_DIR) rm -rf stap.info rm -rf staplog.so distclean-local: rm -rf build-elfutils include-elfutils lib-elfutils rm -f doc/beginners/en-US doc/beginners/build/en-US/testsuite uninstall-local: rm -rf $(DESTDIR)$(pkgdatadir) rm -rf $(DESTDIR)$(libdir)/$(PACKAGE) -rm -rf $(DESTDIR)$(localstatedir)/cache/$(PACKAGE) @list='$(EXAMPLE_SRC)'; for f in $$list; do p=`basename $$f`; \ echo " rm -f '$(EXAMPLE_INSTALL_DIR)/$$p'"; \ rm -f "$(EXAMPLE_INSTALL_DIR)/$$p"; \ done @list='$(DEMO_SRC)'; for f in $$list; do p=`basename $$f`; \ echo " rm -f '$(DEMO_INSTALL_DIR)/$$p'"; \ rm -f "$(DEMO_INSTALL_DIR)/$$p"; \ done @list='$(SAMPLE_SRC)'; for f in $$list; do p=`basename $$f`; \ echo " rm -f '$(SAMPLE_INSTALL_DIR)/$$p'"; \ rm -f "$(SAMPLE_INSTALL_DIR)/$$p"; \ done rm -rf $(DESTDIR)$(sysconfdir)/systemtap rm -rf $(DESTDIR)$(docdir)/examples @BUILD_SERVER_TRUE@ rm -rf $(DESTDIR)$(localstatedir)/run/stap-server @BUILD_SERVER_TRUE@ rm -f $(DESTDIR)$(localstatedir)/log/stap-server/log check-local: SRCDIR=`cd $(srcdir); pwd`; \ PWD=`pwd`; \ $(MAKE) -C testsuite check SYSTEMTAP_RUNTIME=$$SRCDIR/runtime SYSTEMTAP_TAPSET=$$SRCDIR/tapset LD_LIBRARY_PATH=$$LD_LIBRARY_PATH$${LD_LIBRARY_PATH:+:}$$PWD/lib-elfutils:$$PWD/lib-elfutils/systemtap SYSTEMTAP_PATH=$$PWD SYSTEMTAP_INCLUDES=$$PWD/includes RUNTESTFLAGS="$(RUNTESTFLAGS)" PKGLIBDIR="$(pkglibexecdir)"; installcheck: if test \! -e $(DESTDIR)$(bindir)/stap; then \ echo $(DESTDIR)$(bindir)/stap doesn\'t exist, run make install; \ exit -1; \ fi; \ if test $(builddir)/stap -nt $(DESTDIR)$(bindir)/stap; then \ echo "$(DESTDIR)$(bindir)/stap is not recent, run make install"; \ exit -1; \ fi; $(MAKE) -C testsuite installcheck RUNTESTFLAGS="$(RUNTESTFLAGS)" # All the variables are overridden by run-stap, but SYSTEMTAP_RUNTIME # is used by the testsuite scripts themselves. runcheck: testsuite/stap testsuite/dtrace $(MAKE) -C testsuite installcheck RUNTESTFLAGS="$(RUNTESTFLAGS)" \ SYSTEMTAP_PATH="`cd testsuite; pwd`" \ SYSTEMTAP_RUNTIME="`cd $(srcdir)/runtime; pwd`" testsuite/stap: run-stap (echo '#!/bin/sh'; echo "exec `pwd`/run-stap" '$${1+"$$@"}') > $@.new chmod 555 $@.new mv -f $@.new $@ testsuite/dtrace: dtrace (echo '#!/bin/sh'; echo "exec `pwd`/dtrace" '$${1+"$$@"}') > $@.new chmod 555 $@.new mv -f $@.new $@ update-po: (cd $(srcdir); ls -1d *.c *.cxx *.h staprun/*.c staprun/*.h) \ | grep -v loc2c-test.c \ | grep -v config.h \ | grep -v git_version.h \ | grep -v staprun/config.h \ | sort > $(srcdir)/po/POTFILES.in $(MAKE) -C po update-po uprobes: $(MAKE) -C $(srcdir)/runtime/uprobes clean default install-uprobes: $(MAKE) -C $(DESTDIR)$(pkgdatadir)/runtime/uprobes clean default .PHONY: $(PHONIES) dist-gzip: cd $(srcdir); git status | grep working.directory.clean || (echo "You should commit your changes before 'make rpm'.") (cd $(srcdir); git archive --prefix=systemtap-$(VERSION)/ --format=tar HEAD) | gzip > systemtap-$(VERSION).tar.gz rpm: dist-gzip if [ `id -u` = 0 ]; then echo NOTE: do not run this as root; exit 1; fi mkdir -p `rpm --eval %_specdir` mkdir -p `rpm --eval %_srcrpmdir` mkdir -p `rpm --eval %_rpmdir` mkdir -p `rpm --eval %_builddir` mkdir -p `rpm --eval %_buildroot` rpmbuild --define "_sourcedir $(PWD)/" -ta systemtap-$(VERSION).tar.gz $(RPMBUILDFLAGS) srpm: dist-gzip mkdir -p `rpm --eval %_srcrpmdir` rpmbuild --define "_sourcedir $(PWD)/" -ts systemtap-$(VERSION).tar.gz $(RPMBUILDFLAGS) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: systemtap-2.3/NEWS000066400000000000000000002447551217430427200141310ustar00rootroot00000000000000* What's new in version 2.3 - java("org.my.MyApp") probes are now restricted to pre-existing jvm pid's with a listing in jps -l output to avoid recursive calls - The tapset [nd_]syscall.semop parameter tsops_uaddr is renamed sops_uaddr for consistency with [nd_]syscall.semtimedop. - The udp.stp tapset adds some ip-address/port variables. - A new guru-mode-only tapset function raise() is available to send signals to the current task. - Support for the standard Posix ERE named character classes has been added to the regexp engine, e.g. [:digit:], [:alpha:], ... - A substantial internal overhaul of the regexp engine has resulted in correct behaviour on further obscure edge cases. The regexp engine now implements the ERE standard and correctly passes the testsuite for the glibc regexp engine (minus portions corresponding to unimplemented features -- i.e. subexpression capture and reuse). - Alternative functions are now suggested when function probes could not be resolved. For example, kernel.function("vfs_reads") will suggest vfs_read. Other probes for which suggestions are made are module.function, process.function, and process.library.function. - Has life been a bit bland lately? Want to spice things up? Why not write a few faulty probes and feast your eyes upon the myriad of colours adorning your terminal as SystemTap softly whispers in your ear... 'parse error'. Search for '--color' in 'man stap' for more info. - The following tapset functions are deprecated in release 2.3: 'stap_NFS_CLIENT', '__getfh_inode', '_success_check', '_sock_prot_num', '_sock_fam_num', '_sock_state_num', '_sock_type_num', and '_sock_flags_num'. * What's new in version 2.2.1, 2013-05-16 * What's new in version 2.2, 2013-05-14 - Experimental support has been added for probing Java methods using Byteman 2.0 as a backend. Java method probes can target method entries, returns, or specific statements in the method as specified by line number. probe java("org.my.MyApp").class("^java.lang.Object").method("foo(int)") { println($$parms) } See java/README for information on how to set up Java/Byteman functionality. Set env STAPBM_VERBOSE=yes for more tracing. - The stap -l output and pn() tapset function's return value may be slightly different for complicated web of wildcarded/aliased probes. - The dyninst backend has improved in several aspects: - Setting custom values for global variables is now supported, both with -G when compiling a script, and from the stapdyn command line when loading a precompiled module. - A high-performance shared-memory-based transport is used for trace data. - A systemd service file and tmpfile have been added to allow systemtap-server to be managed natively by systemd. - Due to the removal of register_timer_hook in recent kernels, the behaviour of timer.profile has been changed slightly. This probe is now an alias which uses the old mechanism where possible, but falls back to perf.sw.cpu_clock or another mechanism when the kernel timer hook is not available. To require the kernel timer hook mechanism in your script, use timer.profile.tick instead of timer.profile. - The following tapset variables are deprecated in release 2.2: - The 'origin' variables in the 'generic.fop.llseek', 'generic.fop.llseek.return', and 'nfs.fop.llseek' probes. The 'origin' variable has been replaced by the 'whence' variable. - The 'page_index' variable in the 'vfs.block_sync_page' and 'vfs.buffer_migrate_page' probe aliases. - The 'write_from' and 'write_upto' variables in the '_vfs.block_prepare_write' and '_vfs.block_prepare_write.return' probe aliases. - The 'regs' variable in the 'syscall.sigaltstack', 'nd_syscall.sigaltstack', 'syscall.fork', and 'nd_syscall.fork' probe aliases. - The 'first', 'second', 'third', and 'uptr_uaddr' variables in the 'syscall.compat_sys_shmat' and 'nd_syscall.compat_sys_shmat' probe aliases. - The following tapset functions are deprecated in release 2.2: 'ppos_pos', '_dev_minor', and '_dev_major' - The folowing tapset functions used to return error strings instead of raising an error. The original behavior is deprecated in release 2.2. 'ctime', 'probemod', 'modname' * What's new in version 2.1, 2013-02-13 - EMACS and VIM editor modes for systemtap source files are included / updated. - The translator now eliminates duplicate tapset files between its preferred directory (as configured during the build with --prefix=/ or specified with the -I /path option), and files it may find under $XDG_DATA_DIRS. This should eliminate a class of conflicts between parallel system- and hand-built systemtap installations. - The translator accepts a --suppress-time-limits option, which defeats time-related constraints, to allows probe handlers to run for indefinite periods. It requires the guru mode (-g) flag to work. Add the earlier --suppress-handler-errors flag for a gung-ho "just-keep-going" attitude. - Perf event probes may now be read on demand. The counter probe is defined using the counter-name part: probe perf.type(0).config(0).counter("NAME"). The counter is read in a user space probe using @perf("NAME"), e.g. process("PROCESS").statement("func@file") {stat <<< @perf("NAME")} - Perf event probes may now be bound to a specific task using the process-name part: probe perf.type(0).config(0).process("NAME") { } If the probed process name is not specified, then it is inferred from the -c CMD argument. - Some error messages and warnings now refer to additional information that is found in man pages. These are generally named error::FOO or warning::BAR (in the 7stap man page section) and may be read via % man error::FOO % man warning::BAR - The dyninst backend has improved in several aspects: - The runtime now allows much more concurrency when probing multithreaded processes, and will also follow probes across forks. - Several new probe types are now supported, including timers, function return, and process.begin/end and process.thread.begin/end. - Semaphores for SDT probes are now set properly. - Attaching to existing processes with -x PID now works. - The foreach looping construct can now sort aggregate arrays by the user's choice of aggregating function. Previously, @count was implied. e.g.: foreach ([x,y] in array @sum +) { println(@sum(array[x,y])) } - Proof of concept support for regular expression matching has been added: if ("aqqqqqb" =~ "q*b") { ... } if ("abc" !~ "q*b") { ... } The eventual aim is to support roughly the same functionality as the POSIX Extended Regular Expressions implemented by glibc. Currently missing features include extraction of the matched string and subexpressions, and named character classes ([:alpha:], [:digit:], &c). Special thanks go to the re2c project, whose public domain code this functionality has been based on. For more info on re2c, see: http://sourceforge.net/projects/re2c/ - The folowing tapset variables are deprecated in release 2.1 and will be removed in release 2.2: - The 'send2queue' variable in the 'signal.send' probe. - The 'oldset_addr' and 'regs' variables in the 'signal.handle' probe. - The following tapset probes are deprecated in release 2.1 and will be removed in release 2.2: - signal.send.return - signal.handle.return * What's new in version 2.0, 2012-10-09 - Systemtap includes a new prototype backend, which uses Dyninst to instrument a user's own processes at runtime. This backend does not use kernel modules, and does not require root privileges, but is restricted with respect to the kinds of probes and other constructs that a script may use. Users from source should configure --with-dyninst and install a fresh dyninst snapshot such as that in Fedora rawhide. It may be necessary to disable conflicting selinux checks; systemtap will advise. Select this new backend with the new stap option --runtime=dyninst and a -c target process, along with normal options. (-x target processes are not supported in this prototype version.) For example: stap --runtime=dyninst -c 'stap -l begin' \ -e 'probe process.function("main") { println("hi from dyninst!") }' - To aid diagnosis, when a kernel panic occurs systemtap now uses the panic_notifier_list facility to dump a summary of its trace buffers to the serial console. - The systemtap preprocessor now has a simple macro facility as follows: @define add(a,b) %( ((@a)+(@b)) %) @define probegin(x) %( probe begin { @x } %) @probegin( foo = @add(40, 2); print(foo) ) Macros defined in the user script and regular tapset .stp files are local to the file. To get around this, the tapset library can define globally visible 'library macros' inside .stpm files. (A .stpm file must contain a series of @define directives and nothing else.) The status of the feature is experimental; semantics of macroexpansion may change (unlikely) or expand in the future. - Systemtap probe aliases may be used with additional suffixes attached. The suffixes are passed on to the underlying probe point(s) as shown below: probe foo = bar, baz { } probe foo.subfoo.option("gronk") { } // expands to: bar.subfoo.option("gronk"), baz.subfoo.option("gronk") In practical terms, this allows us to specify additional options to certain tapset probe aliases, by writing e.g. probe syscall.open.return.maxactive(5) { ... } - To support the possibility of separate kernel and dyninst backends, the tapsets have been reorganized into separate folders according to backend. Thus kernel-specific tapsets are located under linux/, the dyninst-specific ones under dyninst/ - The backtrace/unwind tapsets have been expanded to allow random access to individual elements of the backtrace. (A caching mechanism ensures that the backtrace computation run at most once for each time a probe fires, regardless of how many times or what order the query functions are called in.) New tapset functions are: stack/ustack - return n'th element of backtrace callers/ucallers - return first n elements of backtrace print_syms/print_usyms - print full information on a list of symbols sprint_syms/sprint_usyms - as above, but return info as a string The following existing functions have been superseded by print_syms() et al.; new scripts are recommended to avoid using them: print_stack() print_ustack() sprint_stack() sprint_ustack() - The probefunc() tapset function is now myproc-unprivileged, and can now be used in unprivileged scripts for such things as profiling in userspace programs. For instance, try running systemtap.examples/general/para-callgraph.stp in unprivileged mode with a stapusr-permitted probe. The previous implementation of probefunc() is available with "stap --compatible=1.8". - Preprocessor conditional to vary code based on script privilege level: unprivileged -- %( systemtap_privilege == "stapusr" %? ... %) privileged -- %( systemtap_privilege != "stapusr" %? ... %) or, alternately %( systemtap_privilege == "stapsys" || systemtap_privilege == "stapdev" %? ... %) - To ease migration to the embedded-C locals syntax introduced in 1.8 (namely, STAP_ARG_* and STAP_RETVALUE), the old syntax can now be re-enabled on a per-function basis using the /* unmangled */ pragma: function add_foo:long(a:long, b:long) %{ /* unmangled */ THIS->__retvalue = THIS->a + STAP_ARG_b; %} Note that both the old and the new syntax may be used in an /* unmangled */ function. Functions not marked /* unmangled */ can only use the new syntax. - Adjacent string literals are now glued together irrespective of intervening whitespace or comments: "foo " "bar" --> "foo bar" "foo " /* comment */ "bar" --> "foo bar" Previously, the first pair of literals would be glued correctly, while the second would cause a syntax error. * What's new in version 1.8, 2012-06-17 - staprun accepts a -T timeout option to allow less frequent wake-ups to poll for low-throughput output from scripts. - When invoked by systemtap, the kbuild $PATH environment is sanitized (prefixed with /usr/bin:/bin:) in an attempt to exclude compilers other than the one the kernel was presumed built with. - Printf formats can now use "%#c" to escape non-printing characters. - Pretty-printed bitfields use integers and chars use escaped formatting for printing. - The systemtap compile-server and client now support IPv6 networks. - IPv6 addresses may now be specified on the --use-server option and will be displayed by --list-servers, if the avahi-daemon service is running and has IPv6 enabled. - Automatic server selection will automatically choose IPv4 or IPv6 servers according to the normal server selection criteria when avahi-daemon is running. One is not preferred over the other. - The compile-server will automatically listen on IPv6 addresses, if available. - To enable IPv6 in avahi-daemon, ensure that /etc/avahi/avahi-daemon.conf contains an active "use-ipv6=yes" line. After adding this line run "service avahi-daemon restart" to activate IPv6 support. - See man stap(1) for details on how to use IPv6 addresses with the --use-server option. - Support for DWARF4 .debug_types sections (for executables and shared libraries compiled with recent GCC's -gdwarf-4 / -fdebug-types-section). PR12997. SystemTap now requires elfutils 0.148+, full .debug_types support depends on elfutils 0.154+. - Systemtap modules are somewhat smaller & faster to compile. Their debuginfo is now suppressed by default; use -B CONFIG_DEBUG_INFO=y to re-enable. - @var now an alternative language syntax for accessing DWARF variables in uprobe and kprobe handlers (process, kernel, module). @var("somevar") can be used where $somevar can be used. The @var syntax also makes it possible to access non-local, global compile unit (CU) variables by specifying the CU source file as follows @var("somevar@some/src/file.c"). This will provide the target variable value of global "somevar" as defined in the source file "some/src/file.c". The @var syntax combines with all normal features of DWARF target variables like @defined(), @entry(), [N] array indexing, field access through ->, taking the address with the & prefix and shallow or deep pretty printing with a $ or $$ suffix. - Stap now has resource limit options: --rlimit-as=NUM --rlimit-cpu=NUM --rlimit-nproc=NUM --rlimit-stack=NUM --rlimit-fsize=NUM All resource limiting has been moved from the compile server to stap itself. When running the server as "stap-server", default resource limit values are specified in ~stap-server/.systemtap/rc. - Bug CVE-2012-0875 (kernel panic when processing malformed DWARF unwind data) is fixed. - The systemtap compile-server now supports multiple concurrent connections. Specify the desired maximum number of concurrent connections with the new stap-server/stap-serverd --max-threads option. Specify a value of '0' to tell the server not to spawn any new threads (handle all connections serially in the main thread). The default value is the number of processor cores on the host. - The following tapset functions are deprecated in release 1.8 and will be removed in release 1.9: daddr_to_string() - SystemTap now mangles local variables to avoid collisions with C headers included by tapsets. This required a change in how embedded-C functions access local parameters and the return value slot. Instead of THIS->foo in an embedded-C function, please use the newly defined macro STAP_ARG_foo (substitute the actual name of the argument for 'foo'); instead of THIS->__retvalue, use the newly defined STAP_RETVALUE. All of the tapsets and test cases have been adapted to use this new notation. If you need to run code which uses the old THIS-> notation, run stap with the --compatible=1.7 option. - There is updated support for user-space probing against kernels >= 3.5, which have no utrace but do have the newer inode-uprobes work by Srikar Dronamraju and colleagues. For kernels < 3.5, the following 3 sets of kernel patches would need to be backported to your kernel to use this preliminary user-space probing support: - inode-uprobes patches: - 2b144498350860b6ee9dc57ff27a93ad488de5dc - 7b2d81d48a2d8e37efb6ce7b4d5ef58822b30d89 - a5f4374a9610fd7286c2164d4e680436727eff71 - 04a3d984d32e47983770d314cdb4e4d8f38fccb7 - 96379f60075c75b261328aa7830ef8aa158247ac - 3ff54efdfaace9e9b2b7c1959a865be6b91de96c - 35aa621b5ab9d08767f7bc8d209b696df281d715 - 900771a483ef28915a48066d7895d8252315607a - e3343e6a2819ff5d0dfc4bb5c9fb7f9a4d04da73 - exec tracepoint kernel patch: - 4ff16c25e2cc48cbe6956e356c38a25ac063a64d - task_work_add kernel patches: - e73f8959af0439d114847eab5a8a5ce48f1217c4 - 4d1d61a6b203d957777d73fcebf19d90b038b5b2 - 413cd3d9abeaef590e5ce00564f7a443165db238 - dea649b8ac1861107c5d91e1a71121434fc64193 - f23ca335462e3c84f13270b9e65f83936068ec2c * What's new in version 1.7, 2012-02-01 - Map inserting and deleting is now significantly faster due to improved hashing and larger hash tables. The hashes are also now randomized to provide better protection against deliberate collision attacks. - Formatted printing is faster by compiling the formatting directives to C code rather than interpreting at run time. - Systemtap loads extra command line options from $SYSTEMTAP_DIR/rc ($HOME/.systemtap/rc by default) before the normal argc/argv. This may be useful to activate site options such as --use-server or --download-debuginfo or --modinfo. - The stap-server has seen many improvements, and is no longer considered experimental. - The stap-server service (initscript) now supports four new options: -D MACRO[=VALUE] --log LOGFILE --port PORT-NUMBER --SSL CERT-DATABASE These allow the specification of macro definitions to be passed to stap by the server, the location of the log file, network port number and NSS certificate database location respectively. These options are also supported within individual server configuration files. See stap-server and initscript/README.stap-server for details. The stap-server is no longer activated by default. - process("PATH").[library("PATH")].function("NAME").exported probes are now supported to filter function() to only exported instances. - The translator supports a new --suppress-handler-errors option, which causes most runtime errors to be turned into quiet skipped probes. This also disables the MAXERRORS and MAXSKIPPED limits. - Translator warnings have been standardized and controlled by the -w / -W flags. - The translator supports a new --modinfo NAME=VALUE option to emit additional MODULE_INFO(n,v) macros into the generated code. - There is no more fixed maximum number of VMA pages that will be tracked at runtime. This reduces memory use for those scripts that don't need any, or only limited target process VMA tracking and allows easier system wide probes inspecting shared library variables and/or user backtraces. stap will now silently ignore -DTASK_FINDER_VMA_ENTRY_ITEMS. - The tapset functions remote_id() and remote_uri() identify the member of a swarm of "stap --remote FOO --remote BAR baz.stp" concurrent executions. - Systemtap now supports a new privilege level and group, "stapsys", which is equivalent to the privilege afforded by membership in the group "stapdev", except that guru mode (-g) functionality may not be used. To support this, a new option, --privilege=[stapusr|stapsys|stapdev] has been added. --privilege=stapusr is equivalent to specifying the existing --unprivileged option. --privilege=stapdev is the default. See man stap(1) for details. - Scripts that use kernel.trace("...") probes compile much faster. - The systemtap module cache is cleaned less frequently, governed by the number of seconds in the $SYSTEMTAP_DIR/cache/cache_clean_interval_s file. - SDT can now define up to 12 arguments in a probe point. - Parse errors no longer generate a cascade of false errors. Instead, a parse error skips the rest of the current probe or function, and resumes at the next one. This should generate fewer and better messages. - Global array wrapping is now supported for both associative and statistics typed arrays using the '%' character to signify a wrapped array. For example, 'global foo%[100]' would allow the array 'foo' to be wrapped if more than 100 elements are inserted. - process("PATH").library("PATH").plt("NAME") probes are now supported. Wildcards are supported in the plt-name part, to refer to any function in the program linkage table which matches the glob pattern and the rest of the probe point. - A new option, --dump-probe-types, will dump a list of supported probe types. If --unprivileged is also specified, the list will be limited to probe types which are available to unprivileged users. - Systemtap can now automatically download the required debuginfo using abrt. The --download-debuginfo[=OPTION] can be used to control this feature. Possible values are: 'yes', 'no', 'ask', and a positive number representing the timeout desired. The default behavior is to not automatically download the debuginfo. - The translator has better support for probing C++ applications by better undertanding of compilation units, nested types, templates, as used in probe point and @cast constructs. - On 2.6.29+ kernels, systemtap can now probe kernel modules that arrive and/or depart during the run-time of a session. This allows probing of device driver initialization functions, which had formerly been blacklisted. - New tapset functions for cpu_clock and local_clock access were added. - There is some limited preliminary support for user-space probing against kernels such as linux-next, which have no utrace but do have the newer inode-uprobes work by Srikar Dronamraju and colleagues. - The following probe types are deprecated in release 1.7 and will be removed in release 1.8: kernel.function(number).inline module(string).function(number).inline process.function(number).inline process.library(string).function(number).inline process(string).function(number).inline process(string).library(string).function(number).inline - The systemtap-grapher is deprecated in release 1.7 and will be removed in release 1.8. - The task_backtrace() tapset function was deprecated in 1.6 and has been removed in 1.7. - MAXBACKTRACE did work in earlier releases, but has now been documented in the stap 1 manual page. - New tapset function probe_type(). Returns a short string describing the low level probe handler type for the current probe point. - Both unwind and symbol data is now only collected and emitted for scripts actually using backtracing or function/data symbols. Tapset functions are marked with /* pragma:symbols */ or /* pragma:unwind */ to indicate they need the specific data. - Kernel backtraces can now be generated for non-pt_regs probe context if the kernel support dump_trace(). This enables backtraces from certain timer probes and tracepoints. - ubacktrace() should now also work for some kernel probes on x86 which can use the dwarf unwinder to recover the user registers to provide more accurate user backtraces. - For s390x the systemtap runtime now properly splits kernel and user addresses (which are in separate address spaces on that architecture) which enable user space introspection. - ppc and s390x now supports user backtraces through the DWARF unwinder. - ppc now handles function descriptors as symbol names correctly. - arm support kernel backtraces through the DWARF unwinder. - arm now have a uprobes port which enables user probes. This still requires some kernel patches (user_regsets and tracehook support for arm). - Starting in release 1.7, these old variables will be deprecated: - The 'pid' variable in the 'kprocess.release' probe has been deprecated in favor of the new 'released_pid' variable. - The 'args' variable in the '_sunrpc.clnt.create_client.rpc_new_client_inline' probe has been deprecated in favor of the new internal-only '__args' variable. - Experimental support for recent kernels without utrace has been added for the following probe types: process(PID).begin process("PATH").begin process.begin process(PID).thread.begin process("PATH").thread.begin process.thread.begin process(PID).end process("PATH").end process.end process(PID).thread.end process("PATH").thread.end process.thread.end process(PID).syscall process("PATH").syscall process.syscall process(PID).syscall.return process("PATH").syscall.return process.syscall.return - staprun disables kprobe-optimizations in recent kernels, as problems were found. (PR13193) * What's new in version 1.6, 2011-07-25 - Security fixes for CVE-2011-2503: read instead of mmap to load modules, CVE-2011-2502: Don't allow path-based auth for uprobes - The systemtap compile-server no longer uses the -k option when calling the translator (stap). As a result, the server will now take advantage of the module cache when compiling the same script more than once. You may observe an improvement in the performance of the server in this situation. - The systemtap compile-server and client now each check the version of the other, allowing both to adapt when communicating with a down-level counterpart. As a result, all version of the client can communicate with all versions of the server and vice-versa. Client will prefer newer servers when selecting a server automatically. - SystemTap has improved support for the ARM architecture. The kread() and kwrite() operations for ARM were corrected allowing many of the tapsets probes and function to work properly on the ARM architecture. - Staprun can now rename the module to a unique name with the '-R' option before inserting it. Systemtap itself will also call staprun with '-R' by default. This allows the same module to be inserted more than once, without conflicting duplicate names. - Systemtap error messages now provide feedback when staprun or any other process fails to launch. This also specifically covers when the user doesn't have the proper permissions to launch staprun. - Systemtap will now map - to _ in module names. Previously, stap -L 'module("i2c-core").function("*")' would be empty. It now returns a list had stap -L 'module("i2c_core").function("*") been specified. - Systemtap now fills in missing process names to probe points, to avoid having to name them twice twice: % stap -e 'probe process("a.out").function("*") {}' -c 'a.out ...' Now the probed process name is inferred from the -c CMD argument. % stap -e 'probe process.function("*") {}' -c 'a.out ...' - stap -L 'process("PATH").syscall' will now list context variables - Depends on elfutils 0.142+. - Deprecated task_backtrace:string (task:long). This function will go away after 1.6. Please run your scripts with stap --check-version. * What's new in version 1.5, 2011-05-23 - Security fixes for CVE-2011-1781, CVE-2011-1769: correct DW_OP_{mod,div} division-by-zero bug - The compile server and its related tools (stap-gen-ert, stap-authorize-cert, stap-sign-module) have been re-implemented in C++. Previously, these components were a mix of bash scripts and C code. These changes should be transparent to the end user with the exception of NSS certificate database password prompting (see below). The old implementation would prompt more than once for the same password in some situations. - eventcount.stp now allows for event counting in the format of 'stap eventcount.stp process.end syscall.* ...', and also reports corresponding event tid's. - Systemtap checks that the build-id of the module being probed matches the build-id saved in the systemtap module. Invoking systemtap with -DSTP_NO_BUILDID_CHECK will bypass this build-id runtime verification. See man ld(1) for info on --build-id. - stapio will now report if a child process has an abnormal exit along with the associated status or signal. - Compiler optimization may sometimes result in systemtap not being able to access a user-space probe argument. Compiling the application with -DSTAP_SDT_ARG_CONSTRAINT=nr will force the argument to be an immediate or register value which should enable systemtap to access the argument. - GNU Gettext has now been intergrated with systemtap. Our translation page can be found at http://www.transifex.net/projects/p/systemtap/ . "make update-po" will generate the necessary files to use translated messages. Please refer to the po/README file for more info and please consider contributing to this I18N effort! - The new addr() function returns the probe's instruction pointer. - process("...").library("...") probes are now supported. Wildcards are supported in the library-name part, to refer to any shared library that is required by process-name, which matches the glob pattern and the rest of the probe point. - The "--remote USER@HOST" functionality can now be specified multiple times to fan out on multiple targets. If the targets have distinct kernel and architecture configurations, stap will automatically build the script appropriately for each one. This option is also no longer considered experimental. - The NSS certificate database generated for use by the compile server is now generated with no password. Previously, a random password was generated and used to access the database. This change should be transparent to most users. However, if you are prompted for a password when using systemtap, then running $libexecdir/stap-gen-cert should correct the problem. - The timestamp tapset includes jiffies() and HZ() for lightweight approximate timekeeping. - A powerful new command line option --version has been added. - process.mark now supports $$parms for reading probe parameters. - A new command line option, --use-server-on-error[=yes|no] is available for stap. It instructs stap to retry compilation of a script using a compile server if it fails on the local host. The default setting is 'no'. - The following deprecated tools have been removed: stap-client stap-authorize-server-cert stap-authorize-signing-cert stap-find-or-start-server stap-find-servers Use the --use-server, --trust-server and --list-servers options of stap instead. * What's new in version 1.4, 2011-01-17 - Security fixes for CVE-2010-4170, CVE-2010-4171: staprun module loading/unloading - A new /* myproc-unprivileged */ marker is now available for embedded C code and and expressions. Like the /* unprivileged */ marker, it makes the code or expression available for use in unprivileged mode (see --unprivileged). However, it also automatically adds a call to assert_is_myproc() to the code or expression, thus, making it available to the unprivileged user only if the target of the current probe is within the user's own process. - The experimental "--remote USER@HOST" option will run pass 5 on a given ssh host, after building locally (or with --use-server) for that target. - Warning messages from the script may now be suppressed with the stap and/or staprun -w option. By default, duplicate warning messages are suppressed (up to a certain limit). With stap --vp 00002 and above, the duplicate elimination is defeated. - The print_ubacktrace and usym* functions attempt to print the full path of the user-space binaries' paths, instead of just the basename. The maximum saved path length is set by -DTASK_FINDER_VMA_ENTRY_PATHLEN, default 64. Warning messages are produced if unwinding fails due to a missing 'stap -d MODULE' option, providing preloaded unwind data. - The new tz_ctime() tapset function prints times in the local time zone. - More kernel tracepoints are accessible to the kernel.trace("...") mechanism, if kernel source trees or debuginfo are available. These formerly "hidden" tracepoints are those that are declared somewhere other than the usual include/linux/trace/ headers, such as xfs and kvm. - debuginfo-based process("...").function/.statement/.mark probes support wildcards in the process-name part, to refer to any executable files that match the glob pattern and the rest of the probe point. - The -t option now displays information per probe-point rather than a summary for each probe. It also now shows the derivation chain for each probe-point. - A rewrite of the sys/sdt.h header file provides zero-cost startup (few or no ELF relocations) for the debuginfo-less near-zero-cost runtime probes. Binaries compiled with earlier sdt.h versions remain supported. The stap -L (listing) option now lists parameters for sys/sdt.h markers. - The implementation of the integrated compile-server client has been extended. o --use-server now accepts an argument representing a particular server and may be specified more than once. o --list-servers now accepts an expanded range of arguments. o a new --trust-servers option has been added to stap to replace several old certificate-management scripts. o The following tools are now deprecated and will be removed in release 1.5: stap-client stap-authorize-server-cert stap-authorize-signing-cert stap-find-or-start-server stap-find-servers See man stap(1) for complete details. - The compile-server now returns the uprobes.ko to the client when it is required by the script being compiled. The integrated compile-server client now makes it available to be loaded by staprun. The old (deprecated) stap-client does not do this. - process probes with scripts as the target are recognized by stap and the interpreter would be selected for probing. - Starting in release 1.5, these old variables/functions will be deprecated and will only be available when the '--compatible=1.4' flag is used: - In the 'syscall.add_key' probe, the 'description_auddr' variable has been deprecated in favor of the new 'description_uaddr' variable. - In the 'syscall.fgetxattr', 'syscall.fsetxattr', 'syscall.getxattr', 'syscall.lgetxattr', and 'syscall.lremovexattr' probes, the 'name2' variable has been deprecated in favor of the new 'name_str' variable. - In the 'nd_syscall.accept' probe the 'flag_str' variable has been deprecated in favor of the new 'flags_str' variable. - In the 'nd_syscall.dup' probe the 'old_fd' variable has been deprecated in favor of the new 'oldfd' variable. - In the 'nd_syscall.fgetxattr', 'nd_syscall.fremovexattr', 'nd_syscall.fsetxattr', 'nd_syscall.getxattr', and 'nd_syscall.lremovexattr' probes, the 'name2' variable has been deprecated in favor of the new 'name_str' variable. - The tapset alias 'nd_syscall.compat_pselect7a' was misnamed. It should have been 'nd_syscall.compat_pselect7' (without the trailing 'a'). - The tapset function 'cpuid' is deprecated in favor of the better known 'cpu'. - In the i386 'syscall.sigaltstack' probe, the 'ussp' variable has been deprecated in favor of the new 'uss_uaddr' variable. - In the ia64 'syscall.sigaltstack' probe, the 'ss_uaddr' and 'oss_uaddr' variables have been deprecated in favor of the new 'uss_uaddr' and 'uoss_uaddr' variables. - The powerpc tapset alias 'syscall.compat_sysctl' was deprecated and renamed 'syscall.sysctl32'. - In the x86_64 'syscall.sigaltstack' probe, the 'regs_uaddr' variable has been deprecated in favor of the new 'regs' variable. * What's new in version 1.3, 2010-07-21 - The uprobes kernel module now has about half the overhead when probing NOPs, which is particularly relevant for sdt.h markers. - New stap option -G VAR=VALUE allows overriding global variables by passing the settings to staprun as module options. - The tapset alias 'syscall.compat_pselect7a' was misnamed. It should have been 'syscall.compat_pselect7' (without the trailing 'a'). Starting in release 1.4, the old name will be deprecated and will only be available when the '--compatible=1.3' flag is used. - A new procfs parameter .umask(UMASK) which provides modification of file permissions using the proper umask value. Default file permissions for a read probe are 0400, 0200 for a write probe, and 0600 for a file with a read and write probe. - It is now possible in some situations to use print_ubacktrace() to get a user space stack trace from a kernel probe point. e.g. for user backtraces when there is a pagefault: $ stap -d /bin/sort --ldd -e 'probe vm.pagefault { if (pid() == target()) { printf("pagefault @0x%x\n", address); print_ubacktrace(); } }' -c /bin/sort [...] pagefault @0x7fea0595fa70 0x000000384f07f958 : __GI_strcmp+0x12b8/0x1440 [libc-2.12.so] 0x000000384f02824e : __gconv_lookup_cache+0xee/0x5a0 [libc-2.12.so] 0x000000384f021092 : __gconv_find_transform+0x92/0x2cf [libc-2.12.so] 0x000000384f094896 : __wcsmbs_load_conv+0x106/0x2b0 [libc-2.12.so] 0x000000384f08bd90 : mbrtowc+0x1b0/0x1c0 [libc-2.12.so] 0x0000000000404199 : ismbblank+0x39/0x90 [sort] 0x0000000000404a4f : inittables_mb+0xef/0x290 [sort] 0x0000000000406934 : main+0x174/0x2510 [sort] 0x000000384f01ec5d : __libc_start_main+0xfd/0x1d0 [libc-2.12.so] 0x0000000000402509 : _start+0x29/0x2c [sort] [...] - New tapset functions to get a string representation of a stack trace: sprint_[u]backtrace() and sprint_[u]stack(). - New tapset function to get the module (shared library) name for a user space address umodname:string(long). The module name will now also be in the output of usymdata() and in backtrace addresses even when they were not given with -d at the command line. - Kernel backtraces are now much faster (replaced a linear search with a binary search). - A new integrated compile-server client is now available as part of stap. o 'stap --use-server ...' is equivalent to 'stap-client ...' o 'stap --list-servers' is equivalent to 'stap-find-servers' o 'stap --list-servers=online' is equivalent to 'stap-find-servers --all' o stap-client and its related tools will soon be deprecated. o the nss-devel and avahi-devel packages are required for building stap with the integrated client (checked during configuration). o nss and avahi are required to run the integrated client. - A new operator @entry is available for automatically saving an expression at entry time for use in a .return probe. probe foo.return { println(get_cycles() - @entry(get_cycles())) } - Probe $target variables and @cast() can now use a suffix to print complex data types as strings. Use a single '$' for a shallow view, or '$$' for a deeper view that includes nested types. For example, with fs_struct: $fs$ : "{.users=%i, .lock={...}, .umask=%i, .in_exec=%i, .root={...}, .pwd={...}}" $fs$$ : "{.users=%i, .lock={.raw_lock={.lock=%u}}, .umask=%i, .in_exec=%i, .root={.mnt=%p, .dentry=%p}, .pwd={.mnt=%p, .dentry=%p}}" - The user-space markers no longer default to an implicit MARKER_NAME_ENABLED() semaphore check for each marker. To check for enabled markers use a .d declaration file, then: if (MARKER_NAME_ENABLED()) MARKER_NAME() - Hyphenated marker names such as process(...).mark("foo-bar") are now accepted in scripts. They are mapped to the double-underscore form ("foo__bar"). - More robust user-space markers support is included. For some platforms (x86*, ppc*), this can let systemtap probe the markers without debuginfo. This implementation also supports preserving the "provider" name associated with a marker: probe process("foo").provider("bar").mark("baz") to match STAP_PROBE(bar, baz <...>) (Compile with -DSTAP_SDT_V1 to revert to the previous implementation. Systemtap supports pre-existing or new binaries using them.) - Embedded-C may be used within expressions as values, when in guru mode: num = %{ LINUX_VERSION_CODE %} // int64_t name = %{ /* string */ THIS_MODULE->name %} // const char* printf ("%s %x\n", name, num) The usual /* pure */, /* unprivileged */, and /* guru */ markers may be used as with embedded-C functions. - By default the systemtap-runtime RPM builds now include a shared library, staplog.so, that allows crash to extract systemtap data from a vmcore image. - Iterating with "foreach" can now explicitly save the value for the loop. foreach(v = [i,j] in array) printf("array[%d,%s] = %d\n", i, j, v /* array[i,j] */) - The new "--ldd" option automatically adds any additional shared libraries needed by probed or -d-listed userspace binaries to the -d list, to enable symbolic backtracing through them. Similarly, the new "--all-modules" option automatically adds any currently loaded kernel modules (listed in /proc/modules) to the -d list. - A new family of set_kernel_* functions make it easier for gurus to write new values at arbitrary memory addresses. - Probe wildcards can now use '**' to cross the '.' separator. $ stap -l 'sys**open' syscall.mq_open syscall.open - Backward compatibility flags (--compatible=VERSION, and matching script preprocessing predicate %( systemtap_v CMP "version" %) and a deprecation policy are being introduced, in case future tapset/language changes break valid scripts. * What's new in version 1.2, 2010-03-22 - Prototype support for "perf events", where the kernel supports the 2.6.33 in-kernel API. Probe points may refer to low-level perf_event_attr type/config numbers, or to a number of aliases defined in the new perf.stp tapset: probe perf.sw.cpu_clock, perf.type(0).config(4) { } - Type-casting can now use multiple headers to resolve codependencies. @cast(task, "task_struct", "kernel")->fs->umask - Tapset-related man pages have been renamed. 'man -k 3stap' should show the installed list, which due to prefixing should no longer collide over ordinary system functions. - User space marker arguments no longer use volatile if the version of gcc, which must be at least 4.5.0, supports richer DWARF debuginfo. Use cflags -DSTAP_SDT_VOLATILE=volatile or -DSTAP_SDT_VOLATILE= when building the sys/sdt.h application to override this one way or another. - A new construct for error handling is available. It is similar to c++ exception catching, using try and catch as new keywords. Within a handler or function, the following is valid and may be nested: try { /* arbitrary statements */ } catch (er) { /* e.g. println("caught error ", er) */ } - A new command line flag '-W' forces systemtap to abort translation of a script if any warnings are produced. It is similar to gcc's -Werror. (If '-w' is also supplied to suppress warnings, it wins.) - A new predicate @defined is available for testing whether a particular $variable/expression is resolvable at translate time: probe foo { if (@defined($bar)) log ("$bar is available here") } - Adjacent string literals are glued together, making this construct valid: probe process("/usr" @1 "/bin").function("*") { ... } - In order to limit potential impact from future security problems, the stap-server process does not permit its being launched as root. - On recent kernels, for some architectures/configurations, hardware breakpoint probes are supported. The probe point syntax is: probe kernel.data(ADDRESS).write probe kernel.data(ADDRESS).length(LEN).write probe kernel.data("SYMBOL_NAME").write * What's new in version 1.1, 2010-01-15 - New tracepoint based tapset for memory subsystem. - The loading of signed modules by staprun is no longer allowed for ordinary, unprivileged users. This means that only root, members of the group 'stapdev' and members of the group 'stapusr' can load systemtap modules using staprun, stap or stap-client. The minimum privilege required to run arbitrary --unprivileged scripts is now 'stapusr' membership. - The stap-server initscript is available. This initscript allows you to start systemtap compile servers as a system service and to manage these servers as a group or individually. The stap-server initscript is installed by the systemtap-server rpm. The build directory for the uprobes module (/usr/share/systemtap/runtime/uprobes) is made writable by the 'stap-server' group. All of the files generated when building the uprobes module, including the digital signature, are also writable by members of stap-server. See initscript/README.stap-server for details. - Some of the compile server client, server and certificate management tools have been moved from $bindir to $libexecdir/systemtap. You should use the new stap-server script or the stap-server initscript for server management where possible. The stap-server script provides the same functionality as the stap-server initscript except that the servers are run by the invoking user by default as opposed to servers started by the stap-server initscript which are run by the user stap-server by default. See stap-server(8) for more information. You may continue to use these tools by adding $libexecdir/systemtap to your path. You would need to do this, for example, if you are not root, you want to start a compile server and you are not running systemtap from a private installation. In this case you still need to use stap-start-server. - Any diagnostic output line that starts with "ERROR", as in error("foo"), will promote a "Pass 5: run failed", and the return code is 1. - Systemtap now warns about global variables being referenced from other script files. This aims to protect against unintended local-vs-global namespace collisions such as: % cat some_tapset.stp probe baz.one = bar { foo = $foo; bar = $bar } % cat end_user_script.stp global foo # intended to be private variable probe timer.s(1) { foo ++ } probe baz.* { println(foo, pp()) } % stap end_user_script.stp WARNING: cross-file global variable reference to foo from some_tapset.stp - Preprocessor conditional for kernel configuration testing: %( CONFIG_foo == "y" %? ... %) - ftrace(msg:string) tapset function to send strings to the system-wide ftrace ring-buffer (if any). - Better support for richer DWARF debuginfo output from GCC 4.5 (variable tracking assignments). Kernel modules are now always resolved against all their dependencies to find any info referring to missing symbols. DW_AT_const_value is now supported when no DW_AT_location is available. * What's new in verson 1.0, 2009-09-22 - process().mark() probes now use an enabling semaphore to reduce the computation overhead of dormant probes. - The function spec for dwarf probes now supports C++ scopes, so you can limit the probes to specific namespaces or classes. Multiple scopes can be specified, and they will be matched progressively outward. probe process("foo").function("std::vector<*>::*") { } probe process("foo").function("::global_function") { } - It is now possible to cross-compile systemtap scripts for foreign architectures, using the new '-a ARCH' and '-B OPT=VALUE' flags. For example, put arm-linux-gcc etc. into your $PATH, and point systemtap at the target kernel build tree with: stap -a arm -B CROSS_COMPILE=arm-linux- -r /build/tree [...] The -B option is passed to kbuild make. -r identifies the already configured/built kernel tree and -a its architecture (kbuild ARCH=...). Systemtap will infer -p4. - Cross compilation using the systemtap client and server - stap-start-server now accepts the -r, -R, -I, -B and -a options in order to start a cross compiling server. The server will correctly advertise itself with respect to the kernel release and architecture that it compiles for. - When specified on stap-client, the -r and -a options will be considered when searching for a suitable server. - When using the systemtap client and server udp port 5353 must be open in your firewall in order for the client to find servers using avahi-browse. Also the systemtap server will choose a random port in the range 1024-63999 for accepting ssl connections. - Support for unprivileged users: *********************************************************************** * WARNING!!!!!!!!!! * * This feature is EXPERIMENTAL at this time and should be used with * * care. This feature allows systemtap kernel modules to be loaded by * * unprivileged users. The user interface and restrictions will change * * as this feature evolves. * *********************************************************************** - Systemtap modules generated from scripts which use a restricted subset of the features available may be loaded by staprun for unprivileged users. Previously, staprun would load modules only for root or for members of the groups stapdev and stapusr. - Using the --unprivileged option on stap enables translation-time checking for use by unprivileged users (see restrictions below). - All modules deemed suitable for use by unprivileged users will be signed by the systemtap server when --unprivileged is specified on stap-client. See module signing in release 0.9.8 and stap-server in release 0.9 below. - Modules signed by trusted signers (servers) and verified by staprun will be loaded by staprun regardless of the user's privilege level. - The system administrator asserts the trustworthiness of a signer (server) by running stap-authorize-signing-cert as root, where the can be found in ~/.systemtap/ssl/server/stap.cert for servers started by ordinary users and in $sysconfdir/systemtap/ssl/server/stap.cert for servers started by root. - Restrictions are intentionally strict at this time and may be relaxed in the future: - probe points are restricted to: begin, begin(n), end, end(n), error, error(n), never, timer.{jiffies,s,sec,ms,msec,us,usec,ns,nsec}(n)*, timer.hz(n), process.* (for processes owned by the user). - use of embedded C code is not allowed. - use of tapset functions is restricted. - some tapset functions may not be used at all. A message will be generated at module compilation time. - some actions by allowed tapset functions may only be performed in the context of the user's own process. A runtime fault will occur in these situations, for example, direct memory access. - The is_myproc() tapset function has been provided so that tapset writers for unprivileged users can check that the context is of the users own process before attempting these actions. - accessing the kernel memory space is not allowed. - The following command line options may not be used by stap-client -g, -I, -D, -R, -B - The following environment variables are ignored by stap-client: SYSTEMTAP_RUNTIME, SYSTEMTAP_TAPSET, SYSTEMTAP_DEBUGINFO_PATH - nss and nss-tools are required to use this feature. - Support output file switching by SIGUSR2. Users can command running stapio to switch output file by sending SIGUSR2. - Memory consumption for scripts involving many uprobes has been dramatically reduced. - The preprocessor now supports || and && in the conditions. e.g. %( arch == "x86_64" || arch == "ia64" %: ... %) - The systemtap notion of "architecture" now matches the kernel's, rather than that of "uname -m". This means that 32-bit i386 family are all known as "i386" rather than "i386" or "i686"; "ppc64" as "powerpc"; "s390x" as "s390", and so on. This is consistent between the new "-a ARCH" flag and the script-level %( arch ... %) conditional. - It is now possible to define multiple probe aliases with the same name. A probe will expand to all matching aliases. probe foo = bar { } probe foo = baz { } probe foo { } # expands twice, once to bar and once to baz - A new experimental transport mechanism, using ftrace's ring_buffer, has been added. This may become the default transport mechanism in future versions of systemtap. To test this new transport mechanism, define 'STP_USE_RING_BUFFER'. - Support for recognizing DW_OP_{stack,implicit}_value DWARF expressions as emitted by GCC 4.5. * What's new in version 0.9.9, 2009-08-04 - Systemwide kernel .function.return (kretprobe) maxactive defaults may be overridden with the -DKRETACTIVE=nnn parameter. - Translation pass 2 is significantly faster by avoiding unnecessary searching through a kernel build/module directory tree. - When compiled against elfutils 0.142 systemtap now handles the new DW_OP_call_frame_CFA generated by by GCC. - uprobes and ustack() are more robust when used on applications that depend on prelinked/separate debuginfo shared libraries. - User space PROBE marks are not always found with or without separate debuginfo. The .probes section itself is now always put in the main elf file and marked as allocated. When building pic code the section is marked writable. The selinux memory check problems seen with programs using STAP_PROBES is fixed. - statement() probes can now override "address not at start of statement" errors in guru mode. They also provide alternative addresses to use in non-guru mode. - The stapgraph application can generate graphs of data and events emitted by systemtap scripts in real time. Run "stapgraph testsuite/systemtap.examples/general/grapher.stp" for an example of graphing the system load average and keyboard events. - Dwarf probes now show parameters and local variables in the verbose listing mode (-L). - Symbol aliases are now resolved to their canonical dwarf names. For example, probing "malloc" in libc resolves to "__libc_malloc". - The syntax for dereferencing $target variables and @cast() gained new capabilities: - Array indexes can now be arbitrary numeric expressions. - Array subscripts are now supported on pointer types. - An '&' operator before a @cast or $target returns the address of the final component, especially useful for nested structures. - For reading all probe variables, kernel.mark now supports $$vars and $$parms, and process.syscall now supports $$vars. - The SNMP tapset provides probes and functions for many network statistics. See stapprobes.snmp(3stap) for more details. - The dentry tapset provides functions to map kernel VFS directory entries to file or full path names: d_path(), d_name() and reverse_path_walk(). - SystemTap now has userspace markers in its own binaries, and the stap tapset provides the available probepoints and local variables. - Miscellaneous new tapset functions: - pgrp() returns the process group ID of the current process - str_replace() performs string replacement * What's new in version 0.9.8, 2009-06-11 - Miscellaneous new tapset functions: - sid() returns the session ID of the current process - stringat() indexes a single character from a string. - Using %M in print formats for hex dumps can now print entire buffers, instead of just small numbers. - Dwarfless syscalls: The nd_syscalls tapset is now available to probe system calls without requiring kernel debugging information. All of the same probepoints in the normal syscalls tapset are available with an "nd_" prefix, e.g. syscall.open becomes nd_syscall.open. Most syscall arguments are also available by name in nd_syscalls. - Module signing: If the appropriate nss libraries are available on your system, stap-server will sign each compiled module using a self-generated certificate. This is the first step toward extending authority to load certain modules to unprivileged users. For now, if the system administrator adds a certificate to a database of trusted signers (stap-authorize-signing-cert), modules signed using that certificate will be verified by staprun against tampering. Otherwise, you should notice no difference in the operation of stap or staprun. * What's new in version 0.9.7, 2009-04-23 - @cast can now determine its type information using an explicit header specification. For example: @cast(tv, "timeval", "")->tv_sec @cast(task, "task_struct", "kernel")->tgid - The overlapping process.* tapsets are now separated. Those probe points documented in stapprobes(3stap) remain the same. Those that were formerly in stapprobes.process(3stap) have been renamed to kprocess, to reflect their kernel perspective on processes. - The --skip-badvars option now also suppresses run-time error messages that would otherwise result from erroneous memory accesses. Such accesses can originate from $context expressions fueled by erroneous debug data, or by kernel_{long,string,...}() tapset calls. - New probes kprobe.function(FUNCTION) and kprobe.function(FUNCTION).return for dwarfless probing. These postpone function address resolution to run-time and use the kprobe symbol-resolution mechanism. Probing of absolute statements can be done using the kprobe.statement(ADDRESS).absolute construct. - EXPERIMENTAL support for user process unwinding. A new collection of tapset functions have been added to handle user space backtraces from probe points that support them (currently process and timer probes - for timer probes test whether or not in user space first with the already existing user_mode() function). The new tapset functions are: uaddr - User space address of current running task. usymname - Return the symbol of an address in the current task. usymdata - Return the symbol and module offset of an address. print_ustack - Print out stack for the current task from string. print_ubacktrace - Print stack back trace for current task. ubacktrace - Hex backtrace of current task stack. Please read http://sourceware.org/ml/systemtap/2009-q2/msg00364.html on the current restrictions and possible changes in the future and give feedback if you want to influence future developments. * What's new in version 0.9.5, 2009-03-27 - New probes process().insn and process().insn.block that allows inspection of the process after each instruction or block of instructions executed. So to count the total number of instructions a process executes during a run do something like: $ stap -e 'global steps; probe process("/bin/ls").insn {steps++} probe end {printf("Total instructions: %d\n", steps);}' \ -c /bin/ls This feature can slow down execution of a process somewhat. - Systemtap probes and function man pages extracted from the tapsets are now available under 3stap. To show the page for probe vm.pagefault or the stap function pexecname do: $ man 3stap vm.pagefault $ man 3stap pexecname - Kernel tracepoints are now supported for probing predefined kernel events without any debuginfo. Tracepoints incur less overhead than kprobes, and context parameters are available with full type information. Any kernel 2.6.28 and later should have defined tracepoints. Try the following to see what's available: $ stap -L 'kernel.trace("*")' - Typecasting with @cast now supports modules search paths, which is useful in case there are multiple places where the type definition may be found. For example: @cast(sdev, "scsi_device", "kernel:scsi_mod")->sdev_state - On-file flight recorder is supported. It allows stap to record huge trace log on the disk and to run in background. Passing -F option with -o option runs stap in background mode. In this mode, staprun is detached from console, and stap itself shows staprun's pid and exits. Specifying the max size and the max number of log files are also available by passing -S option. This option has one or two arguments seperated by a comma. The first argument is the max size of a log file in MB. If the size of a log file exceeds it, stap switches to the next log file automatically. The second is how many files are kept on the disk. If the number of log files exceeds it, the oldest log file is removed automatically. The second argument can be omitted. For example, this will record output on log files each of them is smaller than 1024MB and keep last 3 logs, in background. % stap -F -o /tmp/staplog -S 1024,3 script.stp - In guru mode (-g), the kernel probing blacklist is disabled, leaving only a subset - the kernel's own internal kprobe blacklist - to attempt to filter out areas unsafe to probe. The differences may be enough to probe more interrupt handlers. - Variables unavailable in current context may be skipped by setting a session level flag with command line option --skip-badvars now available. This replaces any dwarf $variable expressions that could not be resolved with literal numeric zeros, along with a warning message. - Both kernel markers and kernel tracepoint support argument listing through stap -L 'kernel.mark("*")' or stap -L 'kernel.trace("*")' - Users can use -DINTERRUPTIBLE=0 to prevent interrupt reentrancy in their script, at the cost of a bit more overhead to toggle the interrupt mask. - Added reentrancy debugging. If stap is run with the arguments "-t -DDEBUG_REENTRANCY", additional warnings will be printed for every reentrancy event, including the probe points of the resident and interloper probes. - Default to --disable-pie for configure. Use --enable-pie to turn it back on. - Improved sdt.h compatibility and test suite for static dtrace compatible user space markers. - Some architectures now use syscall wrappers (HAVE_SYSCALL_WRAPPERS). The syscall tapset has been enhanced to take care of the syscall wrappers in this release. - Security fix for CVE-2009-0784: stapusr module-path checking race. * What's new in version 0.9, 2009-02-19 - Typecasting is now supported using the @cast operator. A script can define a pointer type for a "long" value, and then access type members using the same syntax as with $target variables. For example, this will retrieve the parent pid from a kernel task_struct: @cast(pointer, "task_struct", "kernel")->parent->pid - process().mark() probes are now possible to trace static user space markers put in programs with the STAP_PROBE macro using the new sys/sdt.h include file. This also provides dtrace compatible markers through DTRACE_PROBE and an associated python 'dtrace' script that can be used in builds based on dtrace that need dtrace -h or -G functionality. - For those that really want to run stap from the build tree there is now the 'run-stap' script in the top-level build directory that sets up the SYSTEMTAP_TAPSET, SYSTEMTAP_RUNTIME, SYSTEMTAP_STAPRUN, and SYSTEMTAP_STAPIO environment variables (installing systemtap, in a local prefix, is still recommended for common use). - Systemtap now comes with a new Beginners Guide that walks the user through their first steps setting up stap, understanding how it all works, introduces some useful scripts and describes some common pitfalls. It isn't created by default since it needs a Publican setup, but full build instructions can be found in the wiki: http://sourceware.org/systemtap/wiki/PublicanQuikHowto An online version can be found at: http://sourceware.org/systemtap/SystemTap_Beginners_Guide.pdf - Standard tapsets included with Systemtap were modified to include extractable documentation information based on the kernel-doc infrastructure. When configured --enabled-docs a HTML and PDF version of the Tapset Reference Manual is produced explaining probes defined in each tapset. - The systemtap client and compile server are now available. These allow you to compile a systemtap module on a host other than the one which it will be run, providing the client and server are compatible. Other than using a server for passes 1 through 4, the client behaves like the 'stap' front end itself. This means, among other things, that the client will automatically load the resulting module on the local host unless -p[1234] was specified. See stap-server(8) for more details. The client/server now use SSL for network connection security and for signing. The systemtap client and server are prototypes only. Interfaces, options and usage may change at any time. - function("func").label("label") probes are now supported to allow matching the label of a function. - Systemtap initscript is available. This initscript allows you to run systemtap scripts as system services (in flight recorder mode) and control those scripts individually. See README.systemtap for details. - The stap "-r DIR" option may be used to identify a hand-made kernel build directory. The tool determines the appropriate release string automatically from the directory. - Serious problems associated with user-space probing in shared libraries were corrected, making it now possible to experiment with probe shared libraries. Assuming dwarf debugging information is installed, use this twist on the normal syntax: probe process("/lib64/libc-2.8.so").function("....") { ... } This would probe all threads that call into that library. Running "stap -c CMD" or "stap -x PID" naturally restricts this to the target command+descendants only. $$vars etc. may be used. - For scripts that sometimes terminate with excessive "skipped" probes, rerunning the script with "-t" (timing) will print more details about the skippage reasons. - Symbol tables and unwind (backtracing) data support were formerly compiled in for all probed modules as identified by the script (kernel; module("name"); process("file")) plus those listed by the stap "-d BINARY" option. Now, this data is included only if the systemtap script uses tapset functions like probefunc() or backtrace() that require such information. This shrinks the probe modules considerably for the rest. - Per-pass verbosity control is available with the new "--vp {N}+" option. "stap --vp 040" adds 4 units of -v verbosity only to pass 2. This is useful for diagnosing errors from one pass without excessive verbosity from others. - Most probe handlers now run with interrupts enabled, for improved system responsiveness and less probing overhead. This may result in more skipped probes, for example if a reentrant probe handler is attempted from within an interrupt handler. It may also make the systemtap overload detection facility more likely to be triggered, as interrupt handlers' run time would be included in the self-assessed overhead of running probe handlers. * What's new in version 0.8, 2008-11-13 - Cache limiting is now available. If the compiled module cache size is over a limit specified in the $SYSTEMTAP_DIR/cache/cache_mb_limit file, some old cache entries will be unlinked. See man stap(1) for more. - Error and warning messages are now followed by source context displaying the erroneous line/s and a handy '^' in the following line pointing to the appropriate column. - A bug reporting tool "stap-report" is now available which will quickly retrieve much of the information requested here: http://sourceware.org/systemtap/wiki/HowToReportBugs - The translator can resolve members of anonymous structs / unions: given struct { int foo; struct { int bar; }; } *p; this now works: $p->bar - The stap "-F" flag activates "flight recorder" mode, which consists of translating the given script as usual, but implicitly launching it into the background with staprun's existing "-L" (launch) option. A user can later reattach to the module with "staprun -A MODULENAME". - Additional context variables are available on user-space syscall probes. - $argN ($arg1, $arg2, ... $arg6) in process(PATH_OR_PID).syscall gives you the argument of the system call. - $return in process(PATH_OR_PID).syscall.return gives you the return value of the system call. - Target process mode (stap -c CMD or -x PID) now implicitly restricts all "process.*" probes to the given child process. (It does not affect kernel.* or other probe types.) The CMD string is normally run directly, rather than via a /bin/sh -c subshell, since then utrace/uprobe probes receive a fairly "clean" event stream. If metacharacters like redirection operators were present in CMD, then "sh -c CMD" is still used, and utrace/uprobe probes will receive events from the shell. % stap -e 'probe process.syscall, process.end { printf("%s %d %s\n", execname(), pid(), pp())}'\ -c ls ls 2323 process.syscall ls 2323 process.syscall ls 2323 process.end - Probe listing mode is improved: "-L" lists available script-level variables % stap -L 'syscall.*open*' syscall.mq_open name:string name_uaddr:long filename:string mode:long u_attr_uaddr:long oflag:long argstr:string syscall.open name:string filename:string flags:long mode:long argstr:string syscall.openat name:string filename:string flags:long mode:long argstr:string - All user-space-related probes support $PATH-resolved executable names, so probe process("ls").syscall {} probe process("./a.out").syscall {} work now, instead of just probe process("/bin/ls").syscall {} probe process("/my/directory/a.out").syscall {} - Prototype symbolic user-space probing support: # stap -e 'probe process("ls").function("*").call { log (probefunc()." ".$$parms) }' \ -c 'ls -l' This requires: - debugging information for the named program - a version of utrace in the kernel that is compatible with the "uprobes" kernel module prototype. This includes RHEL5 and older Fedora, but not yet current lkml-track utrace; a "pass 4a"-time build failure means your system cannot use this yet. - Global variables which are written to but never read are now automatically displayed when the session does a shutdown. For example: global running_tasks probe timer.profile {running_tasks[pid(),tid()] = execname()} probe timer.ms(8000) {exit()} - A formatted string representation of the variables, parameters, or local variables at a probe point is now supported via the special $$vars, $$parms, and $$locals context variables, which expand to a string containing a list "var1=0xdead var2=0xbeef var3=?". (Here, var3 exists but is for some reason unavailable.) In return probes only, $$return expands to an empty string for a void function, or "return=0xf00". * What's new in version 0.7, 2008-07-15 - .statement("func@file:*") and .statement("func@file:M-N") probes are now supported to allow matching a range of lines in a function. This allows tracing the execution of a function. - Scripts relying on probe point wildcards like "syscall.*" that expand to distinct kprobes are processed significantly faster than before. - The vector of script command line arguments is available in a tapset-provided global array argv[]. It is indexed 1 ... argc, another global. This can substitute for of preprocessor directives @NNN that fail at parse time if there are not enough arguments. printf("argv: %s %s %s", argv[1], argv[2], argv[3]) - .statement("func@file+line") probes are now supported to allow a match relative to the entry of the function incremented by line number. This allows using the same systemtap script if the rest of the file.c source only changes slightly. - A probe listing mode is available. % stap -l vm.* vm.brk vm.mmap vm.munmap vm.oom_kill vm.pagefault vm.write_shared - More user-space probe types are added: probe process(PID).begin { } probe process("PATH").begin { } probe process(PID).thread.begin { } probe process("PATH").thread.begin { } probe process(PID).end { } probe process("PATH").end { } probe process(PID).thread.end { } probe process("PATH").thread.end { } probe process(PID).syscall { } probe process("PATH").syscall { } probe process(PID).syscall.return { } probe process("PATH").syscall.return { } - Globals now accept ; terminators global odds, evens; global little[10], big[5]; * What's new in version 0.6, 2007-12-15 - A copy of the systemtap tutorial and language reference guide are now included. - There is a new format specifier, %m, for the printf family of functions. It functions like %s, except that it does not stop when a nul ('\0') byte is encountered. The number of bytes output is determined by the precision specifier. The default precision is 1. For example: printf ("%m", "My String") // prints one character: M printf ("%.5", myString) // prints 5 bytes beginning at the start // of myString - The %b format specifier for the printf family of functions has been enhanced as follows: 1) When the width and precision are both unspecified, the default is %8.8b. 2) When only one of the width or precision is specified, the other defaults to the same value. For example, %4b == %.4b == %4.4b 3) Nul ('\0') bytes are used for field width padding. For example, printf ("%b", 0x1111deadbeef2222) // prints all eight bytes printf ("%4.2b", 0xdeadbeef) // prints \0\0\xbe\xef - Dynamic width and precision are now supported for all printf family format specifiers. For example: four = 4 two = 2 printf ("%*.*b", four, two, 0xdeadbbeef) // prints \0\0\xbe\xef printf ("%*d", four, two) // prints 2 - Preprocessor conditional expressions can now include wildcard style matches on kernel versions. %( kernel_vr != "*xen" %? foo %: bar %) - Prototype support for user-space probing is showing some progress. No symbolic notations are supported yet (so no probing by function names, file names, process names, and no access to $context variables), but at least it's something: probe process(PID).statement(ADDRESS).absolute { } This will set a uprobe on the given process-id and given virtual address. The proble handler runs in kernel-space as usual, and can generally use existing tapset functions. - Crash utility can retrieve systemtap's relay buffer from a kernel dump image by using staplog which is a crash extension module. To use this feature, type commands as below from crash(8)'s command line: crash> extend staplog.so crash> help systemtaplog Then, you can see more precise help message. - You can share a relay buffer amoung several scripts and merge outputs from several scripts by using "-DRELAY_HOST" and "-DRELAY_GUEST" options. For example: # run a host script % stap -ve 'probe begin{}' -o merged.out -DRELAY_HOST & # wait until starting the host. % stap -ve 'probe begin{print("hello ");exit()}' -DRELAY_GUEST % stap -ve 'probe begin{print("world\n");exit()}' -DRELAY_GUEST Then, you'll see "hello world" in merged.out. - You can add a conditional statement for each probe point or aliase, which is evaluated when the probe point is hit. If the condition is false, the whole probe body(including aliases) is skipped. For example: global switch = 0; probe syscall.* if (switch) { ... } probe procfs.write {switch = strtol($value,10)} /* enable/disable ctrl */ - Systemtap will warn you if your script contains unused variables or functions. This is helpful in case of misspelled variables. If it doth protest too much, turn it off with "stap -w ...". - You can add error-handling probes to a script, which are run if a script was stopped due to errors. In such a case, "end" probes are not run, but "error" ones are. probe error { println ("oops, errors encountered; here's a report anyway") foreach (coin in mint) { println (coin) } } - In a related twist, one may list probe points in order of preference, and mark any of them as "sufficient" beyond just "optional". Probe point sequence expansion stops if a sufficient-marked probe point has a hit. This is useful for probes on functions that may be in a module (CONFIG_FOO=m) or may have been compiled into the kernel (CONFIG_FOO=y), but we don't know which. Instead of probe module("sd").function("sd_init_command") ? , kernel.function("sd_init_command") ? { ... } which might match neither, now one can write this: probe module("sd").function("sd_init_command") ! , /* <-- note excl. mark */ kernel.function("sd_init_command") { ... } - New security model. To install a systemtap kernel module, a user must be one of the following: the root user; a member of the 'stapdev' group; or a member of the 'stapusr' group. Members of the stapusr group can only use modules located in the /lib/modules/VERSION/systemtap directory (where VERSION is the output of "uname -r"). - .statement("...@file:line") probes now apply heuristics to allow an approximate match for the line number. This works similarly to gdb, where a breakpoint placed on an empty source line is automatically moved to the next statement. A silly bug that made many $target variables inaccessible to .statement() probes was also fixed. - LKET has been retired. Please let us know on if you have been a user of the tapset/tools, so we can help you find another way. - New families of printing functions println() and printd() have been added. println() is like print() but adds a newline at the end; printd() is like a sequence of print()s, with a specified field delimiter. * What's new since version 0.5.14?, 2007-07-03 - The way in which command line arguments for scripts are substituted has changed. Previously, $1 etc. would interpret the corresponding command line argument as an numeric literal, and @1 as a string literal. Now, the command line arguments are pasted uninterpreted wherever $1 etc. appears at the beginning of a token. @1 is similar, but is quoted as a string. This change does not modify old scripts, but has the effect of permitting substitution of arbitrary token sequences. # This worked before, and still does: % stap -e 'probe timer.s($1) {}' 5 # Now this also works: % stap -e 'probe syscall.$1 {log(@1)}' open # This won't crash, just signal a recursion error: % stap -e '$1' '$1' # As before, $1... is recognized only at the beginning of a token % stap -e 'probe begin {foo$1=5}' * What's new since version 0.5.13?, 2007-03-26 - The way in which systemtap resolves function/inline probes has changed: .function(...) - now refers to all functions, inlined or not .inline(...) - is deprecated, use instead: .function(...).inline - filters function() to only inlined instances .function(...).call - filters function() to only non-inlined instances .function(...).return - as before, but now pairs best with .function().call .statement() is unchanged. * What's new since version 0.5.12?, 2007-01-01 - When running in -p4 (compile-only) mode, the compiled .ko file name is printed on standard output. - An array element with a null value such as zero or an empty string is now preserved, and will show up in a "foreach" loop or "in" test. To delete such an element, the scripts needs to use an explicit "delete array[idx]" statement rather than something like "array[idx]=0". - The new "-P" option controls whether prologue searching heuristics will be activated for function probes. This was needed to get correct debugging information (dwarf location list) data for $target variables. Modern compilers (gcc 4.1+) tend not to need this heuristic, so it is no longer default. A new configure flag (--enable-prologues) restores it as a default setting, and is appropriate for older compilers (gcc 3.*). - Each systemtap module prints a one-line message to the kernel informational log when it starts. This line identifies the translator version, base address of the probe module, a broken-down memory consumption estimate, and the total number of probes. This is meant as a debugging / auditing aid. - Begin/end probes are run with interrupts enabled (but with preemption disabled). This will allow begin/end probes to be longer, to support generating longer reports. - The numeric forms of kernel.statement() and kernel.function() probe points are now interpreted as relocatable values - treated as relative to the _stext symbol in that kernel binary. Since some modern kernel images are relocated to a different virtual address at startup, such addresses may shift up or down when actually inserted into a running kernel. kernel.statement(0xdeadbeef): validated, interpreted relative to _stext, may map to 0xceadbeef at run time. In order to specify unrelocated addresses, use the new ".absolute" probe point suffix for such numeric addresses. These are only allowed in guru mode, and provide access to no $target variables. They don't use debugging information at all, actually. kernel.statement(0xfeedface).absolute: raw, unvalidated, guru mode only * What's new since version 0.5.10?, 2006-10-19 - Offline processing of debugging information, enabling general cross-compilation of probe scripts to remote hosts, without requiring identical module/memory layout. This slows down compilation/translation somewhat. - Kernel symbol table data is loaded by staprun at startup time rather than compiled into the module. - Support the "limit" keyword for foreach iterations: foreach ([x,y] in ary limit 5) { ... } This implicitly exits after the fifth iteration. It also enables more efficient key/value sorting. - Support the "maxactive" keyword for return probes: probe kernel.function("sdfsdf").maxactive(848) { ... } This allows up to 848 concurrently outstanding entries to the sdfsdf function before one returns. The default maxactive number is smaller, and can result in missed return probes. - Support accessing of saved function arguments from within return probes. These values are saved by a synthesized function-entry probe. - Add substantial version/architecture checking in compiled probes to assert correct installation of debugging information and correct execution on a compatible kernel. - Add probe-time checking for sufficient free stack space when probe handlers are invoked, as a safety improvement. - Add an optional numeric parameter for begin/end probe specifications, to order their execution. probe begin(10) { } /* comes after */ probe begin(-10) {} - Add an optional array size declaration, which is handy for very small or very large ones. global little[5], big[20000] - Include some example scripts along with the documentation. - Change the start-time allocation of probe memory to avoid causing OOM situations, and to abort cleanly if free kernel memory is short. - Automatically use the kernel DWARF unwinder, if present, for stack tracebacks. - Many minor bug fixes, performance, tapset, and error message improvements. systemtap-2.3/README000066400000000000000000000122661217430427200143000ustar00rootroot00000000000000systemtap: a linux trace/probe tool Visit the project web site at , for documentation and mailing lists for developers and users. This is free software. See the COPYING file for redistribution/modification terms. See the INSTALL file for generic build instructions. Prerequisites: - linux kernel - kernel module build environment (kernel-devel rpm) and/or dyninst - optionally, debugging information for kernel/user-space being instrumented - C compiler (same as what kernel was compiled with) - elfutils with libdwfl for debugging information parsing - root privileges Installation steps: - Install any debuginfo packages you need, for kernel and/or userspace. On modern Fedora, # debuginfo-install kernel [...] (Beware of confusion between kernel vs. kernel-debug vs kernel-PAE etc. variants. Each likely has a corresponding development and debuginfo package.) - Install the systemtap package. On modern Fedora, # yum install systemtap systemtap-runtime Build steps: - Consider installing the kernel-debuginfo, kernel-devel, gcc and dependent packages (or see below if you are building your own kernels from source). If using only the pure-userspace dyninst backend, install gcc and dyninst-devel. - If available, install your distribution's copy of elfutils and its development headers/libraries. Or if desired, download an elfutils source release to build in "bundled mode" (below), and untar it into some new directory. Or if desired, build elfutils separately one time, and install it to /usr/local. See http://fedorahosted.org/elfutils/ Version 0.151 is recommended for i386 hosts probing prelinked programs. (PR12141) - On modern Fedora, install general optional build-requisites: # yum-builddep systemtap On modern Debian/Ubuntu, similarly: # apt-get build-dep systemtap - Download systemtap sources: http://sourceware.org/systemtap/ftp/releases/ http://sourceware.org/systemtap/ftp/snapshots/ (or) git clone git://sourceware.org/git/systemtap.git (or) http://sourceware.org/git/systemtap.git - Build systemtap normally: % .../configure [other autoconf options] Or, with build it with a bundled internal copy of elfutils: % .../configure --with-elfutils=ELFUTILS-SOURCE-DIR [other autoconf options] (Note that elfutils > 0.139 requires gcc > 4.0 or else the appropriate elfutils-portability.patch.) Consider configuring with "--enable-dejazilla" to automatically contribute to our public test result database. Consider configuring with "--prefix=DIRECTORY" to specify an installation directory other than /usr/local. It can be an ordinary personal directory. % make all # make install To uninstall systemtap: # make uninstall - Run systemtap: To run systemtap after installation, add $prefix/bin to your $PATH, or refer to $prefix/bin/stap directly. If you keep your build tree around, you can also use the "stap" binary there. Some samples should be available under $prefix/share/doc/systemtap/examples. For the normal linux-kernel-module based backend, run "stap" as root. If desired, create "stapdev" and "stapusr" entries in /etc/groups. Any users in "stapdev"+"stapusr" will be able to run systemtap as if with root privileges. Users in "stapusr" only may launch (with "staprun") pre-compiled probe modules (created by "stap -p4 ...") that a system administrator copied under /lib/modules/`uname -r`/systemtap. "stapusr" may also be permitted to create arbitrary unprivileged systemtap scripts of their own. See README.unprivileged for additional setup instructions. To run a simple test. # stap -v -e 'probe vfs.read {printf("read performed\n"); exit()}' To run the full test suite from the build tree. # make installcheck For the prototype dyninst pure-userspace backend, run "stap" as any user. % stap --runtime=dyninst -e 'probe process.function("*") { println(pn(), ":", $$parms) }' -c 'ls' Tips: - By default, systemtap looks for the debug info in these locations: /boot/vmlinux-`uname -r` /usr/lib/debug/lib/modules/`uname -r`/vmlinux /lib/modules/`uname -r`/vmlinux /lib/modules/`uname -r`/build/vmlinux Building a kernel.org kernel: - Consider applying the utrace kernel patches, if you wish to probe user-space applications. http://sourceware.org/systemtap/wiki/utrace Or if your kernel is near 3.5, apply the uprobes and related patches (see NEWS). Or if your kernel is >= 3.5, enjoy the built-in uprobes. - Build the kernel using your normal procedures. Enable CONFIG_DEBUG_INFO, CONFIG_KPROBES, CONFIG_RELAY, CONFIG_DEBUG_FS, CONFIG_MODULES, CONFIG_MODULE_UNLOAD, CONFIG_UTRACE if able - % make modules_install install headers_install - Boot into the kernel. - If you wish to leave the kernel build tree in place, simply run % stap -r /path/to/kernel/build/tree [...] You're done. - Or else, if you wish to install the kernel build/debuginfo data into a place where systemtap will find it without the "-r" option: % ln -s /path/to/kernel/build/tree /lib/modules/RELEASE/build - Instead of using the "-r" option, you can also use the environment variable SYSTEMTAP_RELEASE to direct systemtap to the kernel data. systemtap-2.3/README.security000066400000000000000000000074731217430427200161520ustar00rootroot00000000000000Systemtap builds kernel modules. To insert a kernel module on a system, root access is needed. SECURITY MODEL ============== Originally sudo(8) was used to grant root access. After compiling a new kernel module, stap ran "sudo staprun module_path". This worked, but required all systemtap users to have root access. Many sysadmins on enterprise systems do not have root access. So, a new security model was developed. To run the staprun program (which installs systemtap kernel modules), a user must be one of the following: * the root user; * a member of both 'stapdev' and 'stapusr' groups; or * a member of the 'stapusr' group. Members of the stapusr group can only use modules located in the /lib/modules/VERSION/systemtap directory (where VERSION is the output of "uname -r"). This directory must be owned by root and not be world writable. So, there are two classes of users: systemtap developers (the root user and members of the stapdev/stapusr groups) and systemtap users (members of only the stapusr group). Systemtap developers can compile and run any systemtap script. Systemtap users can only run "approved" pre-compiled modules located in /lib/modules/VERSION/systemtap. USAGE ===== Here's the usage case. A systemtap developer hears of a problem on a production machine (which doesn't have a compiler or kernel debuginfo installed). So, he write a systemtap script to probe certain areas of the kernel that will give him a better idea of what is going on. He develops the script on a development machine (that has the compiler and kernel debuginfo installed). Once he is satisfied with the systemtap script, he creates the systemtap kernel module and copies it to /lib/modules/VERSION/systemtap on the target production machine. He then asks a systemtap user on that machine to run the module and report the results. The above usage case would look something like this: On the development machine: # vi pmod.stp (The systemtap developer writes the systemtap script.) # stap -m pmod pmod.stp (The systemtap developer compiles and runs the script. If necessary, the script may need to be edited to fix any errors.) # scp pmod.ko prod_machine:/lib/modules/`uname -r`/systemtap (The systemtap developer copies the compiled kernel module to the proper directory on the production machine. Of course other methods - ftp, nfs, etc. could be used to transfer the module.) On the production machine: $ staprun pmod (The systemtap user runs the newly developed systemtap kernel module.) There are (at least) 2 different usage scenarios for the /lib/modules/VERSION/systemtap directory. 1) Most restrictive usage. If only root should be able to add "approved" systemtap modules to /lib/modules/VERSION/systemtap, the permissions should be 755, like this: drwxr-xr-x 2 root root 4096 2007-08-07 13:54 systemtap/ 2) More permissive usage. If all systemtap developers should be able to add "approved" systemtap modules to /lib/modules/VERSION/systemtap, its permissions should be 775 (and be owned by root, group stapdev), like this: drwxrwxr-x 2 root stapdev 4096 2007-08-07 13:54 systemtap/ INTERNALS ========= To accomplish the new security model, staprun has been split into two programs: staprun and stapio. Here is a description of a typical systemtap session. The staprun program is a setuid program that does some system setup, loads the kernel module, then runs stapio (and waits for it to finish). The stapio program runs as the invoking user and is responsible for all communication with the kernel module. After the script runs to completion, stapio fork/execs staprun -d to unload the kernel module. staprun is a setuid program. It holds on to the root privileges only for the least amount of time (as required to verify/load compiled kernel module files). It invokes only stapio, and only as the original (unprivileged) user. systemtap-2.3/README.stapregex000066400000000000000000000011361217430427200162730ustar00rootroot00000000000000The following files in this directory incorporate code from the re2c project: - stapregex.h - stapregex.cxx - stapregex-tree.h - stapregex-tree.cxx - stapregex-parse.h - stapregex-parse.cxx - stapregex-dfa.h - stapregex-dfa.cxx The codebase these files are based on was originally released into the public domain. Many thanks to the developers of re2c for their work. As a courtesy to the original developers of re2c, please include appropriate acknowledgment in future code derived from this file. Information on the original re2c distribution can be found at: http://sourceforge.net/projects/re2c/ systemtap-2.3/README.unprivileged000066400000000000000000000303111217430427200167630ustar00rootroot00000000000000Unprivileged Mode for Systemtap Users ===================================== Introduction ------------ In order to use the full capabilities of systemtap, one must run it as root or as a member of the groups stapusr and stapdev. For other (unprivileged) users, systemtap does provide support for use of a subset of systemtap's capabilities to perform limited probing. For example, tracing your own applications or polling using timers. The intent is to give unprivileged users capabilities similar to those provided by a debugger. Below are instructions for running systemtap scripts in unprivileged mode. Systemtap Compile Server ------------------------ In order to load the kernel module produced by compiling a systemtap script for an unprivileged user, we must know that the script was compiled correctly and that the script does not do anything dangerous. A systemap compile server provides the trusted compilation environment needed to certify both conditions. NOTE: In order to use a compile server, the nss and nspr packages must be installed on the client host and systemtap must have been built with NSS enabled. Run 'stap -V | grep NSS' to find out if NSS is enabled. NOTE: In order to detect servers on the local network, the avahi package must be installed on the client host and systemtap must have been built with avahi enabled. Run 'stap -V | grep AVAHI' to find out if avahi is enabled. To find out if a suitable server is available on the local network, this command should produce output similar to the following: # stap --list-servers --privileged=stapusr Systemtap Compile Server Status for 'online,trusted,compatible,signer' host=somehost ip=10.15.16.156 port=10913 sysinfo="2.6.34.7-66.fc13.x86_64 x86_64" certinfo="00:93:49:be:2a" NOTE: In order for servers to be detected, the port for mDNS (5353/udp) must be open on the server and client hosts. If no servers are listed, then you must ask your system administrator to make the appropriate compile server available on the local host or on the local network. The server must be trusted as an ssl peer and as a systemtap module signer on the local host. See "Setup and Administration of Unprivileged Users for System Administrators" below for more details. Trust of Unprivileged Users --------------------------- Even with the appropriate compile server available, each unprivileged user must be explicitly trusted. This is done by adding each unprivileged user to the group stapusr and possibly the group stapsys on each host on which they will run systemtap scripts. To see if you are a member of the group stapusr on the local host, this command should produce output similar to the following: # getent group stapusr stapusr:x:483:someuser,anotheruser If your userid is listed, then you are already a member of the group stapusr. If it is not, then you must ask your system administrator to add you to this group. Once added, Try the command newgrp stapusr to activate your membership. If all else fails, logging out and back in again should work. See the manual page for newgrp(1) for details. Using Systemtap in Unprivileged Mode ------------------------------------ Unprivileged users can compile any systemtap script either directly or using a compile server, but systemtap will not load the resulting kernel module for an unprivileged user unless it has been compiled and certified by a trusted compile server. To do this, as an unprivileged user, this command should produce output similar to the following: # stap -e 'probe begin { printf ("Hello\n"); exit (); }' Hello For unprivileged users, stap will automatically add the options --privilege and --use-server (you could also specify them yourself). --use-server tells systemtap to compile the script using a server. --privilege tells the server to check the script to maker sure it doesn't do anything 'dangerous', i.e. nothing that a user with the specified privilege credentials shouldn't be able to do. If the server approves of your script and is able to compile it, systemtap will then load the resulting module for you even though you are an unprivileged user. If you save the resulting module by using the -p4 option of stap, then trusted, unprivileged users can load the module at a later time using staprun: # stap -e 'probe begin { printf ("Hello\n"); exit (); }' -p4 stap_5330.ko # staprun stap_5330.ko Hello Note that the module has already been certified (signed), so no special options are needed. Additional Information ---------------------- o When specifying path names in your script and compiling using a server, you must use a server which has access to those paths (e.g. via nfs, or a server on the local host) and you must specify the paths in full from the servers's point of view. For example, specify probe process("foo").begin() as probe process("/the/full/path/as/seen/by/the/server/to/foo").begin() o You can use '--privilege=[stapusr|stapsys] -pN' (for 1 <= N <= 4) without --use-server to compile and check scripts directly. stap will still check your script for 'dangerous' behavior, but will not load it for an unprivileged user. o When using --privilege, all compile time and run time restrictions are enforced for all users, including root and members of the group stapdev. Setup and Administration of Unprivileged Users for System Administrators ======================================================================== Introduction ------------ In order to use the full capabilities of systemtap, one must run it as root or as a member of the group stapdev. For other (unprivileged) users, systemtap does provide support for use of a subset of systemtap's capabilities to perform limited probing. For example, tracing your own applications or polling using timers. The intent is to give unprivileged users capabilities similar to those provided by a debugger. In order for this to happen, the system administrator must first perform some setup: o Systemtap compile server(s) must be made available on the local network. One server is needed for each kernel version and architecture pair for which users will compile scripts. o The compile server(s) must be trusted as an SSL peer and as a signer of systemtap modules on hosts on which unprivileged users will compile and run their scripts respectively. o Unprivileged users must be added to the group stapusr, and possibly the group stapsys on the host(s) on which they will run their scripts. Below are the necessary steps for the system administrator to setup the above infrastructure. Systemtap Compile Server ------------------------ In order to load the kernel module produced by compiling a systemtap script for an unprivileged user, we must know that the script was compiled correctly and that the script does not do anything dangerous. A systemap compile server provides a trusted environment needed to certify both conditions. In order to make a compile server available on the local network the systemtap-server package and its prerequisites must be installed on the server host. The system administrator then uses the following command: sudo service stap-server start [-r KERNEL-RELEASE] [-a ARCH] For example: # sudo service stap-server start -r 2.6.34.7-61.fc13.x86_64 -a x86_64 Starting stap-server -a "x86_64" -r "2.6.34.7-61.fc13.x86_64" -u "stap-server" [ OK ] This starts a compile server for the specified kernel release and hardware architecture. The kernel and kernel-devel package for the specified release and architecture must be installed on the server host. The kernel-debuginfo package for each kernel release and architecture should also be installed, but is not relevant for unprivileged users. If either one (or both) the kernel release and/or architecture is not specified, the kernel release and/or architecture of the server host will be used: # sudo service stap-server start Starting stap-server -a "x86_64" -r "2.6.34.7-66.fc13.x86_64" -u "stap-server" [ OK ] As a short cut, to start a server for each kernel release and architecture installed on the server host, use the command: # sudo service stap-server start -i Starting stap-server -a "x86_64" -r "2.6.34.7-61.fc13.x86_64" -u "stap-server" [ OK ] Starting stap-server -a "x86_64" -r "2.6.34.7-63.fc13.x86_64" -u "stap-server" [ OK ] Starting stap-server -a "x86_64" -r "2.6.34.7-66.fc13.x86_64" -u "stap-server" [ OK ] NOTE: Only root can start a systemtap server using the service command. Trust of Compile Servers ------------------------ Once systemtap compile servers have been made available on the local network, the system administrator must certify which ones are trusted as SSL peers, as systemtap kernel module signers or both. Certifying a compile server as an SSL peer means what the system administrator trusts that it compiles systemtap scripts correctly. Certifying a compile server as a module signer means that the system administrator trusts it to correctly check a systemtap script for behavior which should not be made available to unprivileged users. When a script is compiled using the --privilege option, the server checks the script for such behavior and cryptographically signs the resulting module if it is safe for use by unprivileged users. Verification of the signature certifies that the module was certified as 'safe' by the server and that it has not been altered since it was certified. Systemtap compile servers started by using the 'service' command are automatically trusted both as SSL peers and as module signers on the server's host. No further setup of the servers is necessary for users (clients) on that same host. Before clients on another host can make use of a server, the system administrator of each client host must certify trust in that server. This is performed in two steps: 1) Identify the server(s) to be trusted. # stap --list-servers=online,compatible Systemtap Compile Server Status for 'online,compatible' host=somehost ip=10.15.16.156 port=26543 sysinfo="2.6.34.7-66.fc13.x86_64 x86_64" certinfo="00:93:49:be:2a" Identify the server(s) to be trusted by examining the host name, ip address and sysinfo (kernel release and architecture). Take note of the 'certinfo' field of each server to be trusted. NOTE: In order for servers to be detected, the port for mDNS (5353/udp) must be open on the server and client hosts. 2) For each server to be trusted for use by unprivileged clients, use the command: sudo stap --trust-servers=ssl,signer,all-users --use-server=CERTINFO1 [--use-server=CERTINFO2 ...] where each CERTINFOn is the value of the 'certinfo' field of a server to be trusted (obtained using the previous command). For example: # sudo stap --trust-servers=ssl,signer,all-users --use-server=00:93:49:be:2a Add trust in the following servers as an SSL peer for all users and as a module signer for all users? host=somehost ip=10.15.16.156 port=26543 sysinfo="2.6.34.7-66.fc13.x86_64 x86_64" certinfo="00:93:49:be:2a" [y/N] y Using the 'certinfo' to specify each server ensures that the exact servers which were intended are the ones which become trusted. Note that only root can certify trust in a server as signer in this way. Now verify the result: # stap --list-servers --privilege=stapusr Systemtap Compile Server Status for 'online,trusted,compatible,signer' host=somehost ip=10.15.16.156 port=26543 sysinfo="2.6.34.7-66.fc13.x86_64 x86_64" certinfo="00:93:49:be:2a" Each of the servers you specified in stap 2 above should be listed. Trust of Unprivileged Users --------------------------- Finally, once compile servers have been set up and are trusted, each unprivileged user must be explicitly trusted. This is done by adding each unprivileged user to the group stapusr, and possibly the group stapsys on each host on which they will run systemtap scripts: sudo usermod -a -G stapusr[,stapsys] USERID If the user is already logged in, they can try using newgrp stapusr to activate their membership. If all else fails, logging out and back in again should work. See newgrp(1) for details. systemtap-2.3/aclocal.m4000066400000000000000000001401541217430427200152560ustar00rootroot00000000000000# generated automatically by aclocal 1.12.2 -*- Autoconf -*- # Copyright (C) 1996-2012 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 1 (pkg-config-0.24) # # Copyright © 2004 Scott James Remnant . # # 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) # only at the first occurence in configure.ac, so if the first place # it's called might be skipped (such as if it is within an "if", you # have to call PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])# PKG_CHECK_MODULES # PKG_INSTALLDIR(DIRECTORY) # ------------------------- # Substitutes the variable pkgconfigdir as the location where a module # should install pkg-config .pc files. By default the directory is # $libdir/pkgconfig, but the default can be changed by passing # DIRECTORY. The user can override through the --with-pkgconfigdir # parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ]) dnl PKG_INSTALLDIR # PKG_NOARCH_INSTALLDIR(DIRECTORY) # ------------------------- # Substitutes the variable noarch_pkgconfigdir as the location where a # module should install arch-independent pkg-config .pc files. By # default the directory is $datadir/pkgconfig, but the default can be # changed by passing DIRECTORY. The user can override through the # --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ]) dnl PKG_NOARCH_INSTALLDIR # Copyright (C) 2002-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.12' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.12.2], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.12.2])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # Copyright (C) 1996-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 5 # This was merged into AC_PROG_CC in Autoconf. AU_DEFUN([AM_PROG_CC_STDC], [AC_PROG_CC AC_DIAGNOSE([obsolete], [$0: your code should no longer depend upon 'am_cv_prog_cc_stdc', but upon 'ac_cv_prog_cc_stdc'. Remove this warning and the assignment when you adjust the code. You can also remove the above call to AC_PROG_CC if you already called it elsewhere.]) am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc ]) AU_DEFUN([fp_PROG_CC_STDC]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 10 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 17 # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 6 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 19 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.62])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated. For more info, see: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl dnl Support for Objective C++ was only introduced in Autoconf 2.65, dnl but we still cater to Autoconf 2.62. m4_ifdef([AC_PROG_OBJCXX], [AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])])dnl ]) _AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl dnl The 'parallel-tests' driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering # Copyright (C) 1996-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 7 # AM_MAINTAINER_MODE([DEFAULT-MODE]) # ---------------------------------- # Control maintainer-specific portions of Makefiles. # Default is to disable them, unless 'enable' is passed literally. # For symmetry, 'disable' may be passed as well. Anyway, the user # can override the default with the --enable/--disable switch. AC_DEFUN([AM_MAINTAINER_MODE], [m4_case(m4_default([$1], [disable]), [enable], [m4_define([am_maintainer_other], [disable])], [disable], [m4_define([am_maintainer_other], [enable])], [m4_define([am_maintainer_other], [enable]) m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) dnl maintainer-mode's default is 'disable' unless 'enable' is passed AC_ARG_ENABLE([maintainer-mode], [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], am_maintainer_other[ make rules and dependencies not useful (and sometimes confusing) to the casual installer])], [USE_MAINTAINER_MODE=$enableval], [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE AC_SUBST([MAINT])dnl ] ) AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 5 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Copyright (C) 1999-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 6 # AM_PROG_CC_C_O # -------------- # Like AC_PROG_CC_C_O, but changed for automake. AC_DEFUN([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC_C_O])dnl AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o if test "$am_t" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi dnl Make sure AC_PROG_CC is never called again, or it will override our dnl setting of CC. m4_define([AC_PROG_CC], [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 7 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Copyright (C) 2003-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # AM_PROG_MKDIR_P # --------------- # Check for 'mkdir -p'. AC_DEFUN([AM_PROG_MKDIR_P], [AC_PREREQ([2.60])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl dnl FIXME to be removed in Automake 1.13. AC_DIAGNOSE([obsolete], [$0: this macro is deprecated, and will soon be removed. You should use the Autoconf-provided 'AC][_PROG_MKDIR_P' macro instead, and use '$(MKDIR_P)' instead of '$(mkdir_p)'in your Makefile.am files.]) dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, dnl while keeping a definition of mkdir_p for backward compatibility. dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of dnl Makefile.ins that do not define MKDIR_P, so we do our own dnl adjustment using top_builddir (which is defined more often than dnl MKDIR_P). AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl case $mkdir_p in [[\\/$]]* | ?:[[\\/]]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 6 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 9 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of '-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/gettext.m4]) m4_include([m4/iconv.m4]) m4_include([m4/lib-ld.m4]) m4_include([m4/lib-link.m4]) m4_include([m4/lib-prefix.m4]) m4_include([m4/nls.m4]) m4_include([m4/po.m4]) m4_include([m4/progtest.m4]) systemtap-2.3/auto_free.h000066400000000000000000000024171217430427200155370ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2008 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef AUTO_FREE_H #define AUTO_FREE_H 1 #include // Very simple auto_ptr-like class for protecting storage allocated // with free(). class auto_free { public: auto_free(void* ptr) : _ptr(ptr) {} ~auto_free() { if (_ptr) std::free(_ptr); } void release() { _ptr = 0; } private: // No copying allowed. auto_free(const auto_free& af); // No assignment either auto_free& operator=(const auto_free& rhs); void* _ptr; }; // Use this to free a pointer whose value may change after the initial // allocation e.g., be realloced. template class auto_free_ref { public: typedef T pointer_type; auto_free_ref(pointer_type& ptr) : _ptr(ptr) { } ~auto_free_ref() { if (_ptr) std::free(_ptr); } private: // No copying allowed. auto_free_ref(const auto_free_ref& af); // No assignment either auto_free_ref& operator=(const auto_free_ref& rhs); pointer_type& _ptr; }; #endif /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/buildrun.cxx000066400000000000000000001021771217430427200157710ustar00rootroot00000000000000// build/run probes // Copyright (C) 2005-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "config.h" #include "buildrun.h" #include "session.h" #include "util.h" #include "hash.h" #include "translate.h" #include #include #include extern "C" { #include #include #include #include #include #include #include #include #include } using namespace std; /* Adjust and run make_cmd to build a kernel module. */ static int run_make_cmd(systemtap_session& s, vector& make_cmd, bool null_out=false, bool null_err=false) { assert_no_interrupts(); // PR14168: we used to unsetenv values here; instead do it via // env(1) in make_any_make_cmd(). // Disable ccache to avoid saving files that will never be reused. // (ccache is useless to us, because our compiler commands always // include the randomized tmpdir path.) // It's not critical if this fails, so the return is ignored. (void) setenv("CCACHE_DISABLE", "1", 0); if (s.verbose > 2) make_cmd.push_back("V=1"); else if (s.verbose > 1) make_cmd.push_back("--no-print-directory"); else { make_cmd.push_back("-s"); make_cmd.push_back("--no-print-directory"); } // Exploit SMP parallelism, if available. long smp = sysconf(_SC_NPROCESSORS_ONLN); if (smp >= 1) make_cmd.push_back("-j" + lex_cast(smp+1)); if (strverscmp (s.kernel_base_release.c_str(), "2.6.29") < 0) { // Older kernels, before linux commit #fd54f502841c1, include // gratuitous "echo"s in their Makefile. We need to suppress // that with this bluntness. null_out = true; } int rc = stap_system (s.verbose, "kbuild", make_cmd, null_out, null_err); if (rc != 0) s.set_try_server (); return rc; } static vector make_any_make_cmd(systemtap_session& s, const string& dir, const string& target) { vector make_cmd; // PR14168: sanitize environment variables for kbuild invocation make_cmd.push_back("env"); make_cmd.push_back("-uARCH"); make_cmd.push_back("-uKBUILD_EXTMOD"); make_cmd.push_back("-uCROSS_COMPILE"); make_cmd.push_back("-uKBUILD_IMAGE"); make_cmd.push_back("-uKCONFIG_CONFIG"); make_cmd.push_back("-uINSTALL_PATH"); string newpath = string("PATH=/usr/bin:/bin:") + (getenv("PATH") ?: ""); make_cmd.push_back(newpath.c_str()); make_cmd.push_back("make"); make_cmd.push_back("-C"); make_cmd.push_back(s.kernel_build_tree); make_cmd.push_back("M=" + dir); // need make-quoting? make_cmd.push_back(target); // Add architecture, except for old powerpc (RHBZ669082) if (s.architecture != "powerpc" || (strverscmp (s.kernel_base_release.c_str(), "2.6.15") >= 0)) make_cmd.push_back("ARCH=" + s.architecture); // need make-quoting? // PR13847: suppress debuginfo creation by default make_cmd.insert(make_cmd.end(), "CONFIG_DEBUG_INFO="); // Add any custom kbuild flags make_cmd.insert(make_cmd.end(), s.kbuildflags.begin(), s.kbuildflags.end()); return make_cmd; } static vector make_make_cmd(systemtap_session& s, const string& dir) { return make_any_make_cmd(s, dir, "modules"); } static vector make_make_objs_cmd(systemtap_session& s, const string& dir) { // Kbuild uses these rules to build external modules: // // module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD)) // modules: $(module-dirs) // @$(kecho) ' Building modules, stage 2.'; // $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost // // So if we're only interested in the stage 1 objects, we can // cheat and make only the $(module-dirs) part. return make_any_make_cmd(s, dir, "_module_" + dir); } static void output_autoconf(systemtap_session& s, ofstream& o, const char *autoconf_c, const char *deftrue, const char *deffalse) { o << "\t"; if (s.verbose < 4) o << "@"; o << "if $(CHECK_BUILD) $(SYSTEMTAP_RUNTIME)/linux/" << autoconf_c; if (s.verbose < 5) o << " > /dev/null 2>&1"; o << "; then "; if (deftrue) o << "echo \"#define " << deftrue << " 1\""; if (deffalse) o << "; else echo \"#define " << deffalse << " 1\""; o << "; fi >> $@" << endl; } void output_exportconf(systemtap_session& s, ofstream& o, const char *symbol, const char *deftrue) { o << "\t"; if (s.verbose < 4) o << "@"; if (s.kernel_exports.find(symbol) != s.kernel_exports.end()) o << "echo \"#define " << deftrue << " 1\""; o << ">> $@" << endl; } void output_dual_exportconf(systemtap_session& s, ofstream& o, const char *symbol1, const char *symbol2, const char *deftrue) { o << "\t"; if (s.verbose < 4) o << "@"; if (s.kernel_exports.find(symbol1) != s.kernel_exports.end() && s.kernel_exports.find(symbol2) != s.kernel_exports.end()) o << "echo \"#define " << deftrue << " 1\""; o << ">> $@" << endl; } void output_either_exportconf(systemtap_session& s, ofstream& o, const char *symbol1, const char *symbol2, const char *deftrue) { o << "\t"; if (s.verbose < 4) o << "@"; if (s.kernel_exports.find(symbol1) != s.kernel_exports.end() || s.kernel_exports.find(symbol2) != s.kernel_exports.end()) o << "echo \"#define " << deftrue << " 1\""; o << ">> $@" << endl; } static int compile_dyninst (systemtap_session& s) { const string module = s.tmpdir + "/" + s.module_filename(); vector cmd; cmd.push_back("gcc"); cmd.push_back("--std=gnu99"); cmd.push_back("-Wall"); cmd.push_back("-Werror"); cmd.push_back("-Wno-unused"); cmd.push_back("-Wno-strict-aliasing"); // BZ855981/948279. Since dyninst/runtime.h includes __sync_* calls, // the compiler may generate different code for it depending on -march. // For example, if the default is i386, we may get references to auxiliary // functions like __sync_add_and_fetch_4, which appear to be defined // nowhere. We hack around this problem thusly: if (s.architecture == "i386") cmd.push_back("-march=i586"); cmd.push_back("-fvisibility=hidden"); cmd.push_back("-O2"); cmd.push_back("-I" + s.runtime_path); cmd.push_back("-D__DYNINST__"); for (size_t i = 0; i < s.c_macros.size(); ++i) cmd.push_back("-D" + s.c_macros[i]); cmd.push_back(s.translated_source); cmd.push_back("-pthread"); cmd.push_back("-lrt"); cmd.push_back("-fPIC"); cmd.push_back("-shared"); cmd.push_back("-o"); cmd.push_back(module); if (s.verbose > 3) { cmd.push_back("-ftime-report"); cmd.push_back("-Q"); } int rc = stap_system (s.verbose, cmd); if (rc) s.set_try_server (); return rc; } int compile_pass (systemtap_session& s) { if (s.runtime_usermode_p()) return compile_dyninst (s); int rc = uprobes_pass (s); if (rc) { s.set_try_server (); return rc; } // fill in a quick Makefile string makefile_nm = s.tmpdir + "/Makefile"; ofstream o (makefile_nm.c_str()); // Create makefile // Clever hacks copied from vmware modules string superverbose; if (s.verbose > 3) superverbose = "set -x;"; string redirecterrors = "> /dev/null 2>&1"; if (s.verbose > 6) redirecterrors = ""; // Support O= (or KBUILD_OUTPUT) option o << "_KBUILD_CFLAGS := $(call flags,KBUILD_CFLAGS)" << endl; o << "stap_check_gcc = $(shell " << superverbose << " if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo \"$(1)\"; else echo \"$(2)\"; fi)" << endl; o << "CHECK_BUILD := $(CC) $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) $(CPPFLAGS) $(LINUXINCLUDE) $(_KBUILD_CFLAGS) $(CFLAGS_KERNEL) $(EXTRA_CFLAGS) $(CFLAGS) -DKBUILD_BASENAME=\\\"" << s.module_name << "\\\"" << (s.omit_werror ? "" : " -Werror") << " -S -o /dev/null -xc " << endl; o << "stap_check_build = $(shell " << superverbose << " if $(CHECK_BUILD) $(1) " << redirecterrors << " ; then echo \"$(2)\"; else echo \"$(3)\"; fi)" << endl; o << "SYSTEMTAP_RUNTIME = \"" << s.runtime_path << "\"" << endl; // "autoconf" options go here // RHBZ 543529: early rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules o << "CONFIG_MODULE_SIG := n" << endl; string module_cflags = "EXTRA_CFLAGS"; o << module_cflags << " :=" << endl; // XXX: This gruesome hack is needed on some kernels built with separate O=directory, // where files like 2.6.27 x86's asm/mach-*/mach_mpspec.h are not found on the cpp path. // This could be a bug in arch/x86/Makefile that names // mflags-y += -Iinclude/asm-x86/mach-default // but that path does not exist in an O= build tree. o << module_cflags << " += -Iinclude2/asm/mach-default" << endl; if (s.kernel_source_tree != "") o << module_cflags << " += -I" + s.kernel_source_tree << endl; // NB: don't try // o << module_cflags << " += -Iusr/include" << endl; // since such headers are cleansed of _KERNEL_ pieces that we need o << "STAPCONF_HEADER := " << s.tmpdir << "/" << s.stapconf_name << endl; o << "$(STAPCONF_HEADER):" << endl; o << "\t@echo -n > $@" << endl; output_autoconf(s, o, "autoconf-hrtimer-rel.c", "STAPCONF_HRTIMER_REL", NULL); output_autoconf(s, o, "autoconf-generated-compile.c", "STAPCONF_GENERATED_COMPILE", NULL); output_autoconf(s, o, "autoconf-hrtimer-getset-expires.c", "STAPCONF_HRTIMER_GETSET_EXPIRES", NULL); output_autoconf(s, o, "autoconf-inode-private.c", "STAPCONF_INODE_PRIVATE", NULL); output_autoconf(s, o, "autoconf-constant-tsc.c", "STAPCONF_CONSTANT_TSC", NULL); output_autoconf(s, o, "autoconf-ktime-get-real.c", "STAPCONF_KTIME_GET_REAL", NULL); output_autoconf(s, o, "autoconf-x86-uniregs.c", "STAPCONF_X86_UNIREGS", NULL); output_autoconf(s, o, "autoconf-nameidata.c", "STAPCONF_NAMEIDATA_CLEANUP", NULL); output_dual_exportconf(s, o, "unregister_kprobes", "unregister_kretprobes", "STAPCONF_UNREGISTER_KPROBES"); output_autoconf(s, o, "autoconf-kprobe-symbol-name.c", "STAPCONF_KPROBE_SYMBOL_NAME", NULL); output_autoconf(s, o, "autoconf-real-parent.c", "STAPCONF_REAL_PARENT", NULL); output_autoconf(s, o, "autoconf-uaccess.c", "STAPCONF_LINUX_UACCESS_H", NULL); output_autoconf(s, o, "autoconf-oneachcpu-retry.c", "STAPCONF_ONEACHCPU_RETRY", NULL); output_autoconf(s, o, "autoconf-dpath-path.c", "STAPCONF_DPATH_PATH", NULL); output_exportconf(s, o, "synchronize_sched", "STAPCONF_SYNCHRONIZE_SCHED"); output_autoconf(s, o, "autoconf-task-uid.c", "STAPCONF_TASK_UID", NULL); output_dual_exportconf(s, o, "alloc_vm_area", "free_vm_area", "STAPCONF_VM_AREA"); output_autoconf(s, o, "autoconf-procfs-owner.c", "STAPCONF_PROCFS_OWNER", NULL); output_autoconf(s, o, "autoconf-alloc-percpu-align.c", "STAPCONF_ALLOC_PERCPU_ALIGN", NULL); output_autoconf(s, o, "autoconf-x86-gs.c", "STAPCONF_X86_GS", NULL); output_autoconf(s, o, "autoconf-grsecurity.c", "STAPCONF_GRSECURITY", NULL); output_autoconf(s, o, "autoconf-trace-printk.c", "STAPCONF_TRACE_PRINTK", NULL); output_autoconf(s, o, "autoconf-regset.c", "STAPCONF_REGSET", NULL); output_autoconf(s, o, "autoconf-utrace-regset.c", "STAPCONF_UTRACE_REGSET", NULL); output_autoconf(s, o, "autoconf-uprobe-get-pc.c", "STAPCONF_UPROBE_GET_PC", NULL); output_autoconf(s, o, "autoconf-hlist-4args.c", "STAPCONF_HLIST_4ARGS", NULL); output_exportconf(s, o, "tsc_khz", "STAPCONF_TSC_KHZ"); output_exportconf(s, o, "cpu_khz", "STAPCONF_CPU_KHZ"); output_exportconf(s, o, "__module_text_address", "STAPCONF_MODULE_TEXT_ADDRESS"); output_exportconf(s, o, "add_timer_on", "STAPCONF_ADD_TIMER_ON"); output_dual_exportconf(s, o, "probe_kernel_read", "probe_kernel_write", "STAPCONF_PROBE_KERNEL"); output_autoconf(s, o, "autoconf-hw_breakpoint_context.c", "STAPCONF_HW_BREAKPOINT_CONTEXT", NULL); output_autoconf(s, o, "autoconf-save-stack-trace.c", "STAPCONF_KERNEL_STACKTRACE", NULL); output_autoconf(s, o, "autoconf-save-stack-trace-no-bp.c", "STAPCONF_KERNEL_STACKTRACE_NO_BP", NULL); output_autoconf(s, o, "autoconf-asm-syscall.c", "STAPCONF_ASM_SYSCALL_H", NULL); output_autoconf(s, o, "autoconf-ring_buffer-flags.c", "STAPCONF_RING_BUFFER_FLAGS", NULL); output_autoconf(s, o, "autoconf-ring_buffer_lost_events.c", "STAPCONF_RING_BUFFER_LOST_EVENTS", NULL); output_autoconf(s, o, "autoconf-ring_buffer_read_prepare.c", "STAPCONF_RING_BUFFER_READ_PREPARE", NULL); output_autoconf(s, o, "autoconf-kallsyms-on-each-symbol.c", "STAPCONF_KALLSYMS_ON_EACH_SYMBOL", NULL); output_autoconf(s, o, "autoconf-walk-stack.c", "STAPCONF_WALK_STACK", NULL); output_autoconf(s, o, "autoconf-stacktrace_ops-warning.c", "STAPCONF_STACKTRACE_OPS_WARNING", NULL); output_autoconf(s, o, "autoconf-mm-context-vdso.c", "STAPCONF_MM_CONTEXT_VDSO", NULL); output_autoconf(s, o, "autoconf-mm-context-vdso-base.c", "STAPCONF_MM_CONTEXT_VDSO_BASE", NULL); output_autoconf(s, o, "autoconf-blk-types.c", "STAPCONF_BLK_TYPES", NULL); output_autoconf(s, o, "autoconf-perf-structpid.c", "STAPCONF_PERF_STRUCTPID", NULL); output_autoconf(s, o, "perf_event_counter_context.c", "STAPCONF_PERF_COUNTER_CONTEXT", NULL); output_autoconf(s, o, "perf_probe_handler_nmi.c", "STAPCONF_PERF_HANDLER_NMI", NULL); output_exportconf(s, o, "path_lookup", "STAPCONF_PATH_LOOKUP"); output_exportconf(s, o, "kern_path_parent", "STAPCONF_KERN_PATH_PARENT"); output_exportconf(s, o, "vfs_path_lookup", "STAPCONF_VFS_PATH_LOOKUP"); output_exportconf(s, o, "proc_create_data", "STAPCONF_PROC_CREATE_DATA"); output_exportconf(s, o, "PDE_DATA", "STAPCONF_PDE_DATA"); output_autoconf(s, o, "autoconf-module-sect-attrs.c", "STAPCONF_MODULE_SECT_ATTRS", NULL); output_autoconf(s, o, "autoconf-utrace-via-tracepoints.c", "STAPCONF_UTRACE_VIA_TRACEPOINTS", NULL); output_autoconf(s, o, "autoconf-task_work-struct.c", "STAPCONF_TASK_WORK_STRUCT", NULL); output_autoconf(s, o, "autoconf-vm-area-pte.c", "STAPCONF_VM_AREA_PTE", NULL); output_autoconf(s, o, "autoconf-relay-umode_t.c", "STAPCONF_RELAY_UMODE_T", NULL); output_autoconf(s, o, "autoconf-fs_supers-hlist.c", "STAPCONF_FS_SUPERS_HLIST", NULL); output_autoconf(s, o, "autoconf-compat_sigaction.c", "STAPCONF_COMPAT_SIGACTION", NULL); // used by tapset/timestamp_monotonic.stp output_exportconf(s, o, "cpu_clock", "STAPCONF_CPU_CLOCK"); output_exportconf(s, o, "local_clock", "STAPCONF_LOCAL_CLOCK"); // used by runtime/uprobe-inode.c output_either_exportconf(s, o, "uprobe_register", "register_uprobe", "STAPCONF_UPROBE_REGISTER_EXPORTED"); output_either_exportconf(s, o, "uprobe_unregister", "unregister_uprobe", "STAPCONF_UPROBE_UNREGISTER_EXPORTED"); output_autoconf(s, o, "autoconf-old-inode-uprobes.c", "STAPCONF_OLD_INODE_UPROBES", NULL); output_autoconf(s, o, "autoconf-inode-uretprobes.c", "STAPCONF_INODE_URETPROBES", NULL); // used by tapsets.cxx inode uprobe generated code output_exportconf(s, o, "uprobe_get_swbp_addr", "STAPCONF_UPROBE_GET_SWBP_ADDR_EXPORTED"); // used by runtime/loc2c-runtime.h output_exportconf(s, o, "task_user_regset_view", "STAPCONF_TASK_USER_REGSET_VIEW_EXPORTED"); // used by runtime/stp_utrace.c output_exportconf(s, o, "task_work_add", "STAPCONF_TASK_WORK_ADD_EXPORTED"); output_exportconf(s, o, "signal_wake_up_state", "STAPCONF_SIGNAL_WAKE_UP_STATE_EXPORTED"); output_exportconf(s, o, "signal_wake_up", "STAPCONF_SIGNAL_WAKE_UP_EXPORTED"); output_exportconf(s, o, "__lock_task_sighand", "STAPCONF___LOCK_TASK_SIGHAND_EXPORTED"); output_autoconf(s, o, "autoconf-pagefault_disable.c", "STAPCONF_PAGEFAULT_DISABLE", NULL); output_exportconf(s, o, "kallsyms_lookup_name", "STAPCONF_KALLSYMS"); output_autoconf(s, o, "autoconf-uidgid.c", "STAPCONF_LINUX_UIDGID_H", NULL); output_exportconf(s, o, "sigset_from_compat", "STAPCONF_SIGSET_FROM_COMPAT_EXPORTED"); o << module_cflags << " += -include $(STAPCONF_HEADER)" << endl; for (unsigned i=0; i 3) o << "EXTRA_CFLAGS += -ftime-report -Q" << endl; // XXX: unfortunately, -save-temps can't work since linux kbuild cwd // is not writable. // // if (s.keep_tmpdir) // o << "CFLAGS += -fverbose-asm -save-temps" << endl; // Kernels can be compiled with CONFIG_CC_OPTIMIZE_FOR_SIZE to select // -Os, otherwise -O2 is the default. o << "EXTRA_CFLAGS += -freorder-blocks" << endl; // improve on -Os // We used to allow the user to override default optimization when so // requested by adding a -O[0123s] so they could determine the // time/space/speed tradeoffs themselves, but we cannot guantantee that // the (un)optimized code actually compiles and/or generates functional // code, so we had to remove it. // o << "EXTRA_CFLAGS += " << s.gcc_flags << endl; // Add -O[0123s] // o << "CFLAGS += -fno-unit-at-a-time" << endl; // 256 bytes should be enough for anybody // XXX this doesn't validate varargs, per gcc bug #41633 o << "EXTRA_CFLAGS += $(call cc-option,-Wframe-larger-than=256)" << endl; // Assumes linux 2.6 kbuild o << "EXTRA_CFLAGS += -Wno-unused" << (s.omit_werror ? "" : " -Werror") << endl; #if CHECK_POINTER_ARITH_PR5947 o << "EXTRA_CFLAGS += -Wpointer-arith" << endl; #endif o << "EXTRA_CFLAGS += -I\"" << s.runtime_path << "\"" << endl; // XXX: this may help ppc toc overflow // o << "CFLAGS := $(subst -Os,-O2,$(CFLAGS)) -fminimal-toc" << endl; o << "obj-m := " << s.module_name << ".o" << endl; // print out all the auxiliary source (->object) file names o << s.module_name << "-y := "; for (unsigned i=0; ifilename; assert (srcname != "" && srcname.rfind('/') != string::npos); string objname = srcname.substr(srcname.rfind('/')+1); // basename assert (objname != "" && objname[objname.size()-1] == 'c'); objname[objname.size()-1] = 'o'; // now objname o << " " + objname; } // and once again, for the translated_source file. It can't simply // be named MODULENAME.c, since kbuild doesn't allow a foo.ko file // consisting of multiple .o's to have foo.o/foo.c as a source. // (It uses ld -r -o foo.o EACH.o EACH.o). { string srcname = s.translated_source; assert (srcname != "" && srcname.rfind('/') != string::npos); string objname = srcname.substr(srcname.rfind('/')+1); // basename assert (objname != "" && objname[objname.size()-1] == 'c'); objname[objname.size()-1] = 'o'; // now objname o << " " + objname; } o << endl; // add all stapconf dependencies o << s.translated_source << ": $(STAPCONF_HEADER)" << endl; for (unsigned i=0; ifilename << ": $(STAPCONF_HEADER)" << endl; o.close (); // Generate module directory pathname and make sure it exists. string module_dir = s.kernel_build_tree; string module_dir_makefile = module_dir + "/Makefile"; struct stat st; rc = stat(module_dir_makefile.c_str(), &st); if (rc != 0) { clog << _F("Checking \" %s \" failed with error: %s\nEnsure kernel development headers & makefiles are installed.", module_dir_makefile.c_str(), strerror(errno)) << endl; s.set_try_server (); return rc; } // Run make vector make_cmd = make_make_cmd(s, s.tmpdir); rc = run_make_cmd(s, make_cmd); if (rc) s.set_try_server (); return rc; } /* * If uprobes was built as part of the kernel build (either built-in * or as a module), the uprobes exports should show up. This is to be * as distinct from the stap-built uprobes.ko from the runtime. */ static bool kernel_built_uprobes (systemtap_session& s) { if (s.runtime_usermode_p()) return true; // sort of, via dyninst // see also tapsets.cxx:kernel_supports_inode_uprobes() return ((s.kernel_config["CONFIG_ARCH_SUPPORTS_UPROBES"] == "y" && s.kernel_config["CONFIG_UPROBES"] == "y") || (s.kernel_exports.find("unregister_uprobe") != s.kernel_exports.end())); } static int make_uprobes (systemtap_session& s) { if (s.verbose > 1) clog << _("Pass 4, preamble: (re)building SystemTap's version of uprobes.") << endl; // create a subdirectory for the uprobes module string dir(s.tmpdir + "/uprobes"); if (create_dir(dir.c_str()) != 0) { s.print_warning("failed to create directory for build uprobes."); s.set_try_server (); return 1; } // create a simple Makefile string makefile(dir + "/Makefile"); ofstream omf(makefile.c_str()); omf << "obj-m := uprobes.o" << endl; // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules omf << "CONFIG_MODULE_SIG := n" << endl; omf.close(); // create a simple #include-chained source file string runtimesourcefile(s.runtime_path + "/linux/uprobes/uprobes.c"); string sourcefile(dir + "/uprobes.c"); ofstream osrc(sourcefile.c_str()); osrc << "#include \"" << runtimesourcefile << "\"" << endl; // pass --modinfo k=v to uprobes build too for (unsigned i = 0; i < s.modinfos.size(); i++) { const string& mi = s.modinfos[i]; size_t loc = mi.find('='); string tag = mi.substr (0, loc); string value = mi.substr (loc+1); osrc << "MODULE_INFO(" << tag << "," << lex_cast_qstring(value) << ");" << endl; } osrc.close(); // make the module vector make_cmd = make_make_cmd(s, dir); int rc = run_make_cmd(s, make_cmd); if (!rc && !copy_file(dir + "/Module.symvers", s.tmpdir + "/Module.symvers")) rc = -1; if (s.verbose > 1) clog << _("uprobes rebuild exit code: ") << rc << endl; if (rc) s.set_try_server (); else s.uprobes_path = dir + "/uprobes.ko"; return rc; } static bool get_cached_uprobes(systemtap_session& s) { s.uprobes_hash = s.use_cache ? find_uprobes_hash(s) : ""; if (!s.uprobes_hash.empty()) { // NB: We always put uprobes.ko in its own directory, especially so // stap-serverd can more easily locate it. string dir(s.tmpdir + "/uprobes"); if (create_dir(dir.c_str()) != 0) return false; string cacheko = s.uprobes_hash + ".ko"; string tmpko = dir + "/uprobes.ko"; // The symvers file still needs to go in the script module's directory. string cachesyms = s.uprobes_hash + ".symvers"; string tmpsyms = s.tmpdir + "/Module.symvers"; if (get_file_size(cacheko) > 0 && copy_file(cacheko, tmpko) && get_file_size(cachesyms) > 0 && copy_file(cachesyms, tmpsyms)) { s.uprobes_path = tmpko; return true; } } return false; } static void set_cached_uprobes(systemtap_session& s) { if (s.use_cache && !s.uprobes_hash.empty()) { string cacheko = s.uprobes_hash + ".ko"; string tmpko = s.tmpdir + "/uprobes/uprobes.ko"; copy_file(tmpko, cacheko); string cachesyms = s.uprobes_hash + ".symvers"; string tmpsyms = s.tmpdir + "/uprobes/Module.symvers"; copy_file(tmpsyms, cachesyms); } } int uprobes_pass (systemtap_session& s) { if (!s.need_uprobes || kernel_built_uprobes(s)) return 0; if (s.kernel_config["CONFIG_UTRACE"] != string("y")) { clog << _("user-space process-tracking facilities not available [man error::process-tracking]") << endl; s.set_try_server (); return 1; } /* * We need to use the version of uprobes that comes with SystemTap. Try to * get it from the cache first. If not found, build it and try to save it to * the cache for future reuse. */ int rc = 0; if (!get_cached_uprobes(s)) { rc = make_uprobes(s); if (!rc) set_cached_uprobes(s); } if (rc) s.set_try_server (); return rc; } static vector make_dyninst_run_command (systemtap_session& s, const string& remotedir, const string& version) { vector cmd; cmd.push_back(getenv("SYSTEMTAP_STAPDYN") ?: BINDIR "/stapdyn"); // use slightly less verbosity for (unsigned i=1; i make_run_command (systemtap_session& s, const string& remotedir, const string& version) { if (s.runtime_usermode_p()) return make_dyninst_run_command(s, remotedir, version); // for now, just spawn staprun vector staprun_cmd; staprun_cmd.push_back(getenv("SYSTEMTAP_STAPRUN") ?: BINDIR "/staprun"); // use slightly less verbosity for (unsigned i=1; i test-contents) map, compile them ASAP, and return // a (header-file -> obj-filename) map. map make_tracequeries(systemtap_session& s, const map& contents) { static unsigned tick = 0; string basename("tracequery_kmod_" + lex_cast(++tick)); map objs; // create a subdirectory for the module string dir(s.tmpdir + "/" + basename); if (create_dir(dir.c_str()) != 0) { s.print_warning("failed to create directory for querying tracepoints."); s.set_try_server (); return objs; } // create a simple Makefile string makefile(dir + "/Makefile"); ofstream omf(makefile.c_str()); // force debuginfo generation, and relax implicit functions omf << "EXTRA_CFLAGS := -g -Wno-implicit-function-declaration" << (s.omit_werror ? "" : " -Werror") << endl; // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules omf << "CONFIG_MODULE_SIG := n" << endl; if (s.kernel_source_tree != "") omf << "EXTRA_CFLAGS += -I" + s.kernel_source_tree << endl; omf << "obj-m := " << endl; // write out each header-specific source file into a separate file for (map::const_iterator it = contents.begin(); it != contents.end(); it++) { string sbasename = basename + "_" + lex_cast(++tick); // suffixed // write out source code string srcname = dir + "/" + sbasename + ".c"; string src = it->second; ofstream osrc(srcname.c_str()); osrc << src; osrc.close(); if (s.verbose > 2) clog << _F("Processing tracepoint header %s with query %s", it->first.c_str(), srcname.c_str()) << endl; // arrange to build it omf << "obj-m += " + sbasename + ".o" << endl; // NB: without prefix objs[it->first] = dir + "/" + sbasename + ".o"; } omf.close(); // make the module vector make_cmd = make_make_objs_cmd(s, dir); make_cmd.push_back ("-i"); // ignore errors, give rc 0 even in case of tracepoint header nits bool quiet = (s.verbose < 4); int rc = run_make_cmd(s, make_cmd, quiet, quiet); if (rc) s.set_try_server (); // Sometimes we fail a tracequery due to PR9993 / PR11649 type // kernel trace header problems. In this case, due to PR12729, we // used to get a lovely "Warning: make exited with status: 2" but no // other useful diagnostic. -vvvv would let a user see what's up, // but the user can't fix the problem even with that. return objs; } // Build a tiny kernel module to query type information static int make_typequery_kmod(systemtap_session& s, const vector& headers, string& name) { static unsigned tick = 0; string basename("typequery_kmod_" + lex_cast(++tick)); // create a subdirectory for the module string dir(s.tmpdir + "/" + basename); if (create_dir(dir.c_str()) != 0) { s.print_warning("failed to create directory for querying types."); s.set_try_server (); return 1; } name = dir + "/" + basename + ".ko"; // create a simple Makefile string makefile(dir + "/Makefile"); ofstream omf(makefile.c_str()); omf << "EXTRA_CFLAGS := -g -fno-eliminate-unused-debug-types" << endl; // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules omf << "CONFIG_MODULE_SIG := n" << endl; // NB: We use -include instead of #include because that gives us more power. // Using #include searches relative to the source's path, which in this case // is /tmp/..., so that's not helpful. Using -include will search relative // to the cwd, which will be the kernel build root. This means if you have a // full kernel build tree, it's possible to get at types that aren't in the // normal include path, e.g.: // @cast(foo, "bsd_acct_struct", "kernel")->... omf << "CFLAGS_" << basename << ".o :="; for (size_t i = 0; i < headers.size(); ++i) omf << " -include " << lex_cast_qstring(headers[i]); // XXX right quoting? omf << endl; omf << "obj-m := " + basename + ".o" << endl; omf.close(); // create our empty source file string source(dir + "/" + basename + ".c"); ofstream osrc(source.c_str()); osrc.close(); // make the module vector make_cmd = make_make_cmd(s, dir); bool quiet = (s.verbose < 4); int rc = run_make_cmd(s, make_cmd, quiet, quiet); if (rc) s.set_try_server (); return rc; } // Build a tiny user module to query type information static int make_typequery_umod(systemtap_session& s, const vector& headers, string& name) { static unsigned tick = 0; name = s.tmpdir + "/typequery_umod_" + lex_cast(++tick) + ".so"; // make the module // // NB: As with kmod, using -include makes relative paths more useful. The // cwd in this case will be the cwd of stap itself though, which may be // trickier to deal with. It might be better to "cd `dirname $script`" // first... vector cmd; cmd.push_back("gcc"); cmd.push_back("-shared"); cmd.push_back("-g"); cmd.push_back("-fno-eliminate-unused-debug-types"); cmd.push_back("-xc"); cmd.push_back("/dev/null"); cmd.push_back("-o"); cmd.push_back(name); for (size_t i = 0; i < headers.size(); ++i) { cmd.push_back("-include"); cmd.push_back(headers[i]); } bool quiet = (s.verbose < 4); int rc = stap_system (s.verbose, cmd, quiet, quiet); if (rc) s.set_try_server (); return rc; } int make_typequery(systemtap_session& s, string& module) { int rc; string new_module; vector headers; bool kernel = startswith(module, "kernel"); for (size_t end, i = kernel ? 6 : 0; i < module.size(); i = end + 1) { if (module[i] != '<') return -1; end = module.find('>', ++i); if (end == string::npos) return -1; string header = module.substr(i, end - i); vector matches; if (regexp_match(header, "^[a-zA-Z0-9/_.+-]+$", matches)) s.print_warning("skipping malformed @cast header \""+ header + "\""); else headers.push_back(header); } if (headers.empty()) return -1; if (kernel) rc = make_typequery_kmod(s, headers, new_module); else rc = make_typequery_umod(s, headers, new_module); if (!rc) module = new_module; return rc; } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/buildrun.h000066400000000000000000000016251217430427200154120ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2005 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef BUILDRUN_H #define BUILDRUN_H #include "elaborate.h" int compile_pass (systemtap_session& s); int uprobes_pass (systemtap_session& s); std::vector make_run_command (systemtap_session& s, const std::string& remotedir="", const std::string& version=VERSION); std::map make_tracequeries(systemtap_session& s, const std::map& contents); int make_typequery(systemtap_session& s, std::string& module); #endif // BUILDRUN_H /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/cache.cxx000066400000000000000000000316101217430427200152010ustar00rootroot00000000000000// systemtap cache manager // Copyright (C) 2006-2009 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "config.h" #include "session.h" #include "cache.h" #include "util.h" #include "stap-probe.h" #include #include #include #include #include #include #include extern "C" { #include #include #include #include #include #include #include #include } using namespace std; #define SYSTEMTAP_CACHE_MAX_FILENAME "cache_mb_limit" #define SYSTEMTAP_CACHE_DEFAULT_MB 256 #define SYSTEMTAP_CACHE_CLEAN_INTERVAL_FILENAME "cache_clean_interval_s" #define SYSTEMTAP_CACHE_CLEAN_DEFAULT_INTERVAL_S 300 struct cache_ent_info { vector paths; off_t size; // sum across all paths time_t mtime; // newest of all paths cache_ent_info(const vector& paths); bool operator<(const struct cache_ent_info& other) const; void unlink() const; }; void add_stapconf_to_cache(systemtap_session& s) { bool verbose = s.verbose > 1; string stapconf_src_path = s.tmpdir + "/" + s.stapconf_name; if (!copy_file(stapconf_src_path, s.stapconf_path, verbose)) { // NB: this is not so severe as to prevent reuse of the .ko // already copied. // // s.use_script_cache = false; // return; } } void add_script_to_cache(systemtap_session& s) { bool verbose = s.verbose > 1; // PR10543: clean the cache *before* we try putting something new into it. // We don't want to risk having the brand new contents being erased again. clean_cache(s); string module_src_path = s.tmpdir + "/" + s.module_filename(); PROBE2(stap, cache__add__module, module_src_path.c_str(), s.hash_path.c_str()); if (!copy_file(module_src_path, s.hash_path, verbose)) { s.use_script_cache = false; return; } // Copy the signature file, if any. It is not an error if this fails. if (file_exists (module_src_path + ".sgn")) copy_file(module_src_path + ".sgn", s.hash_path + ".sgn", verbose); string c_dest_path = s.hash_path; if (endswith(c_dest_path, ".ko") || endswith(c_dest_path, ".so")) c_dest_path.resize(c_dest_path.size() - 3); c_dest_path += ".c"; PROBE2(stap, cache__add__source, s.translated_source.c_str(), c_dest_path.c_str()); if (!copy_file(s.translated_source, c_dest_path, verbose)) { // NB: this is not so severe as to prevent reuse of the .ko // already copied. // // s.use_script_cache = false; } } bool get_stapconf_from_cache(systemtap_session& s) { if (s.poison_cache) return false; string stapconf_dest_path = s.tmpdir + "/" + s.stapconf_name; int fd_stapconf; // See if stapconf exists fd_stapconf = open(s.stapconf_path.c_str(), O_RDONLY); if (fd_stapconf == -1) { // It isn't in cache. return false; } // Copy the stapconf header file to the destination if (!get_file_size(fd_stapconf) || !copy_file(s.stapconf_path, stapconf_dest_path)) { close(fd_stapconf); return false; } // We're done with this file handle. close(fd_stapconf); if (s.verbose > 1) clog << _("Pass 4: using cached ") << s.stapconf_path << endl; return true; } bool get_script_from_cache(systemtap_session& s) { if (s.poison_cache) return false; string module_dest_path = s.tmpdir + "/" + s.module_filename(); string c_src_path = s.hash_path; int fd_module, fd_c; if (endswith(c_src_path, ".ko") || endswith(c_src_path, ".so")) c_src_path.resize(c_src_path.size() - 3); c_src_path += ".c"; // See if module exists fd_module = open(s.hash_path.c_str(), O_RDONLY); if (fd_module == -1) { // It isn't in cache. return false; } // See if C file exists. fd_c = open(c_src_path.c_str(), O_RDONLY); if (fd_c == -1) { // The module is there, but the C file isn't. Cleanup and // return. close(fd_module); unlink(s.hash_path.c_str()); return false; } // Check that the files aren't empty, and then // copy the cached C file to the destination if (!get_file_size(fd_module) || !get_file_size(fd_c) || !copy_file(c_src_path, s.translated_source)) { close(fd_module); close(fd_c); return false; } // Copy the cached module to the destination (if needed) if (s.last_pass != 3) { if (!copy_file(s.hash_path, module_dest_path)) { unlink(c_src_path.c_str()); close(fd_module); close(fd_c); return false; } // Copy the module signature file, if any. // It is not an error if this fails. if (file_exists (s.hash_path + ".sgn")) copy_file(s.hash_path + ".sgn", module_dest_path + ".sgn"); } // We're done with these file handles. close(fd_module); close(fd_c); // To preserve semantics (since this will happen if we're not // caching), display the C source if the last pass is 3. if (s.last_pass == 3) { ifstream i (s.translated_source.c_str()); cout << i.rdbuf(); } // And similarly, display probe module name for -p4. if (s.last_pass == 4) cout << s.hash_path << endl; // If everything worked, tell the user. We need to do this here, // since if copying the cached C file works, but copying the cached // module fails, we remove the cached C file and let the C file get // regenerated. // NB: don't use s.verbose here, since we're still in pass-2, // i.e., s.verbose = s.perpass_verbose[1]. if (s.perpass_verbose[2]) clog << _("Pass 3: using cached ") << c_src_path << endl; if (s.perpass_verbose[3] && s.last_pass != 3) clog << _("Pass 4: using cached ") << s.hash_path << endl; PROBE2(stap, cache__get, c_src_path.c_str(), s.hash_path.c_str()); return true; } void clean_cache(systemtap_session& s) { if (s.cache_path != "") { /* Get cache size limit from file in the stap cache dir */ string cache_max_filename = s.cache_path + "/"; cache_max_filename += SYSTEMTAP_CACHE_MAX_FILENAME; ifstream cache_max_file(cache_max_filename.c_str(), ios::in); unsigned long cache_mb_max; if (cache_max_file.is_open()) { cache_max_file >> cache_mb_max; cache_max_file.close(); } else { //file doesnt exist, create a default size ofstream default_cache_max(cache_max_filename.c_str(), ios::out); default_cache_max << SYSTEMTAP_CACHE_DEFAULT_MB << endl; cache_mb_max = SYSTEMTAP_CACHE_DEFAULT_MB; if (s.verbose > 1) clog << _F("Cache limit file %s/%s missing, creating default.", s.cache_path.c_str(), SYSTEMTAP_CACHE_MAX_FILENAME) << endl; } /* Get cache clean interval from file in the stap cache dir */ string cache_clean_interval_filename = s.cache_path + "/"; cache_clean_interval_filename += SYSTEMTAP_CACHE_CLEAN_INTERVAL_FILENAME; ifstream cache_clean_interval_file(cache_clean_interval_filename.c_str(), ios::in); unsigned long cache_clean_interval; if (cache_clean_interval_file.is_open()) { cache_clean_interval_file >> cache_clean_interval; cache_clean_interval_file.close(); } else { //file doesnt exist, create a default interval ofstream default_cache_clean_interval(cache_clean_interval_filename.c_str(), ios::out); default_cache_clean_interval << SYSTEMTAP_CACHE_CLEAN_DEFAULT_INTERVAL_S << endl; cache_clean_interval = SYSTEMTAP_CACHE_CLEAN_DEFAULT_INTERVAL_S; if (s.verbose > 1) clog << _F("Cache clean interval file %s missing, creating default.", cache_clean_interval_filename.c_str())<< endl; } /* Check the cache cleaning interval */ struct stat sb; if(stat(cache_clean_interval_filename.c_str(), &sb) < 0) { const char* e = strerror (errno); cerr << _F("clean_cache stat error: %s", e) << endl; return; } struct timeval current_time; gettimeofday(¤t_time, NULL); if(difftime(current_time.tv_sec, sb.st_mtime) < cache_clean_interval) { //interval not passed, don't continue if (s.verbose > 1) clog << _F("Cache cleaning skipped, interval not reached %lu s / %lu s.", (current_time.tv_sec-sb.st_mtime), cache_clean_interval) << endl; return; } else { //interval reached, continue if (s.verbose > 1) clog << _F("Cleaning cache, interval reached %lu s > %lu s.", (current_time.tv_sec-sb.st_mtime), cache_clean_interval) << endl; } // glob for all files that look like hashes glob_t cache_glob; ostringstream glob_pattern; glob_pattern << s.cache_path << "/*/*"; for (unsigned int i = 0; i < 32; i++) glob_pattern << "[[:xdigit:]]"; glob_pattern << "*"; int rc = glob(glob_pattern.str().c_str(), 0, NULL, &cache_glob); if (rc) { cerr << _F("clean_cache glob error rc=%d", rc) << endl; return; } regex_t hash_len_re; rc = regcomp (&hash_len_re, "([[:xdigit:]]{32}_[[:digit:]]+)", REG_EXTENDED); if (rc) { cerr << _F("clean_cache regcomp error rc=%d", rc) << endl; globfree(&cache_glob); return; } // group all files with the same HASH_LEN map > cache_groups; for (size_t i = 0; i < cache_glob.gl_pathc; i++) { const char* path = cache_glob.gl_pathv[i]; regmatch_t hash_len; rc = regexec(&hash_len_re, path, 1, &hash_len, 0); if (rc || hash_len.rm_so == -1 || hash_len.rm_eo == -1) cache_groups[path].push_back(path); // ungrouped else cache_groups[string(path + hash_len.rm_so, hash_len.rm_eo - hash_len.rm_so)] .push_back(path); } regfree(&hash_len_re); globfree(&cache_glob); // create each cache entry and accumulate the sum off_t cache_size_b = 0; set cache_contents; for (map >::const_iterator it = cache_groups.begin(); it != cache_groups.end(); ++it) { cache_ent_info cur_info(it->second); if (cache_contents.insert(cur_info).second) cache_size_b += cur_info.size; } unsigned long r_cache_size = cache_size_b; vector removed; //unlink .ko and .c until the cache size is under the limit for (set::iterator i = cache_contents.begin(); i != cache_contents.end(); ++i) { if (r_cache_size < cache_mb_max * 1024 * 1024) //convert cache_mb_max to bytes break; //remove this (*i) cache_entry, add to removed list for (size_t j = 0; j < i->paths.size(); ++j) PROBE1(stap, cache__clean, i->paths[j].c_str()); i->unlink(); r_cache_size -= i->size; removed.push_back(&*i); } if (s.verbose > 1 && !removed.empty()) { clog << _("Cache cleaning successful, removed entries: ") << endl; for (size_t i = 0; i < removed.size(); ++i) for (size_t j = 0; j < removed[i]->paths.size(); ++j) clog << " " << removed[i]->paths[j] << endl; } if(utime(cache_clean_interval_filename.c_str(), NULL)<0) { const char* e = strerror (errno); cerr << _F("clean_cache utime error: %s", e) << endl; return; } } else { if (s.verbose > 1) clog << _("Cache cleaning skipped, no cache path.") << endl; } } cache_ent_info::cache_ent_info(const vector& paths): paths(paths), size(0), mtime(0) { struct stat file_info; for (size_t i = 0; i < paths.size(); ++i) if (stat(paths[i].c_str(), &file_info) == 0) { size += file_info.st_size; if (file_info.st_mtime > mtime) mtime = file_info.st_mtime; } } // The ordering here determines the order that // files will be removed from the cache. bool cache_ent_info::operator<(const struct cache_ent_info& other) const { if (mtime != other.mtime) return mtime < other.mtime; if (size != other.size) return size < other.size; if (paths.size() != other.paths.size()) return paths.size() < other.paths.size(); for (size_t i = 0; i < paths.size(); ++i) if (paths[i] != other.paths[i]) return paths[i] < other.paths[i]; return false; } void cache_ent_info::unlink() const { for (size_t i = 0; i < paths.size(); ++i) ::unlink(paths[i].c_str()); } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/cache.h000066400000000000000000000004601217430427200146250ustar00rootroot00000000000000void add_script_to_cache(systemtap_session& s); bool get_script_from_cache(systemtap_session& s); void add_stapconf_to_cache(systemtap_session& s); bool get_stapconf_from_cache(systemtap_session& s); void clean_cache(systemtap_session& s); /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/cmdline.cxx000066400000000000000000000053541217430427200155570ustar00rootroot00000000000000// Shared data for parsing the stap command line // Copyright (C) 2012 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include #include "cmdline.h" // NB: when adding new options, consider very carefully whether they // should be restricted from stap clients (after --client-options)! struct option stap_long_options[] = { { "skip-badvars", 0, NULL, LONG_OPT_SKIP_BADVARS }, { "vp", 1, NULL, LONG_OPT_VERBOSE_PASS }, { "unprivileged", 0, NULL, LONG_OPT_UNPRIVILEGED }, #define OWE5 "tter" #define OWE1 "uild-" #define OWE6 "fu-kb" #define OWE2 "i-kno" #define OWE4 "st" #define OWE3 "w-be" { OWE4 OWE6 OWE1 OWE2 OWE3 OWE5, 0, NULL, LONG_OPT_OMIT_WERROR }, { "client-options", 0, NULL, LONG_OPT_CLIENT_OPTIONS }, { "help", 0, NULL, LONG_OPT_HELP }, { "disable-cache", 0, NULL, LONG_OPT_DISABLE_CACHE }, { "poison-cache", 0, NULL, LONG_OPT_POISON_CACHE }, { "clean-cache", 0, NULL, LONG_OPT_CLEAN_CACHE }, { "compatible", 1, NULL, LONG_OPT_COMPATIBLE }, { "ldd", 0, NULL, LONG_OPT_LDD }, { "use-server", 2, NULL, LONG_OPT_USE_SERVER }, { "list-servers", 2, NULL, LONG_OPT_LIST_SERVERS }, { "trust-servers", 2, NULL, LONG_OPT_TRUST_SERVERS }, { "use-server-on-error", 2, NULL, LONG_OPT_USE_SERVER_ON_ERROR }, { "all-modules", 0, NULL, LONG_OPT_ALL_MODULES }, { "remote", 1, NULL, LONG_OPT_REMOTE }, { "remote-prefix", 0, NULL, LONG_OPT_REMOTE_PREFIX }, { "check-version", 0, NULL, LONG_OPT_CHECK_VERSION }, { "version", 0, NULL, LONG_OPT_VERSION }, { "tmpdir", 1, NULL, LONG_OPT_TMPDIR }, { "download-debuginfo", 2, NULL, LONG_OPT_DOWNLOAD_DEBUGINFO }, { "dump-probe-types", 0, NULL, LONG_OPT_DUMP_PROBE_TYPES }, { "privilege", 1, NULL, LONG_OPT_PRIVILEGE }, { "suppress-handler-errors", 0, NULL, LONG_OPT_SUPPRESS_HANDLER_ERRORS }, { "modinfo", 1, NULL, LONG_OPT_MODINFO }, { "rlimit-as", 1, NULL, LONG_OPT_RLIMIT_AS }, { "rlimit-cpu", 1, NULL, LONG_OPT_RLIMIT_CPU }, { "rlimit-nproc", 1, NULL, LONG_OPT_RLIMIT_NPROC }, { "rlimit-stack", 1, NULL, LONG_OPT_RLIMIT_STACK }, { "rlimit-fsize", 1, NULL, LONG_OPT_RLIMIT_FSIZE }, { "sysroot", 1, NULL, LONG_OPT_SYSROOT }, { "sysenv", 1, NULL, LONG_OPT_SYSENV }, { "suppress-time-limits", 0, NULL, LONG_OPT_SUPPRESS_TIME_LIMITS }, { "runtime", 1, NULL, LONG_OPT_RUNTIME }, { "dyninst", 0, NULL, LONG_OPT_RUNTIME_DYNINST }, { "benchmark-sdt-loops", 1, NULL, LONG_OPT_BENCHMARK_SDT_LOOPS }, { "benchmark-sdt-threads", 1, NULL, LONG_OPT_BENCHMARK_SDT_THREADS }, { "color", 2, NULL, LONG_OPT_COLOR_ERRS }, { "colour", 2, NULL, LONG_OPT_COLOR_ERRS }, { NULL, 0, NULL, 0 } }; systemtap-2.3/cmdline.h000066400000000000000000000040471217430427200152020ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2012 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef CMDLINE_H #define CMDLINE_H 1 extern "C" { #include } // NB: when adding new options, consider very carefully whether they // should be restricted from stap clients (after --client-options)! // NB: The values of these enumerators must not conflict with the values of ordinary // characters, since those are returned by getopt_long for short options. enum { LONG_OPT_VERBOSE_PASS = 256, LONG_OPT_SKIP_BADVARS, LONG_OPT_UNPRIVILEGED, LONG_OPT_OMIT_WERROR, LONG_OPT_CLIENT_OPTIONS, LONG_OPT_HELP, LONG_OPT_DISABLE_CACHE, LONG_OPT_POISON_CACHE, LONG_OPT_CLEAN_CACHE, LONG_OPT_COMPATIBLE, LONG_OPT_LDD, LONG_OPT_USE_SERVER, LONG_OPT_LIST_SERVERS, LONG_OPT_TRUST_SERVERS, LONG_OPT_ALL_MODULES, LONG_OPT_REMOTE, LONG_OPT_CHECK_VERSION, LONG_OPT_USE_SERVER_ON_ERROR, LONG_OPT_VERSION, LONG_OPT_REMOTE_PREFIX, LONG_OPT_TMPDIR, LONG_OPT_DOWNLOAD_DEBUGINFO, LONG_OPT_DUMP_PROBE_TYPES, LONG_OPT_PRIVILEGE, LONG_OPT_SUPPRESS_HANDLER_ERRORS, LONG_OPT_MODINFO, LONG_OPT_RLIMIT_AS, LONG_OPT_RLIMIT_CPU, LONG_OPT_RLIMIT_NPROC, LONG_OPT_RLIMIT_STACK, LONG_OPT_RLIMIT_FSIZE, LONG_OPT_SYSROOT, LONG_OPT_SYSENV, LONG_OPT_SUPPRESS_TIME_LIMITS, LONG_OPT_RUNTIME, LONG_OPT_RUNTIME_DYNINST, LONG_OPT_BENCHMARK_SDT_LOOPS, LONG_OPT_BENCHMARK_SDT_THREADS, LONG_OPT_COLOR_ERRS, }; // NB: when adding new options, consider very carefully whether they // should be restricted from stap clients (after --client-options)! #define STAP_SHORT_OPTIONS "hVvtp:I:e:o:R:r:a:m:kgPc:x:D:bs:uqwl:d:L:FS:B:J:jWG:" #define OWE5 "tter" #define OWE1 "uild-" #define OWE6 "fu-kb" #define OWE2 "i-kno" #define OWE4 "st" #define OWE3 "w-be" #define OMIT_WERROR_NAME OWE4 OWE6 OWE1 OWE2 OWE3 OWE5 extern struct option stap_long_options[]; #endif // CMDLINE_H systemtap-2.3/compile000077500000000000000000000072711217430427200147760ustar00rootroot00000000000000#! /bin/sh # Wrapper for compilers which do not understand `-c -o'. scriptversion=2009-10-06.20; # UTC # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009 Free Software # Foundation, Inc. # Written by Tom Tromey . # # 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, 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, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand `-c -o'. Remove `-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file `INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; esac ofile= cfile= eat= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as `compile cc -o foo foo.c'. # So we strip `-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no `-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # `.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use `[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: systemtap-2.3/config.guess000077500000000000000000001261461217430427200157430ustar00rootroot00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, # Inc. timestamp='2006-07-02' # This file 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, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm:riscos:*:*|arm:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep __LP64__ >/dev/null then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) case ${UNAME_MACHINE} in pc98) echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; x86:Interix*:[3456]*) echo i586-pc-interix${UNAME_RELEASE} exit ;; EM64T:Interix*:[3456]*) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; cris:Linux:*:*) echo cris-axis-linux-gnu exit ;; crisv32:Linux:*:*) echo crisv32-axis-linux-gnu exit ;; frv:Linux:*:*) echo frv-unknown-linux-gnu exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' /^CPU/{ s: ::g p }'`" test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips64 #undef mips64el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mips64el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips64 #else CPU= #endif #endif EOF eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' /^CPU/{ s: ::g p }'`" test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; or32:Linux:*:*) echo or32-unknown-linux-gnu exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) LIBC=gnu #else LIBC=gnuaout #endif #endif #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' /^LIBC/{ s: ::g p }'`" test x"${LIBC}" != x && { echo "${UNAME_MACHINE}-pc-linux-${LIBC}" exit } test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NSE-?:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: systemtap-2.3/config.in000066400000000000000000000111611217430427200152060ustar00rootroot00000000000000/* config.in. Generated from configure.ac by autoheader. */ /* Configuration/build date */ #undef DATE /* Define to 1 if translation of program messages to the user's native language is requested. */ #undef ENABLE_NLS /* make -P prologue-searching default */ #undef ENABLE_PROLOGUES /* Define to 1 to enable process.mark probes in stap, staprun, stapio. */ #undef ENABLE_SDT_PROBES /* Define to 1 if you have the avahi libraries. */ #undef HAVE_AVAHI /* Define to 1 if you have the header file. */ #undef HAVE_BOOST_SHARED_PTR_HPP /* Define to 1 if you have the header file. */ #undef HAVE_BPATCH_OBJECT_H /* Define to 1 if you have the header file. */ #undef HAVE_CRASH_DEFS_H /* Define if the GNU dcgettext() function is already present or preinstalled. */ #undef HAVE_DCGETTEXT /* Define to 1 if Dyninst is enabled */ #undef HAVE_DYNINST /* Define to 1 if libelf has elf_getshdrstrndx */ #undef HAVE_ELF_GETSHDRSTRNDX /* Define if the GNU gettext() function is already present or preinstalled. */ #undef HAVE_GETTEXT /* Define if you have the iconv() function and it works. */ #undef HAVE_ICONV /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Flag indicating that libHelperSDT.so is available (can be found in PKGLIBDIR) */ #undef HAVE_JAVA /* Define to 1 if you have the `dw' library (-ldw). */ #undef HAVE_LIBDW /* Define to 1 if you have the header file. */ #undef HAVE_LIBELF_H /* have librpm */ #undef HAVE_LIBRPM /* have librpmio */ #undef HAVE_LIBRPMIO /* Define to 1 if you have the 'sqlite3' library (-lsqlite3). */ #undef HAVE_LIBSQLITE3 /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the nss libraries. */ #undef HAVE_NSS /* Define to 1 if you have the `openat' function. */ #undef HAVE_OPENAT /* Define to 1 if you have the `ppoll' function. */ #undef HAVE_PPOLL /* Define to 1 if you have the SELinux libraries. */ #undef HAVE_SELINUX /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_TR1_MEMORY /* Define to 1 if you have the header file. */ #undef HAVE_TR1_UNORDERED_MAP /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if your C compiler doesn't accept -c and -o together. */ #undef NO_MINUS_C_MINUS_O /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* extra stap version code */ #undef STAP_EXTRA_VERSION /* configure prefix location */ #undef STAP_PREFIX /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # undef _GNU_SOURCE #endif /* Enable threading extensions on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # undef _POSIX_PTHREAD_SEMANTICS #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # undef _TANDEM_SOURCE #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # undef __EXTENSIONS__ #endif /* Version number of package */ #undef VERSION /* Enable large inode numbers on Mac OS X 10.5. */ #ifndef _DARWIN_USE_64_BIT_INODE # define _DARWIN_USE_64_BIT_INODE 1 #endif /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES /* Define to 1 if on MINIX. */ #undef _MINIX /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ #undef _POSIX_1_SOURCE /* Define to 1 if you need to in order for `stat' and other things to work. */ #undef _POSIX_SOURCE systemtap-2.3/config.rpath000077500000000000000000000440121217430427200157220ustar00rootroot00000000000000#! /bin/sh # Output a system dependent set of variables, describing how to set the # run time search path of shared libraries in an executable. # # Copyright 1996-2010 Free Software Foundation, Inc. # Taken from GNU libtool, 2001 # Originally by Gordon Matzigkeit , 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # # The first argument passed to this file is the canonical host specification, # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld # should be set by the caller. # # The set of defined variables is at the end of this script. # Known limitations: # - On IRIX 6.5 with CC="cc", the run time search patch must not be longer # than 256 bytes, otherwise the compiler driver will dump core. The only # known workaround is to choose shorter directory names for the build # directory and/or the installation directory. # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a shrext=.so host="$1" host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` # Code taken from libtool.m4's _LT_CC_BASENAME. for cc_temp in $CC""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` # Code taken from libtool.m4's _LT_COMPILER_PIC. wl= if test "$GCC" = yes; then wl='-Wl,' else case "$host_os" in aix*) wl='-Wl,' ;; darwin*) case $cc_basename in xlc*) wl='-Wl,' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) ;; hpux9* | hpux10* | hpux11*) wl='-Wl,' ;; irix5* | irix6* | nonstopux*) wl='-Wl,' ;; newsos6) ;; linux* | k*bsd*-gnu) case $cc_basename in ecc*) wl='-Wl,' ;; icc* | ifort*) wl='-Wl,' ;; lf95*) wl='-Wl,' ;; pgcc | pgf77 | pgf90) wl='-Wl,' ;; ccc*) wl='-Wl,' ;; como) wl='-lopt=' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) wl='-Wl,' ;; esac ;; esac ;; osf3* | osf4* | osf5*) wl='-Wl,' ;; rdos*) ;; solaris*) wl='-Wl,' ;; sunos4*) wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3*) wl='-Wl,' ;; sysv4*MP*) ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) wl='-Wl,' ;; unicos*) wl='-Wl,' ;; uts4*) ;; esac fi # Code taken from libtool.m4's _LT_LINKER_SHLIBS. hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no case "$host_os" in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. # Unlike libtool, we use -rpath here, not --rpath, since the documented # option of GNU ld is called -rpath, not --rpath. hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' case "$host_os" in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we cannot use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then : else ld_shlibs=no fi ;; interix[3-9]*) hardcode_direct=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; gnu* | linux* | k*bsd*-gnu) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; netbsd*) ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs=no elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' else ld_shlibs=no fi ;; esac ;; sunos4*) hardcode_direct=yes ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then hardcode_libdir_flag_spec= fi else case "$host_os" in aix3*) # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac fi hardcode_direct=yes hardcode_libdir_separator=':' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac fi # Begin _LT_AC_SYS_LIBPATH_AIX. echo 'int main () { return 0; }' > conftest.c ${CC} ${LDFLAGS} conftest.c -o conftest aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` fi if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib" fi rm -f conftest.c conftest # End _LT_AC_SYS_LIBPATH_AIX. if test "$aix_use_runtimelinking" = yes; then hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' else hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" fi fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; bsdi[45]*) ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' libext=lib ;; darwin* | rhapsody*) hardcode_direct=no if test "$GCC" = yes ; then : else case $cc_basename in xlc*) ;; *) ld_shlibs=no ;; esac fi ;; dgux*) hardcode_libdir_flag_spec='-L$libdir' ;; freebsd1*) ld_shlibs=no ;; freebsd2.2*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; freebsd2*) hardcode_direct=yes hardcode_minus_L=yes ;; freebsd* | dragonfly*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; hpux9*) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; hpux10*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no ;; *) hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; netbsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; newsos6) hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then hardcode_libdir_flag_spec='${wl}-rpath,$libdir' else case "$host_os" in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) hardcode_libdir_flag_spec='-R$libdir' ;; *) hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; osf3*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) if test "$GCC" = yes; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else # Both cc and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; solaris*) hardcode_libdir_flag_spec='-R$libdir' ;; sunos4*) hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes ;; sysv4) case $host_vendor in sni) hardcode_direct=yes # is this really true??? ;; siemens) hardcode_direct=no ;; motorola) hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac ;; sysv4.3*) ;; sysv4*MP*) if test -d /usr/nec; then ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) ;; sysv5* | sco3.2v5* | sco5v6*) hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator=':' ;; uts4*) hardcode_libdir_flag_spec='-L$libdir' ;; *) ld_shlibs=no ;; esac fi # Check dynamic linker characteristics # Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER. # Unlike libtool.m4, here we don't care about _all_ names of the library, but # only about the one the linker finds when passed -lNAME. This is the last # element of library_names_spec in libtool.m4, or possibly two of them if the # linker has special search rules. library_names_spec= # the last element of library_names_spec in libtool.m4 libname_spec='lib$name' case "$host_os" in aix3*) library_names_spec='$libname.a' ;; aix[4-9]*) library_names_spec='$libname$shrext' ;; amigaos*) library_names_spec='$libname.a' ;; beos*) library_names_spec='$libname$shrext' ;; bsdi[45]*) library_names_spec='$libname$shrext' ;; cygwin* | mingw* | pw32* | cegcc*) shrext=.dll library_names_spec='$libname.dll.a $libname.lib' ;; darwin* | rhapsody*) shrext=.dylib library_names_spec='$libname$shrext' ;; dgux*) library_names_spec='$libname$shrext' ;; freebsd1*) ;; freebsd* | dragonfly*) case "$host_os" in freebsd[123]*) library_names_spec='$libname$shrext$versuffix' ;; *) library_names_spec='$libname$shrext' ;; esac ;; gnu*) library_names_spec='$libname$shrext' ;; hpux9* | hpux10* | hpux11*) case $host_cpu in ia64*) shrext=.so ;; hppa*64*) shrext=.sl ;; *) shrext=.sl ;; esac library_names_spec='$libname$shrext' ;; interix[3-9]*) library_names_spec='$libname$shrext' ;; irix5* | irix6* | nonstopux*) library_names_spec='$libname$shrext' case "$host_os" in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; *) libsuff= shlibsuff= ;; esac ;; esac ;; linux*oldld* | linux*aout* | linux*coff*) ;; linux* | k*bsd*-gnu) library_names_spec='$libname$shrext' ;; knetbsd*-gnu) library_names_spec='$libname$shrext' ;; netbsd*) library_names_spec='$libname$shrext' ;; newsos6) library_names_spec='$libname$shrext' ;; nto-qnx*) library_names_spec='$libname$shrext' ;; openbsd*) library_names_spec='$libname$shrext$versuffix' ;; os2*) libname_spec='$name' shrext=.dll library_names_spec='$libname.a' ;; osf3* | osf4* | osf5*) library_names_spec='$libname$shrext' ;; rdos*) ;; solaris*) library_names_spec='$libname$shrext' ;; sunos4*) library_names_spec='$libname$shrext$versuffix' ;; sysv4 | sysv4.3*) library_names_spec='$libname$shrext' ;; sysv4*MP*) library_names_spec='$libname$shrext' ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) library_names_spec='$libname$shrext' ;; uts4*) library_names_spec='$libname$shrext' ;; esac sed_quote_subst='s/\(["`$\\]\)/\\\1/g' escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` shlibext=`echo "$shrext" | sed -e 's,^\.,,'` escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted GNU ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nios | nios2 \ | ns16k | ns32k \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | ubicom32 \ | v850 | v850e \ | we32k \ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | picochip) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze) basic_machine=microblaze-xilinx ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tic55x | c55x*) basic_machine=tic55x-unknown os=-coff ;; tic6x | c6x*) basic_machine=tic6x-unknown os=-coff ;; tile*) basic_machine=tile-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: systemtap-2.3/configure000077500000000000000000014001041217430427200153200ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for systemtap 2.3. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and $0: systemtap@sourceware.org about your system, including $0: any error possibly output before this message. Then $0: install a modern shell, or manually run the script $0: under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='systemtap' PACKAGE_TARNAME='systemtap' PACKAGE_VERSION='2.3' PACKAGE_STRING='systemtap 2.3' PACKAGE_BUGREPORT='systemtap@sourceware.org' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" gt_needs= enable_option_checking=no ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS subdirs STAP_PREFIX STAP_EXTRA_VERSION LOCALEDIR ENABLE_NLS HAVE_JAVA_FALSE HAVE_JAVA_TRUE JAVADIR have_jar have_javac HAVE_SELINUX_FALSE HAVE_SELINUX_TRUE selinux_LIBS selinux_CFLAGS support_section_question HAVE_DYNINST_FALSE HAVE_DYNINST_TRUE DYNINST_LDFLAGS DYNINST_CXXFLAGS CXXCPP DATE staprun_LIBS stap_LIBS elfutils_abs_srcdir BUILD_ELFUTILS_FALSE BUILD_ELFUTILS_TRUE HAVE_AVAHI_FALSE HAVE_AVAHI_TRUE avahi_LIBS avahi_CFLAGS BUILD_SERVER_FALSE BUILD_SERVER_TRUE HAVE_NSS_FALSE HAVE_NSS_TRUE nss_LIBS nss_CFLAGS PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG BUILD_PDFREFDOCS_FALSE BUILD_PDFREFDOCS_TRUE XMLTO_STRINGPARAM_FALSE XMLTO_STRINGPARAM_TRUE HAVE_FOP_FALSE HAVE_FOP_TRUE have_fop BUILD_REFDOCS_FALSE BUILD_REFDOCS_TRUE have_xmlto PUBLICAN_BRAND BUILD_PUBLICAN_FALSE BUILD_PUBLICAN_TRUE have_publican BUILD_DOCS_FALSE BUILD_DOCS_TRUE have_latex2html have_ps2pdf have_dvips have_latex HAVE_XVFB_FALSE HAVE_XVFB_TRUE have_xvfb BUILD_CRASHMOD_FALSE BUILD_CRASHMOD_TRUE staplog_CPPFLAGS BUILD_TRANSLATOR_FALSE BUILD_TRANSLATOR_TRUE sqlite3_LIBS PIECXXFLAGS PIECFLAGS PIELDFLAGS POSUB LTLIBINTL LIBINTL INTLLIBS LTLIBICONV LIBICONV XGETTEXT_EXTRA_OPTIONS MSGMERGE XGETTEXT_015 XGETTEXT GMSGFMT_015 MSGFMT_015 GMSGFMT MSGFMT GETTEXT_MACRO_VERSION USE_NLS RANLIB am__fastdepCXX_FALSE am__fastdepCXX_TRUE CXXDEPMODE ac_ct_CXX CXXFLAGS CXX LN_S EGREP GREP CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_os target_vendor target_cpu target host_os host_vendor host_cpu host build_os build_vendor build_cpu build target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_maintainer_mode enable_silent_rules enable_dependency_tracking enable_largefile enable_nls with_gnu_ld enable_rpath with_libiconv_prefix with_libintl_prefix enable_prologues enable_sdt_probes enable_ssp enable_pie enable_sqlite enable_translator enable_crash enable_docs enable_publican with_publican_brand enable_refdocs with_nss enable_server with_avahi with_rpm with_elfutils with_dyninst with_selinux with_java with_extra_version ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP CXX CXXFLAGS CCC PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR nss_CFLAGS nss_LIBS avahi_CFLAGS avahi_LIBS CXXCPP selinux_CFLAGS selinux_LIBS' ac_subdirs_all='testsuite' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures systemtap 2.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/systemtap] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] --target=TARGET configure for building compilers for TARGET [HOST] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of systemtap 2.3:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --disable-largefile omit support for large files --disable-nls do not use Native Language Support --disable-rpath do not hardcode runtime library paths --enable-prologues make -P prologue-searching default --disable-sdt-probes disable process.mark probes in stap, staprun, stapio --disable-ssp disable gcc stack-protector --enable-pie enable position-independent-executable --enable-sqlite build with sqlite support --disable-translator build only runtime utilities --enable-crash[=DIRECTORY] enable crash extension (default is disabled). Optional DIRECTORY is the path to the crash header file (needed if installed in a non-standard location). --enable-docs enable building documentation (default on if latex etc. found). --enable-publican enable building publican documentation guides (default on if publican found and other documentation built). --enable-refdocs enable building reference documentation (default on if xmlto etc. found and other documentation built). --enable-server enable building of stap-server (default on if nss etc. found). Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-gnu-ld assume the C compiler uses GNU ld default=no --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib --without-libiconv-prefix don't search for libiconv in includedir and libdir --with-libintl-prefix[=DIR] search for libintl in DIR/include and DIR/lib --without-libintl-prefix don't search for libintl in includedir and libdir --with-publican-brand=BRAND building publican documentation guides using given brand (defaults to "common"). --without-nss Do not use NSS even if present --without-avahi Do not use Avahi even if present --with-rpm query rpm database for missing debuginfos --with-elfutils=DIRECTORY find elfutils source code in DIRECTORY --with-dyninst=DIRECTORY find dyninst headers/libraries in DIRECTORY --without-selinux Do not use libselinux even if present --with-java=DIRECTORY Specify JDK directory to compile libHelperSDT.so against (default is /usr/lib/jvm/java) --with-extra-version=STRING Add STRING to stap -V version Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor CXX C++ compiler command CXXFLAGS C++ compiler flags PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path nss_CFLAGS C compiler flags for nss, overriding pkg-config nss_LIBS linker flags for nss, overriding pkg-config avahi_CFLAGS C compiler flags for avahi, overriding pkg-config avahi_LIBS linker flags for avahi, overriding pkg-config CXXCPP C++ preprocessor selinux_CFLAGS C compiler flags for selinux, overriding pkg-config selinux_LIBS linker flags for selinux, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF systemtap configure 2.3 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## --------------------------------------- ## ## Report this to systemtap@sourceware.org ## ## --------------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_cxx_try_cpp LINENO # ------------------------ # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_cpp # ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES # --------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_cxx_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## --------------------------------------- ## ## Report this to systemtap@sourceware.org ## ## --------------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_header_mongrel cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by systemtap $as_me 2.3, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi gt_needs="$gt_needs " # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 $as_echo_n "checking target system type... " >&6; } if ${ac_cv_target+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$target_alias" = x; then ac_cv_target=$ac_cv_host else ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 $as_echo "$ac_cv_target" >&6; } case $ac_cv_target in *-*-*) ;; *) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; esac target=$ac_cv_target ac_save_IFS=$IFS; IFS='-' set x $ac_cv_target shift target_cpu=$1 target_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: target_os=$* IFS=$ac_save_IFS case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac # The aliases save the names the user supplied, while $host etc. # will get canonicalized. test -n "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- am__api_version='1.12' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='systemtap' VERSION='2.3' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then : enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 $as_echo "$USE_MAINTAINER_MODE" >&6; } if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=0;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" if test "x$ac_cv_header_minix_config_h" = xyes; then : MINIX=yes else MINIX= fi if test "$MINIX" = yes; then $as_echo "#define _POSIX_SOURCE 1" >>confdefs.h $as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h $as_echo "#define _MINIX 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 $as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } if ${ac_cv_safe_to_define___extensions__+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # define __EXTENSIONS__ 1 $ac_includes_default int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_safe_to_define___extensions__=yes else ac_cv_safe_to_define___extensions__=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 $as_echo "$ac_cv_safe_to_define___extensions__" >&6; } test $ac_cv_safe_to_define___extensions__ = yes && $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h $as_echo "#define _ALL_SOURCE 1" >>confdefs.h $as_echo "#define _GNU_SOURCE 1" >>confdefs.h $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h mkdir_p="$MKDIR_P" case $mkdir_p in [\\/$]* | ?:[\\/]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CXX" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CXX_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 $as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc if test "x$CC" != xcc; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 $as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 $as_echo_n "checking whether cc understands -c and -o together... " >&6; } fi set dummy $CC; ac_cc=`$as_echo "$2" | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # We do the test twice because some compilers refuse to overwrite an # existing .o file with -o, though they will create one. ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -f conftest2.$ac_objext && { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then eval ac_cv_prog_cc_${ac_cc}_c_o=yes if test "x$CC" != xcc; then # Test first that cc exists at all. if { ac_try='cc -c conftest.$ac_ext >&5' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -f conftest2.$ac_objext && { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # cc works too. : else # cc exists but doesn't like -o. eval ac_cv_prog_cc_${ac_cc}_c_o=no fi fi fi else eval ac_cv_prog_cc_${ac_cc}_c_o=no fi rm -f core conftest* fi if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h fi # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o if test "$am_t" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi # Check whether --enable-largefile was given. if test "${enable_largefile+set}" = set; then : enableval=$enable_largefile; fi if test "$enable_largefile" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 $as_echo_n "checking for special C compiler options needed for large files... " >&6; } if ${ac_cv_sys_largefile_CC+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_sys_largefile_CC=no if test "$GCC" != yes; then ac_save_CC=$CC while :; do # IRIX 6.2 and later do not support large files by default, # so use the C compiler's -n32 option if that helps. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : break fi rm -f core conftest.err conftest.$ac_objext CC="$CC -n32" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_largefile_CC=' -n32'; break fi rm -f core conftest.err conftest.$ac_objext break done CC=$ac_save_CC rm -f conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 $as_echo "$ac_cv_sys_largefile_CC" >&6; } if test "$ac_cv_sys_largefile_CC" != no; then CC=$CC$ac_cv_sys_largefile_CC fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 $as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } if ${ac_cv_sys_file_offset_bits+:} false; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=64; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_file_offset_bits=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 $as_echo "$ac_cv_sys_file_offset_bits" >&6; } case $ac_cv_sys_file_offset_bits in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits _ACEOF ;; esac rm -rf conftest* if test $ac_cv_sys_file_offset_bits = unknown; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 $as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } if ${ac_cv_sys_large_files+:} false; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGE_FILES 1 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=1; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_large_files=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 $as_echo "$ac_cv_sys_large_files" >&6; } case $ac_cv_sys_large_files in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _LARGE_FILES $ac_cv_sys_large_files _ACEOF ;; esac rm -rf conftest* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5 $as_echo_n "checking whether NLS is requested... " >&6; } # Check whether --enable-nls was given. if test "${enable_nls+set}" = set; then : enableval=$enable_nls; USE_NLS=$enableval else USE_NLS=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 $as_echo "$USE_NLS" >&6; } GETTEXT_MACRO_VERSION=0.18 # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "msgfmt", so it can be a program name with args. set dummy msgfmt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_MSGFMT+:} false; then : $as_echo_n "(cached) " >&6 else case "$MSGFMT" in [\\/]* | ?:[\\/]*) ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&5 if $ac_dir/$ac_word --statistics /dev/null >&5 2>&1 && (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then ac_cv_path_MSGFMT="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT=":" ;; esac fi MSGFMT="$ac_cv_path_MSGFMT" if test "$MSGFMT" != ":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 $as_echo "$MSGFMT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "gmsgfmt", so it can be a program name with args. set dummy gmsgfmt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_GMSGFMT+:} false; then : $as_echo_n "(cached) " >&6 else case $GMSGFMT in [\\/]* | ?:[\\/]*) ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" ;; esac fi GMSGFMT=$ac_cv_path_GMSGFMT if test -n "$GMSGFMT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 $as_echo "$GMSGFMT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; *) MSGFMT_015=$MSGFMT ;; esac case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; *) GMSGFMT_015=$GMSGFMT ;; esac # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "xgettext", so it can be a program name with args. set dummy xgettext; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_XGETTEXT+:} false; then : $as_echo_n "(cached) " >&6 else case "$XGETTEXT" in [\\/]* | ?:[\\/]*) ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&5 if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&5 2>&1 && (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then ac_cv_path_XGETTEXT="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" ;; esac fi XGETTEXT="$ac_cv_path_XGETTEXT" if test "$XGETTEXT" != ":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 $as_echo "$XGETTEXT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f messages.po case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; *) XGETTEXT_015=$XGETTEXT ;; esac # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "msgmerge", so it can be a program name with args. set dummy msgmerge; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_MSGMERGE+:} false; then : $as_echo_n "(cached) " >&6 else case "$MSGMERGE" in [\\/]* | ?:[\\/]*) ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&5 if $ac_dir/$ac_word --update -q /dev/null /dev/null >&5 2>&1; then ac_cv_path_MSGMERGE="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" test -z "$ac_cv_path_MSGMERGE" && ac_cv_path_MSGMERGE=":" ;; esac fi MSGMERGE="$ac_cv_path_MSGMERGE" if test "$MSGMERGE" != ":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 $as_echo "$MSGMERGE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$localedir" || localedir='${datadir}/locale' test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= ac_config_commands="$ac_config_commands po-directories" if test "X$prefix" = "XNONE"; then acl_final_prefix="$ac_default_prefix" else acl_final_prefix="$prefix" fi if test "X$exec_prefix" = "XNONE"; then acl_final_exec_prefix='${prefix}' else acl_final_exec_prefix="$exec_prefix" fi acl_save_prefix="$prefix" prefix="$acl_final_prefix" eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" prefix="$acl_save_prefix" # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by GCC" >&5 $as_echo_n "checking for ld used by GCC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | [A-Za-z]:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the path of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${acl_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then acl_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in *GNU* | *'with BFD'*) test "$with_gnu_ld" != no && break ;; *) test "$with_gnu_ld" != yes && break ;; esac fi done IFS="$ac_save_ifs" else acl_cv_path_LD="$LD" # Let the user override the test with a path. fi fi LD="$acl_cv_path_LD" if test -n "$LD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${acl_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU ld's only accept -v. case `$LD -v 2>&1 &5 $as_echo "$acl_cv_prog_gnu_ld" >&6; } with_gnu_ld=$acl_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shared library run path origin" >&5 $as_echo_n "checking for shared library run path origin... " >&6; } if ${acl_cv_rpath+:} false; then : $as_echo_n "(cached) " >&6 else CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh . ./conftest.sh rm -f ./conftest.sh acl_cv_rpath=done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acl_cv_rpath" >&5 $as_echo "$acl_cv_rpath" >&6; } wl="$acl_cv_wl" acl_libext="$acl_cv_libext" acl_shlibext="$acl_cv_shlibext" acl_libname_spec="$acl_cv_libname_spec" acl_library_names_spec="$acl_cv_library_names_spec" acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" acl_hardcode_direct="$acl_cv_hardcode_direct" acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" # Check whether --enable-rpath was given. if test "${enable_rpath+set}" = set; then : enableval=$enable_rpath; : else enable_rpath=yes fi acl_libdirstem=lib acl_libdirstem2= case "$host_os" in solaris*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit host" >&5 $as_echo_n "checking for 64-bit host... " >&6; } if ${gl_cv_solaris_64bit+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef _LP64 sixtyfour bits #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "sixtyfour bits" >/dev/null 2>&1; then : gl_cv_solaris_64bit=yes else gl_cv_solaris_64bit=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_solaris_64bit" >&5 $as_echo "$gl_cv_solaris_64bit" >&6; } if test $gl_cv_solaris_64bit = yes; then acl_libdirstem=lib/64 case "$host_cpu" in sparc*) acl_libdirstem2=lib/sparcv9 ;; i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; esac fi ;; *) searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` if test -n "$searchpath"; then acl_save_IFS="${IFS= }"; IFS=":" for searchdir in $searchpath; do if test -d "$searchdir"; then case "$searchdir" in */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; */../ | */.. ) # Better ignore directories of this form. They are misleading. ;; *) searchdir=`cd "$searchdir" && pwd` case "$searchdir" in */lib64 ) acl_libdirstem=lib64 ;; esac ;; esac fi done IFS="$acl_save_IFS" fi ;; esac test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" use_additional=yes acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" # Check whether --with-libiconv-prefix was given. if test "${with_libiconv_prefix+set}" = set; then : withval=$with_libiconv_prefix; if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" if test "$acl_libdirstem2" != "$acl_libdirstem" \ && ! test -d "$withval/$acl_libdirstem"; then additional_libdir="$withval/$acl_libdirstem2" fi fi fi fi LIBICONV= LTLIBICONV= INCICONV= LIBICONV_PREFIX= HAVE_LIBICONV= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='iconv ' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value" else : fi else found_dir= found_la= found_so= found_a= eval libname=\"$acl_libname_spec\" # typically: libname=lib$name if test -n "$acl_shlibext"; then shrext=".$acl_shlibext" # typically: shrext=.so else shrext= fi if test $use_additional = yes; then dir="$additional_libdir" if test -n "$acl_shlibext"; then if test -f "$dir/$libname$shrext"; then found_dir="$dir" found_so="$dir/$libname$shrext" else if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then ver=`(cd "$dir" && \ for f in "$libname$shrext".*; do echo "$f"; done \ | sed -e "s,^$libname$shrext\\\\.,," \ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ | sed 1q ) 2>/dev/null` if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then found_dir="$dir" found_so="$dir/$libname$shrext.$ver" fi else eval library_names=\"$acl_library_names_spec\" for f in $library_names; do if test -f "$dir/$f"; then found_dir="$dir" found_so="$dir/$f" break fi done fi fi fi if test "X$found_dir" = "X"; then if test -f "$dir/$libname.$acl_libext"; then found_dir="$dir" found_a="$dir/$libname.$acl_libext" fi fi if test "X$found_dir" != "X"; then if test -f "$dir/$libname.la"; then found_la="$dir/$libname.la" fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` if test -n "$acl_shlibext"; then if test -f "$dir/$libname$shrext"; then found_dir="$dir" found_so="$dir/$libname$shrext" else if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then ver=`(cd "$dir" && \ for f in "$libname$shrext".*; do echo "$f"; done \ | sed -e "s,^$libname$shrext\\\\.,," \ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ | sed 1q ) 2>/dev/null` if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then found_dir="$dir" found_so="$dir/$libname$shrext.$ver" fi else eval library_names=\"$acl_library_names_spec\" for f in $library_names; do if test -f "$dir/$f"; then found_dir="$dir" found_so="$dir/$f" break fi done fi fi fi if test "X$found_dir" = "X"; then if test -f "$dir/$libname.$acl_libext"; then found_dir="$dir" found_a="$dir/$libname.$acl_libext" fi fi if test "X$found_dir" != "X"; then if test -f "$dir/$libname.la"; then found_la="$dir/$libname.la" fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then if test "$enable_rpath" = no \ || test "X$found_dir" = "X/usr/$acl_libdirstem" \ || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" else haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi if test "$acl_hardcode_direct" = yes; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" else if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else haveit= for x in $LDFLAGS $LIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir" fi if test "$acl_hardcode_minus_L" != no; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" else LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a" else LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name" fi fi additional_includedir= case "$found_dir" in */$acl_libdirstem | */$acl_libdirstem/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` if test "$name" = 'iconv'; then LIBICONV_PREFIX="$basedir" fi additional_includedir="$basedir/include" ;; */$acl_libdirstem2 | */$acl_libdirstem2/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` if test "$name" = 'iconv'; then LIBICONV_PREFIX="$basedir" fi additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INCICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir" fi fi fi fi fi if test -n "$found_la"; then save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then haveit= if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) LIBICONV="${LIBICONV}${LIBICONV:+ }$dep" LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep" ;; esac done fi else LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$acl_hardcode_libdir_separator"; then alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" else for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then for found_dir in $ltrpathdirs; do LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir" done fi LIBINTL= LTLIBINTL= POSUB= case " $gt_needs " in *" need-formatstring-macros "*) gt_api_version=3 ;; *" need-ngettext "*) gt_api_version=2 ;; *) gt_api_version=1 ;; esac gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" if test "$USE_NLS" = "yes"; then gt_use_preinstalled_gnugettext=no if test $gt_api_version -ge 3; then gt_revision_test_code=' #ifndef __GNU_GETTEXT_SUPPORTED_REVISION #define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) #endif typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; ' else gt_revision_test_code= fi if test $gt_api_version -ge 2; then gt_expression_test_code=' + * ngettext ("", "", 0)' else gt_expression_test_code= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libc" >&5 $as_echo_n "checking for GNU gettext in libc... " >&6; } if eval \${$gt_func_gnugettext_libc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern int *_nl_domain_bindings; int main () { bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$gt_func_gnugettext_libc=yes" else eval "$gt_func_gnugettext_libc=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$gt_func_gnugettext_libc { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then am_save_CPPFLAGS="$CPPFLAGS" for element in $INCICONV; do haveit= for x in $CPPFLAGS; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5 $as_echo_n "checking for iconv... " >&6; } if ${am_cv_func_iconv+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : am_cv_func_iconv=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$am_cv_func_iconv" != yes; then am_save_LIBS="$LIBS" LIBS="$LIBS $LIBICONV" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : am_cv_lib_iconv=yes am_cv_func_iconv=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$am_save_LIBS" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5 $as_echo "$am_cv_func_iconv" >&6; } if test "$am_cv_func_iconv" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working iconv" >&5 $as_echo_n "checking for working iconv... " >&6; } if ${am_cv_func_iconv_works+:} false; then : $as_echo_n "(cached) " >&6 else am_save_LIBS="$LIBS" if test $am_cv_lib_iconv = yes; then LIBS="$LIBS $LIBICONV" fi if test "$cross_compiling" = yes; then : case "$host_os" in aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; *) am_cv_func_iconv_works="guessing yes" ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { /* Test against AIX 5.1 bug: Failures are not distinguishable from successful returns. */ { iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); if (cd_utf8_to_88591 != (iconv_t)(-1)) { static const char input[] = "\342\202\254"; /* EURO SIGN */ char buf[10]; const char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_utf8_to_88591, (char **) &inptr, &inbytesleft, &outptr, &outbytesleft); if (res == 0) return 1; } } /* Test against Solaris 10 bug: Failures are not distinguishable from successful returns. */ { iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); if (cd_ascii_to_88591 != (iconv_t)(-1)) { static const char input[] = "\263"; char buf[10]; const char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_ascii_to_88591, (char **) &inptr, &inbytesleft, &outptr, &outbytesleft); if (res == 0) return 1; } } #if 0 /* This bug could be worked around by the caller. */ /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ { iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); if (cd_88591_to_utf8 != (iconv_t)(-1)) { static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; char buf[50]; const char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_88591_to_utf8, (char **) &inptr, &inbytesleft, &outptr, &outbytesleft); if ((int)res > 0) return 1; } } #endif /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is provided. */ if (/* Try standardized names. */ iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) /* Try IRIX, OSF/1 names. */ && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) /* Try AIX names. */ && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) /* Try HP-UX names. */ && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) return 1; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : am_cv_func_iconv_works=yes else am_cv_func_iconv_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi LIBS="$am_save_LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv_works" >&5 $as_echo "$am_cv_func_iconv_works" >&6; } case "$am_cv_func_iconv_works" in *no) am_func_iconv=no am_cv_lib_iconv=no ;; *) am_func_iconv=yes ;; esac else am_func_iconv=no am_cv_lib_iconv=no fi if test "$am_func_iconv" = yes; then $as_echo "#define HAVE_ICONV 1" >>confdefs.h fi if test "$am_cv_lib_iconv" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5 $as_echo_n "checking how to link with libiconv... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5 $as_echo "$LIBICONV" >&6; } else CPPFLAGS="$am_save_CPPFLAGS" LIBICONV= LTLIBICONV= fi use_additional=yes acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" # Check whether --with-libintl-prefix was given. if test "${with_libintl_prefix+set}" = set; then : withval=$with_libintl_prefix; if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" if test "$acl_libdirstem2" != "$acl_libdirstem" \ && ! test -d "$withval/$acl_libdirstem"; then additional_libdir="$withval/$acl_libdirstem2" fi fi fi fi LIBINTL= LTLIBINTL= INCINTL= LIBINTL_PREFIX= HAVE_LIBINTL= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='intl ' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIBINTL="${LIBINTL}${LIBINTL:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$value" else : fi else found_dir= found_la= found_so= found_a= eval libname=\"$acl_libname_spec\" # typically: libname=lib$name if test -n "$acl_shlibext"; then shrext=".$acl_shlibext" # typically: shrext=.so else shrext= fi if test $use_additional = yes; then dir="$additional_libdir" if test -n "$acl_shlibext"; then if test -f "$dir/$libname$shrext"; then found_dir="$dir" found_so="$dir/$libname$shrext" else if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then ver=`(cd "$dir" && \ for f in "$libname$shrext".*; do echo "$f"; done \ | sed -e "s,^$libname$shrext\\\\.,," \ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ | sed 1q ) 2>/dev/null` if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then found_dir="$dir" found_so="$dir/$libname$shrext.$ver" fi else eval library_names=\"$acl_library_names_spec\" for f in $library_names; do if test -f "$dir/$f"; then found_dir="$dir" found_so="$dir/$f" break fi done fi fi fi if test "X$found_dir" = "X"; then if test -f "$dir/$libname.$acl_libext"; then found_dir="$dir" found_a="$dir/$libname.$acl_libext" fi fi if test "X$found_dir" != "X"; then if test -f "$dir/$libname.la"; then found_la="$dir/$libname.la" fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` if test -n "$acl_shlibext"; then if test -f "$dir/$libname$shrext"; then found_dir="$dir" found_so="$dir/$libname$shrext" else if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then ver=`(cd "$dir" && \ for f in "$libname$shrext".*; do echo "$f"; done \ | sed -e "s,^$libname$shrext\\\\.,," \ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ | sed 1q ) 2>/dev/null` if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then found_dir="$dir" found_so="$dir/$libname$shrext.$ver" fi else eval library_names=\"$acl_library_names_spec\" for f in $library_names; do if test -f "$dir/$f"; then found_dir="$dir" found_so="$dir/$f" break fi done fi fi fi if test "X$found_dir" = "X"; then if test -f "$dir/$libname.$acl_libext"; then found_dir="$dir" found_a="$dir/$libname.$acl_libext" fi fi if test "X$found_dir" != "X"; then if test -f "$dir/$libname.la"; then found_la="$dir/$libname.la" fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then if test "$enable_rpath" = no \ || test "X$found_dir" = "X/usr/$acl_libdirstem" \ || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" else haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi if test "$acl_hardcode_direct" = yes; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" else if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else haveit= for x in $LDFLAGS $LIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir" fi if test "$acl_hardcode_minus_L" != no; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" else LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_a" else LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir -l$name" fi fi additional_includedir= case "$found_dir" in */$acl_libdirstem | */$acl_libdirstem/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` if test "$name" = 'intl'; then LIBINTL_PREFIX="$basedir" fi additional_includedir="$basedir/include" ;; */$acl_libdirstem2 | */$acl_libdirstem2/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` if test "$name" = 'intl'; then LIBINTL_PREFIX="$basedir" fi additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INCINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then INCINTL="${INCINTL}${INCINTL:+ }-I$additional_includedir" fi fi fi fi fi if test -n "$found_la"; then save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then haveit= if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LIBINTL="${LIBINTL}${LIBINTL:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) LIBINTL="${LIBINTL}${LIBINTL:+ }$dep" LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$dep" ;; esac done fi else LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$acl_hardcode_libdir_separator"; then alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" else for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then for found_dir in $ltrpathdirs; do LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-R$found_dir" done fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libintl" >&5 $as_echo_n "checking for GNU gettext in libintl... " >&6; } if eval \${$gt_func_gnugettext_libintl+:} false; then : $as_echo_n "(cached) " >&6 else gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $INCINTL" gt_save_LIBS="$LIBS" LIBS="$LIBS $LIBINTL" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *); int main () { bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$gt_func_gnugettext_libintl=yes" else eval "$gt_func_gnugettext_libintl=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then LIBS="$LIBS $LIBICONV" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *); int main () { bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : LIBINTL="$LIBINTL $LIBICONV" LTLIBINTL="$LTLIBINTL $LTLIBICONV" eval "$gt_func_gnugettext_libintl=yes" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS" fi eval ac_res=\$$gt_func_gnugettext_libintl { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ && test "$PACKAGE" != gettext-runtime \ && test "$PACKAGE" != gettext-tools; }; then gt_use_preinstalled_gnugettext=yes else LIBINTL= LTLIBINTL= INCINTL= fi if test -n "$INTL_MACOSX_LIBS"; then if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" fi fi if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then $as_echo "#define ENABLE_NLS 1" >>confdefs.h else USE_NLS=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use NLS" >&5 $as_echo_n "checking whether to use NLS... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 $as_echo "$USE_NLS" >&6; } if test "$USE_NLS" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking where the gettext function comes from" >&5 $as_echo_n "checking where the gettext function comes from... " >&6; } if test "$gt_use_preinstalled_gnugettext" = "yes"; then if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then gt_source="external libintl" else gt_source="libc" fi else gt_source="included intl directory" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_source" >&5 $as_echo "$gt_source" >&6; } fi if test "$USE_NLS" = "yes"; then if test "$gt_use_preinstalled_gnugettext" = "yes"; then if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libintl" >&5 $as_echo_n "checking how to link with libintl... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBINTL" >&5 $as_echo "$LIBINTL" >&6; } for element in $INCINTL; do haveit= for x in $CPPFLAGS; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" fi done fi $as_echo "#define HAVE_GETTEXT 1" >>confdefs.h $as_echo "#define HAVE_DCGETTEXT 1" >>confdefs.h fi POSUB=po fi INTLLIBS="$LIBINTL" for ac_func in ppoll do : ac_fn_c_check_func "$LINENO" "ppoll" "ac_cv_func_ppoll" if test "x$ac_cv_func_ppoll" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PPOLL 1 _ACEOF fi done for ac_func in openat do : ac_fn_c_check_func "$LINENO" "openat" "ac_cv_func_openat" if test "x$ac_cv_func_openat" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_OPENAT 1 _ACEOF fi done if test "${enable_prologues+set}" != set; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if prologue searching should be the default" >&5 $as_echo_n "checking to see if prologue searching should be the default... " >&6; } if { echo '#if __i386__ == 1 && __GNUC__ < 4' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then enable_prologues=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi # Check whether --enable-prologues was given. if test "${enable_prologues+set}" = set; then : enableval=$enable_prologues; if test "$enable_prologues" = yes; then $as_echo "#define ENABLE_PROLOGUES /**/" >>confdefs.h fi fi if test "${enable_sdt_probes+set}" != set; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if sdt probes should be the default" >&5 $as_echo_n "checking to see if sdt probes should be the default... " >&6; } if { echo '#if __GNUC__ < 4' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then enable_sdt_probes=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi fi # Check whether --enable-sdt-probes was given. if test "${enable_sdt_probes+set}" = set; then : enableval=$enable_sdt_probes; fi if test "x$enable_sdt_probes" != xno; then : $as_echo "#define ENABLE_SDT_PROBES 1" >>confdefs.h fi # Check whether --enable-ssp was given. if test "${enable_ssp+set}" = set; then : enableval=$enable_ssp; fi if test "x$enable_ssp" != xno; then : save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS -Werror -fstack-protector-all -D_FORTIFY_SOURCE=2" CFLAGS="$CFLAGS -Werror -fstack-protector-all -D_FORTIFY_SOURCE=2" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int something (); _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: Compiling with gcc -fstack-protector-all et al." >&5 $as_echo "$as_me: Compiling with gcc -fstack-protector-all et al." >&6;} CFLAGS="$save_CFLAGS -fstack-protector-all -D_FORTIFY_SOURCE=2" CXXFLAGS="$save_CXXFLAGS -fstack-protector-all -D_FORTIFY_SOURCE=2" else { $as_echo "$as_me:${as_lineno-$LINENO}: Compiler does not support -fstack-protector-all et al." >&5 $as_echo "$as_me: Compiler does not support -fstack-protector-all et al." >&6;} CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi # Compiling without fPIE by default (see PR 9922) # Check whether --enable-pie was given. if test "${enable_pie+set}" = set; then : enableval=$enable_pie; fi if test "x$enable_pie" == xyes; then : PIECFLAGS='-fPIE' PIECXXFLAGS='-fPIE' PIELDFLAGS='-pie -Wl,-z,relro -Wl,-z,now' save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" save_LDFLAGS="$LDFLAGS" CFLAGS="$CFLAGS $PIECFLAGS" CXXFLAGS="$CXXFLAGS $PIECXXFLAGS" LDFLAGS="$LDFLAGS $PIELDFLAGS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ void main () {} _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: Compiling with gcc pie et al." >&5 $as_echo "$as_me: Compiling with gcc pie et al." >&6;} else { $as_echo "$as_me:${as_lineno-$LINENO}: Compiler does not support -pie et al." >&5 $as_echo "$as_me: Compiler does not support -pie et al." >&6;} PIECFLAGS="" PIECXXFLAGS="" PIELDFLAGS="" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS" LDFLAGS="$save_LDFLAGS" fi # Check whether --enable-sqlite was given. if test "${enable_sqlite+set}" = set; then : enableval=$enable_sqlite; else enable_sqlite=check fi sqlite3_LIBS= if test "x$enable_sqlite" != xno; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3_open in -lsqlite3" >&5 $as_echo_n "checking for sqlite3_open in -lsqlite3... " >&6; } if ${ac_cv_lib_sqlite3_sqlite3_open+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsqlite3 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sqlite3_open (); int main () { return sqlite3_open (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_sqlite3_sqlite3_open=yes else ac_cv_lib_sqlite3_sqlite3_open=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sqlite3_sqlite3_open" >&5 $as_echo "$ac_cv_lib_sqlite3_sqlite3_open" >&6; } if test "x$ac_cv_lib_sqlite3_sqlite3_open" = xyes; then : sqlite3_LIBS=-lsqlite3 $as_echo "#define HAVE_LIBSQLITE3 1" >>confdefs.h else if test "x$enable_sqlite" != xcheck; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "--enable-sqlite was given, but test for sqlite failed See \`config.log' for more details" "$LINENO" 5; } fi fi fi # Check whether --enable-translator was given. if test "${enable_translator+set}" = set; then : enableval=$enable_translator; else enable_translator="yes" fi if test "$enable_translator" == "yes"; then BUILD_TRANSLATOR_TRUE= BUILD_TRANSLATOR_FALSE='#' else BUILD_TRANSLATOR_TRUE='#' BUILD_TRANSLATOR_FALSE= fi # Check whether --enable-crash was given. if test "${enable_crash+set}" = set; then : enableval=$enable_crash; if test "$enable_crash" != "no"; then save_CPPFLAGS="$CPPFLAGS" if test "$enable_crash" != "yes"; then staplog_CPPFLAGS=-I$enable_crash CPPFLAGS="${staplog_CPPFLAGS} $CPPFLAGS" fi for ac_header in crash/defs.h do : ac_fn_c_check_header_compile "$LINENO" "crash/defs.h" "ac_cv_header_crash_defs_h" " #define NR_CPUS 256 " if test "x$ac_cv_header_crash_defs_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_CRASH_DEFS_H 1 _ACEOF else as_fn_error $? "cannot find required crash header (crash-devel may need to be installed)" "$LINENO" 5 fi done CPPFLAGS="$save_CPPFLAGS" fi else enable_crash="no" fi if test "$enable_crash" != "no"; then BUILD_CRASHMOD_TRUE= BUILD_CRASHMOD_FALSE='#' else BUILD_CRASHMOD_TRUE='#' BUILD_CRASHMOD_FALSE= fi building_docs="no" # Check whether --enable-docs was given. if test "${enable_docs+set}" = set; then : enableval=$enable_docs; enable_docs=$enableval else enable_docs="check" fi # Extract the first word of "xvfb-run", so it can be a program name with args. set dummy xvfb-run; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_have_xvfb+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$have_xvfb"; then ac_cv_prog_have_xvfb="$have_xvfb" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_have_xvfb="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_have_xvfb" && ac_cv_prog_have_xvfb="no" fi fi have_xvfb=$ac_cv_prog_have_xvfb if test -n "$have_xvfb"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_xvfb" >&5 $as_echo "$have_xvfb" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$have_xvfb" == "yes"; then HAVE_XVFB_TRUE= HAVE_XVFB_FALSE='#' else HAVE_XVFB_TRUE='#' HAVE_XVFB_FALSE= fi # Extract the first word of "latex", so it can be a program name with args. set dummy latex; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_have_latex+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$have_latex"; then ac_cv_prog_have_latex="$have_latex" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_have_latex="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_have_latex" && ac_cv_prog_have_latex="no" fi fi have_latex=$ac_cv_prog_have_latex if test -n "$have_latex"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_latex" >&5 $as_echo "$have_latex" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "dvips", so it can be a program name with args. set dummy dvips; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_have_dvips+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$have_dvips"; then ac_cv_prog_have_dvips="$have_dvips" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_have_dvips="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_have_dvips" && ac_cv_prog_have_dvips="no" fi fi have_dvips=$ac_cv_prog_have_dvips if test -n "$have_dvips"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_dvips" >&5 $as_echo "$have_dvips" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "ps2pdf", so it can be a program name with args. set dummy ps2pdf; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_have_ps2pdf+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$have_ps2pdf"; then ac_cv_prog_have_ps2pdf="$have_ps2pdf" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_have_ps2pdf="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_have_ps2pdf" && ac_cv_prog_have_ps2pdf="no" fi fi have_ps2pdf=$ac_cv_prog_have_ps2pdf if test -n "$have_ps2pdf"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_ps2pdf" >&5 $as_echo "$have_ps2pdf" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "latex2html", so it can be a program name with args. set dummy latex2html; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_have_latex2html+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$have_latex2html"; then ac_cv_prog_have_latex2html="$have_latex2html" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_have_latex2html="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_have_latex2html" && ac_cv_prog_have_latex2html="no" fi fi have_latex2html=$ac_cv_prog_have_latex2html if test -n "$have_latex2html"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_latex2html" >&5 $as_echo "$have_latex2html" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x${have_latex}${have_dvips}${have_ps2pdf}${have_latex2html}" != "xyesyesyesyes"; then if test "$enable_docs" == "yes"; then as_fn_error $? "cannot find all tools for building documentation" "$LINENO" 5 fi if test "$enable_docs" == "check"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: will not build documentation, cannot find all tools" >&5 $as_echo "$as_me: WARNING: will not build documentation, cannot find all tools" >&2;} fi fi if test "x${have_latex}${have_dvips}${have_ps2pdf}${have_latex2html}" == "xyesyesyesyes" -a "$enable_docs" != "no"; then building_docs="yes" fi if test "$building_docs" == "yes"; then BUILD_DOCS_TRUE= BUILD_DOCS_FALSE='#' else BUILD_DOCS_TRUE='#' BUILD_DOCS_FALSE= fi building_publican="no" # Check whether --enable-publican was given. if test "${enable_publican+set}" = set; then : enableval=$enable_publican; enable_publican=$enableval else enable_publican="check" fi if test "$building_docs" == "no" -a "$enable_publican" == "yes" ; then as_fn_error $? "must use --enable-docs with --enable-publican" "$LINENO" 5 fi # Extract the first word of "publican", so it can be a program name with args. set dummy publican; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_have_publican+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$have_publican"; then ac_cv_prog_have_publican="$have_publican" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_have_publican="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_have_publican" && ac_cv_prog_have_publican="no" fi fi have_publican=$ac_cv_prog_have_publican if test -n "$have_publican"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_publican" >&5 $as_echo "$have_publican" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$enable_publican" == "yes"; then if test "x${have_publican}" != "xyes"; then as_fn_error $? "cannot find publican for building publican guides" "$LINENO" 5 fi fi if test "x${have_publican}" == "xyes" -a "$enable_publican" != "no" -a "${building_docs}" == "yes"; then building_publican="yes" fi if test "$building_publican" == "yes"; then BUILD_PUBLICAN_TRUE= BUILD_PUBLICAN_FALSE='#' else BUILD_PUBLICAN_TRUE='#' BUILD_PUBLICAN_FALSE= fi publican_brand="common" # Check whether --with-publican-brand was given. if test "${with_publican_brand+set}" = set; then : withval=$with_publican_brand; publican_brand=$withval else publican_brand="common" fi PUBLICAN_BRAND=$publican_brand building_refdocs="no" # Check whether --enable-refdocs was given. if test "${enable_refdocs+set}" = set; then : enableval=$enable_refdocs; enable_refdocs=$enableval else enable_refdocs="check" fi if test "$building_docs" == "no" -a "$enable_refdocs" == "yes" ; then as_fn_error $? "must use --enable-docs with --enable-refdocs" "$LINENO" 5 fi # Extract the first word of "xmlto", so it can be a program name with args. set dummy xmlto; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_have_xmlto+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$have_xmlto"; then ac_cv_prog_have_xmlto="$have_xmlto" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_have_xmlto="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_have_xmlto" && ac_cv_prog_have_xmlto="no" fi fi have_xmlto=$ac_cv_prog_have_xmlto if test -n "$have_xmlto"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_xmlto" >&5 $as_echo "$have_xmlto" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$enable_refdocs" == "yes"; then if test "x${have_xmlto}" != "xyes"; then as_fn_error $? "cannot find xmlto for building reference documentation" "$LINENO" 5 fi fi if test "x${have_xmlto}" == "xyes" -a "$enable_refdocs" != "no" -a "${building_docs}" == "yes"; then building_refdocs="yes" fi if test "$building_refdocs" == "yes"; then BUILD_REFDOCS_TRUE= BUILD_REFDOCS_FALSE='#' else BUILD_REFDOCS_TRUE='#' BUILD_REFDOCS_FALSE= fi # Extract the first word of "fop", so it can be a program name with args. set dummy fop; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_have_fop+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$have_fop"; then ac_cv_prog_have_fop="$have_fop" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_have_fop="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_have_fop" && ac_cv_prog_have_fop="no" fi fi have_fop=$ac_cv_prog_have_fop if test -n "$have_fop"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_fop" >&5 $as_echo "$have_fop" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x${have_fop}" == "xyes"; then # Due to rhbz505364 / 830266, we must actually test-run fop, not just # hope that it works. { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if xmlto --with-fop actually works" >&5 $as_echo_n "checking to see if xmlto --with-fop actually works... " >&6; } if xmlto --with-fop pdf ${srcdir}/doc/SystemTap_Tapset_Reference/dummy-tapsets.xml >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: it's dead, Jim" >&5 $as_echo "it's dead, Jim" >&6; } have_fop="broken" fi rm -f dummy-tapsets.pdf fi if test "$have_fop" == "yes"; then HAVE_FOP_TRUE= HAVE_FOP_FALSE='#' else HAVE_FOP_TRUE='#' HAVE_FOP_FALSE= fi cat > conftest.xml << 'EOF' foo Logging Tapset log logging Description baz EOF if test "x${have_xmlto}" == "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xmlto --stringparam support" >&5 $as_echo_n "checking for xmlto --stringparam support... " >&6; } xmlto --stringparam man.authors.section.enabled=0 html-nochunks conftest.xml >/dev/null 2>&1 if test $? == 0; then have_xmlto_stringparam="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f conftest.html fi if test "$have_xmlto_stringparam" == "yes"; then XMLTO_STRINGPARAM_TRUE= XMLTO_STRINGPARAM_FALSE='#' else XMLTO_STRINGPARAM_TRUE='#' XMLTO_STRINGPARAM_FALSE= fi if test "x${building_refdocs}" == "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xmlto pdf support" >&5 $as_echo_n "checking for xmlto pdf support... " >&6; } # xmlto pdf may work *only* with --with-fop # XXX: To an extent this test is redundant in that the --with-fop test # already ran xmlto --with-fop pdf .... if test "x$have_fop" == "xyes"; then XMLTOPDF_FOP=--with-fop else XMLTOPDF_FOP= fi xmlto $XMLTOPDF_FOP pdf conftest.xml >& /dev/null if test $? == 0; then have_xmlto_pdf="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Not building reference documentation in PDF format" >&5 $as_echo "$as_me: WARNING: Not building reference documentation in PDF format" >&2;} fi rm -f conftest.pdf fi if test "$have_xmlto_pdf" == "yes"; then BUILD_PDFREFDOCS_TRUE= BUILD_PDFREFDOCS_FALSE='#' else BUILD_PDFREFDOCS_TRUE='#' BUILD_PDFREFDOCS_FALSE= fi rm -f conftest.xml # Check whether --with-nss was given. if test "${with_nss+set}" = set; then : withval=$with_nss; fi if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 $as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 $as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } PKG_CONFIG="" fi fi if test "x$with_nss" != "xno"; then : pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nss" >&5 $as_echo_n "checking for nss... " >&6; } if test -n "$nss_CFLAGS"; then pkg_cv_nss_CFLAGS="$nss_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"nss >= 3\""; } >&5 ($PKG_CONFIG --exists --print-errors "nss >= 3") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_nss_CFLAGS=`$PKG_CONFIG --cflags "nss >= 3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$nss_LIBS"; then pkg_cv_nss_LIBS="$nss_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"nss >= 3\""; } >&5 ($PKG_CONFIG --exists --print-errors "nss >= 3") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_nss_LIBS=`$PKG_CONFIG --libs "nss >= 3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then nss_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "nss >= 3" 2>&1` else nss_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "nss >= 3" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$nss_PKG_ERRORS" >&5 have_nss=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_nss=no else nss_CFLAGS=$pkg_cv_nss_CFLAGS nss_LIBS=$pkg_cv_nss_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } have_nss=yes $as_echo "#define HAVE_NSS 1" >>confdefs.h fi else have_nss=no fi if test "${have_nss}" = "yes"; then HAVE_NSS_TRUE= HAVE_NSS_FALSE='#' else HAVE_NSS_TRUE='#' HAVE_NSS_FALSE= fi # Check whether --enable-server was given. if test "${enable_server+set}" = set; then : enableval=$enable_server; enable_server=$enableval else enable_server="check" fi if test "$enable_server" != "no"; then if test "x${have_nss}" != "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: will not build systemtap compile server, cannot find nss headers" >&5 $as_echo "$as_me: WARNING: will not build systemtap compile server, cannot find nss headers" >&2;} fi fi if test "${have_nss}" == "yes" -a "$enable_server" != "no"; then BUILD_SERVER_TRUE= BUILD_SERVER_FALSE='#' else BUILD_SERVER_TRUE='#' BUILD_SERVER_FALSE= fi if test "${have_nss}" != "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: compile-server client functionality will be disabled, cannot find nss development files" >&5 $as_echo "$as_me: WARNING: compile-server client functionality will be disabled, cannot find nss development files" >&2;} fi # Check whether --with-avahi was given. if test "${with_avahi+set}" = set; then : withval=$with_avahi; fi if test "x$with_avahi" != "xno"; then : pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for avahi" >&5 $as_echo_n "checking for avahi... " >&6; } if test -n "$avahi_CFLAGS"; then pkg_cv_avahi_CFLAGS="$avahi_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"avahi-client\""; } >&5 ($PKG_CONFIG --exists --print-errors "avahi-client") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_avahi_CFLAGS=`$PKG_CONFIG --cflags "avahi-client" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$avahi_LIBS"; then pkg_cv_avahi_LIBS="$avahi_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"avahi-client\""; } >&5 ($PKG_CONFIG --exists --print-errors "avahi-client") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_avahi_LIBS=`$PKG_CONFIG --libs "avahi-client" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then avahi_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "avahi-client" 2>&1` else avahi_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "avahi-client" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$avahi_PKG_ERRORS" >&5 have_avahi=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_avahi=no else avahi_CFLAGS=$pkg_cv_avahi_CFLAGS avahi_LIBS=$pkg_cv_avahi_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } have_avahi=yes $as_echo "#define HAVE_AVAHI 1" >>confdefs.h fi else have_avahi=no fi if test "${have_avahi}" = "yes"; then HAVE_AVAHI_TRUE= HAVE_AVAHI_FALSE='#' else HAVE_AVAHI_TRUE='#' HAVE_AVAHI_FALSE= fi if test "${have_avahi}" != "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: some compile-server functionality will be restricted, cannot find avahi development files" >&5 $as_echo "$as_me: WARNING: some compile-server functionality will be restricted, cannot find avahi development files" >&2;} fi # Check whether --with-rpm was given. if test "${with_rpm+set}" = set; then : withval=$with_rpm; else with_rpm="auto" fi if test "$with_rpm" != "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rpmtsInitIterator in -lrpm" >&5 $as_echo_n "checking for rpmtsInitIterator in -lrpm... " >&6; } if ${ac_cv_lib_rpm_rpmtsInitIterator+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lrpm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char rpmtsInitIterator (); int main () { return rpmtsInitIterator (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_rpm_rpmtsInitIterator=yes else ac_cv_lib_rpm_rpmtsInitIterator=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rpm_rpmtsInitIterator" >&5 $as_echo "$ac_cv_lib_rpm_rpmtsInitIterator" >&6; } if test "x$ac_cv_lib_rpm_rpmtsInitIterator" = xyes; then : $as_echo "#define HAVE_LIBRPM 1" >>confdefs.h stap_LIBS="$stap_LIBS -lc -lrpm" have_librpm="yes" else have_librpm="no" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rpmFreeCrypto in -lrpmio" >&5 $as_echo_n "checking for rpmFreeCrypto in -lrpmio... " >&6; } if ${ac_cv_lib_rpmio_rpmFreeCrypto+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lrpmio $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char rpmFreeCrypto (); int main () { return rpmFreeCrypto (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_rpmio_rpmFreeCrypto=yes else ac_cv_lib_rpmio_rpmFreeCrypto=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rpmio_rpmFreeCrypto" >&5 $as_echo "$ac_cv_lib_rpmio_rpmFreeCrypto" >&6; } if test "x$ac_cv_lib_rpmio_rpmFreeCrypto" = xyes; then : $as_echo "#define HAVE_LIBRPMIO 1" >>confdefs.h stap_LIBS="$stap_LIBS -lc -lrpmio" have_librpmio="yes" else have_librpmio="no" fi if test "x$have_librpm" != "xyes" -a "$with_rpm" == "yes"; then as_fn_error $? "cannot find librpm" "$LINENO" 5 fi if test "x$have_librpmio" != "xyes" -a "$with_rpm" == "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot find librpmio" >&5 $as_echo "$as_me: WARNING: cannot find librpmio" >&2;} fi fi build_elfutils=no # Check whether --with-elfutils was given. if test "${with_elfutils+set}" = set; then : withval=$with_elfutils; case "$with_elfutils" in yes) as_fn_error $? "--with-elfutils requires an argument" "$LINENO" 5 ;; ''|no) ;; *) build_elfutils=yes ;; esac fi if test $build_elfutils = yes; then BUILD_ELFUTILS_TRUE= BUILD_ELFUTILS_FALSE='#' else BUILD_ELFUTILS_TRUE='#' BUILD_ELFUTILS_FALSE= fi elfutils_abs_srcdir=`if test $build_elfutils = yes; then : cd $with_elfutils && pwd fi` if test $enable_translator = yes; then if test $build_elfutils = no; then # Need libdwfl-capable recent elfutils http://elfutils.fedorahosted.org/ # On modern debian/ubuntu, libebl has been merged into libdw # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=457543 save_LIBS="$LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ebl_get_elfmachine in -lebl" >&5 $as_echo_n "checking for ebl_get_elfmachine in -lebl... " >&6; } if ${ac_cv_lib_ebl_ebl_get_elfmachine+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lebl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char ebl_get_elfmachine (); int main () { return ebl_get_elfmachine (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ebl_ebl_get_elfmachine=yes else ac_cv_lib_ebl_ebl_get_elfmachine=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ebl_ebl_get_elfmachine" >&5 $as_echo "$ac_cv_lib_ebl_ebl_get_elfmachine" >&6; } if test "x$ac_cv_lib_ebl_ebl_get_elfmachine" = xyes; then : ebl_LIBS=-lebl else ebl_LIBS= fi LIBS="$save_LIBS" save_LIBS="$LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dwfl_module_getsym in -ldw" >&5 $as_echo_n "checking for dwfl_module_getsym in -ldw... " >&6; } if ${ac_cv_lib_dw_dwfl_module_getsym+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldw -Wl,--start-group -ldw $ebl_LIBS -Wl,--end-group -lelf $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dwfl_module_getsym (); int main () { return dwfl_module_getsym (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dw_dwfl_module_getsym=yes else ac_cv_lib_dw_dwfl_module_getsym=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dw_dwfl_module_getsym" >&5 $as_echo "$ac_cv_lib_dw_dwfl_module_getsym" >&6; } if test "x$ac_cv_lib_dw_dwfl_module_getsym" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBDW 1 _ACEOF LIBS="-ldw $LIBS" else as_fn_error $? "missing elfutils development headers/libraries (install elfutils-devel, libebl-dev, libdw-dev and/or libebl-devel)" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dwarf_next_unit in -ldw" >&5 $as_echo_n "checking for dwarf_next_unit in -ldw... " >&6; } if ${ac_cv_lib_dw_dwarf_next_unit+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldw -Wl,--start-group -ldw $ebl_LIBS -Wl,--end-group -lelf $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dwarf_next_unit (); int main () { return dwarf_next_unit (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dw_dwarf_next_unit=yes else ac_cv_lib_dw_dwarf_next_unit=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dw_dwarf_next_unit" >&5 $as_echo "$ac_cv_lib_dw_dwarf_next_unit" >&6; } if test "x$ac_cv_lib_dw_dwarf_next_unit" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBDW 1 _ACEOF LIBS="-ldw $LIBS" else as_fn_error $? "elfutils, libdw too old, need 0.148+" "$LINENO" 5 fi stap_LIBS="$stap_LIBS -Wl,--start-group -ldw $ebl_LIBS -Wl,--end-group -lelf" LIBS="$save_LIBS" else # We built our own and stap_LDFLAGS points at the install. stap_LIBS="$stap_LIBS -Wl,--start-group -ldw -lebl -Wl,--end-group -lelf" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: stap will link $stap_LIBS" >&5 $as_echo "$as_me: stap will link $stap_LIBS" >&6;} # staprun has more modest libelf needs if test $build_elfutils = no; then for ac_header in libelf.h do : ac_fn_c_check_header_mongrel "$LINENO" "libelf.h" "ac_cv_header_libelf_h" "$ac_includes_default" if test "x$ac_cv_header_libelf_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBELF_H 1 _ACEOF fi done save_LIBS="$LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for elf_getshdrstrndx in -lelf" >&5 $as_echo_n "checking for elf_getshdrstrndx in -lelf... " >&6; } if ${ac_cv_lib_elf_elf_getshdrstrndx+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lelf $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char elf_getshdrstrndx (); int main () { return elf_getshdrstrndx (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_elf_elf_getshdrstrndx=yes else ac_cv_lib_elf_elf_getshdrstrndx=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_elf_elf_getshdrstrndx" >&5 $as_echo "$ac_cv_lib_elf_elf_getshdrstrndx" >&6; } if test "x$ac_cv_lib_elf_elf_getshdrstrndx" = xyes; then : $as_echo "#define HAVE_ELF_GETSHDRSTRNDX 1" >>confdefs.h staprun_LIBS="$staprun_LIBS -lelf" fi LIBS="$save_LIBS" else # We built our own and staprun_LDFLAGS points at the install. staprun_LIBS="$staprun_LIBS -lelf" fi { $as_echo "$as_me:${as_lineno-$LINENO}: staprun will link $staprun_LIBS" >&5 $as_echo "$as_me: staprun will link $staprun_LIBS" >&6;} date=`date +%Y-%m-%d` cat >>confdefs.h <<_ACEOF #define DATE "$date" _ACEOF DATE="$date" # Before PR4037, we used to arrange to pass CFLAGS+=-m64 for a staprun # being compiled on 32-bit userspace but running against 64-bit kernels. # This is no longer necessary. # Use tr1/unordered_map if available ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 $as_echo_n "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then if ${ac_cv_prog_CXXCPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 $as_echo "$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu for ac_header in tr1/unordered_map do : ac_fn_cxx_check_header_mongrel "$LINENO" "tr1/unordered_map" "ac_cv_header_tr1_unordered_map" "$ac_includes_default" if test "x$ac_cv_header_tr1_unordered_map" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_TR1_UNORDERED_MAP 1 _ACEOF fi done for ac_header in tr1/memory do : ac_fn_cxx_check_header_mongrel "$LINENO" "tr1/memory" "ac_cv_header_tr1_memory" "$ac_includes_default" if test "x$ac_cv_header_tr1_memory" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_TR1_MEMORY 1 _ACEOF fi done for ac_header in boost/shared_ptr.hpp do : ac_fn_cxx_check_header_mongrel "$LINENO" "boost/shared_ptr.hpp" "ac_cv_header_boost_shared_ptr_hpp" "$ac_includes_default" if test "x$ac_cv_header_boost_shared_ptr_hpp" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_BOOST_SHARED_PTR_HPP 1 _ACEOF fi done ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Check for Dyninst headers and libraries # Check whether --with-dyninst was given. if test "${with_dyninst+set}" = set; then : withval=$with_dyninst; fi case "$with_dyninst" in no) ;; ''|yes) # Try a simple-minded distro search DYNINST_CXXFLAGS="-I/usr/include/dyninst" DYNINST_LDFLAGS="-L/usr/lib64/dyninst -L/usr/lib/dyninst" # XXX both lib paths!?! ;; *) # Use paths in the user-specified prefix DYNINST_CXXFLAGS="-I$with_dyninst/include" DYNINST_LDFLAGS="-L$with_dyninst/lib/" # XXX need lib64 too? ;; esac if test "$with_dyninst" != "no"; then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu old_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $DYNINST_CXXFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking dyninst support" >&5 $as_echo "$as_me: checking dyninst support" >&6;} for ac_header in BPatch_object.h do : ac_fn_cxx_check_header_mongrel "$LINENO" "BPatch_object.h" "ac_cv_header_BPatch_object_h" "$ac_includes_default" if test "x$ac_cv_header_BPatch_object_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_BPATCH_OBJECT_H 1 _ACEOF $as_echo "#define HAVE_DYNINST 1" >>confdefs.h have_dyninst=yes { $as_echo "$as_me:${as_lineno-$LINENO}: dyninst support available" >&5 $as_echo "$as_me: dyninst support available" >&6;} fi done if test -n "$with_dyninst" -a "$have_dyninst" != "yes"; then as_fn_error $? "Dyninst does not appear to be usable" "$LINENO" 5 fi CPPFLAGS="$old_CPPFLAGS" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi if test "${have_dyninst}" = "yes"; then HAVE_DYNINST_TRUE= HAVE_DYNINST_FALSE='#' else HAVE_DYNINST_TRUE='#' HAVE_DYNINST_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for assembler .section \"?\" flags support" >&5 $as_echo_n "checking for assembler .section \"?\" flags support... " >&6; } if ${stap_cv_sectionq+:} false; then : $as_echo_n "(cached) " >&6 else old_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wa,--fatal-warnings" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ asm(".section .note.foo,\"?\",\"note\"\n" ".byte 1, 2, 3\n" ".previous\n" ".section .text,\"axG\",\"progbits\",foogroup,comdat\n" ".byte 1\n" ".pushsection .note.foo,\"?\",\"note\"\n" ".byte 4, 5, 6\n" ".popsection\n" ".byte 2\n"); _ACEOF if ac_fn_c_try_compile "$LINENO"; then : stap_cv_sectionq=yes else stap_cv_sectionq=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$old_CFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $stap_cv_sectionq" >&5 $as_echo "$stap_cv_sectionq" >&6; } support_section_question=0 if test $stap_cv_sectionq = yes; then support_section_question=1 fi ac_config_files="$ac_config_files includes/sys/sdt-config.h po/Makefile.in" if test $build_elfutils = yes -a $enable_translator = yes; then case "$with_elfutils" in /*) elfutils_srcdir="$with_elfutils" ;; *) elfutils_srcdir="../$with_elfutils" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: running ${elfutils_srcdir}/configure" >&5 $as_echo "$as_me: running ${elfutils_srcdir}/configure" >&6;} save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS -fgnu89-inline" CFLAGS="$CFLAGS -fgnu89-inline" gnu89_inline_flag="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int something (); _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: Compiling elfutils with gcc -fgnu89-inline" >&5 $as_echo "$as_me: Compiling elfutils with gcc -fgnu89-inline" >&6;} gnu89_inline_flag="-fgnu89-inline" else { $as_echo "$as_me:${as_lineno-$LINENO}: Compiler does not support -fgnu89-inline" >&5 $as_echo "$as_me: Compiler does not support -fgnu89-inline" >&6;} fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS" # Our libdw.so's libebl will look in $ORIGIN/../lib/... but that # $ORIGIN is where libdw.so resides, which is not where there is a ../lib. # Note that $libdir might be using a quoted use of $exec_prefix or $prefix. # So we must make sure to pass those settings to elfutils configure. elfutils_rpath="-Wl,--enable-new-dtags,-rpath,${libdir}/${PACKAGE_NAME}" here=`pwd` # Check whether this is a source release, or a source checkout. # We need --enable-maintainer-mode if it isn't a source release. # elfutils.spec is only distributed in source releases. if test -f ${elfutils_srcdir}/elfutils.spec; then need_maintainer_option="" else need_maintainer_option="--enable-maintainer-mode" fi (mkdir -p build-elfutils && cd build-elfutils && bash ${elfutils_srcdir}/configure --enable-libebl-subdir=${PACKAGE_NAME} \ --includedir="${here}/include-elfutils" \ --libdir="${here}/lib-elfutils" \ --exec-prefix="$exec_prefix" \ --prefix="$prefix" \ --enable-dwz \ ${need_maintainer_option} \ CFLAGS="${CFLAGS/-Wall/} $gnu89_inline_flag -fexceptions" \ LDFLAGS="$LDFLAGS $elfutils_rpath" && if test -f ${elfutils_srcdir}/config/version.h.in; then echo Found elfutils/version.h header... else echo elfutils/version.h header not found, need elfutils 0.142+... exit -1 fi ) if test $? != 0; then exit -1; fi fi # Check whether --with-selinux was given. if test "${with_selinux+set}" = set; then : withval=$with_selinux; fi if test "x$with_selinux" != "xno"; then : pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for selinux" >&5 $as_echo_n "checking for selinux... " >&6; } if test -n "$selinux_CFLAGS"; then pkg_cv_selinux_CFLAGS="$selinux_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libselinux\""; } >&5 ($PKG_CONFIG --exists --print-errors "libselinux") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_selinux_CFLAGS=`$PKG_CONFIG --cflags "libselinux" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$selinux_LIBS"; then pkg_cv_selinux_LIBS="$selinux_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libselinux\""; } >&5 ($PKG_CONFIG --exists --print-errors "libselinux") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_selinux_LIBS=`$PKG_CONFIG --libs "libselinux" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then selinux_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libselinux" 2>&1` else selinux_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libselinux" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$selinux_PKG_ERRORS" >&5 have_selinux=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_selinux=no else selinux_CFLAGS=$pkg_cv_selinux_CFLAGS selinux_LIBS=$pkg_cv_selinux_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } have_selinux=yes $as_echo "#define HAVE_SELINUX 1" >>confdefs.h fi else have_selinux=no fi if test "${have_selinux}" = "yes"; then HAVE_SELINUX_TRUE= HAVE_SELINUX_FALSE='#' else HAVE_SELINUX_TRUE='#' HAVE_SELINUX_FALSE= fi # Extract the first word of "javac", so it can be a program name with args. set dummy javac; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_have_javac+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$have_javac"; then ac_cv_prog_have_javac="$have_javac" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_have_javac="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_have_javac" && ac_cv_prog_have_javac="no" fi fi have_javac=$ac_cv_prog_have_javac if test -n "$have_javac"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_javac" >&5 $as_echo "$have_javac" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "jar", so it can be a program name with args. set dummy jar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_have_jar+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$have_jar"; then ac_cv_prog_have_jar="$have_jar" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_have_jar="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_have_jar" && ac_cv_prog_have_jar="no" fi fi have_jar=$ac_cv_prog_have_jar if test -n "$have_jar"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_jar" >&5 $as_echo "$have_jar" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$have_javac" != no -a "$have_jar" != no; then echo java found, will try to configure Byteman support # Check whether --with-java was given. if test "${with_java+set}" = set; then : withval=$with_java; else with_java=/usr/lib/jvm/java fi as_ac_File=`$as_echo "ac_cv_file_$with_java" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $with_java" >&5 $as_echo_n "checking for $with_java... " >&6; } if eval \${$as_ac_File+:} false; then : $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "$with_java"; then eval "$as_ac_File=yes" else eval "$as_ac_File=no" fi fi eval ac_res=\$$as_ac_File { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_File"\" = x"yes"; then : else with_java=no fi JAVADIR="${with_java}" # always needed to compile if test "$with_java" != "no"; then cat >>confdefs.h <<_ACEOF #define HAVE_JAVA "1" _ACEOF fi if test "$with_java" != "no"; then HAVE_JAVA_TRUE= HAVE_JAVA_FALSE='#' else HAVE_JAVA_TRUE='#' HAVE_JAVA_FALSE= fi else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: will not run per-method java probing, missing byteman or java requirements" >&5 $as_echo "$as_me: WARNING: will not run per-method java probing, missing byteman or java requirements" >&2;} if false; then HAVE_JAVA_TRUE= HAVE_JAVA_FALSE='#' else HAVE_JAVA_TRUE='#' HAVE_JAVA_FALSE= fi fi # java+byteman support ENABLE_NLS="$USE_NLS" localedir="$localedir" LOCALEDIR="$localedir" # Check whether --with-extra-version was given. if test "${with_extra_version+set}" = set; then : withval=$with_extra_version; fi if test "x$with_extra_version" != "xno"; then : stap_extra_version="$with_extra_version" { $as_echo "$as_me:${as_lineno-$LINENO}: Adding extra version $stap_extra_version" >&5 $as_echo "$as_me: Adding extra version $stap_extra_version" >&6;} else stap_extra_version="" fi cat >>confdefs.h <<_ACEOF #define STAP_EXTRA_VERSION "$stap_extra_version" _ACEOF STAP_EXTRA_VERSION="$stap_extra_version" stap_prefix=$prefix test "$stap_prefix" = NONE && stap_prefix=$ac_default_prefix cat >>confdefs.h <<_ACEOF #define STAP_PREFIX "$stap_prefix" _ACEOF STAP_PREFIX="$stap_prefix" ac_config_headers="$ac_config_headers config.h:config.in" ac_config_files="$ac_config_files Makefile doc/Makefile man/Makefile doc/beginners/Makefile doc/SystemTap_Tapset_Reference/Makefile man/stappaths.7 initscript/config.systemtap initscript/config.stap-server initscript/systemtap initscript/stap-server" subdirs="$subdirs testsuite" if test $enable_translator == "yes"; then ac_config_files="$ac_config_files run-stap" fi ac_config_files="$ac_config_files dtrace" ac_config_files="$ac_config_files stapdyn/Makefile" ac_config_files="$ac_config_files java/Makefile" ac_config_files="$ac_config_files java/stapbm" ac_config_files="$ac_config_files staprun/Makefile" ac_config_files="$ac_config_files staprun/run-staprun" ac_config_files="$ac_config_files re2c-migrate/Makefile" # Setup "shadow" directory doc/beginners that has everything setup for # publican in one directory (through directory links if necessary). # It would be nice to use AC_CONFIG_LINKS, but automake complains when # the src is a directory and not a file. ac_config_files="$ac_config_files doc/beginners/publican.cfg:doc/SystemTap_Beginners_Guide/publican.cfg.in" ac_config_commands="$ac_config_commands doc/beginners" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_TRANSLATOR_TRUE}" && test -z "${BUILD_TRANSLATOR_FALSE}"; then as_fn_error $? "conditional \"BUILD_TRANSLATOR\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_CRASHMOD_TRUE}" && test -z "${BUILD_CRASHMOD_FALSE}"; then as_fn_error $? "conditional \"BUILD_CRASHMOD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_XVFB_TRUE}" && test -z "${HAVE_XVFB_FALSE}"; then as_fn_error $? "conditional \"HAVE_XVFB\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_DOCS_TRUE}" && test -z "${BUILD_DOCS_FALSE}"; then as_fn_error $? "conditional \"BUILD_DOCS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_PUBLICAN_TRUE}" && test -z "${BUILD_PUBLICAN_FALSE}"; then as_fn_error $? "conditional \"BUILD_PUBLICAN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_REFDOCS_TRUE}" && test -z "${BUILD_REFDOCS_FALSE}"; then as_fn_error $? "conditional \"BUILD_REFDOCS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_FOP_TRUE}" && test -z "${HAVE_FOP_FALSE}"; then as_fn_error $? "conditional \"HAVE_FOP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${XMLTO_STRINGPARAM_TRUE}" && test -z "${XMLTO_STRINGPARAM_FALSE}"; then as_fn_error $? "conditional \"XMLTO_STRINGPARAM\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_PDFREFDOCS_TRUE}" && test -z "${BUILD_PDFREFDOCS_FALSE}"; then as_fn_error $? "conditional \"BUILD_PDFREFDOCS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_NSS_TRUE}" && test -z "${HAVE_NSS_FALSE}"; then as_fn_error $? "conditional \"HAVE_NSS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_SERVER_TRUE}" && test -z "${BUILD_SERVER_FALSE}"; then as_fn_error $? "conditional \"BUILD_SERVER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_AVAHI_TRUE}" && test -z "${HAVE_AVAHI_FALSE}"; then as_fn_error $? "conditional \"HAVE_AVAHI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_ELFUTILS_TRUE}" && test -z "${BUILD_ELFUTILS_FALSE}"; then as_fn_error $? "conditional \"BUILD_ELFUTILS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_DYNINST_TRUE}" && test -z "${HAVE_DYNINST_FALSE}"; then as_fn_error $? "conditional \"HAVE_DYNINST\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_SELINUX_TRUE}" && test -z "${HAVE_SELINUX_FALSE}"; then as_fn_error $? "conditional \"HAVE_SELINUX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_JAVA_TRUE}" && test -z "${HAVE_JAVA_FALSE}"; then as_fn_error $? "conditional \"HAVE_JAVA\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_JAVA_TRUE}" && test -z "${HAVE_JAVA_FALSE}"; then as_fn_error $? "conditional \"HAVE_JAVA\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by systemtap $as_me 2.3, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ systemtap config.status 2.3 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # Capture the value of obsolete ALL_LINGUAS because we need it to compute # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it # from automake < 1.5. eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' # Capture the value of LINGUAS because we need it to compute CATALOGS. LINGUAS="${LINGUAS-%UNSET%}" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "po-directories") CONFIG_COMMANDS="$CONFIG_COMMANDS po-directories" ;; "includes/sys/sdt-config.h") CONFIG_FILES="$CONFIG_FILES includes/sys/sdt-config.h" ;; "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h:config.in" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; "doc/beginners/Makefile") CONFIG_FILES="$CONFIG_FILES doc/beginners/Makefile" ;; "doc/SystemTap_Tapset_Reference/Makefile") CONFIG_FILES="$CONFIG_FILES doc/SystemTap_Tapset_Reference/Makefile" ;; "man/stappaths.7") CONFIG_FILES="$CONFIG_FILES man/stappaths.7" ;; "initscript/config.systemtap") CONFIG_FILES="$CONFIG_FILES initscript/config.systemtap" ;; "initscript/config.stap-server") CONFIG_FILES="$CONFIG_FILES initscript/config.stap-server" ;; "initscript/systemtap") CONFIG_FILES="$CONFIG_FILES initscript/systemtap" ;; "initscript/stap-server") CONFIG_FILES="$CONFIG_FILES initscript/stap-server" ;; "run-stap") CONFIG_FILES="$CONFIG_FILES run-stap" ;; "dtrace") CONFIG_FILES="$CONFIG_FILES dtrace" ;; "stapdyn/Makefile") CONFIG_FILES="$CONFIG_FILES stapdyn/Makefile" ;; "java/Makefile") CONFIG_FILES="$CONFIG_FILES java/Makefile" ;; "java/stapbm") CONFIG_FILES="$CONFIG_FILES java/stapbm" ;; "staprun/Makefile") CONFIG_FILES="$CONFIG_FILES staprun/Makefile" ;; "staprun/run-staprun") CONFIG_FILES="$CONFIG_FILES staprun/run-staprun" ;; "re2c-migrate/Makefile") CONFIG_FILES="$CONFIG_FILES re2c-migrate/Makefile" ;; "doc/beginners/publican.cfg") CONFIG_FILES="$CONFIG_FILES doc/beginners/publican.cfg:doc/SystemTap_Beginners_Guide/publican.cfg.in" ;; "doc/beginners") CONFIG_COMMANDS="$CONFIG_COMMANDS doc/beginners" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "po-directories":C) for ac_file in $CONFIG_FILES; do # Support "outfile[:infile[:infile...]]" case "$ac_file" in *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; esac # PO directories have a Makefile.in generated from Makefile.in.in. case "$ac_file" in */Makefile.in) # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" case "$ac_given_srcdir" in .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; /*) top_srcdir="$ac_given_srcdir" ;; *) top_srcdir="$ac_dots$ac_given_srcdir" ;; esac # Treat a directory as a PO directory if and only if it has a # POTFILES.in file. This allows packages to have multiple PO # directories under different names or in different locations. if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then rm -f "$ac_dir/POTFILES" test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" POMAKEFILEDEPS="POTFILES.in" # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend # on $ac_dir but don't depend on user-specified configuration # parameters. if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then # The LINGUAS file contains the set of available languages. if test -n "$OBSOLETE_ALL_LINGUAS"; then test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" fi ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` # Hide the ALL_LINGUAS assigment from automake < 1.5. eval 'ALL_LINGUAS''=$ALL_LINGUAS_' POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" else # The set of available languages was given in configure.in. # Hide the ALL_LINGUAS assigment from automake < 1.5. eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' fi # Compute POFILES # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) # Compute UPDATEPOFILES # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) # Compute DUMMYPOFILES # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) # Compute GMOFILES # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) case "$ac_given_srcdir" in .) srcdirpre= ;; *) srcdirpre='$(srcdir)/' ;; esac POFILES= UPDATEPOFILES= DUMMYPOFILES= GMOFILES= for lang in $ALL_LINGUAS; do POFILES="$POFILES $srcdirpre$lang.po" UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" DUMMYPOFILES="$DUMMYPOFILES $lang.nop" GMOFILES="$GMOFILES $srcdirpre$lang.gmo" done # CATALOGS depends on both $ac_dir and the user's LINGUAS # environment variable. INST_LINGUAS= if test -n "$ALL_LINGUAS"; then for presentlang in $ALL_LINGUAS; do useit=no if test "%UNSET%" != "$LINGUAS"; then desiredlanguages="$LINGUAS" else desiredlanguages="$ALL_LINGUAS" fi for desiredlang in $desiredlanguages; do # Use the presentlang catalog if desiredlang is # a. equal to presentlang, or # b. a variant of presentlang (because in this case, # presentlang can be used as a fallback for messages # which are not translated in the desiredlang catalog). case "$desiredlang" in "$presentlang"*) useit=yes;; esac done if test $useit = yes; then INST_LINGUAS="$INST_LINGUAS $presentlang" fi done fi CATALOGS= if test -n "$INST_LINGUAS"; then for lang in $INST_LINGUAS; do CATALOGS="$CATALOGS $lang.gmo" done fi test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do if test -f "$f"; then case "$f" in *.orig | *.bak | *~) ;; *) cat "$f" >> "$ac_dir/Makefile" ;; esac fi done fi ;; esac done ;; "run-stap":F) chmod +x run-stap ;; "dtrace":F) chmod +x dtrace ;; "java/stapbm":F) chmod +x java/stapbm ;; "staprun/run-staprun":F) chmod +x staprun/run-staprun ;; "doc/beginners":C) rm -f $ac_abs_top_builddir/doc/beginners/en-US $ac_abs_top_builddir/doc/beginners/build/en-US/testsuite && mkdir -p $ac_abs_top_builddir/doc/beginners/build/en-US && ln -s $ac_abs_top_srcdir/doc/SystemTap_Beginners_Guide/en-US $ac_abs_top_builddir/doc/beginners/en-US && ln -s $ac_abs_top_srcdir/testsuite $ac_abs_top_builddir/doc/beginners/build/en-US/testsuite ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi # # CONFIG_SUBDIRS section. # if test "$no_recursion" != yes; then # Remove --cache-file, --srcdir, and --disable-option-checking arguments # so they do not pile up. ac_sub_configure_args= ac_prev= eval "set x $ac_configure_args" shift for ac_arg do if test -n "$ac_prev"; then ac_prev= continue fi case $ac_arg in -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \ | --c=*) ;; --config-cache | -C) ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) ;; --disable-option-checking) ;; *) case $ac_arg in *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append ac_sub_configure_args " '$ac_arg'" ;; esac done # Always prepend --prefix to ensure using the same prefix # in subdir configurations. ac_arg="--prefix=$prefix" case $ac_arg in *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args" # Pass --silent if test "$silent" = yes; then ac_sub_configure_args="--silent $ac_sub_configure_args" fi # Always prepend --disable-option-checking to silence warnings, since # different subdirs can have different --enable and --with options. ac_sub_configure_args="--disable-option-checking $ac_sub_configure_args" ac_popdir=`pwd` for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue # Do not complain, so a configure script can configure whichever # parts of a large source tree are present. test -d "$srcdir/$ac_dir" || continue ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)" $as_echo "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5 $as_echo "$ac_msg" >&6 as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" # Check for guested configure; otherwise get Cygnus style configure. if test -f "$ac_srcdir/configure.gnu"; then ac_sub_configure=$ac_srcdir/configure.gnu elif test -f "$ac_srcdir/configure"; then ac_sub_configure=$ac_srcdir/configure elif test -f "$ac_srcdir/configure.in"; then # This should be Cygnus configure. ac_sub_configure=$ac_aux_dir/configure else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5 $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} ac_sub_configure= fi # The recursion is here. if test -n "$ac_sub_configure"; then # Make the cache file name correct relative to the subdirectory. case $cache_file in [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;; *) # Relative name. ac_sub_cache_file=$ac_top_build_prefix$cache_file ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 $as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} # The eval makes quoting arguments work. eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \ --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" || as_fn_error $? "$ac_sub_configure failed for $ac_dir" "$LINENO" 5 fi cd "$ac_popdir" done fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi if test "${prefix}" = "/usr/local"; then { $as_echo "$as_me:${as_lineno-$LINENO}: " >&5 $as_echo "$as_me: " >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: For a private or temporary build of systemtap, we recommend" >&5 $as_echo "$as_me: For a private or temporary build of systemtap, we recommend" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: configuring with a prefix. For example, try" >&5 $as_echo "$as_me: configuring with a prefix. For example, try" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: $0 $ac_configure_args --prefix=$HOME/systemtap-${PACKAGE_VERSION}-$$" >&5 $as_echo "$as_me: $0 $ac_configure_args --prefix=$HOME/systemtap-${PACKAGE_VERSION}-$$" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: Running systemtap uninstalled, entirely out of the build tree," >&5 $as_echo "$as_me: Running systemtap uninstalled, entirely out of the build tree," >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: is not supported." >&5 $as_echo "$as_me: is not supported." >&6;} fi systemtap-2.3/configure.ac000066400000000000000000000622021217430427200157010ustar00rootroot00000000000000dnl configure.ac --- autoconf input file for systemtap dnl Process this file with autoconf to produce a configure script. AC_INIT([systemtap], 2.3, systemtap@sourceware.org, systemtap) dnl ^^^ see also NEWS, systemtap.spec, testsuite/configure.ac dnl doc/SystemTap_Beginners_Guide/en-US/Book_Info.xml dnl Get the target arch for libHelperSDT.so AC_CANONICAL_TARGET AC_PREREQ(2.63) dnl We don't maintain a ChangeLog, which makes us non-GNU -> foreign. AM_INIT_AUTOMAKE([no-dist foreign]) AM_MAINTAINER_MODE m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) AC_USE_SYSTEM_EXTENSIONS AM_PROG_MKDIR_P AC_SUBST(MKDIR_P) AC_PROG_LN_S AC_PROG_CC AC_PROG_CXX AC_PROG_CPP AM_PROG_CC_STDC AM_PROG_CC_C_O AC_PROG_RANLIB AC_OBJEXT AC_EXEEXT AC_PROG_INSTALL AC_PROG_MAKE_SET AC_SUBST(CFLAGS) AC_SUBST(CXXFLAGS) AC_SYS_LARGEFILE AM_GNU_GETTEXT(external) AM_GNU_GETTEXT_VERSION(0.17) AC_CHECK_FUNCS(ppoll) AC_CHECK_FUNCS(openat) dnl Handle the prologues option. dnl dnl If the user didn't specify --enable-prologues/--disable-prologues dnl and the x86 system has a version of gcc less than version 4, dnl automatically enable prologues. if test "${enable_prologues+set}" != set; then AC_MSG_CHECKING([to see if prologue searching should be the default]) if { echo '#if __i386__ == 1 && __GNUC__ < 4' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then enable_prologues=yes AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi fi AC_ARG_ENABLE([prologues], AS_HELP_STRING([--enable-prologues], [make -P prologue-searching default]), [ if test "$enable_prologues" = yes; then AC_DEFINE([ENABLE_PROLOGUES],[],[make -P prologue-searching default]) fi]) dnl Handle the disable-sdt-probes option. dnl dnl Default to --disable-sdt-probes if --enable-sdt-probes/--disable-prologues dnl was not specified and the gcc version is less than version 4, if test "${enable_sdt_probes+set}" != set; then AC_MSG_CHECKING([to see if sdt probes should be the default]) if { echo '#if __GNUC__ < 4' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then enable_sdt_probes=no AC_MSG_RESULT([no]) else AC_MSG_RESULT([yes]) fi fi AC_ARG_ENABLE([sdt-probes], [AS_HELP_STRING([--disable-sdt-probes], [disable process.mark probes in stap, staprun, stapio])]) AS_IF([test "x$enable_sdt_probes" != xno], [ AC_DEFINE([ENABLE_SDT_PROBES], [1], [Define to 1 to enable process.mark probes in stap, staprun, stapio.]) ]) AC_ARG_ENABLE([ssp], [AS_HELP_STRING([--disable-ssp], [disable gcc stack-protector])]) AS_IF([test "x$enable_ssp" != xno],[ save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS -Werror -fstack-protector-all -D_FORTIFY_SOURCE=2" CFLAGS="$CFLAGS -Werror -fstack-protector-all -D_FORTIFY_SOURCE=2" AC_COMPILE_IFELSE([AC_LANG_SOURCE([int something ();])], [ AC_MSG_NOTICE([Compiling with gcc -fstack-protector-all et al.]) CFLAGS="$save_CFLAGS -fstack-protector-all -D_FORTIFY_SOURCE=2" CXXFLAGS="$save_CXXFLAGS -fstack-protector-all -D_FORTIFY_SOURCE=2"],[ AC_MSG_NOTICE([Compiler does not support -fstack-protector-all et al.]) CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS"])]) dnl Link with gold if possible dnl but: https://bugzilla.redhat.com/show_bug.cgi?id=636603 dnl dnl AC_PATH_PROG(GOLD, [ld.gold], [no]) dnl if test "x$GOLD" != "xno" dnl then dnl mkdir -p Bdir dnl ln -sf $GOLD Bdir/ld dnl LDFLAGS="$LDFLAGS -B`pwd`/Bdir/" dnl AC_MSG_NOTICE([using ld.gold to link]) dnl fi # Compiling without fPIE by default (see PR 9922) AC_ARG_ENABLE([pie], [AS_HELP_STRING([--enable-pie], [enable position-independent-executable])]) AS_IF([test "x$enable_pie" == xyes],[ PIECFLAGS='-fPIE' PIECXXFLAGS='-fPIE' PIELDFLAGS='-pie -Wl,-z,relro -Wl,-z,now' save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" save_LDFLAGS="$LDFLAGS" CFLAGS="$CFLAGS $PIECFLAGS" CXXFLAGS="$CXXFLAGS $PIECXXFLAGS" LDFLAGS="$LDFLAGS $PIELDFLAGS" AC_LINK_IFELSE([AC_LANG_SOURCE([void main () {}])], [ AC_MSG_NOTICE([Compiling with gcc pie et al.]) ], [ AC_MSG_NOTICE([Compiler does not support -pie et al.]) PIECFLAGS="" PIECXXFLAGS="" PIELDFLAGS="" ]) CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS" LDFLAGS="$save_LDFLAGS" ]) AC_SUBST(PIELDFLAGS) AC_SUBST(PIECFLAGS) AC_SUBST(PIECXXFLAGS) dnl Handle optional sqlite support. If enabled/disabled by the user, dnl do the right thing. If not specified by the user, use it if dnl present. AC_ARG_ENABLE([sqlite], AS_HELP_STRING([--enable-sqlite], [build with sqlite support]), [], dnl ACTION-IF-GIVEN [enable_sqlite=check]) dnl ACTION-IF-NOT-GIVEN sqlite3_LIBS= AS_IF([test "x$enable_sqlite" != xno], [AC_CHECK_LIB([sqlite3], [sqlite3_open], [AC_SUBST([sqlite3_LIBS], [-lsqlite3]) AC_DEFINE([HAVE_LIBSQLITE3], [1], [Define to 1 if you have the 'sqlite3' library (-lsqlite3).])], [if test "x$enable_sqlite" != xcheck; then AC_MSG_FAILURE([--enable-sqlite was given, but test for sqlite failed]) fi])]) dnl Handle the option to only build runtime AC_ARG_ENABLE([translator], AS_HELP_STRING([--disable-translator], [build only runtime utilities]), [], [enable_translator="yes"]) AM_CONDITIONAL([BUILD_TRANSLATOR], [test "$enable_translator" == "yes"]) dnl Handle the option to build the crash extension AC_ARG_ENABLE([crash], AS_HELP_STRING([--enable-crash@<:@=DIRECTORY@:>@], [enable crash extension (default is disabled). Optional DIRECTORY is the path to the crash header file (needed if installed in a non-standard location).]), [if test "$enable_crash" != "no"; then dnl Handle custom install dir (if needed) save_CPPFLAGS="$CPPFLAGS" if test "$enable_crash" != "yes"; then staplog_CPPFLAGS=-I$enable_crash CPPFLAGS="${staplog_CPPFLAGS} $CPPFLAGS" AC_SUBST([staplog_CPPFLAGS]) fi AC_CHECK_HEADERS([crash/defs.h], [], [AC_MSG_ERROR([cannot find required crash header (crash-devel may need to be installed)])], [ #define NR_CPUS 256 ]) CPPFLAGS="$save_CPPFLAGS" fi], [enable_crash="no"]) AM_CONDITIONAL([BUILD_CRASHMOD], [test "$enable_crash" != "no"]) dnl Handle the option to build the documentation building_docs="no" AC_ARG_ENABLE([docs], AS_HELP_STRING([--enable-docs], [enable building documentation (default on if latex etc. found).]), [enable_docs=$enableval], [enable_docs="check"]) AC_CHECK_PROG(have_xvfb, xvfb-run, yes, no) AM_CONDITIONAL([HAVE_XVFB], [test "$have_xvfb" == "yes"]) AC_CHECK_PROG(have_latex, latex, yes, no) AC_CHECK_PROG(have_dvips, dvips, yes, no) AC_CHECK_PROG(have_ps2pdf, ps2pdf, yes, no) AC_CHECK_PROG(have_latex2html, latex2html, yes, no) if test "x${have_latex}${have_dvips}${have_ps2pdf}${have_latex2html}" != "xyesyesyesyes"; then if test "$enable_docs" == "yes"; then AC_MSG_ERROR([cannot find all tools for building documentation]) fi if test "$enable_docs" == "check"; then AC_MSG_WARN([will not build documentation, cannot find all tools]) fi fi if test "x${have_latex}${have_dvips}${have_ps2pdf}${have_latex2html}" == "xyesyesyesyes" -a "$enable_docs" != "no"; then building_docs="yes" fi AM_CONDITIONAL([BUILD_DOCS], [test "$building_docs" == "yes"]) dnl Handle the options to build the publican options building_publican="no" AC_ARG_ENABLE([publican], AS_HELP_STRING([--enable-publican], [enable building publican documentation guides (default on if publican found and other documentation built).]), [enable_publican=$enableval], [enable_publican="check"]) if test "$building_docs" == "no" -a "$enable_publican" == "yes" ; then AC_MSG_ERROR([must use --enable-docs with --enable-publican]) fi AC_CHECK_PROG(have_publican, publican, yes, no) if test "$enable_publican" == "yes"; then if test "x${have_publican}" != "xyes"; then AC_MSG_ERROR([cannot find publican for building publican guides]) fi fi if test "x${have_publican}" == "xyes" -a "$enable_publican" != "no" -a "${building_docs}" == "yes"; then building_publican="yes" fi AM_CONDITIONAL([BUILD_PUBLICAN], [test "$building_publican" == "yes"]) publican_brand="common" AC_ARG_WITH([publican-brand], AS_HELP_STRING([--with-publican-brand=BRAND], [building publican documentation guides using given brand (defaults to "common").]), [publican_brand=$withval], [publican_brand="common"]) PUBLICAN_BRAND=$publican_brand AC_SUBST(PUBLICAN_BRAND) dnl Handle the option to build the reference documentation building_refdocs="no" AC_ARG_ENABLE([refdocs], AS_HELP_STRING([--enable-refdocs], [enable building reference documentation (default on if xmlto etc. found and other documentation built).]), [enable_refdocs=$enableval], [enable_refdocs="check"]) if test "$building_docs" == "no" -a "$enable_refdocs" == "yes" ; then AC_MSG_ERROR([must use --enable-docs with --enable-refdocs]) fi AC_CHECK_PROG(have_xmlto, xmlto, yes, no) if test "$enable_refdocs" == "yes"; then if test "x${have_xmlto}" != "xyes"; then AC_MSG_ERROR([cannot find xmlto for building reference documentation]) fi fi if test "x${have_xmlto}" == "xyes" -a "$enable_refdocs" != "no" -a "${building_docs}" == "yes"; then building_refdocs="yes" fi AM_CONDITIONAL([BUILD_REFDOCS], [test "$building_refdocs" == "yes"]) AC_CHECK_PROG(have_fop, fop, yes, no) if test "x${have_fop}" == "xyes"; then # Due to rhbz505364 / 830266, we must actually test-run fop, not just # hope that it works. AC_MSG_CHECKING([to see if xmlto --with-fop actually works]) if xmlto --with-fop pdf ${srcdir}/doc/SystemTap_Tapset_Reference/dummy-tapsets.xml >/dev/null 2>&1; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([it's dead, Jim]) have_fop="broken" fi rm -f dummy-tapsets.pdf fi AM_CONDITIONAL([HAVE_FOP], [test "$have_fop" == "yes"]) dnl There is a strange bug in older versions of xmlto when generating pdf. dnl https://bugzilla.redhat.com/show_bug.cgi?id=526273 dnl So make sure to have a chapter title starting with L plus an refentry. dnl This will make sure the xmlto pdf support test fails on buggy versions. cat > conftest.xml << 'EOF' foo Logging Tapset log logging Description baz EOF if test "x${have_xmlto}" == "xyes"; then AC_MSG_CHECKING([for xmlto --stringparam support]) xmlto --stringparam man.authors.section.enabled=0 html-nochunks conftest.xml >/dev/null 2>&1 if test $? == 0; then have_xmlto_stringparam="yes" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi rm -f conftest.html fi AM_CONDITIONAL([XMLTO_STRINGPARAM], [test "$have_xmlto_stringparam" == "yes"]) if test "x${building_refdocs}" == "xyes"; then AC_MSG_CHECKING([for xmlto pdf support]) # xmlto pdf may work *only* with --with-fop # XXX: To an extent this test is redundant in that the --with-fop test # already ran xmlto --with-fop pdf .... if test "x$have_fop" == "xyes"; then XMLTOPDF_FOP=--with-fop else XMLTOPDF_FOP= fi xmlto $XMLTOPDF_FOP pdf conftest.xml >& /dev/null if test $? == 0; then have_xmlto_pdf="yes" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) AC_MSG_WARN([Not building reference documentation in PDF format]) fi rm -f conftest.pdf fi AM_CONDITIONAL([BUILD_PDFREFDOCS], [test "$have_xmlto_pdf" == "yes"]) rm -f conftest.xml dnl See if we have the nss/nspr headers and libraries AC_ARG_WITH([nss], AS_HELP_STRING([--without-nss], [Do not use NSS even if present])) AS_IF([test "x$with_nss" != "xno"], [ PKG_CHECK_MODULES([nss], [nss >= 3], [have_nss=yes AC_DEFINE([HAVE_NSS], [1], [Define to 1 if you have the nss libraries.]) ], [have_nss=no]) ], [have_nss=no]) AM_CONDITIONAL([HAVE_NSS], [test "${have_nss}" = "yes"]) dnl Handle the option to build the compile server. AC_ARG_ENABLE([server], AS_HELP_STRING([--enable-server], [enable building of stap-server (default on if nss etc. found).]), [enable_server=$enableval], [enable_server="check"]) if test "$enable_server" != "no"; then dnl See if we have enough libraries and tools to build the compile server if test "x${have_nss}" != "xyes"; then AC_MSG_WARN([will not build systemtap compile server, cannot find nss headers]) fi fi AM_CONDITIONAL([BUILD_SERVER], [test "${have_nss}" == "yes" -a "$enable_server" != "no"]) if test "${have_nss}" != "yes"; then AC_MSG_WARN([compile-server client functionality will be disabled, cannot find nss development files]) fi dnl See if we have the avahi libraries and headers AC_ARG_WITH([avahi], AS_HELP_STRING([--without-avahi], [Do not use Avahi even if present])) AS_IF([test "x$with_avahi" != "xno"], [ PKG_CHECK_MODULES([avahi], [avahi-client], [have_avahi=yes AC_DEFINE([HAVE_AVAHI], [1], [Define to 1 if you have the avahi libraries.]) ], [have_avahi=no]) ], [have_avahi=no]) AM_CONDITIONAL([HAVE_AVAHI], [test "${have_avahi}" = "yes"]) if test "${have_avahi}" != "yes"; then AC_MSG_WARN([some compile-server functionality will be restricted, cannot find avahi development files]) fi dnl Look for librpm. AC_ARG_WITH([rpm], [AS_HELP_STRING([--with-rpm], [query rpm database for missing debuginfos])], [], [with_rpm="auto"]) if test "$with_rpm" != "no"; then AC_CHECK_LIB(rpm, rpmtsInitIterator, [ AC_DEFINE([HAVE_LIBRPM],[1],[have librpm]) stap_LIBS="$stap_LIBS -lc -lrpm" have_librpm="yes"], [have_librpm="no"]) AC_CHECK_LIB(rpmio, rpmFreeCrypto, [ AC_DEFINE([HAVE_LIBRPMIO],[1],[have librpmio]) stap_LIBS="$stap_LIBS -lc -lrpmio" have_librpmio="yes"], [have_librpmio="no"]) if test "x$have_librpm" != "xyes" -a "$with_rpm" == "yes"; then AC_MSG_ERROR([cannot find librpm]) fi if test "x$have_librpmio" != "xyes" -a "$with_rpm" == "yes"; then AC_MSG_WARN([cannot find librpmio]) fi fi dnl Handle elfutils. If '--with-elfutils=DIR' wasn't specified, used dnl the system's elfutils. build_elfutils=no AC_ARG_WITH([elfutils], AS_HELP_STRING([--with-elfutils=DIRECTORY], [find elfutils source code in DIRECTORY]), [ case "$with_elfutils" in yes) AC_MSG_ERROR([--with-elfutils requires an argument]) ;; ''|no) ;; *) build_elfutils=yes ;; esac]) AM_CONDITIONAL(BUILD_ELFUTILS, test $build_elfutils = yes) AC_SUBST(elfutils_abs_srcdir, `AS_IF([test $build_elfutils = yes], [cd $with_elfutils && pwd])`) if test $enable_translator = yes; then if test $build_elfutils = no; then # Need libdwfl-capable recent elfutils http://elfutils.fedorahosted.org/ # On modern debian/ubuntu, libebl has been merged into libdw # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=457543 save_LIBS="$LIBS" AC_CHECK_LIB(ebl, ebl_get_elfmachine,[ebl_LIBS=-lebl],[ebl_LIBS=]) LIBS="$save_LIBS" save_LIBS="$LIBS" AC_CHECK_LIB(dw, dwfl_module_getsym,[],[ AC_MSG_ERROR([missing elfutils development headers/libraries (install elfutils-devel, libebl-dev, libdw-dev and/or libebl-devel)])], [-Wl,--start-group -ldw $ebl_LIBS -Wl,--end-group -lelf]) AC_CHECK_LIB(dw, dwarf_next_unit,[],[ AC_MSG_ERROR([elfutils, libdw too old, need 0.148+])], [-Wl,--start-group -ldw $ebl_LIBS -Wl,--end-group -lelf]) stap_LIBS="$stap_LIBS -Wl,--start-group -ldw $ebl_LIBS -Wl,--end-group -lelf" LIBS="$save_LIBS" else # We built our own and stap_LDFLAGS points at the install. stap_LIBS="$stap_LIBS -Wl,--start-group -ldw -lebl -Wl,--end-group -lelf" fi fi AC_SUBST(stap_LIBS) AC_MSG_NOTICE([stap will link $stap_LIBS]) # staprun has more modest libelf needs if test $build_elfutils = no; then AC_CHECK_HEADERS([libelf.h]) save_LIBS="$LIBS" dnl this will only succeed with elfutils 0.142+ AC_CHECK_LIB(elf,elf_getshdrstrndx,[ AC_DEFINE([HAVE_ELF_GETSHDRSTRNDX],[1],[Define to 1 if libelf has elf_getshdrstrndx]) staprun_LIBS="$staprun_LIBS -lelf" ]) LIBS="$save_LIBS" else # We built our own and staprun_LDFLAGS points at the install. staprun_LIBS="$staprun_LIBS -lelf" fi AC_SUBST(staprun_LIBS) AC_MSG_NOTICE([staprun will link $staprun_LIBS]) dnl Plop in the build (configure) date date=`date +%Y-%m-%d` AC_DEFINE_UNQUOTED(DATE, "$date", [Configuration/build date]) AC_SUBST(DATE, "$date") # Before PR4037, we used to arrange to pass CFLAGS+=-m64 for a staprun # being compiled on 32-bit userspace but running against 64-bit kernels. # This is no longer necessary. # Use tr1/unordered_map if available AC_LANG_PUSH(C++) AC_CHECK_HEADERS([tr1/unordered_map]) AC_CHECK_HEADERS([tr1/memory]) AC_CHECK_HEADERS([boost/shared_ptr.hpp]) AC_LANG_POP(C++) # Check for Dyninst headers and libraries AC_ARG_WITH([dyninst], AS_HELP_STRING([--with-dyninst=DIRECTORY], [find dyninst headers/libraries in DIRECTORY])) case "$with_dyninst" in no) ;; ''|yes) # Try a simple-minded distro search DYNINST_CXXFLAGS="-I/usr/include/dyninst" DYNINST_LDFLAGS="-L/usr/lib64/dyninst -L/usr/lib/dyninst" # XXX both lib paths!?! ;; *) # Use paths in the user-specified prefix DYNINST_CXXFLAGS="-I$with_dyninst/include" DYNINST_LDFLAGS="-L$with_dyninst/lib/" # XXX need lib64 too? ;; esac if test "$with_dyninst" != "no"; then AC_LANG_PUSH(C++) old_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $DYNINST_CXXFLAGS" AC_MSG_NOTICE([checking dyninst support]) AC_CHECK_HEADERS([BPatch_object.h], [ AC_SUBST(DYNINST_CXXFLAGS) AC_SUBST(DYNINST_LDFLAGS) AC_DEFINE([HAVE_DYNINST],[1],[Define to 1 if Dyninst is enabled]) have_dyninst=yes AC_MSG_NOTICE([dyninst support available])]) if test -n "$with_dyninst" -a "$have_dyninst" != "yes"; then AC_MSG_ERROR([Dyninst does not appear to be usable]) fi CPPFLAGS="$old_CPPFLAGS" AC_LANG_POP(C++) fi AM_CONDITIONAL([HAVE_DYNINST], [test "${have_dyninst}" = "yes"]) AC_CACHE_CHECK([for assembler .section "?" flags support], stap_cv_sectionq, [ old_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wa,--fatal-warnings" AC_COMPILE_IFELSE([AC_LANG_SOURCE([asm(".section .note.foo,\"?\",\"note\"\n" ".byte 1, 2, 3\n" ".previous\n" ".section .text,\"axG\",\"progbits\",foogroup,comdat\n" ".byte 1\n" ".pushsection .note.foo,\"?\",\"note\"\n" ".byte 4, 5, 6\n" ".popsection\n" ".byte 2\n");])], stap_cv_sectionq=yes, stap_cv_sectionq=no) CFLAGS="$old_CFLAGS"]) AC_SUBST(support_section_question) support_section_question=0 if test $stap_cv_sectionq = yes; then support_section_question=1 fi AC_CONFIG_FILES([includes/sys/sdt-config.h po/Makefile.in]) if test $build_elfutils = yes -a $enable_translator = yes; then case "$with_elfutils" in /*) elfutils_srcdir="$with_elfutils" ;; *) elfutils_srcdir="../$with_elfutils" ;; esac AC_MSG_NOTICE([running ${elfutils_srcdir}/configure]) save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS -fgnu89-inline" CFLAGS="$CFLAGS -fgnu89-inline" gnu89_inline_flag="" AC_COMPILE_IFELSE([AC_LANG_SOURCE([int something ();])], [ AC_MSG_NOTICE([Compiling elfutils with gcc -fgnu89-inline]) gnu89_inline_flag="-fgnu89-inline"],[ AC_MSG_NOTICE([Compiler does not support -fgnu89-inline])]) CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS" # Our libdw.so's libebl will look in $ORIGIN/../lib/... but that # $ORIGIN is where libdw.so resides, which is not where there is a ../lib. # Note that $libdir might be using a quoted use of $exec_prefix or $prefix. # So we must make sure to pass those settings to elfutils configure. elfutils_rpath="-Wl,--enable-new-dtags,-rpath,${libdir}/${PACKAGE_NAME}" here=`pwd` # Check whether this is a source release, or a source checkout. # We need --enable-maintainer-mode if it isn't a source release. # elfutils.spec is only distributed in source releases. if test -f ${elfutils_srcdir}/elfutils.spec; then need_maintainer_option="" else need_maintainer_option="--enable-maintainer-mode" fi (mkdir -p build-elfutils && cd build-elfutils && bash ${elfutils_srcdir}/configure --enable-libebl-subdir=${PACKAGE_NAME} \ --includedir="${here}/include-elfutils" \ --libdir="${here}/lib-elfutils" \ --exec-prefix="$exec_prefix" \ --prefix="$prefix" \ --enable-dwz \ ${need_maintainer_option} \ CFLAGS="${CFLAGS/-Wall/} $gnu89_inline_flag -fexceptions" \ LDFLAGS="$LDFLAGS $elfutils_rpath" && if test -f ${elfutils_srcdir}/config/version.h.in; then echo Found elfutils/version.h header... else echo elfutils/version.h header not found, need elfutils 0.142+... exit -1 fi ) if test $? != 0; then exit -1; fi fi dnl Optional libselinux support allows stapdyn to check dnl for booleans that would prevent Dyninst from working. AC_ARG_WITH([selinux], AS_HELP_STRING([--without-selinux], [Do not use libselinux even if present])) AS_IF([test "x$with_selinux" != "xno"], [ PKG_CHECK_MODULES([selinux], [libselinux], [have_selinux=yes AC_DEFINE([HAVE_SELINUX], [1], [Define to 1 if you have the SELinux libraries.]) ], [have_selinux=no]) ], [have_selinux=no]) AM_CONDITIONAL([HAVE_SELINUX], [test "${have_selinux}" = "yes"]) dnl Handle java+byteman support AC_CHECK_PROG(have_javac, javac, yes, no) AC_CHECK_PROG(have_jar, jar, yes, no) if test "$have_javac" != no -a "$have_jar" != no; then echo java found, will try to configure Byteman support AC_ARG_WITH([java], [AS_HELP_STRING([--with-java=DIRECTORY], [Specify JDK directory to compile libHelperSDT.so against (default is /usr/lib/jvm/java)])], [], [with_java=/usr/lib/jvm/java]) AC_CHECK_FILE([$with_java],[],[with_java=no]) AC_SUBST(JAVADIR, "${with_java}") # always needed to compile if test "$with_java" != "no"; then AC_DEFINE_UNQUOTED(HAVE_JAVA, "1", [Flag indicating that libHelperSDT.so is available (can be found in PKGLIBDIR)]) fi AM_CONDITIONAL([HAVE_JAVA], [test "$with_java" != "no"]) else AC_MSG_WARN([will not run per-method java probing, missing byteman or java requirements]) AM_CONDITIONAL([HAVE_JAVA],false) fi # java+byteman support AC_SUBST(ENABLE_NLS, "$USE_NLS") AC_SUBST(localedir, "$localedir") AC_SUBST(LOCALEDIR, "$localedir") AC_ARG_WITH([extra-version], AS_HELP_STRING([--with-extra-version=STRING], [Add STRING to stap -V version])) AS_IF([test "x$with_extra_version" != "xno"], [ stap_extra_version="$with_extra_version" AC_MSG_NOTICE([Adding extra version $stap_extra_version])], [ stap_extra_version=""]) AC_DEFINE_UNQUOTED(STAP_EXTRA_VERSION, "$stap_extra_version", [extra stap version code]) AC_SUBST(STAP_EXTRA_VERSION, "$stap_extra_version") dnl This is here mainly to make sure that configure --prefix=... changes dnl the config.h files so files depending on it are recompiled dnl prefix is passed through indirectly in the Makefile.am AM_CPPFLAGS. dnl Formerly: Don't use this directly (when not given it is set to NONE). dnl Currently: inline autoconf's later defaulting stap_prefix=$prefix test "$stap_prefix" = NONE && stap_prefix=$ac_default_prefix AC_DEFINE_UNQUOTED(STAP_PREFIX, "$stap_prefix", [configure prefix location]) AC_SUBST(STAP_PREFIX, "$stap_prefix") AC_CONFIG_HEADERS([config.h:config.in]) AC_CONFIG_FILES([Makefile doc/Makefile man/Makefile \ doc/beginners/Makefile doc/SystemTap_Tapset_Reference/Makefile \ man/stappaths.7 \ initscript/config.systemtap initscript/config.stap-server \ initscript/systemtap initscript/stap-server ]) AC_CONFIG_SUBDIRS(testsuite) if test $enable_translator == "yes"; then AC_CONFIG_FILES([run-stap], [chmod +x run-stap]) fi AC_CONFIG_FILES([dtrace], [chmod +x dtrace]) AC_CONFIG_FILES(stapdyn/Makefile) AC_CONFIG_FILES(java/Makefile) AC_CONFIG_FILES([java/stapbm], [chmod +x java/stapbm]) AC_CONFIG_FILES(staprun/Makefile) AC_CONFIG_FILES([staprun/run-staprun], [chmod +x staprun/run-staprun]) AC_CONFIG_FILES(re2c-migrate/Makefile) # Setup "shadow" directory doc/beginners that has everything setup for # publican in one directory (through directory links if necessary). # It would be nice to use AC_CONFIG_LINKS, but automake complains when # the src is a directory and not a file. AC_CONFIG_FILES([doc/beginners/publican.cfg:doc/SystemTap_Beginners_Guide/publican.cfg.in]) AC_CONFIG_COMMANDS([doc/beginners], [rm -f $ac_abs_top_builddir/doc/beginners/en-US $ac_abs_top_builddir/doc/beginners/build/en-US/testsuite && mkdir -p $ac_abs_top_builddir/doc/beginners/build/en-US && ln -s $ac_abs_top_srcdir/doc/SystemTap_Beginners_Guide/en-US $ac_abs_top_builddir/doc/beginners/en-US && ln -s $ac_abs_top_srcdir/testsuite $ac_abs_top_builddir/doc/beginners/build/en-US/testsuite]) AC_OUTPUT if test "${prefix}" = "/usr/local"; then AC_MSG_NOTICE([]) AC_MSG_NOTICE([For a private or temporary build of systemtap, we recommend]) AC_MSG_NOTICE([configuring with a prefix. For example, try]) AC_MSG_NOTICE([$0 $ac_configure_args --prefix=$HOME/systemtap-${PACKAGE_VERSION}-$$]) AC_MSG_NOTICE([Running systemtap uninstalled, entirely out of the build tree,]) AC_MSG_NOTICE([is not supported.]) fi systemtap-2.3/coveragedb.cxx000066400000000000000000000243471217430427200162500ustar00rootroot00000000000000// coveragedb.cxx // Copyright (C) 2007 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "parse.h" #include "coveragedb.h" #include "config.h" #include "elaborate.h" #include "tapsets.h" #include "session.h" #include "util.h" #ifdef HAVE_LIBSQLITE3 #include #include #include using namespace std; void print_coverage_info(systemtap_session &s) { // print out used probes clog << _("---- used probes-----") << endl; for (unsigned i=0; i used_probe_list; s.probes[i]->collect_derivation_chain(used_probe_list); for (unsigned j=0; jlocations.size(); ++k) clog << _("probe: ") << used_probe_list[j]->locations[k]->components.front()->tok->location << endl; } clog << "----" << endl; // for each probe print used and unused variables for (unsigned j=0; jlocals.size(); ++j) { clog << _("local: ") << s.probes[i]->locals[j]->tok->location << endl; } for (unsigned j=0; junused_locals.size(); ++j) { clog << _("unused_local: ") << s.probes[i]->unused_locals[j]->tok->location << endl; } } // print out unused probes clog << _("---- unused probes----- ") << endl; for (unsigned i=0; i unused_probe_list; s.unused_probes[i]->collect_derivation_chain(unused_probe_list); for (unsigned j=0; jlocations.size(); ++k) clog << _("probe: ") << unused_probe_list[j]->locations[k]->components.front()->tok->location << endl; } } // print out used functions clog << _("---- used functions----- ") << endl; for (map::iterator it = s.functions.begin(); it != s.functions.end(); it++) { clog << "function: " << it->second->tok->location << " " << it->second->name << endl; } // print out unused functions clog << _("---- unused functions----- ") << endl; for (unsigned i=0; itok->location << " " << s.unused_functions[i]->name << endl; } // print out used globals clog << _("---- used globals----- ") << endl; for (unsigned i=0; itok->location << " " << s.globals[i]->name << endl; } // print out unused globals clog << _("---- unused globals----- ") << endl; for (unsigned i=0; itok->location << " " << s.unused_globals[i]->name << endl; } } bool has_table(sqlite3 *db, const char * table) { int rc, rows, columns; char *errmsg; char **results = NULL; ostringstream command; command << "SELECT name FROM sqlite_master " << "WHERE type='table' AND name='" << table << "'"; rc = sqlite3_get_table(db, command.str().c_str(), &results, &rows, &columns, &errmsg); if(rc != SQLITE_OK) { cerr << _("Error in statement: ") << command << " [" << errmsg << "]." << endl; } sqlite3_free_table(results); return (rows !=0); } bool has_index(sqlite3 *db, const char * index) { int rc, rows, columns; char *errmsg; char **results = NULL; ostringstream command; command << "SELECT name FROM sqlite_master " << "WHERE type='index' AND name='" << index << "'"; rc = sqlite3_get_table(db, command.str().c_str(), &results, &rows, &columns, &errmsg); if(rc != SQLITE_OK) { cerr << _("Error in statement: ") << command << " [" << errmsg << "]." << endl; } sqlite3_free_table(results); return (rows !=0); } void sql_stmt(sqlite3 *db, const char* stmt) { char *errmsg; int ret; // cerr << "sqlite: " << stmt << endl; ret = sqlite3_exec(db, stmt, 0, 0, &errmsg); if(ret != SQLITE_OK) { cerr << _("Error in statement: ") << stmt << " [" << errmsg << "]." << endl; } } void enter_element(sqlite3 *db, coverage_element &x) { ostringstream command; command << "insert or ignore into counts values ('" << x.file << "', '" << x.line << "', '" << x.col << "', '" << x.type << "','" << x.name << "', '" << x.parent <<"'," << "'0', '0')"; sql_stmt(db, command.str().c_str()); } void increment_element(sqlite3 *db, coverage_element &x) { ostringstream command; // make sure value in table command << "insert or ignore into counts values ('" << x.file << "', '" << x.line << "', '" << x.col << "', '" << x.type << "','" << x.name << "', '" << x.parent <<"'," << "'0', '0'); " // increment appropriate value << "update counts set compiled=compiled+" << x.compiled << " where (" << "file=='" << x.file << "' and " << "line=='" << x.line << "' and " << "col=='" << x.col << "' and " << "type=='" << x.type << "' and " << "name=='" << x.name << "')"; sql_stmt(db, command.str().c_str()); } void sql_update_used_probes(sqlite3 *db, systemtap_session &s) { // update database used probes for (unsigned i=0; i used_probe_list; s.probes[i]->collect_derivation_chain(used_probe_list); for (unsigned j=0; jlocations.size(); ++k){ struct source_loc place = used_probe_list[j]->locations[k]->components.front()->tok->location; coverage_element x(place); x.type = db_type_probe; x.name = used_probe_list[j]->locations[k]->str(); x.compiled = 1; increment_element(db, x); } } // for each probe update used and unused variables for (unsigned j=0; jlocals.size(); ++j) { struct source_loc place = s.probes[i]->locals[j]->tok->location; coverage_element x(place); x.type = db_type_local; x.name = s.probes[i]->locals[j]->tok->content; x.compiled = 1; increment_element(db, x); } for (unsigned j=0; junused_locals.size(); ++j) { struct source_loc place = s.probes[i]->unused_locals[j]->tok->location; coverage_element x(place); x.type = db_type_local; x.name = s.probes[i]->unused_locals[j]->tok->content; x.compiled = 0; increment_element(db, x); } } } void sql_update_unused_probes(sqlite3 *db, systemtap_session &s) { // update database unused probes for (unsigned i=0; i unused_probe_list; s.unused_probes[i]->collect_derivation_chain(unused_probe_list); for (unsigned j=0; jlocations.size(); ++k) { struct source_loc place = unused_probe_list[j]->locations[k]->components.front()->tok->location; coverage_element x(place); x.type = db_type_probe; x.name = unused_probe_list[j]->locations[k]->str(); x.compiled = 0; increment_element(db, x); } } } } void sql_update_used_functions(sqlite3 *db, systemtap_session &s) { // update db used functions for (map::iterator it = s.functions.begin(); it != s.functions.end(); it++) { struct source_loc place = it->second->tok->location; coverage_element x(place); x.type = db_type_function; x.name = it->second->name; x.compiled = 1; increment_element(db, x); } } void sql_update_unused_functions(sqlite3 *db, systemtap_session &s) { // update db unused functions for (unsigned i=0; itok->location; coverage_element x(place); x.type = db_type_function; x.name = s.unused_functions[i]->name; x.compiled = 0; increment_element(db, x); } } void sql_update_used_globals(sqlite3 *db, systemtap_session &s) { // update db used globals for (unsigned i=0; itok->location; coverage_element x(place); x.type = db_type_global; x.name = s.globals[i]->name; x.compiled = 1; increment_element(db, x); } } void sql_update_unused_globals(sqlite3 *db, systemtap_session &s) { // update db unused globals for (unsigned i=0; itok->location; coverage_element x(place); x.type = db_type_global; x.name = s.unused_globals[i]->name; x.compiled = 0; increment_element(db, x); } } void update_coverage_db(systemtap_session &s) { sqlite3 *db; int rc; string filename(s.data_path + "/" + s.kernel_release + ".db"); rc = sqlite3_open(filename.c_str(), &db); if( rc ){ cerr << "Can't open database: " << sqlite3_errmsg(db) << endl; sqlite3_close(db); return; } // lock the database sql_stmt(db, "begin"); string create_table("create table counts (" "file text, line integer, col integer, " "type text, name text, parent text, " "compiled integer, executed integer)"); string create_index("create unique index tokens on counts (file, line, col, " "type, name)"); // make sure the table is there if (!has_table(db, "counts")) sql_stmt(db, create_table.c_str()); // make sure the index is there if (!has_index(db, "tokens")) sql_stmt(db, create_index.c_str()); sql_update_used_probes(db, s); sql_update_unused_probes(db, s); sql_update_used_functions(db, s); sql_update_unused_functions(db, s); sql_update_used_globals(db, s); sql_update_unused_globals(db, s); // unlock the database and close database sql_stmt(db, "commit"); sqlite3_close(db); } #endif /* HAVE_LIBSQLITE3 */ /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/coveragedb.h000066400000000000000000000035501217430427200156660ustar00rootroot00000000000000// coveragedb.cxx // Copyright (C) 2007 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef COVERAGEDB_H #define COVERAGEDB_H #include "session.h" #include "staptree.h" #include /* tuples: file, line number, column, type of object, name values: number of times object "pulled_in", number of times "removed", times executed if (compiled == 0) object never compiled if (compiled > 0) object compiled The following are not currently implemented. if (executed == 0) never executed if (executed > 0) executed Want to make sure that the data base accurately reflects testing. 1) atomic updates, either commit all or none of information 2) only update coverage db compile info, if compile successful 3) only update coverage db execute info, if instrumentation run suscessfully Would like to have something that looks for interesting features in db: list which things are not compile list which things are not exectuted ratio of compiled/total (overall, by file, by line) ratio of executed/total (overall, by file, by line) */ enum db_type { db_type_probe = 1, db_type_function = 2, db_type_local = 3, db_type_global = 4, }; class coverage_element { public: std::string file; int line; int col; int type; std::string name; std::string parent; int compiled; int executed; coverage_element(): line(0), col(0), compiled(0), executed(0) {} coverage_element(source_loc &place): file(place.file->name), line(place.line), col(place.column), type(0), compiled(0), executed(0) {} }; void print_coverage_info(systemtap_session &s); void update_coverage_db(systemtap_session &s); #endif /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/csclient.cxx000066400000000000000000003201341217430427200157440ustar00rootroot00000000000000/* Compile server client functions Copyright (C) 2010-2013 Red Hat Inc. This file is part of systemtap, and is free software. You can redistribute it and/or modify it under the terms of the GNU General Public License (GPL); either version 2, or (at your option) any later version. */ // Completely disable the client if NSS is not available. #include "config.h" #if HAVE_NSS #include "session.h" #include "cscommon.h" #include "csclient.h" #include "util.h" #include "stap-probe.h" #include #include #include #include #include #include #include #include extern "C" { #include #include #include #include #include #include #include #include #include #include #include } #if HAVE_AVAHI extern "C" { #include #include #include #include #include #include } #endif // HAVE_AVAHI extern "C" { #include #include #include #include #include #include #include #include } #include "nsscommon.h" using namespace std; #define STAP_CSC_01 _("WARNING: The domain name, %s, does not match the DNS name(s) on the server certificate:\n") #define STAP_CSC_02 _("could not find input file %s\n") #define STAP_CSC_03 _("could not open input file %s\n") #define STAP_CSC_04 _("Unable to open output file %s\n") #define STAP_CSC_05 _("could not write to %s\n") static PRIPv6Addr ©Address (PRIPv6Addr &PRin6, const in6_addr &in6); static PRNetAddr ©NetAddr (PRNetAddr &x, const PRNetAddr &y); bool operator!= (const PRNetAddr &x, const PRNetAddr &y); bool operator== (const PRNetAddr &x, const PRNetAddr &y); extern "C" void nsscommon_error (const char *msg, int logit __attribute ((unused))) { clog << msg << endl << flush; } // Information about compile servers. struct compile_server_info { compile_server_info () { memset (& address, 0, sizeof (address)); } string host_name; PRNetAddr address; string version; string sysinfo; string certinfo; bool empty () const { return this->host_name.empty () && ! this->hasAddress (); } bool hasAddress () const { return this->address.raw.family != 0; } unsigned short port () const { if (this->address.raw.family == PR_AF_INET) return ntohs (this->address.inet.port); if (this->address.raw.family == PR_AF_INET6) return ntohs (this->address.ipv6.port); return 0; } unsigned short setPort (unsigned short port) { if (this->address.raw.family == PR_AF_INET) return this->address.inet.port = htons (port); if (this->address.raw.family == PR_AF_INET6) return this->address.ipv6.port = htons (port); return 0; } bool operator== (const compile_server_info &that) const { // If both ip addressed are not set, then the host names must match, otherwise // the addresses must match. if (! this->hasAddress() || ! that.hasAddress()) { if (this->host_name != that.host_name) return false; } else if (this->address != that.address) return false; // Compare the other fields only if they have both been set. if (this->port() != 0 && that.port() != 0 && this->port() != that.port()) return false; if (! this->version.empty () && ! that.version.empty () && this->version != that.version) return false; if (! this->sysinfo.empty () && ! that.sysinfo.empty () && this->sysinfo != that.sysinfo) return false; if (! this->certinfo.empty () && ! that.certinfo.empty () && this->certinfo != that.certinfo) return false; return true; // They are equal } // Used to sort servers by preference for order of contact. The preferred server is // "less" than the other one. bool operator< (const compile_server_info &that) const { // Prefer servers with a later (higher) version number. cs_protocol_version this_version (this->version.c_str ()); cs_protocol_version that_version (that.version.c_str ()); return that_version < this_version; } }; ostream &operator<< (ostream &s, const compile_server_info &i); ostream &operator<< (ostream &s, const vector &v); static void preferred_order (vector &servers) { // Sort the given list of servers into the preferred order for contacting. // Don't bother if there are less than 2 servers in the list. if (servers.size () < 2) return; // Sort the list using compile_server_info::operator< sort (servers.begin (), servers.end ()); } struct compile_server_cache { vector default_servers; vector specified_servers; vector trusted_servers; vector signing_servers; vector online_servers; vector all_servers; map > resolved_servers; }; // For filtering queries. enum compile_server_properties { compile_server_all = 0x1, compile_server_trusted = 0x2, compile_server_online = 0x4, compile_server_compatible = 0x8, compile_server_signer = 0x10, compile_server_specified = 0x20 }; // Static functions. static compile_server_cache* cscache(systemtap_session& s); static void query_server_status (systemtap_session &s, const string &status_string); static void get_server_info (systemtap_session &s, int pmask, vector &servers); static void get_all_server_info (systemtap_session &s, vector &servers); static void get_default_server_info (systemtap_session &s, vector &servers); static void get_specified_server_info (systemtap_session &s, vector &servers, bool no_default = false); static void get_or_keep_online_server_info (systemtap_session &s, vector &servers, bool keep); static void get_or_keep_trusted_server_info (systemtap_session &s, vector &servers, bool keep); static void get_or_keep_signing_server_info (systemtap_session &s, vector &servers, bool keep); static void get_or_keep_compatible_server_info (systemtap_session &s, vector &servers, bool keep); static void keep_common_server_info (const compile_server_info &info_to_keep, vector &filtered_info); static void keep_common_server_info (const vector &info_to_keep, vector &filtered_info); static void keep_server_info_with_cert_and_port (systemtap_session &s, const compile_server_info &server, vector &servers); static void add_server_info (const compile_server_info &info, vector& list); static void add_server_info (const vector &source, vector &target); static void merge_server_info (const compile_server_info &source, compile_server_info &target); #if 0 // not used right now static void merge_server_info (const compile_server_info &source, vector &target); static void merge_server_info (const vector &source, vector &target); #endif static void resolve_host (systemtap_session& s, compile_server_info &server, vector &servers); /* Exit error codes */ #define SUCCESS 0 #define GENERAL_ERROR 1 #define CA_CERT_INVALID_ERROR 2 #define SERVER_CERT_EXPIRED_ERROR 3 // ----------------------------------------------------- // NSS related code used by the compile server client // ----------------------------------------------------- static void add_server_trust (systemtap_session &s, const string &cert_db_path, const vector &server_list); static void revoke_server_trust (systemtap_session &s, const string &cert_db_path, const vector &server_list); static void get_server_info_from_db (systemtap_session &s, vector &servers, const string &cert_db_path); static string global_client_cert_db_path () { return SYSCONFDIR "/systemtap/ssl/client"; } static string private_ssl_cert_db_path () { return local_client_cert_db_path (); } static string global_ssl_cert_db_path () { return global_client_cert_db_path (); } static string signing_cert_db_path () { return SYSCONFDIR "/systemtap/staprun"; } /* Connection state. */ typedef struct connectionState_t { const char *hostName; PRNetAddr addr; const char *infileName; const char *outfileName; const char *trustNewServerMode; } connectionState_t; #if 0 /* No client authorization */ static char * myPasswd(PK11SlotInfo *info, PRBool retry, void *arg) { char * passwd = NULL; if ( (!retry) && arg ) passwd = PORT_Strdup((char *)arg); return passwd; } #endif /* Add the server's certificate to our database of trusted servers. */ static SECStatus trustNewServer (CERTCertificate *serverCert) { SECStatus secStatus; CERTCertTrust *trust = NULL; PK11SlotInfo *slot = NULL; /* Import the certificate. */ slot = PK11_GetInternalKeySlot(); const char *nickname = server_cert_nickname (); secStatus = PK11_ImportCert(slot, serverCert, CK_INVALID_HANDLE, nickname, PR_FALSE); if (secStatus != SECSuccess) goto done; /* Make it a trusted peer. */ trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust)); if (! trust) { secStatus = SECFailure; goto done; } secStatus = CERT_DecodeTrustString(trust, "P,P,P"); if (secStatus != SECSuccess) goto done; secStatus = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), serverCert, trust); done: if (slot) PK11_FreeSlot (slot); if (trust) PORT_Free(trust); return secStatus; } /* Called when the server certificate verification fails. This gives us the chance to trust the server anyway and add the certificate to the local database. */ static SECStatus badCertHandler(void *arg, PRFileDesc *sslSocket) { SECStatus secStatus; PRErrorCode errorNumber; CERTCertificate *serverCert = NULL; SECItem subAltName; PRArenaPool *tmpArena = NULL; CERTGeneralName *nameList, *current; char *expected = NULL; const connectionState_t *connectionState = (connectionState_t *)arg; errorNumber = PR_GetError (); switch (errorNumber) { case SSL_ERROR_BAD_CERT_DOMAIN: /* Since we administer our own client-side databases of trustworthy certificates, we don't need the domain name(s) on the certificate to match. If the cert is in our database, then we can trust it. Issue a warning and accept the certificate. */ expected = SSL_RevealURL (sslSocket); fprintf (stderr, STAP_CSC_01, expected); /* List the DNS names from the server cert as part of the warning. First, find the alt-name extension on the certificate. */ subAltName.data = NULL; serverCert = SSL_PeerCertificate (sslSocket); secStatus = CERT_FindCertExtension (serverCert, SEC_OID_X509_SUBJECT_ALT_NAME, & subAltName); if (secStatus != SECSuccess || ! subAltName.data) { fprintf (stderr, _("Unable to find alt name extension on the server certificate\n")); secStatus = SECSuccess; /* Not a fatal error */ break; } // Now, decode the extension. tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (! tmpArena) { fprintf (stderr, _("Out of memory\n")); SECITEM_FreeItem(& subAltName, PR_FALSE); secStatus = SECSuccess; /* Not a fatal error here */ break; } nameList = CERT_DecodeAltNameExtension (tmpArena, & subAltName); SECITEM_FreeItem(& subAltName, PR_FALSE); if (! nameList) { fprintf (stderr, _("Unable to decode alt name extension on server certificate\n")); secStatus = SECSuccess; /* Not a fatal error */ break; } /* List the DNS names from the server cert as part of the warning. The names are in a circular list. */ current = nameList; do { /* Make sure this is a DNS name. */ if (current->type == certDNSName) { fprintf (stderr, " %.*s\n", (int)current->name.other.len, current->name.other.data); } current = CERT_GetNextGeneralName (current); } while (current != nameList); /* Accept the certificate */ secStatus = SECSuccess; break; case SEC_ERROR_CA_CERT_INVALID: /* The server's certificate is not trusted. Should we trust it? */ secStatus = SECFailure; /* Do not trust by default. */ if (! connectionState->trustNewServerMode) break; /* Trust it for this session only? */ if (strcmp (connectionState->trustNewServerMode, "session") == 0) { secStatus = SECSuccess; break; } /* Trust it permanently? */ if (strcmp (connectionState->trustNewServerMode, "permanent") == 0) { /* The user wants to trust this server. Get the server's certificate so and add it to our database. */ serverCert = SSL_PeerCertificate (sslSocket); if (serverCert != NULL) { secStatus = trustNewServer (serverCert); } } break; default: secStatus = SECFailure; /* Do not trust this server */ break; } if (expected) PORT_Free (expected); if (tmpArena) PORT_FreeArena (tmpArena, PR_FALSE); if (serverCert != NULL) { CERT_DestroyCertificate (serverCert); } return secStatus; } static PRFileDesc * setupSSLSocket (connectionState_t *connectionState) { PRFileDesc *tcpSocket; PRFileDesc *sslSocket; PRSocketOptionData socketOption; PRStatus prStatus; SECStatus secStatus; tcpSocket = PR_OpenTCPSocket(connectionState->addr.raw.family); if (tcpSocket == NULL) goto loser; /* Make the socket blocking. */ socketOption.option = PR_SockOpt_Nonblocking; socketOption.value.non_blocking = PR_FALSE; prStatus = PR_SetSocketOption(tcpSocket, &socketOption); if (prStatus != PR_SUCCESS) goto loser; /* Import the socket into the SSL layer. */ sslSocket = SSL_ImportFD(NULL, tcpSocket); if (!sslSocket) goto loser; /* Set configuration options. */ secStatus = SSL_OptionSet(sslSocket, SSL_SECURITY, PR_TRUE); if (secStatus != SECSuccess) goto loser; secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); if (secStatus != SECSuccess) goto loser; /* Set SSL callback routines. */ #if 0 /* no client authentication */ secStatus = SSL_GetClientAuthDataHook(sslSocket, (SSLGetClientAuthData)myGetClientAuthData, (void *)certNickname); if (secStatus != SECSuccess) goto loser; #endif #if 0 /* Use the default */ secStatus = SSL_AuthCertificateHook(sslSocket, (SSLAuthCertificate)myAuthCertificate, (void *)CERT_GetDefaultCertDB()); if (secStatus != SECSuccess) goto loser; #endif secStatus = SSL_BadCertHook(sslSocket, (SSLBadCertHandler)badCertHandler, connectionState); if (secStatus != SECSuccess) goto loser; #if 0 /* No handshake callback */ secStatus = SSL_HandshakeCallback(sslSocket, myHandshakeCallback, NULL); if (secStatus != SECSuccess) goto loser; #endif return sslSocket; loser: if (tcpSocket) PR_Close(tcpSocket); return NULL; } static SECStatus handle_connection (PRFileDesc *sslSocket, connectionState_t *connectionState) { PRInt32 numBytes; char *readBuffer; PRFileInfo info; PRFileDesc *local_file_fd; PRStatus prStatus; SECStatus secStatus = SECSuccess; #define READ_BUFFER_SIZE (60 * 1024) /* If we don't have both the input and output file names, then we're contacting this server only in order to establish trust. In this case send 0 as the file size and exit. */ if (! connectionState->infileName || ! connectionState->outfileName) { numBytes = htonl ((PRInt32)0); numBytes = PR_Write (sslSocket, & numBytes, sizeof (numBytes)); if (numBytes < 0) return SECFailure; return SECSuccess; } /* read and send the data. */ /* Try to open the local file named. * If successful, then write it to the server */ prStatus = PR_GetFileInfo(connectionState->infileName, &info); if (prStatus != PR_SUCCESS || info.type != PR_FILE_FILE || info.size < 0) { fprintf (stderr, STAP_CSC_02, connectionState->infileName); return SECFailure; } local_file_fd = PR_Open(connectionState->infileName, PR_RDONLY, 0); if (local_file_fd == NULL) { fprintf (stderr, STAP_CSC_03, connectionState->infileName); return SECFailure; } /* Send the file size first, so the server knows when it has the entire file. */ numBytes = htonl ((PRInt32)info.size); numBytes = PR_Write(sslSocket, & numBytes, sizeof (numBytes)); if (numBytes < 0) { PR_Close(local_file_fd); return SECFailure; } /* Transmit the local file across the socket. */ numBytes = PR_TransmitFile(sslSocket, local_file_fd, NULL, 0, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); if (numBytes < 0) { PR_Close(local_file_fd); return SECFailure; } PR_Close(local_file_fd); /* read until EOF */ readBuffer = (char *)PORT_Alloc(READ_BUFFER_SIZE); if (! readBuffer) { fprintf (stderr, _("Out of memory\n")); return SECFailure; } local_file_fd = PR_Open(connectionState->outfileName, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, PR_IRUSR | PR_IWUSR | PR_IRGRP | PR_IWGRP | PR_IROTH); if (local_file_fd == NULL) { fprintf (stderr, STAP_CSC_04, connectionState->outfileName); return SECFailure; } while (PR_TRUE) { // No need for PR_Read_Complete here, since we're already managing multiple // reads to a fixed size buffer. numBytes = PR_Read (sslSocket, readBuffer, READ_BUFFER_SIZE); if (numBytes == 0) break; /* EOF */ if (numBytes < 0) { secStatus = SECFailure; break; } /* Write to output file */ numBytes = PR_Write(local_file_fd, readBuffer, numBytes); if (numBytes < 0) { fprintf (stderr, STAP_CSC_05, connectionState->outfileName); secStatus = SECFailure; break; } } PR_Free(readBuffer); PR_Close(local_file_fd); /* Caller closes the socket. */ return secStatus; } /* make the connection. */ static SECStatus do_connect (connectionState_t *connectionState) { PRFileDesc *sslSocket; PRStatus prStatus; SECStatus secStatus; secStatus = SECSuccess; /* Set up SSL secure socket. */ sslSocket = setupSSLSocket (connectionState); if (sslSocket == NULL) return SECFailure; #if 0 /* no client authentication */ secStatus = SSL_SetPKCS11PinArg(sslSocket, password); if (secStatus != SECSuccess) goto done; #endif secStatus = SSL_SetURL(sslSocket, connectionState->hostName); if (secStatus != SECSuccess) goto done; prStatus = PR_Connect(sslSocket, & connectionState->addr, PR_INTERVAL_NO_TIMEOUT); if (prStatus != PR_SUCCESS) { secStatus = SECFailure; goto done; } /* Established SSL connection, ready to send data. */ secStatus = SSL_ResetHandshake(sslSocket, /* asServer */ PR_FALSE); if (secStatus != SECSuccess) goto done; /* This is normally done automatically on the first I/O operation, but doing it here catches any authentication problems early. */ secStatus = SSL_ForceHandshake(sslSocket); if (secStatus != SECSuccess) goto done; // Connect to the server and make the request. secStatus = handle_connection(sslSocket, connectionState); done: prStatus = PR_Close(sslSocket); return secStatus; } static bool isIPv6LinkLocal (const PRNetAddr &address) { // Link-local addresses are members of the address block fe80:: if (address.raw.family == PR_AF_INET6 && address.ipv6.ip.pr_s6_addr[0] == 0xfe && address.ipv6.ip.pr_s6_addr[1] == 0x80) return true; return false; } int client_connect (const compile_server_info &server, const char* infileName, const char* outfileName, const char* trustNewServer) { SECStatus secStatus; PRErrorCode errorNumber; int attempt; int errCode = GENERAL_ERROR; struct connectionState_t connectionState; // Set up a connection state for use by NSS error callbacks. memset (& connectionState, 0, sizeof (connectionState)); connectionState.hostName = server.host_name.c_str (); connectionState.addr = server.address; connectionState.infileName = infileName; connectionState.outfileName = outfileName; connectionState.trustNewServerMode = trustNewServer; /* Some errors (see below) represent a situation in which trying again should succeed. However, don't try forever. */ for (attempt = 0; attempt < 5; ++attempt) { secStatus = do_connect (& connectionState); if (secStatus == SECSuccess) return SUCCESS; errorNumber = PR_GetError (); switch (errorNumber) { case PR_CONNECT_RESET_ERROR: /* Server was not ready. */ sleep (1); break; /* Try again */ case SEC_ERROR_EXPIRED_CERTIFICATE: /* The server's certificate has expired. It should generate a new certificate. Return now and we'll try again. */ errCode = SERVER_CERT_EXPIRED_ERROR; return errCode; case SEC_ERROR_CA_CERT_INVALID: /* The server's certificate is not trusted. The exit code must reflect this. */ errCode = CA_CERT_INVALID_ERROR; return errCode; default: /* This error is fatal. */ return errCode; } } return errCode; } int compile_server_client::passes_0_4 () { PROBE1(stap, client__start, &s); // arguments parsed; get down to business if (s.verbose) clog << _("Using a compile server.") << endl; struct tms tms_before; times (& tms_before); struct timeval tv_before; gettimeofday (&tv_before, NULL); // Create the request package. int rc = initialize (); assert_no_interrupts(); if (rc != 0) goto done; rc = create_request (); assert_no_interrupts(); if (rc != 0) goto done; rc = package_request (); assert_no_interrupts(); if (rc != 0) goto done; // Submit it to the server. rc = find_and_connect_to_server (); assert_no_interrupts(); if (rc != 0) goto done; // Unpack and process the response. rc = unpack_response (); assert_no_interrupts(); if (rc != 0) goto done; rc = process_response (); if (rc == 0 && s.last_pass == 4) { cout << s.module_name + ".ko"; cout << endl; } done: struct tms tms_after; times (& tms_after); unsigned _sc_clk_tck = sysconf (_SC_CLK_TCK); struct timeval tv_after; gettimeofday (&tv_after, NULL); #define TIMESPRINT "in " << \ (tms_after.tms_cutime + tms_after.tms_utime \ - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck) << "usr/" \ << (tms_after.tms_cstime + tms_after.tms_stime \ - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck) << "sys/" \ << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + \ ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms." // syntax errors, if any, are already printed if (s.verbose) { string ws = s.winning_server; if (ws == "") ws = "?"; clog << _("Passes: via server ") << ws << " " << getmemusage() << TIMESPRINT << endl; } if (rc) { clog << _("Passes: via server failed. Try again with another '-v' option.") << endl; } if (rc == 0) { // Save the module, if necessary. if (s.last_pass == 4) s.save_module = true; // Copy module to the current directory. if (s.save_module && ! pending_interrupts) { string module_src_path = s.tmpdir + "/" + s.module_name + ".ko"; string module_dest_path = s.module_name + ".ko"; copy_file (module_src_path, module_dest_path, s.verbose >= 3); // Also copy the module signature, it it exists. module_src_path += ".sgn"; if (file_exists (module_src_path)) { module_dest_path += ".sgn"; copy_file(module_src_path, module_dest_path, s.verbose >= 3); } } } PROBE1(stap, client__end, &s); return rc; } // Initialize a client/server session. int compile_server_client::initialize () { int rc = 0; // Initialize session state argc = 0; // Private location for server certificates. private_ssl_dbs.push_back (private_ssl_cert_db_path ()); // Additional public location. public_ssl_dbs.push_back (global_ssl_cert_db_path ()); // Create a temporary directory to package things in. client_tmpdir = s.tmpdir + "/client"; rc = create_dir (client_tmpdir.c_str ()); if (rc != 0) { const char* e = strerror (errno); clog << _("ERROR: cannot create temporary directory (\"") << client_tmpdir << "\"): " << e << endl; } return rc; } // Create the request package. int compile_server_client::create_request () { // Add the current protocol version. int rc = write_to_file (client_tmpdir + "/version", CURRENT_CS_PROTOCOL_VERSION); if (rc != 0) return rc; // Add the script file or script option if (s.script_file != "") { if (s.script_file == "-") { // Copy the script from stdin string packaged_script_dir = client_tmpdir + "/script"; rc = create_dir (packaged_script_dir.c_str ()); if (rc != 0) { const char* e = strerror (errno); clog << _("ERROR: cannot create temporary directory ") << packaged_script_dir << ": " << e << endl; return rc; } rc = ! copy_file("/dev/stdin", packaged_script_dir + "/-"); if (rc != 0) return rc; // Name the script in the packaged arguments. rc = add_package_arg ("script/-"); if (rc != 0) return rc; } else { // Add the script to our package. This will also name the script // in the packaged arguments. rc = include_file_or_directory ("script", s.script_file); if (rc != 0) return rc; } } // Add -I paths. Skip the default directory. if (s.include_arg_start != -1) { unsigned limit = s.include_path.size (); for (unsigned i = s.include_arg_start; i < limit; ++i) { rc = add_package_arg ("-I"); if (rc != 0) return rc; rc = include_file_or_directory ("tapset", s.include_path[i]); if (rc != 0) return rc; } } // Add other options. rc = add_package_args (); if (rc != 0) return rc; // Add the sysinfo file string sysinfo = "sysinfo: " + s.kernel_release + " " + s.architecture; rc = write_to_file (client_tmpdir + "/sysinfo", sysinfo); if (rc != 0) return rc; // Add localization data rc = add_localization_variables(); return rc; } // Add the arguments specified on the command line to the server request // package, as appropriate. int compile_server_client::add_package_args () { // stap arguments to be passed to the server. int rc = 0; unsigned limit = s.server_args.size(); for (unsigned i = 0; i < limit; ++i) { rc = add_package_arg (s.server_args[i]); if (rc != 0) return rc; } // Script arguments. limit = s.args.size(); if (limit > 0) { rc = add_package_arg ("--"); if (rc != 0) return rc; for (unsigned i = 0; i < limit; ++i) { rc = add_package_arg (s.args[i]); if (rc != 0) return rc; } } return rc; } int compile_server_client::add_package_arg (const string &arg) { int rc = 0; ostringstream fname; fname << client_tmpdir << "/argv" << ++argc; write_to_file (fname.str (), arg); // NB: No terminating newline return rc; } // Symbolically link the given file or directory into the client's temp // directory under the given subdirectory. int compile_server_client::include_file_or_directory ( const string &subdir, const string &path ) { // Must predeclare these because we do use 'goto done' to // exit from error situations. vector components; string name; int rc; // Canonicalize the given path and remove the leading /. string rpath; char *cpath = canonicalize_file_name (path.c_str ()); if (! cpath) { // It can not be canonicalized. Use the name relative to // the current working directory and let the server deal with it. char cwd[PATH_MAX]; if (getcwd (cwd, sizeof (cwd)) == NULL) { rpath = path; rc = 1; goto done; } rpath = string (cwd) + "/" + path; } else { // It can be canonicalized. Use the canonicalized name and add this // file or directory to the request package. rpath = cpath; free (cpath); // Including / would require special handling in the code below and // is a bad idea anyway. Let's not allow it. if (rpath == "/") { if (rpath != path) clog << _F("%s resolves to %s\n", path.c_str (), rpath.c_str ()); clog << _F("Unable to send %s to the server\n", path.c_str ()); return 1; } // First create the requested subdirectory. name = client_tmpdir + "/" + subdir; rc = create_dir (name.c_str ()); if (rc) goto done; // Now create each component of the path within the sub directory. assert (rpath[0] == '/'); tokenize (rpath.substr (1), components, "/"); assert (components.size () >= 1); unsigned i; for (i = 0; i < components.size() - 1; ++i) { if (components[i].empty ()) continue; // embedded '//' name += "/" + components[i]; rc = create_dir (name.c_str ()); if (rc) goto done; } // Now make a symbolic link to the actual file or directory. assert (i == components.size () - 1); name += "/" + components[i]; rc = symlink (rpath.c_str (), name.c_str ()); if (rc) goto done; } // Name this file or directory in the packaged arguments. rc = add_package_arg (subdir + "/" + rpath.substr (1)); done: if (rc != 0) { const char* e = strerror (errno); clog << "ERROR: unable to add " << rpath << " to temp directory as " << name << ": " << e << endl; } return rc; } // Add the localization variables to the server request // package. int compile_server_client::add_localization_variables() { int rc; string envVar; string fname; const set &locVars = localization_variables(); set::iterator it; /* Note: We don't have to check for the contents of the environment * variables here, since they will be checked extensively on the * server. */ for (it = locVars.begin(); it != locVars.end(); it++) { char* var = getenv((*it).c_str()); if (var) envVar += *it + "=" + (string)var + "\n"; } fname = client_tmpdir + "/locale"; rc = write_to_file(fname, envVar); return rc; } // Package the client's temp directory into a form suitable for sending to the // server. int compile_server_client::package_request () { // Package up the temporary directory into a zip file. client_zipfile = client_tmpdir + ".zip"; string cmd = "cd " + cmdstr_quoted(client_tmpdir) + " && zip -qr " + cmdstr_quoted(client_zipfile) + " *"; vector sh_cmd; sh_cmd.push_back("sh"); sh_cmd.push_back("-c"); sh_cmd.push_back(cmd); int rc = stap_system (s.verbose, sh_cmd); return rc; } int compile_server_client::find_and_connect_to_server () { // Accumulate info on the specified servers. vector specified_servers; get_specified_server_info (s, specified_servers); // Examine the specified servers to make sure that each has been resolved // with a host name, ip address and port. If not, try to obtain this // information by examining online servers. vector server_list; for (vector::const_iterator i = specified_servers.begin (); i != specified_servers.end (); ++i) { // If we have an ip address and port number, then just use the one we've // been given. Otherwise, check for matching online servers and try their // ip addresses and ports. if (i->hasAddress() && i->port() != 0) add_server_info (*i, server_list); else { // Obtain a list of online servers. vector online_servers; get_or_keep_online_server_info (s, online_servers, false/*keep*/); // If no specific server (port) has been specified, // then we'll need the servers to be // compatible and possible trusted as signers as well. if (i->port() == 0) { get_or_keep_compatible_server_info (s, online_servers, true/*keep*/); if (! pr_contains (s.privilege, pr_stapdev)) get_or_keep_signing_server_info (s, online_servers, true/*keep*/); } // Keep the ones (if any) which match our server. keep_common_server_info (*i, online_servers); // Add these servers (if any) to the server list. add_server_info (online_servers, server_list); } } // Did we identify any potential servers? unsigned limit = server_list.size (); if (limit == 0) { clog << _("Unable to find a suitable compile server.") << endl; // Try to explain why. vector online_servers; get_or_keep_online_server_info (s, online_servers, false/*keep*/); if (online_servers.empty ()) clog << _("No servers online to select from.") << endl; else { clog << _("The following servers are online:") << endl; clog << online_servers; if (! specified_servers.empty ()) { clog << _("The following servers were requested:") << endl; clog << specified_servers; } else { string criteria = "online,trusted,compatible"; if (! pr_contains (s.privilege, pr_stapdev)) criteria += ",signer"; clog << _F("No servers matched the selection criteria of %s.", criteria.c_str()) << endl; } } return 1; } // Sort the list of servers into a preferred order. preferred_order (server_list); // Now try each of the identified servers in turn. int rc = compile_using_server (server_list); if (rc == SUCCESS) return 0; // success! // If the error was that a server's cert was expired, try again. This is because the server // should generate a new cert which may be automatically trusted by us if it is our server. // Give the server a chance to do this before retrying. if (rc == SERVER_CERT_EXPIRED_ERROR) { if (s.verbose >= 2) clog << _("The server's certificate was expired. Trying again") << endl << flush; sleep (2); rc = compile_using_server (server_list); if (rc == SUCCESS) return 0; // success! } // We were unable to use any available server clog << _("Unable to connect to a server.") << endl; if (s.verbose == 1) { // This information is redundant at higher verbosity levels. clog << _("The following servers were tried:") << endl; clog << server_list; } return 1; // Failure } int compile_server_client::compile_using_server ( const vector &servers ) { // Make sure NSPR is initialized. Must be done before NSS is initialized s.NSPR_init (); // Attempt connection using each of the available client certificate // databases. Assume the server certificate is invalid until proven otherwise. PR_SetError (SEC_ERROR_CA_CERT_INVALID, 0); vector dbs = private_ssl_dbs; vector::iterator i = dbs.end(); dbs.insert (i, public_ssl_dbs.begin (), public_ssl_dbs.end ()); int rc = GENERAL_ERROR; // assume failure bool serverCertExpired = false; for (i = dbs.begin (); i != dbs.end (); ++i) { // Make sure the database directory exists. It is not an error if it // doesn't. if (! file_exists (*i)) continue; #if 0 // no client authentication for now. // Set our password function callback. PK11_SetPasswordFunc (myPasswd); #endif // Initialize the NSS libraries. const char *cert_dir = i->c_str (); SECStatus secStatus = nssInit (cert_dir); if (secStatus != SECSuccess) { // Message already issued. continue; // try next database } // Enable cipher suites which are allowed by U.S. export regulations. // SSL_ClearSessionCache is required for the new settings to take effect. secStatus = NSS_SetExportPolicy (); SSL_ClearSessionCache (); if (secStatus != SECSuccess) { clog << _("Unable to set NSS export policy"); nssError (); nssCleanup (cert_dir); continue; // try next database } server_zipfile = s.tmpdir + "/server.zip"; // Try each server in turn. for (vector::const_iterator j = servers.begin (); j != servers.end (); ++j) { // At a minimum we need an ip_address along with a port // number in order to contact the server. if (! j->hasAddress() || j->port() == 0) continue; if (s.verbose >= 2) clog << _F("Attempting SSL connection with %s\n" " using certificates from the database in %s\n", lex_cast(*j).c_str(), cert_dir); rc = client_connect (*j, client_zipfile.c_str(), server_zipfile.c_str (), NULL/*trustNewServer_p*/); if (rc == SUCCESS) { s.winning_server = lex_cast(*j); break; // Success! } // Server cert has expired. Try other servers and/or databases, but take note because // server should generate a new certificate. If no other servers succeed, we'll try again // in case the new cert works. if (rc == SERVER_CERT_EXPIRED_ERROR) { serverCertExpired = true; continue; } if (s.verbose >= 2) { clog << _(" Unable to connect: "); nssError (); // Additional information: if the address is IPv6 and is link-local, then it must // have a scope_id. if (isIPv6LinkLocal (j->address) && j->address.ipv6.scope_id == 0) { clog << _(" The address is an IPv6 link-local address with no scope specifier.") << endl; } } } // SSL_ClearSessionCache is required before shutdown for client applications. SSL_ClearSessionCache (); nssCleanup (cert_dir); if (rc == SECSuccess) break; // Success! } // Indicate whether a server cert was expired, so we can try again, if desired. if (rc != SUCCESS) { if (serverCertExpired) rc = SERVER_CERT_EXPIRED_ERROR; } return rc; } int compile_server_client::unpack_response () { // Unzip the response package. server_tmpdir = s.tmpdir + "/server"; vector cmd; cmd.push_back("unzip"); cmd.push_back("-qd"); cmd.push_back(server_tmpdir); cmd.push_back(server_zipfile); int rc = stap_system (s.verbose, cmd); if (rc != 0) { clog << _F("Unable to unzip the server response '%s'\n", server_zipfile.c_str()); return rc; } // Determine the server protocol version. string filename = server_tmpdir + "/version"; if (file_exists (filename)) ::read_from_file (filename, server_version); // Warn about the shortcomings of this server, if it is down level. show_server_compatibility (); // If the server's response contains a systemtap temp directory, move // its contents to our temp directory. glob_t globbuf; string filespec = server_tmpdir + "/stap??????"; if (s.verbose >= 3) clog << _F("Searching \"%s\"\n", filespec.c_str()); int r = glob(filespec.c_str (), 0, NULL, & globbuf); if (r != GLOB_NOSPACE && r != GLOB_ABORTED && r != GLOB_NOMATCH) { if (globbuf.gl_pathc > 1) { clog << _("Incorrect number of files in server response") << endl; rc = 1; goto done; } assert (globbuf.gl_pathc == 1); string dirname = globbuf.gl_pathv[0]; if (s.verbose >= 3) clog << _(" found ") << dirname << endl; filespec = dirname + "/*"; if (s.verbose >= 3) clog << _F("Searching \"%s\"\n", filespec.c_str()); int r = glob(filespec.c_str (), GLOB_PERIOD, NULL, & globbuf); if (r != GLOB_NOSPACE && r != GLOB_ABORTED && r != GLOB_NOMATCH) { unsigned prefix_len = dirname.size () + 1; for (unsigned i = 0; i < globbuf.gl_pathc; ++i) { string oldname = globbuf.gl_pathv[i]; if (oldname.substr (oldname.size () - 2) == "/." || oldname.substr (oldname.size () - 3) == "/..") continue; string newname = s.tmpdir + "/" + oldname.substr (prefix_len); if (s.verbose >= 3) clog << _F(" found %s -- linking from %s", oldname.c_str(), newname.c_str()); rc = symlink (oldname.c_str (), newname.c_str ()); if (rc != 0) { clog << _F("Unable to link '%s' to '%s':%s\n", oldname.c_str(), newname.c_str(), strerror(errno)); goto done; } } } } // If the server version is less that 1.6, remove the output line due to the synthetic // server-side -k. Look for a message containing the name of the temporary directory. // We can look for the English message since server versions before 1.6 do not support // localization. if (server_version < "1.6") { cmd.clear(); cmd.push_back("sed"); cmd.push_back("-i"); cmd.push_back("/^Keeping temporary directory.*/ d"); cmd.push_back(server_tmpdir + "/stderr"); stap_system (s.verbose, cmd); } // Remove the output line due to the synthetic server-side -p4 cmd.clear(); cmd.push_back("sed"); cmd.push_back("-i"); cmd.push_back("/^.*\\.ko$/ d"); cmd.push_back(server_tmpdir + "/stdout"); stap_system (s.verbose, cmd); done: globfree (& globbuf); return rc; } int compile_server_client::process_response () { // Pick up the results of running stap on the server. string filename = server_tmpdir + "/rc"; int stap_rc; int rc = read_from_file (filename, stap_rc); if (rc != 0) return rc; rc = stap_rc; if (s.last_pass >= 4) { // The server should have returned a module. string filespec = s.tmpdir + "/*.ko"; if (s.verbose >= 3) clog << _F("Searching \"%s\"\n", filespec.c_str()); glob_t globbuf; int r = glob(filespec.c_str (), 0, NULL, & globbuf); if (r != GLOB_NOSPACE && r != GLOB_ABORTED && r != GLOB_NOMATCH) { if (globbuf.gl_pathc > 1) clog << _("Incorrect number of modules in server response") << endl; else { assert (globbuf.gl_pathc == 1); string modname = globbuf.gl_pathv[0]; if (s.verbose >= 3) clog << _(" found ") << modname << endl; // If a module name was not specified by the user, then set it to // be the one generated by the server. if (! s.save_module) { vector components; tokenize (modname, components, "/"); s.module_name = components.back (); s.module_name.erase(s.module_name.size() - 3); } // If a uprobes.ko module was returned, then make note of it. string uprobes_ko; if (server_version < "1.6") uprobes_ko = s.tmpdir + "/server/uprobes.ko"; else uprobes_ko = s.tmpdir + "/uprobes/uprobes.ko"; if (file_exists (uprobes_ko)) { s.need_uprobes = true; s.uprobes_path = uprobes_ko; } } } else if (s.have_script) { if (rc == 0) { clog << _("No module was returned by the server.") << endl; rc = 1; } } globfree (& globbuf); } // Output stdout and stderr. filename = server_tmpdir + "/stderr"; flush_to_stream (filename, clog); filename = server_tmpdir + "/stdout"; flush_to_stream (filename, cout); return rc; } int compile_server_client::read_from_file (const string &fname, int &data) { // C++ streams may not set errno in the even of a failure. However if we // set it to 0 before each operation and it gets set during the operation, // then we can use its value in order to determine what happened. errno = 0; ifstream f (fname.c_str ()); if (! f.good ()) { clog << _F("Unable to open file '%s' for reading: ", fname.c_str()); goto error; } // Read the data; errno = 0; f >> data; if (f.fail ()) { clog << _F("Unable to read from file '%s': ", fname.c_str()); goto error; } // NB: not necessary to f.close (); return 0; // Success error: if (errno) clog << strerror (errno) << endl; else clog << _("unknown error") << endl; return 1; // Failure } template int compile_server_client::write_to_file (const string &fname, const T &data) { // C++ streams may not set errno in the even of a failure. However if we // set it to 0 before each operation and it gets set during the operation, // then we can use its value in order to determine what happened. errno = 0; ofstream f (fname.c_str ()); if (! f.good ()) { clog << _F("Unable to open file '%s' for writing: ", fname.c_str()); goto error; } // Write the data; f << data; errno = 0; if (f.fail ()) { clog << _F("Unable to write to file '%s': ", fname.c_str()); goto error; } // NB: not necessary to f.close (); return 0; // Success error: if (errno) clog << strerror (errno) << endl; else clog << _("unknown error") << endl; return 1; // Failure } int compile_server_client::flush_to_stream (const string &fname, ostream &o) { // C++ streams may not set errno in the even of a failure. However if we // set it to 0 before each operation and it gets set during the operation, // then we can use its value in order to determine what happened. errno = 0; ifstream f (fname.c_str ()); if (! f.good ()) { clog << _F("Unable to open file '%s' for reading: ", fname.c_str()); goto error; } // Stream the data // NB: o << f.rdbuf() misbehaves for some reason, appearing to close o, // which is unfortunate if o == clog or cout. while (1) { errno = 0; int c = f.get(); if (f.eof ()) return 0; // normal exit if (! f.good()) break; o.put(c); if (! o.good()) break; } // NB: not necessary to f.close (); error: if (errno) clog << strerror (errno) << endl; else clog << _("unknown error") << endl; return 1; // Failure } void compile_server_client::show_server_compatibility () const { // Locale sensitivity was added in version 1.6 if (server_version < "1.6") { clog << _F("Server protocol version is %s\n", server_version.v); clog << _("The server does not use localization information passed by the client\n"); } } // Issue a status message for when a server's trust is already in place. static void trust_already_in_place ( const compile_server_info &server, const vector &server_list, const string cert_db_path, bool revoking ) { // What level of trust? string purpose; if (cert_db_path == signing_cert_db_path ()) purpose = _("as a module signer for all users"); else { purpose = _("as an SSL peer"); if (cert_db_path == global_ssl_cert_db_path ()) purpose += _(" for all users"); else purpose += _(" for the current user"); } // Issue a message for each server in the list with the same certificate. unsigned limit = server_list.size (); for (unsigned i = 0; i < limit; ++i) { if (server.certinfo != server_list[i].certinfo) continue; clog << server_list[i] << _(" is already "); if (revoking) clog << _("untrusted ") << purpose << endl; else clog << _("trusted ") << purpose << endl; } } // Add the given servers to the given database of trusted servers. static void add_server_trust ( systemtap_session &s, const string &cert_db_path, const vector &server_list ) { // Get a list of servers already trusted. This opens the database, so do it // before we open it for our own purposes. vector already_trusted; get_server_info_from_db (s, already_trusted, cert_db_path); // Make sure the given path exists. if (create_dir (cert_db_path.c_str (), 0755) != 0) { clog << _F("Unable to find or create the client certificate database directory %s: ", cert_db_path.c_str()); perror (""); return; } // Must predeclare this because of jumps to cleanup: below. vector processed_certs; // Make sure NSPR is initialized. Must be done before NSS is initialized s.NSPR_init (); // Initialize the NSS libraries -- read/write SECStatus secStatus = nssInit (cert_db_path.c_str (), 1/*readwrite*/); if (secStatus != SECSuccess) { // Message already issued. goto cleanup; } // Enable cipher suites which are allowed by U.S. export regulations. // SSL_ClearSessionCache is required for the new settings to take effect. secStatus = NSS_SetExportPolicy (); SSL_ClearSessionCache (); if (secStatus != SECSuccess) { clog << _("Unable to set NSS export policy"); nssError (); goto cleanup; } // Iterate over the servers to become trusted. Contact each one and // add it to the list of trusted servers if it is not already trusted. // client_connect will issue any error messages. for (vector::const_iterator server = server_list.begin(); server != server_list.end (); ++server) { // Trust is based on certificates. We need only add trust in the // same certificate once. if (find (processed_certs.begin (), processed_certs.end (), server->certinfo) != processed_certs.end ()) continue; processed_certs.push_back (server->certinfo); // We need not contact the server if it is already trusted. if (find (already_trusted.begin (), already_trusted.end (), *server) != already_trusted.end ()) { if (s.verbose >= 2) trust_already_in_place (*server, server_list, cert_db_path, false/*revoking*/); continue; } // At a minimum we need an ip_address along with a port // number in order to contact the server. if (! server->hasAddress() || server->port() == 0) continue; int rc = client_connect (*server, NULL, NULL, "permanent"); if (rc != SUCCESS) { clog << _F("Unable to connect to %s", lex_cast(*server).c_str()) << endl; nssError (); // Additional information: if the address is IPv6 and is link-local, then it must // have a scope_id. if (isIPv6LinkLocal (server->address) && server->address.ipv6.scope_id == 0) { clog << _(" The address is an IPv6 link-local address with no scope specifier.") << endl; } } } cleanup: // Shutdown NSS. // SSL_ClearSessionCache is required before shutdown for client applications. SSL_ClearSessionCache (); nssCleanup (cert_db_path.c_str ()); // Make sure the database files are readable. glob_t globbuf; string filespec = cert_db_path + "/*.db"; if (s.verbose >= 3) clog << _F("Searching \"%s\"\n", filespec.c_str()); int r = glob (filespec.c_str (), 0, NULL, & globbuf); if (r != GLOB_NOSPACE && r != GLOB_ABORTED && r != GLOB_NOMATCH) { for (unsigned i = 0; i < globbuf.gl_pathc; ++i) { string filename = globbuf.gl_pathv[i]; if (s.verbose >= 3) clog << _(" found ") << filename << endl; if (chmod (filename.c_str (), 0644) != 0) { s.print_warning("Unable to change permissions on " + filename + ": "); perror (""); } } } } // Remove the given servers from the given database of trusted servers. static void revoke_server_trust ( systemtap_session &s, const string &cert_db_path, const vector &server_list ) { // Make sure the given path exists. if (! file_exists (cert_db_path)) { if (s.verbose >= 5) { clog << _F("Certificate database '%s' does not exist", cert_db_path.c_str()) << endl; for (vector::const_iterator server = server_list.begin(); server != server_list.end (); ++server) trust_already_in_place (*server, server_list, cert_db_path, true/*revoking*/); } return; } // Must predeclare these because of jumps to cleanup: below. CERTCertDBHandle *handle; PRArenaPool *tmpArena = NULL; CERTCertList *certs = NULL; CERTCertificate *db_cert; vector processed_certs; const char *nickname; // Make sure NSPR is initialized. Must be done before NSS is initialized s.NSPR_init (); // Initialize the NSS libraries -- read/write SECStatus secStatus = nssInit (cert_db_path.c_str (), 1/*readwrite*/); if (secStatus != SECSuccess) { // Message already issued goto cleanup; } handle = CERT_GetDefaultCertDB(); // A memory pool to work in tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (! tmpArena) { clog << _("Out of memory:"); nssError (); goto cleanup; } // Iterate over the servers to become untrusted. nickname = server_cert_nickname (); for (vector::const_iterator server = server_list.begin(); server != server_list.end (); ++server) { // If the server's certificate serial number is unknown, then we can't // match it with one in the database. if (server->certinfo.empty ()) continue; // Trust is based on certificates. We need only revoke trust in the same // certificate once. if (find (processed_certs.begin (), processed_certs.end (), server->certinfo) != processed_certs.end ()) continue; processed_certs.push_back (server->certinfo); // Search the client-side database of trusted servers. db_cert = PK11_FindCertFromNickname (nickname, NULL); if (! db_cert) { // No trusted servers. Not an error, but issue a status message. if (s.verbose >= 2) trust_already_in_place (*server, server_list, cert_db_path, true/*revoking*/); continue; } // Here, we have one cert with the desired nickname. // Now, we will attempt to get a list of ALL certs // with the same subject name as the cert we have. That list // should contain, at a minimum, the one cert we have already found. // If the list of certs is empty (NULL), the libraries have failed. certs = CERT_CreateSubjectCertList (NULL, handle, & db_cert->derSubject, PR_Now (), PR_FALSE); CERT_DestroyCertificate (db_cert); if (! certs) { clog << _F("Unable to query certificate database %s: ", cert_db_path.c_str()) << endl; PORT_SetError (SEC_ERROR_LIBRARY_FAILURE); nssError (); goto cleanup; } // Find the certificate matching the one belonging to our server. CERTCertListNode *node; for (node = CERT_LIST_HEAD (certs); ! CERT_LIST_END (node, certs); node = CERT_LIST_NEXT (node)) { // The certificate we're working with. db_cert = node->cert; // Get the serial number. string serialNumber = get_cert_serial_number (db_cert); // Does the serial number match that of the current server? if (serialNumber != server->certinfo) continue; // goto next certificate // All is ok! Remove the certificate from the database. break; } // Loop over certificates in the database // Was a certificate matching the server found? */ if (CERT_LIST_END (node, certs)) { // Not found. Server is already untrusted. if (s.verbose >= 2) trust_already_in_place (*server, server_list, cert_db_path, true/*revoking*/); } else { secStatus = SEC_DeletePermCertificate (db_cert); if (secStatus != SECSuccess) { clog << _F("Unable to remove certificate from %s: ", cert_db_path.c_str()) << endl; nssError (); } } CERT_DestroyCertList (certs); certs = NULL; } // Loop over servers cleanup: assert(!certs); if (tmpArena) PORT_FreeArena (tmpArena, PR_FALSE); nssCleanup (cert_db_path.c_str ()); } // Obtain information about servers from the certificates in the given database. static void get_server_info_from_db ( systemtap_session &s, vector &servers, const string &cert_db_path ) { // Make sure the given path exists. if (! file_exists (cert_db_path)) { if (s.verbose >= 5) clog << _F("Certificate database '%s' does not exist.", cert_db_path.c_str()) << endl; return; } // Make sure NSPR is initialized. Must be done before NSS is initialized s.NSPR_init (); // Initialize the NSS libraries -- readonly SECStatus secStatus = nssInit (cert_db_path.c_str ()); if (secStatus != SECSuccess) { // Message already issued. return; } // Must predeclare this because of jumps to cleanup: below. PRArenaPool *tmpArena = NULL; CERTCertList *certs = get_cert_list_from_db (server_cert_nickname ()); if (! certs) { if (s.verbose >= 5) clog << _F("No certificate found in database %s", cert_db_path.c_str ()) << endl; goto cleanup; } // A memory pool to work in tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (! tmpArena) { clog << _("Out of memory:"); nssError (); goto cleanup; } for (CERTCertListNode *node = CERT_LIST_HEAD (certs); ! CERT_LIST_END (node, certs); node = CERT_LIST_NEXT (node)) { compile_server_info server_info; // The certificate we're working with. CERTCertificate *db_cert = node->cert; // Get the host name. It is in the alt-name extension of the // certificate. SECItem subAltName; subAltName.data = NULL; secStatus = CERT_FindCertExtension (db_cert, SEC_OID_X509_SUBJECT_ALT_NAME, & subAltName); if (secStatus != SECSuccess || ! subAltName.data) { clog << _("Unable to find alt name extension on server certificate: ") << endl; nssError (); continue; } // Decode the extension. CERTGeneralName *nameList = CERT_DecodeAltNameExtension (tmpArena, & subAltName); SECITEM_FreeItem(& subAltName, PR_FALSE); if (! nameList) { clog << _("Unable to decode alt name extension on server certificate: ") << endl; nssError (); continue; } // We're interested in the first alternate name. assert (nameList->type == certDNSName); server_info.host_name = string ((const char *)nameList->name.other.data, nameList->name.other.len); // Don't free nameList. It's part of the tmpArena. // Get the serial number. server_info.certinfo = get_cert_serial_number (db_cert); // Our results will at a minimum contain this server. add_server_info (server_info, servers); // Augment the list by querying all online servers and keeping the ones // with the same cert serial number. vector online_servers; get_or_keep_online_server_info (s, online_servers, false/*keep*/); keep_server_info_with_cert_and_port (s, server_info, online_servers); add_server_info (online_servers, servers); } cleanup: if (certs) CERT_DestroyCertList (certs); if (tmpArena) PORT_FreeArena (tmpArena, PR_FALSE); nssCleanup (cert_db_path.c_str ()); } // Utility Functions. //----------------------------------------------------------------------- ostream &operator<< (ostream &s, const compile_server_info &i) { // Don't print empty information if (i.empty ()) return s; s << " host="; if (! i.host_name.empty ()) s << i.host_name; else s << "unknown"; s << " address="; if (i.hasAddress()) { PRStatus prStatus; switch (i.address.raw.family) { case PR_AF_INET: case PR_AF_INET6: { #define MAX_NETADDR_SIZE 46 // from the NSPR API reference. char buf[MAX_NETADDR_SIZE]; prStatus = PR_NetAddrToString(& i.address, buf, sizeof (buf)); if (prStatus == PR_SUCCESS) { s << buf; break; } } // Fall through default: s << "offline"; break; } } else s << "offline"; s << " port="; if (i.port() != 0) s << i.port(); else s << "unknown"; s << " sysinfo=\""; if (! i.sysinfo.empty ()) s << i.sysinfo << '"'; else s << "unknown\""; s << " version="; if (! i.version.empty ()) s << i.version; else s << "unknown"; s << " certinfo=\""; if (! i.certinfo.empty ()) s << i.certinfo << '"'; else s << "unknown\""; return s; } ostream &operator<< (ostream &s, const vector &v) { // Indicate an empty list. if (v.size () == 0 || (v.size () == 1 && v[0].empty())) s << "No Servers" << endl; else { for (unsigned i = 0; i < v.size(); ++i) { // Don't print empty items. if (! v[i].empty()) s << v[i] << endl; } } return s; } PRNetAddr & copyNetAddr (PRNetAddr &x, const PRNetAddr &y) { PRUint32 saveScope = 0; // For IPv6 addresses, don't overwrite the scope_id of x unless x is uninitialized or it is 0. if (x.raw.family == PR_AF_INET6) saveScope = x.ipv6.scope_id; x = y; if (saveScope != 0) x.ipv6.scope_id = saveScope; return x; } bool operator== (const PRNetAddr &x, const PRNetAddr &y) { // Same address family? if (x.raw.family != y.raw.family) return false; switch (x.raw.family) { case PR_AF_INET6: // If both scope ids are set, compare them. if (x.ipv6.scope_id != 0 && y.ipv6.scope_id != 0 && x.ipv6.scope_id != y.ipv6.scope_id) return false; // not equal // Scope is not a factor. Compare the address bits return memcmp (& x.ipv6.ip, & y.ipv6.ip, sizeof(x.ipv6.ip)) == 0; case PR_AF_INET: return x.inet.ip == y.inet.ip; default: break; } return false; } bool operator!= (const PRNetAddr &x, const PRNetAddr &y) { return !(x == y); } static PRIPv6Addr & copyAddress (PRIPv6Addr &PRin6, const in6_addr &in6) { // The NSPR type is a typedef of struct in6_addr, but C++ won't let us copy it assert (sizeof (PRin6) == sizeof (in6)); memcpy (& PRin6, & in6, sizeof (PRin6)); return PRin6; } // Return the default server specification, used when none is given on the // command line. static string default_server_spec (const systemtap_session &s) { // If --privilege=X has been used, where X is not stapdev, // the default is online,trusted,compatible,signer // otherwise // the default is online,trusted,compatible // // Having said that, // 'online' and 'compatible' will only succeed if we have avahi // 'trusted' and 'signer' will only succeed if we have NSS // string working_string = "online,trusted,compatible"; if (! pr_contains (s.privilege, pr_stapdev)) working_string += ",signer"; return working_string; } static int server_spec_to_pmask (const string &server_spec) { // Construct a mask of the server properties that have been requested. // The available properties are: // trusted - servers which are trusted SSL peers. // online - online servers. // compatible - servers which compile for the current kernel release // and architecture. // signer - servers which are trusted module signers. // specified - servers which have been specified using --use-server=XXX. // If no servers have been specified, then this is // equivalent to --list-servers=trusted,online,compatible. // all - all trusted servers, trusted module signers, // servers currently online and specified servers. string working_spec = server_spec; vector properties; tokenize (working_spec, properties, ","); int pmask = 0; unsigned limit = properties.size (); for (unsigned i = 0; i < limit; ++i) { const string &property = properties[i]; // Tolerate (and ignore) empty properties. if (property.empty ()) continue; if (property == "all") { pmask |= compile_server_all; } else if (property == "specified") { pmask |= compile_server_specified; } else if (property == "trusted") { pmask |= compile_server_trusted; } else if (property == "online") { pmask |= compile_server_online; } else if (property == "compatible") { pmask |= compile_server_compatible; } else if (property == "signer") { pmask |= compile_server_signer; } else { // XXX PR13274 needs-session to use print_warning() clog << _F("WARNING: unsupported compile server property: %s", property.c_str()) << endl; } } return pmask; } void query_server_status (systemtap_session &s) { unsigned limit = s.server_status_strings.size (); for (unsigned i = 0; i < limit; ++i) query_server_status (s, s.server_status_strings[i]); } static void query_server_status (systemtap_session &s, const string &status_string) { // If this string is empty, then the default is "specified" string working_string = status_string; if (working_string.empty ()) working_string = "specified"; // If the query is "specified" and no servers have been specified // (i.e. --use-server not used or used with no argument), then // use the default query. // TODO: This may not be necessary. The underlying queries should handle // "specified" properly. if (working_string == "specified" && (s.specified_servers.empty () || (s.specified_servers.size () == 1 && s.specified_servers[0].empty ()))) working_string = default_server_spec (s); int pmask = server_spec_to_pmask (working_string); // Now obtain a list of the servers which match the criteria. vector raw_servers; get_server_info (s, pmask, raw_servers); // Augment the listing with as much information as possible by adding // information from known servers. vector servers; get_all_server_info (s, servers); keep_common_server_info (raw_servers, servers); // Sort the list of servers into a preferred order. preferred_order (servers); // Print the server information. Skip the empty entry at the head of the list. clog << _F("Systemtap Compile Server Status for '%s'", working_string.c_str()) << endl; bool found = false; unsigned limit = servers.size (); for (unsigned i = 0; i < limit; ++i) { assert (! servers[i].empty ()); // Don't list servers with no cert information. They may not actually // exist. // TODO: Could try contacting the server and obtaining its cert if (servers[i].certinfo.empty ()) continue; clog << servers[i] << endl; found = true; } if (! found) clog << _("No servers found") << endl; } // Add or remove trust of the servers specified on the command line. void manage_server_trust (systemtap_session &s) { // This function should do nothing if we don't have NSS. // Nothing to do if --trust-servers was not specified. if (s.server_trust_spec.empty ()) return; // Break up and analyze the trust specification. Recognized components are: // ssl - trust the specified servers as ssl peers // signer - trust the specified servers as module signers // revoke - revoke the requested trust // all-users - apply/revoke the requested trust for all users // no-prompt - don't prompt the user for confirmation vectorcomponents; tokenize (s.server_trust_spec, components, ","); bool ssl = false; bool signer = false; bool revoke = false; bool all_users = false; bool no_prompt = false; bool error = false; for (vector::const_iterator i = components.begin (); i != components.end (); ++i) { if (*i == "ssl") ssl = true; else if (*i == "signer") { if (geteuid () != 0) { clog << _("Only root can specify 'signer' on --trust-servers") << endl; error = true; } else signer = true; } else if (*i == "revoke") revoke = true; else if (*i == "all-users") { if (geteuid () != 0) { clog << _("Only root can specify 'all-users' on --trust-servers") << endl; error = true; } else all_users = true; } else if (*i == "no-prompt") no_prompt = true; else s.print_warning("Unrecognized server trust specification: " + *i); } if (error) return; // Make sure NSPR is initialized s.NSPR_init (); // Now obtain the list of specified servers. vector server_list; get_specified_server_info (s, server_list, true/*no_default*/); // Did we identify any potential servers? unsigned limit = server_list.size (); if (limit == 0) { clog << _("No servers identified for trust") << endl; return; } // Create a string representing the request in English. // If neither 'ssl' or 'signer' was specified, the default is 'ssl'. if (! ssl && ! signer) ssl = true; ostringstream trustString; if (ssl) { trustString << _("as an SSL peer"); if (all_users) trustString << _(" for all users"); else trustString << _(" for the current user"); } if (signer) { if (ssl) trustString << _(" and "); trustString << _("as a module signer for all users"); } // Prompt the user to confirm what's about to happen. if (no_prompt) { if (revoke) clog << _("Revoking trust "); else clog << _("Adding trust "); } else { if (revoke) clog << _("Revoke trust "); else clog << _("Add trust "); } clog << _F("in the following servers %s", trustString.str().c_str()); if (! no_prompt) clog << '?'; clog << endl; for (unsigned i = 0; i < limit; ++i) clog << " " << server_list[i] << endl; if (! no_prompt) { clog << "[y/N] " << flush; // Only carry out the operation if the response is "yes" string response; cin >> response; if (response[0] != 'y' && response [0] != 'Y') { clog << _("Server trust unchanged") << endl; return; } } // Now add/revoke the requested trust. string cert_db_path; if (ssl) { if (all_users) cert_db_path = global_ssl_cert_db_path (); else cert_db_path = private_ssl_cert_db_path (); if (revoke) revoke_server_trust (s, cert_db_path, server_list); else add_server_trust (s, cert_db_path, server_list); } if (signer) { cert_db_path = signing_cert_db_path (); if (revoke) revoke_server_trust (s, cert_db_path, server_list); else add_server_trust (s, cert_db_path, server_list); } } static compile_server_cache* cscache(systemtap_session& s) { if (!s.server_cache) s.server_cache = new compile_server_cache(); return s.server_cache; } static void get_server_info ( systemtap_session &s, int pmask, vector &servers ) { // Get information on compile servers matching the requested criteria. // The order of queries is significant. Accumulating queries must go first // followed by accumulating/filtering queries. bool keep = false; if (((pmask & compile_server_all))) { get_all_server_info (s, servers); keep = true; } // Add the specified servers, if requested if ((pmask & compile_server_specified)) { get_specified_server_info (s, servers); keep = true; } // Now filter or accumulate the list depending on whether a query has // already been made. if ((pmask & compile_server_online)) { get_or_keep_online_server_info (s, servers, keep); keep = true; } if ((pmask & compile_server_trusted)) { get_or_keep_trusted_server_info (s, servers, keep); keep = true; } if ((pmask & compile_server_signer)) { get_or_keep_signing_server_info (s, servers, keep); keep = true; } if ((pmask & compile_server_compatible)) { get_or_keep_compatible_server_info (s, servers, keep); keep = true; } } // Get information about all online servers as well as servers trusted // as SSL peers and servers trusted as signers. static void get_all_server_info ( systemtap_session &s, vector &servers ) { // We only need to obtain this once per session. This is a good thing(tm) // since obtaining this information is expensive. vector& all_servers = cscache(s)->all_servers; if (all_servers.empty ()) { get_or_keep_online_server_info (s, all_servers, false/*keep*/); get_or_keep_trusted_server_info (s, all_servers, false/*keep*/); get_or_keep_signing_server_info (s, all_servers, false/*keep*/); if (s.verbose >= 4) { clog << _("All known servers:") << endl; clog << all_servers; } } // Add the information, but not duplicates. add_server_info (all_servers, servers); } static void get_default_server_info ( systemtap_session &s, vector &servers ) { if (s.verbose >= 3) clog << _("Using the default servers") << endl; // We only need to obtain this once per session. This is a good thing(tm) // since obtaining this information is expensive. vector& default_servers = cscache(s)->default_servers; if (default_servers.empty ()) { // Get the required information. // get_server_info will add an empty entry at the beginning to indicate // that the search has been performed, in case the search comes up empty. int pmask = server_spec_to_pmask (default_server_spec (s)); get_server_info (s, pmask, default_servers); if (s.verbose >= 3) { clog << _("Default servers are:") << endl; clog << default_servers; } } // Add the information, but not duplicates. add_server_info (default_servers, servers); } static bool isPort (const char *pstr, compile_server_info &server_info) { errno = 0; char *estr; unsigned long p = strtoul (pstr, & estr, 10); if (errno != 0 || *estr != '\0' || p > USHRT_MAX) { clog << _F("Invalid port number specified: %s", pstr) << endl; return false; } server_info.setPort (p); return true; } static bool isIPv6 (const string &server, compile_server_info &server_info) { // An IPv6 address is 8 hex components separated by colons. // One contiguous block of zero segments in the address may be elided using ::. // An interface may be specified by appending %IF_NAME to the address (e.g. %eth0). // A port may be specified by enclosing the ip address in [] and adding :. // Allow a bracketed address without a port. assert (! server.empty()); string ip; string::size_type portIx; if (server[0] == '[') { string::size_type endBracket = server.find (']'); if (endBracket == string::npos) return false; // Not a valid IPv6 address // Extract the address. ip = server.substr (1, endBracket - 1); portIx = endBracket + 1; } else { ip = server; portIx = string::npos; } // Find out how many components there are. The maximum is 8 unsigned empty = 0; vector components; tokenize_full (ip, components, ":"); if (components.size() > 8) return false; // Not a valid IPv6 address // The components must be either hex values between 0 and 0xffff, or must be empty. // There can be only one empty component. string interface; for (unsigned i = 0; i < components.size(); ++i) { if (components[i].empty()) { if (++empty > 1) return false; // Not a valid IPv6 address } // If it's the final component, see if it specifies the interface. If so, strip it from the // component in order to simplify parsing. It still remains as part of the original ip address // string. if (i == components.size() - 1) { size_t ix = components[i].find ('%'); if (ix != string::npos) { interface = components[i].substr(ix); components[i] = components[i].substr(0, ix); } } // Skip leading zeroes. unsigned j; for (j = 0; j < components[i].size(); ++j) { if (components[i][j] != '0') break; } // Max of 4 hex digits if (components[i].size() - j > 4) return false; // Not a valid IPv6 address for (/**/; j < components[i].size(); ++j) { if (! isxdigit (components[i][j])) return false; // Not a valid IPv6 address } } // If there is no empty component, then there must be exactly 8 components. if (! empty && components.size() != 8) return false; // Not a valid IPv6 address // Calls to setPort and isPort need to know that this is an IPv6 address. server_info.address.raw.family = PR_AF_INET6; // Examine the optional port if (portIx != string::npos) { string port = server.substr (portIx); if (port.size() != 0) { if (port.size() < 2 || port[0] != ':') return false; // Not a valid Port port = port.substr (1); if (! isPort (port.c_str(), server_info)) return false; // not a valid port } } else server_info.setPort (0); // Treat the ip address string like a host name. server_info.host_name = ip; return true; // valid IPv6 address. } static bool isIPv4 (const string &server, compile_server_info &server_info) { // An IPv4 address is 4 decimal components separated by periods with an // additional optional decimal port separated from the address by a colon. assert (! server.empty()); // Find out how many components there are. The maximum is 8 vector components; tokenize (server, components, ":"); if (components.size() > 2) return false; // Not a valid IPv4 address // Separate the host from the port (if any). string host; string port; if (components.size() <= 1) host = server; else { host = components[0]; port = components[1]; } // Separate the host components. // There must be exactly 4 components. components.clear (); tokenize (server, components, "."); if (components.size() != 4) return false; // Not a valid IPv4 address // The components must be decimal values between 0 and 255. for (unsigned i = 0; i < components.size(); ++i) { if (components[i].empty()) return false; // Not a valid IPv4 address errno = 0; char *estr; long p = strtol (components[i].c_str(), & estr, 10); if (errno != 0 || *estr != '\0' || p < 0 || p > 255) return false; // Not a valid IPv4 address } // Calls to setPort and isPort need to know that this is an IPv4 address. server_info.address.raw.family = PR_AF_INET; // Examine the optional port if (! port.empty ()) { if (! isPort (port.c_str(), server_info)) return false; // not a valid port } else server_info.setPort (0); // Treat the ip address string like a host name. server_info.host_name = host; return true; // valid IPv4 address. } static bool isCertSerialNumber (const string &server, compile_server_info &server_info) { // This function assumes that we have already ruled out the server spec being an IPv6 address. // Certificate serial numbers are 5 fields separated by colons plus an optional 6th decimal // field specifying a port. // Assume IPv4 (for now) when storing the port. server_info.address.raw.family = PR_AF_INET; assert (! server.empty()); string host = server; vector components; tokenize (host, components, ":"); switch (components.size ()) { case 6: if (! isPort (components.back().c_str(), server_info)) return false; // not a valid port host = host.substr (0, host.find_last_of (':')); // fall through case 5: server_info.certinfo = host; break; default: return false; // not a cert serial number } return true; // valid cert serial number and optional port } static bool isDomain (const string &server, compile_server_info &server_info) { // Accept one or two components separated by a colon. The first will be the domain name and // the second must a port number. // Assume IPv4 (for now) when storing the port. server_info.address.raw.family = PR_AF_INET; assert (! server.empty()); string host = server; vector components; tokenize (host, components, ":"); switch (components.size ()) { case 2: if (! isPort (components.back().c_str(), server_info)) return false; // not a valid port host = host.substr (0, host.find_last_of (':')); // fall through case 1: server_info.host_name = host; break; default: return false; // not a valid domain name } return true; } static void get_specified_server_info ( systemtap_session &s, vector &servers, bool no_default ) { // We only need to obtain this once per session. This is a good thing(tm) // since obtaining this information is expensive. vector& specified_servers = cscache(s)->specified_servers; if (specified_servers.empty ()) { // Maintain an empty entry to indicate that this search has been // performed, in case the search comes up empty. specified_servers.push_back (compile_server_info ()); // If --use-server was not specified at all, then return info for the // default server list. if (s.specified_servers.empty ()) { if (s.verbose >= 3) clog << _("No servers specified") << endl; if (! no_default) get_default_server_info (s, specified_servers); } else { // Iterate over the specified servers. For each specification, add to // the list of servers. unsigned num_specified_servers = s.specified_servers.size (); for (unsigned i = 0; i < num_specified_servers; ++i) { string &server = s.specified_servers[i]; // If no specific server(s) specified, then use the default servers. if (server.empty ()) { if (s.verbose >= 3) clog << _("No servers specified") << endl; if (! no_default) get_default_server_info (s, specified_servers); continue; } // Determine what has been specified. Servers may be specified by: // - domain{:port} // - certificate-serial-number{:port} // - IPv4-address{:port} // - IPv6-address{:port} // where items within {} are optional. // Check for IPv6 addresses first. It reduces the amount of checking necessary for // certificate serial numbers. compile_server_info server_info; vector known_servers; if (isIPv6 (server, server_info) || isIPv4 (server, server_info) || isDomain (server, server_info)) { // Resolve this host and add any information that is discovered. // Try to augment the resolved servers with information about known servers. // There may be no intersection. get_all_server_info (s, known_servers); vector resolved_servers; resolve_host (s, server_info, resolved_servers); vector common_servers = resolved_servers; keep_common_server_info (known_servers, common_servers); if (! common_servers.empty ()) add_server_info (common_servers, resolved_servers); if (s.verbose >= 3) { clog << _F("Servers matching %s: ", server.c_str()) << endl; clog << resolved_servers; } add_server_info (resolved_servers, specified_servers); } else if (isCertSerialNumber (server, server_info)) { // The host could not be resolved. Try resolving it as a certificate serial // number. Look for all known servers with this serial number and (optional) // port number. get_all_server_info (s, known_servers); keep_server_info_with_cert_and_port (s, server_info, known_servers); if (s.verbose >= 3) { clog << _F("Servers matching %s: ", server.c_str()) << endl; clog << known_servers; } add_server_info (known_servers, specified_servers); } else { clog << _F("Invalid server specification for --use-server: %s", server.c_str()) << endl; } } // Loop over --use-server options } // -- use-server specified if (s.verbose >= 2) { clog << _("All specified servers:") << endl; clog << specified_servers; } } // Server information is not cached // Add the information, but not duplicates. add_server_info (specified_servers, servers); } static void get_or_keep_trusted_server_info ( systemtap_session &s, vector &servers, bool keep ) { // If we're filtering the list and it's already empty, then // there's nothing to do. if (keep && servers.empty ()) return; // We only need to obtain this once per session. This is a good thing(tm) // since obtaining this information is expensive. vector& trusted_servers = cscache(s)->trusted_servers; if (trusted_servers.empty ()) { // Maintain an empty entry to indicate that this search has been // performed, in case the search comes up empty. trusted_servers.push_back (compile_server_info ()); // Check the private database first. string cert_db_path = private_ssl_cert_db_path (); get_server_info_from_db (s, trusted_servers, cert_db_path); // Now check the global database. cert_db_path = global_ssl_cert_db_path (); get_server_info_from_db (s, trusted_servers, cert_db_path); if (s.verbose >= 5) { clog << _("All servers trusted as ssl peers:") << endl; clog << trusted_servers; } } // Server information is not cached if (keep) { // Filter the existing vector by keeping the information in common with // the trusted_server vector. keep_common_server_info (trusted_servers, servers); } else { // Add the information, but not duplicates. add_server_info (trusted_servers, servers); } } static void get_or_keep_signing_server_info ( systemtap_session &s, vector &servers, bool keep ) { // If we're filtering the list and it's already empty, then // there's nothing to do. if (keep && servers.empty ()) return; // We only need to obtain this once per session. This is a good thing(tm) // since obtaining this information is expensive. vector& signing_servers = cscache(s)->signing_servers; if (signing_servers.empty ()) { // Maintain an empty entry to indicate that this search has been // performed, in case the search comes up empty. signing_servers.push_back (compile_server_info ()); // For all users, check the global database. string cert_db_path = signing_cert_db_path (); get_server_info_from_db (s, signing_servers, cert_db_path); if (s.verbose >= 5) { clog << _("All servers trusted as module signers:") << endl; clog << signing_servers; } } // Server information is not cached if (keep) { // Filter the existing vector by keeping the information in common with // the signing_server vector. keep_common_server_info (signing_servers, servers); } else { // Add the information, but not duplicates. add_server_info (signing_servers, servers); } } static void get_or_keep_compatible_server_info ( systemtap_session &s, vector &servers, bool keep ) { #if HAVE_AVAHI // If we're filtering the list and it's already empty, then // there's nothing to do. if (keep && servers.empty ()) return; // Remove entries for servers incompatible with the host environment // from the given list of servers. // A compatible server compiles for the kernel release and architecture // of the host environment. // // Compatibility can only be determined for online servers. So, augment // and filter the information we have with information for online servers. vector online_servers; get_or_keep_online_server_info (s, online_servers, false/*keep*/); if (keep) keep_common_server_info (online_servers, servers); else add_server_info (online_servers, servers); // Now look to see which ones are compatible. // The vector can change size as we go, so be careful!! for (unsigned i = 0; i < servers.size (); /**/) { // Retain empty entries. assert (! servers[i].empty ()); // Check the target of the server. if (servers[i].sysinfo != s.kernel_release + " " + s.architecture) { // Target platform mismatch. servers.erase (servers.begin () + i); continue; } // The server is compatible. Leave it in the list. ++i; } #else // ! HAVE_AVAHI // Without Avahi, we can't obtain the target platform of the server. // Issue a warning. if (s.verbose >= 2) clog << _("Unable to detect server compatibility without avahi") << endl; if (keep) servers.clear (); #endif } static void keep_server_info_with_cert_and_port ( systemtap_session &, const compile_server_info &server, vector &servers ) { assert (! server.certinfo.empty ()); // Search the list of servers for ones matching the // serial number specified. // The vector can change size as we go, so be careful!! for (unsigned i = 0; i < servers.size (); /**/) { // Retain empty entries. if (servers[i].empty ()) { ++i; continue; } if (servers[i].certinfo == server.certinfo && (servers[i].port() == 0 || server.port() == 0 || servers[i].port() == server.port())) { // If the server is not online, then use the specified // port, if any. if (servers[i].port() == 0) servers[i].setPort (server.port()); ++i; continue; } // The item does not match. Delete it. servers.erase (servers.begin () + i); } } // Obtain missing host name or ip address, if any. Return 0 on success. static void resolve_host ( systemtap_session& s, compile_server_info &server, vector &resolved_servers ) { vector& cached_servers = cscache(s)->resolved_servers[server.host_name]; if (cached_servers.empty ()) { // The server's host_name member is a string containing either a host name or an ip address. // Either is acceptable for lookup. const char *lookup_name = server.host_name.c_str(); if (s.verbose >= 6) clog << _F("Looking up %s", lookup_name) << endl; struct addrinfo hints; memset(& hints, 0, sizeof (hints)); hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version struct addrinfo *addr_info = 0; int rc = getaddrinfo (lookup_name, NULL, & hints, & addr_info); // Failure to resolve will result in an appropriate message later, if other methods fail. if (rc != 0) { // At a minimum, return the information we were given. if (s.verbose >= 6) clog << _F("%s not found: %s", lookup_name, gai_strerror (rc)) << endl; add_server_info (server, cached_servers); } else { // Loop over the results collecting information. assert (addr_info); for (const struct addrinfo *ai = addr_info; ai != NULL; ai = ai->ai_next) { // Start with the info we were given. compile_server_info new_server = server; // We support IPv4 and IPv6, Ignore other protocols, if (ai->ai_family == AF_INET) { // IPv4 Address struct sockaddr_in *ip = (struct sockaddr_in *)ai->ai_addr; new_server.address.inet.family = PR_AF_INET; if (ip->sin_port != 0) new_server.address.inet.port = ip->sin_port; new_server.address.inet.ip = ip->sin_addr.s_addr; } else if (ai->ai_family == AF_INET6) { // IPv6 Address struct sockaddr_in6 *ip = (struct sockaddr_in6 *)ai->ai_addr; new_server.address.ipv6.family = PR_AF_INET6; if (ip->sin6_port != 0) new_server.address.ipv6.port = ip->sin6_port; new_server.address.ipv6.scope_id = ip->sin6_scope_id; copyAddress (new_server.address.ipv6.ip, ip->sin6_addr); } else continue; // Try to obtain a host name. Otherwise, leave it empty. char hbuf[NI_MAXHOST]; int status = getnameinfo (ai->ai_addr, ai->ai_addrlen, hbuf, sizeof (hbuf), NULL, 0, NI_NAMEREQD | NI_IDN); if (status == 0) new_server.host_name = hbuf; // Add the new resolved server to the list. add_server_info (new_server, cached_servers); } } if (addr_info) freeaddrinfo (addr_info); // free the linked list if (s.verbose >= 6) { clog << _F("%s resolves to:", lookup_name) << endl; clog << cached_servers; } } // Add the information, but not duplicates. add_server_info (cached_servers, resolved_servers); } #if HAVE_AVAHI // Avahi API Callbacks. //----------------------------------------------------------------------- struct browsing_context { AvahiSimplePoll *simple_poll; AvahiClient *client; vector *servers; }; static string extract_field_from_avahi_txt (const string &label, const string &txt) { // Extract the requested field from the Avahi TXT. string prefix = "\"" + label; size_t ix = txt.find (prefix); if (ix == string::npos) { // Label not found. return ""; } // This is the start of the field. string field = txt.substr (ix + prefix.size ()); // Find the end of the field. ix = field.find('"'); if (ix != string::npos) field = field.substr (0, ix); return field; } extern "C" void resolve_callback( AvahiServiceResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags /*flags*/, AVAHI_GCC_UNUSED void* userdata) { PRStatus prStatus; assert(r); const browsing_context *context = (browsing_context *)userdata; vector *servers = context->servers; // Called whenever a service has been resolved successfully or timed out. switch (event) { case AVAHI_RESOLVER_FAILURE: clog << _F("Failed to resolve service '%s' of type '%s' in domain '%s': %s", name, type, domain, avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r)))) << endl; break; case AVAHI_RESOLVER_FOUND: { compile_server_info info; // Decode the address. char a[AVAHI_ADDRESS_STR_MAX]; avahi_address_snprint(a, sizeof(a), address); prStatus = PR_StringToNetAddr (a, & info.address); if (prStatus != PR_SUCCESS) { clog << _F("Invalid address '%s' from avahi", a) << endl; break; } // We support both IPv4 and IPv6. Ignore other protocols. if (protocol == AVAHI_PROTO_INET6) { info.address.ipv6.family = PR_AF_INET6; info.address.ipv6.port = htons (port); info.address.ipv6.scope_id = interface; } else if (protocol == AVAHI_PROTO_INET) { info.address.inet.family = PR_AF_INET; info.address.inet.port = htons (port); } else break; // Save the host name. info.host_name = host_name; // Save the text tags. char *t = avahi_string_list_to_string(txt); info.sysinfo = extract_field_from_avahi_txt ("sysinfo=", t); info.certinfo = extract_field_from_avahi_txt ("certinfo=", t); info.version = extract_field_from_avahi_txt ("version=", t); if (info.version.empty ()) info.version = "1.0"; // default version is 1.0 avahi_free(t); // Add this server to the list of discovered servers. add_server_info (info, *servers); } } avahi_service_resolver_free(r); } extern "C" void browse_callback( AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AVAHI_GCC_UNUSED AvahiLookupResultFlags flags, void* userdata) { browsing_context *context = (browsing_context *)userdata; AvahiClient *c = context->client; AvahiSimplePoll *simple_poll = context->simple_poll; assert(b); // Called whenever a new services becomes available on the LAN or is removed from the LAN. switch (event) { case AVAHI_BROWSER_FAILURE: clog << _F("Avahi browse failed: %s", avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b)))) << endl; avahi_simple_poll_quit(simple_poll); break; case AVAHI_BROWSER_NEW: // We ignore the returned resolver object. In the callback // function we free it. If the server is terminated before // the callback function is called the server will free // the resolver for us. if (!(avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, (AvahiLookupFlags)0, resolve_callback, context))) { clog << _F("Failed to resolve service '%s': %s", name, avahi_strerror(avahi_client_errno(c))) << endl; } break; case AVAHI_BROWSER_REMOVE: case AVAHI_BROWSER_ALL_FOR_NOW: case AVAHI_BROWSER_CACHE_EXHAUSTED: break; } } extern "C" void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) { assert(c); browsing_context *context = (browsing_context *)userdata; AvahiSimplePoll *simple_poll = context->simple_poll; // Called whenever the client or server state changes. if (state == AVAHI_CLIENT_FAILURE) { clog << _F("Avahi Server connection failure: %s", avahi_strerror(avahi_client_errno(c))) << endl; avahi_simple_poll_quit(simple_poll); } } extern "C" void timeout_callback(AVAHI_GCC_UNUSED AvahiTimeout *e, AVAHI_GCC_UNUSED void *userdata) { browsing_context *context = (browsing_context *)userdata; AvahiSimplePoll *simple_poll = context->simple_poll; avahi_simple_poll_quit(simple_poll); } #endif // HAVE_AVAHI static void get_or_keep_online_server_info ( systemtap_session &s, vector &servers, bool keep ) { // If we're filtering the list and it's already empty, then // there's nothing to do. if (keep && servers.empty ()) return; // We only need to obtain this once per session. This is a good thing(tm) // since obtaining this information is expensive. vector& online_servers = cscache(s)->online_servers; if (online_servers.empty ()) { // Maintain an empty entry to indicate that this search has been // performed, in case the search comes up empty. online_servers.push_back (compile_server_info ()); #if HAVE_AVAHI // Must predeclare these due to jumping on error to fail: unsigned limit; vector avahi_servers; // Initialize. AvahiClient *client = NULL; AvahiServiceBrowser *sb = NULL; // Allocate main loop object. AvahiSimplePoll *simple_poll; if (!(simple_poll = avahi_simple_poll_new())) { clog << _("Failed to create Avahi simple poll object") << endl; goto fail; } browsing_context context; context.simple_poll = simple_poll; context.servers = & avahi_servers; // Allocate a new Avahi client int error; client = avahi_client_new (avahi_simple_poll_get (simple_poll), (AvahiClientFlags)0, client_callback, & context, & error); // Check whether creating the client object succeeded. if (! client) { clog << _F("Failed to create Avahi client: %s", avahi_strerror(error)) << endl; goto fail; } context.client = client; // Create the service browser. if (!(sb = avahi_service_browser_new (client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_stap._tcp", NULL, (AvahiLookupFlags)0, browse_callback, & context))) { clog << _F("Failed to create Avahi service browser: %s", avahi_strerror(avahi_client_errno(client))) << endl; goto fail; } // Timeout after 2 seconds. struct timeval tv; avahi_simple_poll_get(simple_poll)->timeout_new( avahi_simple_poll_get(simple_poll), avahi_elapse_time(&tv, 1000*2, 0), timeout_callback, & context); // Run the main loop. avahi_simple_poll_loop(simple_poll); if (s.verbose >= 6) { clog << _("Avahi reports the following servers online:") << endl; clog << avahi_servers; } // Resolve each server discovered, in case there are alternate ways to reach them // (e.g. localhost). limit = avahi_servers.size (); for (unsigned i = 0; i < limit; ++i) { compile_server_info &avahi_server = avahi_servers[i]; // Delete the domain, if it is '.local' string &host_name = avahi_server.host_name; string::size_type dot_index = host_name.find ('.'); assert (dot_index != 0); string domain = host_name.substr (dot_index + 1); if (domain == "local") host_name = host_name.substr (0, dot_index); // Add it to the list of servers, unless it is duplicate. resolve_host (s, avahi_server, online_servers); } // Merge with the list of servers, as obtained by avahi. add_server_info (avahi_servers, online_servers); fail: // Cleanup. if (sb) avahi_service_browser_free(sb); if (client) avahi_client_free(client); if (simple_poll) avahi_simple_poll_free(simple_poll); #else // ! HAVE_AVAHI // Without Avahi, we can't detect online servers. Issue a warning. if (s.verbose >= 2) clog << _("Unable to detect online servers without avahi") << endl; #endif // ! HAVE_AVAHI if (s.verbose >= 5) { clog << _("All online servers:") << endl; clog << online_servers; } } // Server information is not cached. if (keep) { // Filter the existing vector by keeping the information in common with // the online_server vector. keep_common_server_info (online_servers, servers); } else { // Add the information, but not duplicates. add_server_info (online_servers, servers); } } // Add server info to a list, avoiding duplicates. Merge information from // two duplicate items. static void add_server_info ( const compile_server_info &info, vector& target ) { if (info.empty ()) return; bool found = false; for (vector::iterator i = target.begin (); i != target.end (); ++i) { if (info == *i) { // Duplicate. Merge the two items. merge_server_info (info, *i); found = true; } } if (! found) target.push_back (info); } // Add server info from one vector to another. static void add_server_info ( const vector &source, vector &target ) { for (vector::const_iterator i = source.begin (); i != source.end (); ++i) { add_server_info (*i, target); } } // Filter the vector by keeping information in common with the item. static void keep_common_server_info ( const compile_server_info &info_to_keep, vector &filtered_info ) { assert (! info_to_keep.empty ()); // The vector may change size as we go. Be careful!! for (unsigned i = 0; i < filtered_info.size (); /**/) { // Retain empty entries. if (filtered_info[i].empty ()) { ++i; continue; } if (info_to_keep == filtered_info[i]) { merge_server_info (info_to_keep, filtered_info[i]); ++i; continue; } // The item does not match. Delete it. filtered_info.erase (filtered_info.begin () + i); continue; } } // Filter the second vector by keeping information in common with the first // vector. static void keep_common_server_info ( const vector &info_to_keep, vector &filtered_info ) { // The vector may change size as we go. Be careful!! for (unsigned i = 0; i < filtered_info.size (); /**/) { // Retain empty entries. if (filtered_info[i].empty ()) { ++i; continue; } bool found = false; for (unsigned j = 0; j < info_to_keep.size (); ++j) { if (filtered_info[i] == info_to_keep[j]) { merge_server_info (info_to_keep[j], filtered_info[i]); found = true; } } // If the item was not found. Delete it. Otherwise, advance to the next // item. if (found) ++i; else filtered_info.erase (filtered_info.begin () + i); } } // Merge two compile server info items. static void merge_server_info ( const compile_server_info &source, compile_server_info &target ) { if (target.host_name.empty ()) target.host_name = source.host_name; // Copy the address unconditionally, if the source has an address, even if they are already // equal. The source address may be an IPv6 address with a scope_id that the target is missing. assert (! target.hasAddress () || ! source.hasAddress () || source.address == target.address); if (source.hasAddress ()) copyNetAddr (target.address, source.address); if (target.port() == 0) target.setPort (source.port()); if (target.sysinfo.empty ()) target.sysinfo = source.sysinfo; if (target.version.empty ()) target.version = source.version; if (target.certinfo.empty ()) target.certinfo = source.certinfo; } #if 0 // not used right now // Merge compile server info from one item into a vector. static void merge_server_info ( const compile_server_info &source, vector &target ) { for (vector::iterator i = target.begin (); i != target.end (); ++i) { if (source == *i) merge_server_info (source, *i); } } // Merge compile server from one vector into another. static void merge_server_info ( const vector &source, vector &target ) { for (vector::const_iterator i = source.begin (); i != source.end (); ++i) merge_server_info (*i, target); } #endif #endif // HAVE_NSS /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/csclient.h000066400000000000000000000033441217430427200153720ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2010-2011 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef CSCLIENT_H #define CSCLIENT_H #if HAVE_NSS #include "cscommon.h" struct compile_server_info; class compile_server_client { public: compile_server_client (systemtap_session &s) : s(s), argc(0), server_version() {} int passes_0_4 (); private: // Client/server session methods. int initialize (); int create_request (); int package_request (); int find_and_connect_to_server (); int unpack_response (); int process_response (); // Client/server utility methods. int include_file_or_directory ( const std::string &subdir, const std::string &path ); int add_package_args (); int add_package_arg (const std::string &arg); int compile_using_server (const std::vector &servers); int add_localization_variables(); int read_from_file (const std::string &fname, int &data); template int write_to_file (const std::string &fname, const T &data); int flush_to_stream (const std::string &fname, std::ostream &o); void show_server_compatibility () const; systemtap_session &s; std::vector private_ssl_dbs; std::vector public_ssl_dbs; std::string client_tmpdir; std::string client_zipfile; std::string server_tmpdir; std::string server_zipfile; unsigned argc; cs_protocol_version server_version; }; // Utility functions void query_server_status (systemtap_session &s); void manage_server_trust (systemtap_session &s); #endif // HAVE_NSS #endif // CSCLIENT_H systemtap-2.3/cscommon.cxx000066400000000000000000000060441217430427200157570ustar00rootroot00000000000000/* Compile-server and client common functions Copyright (C) 2011 Red Hat Inc. This file is part of systemtap, and is free software. You can redistribute it and/or modify it under the terms of the GNU General Public License (GPL); either version 2, or (at your option) any later version. */ #include "config.h" // Disable the code in this file if NSS is not available #if HAVE_NSS #include "util.h" #include "cscommon.h" #include #include #include #include #include #include #include extern "C" { #include } using namespace std; cs_protocol_version::~cs_protocol_version () { assert (this->v); free ((void*)this->v); } const cs_protocol_version & cs_protocol_version::operator= (const char *v) { if (this->v) free ((void *)this->v); this->v = strdup (v); return *this; } bool cs_protocol_version::operator< (const cs_protocol_version &that) const { // Compare the levels of each version in turn. vector these_tokens; tokenize (this->v, these_tokens, "."); vector those_tokens; tokenize (that.v, those_tokens, "."); unsigned this_limit = these_tokens.size (); unsigned that_limit = those_tokens.size (); unsigned i; for (i = 0; i < this_limit && i < that_limit; ++i) { char *e; unsigned long this_level = strtoul (these_tokens[i].c_str (), & e, 0); assert (! *e); unsigned long that_level = strtoul (those_tokens[i].c_str (), & e, 0); assert (! *e); if (this_level > that_level) return false; if (this_level < that_level) return true; } // If the other version has more components, then this one is less than that one. if (i < that_limit) { assert (i == this_limit); return true; } // This version is greater than or equal to that one. return false; } int read_from_file (const string &fname, cs_protocol_version &data) { // C++ streams may not set errno in the even of a failure. However if we // set it to 0 before each operation and it gets set during the operation, // then we can use its value in order to determine what happened. string dataStr; errno = 0; ifstream f (fname.c_str ()); if (! f.good ()) { clog << _F("Unable to open file '%s' for reading: ", fname.c_str()); goto error; } // Read the data; errno = 0; f >> dataStr; if (f.fail ()) { clog << _F("Unable to read from file '%s': ", fname.c_str()); goto error; } data = dataStr.c_str (); // NB: not necessary to f.close (); return 0; // Success error: if (errno) clog << strerror (errno) << endl; else clog << _("unknown error") << endl; return 1; // Failure } string get_cert_serial_number (const CERTCertificate *cert) { ostringstream serialNumber; serialNumber << hex << setfill('0') << right; for (unsigned i = 0; i < cert->serialNumber.len; ++i) { if (i > 0) serialNumber << ':'; serialNumber << setw(2) << (unsigned)cert->serialNumber.data[i]; } return serialNumber.str (); } #endif /* HAVE_NSS */ systemtap-2.3/cscommon.h000066400000000000000000000044021217430427200154000ustar00rootroot00000000000000// Common functions and macros used by the compile-server and its client. #ifndef CSCOMMON_H #define CSCOMMON_H 1 #if HAVE_NSS extern "C" { #include #include } #endif // Versioning system for the protocol used for communication between the compile-server and client. // The original version is 1.0. After that, we use the systemtap release number. // // By Policy: // - All servers are backward compatible with clients. Servers adapt to the protocol version // of the client. // - All clients are backward compatible with servers. Clients adapt to the protocol version // of the server. Warnings are issued for servers lacking features. // // Features: // Version 1.0 // Original version // Versions 1.6 and higher // Client: // - Passes localization variables to the server in the file client_tmpdir + "/locale" // - Looks for the uprobes module in server_response + "/uprobes" // - No longer needs to remove stap's "Keeping temporary directory ..." message from // the server's stderr response. // - Looks for 'version' tag in server's avahi record and does not automatically connect to // an incompatible server. Also prefers newer servers over older ones. // Server: // - Applies localization variables passed from the client to stap during translation. // - Looks for the uprobes module in server_response + "/uprobes" // - Uses --tmpdir to specify temp directory to be used by stap, instead of -k, in order to // avoid parsing error messages in search of stap's randomly-generated temp dir. // - Advertises its protocol version using a 'version' tag in avahi. // #define CURRENT_CS_PROTOCOL_VERSION VERSION struct cs_protocol_version { cs_protocol_version (const char *v = "1.0") : v(0) { *this = v; } ~cs_protocol_version (); const cs_protocol_version &operator= (const char *v); bool operator< (const cs_protocol_version &that) const; const char *v; }; #if HAVE_NSS struct thread_arg { PRFileDesc *tcpSocket; CERTCertificate *cert; SECKEYPrivateKey *privKey; PRNetAddr addr; }; extern int read_from_file (const std::string &fname, cs_protocol_version &data); extern std::string get_cert_serial_number (const CERTCertificate *cert); #endif #endif // CSCOMMON_H systemtap-2.3/depcomp000077500000000000000000000442671217430427200150030ustar00rootroot00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2009-04-28.21; # UTC # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free # Software Foundation, Inc. # 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, 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, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by `PROGRAMS ARGS'. object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputing dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u="sed s,\\\\\\\\,/,g" depmode=msvisualcpp fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts `$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler understands `-MD -MF file'. However on # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want: # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using \ : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" # Add `dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # With Tru64 cc, shared objects can also be used to make a # static library. This mechanism is used in libtool 1.4 series to # handle both shared and static libraries in a single compilation. # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. # # With libtool 1.5 this exception was removed, and libtool now # generates 2 separate objects for the 2 libraries. These two # compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 tmpdepfile2=$dir$base.o.d # libtool 1.5 tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.o.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d tmpdepfile4=$dir$base.d "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for `:' # in the target name. This is to cope with DOS-style filenames: # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. "$@" $dashmflag | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: systemtap-2.3/doc/000077500000000000000000000000001217430427200141565ustar00rootroot00000000000000systemtap-2.3/doc/.gitignore000066400000000000000000000001231217430427200161420ustar00rootroot00000000000000*.aux *.glo *.idx *.log *.lot *.out *.pdf *.toc *.dvi _region_.* beginners langref systemtap-2.3/doc/.latex2html-init000066400000000000000000000021161217430427200172040ustar00rootroot00000000000000$CUSTOM_TITLES = 1; $CUSTOM_TITLES_LENGTH = 6; # modified version of make_long_title # does not include the section number in the title (name) of the file sub custom_title_hook { local($_)= @_; local($num_words) = $CUSTOM_TITLES_LENGTH; #RRM: scan twice for short words, due to the $4 overlap # Cannot use \b , else words break at accented letters $_ =~ s/(^|\s)\s*($GENERIC_WORDS)(\'|(\s))/$4/ig; $_ =~ s/(^|\s)\s*($GENERIC_WORDS)(\'|(\s))/$4/ig; #remove leading numbering, unless that's all there is. local($sec_num); if (!(/^\d+(\.\d*)*\s*$/)&&(s/^\s*(\d+(\.\d*)*)\s*/$sec_num=$1;''/e)) { $num_words-- }; &remove_markers; s/<[^>]*>//g; #remove tags #revert entities, etc. to TeX-form... s/([\200-\377])/"\&#".ord($1).";"/eg; $_ = &revert_to_raw_tex($_); # get $LONG_TITLES number of words from what remains $_ = &get_first_words($_, $num_words) if ($num_words); # ...and cleanup accents, spaces and punctuation $_ = join('', (0 ? $sec_num : ''), $_); s/\\\W\{?|\}//g; s/\s/_/g; s/\W/_/g; s/__+/_/g; s/_+$//; $_; } systemtap-2.3/doc/Language_Reference_Guide/000077500000000000000000000000001217430427200207745ustar00rootroot00000000000000systemtap-2.3/doc/Language_Reference_Guide/Makefile000066400000000000000000000006731217430427200224420ustar00rootroot00000000000000#Makefile for Language_Reference_Guide XML_LANG = en-US DOCNAME = Language_Reference_Guide PRODUCT = Fedora BRAND = fedora CHUNK_SECTION_DEPTH=1 #OTHER_LANGS = as-IN bn-IN de-DE es-ES fr-FR gu-IN hi-IN it-IT ja-JP kn-IN ko-KR ml-IN mr-IN or-IN pa-IN pt-BR ru-RU si-LK ta-IN te-IN zh-CN zh-TW # Extra Parameters start here # Extra Parameters stop here COMMON_CONFIG = /usr/share/publican include $(COMMON_CONFIG)/make/Makefile.common systemtap-2.3/doc/Language_Reference_Guide/README000066400000000000000000000016541217430427200216620ustar00rootroot00000000000000This is an automated source build of the Language Reference Guide, used to build it in Publican. To build the source, run: bash publicanize-langref.sh This will copy the LaTeX source of the Language Reference Guide and convert it to DocBook XML. You can now build it in pdf, html, etc using Publican. The main source of the Language Reference Guide is in: ../langref.tex As such, any revisions to this document should be applied to ../langref.tex, not to the source in this directory. IMPORTANT: The publicanize-langref.sh script uses latexml to create the raw XML files from langref.tex first before cleaning it up for Publican. You will need LaTeXML along with all its required perl modules to use publicanize-langref.sh. For more information on building from source, downloading, and installing LaTeXML, refer to the following URLs: http://dlmf.nist.gov/LaTeXML/download.html http://dlmf.nist.gov/LaTeXML/install.html systemtap-2.3/doc/Language_Reference_Guide/en-US/000077500000000000000000000000001217430427200217235ustar00rootroot00000000000000systemtap-2.3/doc/Language_Reference_Guide/en-US/Author_Group.xml000066400000000000000000000006121217430427200250620ustar00rootroot00000000000000 Robb Romans IBM Documentation robb@linux.vnet.ibm.com systemtap-2.3/doc/Language_Reference_Guide/en-US/Book_Info.xml000066400000000000000000000042401217430427200243120ustar00rootroot00000000000000 Language Reference Guide A guide to the constructs and syntax used in SystemTap scripts Fedora 10 1 1 The SystemTap Language Reference Guide is a comprehensive reference of the language constructs and syntax used in SystemTap scripts. It is suitable for users who have intermediate to advanced knowledge of SystemTap. For other available SystemTap documentation, refer to . Logo Copyright © 2007 Red Hat Inc., Copyright © 2007 IBM Corp., Copyright © 2007 Intel Corporation. This document was derived from other documents contributed to the SystemTap project by employees of Red Hat, IBM and Intel. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. The GNU Free Documentation License is available from or by writing to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. systemtap-2.3/doc/Language_Reference_Guide/en-US/Language_Reference_Guide.ent000066400000000000000000000001071217430427200272470ustar00rootroot00000000000000 systemtap-2.3/doc/Language_Reference_Guide/en-US/Preface.xml000066400000000000000000000011171217430427200240120ustar00rootroot00000000000000 Preface systemtap-2.3/doc/Language_Reference_Guide/en-US/Revision_History.xml000066400000000000000000000011031217430427200257570ustar00rootroot00000000000000 Revision History 1.0 systemtap-2.3/doc/Language_Reference_Guide/en-US/images/000077500000000000000000000000001217430427200231705ustar00rootroot00000000000000systemtap-2.3/doc/Language_Reference_Guide/en-US/images/icon.svg000066400000000000000000003301271217430427200246470ustar00rootroot00000000000000 image/svg+xml id="path2858" /> systemtap-2.3/doc/Language_Reference_Guide/publicanize-langref.sh000077500000000000000000000204551217430427200252620ustar00rootroot00000000000000#!/bin/bash #this script converts the langref.tex source for the Language Reference Guide into #DocBook XML. the conversion is done thru latexml, a utility that comes with dblatex-0.2.7. #the output xml file of latexml is pretty dirty, so this script is needed to further clean it up. #copy latex file to here cp ../langref.tex . #convert it to raw xml latexml langref.tex --dest=Language_Reference_Guide.xml #remove excess whitespace sed -i -e 's/^\s*//g' Language_Reference_Guide.xml sed -i -e 's///g' Language_Reference_Guide.xml cat Language_Reference_Guide.xml | perl -p -e 'undef $/;s|\n<\?latexml options="twoside,english" class="article"\?>\n<\?latexml package="geometry"\?>\n<\?latexml RelaxNGSchema="LaTeXML"\?>\n<\?latexml RelaxNGSchema="LaTeXML"\?>\n\nSystemTap Language Reference|<\!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ ]>\n\n|msg' | perl -p -e 'undef $/;s|\n

This document was derived from other documents contributed to the SystemTap project by employees of Red Hat, IBM and Intel.

\n
\n\n

Copyright © 2007 Red Hat Inc.\nCopyright © 2007 IBM Corp.\nCopyright © 2007 Intel Corporation.

\n
\n\n

Permission is granted to copy, distribute and/or modify this document\nunder the terms of the GNU Free Documentation License, Version 1.2\nor any later version published by the Free Software Foundation;\nwith no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.

\n
\n\n

The GNU Free Documentation License is available from\nhttp://www.gnu.org/licenses/fdl.html or by writing to\nthe Free Software Foundation, Inc., 51 Franklin Street,\nFifth Floor, Boston, MA 02110-1301, USA.

\n
||msg' | #fix up screens perl -p -e 'undef $/;s|\n\n||msg' | perl -p -e 'undef $/;s|\n\n\n||msg' | perl -p -e 'undef $/;s|\n\n||msg' | perl -p -e 'undef $/;s|\n\n\n||msg' | #fix up index tags perl -p -e 'undef $/;s|\nIndex\n||msg' | #needed later, for TABLES! perl -p -e 'undef $/;s|\n||msg' > clean.xml #further fix up headers! perl -p -i -e 's|<\?latexml searchpaths="[^>]*>\n||g' clean.xml #change main tags sed -i -e 's/<\/document>/<\/book>/g' clean.xml #more fixup for screen tags perl -p -i -e 's|||g' clean.xml perl -p -i -e 's|||g' clean.xml #clean section tags sed -i -e 's/
/<\/chapter>/g' clean.xml #change subsection and subsubsection tags to section sed -i -e 's//<\/section>/g' clean.xml sed -i -e 's//<\/section>/g' clean.xml #remove with sed -i -e 's///g' clean.xml sed -i -e 's/<\/para>//g' clean.xml sed -i -e 's/

//g' clean.xml sed -i -e 's/<\/p>/<\/para>/g' clean.xml #properly convert xrefs sed -i -e 's//indexterm>/g' clean.xml perl -p -i -e 's///g' clean.xml sed -i -e 's///g' clean.xml sed -i -e 's/<\/indexphrase>/<\/primary>/g' clean.xml #convert s sed -i -e 's/emph>/emphasis>/g' clean.xml #convert itemizedlists and listitems, dependent on successful exec of "fix up screens" perl routines sed -i -e 's///g' clean.xml sed -i -e 's///g' clean.xml sed -i -e 's/<\/itemize>/<\/itemizedlist>/g' clean.xml sed -i -e 's/<\/item>/<\/listitem>/g' clean.xml #convert orderedlists and their respective listitems perl -p -i -e 's|||g' clean.xml perl -p -i -e 's|||g' clean.xml perl -p -i -e 's|||g' clean.xml #TRICKY: this perl expression takes all occurences of # http://sourceware.org/systemtap/wiki/HomePage # and replaces the string with "/>". from jfearn # note: [^"]* means "any number of occurences of characters that are NOT quotes # note: () groups strings/an expression together, which can be called later as $1 when replacing perl -p -i -e 's|([^<]*|$1/>|g' clean.xml #now, convert s sed -i -e 's/ accordingly; bold is , typewriter is perl -p -i -e 's|([^<]*)|$1|g' clean.xml sed -i -e 's///g' clean.xml perl -p -i -e 's|([^<]*)|$1|g' clean.xml sed -i -e 's///g' clean.xml #weird remainders, defaulting them to command perl -p -i -e 's|([^<]*)|$1|g' clean.xml sed -i -e 's///g' clean.xml perl -p -i -e 's|([^<]*)|$1|g' clean.xml sed -i -e 's///g' clean.xml #TABLES! #the first expression is quite dirty, since it assumes that all tables have 3 columns. dunno yet how to #automagicize this, since the orig XML doesn't have any attribute that specifies columns per table sed -i -e 's///g' clean.xml sed -i -e 's/tabular>/tgroup>/g' clean.xml perl -p -i -e 's|)|
]*>||g' clean.xml perl -p -i -e 's|]*>||g' clean.xml perl -p -i -e 's|||g' clean.xml perl -p -i -e 's|||g' clean.xml perl -p -i -e 's|||g' clean.xml perl -p -i -e 's|||g' clean.xml #remove "About this guide" section #perl -p -i -e 'undef $/;s|
\nAbout this guide||msg' clean.xml #finalize: copy clean.xml to en-US, then deletes it cp clean.xml en-US/Language_Reference_Guide.xml #delete excess files rm langref.tex rm clean.xml rm Language_Reference_Guide.xml systemtap-2.3/doc/Makefile.am000066400000000000000000000017031217430427200162130ustar00rootroot00000000000000# Makefile.am --- automake input file for systemtap docs ## process this file with automake to produce Makefile.in PDF_FILES = tutorial.pdf langref.pdf DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap SUBDIRS = SystemTap_Tapset_Reference beginners if BUILD_DOCS all-local: $(PDF_FILES) clean-local: rm -f *.pdf *.out *.log *.aux *.toc *.lot *.idx *.glo *.dvi install-data-hook: $(MKDIR_P) $(DOC_INSTALL_DIR) $(INSTALL_DATA) $(PDF_FILES) $(DOC_INSTALL_DIR) uninstall-local: @list='$(PDF_FILES)'; for p in $$list; do \ echo " rm -f '$(DOC_INSTALL_DIR)/$$p'"; \ rm -f "$(DOC_INSTALL_DIR)/$$p"; \ done endif SUFFIXES = ps pdf dvi ps tex .ps.pdf: ps2pdf -r600 $< .dvi.ps: dvips -t letter -o $@ $< .tex.dvi: pwd=`pwd`; cd $(srcdir); \ latex -output-directory=$$pwd $<; \ touch $*.glo \ makeindex $*.glo -s nomencl.ist -o $*.gls \ latex -output-directory=$$pwd $<; \ latex -output-directory=$$pwd $<; \ latex -output-directory=$$pwd $< systemtap-2.3/doc/Makefile.in000066400000000000000000000420011217430427200162200ustar00rootroot00000000000000# Makefile.in generated by automake 1.12.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Makefile.am --- automake input file for systemtap docs VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = doc DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DATE = @DATE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DYNINST_CXXFLAGS = @DYNINST_CXXFLAGS@ DYNINST_LDFLAGS = @DYNINST_LDFLAGS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_NLS = @ENABLE_NLS@ EXEEXT = @EXEEXT@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ JAVADIR = @JAVADIR@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PIECFLAGS = @PIECFLAGS@ PIECXXFLAGS = @PIECXXFLAGS@ PIELDFLAGS = @PIELDFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POSUB = @POSUB@ PUBLICAN_BRAND = @PUBLICAN_BRAND@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STAP_EXTRA_VERSION = @STAP_EXTRA_VERSION@ STAP_PREFIX = @STAP_PREFIX@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ elfutils_abs_srcdir = @elfutils_abs_srcdir@ exec_prefix = @exec_prefix@ have_dvips = @have_dvips@ have_fop = @have_fop@ have_jar = @have_jar@ have_javac = @have_javac@ have_latex = @have_latex@ have_latex2html = @have_latex2html@ have_ps2pdf = @have_ps2pdf@ have_publican = @have_publican@ have_xmlto = @have_xmlto@ have_xvfb = @have_xvfb@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ nss_CFLAGS = @nss_CFLAGS@ nss_LIBS = @nss_LIBS@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ selinux_CFLAGS = @selinux_CFLAGS@ selinux_LIBS = @selinux_LIBS@ sharedstatedir = @sharedstatedir@ sqlite3_LIBS = @sqlite3_LIBS@ srcdir = @srcdir@ stap_LIBS = @stap_LIBS@ staplog_CPPFLAGS = @staplog_CPPFLAGS@ staprun_LIBS = @staprun_LIBS@ subdirs = @subdirs@ support_section_question = @support_section_question@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ PDF_FILES = tutorial.pdf langref.pdf DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap SUBDIRS = SystemTap_Tapset_Reference beginners SUFFIXES = ps pdf dvi ps tex all: all-recursive .SUFFIXES: .SUFFIXES: ps pdf dvi ps tex .dvi .pdf .ps .tex $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign doc/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done cscopelist-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags check-am: all-am check: check-recursive @BUILD_DOCS_FALSE@all-local: all-am: Makefile all-local installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @BUILD_DOCS_FALSE@uninstall-local: @BUILD_DOCS_FALSE@clean-local: @BUILD_DOCS_FALSE@install-data-hook: clean: clean-recursive clean-am: clean-generic clean-local mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-local .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \ cscopelist-recursive ctags-recursive install-am \ install-data-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am all-local check check-am clean clean-generic \ clean-local cscopelist cscopelist-recursive ctags \ ctags-recursive distclean distclean-generic distclean-tags dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-data-hook install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ tags-recursive uninstall uninstall-am uninstall-local @BUILD_DOCS_TRUE@all-local: $(PDF_FILES) @BUILD_DOCS_TRUE@clean-local: @BUILD_DOCS_TRUE@ rm -f *.pdf *.out *.log *.aux *.toc *.lot *.idx *.glo *.dvi @BUILD_DOCS_TRUE@install-data-hook: @BUILD_DOCS_TRUE@ $(MKDIR_P) $(DOC_INSTALL_DIR) @BUILD_DOCS_TRUE@ $(INSTALL_DATA) $(PDF_FILES) $(DOC_INSTALL_DIR) @BUILD_DOCS_TRUE@uninstall-local: @BUILD_DOCS_TRUE@ @list='$(PDF_FILES)'; for p in $$list; do \ @BUILD_DOCS_TRUE@ echo " rm -f '$(DOC_INSTALL_DIR)/$$p'"; \ @BUILD_DOCS_TRUE@ rm -f "$(DOC_INSTALL_DIR)/$$p"; \ @BUILD_DOCS_TRUE@ done .ps.pdf: ps2pdf -r600 $< .dvi.ps: dvips -t letter -o $@ $< .tex.dvi: pwd=`pwd`; cd $(srcdir); \ latex -output-directory=$$pwd $<; \ touch $*.glo \ makeindex $*.glo -s nomencl.ist -o $*.gls \ latex -output-directory=$$pwd $<; \ latex -output-directory=$$pwd $<; \ latex -output-directory=$$pwd $< # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: systemtap-2.3/doc/SystemTap_Beginners_Guide/000077500000000000000000000000001217430427200212205ustar00rootroot00000000000000systemtap-2.3/doc/SystemTap_Beginners_Guide/.gitignore000066400000000000000000000000041217430427200232020ustar00rootroot00000000000000tmp systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/000077500000000000000000000000001217430427200221475ustar00rootroot00000000000000systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Appendix.xml000066400000000000000000000010311217430427200244340ustar00rootroot00000000000000 Full Version of Advanced Scripts This appendix contains the full versions of all scripts discussed in . systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Array-Operations.xml000066400000000000000000001170041217430427200260730ustar00rootroot00000000000000
Array Operations in SystemTap array operations associative arrays operations associative arrays This section enumerates some of the most commonly used array operations in SystemTap.
Assigning an Associated Value array operations assigning associated values assigning associated values array operations values, assignment of array operations Use = to set an associated value to indexed unique pairs, as in: array_name[index_expression] = value shows a very basic example of how to set an explicit associated value to a unique key. You can also use a handler function as both your index_expression and value. For example, you can use arrays to set a timestamp as the associated value to a process name (which you wish to use as your unique key), as in: assigning associated values array operations associating timestamps to process names array operations assigning associated values associating timestamps to process names operations assigning associated values associating timestamps to process names assigning associated values associating timestamps to process names array operations associating timestamps to process names assigning associated values array operations timestamps, association thereof to process names assigning associated values array operations Associating Timestamps to Process Names foo[tid()] = gettimeofday_s() Whenever an event invokes the statement in , SystemTap returns the appropriate tid() value (i.e. the ID of a thread, which is then used as the unique key). At the same time, SystemTap also uses the function gettimeofday_s() to set the corresponding timestamp as the associated value to the unique key defined by the function tid(). This creates an array composed of key pairs containing thread IDs and timestamps. In this same example, if tid() returns a value that is already defined in the array foo, the operator will discard the original associated value to it, and replace it with the current timestamp from gettimeofday_s().
Reading Values From Arrays reading values from arrays array operations array operations reading values from arrays operations reading values from arrays You can also read values from an array the same way you would read the value of a variable. To do so, include the array_name[index_expression] statement as an element in a mathematical expression. For example: reading values from arrays array operations using arrays in simple computations array operations reading values from arrays using arrays in simple computations operations reading values from arrays using arrays in simple computations using arrays in simple computations reading values from arrays array operations algebraic formulas using arrays reading values from arrays array operations array operations reading values from arrays computing for timestamp deltas operations reading values from arrays computing for timestamp deltas computing for timestamp deltas reading values from arrays array operations reading values from arrays computing for timestamp deltas array operations timestamp deltas, computing for reading values from arrays array operations Using Array Values in Simple Computations delta = gettimeofday_s() - foo[tid()] This example assumes that the array foo was built using the construct in (from ). This sets a timestamp that will serve as a reference point, to be used in computing for delta. The construct in computes a value for the variable delta by subtracting the associated value of the key tid() from the current gettimeofday_s(). The construct does this by reading the value of tid() from the array. This particular construct is useful for determining the time between two events, such as the start and completion of a read operation. reading values from arrays array operations empty unique keys array operations reading values from arrays empty unique keys operations reading values from arrays empty unique keys empty unique keys reading values from arrays array operations Note If the index_expression cannot find the unique key, it returns a value of 0 (for numerical operations, such as ) or a null/empty string value (for string operations) by default.
Incrementing Associated Values array operations incrementing associated values incrementing associated values array operations operations incrementing associated values Use ++ to increment the associated value of a unique key in an array, as in: array_name[index_expression] ++ Again, you can also use a handler function for your index_expression. For example, if you wanted to tally how many times a specific process performed a read to the virtual file system (using the event vfs.read), you can use the following probe: incrementing associated values array operations tallying virtual file system reads (VFS reads) array operations incrementing associated values tallying virtual file system reads (VFS reads) operations incrementing associated values tallying virtual file system reads (VFS reads) tallying virtual file system reads (VFS reads) incrementing associated values array operations VFS reads, tallying of incrementing associated values array operations vfsreads.stp probe vfs.read { reads[execname()] ++ } In , the first time that the probe returns the process name gnome-terminal (i.e. the first time gnome-terminal performs a VFS read), that process name is set as the unique key gnome-terminal with an associated value of 1. The next time that the probe returns the process name gnome-terminal, SystemTap increments the associated value of gnome-terminal by 1. SystemTap performs this operation for all process names as the probe returns them.
Processing Multiple Elements in an Array multiple elements in an array array operations array operations multiple elements in an array operations multiple elements in an array array operations processing multiple elements in an array processing multiple elements in an array array operations operations processing multiple elements in an array Once you've collected enough information in an array, you will need to retrieve and process all elements in that array to make it useful. Consider : the script collects information about how many VFS reads each process performs, but does not specify what to do with it. The obvious means for making useful is to print the key pairs in the array reads, but how? array operations processing multiple elements in an array foreach operations processing multiple elements in an array foreach processing multiple elements in an array foreach array operations foreach processing multiple elements in an array array operations array operations processing multiple elements in an array iterations, processing elements in an array as operations processing multiple elements in an array iterations, processing elements in an array as iterations, processing elements in an array as processing multiple elements in an array array operations The best way to process all key pairs in an array (as an iteration) is to use the foreach statement. Consider the following example: array operations processing multiple elements in an array cumulative virtual file system reads, tallying operations processing multiple elements in an array cumulative virtual file system reads, tallying cumulative virtual file system reads, tallying processing multiple elements in an array array operations processing multiple elements in an array cumulative virtual file system reads, tallying array operations virtual file system reads (cumulative), tallying processing multiple elements in an array array operations cumulative-vfsreads.stp global reads probe vfs.read { reads[execname()] ++ } probe timer.s(3) { foreach (count in reads) printf("%s : %d \n", count, reads[count]) } In the second probe of , the foreach statement uses the variable count to reference each iteration of a unique key in the array reads. The reads[count] array statement in the same probe retrieves the associated value of each unique key. Given what we know about the first probe in , the script prints VFS-read statistics every 3 seconds, displaying names of processes that performed a VFS-read along with a corresponding VFS-read count. array operations processing multiple elements in an array limiting the output of foreach operations processing multiple elements in an array limiting the output of foreach processing multiple elements in an array limiting the output of foreach array operations limiting the output of foreach processing multiple elements in an array array operations array operations processing multiple elements in an array ordering the output of foreach operations processing multiple elements in an array ordering the output of foreach processing multiple elements in an array ordering the output of foreach array operations ordering the output of foreach processing multiple elements in an array array operations Now, remember that the foreach statement in prints all iterations of process names in the array, and in no particular order. You can instruct the script to process the iterations in a particular order by using + (ascending) or - (descending). In addition, you can also limit the number of iterations the script needs to process with the limit value option. For example, consider the following replacement probe: probe timer.s(3) { foreach (count in reads- limit 10) printf("%s : %d \n", count, reads[count]) } This foreach statement instructs the script to process the elements in the array reads in descending order (of associated value). The limit 10 option instructs the foreach to only process the first ten iterations (i.e. print the first 10, starting with the highest value).
Clearing/Deleting Arrays and Array Elements array operations deleting arrays and array elements operations deleting arrays and array elements array operations clearing arrays/array elements operations clearing arrays/array elements clearing arrays/array elements array operations Sometimes, you may need to clear the associated values in array elements, or reset an entire array for re-use in another probe. in allows you to track how the number of VFS reads per process grows over time, but it does not show you the number of VFS reads each process makes per 3-second period. array operations clearing arrays/array elements delete operator operations clearing arrays/array elements delete operator clearing arrays/array elements array operations delete operator delete operator clearing arrays/array elements array operations To do that, you will need to clear the values accumulated by the array. You can accomplish this using the delete operator to delete elements in an array, or an entire array. Consider the following example: array operations clearing arrays/array elements virtual file system reads (non-cumulative), tallying operations clearing arrays/array elements virtual file system reads (non-cumulative), tallying clearing arrays/array elements array operations virtual file system reads (non-cumulative), tallying virtual file system reads (non-cumulative), tallying clearing arrays/array elements array operations noncumulative-vfsreads.stp global reads probe vfs.read { reads[execname()] ++ } probe timer.s(3) { foreach (count in reads) printf("%s : %d \n", count, reads[count]) delete reads } In , the second probe prints the number of VFS reads each process made within the probed 3-second period only. The delete reads statement clears the reads array within the probe. Note array operations clearing arrays/array elements multiple array operations within the same probe operations clearing arrays/array elements multiple array operations within the same probe clearing arrays/array elements array operations multiple array operations within the same probe multiple array operations within the same probe clearing arrays/array elements array operations You can have multiple array operations within the same probe. Using the examples from and , you can track the number of VFS reads each process makes per 3-second period and tally the cumulative VFS reads of those same processes. Consider the following example: global reads, totalreads probe vfs.read { reads[execname()] ++ totalreads[execname()] ++ } probe timer.s(3) { printf("=======\n") foreach (count in reads-) printf("%s : %d \n", count, reads[count]) delete reads } probe end { printf("TOTALS\n") foreach (total in totalreads-) printf("%s : %d \n", total, totalreads[total]) } In this example, the arrays reads and totalreads track the same information, and are printed out in a similar fashion. The only difference here is that reads is cleared every 3-second period, whereas totalreads keeps growing.
Using Arrays in Conditional Statements array operations conditional statements, using arrays in operations conditional statements, using arrays in conditional statements, using arrays in array operations if/else statements, using arrays in array operations You can also use associative arrays in if statements. This is useful if you want to execute a subroutine once a value in the array matches a certain condition. Consider the following example: vfsreads-print-if-1kb.stp global reads probe vfs.read { reads[execname()] ++ } probe timer.s(3) { printf("=======\n") foreach (count in reads-) if (reads[count] >= 1024) printf("%s : %dkB \n", count, reads[count]/1024) else printf("%s : %dB \n", count, reads[count]) } Every three seconds, prints out a list of all processes, along with how many times each process performed a VFS read. If the associated value of a process name is equal or greater than 1024, the if statement in the script converts and prints it out in kB. Testing for Membership array operations conditional statements, using arrays in testing for array membership operations conditional statements, using arrays in testing for array membership conditional statements, using arrays in array operations testing for array membership testing for array membership conditional statements, using arrays in array operations membership (in array), testing for conditional statements, using arrays in array operations You can also test whether a specific unique key is a member of an array. Further, membership in an array can be used in if statements, as in: if([index_expression] in array_name) statement To illustrate this, consider the following example: vfsreads-stop-on-stapio2.stp global reads probe vfs.read { reads[execname()] ++ } probe timer.s(3) { printf("=======\n") foreach (count in reads+) printf("%s : %d \n", count, reads[count]) if(["stapio"] in reads) { printf("stapio read detected, exiting\n") exit() } } The if(["stapio"] in reads) statement instructs the script to print stapio read detected, exiting once the unique key stapio is added to the array reads.
Computing for Statistical Aggregates statistical aggregates array operations aggregates (statistical) array operations array operations computing for statistical aggregates operations computing for statistical aggregates computing for statistical aggregates array operations Statistical aggregates are used to collect statistics on numerical values where it is important to accumulate new data quickly and in large volume (i.e. storing only aggregated stream statistics). Statistical aggregates can be used in global variables or as elements in an array. array operations computing for statistical aggregates adding values to statistical aggregates operations computing for statistical aggregates adding values to statistical aggregates computing for statistical aggregates array operations adding values to statistical aggregates adding values to statistical aggregates computing for statistical aggregates array operations To add value to a statistical aggregate, use the operator <<< value. need more examples of supported rvalues, e.g. length, count, and what each one does. stat-aggregates.stp global reads probe vfs.read { reads[execname()] <<< count } array operations computing for statistical aggregates count (operator) operations computing for statistical aggregates count (operator) computing for statistical aggregates array operations count (operator) count operator computing for statistical aggregates array (operator) In , the operator <<< count stores the amount returned by count to to the associated value of the corresponding execname() in the reads array. Remember, these values are stored; they are not added to the associated values of each unique key, nor are they used to replace the current associated values. In a manner of speaking, think of it as having each unique key (execname()) having multiple associated values, accumulating with each probe handler run. Note In the context of , count returns the amount of data read by the returned execname() to the virtual file system. array operations computing for statistical aggregates extracting data collected by statistical aggregates operations computing for statistical aggregates extracting data collected by statistical aggregates computing for statistical aggregates array operations extracting data collected by statistical aggregates extracting data collected by statistical aggregates computing for statistical aggregates array operations integer extractors computing for statistical aggregates array operations To extract data collected by statistical aggregates, use the syntax format @extractor(variable/array index expression). extractor can be any of the following integer extractors: count array operations computing for statistical aggregates @count (integer extractor) operations computing for statistical aggregates @count (integer extractor) computing for statistical aggregates array operations @count (integer extractor) @count (integer extractor) computing for statistical aggregates array operations Returns the number of all values stored into the variable/array index expression. Given the sample probe in , the expression @count(reads[execname()]) will return how many values are stored in each unique key in array reads. sum array operations computing for statistical aggregates @sum (integer extractor) operations computing for statistical aggregates @sum (integer extractor) computing for statistical aggregates array operations @sum (integer extractor) @sum (integer extractor) computing for statistical aggregates array operations Returns the sum of all values stored into the variable/array index expression. Again, given sample probe in , the expression @sum(reads[execname()]) will return the total of all values stored in each unique key in array reads. min array operations computing for statistical aggregates @min (integer extractor) operations computing for statistical aggregates @min (integer extractor) computing for statistical aggregates array operations @min (integer extractor) @min (integer extractor) computing for statistical aggregates array operations Returns the smallest among all the values stored in the variable/array index expression. max array operations computing for statistical aggregates @max (integer extractor) operations computing for statistical aggregates @max (integer extractor) computing for statistical aggregates array operations @max (integer extractor) @max (integer extractor) computing for statistical aggregates array operations Returns the largest among all the values stored in the variable/array index expression. avg array operations computing for statistical aggregates @avg (integer extractor) operations computing for statistical aggregates @avg (integer extractor) computing for statistical aggregates array operations @avg (integer extractor) @avg (integer extractor) computing for statistical aggregates array operations Returns the average of all values stored in the variable/array index expression. When using statistical aggregates, you can also build array constructs that use multiple index expressions (to a maximum of 5). This is helpful in capturing additional contextual information during a probe. For example: Multiple Array Indexes global reads probe vfs.read { reads[execname(),pid()] <<< 1 } probe timer.s(3) { foreach([var1,var2] in reads) printf("%s (%d) : %d \n", var1, var2, @count(reads[var1,var2])) } In , the first probe tracks how many times each process performs a VFS read. What makes this different from earlier examples is that this array associates a performed read to both a process name and its corresponding process ID. The second probe in demonstrates how to process and print the information collected by the array reads. Note how the foreach statement uses the same number of variables (i.e. var1 and var2) contained in the first instance of the array reads from the first probe.
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Arrays.xml000066400000000000000000000217741217430427200241450ustar00rootroot00000000000000
Associative Arrays arrays associative arrays associative arrays introduction SystemTap also supports the use of associative arrays. While an ordinary variable represents a single value, associative arrays can represent a collection of values. Simply put, an associative array is a collection of unique keys; each key in the array has a value associated with it. associative arrays introduction key pairs key pairs introduction arrays associative arrays introduction unique keys unique keys introduction arrays associative arrays introduction associated values associated values introduction arrays associative arrays introduction index expression index expression introduction arrays Since associative arrays are normally processed in multiple probes (as we will demonstrate later), they should be declared as global variables in the SystemTap script. The syntax for accessing an element in an associative array is similar to that of awk, and is as follows: associative arrays introduction syntax syntax introduction arrays format introduction arrays array_name[index_expression] Here, the array_name is any arbitrary name the array uses. The index_expression is used to refer to a specific unique key in the array. To illustrate, let us try to build an array named foo that specifies the ages of three people (i.e. the unique keys): tom, dick, and harry. To assign them the ages (i.e. associated values) of 23, 24, and 25 respectively, we'd use the following array statements: associative arrays introduction example example introduction arrays Basic Array Statements foo["tom"] = 23 foo["dick"] = 24 foo["harry"] = 25 You can specify up to nine index expressions in an array statement, each one delimited by a comma (,). This is useful if you wish to have a key that contains multiple pieces of information. The following line from uses 5 elements for the key: process ID, executable name, user ID, parent process ID, and string "W". It associates the value of devname with that key. device[pid(),execname(),uid(),ppid(),"W"] = devname Important All associate arrays must be declared as global, regardless of whether the associate array is used in one or multiple probes.
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Author_Group.xml000066400000000000000000000013071217430427200253100ustar00rootroot00000000000000 Red Hat, Inc. Don Domingo Engineering Services and Operations Content Services ddomingo@redhat.com William Cohen Engineering Services and Operations Performance Tools wcohen@redhat.com systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Book_Info.xml000066400000000000000000000037271217430427200245470ustar00rootroot00000000000000 SystemTap Beginners Guide Introduction to SystemTap (for Red Hat Enterprise Linux) Introduction to SystemTap (for Fedora) 2.3 Systemtap 2.3 2 This guide provides basic instructions on how to use SystemTap to monitor different subsystems of &PRODUCT; in finer detail. The SystemTap Beginners Guide is recommended for users who have taken RHCT or have a similar level of expertise in &PRODUCT;. This guide provides basic instructions on how to use SystemTap to monitor different subsystems of Fedora in finer detail. The SystemTap Beginners Guide is recommended for users who have taken RHCT or have a similar level of expertise in Fedora. Logo &YEAR; &HOLDER; systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Chapter.xml000066400000000000000000000010641217430427200242600ustar00rootroot00000000000000 Test This is a test paragraph
Section 1 Test Test of a section
Section 2 Test Test of a section
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/CrossInstrumenting.xml000066400000000000000000000276711217430427200265660ustar00rootroot00000000000000
Generating Instrumentation for Other Computers cross-instrumentation building kernel modules from SystemTap scripts cross-instrumentation generating instrumentation from SystemTap scripts cross-compiling script from here: http://sourceware.org/ml/systemtap/2008-q3/msg00310.html kernel modules from SystemTap scripts, building building kernel modules from SystemTap scripts instrumentation modules from SystemTap scripts, building building instrumentation modules from SystemTap scripts compiling instrumentation/kernel modules from SystemTap scripts cross-compiling above; add short description, significance, howto, script (test first) When users run a SystemTap script, SystemTap builds a kernel module out of that script. SystemTap then loads the module into the kernel, allowing it to extract the specified data directly from the kernel (refer to in for more information). Normally, however, SystemTap scripts can only be run on systems where SystemTap is deployed (as in ). This could mean that if you want to run SystemTap on ten systems, you would need to deploy SystemTap on all those systems. In some cases, this may be neither feasible nor desired. For instance, corporate policy may prohibit an administrator from installing RPMs that provide compilers or debug information on specific machines, which will prevent the deployment of SystemTap. To work around this, you can resort to cross-instrumentation. Cross-instrumentation is the process of generating SystemTap instrumentation module from a SystemTap script on one computer to be used on another computer. This process offers the following benefits: cross-instrumentation advantages of advantages of cross-instrumentation The kernel information packages for various machines can be installed on a single host machine. Each target machine only needs one RPM to be installed to use the generated SystemTap instrumentation module: systemtap-runtime. Note For the sake of simplicity, we will be using the following terms throughout this section: cross-instrumentation instrumentation module instrumentation module cross-instrumentation instrumentation module — the kernel module built from a SystemTap script; i.e. the SystemTap module is built on the host system, and will be loaded on the target kernel of target system. cross-instrumentation host system host system cross-instrumentation host system — the system on which you compile the instrumentation modules (from SystemTap scripts), to be loaded on target systems. cross-instrumentation target system target system cross-instrumentation target system — the system for which you are building the instrumentation module (from SystemTap scripts). cross-instrumentation target kernel target kernel cross-instrumentation target kernel — the kernel of the target system. This is the kernel on which you wish to load/run the instrumentation module. Configuring a Host System and Target Systems cross-instrumentation configuration host system and target system host system and target system cross-instrumentation configuration target system and host system configuration Install the systemtap-runtime RPM on each target system. Determine the kernel running on each target system by running uname -r on each target system. Install SystemTap on the host system. You will be building the instrumentation module for the target systems on the host system. For instructions on how to install SystemTap, refer to . Using the target kernel version determined earlier, install the target kernel and related RPMs on the host system by the method described in . If multiple target systems use different target kernels, you will need to repeat this step for each different kernel used on the target systems. After performing , you can now build the instrumentation module (for any target system) on the host system. To build the instrumentation module, run the following command on the host system (be sure to specify the appropriate values): stap -r kernel_version script -m module_name Here, kernel_version refers to the version of the target kernel (the output of uname -r on the target machine), script refers to the script to be converted into an instrumentation module, and module_name is the desired name of the instrumentation module. Note uname -m determining architecture notation architecture notation, determining To determine the architecture notation of a running kernel, run uname -m. Once the instrumentation module is compiled, copy it to the target system and then load it using: staprun module_name.ko For example, to create the instrumentation module simple.ko from a SystemTap script named simple.stp for the target kernel 2.6.18-92.1.10.el5 (on x86_64 architecture), use the following command: stap -r 2.6.18-92.1.10.el5 -e 'probe vfs.read {exit()}' -m simple This will create a module named simple.ko. To use the instrumentation module simple.ko, copy it to the target system and run the following command (on the target system): staprun simple.ko Important The host system must be the same architecture and running the same distribution of Linux as the target system in order for the built instrumentation module to work.
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Errors.xml000066400000000000000000000673061217430427200241610ustar00rootroot00000000000000 Understanding SystemTap Errors By type - http://sourceware.org/systemtap/tutorial/node23.html This chapter explains the most common errors you may encounter while using SystemTap.
Parse and Semantic Errors understanding SystemTap errors parse/semantics error errors parse/semantics error parse/semantics error understanding SystemTap errors These types of errors occur while SystemTap attempts to parse and translate the script into C, prior to being converted into a kernel module. For example type errors result from operations that assign invalid values to variables or arrays. parse error: expected <replaceable>foo</replaceable>, saw <replaceable>bar</replaceable> understanding SystemTap errors parse/semantics error invalid values to variables/arrays errors parse/semantics error invalid values to variables/arrays parse/semantics error understanding SystemTap errors invalid values to variables/arrays invalid values to variables/arrays parse/semantics error understanding SystemTap errors understanding SystemTap errors parse/semantics error grammatical/typographical script error errors parse/semantics error grammatical/typographical script error parse/semantics error understanding SystemTap errors grammatical/typographical script error grammatical/typographical script error parse/semantics error understanding SystemTap errors typographical script error parse/semantics error understanding SystemTap errors The script contains a grammatical/typographical error. SystemTap detected type of construct that is incorrect, given the context of the probe. need more clarification (example) on this; could not replicate. how to replicate? The following invalid SystemTap script is missing its probe handlers: It results in the following error message showing that the parser was expecting something other than the probe keyword in column 1 of line 2: parse error: expected one of '. , ( ? ! { = +=' saw: keyword at perror.stp:2:1 1 parse error(s). parse error: embedded code in unprivileged script understanding SystemTap errors parse/semantics error embedded code in unprivileged script errors parse/semantics error embedded code in unprivileged script parse/semantics error understanding SystemTap errors embedded code in unprivileged script embedded code in unprivileged script parse/semantics error understanding SystemTap errors unprivileged script, embedded code in parse/semantics error understanding SystemTap errors unsafe embedded code in unprivileged script parse/semantics error understanding SystemTap errors The script contains unsafe embedded C code (blocks of code surrounded by %{ %}. SystemTap allows you to embed C code in a script, which is useful if there are no tapsets to suit your purposes. However, embedded C constructs are not safe; as such, SystemTap warns you with this error if such constructs appear in the script. understanding SystemTap errors parse/semantics error guru mode errors parse/semantics error guru mode parse/semantics error understanding SystemTap errors guru mode guru mode parse/semantics error understanding SystemTap errors If you are sure of the safety of any similar constructs in the script and are member of stapdev group (or have root privileges), run the script in "guru" mode by using the option -g (i.e. stap -g script). semantic error: type mismatch for identifier '<replaceable>foo</replaceable>' ... string vs. long understanding SystemTap errors parse/semantics error type mismatch for identifier errors parse/semantics error type mismatch for identifier parse/semantics error understanding SystemTap errors type mismatch for identifier type mismatch for identifier parse/semantics error understanding SystemTap errors identifier type mismatch parse/semantics error understanding SystemTap errors The function foo in the script used the wrong type (i.e. %s or %d). This error will present itself in , because the function execname() returns a string the format specifier should be a %s, not %d. error-variable.stp probe syscall.open { printf ("%d(%d) open\n", execname(), pid()) } semantic error: unresolved type for identifier '<replaceable>foo</replaceable>' understanding SystemTap errors parse/semantics error unresolved type for identifier errors parse/semantics error unresolved type for identifier parse/semantics error understanding SystemTap errors unresolved type for identifier unresolved type for identifier parse/semantics error understanding SystemTap errors The identifier (e.g. a variable) was used, but no type (integer or string) could be determined. This occurs, for instance, if you use a variable in a printf statement while the script never assigns a value to the variable. semantic error: Expecting symbol or array index expression understanding SystemTap errors parse/semantics error expected symbol/array index expression errors parse/semantics error expected symbol/array index expression parse/semantics error understanding SystemTap errors expected symbol/array index expression expected symbol/array index expression parse/semantics error understanding SystemTap errors SystemTap could not assign a value to a variable or to a location in an array. The destination for the assignment is not a valid destination. The following example code would generate this error: while searching for arity <replaceable>N</replaceable> function, semantic error: unresolved function call understanding SystemTap errors parse/semantics error unresolved function call errors parse/semantics error unresolved function call parse/semantics error understanding SystemTap errors unresolved function call unresolved function call parse/semantics error understanding SystemTap errors function call (unresolved) parse/semantics error understanding SystemTap errors A function call or array index expression in the script used an invalid number of arguments/parameters. In SystemTap arity can either refer to the number of indices for an array, or the number of parameters to a function. semantic error: array locals not supported, missing global declaration? array locals not supported parse/semantics error understanding SystemTap errors understanding SystemTap errors parse/semantics error non-global arrays errors parse/semantics error non-global arrays parse/semantics error understanding SystemTap errors non-global arrays non-global arrays parse/semantics error understanding SystemTap errors The script used an array operation without declaring the array as a global variable (global variables can be declared after their use in SystemTap scripts). Similar messages appear if an array is used, but with inconsistent arities. semantic error: variable ’<replaceable>foo</replaceable>’ modified during ’foreach’ iteration understanding SystemTap errors parse/semantics error variable modified during 'foreach' errors parse/semantics error variable modified during 'foreach' parse/semantics error understanding SystemTap errors variable modified during 'foreach' variable modified during 'foreach' parse/semantics error understanding SystemTap errors The array foo is being modifed (being assigned to or deleted from) within an active foreach loop. This error also displays if an operation within the script performs a function call within the foreach loop. semantic error: probe point mismatch at position <replaceable>N</replaceable>, while resolving probe point <replaceable>foo</replaceable> understanding SystemTap errors parse/semantics error probe mismatch errors parse/semantics error probe mismatch parse/semantics error understanding SystemTap errors probe mismatch probe mismatch parse/semantics error understanding SystemTap errors SystemTap did not understand what the event or SystemTap function foo refers to. This usually means that SystemTap could not find a match for foo in the tapset library. The N refers to the line and column of the error. how to explain N in previous? "The divergence from the “tree” of probe point namespace is at position N (starting with zero at left)." (from tutorial) semantic error: no match for probe point, while resolving probe point <replaceable>foo</replaceable> understanding SystemTap errors parse/semantics error no match for probe point errors parse/semantics error no match for probe point parse/semantics error understanding SystemTap errors no match for probe point no match for probe point parse/semantics error understanding SystemTap errors probe point (no match for) parse/semantics error understanding SystemTap errors The events/handler function foo could not be resolved altogether, for a variety of reasons. This error occurs when the script contains the event kernel.function("blah"), and blah does not exist. In some cases, the error could also mean the script contains an invalid kernel file name or source line number. semantic error: unresolved target-symbol expression understanding SystemTap errors parse/semantics error unresolved target-symbol expression errors parse/semantics error unresolved target-symbol expression parse/semantics error understanding SystemTap errors unresolved target-symbol expression unresolved target-symbol expression parse/semantics error understanding SystemTap errors target-symbol expression, unresolved parse/semantics error understanding SystemTap errors A handler in the script references a target variable, but the value of the variable could not be resolved. This error could also mean that a handler is referencing a target variable that is not valid in the context when it was referenced. This may be a result of compiler optimization of the generated code. semantic error: libdwfl failure understanding SystemTap errors parse/semantics error libdwfl failure errors parse/semantics error libdwfl failure parse/semantics error understanding SystemTap errors libdwfl failure libdwfl failure parse/semantics error understanding SystemTap errors There was a problem processing the debugging information. In most cases, this error results from the installation of a kernel-debuginfo RPM whose version does not match the probed kernel exactly. The installed kernel-debuginfo RPM itself may have some consistency/correctness problems. semantic error: cannot find <replaceable>foo</replaceable> debuginfo SystemTap could not find a suitable kernel-debuginfo at all.
Run Time Errors and Warnings understainding SystemTap errors runtime errors/warnings errors runtime errors/warnings runtime errors/warnings understainding SystemTap errors Runtime errors and warnings occur when the SystemTap instrumentation has been installed and is collecting data on the system. WARNING: Number of errors: <replaceable>N</replaceable>, skipped probes: <replaceable>M</replaceable> understainding SystemTap errors runtime errors/warnings number of errors: N, skipped probes: M errors runtime errors/warnings number of errors: N, skipped probes: M runtime errors/warnings understainding SystemTap errors number of errors: N, skipped probes: M number of errors: N, skipped probes: M runtime errors/warnings understainding SystemTap errors Errors and/or skipped probes occurred during this run. Both N and M are the counts of the number of probes that were not executed due to conditions such as too much time required to execute event handlers over an interval of time. division by 0 understainding SystemTap errors runtime errors/warnings division by 0 errors runtime errors/warnings division by 0 runtime errors/warnings understainding SystemTap errors division by 0 division by 0 runtime errors/warnings understainding SystemTap errors invalid division runtime errors/warnings understainding SystemTap errors The script code performed an invalid division. aggregate element not found understainding SystemTap errors runtime errors/warnings aggregate element not found errors runtime errors/warnings aggregate element not found runtime errors/warnings understainding SystemTap errors aggregate element not found aggregate element not found runtime errors/warnings understainding SystemTap errors A statistics extractor function other than @count was invoked on an aggregate that has not had any values accumulated yet. This is similar to a division by zero. aggregation overflow understainding SystemTap errors runtime errors/warnings aggregation overflow errors runtime errors/warnings aggregation overflow runtime errors/warnings understainding SystemTap errors aggregation overflow aggregation overflow runtime errors/warnings understainding SystemTap errors overflow of aggregation runtime errors/warnings understainding SystemTap errors An array containing aggregate values contains too many distinct key pairs at this time. MAXNESTING exceeded understainding SystemTap errors runtime errors/warnings MAXNESTING exceeded errors runtime errors/warnings MAXNESTING exceeded runtime errors/warnings understainding SystemTap errors MAXNESTING exceeded MAXNESTING exceeded runtime errors/warnings understainding SystemTap errors exceeded MAXNESTING runtime errors/warnings understainding SystemTap errors Too many levels of function call nesting were attempted. The default nesting of function calls allowed is 10. MAXACTION exceeded understainding SystemTap errors runtime errors/warnings MAXACTION exceeded errors runtime errors/warnings MAXACTION exceeded runtime errors/warnings understainding SystemTap errors MAXACTION exceeded MAXACTION exceeded runtime errors/warnings understainding SystemTap errors exceeded MAXACTION runtime errors/warnings understainding SystemTap errors The probe handler attempted to execute too many statements in the probe handler. The default number of actions allowed in a probe handler is 1000. kernel/user string copy fault at <replaceable>ADDR</replaceable> understainding SystemTap errors runtime errors/warnings copy fault errors runtime errors/warnings copy fault runtime errors/warnings understainding SystemTap errors copy fault copy fault runtime errors/warnings understainding SystemTap errors The probe handler attempted to copy a string from kernel or user-space at an invalid address (ADDR). pointer dereference fault understainding SystemTap errors runtime errors/warnings pointer dereference fault errors runtime errors/warnings pointer dereference fault runtime errors/warnings understainding SystemTap errors pointer dereference fault pointer dereference fault runtime errors/warnings understainding SystemTap errors There was a fault encountered during a pointer dereference operation such as a target variable evaluation.
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Feedback.xml000066400000000000000000000025051217430427200243570ustar00rootroot00000000000000
We Need Feedback! feedback contact information for this manual If you find a typographical error in this manual, or if you have thought of a way to make this manual better, we would love to hear from you! Please submit a report in Bugzilla: http://sourceware.org/bugzilla/ http://bugzilla.redhat.com/bugzilla/ http://bugzilla.redhat.com/bugzilla/ against the product systemtap. When submitting a report, be sure to include the specific file or URL the report refers to and the manual's identifier: &BOOKID; If you have a suggestion for improving the documentation, try to be as specific as possible when describing it. If you have found an error, please include the section number and some of the surrounding text so we can find it easily.
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Installation.xml000066400000000000000000000323471217430427200253430ustar00rootroot00000000000000
Installation and Setup required packages, installation thru yum, repos (?); possibly, a script to install all required packages notes in ~/Desktop/SystemTap/aug21chatlog and ~/Desktop/SystemTap/noted_wcohenmeeting Installation Setup and Installation Setup and Installation To deploy SystemTap, you need to install the SystemTap packages along with the corresponding set of -devel, -debuginfo and -debuginfo-common packages for your kernel. If your system has multiple kernels installed, and you wish to use SystemTap on more than one kernel kernel, you will need to install the -devel and -debuginfo packages for each of those kernel versions. These procedures will be discussed in detail in the following sections. Important Many users confuse -debuginfo with -debug. Remember that the deployment of SystemTap requires the installation of the -debuginfo package of the kernel, not the -debug version of the kernel.
Installing SystemTap To deploy Systemtap, you will need to to install the following RPMs: Installation systemtap package systemtap package Installation systemtap-runtime package systemtap-runtime package systemtap systemtap-runtime Assuming that yum is installed in the system, these two rpms can be installed with yum install systemtap systemtap-runtime. Note that before you can use SystemTap, you will still need to install the required kernel information RPMs.
Installing Required Kernel Information RPMs Installation required packages required packages packages required to run SystemTap RPMs required to run SystemTap Installation kernel information packages kernel information packages SystemTap needs information about the kernel in order to place instrumentation in it (i.e. probe it). This information also allows SystemTap to generate the code for the instrumentation. This information is contained in the matching -devel, -debuginfo, and -debuginfo-common packages for your kernel. The necessary -devel and -debuginfo packages for the ordinary "vanilla" kernel are as follows: kernel-debuginfo kernel-debuginfo-common kernel-devel Likewise, the necessary packages for the PAE kernel would be kernel-PAE-debuginfo, kernel-PAE-debuginfo-common, and kernel-PAE-devel. Installation kernel version, determining the kernel version, determining the determining the kernel version uname -r To determine what kernel your system is currently using, use: uname -r For example, if you wish to use SystemTap on kernel version 2.6.18-53.el5 on an i686 machine, then you would need to download and install the following RPMs: kernel-debuginfo-2.6.18-53.1.13.el5.i686.rpm kernel-debuginfo-common-2.6.18-53.1.13.el5.i686.rpm kernel-devel-2.6.18-53.1.13.el5.i686.rpm Important The version, variant, and architecture of the -devel, -debuginfo and -debuginfo-common packages must match the kernel you wish to probe with SystemTap exactly. The easiest way to install the required kernel information packages is through yum install and debuginfo-install commands. debuginfo-install is included with later versions of the yum-utils package (for example, version 1.1.10), and also requires an appropriate yum repository from which to download and install -debuginfo/-debuginfo-common packages. You can install the required -devel, -debuginfo, and -debuginfo-common packages for your kernel. For Red Hat Enterprise Linux 6 and newer you need the appropriate channels enabled for the system for yum to download and install the appropriate packages. Configure the channels with either the rhn-channel command or the Red Hat Network web interface. To obtain a list of the channels SystemTap needs on the system use the following script: Installation rhelchannels.sh rhelchannels.sh rhelchannels.sh On a system with Red Hat Enterprise Linux 6 for Workstation running the previous script would return the following list: rhel-x86_64-workstation-6 rhel-x86_64-workstation-6-debuginfo rhel-x86_64-workstation-optional-6-debuginfo rhel-x86_64-workstation-optional-6 The rhn-channel --list will provide a list of channels the machine is currently subscribed to. If the machine is only subscribed to rhel-x86_64-workstation-6, then with root and Red Hat Network administrator privileges for the machine the other channels could be added with the following command: rhn-channel --add \ --channel=rhel-x86_64-workstation-6-debuginfo \ --channel=rhel-x86_64-workstation-optional-6-debuginfo \ --channel=rhel-x86_64-workstation-optional-6 With the appropriate software repositories are enabled, install the corresponding packages for a specific kernel using yum with the following commands: yum install kernelname-devel-version debuginfo-install kernelname-version Replace kernelname with the appropriate kernel variant name (for example, kernel-PAE), and version with the target kernel's version. For example, to install the required kernel information packages for the kernel-PAE-2.6.18-53.1.13.el5 kernel, run: yum install kernel-PAE-devel-2.6.18-53.1.13.el5 debuginfo-install kernel-PAE-2.6.18-53.1.13.el5 If you do not have yum and yum-utils installed (and you are unable to install them), you will have to manually download and install the required kernel information packages. To generate the URL from which to download the required packages, use the following script: Installation fedoradebugurl.sh fedoradebugurl.sh If you do not have yum and yum-utils installed (and you are unable to install them) on Red Hat Enterprise Linux 4 or 5, you will have to manually download and install the required kernel information packages. To generate the URL from which to download the required packages, use the following script: Installation rheldebugurl.sh rheldebugurl.sh rheldebugurl.sh fedoradebugurl.sh Once you have manually downloaded the required packages to the machine, install the RPMs by running rpm --force -ivh package_names.
Initial Testing Installation initial testing initial testing testing, initial If you are currently using the kernel you wish to probe with SystemTap, you can immediately test whether the deployment was successful. If not, you will need to reboot and load the appropriate kernel. To start the test, run the command stap -v -e 'probe vfs.read {printf("read performed\n"); exit()}'. This command simply instructs SystemTap to print read performed then exit properly once a virtual file system read is detected. If the SystemTap deployment was successful, you should get output similar to the following: Pass 1: parsed user script and 45 library script(s) in 340usr/0sys/358real ms. Pass 2: analyzed script: 1 probe(s), 1 function(s), 0 embed(s), 0 global(s) in 290usr/260sys/568real ms. Pass 3: translated to C into "/tmp/stapiArgLX/stap_e5886fa50499994e6a87aacdc43cd392_399.c" in 490usr/430sys/938real ms. Pass 4: compiled C into "stap_e5886fa50499994e6a87aacdc43cd392_399.ko" in 3310usr/430sys/3714real ms. Pass 5: starting run. read performed Pass 5: run completed in 10usr/40sys/73real ms. The last three lines of the output (i.e. beginning with Pass 5) indicate that SystemTap was able to successfully create the instrumentation to probe the kernel, run the instrumentation, detect the event being probed (in this case, a virtual file system read), and execute a valid handler (print text then close it with no errors).
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Introduction.xml000066400000000000000000000224131217430427200253540ustar00rootroot00000000000000 Introduction Introduction performance monitoring performance monitoring Introduction SystemTap is a tracing and probing tool that allows users to study and monitor the activities of the computer system (particularly, the kernel) in fine detail. It provides information similar to the output of tools like netstat, ps, top, and iostat; however, SystemTap is designed to provide more filtering and analysis options for collected information. For system administrators, SystemTap can be used as a performance monitoring tool for &PROD;. It is most useful when other similar tools cannot precisely pinpoint a bottleneck in the system, requiring a deep analysis of system activity. In the same manner, application developers can also use SystemTap to monitor, in finer detail, how their application behaves within the Linux system. For system administrators, SystemTap can be used as a performance monitoring tool for &PROD2;. It is most useful when other similar tools cannot precisely pinpoint a bottleneck in the system, requiring a deep analysis of kernel activity. In the same manner, application developers can also use SystemTap to monitor, in finer detail, how their application behaves within the Linux system.
Documentation Goals Introduction documentation goals documentation goals Introduction Introduction goals, documentation goals, documentation Introduction SystemTap provides the infrastructure to monitor the running Linux kernel for detailed analysis. This can assist administrators and developers in identifying the underlying cause of a bug or performance problem. Without SystemTap, monitoring the activity of a running kernel would require a tedious instrument, recompile, install, and reboot sequence. SystemTap is designed to eliminate this, allowing users to gather the same information by simply running user-written SystemTap scripts. However, SystemTap was initially designed for users with intermediate to advanced knowledge of the kernel. This makes SystemTap less useful to administrators or developers with limited knowledge of and experience with the Linux kernel. Moreover, much of the existing SystemTap documentation is similarly aimed at knowledgeable and experienced users. This makes learning the tool similarly difficult. To lower these barriers the SystemTap Beginners Guide was written with the following goals: To introduce users to SystemTap, familiarize them with its architecture, and provide setup instructions. To provide pre-written SystemTap scripts for monitoring detailed activity in different components of the system, along with instructions on how to run them and analyze their output. above, Short description on the underlying goals of SystemTap_Beginners_Guide, what we want to teach users.
SystemTap Capabilities ** Short summary; when is SystemTap suitable vs other popular monitoring tools (e.g. top, Oprofile, /proc) Introduction capabilities of SystemTap capabilities of SystemTap Introduction SystemTap was originally developed to provide functionality for &PROD; similar to previous Linux probing tools such as dprobes and the Linux Trace Toolkit. SystemTap aims to supplement the existing suite of Linux monitoring tools by providing users with the infrastructure to track kernel activity. In addition, SystemTap combines this capability with two things: SystemTap was originally developed to provide functionality for Fedora similar to previous Linux probing tools such as dprobes and the Linux Trace Toolkit. SystemTap aims to supplement the existing suite of Linux monitoring tools by providing users with the infrastructure to track kernel activity. In addition, SystemTap combines this capability with two things: Flexibility: SystemTap's framework allows users to develop simple scripts for investigating and monitoring a wide variety of kernel functions, system calls, and other events that occur in kernel-space. With this, SystemTap is not so much a tool as it is a system that allows you to develop your own kernel-specific forensic and monitoring tools. Ease-Of-Use: as mentioned earlier, SystemTap allows users to probe kernel-space events without having to resort to instrument, recompile, install, and reboot the kernel. Most of the SystemTap scripts enumerated in demonstrate system forensics and monitoring capabilities not natively available with other similar tools (such as top, oprofile, or ps). These scripts are provided to give readers extensive examples of the application of SystemTap, which in turn will educate them further on the capabilities they can employ when writing their own SystemTap scripts. Introduction limitations of SystemTap limitations of SystemTap Introduction Limitations The current iteration of SystemTap allows for a multitude of options when probing kernel-space events for a wide range of kernels. However, SystemTap's ability to probe user-space events is dependent on kernel support (the Utrace mechanism) that is unavailable in many kernels. Thus, only some kernel versions support user-space probing. At present, the developmental efforts of the SystemTap community are geared towards improving SystemTap's user-space probing capabilities.
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Legal_Notice.xml000066400000000000000000000017171217430427200252240ustar00rootroot00000000000000 This documentation is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. For more details see the file COPYING in the source distribution of Linux. systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Preface.xml000066400000000000000000000011411217430427200242330ustar00rootroot00000000000000 Preface systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/References.xml000066400000000000000000000101241217430427200247500ustar00rootroot00000000000000 References display links to other useful, more advanced systemtap docs - http://sourceware.org/systemtap/documentation.html, http://sourceware.org/systemtap/wiki/HomePage This chapter enumerates other references for more information about SystemTap. It is advisable that you refer to these sources in the course of writing advanced probes and tapsets. SystemTap Wiki The SystemTap Wiki is a collection of links and articles related to the deployment, usage, and development of SystemTap. You can find it at . SystemTap Tutorial Much of the content in this book comes from the SystemTap Tutorial. The SystemTap Tutorial is a more appropriate reference for users with intermediate to advanced knowledge of C++ and kernel development, and can be found at . man stapprobes The stapprobes man page enumerates a variety of probe points supported by SystemTap, along with additional aliases defined by the SystemTap tapset library. The bottom of the man page includes a list of other man pages enumerating similar probe points for specific system components, such as tapset::scsi, tapset::kprocess, tapset::signal, etc. man stapfuncs The stapfuncs man page enumerates numerous functions supported by the SystemTap tapset library, along with the prescribed syntax for each one. Note, however, that this is not a complete list of all supported functions; there are more undocumented functions available. SystemTap Tapset Reference Manual The SystemTap Tapset Reference Manual at describes the individual predefined functions and probe points of the tapsets greater detail. SystemTap Language Reference This document is a comprehensive reference of SystemTap's language constructs and syntax. It is recommended for users with a rudimentary to intermediate knowledge of C++ and other similar programming languages. The SystemTap Language Reference is available to all users at Tapset Developers Guide Once you have sufficient proficiency in writing SystemTap scripts, you can then try your hand out on writing your own tapsets. The Tapset Developers Guide describes how to add functions to your tapset library. Test Suite The systemtap-testsuite package allows you to test the entire SystemTap toolchain without having to build from source. In addition, it also contains numerous examples of SystemTap scripts you can study and test; some of these scripts are also documented in . By default, the example scripts included in systemtap-testsuite are located in /usr/share/systemtap/testsuite/systemtap.examples. systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Revision_History.xml000066400000000000000000000043471217430427200262200ustar00rootroot00000000000000 Revision History 2.0-1 Mon Jul 20 2009 Don Domingo ddomingo@redhat.com includes 5.4 minor updates and additional script "dropwatch.stp" 1.0-1 Wed Jun 17 2009 Don Domingo ddomingo@redhat.com Building+pushing to RHEL systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/ScriptConstructs.xml000066400000000000000000000654441217430427200262420ustar00rootroot00000000000000
Basic SystemTap Handler Constructs handlers SystemTap handler constructs SystemTap handlers SystemTap handler constructs handlers SystemTap handler constructs syntax and format SystemTap handlers SystemTap handler constructs syntax and format syntax and format SystemTap handler constructs handlers SystemTap supports the use of several basic constructs in handlers. The syntax for most of these handler constructs are mostly based on C and awk syntax. This section describes several of the most useful SystemTap handler constructs, which should provide you with enough information to write simple yet useful SystemTap scripts.
Variables handlers SystemTap handler constructs variables SystemTap statements SystemTap handler constructs variables variables SystemTap handler constructs handlers format and syntax SystemTap handler constructs handlers Variables can be used freely throughout a handler; simply choose a name, assign a value from a function or expression to it, and use it in an expression. SystemTap automatically identifies whether a variable should be typed as a string or integer, based on the type of the values assigned to it. For instance, if you use set the variable foo to gettimeofday_s() (as in foo = gettimeofday_s()), then foo is typed as a number and can be printed in a printf() with the integer format specifier (%d). handlers SystemTap handler constructs global SystemTap statements SystemTap handler constructs global global SystemTap handler constructs handlers Note, however, that by default variables are only local to the probe they are used in. This means that variables are initialized, used and disposed at each probe handler invocation. To share a variable between probes, declare the variable name using global outside of the probes. Consider the following example: timer-jiffies.stp global count_jiffies, count_ms probe timer.jiffies(100) { count_jiffies ++ } probe timer.ms(100) { count_ms ++ } probe timer.ms(12345) { hz=(1000*count_jiffies) / count_ms printf ("jiffies:ms ratio %d:%d => CONFIG_HZ=%d\n", count_jiffies, count_ms, hz) exit () } CONFIG_HZ, computing for computes the CONFIG_HZ setting of the kernel using timers that count jiffies and milliseconds, then computing accordingly. The global statement allows the script to use the variables count_jiffies and count_ms (set in their own respective probes) to be shared with probe timer.ms(12345). Note The ++ notation in (i.e. count_jiffies ++ and count_ms ++) is used to increment the value of a variable by 1. In the following probe, count_jiffies is incremented by 1 every 100 jiffies: probe timer.jiffies(100) { count_jiffies ++ } In this instance, SystemTap understands that count_jiffies is an integer. Because no initial value was assigned to count_jiffies, its initial value is zero by default.
Target Variables handlers target variables target variables The probe events that map to actual locations in the code (for example kernel.function("function") and kernel.statement("statement")) allow the use of target variables to obtain the value of variables visible at that location in the code. You can use the -L option to list the target variable available at a probe point. If the debug information is installed for the running kernel, you can run the following command to find out what target variables are available for the vfs_read function: stap -L 'kernel.function("vfs_read")' This will yield something similar to the following: kernel.function("vfs_read@fs/read_write.c:277") $file:struct file* $buf:char* $count:size_t $pos:loff_t* Each target variable is proceeded by a $ and the type of the target variable follows the :. The kernel's vfs_read function has $file (pointer to structure describing the file), $buf (pointer to the user-space memory to store the read data), $count (number of bytes to read), and $pos (position to start reading from in the file) target variables at the entry to the function. When a target variable is not local to the probe point, like a global external variable or a file local static variable defined in another file then it can be referenced through @var("varname@src/file.c"). SystemTap tracks the typing information of the target variable and can examine the fields of a structure with the -> operator. The -> operator can be chained to look at data structures contained within data structures and follow pointers to other data structures. The -> operator will obtain the value in the field of the structure. The -> operator is used regardless whether accessing a field in a substructure or accessing another structure through a pointer. For example to access a field of the static files_stat target variable defined in fs/file_table.c (which holds some of the current file system sysctl tunables), one could write: stap -e 'probe kernel.function("vfs_read") { printf ("current files_stat max_files: %d\n", @var("files_stat@fs/file_table.c")->max_files); exit(); }' Which will yield something similar to the following: current files_stat max_files: 386070 For pointers to base types such as integers and strings there are a number of functions listed below to access kernel-space data. The first argument for each functions is the pointer to the data item. Similar functions are described in for accessing target variables in user-space code. kernel_char(address) Obtain the character at address from kernel memory. kernel_short(address) Obtain the short at address from kernel memory. kernel_int(address) Obtain the int at address from kernel memory. kernel_long(address) Obtain the long at address from kernel memory kernel_string(address) Obtain the string at address from kernel memory. kernel_string_n(address, n) Obtain the string at address from the kernel memory and limits the string to n bytes.
Pretty Printing Target Variables target variables pretty printing SystemTap scripts are often used to observe what is happening within the code. In many cases just printing the values of the various context variables is sufficient. SystemTap makes a number operations available that can generate printable strings for target variables: $$vars Expands to a character string that is equivalent to sprintf("parm1=%x ... parmN=%x var1=%x ... varN=%x", parm1, ..., parmN, var1, ..., varN) for each variable in scope at the probe point. Some values may be printed as =? if their run-time location cannot be found. $$locals Expands to a subset of $$vars containing only the local variables. $$parms Expands to a subset of $$vars containing only the function parameters. $$return Is available in return probes only. It expands to a string that is equivalent to sprintf("return=%x", $return) if the probed function has a return value, or else an empty string. Below is a command-line script that prints the values of the parameters passed into the function vfs_read: stap -e 'probe kernel.function("vfs_read") {printf("%s\n", $$parms); exit(); }' There are four parameters passed into vfs_read: file, buf, count, and pos. The $$parms generates a string for the parameters passed into the function. In this case all but the count parameter are pointers. The following is an example of the output from the previous command-line script: file=0xffff8800b40d4c80 buf=0x7fff634403e0 count=0x2004 pos=0xffff8800af96df48 Having the address a pointer points to may not be useful. You might be more interested in the fields of the data structure the pointer points to. You can use the $ suffix to pretty print the data structure. The following command-line example uses the pretty printing suffix to print more details about the data structures passed into the function vfs_read: stap -e 'probe kernel.function("vfs_read") {printf("%s\n", $$parms$); exit(); }' The previous command line will generate something similar to the following with the fields of the data structure included in the output: file={.f_u={...}, .f_path={...}, .f_op=0xffffffffa06e1d80, .f_lock={...}, .f_count={...}, .f_flags=34818, .f_mode=31, .f_pos=0, .f_owner={...}, .f_cred=0xffff88013148fc80, .f_ra={...}, .f_version=0, .f_security=0xffff8800b8dce560, .private_data=0x0, .f_ep_links={...}, .f_mapping=0xffff880037f8fdf8} buf="" count=8196 pos=-131938753921208 With the $ suffix fields that are composed of data structures are not expanded. The $$ suffix will print the values contained within the nested data structures. Below is an example using the $$ suffix: stap -e 'probe kernel.function("vfs_read") {printf("%s\n", $$parms$$); exit(); }' The $$ suffix, like all strings, is limited to the maximum string size. Below is a represenative output from the previous command-line script, which is truncated because of the string size limit: file={.f_u={.fu_list={.next=0xffff8801336ca0e8, .prev=0xffff88012ded0840}, .fu_rcuhead={.next=0xffff8801336ca0e8, .func=0xffff88012ded0840}}, .f_path={.mnt=0xffff880132fc97c0, .dentry=0xffff88001a889cc0}, .f_op=0xffffffffa06f64c0, .f_lock={.raw_lock={.slock=196611}}, .f_count={.counter=2}, .f_flags=34818, .f_mode=31, .f_pos=0, .f_owner={.lock={.raw_lock={.lock=16777216}}, .pid=0x0, .pid_type=0, .uid=0, .euid=0, .signum=0}, .f_cred=0xffff880130129a80, .f_ra={.start=0, .size=0, .async_size=0, .ra_pages=32, .
Typecasting target variables typecasting In most cases SystemTap can determine a variable's type from the debug information. However, code may use void pointers for variables (for example memory allocation routines) and typing information is not available. Also the typing information available within a probe handler is not available within a function; SystemTap functions arguments use a long in place of a typed pointer. SystemTap's @cast operator (first available in SystemTap 0.9) can be used to indicate the correct type of the object. The is from the task.stp tapset. The function returns the value of the state field from a task_struct pointed to by the long task. The first argument of the @cast operator, task, is the pointer to the object. The second argument is the type to cast the object to, task_struct. The third arument lists what file that the type definition information comes from and is optional. With the @cast operator the various fields of this particular task_struct task can be accessed; in this example the state field is obtained. Casting Example
Checking Target Variable Availablility target variables variable availability As code evolves the target variables available may change. The @defined makes it easier to handle those variations in the available target variables. The @defined provides a test to see if a particular target variable is available. The result of this test can be used to select the appropriate expression. The from the memory.stp tapset provides an probe event alias. Some version of the kernel functions being probed have an argument $flags. When available, the $flags argument is used to generate the local variable write_access. The versions of the probed functions that do not have the $flags argument have a $write argument and that is used instead for the local variable write_access. Testing target variable available Example
Conditional Statements handlers conditional statements SystemTap statements conditional statements In some cases, the output of a SystemTap script may be too big. To address this, you need to further refine the script's logic in order to delimit the output into something more relevant or useful to your probe. You can do this by using conditionals in handlers. SystemTap accepts the following types of conditional statements: If/Else Statements handlers conditional statements if/else SystemTap statements conditional statements if/else if/else conditional statements handlers Format: if (condition) statement1 else statement2 The statement1 is executed if the condition expression is non-zero. The statement2 is executed if the condition expression is zero. The else clause (else statement2) is optional. Both statement1 and statement2 can be statement blocks. ifelse.stp global countread, countnonread probe kernel.function("vfs_read"),kernel.function("vfs_write") { if (probefunc()=="vfs_read") countread ++ else countnonread ++ } probe timer.s(5) { exit() } probe end { printf("VFS reads total %d\n VFS writes total %d\n", countread, countnonread) } is a script that counts how many virtual file system reads (vfs_read) and writes (vfs_write) the system performs within a 5-second span. When run, the script increments the value of the variable countread by 1 if the name of the function it probed matches vfs_read (as noted by the condition if (probefunc()=="vfs_read")); otherwise, it increments countnonread (else {countnonread ++}). While Loops handlers conditional statements while loops SystemTap statements conditional statements while loops while loops conditional statements handlers Format: while (condition) statement So long as condition is non-zero the block of statements in statement are executed. The statement is often a statement block and it must change a value so condition will eventually be zero. For Loops handlers conditional statements for loops SystemTap statements conditional statements for loops for loops conditional statements handlers Format: for (initialization; conditional; increment) statement The for loop is simply shorthand for a while loop. The following is the equivalent while loop: initialization while (conditional) { statement increment } need simple, simple examples for FOR and WHILE Conditional Operators handlers conditional statements conditional operators SystemTap statements conditional statements conditional operators conditional operators conditional statements handlers Aside from == ("is equal to"), you can also use the following operators in your conditional statements: >= Greater than or equal to <= Less than or equal to != Is not equal to
Command-Line Arguments handlers SystemTap handler constructs command-line arguments SystemTap statements SystemTap handler constructs command-line arguments command-line arguments SystemTap handler constructs handlers You can also allow a SystemTap script to accept simple command-line arguments using a $ or @ immediately followed by the number of the argument on the command line. Use $ if you are expecting the user to enter an integer as a command-line argument, and @ if you are expecting a string. commandlineargs.stp probe kernel.function(@1) { } probe kernel.function(@1).return { } is similar to , except that it allows you to pass the kernel function to be probed as a command-line argument (as in stap commandlineargs.stp kernel function). You can also specify the script to accept multiple command-line arguments, noting them as @1, @2, and so on, in the order they are entered by the user. handlers SystemTap handler constructs variable notations SystemTap statements SystemTap handler constructs variable notations variable notations SystemTap handler constructs handlers
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Scripts.xml000066400000000000000000001125401217430427200243230ustar00rootroot00000000000000
SystemTap Scripts scripts introduction SystemTap scripts introduction For the most part, SystemTap scripts are the foundation of each SystemTap session. SystemTap scripts instruct SystemTap on what type of information to collect, and what to do once that information is collected. scripts introduction components SystemTap scripts introduction components components SystemTap scripts introduction scripts introduction events and handlers SystemTap scripts introduction events and handlers handlers and events SystemTap scripts introduction As stated in , SystemTap scripts are made up of two components: events and handlers. Once a SystemTap session is underway, SystemTap monitors the operating system for the specified events and executes the handlers as they occur. Note scripts introduction probes SystemTap scripts introduction probes probes SystemTap scripts introduction An event and its corresponding handler is collectively called a probe. A SystemTap script can have multiple probes. A probe's handler is commonly referred to as a probe body. In terms of application development, using events and handlers is similar to instrumenting the code by inserting diagnostic print statements in a program's sequence of commands. These diagnostic print statements allow you to view a history of commands executed once the program is run. SystemTap scripts allow insertion of the instrumentation code without recompilation of the code and allows more flexibility with regard to handlers. Events serve as the triggers for handlers to run; handlers can be specified to record specified data and print it in a certain manner. Format scripts introduction format and syntax SystemTap scripts introduction format and syntax format and syntax SystemTap scripts introduction syntax and format SystemTap scripts introduction SystemTap scripts use the file extension .stp, and contains probes written in the following format: probe event {statements} SystemTap supports multiple events per probe; multiple events are delimited by a comma (,). If multiple events are specified in a single probe, SystemTap will execute the handler when any of the specified events occur. scripts introduction statement blocks SystemTap scripts introduction statement blocks statement blocks SystemTap scripts introduction Each probe has a corresponding statement block. This statement block is enclosed in braces ({ }) and contains the statements to be executed per event. SystemTap executes these statements in sequence; special separators or terminators are generally not necessary between multiple statements. Note Statement blocks in SystemTap scripts follow the same syntax and semantics as the C programming language. A statement block can be nested within another statement block. scripts introduction functions SystemTap scripts introduction functions functions SystemTap scripts introduction Systemtap allows you to write functions to factor out code to be used by a number of probes. Thus, rather than repeatedly writing the same series of statements in multiple probes, you can just place the instructions in a function, as in: function function_name(arguments) {statements} probe event {function_name(arguments)} The statements in function_name are executed when the probe for event executes. The arguments are optional values passed into the function. Important is designed to introduce readers to the basics of SystemTap scripts. To understand SystemTap scripts better, it is advisable that you refer to ; each section therein provides a detailed explanation of the script, its events, handlers, and expected output.
Event Events introduction SystemTap events can be broadly classified into two types: synchronous and asynchronous. Synchronous Events Events synchronous events synchronous events Events A synchronous event occurs when any process executes an instruction at a particular location in kernel code. This gives other events a reference point from which more contextual data may be available. Events examples of synchronous and asynchronous events examples of synchronous and asynchronous events Events Examples of synchronous events include: syscall.system_call Events syscall.system_call syscall.system_call Events The entry to the system call system_call. If the exit from a syscall is desired, appending a .return to the event monitor the exit of the system call instead. For example, to specify the entry and exit of the system call close, use syscall.close and syscall.close.return respectively. vfs.file_operation Events vfs.file_operation vfs.file_operation Events The entry to the file_operation event for Virtual File System (VFS). Similar to syscall event, appending a .return to the event monitors the exit of the file_operation operation. kernel.function("function") Events kernel.function("function") kernel.function("function") Events The entry to the kernel function function. For example, kernel.function("sys_open") refers to the "event" that occurs when the kernel function sys_open is called by any thread in the system. To specify the return of the kernel function sys_open, append the return string to the event statement; i.e. kernel.function("sys_open").return. Events wildcards wildcards in events events wildcards When defining probe events, you can use asterisk (*) for wildcards. You can also trace the entry or exit of a function in a kernel source file. Consider the following example: wildcards.stp probe kernel.function("*@net/socket.c") { } probe kernel.function("*@net/socket.c").return { } Wild cards also work for other types of events, e.g. syscall.* In the previous example, the first probe's event specifies the entry of ALL functions in the kernel source file net/socket.c. The second probe specifies the exit of all those functions. Note that in this example, there are no statements in the handler; as such, no information will be collected or displayed. kernel.trace("tracepoint") tracepoint Events kernel.trace("tracepoint") kernel.trace("tracepoint") Events The static probe for tracepoint. Recent kernels (2.6.30 and newer) include instrumentation for specific events in the kernel. These events are statically marked with tracepoints. One example of a tracepoint available in systemtap is kernel.trace("kfree_skb") which indicates each time a network buffer is freed in the kernel. module("module").function("function") Events module("module") module("module") Events Allows you to probe functions within modules. For example: moduleprobe.stp probe module("ext3").function("*") { } probe module("ext3").function("*").return { } The first probe in points to the entry of all functions for the ext3 module. The second probe points to the exits of all functions for that same module; the use of the .return suffix is similar to kernel.function(). Note that the probes in do not contain statements in the probe handlers, and as such will not print any useful data (as in ). A system's kernel modules are typically located in /lib/modules/kernel_version, where kernel_version refers to the currently loaded kernel version. Modules use the file name extension .ko. Asynchronous Events Events asynchronous events asynchronous events Events Asynchronous events are not tied to a particular instruction or location in code. This family of probe points consists mainly of counters, timers, and similar constructs. Examples of asynchronous events include: begin Events begin begin Events The startup of a SystemTap session; i.e. as soon as the SystemTap script is run. end Events end end Events The end of a SystemTap session. timer events Events timer events timer events Events An event that specifies a handler to be executed periodically. For example: timer-s.stp probe timer.s(4) { printf("hello world\n") } is an example of a probe that prints hello world every 4 seconds. Note that you can also use the following timer events: timer.ms(milliseconds) timer.us(microseconds) timer.ns(nanoseconds) timer.hz(hertz) timer.jiffies(jiffies) When used in conjunction with other probes that collect information, timer events allows you to print out get periodic updates and see how that information changes over time. Important SystemTap supports the use of a large collection of probe events. For more information about supported events, refer to man stapprobes. The SEE ALSO section of man stapprobes also contains links to other man pages that discuss supported events for specific subsystems and components. is reference appropriate? too advanced for readers (it seems so to me)? please advise.
Systemtap Handler/Body handlers introduction Consider the following sample script: helloworld.stp probe begin { printf ("hello world\n") exit () } In , the event begin (i.e. the start of the session) triggers the handler enclosed in { }, which simply prints hello world followed by a new-line, then exits. Note functions (used in handlers) exit() exit() functions SystemTap scripts continue to run until the exit() function executes. If the users wants to stop the execution of the script, it can interrupted manually with CtrlC. printf ( ) Statements printf() format strings The printf () statement is one of the simplest functions for printing data. printf () can also be used to display data using a wide variety of SystemTap functions in the following format: printf ("format string\n", arguments) printf() format strings format strings printf() The format string specifies how arguments should be printed. The format string of simply instructs SystemTap to print hello world, and contains no format specifiers. printf() format specifiers format specifiers printf() You can use the format specifiers %s (for strings) and %d (for numbers) in format strings, depending on your list of arguments. Format strings can have multiple format specifiers, each matching a corresponding argument; multiple arguments are delimited by a comma (,). Note printf() syntax and format syntax and format printf() format and syntax printf() Semantically, the SystemTap printf function is very similar to its C language counterpart. The aforementioned syntax and format for SystemTap's printf function is identical to that of the C-style printf. To illustrate this, consider the following probe example: variables-in-printf-statements.stp probe syscall.open { printf ("%s(%d) open\n", execname(), pid()) } instructs SystemTap to probe all entries to the system call open; for each event, it prints the current execname() (a string with the executable name) and pid() (the current process ID number), followed by the word open. A snippet of this probe's output would look like: editorial review: does a clarification that "format specifier1" is to "argument1", "format specifier2" is to "argument2", or is this clear enough? vmware-guestd(2206) open hald(2360) open hald(2360) open hald(2360) open df(3433) open df(3433) open df(3433) open hald(2360) open SystemTap Functions functions SystemTap script functions handler functions SystemTap supports a wide variety of functions that can be used as printf () arguments. uses the SystemTap functions execname() (name of the process that called a kernel function/performed a system call) and pid() (current process ID). is "handler function" an appropriate term? wcohen: use "SystemTap functions" to match up language in man pages The following is a list of commonly-used SystemTap functions: tid() functions tid() functions tid() tid() functions The ID of the current thread. uid() functions uid() uid() functions The ID of the current user. cpu() functions cpu() cpu() functions The current CPU number. gettimeofday_s() functions gettimeofday_s() gettimeofday_s() functions The number of seconds since UNIX epoch (January 1, 1970). ctime() functions ctime() ctime() functions Convert number of seconds since UNIX epoch to date. pp() functions pp() pp() functions A string describing the probe point currently being handled. thread_indent() functions thread_indent() thread_indent() functions This particular function is quite useful, providing you with a way to better organize your print results. The function takes one argument, an indentation delta, which indicates how many spaces to add or remove from a thread's "indentation counter". It then returns a string with some generic trace data along with an appropriate number of indentation spaces. The generic data included in the returned string includes a timestamp (number of microseconds since the first call to thread_indent() by the thread), a process name, and the thread ID. This allows you to identify what functions were called, who called them, and the duration of each function call. If call entries and exits immediately precede each other, it is easy to match them. However, in most cases, after a first function call entry is made several other call entries and exits may be made before the first call exits. The indentation counter helps you match an entry with its corresponding exit by indenting the next function call if it is not the exit of the previous one. Consider the following example on the use of thread_indent(): thread_indent.stp probe kernel.function("*@net/socket.c").call { printf ("%s -> %s\n", thread_indent(1), probefunc()) } probe kernel.function("*@net/socket.c").return { printf ("%s <- %s\n", thread_indent(-1), probefunc()) } prints out the thread_indent() and probe functions at each event in the following format: 0 ftp(7223): -> sys_socketcall 1159 ftp(7223): -> sys_socket 2173 ftp(7223): -> __sock_create 2286 ftp(7223): -> sock_alloc_inode 2737 ftp(7223): <- sock_alloc_inode 3349 ftp(7223): -> sock_alloc 3389 ftp(7223): <- sock_alloc 3417 ftp(7223): <- __sock_create 4117 ftp(7223): -> sock_create 4160 ftp(7223): <- sock_create 4301 ftp(7223): -> sock_map_fd 4644 ftp(7223): -> sock_map_file 4699 ftp(7223): <- sock_map_file 4715 ftp(7223): <- sock_map_fd 4732 ftp(7223): <- sys_socket 4775 ftp(7223): <- sys_socketcall This sample output contains the following information: The time (in microseconds) since the initial thread_indent() call for the thread (included in the string from thread_indent()). The process name (and its corresponding ID) that made the function call (included in the string from thread_indent()). An arrow signifying whether the call was an entry (<-) or an exit (->); the indentations help you match specific function call entries with their corresponding exits. The name of the function called by the process. remember to add a reference later to "tapsets" from here, to clarify that thread_indent is defined in tapsets as a special function of sorts name local variables name variables (local) name name local variables Identifies the name of a specific system call. This variable can only be used in probes that use the event syscall.system_call. target() functions target() target() functions Used in conjunction with stap script -x process ID or stap script -c command. If you want to specify a script to take an argument of a process ID or command, use target() as the variable in the script to refer to it. For example: targetexample.stp probe syscall.* { if (pid() == target()) printf("%s\n", name) } When is run with the argument -x process ID, it watches all system calls (as specified by the event syscall.*) and prints out the name of all system calls made by the specified process. This has the same effect as specifying if (pid() == process ID) each time you wish to target a specific process. However, using target() makes it easier for you to re-use the script, giving you the ability to simply pass a process ID as an argument each time you wish to run the script (e.g. stap targetexample.stp -x process ID). For more information about supported SystemTap functions, refer to man stapfuncs. will need a complete listing of supported handler functions? also, SystemTap function descriptions seem ambiguous, please advise.
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Section.xml000066400000000000000000000004471217430427200243020ustar00rootroot00000000000000
Section 1 Test Test of a section
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/SystemTap_Beginners_Guide.ent000066400000000000000000000004171217430427200277230ustar00rootroot00000000000000 systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/SystemTap_Beginners_Guide.xml000066400000000000000000000027351217430427200277420ustar00rootroot00000000000000 systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Tips_Tricks.xml000066400000000000000000000012061217430427200251260ustar00rootroot00000000000000 Tips and Tricks - This chapter covers miscellaneous tips/tricks - This is a tentative section, and will only be included if content can be provided - add use of exit() here - add "basic constructs" here; i.e. using if/else, while loops, for loops, examples; if done, consider moving up to before Useful_SystemTap_Scripts.xm, after Understanding_How_SystemTap_Works.xml systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Understanding_How_SystemTap_Works.xml000066400000000000000000000200601217430427200315070ustar00rootroot00000000000000 Understanding How SystemTap Works Short summary; probes, handlers, events Understanding How SystemTap Works SystemTap allows users to write and reuse simple scripts to deeply examine the activities of a running Linux system. These scripts can be designed to extract data, filter it, and summarize it quickly (and safely), enabling the diagnosis of complex performance (or even functional) problems. Understanding How SystemTap Works events and handlers events and handlers handlers and events The essential idea behind a SystemTap script is to name events, and to give them handlers. When SystemTap runs the script, SystemTap monitors for the event; once the event occurs, the Linux kernel then runs the handler as a quick sub-routine, then resumes. Understanding How SystemTap Works event types event types Understanding How SystemTap Works There are several kind of events; entering/exiting a function, timer expiration, session termination, etc. A handler is a series of script language statements that specify the work to be done whenever the event occurs. This work normally includes extracting data from the event context, storing them into internal variables, and printing results.
Architecture ** add diagram, describe architecture, enumerate common tools ** architecture diagram must be simpler, if at all included ** add design advantages? e.g. "building kmods on-the-fly allows safer execution of script etc etc" Understanding How SystemTap Works architecture architecture of SystemTap SystemTap architecture A SystemTap session begins when you run a SystemTap script. This session occurs in the following fashion: SystemTap Session Understanding How SystemTap Works SystemTap sessions SystemTap sessions sessions, SystemTap First, SystemTap checks the script against the existing tapset library (normally in /usr/share/systemtap/tapset/ for any tapsets used. SystemTap will then substitute any located tapsets with their corresponding definitions in the tapset library. SystemTap then translates the script to C, running the system C compiler to create a kernel module from it. The tools that perform this step are contained in the systemtap package (refer to for more information). SystemTap loads the module, then enables all the probes (events and handlers) in the script. The staprun in the systemtap-runtime package (refer to for more information) provides this functionality. As the events occur, their corresponding handlers are executed. Once the SystemTap session is terminated, the probes are disabled, and the kernel module is unloaded. This sequence is driven from a single command-line program: stap. This program is SystemTap's main front-end tool. For more information about stap, refer to man stap (once SystemTap is properly installed on your machine).
Tapsets Tapsets definition of definition, significance, difference with stap scripts (previous section), library of tapsets in system: location Tapsets are scripts that form a library of pre-written probes and functions to be used in SystemTap scripts. When a user runs a SystemTap script, SystemTap checks the script's probe events and handlers against the tapset library; SystemTap then loads the corresponding probes and functions before translating the script to C (refer to for information on what transpires in a SystemTap session). Like SystemTap scripts, tapsets use the file name extension .stp. The standard library of tapsets is located in /usr/share/systemtap/tapset/ by default. However, unlike SystemTap scripts, tapsets are not meant for direct execution; rather, they constitute the library from which other scripts can pull definitions. Simply put, the tapset library is an abstraction layer designed to make it easier for users to define events and functions. In a manner of speaking, tapsets provide useful aliases for functions that users may want to specify as an event; knowing the proper alias to use is, for the most part, easier than remembering specific kernel functions that might vary between kernel versions. Several handlers and functions in and are defined in tapsets. For example, thread_indent() is defined in indent.stp. any other details to be included? i dont want to dwell too long here, though, since IMHO tapset development is beyond the scope of this "beginner's guide"
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Advanced_Scripts.xml000066400000000000000000000030041217430427200274250ustar00rootroot00000000000000 Useful SystemTap Scripts This chapter contains several advanced applications of SystemTap. The scripts enumerated herein combine SystemTap scripts with other tools in order to address some complex administrative tasks. All of these scripts are available at the following link: http://sourceware.org/systemtap/wiki/WarStories?action=fullsearch&context=180&value=traceio2&titlesearch=Titles Due to the relative length of the scripts discussed in this chapter, the full version of each script is documented in . this chapter will feature the following scripts: http://sourceware.org/systemtap/wiki/WSPSTimeouts?highlight=((WarStories)) http://sourceware.org/systemtap/wiki/WSPfiles?highlight=((WarStories)) http://sourceware.org/systemtap/wiki/WSPSTimeouts?highlight=%28%28WarStories%29%29 WAIT http://sourceware.org/systemtap/wiki/WSPanicOnOom?highlight=((WarStories)) http://sourceware.org/systemtap/wiki/WSPfiles?highlight=((WarStories)) systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-Disk.xml000066400000000000000000000110171217430427200265330ustar00rootroot00000000000000
Real-Time Graphing of Disk and CPU Utilization http://sourceware.org/systemtap/examples/subsystem-index.html Graphing Disk and CPU Utilization - http://sourceware.org/systemtap/examples/general/graphs.stp This section describes how you can graph disk and CPU utilization in real-time, i.e. in samples of 1 second each. disk-usage-graph.stp #! stap # disk I/O stats probe begin { qnames["ioblock"] ++; qsq_start ("ioblock") } probe ioblock.request { qs_wait ("ioblock") qs_run("ioblock") } probe ioblock.end { qs_done ("ioblock") } # CPU utilization probe begin { qnames["cpu"] ++; qsq_start ("cpu") } probe scheduler.cpu_on { if (!idle) {qs_wait ("cpu") qs_run ("cpu") }} probe scheduler.cpu_off { if (!idle) qs_done ("cpu") } # ------------------------------------------------------------------------ # utilization history tracking global N probe begin { N = 50 } global qnames, util, histidx function qsq_util_reset(q) { u=qsq_utilization (q, 100) qsq_start (q) return u } probe timer.ms(100) { # collect utilization percentages frequently histidx = (histidx + 1) % N # into circular buffer foreach (q in qnames) util[histidx,q] = qsq_util_reset(q) } # ------------------------------------------------------------------------ # general gnuplot graphical report generation probe timer.ms(1000) { # emit gnuplot command to display recent history printf ("set yrange [0:100]\n") printf ("plot ") foreach (q in qnames+) { if (++nq >= 2) printf (", ") printf ("'-' title \"%s\" with lines", q) } printf ("\n") foreach (q in qnames+) { for (i = (histidx + 1) % N; i != histidx; i = (i + 1) % N) printf("%d\n", util[i,q]) printf ("e\n") } printf ("pause 1\n") } outputs raw statistics on both CPU and disk usage per second. I/O usage is tracked through the events ioblock.request and ioblock.request.end, which track each request (and request completion) for a generic block I/O. CPU usage is tracked through scheduler.cpu_on and scheduler.cpu_off, which are activated whenever a process begins (and ends) a command execution on a CPU.
gnuplot Running by itself hardly presents any data that is useful, as in . Raw disk-usage-graph.stp Output [...] 62 5 3 4 6 4 4 5 5 3 6 5 e pause 1 However, refining the output of through gnuplot presents us with a more useful result. gnuplot is a lightweight, command-line driven plotting program that helps you display data in a graphical format. By piping output to gnuplot (as in stap disk-usage-gr http://sourceware.org/systemtap/examples/subsystem-index.html Graphing Disk and CPU Utilization - http://sourceware.org/systemtap/examples/general/graphs.stp aph.stp | gnuplot), we get a graphical output similar to the following:
Graphical Output Sample Sample output
presents a cleaner, more useful graphical output. This graph can show you the level of utilization for both I/O and CPU, in real time. question: does this script also capture stap process? i.e. does the graph also include CPU utilization by systemtap while the script is running? systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-IO.xml000066400000000000000000000014571217430427200261570ustar00rootroot00000000000000
I/O Subsystem http://sourceware.org/systemtap/examples/subsystem-index.html Tally Reschedule Reason During AIO io_submit Call - http://sourceware.org/systemtap/examples/io/io_submit.stp Periodically Print I/O Activity by Process Name - http://sourceware.org/systemtap/examples/io/iotop.stp Track Cumulative I/O Activity by Process Name - http://sourceware.org/systemtap/examples/io/traceio.stp Watch I/O Activity on a Particular Device http://sourceware.org/systemtap/examples/io/traceio2.stp
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-Kernel.xml000066400000000000000000000014151217430427200270620ustar00rootroot00000000000000
Kernel http://sourceware.org/systemtap/examples/subsystem-index.html Tracing Calls for Sections of Code - http://sourceware.org/systemtap/examples/general/para-callgraph.stp Profile kernel functions - http://sourceware.org/systemtap/examples/process/pf2.stp Count Times Functions Called - http://sourceware.org/systemtap/examples/profiling/functioncallcount.stp Profile kernel functions - http://sourceware.org/systemtap/examples/profiling/thread-times.stp
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-Network.xml000066400000000000000000000011001217430427200272620ustar00rootroot00000000000000
Network http://sourceware.org/systemtap/examples/subsystem-index.html Periodic Listing of Processes Using Network Interfaces - http://sourceware.org/systemtap/examples/network/nettop.stp Trace Functions called in Network Socket Code - http://sourceware.org/systemtap/examples/network/socket-trace.stp
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-Others.xml000066400000000000000000000013331217430427200271050ustar00rootroot00000000000000
Other Useful Scripts http://sourceware.org/systemtap/examples/subsystem-index.html SCHEDULER - Generating Backtraces of Threads Waiting for IO Operations - http://sourceware.org/systemtap/examples/process/sleepingBeauties.stp LOCKING - System-Wide Futex Contention - http://sourceware.org/systemtap/examples/process/futexes.stp CPU - Graphing Disk and CPU Utilization - http://sourceware.org/systemtap/examples/general/graphs.stp
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-Signals.xml000066400000000000000000000014101217430427200272350ustar00rootroot00000000000000
Signals http://sourceware.org/systemtap/examples/subsystem-index.html Signal Counts by Process ID - http://sourceware.org/systemtap/examples/process/sig_by_pid.stp Signal Counts by Process Name - http://sourceware.org/systemtap/examples/process/sig_by_proc.stp Track SIGKILL Signals - http://sourceware.org/systemtap/examples/process/sigkill.stp System-Wide Count of Syscalls by PID - http://sourceware.org/systemtap/examples/process/syscalls_by_pid.stp
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-Syscalls.xml000066400000000000000000000016701217430427200274420ustar00rootroot00000000000000
System Calls http://sourceware.org/systemtap/examples/subsystem-index.html Trace Time Spent in Read and Write for Files - http://sourceware.org/systemtap/examples/io/iotime.stp Trace Time Spent in nanosleep Syscalls - http://sourceware.org/systemtap/examples/process/sleeptime.stp System-Wide Count of Syscalls by PID - http://sourceware.org/systemtap/examples/process/syscalls_by_pid.stp System-Wide Count of Syscalls by Executable - http://sourceware.org/systemtap/examples/process/syscalls_by_proc.stp Trace Time Spent in wait4 Syscalls - http://sourceware.org/systemtap/examples/process/wait4time.stp
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-disktop.xml000066400000000000000000000163021217430427200273200ustar00rootroot00000000000000
Summarizing Disk Read/Write Traffic script examples summarizing disk I/O traffic examples of SystemTap scripts summarizing disk I/O traffic summarizing disk I/O traffic script examples NO ENTRY IN WAR STORIES: Summarize Disk Read/Write Traffic http://sourceware.org/systemtap/examples/io/disktop.stp disk I/O traffic, summarizing script examples I/O traffic, summarizing script examples heaviest disk reads/writes, identifying script examples summarizing disk I/O traffic script examples identifying heaviest disk reads/writes script examples This section describes how to identify which processes are performing the heaviest disk reads/writes to the system. disktop.stp outputs the top ten processes responsible for the heaviest reads/writes to disk. displays a sample output for this script, and includes the following data per listed process: UID — user ID. A user ID of 0 refers to the root user. PID — the ID of the listed process. PPID — the process ID of the listed process's parent process. CMD — the name of the listed process. DEVICE — which storage device the listed process is reading from or writing to. T — the type of action performed by the listed process; W refers to write, while R refers to read. BYTES — the amount of data read to or written from disk. script examples ctime(), example of usage examples of SystemTap scripts ctime(), example of usage ctime(), example of usage script examples The time and date in the output of is returned by the functions ctime() and gettimeofday_s(). ctime() derives calendar time in terms of seconds passed since the Unix epoch (January 1, 1970). gettimeofday_s() counts the actual number of seconds since Unix epoch, which gives a fairly accurate human-readable timestamp for the output. local variables sample usage $return variables (local) sample usage $return $return sample usage local variables In this script, the $return is a local variable that stores the actual number of bytes each process reads or writes from the virtual file system. $return can only be used in return probes (e.g. vfs.read.return and vfs.read.return). <xref linkend="scriptdisktop"/> Sample Output [...] Mon Sep 29 03:38:28 2008 , Average: 19Kb/sec, Read: 7Kb, Write: 89Kb UID PID PPID CMD DEVICE T BYTES 0 26319 26294 firefox sda5 W 90229 0 2758 2757 pam_timestamp_c sda5 R 8064 0 2885 1 cupsd sda5 W 1678 Mon Sep 29 03:38:38 2008 , Average: 1Kb/sec, Read: 7Kb, Write: 1Kb UID PID PPID CMD DEVICE T BYTES 0 2758 2757 pam_timestamp_c sda5 R 8064 0 2885 1 cupsd sda5 W 1678
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-dropwatch.xml000066400000000000000000000102421217430427200276330ustar00rootroot00000000000000
Monitoring Network Packets Drops in Kernel script examples network profiling examples of SystemTap scripts network profiling network profiling examples of SystemTap scripts profiling the network examples of SystemTap scripts network traffic, monitoring examples of SystemTap scripts tracepoint The network stack in Linux can discard packets for various reasons. Some Linux kernels include a tracepoint, kernel.trace("kfree_skb"), which easily tracks where packets are discarded. uses kernel.trace("kfree_skb") to trace packet discards; the script summarizes which locations discard packets every five-second interval. dropwatch.stp The kernel.trace("kfree_skb") traces which places in the kernel drop network packets. The kernel.trace("kfree_skb") has two arguments: a pointer to the buffer being freed ($skb) and the location in kernel code the buffer is being freed ($location). The script provides the function containing $location where possible. The information to map $location back to the function is not in the instrumentation by default. On Systemtap 1.4 the --all-modules option will include the required mapping information and the following command can be used to run the script: stap --all-modules dropwatch.stp On older versions of Systemtap you can use the following command to emulate the --all-modules option: stap -dkernel \ `cat /proc/modules | awk 'BEGIN { ORS = " " } {print "-d"$1}'` \ dropwatch.stp Running the dropwatch.stp script 15 seconds would result in output similar in . The output lists the number of misses for each tracepoint location with either the function name or the address. <xref linkend="dropwatch"/> Sample Output Monitoring for dropped packets 1762 packets dropped at unix_stream_recvmsg 4 packets dropped at tun_do_read 2 packets dropped at nf_hook_slow 467 packets dropped at unix_stream_recvmsg 20 packets dropped at nf_hook_slow 6 packets dropped at tun_do_read 446 packets dropped at unix_stream_recvmsg 4 packets dropped at tun_do_read 4 packets dropped at nf_hook_slow Stopping dropped packet monitor When the script is being compiled on one machine and run on another the --all-modules and /proc/modules directory are not available; the symname function will just print out the raw address. To make the raw address of packet drops more meaningful, refer to the /boot/System.map-`uname -r` file. This file lists the starting addresses for each function, allowing you to map the addresses in the output of to a specific function name. Given the following snippet of the /boot/System.map-`uname -r` file, the address 0xffffffff8149a8ed maps to the function unix_stream_recvmsg: [...] ffffffff8149a420 t unix_dgram_poll ffffffff8149a5e0 t unix_stream_recvmsg ffffffff8149ad00 t unix_find_other [...]
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-functioncalls.xml000066400000000000000000000065361217430427200305170ustar00rootroot00000000000000
Counting Function Calls Made script examples tallying function calls examples of SystemTap scripts tallying function calls tallying function calls examples of SystemTap scripts counting function calls examples of SystemTap scripts function calls, tallying examples of SystemTap scripts WAR STORY: Function call count http://sourceware.org/systemtap/wiki/WSFunctionCallCount?highlight=((WarStories)) no script in examples This section describes how to identify how many times the system called a specific kernel function in a 30-second sample. Depending on your use of wildcards, you can also use this script to target multiple kernel functions. functioncallcount.stp takes the targeted kernel function as an argument. The argument supports wildcards, which enables you to target multiple kernel functions up to a certain extent. script examples timer.ms(), sample usage examples of SystemTap scripts timer.ms(), sample usage timer.ms(), sample usage examples of SystemTap scripts The output of contains the name of the function called and how many times it was called during the sample time (in alphabetical order). contains an excerpt from the output of stap functioncallcount.stp "*@mm/*.c": <xref linkend="countcalls"/> Sample Output [...] __vma_link 97 __vma_link_file 66 __vma_link_list 97 __vma_link_rb 97 __xchg 103 add_page_to_active_list 102 add_page_to_inactive_list 19 add_to_page_cache 19 add_to_page_cache_lru 7 all_vm_events 6 alloc_pages_node 4630 alloc_slabmgmt 67 anon_vma_alloc 62 anon_vma_free 62 anon_vma_lock 66 anon_vma_prepare 98 anon_vma_unlink 97 anon_vma_unlock 66 arch_get_unmapped_area_topdown 94 arch_get_unmapped_exec_area 3 arch_unmap_area_topdown 97 atomic_add 2 atomic_add_negative 97 atomic_dec_and_test 5153 atomic_inc 470 atomic_inc_and_test 1 [...]
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-futexes.xml000066400000000000000000000117341217430427200273320ustar00rootroot00000000000000
Identifying Contended User-Space Locks script examples identifying contended user-space locks (i.e. futex contentions) examples of SystemTap scripts identifying contended user-space locks (i.e. futex contentions) identifying contended user-space locks (i.e. futex contentions) examples of SystemTap scripts contended user-space locks (futex contentions), identifying examples of SystemTap scripts WAR STORY: Futex contention http://sourceware.org/systemtap/wiki/WSFutexContention?highlight=((WarStories)) This section describes how to identify contended user-space locks throughout the system within a specific time period. The ability to identify contended user-space locks can help you investigate poor program performance that you suspect may be caused by futex contentions. futex contentions, identifying examples of SystemTap scripts futex contention, definition examples of SystemTap scripts script examples futex (lock) contentions examples of SystemTap scripts futex (lock) contentions futex (lock) contentions examples of SystemTap scripts Simply put, futex contention occurs when multiple processes are trying to access the same lock variable at the same time. This can result in a poor performance because the lock serializes execution; one process obtains the lock while the other processes must wait for the lock variable to become available again. script examples futex system call examples of SystemTap scripts futex system call futex system call examples of SystemTap scripts The script probes the futex system call to show lock contention. futexes.stp needs to be manually stopped; upon exit, it prints the following information: Name and ID of the process responsible for a contention The location of the contested lock variable How many times the lock variable was contended Average time of contention throughout the probe contains an excerpt from the output of upon exiting the script (after approximately 20 seconds). <xref linkend="futexcontention"/> Sample Output [...] automount[2825] lock 0x00bc7784 contended 18 times, 999931 avg us synergyc[3686] lock 0x0861e96c contended 192 times, 101991 avg us synergyc[3758] lock 0x08d98744 contended 192 times, 101990 avg us synergyc[3938] lock 0x0982a8b4 contended 192 times, 101997 avg us [...]
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-inodewatch.xml000066400000000000000000000122631217430427200277720ustar00rootroot00000000000000
Monitoring Reads and Writes to a File script examples monitoring reads and writes to a file examples of SystemTap scripts monitoring reads and writes to a file monitoring reads and writes to a file examples of SystemTap scripts file reads/writes, monitoring examples of SystemTap scripts reads/writes to a file, monitoring examples of SystemTap scripts writes/reads to a file, monitoring examples of SystemTap scripts WAR STORY: monitoring inode activity http://sourceware.org/systemtap/wiki/WSFileMonitor?highlight=((WarStories)) no script in examples This section describes how to monitor reads from and writes to a file in real time. inodewatch.stp need to add references to sources/man pages that explain how "dev_nr = $file->f_dentry->d_inode->i_sb->s_dev" and "($1 << 20 | $2)". takes the following information about the file as arguments on the command line: script examples file device number (integer format) examples of SystemTap scripts file device number (integer format) file device number (integer format) examples of SystemTap scripts device number of a file (integer format) examples of SystemTap scripts The file's major device number. The file's minor device number. The file's inode number. script examples stat -c, determining file device number (integer format) examples of SystemTap scripts stat -c, determining file device number (integer format) stat -c, determining file device number (integer format) examples of SystemTap scripts To get this information, use stat -c '%D %i' filename, where filename is an absolute path. For instance: if you wish to monitor /etc/crontab, run stat -c '%D %i' /etc/crontab first. This gives the following output: 805 1078319 script examples inode number examples of SystemTap scripts inode number inode number examples of SystemTap scripts 805 is the base-16 (hexadecimal) device number. The lower two digits are the minor device number and the upper digits are the major number. 1078319 is the inode number. To start monitoring /etc/crontab, run stap inodewatch.stp 0x8 0x05 1078319 (The 0x prefixes indicate base-16 values. The output of this command contains the name and ID of any process performing a read/write, the function it is performing (i.e. vfs_read or vfs_write), the device number (in hex format), and the inode number. contains the output of stap inodewatch.stp 0x8 0x05 1078319 (when cat /etc/crontab is executed while the script is running) : <xref linkend="inodewatch"/> Sample Output cat(16437) vfs_read 0x800005/1078319 cat(16437) vfs_read 0x800005/1078319
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-inodewatch2.xml000066400000000000000000000057141217430427200300570ustar00rootroot00000000000000
Monitoring Changes to File Attributes script examples monitoring changes to file attributes examples of SystemTap scripts monitoring changes to file attributes monitoring changes to file attributes examples of SystemTap scripts changes to file attributes, monitoring examples of SystemTap scripts file attributes, monitoring changes to examples of SystemTap scripts WAR STORY: monitoring more inode activity http://sourceware.org/systemtap/wiki/WSFileMonitor2?highlight=((WarStories)) no script in examples This section describes how to monitor if any processes are changing the attributes of a targeted file, in real time. inodewatch2.stp Like from , takes the targeted file's device number (in integer format) and inode number as arguments. For more information on how to retrieve this information, refer to . The output for is similar to that of , except that also contains the attribute changes to the monitored file, as well as the ID of the user responsible (uid()). shows the output of while monitoring /home/joe/bigfile when user joe executes chmod 777 /home/joe/bigfile and chmod 666 /home/joe/bigfile. <xref linkend="inodewatch2"/> Sample Output chmod(17448) inode_setattr 0x800005/6011835 100777 500 chmod(17449) inode_setattr 0x800005/6011835 100666 500
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-ioblktime.xml000066400000000000000000000066531217430427200276320ustar00rootroot00000000000000
Periodically Print I/O Block Time script examples monitoring I/O block time examples of SystemTap scripts monitoring I/O block time monitoring I/O block time examples of SystemTap scripts I/O block time, monitoring examples of SystemTap scripts printing I/O block time (periodically) examples of SystemTap scripts This section describes how to track the amount of time each block I/O requests spends waiting for completion. This is useful in determining whether there are too many outstanding block I/O operations at any given time. ioblktime.stp computes the average waiting time for block I/O per device, and prints a list every 10 seconds. As always, you can revise this refresh rate by editing the specified value in probe timer.s(10), end {. In some cases, there can be too many outstanding block I/O operations, at which point the script can exceed the default number of MAXMAPENTRIES. MAXMAPENTRIES is the maximum number of rows in an array if the array size is not specified explicitly when declared. If the script exceeds the default MAXMAPENTRIES value of 2048, run the script again with the stap option -DMAXMAPENTRIES=10000. <xref linkend="ioblktime"/> Sample Output device rw total (us) count avg (us) sda W 9659 6 1609 dm-0 W 20278 6 3379 dm-0 R 20524 5 4104 sda R 19277 5 3855 displays the device name, operations performed (rw), total wait time of all operations (total(us)), number of operations (count), and average wait time for all those operations (avg (us)). The times tallied by the script are in microseconds.
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-iotime.xml000066400000000000000000000123421217430427200271310ustar00rootroot00000000000000
Tracking I/O Time For Each File Read or Write script examples monitoring I/O time examples of SystemTap scripts monitoring I/O time monitoring I/O time examples of SystemTap scripts I/O time, monitoring examples of SystemTap scripts time of I/O examples of SystemTap scripts This section describes how to monitor the amount of time it takes for each process to read from or write to any file. This is useful if you wish to determine what files are slow to load on a given system. iotime.stp tracks each time a system call opens, closes, reads from, and writes to a file. For each file any system call accesses, counts the number of microseconds it takes for any reads or writes to finish and tracks the amount of data (in bytes) read from or written to the file. local variables sample usage $count variables (local) sample usage $count $count sample usage local variables also uses the local variable $count to track the amount of data (in bytes) that any system call attempts to read or write. Note that $return (as used in from ) stores the actual amount of data read/written. $count can only be used on probes that track data reads or writes (e.g. syscall.read and syscall.write). <xref linkend="iotime"/> Sample Output [...] 825946 3364 (NetworkManager) access /sys/class/net/eth0/carrier read: 8190 write: 0 825955 3364 (NetworkManager) iotime /sys/class/net/eth0/carrier time: 9 [...] 117061 2460 (pcscd) access /dev/bus/usb/003/001 read: 43 write: 0 117065 2460 (pcscd) iotime /dev/bus/usb/003/001 time: 7 [...] 3973737 2886 (sendmail) access /proc/loadavg read: 4096 write: 0 3973744 2886 (sendmail) iotime /proc/loadavg time: 11 [...] prints out the following data: A timestamp, in microseconds. Process ID and process name. An access or iotime flag. The file accessed. If a process was able to read or write any data, a pair of access and iotime lines should appear together. The access line's timestamp refers to the time that a given process started accessing a file; at the end of the line, it will show the amount of data read/written (in bytes). The iotime line will show the amount of time (in microseconds) that the process took in order to perform the read or write. If an access line is not followed by an iotime line, it simply means that the process did not read or write any data.
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-iotop.xml000066400000000000000000000070001217430427200267700ustar00rootroot00000000000000
Periodically Print I/O Activity script examples monitoring I/O activity examples of SystemTap scripts monitoring I/O activity monitoring I/O activity examples of SystemTap scripts I/O activity, monitoring examples of SystemTap scripts printing I/O activity (periodically) examples of SystemTap scripts This section describes how to monitor I/O activity on the system. iotop.stp prints out the top ten executables generating I/O traffic every 5-second interval, in descending order. Its output contains the process name and the amount of data read or written by the process, in KB. For example: <xref linkend="iotop"/> Sample Output [...] Process KB Read KB Written Xorg 50287 0 staprun 3328 0 multiload-apple 3039 23 sshd 208 1 floaters 14 62 NetworkManager 15 0 gnome-vfs-daemo 8 0 cupsd 3 3 sendmail 4 0 mixer_applet2 3 0 Process KB Read KB Written Xorg 51886 0 staprun 3328 0 multiload-apple 3039 23 sshd 1344 4 snmpd 90 0 floaters 15 66 NetworkManager 23 0 irqbalance 16 0 pam_timestamp_c 9 0 sendmail 4 0 displays top I/O writes and reads within a random 10-second interval. Note that also detects I/O resulting from SystemTap activity — displays reads done by staprun.
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-kernelprofiling.xml000066400000000000000000000101741217430427200310360ustar00rootroot00000000000000
Kernel Profiling WAR STORY: Kernel Profiling http://sourceware.org/systemtap/wiki/WSKernelProfile?highlight=((WarStories)) http://sourceware.org/systemtap/examples/process/pf2.stp In , you can revise the wildcards used in the probe to target all kernel functions. This can be useful if you are interested in indentifying what the kernel is performing over a specific time period. However, doing so can cause considerable stress on the machine. In addition, this does not provide any indication of whether a specific function is being called too often during small time increments. This section describes how to profile the kernel properly. does this by providing a list of the top ten kernel functions called within a specific time period, and how many times each function was called during that time. kernelprof.stp #! /usr/bin/env stap global profile, pcount probe timer.profile { pcount <<< 1 fn = probefunc () if (fn != "") profile[fn] <<< 1 } probe timer.ms(5000) { printf ("\n--- %d samples recorded:\n", @count(pcount)) foreach (f in profile- limit 10) { printf ("%-30s\t%6d\n", f, @count(profile[f])) } delete profile delete pcount } records and outputs kernel functions called every 5 seconds. You can change this setting by editing probe timer.ms(5000) accordingly. contains an excerpt of the output over a 20-second period: <xref linkend="kernelprof"/> Sample Output [...] --- 10002 samples recorded: sys_recvfrom 1 memmove 1 __copy_from_user_ll 17 __copy_to_user_ll 15 mwait_idle 5868 link_path_walk 1 kfree 1 fget_light 1 audit_syscall_exit 1 __d_lookup 1 --- 10002 samples recorded: sysfs_read_file 1 free_poll_entry 1 syscall_exit_work 1 profile_hit 1 do_page_fault 2 _read_lock 3 kmap_atomic 4 strncpy_from_user 1 find_vma_prepare 1 __copy_from_user_ll 12 --- 10000 samples recorded: system_call 4 unix_stream_sendmsg 1 __d_path 1 do_page_fault 2 kmap_atomic 1 find_vma 1 __copy_to_user_ll 16 __copy_from_user_ll 10 mwait_idle 5759 memcpy_fromiovec 1 --- 10004 samples recorded: syscall_exit 1 __d_path 1 fput 2 do_page_fault 4 strncpy_from_user 1 may_open 1 ide_outb 1 ide_outsw 1 __copy_to_user_ll 11 __copy_from_user_ll 14 [...] allows you to identify interesting kernel-specific performance facts about the system, such as kernel-intensive workloads and idle times (in this case, mwait_idle. Note that does not count user-space functions, although it counts all kernel functions as part of the sample (even if the script cannot identify from which specific kernel function a call originated.
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-nettop.xml000066400000000000000000000141311217430427200271520ustar00rootroot00000000000000
Network Profiling script examples network profiling examples of SystemTap scripts network profiling network profiling examples of SystemTap scripts WAR STORY: Top network users by PID http://sourceware.org/systemtap/wiki/WSNetTop?highlight=((WarStories)) probably http://sourceware.org/systemtap/examples/network/nettop.stp profiling the network examples of SystemTap scripts network traffic, monitoring examples of SystemTap scripts This section describes how to profile network activity. provides a glimpse into how much network traffic each process is generating on a machine. nettop.stp script examples if/else conditionals, alternative syntax examples of SystemTap scripts if/else conditionals, alternative syntax if/else conditionals, alternative syntax examples of SystemTap scripts Note that function print_activity() uses the following expressions: n_xmit ? @sum(ifxmit[pid, dev, exec, uid])/1024 : 0 n_recv ? @sum(ifrecv[pid, dev, exec, uid])/1024 : 0 These expressions are if/else conditionals. The first statement is simply a more concise way of writing the following psuedo code: if n_recv != 0 then @sum(ifrecv[pid, dev, exec, uid])/1024 else 0 tracks which processes are generating network traffic on the system, and provides the following information about each process: PID — the ID of the listed process. UID — user ID. A user ID of 0 refers to the root user. DEV — which ethernet device the process used to send / receive data (e.g. eth0, eth1) XMIT_PK — number of packets transmitted by the process RECV_PK — number of packets received by the process XMIT_KB — amount of data sent by the process, in kilobytes RECV_KB — amount of data received by the service, in kilobytes provides network profile sampling every 5 seconds. You can change this setting by editing probe timer.ms(5000) accordingly. contains an excerpt of the output from over a 20-second period: <xref linkend="nettop"/> Sample Output [...] PID UID DEV XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND 0 0 eth0 0 5 0 0 swapper 11178 0 eth0 2 0 0 0 synergyc PID UID DEV XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND 2886 4 eth0 79 0 5 0 cups-polld 11362 0 eth0 0 61 0 5 firefox 0 0 eth0 3 32 0 3 swapper 2886 4 lo 4 4 0 0 cups-polld 11178 0 eth0 3 0 0 0 synergyc PID UID DEV XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND 0 0 eth0 0 6 0 0 swapper 2886 4 lo 2 2 0 0 cups-polld 11178 0 eth0 3 0 0 0 synergyc 3611 0 eth0 0 1 0 0 Xorg PID UID DEV XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND 0 0 eth0 3 42 0 2 swapper 11178 0 eth0 43 1 3 0 synergyc 11362 0 eth0 0 7 0 0 firefox 3897 0 eth0 0 1 0 0 multiload-apple [...]
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-paracallgraph.xml000066400000000000000000000122361217430427200304460ustar00rootroot00000000000000
Call Graph Tracing script examples call graph tracing examples of SystemTap scripts call graph tracing call graph tracing examples of SystemTap scripts incoming/outgoing function calls, tracing examples of SystemTap scripts function calls (incoming/outgoing), tracing examples of SystemTap scripts tracing incoming/outgoing function calls examples of SystemTap scripts tracing call graph examples of SystemTap scripts WAR STORY: Call graph tracing http://sourceware.org/systemtap/wiki/WSCallGraph?highlight=((WarStories)) script: http://sourceware.org/systemtap/examples/general/para-callgraph.stp This section describes how to trace incoming and outgoing function calls. para-callgraph.stp script examples multiple command-line arguments, example of examples of SystemTap scripts multiple command-line arguments, example of multiple command-line arguments, example of examples of SystemTap scripts example of multiple command-line arguments examples of SystemTap scripts takes two command-line arguments: script examples trigger function examples of SystemTap scripts trigger function trigger function examples of SystemTap scripts The function/s whose entry/exit call you'd like to trace ($1). A second optional trigger function ($2), which enables or disables tracing on a per-thread basis. Tracing in each thread will continue as long as the trigger function has not exited yet. please verify previous if correct; i'm particularly interested in finding out how to better describe "trigger function" script examples thread_indent(), sample usage examples of SystemTap scripts thread_indent(), sample usage thread_indent(), sample usage examples of SystemTap scripts uses thread_indent(); as such, its output contains the timestamp, process name, and thread ID of $1 (i.e. the probe function you are tracing). For more information about thread_indent(), refer to its entry in . The following example contains an excerpt from the output for stap para-callgraph.stp 'kernel.function("*@fs/*.c")' 'kernel.function("sys_read")': <xref linkend="scriptcallgraph"/> Sample Output [...] 267 gnome-terminal(2921): <-do_sync_read return=0xfffffffffffffff5 269 gnome-terminal(2921):<-vfs_read return=0xfffffffffffffff5 0 gnome-terminal(2921):->fput file=0xffff880111eebbc0 2 gnome-terminal(2921):<-fput 0 gnome-terminal(2921):->fget_light fd=0x3 fput_needed=0xffff88010544df54 3 gnome-terminal(2921):<-fget_light return=0xffff8801116ce980 0 gnome-terminal(2921):->vfs_read file=0xffff8801116ce980 buf=0xc86504 count=0x1000 pos=0xffff88010544df48 4 gnome-terminal(2921): ->rw_verify_area read_write=0x0 file=0xffff8801116ce980 ppos=0xffff88010544df48 count=0x1000 7 gnome-terminal(2921): <-rw_verify_area return=0x1000 12 gnome-terminal(2921): ->do_sync_read filp=0xffff8801116ce980 buf=0xc86504 len=0x1000 ppos=0xffff88010544df48 15 gnome-terminal(2921): <-do_sync_read return=0xfffffffffffffff5 18 gnome-terminal(2921):<-vfs_read return=0xfffffffffffffff5 0 gnome-terminal(2921):->fput file=0xffff8801116ce980
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-sockettrace.xml000066400000000000000000000104551217430427200301550ustar00rootroot00000000000000
Tracing Functions Called in Network Socket Code script examples tracing functions called in network socket code examples of SystemTap scripts tracing functions called in network socket code tracing functions called in network socket code examples of SystemTap scripts network socket code, tracing functions called in examples of SystemTap scripts functions called in network socket code, tracing examples of SystemTap scripts http://sourceware.org/systemtap/examples/network/socket-trace.stp script examples net/socket.c, tracing functions from examples of SystemTap scripts net/socket.c, tracing functions from net/socket.c, tracing functions from examples of SystemTap scripts This section describes how to trace functions called from the kernel's net/socket.c file. This task helps you identify, in finer detail, how each process interacts with the network at the kernel level. socket-trace.stp is identical to , which was earlier used in to illustrate how thread_indent() works. <xref linkend="sockettrace"/> Sample Output [...] 0 Xorg(3611): -> sock_poll 3 Xorg(3611): <- sock_poll 0 Xorg(3611): -> sock_poll 3 Xorg(3611): <- sock_poll 0 gnome-terminal(11106): -> sock_poll 5 gnome-terminal(11106): <- sock_poll 0 scim-bridge(3883): -> sock_poll 3 scim-bridge(3883): <- sock_poll 0 scim-bridge(3883): -> sys_socketcall 4 scim-bridge(3883): -> sys_recv 8 scim-bridge(3883): -> sys_recvfrom 12 scim-bridge(3883):-> sock_from_file 16 scim-bridge(3883):<- sock_from_file 20 scim-bridge(3883):-> sock_recvmsg 24 scim-bridge(3883):<- sock_recvmsg 28 scim-bridge(3883): <- sys_recvfrom 31 scim-bridge(3883): <- sys_recv 35 scim-bridge(3883): <- sys_socketcall [...] contains a 3-second excerpt of the output for . For more information about the output of this script as provided by thread_indent(), refer to .
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-syscallsbyprocpid.xml000066400000000000000000000073551217430427200314240ustar00rootroot00000000000000
Tracking System Call Volume Per Process script examples monitoring system calls (volume per process) examples of SystemTap scripts monitoring system calls (volume per process) monitoring system calls (volume per process) examples of SystemTap scripts system calls volume (per process), monitoring examples of SystemTap scripts uses systemtap/testsuite/systemtap.examples/process/syscalls_by_p*.stp This section illustrates how to determine which processes are performing the highest volume of system calls. In previous sections, we've described how to monitor the top system calls used by the system over time (). We've also described how to identify which applications use a specific set of "polling suspect" system calls the most (). Monitoring the volume of system calls made by each process provides more data in investigating your system for polling processes and other resource hogs. syscalls_by_proc.stp lists the top 20 processes performing the highest number of system calls. It also lists how many system calls each process performed during the time period. Refer to for a sample output. <xref linkend="topsys"/> Sample Output Collecting data... Type Ctrl-C to exit and display results #SysCalls Process Name 1577 multiload-apple 692 synergyc 408 pcscd 376 mixer_applet2 299 gnome-terminal 293 Xorg 206 scim-panel-gtk 95 gnome-power-man 90 artsd 85 dhcdbd 84 scim-bridge 78 gnome-screensav 66 scim-launcher [...] If you prefer the output to display the process IDs instead of the process names, use the following script instead. syscalls_by_pid.stp As indicated in the output, you need to manually exit the script in order to display the results. You can add a timed expiration to either script by simply adding a timer.s() probe; for example, to instruct the script to expire after 5 seconds, add the following probe to the script: probe timer.s(5) { exit() }
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-tcp_connections.xml000066400000000000000000000051661217430427200310410ustar00rootroot00000000000000
Monitoring Incoming TCP Connections script examples monitoring incoming TCP connections examples of SystemTap scripts monitoring incoming TCP connections monitoring incoming TCP connections examples of SystemTap scripts TCP connections (incoming), monitoring examples of SystemTap scripts incoming TCP connections, monitoring examples of SystemTap scripts This section illustrates how to monitor incoming TCP connections. This task is useful in identifying any unauthorized, suspicious, or otherwise unwanted network access requests in real time. tcp_connections.stp While is running, it will print out the following information about any incoming TCP connections accepted by the system in real time: Current UID CMD - the command accepting the connection PID of the command Port used by the connection IP address from which the TCP connection originated <xref linkend="tcpconnections"/> Sample Output UID CMD PID PORT IP_SOURCE 0 sshd 3165 22 10.64.0.227 0 sshd 3165 22 10.64.0.227
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-tcpdumplike.xml000066400000000000000000000075571217430427200302000ustar00rootroot00000000000000
Monitoring TCP Packets script examples monitoring TCP packets examples of SystemTap scripts monitoring TCP packets monitoring TCP packets examples of SystemTap scripts TCP packets, monitoring examples of SystemTap scripts TCP packets, monitoring examples of SystemTap scripts This section illustrates how to monitor TCP packets received by the system. This is useful in analyzing network traffic generated by applications running on the system. tcpdumplike.stp While is running, it will print out the following information about any received TCP packets in real time: Source and destination IP address (saddr, daddr, respectively) Source and destination ports (sport, dport, respectively) Packet flags To determine the flags used by the packet, uses the following functions: urg - urgent ack - acknowledgement psh - push rst - reset syn - synchronize fin - finished The aforementioned functions return 1 or 0 to specify whether the packet uses the corresponding flag. <xref linkend="tcpdumplike"/> Sample Output ----------------------------------------------------------------- Source IP Dest IP SPort DPort U A P R S F ----------------------------------------------------------------- 209.85.229.147 10.0.2.15 80 20373 0 1 1 0 0 0 92.122.126.240 10.0.2.15 80 53214 0 1 0 0 1 0 92.122.126.240 10.0.2.15 80 53214 0 1 0 0 0 0 209.85.229.118 10.0.2.15 80 63433 0 1 0 0 1 0 209.85.229.118 10.0.2.15 80 63433 0 1 0 0 0 0 209.85.229.147 10.0.2.15 80 21141 0 1 1 0 0 0 209.85.229.147 10.0.2.15 80 21141 0 1 1 0 0 0 209.85.229.147 10.0.2.15 80 21141 0 1 1 0 0 0 209.85.229.147 10.0.2.15 80 21141 0 1 1 0 0 0 209.85.229.147 10.0.2.15 80 21141 0 1 1 0 0 0 209.85.229.118 10.0.2.15 80 63433 0 1 1 0 0 0 [...]
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-threadtimes.xml000066400000000000000000000056671217430427200301700ustar00rootroot00000000000000
Determining Time Spent in Kernel and User Space script examples determining time spent in kernel and user space examples of SystemTap scripts determining time spent in kernel and user space determining time spent in kernel and user space examples of SystemTap scripts time spent in kernel/user space, determining examples of SystemTap scripts kernel and user space, determining time spent in examples of SystemTap scripts user and kernel space, determining time spent in examples of SystemTap scripts http://sourceware.org/systemtap/examples/profiling/thread-times.stp This section illustrates how to determine the amount of time any given thread is spending in either kernel or user-space. thread-times.stp script examples CPU ticks examples of SystemTap scripts CPU ticks CPU ticks examples of SystemTap scripts lists the top 20 processes currently taking up CPU time within a 5-second sample, along with the total number of CPU ticks made during the sample. The output of this script also notes the percentage of CPU time each process used, as well as whether that time was spent in kernel space or user space. contains a 5-second sample of the output for : <xref linkend="threadtimes"/> Sample Output tid %user %kernel (of 20002 ticks) 0 0.00% 87.88% 32169 5.24% 0.03% 9815 3.33% 0.36% 9859 0.95% 0.00% 3611 0.56% 0.12% 9861 0.62% 0.01% 11106 0.37% 0.02% 32167 0.08% 0.08% 3897 0.01% 0.08% 3800 0.03% 0.00% 2886 0.02% 0.00% 3243 0.00% 0.01% 3862 0.01% 0.00% 3782 0.00% 0.00% 21767 0.00% 0.00% 2522 0.00% 0.00% 3883 0.00% 0.00% 3775 0.00% 0.00% 3943 0.00% 0.00% 3873 0.00% 0.00%
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-timeout.xml000066400000000000000000000110161217430427200273260ustar00rootroot00000000000000
Monitoring Polling Applications script examples monitoring polling applications examples of SystemTap scripts monitoring polling applications monitoring polling applications examples of SystemTap scripts polling applications, monitoring examples of SystemTap scripts uses systemtap/testsuite/systemtap.examples/profiling/timeout.stp This section describes how to identify and monitor which applications are polling. Doing so allows you to track unnecessary or excessive polling, which can help you pinpoint areas for improvement in terms of CPU usage and power savings. timeout.stp tracks how many times each of the following system calls completed due to time expiring rather than due to an actual event occurring: poll select epoll itimer futex nanosleep signal script examples timer.s(), sample usage examples of SystemTap scripts timer.s(), sample usage timer.s(), sample usage examples of SystemTap scripts <xref linkend="timeouts"/> Sample Output uid | poll select epoll itimer futex nanosle signal| process 28937 | 148793 0 0 4727 37288 0 0| firefox 22945 | 0 56949 0 1 0 0 0| scim-bridge 0 | 0 0 0 36414 0 0 0| swapper 4275 | 23140 0 0 1 0 0 0| mixer_applet2 4191 | 0 14405 0 0 0 0 0| scim-launcher 22941 | 7908 1 0 62 0 0 0| gnome-terminal 4261 | 0 0 0 2 0 7622 0| escd 3695 | 0 0 0 0 0 7622 0| gdm-binary 3483 | 0 7206 0 0 0 0 0| dhcdbd 4189 | 6916 0 0 2 0 0 0| scim-panel-gtk 1863 | 5767 0 0 0 0 0 0| iscsid 2562 | 0 2881 0 1 0 1438 0| pcscd 4257 | 4255 0 0 1 0 0 0| gnome-power-man 4278 | 3876 0 0 60 0 0 0| multiload-apple 4083 | 0 1331 0 1728 0 0 0| Xorg 3921 | 1603 0 0 0 0 0 0| gam_server 4248 | 1591 0 0 0 0 0 0| nm-applet 3165 | 0 1441 0 0 0 0 0| xterm 29548 | 0 1440 0 0 0 0 0| httpd 1862 | 0 0 0 0 0 1438 0| iscsid You can increase the sample time by editing the second probe (timer.s(1)). The output of contains the name and UID of the top 20 polling applications, along with how many times each application performed each polling system call (over time). contains an excerpt of the script. In this particular example firefox is doing an excessive amount of polling due to a plugin module.
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-topsys.xml000066400000000000000000000073321217430427200272070ustar00rootroot00000000000000
Tracking Most Frequently Used System Calls script examples monitoring system calls examples of SystemTap scripts monitoring system calls monitoring system calls examples of SystemTap scripts system calls, monitoring examples of SystemTap scripts from helps you identify which applications are polling by examining a small subset of system calls ( poll, select, epoll, itimer, futex, nanosleep, and signal). However, in some systems, an excessive number of system calls outside that small subset might be responsible for time spent in the kernel. If you suspect that an application is using system calls excessively, you need to identify the most frequently used system calls on the system. To do this, use . topsys.stp lists the top 20 system calls used by the system per 5-second interval. It also lists how many times each system call was used during that period. Refer to for a sample output. script examples timer.s(), sample usage examples of SystemTap scripts timer.s(), sample usage timer.s(), sample usage examples of SystemTap scripts <xref linkend="topsys"/> Sample Output -------------------------------------------------------------- SYSCALL COUNT gettimeofday 1857 read 1821 ioctl 1568 poll 1033 close 638 open 503 select 455 write 391 writev 335 futex 303 recvmsg 251 socket 137 clock_gettime 124 rt_sigprocmask 121 sendto 120 setitimer 106 stat 90 time 81 sigreturn 72 fstat 66 --------------------------------------------------------------
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-traceio.xml000066400000000000000000000114771217430427200273010ustar00rootroot00000000000000
Track Cumulative IO script examples tracking cumulative I/O examples of SystemTap scripts tracking cumulative I/O tracking cumulative I/O examples of SystemTap scripts cumulative I/O, tracking examples of SystemTap scripts monitoring cumulative I/O examples of SystemTap scripts printing I/O activity (cumulative) examples of SystemTap scripts This section describes how to track the cumulative amount of I/O to the system. traceio.stp prints the top ten executables generating I/O traffic over time. In addition, it also tracks the cumulative amount of I/O reads and writes done by those ten executables. This information is tracked and printed out in 1-second intervals, and in descending order. local variables sample usage $return variables (local) sample usage $return $return sample usage local variables Note that also uses the local variable $return, which is also used by from . <xref linkend="traceio"/> Sample Output [...] Xorg r: 583401 KiB w: 0 KiB floaters r: 96 KiB w: 7130 KiB multiload-apple r: 538 KiB w: 537 KiB sshd r: 71 KiB w: 72 KiB pam_timestamp_c r: 138 KiB w: 0 KiB staprun r: 51 KiB w: 51 KiB snmpd r: 46 KiB w: 0 KiB pcscd r: 28 KiB w: 0 KiB irqbalance r: 27 KiB w: 4 KiB cupsd r: 4 KiB w: 18 KiB Xorg r: 588140 KiB w: 0 KiB floaters r: 97 KiB w: 7143 KiB multiload-apple r: 543 KiB w: 542 KiB sshd r: 72 KiB w: 72 KiB pam_timestamp_c r: 138 KiB w: 0 KiB staprun r: 51 KiB w: 51 KiB snmpd r: 46 KiB w: 0 KiB pcscd r: 28 KiB w: 0 KiB irqbalance r: 27 KiB w: 4 KiB cupsd r: 4 KiB w: 18 KiB
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-traceio2.xml000066400000000000000000000126571217430427200273640ustar00rootroot00000000000000
I/O Monitoring (By Device) script examples monitoring device I/O examples of SystemTap scripts monitoring device I/O monitoring device I/O examples of SystemTap scripts I/O monitoring (by device) examples of SystemTap scripts device I/O, monitoring examples of SystemTap scripts example from http://sourceware.org/systemtap/examples/io/traceio2.stp, but error WAR STORY: http://sourceware.org/systemtap/wiki/WSDeviceMonitor?highlight=((WarStories)), but script errored was able to correct script through http://sourceware.org/systemtap/wiki/WSFileMonitor?highlight=((WarStories)) This section describes how to monitor I/O activity on a specific device. traceio2.stp script examples stat -c, determining whole device number examples of SystemTap scripts stat -c, determining whole device number stat -c, determining whole device number examples of SystemTap scripts script examples whole device number (usage as a command-line argument) examples of SystemTap scripts whole device number (usage as a command-line argument) whole device number (usage as a command-line argument) examples of SystemTap scripts takes 1 argument: the whole device number. To get this number, use stat -c "0x%D" directory, where directory is located in the device you wish to monitor. script examples usrdev2kerndev() examples of SystemTap scripts usrdev2kerndev() usrdev2kerndev() examples of SystemTap scripts The usrdev2kerndev() function converts the whole device number into the format understood by the kernel. The output produced by usrdev2kerndev() is used in conjunction with the MKDEV(), MINOR(), and MAJOR() functions to determine the major and minor numbers of a specific device. The output of includes the name and ID of any process performing a read/write, the function it is performing (i.e. vfs_read or vfs_write), and the kernel device number. The following example is an excerpt from the full output of stap traceio2.stp 0x805, where 0x805 is the whole device number of /home. /home resides in /dev/sda5, which is the device we wish to monitor. <xref linkend="traceio2"/> Sample Output [...] synergyc(3722) vfs_read 0x800005 synergyc(3722) vfs_read 0x800005 cupsd(2889) vfs_write 0x800005 cupsd(2889) vfs_write 0x800005 cupsd(2889) vfs_write 0x800005 [...]
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Useful_SystemTap_Scripts.xml000066400000000000000000000111411217430427200276520ustar00rootroot00000000000000 Useful SystemTap Scripts SystemTap scripts useful examples examples of SystemTap scripts useful examples of SystemTap scripts systemtap-testsuite package sample scripts This chapter enumerates several SystemTap scripts you can use to monitor and investigate different subsystems. All of these scripts are available at /usr/share/systemtap/testsuite/systemtap.examples/ once you install the systemtap-testsuite RPM. short intro, reference to online source (http://sourceware.org/systemtap/examples/subsystem-index.html); "always updated" short description of gnuplot (?) for better GUI of results case studies and more info on some scripts here - http://sourceware.org/systemtap/wiki/WarStories
Network The following sections showcase scripts that trace network-related functions and build a profile of network activity.
Disk The following sections showcase scripts that monitor disk and I/O activity.
Profiling The following sections showcase scripts that profile kernel activity by monitoring function calls.
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Userspace_probing.xml000066400000000000000000000270561217430427200263550ustar00rootroot00000000000000 User-Space Probing SystemTap initially focused on kernel-space probing. However, there are many instances where user-space probing can help diagnose a problem. SystemTap 0.6 added support to allow probing user-space processes. SystemTap includes support for probing the entry into and return from a function in user-space processes, probing predefined markers in user-space code, and monitoring user-process events. SystemTap requires the uprobes module to perform user-space probing. If your Linux kernel is version 3.5 or higher, it already includes uprobes. The following command can verify whether the current kernel supports uprobes natively: grep CONFIG_UPROBES /boot/config-`uname -r` If uprobes is integrated, the output should be: CONFIG_UPROBES=y If you are running a kernel prior to version 3.5, SystemTap will automatically build the uprobes module. However, you will also need the utrace kernel extensions, which is required by the SystemTap user-space probing to track various user-space events. More details about the utrace infrastructure are available at . The following command determines whether the currently running Linux kernel provides the needed utrace support: grep CONFIG_UTRACE /boot/config-`uname -r` If the Linux kernel supports user-space probing, the following output is printed: CONFIG_UTRACE=y
User-Space Events Events user-space All user-space event probes begin with process. The process events can be limited to a specific running process by specifying the process ID. The process events can also be limited to monitoring a particular executable by specifying the path to executable (PATH). SystemTap makes use of the PATH environment variable, so both the name used on the command-line to start the executable and the absolute path to the executable can be used. Several of the user-space probe events limit their scope to a particular executable name (PATH) because SystemTap must use debug information to statically analyze where to place the probes. But for many user-space probe events, the process ID and executable name are optional. Any process event in the list below that include process ID or the path to the executable must include those arguments. The process ID and path to the executable are optional for the process events that do not list them: process("PATH").function("function") The entry to the user-space function function for the executable PATH. This event is the user-space analogue of the kernel.function("function") event. It allows wildcards for the function function and .return suffix. process("PATH").statement("statement") The earliest instruction in the code for statement. This is the user-space analogue of kernel.statement("statement"). process("PATH").mark("marker") The static probe point marker defined in PATH. Wildcards can be used for marker to specify mutiple marks with a single probe. The static probe points may also have numbered arguments ($1, $2, etc.) available to the probe. A variety of user-space packages such as Java include these static probe points. Most packages that provide static probe points also provide aliases for the raw user-space mark events. Below is one such alias for the x86_64 Java hotspot JVM: probe hotspot.gc_begin = process("/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/amd64/server/libjvm.so").mark("gc__begin") process.begin User-space process is created. This can be limited to a particular process ID or a full path to the executable. process.thread.begin User-space thread is created. This can be limited to a particular process ID or a full path to the executable. process.end User-space process died. This can be limited to a particular process ID or a full path to the executable. process.thread.end User-space thread is destroyed. This can be limited to a particular process ID or a full path to the executable. process.syscall User-space process makes a system call. The system call number is available via $syscall context variable, and the fist six arguments are available via $arg1 through $arg6. The ".return" suffix will place the probe at the return from the system call. For the "syscall.return" the return value is available through the $return context variable. This can be limited to a particular process ID or a full path to the executable.
Accessing User-Space Target Variables target variables user-space User-space target variables can be accessed in the same manner as described in . However, in Linux there are separate address spaces for the user and kernel code. When using "->" operator SystemTap will access the appropriate address space. For pointers to base types such as integers and strings there are a number of functions listed below to access user-space data. The first argument for each functions is the pointer to the data item. user_char(address) Obtain the character at address for the current user process. user_short(address) Obtain the short at address for the current user process. user_int(address) Obtain the int at address for the current user process. user_long(address) Obtain the long at address for the current user process. user_string(address) Obtain the string at address for the current user process. user_string_n(address, n) Obtain the string at address for the current user process and limits the string to n bytes.
User-Space Stack Backtraces Stack backtrace user-space The probe point (pp) function indicates which particular event triggered the SystemTap event handler. A probe on the entry into a function would list the function name. However, in many cases the same probe point event may be triggered by many different modules in the program; this is particularly true for functions in shared libraries. A SystemTap backtrace of the user-space stack can provide additional context on how the probe point event is triggered. The user-space stack backtrace generation is complicated by the compiler producing code optimized to eliminate stack frame pointers. However, the compiler also includes information in the debug information section to allow debugging tools to produce stack backtraces. SystemTap user-space stack backtrace mechanism makes use of that debug information to walk the stack to generate stack traces for 32-bit and 64-bit x86 processors; other processor architectures do not yet support the use of debug information to unwind the user-space stack. You will need to use the -d executable for the application executable and -ldd for shared libraries to ensure that the needed debug information is used to produce the user-space stack backtraces. If you want to see how the function xmalloc function is being called by the command ls, you could use the user-space backtrack functions to provide that information. With the debuginfo for the ls command installed the following SystemTap command will provide a backtrace each time the xmalloc function is called: stap -d /bin/ls --ldd \ -e 'probe process("ls").function("xmalloc") {print_usyms(ubacktrace())}' \ -c "ls /" When the SystemTap script runs will have output similar to the following: bin dev lib media net proc sbin sys var boot etc lib64 misc op_session profilerc selinux tmp cgroup home lost+found mnt opt root srv usr 0x4116c0 : xmalloc+0x0/0x20 [/bin/ls] 0x4116fc : xmemdup+0x1c/0x40 [/bin/ls] 0x40e68b : clone_quoting_options+0x3b/0x50 [/bin/ls] 0x4087e4 : main+0x3b4/0x1900 [/bin/ls] 0x3fa441ec5d : __libc_start_main+0xfd/0x1d0 [/lib64/libc-2.12.so] 0x402799 : _start+0x29/0x2c [/bin/ls] 0x4116c0 : xmalloc+0x0/0x20 [/bin/ls] 0x4116fc : xmemdup+0x1c/0x40 [/bin/ls] 0x40e68b : clone_quoting_options+0x3b/0x50 [/bin/ls] 0x40884a : main+0x41a/0x1900 [/bin/ls] 0x3fa441ec5d : __libc_start_main+0xfd/0x1d0 [/lib64/libc-2.12.so] ... For more details on the functions available for user-space stack backtraces look at the ucontext-symbols.stp and ucontext-unwind.stp tapsets. The descriptions of the functions in those tapsets can also be found in the SystemTap Tapset Reference Manual.
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/Using_SystemTap.xml000066400000000000000000000307261217430427200257770ustar00rootroot00000000000000 Using SystemTap short intro, contents of chapter Using SystemTap This chapter instructs users how to install SystemTap, and provides an introduction on how to run SystemTap scripts.
Running SystemTap Scripts - basic commands (e.g. stap), useful options per command (e.g. stap -vv), tool references (man pages, related kernel-doc), references within book (i.e. errors chapter) - running systemtap scripts Usage running SystemTap scripts running SystemTap scripts Usage Usage stap stap Usage Usage staprun staprun Usage SystemTap scripts are run through the command stap. stap can run SystemTap scripts from standard input or from file. SystemTap scripts, how to run Running stap and staprun requires elevated privileges to the system. However, not all users can be granted root access just to run SystemTap. In some cases, for instance, you may want to allow a non-privileged user to run SystemTap instrumentation on his machine. To allow ordinary users to run SystemTap without root access, add them to one of these user groups: stapdev Usage stapdev stapdev Usage Members of this group can use stap to run SystemTap scripts, or staprun to run SystemTap instrumentation modules. Running stap involves compiling SystemTap scripts into kernel modules and loading them into the kernel. This requires elevated privileges to the system, which are granted to stapdev members. Unfortunately, such privileges also grant effective root access to stapdev members. As such, you should only grant stapdev group membership to users whom you can trust root access. stapusr Usage stapusr stapusr Usage Members of this group can only run staprun to run SystemTap instrumentation modules. In addition, they can only run those modules from /lib/modules/kernel_version/systemtap/. Note that this directory must be owned only by the root user, and must only be writable by the root user. Below is a list of commonly used stap options: Usage options, stap options, stap Usage stap options -v Makes the output of the SystemTap session more verbose. You can repeat this option (for example, stap -vvv script.stp) to provide more details on the script's execution. This option is particularly useful if you encounter any errors in running the script. For more information about common SystemTap script errors, refer to . -o filename Sends the standard output to file (filename). -S size,count Limit files to size megabytes and limit the number of files kept around to count. The file names will have a sequence number suffix. This option implements logrotate operations for SystemTap. -x process ID Sets the SystemTap handler function target() to the specified process ID. For more information about target(), refer to . -c 'command' Sets the SystemTap handler function target() to the specified command and runs the SystemTap instrumentation for the duration of the specified command. For more information about target(), refer to . -e 'script' Use script string rather than a file as input for systemtap translator. -F Use SystemTap's Flight recorder mode and make the script a background process. For more information about flight recorder mode, refer to . You can also instruct stap to run scripts from standard input using the switch -. To illustrate: Usage standard input, running scripts from standard input, running scripts from Usage running scripts from standard input Running Scripts From Standard Input echo "probe timer.s(1) {exit()}" | stap - instructs stap to run the script passed by echo to standard input. Any stap options you wish to use should be inserted before the - switch; for instance, to make the example in more verbose, the command would be: echo "probe timer.s(1) {exit()}" | stap -v - any other useful options worth noting here for beginners? For more information about stap, refer to man stap. To run SystemTap instrumentation (i.e. the kernel module built from SystemTap scripts during a cross-instrumentation), use staprun instead. For more information about staprun and cross-instrumentation, refer to . Note The stap options -v and -o also work for staprun. For more information about staprun, refer to man staprun.
SystemTap Flight Recorder Mode flight recorder mode SystemTap's flight recorder mode allows you to run a SystemTap script run for long periods and just focus on recent output. The flight recorder mode (the -F option) limits the amount of output generated. There are two variations of the flight recorder mode: in-memory and file mode. In both cases the SystemTap script runs as a background process.
In-memory Flight Recorder flight recorder mode in-memory mode When flight recorder mode (the -F option) is used without a file name SystemTap uses a buffer in kernel memory to store the output of the script. The SystemTap instrumentation module will load and the probes start running, the instrumentation will then detach and be put in the background. When the interesting event occurs, you can reattach to the instrumentation and see the recent output in the memory buffer and any continuing output. The following command starts a script using the flight recorder in-memory mode: stap -F iotime.stp Once the script starts, you will see a message like the following that provides the command to reconnect to the running script: Disconnecting from systemtap module. To reconnect, type "staprun -A stap_5dd0073edcb1f13f7565d8c343063e68_19556" When the interesting event occurs, you reattach to the currently running script and output the recent data in the memory buffer and get continuing output with the following command: staprun -A stap_5dd0073edcb1f13f7565d8c343063e68_19556 By default the kernel buffer is 1MB in size and it can be increased with the -s option specifying the size in megabytes (rounded up to the next power over 2) for the buffer. For example -s2 on the SystemTap command line would specify 2MB for the buffer.
File Flight Recorder flight recorder mode file mode The flight recorder mode can also store data to files. The number and size of the files kept is controlled by the -S option followed by two numerical arguments separated by a comma. The first argument is the maximum size in megabytes for the each output file. The second argument is the number of recent files to keep. The file name is specified by the -o option followed by the name. SystemTap will add a number suffix to the file name to indicate the order of the files. The following will start SystemTap in file flight recorder mode with the output going to files named /tmp/iotime.log.[0-9]+ and each file 1MB or smaller and keeping latest two files: stap -F -o /tmp/pfaults.log -S 1,2 pfaults.stp The number printed by the command is the process ID. Sending a SIGTERM to the process will shutdown the SystemTap script and stop the data collection. For example if the previous command listed the 7590 as the process ID, the following command whould shutdown the systemtap script: kill -s SIGTERM 7590 Only the most recent two file generated by the script are kept and the older files are been removed. Thus, ls -sh /tmp/pfaults.log.* shows the only two files: 1020K /tmp/pfaults.log.5 44K /tmp/pfaults.log.6 One can look at the highest number file for the latest data, in this case /tmp/pfaults.log.6.
systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/extras/000077500000000000000000000000001217430427200234555ustar00rootroot00000000000000systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/extras/cast_example.stp000066400000000000000000000001571217430427200266550ustar00rootroot00000000000000function task_state:long (task:long) { return @cast(task, "task_struct", "kernel")->state } systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/extras/defined_example.stp000066400000000000000000000004341217430427200273170ustar00rootroot00000000000000probe vm.pagefault = kernel.function("__handle_mm_fault@mm/memory.c") ?, kernel.function("handle_mm_fault@mm/memory.c") ? { name = "pagefault" write_access = (@defined($flags) ? $flags & FAULT_FLAG_WRITE : $write_access) address = $address } systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/extras/fedoradebugurl.sh000077500000000000000000000005151217430427200270070ustar00rootroot00000000000000#! /bin/bash echo -n "Enter nvr of kernel-debuginfo (e.g. 2.6.25-14.fc9.x86_64) " ; \ read NVR; \ BASE=`uname -m` ; \ NVR=`echo $NVR | sed s/.$BASE//` ; \ VERSION=`echo $NVR | awk -F- '{print $1}'` ; \ RELEASE=`echo $NVR | awk -F- '{print $2}'` ; \ echo "http://kojipkgs.fedoraproject.org/\ packages/kernel/$VERSION/$RELEASE/$BASE/" systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/extras/perror.stp000066400000000000000000000000371217430427200255160ustar00rootroot00000000000000probe vfs.read probe vfs.write systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/extras/rhelchannels.sh000077500000000000000000000010401217430427200264550ustar00rootroot00000000000000#! /bin/bash pkg=`rpm -q --whatprovides "redhat-release"` releasever=`rpm -q --qf "%{version}" $pkg` variant=`echo $releasever | tr -d "[:digit:]" | tr "[:upper:]" "[:lower:]" ` if test -z "$variant"; then echo "No Red Hat Enterprise Linux variant (workstation/client/server) found." exit 1 fi version=`echo $releasever | tr -cd "[:digit:]"` base=`uname -i` echo "rhel-$base-$variant-$version" echo "rhel-$base-$variant-$version-debuginfo" echo "rhel-$base-$variant-optional-$version-debuginfo" echo "rhel-$base-$variant-optional-$version" systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/extras/rheldebugurl.sh000077500000000000000000000002711217430427200265000ustar00rootroot00000000000000#! /bin/bash pkg="redhat-release" releasever=`rpm -q --qf "%{version}" $pkg` base=`uname -m` echo "ftp://ftp.redhat.com/pub/redhat/linux/\ enterprise/$releasever/en/os/$base/Debuginfo" systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/extras/werror.stp000066400000000000000000000000401217430427200255170ustar00rootroot00000000000000probe begin { printf("x") = 1 } systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/images/000077500000000000000000000000001217430427200234145ustar00rootroot00000000000000systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/images/gnuplotsample.png000077500000000000000000000201361217430427200270210ustar00rootroot00000000000000PNG  IHDR/(?Zj9Rp,T0vӖ@8X|,-:m}w_q)Y[@=϶bG??=U+ret'jW|Wb>x^DϏ2.a7x_K IE[33흉4J*OVϾ^]}aj^Ze2cK*53[^[I^`C>ǻvEXbB1Bs;( _>smU_S(#?yo}{bpݖ(Gyh}cj9xq5qqՙƏw?戈­<_c?O;ŎxW ^;1q,v]zVڛKqڦ(DǷlzω~+rh`]Gi[`׶2^.X~NQaU!yk*Oo?gS{ĚU08Q񙣱MqR|Ǣʸ3wXuם1ykbx썋>1v)q=?3O_.ſ#l^{ŧF̖w?3GǮw5ψgLįwC8DXِ3al6vFӇ㦏aZc#(Dsz&Y""";C#;bpxc|s +]Q>c黷џq] Y' q+N[M7~qݟ}=ν Ҧ8[_Ŋ WgC}{|3q}\1߽q]/+Ц37Yᐫ`l0lfQ [~ϝlzKF#]X,E(cx !~qXl^76Gqh =|~t\~Ʌ1yc<qlÉV#~hMص=btgLĖnG7"޹kKēOXx幨=9^yں""b~ȑ,5~Z-\|w>qQ??ﷴ`\tSK.q,GY0Bt|[C</ kO}`8qL kFk㵙r bqu i;^駝6EY\/m<=퉁_u?\=3D9" Q,ΝAX_5# @vUS0Y5n<߯T>v'/nk=Gab1sO\g<5n'̪8gkGFDՋ>G1x;p~/M[t߁xGc7/z*> _}ol*m[mϝ~š(->8=Q\j\V4RnzJM/"ED?}iӫ-wmPsxb?s?}XٵW/y-~ŕgxybpp0~qPu4k};?ϼgGuWqI|;~=u7K.Wc?&>{b"V,ڿg'㪷oyyQ(_Սq|/Vm0 '?q8ct_vYِ3#xg?v k̅fg˯{OplƸ-7f{LP oUFy]1u᱋<;cO1>3GFapexqxط2k/O_DqyiW;?wgLY\?؁'bQj1t뢸vSsqm7Ǒ쫇"b{թSlȑv[jf>8 b[ ].V@N7lGt_;QّQ(Ć~#G;}l #Q.GXgF#p=]ry& +q{˳[X1ç]6Gg"ʅ1vSV+]O8zhCSQ\Ŋi: ][I^Љ5QXLoX"b`u[Ea~V †m1uG7!V]+5^;T}8}׿bzȤ]sG/ES,ݰW3w|ݷTMO04W;}uߛ5 xe(k?c+`ގkOcD7-'X2;(Z4#H~0ƺq2͢pjb|} c%}:}cX Y>F! [`rVO}W6,A5nLpJ:#1PIEqFcF͜Mzэw %`$د;"FR=S}G.?Ȃ8u lr*1GѸQ',zH`dA *< pt]@0fR_ԍ,a[@0rh#XH p `@0F#,7@02J;`IF#Iֿ`@0 rr"`@0 Dq 059[,"#H7 Ʈ-rjǃpjb|_u V>h$ !Fk0TaeT]ݜ@%,`RRu79n]T;poŴ-B3)znTI5ωEcm$.st@@iR&nx@0 F#(nx@0""`@0w@\ `@0  a~߹#`w=@0'#U~1S<@0 F nx@0 !K@q4S9HMOLj<_VD#`r1$`Ré<洖uxV_jC^u`l:OE {ij$6Ӷ* ͨ#˲͹9X{tuV>'rAҹ X;FFHF#X:@0 -#S1ŝ~`@0B4:EFF#FX.1R#G`@0 @0R5z{@F;P (#]0eLX]a]D F.FF#\FЎҘG 2`@0)aHFԤFȉq@0 C`@0 !+F ""'cG#uNݍ:Gx1951.A $Vb1"D#@ރ:lXn\0ާ`\û(1 F2R טК\(@sU@f$QuYQ0t 1 F#|cbq46Һ!yiɒDhi,&Ubs~`T@0vh3r]΃q[~;D:,LUdbȷnIYDF,h;(#݌E@³]0ژ軤-B#@?$z^iWQ,8Ob^[rրRnJ؁gDZF92ix#Ɣx{#qsO` `>Mhe$p7=4nZU`>WӸ| E;f<@콳m{di;59 Iiv{ rJ@$}OAέw#=y 2߶:*hTBZ Z^P򶿭nLig\D+ =7ĐEFv_[woj/F!1 dQgHwbp2g)v{~SA0f2{A_,v*Mōɖ]ؼ}xN\x7{`p 7ۉ_QGȳf](`lC3)|-^L؀<`RF̀ιT0BnLuG 'n1(31 H F ׌. F(`%~-@04A^F# QǹYLϣ3{ftNы4?[{Lz:d::۾5x:}}!tp50/k?#6֧dcVaw~<گڗmRӚ֧XLԟ캷,oY[Y;޽uhv_.NIg:Y|D#cVyy]:La\.Gwӓ{&ŏ54'F#`@0 @0 F#@ Vݖmo`B\.[ 4/IENDB`systemtap-2.3/doc/SystemTap_Beginners_Guide/en-US/images/icon.svg000066400000000000000000003301271217430427200250730ustar00rootroot00000000000000 image/svg+xml id="path2858" /> systemtap-2.3/doc/SystemTap_Beginners_Guide/publican.cfg.in000066400000000000000000000001341217430427200241010ustar00rootroot00000000000000debug: 0 xml_lang: en-US brand: @PUBLICAN_BRAND@ condition: @PUBLICAN_BRAND@ tmp_dir: build systemtap-2.3/doc/SystemTap_Tapset_Reference/000077500000000000000000000000001217430427200214055ustar00rootroot00000000000000systemtap-2.3/doc/SystemTap_Tapset_Reference/.gitignore000066400000000000000000000000461217430427200233750ustar00rootroot00000000000000/docproc stamp-* tapsets/ tapsets.xml systemtap-2.3/doc/SystemTap_Tapset_Reference/Makefile.am000066400000000000000000000051531217430427200234450ustar00rootroot00000000000000# Makefile.am --- automake input file for systemtap tapset reference manual ## process this file with automake to produce Makefile.in DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap MAN_INSTALL_DIR = $(DESTDIR)$(mandir)/man3 HTML_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap/tapsets ### # The build process is as follows (targets): # (xmldocs) [by docproc] # file.tmpl --> file.xml +--> file.ps (psdocs) [by xmlto] # +--> file.pdf (pdfdocs) [by xmlto] # +--> DIR=file (htmldocs) [by xmlto] # +--> man/ (mandocs) [by xmlto] if BUILD_PDFREFDOCS PDFDOCS = tapsets.pdf endif if XMLTO_STRINGPARAM XMLTOMANPARAMS=--stringparam man.authors.section.enabled=0 --stringparam man.copyright.section.enabled=0 XMLTOHTMLPARAMS=--stringparam use.id.as.filename=1 XMLTOPDFPARAMS=--stringparam refentry.generate.name=0 --stringparam refentry.generate.title=1 endif if HAVE_FOP XMLTOPDF_FOP=--with-fop else XMLTOPDF_FOP= endif if BUILD_REFDOCS noinst_PROGRAMS = docproc SRCTREE=$(abs_top_srcdir)/ DOCPROC=$(abs_builddir)/docproc noinst_SCRIPTS = manpager MANPAGER=$(abs_srcdir)/manpager all: $(PDFDOCS) stamp-htmldocs stamp-mandocs tapsets.xml: docproc $(shell find $(SRCTREE)/tapset -name '*.stp') SRCTREE=$(SRCTREE) $(DOCPROC) doc $(abs_srcdir)/tapsets.tmpl > tapsets.xml.new xsltproc $(srcdir)/sort-tapsets.xslt tapsets.xml.new > tapsets.xml.new2 rm tapsets.xml.new if test -s tapsets.xml && cmp tapsets.xml.new2 tapsets.xml >/dev/null ; then \ echo tapsets.xml unchanged; \ rm tapsets.xml.new2; \ else \ mv tapsets.xml.new2 tapsets.xml; \ fi stamp-htmldocs: tapsets.xml xmlto $(XMLTOHTMLPARAMS) html -o tapsets tapsets.xml >/dev/null 2>&1 touch stamp-htmldocs # bump up the allocated space so "xmlto pdf" works tapsets.pdf: tapsets.xml env pool_size=6000000 hash_extra=6000000 xmlto $(XMLTOPDF_FOP) $(XMLTOPDFPARAMS) pdf tapsets.xml >/dev/null 2>&1 stamp-mandocs: tapsets.xml xmlto $(XMLTOMANPARAMS) man -o man3 tapsets.xml >/dev/null 2>&1 SRCTREE=$(SRCTREE) $(MANPAGER) # generate tapset::* pages touch stamp-mandocs #FIXME need to figure out where to install things appropriately #installmandocs: mandocs install-data-hook: if BUILD_PDFREFDOCS $(MKDIR_P) $(DOC_INSTALL_DIR) $(INSTALL_DATA) tapsets.pdf $(DOC_INSTALL_DIR) endif $(MKDIR_P) $(MAN_INSTALL_DIR) $(INSTALL_DATA) man3/* $(MAN_INSTALL_DIR) $(INSTALL_DATA) man_pages/* $(MAN_INSTALL_DIR) # manpager output $(MKDIR_P) $(HTML_INSTALL_DIR) $(INSTALL_DATA) tapsets/* $(HTML_INSTALL_DIR) endif CLEANFILES=tapsets.xml stamp-* $(PDFDOCS) clean-local: rm -rf man3 man_pages tapsets systemtap-2.3/doc/SystemTap_Tapset_Reference/Makefile.in000066400000000000000000000444061217430427200234620ustar00rootroot00000000000000# Makefile.in generated by automake 1.12.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Makefile.am --- automake input file for systemtap tapset reference manual VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ @BUILD_REFDOCS_TRUE@noinst_PROGRAMS = docproc$(EXEEXT) subdir = doc/SystemTap_Tapset_Reference DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = PROGRAMS = $(noinst_PROGRAMS) docproc_SOURCES = docproc.c docproc_OBJECTS = docproc.$(OBJEXT) docproc_LDADD = $(LDADD) SCRIPTS = $(noinst_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = docproc.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac ETAGS = etags CTAGS = ctags ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DATE = @DATE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DYNINST_CXXFLAGS = @DYNINST_CXXFLAGS@ DYNINST_LDFLAGS = @DYNINST_LDFLAGS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_NLS = @ENABLE_NLS@ EXEEXT = @EXEEXT@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ JAVADIR = @JAVADIR@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PIECFLAGS = @PIECFLAGS@ PIECXXFLAGS = @PIECXXFLAGS@ PIELDFLAGS = @PIELDFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POSUB = @POSUB@ PUBLICAN_BRAND = @PUBLICAN_BRAND@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STAP_EXTRA_VERSION = @STAP_EXTRA_VERSION@ STAP_PREFIX = @STAP_PREFIX@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ elfutils_abs_srcdir = @elfutils_abs_srcdir@ exec_prefix = @exec_prefix@ have_dvips = @have_dvips@ have_fop = @have_fop@ have_jar = @have_jar@ have_javac = @have_javac@ have_latex = @have_latex@ have_latex2html = @have_latex2html@ have_ps2pdf = @have_ps2pdf@ have_publican = @have_publican@ have_xmlto = @have_xmlto@ have_xvfb = @have_xvfb@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ nss_CFLAGS = @nss_CFLAGS@ nss_LIBS = @nss_LIBS@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ selinux_CFLAGS = @selinux_CFLAGS@ selinux_LIBS = @selinux_LIBS@ sharedstatedir = @sharedstatedir@ sqlite3_LIBS = @sqlite3_LIBS@ srcdir = @srcdir@ stap_LIBS = @stap_LIBS@ staplog_CPPFLAGS = @staplog_CPPFLAGS@ staprun_LIBS = @staprun_LIBS@ subdirs = @subdirs@ support_section_question = @support_section_question@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap MAN_INSTALL_DIR = $(DESTDIR)$(mandir)/man3 HTML_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap/tapsets ### # The build process is as follows (targets): # (xmldocs) [by docproc] # file.tmpl --> file.xml +--> file.ps (psdocs) [by xmlto] # +--> file.pdf (pdfdocs) [by xmlto] # +--> DIR=file (htmldocs) [by xmlto] # +--> man/ (mandocs) [by xmlto] @BUILD_PDFREFDOCS_TRUE@PDFDOCS = tapsets.pdf @XMLTO_STRINGPARAM_TRUE@XMLTOMANPARAMS = --stringparam man.authors.section.enabled=0 --stringparam man.copyright.section.enabled=0 @XMLTO_STRINGPARAM_TRUE@XMLTOHTMLPARAMS = --stringparam use.id.as.filename=1 @XMLTO_STRINGPARAM_TRUE@XMLTOPDFPARAMS = --stringparam refentry.generate.name=0 --stringparam refentry.generate.title=1 @HAVE_FOP_FALSE@XMLTOPDF_FOP = @HAVE_FOP_TRUE@XMLTOPDF_FOP = --with-fop @BUILD_REFDOCS_TRUE@SRCTREE = $(abs_top_srcdir)/ @BUILD_REFDOCS_TRUE@DOCPROC = $(abs_builddir)/docproc @BUILD_REFDOCS_TRUE@noinst_SCRIPTS = manpager @BUILD_REFDOCS_TRUE@MANPAGER = $(abs_srcdir)/manpager CLEANFILES = tapsets.xml stamp-* $(PDFDOCS) all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/SystemTap_Tapset_Reference/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign doc/SystemTap_Tapset_Reference/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) docproc$(EXEEXT): $(docproc_OBJECTS) $(docproc_DEPENDENCIES) $(EXTRA_docproc_DEPENDENCIES) @rm -f docproc$(EXEEXT) $(AM_V_CCLD)$(LINK) $(docproc_OBJECTS) $(docproc_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/docproc.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(SCRIPTS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @BUILD_REFDOCS_FALSE@install-data-hook: clean: clean-am clean-am: clean-generic clean-local clean-noinstPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-data-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-local clean-noinstPROGRAMS cscopelist ctags distclean \ distclean-compile distclean-generic distclean-tags dvi dvi-am \ html html-am info info-am install install-am install-data \ install-data-am install-data-hook install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am @BUILD_REFDOCS_TRUE@all: $(PDFDOCS) stamp-htmldocs stamp-mandocs @BUILD_REFDOCS_TRUE@tapsets.xml: docproc $(shell find $(SRCTREE)/tapset -name '*.stp') @BUILD_REFDOCS_TRUE@ SRCTREE=$(SRCTREE) $(DOCPROC) doc $(abs_srcdir)/tapsets.tmpl > tapsets.xml.new @BUILD_REFDOCS_TRUE@ xsltproc $(srcdir)/sort-tapsets.xslt tapsets.xml.new > tapsets.xml.new2 @BUILD_REFDOCS_TRUE@ rm tapsets.xml.new @BUILD_REFDOCS_TRUE@ if test -s tapsets.xml && cmp tapsets.xml.new2 tapsets.xml >/dev/null ; then \ @BUILD_REFDOCS_TRUE@ echo tapsets.xml unchanged; \ @BUILD_REFDOCS_TRUE@ rm tapsets.xml.new2; \ @BUILD_REFDOCS_TRUE@ else \ @BUILD_REFDOCS_TRUE@ mv tapsets.xml.new2 tapsets.xml; \ @BUILD_REFDOCS_TRUE@ fi @BUILD_REFDOCS_TRUE@stamp-htmldocs: tapsets.xml @BUILD_REFDOCS_TRUE@ xmlto $(XMLTOHTMLPARAMS) html -o tapsets tapsets.xml >/dev/null 2>&1 @BUILD_REFDOCS_TRUE@ touch stamp-htmldocs # bump up the allocated space so "xmlto pdf" works @BUILD_REFDOCS_TRUE@tapsets.pdf: tapsets.xml @BUILD_REFDOCS_TRUE@ env pool_size=6000000 hash_extra=6000000 xmlto $(XMLTOPDF_FOP) $(XMLTOPDFPARAMS) pdf tapsets.xml >/dev/null 2>&1 @BUILD_REFDOCS_TRUE@stamp-mandocs: tapsets.xml @BUILD_REFDOCS_TRUE@ xmlto $(XMLTOMANPARAMS) man -o man3 tapsets.xml >/dev/null 2>&1 @BUILD_REFDOCS_TRUE@ SRCTREE=$(SRCTREE) $(MANPAGER) # generate tapset::* pages @BUILD_REFDOCS_TRUE@ touch stamp-mandocs #FIXME need to figure out where to install things appropriately #installmandocs: mandocs @BUILD_REFDOCS_TRUE@install-data-hook: @BUILD_PDFREFDOCS_TRUE@@BUILD_REFDOCS_TRUE@ $(MKDIR_P) $(DOC_INSTALL_DIR) @BUILD_PDFREFDOCS_TRUE@@BUILD_REFDOCS_TRUE@ $(INSTALL_DATA) tapsets.pdf $(DOC_INSTALL_DIR) @BUILD_REFDOCS_TRUE@ $(MKDIR_P) $(MAN_INSTALL_DIR) @BUILD_REFDOCS_TRUE@ $(INSTALL_DATA) man3/* $(MAN_INSTALL_DIR) @BUILD_REFDOCS_TRUE@ $(INSTALL_DATA) man_pages/* $(MAN_INSTALL_DIR) # manpager output @BUILD_REFDOCS_TRUE@ $(MKDIR_P) $(HTML_INSTALL_DIR) @BUILD_REFDOCS_TRUE@ $(INSTALL_DATA) tapsets/* $(HTML_INSTALL_DIR) clean-local: rm -rf man3 man_pages tapsets # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: systemtap-2.3/doc/SystemTap_Tapset_Reference/docproc.c000066400000000000000000000262621217430427200232120ustar00rootroot00000000000000/* * docproc is a simple preprocessor for the template files * used as placeholders for the kernel internal documentation. * docproc is used for documentation-frontend and * dependency-generator. * The two usages have in common that they require * some knowledge of the .tmpl syntax, therefore they * are kept together. * * documentation-frontend * Scans the template file and call kernel-doc for * all occurrences of ![EIF]file * Beforehand each referenced file is scanned for * any symbols that are exported via these macros: * EXPORT_SYMBOL(), EXPORT_SYMBOL_GPL(), & * EXPORT_SYMBOL_GPL_FUTURE() * This is used to create proper -function and * -nofunction arguments in calls to kernel-doc. * Usage: docproc doc file.tmpl * * dependency-generator: * Scans the template file and list all files * referenced in a format recognized by make. * Usage: docproc depend file.tmpl * Writes dependency information to stdout * in the following format: * file.tmpl src.c src2.c * The filenames are obtained from the following constructs: * !Efilename * !Ifilename * !Dfilename * !Ffilename * !Pfilename * */ #include #include #include #include #include #include #include #include /* exitstatus is used to keep track of any failing calls to kernel-doc, * but execution continues. */ int exitstatus = 0; typedef void DFL(char *); DFL *defaultline; typedef void FILEONLY(char * file); FILEONLY *internalfunctions; FILEONLY *externalfunctions; FILEONLY *symbolsonly; typedef void FILELINE(char * file, char * line); FILELINE * singlefunctions; FILELINE * entity_system; FILELINE * docsection; #define MAXLINESZ 2048 #define MAXFILES 250 #define KERNELDOCPATH "scripts/" #define KERNELDOC "kernel-doc" #define DOCBOOK "-docbook" #define FUNCTION "-function" #define NOFUNCTION "-nofunction" #define NODOCSECTIONS "-no-doc-sections" char *srctree; void usage (void) { fprintf(stderr, "Usage: docproc {doc|depend} file\n"); fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n"); fprintf(stderr, "doc: frontend when generating kernel documentation\n"); fprintf(stderr, "depend: generate list of files referenced within file\n"); fprintf(stderr, "Environment variable SRCTREE: absolute path to kernel source tree.\n"); } /* * Execute kernel-doc with parameters given in svec */ void exec_kernel_doc(char **svec) { pid_t pid; int ret; char real_filename[PATH_MAX + 1]; /* Make sure output generated so far are flushed */ fflush(stdout); switch (pid=fork()) { case -1: perror("fork"); exit(1); case 0: memset(real_filename, 0, sizeof(real_filename)); strncat(real_filename, srctree, PATH_MAX); strncat(real_filename, KERNELDOCPATH KERNELDOC, PATH_MAX - strlen(real_filename)); execvp(real_filename, svec); fprintf(stderr, "exec "); perror(real_filename); exit(1); default: waitpid(pid, &ret ,0); } if (WIFEXITED(ret)) exitstatus |= WEXITSTATUS(ret); else exitstatus = 0xff; } /* Types used to create list of all exported symbols in a number of files */ struct symbols { char *name; }; struct symfile { char *filename; struct symbols *symbollist; int symbolcnt; }; struct symfile symfilelist[MAXFILES]; int symfilecnt = 0; void add_new_symbol(struct symfile *sym, char * symname) { sym->symbollist = realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *)); sym->symbollist[sym->symbolcnt++].name = strdup(symname); } /* Add a filename to the list */ struct symfile * add_new_file(char * filename) { symfilelist[symfilecnt++].filename = strdup(filename); return &symfilelist[symfilecnt - 1]; } /* Check if file already are present in the list */ struct symfile * filename_exist(char * filename) { int i; for (i=0; i < symfilecnt; i++) if (strcmp(symfilelist[i].filename, filename) == 0) return &symfilelist[i]; return NULL; } /* * List all files referenced within the template file. * Files are separated by tabs. */ void adddep(char * file) { printf("\t%s", file); } void adddep2(char * file, char * line) { line = line; adddep(file); } void noaction(char * line) { line = line; } void noaction2(char * file, char * line) { file = file; line = line; } /* Echo the line without further action */ void printline(char * line) { printf("%s", line); } /* * Find all symbols in filename that are exported with EXPORT_SYMBOL & * EXPORT_SYMBOL_GPL (& EXPORT_SYMBOL_GPL_FUTURE implicitly). * All symbols located are stored in symfilelist. */ void find_export_symbols(char * filename) { FILE * fp; struct symfile *sym; char line[MAXLINESZ]; if (filename_exist(filename) == NULL) { char real_filename[PATH_MAX + 1]; memset(real_filename, 0, sizeof(real_filename)); strncat(real_filename, srctree, PATH_MAX); strncat(real_filename, filename, PATH_MAX - strlen(real_filename)); sym = add_new_file(filename); fp = fopen(real_filename, "r"); if (fp == NULL) { fprintf(stderr, "docproc: "); perror(real_filename); exit(1); } while (fgets(line, MAXLINESZ, fp)) { char *p; char *e; if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != NULL) || ((p = strstr(line, "EXPORT_SYMBOL")) != NULL)) { /* Skip EXPORT_SYMBOL{_GPL} */ while (isalnum(*p) || *p == '_') p++; /* Remove parentheses & additional whitespace */ while (isspace(*p)) p++; if (*p != '(') continue; /* Syntax error? */ else p++; while (isspace(*p)) p++; e = p; while (isalnum(*e) || *e == '_') e++; *e = '\0'; add_new_symbol(sym, p); } } fclose(fp); } } /* * Document all external or internal functions in a file. * Call kernel-doc with following parameters: * kernel-doc -docbook -nofunction function_name1 filename * Function names are obtained from all the src files * by find_export_symbols. * intfunc uses -nofunction * extfunc uses -function */ void docfunctions(char * filename, char * type) { int i,j; int symcnt = 0; int idx = 0; char **vec; for (i=0; i <= symfilecnt; i++) symcnt += symfilelist[i].symbolcnt; vec = malloc((2 + 2 * symcnt + 3) * sizeof(char *)); if (vec == NULL) { perror("docproc: "); exit(1); } vec[idx++] = KERNELDOC; vec[idx++] = DOCBOOK; vec[idx++] = NODOCSECTIONS; for (i=0; i < symfilecnt; i++) { struct symfile * sym = &symfilelist[i]; for (j=0; j < sym->symbolcnt; j++) { vec[idx++] = type; vec[idx++] = sym->symbollist[j].name; } } vec[idx++] = filename; vec[idx] = NULL; printf("\n", filename); exec_kernel_doc(vec); fflush(stdout); free(vec); } void intfunc(char * filename) { docfunctions(filename, NOFUNCTION); } void extfunc(char * filename) { docfunctions(filename, FUNCTION); } /* * Document specific function(s) in a file. * Call kernel-doc with the following parameters: * kernel-doc -docbook -function function1 [-function function2] */ void singfunc(char * filename, char * line) { char *vec[200]; /* Enough for specific functions */ int i, idx = 0; int startofsym = 1; vec[idx++] = KERNELDOC; vec[idx++] = DOCBOOK; /* Split line up in individual parameters preceded by FUNCTION */ for (i=0; line[i]; i++) { if (isspace(line[i])) { line[i] = '\0'; startofsym = 1; continue; } if (startofsym) { startofsym = 0; vec[idx++] = FUNCTION; vec[idx++] = &line[i]; } } vec[idx++] = filename; vec[idx] = NULL; exec_kernel_doc(vec); } /* * Insert specific documentation section from a file. * Call kernel-doc with the following parameters: * kernel-doc -docbook -function "doc section" filename */ void docsect(char *filename, char *line) { char *vec[6]; /* kerneldoc -docbook -function "section" file NULL */ char *s; for (s = line; *s; s++) if (*s == '\n') *s = '\0'; vec[0] = KERNELDOC; vec[1] = DOCBOOK; vec[2] = FUNCTION; vec[3] = line; vec[4] = filename; vec[5] = NULL; exec_kernel_doc(vec); } /* * Parse file, calling action specific functions for: * 1) Lines containing !E * 2) Lines containing !I * 3) Lines containing !D * 4) Lines containing !F * 5) Lines containing !P * 6) Default lines - lines not matching the above */ void parse_file(FILE *infile) { char line[MAXLINESZ]; char * s; while (fgets(line, MAXLINESZ, infile)) { if (line[0] == '!') { s = line + 2; switch (line[1]) { case 'E': while (*s && !isspace(*s)) s++; *s = '\0'; externalfunctions(line+2); break; case 'I': while (*s && !isspace(*s)) s++; *s = '\0'; internalfunctions(line+2); break; case 'D': while (*s && !isspace(*s)) s++; *s = '\0'; symbolsonly(line+2); break; case 'F': /* filename */ while (*s && !isspace(*s)) s++; *s++ = '\0'; /* function names */ while (isspace(*s)) s++; singlefunctions(line +2, s); break; case 'P': /* filename */ while (*s && !isspace(*s)) s++; *s++ = '\0'; /* DOC: section name */ while (isspace(*s)) s++; docsection(line + 2, s); break; default: defaultline(line); } } else { defaultline(line); } } fflush(stdout); } int main(int argc, char *argv[]) { FILE * infile; srctree = getenv("SRCTREE"); if (!srctree) srctree = getcwd(NULL, 0); if (argc != 3) { usage(); exit(1); } /* Open file, exit on error */ infile = fopen(argv[2], "r"); if (infile == NULL) { fprintf(stderr, "docproc: "); perror(argv[2]); exit(2); } if (strcmp("doc", argv[1]) == 0) { /* Need to do this in two passes. * First pass is used to collect all symbols exported * in the various files; * Second pass generate the documentation. * This is required because some functions are declared * and exported in different files :-(( */ /* Collect symbols */ defaultline = noaction; internalfunctions = find_export_symbols; externalfunctions = find_export_symbols; symbolsonly = find_export_symbols; singlefunctions = noaction2; docsection = noaction2; parse_file(infile); /* Rewind to start from beginning of file again */ fseek(infile, 0, SEEK_SET); defaultline = printline; internalfunctions = intfunc; externalfunctions = extfunc; symbolsonly = printline; singlefunctions = singfunc; docsection = docsect; parse_file(infile); } else if (strcmp("depend", argv[1]) == 0) { /* Create first part of dependency chain * file.tmpl */ printf("%s\t", argv[2]); defaultline = noaction; internalfunctions = adddep; externalfunctions = adddep; symbolsonly = adddep; singlefunctions = adddep2; docsection = adddep2; parse_file(infile); printf("\n"); } else { fprintf(stderr, "Unknown option: %s\n", argv[1]); exit(1); } fclose(infile); fflush(stdout); return exitstatus; } systemtap-2.3/doc/SystemTap_Tapset_Reference/dummy-tapsets.xml000066400000000000000000000025731217430427200247520ustar00rootroot00000000000000 SystemTap Tapset Reference Manual 2008-2013 Red Hat, Inc. and others SystemTap Hackers Introduction SystemTap provides free software (GPL) infrastructure to simplify the gathering of information about the running Linux system. This assists diagnosis of a performance or functional problem. SystemTap eliminates the need for the developer to go through the tedious and disruptive instrument, recompile, install, and reboot sequence that may be otherwise required to collect data. SystemTap provides a simple command line interface and scripting language for writing instrumentation for a live running kernel. The instrumentation makes extensive use of the probe points and functions provided in the tapset library. This document describes the various probe points and functions. systemtap-2.3/doc/SystemTap_Tapset_Reference/manpager000077500000000000000000000100151217430427200231220ustar00rootroot00000000000000#!/bin/bash # This script builds overview man pages for each tapset from the doc # comments in the tapset source. As such, the man page content # generated herein should be in sync with the SystemTap Tapset # Reference. # If testing manually, just run this script with # doc/SystemTap_Tapset_Reference as the working directory # and the SRCTREE variable set to the location of your # systemtap source tree. echo "Starting manpager in" `pwd` # cleanup rm -rf man_pages # create working directory mkdir workingdir ; # create list of man pages to generate cat $SRCTREE/doc/SystemTap_Tapset_Reference/tapsets.tmpl | grep ^\!Itapset > manpageus ; sed -i -e 's/\!Itapset\///g' manpageus ; # copy list of man pages into working directory # with similar basenames concatenated for i in `cat manpageus` ; do b=`basename $i` cat $SRCTREE/tapset/$i >>workingdir/$b ; done ; # rewrite manpageus to the resulting files ls workingdir >manpageus # enter workdir cd workingdir ; # copy tapsetdescriptions, then clean for i in `cat ../manpageus`; do sed -n '/\/\/ /,/\/\/ <\/tapsetdescription>/ s/.*/&/w temp' < $i ; mv temp $i.tapsetdescription ; sed -i -e 's/\/\/ //g' $i.tapsetdescription ; sed -i -e 's/\/\/ <\/tapsetdescription>//g' $i.tapsetdescription ; sed -i -e 's/\/\///g' $i.tapsetdescription ; # XXX: may want to trim whitespace from description edges done # strip all tapset files to just comments; but all comments must be exactly 1 space before and after "*" for i in `cat ../manpageus` ; do sed -i -e 's/^ \*/ \*/g' $i; sed -i -e 's/^ \* / \* /g' $i; # mark the start of each probe entry (sub "/**") perl -p -i -e 's|^/\*\*| *probestart|g' $i; sed -i -e '/^ \*/!d' $i; # rename all tapsets (remove .stp filename suffix), create templates echo $i > tempname ; sed -i -e 's/.stp//g' tempname ; mv $i `cat tempname` ; mv tempname $i ; done ; # create man page headers for i in `ls | grep -v .stp | grep -v tapsetdescription` ; do echo ".\\\" -*- nroff -*-" >> $i.template ; echo ".TH tapset::"$i" 3stap --- IBM" >> $i.template ; echo ".SH NAME" >> $i.template ; echo "tapset::"`cat $i.stp`" \- systemtap "`cat $i.stp`" tapset" >> $i.template ; echo " " >> $i.template ; echo ".SH DESCRIPTION" >> $i.template ; cat $i.stp.tapsetdescription >> $i.template ; echo ".TP" >> $i.template ; done # clean man page body sed -i -e 's/\.stp$//g' ../manpageus ; for i in `cat ../manpageus` ; do mv $i $i.tmp ; perl -e 'while(<>){print"$1\n"if/ \* probe ([^\n]*) -/;}' $i.tmp >$i.probenames; perl -e 'while(<>){print"$1\n"if/ \* sfunction ([^\n]*) -/;}' $i.tmp >$i.funcnames; # perl -p -i -e 's/ \* (probe|sfunction) ([^\n]*)\n/.P\n.TP\n.B $1 \n $2\n$3\n perl -p -i -e 's/ \* sfunction ([^\n]*) - ([^\n]*)\n/.P\n.TP\n.B $1 \n$2\n.IP\nSee \n.IR function::$1 \(3stap\)\n for details.\n/g' $i.tmp ; perl -p -i -e 's/ \* probe ([^\n]*) - ([^\n]*)\n/.P\n.TP\n.B $1 \n$2\n.IP\n See \n.IR probe::$1 \(3stap\)\n for details.\n/g' $i.tmp ; # XXX: the people hunger for argument descriptions, which would be extracted here perl -p -i -e 's/ \*([^\n]*)\n//g' $i.tmp ; # nuke the rest of it done # generate footer template for i in `cat ../manpageus` ; do echo "" >> $i.footer echo ".SH SEE ALSO" >> $i.footer for j in `cat $i.funcnames` ; do echo ".BR" >> $i.footer echo ".IR \\%function::"$j" (3stap)," >> $i.footer done for j in `cat $i.probenames` ; do echo ".BR" >> $i.footer echo ".IR \\%probe::"$j" (3stap)," >> $i.footer done echo ".BR" >> $i.footer echo ".IR \\%stap (1)," >> $i.footer echo ".IR \\%stapprobes (3stap)" >> $i.footer done # assemble parts for i in `cat ../manpageus`; do cat $i.template >> tapset\:\:$i.3stap ; cat $i.tmp >> tapset\:\:$i.3stap ; cat $i.footer >> tapset\:\:$i.3stap ; # final polish sed -i -e 's/\*\/$//g' tapset\:\:$i.3stap ; done # cleanup for i in `ls | grep -v -e "tapset::.*\\.3stap"` ; do rm $i ; done rm ../manpageus ; cd .. mv workingdir man_pages echo " " echo "Finished! man pages generated in ./man_pages." echo " " systemtap-2.3/doc/SystemTap_Tapset_Reference/sort-tapsets.xslt000066400000000000000000000012611217430427200247710ustar00rootroot00000000000000 systemtap-2.3/doc/SystemTap_Tapset_Reference/tapcheck.sh000077500000000000000000000035241217430427200235320ustar00rootroot00000000000000#!/bin/sh #check to make sure a tapsets.tmpl file exists if [ ! -f tapsets.tmpl ]; then echo "Error: tapsets.tmpl doesn't exist in the current directory!" exit 1 fi # list the tapsets in the tapsets.tmpl file and properly format the # file names grep "\.stp" tapsets.tmpl | grep ! | sed 's/!Itapset\///g' > checkfile2 # change to the tapset directory and check the tapsets there # check to see if directory is present first if [ ! -d ../../tapset/ ]; then echo "Error: tapsets directory doesn't exist!" exit 1 fi (cd ../../tapset/; find -path "*.stp") | sed 's/\.\///g' > checkfile1 #might as well check for the functions that are documented in #langref now too (cd ../../tapset/; find -path "*.stp" -exec grep -H sfunction {} \; ) \ | sed 's/\.\///g' | cut -d : -f 1 | sort -d | uniq > tap1 # order the tapset names then diff the files to examine the differences sort -d checkfile1 | uniq > checkfile1s sort -d checkfile2 | uniq > checkfile2s comm -23 checkfile1s checkfile2s > missingdoc comm -12 missingdoc tap1 > commondoc comm -23 missingdoc tap1 > missingdoc1 comm -13 checkfile1s checkfile2s > missingtap zero='0' one='1' Missingdoc=`cat missingdoc1 |wc -l ` Missingtap=`cat missingtap | wc -l ` Commondoc=`cat commondoc | wc -l ` if [ "$Missingdoc" -gt "$zero" ] then echo "You have missing documentation from tapsets in use, specifically:" cat missingdoc1 fi if [ "$Missingtap" -gt "$zero" ] then echo "You have documentation for the following tapsets that don't exist!" cat missingtap fi if [ "$Commondoc" -gt "$zero" ] then echo "The following tapsets did not appear in tapset.tmpl, but have references in the langref file." cat commondoc fi rm checkfile2 checkfile2s checkfile1 checkfile1s missingtap missingdoc missingdoc1 commondoc tap1 # at the end we need to make sure we remove any files that we created # change to proper directory first systemtap-2.3/doc/SystemTap_Tapset_Reference/tapsets.tmpl000066400000000000000000000321721217430427200237730ustar00rootroot00000000000000 SystemTap Tapset Reference Manual 2008-2013 Red Hat, Inc. and others SystemTap Hackers This documentation is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. For more details see the file COPYING in the source distribution of Linux. Introduction SystemTap provides free software (GPL) infrastructure to simplify the gathering of information about the running Linux system. This assists diagnosis of a performance or functional problem. SystemTap eliminates the need for the developer to go through the tedious and disruptive instrument, recompile, install, and reboot sequence that may be otherwise required to collect data. SystemTap provides a simple command line interface and scripting language for writing instrumentation for a live running kernel. The instrumentation makes extensive use of the probe points and functions provided in the tapset library. This document describes the various probe points and functions.
Tapset Name Format In this guide, tapset definitions appear in the following format: name:return (parameters) definition The return field specifies what data type the tapset extracts and returns from the kernel during a probe (and thus, returns). Tapsets use 2 data types for return: long (tapset extracts and returns an integer) and string (tapset extracts and returns a string). In some cases, tapsets do not have a return value. This simply means that the tapset does not extract anything from the kernel. This is common among asynchronous events such as timers, exit functions, and print functions.
Context Functions The context functions provide additional information about where an event occurred. These functions can provide information such as a backtrace to where the event occurred and the current register values for the processor. !Itapset/context.stp !Itapset/linux/context.stp !Itapset/linux/context-envvar.stp !Itapset/linux/context-symbols.stp !Itapset/linux/ucontext.stp !Itapset/linux/ucontext-symbols.stp !Itapset/linux/context-unwind.stp !Itapset/linux/context-caller.stp !Itapset/linux/ucontext-unwind.stp !Itapset/linux/task.stp !Itapset/pn.stp !Itapset/linux/pstrace.stp !Itapset/registers.stp Timestamp Functions Each timestamp function returns a value to indicate when a function is executed. These returned values can then be used to indicate when an event occurred, provide an ordering for events, or compute the amount of time elapsed between two time stamps. !Itapset/linux/timestamp.stp !Itapset/linux/timestamp_gtod.stp !Itapset/linux/timestamp_monotonic.stp !Itapset/stopwatch.stp Time utility functions Utility functions to turn seconds since the epoch (as returned by the timestamp function gettimeofday_s()) into a human readable date/time strings. !Itapset/linux/ctime.stp !Itapset/linux/tzinfo.stp !Itapset/tzinfo.stp Shell command functions Utility functions to enqueue shell commands. !Itapset/system.stp Memory Tapset This family of probe points is used to probe memory-related events or query the memory usage of the current process. It contains the following probe points: !Itapset/linux/memory.stp !Itapset/linux/proc_mem.stp Task Time Tapset This tapset defines utility functions to query time related properties of the current tasks, translate those in miliseconds and human readable strings. !Itapset/linux/task_time.stp Scheduler Tapset This family of probe points is used to probe the task scheduler activities. It contains the following probe points: !Itapset/linux/scheduler.stp IO Scheduler and block IO Tapset This family of probe points is used to probe block IO layer and IO scheduler activities. It contains the following probe points: !Itapset/linux/ioscheduler.stp !Itapset/linux/ioblock.stp SCSI Tapset This family of probe points is used to probe SCSI activities. It contains the following probe points: !Itapset/linux/scsi.stp TTY Tapset This family of probe points is used to probe TTY (Teletype) activities. It contains the following probe points: !Itapset/linux/tty.stp Interrupt Request (IRQ) Tapset This family of probe points is used to probe interrupt request (IRQ) activities. It contains the following probe points: !Itapset/linux/irq.stp Networking Tapset This family of probe points is used to probe the activities of the network device and protocol layers. !Itapset/linux/networking.stp !Itapset/linux/tcp.stp !Itapset/linux/udp.stp !Itapset/linux/ip.stp !Itapset/linux/inet.stp !Itapset/linux/rpc.stp !Itapset/linux/netfilter.stp Socket Tapset This family of probe points is used to probe socket activities. It contains the following probe points: !Itapset/linux/socket.stp !Itapset/linux/inet_sock.stp SNMP Information Tapset This family of probe points is used to probe socket activities to provide SNMP type information. It contains the following functions and probe points: !Itapset/linux/ipmib.stp !Itapset/linux/ipmib-filter-default.stp !Itapset/linux/tcpmib.stp !Itapset/linux/tcpmib-filter-default.stp !Itapset/linux/linuxmib.stp !Itapset/linux/linuxmib-filter-default.stp Kernel Process Tapset This family of probe points is used to probe process-related activities. It contains the following probe points: !Itapset/linux/kprocess.stp !Itapset/linux/target_set.stp Signal Tapset This family of probe points is used to probe signal activities. It contains the following probe points: !Itapset/linux/signal.stp Errno Tapset This set of functions is used to handle errno number values. It contains the following functions: !Itapset/errno.stp Device Tapset This set of functions is used to handle kernel and userspace device numbers. It contains the following functions: !Itapset/linux/dev.stp Directory-entry (dentry) Tapset This family of functions is used to map kernel VFS directory entry pointers to file or full path names. !Itapset/linux/dentry.stp Logging Tapset This family of functions is used to send simple message strings to various destinations. !Itapset/logging.stp !Itapset/linux/logging.stp Queue Statistics Tapset This family of functions is used to track performance of queuing systems. !Itapset/queue_stats.stp Random functions Tapset These functions deal with random number generation. !Itapset/random.stp String and data retrieving functions Tapset Functions to retrieve strings and other primitive types from the kernel or a user space programs based on addresses. All strings are of a maximum length given by MAXSTRINGLEN. !Itapset/linux/conversions.stp !Itapset/linux/atomic.stp !Itapset/uconversions.stp String and data writing functions Tapset The SystemTap guru mode can be used to test error handling in kernel code by simulating faults. The functions in the this tapset provide standard methods of writing to primitive types in the kernel's memory. All the functions in this tapset require the use of guru mode (-g). !Itapset/linux/conversions-guru.stp Guru tapsets Functions to deliberately interfere with the system's behavior, in order to inject faults or improve observability. All the functions in this tapset require the use of guru mode (-g). !Itapset/linux/guru-delay.stp !Itapset/linux/panic.stp !Itapset/linux/guru-signal.stp A collection of standard string functions Functions to get the length, a substring, getting at individual characters, string seaching, escaping, tokenizing, and converting strings to longs. !Itapset/string.stp !Itapset/tokenize.stp Utility functions for using ansi control chars in logs Utility functions for logging using ansi control characters. This lets you manipulate the cursor position and character color output and attributes of log messages. !Itapset/ansi.stp !Itapset/indent.stp SystemTap Translator Tapset This family of user-space probe points is used to probe the operation of the SystemTap translator (stap) and run command (staprun). The tapset includes probes to watch the various phases of SystemTap and SystemTap's management of instrumentation cache. It contains the following probe points: !Itapset/stap_staticmarkers.stp Network File Storage Tapsets This family of probe points is used to probe network file storage functions and operations. !Itapset/linux/nfs_proc.stp !Itapset/linux/nfs.stp !Itapset/linux/nfsd.stp !Itapset/linux/nfsderrno.stp Speculation This family of functions provides the ability to speculative record information and then at a later point in the SystemTap script either commit the information or discard it. !Itapset/speculative.stp
systemtap-2.3/doc/Tapset_Reference_Guide/000077500000000000000000000000001217430427200205115ustar00rootroot00000000000000systemtap-2.3/doc/Tapset_Reference_Guide/Makefile000066400000000000000000000006411217430427200221520ustar00rootroot00000000000000#Makefile for Tapset_Reference_Guide XML_LANG = en-US DOCNAME = Tapset_Reference_Guide #PRODUCT = FIX_ME! BRAND = fedora #OTHER_LANGS = as-IN bn-IN de-DE es-ES fr-FR gu-IN hi-IN it-IT ja-JP kn-IN ko-KR ml-IN mr-IN or-IN pa-IN pt-BR ru-RU si-LK ta-IN te-IN zh-CN zh-TW # Extra Parameters start here # Extra Parameters stop here COMMON_CONFIG = /usr/share/publican include $(COMMON_CONFIG)/make/Makefile.common systemtap-2.3/doc/Tapset_Reference_Guide/README000066400000000000000000000032661217430427200214000ustar00rootroot00000000000000The Publican Tapset Reference Guide is build from files generated during the build of SystemTap when it is configured with "--enable-refdocs". Assuming that SystemTap was built in /home/wcohen/systemtap/build, the file needed to generate the Publican Tapset Reference Guide would be /home/wcohen/systemtap/build/doc/SystemTap_Tapset_Reference/tapsets.xml. To generate the required DocBook XML file of the tapsets.xml file and build the Publican Tapset Reference Guide from this directory: export BUILD=/home/wcohen/systemtap/build ./publicanize.sh -i=$BUILD/doc/SystemTap_Tapset_Reference/tapsets.xml This will copy and clean the XML source of SystemTap_Tapset_Reference created by kernel-doc and place the resulting file in ./en-US/Tapset_Reference_Guide.xml. You can now build it in pdf, html, etc using Publican. To make the Publican pdf file: make pdf-en-US The resulting output file will be ./tmp/en-US/pdf/Tapset_Reference_Guide.pdf The main source of the Language Reference Guide is in the build directory: $BUILD/doc/SystemTap_Tapset_Reference/tapsets.xml This main source is generated by kernel-doc when you run 'make' in the main git tree. The tapset documentation inside is collected from all tapset files defined in the following template file: ../SystemTap_Tapset_Reference/tapsets.tmpl The tapset file definitions appear in tapsets.tmpl as: !Itapset/context.stp !Itapset/context-symbols.stp etc context.stp, context-symbols, and all the other tapset files are located in: ../../tapset All tapset documentation should be done inside their respective tapset files. For more information about this project, refer to: http://sourceware.org/systemtap/wiki/ProjectTapsetReferenceGuide systemtap-2.3/doc/Tapset_Reference_Guide/en-US/000077500000000000000000000000001217430427200214405ustar00rootroot00000000000000systemtap-2.3/doc/Tapset_Reference_Guide/en-US/Author_Group.xml000066400000000000000000000013371217430427200246040ustar00rootroot00000000000000 Red Hat Enterprise Linux Documentation Don Domingo Engineering Services and Operations Content Services ddomingo@redhat.com William Cohen Engineering Services and Operations Performance Tools wcohen@redhat.com systemtap-2.3/doc/Tapset_Reference_Guide/en-US/Book_Info.xml000066400000000000000000000023111217430427200240240ustar00rootroot00000000000000 Tapset Reference Guide For SystemTap in Fedora 10 Fedora 10 1.0 0 The Tapset Reference Guide describes the most common tapset definitions users can apply to SystemTap scripts. All included tapsets documented in this guide are current as of Fedora 10 and the latest upstream version of SystemTap. Logo &YEAR; &HOLDER; systemtap-2.3/doc/Tapset_Reference_Guide/en-US/Introduction.xml000066400000000000000000000046631217430427200246540ustar00rootroot00000000000000 Introduction SystemTap provides free software (GPL) infrastructure to simplify the gathering of information about the running Linux system. This assists diagnosis of a performance or functional problem. SystemTap eliminates the need for the developer to go through the tedious and disruptive instrument, recompile, install, and reboot sequence that may be otherwise required to collect data. SystemTap provides a simple command line interface and scripting language for writing instrumentation for a live, running kernel. This instrumentation uses probe points and functions provided in the tapset library. Simply put, tapsets are scripts that encapsulate knowledge about a kernel subsystem into pre-written probes and functions that can be used by other scripts. Tapsets are analogous to libraries for C programs. They hide the underlying details of a kernel area while exposing the key information needed to manage and monitor that aspect of the kernel. They are typically developed by kernel subject-matter experts. A tapset exposes the high-level data and state transitions of a subsystem. For the most part, good tapset developers assume that SystemTap users know little to nothing about the kernel subsystem's low-level details. As such, tapset developers write tapsets that help ordinary SystemTap users write meaningful and useful SystemTap scripts.
Documentation Goals This guide aims to document SystemTap's most useful and common tapset entries; it also contains guidelines on proper tapset development and documentation. The tapset definitions contained in this guide are extracted automatically from properly-formatted comments in the code of each tapset file. As such, any revisions to the definitions in this guide should be applied directly to their respective tapset file. add: "while users can read from code, it's easier to read from here!" add: target audience, expected proficiency of readers
systemtap-2.3/doc/Tapset_Reference_Guide/en-US/Legal_Notice.xml000066400000000000000000000017221217430427200245110ustar00rootroot00000000000000 This documentation is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. For more details see the file COPYING in the source distribution of Linux. systemtap-2.3/doc/Tapset_Reference_Guide/en-US/Preface.xml000066400000000000000000000011361217430427200235300ustar00rootroot00000000000000 Preface systemtap-2.3/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml000066400000000000000000000220311217430427200253330ustar00rootroot00000000000000 Tapset Development Guidelines This chapter describes the upstream guidelines on proper tapset documentation. It also contains information on how to properly document your tapsets, to ensure that they are properly defined in this guide.
Writing Good Tapsets The first step to writing good tapsets is to create a simple model of your subject area. For example, a model of the process subsystem might include the following: Key Data process ID parent process ID process group ID State Transitions forked exec'd running stopped terminated Note Both lists are examples, and are not meant to represent a complete list. Use your subsystem expertise to find probe points (function entries and exits) that expose the elements of the model, then define probe aliases for those points. Be aware that some state transitions can occur in more than one place. In those cases, an alias can place a probe in multiple locations. For example, process execs can occur in either the do_execve() or the compat_do_execve() functions. The following alias inserts probes at the beginning of those functions: probe kprocess.exec = kernel.function("do_execve"), kernel.function("compat_do_execve") {probe body} Try to place probes on stable interfaces (i.e., functions that are unlikely to change at the interface level) whenever possible. This will make the tapset less likely to break due to kernel changes. Where kernel version or architecture dependencies are unavoidable, use preprocessor conditionals (see the stap(1) man page for details). Fill in the probe bodies with the key data available at the probe points. Function entry probes can access the entry parameters specified to the function, while exit probes can access the entry parameters and the return value. Convert the data into meaningful forms where appropriate (e.g., bytes to kilobytes, state values to strings, etc). You may need to use auxiliary functions to access or convert some of the data. Auxiliary functions often use embedded C to do things that cannot be done in the SystemTap language, like access structure fields in some contexts, follow linked lists, etc. You can use auxiliary functions defined in other tapsets or write your own. In the following example, copy_process() returns a pointer to the task_struct for the new process. Note that the process ID of the new process is retrieved by calling task_pid() and passing it the task_struct pointer. In this case, the auxiliary function is an embedded C function defined in task.stp. probe kprocess.create = kernel.function("copy_process").return { task = $return new_pid = task_pid(task) } It is not advisable to write probes for every function. Most SystemTap users will not need or understand them. Keep your tapsets simple and high-level. info from here:http://sourceware.org/git/?p=systemtap.git;a=blob_plain;f=tapset/DEVGUIDE
Elements of a Tapset The following sections describe the most important aspects of writing a tapset. Most of the content herein is suitable for developers who wish to contribute to SystemTap's upstream library of tapsets.
Tapset Files Tapset files are stored in src/tapset/ of the SystemTap GIT directory. Most tapset files are kept at that level. If you have code that only works with a specific architecture or kernel version, you may choose to put your tapset in the appropriate subdirectory. Installed tapsets are located in /usr/share/systemtap/tapset/ or /usr/local/share/systemtap/tapset. Personal tapsets can be stored anywhere. However, to ensure that SystemTap can use them, use -I tapset_directory to specify their location when invoking stap.
Namespace Probe alias names should take the form tapset_name.probe_name. For example, the probe for sending a signal could be named signal.send. Global symbol names (probes, functions, and variables) should be unique accross all tapsets. This helps avoid namespace collisions in scripts that use multiple tapsets. To ensure this, use tapset-specific prefixes in your global symbols. Internal symbol names should be prefixed with an underscore (_).
Comments and Documentation All probes and functions should include comment blocks that describe their purpose, the data they provide, and the context in which they run (e.g. interrupt, process, etc). Use comments in areas where your intent may not be clear from reading the code. Note that specially-formatted comments are automatically extracted from most tapsets and included in this guide. This helps ensure that tapset contributors can write their tapset and document it in the same place. The specified format for documenting tapsets is as follows: /** * probe tapset.name - Short summary of what the tapset does. * @argument: Explanation of argument. * @argument2: Explanation of argument2. Probes can have multiple arguments. * * Context: * A brief explanation of the tapset context. * Note that the context should only be 1 paragraph short. * * Text that will appear under "Description." * * A new paragraph that will also appear under the heading "Description". * * Header: * A paragraph that will appear under the heading "Header". **/ For example: /** * probe vm.write_shared_copy- Page copy for shared page write. * @address: The address of the shared write. * @zero: Boolean indicating whether it is a zero page * (can do a clear instead of a copy). * * Context: * The process attempting the write. * * Fires when a write to a shared page requires a page copy. This is * always preceded by a vm.write_shared. **/ To override the automatically-generated Synopsis content, use: * Synopsis: * New Synopsis string * For example: /** * probe signal.handle - Fires when the signal handler is invoked * @sig: The signal number that invoked the signal handler * * Synopsis: * <programlisting>static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, * sigset_t *oldset, struct pt_regs * regs)</programlisting> */ It is recommended that you use the <programlisting> tag in this instance, since overriding the Synopsis content of an entry does not automatically form the necessary tags. For the purposes of improving the DocBook XML output of your comments, you can also use the following XML tags in your comments: command emphasis programlisting remark (tagged strings will appear in Publican beta builds of the document)
systemtap-2.3/doc/Tapset_Reference_Guide/en-US/Tapset_Reference_Guide.ent000066400000000000000000000002521217430427200265020ustar00rootroot00000000000000 systemtap-2.3/doc/Tapset_Reference_Guide/en-US/images/000077500000000000000000000000001217430427200227055ustar00rootroot00000000000000systemtap-2.3/doc/Tapset_Reference_Guide/en-US/images/icon.svg000066400000000000000000003301271217430427200243640ustar00rootroot00000000000000 image/svg+xml id="path2858" /> systemtap-2.3/doc/Tapset_Reference_Guide/manpager.sh000077500000000000000000000100771217430427200226470ustar00rootroot00000000000000#!/bin/bash # This script builds the man pages from comments in tapsets. As such, the man page content # generated herein should be in sync with Tapset Reference Guide # NOTE: proposed newer version is being developed in doc/Systemtap_Tapset_Reference/manpager.sh # cleanup rm -rf man_pages # create working directory mkdir workingdir ; # create list of man pages to generate cat ../SystemTap_Tapset_Reference/tapsets.tmpl | grep ^\!Itapset > manpageus ; sed -i -e 's/\!Itapset\///g' manpageus ; # copy list of man pages into working directory for i in `cat manpageus` ; do cp ../../tapset/$i workingdir ; done ; # enter workdir cd workingdir ; # copy tapsetdescriptions, then clean for i in `cat ../manpageus`; do sed -n '/\/\/ /,/\/\/ <\/tapsetdescription>/ s/.*/&/w temp' < $i ; mv temp $i.tapsetdescription ; sed -i -e 's/\/\/ //g' $i.tapsetdescription ; sed -i -e 's/\/\/ <\/tapsetdescription>//g' $i.tapsetdescription ; sed -i -e 's/\/\///g' $i.tapsetdescription ; done # strip all tapset files to just comments; but all comments must be exactly 1 space before and after "*" for i in `cat ../manpageus` ; do sed -i -e 's/^ \*/ \*/g' $i; sed -i -e 's/^ \* / \* /g' $i; # mark the start of each probe entry (sub "/**") perl -p -i -e 's|^/\*\*| *probestart|g' $i; sed -i -e '/^ \*/!d' $i; # rename all tapsets (remove .stp filename suffix), create templates echo $i > tempname ; sed -i -e 's/.stp//g' tempname ; mv $i `cat tempname` ; mv tempname $i ; done ; # create man page headers for i in `ls | grep -v .stp | grep -v tapsetdescription` ; do #echo ".\" -*- nroff -*-" >> $i.template ; echo ".TH STAPPROBES."$i" 5 @DATE@ "IBM"" >> $i.template ; echo ".SH NAME" >> $i.template ; echo "stapprobes."`cat $i.stp`" \- systemtap "`cat $i.stp`" probe points" >> $i.template ; echo " " >> $i.template ; echo ".SH DESCRIPTION" >> $i.template ; cat $i.stp.tapsetdescription >> $i.template ; echo " " >> $i.template ; echo ".SH PROBES" >> $i.template ; echo ".br" >> $i.template ; echo ".P" >> $i.template ; echo ".TP" >> $i.template ; done # MOST IMPORTANT: clean man page body! sed -i -e 's/\.stp$//g' ../manpageus ; for i in `cat ../manpageus` ; do mv $i $i.tmp ; perl -p -i -e 's| \* sfunction|.BR|g' $i.tmp ; perl -p -i -e 's| \* probe|.BR|g' $i.tmp ; perl -p -i -e 's| -|\ninitlinehere|g' $i.tmp ; perl -p -i -e 's|^initlinehere([^\n]*)\n|$1\n |g' $i.tmp ; perl -p -i -e 's| \* @([^:]*):|\n.I $1:\n|g' $i.tmp ; perl -p -i -e 's| \* ([^:]*):|\n.BR $1:\n|g' $i.tmp ; perl -p -i -e 's| \* ||g' $i.tmp perl -p -i -e 's|\*probestart|\n.P\n.TP|g' $i.tmp ; perl -p -i -e 's|\.I|\n.I|g' $i.tmp ; # remove empty lines sed -i -e '/^$/d' $i.tmp ; sed -i -e '/^$/d' $i.tmp ; sed -i -e 's/^[ \t]*//g' $i.tmp ; # process Description headers perl -p -i -e 's|^\*[^/]|\n.BR Description:\n|g' $i.tmp ; perl -p -i -e 'undef $/;s|\.BR Description:\n\.BR|.BR|g' $i.tmp ; perl -p -i -e 'undef $/;s|\.BR Description:\n\*\/||g' $i.tmp ; # process Argument headers perl -p -i -e 'undef $/;s|\n\n.I|\n.br\n.BR Arguments:\n.I|g' $i.tmp ; # clean up formatting of arguments perl -p -i -e 's|^.I([^:]*:)|\n.br\n.br\n.IR$1\n.br\n\t|g' $i.tmp ; done # make tags work for i in `cat ../manpageus` ; do perl -p -i -e 's|]*>([^.])|$1\n|g' $i.tmp ; perl -p -i -e 's|<[^>]*>|\n.B |g' $i.tmp ; # the previous two statements create excess empty lines, remove some of them sed -i -e '/^$/d' $i.tmp ; # increase whitespace between some headers perl -p -i -e 's|^\.BR ([^:]*:)|\n.br\n.BR $1\n.br\n|g' $i.tmp done # generate footer template echo ".SH SEE ALSO" >> footer echo ".IR stap (1)," >> footer echo ".IR stapprobes (5)," >> footer for i in `cat ../manpageus`; do echo ".IR stapprobes."$i" (5)," >> footer ; done # assemble parts for i in `cat ../manpageus`; do cat $i.template >> stapprobes.$i.5 ; cat $i.tmp >> stapprobes.$i.5 ; cat footer >> stapprobes.$i.5 ; # final polish sed -i -e 's/\*\/$//g' stapprobes.$i.5 ; done # cleanup for i in `ls | grep -v 'stapprobes.*.5'` ; do rm $i ; done rm ../manpageus ; cd .. mv workingdir man_pages echo " " echo "Finished! man pages generated in ./man_pages." echo " " systemtap-2.3/doc/Tapset_Reference_Guide/publicanize.sh000077500000000000000000000116451217430427200233640ustar00rootroot00000000000000#!/bin/bash INFILE="../SystemTap_Tapset_Reference/tapsets.xml" OUTFILE="en-US/Tapset_Reference_Guide.xml" TMPFILE=`mktemp` || exit 1 TMPFILE2=`mktemp` || exit 1 do_help() { echo "publicanize.sh: usage: -?/--help this message -i/--input=file input file name -o/--output=file output file name " >&2 } #process optional arguments -i -o while [ "$#" -ne 0 ] do arg=`printf %s $1 | awk -F= '{print $1}'` val=`printf %s $1 | awk -F= '{print $2}'` shift if test -z "$val"; then local possibleval=$1 printf %s $1 "$possibleval" | grep ^- >/dev/null 2>&1 if test "$?" != "0"; then val=$possibleval if [ "$#" -ge 1 ]; then shift fi fi fi case "$arg" in -i|--input) INFILE=$val ;; -o|--output) OUTFILE=$val ;; -\?|--help) do_help exit 0 ;; *) echo "Unknown option \"$arg\". See opcontrol --help" >&2 exit 1 ;; esac done #copy the generated tapsets.xml cp $INFILE $TMPFILE || exit 1 #remove all excess whitespace sed -i -e 's/^\s*//g' $TMPFILE #remove marked Intro (starthere to endhere) sed -i -e '/starthere/,/endhere/d' $TMPFILE #re-convert programlisting tags sed -i -e 's/<programlisting>//g' $TMPFILE sed -i -e 's/<\/programlisting>/<\/programlisting>/g' $TMPFILE #replace header cat $TMPFILE | perl -p -e 'undef $/;s|\nSystemTap Tapset Reference Manual|\n|msg' | #perl -p -e 'undef $/;s|\n\nSystemTap\nHackers\n\n||msg' | #perl -p -e 'undef $/;s|\n2008-2009\nRed Hat, Inc. and others\n||msg' | #perl -p -e 'undef $/;s|\n\nThis documentation is free software\; you can redistribute\nit and/or modify it under the terms of the GNU General Public\nLicense version 2 as published by the Free Software Foundation.\n||msg' | #perl -p -e 'undef $/;s|\nThis program is distributed in the hope that it will be\nuseful, but WITHOUT ANY WARRANTY; without even the implied\nwarranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\nSee the GNU General Public License for more details.\n||msg' | #perl -p -e 'undef $/;s|\nYou should have received a copy of the GNU General Public\nLicense along with this program; if not, write to the Free\nSoftware Foundation, Inc., 51 Franklin Street, Fifth Floor,\nBoston, MA 02110-1301 USA.\n||msg' | #perl -p -e 'undef $/;s|\nFor more details see the file COPYING in the source\ndistribution of Linux.\n\n\n||msg' | #perl -p -e 'undef $/;s|||msg' | perl -p -e 'undef $/;s|\n\n\n\n\n\n\n\n\n\n\n\n\n\n||msg' | perl -p -e 'undef $/;s|\n\n\n\n\n\n\n\n\n\n\n||msg' | perl -p -e 'undef $/;s|\n|\nfunction <\/emphasis>|msg' | perl -p -e 'undef $/;s|\n||msg' | perl -p -e 'undef $/;s|\n\n||msg' | perl -p -e 'undef $/;s|\n||msg' | perl -p -e 'undef $/;s|\n||msg' > $TMPFILE2 #replace Intro with my own perl -p -i -e 's||\n|g' $TMPFILE2 #for tapset name format section #perl -p -i -e 'undef $/;s|\nname:return \(parameters\)\ndefinition\n|\nfunction/probe tapset_name:return \(parameters\)\n|msg' $TMPFILE2 #perl -p -i -e 's|In this guide, tapset definitions appear in the following format:|In this guide, the synopsis of each tapset appears in the following format:|g' $TMPFILE2 #perl -p -i -e 's||\n|g' $TMPFILE2 # statements change synopsis tags, as they are still currently unfixed in publican-redhat sed -i -e 's/refsynopsisdiv>/refsect1>/g' $TMPFILE2 sed -i -e 's/refsect1>/refsection>/g' $TMPFILE2 sed -i -e 's/synopsis>/programlisting>\n/g' $TMPFILE2 # re-convert tags sed -i -e 's/<emphasis>//g' $TMPFILE2 sed -i -e 's/<\/emphasis>/<\/emphasis>/g' $TMPFILE2 sed -i -e 's/<remark>//g' $TMPFILE2 sed -i -e 's/<\/remark>/<\/remark>/g' $TMPFILE2 sed -i -e 's/<command>//g' $TMPFILE2 sed -i -e 's/<\/command>/<\/command>/g' $TMPFILE2 #useful marker script; moves content between starthere and endhere to file target #sed -n '/starthere/,/endhere/ s/.*/&/w target' $TMPFILE2 mv $TMPFILE2 $OUTFILE systemtap-2.3/doc/beginners/000077500000000000000000000000001217430427200161325ustar00rootroot00000000000000systemtap-2.3/doc/beginners/Makefile.am000066400000000000000000000036721217430427200201760ustar00rootroot00000000000000# Makefile.am --- automake input file for systemtap tapset reference manual ## process this file with automake to produce Makefile.in # publican will create a pdf file and a directory with *.html files, # a directory called images that contain *.png and *.svg files, a # Common_Content/images with more *.png and *.svg files and a # Common_Content/css directory with *.css files. DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap SBG = SystemTap_Beginners_Guide BEGIN_INSTALL_DIR = $(DOC_INSTALL_DIR)/$(SBG) if BUILD_PUBLICAN all: $(SBG).pdf $(SBG)/index.html # publican isn't make -j safe. So cheat a little, always create pdf and html # at the same time, then make html depend on pdf build for copying. $(SBG).pdf: # We're force to have this workaround due to BZ920216 # which requires a connection to an X server if HAVE_XVFB xvfb-run -a publican build --formats=pdf,html --langs=en-US && \ mv build/en-US/pdf/*$(SBG)*.pdf $(SBG).pdf else publican build --formats=pdf,html --langs=en-US && \ mv build/en-US/pdf/*$(SBG)*.pdf $(SBG).pdf endif #HAVE_XVFB $(SBG)/index.html: $(SBG).pdf mv build/en-US/html $(SBG) clean-local: publican clean rm -f $(SBG).pdf rm -rf $(SBG) install-data-hook: $(MKDIR_P) $(DOC_INSTALL_DIR) $(INSTALL_DATA) $(SBG).pdf $(DOC_INSTALL_DIR) $(MKDIR_P) $(DOC_INSTALL_DIR)/$(SBG) $(INSTALL_DATA) $(SBG)/*.html $(DOC_INSTALL_DIR)/$(SBG) $(MKDIR_P) $(DOC_INSTALL_DIR)/$(SBG)/images $(INSTALL_DATA) $(SBG)/images/*.png $(SBG)/images/*.svg \ $(DOC_INSTALL_DIR)/$(SBG)/images $(MKDIR_P) $(DOC_INSTALL_DIR)/$(SBG)/Common_Content/css $(MKDIR_P) $(DOC_INSTALL_DIR)/$(SBG)/Common_Content/images $(INSTALL_DATA) $(SBG)/Common_Content/css/*.css \ $(DOC_INSTALL_DIR)/$(SBG)/Common_Content/css $(INSTALL_DATA) $(SBG)/Common_Content/images/*.png \ $(SBG)/Common_Content/images/*.svg \ $(DOC_INSTALL_DIR)/$(SBG)/Common_Content/images uninstall-local: rm -f $(DOC_INSTALL_DIR)/$(SBG).pdf rm -rf $(DOC_INSTALL_DIR)/$(SBG) endif systemtap-2.3/doc/beginners/Makefile.in000066400000000000000000000327061217430427200202070ustar00rootroot00000000000000# Makefile.in generated by automake 1.12.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Makefile.am --- automake input file for systemtap tapset reference manual # publican will create a pdf file and a directory with *.html files, # a directory called images that contain *.png and *.svg files, a # Common_Content/images with more *.png and *.svg files and a # Common_Content/css directory with *.css files. VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = doc/beginners DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/doc/SystemTap_Beginners_Guide/publican.cfg.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = publican.cfg CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DATE = @DATE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DYNINST_CXXFLAGS = @DYNINST_CXXFLAGS@ DYNINST_LDFLAGS = @DYNINST_LDFLAGS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_NLS = @ENABLE_NLS@ EXEEXT = @EXEEXT@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ JAVADIR = @JAVADIR@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PIECFLAGS = @PIECFLAGS@ PIECXXFLAGS = @PIECXXFLAGS@ PIELDFLAGS = @PIELDFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POSUB = @POSUB@ PUBLICAN_BRAND = @PUBLICAN_BRAND@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STAP_EXTRA_VERSION = @STAP_EXTRA_VERSION@ STAP_PREFIX = @STAP_PREFIX@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ elfutils_abs_srcdir = @elfutils_abs_srcdir@ exec_prefix = @exec_prefix@ have_dvips = @have_dvips@ have_fop = @have_fop@ have_jar = @have_jar@ have_javac = @have_javac@ have_latex = @have_latex@ have_latex2html = @have_latex2html@ have_ps2pdf = @have_ps2pdf@ have_publican = @have_publican@ have_xmlto = @have_xmlto@ have_xvfb = @have_xvfb@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ nss_CFLAGS = @nss_CFLAGS@ nss_LIBS = @nss_LIBS@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ selinux_CFLAGS = @selinux_CFLAGS@ selinux_LIBS = @selinux_LIBS@ sharedstatedir = @sharedstatedir@ sqlite3_LIBS = @sqlite3_LIBS@ srcdir = @srcdir@ stap_LIBS = @stap_LIBS@ staplog_CPPFLAGS = @staplog_CPPFLAGS@ staprun_LIBS = @staprun_LIBS@ subdirs = @subdirs@ support_section_question = @support_section_question@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap SBG = SystemTap_Beginners_Guide BEGIN_INSTALL_DIR = $(DOC_INSTALL_DIR)/$(SBG) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/beginners/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign doc/beginners/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): publican.cfg: $(top_builddir)/config.status $(top_srcdir)/doc/SystemTap_Beginners_Guide/publican.cfg.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ tags: TAGS TAGS: ctags: CTAGS CTAGS: cscope cscopelist: check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @BUILD_PUBLICAN_FALSE@uninstall-local: @BUILD_PUBLICAN_FALSE@clean-local: @BUILD_PUBLICAN_FALSE@install-data-hook: clean: clean-am clean-am: clean-generic clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-local .MAKE: install-am install-data-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-local \ distclean distclean-generic dvi dvi-am html html-am info \ info-am install install-am install-data install-data-am \ install-data-hook install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ pdf-am ps ps-am uninstall uninstall-am uninstall-local @BUILD_PUBLICAN_TRUE@all: $(SBG).pdf $(SBG)/index.html # publican isn't make -j safe. So cheat a little, always create pdf and html # at the same time, then make html depend on pdf build for copying. @BUILD_PUBLICAN_TRUE@$(SBG).pdf: # We're force to have this workaround due to BZ920216 # which requires a connection to an X server @BUILD_PUBLICAN_TRUE@@HAVE_XVFB_TRUE@ xvfb-run -a publican build --formats=pdf,html --langs=en-US && \ @BUILD_PUBLICAN_TRUE@@HAVE_XVFB_TRUE@ mv build/en-US/pdf/*$(SBG)*.pdf $(SBG).pdf @BUILD_PUBLICAN_TRUE@@HAVE_XVFB_FALSE@ publican build --formats=pdf,html --langs=en-US && \ @BUILD_PUBLICAN_TRUE@@HAVE_XVFB_FALSE@ mv build/en-US/pdf/*$(SBG)*.pdf $(SBG).pdf @BUILD_PUBLICAN_TRUE@$(SBG)/index.html: $(SBG).pdf @BUILD_PUBLICAN_TRUE@ mv build/en-US/html $(SBG) @BUILD_PUBLICAN_TRUE@clean-local: @BUILD_PUBLICAN_TRUE@ publican clean @BUILD_PUBLICAN_TRUE@ rm -f $(SBG).pdf @BUILD_PUBLICAN_TRUE@ rm -rf $(SBG) @BUILD_PUBLICAN_TRUE@install-data-hook: @BUILD_PUBLICAN_TRUE@ $(MKDIR_P) $(DOC_INSTALL_DIR) @BUILD_PUBLICAN_TRUE@ $(INSTALL_DATA) $(SBG).pdf $(DOC_INSTALL_DIR) @BUILD_PUBLICAN_TRUE@ $(MKDIR_P) $(DOC_INSTALL_DIR)/$(SBG) @BUILD_PUBLICAN_TRUE@ $(INSTALL_DATA) $(SBG)/*.html $(DOC_INSTALL_DIR)/$(SBG) @BUILD_PUBLICAN_TRUE@ $(MKDIR_P) $(DOC_INSTALL_DIR)/$(SBG)/images @BUILD_PUBLICAN_TRUE@ $(INSTALL_DATA) $(SBG)/images/*.png $(SBG)/images/*.svg \ @BUILD_PUBLICAN_TRUE@ $(DOC_INSTALL_DIR)/$(SBG)/images @BUILD_PUBLICAN_TRUE@ $(MKDIR_P) $(DOC_INSTALL_DIR)/$(SBG)/Common_Content/css @BUILD_PUBLICAN_TRUE@ $(MKDIR_P) $(DOC_INSTALL_DIR)/$(SBG)/Common_Content/images @BUILD_PUBLICAN_TRUE@ $(INSTALL_DATA) $(SBG)/Common_Content/css/*.css \ @BUILD_PUBLICAN_TRUE@ $(DOC_INSTALL_DIR)/$(SBG)/Common_Content/css @BUILD_PUBLICAN_TRUE@ $(INSTALL_DATA) $(SBG)/Common_Content/images/*.png \ @BUILD_PUBLICAN_TRUE@ $(SBG)/Common_Content/images/*.svg \ @BUILD_PUBLICAN_TRUE@ $(DOC_INSTALL_DIR)/$(SBG)/Common_Content/images @BUILD_PUBLICAN_TRUE@uninstall-local: @BUILD_PUBLICAN_TRUE@ rm -f $(DOC_INSTALL_DIR)/$(SBG).pdf @BUILD_PUBLICAN_TRUE@ rm -rf $(DOC_INSTALL_DIR)/$(SBG) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: systemtap-2.3/doc/langref.tex000066400000000000000000003152351217430427200163270ustar00rootroot00000000000000% SystemTap Language Reference \documentclass[twoside,english]{article} \usepackage{geometry} \geometry{verbose,letterpaper,tmargin=1.5in,bmargin=1.5in,lmargin=1in,rmargin=1in} \usepackage{fancyhdr} \pagestyle{fancy} \usepackage{array} \usepackage{varioref} \usepackage{float} \usepackage{makeidx} \usepackage{verbatim} \usepackage{url} \makeindex \makeatletter %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% LyX specific LaTeX commands. \newcommand{\noun}[1]{\textsc{#1}} %% Bold symbol macro for standard LaTeX users %\providecommand{\boldsymbol}[1]{\mbox{\boldmath $#1$}} %% Because html converters don't know tabularnewline \providecommand{\tabularnewline}{\\} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% User specified LaTeX commands. \setlength{\parindent}{0pt} %\setlength{\parskip}{3pt plus 2pt minus 1pt} \setlength{\parskip}{5pt} % % this makes list spacing much better. % \newenvironment{my_itemize}{ \begin{itemize} \setlength{\itemsep}{1pt} \setlength{\parskip}{0pt} \setlength{\parsep}{0pt}}{\end{itemize} } \newenvironment{vindent} {\begin{list}{}{\setlength{\listparindent}{6pt}} \item[]} {\end{list}} \usepackage{babel} \makeatother \begin{document} \title{SystemTap Language Reference} \maketitle \newpage{} This document was derived from other documents contributed to the SystemTap project by employees of Red Hat, IBM and Intel.\newline Copyright \copyright\space 2007-2013 Red Hat Inc.\newline Copyright \copyright\space 2007-2009 IBM Corp.\newline Copyright \copyright\space 2007 Intel Corporation.\newline Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.\newline The GNU Free Documentation License is available from \url{http://www.gnu.org/licenses/fdl.html} or by writing to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. \newpage{} \tableofcontents{} % \listoftables \newpage{} \section{SystemTap overview\label{sec:SystemTap-Overview}} \subsection{About this guide} This guide is a comprehensive reference of SystemTap's language constructs and syntax. The contents borrow heavily from existing SystemTap documentation found in manual pages and the tutorial. The presentation of information here provides the reader with a single place to find language syntax and recommended usage. In order to successfully use this guide, you should be familiar with the general theory and operation of SystemTap. If you are new to SystemTap, you will find the tutorial to be an excellent place to start learning. For detailed information about tapsets, see the manual pages provided with the distribution. For information about the entire collection of SystemTap reference material, see Section~\ref{sec:For-Further-Reference} \subsection{Reasons to use SystemTap} SystemTap provides infrastructure to simplify the gathering of information about a running Linux kernel so that it may be further analyzed. This analysis assists in identifying the underlying cause of a performance or functional problem. SystemTap was designed to eliminate the need for a developer to go through the tedious instrument, recompile, install, and reboot sequence normally required to collect this kind of data. To do this, it provides a simple command-line interface and scripting language for writing instrumenation for both kernel and user space. With SystemTap, developers, system administrators, and users can easily write scripts that gather and manipulate system data that is otherwise unavailable from standard Linux tools. Users of SystemTap will find it to be a significant improvement over older methods. \subsection{Event-action language} \index{language} SystemTap's language is strictly typed, declaration free, procedural, and inspired by dtrace and awk. Source code points or events in the kernel are associated with handlers, which are subroutines that are executed synchronously. These probes are conceptually similar to \char`\"{}breakpoint command lists\char`\"{} in the GDB debugger. There are two main outermost constructs: probes and functions. Within these, statements and expressions use C-like operator syntax and precedence. \subsection{Sample SystemTap scripts} \index{example scripts} Following are some example scripts that illustrate the basic operation of SystemTap. For more examples, see the examples/small\_demos/ directory in the source directory, the SystemTap wiki at \url{http://sourceware.org/systemtap/wiki/HomePage}, or the SystemTap War Stories at \url{http://sourceware.org/systemtap/wiki/WarStories} page. \subsubsection{Basic SystemTap syntax and control structures} The following code examples demonstrate SystemTap syntax and control structures. \begin{vindent} \begin{verbatim} global odds, evens probe begin { # "no" and "ne" are local integers for (i = 0; i < 10; i++) { if (i % 2) odds [no++] = i else evens [ne++] = i } delete odds[2] delete evens[3] exit() } probe end { foreach (x+ in odds) printf ("odds[%d] = %d", x, odds[x]) foreach (x in evens-) printf ("evens[%d] = %d", x, evens[x]) } \end{verbatim} \end{vindent} This prints: \begin{vindent} \begin{verbatim} odds[0] = 1 odds[1] = 3 odds[3] = 7 odds[4] = 9 evens[4] = 8 evens[2] = 4 evens[1] = 2 evens[0] = 0 \end{verbatim} \end{vindent} Note that all variable types are inferred, and that all locals and globals are initialized. Integers are set to 0 and strings are set to the empty string. \subsubsection{Primes between 0 and 49} \begin{vindent} \begin{verbatim} function isprime (x) { if (x < 2) return 0 for (i = 2; i < x; i++) { if (x % i == 0) return 0 if (i * i > x) break } return 1 } probe begin { for (i = 0; i < 50; i++) if (isprime (i)) printf("%d\n", i) exit() } \end{verbatim} \end{vindent} This prints: \begin{vindent} \begin{verbatim} 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 \end{verbatim} \end{vindent} \subsubsection{Recursive functions} \index{recursion} \begin{vindent} \begin{verbatim} function fibonacci(i) { if (i < 1) error ("bad number") if (i == 1) return 1 if (i == 2) return 2 return fibonacci (i-1) + fibonacci (i-2) } probe begin { printf ("11th fibonacci number: %d", fibonacci (11)) exit () } \end{verbatim} \end{vindent} This prints: \begin{vindent} \begin{verbatim} 11th fibonacci number: 118 \end{verbatim} \end{vindent} Any larger number input to the function may exceed the MAXACTION or MAXNESTING limits, which will be caught at run time and result in an error. For more about limits see Section~\ref{sub:SystemTap-safety}. \newpage{} \subsection{The stap command} \index{stap} The stap program is the front-end to the SystemTap tool. It accepts probing instructions written in its scripting language, translates those instructions into C code, compiles this C code, and loads the resulting kernel module into a running Linux kernel to perform the requested system trace or probe functions. You can supply the script in a named file, from standard input, or from the command line. The SystemTap script runs until one of the following conditions occurs: \begin{itemize} \item The user interrupts the script with a CTRL-C. \item The script executes the exit() function. \item The script encounters a sufficient number of soft errors. \item The monitored command started with the stap program's \texttt{\textbf{-c}} option exits. \end{itemize} The stap command does the following: \begin{itemize} \item Translates the script \item Generates and compiles a kernel module \item Inserts the module; output to stap's stdout \item CTRL-C unloads the module and terminates stap \end{itemize} For a full list of options to the stap command, see the stap(1) manual page. \subsection{Safety and security\label{sub:SystemTap-safety}} \index{limits} SystemTap is an administrative tool. It exposes kernel internal data structures and potentially private user information. It requires root privileges to actually run the kernel objects it builds using the \textbf{sudo} command, applied to the \textbf{staprun} program. staprun is a part of the SystemTap package, dedicated to module loading and unloading and kernel-to-user data transfer. Since staprun does not perform any additional security checks on the kernel objects it is given, do not give elevated privileges via sudo to untrusted users. The translator asserts certain safety constraints. \index{constraints}It ensures that no handler routine can run for too long, allocate memory, perform unsafe operations, or unintentionally interfere with the kernel. Use of script global variables is locked to protect against manipulation by concurrent probe handlers. Use of \emph{guru mode} constructs such as embedded C (see Section~\ref{sub:Embedded-C}) can violate these constraints, leading to a kernel crash or data corruption. The resource use limits are set by macros in the generated C code. These may be overridden with the -D flag. The following list describes a selection of these macros: \textbf{MAXNESTING} -- The maximum number of recursive function call levels. The default is 10. \textbf{MAXSTRINGLEN} -- The maximum length of strings. The default is 256 bytes for 32 bit machines and 512 bytes for all other machines. \textbf{MAXTRYLOCK} -- The maximum number of iterations to wait for locks on global variables before declaring possible deadlock and skipping the probe. The default is 1000. \textbf{MAXACTION} -- The maximum number of statements to execute during any single probe hit. The default is 1000. \textbf{MAXMAPENTRIES} -- The maximum number of rows in an array if the array size is not specified explicitly when declared. The default is 2048. \textbf{MAXERRORS} -- The maximum number of soft errors before an exit is triggered. The default is 0. \textbf{MAXSKIPPED} -- The maximum number of skipped reentrant probes before an exit is triggered. The default is 100. \textbf{MINSTACKSPACE} -- The minimum number of free kernel stack bytes required in order to run a probe handler. This number should be large enough for the probe handler's own needs, plus a safety margin. The default is 1024. If something goes wrong with stap or staprun after a probe has started running, you may safely kill both user processes, and remove the active probe kernel module with the rmmod command. Any pending trace messages may be lost. \section{Types of SystemTap scripts\label{sec:Types-of-SystemTap}} \subsection{Probe scripts} Probe scripts are analogous to programs; these scripts identify probe points and associated handlers. \subsection{Tapset scripts} Tapset scripts are libraries of probe aliases and auxiliary functions. The /usr/share/systemtap/tapset directory contains tapset scripts. While these scripts look like regular SystemTap scripts, they cannot be run directly. \section{Components of a SystemTap script} The main construct in the scripting language identifies probes. Probes associate abstract events with a statement block, or probe handler, that is to be executed when any of those events occur. The following example shows how to trace entry and exit from a function using two probes. \begin{vindent} \begin{verbatim} probe kernel.function("sys_mkdir").call { log ("enter") } probe kernel.function("sys_mkdir").return { log ("exit") } \end{verbatim} \end{vindent} To list the probe-able functions in the kernel, use the listing option (\texttt{\textbf{-l}}). For example: \begin{vindent} \begin{verbatim} $ stap -l 'kernel.function("*")' | sort \end{verbatim} \end{vindent} \subsection{Probe definitions} The general syntax is as follows. \begin{vindent} \begin{verbatim} probe PROBEPOINT [, PROBEPOINT] { [STMT ...] } \end{verbatim} \end{vindent} Events are specified in a special syntax called \emph{probe points}. There are several varieties of probe points defined by the translator, and tapset scripts may define others using aliases. The provided probe points are listed in the \texttt{stapprobes(3)}, \texttt{tapset::*(3stap)}, and \texttt{probe::*(3stap)} man pages. The STMT statement block is executed whenever {\i any} of the named PROBEPOINT events occurs. The probe handler is interpreted relative to the context of each event. For events associated with kernel code, this context may include variables defined in the source code at that location. These \emph{target variables}\index{target variables} (or ``context variables'') are presented to the script as variables whose names are prefixed with a dollar sign (\$). They may be accessed only if the compiler used to compile the kernel preserved them, despite optimization. This is the same constraint imposed by a debugger when working with optimized code. Other events may have very little context. \subsection{Probe aliases\label{sub:Probe-aliases}} \index{probe aliases} The general syntax is as follows. \begin{vindent} \begin{verbatim} probe = { } probe += { } \end{verbatim} \end{vindent} New probe points may be defined using \emph{aliases}. A probe point alias looks similar to probe definitions, but instead of activating a probe at the given point, it defines a new probe point name as an alias to an existing one. New probe aliases may refer to one or more existing probe aliases. Multiple aliases may share the same underlying probe points. The following is an example. \begin{vindent} \begin{verbatim} probe socket.sendmsg = kernel.function ("sock_sendmsg") { ... } probe socket.do_write = kernel.function ("do_sock_write") { ... } probe socket.send = socket.sendmsg, socket.do_write { ... } \end{verbatim} \end{vindent} There are two types of aliases, the prologue style and the epilogue style which are identified by the equal sign (\texttt{\textbf{=}}) and \char`\"{}\texttt{\textbf{+=}}\char`\"{} respectively. A probe that uses a probe point alias will create an actual probe, with the handler of the alias \emph{pre-pended}. This pre-pending behavior serves several purposes. It allows the alias definition to pre-process the context of the probe before passing control to the handler specified by the user. This has several possible uses, demonstrated as follows. \begin{vindent} \begin{verbatim} # Skip probe unless given condition is met: if ($flag1 != $flag2) next # Supply values describing probes: name = "foo" # Extract the target variable to a plain local variable: var = $var \end{verbatim} \end{vindent} \subsubsection{Prologue-style aliases (=)} \index{prologue-style aliases} \index{=} For a prologue style alias, the statement block that follows an alias definition is implicitly added as a prologue to any probe that refers to the alias. The following is an example. \begin{vindent} \begin{verbatim} # Defines a new probe point syscall.read, which expands to # kernel.function("sys_read"), with the given statement as # a prologue. # probe syscall.read = kernel.function("sys_read") { fildes = $fd } \end{verbatim} \end{vindent} \subsubsection{Epilogue-style aliases (+=)} \index{epilogue-style aliases} \index{+=} The statement block that follows an alias definition is implicitly added as an epilogue to any probe that refers to the alias. It is not useful to define new variables there (since no subsequent code will see them), but rather the code can take action based upon variables set by the prologue or by the user code. The following is an example: \begin{vindent} \begin{verbatim} # Defines a new probe point with the given statement as an # epilogue. # probe syscall.read += kernel.function("sys_read") { if (traceme) println ("tracing me") } \end{verbatim} \end{vindent} \subsubsection{Probe alias usage} A probe alias is used the same way as any built-in probe type, by naming it: \begin{vindent} \begin{verbatim} probe syscall.read { printf("reading fd=%d\n", fildes) } \end{verbatim} \end{vindent} \subsubsection{Alias suffixes} It is possible to include a suffix with a probe alias invocation. If only the initial part of a probe point matches an alias, the remainder is treated as a suffix and attached to the underlying probe point(s) when the alias is expanded. For example: \begin{vindent} \begin{verbatim} /* Define an alias: */ probe sendrecv = tcp.sendmsg, tcp.recvmsg { ... } /* Use the alias in its basic form: */ probe sendrecv { ... } /* Use the alias with an additional suffix: */ probe sendrecv.return { ... } \end{verbatim} \end{vindent} Here, the second use of the probe alias is equivalent to writing \verb+probe tcp.sendmsg.return, tcp.recvmsg.return+. As another example, the probe points \verb+tcp.sendmsg.return+ and \verb+tcp.recvmsg.return+ are actually defined as aliases in the tapset \verb+tcp.stp+. They expand to a probe point of the form \verb+kernel.function("...").return+, so they can also be suffixed: \begin{vindent} \begin{verbatim} probe tcp.sendmsg.return.maxactive(10) { printf("returning from sending %d bytes\n", size) } \end{verbatim} \end{vindent} Here, the probe point expands to \verb+kernel.function("tcp_sendmsg").return.maxactive(10)+. \subsubsection{Alias suffixes and wildcards} When expanding wildcards, SystemTap generally avoids considering alias suffixes in the expansion. The exception is when a wildcard element is encountered that does not have any ordinary expansions. Consider the following example: \begin{vindent} \begin{verbatim} probe some_unrelated_probe = ... { ... } probe myprobe = syscall.read { ... } probe myprobe.test = some_unrelated_probe { ... } probe myprobe.* { ... } probe myprobe.ret* { ... } \end{verbatim} \end{vindent} Here, \verb+return+ would be a valid suffix for \verb+myprobe+. The wildcard \verb+myprobe.*+ matches the ordinary alias \verb+myprobe.test+, and hence the suffix expansion \verb+myprobe.return+ is not included. Conversely, \verb+myprobe.ret*+ does not match any ordinary aliases, so the suffix \verb+myprobe.return+ is included as an expansion. \subsection{Variables\label{sub:Variables}} \index{variables} Identifiers for variables and functions are alphanumeric sequences, and may include the underscore (\_) and the dollar sign (\$) characters. They may not start with a plain digit. Each variable is by default local to the probe or function statement block where it is mentioned, and therefore its scope and lifetime is limited to a particular probe or function invocation. Scalar variables are implicitly typed as either string or integer. Associative arrays also have a string or integer value, and a tuple of strings or integers serves as a key. Arrays must be declared as global. Local arrays\index{local arrays} are not allowed. The translator performs \emph{type inference} on all identifiers, including array indexes and function parameters. Inconsistent type-related use of identifiers results in an error. Variables may be declared global. Global variables are shared among all probes and remain instantiated as long as the SystemTap session. There is one namespace for all global variables, regardless of the script file in which they are found. Because of possible concurrency limits, such as multiple probe handlers, each global variable used by a probe is automatically read- or write-locked while the handler is running. A global declaration may be written at the outermost level anywhere in a script file, not just within a block of code. Global variables which are written but never read will be displayed automatically at session shutdown. The following declaration marks \texttt{var1} and \texttt{var2} as global. The translator will infer a value type for each, and if the variable is used as an array, its key types. \begin{vindent} \begin{verbatim} global var1[=], var2[=] \end{verbatim} \end{vindent} \subsubsection{Unused variables} \index{unused variables} The SystemTap translator removes unused variables. Global variable that are never written or read are discarded. Every local variables where the variable is only written but never read are also discarded. This optimization prunes unused variables defined in the probe aliases, but never used in the probe handler. If desired, this optimization can disabled with the \texttt{-u} option. \subsection{Auxiliary functions\label{sub:Auxiliary-functions}} \index{auxiliary functions} General syntax: \begin{vindent} \begin{verbatim} function [:] ( [:], ... ) { } \end{verbatim} \end{vindent} SystemTap scripts may define subroutines to factor out common work. Functions may take any number of scalar arguments, and must return a single scalar value. Scalars in this context are integers or strings. For more information on scalars, see Section~\ref{sub:Variables} and Section~\ref{sub:Data-types}\texttt{.} The following is an example function declaration. \begin{vindent} \begin{verbatim} function thisfn (arg1, arg2) { return arg1 + arg2 } \end{verbatim} \end{vindent} Note the general absence of type declarations, which are inferred by the translator. If desired, a function definition may include explicit type declarations for its return value, its arguments, or both. This is helpful for embedded-C functions. In the following example, the type inference engine need only infer the type of arg2, a string. \begin{vindent} \begin{verbatim} function thatfn:string(arg1:long, arg2) { return sprintf("%d%s", arg1, arg2) } \end{verbatim} \end{vindent} Functions may call others or themselves recursively, up to a fixed nesting limit. See Section~\ref{sub:SystemTap-safety}. \subsection{Embedded C\label{sub:Embedded-C}} \index{embedded C} SystemTap supports a \emph{guru\index{guru mode} mode} where script safety features such as code and data memory reference protection are removed. Guru mode is set by passing the \textbf{-g} option to the stap command. When in guru mode, the translator accepts C code enclosed between {}``\%\{'' and {}``\%\}'' markers in the top level of the script file. The embedded C code is transcribed verbatim, without analysis, in sequence, into the top level of the generated C code. Thus, guru mode may be useful for adding \#include instructions at the top level of the generated module, or providing auxiliary definitions for use by other embedded code. When in guru mode, embedded C code blocks are also allowed as the body of a SystemTap function (as described in Section~\ref{sub:Embedded-C-Functions}), and in place of any SystemTap expression. In the latter case, the code block must contain a valid expression according to C syntax. Here is an example of the various permitted methods of embedded C code inclusion: \begin{vindent} \begin{verbatim} %{ #include #include %} /* <-- top level */ /* Reads the char value stored at a given address: */ function __read_char:long(addr:long) %{ /* pure */ STAP_RETVALUE = kderef(sizeof(char), STAP_ARG_addr); CATCH_DEREF_FAULT (); %} /* <-- function body */ /* Determines whether an IP packet is TCP, based on the iphdr: */ function is_tcp_packet:long(iphdr) { protocol = @cast(iphdr, "iphdr")->protocol return (protocol == %{ IPPROTO_TCP %}) /* <-- expression */ } \end{verbatim} \end{vindent} \subsection{Embedded C functions\label{sub:Embedded-C-Functions}} General syntax: \begin{vindent} \begin{verbatim} function : ( :, ... ) %{ %} \end{verbatim} \end{vindent} Embedded C code is permitted in a function body. In that case, the script language body is replaced entirely by a piece of C code enclosed between {}``\%\{'' and {}``\%\}'' markers. The enclosed code may do anything reasonable and safe as allowed by the C parser. There are a number of undocumented but complex safety constraints on concurrency, resource consumption and runtime limits that are applied to code written in the SystemTap language. These constraints are not applied to embedded C code, so use embedded C code with extreme caution. Be especially careful when dereferencing pointers. Use the kread() macro to dereference any pointers that could potentially be invalid or dangerous. If you are unsure, err on the side of caution and use kread(). The kread() macro is one of the safety mechanisms used in code generated by embedded C. It protects against pointer accesses that could crash the system. For example, to access the pointer chain \texttt{name = skb->dev->name} in embedded C, use the following code. \begin{vindent} \begin{verbatim} struct net_device *dev; char *name; dev = kread(&(skb->dev)); name = kread(&(dev->name)); \end{verbatim} \end{vindent} The memory locations reserved for input and output values are provided to a function using macros named \texttt{STAP\_ARG\_foo}\index{STAP_ARG_} (for arguments named \texttt{foo}) and \texttt{STAP\_RETVALUE}\index{STAP_RETVALUE}. The following are examples. \begin{vindent} \begin{verbatim} function add_one (val:long) %{ STAP_RETVALUE = STAP_ARG_val + 1; %} function add_one_str:string (val:string) %{ strlcpy (STAP_RETVALUE, STAP_ARG_val, MAXSTRINGLEN); strlcat (STAP_RETVALUE, "one", MAXSTRINGLEN); %} \end{verbatim} \end{vindent} The function argument and return value types should be stated; the translator does not analyze the embedded C code within the function. You should examine C code generated for ordinary script language functions to write compatible embedded-C. Note that all SystemTap functions and probes run with interrupts disabled, thus you cannot call functions that might sleep within the embedded C. \subsection{Embedded C pragma comments} Embedded C blocks may contain various markers to assert optimization and safety properties. \begin{itemize} \item \verb+/* pure */+ means that the C code has no side effects and may be elided entirely if its value is not used by script code. \item \verb+/* unprivileged */+ means that the C code is so safe that even unprivileged users are permitted to use it. (This is useful, in particular, to define an embedded-C function inside a tapset that may be used by unprivileged code.) \item \verb+/* myproc-unprivileged */+ means that the C code is so safe that even unprivileged users are permitted to use it, provided that the target of the current probe is within the user's own process. \item \verb+/* guru */+ means that the C code is so unsafe that a systemtap user must specify \verb+-g+ (guru mode) to use this, even if the C code is being exported from a tapset. \item \verb+/* unmangled */+, used in an embedded-C function, means that the legacy (pre-1.8) argument access syntax should be made available inside the function. Hence, in addition to \verb+STAP_ARG_foo+ and \verb+STAP_RETVALUE+ one can use \verb+THIS->foo+ and \verb+THIS->__retvalue+ respectively inside the function. This is useful for quickly migrating code written for SystemTap version 1.7 and earlier. \item \verb+/* string */+ in embedded-C expressions only, means that the expression has \verb+const char *+ type and should be treated as a string value, instead of the default long numeric. \end{itemize} \section{Probe points\label{sec:Probe-Points}} \index{probe points} \subsection{General syntax} \index{probe syntax} The general probe point syntax is a dotted-symbol sequence. This divides the event namespace into parts, analogous to the style of the Domain Name System. Each component identifier is parameterized by a string or number literal, with a syntax analogous to a function call. The following are all syntactically valid probe points. \begin{vindent} \begin{verbatim} kernel.function("foo") kernel.function("foo").return module{"ext3"}.function("ext3_*") kernel.function("no_such_function") ? syscall.* end timer.ms(5000) \end{verbatim} \end{vindent} Probes may be broadly classified into \emph{synchronous}\index{synchronous} or \emph{asynchronous}.\index{asynchronous} A synchronous event occurs when any processor executes an instruction matched by the specification. This gives these probes a reference point (instruction address) from which more contextual data may be available. Other families of probe points refer to asynchronous events such as timers, where no fixed reference point is related. Each probe point specification may match multiple locations, such as by using wildcards or aliases, and all are probed. A probe declaration may contain several specifications separated by commas, which are all probed. \subsubsection{Prefixes} \index{prefixes} Prefixes specify the probe target, such as \textbf{kernel}, \textbf{module}, \textbf{timer}, and so on. \subsubsection{Suffixes} \index{suffixes} Suffixes further qualify the point to probe, such as \textbf{.return} for the exit point of a probed function. The absence of a suffix implies the function entry point. \subsubsection{Wildcarded file names, function names} \index{wildcards} A component may include an asterisk ({*}) character, which expands to other matching probe points. An example follows. \begin{vindent} \begin{verbatim} kernel.syscall.* kernel.function("sys_*) \end{verbatim} \end{vindent} \subsubsection{Optional probe points\label{sub:Optional-probe-points}} \index{?} A probe point may be followed by a question mark (?) character, to indicate that it is optional, and that no error should result if it fails to expand. This effect passes down through all levels of alias or wildcard expansion. The following is the general syntax. \begin{vindent} \begin{verbatim} kernel.function("no_such_function") ? \end{verbatim} \end{vindent} \subsection{Built-in probe point types (DWARF probes)} \index{built-in probes} \index{dwarf probes} \label{dwarfprobes} This family of probe points uses symbolic debugging information for the target kernel or module, as may be found in executables that have not been stripped, or in the separate \textbf{debuginfo} packages. They allow logical placement of probes into the execution path of the target by specifying a set of points in the source or object code. When a matching statement executes on any processor, the probe handler is run in that context. Points in a kernel are identified by module, source file, line number, function name or some combination of these. Here is a list of probe point specifications currently supported: \begin{vindent} \begin{verbatim} kernel.function(PATTERN) kernel.function(PATTERN).call kernel.function(PATTERN).return kernel.function(PATTERN).return.maxactive(VALUE) kernel.function(PATTERN).inline kernel.function(PATTERN).label(LPATTERN) module(MPATTERN).function(PATTERN) module(MPATTERN).function(PATTERN).call module(MPATTERN).function(PATTERN).return.maxactive(VALUE) module(MPATTERN).function(PATTERN).inline kernel.statement(PATTERN) kernel.statement(ADDRESS).absolute module(MPATTERN).statement(PATTERN) \end{verbatim} \end{vindent} The \textbf{.function} variant places a probe near the beginning of the named function, so that parameters are available as context variables. The \textbf{.return} variant places a probe at the moment of return from the named function, so the return value is available as the \$return context variable. The entry parameters are also available, though the function may have changed their values. Return probes may be further qualified with \textbf{.maxactive}, which specifies how many instances of the specified function can be probed simultaneously. You can leave off \textbf{.maxactive} in most cases, as the default (\textbf{KRETACTIVE}) should be sufficient. However, if you notice an excessive number of skipped probes, try setting \textbf{.maxactive} to incrementally higher values to see if the number of skipped probes decreases. The \textbf{.inline} modifier for \textbf{.function} filters the results to include only instances of inlined functions. The \textbf{.call} modifier selects the opposite subset. The \textbf{.exported} modifier filters the results to include only exported functions. Inline functions do not have an identifiable return point, so \textbf{.return} is not supported on \textbf{.inline} probes. The \textbf{.statement} variant places a probe at the exact spot, exposing those local variables that are visible there. In the above probe descriptions, MPATTERN stands for a string literal that identifies the loaded kernel module of interest and LPATTERN stands for a source program label. Both MPATTERN and LPATTERN may include asterisk ({*}), square brackets \char`\"{}{[}]\char`\"{}, and question mark (?) wildcards. PATTERN stands for a string literal that identifies a point in the program. It is composed of three parts: \begin{enumerate} \item The first part is the name of a function, as would appear in the nm program's output. This part may use the asterisk and question mark wildcard operators to match multiple names. \item The second part is optional, and begins with the ampersand (@) character. It is followed by the path to the source file containing the function, which may include a wildcard pattern, such as mm/slab{*}. In most cases, the path should be relative to the top of the linux source directory, although an absolute path may be necessary for some kernels. If a relative pathname doesn't work, try absolute. \item The third part is optional if the file name part was given. It identifies the line number in the source file, preceded by a ``:'' or ``+''. The line number is assumed to be an absolute line number if preceded by a ``:'', or relative to the entry of the function if preceded by a ``+''. All the lines in the function can be matched with ``:*''. A range of lines x through y can be matched with ``:x-y''. \end{enumerate} Alternately, specify PATTERN as a numeric constant to indicate a relative module address or an absolute kernel address. Some of the source-level variables, such as function parameters, locals, or globals visible in the compilation unit, are visible to probe handlers. Refer to these variables by prefixing their name with a dollar sign within the scripts. In addition, a special syntax allows limited traversal of structures, pointers, arrays, taking the address of a variable or pretty printing a whole structure. \texttt{\$var} refers to an in-scope variable var. If it is a type similar to an integer, it will be cast to a 64-bit integer for script use. Pointers similar to a string (char {*}) are copied to SystemTap string values by the \texttt{kernel\_string()} or \texttt{user\_string()} functions. \texttt{@var("varname")} is an alternative syntax for \texttt{\$varname}. It can also be used to access global variables in a particular compile unit (CU). \texttt{@var("varname@src/file.c")} refers to the global (either file local or external) variable varname defined when the file src/file.c was compiled. The CU in which the variable is resolved is the first CU in the module of the probe point which matches the given file name at the end and has the shortest file name path (e.g. given \texttt{@var("foo@bar/baz.c")} and CUs with file name paths \texttt{src/sub/module/bar/baz.c} and \texttt{src/bar/baz.c} the second CU will be chosen to resolve \texttt{foo}). \texttt{\$var->field} or \texttt{@var("var@file.c")->field} traverses a structure's field. The indirection operator may be repeated to follow additional levels of pointers. \texttt{\$var{[}N]} or \texttt{@var("var@file.c"){[}N]} indexes into an array. The index is given with a literal number. \texttt{\&\$var} or \texttt{\&@var("var@file.c")} provides the address of a variable as a long. It can also be used in combination with field access or array indexing to provide the address of a particular field or an element in an array with \texttt{\&var->field}, \texttt{\&@var("var@file.c"){[}N]} or a combination of those accessors. Using a single \texttt{\$} or a double \texttt{\$\$} suffix provides a swallow or deep string representation of the variable data type. Using a single \texttt{\$}, as in \texttt{\$var\$}, will provide a string that only includes the values of all basic type values of fields of the variable structure type but not any nested complex type values (which will be represented with \texttt{\{...\}}). Using a double \texttt{\$\$}, as in \texttt{@var("var")\$\$} will provide a string that also includes all values of nested data types. \texttt{\$\$vars} expands to a character string that is equivalent to \texttt{sprintf("parm1=\%x ... parmN=\%x var1=\%x ... varN=\%x", \$parm1, ..., \$parmN, \$var1, ..., \$varN)} \texttt{\$\$locals} expands to a character string that is equivalent to \texttt{sprintf("var1=\%x ... varN=\%x", \$var1, ..., \$varN)} \texttt{\$\$parms} expands to a character string that is equivalent to \texttt{sprintf("parm1=\%x ... parmN=\%x", \$parm1, ..., \$parmN)} \subsubsection{kernel.function, module().function} \index{kernel.function} \index{module().function} The \textbf{.function} variant places a probe near the beginning of the named function, so that parameters are available as context variables. General syntax: \begin{vindent} \begin{verbatim} kernel.function("func[@file]" module("modname").function("func[@file]" \end{verbatim} \end{vindent} Examples: \begin{vindent} \begin{verbatim} # Refers to all kernel functions with "init" or "exit" # in the name: kernel.function("*init*"), kernel.function("*exit*") # Refers to any functions within the "kernel/time.c" # file that span line 240: kernel.function("*@kernel/time.c:240") # Refers to all functions in the ext3 module: module("ext3").function("*") \end{verbatim} \end{vindent} \subsubsection{kernel.statement, module().statement} \index{kernel.statement} \index{module().statement} The \textbf{.statement} variant places a probe at the exact spot, exposing those local variables that are visible there. General syntax: \begin{vindent} \begin{verbatim} kernel.statement("func@file:linenumber") module("modname").statement("func@file:linenumber") \end{verbatim} \end{vindent} Example: \begin{vindent} \begin{verbatim} # Refers to the statement at line 296 within the # kernel/time.c file: kernel.statement("*@kernel/time.c:296") # Refers to the statement at line bio_init+3 within the fs/bio.c file: kernel.statement("bio_init@fs/bio.c+3") \end{verbatim} \end{vindent} \subsection{Function return probes} \index{return probes} The \texttt{.return} variant places a probe at the moment of return from the named function, so that the return value is available as the \$return context variable. The entry parameters are also accessible in the context of the return probe, though their values may have been changed by the function. Inline functions do not have an identifiable return point, so \texttt{.return} is not supported on \texttt{.inline} probes. \subsection{DWARF-less probing} \index{DWARF-less probing} In the absence of debugging information, you can still use the \emph{kprobe} family of probes to examine the entry and exit points of kernel and module functions. You cannot look up the arguments or local variables of a function using these probes. However, you can access the parameters by following this procedure: When you're stopped at the entry to a function, you can refer to the function's arguments by number. For example, when probing the function declared: \begin{vindent} \begin{verbatim} asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count) \end{verbatim} \end{vindent} You can obtain the values of \texttt{fd}, \texttt{buf}, and \texttt{count}, respectively, as \texttt{uint\_arg(1)}, \texttt{pointer\_arg(2)}, and \texttt{ulong\_arg(3)}. In this case, your probe code must first call \texttt{asmlinkage()}, because on some architectures the asmlinkage attribute affects how the function's arguments are passed. When you're in a return probe, \texttt{\$return} isn't supported without DWARF, but you can call \texttt{returnval()} to get the value of the register in which the function value is typically returned, or call \texttt{returnstr()} to get a string version of that value. And at any code probepoint, you can call \texttt{{register("regname")}} to get the value of the specified CPU register when the probe point was hit. \texttt{u\_register("regname")} is like \texttt{register("regname")}, but interprets the value as an unsigned integer. SystemTap supports the following constructs: \begin{vindent} \begin{verbatim} kprobe.function(FUNCTION) kprobe.function(FUNCTION).return kprobe.module(NAME).function(FUNCTION) kprobe.module(NAME).function(FUNCTION).return kprobe.statement(ADDRESS).absolute \end{verbatim} \end{vindent} Use \textbf{.function} probes for kernel functions and \textbf{.module} probes for probing functions of a specified module. If you do not know the absolute address of a kernel or module function, use \textbf{.statement} probes. Do not use wildcards in \textit{FUNCTION} and \textit{MODULE} names. Wildcards cause the probe to not register. Also, statement probes are available only in guru mode. \subsection{Userspace probing} \index{userspace probing} \index{process} Support for userspace probing is supported on kernels that are configured to include the utrace or uprobes extensions. \subsubsection{Begin/end variants} \label{sec:beginendvariants} Constructs: \begin{vindent} \begin{verbatim} process.begin process("PATH").begin process(PID).begin process.thread.begin process("PATH").thread.begin process(PID).thread.begin process.end process("PATH").end process(PID).end process.thread.end process("PATH").thread.end process(PID).thread.end \end{verbatim} \end{vindent} The \texttt{.begin} variant is called when a new process described by \texttt{PID} or \texttt{PATH} is created. If no \texttt{PID} or \texttt{PATH} argument is specified (for example \texttt{process.begin}), the probe flags any new process being spawned. The \texttt{.thread.begin} variant is called when a new thread described by \texttt{PID} or \texttt{PATH} is created. The \texttt{.end} variant is called when a process described by \texttt{PID} or \texttt{PATH} dies. The \texttt{.thread.end} variant is called when a thread described by \texttt{PID} or \texttt{PATH} dies. \subsubsection{Syscall variants} \label{sec:syscallvariants} Constructs: \begin{vindent} \begin{verbatim} process.syscall process("PATH").syscall process(PID).syscall process.syscall.return process("PATH").syscall.return process(PID).syscall.return \end{verbatim} \end{vindent} The \texttt{.syscall} variant is called when a thread described by \texttt{PID} or \texttt{PATH} makes a system call. The system call number is available in the \texttt{\$syscall} context variable. The first six arguments of the system call are available in the \texttt{\$argN} parameter, for example \texttt{\$arg1}, \texttt{\$arg2}, and so on. The \texttt{.syscall.return} variant is called when a thread described by \texttt{PID} or \texttt{PATH} returns from a system call. The system call number is available in the \texttt{\$syscall} context variable. The return value of the system call is available in the \texttt{\$return} context variable. \subsubsection{Function/statement variants} \label{sec:function-statement} Constructs: \begin{vindent} \begin{verbatim} process("PATH").function("NAME") process("PATH").statement("*@FILE.c:123") process("PATH").function("*").return process("PATH").function("myfun").label("foo") \end{verbatim} \end{vindent} Full symbolic source-level probes in userspace programs and shared libraries are supported. These are exactly analogous to the symbolic DWARF-based kernel or module probes described previously and expose similar contextual \texttt{\$-variables}. See Section~\ref{dwarfprobes} for more information Here is an example of prototype symbolic userspace probing support: \begin{vindent} \begin{verbatim} # stap -e 'probe process("ls").function("*").call { log (probefunc()." ".$$parms) }' \ -c 'ls -l' \end{verbatim} \end{vindent} To run, this script requires debugging information for the named program and utrace support in the kernel. If you see a "pass 4a-time" build failure, check that your kernel supports utrace. \subsubsection{Absolute variant} \label{sec:absolutevariant} A non-symbolic probe point such as \texttt{process(PID).statement(ADDRESS).absolute} is analogous to \newline\texttt{kernel.statement(ADDRESS).absolute} in that both use raw, unverified virtual addresses and provide no \texttt{\$variables}. The target \texttt{PID} parameter must identify a running process and \texttt{ADDRESS} must identify a valid instruction address. All threads of the listed process will be probed. This is a guru mode probe. \subsubsection{Process probe paths} \label{sec:paths} For all process probes, \texttt{PATH} names refer to executables that are searched the same way that shells do: the explicit path specified if the path name begins with a slash (/) character sequence; otherwise \texttt{\$PATH} is searched. For example, the following probe syntax: \begin{vindent} \begin{verbatim} probe process("ls").syscall {} probe process("./a.out").syscall {} \end{verbatim} \end{vindent} works the same as: \begin{vindent} \begin{verbatim} probe process("/bin/ls").syscall {} probe process("/my/directory/a.out").syscall {} \end{verbatim} \end{vindent} If a process probe is specified without a \texttt{PID} or \texttt{PATH} parameter, all user threads are probed. However, if systemtap is invoked in target process mode, process probes are restricted to the process hierarchy associated with the target process. If stap is running in \texttt{--unprivileged} mode, only processes owned by the current user are selected. \subsubsection{Target process mode} \label{sec:targetprocessmode} Target process mode (invoked with \texttt{stap -c CMD} or \texttt{-x PID}) implicitly restricts all \texttt{process.*} probes to the given child process. It does not affect \texttt{kernel.*} or other probe types. The \texttt{CMD} string is normally run directly, rather than from a ``\texttt{/bin/sh -c}'' sub-shell, since utrace and uprobe probes receive a fairly "clean" event stream. If meta-characters such as redirection operators are present in \texttt{CMD}, ``\texttt{/bin/sh -c CMD}'' is still used, and utrace and uprobe probes will receive events from the shell. For example: \begin{vindent} \begin{verbatim} % stap -e 'probe process.syscall, process.end { printf("%s %d %s\n", execname(), pid(), pp())}' \ -c ls \end{verbatim} \end{vindent} Here is the output from this command: \begin{vindent} \begin{verbatim} ls 2323 process.syscall ls 2323 process.syscall ls 2323 process.end \end{verbatim} \end{vindent} If \texttt{PATH} names a shared library, all processes that map that shared library can be probed. If dwarf debugging information is installed, try using a command with this syntax: \begin{vindent} \begin{verbatim} probe process("/lib64/libc-2.8.so").function("....") { ... } \end{verbatim} \end{vindent} This command probes all threads that call into that library. Typing ``\texttt{stap -c CMD}'' or ``\texttt{stap -x PID}'' restricts this to the target command and descendants only. You can use \texttt{\$\$vars} and others. You can provide the location of debug information to the stap command with the \texttt{-d DIRECTORY} option. To qualify a probe point to a location in a library required by a particular process try using a command with this syntax: \begin{vindent} \begin{verbatim} probe process("...").library("...").function("....") { ... } \end{verbatim} \end{vindent} The library name may use wildcards. The first syntax in the following will probe the functions in the program linkage table of a particular process. The second syntax will also add the program linkage tables of libraries required by that process. .plt("...") can be specified to match particular plt entries. \begin{vindent} \begin{verbatim} probe process("...").plt { ... } probe process("...").plt process("...").library("...").plt { ... } \end{verbatim} \end{vindent} \subsubsection{Instruction probes} \label{sec:insnprobes} Constructs: \begin{vindent} \begin{verbatim} process("PATH").insn process(PID).insn process("PATH").insn.block process(PID).insn.block \end{verbatim} \end{vindent} The \texttt{process().insn} and \texttt{process().insn.block} probes inspect the process after each instruction or block of instructions is executed. These probes are not implemented on all architectures. If they are not implemented on your system, you will receive an error message when the script starts. The \texttt{.insn} probe is called for every single-stepped instruction of the process described by \texttt{PID} or \texttt{PATH}. The \texttt{.insn.block} probe is called for every block-stepped instruction of the process described by \texttt{PID} or \texttt{PATH}. To count the total number of instructions that a process executes, type a command similar to: \begin{vindent} \begin{verbatim} $ stap -e 'global steps; probe process("/bin/ls").insn {steps++} probe end {printf("Total instructions: %d\n", steps);}' \ -c /bin/ls \end{verbatim} \end{vindent} Using this feature will significantly slow process execution. \subsubsection{Static userspace probing} \label{sec:staticuserspace} You can probe symbolic static instrumentation compiled into programs and shared libraries with the following syntax: \begin{vindent} \begin{verbatim} process("PATH").mark("LABEL") \end{verbatim} \end{vindent} The \texttt{.mark} variant is called from a static probe defined in the application by \texttt{STAP\_PROBE1(handle,LABEL,arg1)}. \texttt{STAP\_PROBE1} is defined in the sdt.h file. The parameters are: \begin{tabular}{|l|r|c|} Parameter & Definition \\ \hline \texttt{handle} & the application handle \\ \hline \texttt{LABEL} & corresponds to the \texttt{.mark} argument \\ \hline \texttt{arg1} & the argument \\ \hline \end{tabular} Use \texttt{STAP\_PROBE1} for probes with one argument. Use \texttt{STAP\_PROBE2} for probes with 2 arguments, and so on. The arguments of the probe are available in the context variables \texttt{\$arg1}, \texttt{\$arg2}, and so on. As an alternative to the \texttt{STAP\_PROBE} macros, you can use the dtrace script to create custom macros. The sdt.h file also provides dtrace compatible markers through \texttt{DTRACE\_PROBE} and an associated python \texttt{dtrace} script. You can use these in builds based on dtrace that need dtrace -h or -G functionality. \subsection{Java probes} \index{Java probes} Support for probing Java methods is available using Byteman as a backend. Byteman is an instrumentation tool from the JBoss project which systemtap can use to monitor invocations for a specific method or line in a Java program. Systemtap does so by generating a Byteman script listing the probes to instrument and then invoking the Byteman \texttt{bminstall} utility. A custom option \texttt{-D OPTION} (see the Byteman documentation for more details) can be passed to bminstall by invoking systemtap with option \texttt{-J OPTION}. The systemtap option \texttt{-j} is also provided as a shorthand for \texttt{-J org.jboss.byteman.compile.to.bytecode}. This Java instrumentation support is currently a prototype feature with major limitations: Java probes attach only to one Java process at a time; other Java processes beyond the first one to be observed are ignored. Moreover, Java probing currently does not work across users; the stap script must run (with appropriate permissions) under the same user as the Java process being probed. (Thus a stap script under root currently cannot probe Java methods in a non-root-user Java process.) There are four probe point variants supported by the translator: \begin{vindent} \begin{verbatim} java("PNAME").class("CLASSNAME").method("PATTERN") java("PNAME").class("CLASSNAME").method("PATTERN").return java(PID).class("CLASSNAME").method("PATTERN") java(PID).class("CLASSNAME").method("PATTERN").return \end{verbatim} \end{vindent} The first two probe points refer to Java processes by the name of the Java process. The PATTERN parameter specifies the signature of the Java method to probe. The signature must consist of the exact name of the method, followed by a bracketed list of the types of the arguments, for instance \texttt{myMethod(int,double,Foo)}. Wildcards are not supported. The probe can be set to trigger at a specific line within the method by appending a line number with colon, just as in other types of probes: \texttt{myMethod(int,double,Foo):245}. The CLASSNAME parameter identifies the Java class the method belongs to, either with or without the package qualification. By default, the probe only triggers on descendants of the class that do not override the method definition of the original class. However, CLASSNAME can take an optional caret prefix, as in \verb+class("^org.my.MyClass")+, which specifies that the probe should also trigger on all descendants of MyClass that override the original method. For instance, every method with signature foo(int) in program org.my.MyApp can be probed at once using \begin{vindent} \begin{verbatim} java("org.my.MyApp").class("^java.lang.Object").method("foo(int)") \end{verbatim} \end{vindent} The last two probe points work analogously, but refer to Java processes by PID. (PIDs for already running processes can be obtained using the \texttt{jps} utility.) Context variables defined within java probes include \verb+$provider+ (which identifies the class providing the definition of the triggered method) and \verb+$name+ (which gives the signature of the method). Arguments to the method can be accessed using context variables \verb+$arg1$+ through \verb+$arg10+, for up to the first 10 arguments of a method. \subsection{PROCFS probes} \index{PROCFS probes} These probe points allow procfs pseudo-files in \texttt{/proc/systemtap/\textit{MODNAME}} to be created, read and written. Specify the name of the systemtap module as \texttt{\textit{MODNAME}}. There are four probe point variants supported by the translator: \begin{vindent} \begin{verbatim} procfs("PATH").read procfs("PATH").write procfs.read procfs.write \end{verbatim} \end{vindent} \texttt{PATH} is the file name to be created, relative to \texttt{/proc/systemtap/MODNAME}. If no \texttt{PATH} is specified (as in the last two variants in the previous list), \texttt{PATH} defaults to "command". When a user reads \texttt{/proc/systemtap/MODNAME/PATH}, the corresponding procfs read probe is triggered. Assign the string data to be read to a variable named \texttt{\$value}, as follows: \begin{vindent} \begin{verbatim} procfs("PATH").read { $value = "100\n" } \end{verbatim} \end{vindent} When a user writes into \texttt{/proc/systemtap/MODNAME/PATH}, the corresponding procfs write probe is triggered. The data the user wrote is available in the string variable named \texttt{\$value}, as follows: \begin{vindent} \begin{verbatim} procfs("PATH").write { printf("User wrote: %s", $value) } \end{verbatim} \end{vindent} \subsection{Marker probes} \index{marker probes} This family of probe points connects to static probe markers inserted into the kernel or a module. These markers are special macro calls in the kernel that make probing faster and more reliable than with DWARF-based probes. DWARF debugging information is not required to use probe markers. Marker probe points begin with a \texttt{kernel} prefix which identifies the source of the symbol table used for finding markers. The suffix names the marker itself: \texttt{mark.("MARK")}. The marker name string, which can contain wildcard characters, is matched against the names given to the marker macros when the kernel or module is compiled. Optionally, you can specify \texttt{format("FORMAT")}. Specifying the marker format string allows differentiation between two markers with the same name but different marker format strings. The handler associated with a marker probe reads any optional parameters specified at the macro call site named \texttt{\$arg1} through \texttt{\$argNN}, where \texttt{NN} is the number of parameters supplied by the macro. Number and string parameters are passed in a type-safe manner. The marker format string associated with a marker is available in \texttt{\$format}. The marker name string is available in \texttt{\$name}. Here are the marker probe constructs: \begin{vindent} \begin{verbatim} kernel.mark("MARK") kernel.mark("MARK").format("FORMAT") \end{verbatim} \end{vindent} For more information about marker probes, see \url{http://sourceware.org/systemtap/wiki/UsingMarkers}. \subsection{Tracepoints} \label{sec:tracepoints} \index{tracepoints} This family of probe points hooks to static probing tracepoints inserted into the kernel or kernel modules. As with marker probes, these tracepoints are special macro calls inserted by kernel developers to make probing faster and more reliable than with DWARF-based probes. DWARF debugging information is not required to probe tracepoints. Tracepoints have more strongly-typed parameters than marker probes. Tracepoint probes begin with \texttt{kernel}. The next part names the tracepoint itself: \texttt{trace("name")}. The tracepoint \texttt{name} string, which can contain wildcard characters, is matched against the names defined by the kernel developers in the tracepoint header files. The handler associated with a tracepoint-based probe can read the optional parameters specified at the macro call site. These parameters are named according to the declaration by the tracepoint author. For example, the tracepoint probe \texttt{kernel.trace("sched\_switch")} provides the parameters \texttt{\$rq}, \texttt{\$prev}, and \texttt{\$next}. If the parameter is a complex type such as a struct pointer, then a script can access fields with the same syntax as DWARF \texttt{\$target} variables. Tracepoint parameters cannot be modified; however, in guru mode a script can modify fields of parameters. The name of the tracepoint is available in \texttt{\$\$name}, and a string of \texttt{name=value} pairs for all parameters of the tracepoint is available in \texttt{\$\$vars} or \texttt{\$\$parms}. \subsection{Syscall probes} \label{sec:syscall} \index{syscall probes} The \texttt{syscall.*} aliases define several hundred probes. They use the following syntax: \begin{vindent} \begin{verbatim} syscall.NAME syscall.NAME.return \end{verbatim} \end{vindent} Generally, two probes are defined for each normal system call as listed in the syscalls(2) manual page: one for entry and one for return. System calls that never return do not have a corresponding \texttt{.return} probe. Each probe alias defines a variety of variables. Look at the tapset source code to find the most reliable source of variable definitions. Generally, each variable listed in the standard manual page is available as a script-level variable. For example, \texttt{syscall.open} exposes file name, flags, and mode. In addition, a standard suite of variables is available at most aliases, as follows: \begin{itemize} \item \texttt{argstr}: A pretty-printed form of the entire argument list, without parentheses. \item \texttt{name}: The name of the system call. \item \texttt{retstr}: For return probes, a pretty-printed form of the system call result. \end{itemize} Not all probe aliases obey all of these general guidelines. Please report exceptions that you encounter as a bug. \subsection{Timer probes} \index{timer probes} You can use intervals defined by the standard kernel jiffies\index{jiffies} timer to trigger probe handlers asynchronously. A \emph{jiffy} is a kernel-defined unit of time typically between 1 and 60 msec. Two probe point variants are supported by the translator: \begin{vindent} \begin{verbatim} timer.jiffies(N) timer.jiffies(N).randomize(M) \end{verbatim} \end{vindent} The probe handler runs every N jiffies. If the \texttt{randomize}\index{randomize} component is given, a linearly distributed random value in the range {[}-M \ldots{} +M] is added to N every time the handler executes. N is restricted to a reasonable range (1 to approximately 1,000,000), and M is restricted to be less than N. There are no target variables provided in either context. Probes can be run concurrently on multiple processors. Intervals may be specified in units of time. There are two probe point variants similar to the jiffies timer: \begin{vindent} \begin{verbatim} timer.ms(N) timer.ms(N).randomize(M) \end{verbatim} \end{vindent} Here, N and M are specified in milliseconds\index{milliseconds}, but the full options for units are seconds (s or sec), milliseconds (ms or msec), microseconds (us or usec), nanoseconds (ns or nsec), and hertz (hz). Randomization is not supported for hertz timers. The resolution of the timers depends on the target kernel. For kernels prior to 2.6.17, timers are limited to jiffies resolution, so intervals are rounded up to the nearest jiffies interval. After 2.6.17, the implementation uses hrtimers for greater precision, though the resulting resolution will be dependent upon architecture. In either case, if the randomize component is given, then the random value will be added to the interval before any rounding occurs. Profiling timers are available to provide probes that execute on all CPUs at each system tick. This probe takes no parameters, as follows. \begin{vindent} \begin{verbatim} timer.profile.tick \end{verbatim} \end{vindent} Full context information of the interrupted process is available, making this probe suitable for implementing a time-based sampling profiler. It is recommended to use the tapset probe \verb+timer.profile+ rather than \verb+timer.profile.tick+. This probe point behaves identically to \verb+timer.profile.tick+ when the underlying functionality is available, and falls back to using \verb+perf.sw.cpu_clock+ on some recent kernels which lack the corresponding profile timer facility. The following is an example of timer usage. \begin{vindent} \begin{verbatim} # Refers to a periodic interrupt, every 1000 jiffies: timer.jiffies(1000) # Fires every 5 seconds: timer.sec(5) # Refers to a periodic interrupt, every 1000 +/- 200 jiffies: timer.jiffies(1000).randomize(200) \end{verbatim} \end{vindent} \subsection{Special probe points} The probe points \texttt{begin} and \texttt{end} are defined by the translator to refer to the time of session startup and shutdown. There are no target variables available in either context. \subsubsection{begin} \index{begin} The \texttt{begin} probe is the start of the SystemTap session. All \texttt{begin} probe handlers are run during the startup of the session. \subsubsection{end} \index{end} The \texttt{end} probe is the end of the SystemTap session. All \texttt{end} probes are run during the normal shutdown of a session, such as in the aftermath of a SystemTap \texttt{exit} function call, or an interruption from the user. In the case of an shutdown triggered by error, \texttt{end} probes are not run. \subsubsection{error} \index{error} The \emph{error} probe point is similar to the end probe, except the probe handler runs when the session ends if an error occurred. In this case, an \texttt{end} probe is skipped, but each \texttt{error} probe is still attempted. You can use an \texttt{error} probe to clean up or perform a final action on script termination. Here is a simple example: \begin{vindent} \begin{verbatim} probe error { println ("Oops, errors occurred. Here's a report anyway.") foreach (coin in mint) { println (coin) } } \end{verbatim} \end{vindent} \subsubsection{begin, end, and error probe sequence} \index{probe sequence} \texttt{begin}, \texttt{end}, and \texttt{error} probes can be specified with an optional sequence number that controls the order in which they are run. If no sequence number is provided, the sequence number defaults to zero and probes are run in the order that they occur in the script file. Sequence numbers may be either positive or negative, and are especially useful for tapset writers who want to do initialization in a \texttt{begin} probe. The following are examples. \begin{vindent} \begin{verbatim} # In a tapset file: probe begin(-1000) { ... } # In a user script: probe begin { ... } \end{verbatim} \end{vindent} The user script \texttt{begin} probe defaults to sequence number zero, so the tapset \texttt{begin} probe will run first. \subsubsection{never} \index{never} The \texttt{never} probe point is defined by the translator to mean \emph{never}. Its statements are analyzed for symbol and type correctness, but its probe handler is never run. This probe point may be useful in conjunction with optional probes. See Section~\ref{sub:Optional-probe-points}. \section{Language elements\label{sec:Language-Elements}} \subsection{Identifiers} \index{identifiers} \emph{Identifiers} are used to name variables and functions. They are an alphanumeric sequence that may include the underscore (\_) and dollar sign (\$) characters. They have the same syntax as C identifiers, except that the dollar sign is also a legal character. Identifiers that begin with a dollar sign are interpreted as references to variables in the target software, rather than to SystemTap script variables. Identifiers may not start with a plain digit. \subsection{Data types\label{sub:Data-types}} \index{data types} The SystemTap language includes a small number of data types, but no type declarations. A variable's type is inferred\index{inference} from its use. To support this inference, the translator enforces consistent typing of function arguments and return values, array indices and values. There are no implicit type conversions between strings and numbers. Inconsistent type-related use of an identifier signals an error. \subsubsection{Literals} \index{literals} Literals are either strings or integers. Literal integers can be expressed as decimal, octal, or hexadecimal, using C notation. Type suffixes (e.g., \emph{L} or \emph{U}) are not used. \subsubsection{Integers\label{sub:Integers}} \index{integers} \index{numbers} Integers are decimal, hexadecimal, or octal, and use the same notation as in C. Integers are 64-bit signed quantities, although the parser also accepts (and wraps around) values above positive $2^{63}$ but below $2^{64}$. \subsubsection{Strings\label{sub:Strings}} \index{strings} Strings are enclosed in quotation marks ({}``string''), and pass through standard C escape codes with backslashes. A string literal may be split into several pieces, which are glued together, as follows. \begin{vindent} \begin{verbatim} str1 = "foo" "bar" /* --> becomes "foobar" */ str2 = "a good way to do a multi-line\n" "string literal" /* --> becomes "a good way to do a multi-line\nstring literal" */ str3 = "also a good way to " @1 " splice command line args" /* --> becomes "also a good way to foo splice command line args", assuming @1 is given as foo on the command line */ \end{verbatim} \end{vindent} Observe that script arguments can also be glued into a string literal. Strings are limited in length to MAXSTRINGLEN. For more information about this and other limits, see Section~\ref{sub:SystemTap-safety}. \subsubsection{Associative arrays} See Section~\ref{sec:Associative-Arrays} \subsubsection{Statistics} See Section~\ref{sec:Statistics} \subsection{Semicolons} \index{;} The semicolon is the null statement, or do nothing statement. It is optional, and useful as a separator between statements to improve detection of syntax errors and to reduce ambiguities in grammar. \subsection{Comments} \index{comments} Three forms of comments are supported, as follows. \begin{vindent} \begin{verbatim} # ... shell style, to the end of line // ... C++ style, to the end of line /* ... C style ... */ \end{verbatim} \end{vindent} \subsection{Whitespace} \index{whitespace} As in C, spaces, tabs, returns, newlines, and comments are treated as whitespace. Whitespace is ignored by the parser. \subsection{Expressions} \index{expressions} SystemTap supports a number of operators that use the same general syntax, semantics, and precedence as in C and awk. Arithmetic is performed per C rules for signed integers. If the parser detects division by zero or an overflow, it generates an error. The following subsections list these operators. \subsubsection{Binary numeric operators} \index{binary} \texttt{{*} / \% + - >\,{}> <\,{}< \& \textasciicircum{} | \&\& ||} \subsubsection{Binary string operators} \index{binary} \texttt{\textbf{.}} (string concatenation) \subsubsection{Numeric assignment operators} \index{numeric} \texttt{= {*}= /= \%= += -= >\,{}>= <\,{}<= \&= \textasciicircum{}= |=} \subsubsection{String assignment operators} \texttt{= .=} \subsubsection{Unary numeric operators} \index{unary} \texttt{+ - ! \textasciitilde{} ++ -{}-} \subsubsection{Binary numeric, string comparison, or regular expression matching operators} \index{comparison} \texttt{< > <= >= == !=} \verb+=~+ \verb+!~+ The regular expression matching (\verb+=~+ and \verb+!~+) is currently an experimental feature. The second operand must be a string literal containing a syntactically valid regular expression. The regular expression syntax supports most of the features of POSIX Extended Regular Expressions, except for subexpression reuse (\verb+\1+) functionality. The ability to capture and extract the contents of the matched string and subexpressions has not yet been implemented. \subsubsection{Ternary operator\label{sub:Ternary-operator}} \index{?} \texttt{cond ? exp1 : exp2} \subsubsection{Grouping operator} \index{grouping} \texttt{( exp )} \subsubsection{Function call} \index{fn} General syntax: \texttt{fn ({[} arg1, arg2, ... ])} \subsubsection{\$ptr-\textgreater member} \index{pointer} \texttt{ptr} is a kernel pointer available in a probed context. \subsubsection{Pointer typecasting} \index{Pointer typecasting} \emph{Typecasting} is supported using the \texttt{@cast()} operator. A script can define a pointer type for a \emph{long} value, then access type members using the same syntax as with \texttt{\$target} variables. After a pointer is saved into a script integer variable, the translator loses the necessary type information to access members from that pointer. The \texttt{@cast()} operator tells the translator how to read a pointer. The following statement interprets \texttt{p} as a pointer to a struct or union named \texttt{type\_name} and dereferences the \texttt{member} value: \begin{vindent} \begin{verbatim} @cast(p, "type_name"[, "module"])->member \end{verbatim} \end{vindent} The optional \texttt{module} parameter tells the translator where to look for information about that type. You can specify multiple modules as a list with colon (\texttt{:}) separators. If you do not specify the module parameter, the translator defaults to either the probe module for dwarf probes or to \textit{kernel} for functions and all other probe types. The following statement retrieves the parent PID from a kernel task\_struct: \begin{vindent} \begin{verbatim} @cast(pointer, "task_struct", "kernel")->parent->tgid \end{verbatim} \end{vindent} The translator can create its own module with type information from a header surrounded by angle brackets (\texttt{< >}) if normal debugging information is not available. For kernel headers, prefix it with \texttt{kernel} to use the appropriate build system. All other headers are built with default GCC parameters into a user module. The following statements are examples. \begin{vindent} \begin{verbatim} @cast(tv, "timeval", "")->tv_sec @cast(task, "task_struct", "kernel")->tgid \end{verbatim} \end{vindent} In guru mode, the translator allows scripts to assign new values to members of typecasted pointers. Typecasting is also useful in the case of \texttt{void*} members whose type might be determinable at run time. \begin{vindent} \begin{verbatim} probe foo { if ($var->type == 1) { value = @cast($var->data, "type1")->bar } else { value = @cast($var->data, "type2")->baz } print(value) } \end{verbatim} \end{vindent} \subsubsection{\textless value\textgreater\ in \textless array\_name\textgreater} \index{index} This expression evaluates to true if the array contains an element with the specified index. \subsubsection{{[} \textless value\textgreater, ... ] in \textless array\_name\textgreater} The number of index values must match the number of indexes previously specified. \subsection{Literals passed in from the stap command line\label{sub:Literals-passed-in}} \index{literals} \emph{Literals} are either strings enclosed in double quotes ('' '') or integers. For information about integers, see Section~\ref{sub:Integers}. For information about strings, see Section~\ref{sub:Strings}. Script arguments at the end of a command line are expanded as literals. You can use these in all contexts where literals are accepted. A reference to a nonexistent argument number is an error. \subsubsection{\$1 \ldots{} \$\textless NN\textgreater\ for literal pasting} \index{\$} Use \texttt{\$1 \ldots{} \$} for pasting the entire argument string into the input stream, which will be further lexically tokenized. \subsubsection{@1 \ldots{} @\textless NN\textgreater\ for strings} Use \texttt{@1 \ldots{} @} for casting an entire argument as a string literal. \subsubsection{Examples} For example, if the following script named example.stp \begin{vindent} \begin{verbatim} probe begin { printf("%d, %s\n", $1, @2) } \end{verbatim} \end{vindent} is invoked as follows \begin{vindent} \begin{verbatim} # stap example.stp '5+5' mystring \end{verbatim} \end{vindent} then 5+5 is substituted for \$1 and \char`\"{}mystring\char`\"{} for @2. The output will be \begin{vindent} \begin{verbatim} 10, mystring \end{verbatim} \end{vindent} \subsection{Conditional compilation} \subsubsection{Conditions} \index{conditions} One of the steps of parsing is a simple preprocessing stage. The preprocessor supports conditionals with a general form similar to the ternary operator (Section~\ref{sub:Ternary-operator}). \begin{vindent} \begin{verbatim} %( CONDITION %? TRUE-TOKENS %) %( CONDITION %? TRUE-TOKENS %: FALSE-TOKENS %) \end{verbatim} \end{vindent} The CONDITION is a limited expression whose format is determined by its first keyword. The following is the general syntax. \begin{vindent} \begin{verbatim} %( %? [ %: ] %) \end{verbatim} \end{vindent} \subsubsection{Conditions based on available target variables} \index{defined target variable} The predicate @defined() is available for testing whether a particular \$variable/expression is resolvable at translation time. The following is an example of its use: \begin{vindent} \begin{verbatim} probe foo { if (@defined($bar)) log ("$bar is available here") } \end{verbatim} \end{vindent} \subsubsection{Conditions based on kernel version: kernel\_v, kernel\_vr} \index{kernel version} \index{kernel\_vr} \index{kernel\_v} If the first part of a conditional expression is the identifier \texttt{kernel\_v} or \texttt{kernel\_vr}, the second part must be one of six standard numeric comparison operators {}``\textless'', {}``\textless ='', {}``=='', {}``!='', {}``\textgreater'', or {}``\textgreater ='', and the third part must be a string literal that contains an RPM-style version-release value. The condition returns true if the version of the target kernel (as optionally overridden by the \textbf{-r} option) matches the given version string. The comparison is performed by the glibc function strverscmp. \texttt{kernel\_v} refers to the kernel version number only, such as {}``2.6.13\char`\"{}. \texttt{kernel\_vr} refers to the kernel version number including the release code suffix, such as {}``2.6.13-1.322FC3smp''. \subsubsection{Conditions based on architecture: arch} \index{arch} If the first part of the conditional expression is the identifier \texttt{arch} which refers to the processor architecture, then the second part is a string comparison operator ''=='' or ''!='', and the third part is a string literal for matching it. This comparison is a simple string equality or inequality. The currently supported architecture strings are i386, i686, x86\_64, ia64, s390, and powerpc. \subsubsection{Conditions based on privilege level: systemtap\_privilege} \index{systemtap\_privilege} If the first part of the conditional expression is the identifier \texttt{systemtap\_privilege} which refers to the privilege level the systemtap script is being compiled with, then the second part is a string comparison operator ''=='' or ''!='', and the third part is a string literal for matching it. This comparison is a simple string equality or inequality. The possible privilege strings to consider are \verb+"stapusr"+ for unprivileged scripts, and \verb+"stapsys"+ or \verb+"stapdev"+ for privileged scripts. (In general, to test for a privileged script it is best to use \verb+!= "stapusr"+.) This condition can be used to write scripts that can be run in both privileged and unprivileged modes, with additional functionality made available in the privileged case. \subsubsection{True and False Tokens} \index{tokens} TRUE-TOKENS and FALSE-TOKENS are zero or more general parser tokens, possibly including nested preprocessor conditionals, that are pasted into the input stream if the condition is true or false. For example, the following code induces a parse error unless the target kernel version is newer than 2.6.5. \begin{vindent} \begin{verbatim} %( kernel_v <= "2.6.5" %? **ERROR** %) # invalid token sequence \end{verbatim} \end{vindent} The following code adapts to hypothetical kernel version drift. \begin{vindent} \begin{verbatim} probe kernel.function ( %( kernel_v <= "2.6.12" %? "__mm_do_fault" %: %( kernel_vr == "2.6.13-1.8273FC3smp" %? "do_page_fault" %: UNSUPPORTED %) %)) { /* ... */ } %( arch == "ia64" %? probe syscall.vliw = kernel.function("vliw_widget") {} %) \end{verbatim} \end{vindent} The following code adapts to the presence of a kernel CONFIG option. \begin{vindent} \begin{verbatim} %( CONFIG_UTRACE == "y" %? probe process.syscall {} %) \end{verbatim} \end{vindent} \subsection{Preprocessor macros (experimental)} This is an experimental feature whose semantics are subject to change. \subsubsection{Local macros} The preprocessor also supports a simple macro facility. Macros taking zero or more arguments are defined using the following construct: \begin{vindent} \begin{verbatim} @define NAME %( BODY %) @define NAME(PARAM_1, PARAM_2, ...) %( BODY %) \end{verbatim} \end{vindent} Macro arguments are referred to in the body by prefixing the argument name with an \texttt{@} symbol. Likewise, once defined, macros are invoked by prefixing the macro name with an \texttt{@} symbol: \begin{vindent} \begin{verbatim} @define foo %( x %) @define add(a,b) %( ((@a)+(@b)) %) @foo = @add(2,2) \end{verbatim} \end{vindent} Macro expansion is currently performed in a separate pass before conditional compilation. Therefore, both TRUE- and FALSE-tokens in conditional expressions will be macroexpanded regardless of how the condition is evaluated. This can sometimes lead to errors: \begin{vindent} \begin{verbatim} // The following results in a conflict: %( CONFIG_UTRACE == "y" %? @define foo %( process.syscall %) %: @define foo %( **ERROR** %) %) // The following works properly as expected: @define foo %( %( CONFIG_UTRACE == "y" %? process.syscall %: **ERROR** %) %) \end{verbatim} \end{vindent} The first example is incorrect because both \texttt{@define}s are evaluated in a pass prior to the conditional being evaluated. \subsubsection{Library macros} Normally, a macro definition is local to the file it occurs in. Thus, defining a macro in a tapset does not make it available to the user of the tapset. Publically available library macros can be defined by including \texttt{.stpm} files on the tapset search path. These files may only contain \texttt{@define} constructs, which become visible across all tapsets and user scripts. \section{Statement types\label{sec:Statement-Types}} Statements enable procedural control flow within functions and probe handlers. The total number of statements executed in response to any single probe event is limited to MAXACTION, which defaults to 1000. See Section~\ref{sub:SystemTap-safety}. \subsection{break and continue} \index{break} \index{continue} Use \texttt{break} or \texttt{continue} to exit or iterate the innermost nesting loop statement, such as within a \texttt{while, for,} or \texttt{foreach} statement. The syntax and semantics are the same as those used in C. \subsection{try/catch} \index{try} \index{catch} Use \texttt{try}/\texttt{catch} to handle most kinds of run-time errors within the script instead of aborting the probe handler in progress. The semantics are similar to C++ in that try/catch blocks may be nested. The error string may be captured by optionally naming a variable which is to receive it. \begin{vindent} \begin{verbatim} try { /* do something */ /* trigger error like kread(0), or divide by zero, or error("foo") */ } catch (msg) { /* omit (msg) entirely if not interested */ /* println("caught error ", msg) */ /* handle error */ } /* execution continues */ \end{verbatim} \end{vindent} \subsection{delete\label{sub:delete}} \index{delete} \texttt{delete} removes an element. The following statement removes from ARRAY the element specified by the index tuple. The value will no longer be available, and subsequent iterations will not report the element. It is not an error to delete an element that does not exist. \begin{vindent} \begin{verbatim} delete ARRAY[INDEX1, INDEX2, ...] \end{verbatim} \end{vindent} The following syntax removes all elements from ARRAY: \begin{vindent} \begin{verbatim} delete ARRAY \end{verbatim} \end{vindent} The following statement removes the value of SCALAR. Integers and strings are cleared to zero and null (\char`\"{}\char`\"{}) respectively, while statistics are reset to their initial empty state. \begin{vindent} \begin{verbatim} delete SCALAR \end{verbatim} \end{vindent} \subsection{EXP (expression)} \index{expression} An \texttt{expression} executes a string- or integer-valued expression and discards the value. \subsection{for} \index{for} General syntax: \begin{vindent} \begin{verbatim} for (EXP1; EXP2; EXP3) STMT \end{verbatim} \end{vindent} The \texttt{for} statement is similar to the \texttt{for} statement in C. The \texttt{for} expression executes EXP1 as initialization. While EXP2 is non-zero, it executes STMT, then the iteration expression EXP3. \subsection{foreach\label{sub:foreach}} \index{foreach} General syntax: \begin{vindent} \begin{verbatim} foreach (VAR in ARRAY) STMT \end{verbatim} \end{vindent} The \texttt{foreach} statement loops over each element of a named global array, assigning the current key to VAR. The array must not be modified within the statement. If you add a single plus (+) or minus (-) operator after the VAR or the ARRAY identifier, the iteration order will be sorted by the ascending or descending index or value. The following statement behaves the same as the first example, except it is used when an array is indexed with a tuple of keys. Use a sorting suffix on at most one VAR or ARRAY identifier. \begin{vindent} \begin{verbatim} foreach ([VAR1, VAR2, ...] in ARRAY) STMT \end{verbatim} \end{vindent} You can combine the first and second syntax to capture both the full tuple and the keys at the same time as follows. \begin{vindent} \begin{verbatim} foreach (VAR = [VAR1, VAR2, ...] in ARRAY) STMT \end{verbatim} \end{vindent} The following statement is the same as the first example, except that the \texttt{limit} keyword limits the number of loop iterations to EXP times. EXP is evaluated once at the beginning of the loop. \begin{vindent} \begin{verbatim} foreach (VAR in ARRAY limit EXP) STMT \end{verbatim} \end{vindent} \subsection{if} \index{if} General syntax: \begin{vindent} \begin{verbatim} if (EXP) STMT1 [ else STMT2 ] \end{verbatim} \end{vindent} The \texttt{if} statement compares an integer-valued EXP to zero. It executes the first STMT if non-zero, or the second STMT if zero. The \texttt{if} command has the same syntax and semantics as used in C. \subsection{next} \index{next} The \texttt{next} statement returns immediately from the enclosing probe handler. \subsection{; (null statement)} \index{;} \index{null statement} General syntax: \begin{vindent} \begin{verbatim} statement1 ; statement2 \end{verbatim} \end{vindent} The semicolon represents the null statement, or do nothing. It is useful as an optional separator between statements to improve syntax error detection and to handle certain grammar ambiguities. \subsection{return} \index{return} General syntax: \begin{vindent} \begin{verbatim} return EXP \end{verbatim} \end{vindent} The \texttt{return} statement returns the EXP value from the enclosing function. If the value of the function is not returned, then a return statement is not needed, and the function will have a special \emph{unknown} type with no return value. \subsection{\{ \} (statement block)} \index{\{ \}} \index{statement block} This is the statement block with zero or more statements enclosed within brackets. The following is the general syntax: \begin{vindent} \begin{verbatim} { STMT1 STMT2 ... } \end{verbatim} \end{vindent} The statement block executes each statement in sequence in the block. Separators or terminators are generally not necessary between statements. The statement block uses the same syntax and semantics as in C. \subsection{while} \index{while} General syntax: \begin{vindent} \begin{verbatim} while (EXP) STMT \end{verbatim} \end{vindent} The \texttt{while} statement uses the same syntax and semantics as in C. In the statement above, while the integer-valued EXP evaluates to non-zero, the parser will execute STMT. \section{Associative arrays\label{sec:Associative-Arrays}} \index{associative arrays} Associative arrays are implemented as hash tables with a maximum size set at startup. Associative arrays are too large to be created dynamically for individual probe handler runs, so they must be declared as global. The basic operations for arrays are setting and looking up elements. These operations are expressed in awk syntax: the array name followed by an opening bracket ({[}), a comma-separated list of up to nine index index expressions, and a closing bracket (]). Each index expression may be a string or a number, as long as it is consistently typed throughout the script. \subsection{Examples} \begin{vindent} \begin{verbatim} # Increment the named array slot: foo [4,"hello"] ++ # Update a statistic: processusage [uid(),execname()] ++ # Set a timestamp reference point: times [tid()] = get_cycles() # Compute a timestamp delta: delta = get_cycles() - times [tid()] \end{verbatim} \end{vindent} \subsection{Types of values} Array elements may be set to a number, a string, or an aggregate. The type must be consistent throughout the use of the array. The first assignment to the array defines the type of the elements. Unset array elements may be fetched and return a null value (zero or empty string) as appropriate, but they are not seen by a membership test. \subsection{Array capacity} Array sizes can be specified explicitly or allowed to default to the maximum size as defined by MAXMAPENTRIES. See Section~\ref{sub:SystemTap-safety} for details on changing MAXMAPENTRIES. You can explicitly specify the size of an array as follows: \begin{vindent} \begin{verbatim} global ARRAY[] \end{verbatim} \end{vindent} If you do not specify the size parameter, then the array is created to hold MAXMAPENTRIES number of elements. \subsection{Array wrapping\label{sub:Array-Wrapping}} Arrays may be wrapped using the percentage symbol (\%) causing previously entered elements to be overwritten if more elements are inserted than the array can hold. This works for both regular and statistics typed arrays. You can mark arrays for wrapping as follows: \begin{vindent} \begin{verbatim} global ARRAY1%[], ARRAY2% \end{verbatim} \end{vindent} \subsection{Iteration, foreach} \index{foreach} Like awk, SystemTap's foreach creates a loop that iterates over key tuples of an array, not only values. The iteration may be sorted by any single key or a value by adding an extra plus symbol (+) or minus symbol (-) to the code or limited to only a few elements with the limit keyword. The following are examples. \begin{vindent} \begin{verbatim} # Simple loop in arbitrary sequence: foreach ([a,b] in foo) fuss_with(foo[a,b]) # Loop in increasing sequence of value: foreach ([a,b] in foo+) { ... } # Loop in decreasing sequence of first key: foreach ([a-,b] in foo) { ... } # Print the first 10 tuples and values in the array in decreasing sequence foreach (v = [i,j] in foo- limit 10) printf("foo[%d,%s] = %d\n", i, j, v) \end{verbatim} \end{vindent} The \texttt{break} and \texttt{continue} statements also work inside foreach loops. Since arrays can be large but probe handlers must execute quickly, you should write scripts that exit iteration early, if possible. For simplicity, SystemTap forbids any modification of an array during iteration with a foreach. For a full description of \texttt{foreach} see subsection \ref{sub:foreach}. \subsection{Deletion} \index{delete} The \texttt{delete} statement can either remove a single element by index from an array or clear an entire array at once. See subsection \ref{sub:delete} for details and examples. \section{Statistics (aggregates)\label{sec:Statistics}} \index{aggregates} Aggregate instances are used to collect statistics on numerical values, when it is important to accumulate new data quickly and in large volume. These instances operate without exclusive locks, and store only aggregated stream statistics. Aggregates make sense only for global variables. They are stored individually or as elements of an associative array. For information about wrapping associative arrays with statistics elements, see section~\ref{sub:Array-Wrapping} \subsection{The aggregation (\textless\hspace{1 sp}\textless\hspace{1 sp}\textless) operator} \index{\textless\hspace{1 sp}\textless\hspace{1 sp}\textless} The aggregation operator is {}``\textless\hspace{1 sp}\textless\hspace{1 sp}\textless'', and its effect is similar to an assignment or a C++ output streaming operation. The left operand specifies a scalar or array-index \emph{l-value}, which must be declared global. The right operand is a numeric expression. The meaning is intuitive: add the given number as a sample to the set of numbers to compute their statistics. The specific list of statistics to gather is given separately by the extraction functions. The following is an example. \begin{vindent} \begin{verbatim} a <<< delta_timestamp writes[execname()] <<< count \end{verbatim} \end{vindent} \subsection{Extraction functions} \index{extraction} For each instance of a distinct extraction function operating on a given identifier, the translator computes a set of statistics. With each execution of an extraction function, the aggregation is computed for that moment across all processors. The first argument of each function is the same style of l-value as used on the left side of the aggregation operation. \subsection{Integer extractors} The following functions provide methods to extract information about aggregate. \subsubsection{@count(s)} \index{count} This statement returns the number of samples accumulated in aggregate s. \subsubsection{@sum(s)} \index{sum} This statement returns the total sum of all samples in aggregate s. \subsubsection{@min(s)} \index{min} This statement returns the minimum of all samples in aggregate s. \subsubsection{@max(s)} \index{max} This statement returns the maximum of all samples in aggregate s. \subsubsection{@avg(s)} \index{avg} This statement returns the average value of all samples in aggregate s. \subsection{Histogram extractors} \index{histograms} The following functions provide methods to extract histogram information. Printing a histogram with the print family of functions renders a histogram object as a tabular "ASCII art" bar chart. \subsubsection{@hist\_linear} \index{hist\_linear} The statement \texttt{@hist\_linear(v,L,H,W)} represents a linear histogram of aggregate \texttt{v}, where \emph{L} and \emph{H} represent the lower and upper end of a range of values and \emph{W} represents the width (or size) of each bucket within the range. The low and high values can be negative, but the overall difference (high minus low) must be positive. The width parameter must also be positive. In the output, a range of consecutive empty buckets may be replaced with a tilde (\textasciitilde{}) character. This can be controlled on the command line with -DHIST\_ELISION=\textless\hspace{1 sp}num\textgreater\hspace{1 sp}, where \textless\hspace{1 sp}num\textgreater\hspace{1 sp} specifies how many empty buckets at the top and bottom of the range to print. The default is 2. A \textless\hspace{1 sp}num\textgreater\hspace{1 sp} of 0 removes all empty buckets. A negative \textless\hspace{1 sp}num\textgreater\hspace{1 sp} disables removal. For example, if you specify -DHIST\_ELISION=3 and the histogram has 10 consecutive empty buckets, the first 3 and last 3 empty buckets will be printed and the middle 4 empty buckets will be represented by a tilde (\textasciitilde{}). The following is an example. \begin{vindent} \begin{verbatim} global reads probe netdev.receive { reads <<< length } probe end { print(@hist_linear(reads, 0, 10240, 200)) } \end{verbatim} \end{vindent} This generates the following output. \begin{samepage} \begin{vindent} \begin{verbatim} value |-------------------------------------------------- count 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1650 200 | 8 400 | 0 600 | 0 ~ 1000 | 0 1200 | 0 1400 | 1 1600 | 0 1800 | 0 \end{verbatim} \end{vindent} \end{samepage} This shows that 1650 network reads were of a size between 0 and 199 bytes, 8 reads were between 200 and 399 bytes, and 1 read was between 1200 and 1399 bytes. The tilde (\textasciitilde{}) character indicates the bucket for 800 to 999 bytes was removed because it was empty. Empty buckets for 2000 bytes and larger were also removed because they were empty. \subsubsection{@hist\_log} \index{hist\_log} The statement \texttt{@hist\_log(v)} represents a base-2 logarithmic histogram. Empty buckets are replaced with a tilde (\textasciitilde{}) character in the same way as \texttt{@hist\_linear()} (see above). The following is an example. \begin{vindent} \begin{verbatim} global reads probe netdev.receive { reads <<< length } probe end { print(@hist_log(reads)) } \end{verbatim} \end{vindent} This generates the following output. \begin{samepage} \begin{vindent} \begin{verbatim} value |-------------------------------------------------- count 8 | 0 16 | 0 32 | 254 64 | 3 128 | 2 256 | 2 512 | 4 1024 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 16689 2048 | 0 4096 | 0 \end{verbatim} \end{vindent} \end{samepage} \subsection{Deletion} \index{delete} The \texttt{delete} statement (subsection \ref{sub:delete}) applied to an aggregate variable will reset it to the initial empty state. \section{Formatted output} \subsection{print} \index{print} General syntax: \begin{vindent} \begin{verbatim} print () \end{verbatim} \end{vindent} This function prints a single value of any type. \subsection{printf} \index{printf} General syntax: \begin{vindent} \begin{verbatim} printf (fmt:string, ...) \end{verbatim} \end{vindent} The printf function takes a formatting string as an argument, and a number of values of corresponding types, and prints them all. The format must be a literal string constant. The printf formatting directives are similar to those of C, except that they are fully checked for type by the translator. The formatting string can contain tags that are defined as follows: \begin{vindent} \begin{verbatim} %[flags][width][.precision][length]specifier \end{verbatim} \end{vindent} Where \texttt{specifier} is required and defines the type and the interpretation of the value of the corresponding argument. The following table shows the details of the specifier parameter: \begin{table}[H] \caption{printf specifier values} \begin{tabular}{|>{\raggedright}p{1in}|>{\raggedright}p{3.5in}|>{\raggedright}p{1.25in}|} \hline \textbf{Specifier}& \textbf{Output}& \textbf{Example}\tabularnewline \hline \hline d or i& Signed decimal& 392\tabularnewline \hline o& Unsigned octal& 610\tabularnewline \hline s& String& sample\tabularnewline \hline u& Unsigned decimal& 7235\tabularnewline \hline x& Unsigned hexadecimal (lowercase letters)& 7fa\tabularnewline \hline X& Unsigned hexadecimal (uppercase letters)& 7FA\tabularnewline \hline p& Pointer address& 0x0000000000bc614e\tabularnewline \hline b& Writes a binary value as text using the computer's native byte order. The field width specifies the number of bytes to write. Valid specifications are \%b, \%1b, \%2b, \%4b and \%8b. The default width is 8 (64-bits).& See below\tabularnewline \hline \%& A \% followed by another \% character will write \% to stdout.& \%\tabularnewline \hline \end{tabular} \end{table} The tag can also contain \texttt{flags}, \texttt{width}, \texttt{.precision} and \texttt{modifiers} sub-specifiers, which are optional and follow these specifications: \begin{table}[H] \caption{printf flag values} \begin{tabular}{|>{\raggedright}p{1.5in}|>{\raggedright}p{4.5in}|} \hline \textbf{Flags}& \textbf{Description}\tabularnewline \hline \hline - (minus sign)& Left-justify within the given field width. Right justification is the default (see \texttt{width} sub-specifier).\tabularnewline \hline + (plus sign)& Precede the result with a plus or minus sign even for positive numbers. By default, only negative numbers are preceded with a minus sign.\tabularnewline \hline (space)& If no sign is going to be written, a blank space is inserted before the value.\tabularnewline \hline \#& Used with \texttt{o}, \texttt{x} or \texttt{X} specifiers the value is preceded with \texttt{0}, \texttt{0x} or \texttt{0X} respectively for non-zero values.\tabularnewline \hline 0& Left-pads the number with zeroes instead of spaces, where padding is specified (see \texttt{width} sub-specifier).\tabularnewline \hline \end{tabular} \end{table} \begin{table}[H] \caption{printf width values} \begin{tabular}{|>{\raggedright}p{1.5in}|>{\raggedright}p{4.5in}|} \hline \textbf{Width}& \textbf{Description}\tabularnewline \hline \hline (number)& Minimum number of characters to be printed. If the value to be printed is shorter than this number, the result is padded with blank spaces. The value is not truncated even if the result is larger.\tabularnewline \hline \end{tabular} \end{table} % \begin{table}[H] \caption{printf precision values} \begin{tabular}{|>{\raggedright}p{1.5in}|>{\raggedright}p{4.5in}|} \hline \textbf{Precision}& \textbf{Description}\tabularnewline \hline \hline .number& For integer specifiers (\texttt{d, i, o, u, x, X}): \texttt{precision} specifies the minimum number of digits to be written. If the value to be written is shorter than this number, the result is padded with leading zeros. The value is not truncated even if the result is longer. A precision of 0 means that no character is written for the value 0. For s: this is the maximum number of characters to be printed. By default all characters are printed until the ending null character is encountered. When no \texttt{precision} is specified, the default is 1. If the period is specified without an explicit value for \texttt{precision}, 0 is assumed.\tabularnewline \hline \end{tabular} \end{table} \textbf{Binary Write Examples} The following is an example of using the binary write functions: \begin{vindent} \begin{verbatim} probe begin { for (i = 97; i < 110; i++) printf("%3d: %1b%1b%1b\n", i, i, i-32, i-64) exit() } \end{verbatim} \end{vindent} This prints: \begin{vindent} \begin{verbatim} 97: aA! 98: bB" 99: cC# 100: dD$ 101: eE% 102: fF& 103: gG' 104: hH( 105: iI) 106: jJ* 107: kK+ 108: lL, 109: mM- \end{verbatim} \end{vindent} Another example: \begin{vindent} \begin{verbatim} stap -e 'probe begin{printf("%b%b", 0xc0dedbad, \ 0x12345678);exit()}' | hexdump -C \end{verbatim} \end{vindent} This prints: \begin{vindent} \begin{verbatim} 00000000 ad db de c0 00 00 00 00 78 56 34 12 00 00 00 00 |........xV4.....| 00000010 \end{verbatim} \end{vindent} Another example: \begin{vindent} \begin{verbatim} probe begin{ printf("%1b%1b%1blo %1b%1brld\n", 72,101,108,87,111) exit() } \end{verbatim} \end{vindent} This prints: \begin{vindent} \begin{verbatim} Hello World \end{verbatim} \end{vindent} \subsection{printd} \index{printd} General syntax: \begin{vindent} \begin{verbatim} printd (delimiter:string, ...) \end{verbatim} \end{vindent} This function takes a string delimiter and two or more values of any type, then prints the values with the delimiter interposed. The delimiter must be a literal string constant. For example: \begin{vindent} \begin{verbatim} printd("/", "one", "two", "three", 4, 5, 6) \end{verbatim} \end{vindent} prints: \begin{vindent} \begin{verbatim} one/two/three/4/5/6 \end{verbatim} \end{vindent} \subsection{printdln} \index{printdln} General syntax: \begin{vindent} \begin{verbatim} printdln (delimiter:string, ...) \end{verbatim} \end{vindent} This function operates like \texttt{printd}, but also appends a newline. \subsection{println} \index{println} General syntax: \begin{vindent} \begin{verbatim} println () \end{verbatim} \end{vindent} This function prints a single value like \texttt{print}, but also appends a newline. \subsection{sprint} \index{sprint} General syntax: \begin{vindent} \begin{verbatim} sprint:string () \end{verbatim} \end{vindent} This function operates like \texttt{print}, but returns the string rather than printing it. \subsection{sprintf} \index{sprintf} General syntax: \begin{vindent} \begin{verbatim} sprintf:string (fmt:string, ...) \end{verbatim} \end{vindent} This function operates like \texttt{printf}, but returns the formatted string rather than printing it. \section{Tapset-defined functions\label{sec:Predefined-Functions}} Unlike built-in functions, tapset-defined functions are implemented in tapset scripts. These are individually documented in the in \texttt{tapset::*(3stap)}, \texttt{function::*(3stap)}, and \texttt{probe::*(3stap)} man pages, and implemented under \texttt{/usr/share/systemtap/tapset}. \section{For Further Reference\label{sec:For-Further-Reference}} For more information, see: \begin{itemize} \item The SystemTap tutorial at \url{http://sourceware.org/systemtap/tutorial/} \item The SystemTap wiki at \url{http://sourceware.org/systemtap/wiki} \item The SystemTap documentation page at \url{http://sourceware.org/systemtap/documentation.html} \item From an unpacked source tarball or GIT directory, the examples in in the src/examples directory, the tapsets in the src/tapset directory, and the test scripts in the src/testsuite directory. \item The man pages for tapsets. For a list, run the command \texttt{{}``man -k tapset::}''. \item The man pages for individual probe points. For a list, run the command \texttt{{}``man -k probe::}''. \item The man pages for individual systemtap functions. For a list, run the command \texttt{{}``man -k function::}''. \end {itemize} \setcounter{secnumdepth}{0} \newpage{} \addcontentsline{toc}{section}{Index} \printindex{} \end{document} systemtap-2.3/doc/nomencl.sty000066400000000000000000000154751217430427200163660ustar00rootroot00000000000000%% %% This is file `nomencl.sty', %% generated with the docstrip utility. %% %% The original source files were: %% %% nomencl.dtx (with options: `package') %% %% Copyright 1996 Boris Veytsman %% Copyright 1999-2001 Bernd Schandl %% www http://sarovar.org/projects/nomencl %% %% This file can be redistributed and/or modified under the terms %% of the LaTeX Project Public License distributed from CTAN %% archives in the directory macros/latex/base/lppl.txt; either %% version 1.2 of the license, or (at your option) any later version. %% %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z %% Digits \0\1\2\3\4\5\6\7\8\9 %% Exclamation \! Double quote \" Hash (number) \# %% Dollar \$ Percent \% Ampersand \& %% Acute accent \' Left paren \( Right paren \) %% Asterisk \* Plus \+ Comma \, %% Minus \- Point \. Solidus \/ %% Colon \: Semicolon \; Less than \< %% Equals \= Greater than \> Question mark \? %% Commercial at \@ Left bracket \[ Backslash \\ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} %% \ProvidesPackage{nomencl}% [2005/09/22 v4.2 Nomenclature package (LN)] \NeedsTeXFormat{LaTeX2e} \newif\if@printeqref \newif\if@printpageref \newif\if@intoc \newif\if@compatibilitymode \DeclareOption{refeq}{\@printeqreftrue} \DeclareOption{norefeq}{\@printeqreffalse} \DeclareOption{refpage}{\@printpagereftrue} \DeclareOption{norefpage}{\@printpagereffalse} \DeclareOption{intoc}{\@intoctrue} \DeclareOption{notintoc}{\@intocfalse} \DeclareOption{compatible}{\@compatibilitymodetrue} \DeclareOption{noncompatible}{\@compatibilitymodefalse} \DeclareOption{prefix}{\def\nomprefix{a}} \DeclareOption{noprefix}{\def\nomprefix{}} \newif\if@loadcfg \DeclareOption{cfg}{\@loadcfgtrue} \DeclareOption{nocfg}{\@loadcfgfalse} \DeclareOption{croatian}{% \def\eqdeclaration#1{, vidi jednad\v{z}bu\nobreakspace(#1)}% \def\pagedeclaration#1{, stranica\nobreakspace#1}% \def\nomname{Popis simbola}} \DeclareOption{danish}{% \def\eqdeclaration#1{, se ligning\nobreakspace(#1)}% \def\pagedeclaration#1{, side\nobreakspace#1}% \def\nomname{Symbolliste}} \DeclareOption{english}{% \def\eqdeclaration#1{, see equation\nobreakspace(#1)}% \def\pagedeclaration#1{, page\nobreakspace#1}% \def\nomname{Nomenclature}} \DeclareOption{french}{% \def\eqdeclaration#1{, voir \'equation\nobreakspace(#1)}% \def\pagedeclaration#1{, page\nobreakspace#1}% \def\nomname{Liste des symboles}} \DeclareOption{german}{% \def\eqdeclaration#1{, siehe Gleichung\nobreakspace(#1)}% \def\pagedeclaration#1{, Seite\nobreakspace#1}% \def\nomname{Symbolverzeichnis}} \DeclareOption{italian}{% \def\eqdeclaration#1{, vedi equazione\nobreakspace(#1)}% \def\pagedeclaration#1{, pagina\nobreakspace#1}% \def\nomname{Elenco dei simboli}} \DeclareOption{polish}{% \def\eqdeclaration#1{, porownaj rownanie\nobreakspace(#1)}% \def\pagedeclaration#1{, strona\nobreakspace#1}% \def\nomname{Lista symboli}} \DeclareOption{portuguese}{% \def\eqdeclaration#1{, veja equa\c{c}\~ao\nobreakspace(#1)}% \def\pagedeclaration#1{, p\'agina\nobreakspace#1}% \def\nomname{Nomenclatura}} \DeclareOption{russian}{% \def\eqdeclaration#1{, \cyrs\cyrm.\nobreakspace(#1)}% \def\pagedeclaration#1{, \cyrs\cyrt\cyrr.\nobreakspace#1}% \def\nomname{\CYRS\cyrp\cyri\cyrs\cyro\cyrk% \ \cyro\cyrb\cyro\cyrz\cyrn\cyra\cyrch\cyre\cyrn\cyri% \cyrishrt}} \DeclareOption{spanish}{% \def\eqdeclaration#1{, v\'ease la ecuaci\'on\nobreakspace(#1)}% \def\pagedeclaration#1{, p\'agina\nobreakspace#1}% \def\nomname{Nomenclatura}} \DeclareOption{ukrainian}{% \def\eqdeclaration#1{, \cyrd\cyri\cyrv.\nobreakspace(#1)}% \def\pagedeclaration#1{, \cyrs\cyrt\cyro\cyrr.\nobreakspace#1}% \def\nomname{\CYRP\cyre\cyrr\cyre\cyrl\cyrii\cyrk% \ \cyrp\cyro\cyrz\cyrn\cyra\cyrch\cyre\cyrn\cyrsftsn}} \ExecuteOptions{noncompatible,notintoc,norefeq,norefpage,prefix,cfg,english} \ProcessOptions\relax \if@compatibilitymode% \def\@outputfileextension{.glo}% \def\@inputfileextension{.gls}% \else% \def\@outputfileextension{.nlo}% \def\@inputfileextension{.nls}% \fi% \def\makenomenclature{% \newwrite\@nomenclaturefile \immediate\openout\@nomenclaturefile=\jobname\@outputfileextension \def\@nomenclature{% \@bsphack \begingroup \@sanitize \@ifnextchar[% {\@@@nomenclature}{\@@@nomenclature[\nomprefix]}}% \typeout{Writing nomenclature file \jobname\@outputfileextension}% \let\makenomenclature\@empty} \if@compatibilitymode\let\makeglossary\makenomenclature\fi% \def\nom@verb{\expandafter\strip@prefix\meaning} \def\nomenclature{\protect\@nomenclature} \def\@nomenclature{% \@bsphack \begingroup \@sanitize \@ifnextchar[% {\@@nomenclature}{\@@nomenclature[\nomprefix]}} \def\@@nomenclature[#1]#2#3{\endgroup\@esphack} \def\@@@nomenclature[#1]#2#3{% \def\@tempa{#2}\def\@tempb{#3}% \protected@write\@nomenclaturefile{}% {\string\nomenclatureentry{#1\nom@verb\@tempa @[{\nom@verb\@tempa}]% \begingroup\nom@verb\@tempb\protect\nomeqref{\theequation}% |nompageref}{\thepage}}% \endgroup \@esphack} \def\nomgroup#1{} \newdimen\nomlabelwidth \nomlabelwidth1cm\relax \newdimen\nom@tempdim \def\printnomenclature{% \@ifnextchar[% {\@printnomenclature}{\@printnomenclature[\nomlabelwidth]}} \def\@printnomenclature[#1]{% \nom@tempdim#1\relax \@input@{\jobname\@inputfileextension}} \if@compatibilitymode\let\printglossary\printnomenclature\fi% \def\nomlabel#1{#1\hfil} \def\nompreamble{} \def\nompostamble{} \def\nomentryend{} \newskip\nomitemsep \nomitemsep\itemsep \def\thenomenclature{% \@ifundefined{chapter}% { \section*{\nomname} \if@intoc\addcontentsline{toc}{section}{\nomname}\fi% }% { \chapter*{\nomname} \if@intoc\addcontentsline{toc}{chapter}{\nomname}\fi% }% \nompreamble \list{}{% \labelwidth\nom@tempdim \leftmargin\labelwidth \advance\leftmargin\labelsep \itemsep\nomitemsep \let\makelabel\nomlabel}} \def\endthenomenclature{% \endlist \nompostamble} \def\nomrefeq{\@printeqreftrue} \def\nomrefpage{\@printpagereftrue} \def\nomrefeqpage{\@printeqreftrue\@printpagereftrue} \def\nomnorefeq{\@printeqreffalse} \def\nomnorefpage{\@printpagereffalse} \def\nomnorefeqpage{\@printeqreffalse\@printpagereffalse} \def\nomeqref#1{\if@printeqref\eqdeclaration{#1}\fi\ignorespaces} \def\nompageref#1{\if@printpageref\pagedeclaration{#1}\fi% \nomentryend\endgroup} \if@loadcfg \InputIfFileExists{nomencl.cfg}{% \typeout{Using the configuration file nomencl.cfg}}{} \fi \endinput %% %% End of file `nomencl.sty'. systemtap-2.3/doc/tutorial.tex000066400000000000000000001473061217430427200165560ustar00rootroot00000000000000% Copyright (C) 2005-2010 Red Hat Inc. % This file is part of systemtap, and is free software. You can % redistribute it and/or modify it under the terms of the GNU General % Public License (GPL); either version 2, or (at your option) any % later version. \documentclass{article} \usepackage{html} \usepackage{graphicx} % \usepackage{moreverb} \usepackage{fancyvrb} \usepackage{listings} \usepackage{fullpage} \usepackage{fancybox} \usepackage[compatible]{nomencl} % \usepackage{geometry} % \geometry{letterpaper,text={7in,8.5in}} \usepackage{charter} \newenvironment{boxedminipage}%% Boxed minipage {\begin{makeimage}\begin{center}\begin{Sbox}\begin{minipage}}% {\end{minipage}\end{Sbox}\fbox{\TheSbox}\end{center}\end{makeimage}} \begin{htmlonly} \renewcommand{\nomenclature}[2]{} \end{htmlonly} % \usepackage{draftcopy} % ugly \bibliographystyle{plain} \makeglossary \parindent0.0cm \parskip0.2cm \begin{document} \begin{center} \LARGE {\bf Systemtap tutorial} \end{center} \hfill \begin{minipage}{2.5in} % contributors please add your names to the list Frank Ch. Eigler {\tt \small } \\ \hfill \today \end{minipage} \tableofcontents \section{Introduction} Systemtap is a tool that allows developers and administrators to write and reuse simple scripts to deeply examine the activities of a live Linux system. Data may be extracted, filtered, and summarized quickly and safely, to enable diagnoses of complex performance or functional problems. {\bf NOTE:} This tutorial does not describe every feature available in systemtap. Please see the individual {\verb+stap+} manual pages for the most up-to-date information. These may be available installed on your system, or at \verb+http://sourceware.org/systemtap/man/+. \nomenclature{script}{A simple programming language understood by systemtap.} The essential idea behind a systemtap script is to name {\em events}, and to give them {\em handlers}. Whenever a specified event occurs, the Linux kernel runs the handler as if it were a quick subroutine, then resumes. There are several kind of events, such as entering or exiting a function, a timer expiring, or the entire systemtap session starting or stopping. A handler is a series of script language statements that specify the work to be done whenever the event occurs. This work normally includes extracting data from the event context, storing them into internal variables, or printing results. \nomenclature{event}{An identifiable instant in the operating system's execution state, such as entry to a function, or expiry of a timer.} \nomenclature{session}{A complete run of a systemtap script program.} \nomenclature{handler}{A series of statements, written in script, which is to be performed whenever an event occurs.} \nomenclature{\tt .stp}{The standard file name extension for systemtap scripts.} Systemtap works by translating the script to C, running the system C compiler to create a kernel module from that. When the module is loaded, it activates all the probed events by hooking into the kernel. Then, as events occur on any processor, the compiled handlers run. Eventually, the session stops, the hooks are disconnected, and the module removed. This entire process is driven from a single command-line program, \verb+stap+. \begin{figure}[!ht] \begin{boxedminipage}{4.5in} \begin{verbatim} # cat hello-world.stp probe begin { print ("hello world\n") exit () } # stap hello-world.stp hello world \end{verbatim} \end{boxedminipage} \label{fig:hello-world} \caption{A systemtap smoke test.} \end{figure} This paper assumes that you have installed systemtap and its prerequisite kernel development tools and debugging data, so that you can run the scripts such as the simple one in Figure~\ref{fig:hello-world}. Log on as \verb+root+, or even better, login as a user that is a member of \verb+stapdev+ group or as a user authorized to \verb+sudo+, before running systemtap. \begin{figure}[ht] \begin{boxedminipage}{4.5in} \begin{verbatim} # cat strace-open.stp probe syscall.open { printf ("%s(%d) open (%s)\n", execname(), pid(), argstr) } probe timer.ms(4000) # after 4 seconds { exit () } # stap strace-open.stp vmware-guestd(2206) open ("/etc/redhat-release", O_RDONLY) hald(2360) open ("/dev/hdc", O_RDONLY|O_EXCL|O_NONBLOCK) hald(2360) open ("/dev/hdc", O_RDONLY|O_EXCL|O_NONBLOCK) hald(2360) open ("/dev/hdc", O_RDONLY|O_EXCL|O_NONBLOCK) df(3433) open ("/etc/ld.so.cache", O_RDONLY) df(3433) open ("/lib/tls/libc.so.6", O_RDONLY) df(3433) open ("/etc/mtab", O_RDONLY) hald(2360) open ("/dev/hdc", O_RDONLY|O_EXCL|O_NONBLOCK) \end{verbatim} \end{boxedminipage} \label{fig:strace-open} \caption{A taste of systemtap: a system-wide {\tt strace}, just for the {\tt open} system call.} \end{figure} \nomenclature{strace}{A standard ptrace-based command line tool to trace system call activity of a process.} \section{Tracing} The simplest kind of probe is simply to {\em trace} an event. \nomenclature{trace}{A compact textual record of an event occurrence.} This is the effect of inserting strategically located \verb+print+ statements into a program. This is often the first step of problem solving: explore by seeing a history of what has happened. This style of instrumentation is the simplest. It just asks systemtap to print something at each event. To express this in the script language, you need to say where to probe and what to print there. \subsection{Where to probe} Systemtap supports a number of built-in events. The library of scripts that comes with systemtap, each called a ``tapset'', may define additional ones defined in terms of the built-in family. {\bf See the \verb+stapprobes+ man page for details on these and many other probe point families.} \nomenclature{tapset}{A reusable script forming part of the automatically searched tapset library.} All these events are named using a unified syntax with dot-separated parameterized identifiers: \begin{tabular}{rl} \verb+begin+ & The startup of the systemtap session. \\ \verb+end+ & The end of the systemtap session. \\ \verb+kernel.function("sys_open")+ & The entry to the function named \verb+sys_open+ in the kernel. \\ \verb+syscall.close.return+ & The return from the \verb+close+ system call. \\ \verb+module("ext3").statement(0xdeadbeef)+ & The addressed instruction in the \verb+ext3+ filesystem driver. \\ \verb+timer.ms(200)+ & A timer that fires every 200 milliseconds. \\ \verb+timer.profile+ & A timer that fires periodically on every CPU. \\ \verb+perf.hw.cache_misses+ & A particular number of CPU cache misses have occurred. \\ \verb+procfs("status").read+ & A process trying to read a synthetic file. \\ \verb+process("a.out").statement("*@main.c:200")+ & Line 200 of the \verb+a.out+ program. \end{tabular} Let's say that you would like to trace all function entries and exits in a source file, say \verb+net/socket.c+ in the kernel. The \verb+kernel.function+ probe point lets you express that easily, since systemtap examines the kernel's debugging information to relate object code to source code. It works like a debugger: if you can name or place it, you can probe it. Use \verb+kernel.function("*@net/socket.c").call+ for the function entries\footnote{Without the {\tt .call} qualifier, inlined function instances are also probed, but they have no corresponding {\tt .return}.}, and \verb+kernel.function("*@net/socket.c").return+ for matching exits. Note the use of wildcards in the function name part, and the subsequent \verb+@FILENAME+ part. You can also put wildcards into the file name, and even add a colon (\verb+:+) and a line number, if you want to restrict the search that precisely. Since systemtap will put a separate probe in every place that matches a probe point, a few wildcards can expand to hundreds or thousands of probes, so be careful what you ask for. \nomenclature{debug information}{Data created by the compiler when the kernel or application was built, sometimes packaged into {\tt debuginfo} files, for use by a symbolic debugger.} \nomenclature{wildcard}{Presence of \verb+*+ globbing patterns in probe points.} Once you identify the probe points, the skeleton of the systemtap script appears. The \verb+probe+ keyword introduces a probe point, or a comma-separated list of them. The following \verb+{+ and \verb+}+ braces enclose the handler for all listed probe points. \begin{verbatim} probe kernel.function("*@net/socket.c") { } probe kernel.function("*@net/socket.c").return { } \end{verbatim} You can run this script as is, though with empty handlers there will be no output. Put the two lines into a new file. Run \verb+stap -v FILE+. Terminate it any time with \verb+^C+. (The \verb+-v+ option tells systemtap to print more verbose messages during its processing. Try the \verb+-h+ option to see more options.) \subsection{What to print} Since you are interested in each function that was entered and exited, a line should be printed for each, containing the function name. In order to make that list easy to read, systemtap should indent the lines so that functions called by other traced functions are nested deeper. To tell each single process apart from any others that may be running concurrently, systemtap should also print the process ID in the line. Systemtap provides a variety of such contextual data, ready for formatting. They usually appear as function calls within the handler, like you already saw in Figure~\ref{fig:strace-open}. {\bf See the \verb+function::*+ man pages for those functions and more defined in the tapset library}, but here's a sampling: \begin{tabular}{rl} \verb+tid()+ & The id of the current thread. \\ \verb+pid()+ & The process (task group) id of the current thread. \\ \verb+uid()+ & The id of the current user. \\ \verb+execname()+ & The name of the current process. \\ \verb+cpu()+ & The current cpu number. \\ \verb+gettimeofday_s()+ & Number of seconds since epoch. \\ \verb+get_cycles()+ & Snapshot of hardware cycle counter. \\ \verb+pp()+ & A string describing the probe point being currently handled. \\ \verb+ppfunc()+ & If known, the the function name in which this probe was placed. \\ \verb+$$vars+ & If available, a pretty-printed listing of all local variables in scope. \\ \verb+print_backtrace()+ & If possible, print a kernel backtrace. \\ \verb+print_ubacktrace()+ & If possible, print a user-space backtrace. \\ \end{tabular} The values returned may be strings or numbers. The \verb+print()+ built-in function accepts either as its sole argument. Or, you can use the C-style \verb+printf()+ built-in, whose formatting argument may include \verb+%s+ for a string, \verb+%d+ for a number. \verb+printf+ and other functions take comma-separated arguments. Don't forget a \verb+"\n"+ at the end. There exist more printing / formatting functions too. A particularly handy function in the tapset library is \verb+thread_indent+. Given an indentation delta parameter, it stores internally an indentation counter for each thread (\verb+tid()+), and returns a string with some generic trace data plus an appropriate number of indentation spaces. That generic data includes a timestamp (number of microseconds since the initial indentation for the thread), a process name and the thread id itself. It therefore gives an idea not only about what functions were called, but who called them, and how long they took. Figure~\ref{fig:socket-trace} shows the finished script. It lacks a call to the \verb+exit()+ function, so you need to interrupt it with \verb+^C+ when you want the tracing to stop. \begin{figure}[!ht] \begin{boxedminipage}{4.5in} \begin{verbatim} # cat socket-trace.stp probe kernel.function("*@net/socket.c").call { printf ("%s -> %s\n", thread_indent(1), ppfunc()) } probe kernel.function("*@net/socket.c").return { printf ("%s <- %s\n", thread_indent(-1), ppfunc()) } # stap socket-trace.stp 0 hald(2632): -> sock_poll 28 hald(2632): <- sock_poll [...] 0 ftp(7223): -> sys_socketcall 1159 ftp(7223): -> sys_socket 2173 ftp(7223): -> __sock_create 2286 ftp(7223): -> sock_alloc_inode 2737 ftp(7223): <- sock_alloc_inode 3349 ftp(7223): -> sock_alloc 3389 ftp(7223): <- sock_alloc 3417 ftp(7223): <- __sock_create 4117 ftp(7223): -> sock_create 4160 ftp(7223): <- sock_create 4301 ftp(7223): -> sock_map_fd 4644 ftp(7223): -> sock_map_file 4699 ftp(7223): <- sock_map_file 4715 ftp(7223): <- sock_map_fd 4732 ftp(7223): <- sys_socket 4775 ftp(7223): <- sys_socketcall [...] \end{verbatim} \end{boxedminipage} \caption{Tracing and timing functions in {\tt net/sockets.c}.} \label{fig:socket-trace} \end{figure} \subsection{Exercises} \begin{enumerate} \item Use the \verb+-L+ option to systemtap to list all the kernel functions named with the word ``nit'' in them. \item Trace some system calls (use \verb+syscall.NAME+ and \verb+.return+ probe points), with the same \verb+thread_indent+ probe handler as in Figure~\ref{fig:socket-trace}. Print parameters using \verb+$$parms+ and \verb+$$return+. Interpret the results. \item Change figure~\ref{fig:socket-trace} by removing the \verb+.call+ modifier from the first probe. Note how function entry and function return now don't match anymore. This is because now the first probe will match both normal function entry and inlined functions. Try putting the \verb+.call+ modifier back and add another probe just for \verb+probe kernel.function("*@net/socket.c").return+ What \verb+printf+ statement can you come up with in the probe handler to show the inlined function entries nicely in between the \verb+.call+ and \verb+.return+ thread indented output? \end{enumerate} \section{Analysis} Pages of generic tracing text may give you enough information for exploring a system. With systemtap, it is possible to analyze that data, to filter, aggregate, transform, and summarize it. Different probes can work together to share data. Probe handlers can use a rich set of control constructs to describe algorithms, with a syntax taken roughly from \verb+awk+. With these tools, systemtap scripts can focus on a specific question and provide a compact response: no \verb+grep+ needed. \nomenclature{awk}{A classic UNIX stream processing language.} \subsection{Basic constructs} Most systemtap scripts include conditionals, to limit tracing or other logic to those processes or users or {\em whatever} of interest. The syntax is simple: \begin{tabular}{rl} \verb+if (+{\em EXPR}\verb+)+ {\em STATEMENT} [\verb+else+ {\em STATEMENT}\verb+]+ & if/else statement \\ \verb+while (+{\em EXPR}\verb+)+ {\em STATEMENT} & while loop \\ \verb+for (+{\em A}\verb+;+ {\em B}\verb+;+ {\em C}\verb+)+ {\em STATEMENT} & for loop \\ \end{tabular} Scripts may use \verb+break+/\verb+continue+ as in C. Probe handlers can return early using \verb+next+ as in \verb+awk+. Blocks of statements are enclosed in \verb+{+ and \verb+}+. In systemtap, the semicolon (\verb+;+) is accepted as a null statement rather than as a statement terminator, so is only rarely\footnote{Use them between consecutive expressions that place unary {\tt +},{\tt -} or mixed pre/post {\tt ++},{\tt --} in an ambiguous manner.} necessary. Shell-style (\verb+#+), C-style (\verb+/* */+), and C++-style (\verb+//+) comments are all accepted. Expressions look like C or \verb+awk+, and support the usual operators, precedences, and numeric literals. Strings are treated as atomic values rather than arrays of characters. String concatenation is done with the dot (\verb+"a" . "b"+). Some examples: \begin{tabular}{rl} \verb+(uid() > 100)+ & probably an ordinary user \\ \verb+(execname() == "sed")+ & current process is sed \\ \verb+(cpu() == 0 && gettimeofday_s() > 1140498000)+ & after Feb. 21, 2006, on CPU 0 \\ \verb+"hello" . " " . "world"+ & a string in three easy pieces \\ \end{tabular} Variables may be used as well. Just pick a name, assign to it, and use it in expressions. They are automatically initialized and declared. The type of each identifier -- string vs. number -- is automatically inferred by systemtap from the kinds of operators and literals used on it. Any inconsistencies will be reported as errors. Conversion between string and number types is done through explicit function calls. \nomenclature{type}{A designation of each identifier such as a variable, or function, or array value or index, as containing a string or number.} \nomenclature{string}{A \verb+\0+-terminated character string of up to a fixed limit in length.} \nomenclature{number}{A 64-bit signed integer.} \nomenclature{type inference}{The automatic determination of the type of each variable, function parameter, array value and index, based on their use.} \begin{tabular}{rl} \verb+foo = gettimeofday_s()+ & foo is a number \\ \verb+bar = "/usr/bin/" . execname()+ & bar is a string \\ \verb|c++| & c is a number \\ \verb+s = sprint(2345)+ & s becomes the string "2345" \\ \end{tabular} By default, variables are local to the probe they are used in. That is, they are initialized, used, and disposed of at each probe handler invocation. To share variables between probes, declare them global anywhere in the script. Because of possible concurrency (multiple probe handlers running on different CPUs), each global variable used by a probe is automatically read- or write-locked while the handler is running. \nomenclature{global variable}{A scalar, array, or aggregate that was named in a \verb+global+ declaration, sharing that object amongst all probe handlers and functions executed during a systemtap session.} \nomenclature{locking}{An automated facility used by systemtap to protect global variables against concurrent modification and/or access.} \begin{figure}[!ht] \begin{boxedminipage}{4.5in} \begin{verbatim} # cat timer-jiffies.stp global count_jiffies, count_ms probe timer.jiffies(100) { count_jiffies ++ } probe timer.ms(100) { count_ms ++ } probe timer.ms(12345) { hz=(1000*count_jiffies) / count_ms printf ("jiffies:ms ratio %d:%d => CONFIG_HZ=%d\n", count_jiffies, count_ms, hz) exit () } # stap timer-jiffies.stp jiffies:ms ratio 30:123 => CONFIG_HZ=243 \end{verbatim} \end{boxedminipage} \caption{Experimentally measuring {\tt CONFIG\_HZ}.} \label{fig:timer-jiffies} \end{figure} \subsection{Target variables} A class of special ``target variables'' allow access to the probe point context. \nomenclature{target variable}{A value that may be extracted from the kernel context of the probe point, such as a parameter or local variable within a probed function.} In a symbolic debugger, when you're stopped at a breakpoint, you can print values from the program's context. In systemtap scripts, for those probe points that match with specific executable point (rather than an asynchronous event like a timer), you can do the same. In addition, you can take their address (the \verb+&+ operator), pretty-print structures (the \verb+$+ and \verb+$$+ suffix), pretty-print multiple variables in scope (the \verb+$$vars+ and related variables), or cast pointers to their types (the \verb+@cast+ operator), or test their existence / resolvability (the \verb+@defined+ operator). Read about these in the manual pages. To know which variables are likely to be available, you will need to be familiar with the kernel source you are probing. In addition, you will need to check that the compiler has not optimized those values into unreachable nonexistence. You can use \verb+stap -L PROBEPOINT+ to enumerate the variables available there. Let's say that you are trying to trace filesystem reads/writes to a particular device/inode. From your knowledge of the kernel, you know that two functions of interest could be \verb+vfs_read+ and \verb+vfs_write+. Each takes a \verb+struct file *+ argument, inside there is either a \verb+struct dentry *+ or \verb+struct path *+ which has a \verb+struct dentry *+. The \verb+struct dentry *+ contains a \verb+struct inode *+, and so on. Systemtap allows limited dereferencing of such pointer chains. Two functions, \verb+user_string+ and \verb+kernel_string+, can copy \verb+char *+ target variables into systemtap strings. Figure~\ref{fig:inode-watch} demonstrates one way to monitor a particular file (identifed by device number and inode number). The script selects the appropriate variants of \verb+dev_nr+ and\verb+inode_nr+ based on the kernel version. This example also demonstrates passing numeric command-line arguments (\verb+$1+ etc.) into scripts. %$ \begin{figure}[!ht] \begin{boxedminipage}{4.5in} \begin{verbatim} # cat inode-watch.stp probe kernel.function ("vfs_write"), kernel.function ("vfs_read") { if (@defined($file->f_path->dentry)) { dev_nr = $file->f_path->dentry->d_inode->i_sb->s_dev inode_nr = $file->f_path->dentry->d_inode->i_ino } else { dev_nr = $file->f_dentry->d_inode->i_sb->s_dev inode_nr = $file->f_dentry->d_inode->i_ino } if (dev_nr == ($1 << 20 | $2) # major/minor device && inode_nr == $3) printf ("%s(%d) %s 0x%x/%u\n", execname(), pid(), ppfunc(), dev_nr, inode_nr) } # stat -c "%D %i" /etc/crontab fd03 133099 # stap inode-watch.stp 0xfd 3 133099 more(30789) vfs_read 0xfd00003/133099 more(30789) vfs_read 0xfd00003/133099 \end{verbatim} % $ \end{boxedminipage} \caption{Watching for reads/writes to a particular file.} \label{fig:inode-watch} \end{figure} \subsection{Functions} Functions are conveniently packaged reusable software: it would be a shame to have to duplicate a complex condition expression or logging directive in every placed it's used. So, systemtap lets you define functions of your own. Like global variables, systemtap functions may be defined anywhere in the script. They may take any number of string or numeric arguments (by value), and may return a single string or number. The parameter types are inferred as for ordinary variables, and must be consistent throughout the program. Local and global script variables are available, but target variables are {\em not}. That's because there is no specific debugging-level context associated with a function. \nomenclature{function}{A clump of parametrized script statements that may be repeatedly and recursively called from probe handlers and other functions.} A function is defined with the keyword \verb+function+ followed by a name. Then comes a comma-separated formal argument list (just a list of variable names). The \verb+{ }+-enclosed body consists of any list of statements, including expressions that call functions. Recursion is possible, up to a nesting depth limit. Figure~\ref{fig:functions} displays function syntax. \begin{figure}[!ht] \begin{boxedminipage}{4.5in} \begin{verbatim} # Red Hat convention; see /etc/login.defs UID_MIN function system_uid_p (u) { return u < 500 } # kernel device number assembly macro function makedev (major,minor) { return major << 20 | minor } function trace_common () { printf("%d %s(%d)", gettimeofday_s(), execname(), pid()) # no return value necessary } function fibonacci (i) { if (i < 1) return 0 else if (i < 2) return 1 else return fibonacci(i-1) + fibonacci(i-2) } \end{verbatim} \end{boxedminipage} \caption{Some functions of dubious utility.} \label{fig:functions} \end{figure} \subsection{Arrays} Often, probes will want to share data that cannot be represented as a simple scalar value. Much data is naturally tabular in nature, indexed by some tuple of thread numbers, processor ids, names, time, and so on. Systemtap offers associative arrays for this purpose. These arrays are implemented as hash tables with a maximum size that is fixed at startup. Because they are too large to be created dynamically for inidividual probes handler runs, they must be declared as global. \nomenclature{array}{A global \verb+[+$k_1,k_2,\ldots,k_n\verb+]+\rightarrow value$ associative lookup table, with a string, number for each index; the value may be a string, number, or an aggregate.} \begin{tabular}{rl} \verb|global a| & declare global scalar or array variable \\ \verb|global b[400]| & declare array, reserving space for up to 400 tuples \\ \end{tabular} The basic operations for arrays are setting and looking up elements. These are expressed in \verb+awk+ syntax: the array name followed by an opening \verb+[+ bracket, a comma-separated list of index expressions, and a closing \verb+]+ bracket. Each index expression may be string or numeric, as long as it is consistently typed throughout the script. \nomenclature{arity}{Number of indexes to an array, or number of parameters to a function.} \begin{tabular}{rl} \verb|foo [4,"hello"] ++ | & increment the named array slot \\ \verb|processusage [uid(),execname()] ++| & update a statistic \\ \verb|times [tid()] = get_cycles()| & set a timestamp reference point \\ \verb|delta = get_cycles() - times [tid()]| & compute a timestamp delta \\ \end{tabular} Array elements that have not been set {\em may} be fetched, and return a dummy null value (zero or an empty string) as appropriate. However, assigning a null value does not delete the element: an explicit \verb|delete| statement is required. \nomenclature{null value}{A default initialized value for globals and array elements: a zero or an empty string, depending on type.} Systemtap provides syntactic sugar for these operations, in the form of explicit membership testing and deletion. \begin{tabular}{rl} \verb|if ([4,"hello"] in foo) { }| & membership test \\ \verb|delete times[tid()]| & deletion of a single element \\ \verb|delete times| & deletion of all elements \\ \end{tabular} One final and important operation is iteration over arrays. This uses the keyword \verb+foreach+. Like \verb+awk+, this creates a loop that {\em iterates over key tuples} of an array, not just {\em values}. In addition, the iteration may be {\em sorted} by any single key or the value by adding an extra \verb|+| or \verb|-| code. The \verb+break+ and \verb+continue+ statements work inside \verb+foreach+ loops, too. Since arrays can be large but probe handlers must not run for long, it is a good idea to exit iteration early if possible. The \verb+limit+ option in the \verb+foreach+ expression is one way. For simplicity, systemtap forbids any {\em modification} of an array while it is being iterated using a \verb+foreach+. \begin{tabular}{rp{0.4\textwidth}} \verb|foreach (x = [a,b] in foo) { fuss_with(x) }| & simple loop in arbitrary sequence \\ \verb|foreach ([a,b] in foo+ limit 5) { }| & loop in increasing sequence of value, stop after 5 \\ \verb|foreach ([a-,b] in foo) { }| & loop in decreasing sequence of first key \\ \end{tabular} \subsection{Aggregates} When we said above that values can only be strings or numbers, we lied a little. There is a third type: statistics aggregates, or aggregates for short. Instances of this type are used to collect statistics on numerical values, where it is important to accumulate new data quickly ({\em without} exclusive locks) and in large volume (storing only aggregated stream statistics). This type only makes sense for global variables, and may be stored individually or as elements of an array. \nomenclature{aggregate}{A special ``write-mostly'' data type used to efficiently store aggregated statistical values of a potentially huge data stream.} To add a value to a statistics aggregate, systemtap uses the special operator \verb+<<<+. Think of it like C++'s \verb+<<+ output streamer: the left hand side object accumulates the data sample given on the right hand side. This operation is efficient (taking a shared lock) because the aggregate values are kept separately on each processor, and are only aggregated across processors on request. \begin{verbatim} a <<< delta_timestamp writes[execname()] <<< count \end{verbatim} To read the aggregate value, special functions are available to extract a selected statistical function. {\em The aggregate value cannot be read by simply naming it as if it were an ordinary variable.} These operations take an exclusive lock on the respective globals, and should therefore be relatively rare. The simple ones are: \verb+@min+, \verb+@max+, \verb+@count+, \verb+@avg+, and \verb+@sum+, and evaluate to a single number. In addition, histograms of the data stream may be extracted using the \verb+@hist_log+ and \verb+@hist_linear+. These evaluate to a special sort of array that may at present\footnote{We anticipate support for indexing and looping using {\tt foreach} shortly.} only be printed. \nomenclature{extractor}{A function-like expression in a script that computes a single statistic for a given aggregate.} \begin{tabular}{rp{0.5\textwidth}} \verb+@avg(a)+ & the average of all the values accumulated into \verb+a+ \\ \verb+print(@hist_linear(a,0,100,10))+ & print an ``ascii art'' linear histogram of the same data stream, bounds $0 \ldots 100$, bucket width is $10$ \\ \verb|@count(writes["zsh"])| & the number of times ``zsh'' ran the probe handler \\ \verb+print(@hist_log(writes["zsh"]))+ & print an ``ascii art'' logarithmic histogram of the same data stream \\ \end{tabular} \subsection{Safety} \label{sec:safety} The full expressivity of the scripting language raises good questions of safety. Here is a set of Q\&A: \begin{description} \item{\bf What about infinite loops? recursion?} A probe handler is bounded in time. The C code generated by systemtap includes explicit checks that limit the total number of statements executed to a small number. A similar limit is imposed on the nesting depth of function calls. When either limit is exceeded, that probe handler cleanly aborts and signals an error. The systemtap session is normally configured to abort as a whole at that time. \item{\bf What about running out of memory?} No dynamic memory allocation whatsoever takes place during the execution of probe handlers. Arrays, function contexts, and buffers are allocated during initialization. These resources may run out during a session, and generally result in errors. \item{\bf What about locking?} If multiple probes seek conflicting locks on the same global variables, one or more of them will time out, and be aborted. Such events are tallied as ``skipped'' probes, and a count is displayed at session end. A configurable number of skipped probes can trigger an abort of the session. \item{\bf What about null pointers? division by zero?} The C code generated by systemtap translates potentially dangerous operations to routines that check their arguments at run time. These signal errors if they are invalid. Many arithmetic and string operations silently overflow if the results exceed representation limits. \item{\bf What about bugs in the translator? compiler?} While bugs in the translator, or the runtime layer certainly exist\footnote{See \tt http://sourceware.org/bugzilla}, our test suite gives some assurance. Plus, the entire generated C code may be inspected (try the \verb+-p3+ option). Compiler bugs are unlikely to be of any greater concern for systemtap than for the kernel as a whole. In other words, if it was reliable enough to build the kernel, it will build the systemtap modules properly too. \item{\bf Is that the whole truth?} In practice, there are several weak points in systemtap and the underlying kprobes system at the time of writing. Putting probes indiscriminately into unusually sensitive parts of the kernel (low level context switching, interrupt dispatching) has reportedly caused crashes in the past. We are fixing these bugs as they are found, and constructing a probe point ``blacklist'', but it is not complete. \nomenclature{blacklist}{A list of probe point patterns encoded into the translator or the kernel, where probing is prohibited for safety reasons.} \nomenclature{kprobes}{A breakpoint dispatching system for dynamic kernel probes, used by systemtap to implement some families of probe points.} \end{description} \subsection{Exercises} \begin{enumerate} \item Alter the last probe in \verb+timer-jiffies.stp+ to reset the counters and continue reporting instead of exiting. \item Write a script that, every ten seconds, displays the top five most frequent users of \verb+open+ system call during that interval. \item Write a script that experimentally measures the speed of the \verb+get_cycles()+ counter on each processor. \item Use any suitable probe point to get an approximate profile of process CPU usage: which processes/users use how much of each CPU. \end{enumerate} \section{Tapsets} After writing enough analysis scripts for yourself, you may become known as an expert to your colleagues, who will want to use your scripts. Systemtap makes it possible to share in a controlled manner; to build libraries of scripts that build on each other. In fact, all of the functions (\verb+pid()+, etc.) used in the scripts above come from tapset scripts like that. A ``tapset'' is just a script that designed for reuse by installation into a special directory. \subsection{Automatic selection} Systemtap attempts to resolve references to global symbols (probes, functions, variables) that are not defined within the script by a systematic search through the tapset library for scripts that define those symbols. Tapset scripts are installed under the default directory named \verb+/usr/share/systemtap/tapset+. A user may give additional directories with the \verb+-I DIR+ option. Systemtap searches these directories for script (\verb+.stp+) files. The search process includes subdirectories that are specialized for a particular kernel version and/or architecture, and ones that name only larger kernel families. Naturally, the search is ordered from specific to general, as shown in Figure~\ref{fig:tapset-search}. \nomenclature{tapset search path}{A list of subdirectories searched by systemtap for tapset scripts, allowing specialization by version architecture.} \begin{figure}[!ht] \begin{boxedminipage}{6in} \begin{verbatim} # stap -p1 -vv -e 'probe begin { }' > /dev/null Created temporary directory "/tmp/staplnEBh7" Searched '/usr/share/systemtap/tapset/2.6.15/i686/*.stp', match count 0 Searched '/usr/share/systemtap/tapset/2.6.15/*.stp', match count 0 Searched '/usr/share/systemtap/tapset/2.6/i686/*.stp', match count 0 Searched '/usr/share/systemtap/tapset/2.6/*.stp', match count 0 Searched '/usr/share/systemtap/tapset/i686/*.stp', match count 1 Searched '/usr/share/systemtap/tapset/*.stp', match count 12 Pass 1: parsed user script and 13 library script(s) in 350usr/10sys/375real ms. Running rm -rf /tmp/staplnEBh7 \end{verbatim} \end{boxedminipage} \caption{Listing the tapset search path.} \label{fig:tapset-search} \end{figure} When a script file is found that {\em defines} one of the undefined symbols, that {\em entire file} is added to the probing session being analyzed. This search is repeated until no more references can become satisfied. Systemtap signals an error if any are still unresolved. This mechanism enables several programming idioms. First, it allows some global symbols to be defined only for applicable kernel version/architecture pairs, and cause an error if their use is attempted on an inapplicable host. Similarly, the same symbol can be defined differently depending on kernels, in much the same way that different kernel \verb+include/asm/ARCH/+ files contain macros that provide a porting layer. Another use is to separate the default parameters of a tapset routine from its implementation. For example, consider a tapset that defines code for relating elapsed time intervals to process scheduling activities. The data collection code can be generic with respect to which time unit (jiffies, wall-clock seconds, cycle counts) it can use. It should have a default, but should not require additional run-time checks to let a user choose another. Figure~\ref{fig:tapset-default} shows a way. \begin{figure}[!ht] \begin{boxedminipage}{6in} \begin{verbatim} # cat tapset/time-common.stp global __time_vars function timer_begin (name) { __time_vars[name] = __time_value () } function timer_end (name) { return __time_value() - __time_vars[name] } # cat tapset/time-default.stp function __time_value () { return gettimeofday_us () } # cat tapset-time-user.stp probe begin { timer_begin ("bench") for (i=0; i<100; i++) ; printf ("%d cycles\n", timer_end ("bench")) exit () } function __time_value () { return get_ticks () } # override for greater precision \end{verbatim} \end{boxedminipage} \caption{Providing an overrideable default.} \label{fig:tapset-default} \end{figure} A tapset that exports only {\em data} may be as useful as ones that exports functions or probe point aliases (see below). Such global data can be computed and kept up-to-date using probes internal to the tapset. Any outside reference to the global variable would incidentally activate all the required probes. \subsection{Probe point aliases} \nomenclature{probe point alias}{A probe point that is defined in terms of another probe point.} Probe point aliases allow creation of new probe points from existing ones. This is useful if the new probe points are named to provide a higher level of abstraction. For example, the system-calls tapset defines probe point aliases of the form \verb+syscall.open+ etc., in terms of lower level ones like \verb+kernel.function("sys_open")+. Even if some future kernel renames \verb+sys_open+, the aliased name can remain valid. A probe point alias definition looks like a normal probe. Both start with the keyword \verb+probe+ and have a probe handler statement block at the end. But where a normal probe just lists its probe points, an alias creates a new name using the assignment (\verb+=+) operator. Another probe that names the new probe point will create an actual probe, with the handler of the alias {\em prepended}. This prepending behavior serves several purposes. It allows the alias definition to ``preprocess'' the context of the probe before passing control to the user-specified handler. This has several possible uses: \begin{tabular}{rl} \verb+if ($flag1 != $flag2) next+ & skip probe unless given condition is met \\ \verb+name = "foo"+ & supply probe-describing values \\ \verb+var = $var+ & extract target variable to plain local variable \\ %$ \end{tabular} Figure~\ref{fig:probe-alias} demonstrates a probe point alias definition as well as its use. It demonstrates how a single probe point alias can expand to multiple probe points, even to other aliases. It also includes probe point wildcarding. These functions are designed to compose sensibly. \begin{figure}[!ht] \begin{boxedminipage}{4.5in} \begin{verbatim} # cat probe-alias.stp probe syscallgroup.io = syscall.open, syscall.close, syscall.read, syscall.write { groupname = "io" } probe syscallgroup.process = syscall.fork, syscall.execve { groupname = "process" } probe syscallgroup.* { groups [execname() . "/" . groupname] ++ } probe end { foreach (eg+ in groups) printf ("%s: %d\n", eg, groups[eg]) } global groups # stap probe-alias.stp 05-wait_for_sys/io: 19 10-udev.hotplug/io: 17 20-hal.hotplug/io: 12 X/io: 73 apcsmart/io: 59 [...] make/io: 515 make/process: 16 [...] xfce-mcs-manage/io: 3 xfdesktop/io: 5 [...] xmms/io: 7070 zsh/io: 78 zsh/process: 5 \end{verbatim} \end{boxedminipage} \caption{Classified system call activity.} \label{fig:probe-alias} \end{figure} \subsection{Embedded C} \label{embedded-c} Sometimes, a tapset needs provide data values from the kernel that cannot be extracted using ordinary target variables (\verb+$var+). %$ This may be because the values are in complicated data structures, may require lock awareness, or are defined by layers of macros. Systemtap provides an ``escape hatch'' to go beyond what the language can safely offer. In certain contexts, you may embed plain raw C in tapsets, exchanging power for the safety guarantees listed in section~\ref{sec:safety}. End-user scripts {\em may not} include embedded C code, unless systemtap is run with the \verb+-g+ (``guru'' mode) option. Tapset scripts get guru mode privileges automatically. \nomenclature{embedded C}{Special syntax permitting tapsets to include literal C code.} Embedded C can be the body of a script function. Instead enclosing the function body statements in \verb+{+ and \verb+}+, use \verb+%{+ and \verb+%}+. Any enclosed C code is literally transcribed into the kernel module: it is up to you to make it safe and correct. In order to take parameters and return a value, macros \verb+STAP_ARG_*+ and \verb+STAP_RETVALUE+ are made available. The familiar data-gathering functions \verb+pid()+, \verb+execname()+, and their neighbours are all embedded C functions. Figure~\ref{fig:embedded-C} contains another example. Since systemtap cannot examine the C code to infer these types, an optional\footnote{This is only necessary if the types cannot be inferred from other sources, such as the call sites.} annotation syntax is available to assist the type inference process. Simply suffix parameter names and/or the function name with \verb+:string+ or \verb+:long+ to designate the string or numeric type. In addition, the script may include a \verb+%{+ \verb+%}+ block at the outermost level of the script, in order to transcribe declarative code like \verb+#include +. These enable the embedded C functions to refer to general kernel types. There are a number of safety-related constraints that should be observed by developers of embedded C code. \begin{enumerate} \item Do not dereference pointers that are not known or testable valid. \item Do not call any kernel routine that may cause a sleep or fault. \item Consider possible undesirable recursion, where your embedded C function calls a routine that may be the subject of a probe. If that probe handler calls your embedded C function, you may suffer infinite regress. Similar problems may arise with respect to non-reentrant locks. \item If locking of a data structure is necessary, use a \verb+trylock+ type call to attempt to take the lock. If that fails, give up, do not block. \end{enumerate} \begin{figure}[!ht] \begin{boxedminipage}{4.5in} \begin{verbatim} # cat embedded-C.stp %{ #include #include %} function task_execname_by_pid:string (pid:long) %{ struct task_struct *p; struct list_head *_p, *_n; list_for_each_safe(_p, _n, ¤t->tasks) { p = list_entry(_p, struct task_struct, tasks); if (p->pid == (int)STAP_ARG_pid) snprintf(STAP_RETVALUE, MAXSTRINGLEN, "%s", p->comm); } %} probe begin { printf("%s(%d)\n", task_execname_by_pid(target()), target()) exit() } # pgrep emacs 16641 # stap -g embedded-C.stp -x 16641 emacs(16641) \end{verbatim} \end{boxedminipage} \caption{Embedded C function.} \label{fig:embedded-C} \end{figure} \subsection{Naming conventions} Using the tapset search mechanism just described, potentially many script files can become selected for inclusion in a single session. This raises the problem of name collisions, where different tapsets accidentally use the same names for functions/globals. This can result in errors at translate or run time. To control this problem, systemtap tapset developers are advised to follow naming conventions. Here is some of the guidance. \nomenclature{naming convention}{Guidelines for naming variables and functions to prevent unintentional duplication.} \begin{enumerate} \item Pick a unique name for your tapset, and substitute it for {\em TAPSET} below. \item Separate identifiers meant to be used by tapset users from those that are internal implementation artifacts. \item Document the first set in the appropriate \verb+man+ pages. \item Prefix the names of external identifiers with {\em TAPSET}\_ if there is any likelihood of collision with other tapsets or end-user scripts. \item Prefix any probe point aliases with an appropriate prefix. \item Prefix the names of internal identifiers with \_\_{\em TAPSET}\_. \end{enumerate} \subsection{Exercises} \begin{enumerate} \item Write a tapset that implements deferred and ``cancelable'' logging. Export a function that enqueues a text string (into some private array), returning an id token. Include a timer-based probe that periodically flushes the array to the standard log output. Export another function that, if the entry was not already flushed, allows a text string to be cancelled from the queue. One might speculate that similar functions and tapsets exist. \item Create a ``relative timestamp'' tapset with functions return all the same values as the ones in the timestamp tapset, except that they are made relative to the start time of the script. \item Create a tapset that exports a global array that contains a mapping of recently seen process ID numbers to process names. Intercept key system calls (\verb+execve+?) to update the list incrementally. \item Send your tapset ideas to the mailing list! \end{enumerate} \section{Further information} For further information about systemtap, several sources are available. There are \verb+man+ pages: \begin{tabular}{rl} \verb+stap+ & systemtap program usage, language summary \\ \verb+stappaths+ & your systemtap installation paths \\ \verb+stapprobes+ & probes / probe aliases provided by built-in tapsets \\ \verb+stapex+ & a few basic example scripts \\ \verb+tapset::*+ & summaries of the probes and functions in each tapset \\ \verb+probe::*+ & detailed descriptions of each probe \\ \verb+function::*+ & detailed descriptions of each function \end{tabular} There is much more documentation and sample scripts included. You may find them under \verb+/usr/share/doc/systemtap*/+. Then, there is the source code itself. Since systemtap is {\em free software}, you should have available the entire source code. The source files in the \verb+tapset/+ directory are also packaged along with the systemtap binary. Since systemtap reads these files rather than their documentation, they are the most reliable way to see what's inside all the tapsets. Use the \verb+-v+ (verbose) command line option, several times if you like, to show inner workings. \nomenclature{free software}{Software licensed under terms such as the GNU GPL, which aims to enforce certain specified user freedoms such as study, modification, and sharing.} Finally, there is the project web site (\verb+http://sourceware.org/systemtap/+) with several articles, an archived public mailing list for users and developers (\verb+systemtap@sourceware.org+), IRC channels, and a live GIT source repository. Come join us! \appendix \section{Glossary} \renewcommand{\nomname}{} \printglossary \begin{htmlonly} {\em Sorry, not available in HTML.} \end{htmlonly} \section{Errors} We explain some common systemtap error messages in this section. Most error messages include line/character numbers with which one can locate the precise location of error in the script code. There is sometimes a subsequent or prior line that elaborates. {\large {\em error} {\tt at:} {\em filename}:{\em line}:{\em column}: {\em details}} \subsection{Parse errors} \begin{description} \item{\bf parse error: expected {\em foo}, saw {\em bar} $\ldots$} \\ The script contained a grammar error. A different type of construct was expected in the given context. \item{\bf parse error: embedded code in unprivileged script} \\ The script contained unsafe constructs such as embedded C (section \ref{embedded-c}), but was run without the \verb+-g+ (guru mode) option. Confirm that the constructs are used safely, then try again with \verb+-g+. \end{description} \subsection{Type errors} \begin{description} \item{\bf semantic error: type mismatch for identifier '{\em foo}' $\ldots$ string vs. long} \\ In this case, the identifier {\em foo} was previously inferred as a numeric type (``long''), but at the given point is being used as a string. Similar messages appear if an array index or function parameter slot is used with conflicting types. \item{\bf semantic error: unresolved type for identifier '{\em foo}'} \\ The identifier {\em foo} was used, for example in a \verb+print+, but without any operations that could assign it a type. Similar messages may appear if a symbol is misspelled by a typo. \item{\bf semantic error: Expecting symbol or array index expression} \\ Something other than an assignable lvalue was on the left hand sign of an assignment. \end{description} \subsection{Symbol errors} \begin{description} \item{\bf while searching for arity {\em N} function, semantic error: unresolved function call} \\ The script calls a function with {\em N} arguments that does not exist. The function may exist with different arity. \item{\bf semantic error: array locals not supported: $\ldots$} \\ An array operation is present for which no matching global declaration was found. Similar messages appear if an array is used with inconsistent arities. \item{\bf semantic error: variable '{\em foo}' modified during 'foreach'} \\ The array {\em foo} is being modified (being assigned to or deleted from) within an active \verb+foreach+ loop. This invalid operation is also detected within a function called from within the loop. \end{description} \subsection{Probing errors } \begin{description} \item{\bf semantic error: probe point mismatch at position {\em N}, while resolving probe point {\em foo}} \\ A probe point was named that neither directly understood by systemtap, nor defined as an alias by a tapset script. The divergence from the ``tree'' of probe point namespace is at position {\em N} (starting with zero at left). \item{\bf semantic error: no match for probe point, while resolving probe point {\em foo}} \\ A probe point cannot be resolved for any of a variety of reasons. It may be a debuginfo-based probe point such as \verb+kernel.function("foobar")+ where no \verb+foobar+ function was found. This can occur if the script specifies a wildcard on function names, or an invalid file name or source line number. \item{\bf semantic error: unresolved target-symbol expression} \\ A target variable was referred to in a probe handler that was not resolvable. Or, a target variable is not valid at all in a context such as a script function. This variable may have been elided by an optimizing compiler, or may not have a suitable type, or there might just be an annoying bug somewhere. Try again with a slightly different probe point (use \verb+statement()+ instead of \verb+function()+) to search for a more cooperative neighbour in the same area. \item{\bf semantic error: libdwfl failure $\ldots$} \\ There was a problem processing the debugging information. It may simply be missing, or may have some consistency / correctness problems. Later compilers tend to produce better debugging information, so if you can upgrade and recompile your kernel/application, it may help. \item{\bf semantic error: cannot find {\em foo} debuginfo} \\ Similarly, suitable debugging information was not found. Check that your kernel build/installation includes a matching version of debugging data. \end{description} \subsection{Runtime errors} Usually, run-time errors cause a script to terminate. Some of these may be caught with the \verb+try { ... } catch { ... }+ construct. \begin{description} \item{\bf WARNING: Number of errors: {\em N}, skipped probes: {\em M}} \\ Errors and/or skipped probes occurred during this run. \nomenclature{skipped probe}{A probe handler that should have run but couldn't, due to contention or temporary resource problems.} \item{\bf division by 0} \\ The script code performed an invalid division. \item{\bf aggregate element not found} \\ An statistics extractor function other than \verb+@count+ was invoked on an aggregate that has not had any values accumulated yet. This is similar to a division by zero. \item{\bf aggregation overflow} \\ An array containing aggregate values contains too many distinct key tuples at this time. \item{\bf MAXNESTING exceeded} \\ Too many levels of function call nesting were attempted. \item{\bf MAXACTION exceeded} \\ The probe handler attempted to execute too many statements. \item{\bf kernel/user string copy fault at {\em 0xaddr}} \\ The probe handler attempted to copy a string from kernel or user space at an invalid address. \item{\bf pointer dereference fault} \\ There was a fault encountered during a pointer dereference operation such as a target variable evaluation. \end{description} \section{Acknowledgments} The author thanks Martin Hunt, Will Cohen, and Jim Keniston for improvement advice for this paper. \end{document} systemtap-2.3/doc/tutorial/000077500000000000000000000000001217430427200160215ustar00rootroot00000000000000systemtap-2.3/doc/tutorial/embedded-C.stp000066400000000000000000000007061217430427200204650ustar00rootroot00000000000000%{ #include #include %} function task_execname_by_pid:string (pid:long) %{ struct task_struct *p; struct list_head *_p, *_n; list_for_each_safe(_p, _n, ¤t->tasks) { p = list_entry(_p, struct task_struct, tasks); if (p->pid == (int)STAP_ARG_pid) snprintf(STAP_RETVALUE, MAXSTRINGLEN, "%s", p->comm); } %} probe begin { printf("%s(%d)\n", task_execname_by_pid(target()), target()) exit() } systemtap-2.3/doc/tutorial/functions.stp000066400000000000000000000006551217430427200205670ustar00rootroot00000000000000# Red Hat convention; see /etc/login.defs UID_MIN function system_uid_p (u) { return u < 500 } # kernel device number assembly macro function makedev (major,minor) { return major << 20 | minor } function trace_common () { printf("%d %s(%d)", gettimeofday_s(), execname(), pid()) # no return value } function fibonacci (i) { if (i < 1) return 0 else if (i < 2) return 1 else return fibonacci(i-1) + fibonacci(i-2) } systemtap-2.3/doc/tutorial/hello-world.stp000066400000000000000000000000651217430427200210020ustar00rootroot00000000000000probe begin { print ("hello world\n") exit () } systemtap-2.3/doc/tutorial/inode-watch.stp000066400000000000000000000007761217430427200207650ustar00rootroot00000000000000probe kernel.function ("vfs_write"), kernel.function ("vfs_read") { if (@defined($file->f_path->dentry)) { dev_nr = $file->f_path->dentry->d_inode->i_sb->s_dev inode_nr = $file->f_path->dentry->d_inode->i_ino } else { dev_nr = $file->f_dentry->d_inode->i_sb->s_dev inode_nr = $file->f_dentry->d_inode->i_ino } if (dev_nr == ($1 << 20 | $2) # major/minor device && inode_nr == $3) printf ("%s(%d) %s 0x%x/%u\n", execname(), pid(), probefunc(), dev_nr, inode_nr) } systemtap-2.3/doc/tutorial/probe-alias.stp000066400000000000000000000005701217430427200207510ustar00rootroot00000000000000probe syscallgroup.io = syscall.open, syscall.close, syscall.read, syscall.write { groupname = "io" } probe syscallgroup.process = syscall.fork, syscall.execve { groupname = "process" } probe syscallgroup.* { groups [execname() . "/" . groupname] ++ } probe end { foreach (eg+ in groups) printf ("%s: %d\n", eg, groups[eg]) } global groups systemtap-2.3/doc/tutorial/socket-trace.stp000066400000000000000000000003231217430427200211330ustar00rootroot00000000000000probe kernel.function("*@net/socket.c").call { printf ("%s -> %s\n", thread_indent(1), probefunc()) } probe kernel.function("*@net/socket.c").return { printf ("%s <- %s\n", thread_indent(-1), probefunc()) } systemtap-2.3/doc/tutorial/strace-open.stp000066400000000000000000000002101217430427200207620ustar00rootroot00000000000000probe syscall.open { printf ("%s(%d) open (%s)\n", execname(), pid(), argstr) } probe timer.ms(4000) # after 4 seconds { exit () } systemtap-2.3/doc/tutorial/tapset-time-user.stp000066400000000000000000000002671217430427200217660ustar00rootroot00000000000000probe begin { timer_begin ("bench") for (i=0; i<100; i++) ; printf ("%d cycles\n", timer_end ("bench")) exit () } function __time_value () { return get_cycles () } # override systemtap-2.3/doc/tutorial/tapset/000077500000000000000000000000001217430427200173215ustar00rootroot00000000000000systemtap-2.3/doc/tutorial/tapset/time-common.stp000066400000000000000000000002401217430427200222710ustar00rootroot00000000000000global __time_vars function timer_begin (name) { __time_vars[name] = __time_value () } function timer_end (name) { return __time_value() - __time_vars[name] } systemtap-2.3/doc/tutorial/tapset/time-default.stp000066400000000000000000000000701217430427200224260ustar00rootroot00000000000000function __time_value () { return gettimeofday_us () } systemtap-2.3/doc/tutorial/timer-jiffies.stp000066400000000000000000000004221217430427200213040ustar00rootroot00000000000000global count_jiffies, count_ms probe timer.jiffies(100) { count_jiffies ++ } probe timer.ms(100) { count_ms ++ } probe timer.ms(12345) { hz=(1000*count_jiffies) / count_ms printf ("jiffies:ms ratio %d:%d => CONFIG_HZ=%d\n", count_jiffies, count_ms, hz) exit () } systemtap-2.3/dtrace.in000077500000000000000000000260751217430427200152200ustar00rootroot00000000000000#!/usr/bin/python # vim: et sta sts=4 sw=4 ts=8 # This handles the systemtap equivalent of # $(DTRACE) $(DTRACEFLAGS) -G -s $^ -o $@ # $(DTRACE) $(DTRACEFLAGS) -h -s $^ -o $@ # which is a step that builds DTrace provider and probe definitions # Copyright (C) 2009, 2010, 2011 Red Hat Inc. # # This file is part of systemtap, and is free software. You can # redistribute it and/or modify it under the terms of the GNU General # Public License (GPL); either version 2, or (at your option) any # later version. import os import posix import sys import shlex from subprocess import call from tempfile import mkstemp class _provider(object): def __init__(self): self.semaphores_def = "\n" # is the type a basic scalar type? def __basic_type(self, arg): basic_types = [ "int","int*","long","long*","short","short int", "unsigned long","char","char*","float","double" ] split_arg = arg.rsplit(None,1) return (split_arg[0].strip() in basic_types) & (arg.find("[") == -1) def __typedef_append(self, typedefs, this_probe, arg, c, add_typedefs): if (add_typedefs): split_arg = arg.rsplit(None,1) if (self.__basic_type(arg)): return typedefs type_name = " %s_arg%d" % (this_probe.replace("__","_"),c) if (len(split_arg) > 1): typedefs += ("typedef " + arg.replace(" " + split_arg[1].split("[")[0].lstrip("*"),type_name).strip() + "; ") typedefs += (type_name + type_name + "_v;\n") else: typedefs += ("typedef " + arg.strip() + type_name + "; ") typedefs += (type_name + type_name + "_v;\n") return typedefs def __semaphore_def_append(self, this_probe): # NB: unsigned short is fixed in ABI self.semaphores_def += '#if defined STAP_SDT_V1\n' self.semaphores_def += '#define %s_%s_semaphore %s_semaphore\n' % \ (self.provider,this_probe,this_probe) self.semaphores_def += '#endif\n' self.semaphores_def += '#if defined STAP_SDT_V1 || defined STAP_SDT_V2 \n' self.semaphores_def += "__extension__ unsigned short %s_%s_semaphore __attribute__ ((unused)) __attribute__ ((section (\".probes\")));\n" % \ (self.provider,this_probe) self.semaphores_def += '#else\n' self.semaphores_def += "__extension__ unsigned short %s_%s_semaphore __attribute__ ((unused)) __attribute__ ((section (\".probes\"))) __attribute__ ((visibility (\"hidden\")));\n" % \ (self.provider,this_probe) self.semaphores_def += '#endif\n' def semaphore_def_write(self, file): file.write(self.semaphores_def) def generate(self, provider, header, add_typedefs): have_provider = False self.f = open(provider) self.h = open(header,mode='w') self.h.write("/* Generated by the Systemtap dtrace wrapper */\n") self.h.write("\n#define _SDT_HAS_SEMAPHORES 1\n\n") self.h.write("\n#define STAP_HAS_SEMAPHORES 1 /* deprecated */\n\n") self.h.write("\n#include \n\n") in_comment = False typedefs = "" while (True): line = self.f.readline() if (line == ""): break if (line.find("/*") != -1): in_comment = True if (line.find("*/") != -1): in_comment = False continue if (in_comment): continue if (line.find("provider") != -1): tokens = line.split() have_provider = True self.provider = tokens[1] elif (not have_provider): if (add_typedefs): self.h.write (line) elif (have_provider and line.find("probe ") != -1): while (line.find(")") < 0): line += self.f.readline() this_probe = line[line.find("probe ")+5:line.find("(")].strip() this_probe_canon = self.provider.upper() + "_" + this_probe.replace("__","_").upper() args = (line[line.find("(")+1:line.find(")")]) args_string = "" arg = "" i = 0 c = 0 self.__semaphore_def_append (this_probe) while (i < len(args)): if (args[i:i+1] == ","): args_string = ('%s %s,' % (args_string, arg.strip())) c += 1 typedefs = self.__typedef_append (typedefs, this_probe, arg, c, add_typedefs) arg = "" else: arg = arg + args[i] i += 1 if (i != 0): args_string = ('%s %s' % (args_string, arg.strip())) if (not args_string): c = 0 stap_str = "DTRACE_PROBE(%s,%s" % \ (self.provider,this_probe) else: c += 1 typedefs = self.__typedef_append (typedefs, this_probe, arg, c, add_typedefs) stap_str = "DTRACE_PROBE%d(%s,%s" % \ (c,self.provider,this_probe) define_str = "#define %s(" % (this_probe_canon) i = 1 while (i <= c): if (i != 1): define_str += "," define_str = define_str + "arg%s" % (i); stap_str = stap_str + ",arg%s" % (i); i += 1 self.h.write('/* %s (%s) */\n' % \ (this_probe_canon,args_string)) self.h.write('#if defined STAP_SDT_V1\n') self.h.write('#define %s_ENABLED() __builtin_expect (%s_semaphore, 0)\n' % \ (this_probe_canon,this_probe)) self.h.write('#define %s_%s_semaphore %s_semaphore\n' % \ (self.provider,this_probe,this_probe)) self.h.write('#else\n') self.h.write('#define %s_ENABLED() __builtin_expect (%s_%s_semaphore, 0)\n' % \ (this_probe_canon,self.provider,this_probe)) self.h.write('#endif\n') # NB: unsigned short is fixed in ABI self.h.write("__extension__ extern unsigned short %s_%s_semaphore __attribute__ ((unused)) __attribute__ ((section (\".probes\")));\n" % \ (self.provider,this_probe)) self.h.write(define_str + ") \\\n") self.h.write(stap_str + ")\n\n") elif (line.find("}") != -1 and have_provider): have_provider = False if (add_typedefs): self.h.write(typedefs) self.h.close() def usage (): print "Usage " + sys.argv[0] + " [--help] [-h | -G] [-C [-I]] -s File.d [-o ]" def help (): usage() print "Where -h builds a systemtap header file from the .d file" print " -C when used with -h, also run cpp preprocessor" print " -o specifies an explicit output file name," print " the default for -G is file.o and -h is file.h" print " -I when running cpp pass through this -I include Path" print " -s specifies the name of the .d input file" print " -G builds a stub file.o from file.d," print " which is required by some packages that use dtrace." sys.exit(1) ######################################################################## # main ######################################################################## def main(): if (len(sys.argv) < 2): usage() return 1 i = 1 build_header = False build_source = False add_typedefs = False keep_temps = False use_cpp = False suffix = "" filename = "" s_filename = "" includes = [] defines = [] while (i < len(sys.argv)): if (sys.argv[i] == "-o"): i += 1 filename = sys.argv[i] elif (sys.argv[i] == "-s"): i += 1 s_filename = sys.argv[i] elif (sys.argv[i] == "-C"): use_cpp = True elif (sys.argv[i].startswith("-D")): defines.append(sys.argv[i]) elif (sys.argv[i] == "-h"): build_header = True suffix = ".h" elif (sys.argv[i].startswith("-I")): includes.append(sys.argv[i]) elif (sys.argv[i] == "-G"): build_source = True suffix = ".o" elif (sys.argv[i] == "-k"): keep_temps = True elif (sys.argv[i] == "--types"): add_typedefs = True elif (sys.argv[i] == "--help"): help() i += 1 if (build_header == False and build_source == False): usage() return 1 if (s_filename != "" and use_cpp): (d,fn) = mkstemp(suffix=".d") CPP = os.environ.get("CPP", "cpp") retcode = call(shlex.split(CPP) + includes + defines + [s_filename, fn]) if (retcode != 0): print "\"cpp includes s_filename\" failed" usage() return 1 s_filename = fn if (filename == ""): if (s_filename != ""): (filename,ext) = os.path.splitext(s_filename) filename = os.path.basename(filename) else: usage() return 1 else: suffix = "" if (build_header): providers = _provider() providers.generate(s_filename, filename + suffix, add_typedefs) elif (build_source): (basename,ext) = os.path.splitext(s_filename) # create for semaphore_def_write providers = _provider() (d,fn) = mkstemp(suffix=".h") providers.generate(s_filename, fn, add_typedefs) if (not keep_temps): os.remove(fn) else: print "header: " + fn (d,fn) = mkstemp(suffix=".c") f = open(fn,mode='w') # dummy declaration just to make the object file non-empty f.write("static void __dtrace (void) __attribute__((unused));\n") f.write("static void __dtrace (void) {}\n") f.write("\n#include \n\n") providers.semaphore_def_write(f) f.close() CC = os.environ.get("CC", "gcc") CFLAGS = "-g " + os.environ.get("CFLAGS", "") retcode = call(shlex.split(CC) + defines + includes + shlex.split(CFLAGS) + ["-fPIC", "-I.", "-I@prefix@/include", "-c", fn, "-o", filename + suffix], shell=False) if (retcode != 0): print "\"gcc " + fn + "\" failed" usage() return 1 if (not keep_temps): os.remove(fn) else: print "source: " + fn if (use_cpp): if (not keep_temps): os.remove(s_filename) else: print "cpp: " + s_filename return 0 if __name__ == "__main__": sys.exit(main()) systemtap-2.3/dwarf_wrappers.cxx000066400000000000000000000115661217430427200171740ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2008-2011 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "dwarf_wrappers.h" #include "staptree.h" #include "util.h" #include #include #include #include #include using namespace std; void dwfl_assert(const string& desc, int rc) { if (rc == 0) return; string msg = _F("libdwfl failure (%s): ", desc.c_str()); if (rc < 0) msg += (dwfl_errmsg (rc) ?: "?"); else msg += std::strerror (rc); throw semantic_error (msg); } void dwarf_assert(const string& desc, int rc) { if (rc == 0) return; string msg = _F("libdw failure (%s): ", desc.c_str()); if (rc < 0) msg += dwarf_errmsg (rc); else msg += std::strerror (rc); throw semantic_error (msg); } #if !_ELFUTILS_PREREQ(0, 143) // Elfutils prior to 0.143 didn't use attr_integrate when looking up the // decl_file or decl_line, so the attributes would sometimes be missed. For // those old versions, we define custom implementations to do the integration. const char * dwarf_decl_file_integrate (Dwarf_Die *die) { Dwarf_Attribute attr_mem; Dwarf_Sword idx = 0; if (dwarf_formsdata (dwarf_attr_integrate (die, DW_AT_decl_file, &attr_mem), &idx) != 0 || idx == 0) return NULL; Dwarf_Die cudie; Dwarf_Files *files = NULL; if (dwarf_getsrcfiles (dwarf_diecu (die, &cudie, NULL, NULL), &files, NULL) != 0) return NULL; return dwarf_filesrc(files, idx, NULL, NULL); } int dwarf_decl_line_integrate (Dwarf_Die *die, int *linep) { Dwarf_Attribute attr_mem; Dwarf_Sword line; int res = dwarf_formsdata (dwarf_attr_integrate (die, DW_AT_decl_line, &attr_mem), &line); if (res == 0) *linep = line; return res; } #endif // !_ELFUTILS_PREREQ(0, 143) static bool dwarf_type_name(Dwarf_Die *type_die, ostream& o) { // if we've gotten down to a basic type, then we're done bool done = true; switch (dwarf_tag(type_die)) { case DW_TAG_enumeration_type: o << "enum "; break; case DW_TAG_structure_type: o << "struct "; break; case DW_TAG_union_type: o << "union "; break; case DW_TAG_class_type: o << "class "; break; case DW_TAG_typedef: case DW_TAG_base_type: break; // modifier types that require recursion first case DW_TAG_reference_type: case DW_TAG_rvalue_reference_type: case DW_TAG_pointer_type: case DW_TAG_array_type: case DW_TAG_const_type: case DW_TAG_volatile_type: done = false; break; // unknown tag default: return false; } if (done) { // this follows gdb precedent that anonymous structs/unions // are displayed as "struct {...}" and "union {...}". o << (dwarf_diename(type_die) ?: "{...}"); return true; } // otherwise, this die is a type modifier. // recurse into the referent type Dwarf_Die subtype_die_mem, *subtype_die; subtype_die = dwarf_attr_die(type_die, DW_AT_type, &subtype_die_mem); // NB: va_list is a builtin type that shows up in the debuginfo as a // "struct __va_list_tag*", but it has to be called only va_list. if (subtype_die != NULL && dwarf_tag(type_die) == DW_TAG_pointer_type && dwarf_tag(subtype_die) == DW_TAG_structure_type && strcmp(dwarf_diename(subtype_die) ?: "", "__va_list_tag") == 0) { o << "va_list"; return true; } // if it can't be named, just call it "void" if (subtype_die == NULL || !dwarf_type_name(subtype_die, o)) o << "void"; switch (dwarf_tag(type_die)) { case DW_TAG_reference_type: o << "&"; break; case DW_TAG_rvalue_reference_type: o << "&&"; break; case DW_TAG_pointer_type: o << "*"; break; case DW_TAG_array_type: o << "[]"; break; case DW_TAG_const_type: // NB: the debuginfo may sometimes have an extra const tag // on reference types, which is redundant to us. if (subtype_die == NULL || (dwarf_tag(subtype_die) != DW_TAG_reference_type && dwarf_tag(subtype_die) != DW_TAG_rvalue_reference_type)) o << " const"; break; case DW_TAG_volatile_type: o << " volatile"; break; default: return false; } return true; } bool dwarf_type_name(Dwarf_Die *type_die, string& type_name) { ostringstream o; bool ret = dwarf_type_name(type_die, o); type_name = o.str(); return ret; } string dwarf_type_name(Dwarf_Die *type_die) { ostringstream o; return dwarf_type_name(type_die, o) ? o.str() : ""; } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/dwarf_wrappers.h000066400000000000000000000101151217430427200166060ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2008-2011 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef DWARF_WRAPPERS_H #define DWARF_WRAPPERS_H 1 #include "config.h" extern "C" { #include #include #include } #include #if ! _ELFUTILS_PREREQ(0, 148) #define DW_AT_linkage_name 0x6e #endif #if ! _ELFUTILS_PREREQ(0, 155) #define DW_ATE_UTF 0x10 #endif // NB: "rc == 0" means OK in this case void dwfl_assert(const std::string& desc, int rc); // Throw error if pointer is NULL inline void dwfl_assert(const std::string& desc, const void* ptr) { if (!ptr) dwfl_assert(desc, -1); } // Throw error if condition is false inline void dwfl_assert(const std::string& desc, bool condition) { if (!condition) dwfl_assert(desc, -1); } // NB: "rc == 0" means OK in this case void dwarf_assert(const std::string& desc, int rc); // Throw error if pointer is NULL inline void dwarf_assert(const std::string& desc, const void* ptr) { if (!ptr) dwarf_assert(desc, -1); } class dwarf_line_t { public: const Dwarf_Line* line; dwarf_line_t() : line(0) {} dwarf_line_t(const Dwarf_Line* line_) : line(line_) {} dwarf_line_t& operator= (const Dwarf_Line* line_) { line = (line_); return *this; } operator bool() const { return line != 0; } int lineno() const { int lineval; if (!line) dwarf_assert("dwarf_line_t::lineno", -1); dwarf_lineno(const_cast(line), &lineval); return lineval; } Dwarf_Addr addr() const { Dwarf_Addr addrval; if (!line) dwarf_assert("dwarf_line_t::addr", -1); dwarf_lineaddr(const_cast(line), &addrval); return addrval; } const char* linesrc(Dwarf_Word* mtime = 0, Dwarf_Word* length = 0) { const char* retval = dwarf_linesrc(const_cast(line), mtime, length); dwarf_assert("dwarf_line_t::linesrc", retval); return retval; } }; // Look up the DIE for a reference-form attribute name inline Dwarf_Die * dwarf_attr_die (Dwarf_Die *die, unsigned int attr, Dwarf_Die *result) { Dwarf_Attribute attr_mem; if (dwarf_formref_die (dwarf_attr_integrate (die, attr, &attr_mem), result) != NULL) { /* If we want a type make sure we get the actual DIE describing the real type. */ if (attr == DW_AT_type) { Dwarf_Attribute sigm; Dwarf_Attribute *sig = dwarf_attr (result, DW_AT_signature, &sigm); if (sig != NULL) result = dwarf_formref_die (sig, result); /* A DW_AT_signature might point to a type_unit, then the actual type DIE we want is the first child. */ if (result != NULL && dwarf_tag (result) == DW_TAG_type_unit) dwarf_child (result, result); } return result; } return NULL; } // Retrieve the linkage name of a die, either by the MIPS vendor extension or // DWARF4's standardized attribute. inline const char * dwarf_linkage_name (Dwarf_Die *die) { Dwarf_Attribute attr_mem; return dwarf_formstring (dwarf_attr_integrate (die, DW_AT_MIPS_linkage_name, &attr_mem) ?: dwarf_attr_integrate (die, DW_AT_linkage_name, &attr_mem)); } #if !_ELFUTILS_PREREQ(0, 143) // Elfutils prior to 0.143 didn't use attr_integrate when looking up the // decl_file or decl_line, so the attributes would sometimes be missed. For // those old versions, we define custom implementations to do the integration. const char *dwarf_decl_file_integrate (Dwarf_Die *die); #define dwarf_decl_file dwarf_decl_file_integrate int dwarf_decl_line_integrate (Dwarf_Die *die, int *linep) __nonnull_attribute__ (2); #define dwarf_decl_line dwarf_decl_line_integrate #endif // !_ELFUTILS_PREREQ(0, 143) // Resolve a full name for dwarf types bool dwarf_type_name(Dwarf_Die *type_die, std::string& type_name); std::string dwarf_type_name(Dwarf_Die *type_die); #endif /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/dwflpp.cxx000066400000000000000000003515561217430427200154500ustar00rootroot00000000000000// C++ interface to dwfl // Copyright (C) 2005-2013 Red Hat Inc. // Copyright (C) 2005-2007 Intel Corporation. // Copyright (C) 2008 James.Bottomley@HansenPartnership.com // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "dwflpp.h" #include "config.h" #include "staptree.h" #include "elaborate.h" #include "tapsets.h" #include "task_finder.h" #include "translate.h" #include "session.h" #include "util.h" #include "buildrun.h" #include "dwarf_wrappers.h" #include "auto_free.h" #include "hash.h" #include "rpm_finder.h" #include "setupdwfl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include extern "C" { #include #include #include #include #include #include #include #include #include #include #include #include "loc2c.h" #define __STDC_FORMAT_MACROS #include } // Older glibc elf.h don't know about this new constant. #ifndef STB_GNU_UNIQUE #define STB_GNU_UNIQUE 10 #endif // debug flag to compare to the uncached version from libdw // #define DEBUG_DWFLPP_GETSCOPES 1 using namespace std; using namespace __gnu_cxx; static string TOK_KERNEL("kernel"); dwflpp::dwflpp(systemtap_session & session, const string& name, bool kernel_p): sess(session), module(NULL), module_bias(0), mod_info(NULL), module_start(0), module_end(0), cu(NULL), module_dwarf(NULL), function(NULL), blacklist_func(), blacklist_func_ret(), blacklist_file(), blacklist_enabled(false) { if (kernel_p) setup_kernel(name, session); else { vector modules; modules.push_back(name); setup_user(modules); } } dwflpp::dwflpp(systemtap_session & session, const vector& names, bool kernel_p): sess(session), module(NULL), module_bias(0), mod_info(NULL), module_start(0), module_end(0), cu(NULL), module_dwarf(NULL), function(NULL), blacklist_enabled(false) { if (kernel_p) setup_kernel(names); else setup_user(names); } dwflpp::~dwflpp() { delete_map(module_cu_cache); delete_map(cu_function_cache); delete_map(mod_function_cache); delete_map(cu_inl_function_cache); delete_map(global_alias_cache); delete_map(cu_die_parent_cache); dwfl_ptr.reset(); // NB: don't "delete mod_info;", as that may be shared // between dwflpp instances, and are stored in // session.module_cache[] anyway. } module_cache::~module_cache () { delete_map(cache); } void dwflpp::get_module_dwarf(bool required, bool report) { module_dwarf = dwfl_module_getdwarf(module, &module_bias); mod_info->dwarf_status = (module_dwarf ? info_present : info_absent); if (!module_dwarf && report) { string msg = _("cannot find "); if (module_name == "") msg += "kernel"; else msg += string("module ") + module_name; msg += " debuginfo"; int i = dwfl_errno(); if (i) msg += string(": ") + dwfl_errmsg (i); msg += " [man warning::debuginfo]"; /* add module_name to list to find rpm */ find_debug_rpms(sess, module_name.c_str()); if (required) throw semantic_error (msg); else sess.print_warning(msg); } } void dwflpp::focus_on_module(Dwfl_Module * m, module_info * mi) { module = m; mod_info = mi; if (m) { module_name = dwfl_module_info(module, NULL, &module_start, &module_end, NULL, NULL, NULL, NULL) ?: "module"; } else { assert(mi && mi->name && mi->name == TOK_KERNEL); module_name = mi->name; module_start = 0; module_end = 0; module_bias = mi->bias; } // Reset existing pointers and names module_dwarf = NULL; cu = NULL; function_name.clear(); function = NULL; } void dwflpp::focus_on_cu(Dwarf_Die * c) { assert(c); assert(module); cu = c; // Reset existing pointers and names function_name.clear(); function = NULL; } string dwflpp::cu_name(void) { return dwarf_diename(cu) ?: ""; } void dwflpp::focus_on_function(Dwarf_Die * f) { assert(f); assert(module); assert(cu); function = f; function_name = dwarf_diename(function) ?: "function"; } /* Return the Dwarf_Die for the given address in the current module. * The address should be in the module address address space (this * function will take care of any dw bias). */ Dwarf_Die * dwflpp::query_cu_containing_address(Dwarf_Addr a) { Dwarf_Addr bias; assert(dwfl_ptr.get()->dwfl); assert(module); get_module_dwarf(); Dwarf_Die* cudie = dwfl_module_addrdie(module, a, &bias); assert(bias == module_bias); return cudie; } bool dwflpp::module_name_matches(const string& pattern) { bool t = (fnmatch(pattern.c_str(), module_name.c_str(), 0) == 0); if (t && sess.verbose>3) clog << _F("pattern '%s' matches module '%s'\n", pattern.c_str(), module_name.c_str()); if (!t && sess.verbose>4) clog << _F("pattern '%s' does not match module '%s'\n", pattern.c_str(), module_name.c_str()); return t; } bool dwflpp::name_has_wildcard (const string& pattern) { return (pattern.find('*') != string::npos || pattern.find('?') != string::npos || pattern.find('[') != string::npos); } bool dwflpp::module_name_final_match(const string& pattern) { // Assume module_name_matches(). Can there be any more matches? // Not unless the pattern is a wildcard, since module names are // presumed unique. return !name_has_wildcard(pattern); } bool dwflpp::function_name_matches_pattern(const string& name, const string& pattern) { bool t = (fnmatch(pattern.c_str(), name.c_str(), 0) == 0); if (t && sess.verbose>3) clog << _F("pattern '%s' matches function '%s'\n", pattern.c_str(), name.c_str()); return t; } bool dwflpp::function_name_matches(const string& pattern) { assert(function); return function_name_matches_pattern(function_name, pattern); } bool dwflpp::function_scope_matches(const vector& scopes) { // walk up the containing scopes Dwarf_Die* die = function; for (int i = scopes.size() - 1; i >= 0; --i) { die = get_parent_scope(die); // check if this scope matches, and prepend it if so // NB: a NULL die is the global scope, compared as "" string name = dwarf_diename(die) ?: ""; if (name_has_wildcard(scopes[i]) ? function_name_matches_pattern(name, scopes[i]) : name == scopes[i]) function_name = name + "::" + function_name; else return false; // make sure there's no more if we're at the global scope if (!die && i > 0) return false; } return true; } void dwflpp::setup_kernel(const string& name, systemtap_session & s, bool debuginfo_needed) { if (! sess.module_cache) sess.module_cache = new module_cache (); unsigned offline_search_matches = 0; dwfl_ptr = setup_dwfl_kernel(name, &offline_search_matches, sess); if (offline_search_matches < 1) { if (debuginfo_needed) { // Suggest a likely kernel dir to find debuginfo rpm for string dir = string(sess.sysroot + "/lib/modules/" + sess.kernel_release ); find_debug_rpms(sess, dir.c_str()); } throw semantic_error (_F("missing %s kernel/module debuginfo [man warning::debuginfo] under '%s'", sess.architecture.c_str(), sess.kernel_build_tree.c_str())); } Dwfl *dwfl = dwfl_ptr.get()->dwfl; if (dwfl != NULL) { ptrdiff_t off = 0; do { assert_no_interrupts(); off = dwfl_getmodules (dwfl, &add_module_build_id_to_hash, &s, off); } while (off > 0); dwfl_assert("dwfl_getmodules", off == 0); } build_blacklist(); } void dwflpp::setup_kernel(const vector &names, bool debuginfo_needed) { if (! sess.module_cache) sess.module_cache = new module_cache (); unsigned offline_search_matches = 0; set offline_search_names(names.begin(), names.end()); dwfl_ptr = setup_dwfl_kernel(offline_search_names, &offline_search_matches, sess); if (offline_search_matches < offline_search_names.size()) { if (debuginfo_needed) { // Suggest a likely kernel dir to find debuginfo rpm for string dir = string(sess.sysroot + "/lib/modules/" + sess.kernel_release ); find_debug_rpms(sess, dir.c_str()); } throw semantic_error (_F("missing %s kernel/module debuginfo [man warning::debuginfo] under '%s'", sess.architecture.c_str(), sess.kernel_build_tree.c_str())); } build_blacklist(); } void dwflpp::setup_user(const vector& modules, bool debuginfo_needed) { if (! sess.module_cache) sess.module_cache = new module_cache (); vector::const_iterator it = modules.begin(); dwfl_ptr = setup_dwfl_user(it, modules.end(), debuginfo_needed, sess); if (debuginfo_needed && it != modules.end()) dwfl_assert (string(_F("missing process %s %s debuginfo", (*it).c_str(), sess.architecture.c_str())), dwfl_ptr.get()->dwfl); } void dwflpp::iterate_over_modules(int (* callback)(Dwfl_Module *, void **, const char *, Dwarf_Addr, void *), void *data) { dwfl_getmodules (dwfl_ptr.get()->dwfl, callback, data, 0); // Don't complain if we exited dwfl_getmodules early. // This could be a $target variable error that will be // reported soon anyway. // dwfl_assert("dwfl_getmodules", off == 0); // PR6864 XXX: For dwarfless case (if .../vmlinux is missing), then the // "kernel" module is not reported in the loop above. However, we // may be able to make do with symbol table data. } void dwflpp::iterate_over_cus (int (*callback)(Dwarf_Die * die, void * arg), void * data, bool want_types) { get_module_dwarf(false); Dwarf *dw = module_dwarf; if (!dw) return; vector* v = module_cu_cache[dw]; if (v == 0) { v = new vector; module_cu_cache[dw] = v; Dwarf_Off off = 0; size_t cuhl; Dwarf_Off noff; while (dwarf_nextcu (dw, off, &noff, &cuhl, NULL, NULL, NULL) == 0) { assert_no_interrupts(); Dwarf_Die die_mem; Dwarf_Die *die; die = dwarf_offdie (dw, off + cuhl, &die_mem); /* Skip partial units. */ if (dwarf_tag (die) == DW_TAG_compile_unit) v->push_back (*die); /* copy */ off = noff; } } if (want_types && module_tus_read.find(dw) == module_tus_read.end()) { // Process type units. Dwarf_Off off = 0; size_t cuhl; Dwarf_Off noff; uint64_t type_signature; while (dwarf_next_unit (dw, off, &noff, &cuhl, NULL, NULL, NULL, NULL, &type_signature, NULL) == 0) { assert_no_interrupts(); Dwarf_Die die_mem; Dwarf_Die *die; die = dwarf_offdie_types (dw, off + cuhl, &die_mem); /* Skip partial units. */ if (dwarf_tag (die) == DW_TAG_type_unit) v->push_back (*die); /* copy */ off = noff; } module_tus_read.insert(dw); } for (vector::iterator i = v->begin(); i != v->end(); ++i) { int rc = (*callback)(&*i, data); assert_no_interrupts(); if (rc != DWARF_CB_OK) break; } } bool dwflpp::func_is_inline() { assert (function); return dwarf_func_inline (function) != 0; } bool dwflpp::func_is_exported() { const char *name = dwarf_linkage_name (function) ?: dwarf_diename (function); assert (function); int syms = dwfl_module_getsymtab (module); dwfl_assert (_("Getting symbols"), syms >= 0); for (int i = 0; i < syms; i++) { GElf_Sym sym; GElf_Word shndxp; const char *symname = dwfl_module_getsym(module, i, &sym, &shndxp); if (symname && strcmp (name, symname) == 0) { if (GELF_ST_TYPE(sym.st_info) == STT_FUNC && (GELF_ST_BIND(sym.st_info) == STB_GLOBAL || GELF_ST_BIND(sym.st_info) == STB_WEAK || GELF_ST_BIND(sym.st_info) == STB_GNU_UNIQUE)) return true; else return false; } } return false; } void dwflpp::cache_inline_instances (Dwarf_Die* die) { // If this is an inline instance, link it back to its origin Dwarf_Die origin; if (dwarf_tag(die) == DW_TAG_inlined_subroutine && dwarf_attr_die(die, DW_AT_abstract_origin, &origin)) { vector*& v = cu_inl_function_cache[origin.addr]; if (!v) v = new vector; v->push_back(*die); } // Recurse through other scopes that may contain inlines Dwarf_Die child, import; if (dwarf_child(die, &child) == 0) do { switch (dwarf_tag (&child)) { // tags that could contain inlines case DW_TAG_compile_unit: case DW_TAG_module: case DW_TAG_lexical_block: case DW_TAG_with_stmt: case DW_TAG_catch_block: case DW_TAG_try_block: case DW_TAG_entry_point: case DW_TAG_inlined_subroutine: case DW_TAG_subprogram: cache_inline_instances(&child); break; // imported dies should be followed case DW_TAG_imported_unit: if (dwarf_attr_die(&child, DW_AT_import, &import)) cache_inline_instances(&import); break; // nothing to do for other tags default: break; } } while (dwarf_siblingof(&child, &child) == 0); } void dwflpp::iterate_over_inline_instances (int (* callback)(Dwarf_Die * die, void * arg), void * data) { assert (function); assert (func_is_inline ()); if (cu_inl_function_cache_done.insert(cu->addr).second) cache_inline_instances(cu); vector* v = cu_inl_function_cache[function->addr]; if (!v) return; for (vector::iterator i = v->begin(); i != v->end(); ++i) { int rc = (*callback)(&*i, data); assert_no_interrupts(); if (rc != DWARF_CB_OK) break; } } void dwflpp::cache_die_parents(cu_die_parent_cache_t* parents, Dwarf_Die* die) { // Record and recurse through DIEs we care about Dwarf_Die child, import; if (dwarf_child(die, &child) == 0) do { switch (dwarf_tag (&child)) { // normal tags to recurse case DW_TAG_compile_unit: case DW_TAG_module: case DW_TAG_lexical_block: case DW_TAG_with_stmt: case DW_TAG_catch_block: case DW_TAG_try_block: case DW_TAG_entry_point: case DW_TAG_inlined_subroutine: case DW_TAG_subprogram: case DW_TAG_namespace: case DW_TAG_class_type: case DW_TAG_structure_type: parents->insert(make_pair(child.addr, *die)); cache_die_parents(parents, &child); break; // record only, nothing to recurse case DW_TAG_label: parents->insert(make_pair(child.addr, *die)); break; // imported dies should be followed case DW_TAG_imported_unit: if (dwarf_attr_die(&child, DW_AT_import, &import)) { parents->insert(make_pair(import.addr, *die)); cache_die_parents(parents, &import); } break; // nothing to do for other tags default: break; } } while (dwarf_siblingof(&child, &child) == 0); } cu_die_parent_cache_t* dwflpp::get_die_parents() { assert (cu); cu_die_parent_cache_t *& parents = cu_die_parent_cache[cu->addr]; if (!parents) { parents = new cu_die_parent_cache_t; cache_die_parents(parents, cu); if (sess.verbose > 4) clog << _F("die parent cache %s:%s size %zu", module_name.c_str(), cu_name().c_str(), parents->size()) << endl; } return parents; } vector dwflpp::getscopes_die(Dwarf_Die* die) { cu_die_parent_cache_t *parents = get_die_parents(); vector scopes; Dwarf_Die *scope = die; cu_die_parent_cache_t::iterator it; do { scopes.push_back(*scope); it = parents->find(scope->addr); scope = &it->second; } while (it != parents->end()); #ifdef DEBUG_DWFLPP_GETSCOPES Dwarf_Die *dscopes = NULL; int nscopes = dwarf_getscopes_die(die, &dscopes); assert(nscopes == (int)scopes.size()); for (unsigned i = 0; i < scopes.size(); ++i) assert(scopes[i].addr == dscopes[i].addr); free(dscopes); #endif return scopes; } std::vector dwflpp::getscopes(Dwarf_Die* die) { cu_die_parent_cache_t *parents = get_die_parents(); vector scopes; Dwarf_Die origin; Dwarf_Die *scope = die; cu_die_parent_cache_t::iterator it; do { scopes.push_back(*scope); if (dwarf_tag(scope) == DW_TAG_inlined_subroutine && dwarf_attr_die(scope, DW_AT_abstract_origin, &origin)) scope = &origin; it = parents->find(scope->addr); scope = &it->second; } while (it != parents->end()); #ifdef DEBUG_DWFLPP_GETSCOPES // there isn't an exact libdw equivalent, but if dwarf_getscopes on the // entrypc returns the same first die, then all the scopes should match Dwarf_Addr pc; if (die_entrypc(die, &pc)) { Dwarf_Die *dscopes = NULL; int nscopes = dwarf_getscopes(cu, pc, &dscopes); if (nscopes > 0 && dscopes[0].addr == die->addr) { assert(nscopes == (int)scopes.size()); for (unsigned i = 0; i < scopes.size(); ++i) assert(scopes[i].addr == dscopes[i].addr); } free(dscopes); } #endif return scopes; } std::vector dwflpp::getscopes(Dwarf_Addr pc) { // The die_parent_cache doesn't help us without knowing where the pc is // contained, so we have to do this one the old fashioned way. assert (cu); vector scopes; Dwarf_Die* dwarf_scopes; int nscopes = dwarf_getscopes(cu, pc, &dwarf_scopes); if (nscopes > 0) { scopes.assign(dwarf_scopes, dwarf_scopes + nscopes); free(dwarf_scopes); } #ifdef DEBUG_DWFLPP_GETSCOPES // check that getscopes on the starting die gets the same result if (!scopes.empty()) { vector other = getscopes(&scopes[0]); assert(scopes.size() == other.size()); for (unsigned i = 0; i < scopes.size(); ++i) assert(scopes[i].addr == other[i].addr); } #endif return scopes; } Dwarf_Die* dwflpp::get_parent_scope(Dwarf_Die* die) { Dwarf_Die specification; if (dwarf_attr_die(die, DW_AT_specification, &specification)) die = &specification; cu_die_parent_cache_t *parents = get_die_parents(); cu_die_parent_cache_t::iterator it = parents->find(die->addr); while (it != parents->end()) { Dwarf_Die* scope = &it->second; switch (dwarf_tag (scope)) { case DW_TAG_namespace: case DW_TAG_class_type: case DW_TAG_structure_type: return scope; default: break; } it = parents->find(scope->addr); } return NULL; } static const char* cache_type_prefix(Dwarf_Die* type) { switch (dwarf_tag(type)) { case DW_TAG_enumeration_type: return "enum "; case DW_TAG_structure_type: case DW_TAG_class_type: // treating struct/class as equals return "struct "; case DW_TAG_union_type: return "union "; } return ""; } /* GCC might generate a struct/class without DW_AT_declaration, but that only contains members which have DW_AT_declaration set. We aren't interested in those. PR14434 (GCC bug #54181). */ static bool has_only_decl_members (Dwarf_Die *die) { Dwarf_Die child, import; if (dwarf_child(die, &child) != 0) return false; /* no members */ do { if (! dwarf_hasattr(&child, DW_AT_declaration)) return false; /* real member found. */ int tag = dwarf_tag(&child); if ((tag == DW_TAG_namespace || tag == DW_TAG_structure_type || tag == DW_TAG_class_type) && ! has_only_decl_members (&child)) return false; /* real grand child member found. */ // Unlikely to ever happen, but if there is an imported unit // then check its children as if they are children of this DIE. if (tag == DW_TAG_imported_unit && dwarf_attr_die(&child, DW_AT_import, &import) && ! has_only_decl_members (&import)) return false; } while (dwarf_siblingof(&child, &child) == 0); return true; /* Tried all children and grandchildren. */ } int dwflpp::global_alias_caching_callback(Dwarf_Die *die, bool has_inner_types, const string& prefix, void *arg) { cu_type_cache_t *cache = static_cast(arg); const char *name = dwarf_diename(die); if (!name || dwarf_hasattr(die, DW_AT_declaration) || has_only_decl_members(die)) return DWARF_CB_OK; int tag = dwarf_tag(die); if (has_inner_types && (tag == DW_TAG_namespace || tag == DW_TAG_structure_type || tag == DW_TAG_class_type)) iterate_over_types(die, has_inner_types, prefix + name + "::", global_alias_caching_callback, arg); if (tag != DW_TAG_namespace) { string type_name = prefix + cache_type_prefix(die) + name; if (cache->find(type_name) == cache->end()) (*cache)[type_name] = *die; } return DWARF_CB_OK; } int dwflpp::global_alias_caching_callback_cus(Dwarf_Die *die, void *arg) { mod_cu_type_cache_t *global_alias_cache; global_alias_cache = &static_cast(arg)->global_alias_cache; cu_type_cache_t *v = (*global_alias_cache)[die->addr]; if (v != 0) return DWARF_CB_OK; v = new cu_type_cache_t; (*global_alias_cache)[die->addr] = v; iterate_over_globals(die, global_alias_caching_callback, v); return DWARF_CB_OK; } Dwarf_Die * dwflpp::declaration_resolve_other_cus(const string& name) { iterate_over_cus(global_alias_caching_callback_cus, this, true); for (mod_cu_type_cache_t::iterator i = global_alias_cache.begin(); i != global_alias_cache.end(); ++i) { cu_type_cache_t *v = (*i).second; if (v->find(name) != v->end()) return & ((*v)[name]); } return NULL; } Dwarf_Die * dwflpp::declaration_resolve(const string& name) { cu_type_cache_t *v = global_alias_cache[cu->addr]; if (v == 0) // need to build the cache, just once per encountered module/cu { v = new cu_type_cache_t; global_alias_cache[cu->addr] = v; iterate_over_globals(cu, global_alias_caching_callback, v); if (sess.verbose > 4) clog << _F("global alias cache %s:%s size %zu", module_name.c_str(), cu_name().c_str(), v->size()) << endl; } // XXX: it may be desirable to search other modules' declarations // too, in case a module/shared-library processes a // forward-declared pointer type only, where the actual definition // may only be in vmlinux or the application. if (v->find(name) == v->end()) return declaration_resolve_other_cus(name); return & ((*v)[name]); } Dwarf_Die * dwflpp::declaration_resolve(Dwarf_Die *type) { const char* name = dwarf_diename(type); if (!name) return NULL; string type_name = cache_type_prefix(type) + string(name); return declaration_resolve(type_name); } int dwflpp::cu_function_caching_callback (Dwarf_Die* func, void *arg) { cu_function_cache_t* v = static_cast(arg); const char *name = dwarf_diename(func); if (!name) return DWARF_CB_OK; v->insert(make_pair(string(name), *func)); return DWARF_CB_OK; } int dwflpp::mod_function_caching_callback (Dwarf_Die* cu, void *arg) { dwarf_getfuncs (cu, cu_function_caching_callback, arg, 0); return DWARF_CB_OK; } int dwflpp::iterate_over_functions (int (* callback)(Dwarf_Die * func, base_query * q), base_query * q, const string& function) { int rc = DWARF_CB_OK; assert (module); assert (cu); cu_function_cache_t *v = cu_function_cache[cu->addr]; if (v == 0) { v = new cu_function_cache_t; cu_function_cache[cu->addr] = v; dwarf_getfuncs (cu, cu_function_caching_callback, v, 0); if (sess.verbose > 4) clog << _F("function cache %s:%s size %zu", module_name.c_str(), cu_name().c_str(), v->size()) << endl; mod_info->update_symtab(v); } cu_function_cache_t::iterator it; cu_function_cache_range_t range = v->equal_range(function); if (range.first != range.second) { for (it = range.first; it != range.second; ++it) { Dwarf_Die& die = it->second; if (sess.verbose > 4) clog << _F("function cache %s:%s hit %s", module_name.c_str(), cu_name().c_str(), function.c_str()) << endl; rc = (*callback)(& die, q); if (rc != DWARF_CB_OK) break; } } else if (startswith(function, "_Z")) { // C++ names are mangled starting with a "_Z" prefix. Most of the time // we can discover the mangled name from a die's MIPS_linkage_name // attribute, so we read that to match against the user's function // pattern. Note that this isn't perfect, as not all will have that // attribute (notably ctors and dtors), but we do what we can... for (it = v->begin(); it != v->end(); ++it) { if (pending_interrupts) return DWARF_CB_ABORT; Dwarf_Die& die = it->second; const char* linkage_name = NULL; if ((linkage_name = dwarf_linkage_name (&die)) && function_name_matches_pattern (linkage_name, function)) { if (sess.verbose > 4) clog << _F("function cache %s:%s match %s vs %s", module_name.c_str(), cu_name().c_str(), linkage_name, function.c_str()) << endl; rc = (*callback)(& die, q); if (rc != DWARF_CB_OK) break; } } } else if (name_has_wildcard (function)) { for (it = v->begin(); it != v->end(); ++it) { if (pending_interrupts) return DWARF_CB_ABORT; const string& func_name = it->first; Dwarf_Die& die = it->second; if (function_name_matches_pattern (func_name, function)) { if (sess.verbose > 4) clog << _F("function cache %s:%s match %s vs %s", module_name.c_str(), cu_name().c_str(), func_name.c_str(), function.c_str()) << endl; rc = (*callback)(& die, q); if (rc != DWARF_CB_OK) break; } } } else // not a linkage name or wildcard and no match in this CU { // do nothing } return rc; } int dwflpp::iterate_single_function (int (* callback)(Dwarf_Die * func, base_query * q), base_query * q, const string& function) { int rc = DWARF_CB_OK; assert (module); get_module_dwarf(false); if (!module_dwarf) return rc; cu_function_cache_t *v = mod_function_cache[module_dwarf]; if (v == 0) { v = new cu_function_cache_t; mod_function_cache[module_dwarf] = v; iterate_over_cus (mod_function_caching_callback, v, false); if (sess.verbose > 4) clog << _F("module function cache %s size %zu", module_name.c_str(), v->size()) << endl; mod_info->update_symtab(v); } cu_function_cache_t::iterator it; cu_function_cache_range_t range = v->equal_range(function); if (range.first != range.second) { for (it = range.first; it != range.second; ++it) { Dwarf_Die cu_mem; Dwarf_Die& die = it->second; if (sess.verbose > 4) clog << _F("module function cache %s hit %s", module_name.c_str(), function.c_str()) << endl; // since we're iterating out of cu-context, we need each focus focus_on_cu(dwarf_diecu(&die, &cu_mem, NULL, NULL)); rc = (*callback)(& die, q); if (rc != DWARF_CB_OK) break; } } // undo the focus_on_cu this->cu = NULL; this->function_name.clear(); this->function = NULL; return rc; } /* This basically only goes one level down from the compile unit so it * only picks up top level stuff (i.e. nothing in a lower scope) */ int dwflpp::iterate_over_globals (Dwarf_Die *cu_die, int (* callback)(Dwarf_Die *, bool, const string&, void *), void * data) { assert (cu_die); assert (dwarf_tag(cu_die) == DW_TAG_compile_unit || dwarf_tag(cu_die) == DW_TAG_type_unit || dwarf_tag(cu_die) == DW_TAG_partial_unit); // Ignore partial_unit, if they get imported by a real unit, then // iterate_over_types will traverse them. if (dwarf_tag(cu_die) == DW_TAG_partial_unit) return DWARF_CB_OK; // If this is C++, recurse for any inner types bool has_inner_types = dwarf_srclang(cu_die) == DW_LANG_C_plus_plus; return iterate_over_types(cu_die, has_inner_types, "", callback, data); } int dwflpp::iterate_over_types (Dwarf_Die *top_die, bool has_inner_types, const string& prefix, int (* callback)(Dwarf_Die *, bool, const string&, void *), void * data) { int rc = DWARF_CB_OK; Dwarf_Die die, import; assert (top_die); if (dwarf_child(top_die, &die) != 0) return rc; do /* We're only currently looking for named types, * although other types of declarations exist */ switch (dwarf_tag(&die)) { case DW_TAG_base_type: case DW_TAG_enumeration_type: case DW_TAG_structure_type: case DW_TAG_class_type: case DW_TAG_typedef: case DW_TAG_union_type: case DW_TAG_namespace: rc = (*callback)(&die, has_inner_types, prefix, data); break; case DW_TAG_imported_unit: // Follow the imported_unit and iterate over its contents // (either a partial_unit or a full compile_unit), all its // children should be treated as if they appear in this place. if (dwarf_attr_die(&die, DW_AT_import, &import)) rc = iterate_over_types(&import, has_inner_types, prefix, callback, data); break; } while (rc == DWARF_CB_OK && dwarf_siblingof(&die, &die) == 0); return rc; } /* For each notes section in the current module call 'callback', use * 'data' for the notes buffer and pass 'object' back in case * 'callback' is a method */ int dwflpp::iterate_over_notes (void *object, void (*callback)(void *object, int type, const char *data, size_t len)) { Dwarf_Addr bias; // Note we really want the actual elf file, not the dwarf .debug file. // Older binutils had a bug where they mangled the SHT_NOTE type during // --keep-debug. Elf* elf = dwfl_module_getelf (module, &bias); size_t shstrndx; if (elf_getshdrstrndx (elf, &shstrndx)) return elf_errno(); Elf_Scn *scn = NULL; vector notes; while ((scn = elf_nextscn (elf, scn)) != NULL) { GElf_Shdr shdr; if (gelf_getshdr (scn, &shdr) == NULL) continue; switch (shdr.sh_type) { case SHT_NOTE: if (!(shdr.sh_flags & SHF_ALLOC)) { Elf_Data *data = elf_getdata (scn, NULL); size_t next; GElf_Nhdr nhdr; size_t name_off; size_t desc_off; for (size_t offset = 0; (next = gelf_getnote (data, offset, &nhdr, &name_off, &desc_off)) > 0; offset = next) (*callback) (object, nhdr.n_type, (const char*)((long)(data->d_buf) + (long)desc_off), nhdr.n_descsz); } break; } } return 0; } /* For each entry in the .dynamic section in the current module call 'callback' * returning 'object' in case 'callback' is a method */ void dwflpp::iterate_over_libraries (void (*callback)(void *object, const char *arg), void *q) { std::set added; string interpreter; assert (this->module_name.length() != 0); Dwarf_Addr bias; // We cannot use this: dwarf_getelf (dwfl_module_getdwarf (module, &bias)) Elf *elf = dwfl_module_getelf (module, &bias); // elf_getphdrnum (elf, &phnum) is not available in all versions of elfutils // needs libelf from elfutils 0.144+ for (int i = 0; ; i++) { GElf_Phdr mem; GElf_Phdr *phdr; phdr = gelf_getphdr (elf, i, &mem); if (phdr == NULL) break; if (phdr->p_type == PT_INTERP) { size_t maxsize; char *filedata = elf_rawfile (elf, &maxsize); if (filedata != NULL && phdr->p_offset < maxsize) interpreter = (char*) (filedata + phdr->p_offset); break; } } if (interpreter.length() == 0) return; // If it gets cumbersome to maintain this whitelist, we could just check for // startswith("/lib/ld") || startswith("/lib64/ld"), and trust that no admin // would install untrustworthy loaders in those paths. // See also http://sourceware.org/git/?p=glibc.git;a=blob;f=shlib-versions;hb=HEAD if (interpreter != "/lib/ld.so.1" // s390, ppc && interpreter != "/lib/ld64.so.1" // s390x, ppc64 && interpreter != "/lib64/ld64.so.1" && interpreter != "/lib/ld-linux-ia64.so.2" // ia64 && interpreter != "/emul/ia32-linux/lib/ld-linux.so.2" && interpreter != "/lib64/ld-linux-x86-64.so.2" // x8664 && interpreter != "/lib/ld-linux.so.2" // x86 && interpreter != "/lib/ld-linux.so.3" // arm && interpreter != "/lib/ld-linux-armhf.so.3" // arm ) { sess.print_warning (_F("module %s --ldd skipped: unsupported interpreter: %s", module_name.c_str(), interpreter.c_str())); return; } vector ldd_command; ldd_command.push_back("/usr/bin/env"); ldd_command.push_back("LD_TRACE_LOADED_OBJECTS=1"); ldd_command.push_back("LD_WARN=yes"); ldd_command.push_back("LD_BIND_NOW=yes"); ldd_command.push_back(interpreter); ldd_command.push_back(module_name); FILE *fp; int child_fd; pid_t child = stap_spawn_piped(sess.verbose, ldd_command, NULL, &child_fd); if (child <= 0 || !(fp = fdopen(child_fd, "r"))) clog << _F("library iteration on %s failed: %s", module_name.c_str(), strerror(errno)) << endl; else { while (1) // this parsing loop borrowed from add_unwindsym_ldd { char linebuf[256]; char *soname = 0; char *shlib = 0; unsigned long int addr = 0; char *line = fgets (linebuf, 256, fp); if (line == 0) break; // EOF or error #if __GLIBC__ >2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7) #define MS_FMT "%ms" #else #define MS_FMT "%as" #endif // Try soname => shlib (0xaddr) int nf = sscanf (line, MS_FMT " => " MS_FMT " (0x%lx)", &soname, &shlib, &addr); if (nf != 3 || shlib[0] != '/') { // Try shlib (0xaddr) nf = sscanf (line, " " MS_FMT " (0x%lx)", &shlib, &addr); if (nf != 2 || shlib[0] != '/') continue; // fewer than expected fields, or bad shlib. } if (added.find (shlib) == added.end()) { if (sess.verbose > 2) { clog << _F("Added -d '%s", shlib); if (nf == 3) clog << _F("' due to '%s'", soname); else clog << "'"; clog << endl; } added.insert (shlib); } free (soname); free (shlib); } if ((fclose(fp) || stap_waitpid(sess.verbose, child))) sess.print_warning("failed to read libraries from " + module_name + ": " + strerror(errno)); } for (std::set::iterator it = added.begin(); it != added.end(); it++) { string modname = *it; (callback) (q, modname.c_str()); } } /* For each plt section in the current module call 'callback', pass the plt entry * 'address' and 'name' back, and pass 'object' back in case 'callback' is a method */ int dwflpp::iterate_over_plt (void *object, void (*callback)(void *object, const char *name, size_t addr)) { Dwarf_Addr load_addr; // Note we really want the actual elf file, not the dwarf .debug file. Elf* elf = dwfl_module_getelf (module, &load_addr); size_t shstrndx; assert (elf_getshdrstrndx (elf, &shstrndx) >= 0); // Get the load address for (int i = 0; ; i++) { GElf_Phdr mem; GElf_Phdr *phdr; phdr = gelf_getphdr (elf, i, &mem); if (phdr == NULL) break; if (phdr->p_type == PT_LOAD) { load_addr = phdr->p_vaddr; break; } } // Get the plt section header Elf_Scn *scn = NULL; GElf_Shdr *plt_shdr = NULL; GElf_Shdr plt_shdr_mem; while ((scn = elf_nextscn (elf, scn))) { plt_shdr = gelf_getshdr (scn, &plt_shdr_mem); assert (plt_shdr != NULL); if (strcmp (elf_strptr (elf, shstrndx, plt_shdr->sh_name), ".plt") == 0) break; } // Layout of the plt section int plt0_entry_size; int plt_entry_size; GElf_Ehdr ehdr_mem; GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem); switch (em->e_machine) { case EM_386: plt0_entry_size = 16; plt_entry_size = 16; break; case EM_X86_64: plt0_entry_size = 16; plt_entry_size = 16; break; case EM_ARM: plt0_entry_size = 20; plt_entry_size = 12; break; case EM_PPC64: case EM_S390: case EM_PPC: default: throw semantic_error(".plt is not supported on this architecture"); } scn = NULL; while ((scn = elf_nextscn (elf, scn))) { GElf_Shdr shdr_mem; GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); bool have_rela = false; bool have_rel = false; if (shdr == NULL) continue; assert (shdr != NULL); if ((have_rela = (strcmp (elf_strptr (elf, shstrndx, shdr->sh_name), ".rela.plt") == 0)) || (have_rel = (strcmp (elf_strptr (elf, shstrndx, shdr->sh_name), ".rel.plt") == 0))) { /* Get the data of the section. */ Elf_Data *data = elf_getdata (scn, NULL); assert (data != NULL); /* Get the symbol table information. */ Elf_Scn *symscn = elf_getscn (elf, shdr->sh_link); GElf_Shdr symshdr_mem; GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); assert (symshdr != NULL); Elf_Data *symdata = elf_getdata (symscn, NULL); assert (symdata != NULL); unsigned int nsyms = shdr->sh_size / shdr->sh_entsize; for (unsigned int cnt = 0; cnt < nsyms; ++cnt) { GElf_Ehdr ehdr_mem; GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem); if (em == 0) { dwfl_assert ("dwfl_getehdr", dwfl_errno()); } GElf_Rela relamem; GElf_Rela *rela = NULL; GElf_Rel relmem; GElf_Rel *rel = NULL; if (have_rela) { rela = gelf_getrela (data, cnt, &relamem); assert (rela != NULL); } else if (have_rel) { rel = gelf_getrel (data, cnt, &relmem); assert (rel != NULL); } GElf_Sym symmem; Elf32_Word xndx; Elf_Data *xndxdata = NULL; GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (have_rela ? rela->r_info : rel->r_info), &symmem, &xndx); assert (sym != NULL); Dwarf_Addr addr = plt_shdr->sh_offset + plt0_entry_size + cnt * plt_entry_size; if (elf_strptr (elf, symshdr->sh_link, sym->st_name)) (*callback) (object, elf_strptr (elf, symshdr->sh_link, sym->st_name), addr + load_addr); } break; // while scn } } return 0; } // This little test routine represents an unfortunate breakdown in // abstraction between dwflpp (putatively, a layer right on top of // elfutils), and dwarf_query (interpreting a systemtap probe point). // It arises because we sometimes try to fix up slightly-off // .statement() probes (something we find out in fairly low-level). // // An alternative would be to put some more intelligence into query_cu(), // and have it print additional suggestions after finding that // q->dw.iterate_over_srcfile_lines resulted in no new finished_results. bool dwflpp::has_single_line_record (dwarf_query * q, char const * srcfile, int lineno) { if (lineno < 0) return false; Dwarf_Line **srcsp = NULL; size_t nsrcs = 0; dwarf_assert ("dwarf_getsrc_file", dwarf_getsrc_file (module_dwarf, srcfile, lineno, 0, &srcsp, &nsrcs)); if (nsrcs != 1) { if (sess.verbose>4) clog << _F("alternative line %d rejected: nsrcs=%zu", lineno, nsrcs) << endl; return false; } // We also try to filter out lines that leave the selected // functions (if any). dwarf_line_t line(srcsp[0]); Dwarf_Addr addr = line.addr(); func_info_map_t *filtered_functions = get_filtered_functions(q); for (func_info_map_t::iterator i = filtered_functions->begin(); i != filtered_functions->end(); ++i) { if (die_has_pc (i->die, addr)) { if (sess.verbose>4) clog << _F("alternative line %d accepted: fn=%s", lineno, i->name.c_str()) << endl; return true; } } inline_instance_map_t *filtered_inlines = get_filtered_inlines(q); for (inline_instance_map_t::iterator i = filtered_inlines->begin(); i != filtered_inlines->end(); ++i) { if (die_has_pc (i->die, addr)) { if (sess.verbose>4) clog << _F("alternative line %d accepted: ifn=%s", lineno, i->name.c_str()) << endl; return true; } } if (sess.verbose>4) //TRANSLATORS: given line number leaves (is beyond) given function. clog << _F("alternative line %d rejected: leaves selected fns", lineno) << endl; return false; } void dwflpp::iterate_over_srcfile_lines (char const * srcfile, int lines[2], bool need_single_match, enum line_t line_type, void (* callback) (const dwarf_line_t& line, void * arg), const std::string& func_pattern, void *data) { Dwarf_Line **srcsp = NULL; size_t nsrcs = 0; dwarf_query * q = static_cast(data); int lineno = lines[0]; auto_free_ref free_srcsp(srcsp); get_module_dwarf(); if (!this->function) return; if (line_type == RELATIVE) { Dwarf_Addr addr; Dwarf_Line *line; int line_number; die_entrypc(this->function, &addr); if (addr != 0) { line = dwarf_getsrc_die (this->cu, addr); dwarf_assert ("dwarf_getsrc_die", line == NULL); dwarf_assert ("dwarf_lineno", dwarf_lineno (line, &line_number)); } else if (dwarf_decl_line (this->function, &line_number) != 0) { // use DW_AT_decl_line as a fallback method Dwarf_Attribute type_attr; Dwarf_Word constant; if (dwarf_attr_integrate (this->function, DW_AT_decl_line, &type_attr)) { dwarf_formudata (&type_attr, &constant); line_number = constant; } else return; } lineno += line_number; } else if (line_type == WILDCARD) { if (name_has_wildcard(func_pattern)) /* PR14774: look at whole file if function name is wildcard */ lineno = 0; else function_line (&lineno); } else if (line_type == RANGE) { /* correct lineno */ int start_lineno; if (name_has_wildcard(func_pattern)) /* PR10294: wider range like statement("*@foo.c") */ start_lineno = lineno; else function_line (&start_lineno); lineno = lineno < start_lineno ? start_lineno : lineno; if (lineno > lines[1]) { /* invalid line range */ stringstream advice; advice << _("Invalid line range (") << lines[0] << "-" << lines[1] << ")"; if (start_lineno > lines[1]) advice << _(", the end line number ") << lines[1] << " < " << start_lineno; throw semantic_error (advice.str()); } } for (int l = lineno; ; l = l + 1) { set lines_probed; pair::iterator,bool> line_probed; int ret = 0; assert_no_interrupts(); nsrcs = 0; ret = dwarf_getsrc_file (module_dwarf, srcfile, l, 0, &srcsp, &nsrcs); if (ret != 0) /* tolerate invalid line number */ break; if (line_type == WILDCARD || line_type == RANGE) { Dwarf_Addr line_addr; dwarf_lineno (srcsp [0], &lineno); /* Maybe lineno will exceed the input end */ if (line_type == RANGE && lineno > lines[1]) break; line_probed = lines_probed.insert(lineno); if (lineno != l || line_probed.second == false || nsrcs > 1) continue; dwarf_lineaddr (srcsp [0], &line_addr); if (!function_name_matches(func_pattern) && dwarf_haspc (function, line_addr) != 1) break; } // NB: Formerly, we used to filter, because: // dwarf_getsrc_file gets one *near hits* for line numbers, not // exact matches. For example, an existing file but a nonexistent // line number will be rounded up to the next definition in that // file. This may be similar to the GDB breakpoint algorithm, but // we don't want to be so fuzzy in systemtap land. So we filter. // But we now see the error of our ways, and skip this filtering. // XXX: the code also fails to match e.g. inline function // definitions when the srcfile is a header file rather than the // CU name. size_t remaining_nsrcs = nsrcs; if (need_single_match && remaining_nsrcs > 1) { // We wanted a single line record (a unique address for the // line) and we got a bunch of line records. We're going to // skip this probe (throw an exception) but before we throw // we're going to look around a bit to see if there's a low or // high line number nearby which *doesn't* have this problem, // so we can give the user some advice. int lo_try = -1; int hi_try = -1; for (size_t i = 1; i < 6; ++i) { if (lo_try == -1 && has_single_line_record(q, srcfile, lineno - i)) lo_try = lineno - i; if (hi_try == -1 && has_single_line_record(q, srcfile, lineno + i)) hi_try = lineno + i; } stringstream advice; advice << _F("multiple addresses for %s:%d [man error::dwarf]", srcfile, lineno); if (lo_try > 0 || hi_try > 0) { //TRANSLATORS: Here we are trying to advise what source file //TRANSLATORS: to attempt. advice << _(" (try "); if (lo_try > 0) advice << srcfile << ":" << lo_try; if (lo_try > 0 && hi_try > 0) advice << _(" or "); if (hi_try > 0) advice << srcfile << ":" << hi_try; advice << ")"; } throw semantic_error (advice.str()); } for (size_t i = 0; i < nsrcs; ++i) { assert_no_interrupts(); if (srcsp [i]) // skip over mismatched lines callback (dwarf_line_t(srcsp[i]), data); } if (line_type == ABSOLUTE || line_type == RELATIVE) break; else if (line_type == RANGE && l == lines[1]) break; } } void dwflpp::iterate_over_labels (Dwarf_Die *begin_die, const string& sym, const string& function, dwarf_query *q, void (* callback)(const string &, const char *, const char *, int, Dwarf_Die *, Dwarf_Addr, dwarf_query *)) { get_module_dwarf(); Dwarf_Die die, import; const char *name; int res = dwarf_child (begin_die, &die); if (res != 0) return; // die without children, bail out. do { switch (dwarf_tag(&die)) { case DW_TAG_label: name = dwarf_diename (&die); if (name && (name == sym || (name_has_wildcard(sym) && function_name_matches_pattern (name, sym)))) { // Don't try to be smart. Just drop no addr labels. Dwarf_Addr stmt_addr; if (dwarf_lowpc (&die, &stmt_addr) == 0) { // Get the file/line number for this label int dline; const char *file = dwarf_decl_file (&die); dwarf_decl_line (&die, &dline); vector scopes = getscopes_die(&die); if (scopes.size() > 1) { Dwarf_Die scope; if (!inner_die_containing_pc(scopes[1], stmt_addr, scope)) { sess.print_warning(_F("label '%s' at address %s (dieoffset: %s) is not " "contained by its scope '%s' (dieoffset: %s) -- bad" " debuginfo? [man error::dwarf]", name, lex_cast_hex(stmt_addr).c_str(), lex_cast_hex(dwarf_dieoffset(&die)).c_str(), (dwarf_diename(&scope) ?: ""), lex_cast_hex(dwarf_dieoffset(&scope)).c_str())); } callback(function, name, file, dline, &scope, stmt_addr, q); } } } break; case DW_TAG_subprogram: case DW_TAG_inlined_subroutine: // Stay within our filtered function break; case DW_TAG_imported_unit: // Iterate over the children of the imported unit as if they // were inserted in place. if (dwarf_attr_die(&die, DW_AT_import, &import)) iterate_over_labels (&import, sym, function, q, callback); break; default: if (dwarf_haschildren (&die)) iterate_over_labels (&die, sym, function, q, callback); break; } } while (dwarf_siblingof (&die, &die) == 0); } void dwflpp::collect_srcfiles_matching (string const & pattern, set & filtered_srcfiles) { assert (module); assert (cu); size_t nfiles; Dwarf_Files *srcfiles; // PR 5049: implicit * in front of given path pattern. // NB: fnmatch() is used without FNM_PATHNAME. string prefixed_pattern = string("*/") + pattern; dwarf_assert ("dwarf_getsrcfiles", dwarf_getsrcfiles (cu, &srcfiles, &nfiles)); { for (size_t i = 0; i < nfiles; ++i) { char const * fname = dwarf_filesrc (srcfiles, i, NULL, NULL); if (fnmatch (pattern.c_str(), fname, 0) == 0 || fnmatch (prefixed_pattern.c_str(), fname, 0) == 0) { filtered_srcfiles.insert (fname); if (sess.verbose>2) clog << _F("selected source file '%s'\n", fname); } } } } void dwflpp::resolve_prologue_endings (func_info_map_t & funcs) { // This heuristic attempts to pick the first address that has a // source line distinct from the function declaration's. In a // perfect world, this would be the first statement *past* the // prologue. assert(module); assert(cu); size_t nlines = 0; Dwarf_Lines *lines = NULL; /* trouble cases: malloc do_symlink in init/initramfs.c tail-recursive/tiny then no-prologue sys_get?id in kernel/timer.c no-prologue sys_exit_group tail-recursive {do_,}sys_open extra-long-prologue (gcc 3.4) cpu_to_logical_apicid NULL-decl_file */ // Fetch all srcline records, sorted by address. dwarf_assert ("dwarf_getsrclines", dwarf_getsrclines(cu, &lines, &nlines)); // XXX: free lines[] later, but how? for(func_info_map_t::iterator it = funcs.begin(); it != funcs.end(); it++) { #if 0 /* someday */ Dwarf_Addr* bkpts = 0; int n = dwarf_entry_breakpoints (& it->die, & bkpts); // ... free (bkpts); #endif Dwarf_Addr entrypc = it->entrypc; Dwarf_Addr highpc; // NB: highpc is exclusive: [entrypc,highpc) dwfl_assert ("dwarf_highpc", dwarf_highpc (& it->die, & highpc)); if (it->decl_file == 0) it->decl_file = ""; unsigned entrypc_srcline_idx = 0; dwarf_line_t entrypc_srcline; // open-code binary search for exact match { unsigned l = 0, h = nlines; while (l < h) { entrypc_srcline_idx = (l + h) / 2; const dwarf_line_t lr(dwarf_onesrcline(lines, entrypc_srcline_idx)); Dwarf_Addr addr = lr.addr(); if (addr == entrypc) { entrypc_srcline = lr; break; } else if (l + 1 == h) { break; } // ran off bottom of tree else if (addr < entrypc) { l = entrypc_srcline_idx; } else { h = entrypc_srcline_idx; } } } if (!entrypc_srcline) { if (sess.verbose > 2) clog << _F("missing entrypc dwarf line record for function '%s'\n", it->name.c_str()); // This is probably an inlined function. We'll end up using // its lowpc as a probe address. continue; } if (entrypc == 0) { if (sess.verbose > 2) clog << _F("null entrypc dwarf line record for function '%s'\n", it->name.c_str()); // This is probably an inlined function. We'll skip this instance; // it is messed up. continue; } if (sess.verbose>2) clog << _F("searching for prologue of function '%s' %#" PRIx64 "-%#" PRIx64 "@%s:%d\n", it->name.c_str(), entrypc, highpc, it->decl_file, it->decl_line); // Now we go searching for the first line record that has a // file/line different from the one in the declaration. // Normally, this will be the next one. BUT: // // We may have to skip a few because some old compilers plop // in dummy line records for longer prologues. If we go too // far (addr >= highpc), we take the previous one. Or, it may // be the first one, if the function had no prologue, and thus // the entrypc maps to a statement in the body rather than the // declaration. unsigned postprologue_srcline_idx = entrypc_srcline_idx; bool ranoff_end = false; while (postprologue_srcline_idx < nlines) { dwarf_line_t lr(dwarf_onesrcline(lines, postprologue_srcline_idx)); Dwarf_Addr postprologue_addr = lr.addr(); const char* postprologue_file = lr.linesrc(); int postprologue_lineno = lr.lineno(); if (sess.verbose>2) clog << _F("checking line record %#" PRIx64 "@%s:%d\n", postprologue_addr, postprologue_file, postprologue_lineno); if (postprologue_addr >= highpc) { ranoff_end = true; postprologue_srcline_idx --; continue; } if (ranoff_end || (strcmp (postprologue_file, it->decl_file) || // We have a winner! (postprologue_lineno != it->decl_line))) { it->prologue_end = postprologue_addr; if (sess.verbose>2) { clog << _F("prologue found function '%s'", it->name.c_str()); // Add a little classification datum //TRANSLATORS: Here we're adding some classification datum (ie Prologue Free) if (postprologue_srcline_idx == entrypc_srcline_idx) clog << _(" (naked)"); //TRANSLATORS: Here we're adding some classification datum (ie Prologue Free) if (ranoff_end) clog << _(" (tail-call?)"); clog << " = 0x" << hex << postprologue_addr << dec << "\n"; } break; } // Let's try the next srcline. postprologue_srcline_idx ++; } // loop over srclines // if (strlen(it->decl_file) == 0) it->decl_file = NULL; } // loop over functions // XXX: how to free lines? } bool dwflpp::function_entrypc (Dwarf_Addr * addr) { assert (function); return (dwarf_entrypc (function, addr) == 0); } bool dwflpp::die_entrypc (Dwarf_Die * die, Dwarf_Addr * addr) { int rc = 0; string lookup_method; * addr = 0; lookup_method = "dwarf_entrypc"; rc = dwarf_entrypc (die, addr); if (rc) { lookup_method = "dwarf_ranges"; Dwarf_Addr base; Dwarf_Addr begin; Dwarf_Addr end; ptrdiff_t offset = dwarf_ranges (die, 0, &base, &begin, &end); if (offset < 0) rc = -1; else if (offset > 0) { * addr = begin; rc = 0; // Now we need to check that there are no more ranges // associated with this function, which could conceivably // happen if a function is inlined, then pieces of it are // split amongst different conditional branches. It's not // obvious which of them to favour. As a heuristic, we // pick the beginning of the first range, and ignore the // others (but with a warning). unsigned extra = 0; while ((offset = dwarf_ranges (die, offset, &base, &begin, &end)) > 0) extra ++; if (extra) lookup_method += _F(", ignored %s more", lex_cast(extra).c_str()); } } // PR10574: reject subprograms where the entrypc address turns out // to be 0, since they tend to correspond to duplicate-eliminated // COMDAT copies of C++ functions. if (rc == 0 && *addr == 0) { lookup_method += _(" (skip comdat)"); rc = 1; } if (sess.verbose > 2) clog << _F("entry-pc lookup (%s dieoffset: %s) = %#" PRIx64 " (rc %d)", lookup_method.c_str(), lex_cast_hex(dwarf_dieoffset(die)).c_str(), *addr, rc) << endl; return (rc == 0); } void dwflpp::function_die (Dwarf_Die *d) { assert (function); *d = *function; } void dwflpp::function_file (char const ** c) { assert (function); assert (c); *c = dwarf_decl_file (function); } void dwflpp::function_line (int *linep) { assert (function); dwarf_decl_line (function, linep); } bool dwflpp::die_has_pc (Dwarf_Die & die, Dwarf_Addr pc) { int res = dwarf_haspc (&die, pc); // dwarf_ranges will return -1 if a function die has no DW_AT_ranges // if (res == -1) // dwarf_assert ("dwarf_haspc", res); return res == 1; } bool dwflpp::inner_die_containing_pc(Dwarf_Die& scope, Dwarf_Addr addr, Dwarf_Die& result) { result = scope; // Sometimes we're in a bad scope to begin with -- just let it be. This can // happen for example if the compiler outputs a label PC that's just outside // the lexical scope. We can't really do anything about that, but variables // will probably not be accessible in this case. if (!die_has_pc(scope, addr)) return false; Dwarf_Die child, import; int rc = dwarf_child(&result, &child); while (rc == 0) { switch (dwarf_tag (&child)) { case DW_TAG_imported_unit: // The children of the imported unit need to be treated as if // they are inserted here. So look inside and set result if // found. if (dwarf_attr_die(&child, DW_AT_import, &import)) { Dwarf_Die import_result; if (inner_die_containing_pc(import, addr, import_result)) { result = import_result; return true; } } break; // lexical tags to recurse within the same starting scope // NB: this intentionally doesn't cross into inlines! case DW_TAG_lexical_block: case DW_TAG_with_stmt: case DW_TAG_catch_block: case DW_TAG_try_block: case DW_TAG_entry_point: if (die_has_pc(child, addr)) { result = child; rc = dwarf_child(&result, &child); continue; } } rc = dwarf_siblingof(&child, &child); } return true; } void dwflpp::loc2c_error (void *, const char *fmt, ...) { const char *msg = "?"; char *tmp = NULL; int rc; va_list ap; va_start (ap, fmt); rc = vasprintf (& tmp, fmt, ap); if (rc < 0) msg = "?"; else msg = tmp; va_end (ap); throw semantic_error (msg); } // This function generates code used for addressing computations of // target variables. void dwflpp::emit_address (struct obstack *pool, Dwarf_Addr address) { int n = dwfl_module_relocations (module); dwfl_assert ("dwfl_module_relocations", n >= 0); Dwarf_Addr reloc_address = address; const char *secname = ""; if (n > 1) { int i = dwfl_module_relocate_address (module, &reloc_address); dwfl_assert ("dwfl_module_relocate_address", i >= 0); secname = dwfl_module_relocation_info (module, i, NULL); } if (sess.verbose > 2) { clog << _F("emit dwarf addr %#" PRIx64 " => module %s section %s relocaddr %#" PRIx64, address, module_name.c_str (), (secname ?: "null"), reloc_address) << endl; } if (n > 0 && !(n == 1 && secname == NULL)) { dwfl_assert ("dwfl_module_relocation_info", secname); if (n > 1 || secname[0] != '\0') { // This gives us the module name, and section name within the // module, for a kernel module (or other ET_REL module object). obstack_printf (pool, "({ unsigned long addr = 0; "); obstack_printf (pool, "addr = _stp_kmodule_relocate (\"%s\",\"%s\",%#" PRIx64 "); ", module_name.c_str(), secname, reloc_address); obstack_printf (pool, "addr; })"); } else if (n == 1 && module_name == TOK_KERNEL && secname[0] == '\0') { // elfutils' way of telling us that this is a relocatable kernel address, which we // need to treat the same way here as dwarf_query::add_probe_point does: _stext. address -= sess.sym_stext; secname = "_stext"; // Note we "cache" the result here through a static because the // kernel will never move after being loaded (unlike modules and // user-space dynamic share libraries). obstack_printf (pool, "({ static unsigned long addr = 0; "); obstack_printf (pool, "if (addr==0) addr = _stp_kmodule_relocate (\"%s\",\"%s\",%#" PRIx64 "); ", module_name.c_str(), secname, address); // PR10000 NB: not reloc_address obstack_printf (pool, "addr; })"); } else { obstack_printf (pool, "/* pragma:vma */"); obstack_printf (pool, "({ unsigned long addr = 0; "); obstack_printf (pool, "addr = _stp_umodule_relocate (\"%s\",%#" PRIx64 ", current); ", canonicalize_file_name(module_name.c_str()), address); obstack_printf (pool, "addr; })"); } } else obstack_printf (pool, "%#" PRIx64 "UL", address); // assume as constant } void dwflpp::loc2c_emit_address (void *arg, struct obstack *pool, Dwarf_Addr address) { static_cast(arg)->emit_address (pool, address); } void dwflpp::print_locals(vector& scopes, ostream &o) { // XXX Shouldn't this be walking up to outer scopes too? print_locals_die(scopes[0], o); } void dwflpp::print_locals_die(Dwarf_Die& die, ostream &o) { // Try to get the first child of die. Dwarf_Die child, import; if (dwarf_child (&die, &child) == 0) { do { const char *name; // Output each sibling's name (that is a variable or // parameter) to 'o'. switch (dwarf_tag (&child)) { case DW_TAG_variable: case DW_TAG_formal_parameter: name = dwarf_diename (&child); if (name) o << " $" << name; break; case DW_TAG_imported_unit: // Treat the imported unit children as if they are // children of the given DIE. if (dwarf_attr_die(&child, DW_AT_import, &import)) print_locals_die (import, o); break; default: break; } } while (dwarf_siblingof (&child, &child) == 0); } } Dwarf_Attribute * dwflpp::find_variable_and_frame_base (vector& scopes, Dwarf_Addr pc, string const & local, const target_symbol *e, Dwarf_Die *vardie, Dwarf_Attribute *fb_attr_mem) { Dwarf_Die *scope_die = &scopes[0]; Dwarf_Attribute *fb_attr = NULL; assert (cu); int declaring_scope = dwarf_getscopevar (&scopes[0], scopes.size(), local.c_str(), 0, NULL, 0, 0, vardie); if (declaring_scope < 0) { stringstream alternatives; print_locals (scopes, alternatives); if (pc) throw semantic_error (_F("unable to find local '%s', [man error::dwarf] dieoffset %s in %s, near pc %s %s %s %s (%s)", local.c_str(), lex_cast_hex(dwarf_dieoffset(scope_die)).c_str(), module_name.c_str(), lex_cast_hex(pc).c_str(), (scope_die == NULL) ? "" : _("in"), (dwarf_diename(scope_die) ?: ""), (dwarf_diename(cu) ?: ""), (alternatives.str() == "" ? (_("")) : (_("alternatives:") + alternatives.str())).c_str()), e->tok); else throw semantic_error (_F("unable to find global '%s', [man error::dwarf] dieoffset %s in %s, %s %s %s (%s)", local.c_str(), lex_cast_hex(dwarf_dieoffset(scope_die)).c_str(), module_name.c_str(), (scope_die == NULL) ? "" : _("in"), (dwarf_diename(scope_die) ?: ""), cu_name().c_str(), (alternatives.str() == "" ? (_("")) : (_("alternatives:") + alternatives.str())).c_str()), e->tok); } /* Some GCC versions would output duplicate external variables, one without a location attribute. If so, try to find the other if it exists in the same scope. See GCC PR51410. */ Dwarf_Attribute attr_mem; if (dwarf_attr_integrate (vardie, DW_AT_const_value, &attr_mem) == NULL && dwarf_attr_integrate (vardie, DW_AT_location, &attr_mem) == NULL && dwarf_attr_integrate (vardie, DW_AT_external, &attr_mem) != NULL && dwarf_tag(&scopes[declaring_scope]) == DW_TAG_compile_unit) { Dwarf_Die orig_vardie = *vardie; bool alt_found = false; if (dwarf_child(&scopes[declaring_scope], vardie) == 0) do { // Note, not handling DW_TAG_imported_unit, assuming GCC // version is recent enough to not need this workaround if // we would see an imported unit. if (dwarf_tag (vardie) == DW_TAG_variable && strcmp (dwarf_diename (vardie), local.c_str ()) == 0 && (dwarf_attr_integrate (vardie, DW_AT_external, &attr_mem) != NULL) && ((dwarf_attr_integrate (vardie, DW_AT_const_value, &attr_mem) != NULL) || (dwarf_attr_integrate (vardie, DW_AT_location, &attr_mem) != NULL))) alt_found = true; } while (!alt_found && dwarf_siblingof(vardie, vardie) == 0); if (! alt_found) *vardie = orig_vardie; } // Global vars don't need (cannot use) frame base in location descriptor. if (pc == 0) return NULL; /* We start out walking the "lexical scopes" as returned by * as returned by dwarf_getscopes for the address, starting with the * declaring_scope that the variable was found in. */ vector physcopes, *fbscopes = &scopes; for (size_t inner = declaring_scope; inner < fbscopes->size() && fb_attr == NULL; ++inner) { Dwarf_Die& scope = (*fbscopes)[inner]; switch (dwarf_tag (&scope)) { default: continue; case DW_TAG_subprogram: case DW_TAG_entry_point: fb_attr = dwarf_attr_integrate (&scope, DW_AT_frame_base, fb_attr_mem); break; case DW_TAG_inlined_subroutine: /* Unless we already are going through the "pyshical die tree", * we now need to start walking the die tree where this * subroutine is inlined to find the appropriate frame base. */ if (declaring_scope != -1) { physcopes = getscopes_die(&scope); if (physcopes.empty()) throw semantic_error (_F("unable to get die scopes for '%s' in an inlined subroutine", local.c_str()), e->tok); fbscopes = &physcopes; inner = 0; // zero is current scope, for look will increase. declaring_scope = -1; } break; } } return fb_attr; } struct location * dwflpp::translate_location(struct obstack *pool, Dwarf_Attribute *attr, Dwarf_Die *die, Dwarf_Addr pc, Dwarf_Attribute *fb_attr, struct location **tail, const target_symbol *e) { /* DW_AT_data_member_location, can be either constant offsets (struct member fields), or full blown location expressions. */ /* There is no location expression, but a constant value instead. */ if (dwarf_whatattr (attr) == DW_AT_const_value) { *tail = c_translate_constant (pool, &loc2c_error, this, &loc2c_emit_address, 0, pc, attr); return *tail; } Dwarf_Op *expr; size_t len; /* PR9768: formerly, we added pc+module_bias here. However, that bias value is not present in the pc value by the time we get it, so adding it would result in false negatives of variable reachibility. In other instances further below, the c_translate_FOO functions, the module_bias value used to be passed in, but instead should now be zero for the same reason. */ retry: switch (dwarf_getlocation_addr (attr, pc /*+ module_bias*/, &expr, &len, 1)) { case 1: /* Should always happen. */ if (len > 0) break; /* Fall through. */ case 0: /* Shouldn't happen.... but can, e.g. due to PR15123. */ { Dwarf_Addr pc2 = pr15123_retry_addr (pc, die); if (pc2 != 0) { pc = pc2; goto retry; } } /* FALLTHROUGH */ throw semantic_error (_F("not accessible at this address [man error::dwarf] (%s, dieoffset: %s)", lex_cast_hex(pc).c_str(), lex_cast_hex(dwarf_dieoffset(die)).c_str()), e->tok); default: /* Shouldn't happen. */ case -1: throw semantic_error (_F("dwarf_getlocation_addr failed [man error::dwarf] , %s", dwarf_errmsg(-1)), e->tok); } Dwarf_Op *cfa_ops; // pc is in the dw address space of the current module, which is what // c_translate_location expects. get_cfa_ops wants the global dwfl address. // cfa_ops only make sense for locals. if (pc) { Dwarf_Addr addr = pc + module_bias; cfa_ops = get_cfa_ops (addr); } else cfa_ops = NULL; return c_translate_location (pool, &loc2c_error, this, &loc2c_emit_address, 1, 0 /* PR9768 */, pc, attr, expr, len, tail, fb_attr, cfa_ops); } void dwflpp::print_members(Dwarf_Die *typedie, ostream &o, set &dupes) { const int typetag = dwarf_tag (typedie); /* compile and partial unit included for recursion through imported_unit below. */ if (typetag != DW_TAG_structure_type && typetag != DW_TAG_class_type && typetag != DW_TAG_union_type && typetag != DW_TAG_compile_unit && typetag != DW_TAG_partial_unit) { o << _F(" Error: %s isn't a struct/class/union", dwarf_type_name(typedie).c_str()); return; } // Try to get the first child of vardie. Dwarf_Die die_mem, import; Dwarf_Die *die = &die_mem; switch (dwarf_child (typedie, die)) { case 1: // No children. o << _F("%s is empty", dwarf_type_name(typedie).c_str()); return; case -1: // Error. default: // Shouldn't happen. o << dwarf_type_name(typedie) << ": " << dwarf_errmsg (-1); return; case 0: // Success. break; } // Output each sibling's name to 'o'. do { int tag = dwarf_tag(die); /* The children of an imported_unit should be treated as members too. */ if (tag == DW_TAG_imported_unit && dwarf_attr_die(die, DW_AT_import, &import)) print_members(&import, o, dupes); if (tag != DW_TAG_member && tag != DW_TAG_inheritance) continue; const char *member = dwarf_diename (die) ; if ( tag == DW_TAG_member && member != NULL ) { // Only output if this is new, to avoid inheritance dupes. if (dupes.insert(member).second) o << " " << member; } else { Dwarf_Die temp_die; if (!dwarf_attr_die (die, DW_AT_type, &temp_die)) { string source = dwarf_decl_file(die) ?: ""; int line = -1; dwarf_decl_line(die, &line); clog << _F("\n Error in obtaining type attribute for anonymous " "member at %s:%d", source.c_str(), line); return; } print_members(&temp_die, o, dupes); } } while (dwarf_siblingof (die, die) == 0); } bool dwflpp::find_struct_member(const target_symbol::component& c, Dwarf_Die *parentdie, Dwarf_Die *memberdie, vector& dies, vector& locs) { Dwarf_Attribute attr; Dwarf_Die die; /* With inheritance, a subclass may mask member names of parent classes, so * our search among the inheritance tree must be breadth-first rather than * depth-first (recursive). The parentdie is still our starting point. */ deque inheritees(1, *parentdie); for (; !inheritees.empty(); inheritees.pop_front()) { switch (dwarf_child (&inheritees.front(), &die)) { case 0: /* First child found. */ break; case 1: /* No children. */ continue; case -1: /* Error. */ default: /* Shouldn't happen */ throw semantic_error (dwarf_type_name(&inheritees.front()) + ": " + string (dwarf_errmsg (-1)), c.tok); } do { int tag = dwarf_tag(&die); /* recurse into imported units as if they are anonymoust structs */ Dwarf_Die import; if (tag == DW_TAG_imported_unit && dwarf_attr_die(&die, DW_AT_import, &import) && find_struct_member(c, &import, memberdie, dies, locs)) goto success; if (tag != DW_TAG_member && tag != DW_TAG_inheritance) continue; const char *name = dwarf_diename(&die); if (tag == DW_TAG_inheritance) { /* Remember inheritee for breadth-first search. */ Dwarf_Die inheritee; if (dwarf_attr_die (&die, DW_AT_type, &inheritee)) inheritees.push_back(inheritee); } else if (name == NULL) { /* Need to recurse for anonymous structs/unions. */ Dwarf_Die subdie; if (dwarf_attr_die (&die, DW_AT_type, &subdie) && find_struct_member(c, &subdie, memberdie, dies, locs)) goto success; } else if (name == c.member) { *memberdie = die; goto success; } } while (dwarf_siblingof (&die, &die) == 0); } return false; success: /* As we unwind the recursion, we need to build the chain of * locations that got to the final answer. */ if (dwarf_attr_integrate (&die, DW_AT_data_member_location, &attr)) { dies.insert(dies.begin(), die); locs.insert(locs.begin(), attr); } /* Union members don't usually have a location, * but just use the containing union's location. */ else if (dwarf_tag(parentdie) != DW_TAG_union_type) throw semantic_error (_F("no location for field '%s':%s", c.member.c_str(), dwarf_errmsg(-1)), c.tok); return true; } static inline void dwarf_die_type (Dwarf_Die *die, Dwarf_Die *typedie_mem, const token *tok=NULL) { if (!dwarf_attr_die (die, DW_AT_type, typedie_mem)) throw semantic_error (_F("cannot get type of field: %s", dwarf_errmsg(-1)), tok); } void dwflpp::translate_components(struct obstack *pool, struct location **tail, Dwarf_Addr pc, const target_symbol *e, Dwarf_Die *vardie, Dwarf_Die *typedie, unsigned first) { unsigned i = first; while (i < e->components.size()) { const target_symbol::component& c = e->components[i]; /* XXX: This would be desirable, but we don't get the target_symbol token, and printing that gives us the file:line number too early anyway. */ #if 0 // Emit a marker to note which field is being access-attempted, to give // better error messages if deref() fails. string piece = string(...target_symbol token...) + string ("#") + lex_cast(components[i].second); obstack_printf (pool, "c->last_stmt = %s;", lex_cast_qstring(piece).c_str()); #endif switch (dwarf_tag (typedie)) { case DW_TAG_typedef: case DW_TAG_const_type: case DW_TAG_volatile_type: /* Just iterate on the referent type. */ dwarf_die_type (typedie, typedie, c.tok); break; case DW_TAG_reference_type: case DW_TAG_rvalue_reference_type: if (pool) c_translate_pointer (pool, 1, 0 /* PR9768*/, typedie, tail); dwarf_die_type (typedie, typedie, c.tok); break; case DW_TAG_pointer_type: /* A pointer with no type is a void* -- can't dereference it. */ if (!dwarf_hasattr_integrate (typedie, DW_AT_type)) throw semantic_error (_F("invalid access '%s' vs '%s'", lex_cast(c).c_str(), dwarf_type_name(typedie).c_str()), c.tok); if (pool) c_translate_pointer (pool, 1, 0 /* PR9768*/, typedie, tail); if (c.type != target_symbol::comp_literal_array_index && c.type != target_symbol::comp_expression_array_index) { dwarf_die_type (typedie, typedie, c.tok); break; } /* else fall through as an array access */ case DW_TAG_array_type: if (c.type == target_symbol::comp_literal_array_index) { if (pool) c_translate_array (pool, 1, 0 /* PR9768 */, typedie, tail, NULL, c.num_index); } else if (c.type == target_symbol::comp_expression_array_index) { string index = "STAP_ARG_index" + lex_cast(i); if (pool) c_translate_array (pool, 1, 0 /* PR9768 */, typedie, tail, index.c_str(), 0); } else throw semantic_error (_F("invalid access '%s' for array type", lex_cast(c).c_str()), c.tok); dwarf_die_type (typedie, typedie, c.tok); *vardie = *typedie; ++i; break; case DW_TAG_structure_type: case DW_TAG_union_type: case DW_TAG_class_type: if (c.type != target_symbol::comp_struct_member) throw semantic_error (_F("invalid access '%s' for %s", lex_cast(c).c_str(), dwarf_type_name(typedie).c_str())); if (dwarf_hasattr(typedie, DW_AT_declaration)) { Dwarf_Die *tmpdie = declaration_resolve(typedie); if (tmpdie == NULL) throw semantic_error (_F("unresolved %s", dwarf_type_name(typedie).c_str()), c.tok); *typedie = *tmpdie; } { vector dies; vector locs; if (!find_struct_member(c, typedie, vardie, dies, locs)) { /* Add a file:line hint for anonymous types */ string source; if (!dwarf_hasattr_integrate(typedie, DW_AT_name)) { int line; const char *file = dwarf_decl_file(typedie); if (file && dwarf_decl_line(typedie, &line) == 0) source = " (" + string(file) + ":" + lex_cast(line) + ")"; } string alternatives; stringstream members; set member_dupes; print_members(typedie, members, member_dupes); if (members.str().size() != 0) alternatives = " (alternatives:" + members.str() + ")"; throw semantic_error(_F("unable to find member '%s' for %s%s%s", c.member.c_str(), dwarf_type_name(typedie).c_str(), source.c_str(), alternatives.c_str()), c.tok); } for (unsigned j = 0; j < locs.size(); ++j) if (pool) translate_location (pool, &locs[j], &dies[j], pc, NULL, tail, e); } dwarf_die_type (vardie, typedie, c.tok); ++i; break; case DW_TAG_enumeration_type: case DW_TAG_base_type: throw semantic_error (_F("invalid access '%s' vs. %s", lex_cast(c).c_str(), dwarf_type_name(typedie).c_str()), c.tok); break; case -1: throw semantic_error (_F("cannot find type: %s", dwarf_errmsg(-1)), c.tok); break; default: throw semantic_error (_F("%s: unexpected type tag %s", dwarf_type_name(typedie).c_str(), lex_cast(dwarf_tag(typedie)).c_str()), c.tok); break; } } } void dwflpp::resolve_unqualified_inner_typedie (Dwarf_Die *typedie, Dwarf_Die *innerdie, const target_symbol *e) { int typetag = dwarf_tag (typedie); *innerdie = *typedie; while (typetag == DW_TAG_typedef || typetag == DW_TAG_const_type || typetag == DW_TAG_volatile_type) { if (!dwarf_attr_die (innerdie, DW_AT_type, innerdie)) throw semantic_error (_F("cannot get type of pointee: %s", dwarf_errmsg(-1)), e->tok); typetag = dwarf_tag (innerdie); } } void dwflpp::translate_final_fetch_or_store (struct obstack *pool, struct location **tail, Dwarf_Addr /*module_bias*/, Dwarf_Die *vardie, Dwarf_Die *start_typedie, bool lvalue, const target_symbol *e, string &, string &, exp_type & ty) { /* First boil away any qualifiers associated with the type DIE of the final location to be accessed. */ Dwarf_Die typedie_mem, *typedie = &typedie_mem; resolve_unqualified_inner_typedie (start_typedie, typedie, e); /* If we're looking for an address, then we can just provide what we computed to this point, without using a fetch/store. */ if (e->addressof) { if (lvalue) throw semantic_error (_("cannot write to member address"), e->tok); if (dwarf_hasattr_integrate (vardie, DW_AT_bit_offset)) throw semantic_error (_("cannot take address of bit-field"), e->tok); c_translate_addressof (pool, 1, 0, vardie, typedie, tail, "STAP_RETVALUE"); ty = pe_long; return; } /* Then switch behavior depending on the type of fetch/store we want, and the type and pointer-ness of the final location. */ int typetag = dwarf_tag (typedie); switch (typetag) { default: throw semantic_error (_F("unsupported type tag %s for %s", lex_cast(typetag).c_str(), dwarf_type_name(typedie).c_str()), e->tok); break; case DW_TAG_structure_type: case DW_TAG_class_type: case DW_TAG_union_type: throw semantic_error (_F("'%s' is being accessed instead of a member", dwarf_type_name(typedie).c_str()), e->tok); break; case DW_TAG_base_type: // Reject types we can't handle in systemtap { Dwarf_Attribute encoding_attr; Dwarf_Word encoding = (Dwarf_Word) -1; dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding, &encoding_attr), & encoding); if (encoding == (Dwarf_Word) -1) { // clog << "bad type1 " << encoding << " diestr" << endl; throw semantic_error (_F("unsupported type (mystery encoding %s for %s", lex_cast(encoding).c_str(), dwarf_type_name(typedie).c_str()), e->tok); } if (encoding == DW_ATE_float || encoding == DW_ATE_complex_float /* XXX || many others? */) { // clog << "bad type " << encoding << " diestr" << endl; throw semantic_error (_F("unsupported type (encoding %s) for %s", lex_cast(encoding).c_str(), dwarf_type_name(typedie).c_str()), e->tok); } } // Fallthrough. enumeration_types are always scalar. case DW_TAG_enumeration_type: ty = pe_long; if (lvalue) c_translate_store (pool, 1, 0 /* PR9768 */, vardie, typedie, tail, "STAP_ARG_value"); else c_translate_fetch (pool, 1, 0 /* PR9768 */, vardie, typedie, tail, "STAP_RETVALUE"); break; case DW_TAG_array_type: case DW_TAG_pointer_type: case DW_TAG_reference_type: case DW_TAG_rvalue_reference_type: if (lvalue) { ty = pe_long; if (typetag == DW_TAG_array_type) throw semantic_error (_("cannot write to array address"), e->tok); if (typetag == DW_TAG_reference_type || typetag == DW_TAG_rvalue_reference_type) throw semantic_error (_("cannot write to reference"), e->tok); assert (typetag == DW_TAG_pointer_type); c_translate_pointer_store (pool, 1, 0 /* PR9768 */, typedie, tail, "STAP_ARG_value"); } else { // We have the pointer: cast it to an integral type via &(*(...)) // NB: per bug #1187, at one point char*-like types were // automagically converted here to systemtap string values. // For several reasons, this was taken back out, leaving // pointer-to-string "conversion" (copying) to tapset functions. ty = pe_long; if (typetag == DW_TAG_array_type) c_translate_array (pool, 1, 0 /* PR9768 */, typedie, tail, NULL, 0); else c_translate_pointer (pool, 1, 0 /* PR9768 */, typedie, tail); c_translate_addressof (pool, 1, 0 /* PR9768 */, NULL, NULL, tail, "STAP_RETVALUE"); } break; } } string dwflpp::express_as_string (string prelude, string postlude, struct location *head) { size_t bufsz = 0; char *buf = 0; // NB: it would leak to pre-allocate a buffer here FILE *memstream = open_memstream (&buf, &bufsz); assert(memstream); fprintf(memstream, "{\n"); fprintf(memstream, "%s", prelude.c_str()); unsigned int stack_depth; bool deref = c_emit_location (memstream, head, 1, &stack_depth); // Ensure that DWARF keeps loc2c to a "reasonable" stack size // 32 intptr_t leads to max 256 bytes on the stack if (stack_depth > 32) throw semantic_error("oversized DWARF stack"); fprintf(memstream, "%s", postlude.c_str()); fprintf(memstream, " goto out;\n"); // dummy use of deref_fault label, to disable warning if deref() not used fprintf(memstream, "if (0) goto deref_fault;\n"); // XXX: deref flag not reliable; emit fault label unconditionally (void) deref; fprintf(memstream, "deref_fault:\n" " goto out;\n"); fprintf(memstream, "}\n"); fclose (memstream); string result(buf); free (buf); return result; } Dwarf_Addr dwflpp::vardie_from_symtable (Dwarf_Die *vardie, Dwarf_Addr *addr) { const char *name = dwarf_linkage_name (vardie) ?: dwarf_diename (vardie); if (sess.verbose > 2) clog << _F("finding symtable address for %s\n", name); *addr = 0; int syms = dwfl_module_getsymtab (module); dwfl_assert (_("Getting symbols"), syms >= 0); for (int i = 0; *addr == 0 && i < syms; i++) { GElf_Sym sym; GElf_Word shndxp; const char *symname = dwfl_module_getsym(module, i, &sym, &shndxp); if (symname && ! strcmp (name, symname) && sym.st_shndx != SHN_UNDEF && (GELF_ST_TYPE (sym.st_info) == STT_NOTYPE // PR13284 || GELF_ST_TYPE (sym.st_info) == STT_OBJECT)) *addr = sym.st_value; } // Don't relocate for the kernel, or kernel modules we handle those // specially in emit_address. if (dwfl_module_relocations (module) == 1 && module_name != TOK_KERNEL) dwfl_module_relocate_address (module, addr); if (sess.verbose > 2) clog << _F("found %s @%#" PRIx64 "\n", name, *addr); return *addr; } string dwflpp::literal_stmt_for_local (vector& scopes, Dwarf_Addr pc, string const & local, const target_symbol *e, bool lvalue, exp_type & ty) { Dwarf_Die vardie; Dwarf_Attribute fb_attr_mem, *fb_attr = NULL; fb_attr = find_variable_and_frame_base (scopes, pc, local, e, &vardie, &fb_attr_mem); if (sess.verbose>2) { if (pc) clog << _F("finding location for local '%s' near address %#" PRIx64 ", module bias %#" PRIx64 "\n", local.c_str(), pc, module_bias); else clog << _F("finding location for global '%s' in CU '%s'\n", local.c_str(), cu_name().c_str()); } #define obstack_chunk_alloc malloc #define obstack_chunk_free free struct obstack pool; obstack_init (&pool); struct location *tail = NULL; /* Given $foo->bar->baz[NN], translate the location of foo. */ struct location *head; Dwarf_Attribute attr_mem; if (dwarf_attr_integrate (&vardie, DW_AT_const_value, &attr_mem) == NULL && dwarf_attr_integrate (&vardie, DW_AT_location, &attr_mem) == NULL) { Dwarf_Op addr_loc; memset(&addr_loc, 0, sizeof(Dwarf_Op)); addr_loc.atom = DW_OP_addr; // If it is an external variable try the symbol table. PR10622. if (dwarf_attr_integrate (&vardie, DW_AT_external, &attr_mem) != NULL && vardie_from_symtable (&vardie, &addr_loc.number) != 0) { head = c_translate_location (&pool, &loc2c_error, this, &loc2c_emit_address, 1, 0, pc, NULL, &addr_loc, 1, &tail, NULL, NULL); } else throw semantic_error (_F("failed to retrieve location attribute for '%s' [man error::dwarf] (dieoffset: %s)", local.c_str(), lex_cast_hex(dwarf_dieoffset(&vardie)).c_str()), e->tok); } else head = translate_location (&pool, &attr_mem, &vardie, pc, fb_attr, &tail, e); /* Translate the ->bar->baz[NN] parts. */ Dwarf_Die typedie; if (dwarf_attr_die (&vardie, DW_AT_type, &typedie) == NULL) throw semantic_error(_F("failed to retrieve type attribute for '%s' [man error::dwarf] (dieoffset: %s)", local.c_str(), lex_cast_hex(dwarf_dieoffset(&vardie)).c_str()), e->tok); translate_components (&pool, &tail, pc, e, &vardie, &typedie); /* Translate the assignment part, either x = $foo->bar->baz[NN] or $foo->bar->baz[NN] = x */ string prelude, postlude; translate_final_fetch_or_store (&pool, &tail, module_bias, &vardie, &typedie, lvalue, e, prelude, postlude, ty); /* Write the translation to a string. */ string result = express_as_string(prelude, postlude, head); obstack_free (&pool, 0); return result; } Dwarf_Die* dwflpp::type_die_for_local (vector& scopes, Dwarf_Addr pc, string const & local, const target_symbol *e, Dwarf_Die *typedie) { Dwarf_Die vardie; Dwarf_Attribute attr_mem; find_variable_and_frame_base (scopes, pc, local, e, &vardie, &attr_mem); if (dwarf_attr_die (&vardie, DW_AT_type, typedie) == NULL) throw semantic_error(_F("failed to retrieve type attribute for '%s' [man error::dwarf]", local.c_str()), e->tok); translate_components (NULL, NULL, pc, e, &vardie, typedie); return typedie; } string dwflpp::literal_stmt_for_return (Dwarf_Die *scope_die, Dwarf_Addr pc, const target_symbol *e, bool lvalue, exp_type & ty) { if (sess.verbose>2) clog << _F("literal_stmt_for_return: finding return value for %s (%s)\n", (dwarf_diename(scope_die) ?: ""), (dwarf_diename(cu) ?: "")); struct obstack pool; obstack_init (&pool); struct location *tail = NULL; /* Given $return->bar->baz[NN], translate the location of return. */ const Dwarf_Op *locops; int nlocops = dwfl_module_return_value_location (module, scope_die, &locops); if (nlocops < 0) { throw semantic_error(_F("failed to retrieve return value location for %s [man error::dwarf] (%s)", (dwarf_diename(scope_die) ?: ""), (dwarf_diename(cu) ?: "")), e->tok); } // the function has no return value (e.g. "void" in C) else if (nlocops == 0) { throw semantic_error(_F("function %s (%s) has no return value", (dwarf_diename(scope_die) ?: ""), (dwarf_diename(cu) ?: "")), e->tok); } struct location *head = c_translate_location (&pool, &loc2c_error, this, &loc2c_emit_address, 1, 0 /* PR9768 */, pc, NULL, locops, nlocops, &tail, NULL, NULL); /* Translate the ->bar->baz[NN] parts. */ Dwarf_Die vardie = *scope_die, typedie; if (dwarf_attr_die (&vardie, DW_AT_type, &typedie) == NULL) throw semantic_error(_F("failed to retrieve return value type attribute for %s [man error::dwarf] (%s)", (dwarf_diename(&vardie) ?: ""), (dwarf_diename(cu) ?: "")), e->tok); translate_components (&pool, &tail, pc, e, &vardie, &typedie); /* Translate the assignment part, either x = $return->bar->baz[NN] or $return->bar->baz[NN] = x */ string prelude, postlude; translate_final_fetch_or_store (&pool, &tail, module_bias, &vardie, &typedie, lvalue, e, prelude, postlude, ty); /* Write the translation to a string. */ string result = express_as_string(prelude, postlude, head); obstack_free (&pool, 0); return result; } Dwarf_Die* dwflpp::type_die_for_return (Dwarf_Die *scope_die, Dwarf_Addr pc, const target_symbol *e, Dwarf_Die *typedie) { Dwarf_Die vardie = *scope_die; if (dwarf_attr_die (&vardie, DW_AT_type, typedie) == NULL) throw semantic_error(_F("failed to retrieve return value type attribute for %s [man error::dwarf] (%s)", (dwarf_diename(&vardie) ?: ""), (dwarf_diename(cu) ?: "")), e->tok); translate_components (NULL, NULL, pc, e, &vardie, typedie); return typedie; } string dwflpp::literal_stmt_for_pointer (Dwarf_Die *start_typedie, const target_symbol *e, bool lvalue, exp_type & ty) { if (sess.verbose>2) clog << _F("literal_stmt_for_pointer: finding value for %s (%s)\n", dwarf_type_name(start_typedie).c_str(), (dwarf_diename(cu) ?: "")); struct obstack pool; obstack_init (&pool); struct location *head = c_translate_argument (&pool, &loc2c_error, this, &loc2c_emit_address, 1, "STAP_ARG_pointer"); struct location *tail = head; /* Translate the ->bar->baz[NN] parts. */ unsigned first = 0; Dwarf_Die typedie = *start_typedie, vardie = typedie; /* As a special case when typedie is not an array or pointer, we can * allow array indexing on STAP_ARG_pointer instead (since we do * know the pointee type and can determine its size). PR11556. */ const target_symbol::component* c = e->components.empty() ? NULL : &e->components[0]; if (c && (c->type == target_symbol::comp_literal_array_index || c->type == target_symbol::comp_expression_array_index)) { resolve_unqualified_inner_typedie (&typedie, &typedie, e); int typetag = dwarf_tag (&typedie); if (typetag != DW_TAG_pointer_type && typetag != DW_TAG_array_type) { if (c->type == target_symbol::comp_literal_array_index) c_translate_array_pointer (&pool, 1, &typedie, &tail, NULL, c->num_index); else c_translate_array_pointer (&pool, 1, &typedie, &tail, "STAP_ARG_index0", 0); ++first; } } /* Now translate the rest normally. */ translate_components (&pool, &tail, 0, e, &vardie, &typedie, first); /* Translate the assignment part, either x = (STAP_ARG_pointer)->bar->baz[NN] or (STAP_ARG_pointer)->bar->baz[NN] = x */ string prelude, postlude; translate_final_fetch_or_store (&pool, &tail, module_bias, &vardie, &typedie, lvalue, e, prelude, postlude, ty); /* Write the translation to a string. */ string result = express_as_string(prelude, postlude, head); obstack_free (&pool, 0); return result; } Dwarf_Die* dwflpp::type_die_for_pointer (Dwarf_Die *start_typedie, const target_symbol *e, Dwarf_Die *typedie) { unsigned first = 0; *typedie = *start_typedie; Dwarf_Die vardie = *typedie; /* Handle the same PR11556 case as above. */ const target_symbol::component* c = e->components.empty() ? NULL : &e->components[0]; if (c && (c->type == target_symbol::comp_literal_array_index || c->type == target_symbol::comp_expression_array_index)) { resolve_unqualified_inner_typedie (typedie, typedie, e); int typetag = dwarf_tag (typedie); if (typetag != DW_TAG_pointer_type && typetag != DW_TAG_array_type) ++first; } translate_components (NULL, NULL, 0, e, &vardie, typedie, first); return typedie; } static bool in_kprobes_function(systemtap_session& sess, Dwarf_Addr addr) { if (sess.sym_kprobes_text_start != 0 && sess.sym_kprobes_text_end != 0) { // If the probe point address is anywhere in the __kprobes // address range, we can't use this probe point. if (addr >= sess.sym_kprobes_text_start && addr < sess.sym_kprobes_text_end) return true; } return false; } bool dwflpp::blacklisted_p(const string& funcname, const string& filename, int, const string& module, Dwarf_Addr addr, bool has_return) { if (!blacklist_enabled) return false; // no blacklist for userspace bool blacklisted = false; // check against section blacklist string section = get_blacklist_section(addr); // PR6503: modules don't need special init/exit treatment if (module == TOK_KERNEL && !regexec (&blacklist_section, section.c_str(), 0, NULL, 0)) { blacklisted = true; if (sess.verbose>1) clog << _(" init/exit"); } // Check for function marked '__kprobes'. if (module == TOK_KERNEL && in_kprobes_function(sess, addr)) { blacklisted = true; if (sess.verbose>1) clog << _(" __kprobes"); } // Check probe point against file/function blacklists. int goodfn = regexec (&blacklist_func, funcname.c_str(), 0, NULL, 0); if (has_return) goodfn = goodfn && regexec (&blacklist_func_ret, funcname.c_str(), 0, NULL, 0); int goodfile = regexec (&blacklist_file, filename.c_str(), 0, NULL, 0); if (! (goodfn && goodfile)) { blacklisted = true; if (sess.verbose>1) clog << _(" file/function blacklist"); } if (sess.guru_mode && blacklisted) { blacklisted = false; if (sess.verbose>1) clog << _(" - not skipped (guru mode enabled)"); } if (blacklisted && sess.verbose>1) clog << _(" - skipped"); // This probe point is not blacklisted. return blacklisted; } void dwflpp::build_blacklist() { // We build up the regexps in these strings // Add ^ anchors at the front; $ will be added just before regcomp. string blfn = "^("; string blfn_ret = "^("; string blfile = "^("; string blsection = "^("; blsection += "\\.init\\."; // first alternative, no "|" blsection += "|\\.exit\\."; blsection += "|\\.devinit\\."; blsection += "|\\.devexit\\."; blsection += "|\\.cpuinit\\."; blsection += "|\\.cpuexit\\."; blsection += "|\\.meminit\\."; blsection += "|\\.memexit\\."; /* NOTE all include/asm .h blfile patterns might need "full path" so prefix those with '.*' - see PR13108 and PR13112. */ blfile += "kernel/kprobes\\.c"; // first alternative, no "|" blfile += "|arch/.*/kernel/kprobes\\.c"; blfile += "|.*/include/asm/io\\.h"; blfile += "|.*/include/asm/io_64\\.h"; blfile += "|.*/include/asm/bitops\\.h"; blfile += "|drivers/ide/ide-iops\\.c"; // paravirt ops blfile += "|arch/.*/kernel/paravirt\\.c"; blfile += "|.*/include/asm/paravirt\\.h"; // XXX: it would be nice if these blacklisted functions were pulled // in dynamically, instead of being statically defined here. // Perhaps it could be populated from script files. A "noprobe // kernel.function("...")" construct might do the trick. // Most of these are marked __kprobes in newer kernels. We list // them here (anyway) so the translator can block them on older // kernels that don't have the __kprobes function decorator. This // also allows detection of problems at translate- rather than // run-time. blfn += "atomic_notifier_call_chain"; // first blfn; no "|" blfn += "|default_do_nmi"; blfn += "|__die"; blfn += "|die_nmi"; blfn += "|do_debug"; blfn += "|do_general_protection"; blfn += "|do_int3"; blfn += "|do_IRQ"; blfn += "|do_page_fault"; blfn += "|do_sparc64_fault"; blfn += "|do_trap"; blfn += "|dummy_nmi_callback"; blfn += "|flush_icache_range"; blfn += "|ia64_bad_break"; blfn += "|ia64_do_page_fault"; blfn += "|ia64_fault"; blfn += "|io_check_error"; blfn += "|mem_parity_error"; blfn += "|nmi_watchdog_tick"; blfn += "|notifier_call_chain"; blfn += "|oops_begin"; blfn += "|oops_end"; blfn += "|program_check_exception"; blfn += "|single_step_exception"; blfn += "|sync_regs"; blfn += "|unhandled_fault"; blfn += "|unknown_nmi_error"; blfn += "|xen_[gs]et_debugreg"; blfn += "|xen_irq_.*"; blfn += "|xen_.*_fl_direct.*"; blfn += "|check_events"; blfn += "|xen_adjust_exception_frame"; blfn += "|xen_iret.*"; blfn += "|xen_sysret64.*"; blfn += "|test_ti_thread_flag.*"; blfn += "|inat_get_opcode_attribute"; blfn += "|system_call_after_swapgs"; blfn += "|HYPERVISOR_[gs]et_debugreg"; blfn += "|HYPERVISOR_event_channel_op"; blfn += "|hash_64"; blfn += "|hash_ptr"; blfn += "|native_set_pte"; // Lots of locks blfn += "|.*raw_.*_lock.*"; blfn += "|.*raw_.*_unlock.*"; blfn += "|.*raw_.*_trylock.*"; blfn += "|.*read_lock.*"; blfn += "|.*read_unlock.*"; blfn += "|.*read_trylock.*"; blfn += "|.*write_lock.*"; blfn += "|.*write_unlock.*"; blfn += "|.*write_trylock.*"; blfn += "|.*write_seqlock.*"; blfn += "|.*write_sequnlock.*"; blfn += "|.*spin_lock.*"; blfn += "|.*spin_unlock.*"; blfn += "|.*spin_trylock.*"; blfn += "|.*spin_is_locked.*"; blfn += "|rwsem_.*lock.*"; blfn += "|.*mutex_.*lock.*"; blfn += "|raw_.*"; // atomic functions blfn += "|atomic_.*"; blfn += "|atomic64_.*"; // few other problematic cases blfn += "|get_bh"; blfn += "|put_bh"; // Experimental blfn += "|.*apic.*|.*APIC.*"; blfn += "|.*softirq.*"; blfn += "|.*IRQ.*"; blfn += "|.*_intr.*"; blfn += "|__delay"; blfn += "|.*kernel_text.*"; blfn += "|get_current"; blfn += "|current_.*"; blfn += "|.*exception_tables.*"; blfn += "|.*setup_rt_frame.*"; // PR 5759, CONFIG_PREEMPT kernels blfn += "|.*preempt_count.*"; blfn += "|preempt_schedule"; // These functions don't return, so return probes would never be recovered blfn_ret += "do_exit"; // no "|" blfn_ret += "|sys_exit"; blfn_ret += "|sys_exit_group"; // __switch_to changes "current" on x86_64 and i686, so return probes // would cause kernel panic, and it is marked as "__kprobes" on x86_64 if (sess.architecture == "x86_64") blfn += "|__switch_to"; if (sess.architecture == "i686") blfn_ret += "|__switch_to"; // RHEL6 pre-beta 2.6.32-19.el6 blfn += "|special_mapping_.*"; blfn += "|.*_pte_.*"; // or "|smaps_pte_range"; blfile += "|fs/seq_file\\.c"; blfn += ")$"; blfn_ret += ")$"; blfile += ")$"; blsection += ")"; // NB: no $, sections match just the beginning if (sess.verbose > 2) { clog << _("blacklist regexps:") << endl; clog << "blfn: " << blfn << endl; clog << "blfn_ret: " << blfn_ret << endl; clog << "blfile: " << blfile << endl; clog << "blsection: " << blsection << endl; } int rc = regcomp (& blacklist_func, blfn.c_str(), REG_NOSUB|REG_EXTENDED); if (rc) throw semantic_error (_("blacklist_func regcomp failed")); rc = regcomp (& blacklist_func_ret, blfn_ret.c_str(), REG_NOSUB|REG_EXTENDED); if (rc) throw semantic_error (_("blacklist_func_ret regcomp failed")); rc = regcomp (& blacklist_file, blfile.c_str(), REG_NOSUB|REG_EXTENDED); if (rc) throw semantic_error (_("blacklist_file regcomp failed")); rc = regcomp (& blacklist_section, blsection.c_str(), REG_NOSUB|REG_EXTENDED); if (rc) throw semantic_error (_("blacklist_section regcomp failed")); blacklist_enabled = true; } string dwflpp::get_blacklist_section(Dwarf_Addr addr) { string blacklist_section; Dwarf_Addr bias; // We prefer dwfl_module_getdwarf to dwfl_module_getelf here, // because dwfl_module_getelf can force costly section relocations // we don't really need, while either will do for this purpose. Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (module, &bias)) ?: dwfl_module_getelf (module, &bias)); Dwarf_Addr offset = addr - bias; if (elf) { Elf_Scn* scn = 0; size_t shstrndx; dwfl_assert ("getshdrstrndx", elf_getshdrstrndx (elf, &shstrndx)); while ((scn = elf_nextscn (elf, scn)) != NULL) { GElf_Shdr shdr_mem; GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); if (! shdr) continue; // XXX error? if (!(shdr->sh_flags & SHF_ALLOC)) continue; GElf_Addr start = shdr->sh_addr; GElf_Addr end = start + shdr->sh_size; if (! (offset >= start && offset < end)) continue; blacklist_section = elf_strptr (elf, shstrndx, shdr->sh_name); break; } } return blacklist_section; } /* Find the section named 'section_name' in the current module * returning the section header using 'shdr_mem' */ GElf_Shdr * dwflpp::get_section(string section_name, GElf_Shdr *shdr_mem, Elf **elf_ret) { GElf_Shdr *shdr = NULL; Elf* elf; Dwarf_Addr bias; size_t shstrndx; // Explicitly look in the main elf file first. elf = dwfl_module_getelf (module, &bias); Elf_Scn *probe_scn = NULL; dwfl_assert ("getshdrstrndx", elf_getshdrstrndx (elf, &shstrndx)); bool have_section = false; while ((probe_scn = elf_nextscn (elf, probe_scn))) { shdr = gelf_getshdr (probe_scn, shdr_mem); assert (shdr != NULL); if (elf_strptr (elf, shstrndx, shdr->sh_name) == section_name) { have_section = true; break; } } // Older versions may put the section in the debuginfo dwarf file, // so check if it actually exists, if not take a look in the debuginfo file if (! have_section || (have_section && shdr->sh_type == SHT_NOBITS)) { elf = dwarf_getelf (dwfl_module_getdwarf (module, &bias)); if (! elf) return NULL; dwfl_assert ("getshdrstrndx", elf_getshdrstrndx (elf, &shstrndx)); probe_scn = NULL; while ((probe_scn = elf_nextscn (elf, probe_scn))) { shdr = gelf_getshdr (probe_scn, shdr_mem); if (elf_strptr (elf, shstrndx, shdr->sh_name) == section_name) { have_section = true; break; } } } if (!have_section) return NULL; if (elf_ret) *elf_ret = elf; return shdr; } Dwarf_Addr dwflpp::relocate_address(Dwarf_Addr dw_addr, string& reloc_section) { // PR10273 // libdw address, so adjust for bias gotten from dwfl_module_getdwarf Dwarf_Addr reloc_addr = dw_addr + module_bias; if (!module) { assert(module_name == TOK_KERNEL); reloc_section = ""; } else if (dwfl_module_relocations (module) > 0) { // This is a relocatable module; libdwfl already knows its // sections, so we can relativize addr. int idx = dwfl_module_relocate_address (module, &reloc_addr); const char* r_s = dwfl_module_relocation_info (module, idx, NULL); if (r_s) reloc_section = r_s; if (reloc_section == "" && dwfl_module_relocations (module) == 1) reloc_section = ".dynamic"; } else reloc_section = ".absolute"; return reloc_addr; } /* Returns the call frame address operations for the given program counter * in the libdw address space. */ Dwarf_Op * dwflpp::get_cfa_ops (Dwarf_Addr pc) { Dwarf_Op *cfa_ops = NULL; if (sess.verbose > 2) clog << "get_cfa_ops @0x" << hex << pc << dec << ", module_start @0x" << hex << module_start << dec << endl; // Try debug_frame first, then fall back on eh_frame. size_t cfa_nops = 0; Dwarf_Addr bias = 0; Dwarf_Frame *frame = NULL; Dwarf_CFI *cfi = dwfl_module_dwarf_cfi (module, &bias); if (cfi != NULL) { if (sess.verbose > 3) clog << "got dwarf cfi bias: 0x" << hex << bias << dec << endl; if (dwarf_cfi_addrframe (cfi, pc - bias, &frame) == 0) dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops); else if (sess.verbose > 3) clog << "dwarf_cfi_addrframe failed: " << dwarf_errmsg(-1) << endl; } else if (sess.verbose > 3) clog << "dwfl_module_dwarf_cfi failed: " << dwfl_errmsg(-1) << endl; if (cfa_ops == NULL) { cfi = dwfl_module_eh_cfi (module, &bias); if (cfi != NULL) { if (sess.verbose > 3) clog << "got eh cfi bias: 0x" << hex << bias << dec << endl; Dwarf_Frame *frame = NULL; if (dwarf_cfi_addrframe (cfi, pc - bias, &frame) == 0) dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops); else if (sess.verbose > 3) clog << "dwarf_cfi_addrframe failed: " << dwarf_errmsg(-1) << endl; } else if (sess.verbose > 3) clog << "dwfl_module_eh_cfi failed: " << dwfl_errmsg(-1) << endl; } if (sess.verbose > 2) { if (cfa_ops == NULL) clog << _("not found cfa") << endl; else { Dwarf_Addr frame_start, frame_end; bool frame_signalp; int info = dwarf_frame_info (frame, &frame_start, &frame_end, &frame_signalp); clog << _F("found cfa, info: %d [start: %#" PRIx64 ", end: %#" PRIx64 ", nops: %zu", info, frame_start, frame_end, cfa_nops) << endl; } } return cfa_ops; } int dwflpp::add_module_build_id_to_hash (Dwfl_Module *m, void **userdata __attribute__ ((unused)), const char *name, Dwarf_Addr base, void *arg) { string modname = name; systemtap_session * s = (systemtap_session *)arg; if (pending_interrupts) return DWARF_CB_ABORT; // Extract the build ID const unsigned char *bits; GElf_Addr vaddr; int bits_length = dwfl_module_build_id(m, &bits, &vaddr); if(bits_length > 0) { // Convert the binary bits to a hex string string hex = hex_dump(bits, bits_length); // Store the build ID in the session s->build_ids.push_back(hex); } return DWARF_CB_OK; } // Perform PR15123 heuristic for given variable at given address. // Return alternate pc address to do location-list lookup at, or 0 if // inapplicable. // Dwarf_Addr dwflpp::pr15123_retry_addr (Dwarf_Addr pc, Dwarf_Die* die) { // For PR15123, we'd like to detect the situation where the // incoming PC may point to a couple-of-byte instruction // sequence that gcc emits for CFLAGS=-mfentry, and where // context variables are in fact available throughout, *but* due // to the bug, the dwarf debuginfo location-list only starts a // few instructions later. Prologue searching does not resolve // this as a line-record is in place at the -mfentry prologue. // // Detecting this is complicated because ... // - we only want to do this if -mfentry was actually used // - if points to the a function entry point // - if the architecture is familiar enough that we can have a // hard-coded constant to skip over the prologue. // // Otherwise, we could give a false-positive - return corrupted data. if (getenv ("PR15123_DISABLE")) return 0; Dwarf_Die cudie; Dwarf_Attribute cudie_producer; dwarf_diecu (die, &cudie, NULL, NULL); if (! dwarf_attr_integrate(&cudie, DW_AT_producer, &cudie_producer)) return 0; const char* producer = dwarf_formstring(&cudie_producer); if (!producer) return 0; if (! strstr(producer, "-mfentry")) return 0; // Determine if this pc maps to the beginning of a // real function (not some inlined doppelganger. This // is made tricker by this->function may not be // pointing at the right DIE (say e.g. stap encountered // the inlined copy first, so was focus_on_function'd). vector scopes = getscopes(pc); if (scopes.size() == 0) return 0; Dwarf_Die outer_function_die = scopes[0]; Dwarf_Addr entrypc; die_entrypc(& outer_function_die, &entrypc); if (entrypc != pc) // (will fail on retry, so we won't loop more than once) return 0; if (sess.architecture == "i386" || sess.architecture == "x86_64") { /* pull the trigger */ if (sess.verbose > 2) clog << _("retrying variable location-list lookup at address pc+5\n"); return pc + 5; } return 0; } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/dwflpp.h000066400000000000000000000407351217430427200150670ustar00rootroot00000000000000// C++ interface to dwfl // Copyright (C) 2005-2013 Red Hat Inc. // Copyright (C) 2005-2007 Intel Corporation. // Copyright (C) 2008 James.Bottomley@HansenPartnership.com // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef DWFLPP_H #define DWFLPP_H #include "config.h" #include "dwarf_wrappers.h" #include "elaborate.h" #include "session.h" #include "unordered.h" #include "setupdwfl.h" #include #include #include #include #include #include extern "C" { #include #include } struct func_info; struct inline_instance_info; struct symbol_table; struct base_query; struct dwarf_query; enum line_t { ABSOLUTE, RELATIVE, RANGE, WILDCARD }; enum info_status { info_unknown, info_present, info_absent }; // module -> cu die[] typedef unordered_map*> module_cu_cache_t; // An instance of this type tracks whether the type units for a given // Dwarf have been read. typedef std::set module_tus_read_t; // typename -> die typedef unordered_map cu_type_cache_t; // cu die -> (typename -> die) typedef unordered_map mod_cu_type_cache_t; // function -> die typedef unordered_multimap cu_function_cache_t; typedef std::pair cu_function_cache_range_t; // cu die -> (function -> die) typedef unordered_map mod_cu_function_cache_t; // module -> (function -> die) typedef unordered_map mod_function_cache_t; // inline function die -> instance die[] typedef unordered_map*> cu_inl_function_cache_t; // die -> parent die typedef unordered_map cu_die_parent_cache_t; // cu die -> (die -> parent die) typedef unordered_map mod_cu_die_parent_cache_t; typedef std::vector func_info_map_t; typedef std::vector inline_instance_map_t; /* XXX FIXME functions that dwflpp needs from tapsets.cxx */ func_info_map_t *get_filtered_functions(dwarf_query *q); inline_instance_map_t *get_filtered_inlines(dwarf_query *q); struct module_info { Dwfl_Module* mod; const char* name; std::string elf_path; Dwarf_Addr addr; Dwarf_Addr bias; symbol_table *sym_table; info_status dwarf_status; // module has dwarf info? info_status symtab_status; // symbol table cached? // set of all symbols in module (includes inlines) std::set sym_seen; void get_symtab(dwarf_query *q); void update_symtab(cu_function_cache_t *funcs); module_info(const char *name) : mod(NULL), name(name), addr(0), bias(0), sym_table(NULL), dwarf_status(info_unknown), symtab_status(info_unknown) {} ~module_info(); }; struct module_cache { std::map cache; bool paths_collected; bool dwarf_collected; module_cache() : paths_collected(false), dwarf_collected(false) {} ~module_cache(); }; struct func_info { func_info() : decl_file(NULL), decl_line(-1), addr(0), entrypc(0), prologue_end(0), weak(false), descriptor(false) { std::memset(&die, 0, sizeof(die)); } std::string name; char const * decl_file; int decl_line; Dwarf_Die die; Dwarf_Addr addr; Dwarf_Addr entrypc; Dwarf_Addr prologue_end; bool weak, descriptor; }; struct inline_instance_info { inline_instance_info() : decl_file(NULL), decl_line(-1), entrypc(0) { std::memset(&die, 0, sizeof(die)); } bool operator<(const inline_instance_info& other) const; std::string name; char const * decl_file; int decl_line; Dwarf_Addr entrypc; Dwarf_Die die; }; struct dwflpp { systemtap_session & sess; // These are "current" values we focus on. Dwfl_Module * module; Dwarf_Addr module_bias; module_info * mod_info; // These describe the current module's PC address range Dwarf_Addr module_start; Dwarf_Addr module_end; Dwarf_Die * cu; std::string module_name; std::string function_name; dwflpp(systemtap_session & session, const std::string& user_module, bool kernel_p); dwflpp(systemtap_session & session, const std::vector& user_modules, bool kernel_p); ~dwflpp(); void get_module_dwarf(bool required = false, bool report = true); void focus_on_module(Dwfl_Module * m, module_info * mi); void focus_on_cu(Dwarf_Die * c); void focus_on_function(Dwarf_Die * f); std::string cu_name(void); Dwarf_Die *query_cu_containing_address(Dwarf_Addr a); bool module_name_matches(const std::string& pattern); static bool name_has_wildcard(const std::string& pattern); bool module_name_final_match(const std::string& pattern); bool function_name_matches_pattern(const std::string& name, const std::string& pattern); bool function_name_matches(const std::string& pattern); bool function_scope_matches(const std::vector& scopes); void iterate_over_modules(int (* callback)(Dwfl_Module *, void **, const char *, Dwarf_Addr, void *), void *data); void iterate_over_cus (int (*callback)(Dwarf_Die * die, void * arg), void * data, bool want_types); bool func_is_inline(); bool func_is_exported(); void iterate_over_inline_instances (int (* callback)(Dwarf_Die * die, void * arg), void * data); std::vector getscopes_die(Dwarf_Die* die); std::vector getscopes(Dwarf_Die* die); std::vector getscopes(Dwarf_Addr pc); Dwarf_Die *declaration_resolve(Dwarf_Die *type); Dwarf_Die *declaration_resolve(const std::string& name); Dwarf_Die *declaration_resolve_other_cus(const std::string& name); int iterate_over_functions (int (* callback)(Dwarf_Die * func, base_query * q), base_query * q, const std::string& function); int iterate_single_function (int (* callback)(Dwarf_Die * func, base_query * q), base_query * q, const std::string& function); void iterate_over_srcfile_lines (char const * srcfile, int lines[2], bool need_single_match, enum line_t line_type, void (* callback) (const dwarf_line_t& line, void * arg), const std::string& func_pattern, void *data); void iterate_over_labels (Dwarf_Die *begin_die, const std::string& sym, const std::string& function, dwarf_query *q, void (* callback)(const std::string &, const char *, const char *, int, Dwarf_Die *, Dwarf_Addr, dwarf_query *)); int iterate_over_notes (void *object, void (*callback)(void *object, int type, const char *data, size_t len)); void iterate_over_libraries (void (*callback)(void *object, const char *data), void *data); int iterate_over_plt (void *object, void (*callback)(void *object, const char *name, size_t address)); GElf_Shdr * get_section(std::string section_name, GElf_Shdr *shdr_mem, Elf **elf_ret=NULL); void collect_srcfiles_matching (std::string const & pattern, std::set & filtered_srcfiles); void resolve_prologue_endings (func_info_map_t & funcs); bool function_entrypc (Dwarf_Addr * addr); bool die_entrypc (Dwarf_Die * die, Dwarf_Addr * addr); void function_die (Dwarf_Die *d); void function_file (char const ** c); void function_line (int *linep); bool die_has_pc (Dwarf_Die & die, Dwarf_Addr pc); bool inner_die_containing_pc(Dwarf_Die& scope, Dwarf_Addr addr, Dwarf_Die& result); std::string literal_stmt_for_local (std::vector& scopes, Dwarf_Addr pc, std::string const & local, const target_symbol *e, bool lvalue, exp_type & ty); Dwarf_Die* type_die_for_local (std::vector& scopes, Dwarf_Addr pc, std::string const & local, const target_symbol *e, Dwarf_Die *die_mem); std::string literal_stmt_for_return (Dwarf_Die *scope_die, Dwarf_Addr pc, const target_symbol *e, bool lvalue, exp_type & ty); Dwarf_Die* type_die_for_return (Dwarf_Die *scope_die, Dwarf_Addr pc, const target_symbol *e, Dwarf_Die *die_mem); std::string literal_stmt_for_pointer (Dwarf_Die *type_die, const target_symbol *e, bool lvalue, exp_type & ty); Dwarf_Die* type_die_for_pointer (Dwarf_Die *type_die, const target_symbol *e, Dwarf_Die *die_mem); bool blacklisted_p(const std::string& funcname, const std::string& filename, int line, const std::string& module, Dwarf_Addr addr, bool has_return); Dwarf_Addr relocate_address(Dwarf_Addr addr, std::string& reloc_section); void resolve_unqualified_inner_typedie (Dwarf_Die *typedie, Dwarf_Die *innerdie, const target_symbol *e); private: DwflPtr dwfl_ptr; // These are "current" values we focus on. Dwarf * module_dwarf; Dwarf_Die * function; void setup_kernel(const std::string& module_name, systemtap_session &s, bool debuginfo_needed = true); void setup_kernel(const std::vector& modules, bool debuginfo_needed = true); void setup_user(const std::vector& modules, bool debuginfo_needed = true); module_cu_cache_t module_cu_cache; module_tus_read_t module_tus_read; mod_cu_function_cache_t cu_function_cache; mod_function_cache_t mod_function_cache; std::set cu_inl_function_cache_done; // CUs that are already cached cu_inl_function_cache_t cu_inl_function_cache; void cache_inline_instances (Dwarf_Die* die); mod_cu_die_parent_cache_t cu_die_parent_cache; void cache_die_parents(cu_die_parent_cache_t* parents, Dwarf_Die* die); cu_die_parent_cache_t *get_die_parents(); Dwarf_Die* get_parent_scope(Dwarf_Die* die); /* The global alias cache is used to resolve any DIE found in a * module that is stubbed out with DW_AT_declaration with a defining * DIE found in a different module. The current assumption is that * this only applies to structures and unions, which have a global * namespace (it deliberately only traverses program scope), so this * cache is indexed by name. If other declaration lookups were * added to it, it would have to be indexed by name and tag */ mod_cu_type_cache_t global_alias_cache; static int global_alias_caching_callback(Dwarf_Die *die, bool has_inner_types, const std::string& prefix, void *arg); static int global_alias_caching_callback_cus(Dwarf_Die *die, void *arg); static int iterate_over_globals (Dwarf_Die *, int (* callback)(Dwarf_Die *, bool, const std::string&, void *), void * data); static int iterate_over_types (Dwarf_Die *, bool, const std::string&, int (* callback)(Dwarf_Die *, bool, const std::string&, void *), void * data); static int mod_function_caching_callback (Dwarf_Die* func, void *arg); static int cu_function_caching_callback (Dwarf_Die* func, void *arg); bool has_single_line_record (dwarf_query * q, char const * srcfile, int lineno); static void loc2c_error (void *, const char *fmt, ...) __attribute__ ((noreturn)); // This function generates code used for addressing computations of // target variables. void emit_address (struct obstack *pool, Dwarf_Addr address); static void loc2c_emit_address (void *arg, struct obstack *pool, Dwarf_Addr address); void print_locals(std::vector& scopes, std::ostream &o); void print_locals_die(Dwarf_Die &die, std::ostream &o); void print_members(Dwarf_Die *vardie, std::ostream &o, std::set &dupes); Dwarf_Attribute *find_variable_and_frame_base (std::vector& scopes, Dwarf_Addr pc, std::string const & local, const target_symbol *e, Dwarf_Die *vardie, Dwarf_Attribute *fb_attr_mem); struct location *translate_location(struct obstack *pool, Dwarf_Attribute *attr, Dwarf_Die *die, Dwarf_Addr pc, Dwarf_Attribute *fb_attr, struct location **tail, const target_symbol *e); bool find_struct_member(const target_symbol::component& c, Dwarf_Die *parentdie, Dwarf_Die *memberdie, std::vector& dies, std::vector& locs); void translate_components(struct obstack *pool, struct location **tail, Dwarf_Addr pc, const target_symbol *e, Dwarf_Die *vardie, Dwarf_Die *typedie, unsigned first=0); void translate_final_fetch_or_store (struct obstack *pool, struct location **tail, Dwarf_Addr module_bias, Dwarf_Die *vardie, Dwarf_Die *typedie, bool lvalue, const target_symbol *e, std::string &, std::string &, exp_type & ty); std::string express_as_string (std::string prelude, std::string postlude, struct location *head); regex_t blacklist_func; // function/statement probes regex_t blacklist_func_ret; // only for .return probes regex_t blacklist_file; // file name regex_t blacklist_section; // init/exit sections bool blacklist_enabled; void build_blacklist(); std::string get_blacklist_section(Dwarf_Addr addr); // Returns the call frame address operations for the given program counter. Dwarf_Op *get_cfa_ops (Dwarf_Addr pc); Dwarf_Addr vardie_from_symtable(Dwarf_Die *vardie, Dwarf_Addr *addr); static int add_module_build_id_to_hash (Dwfl_Module *m, void **userdata __attribute__ ((unused)), const char *name, Dwarf_Addr base, void *arg); public: Dwarf_Addr pr15123_retry_addr (Dwarf_Addr pc, Dwarf_Die* var); }; #endif // DWFLPP_H /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/elaborate.cxx000066400000000000000000004527511217430427200161110ustar00rootroot00000000000000// elaboration functions // Copyright (C) 2005-2013 Red Hat Inc. // Copyright (C) 2008 Intel Corporation // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "config.h" #include "elaborate.h" #include "translate.h" #include "parse.h" #include "tapsets.h" #include "session.h" #include "util.h" #include "task_finder.h" #include "stapregex.h" extern "C" { #include #include #define __STDC_FORMAT_MACROS #include } #include #include #include #include #include #include #include #include #include using namespace std; // ------------------------------------------------------------------------ // Used in probe_point condition construction. Either argument may be // NULL; if both, return NULL too. Resulting expression is a deep // copy for symbol resolution purposes. expression* add_condition (expression* a, expression* b) { if (!a && !b) return 0; if (! a) return deep_copy_visitor::deep_copy(b); if (! b) return deep_copy_visitor::deep_copy(a); logical_and_expr la; la.op = "&&"; la.left = a; la.right = b; la.tok = a->tok; // or could be b->tok return deep_copy_visitor::deep_copy(& la); } // ------------------------------------------------------------------------ derived_probe::derived_probe (probe *p, probe_point *l, bool rewrite_loc): base (p), base_pp(l), sdt_semaphore_addr(0), session_index((unsigned)-1) { assert (p); this->tok = p->tok; this->privileged = p->privileged; this->body = deep_copy_visitor::deep_copy(p->body); assert (l); // make a copy for subclasses which want to rewrite the location if (rewrite_loc) l = new probe_point(*l); this->locations.push_back (l); } void derived_probe::printsig (ostream& o) const { probe::printsig (o); printsig_nested (o); } void derived_probe::printsig_nested (ostream& o) const { // We'd like to enclose the probe derivation chain in a /* */ // comment delimiter. But just printing /* base->printsig() */ is // not enough, since base might itself be a derived_probe. So we, // er, "cleverly" encode our nesting state as a formatting flag for // the ostream. ios::fmtflags f = o.flags (ios::internal); if (f & ios::internal) { // already nested o << " <- "; base->printsig (o); } else { // outermost nesting o << " /* <- "; base->printsig (o); o << " */"; } // restore flags (void) o.flags (f); } void derived_probe::collect_derivation_chain (std::vector &probes_list) const { probes_list.push_back(const_cast(this)); base->collect_derivation_chain(probes_list); } void derived_probe::collect_derivation_pp_chain (std::vector &pp_list) const { pp_list.push_back(const_cast(this->sole_location())); base->collect_derivation_pp_chain(pp_list); } string derived_probe::derived_locations () { ostringstream o; vector reference_point; collect_derivation_pp_chain(reference_point); if (reference_point.size() > 0) for(unsigned i=1; istr(false); // no ?,!,etc return o.str(); } probe_point* derived_probe::sole_location () const { if (locations.size() == 0 || locations.size() > 1) throw semantic_error (_N("derived_probe with no locations", "derived_probe with too many locations", locations.size()), this->tok); else return locations[0]; } probe_point* derived_probe::script_location () const { // This feeds function::pn() in the tapset, which is documented as the // script-level probe point expression, *after wildcard expansion*. If // it were not for wildcard stuff, we'd just return the last item in the // derivation chain. But alas ... we need to search for the last one // that doesn't have a * in the textual representation. Heuristics, eww. vector chain; collect_derivation_pp_chain (chain); // NB: we actually start looking from the second-to-last item, so the user's // direct input is not considered. Input like 'kernel.function("init_once")' // will thus be listed with the resolved @file:line too, disambiguating the // distinct functions by this name, and matching our historical behavior. for (int i=chain.size()-2; i>=0; i--) { probe_point pp_copy (* chain [i]); // drop any ?/! denotations that would confuse a glob-char search pp_copy.optional = false; pp_copy.sufficient = false; string pp_printed = lex_cast(pp_copy); if (! contains_glob_chars(pp_printed)) return chain[i]; } // If that didn't work, just fallback to -something-. return sole_location(); } void derived_probe::emit_privilege_assertion (translator_output* o) { // Emit code which will cause compilation to fail if it is compiled in // unprivileged mode. o->newline() << "#if ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPDEV) && \\"; o->newline() << " ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPSYS)"; o->newline() << "#error Internal Error: Probe "; probe::printsig (o->line()); o->line() << " generated in --unprivileged mode"; o->newline() << "#endif"; } void derived_probe::emit_process_owner_assertion (translator_output* o) { // Emit code which will abort should the current target not belong to the // user in unprivileged mode. o->newline() << "#if ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPDEV) && \\"; o->newline() << " ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPSYS)"; o->newline(1) << "if (! is_myproc ()) {"; o->newline(1) << "snprintf(c->error_buffer, sizeof(c->error_buffer),"; o->newline() << " \"Internal Error: Process %d does not belong to user %d in probe %s in --unprivileged mode\","; o->newline() << " current->tgid, _stp_uid, c->probe_point);"; o->newline() << "c->last_error = c->error_buffer;"; // NB: since this check occurs before probe locking, its exit should // not be a "goto out", which would attempt unlocking. o->newline() << "return;"; o->newline(-1) << "}"; o->newline(-1) << "#endif"; } void derived_probe::print_dupe_stamp_unprivileged(ostream& o) { o << _("unprivileged users: authorized") << endl; } void derived_probe::print_dupe_stamp_unprivileged_process_owner(ostream& o) { o << _("unprivileged users: authorized for process owner") << endl; } // ------------------------------------------------------------------------ // Members of derived_probe_builder void derived_probe_builder::build_with_suffix(systemtap_session & sess, probe * use, probe_point * location, std::map const & parameters, std::vector & finished_results, std::vector const & suffix) { // XXX perhaps build the probe if suffix is empty? // if (suffix.empty()) { // build (sess, use, location, parameters, finished_results); // return; // } throw semantic_error (_("invalid suffix for probe")); } bool derived_probe_builder::get_param (std::map const & params, const std::string& key, std::string& value) { map::const_iterator i = params.find (key); if (i == params.end()) return false; literal_string * ls = dynamic_cast(i->second); if (!ls) return false; value = ls->value; return true; } bool derived_probe_builder::get_param (std::map const & params, const std::string& key, int64_t& value) { map::const_iterator i = params.find (key); if (i == params.end()) return false; if (i->second == NULL) return false; literal_number * ln = dynamic_cast(i->second); if (!ln) return false; value = ln->value; return true; } bool derived_probe_builder::has_null_param (std::map const & params, const std::string& key) { map::const_iterator i = params.find(key); return (i != params.end() && i->second == NULL); } // ------------------------------------------------------------------------ // Members of match_key. match_key::match_key(string const & n) : name(n), have_parameter(false), parameter_type(pe_unknown) { } match_key::match_key(probe_point::component const & c) : name(c.functor), have_parameter(c.arg != NULL), parameter_type(c.arg ? c.arg->type : pe_unknown) { } match_key & match_key::with_number() { have_parameter = true; parameter_type = pe_long; return *this; } match_key & match_key::with_string() { have_parameter = true; parameter_type = pe_string; return *this; } string match_key::str() const { if (have_parameter) switch (parameter_type) { case pe_string: return name + "(string)"; case pe_long: return name + "(number)"; default: return name + "(...)"; } return name; } bool match_key::operator<(match_key const & other) const { return ((name < other.name) || (name == other.name && have_parameter < other.have_parameter) || (name == other.name && have_parameter == other.have_parameter && parameter_type < other.parameter_type)); } // NB: these are only used in the probe point name components, where // only "*" is permitted. // // Within module("bar"), function("foo"), process("baz") strings, real // wildcards are permitted too. See also util.h:contains_glob_chars static bool isglob(string const & str) { return(str.find('*') != str.npos); } static bool isdoubleglob(string const & str) { return(str.find("**") != str.npos); } bool match_key::globmatch(match_key const & other) const { const char *other_str = other.name.c_str(); const char *name_str = name.c_str(); return ((fnmatch(name_str, other_str, FNM_NOESCAPE) == 0) && have_parameter == other.have_parameter && parameter_type == other.parameter_type); } // ------------------------------------------------------------------------ // Members of match_node // ------------------------------------------------------------------------ match_node::match_node() : privilege(privilege_t (pr_stapdev | pr_stapsys)) { } match_node * match_node::bind(match_key const & k) { if (k.name == "*") throw semantic_error(_("invalid use of wildcard probe point component")); map::const_iterator i = sub.find(k); if (i != sub.end()) return i->second; match_node * n = new match_node(); sub.insert(make_pair(k, n)); return n; } void match_node::bind(derived_probe_builder * e) { ends.push_back (e); } match_node * match_node::bind(string const & k) { return bind(match_key(k)); } match_node * match_node::bind_str(string const & k) { return bind(match_key(k).with_string()); } match_node * match_node::bind_num(string const & k) { return bind(match_key(k).with_number()); } match_node * match_node::bind_privilege(privilege_t p) { privilege = p; return this; } void match_node::find_and_build (systemtap_session& s, probe* p, probe_point *loc, unsigned pos, vector& results) { assert (pos <= loc->components.size()); if (pos == loc->components.size()) // matched all probe point components so far { if (ends.empty()) { string alternatives; for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++) alternatives += string(" ") + i->first.str(); throw semantic_error (_F("probe point truncated (follow: %s)", alternatives.c_str()), loc->components.back()->tok); } if (! pr_contains (privilege, s.privilege)) { throw semantic_error (_F("probe point is not allowed for --privilege=%s", pr_name (s.privilege)), loc->components.back()->tok); } map param_map; for (unsigned i=0; icomponents[i]->functor] = loc->components[i]->arg; // maybe 0 // Iterate over all bound builders for (unsigned k=0; kbuild (s, p, loc, param_map, results); } } else if (isdoubleglob(loc->components[pos]->functor)) // ** wildcard? { unsigned int num_results = results.size(); // When faced with "foo**bar", we try "foo*bar" and "foo*.**bar" const probe_point::component *comp = loc->components[pos]; const string &functor = comp->functor; size_t glob_start = functor.find("**"); size_t glob_end = functor.find_first_not_of('*', glob_start); const string prefix = functor.substr(0, glob_start); const string suffix = ((glob_end != string::npos) ? functor.substr(glob_end) : ""); // Synthesize "foo*bar" probe_point *simple_pp = new probe_point(*loc); probe_point::component *simple_comp = new probe_point::component(*comp); simple_comp->functor = prefix + "*" + suffix; simple_pp->components[pos] = simple_comp; try { find_and_build (s, p, simple_pp, pos, results); } catch (const semantic_error& e) { // Ignore semantic_errors, but cleanup delete simple_pp; delete simple_comp; } // Synthesize "foo*.**bar" // NB: any component arg should attach to the latter part only probe_point *expanded_pp = new probe_point(*loc); probe_point::component *expanded_comp_pre = new probe_point::component(*comp); expanded_comp_pre->functor = prefix + "*"; expanded_comp_pre->arg = NULL; probe_point::component *expanded_comp_post = new probe_point::component(*comp); expanded_comp_post->functor = "**" + suffix; expanded_pp->components[pos] = expanded_comp_pre; expanded_pp->components.insert(expanded_pp->components.begin() + pos + 1, expanded_comp_post); try { find_and_build (s, p, expanded_pp, pos, results); } catch (const semantic_error& e) { // Ignore semantic_errors, but cleanup delete expanded_pp; delete expanded_comp_pre; delete expanded_comp_post; } // Try suffix expansion only if no matches found: if (num_results == results.size()) try { this->try_suffix_expansion (s, p, loc, pos, results); } catch (const recursive_expansion_error &e) { s.print_error(e); return; // Suppress probe mismatch msg. } if (! loc->optional && num_results == results.size()) { // We didn't find any wildcard matches (since the size of // the result vector didn't change). Throw an error. string alternatives; for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++) alternatives += string(" ") + i->first.str(); throw semantic_error(_F("probe point mismatch (alternatives: %s)", alternatives.c_str()), comp->tok); } } else if (isglob(loc->components[pos]->functor)) // wildcard? { match_key match (* loc->components[pos]); // Call find_and_build for each possible match. Ignore errors - // unless we don't find any match. unsigned int num_results = results.size(); for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++) { const match_key& subkey = i->first; match_node* subnode = i->second; assert_no_interrupts(); if (match.globmatch(subkey)) { if (s.verbose > 2) clog << _F("wildcard '%s' matched '%s'", loc->components[pos]->functor.c_str(), subkey.name.c_str()) << endl; // When we have a wildcard, we need to create a copy of // the probe point. Then we'll create a copy of the // wildcard component, and substitute the non-wildcard // functor. probe_point *non_wildcard_pp = new probe_point(*loc); probe_point::component *non_wildcard_component = new probe_point::component(*loc->components[pos]); non_wildcard_component->functor = subkey.name; non_wildcard_pp->components[pos] = non_wildcard_component; // NB: probe conditions are not attached at the wildcard // (component/functor) level, but at the overall // probe_point level. // recurse (with the non-wildcard probe point) try { subnode->find_and_build (s, p, non_wildcard_pp, pos+1, results); } catch (const semantic_error& e) { // Ignore semantic_errors while expanding wildcards. // If we get done and nothing was expanded, the code // following the loop will complain. // If this wildcard didn't match, cleanup. delete non_wildcard_pp; delete non_wildcard_component; } } } // Try suffix expansion only if no matches found: if (num_results == results.size()) try { this->try_suffix_expansion (s, p, loc, pos, results); } catch (const recursive_expansion_error &e) { s.print_error(e); return; // Suppress probe mismatch msg. } if (! loc->optional && num_results == results.size()) { // We didn't find any wildcard matches (since the size of // the result vector didn't change). Throw an error. string alternatives; for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++) alternatives += string(" ") + i->first.str(); throw semantic_error(_F("probe point mismatch %s didn't find any wildcard matches", (alternatives == "" ? "" : _(" (alternatives: ") + alternatives + ")").c_str()), loc->components[pos]->tok); } } else { match_key match (* loc->components[pos]); sub_map_iterator_t i = sub.find (match); if (i != sub.end()) // match found { match_node* subnode = i->second; // recurse subnode->find_and_build (s, p, loc, pos+1, results); return; } unsigned int num_results = results.size(); try { this->try_suffix_expansion (s, p, loc, pos, results); } catch (const recursive_expansion_error &e) { s.print_error(e); return; // Suppress probe mismatch msg. } // XXX: how to correctly report alternatives + position numbers // for alias suffixes? file a separate PR to address the issue if (! loc->optional && num_results == results.size()) { // We didn't find any alias suffixes (since the size of the // result vector didn't change). Throw an error. string alternatives; for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++) alternatives += string(" ") + i->first.str(); throw semantic_error(_F("probe point mismatch %s", (alternatives == "" ? "" : (_(" (alternatives:") + alternatives + ")").c_str())), loc->components[pos]->tok); } } } void match_node::try_suffix_expansion (systemtap_session& s, probe *p, probe_point *loc, unsigned pos, vector& results) { // PR12210: match alias suffixes. If the components thus far // have been matched, but there is an additional unknown // suffix, we have a potential alias suffix on our hands. We // need to expand the preceding components as probe aliases, // reattach the suffix, and re-run derive_probes() on the // resulting expansion. This is done by the routine // build_with_suffix(). if (strverscmp(s.compatible.c_str(), "2.0") >= 0) { // XXX: technically, param_map isn't used here. So don't // bother actually assembling it unless some // derived_probe_builder appears that actually takes // suffixes *and* consults parameters (currently no such // builders exist). map param_map; // for (unsigned i=0; icomponents[i]->functor] = loc->components[i]->arg; // maybe 0 vector suffix (loc->components.begin()+pos, loc->components.end()); // Multiple derived_probe_builders may be bound at a // match_node due to the possibility of multiply defined // aliases. for (unsigned k=0; k < ends.size(); k++) { derived_probe_builder *b = ends[k]; try { b->build_with_suffix (s, p, loc, param_map, results, suffix); } catch (const recursive_expansion_error &e) { // Re-throw: throw semantic_error(e); } catch (const semantic_error &e) { // Adjust source coordinate and re-throw: if (! loc->optional) throw semantic_error(e.what(), loc->components[pos]->tok); } } } } void match_node::build_no_more (systemtap_session& s) { for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++) i->second->build_no_more (s); for (unsigned k=0; kbuild_no_more (s); } } void match_node::dump (systemtap_session &s, const string &name) { // Dump this node, if it is complete. for (unsigned k=0; kis_alias ()) continue; // In unprivileged mode, don't show the probes which are not allowed for unprivileged // users. if (pr_contains (privilege, s.privilege)) { cout << name << endl; break; // we need only print one instance. } } // Recursively dump the children of this node string dot; if (! name.empty ()) dot = "."; for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++) { i->second->dump (s, name + dot + i->first.str()); } } // ------------------------------------------------------------------------ // Alias probes // ------------------------------------------------------------------------ struct alias_derived_probe: public derived_probe { alias_derived_probe (probe* base, probe_point *l, const probe_alias *a, const vector *suffix = 0); void upchuck () { throw semantic_error (_("inappropriate"), this->tok); } // Alias probes are immediately expanded to other derived_probe // types, and are not themselves emitted or listed in // systemtap_session.probes void join_group (systemtap_session&) { upchuck (); } virtual const probe_alias *get_alias () const { return alias; } virtual probe_point *get_alias_loc () const { return alias_loc; } virtual probe_point *sole_location () const; private: const probe_alias *alias; // Used to check for recursion probe_point *alias_loc; // Hack to recover full probe name }; alias_derived_probe::alias_derived_probe(probe *base, probe_point *l, const probe_alias *a, const vector *suffix): derived_probe (base, l), alias(a) { // XXX pretty nasty -- this was cribbed from printscript() in main.cxx assert (alias->alias_names.size() >= 1); alias_loc = new probe_point(*alias->alias_names[0]); // XXX: [0] is arbitrary; it would make just as much sense to collect all of the names if (suffix) { alias_loc->components.insert(alias_loc->components.end(), suffix->begin(), suffix->end()); } } probe_point* alias_derived_probe::sole_location () const { return const_cast(alias_loc); } probe* probe::create_alias(probe_point* l, probe_point* a) { vector aliases(1, a); probe_alias* p = new probe_alias(aliases); p->tok = tok; p->locations.push_back(l); p->body = body; p->base = this; p->privileged = privileged; p->epilogue_style = false; return new alias_derived_probe(this, l, p); } void alias_expansion_builder::build(systemtap_session & sess, probe * use, probe_point * location, std::map const & parameters, vector & finished_results) { vector empty_suffix; build_with_suffix (sess, use, location, parameters, finished_results, empty_suffix); } void alias_expansion_builder::build_with_suffix(systemtap_session & sess, probe * use, probe_point * location, std::map const &, vector & finished_results, vector const & suffix) { // Don't build the alias expansion if infinite recursion is detected. if (checkForRecursiveExpansion (use)) { stringstream msg; msg << _F("Recursive loop in alias expansion of %s at %s", lex_cast(*location).c_str(), lex_cast(location->components.front()->tok->location).c_str()); // semantic_errors thrown here might be ignored, so we need a special class: throw recursive_expansion_error (msg.str()); // XXX The point of throwing this custom error is to suppress a // cascade of "probe mismatch" messages that appear in addition to // the error. The current approach suppresses most of the error // cascade, but leaves one spurious error; in any case, the way // this particular error is reported could be improved. } // We're going to build a new probe and wrap it up in an // alias_expansion_probe so that the expansion loop recognizes it as // such and re-expands its expansion. alias_derived_probe * n = new alias_derived_probe (use, location /* soon overwritten */, this->alias, &suffix); n->body = new block(); // The new probe gets a deep copy of the location list of the alias // (with incoming condition joined) plus the suffix (if any), n->locations.clear(); for (unsigned i=0; ilocations.size(); i++) { probe_point *pp = new probe_point(*alias->locations[i]); pp->components.insert(pp->components.end(), suffix.begin(), suffix.end()); pp->condition = add_condition (pp->condition, location->condition); n->locations.push_back(pp); } // the token location of the alias, n->tok = location->components.front()->tok; // and statements representing the concatenation of the alias' // body with the use's. // // NB: locals are *not* copied forward, from either alias or // use. The expansion should have its locals re-inferred since // there's concatenated code here and we only want one vardecl per // resulting variable. if (alias->epilogue_style) n->body = new block (use->body, alias->body); else n->body = new block (alias->body, use->body); unsigned old_num_results = finished_results.size(); // If expanding for an alias suffix, be sure to pass on any errors // to the caller instead of printing them in derive_probes(): derive_probes (sess, n, finished_results, location->optional, !suffix.empty()); // Check whether we resolved something. If so, put the // whole library into the queue if not already there. if (finished_results.size() > old_num_results) { stapfile *f = alias->tok->location.file; if (find (sess.files.begin(), sess.files.end(), f) == sess.files.end()) sess.files.push_back (f); } } bool alias_expansion_builder::checkForRecursiveExpansion (probe *use) { // Collect the derivation chain of this probe. vectorderivations; use->collect_derivation_chain (derivations); // Check all probe points in the alias expansion against the currently-being-expanded probe point // of each of the probes in the derivation chain, looking for a match. This // indicates infinite recursion. // The first element of the derivation chain will be the derived_probe representing 'use', so // start the search with the second element. assert (derivations.size() > 0); assert (derivations[0] == use); for (unsigned d = 1; d < derivations.size(); ++d) { if (use->get_alias() == derivations[d]->get_alias()) return true; // recursion detected } return false; } // ------------------------------------------------------------------------ // Pattern matching // ------------------------------------------------------------------------ static unsigned max_recursion = 100; struct recursion_guard { unsigned & i; recursion_guard(unsigned & i) : i(i) { if (i > max_recursion) throw semantic_error(_("recursion limit reached")); ++i; } ~recursion_guard() { --i; } }; // The match-and-expand loop. void derive_probes (systemtap_session& s, probe *p, vector& dps, bool optional, bool rethrow_errors) { for (unsigned i = 0; i < p->locations.size(); ++i) { assert_no_interrupts(); probe_point *loc = p->locations[i]; if (s.verbose > 4) clog << "derive-probes " << *loc << endl; try { unsigned num_atbegin = dps.size(); // Pass down optional flag from e.g. alias reference to each // probe_point instance. We do this by temporarily overriding // the probe_point optional flag. We could instead deep-copy // and set a flag on the copy permanently. bool old_loc_opt = loc->optional; loc->optional = loc->optional || optional; try { s.pattern_root->find_and_build (s, p, loc, 0, dps); // <-- actual derivation! } catch (const semantic_error& e) { if (!loc->optional) throw semantic_error(e); else /* tolerate failure for optional probe */ continue; } loc->optional = old_loc_opt; unsigned num_atend = dps.size(); if (! (loc->optional||optional) && // something required, but num_atbegin == num_atend) // nothing new derived! throw semantic_error (_("no match")); if (loc->sufficient && (num_atend > num_atbegin)) { if (s.verbose > 1) { clog << "Probe point "; p->locations[i]->print(clog); clog << " sufficient, skipped"; for (unsigned j = i+1; j < p->locations.size(); ++j) { clog << " "; p->locations[j]->print(clog); } clog << endl; } break; // we need not try to derive for any other locations } } catch (const semantic_error& e) { // The rethrow_errors parameter lets the caller decide an // alternative to printing the error. This is necessary when // calling derive_probes() recursively during expansion of // an alias with suffix -- any message printed here would // point to the alias declaration and not the invalid suffix // usage, so the caller needs to catch the error themselves // and print a more appropriate message. if (rethrow_errors) { throw semantic_error(e); } // Only output in listing if -vv is supplied: else if (!s.listing_mode || (s.listing_mode && s.verbose > 1)) { // XXX: prefer not to print_error at every nest/unroll level semantic_error* er = new semantic_error (_("while resolving probe point"), loc->components[0]->tok); er->chain = & e; s.print_error (* er); delete er; } } } } // ------------------------------------------------------------------------ // // Indexable usage checks // struct symbol_fetcher : public throwing_visitor { symbol *&sym; symbol_fetcher (symbol *&sym): sym(sym) {} void visit_symbol (symbol* e) { sym = e; } void visit_target_symbol (target_symbol* e) { sym = e; } void visit_arrayindex (arrayindex* e) { e->base->visit (this); } void visit_atvar_op (atvar_op *e) { sym = e; } void visit_cast_op (cast_op* e) { sym = e; } void throwone (const token* t) { if (t->type == tok_operator && t->content == ".") // guess someone misused . in $foo->bar.baz expression throw semantic_error (_("Expecting symbol or array index expression, try -> instead"), t); else throw semantic_error (_("Expecting symbol or array index expression"), t); } }; symbol * get_symbol_within_expression (expression *e) { symbol *sym = NULL; symbol_fetcher fetcher(sym); e->visit (&fetcher); return sym; // NB: may be null! } static symbol * get_symbol_within_indexable (indexable *ix) { symbol *array = NULL; hist_op *hist = NULL; classify_indexable(ix, array, hist); if (array) return array; else return get_symbol_within_expression (hist->stat); } struct mutated_var_collector : public traversing_visitor { set * mutated_vars; mutated_var_collector (set * mm) : mutated_vars (mm) {} void visit_assignment(assignment* e) { if (e->type == pe_stats && e->op == "<<<") { vardecl *vd = get_symbol_within_expression (e->left)->referent; if (vd) mutated_vars->insert (vd); } traversing_visitor::visit_assignment(e); } void visit_arrayindex (arrayindex *e) { if (is_active_lvalue (e)) { symbol *sym; if (e->base->is_symbol (sym)) mutated_vars->insert (sym->referent); else throw semantic_error(_("Assignment to read-only histogram bucket"), e->tok); } traversing_visitor::visit_arrayindex (e); } }; struct no_var_mutation_during_iteration_check : public traversing_visitor { systemtap_session & session; map *> & function_mutates_vars; vector vars_being_iterated; no_var_mutation_during_iteration_check (systemtap_session & sess, map *> & fmv) : session(sess), function_mutates_vars (fmv) {} void visit_arrayindex (arrayindex *e) { if (is_active_lvalue(e)) { vardecl *vd = get_symbol_within_indexable (e->base)->referent; if (vd) { for (unsigned i = 0; i < vars_being_iterated.size(); ++i) { vardecl *v = vars_being_iterated[i]; if (v == vd) { string err = _F("variable '%s' modified during 'foreach' iteration", v->name.c_str()); session.print_error (semantic_error (err, e->tok)); } } } } traversing_visitor::visit_arrayindex (e); } void visit_functioncall (functioncall* e) { map *>::const_iterator i = function_mutates_vars.find (e->referent); if (i != function_mutates_vars.end()) { for (unsigned j = 0; j < vars_being_iterated.size(); ++j) { vardecl *m = vars_being_iterated[j]; if (i->second->find (m) != i->second->end()) { string err = _F("function call modifies var '%s' during 'foreach' iteration", m->name.c_str()); session.print_error (semantic_error (err, e->tok)); } } } traversing_visitor::visit_functioncall (e); } void visit_foreach_loop(foreach_loop* s) { vardecl *vd = get_symbol_within_indexable (s->base)->referent; if (vd) vars_being_iterated.push_back (vd); traversing_visitor::visit_foreach_loop (s); if (vd) vars_being_iterated.pop_back(); } }; // ------------------------------------------------------------------------ struct stat_decl_collector : public traversing_visitor { systemtap_session & session; stat_decl_collector(systemtap_session & sess) : session(sess) {} void visit_stat_op (stat_op* e) { symbol *sym = get_symbol_within_expression (e->stat); if (session.stat_decls.find(sym->name) == session.stat_decls.end()) session.stat_decls[sym->name] = statistic_decl(); } void visit_assignment (assignment* e) { if (e->op == "<<<") { symbol *sym = get_symbol_within_expression (e->left); if (session.stat_decls.find(sym->name) == session.stat_decls.end()) session.stat_decls[sym->name] = statistic_decl(); } else traversing_visitor::visit_assignment(e); } void visit_hist_op (hist_op* e) { symbol *sym = get_symbol_within_expression (e->stat); statistic_decl new_stat; if (e->htype == hist_linear) { new_stat.type = statistic_decl::linear; assert (e->params.size() == 3); new_stat.linear_low = e->params[0]; new_stat.linear_high = e->params[1]; new_stat.linear_step = e->params[2]; } else { assert (e->htype == hist_log); new_stat.type = statistic_decl::logarithmic; assert (e->params.size() == 0); } map::iterator i = session.stat_decls.find(sym->name); if (i == session.stat_decls.end()) session.stat_decls[sym->name] = new_stat; else { statistic_decl & old_stat = i->second; if (!(old_stat == new_stat)) { if (old_stat.type == statistic_decl::none) i->second = new_stat; else { // FIXME: Support multiple co-declared histogram types semantic_error se(_F("multiple histogram types declared on '%s'", sym->name.c_str()), e->tok); session.print_error (se); } } } } }; static int semantic_pass_stats (systemtap_session & sess) { stat_decl_collector sdc(sess); for (map::iterator it = sess.functions.begin(); it != sess.functions.end(); it++) it->second->body->visit (&sdc); for (unsigned i = 0; i < sess.probes.size(); ++i) sess.probes[i]->body->visit (&sdc); for (unsigned i = 0; i < sess.globals.size(); ++i) { vardecl *v = sess.globals[i]; if (v->type == pe_stats) { if (sess.stat_decls.find(v->name) == sess.stat_decls.end()) { semantic_error se(_F("unable to infer statistic parameters for global '%s'", v->name.c_str())); sess.print_error (se); } } } return sess.num_errors(); } // ------------------------------------------------------------------------ // Enforce variable-related invariants: no modification of // a foreach()-iterated array. static int semantic_pass_vars (systemtap_session & sess) { map *> fmv; no_var_mutation_during_iteration_check chk(sess, fmv); for (map::iterator it = sess.functions.begin(); it != sess.functions.end(); it++) { functiondecl * fn = it->second; if (fn->body) { set * m = new set(); mutated_var_collector mc (m); fn->body->visit (&mc); fmv[fn] = m; } } for (map::iterator it = sess.functions.begin(); it != sess.functions.end(); it++) { functiondecl * fn = it->second; if (fn->body) fn->body->visit (&chk); } for (unsigned i = 0; i < sess.probes.size(); ++i) { if (sess.probes[i]->body) sess.probes[i]->body->visit (&chk); } return sess.num_errors(); } // ------------------------------------------------------------------------ // Rewrite probe condition expressions into probe bodies. Tricky and // exciting business, this. This: // // probe foo if (g1 || g2) { ... } // probe bar { ... g1 ++ ... } // // becomes: // // probe begin(MAX) { if (! (g1 || g2)) %{ disable_probe_foo %} } // probe foo { if (! (g1 || g2)) next; ... } // probe bar { ... g1 ++ ...; // if (g1 || g2) %{ enable_probe_foo %} else %{ disable_probe_foo %} // } // // XXX: As a first cut, do only the "inline probe condition" part of the // transform. static int semantic_pass_conditions (systemtap_session & sess) { for (unsigned i = 0; i < sess.probes.size(); ++i) { derived_probe* p = sess.probes[i]; expression* e = p->sole_location()->condition; if (e) { varuse_collecting_visitor vut(sess); e->visit (& vut); if (! vut.written.empty()) { string err = (_("probe condition must not modify any variables")); sess.print_error (semantic_error (err, e->tok)); } else if (vut.embedded_seen) { sess.print_error (semantic_error (_("probe condition must not include impure embedded-C"), e->tok)); } // Add the condition expression to the front of the // derived_probe body. if_statement *ifs = new if_statement (); ifs->tok = e->tok; ifs->thenblock = new next_statement (); ifs->thenblock->tok = e->tok; ifs->elseblock = NULL; unary_expression *notex = new unary_expression (); notex->op = "!"; notex->tok = e->tok; notex->operand = e; ifs->condition = notex; p->body = new block (ifs, p->body); } } return sess.num_errors(); } // ------------------------------------------------------------------------ // Simple visitor that just goes through all embedded code blocks that // are available at the end all the optimizations to register any // relevant pragmas or other indicators found, so that session flags can // be set that can be inspected at translation time to trigger any // necessary initialization of code needed by the embedded code functions. // This is only for pragmas that don't have any other side-effect than // needing some initialization at module init time. Currently handles // /* pragma:vma */ /* pragma:unwind */ /* pragma:symbol */ // /* pragma:uprobes */ is handled during the typeresolution_info pass. // /* pure */, /* unprivileged */. /* myproc-unprivileged */ and /* guru */ // are handled by the varuse_collecting_visitor. struct embeddedcode_info: public functioncall_traversing_visitor { protected: systemtap_session& session; public: embeddedcode_info (systemtap_session& s): session(s) { } void visit_embeddedcode (embeddedcode* c) { if (! vma_tracker_enabled(session) && c->code.find("/* pragma:vma */") != string::npos) { if (session.verbose > 2) clog << _F("Turning on task_finder vma_tracker, pragma:vma found in %s", current_function->name.c_str()) << endl; // PR15052: stapdyn doesn't have VMA-tracking yet. if (session.runtime_usermode_p()) throw semantic_error(_("VMA-tracking is only supported by the kernel runtime (PR15052)"), c->tok); enable_vma_tracker(session); } if (! session.need_unwind && c->code.find("/* pragma:unwind */") != string::npos) { if (session.verbose > 2) clog << _F("Turning on unwind support, pragma:unwind found in %s", current_function->name.c_str()) << endl; session.need_unwind = true; } if (! session.need_symbols && c->code.find("/* pragma:symbols */") != string::npos) { if (session.verbose > 2) clog << _F("Turning on symbol data collecting, pragma:symbols found in %s", current_function->name.c_str()) << endl; session.need_symbols = true; } } }; void embeddedcode_info_pass (systemtap_session& s) { embeddedcode_info eci (s); for (unsigned i=0; ibody->visit (& eci); } // ------------------------------------------------------------------------ // Simple visitor that collects all the regular expressions in the // file and adds them to the session DFA table. struct regex_collecting_visitor: public functioncall_traversing_visitor { protected: systemtap_session& session; public: regex_collecting_visitor (systemtap_session& s): session(s) { } void visit_regex_query (regex_query *q) { functioncall_traversing_visitor::visit_regex_query (q); string re = q->right->value; regex_to_stapdfa (&session, re, q->right->tok); } }; // Go through the regex match invocations and generate corresponding DFAs. int gen_dfa_table (systemtap_session& s) { regex_collecting_visitor rcv(s); for (unsigned i=0; ibody->visit (& rcv); if (s.probes[i]->sole_location()->condition) s.probes[i]->sole_location()->condition->visit (& rcv); } catch (const semantic_error& e) { s.print_error (e); } } return s.num_errors(); } // ------------------------------------------------------------------------ static int semantic_pass_symbols (systemtap_session&); static int semantic_pass_optimize1 (systemtap_session&); static int semantic_pass_optimize2 (systemtap_session&); static int semantic_pass_types (systemtap_session&); static int semantic_pass_vars (systemtap_session&); static int semantic_pass_stats (systemtap_session&); static int semantic_pass_conditions (systemtap_session&); // Link up symbols to their declarations. Set the session's // files/probes/functions/globals vectors from the transitively // reached set of stapfiles in s.library_files, starting from // s.user_file. Perform automatic tapset inclusion and probe // alias expansion. static int semantic_pass_symbols (systemtap_session& s) { symresolution_info sym (s); // NB: s.files can grow during this iteration, so size() can // return gradually increasing numbers. s.files.push_back (s.user_file); for (unsigned i = 0; i < s.files.size(); i++) { assert_no_interrupts(); stapfile* dome = s.files[i]; // Pass 1: add globals and functions to systemtap-session master list, // so the find_* functions find them // // NB: tapset global/function definitions may duplicate or conflict // with those already in s.globals/functions. We need to deconflict // here. for (unsigned i=0; iglobals.size(); i++) { vardecl* g = dome->globals[i]; for (unsigned j=0; jname == g2->name) { s.print_error (semantic_error (_("conflicting global variables"), g->tok, g2->tok)); } } s.globals.push_back (g); } for (unsigned i=0; ifunctions.size(); i++) { functiondecl* f = dome->functions[i]; functiondecl* f2 = s.functions[f->name]; if (f2 && f != f2) { s.print_error (semantic_error (_("conflicting functions"), f->tok, f2->tok)); } s.functions[f->name] = f; } // NB: embeds don't conflict with each other for (unsigned i=0; iembeds.size(); i++) s.embeds.push_back (dome->embeds[i]); // Pass 2: derive probes and resolve any further symbols in the // derived results. for (unsigned i=0; iprobes.size(); i++) { assert_no_interrupts(); probe* p = dome->probes [i]; vector dps; // much magic happens here: probe alias expansion, wildcard // matching, low-level derived_probe construction. derive_probes (s, p, dps); for (unsigned j=0; jjoin_group (s); try { for (unsigned k=0; kreplace (dp->body); sym.current_function = 0; sym.current_probe = dp; dp->body->visit (& sym); // Process the probe-point condition expression. sym.current_function = 0; sym.current_probe = 0; if (dp->sole_location()->condition) dp->sole_location()->condition->visit (& sym); } catch (const semantic_error& e) { s.print_error (e); } } } // Pass 3: process functions for (unsigned i=0; ifunctions.size(); i++) { assert_no_interrupts(); functiondecl* fd = dome->functions[i]; try { for (unsigned j=0; jreplace (fd->body); sym.current_function = fd; sym.current_probe = 0; fd->body->visit (& sym); } catch (const semantic_error& e) { s.print_error (e); } } } // Inform all derived_probe builders that we're done with // all resolution, so it's time to release caches. s.pattern_root->build_no_more (s); if(s.systemtap_v_check){ for(unsigned i=0;isystemtap_v_conditional) s.print_warning(_("This global uses tapset constructs that are dependent on systemtap version"), s.globals[i]->tok); } for(map::const_iterator i=s.functions.begin();i != s.functions.end();++i){ if(i->second->systemtap_v_conditional) s.print_warning(_("This function uses tapset constructs that are dependent on systemtap version"), i->second->tok); } for(unsigned i=0;i sysvc; s.probes[i]->collect_derivation_chain(sysvc); for(unsigned j=0;jsystemtap_v_conditional) s.print_warning(_("This probe uses tapset constructs that are dependent on systemtap version"), sysvc[j]->tok); if(sysvc[j]->get_alias() && sysvc[j]->get_alias()->systemtap_v_conditional) s.print_warning(_("This alias uses tapset constructs that are dependent on systemtap version"), sysvc[j]->get_alias()->tok); } } } return s.num_errors(); // all those print_error calls } // Keep unread global variables for probe end value display. void add_global_var_display (systemtap_session& s) { // Don't generate synthetic end probes when in listings mode; // it would clutter up the list of probe points with "end ...". if (s.listing_mode) return; varuse_collecting_visitor vut(s); for (unsigned i=0; ibody->visit (& vut); if (s.probes[i]->sole_location()->condition) s.probes[i]->sole_location()->condition->visit (& vut); } for (unsigned g=0; g < s.globals.size(); g++) { vardecl* l = s.globals[g]; if ((vut.read.find (l) != vut.read.end() && vut.used.find (l) != vut.used.end()) || vut.written.find (l) == vut.written.end()) continue; // Don't generate synthetic end probes for unread globals // declared only within tapsets. (RHBZ 468139), but rather // only within the end-user script. bool tapset_global = false; for (size_t m=0; m < s.library_files.size(); m++) { for (size_t n=0; n < s.library_files[m]->globals.size(); n++) { if (l->name == s.library_files[m]->globals[n]->name) {tapset_global = true; break;} } } if (tapset_global) continue; probe_point::component* c = new probe_point::component("end"); probe_point* pl = new probe_point; pl->components.push_back (c); vector dps; block *b = new block; b->tok = l->tok; probe* p = new probe; p->tok = l->tok; p->locations.push_back (pl); // Create a symbol symbol* g_sym = new symbol; g_sym->name = l->name; g_sym->tok = l->tok; g_sym->type = l->type; g_sym->referent = l; token* print_tok = new token(*l->tok); print_tok->type = tok_identifier; print_tok->content = "printf"; print_format* pf = print_format::create(print_tok); pf->raw_components += l->name; if (l->index_types.size() == 0) // Scalar { if (l->type == pe_stats) if (strverscmp(s.compatible.c_str(), "1.4") >= 0) pf->raw_components += " @count=%#d @min=%#d @max=%#d @sum=%#d @avg=%#d\\n"; else pf->raw_components += " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n"; else if (l->type == pe_string) pf->raw_components += "=\"%#s\"\\n"; else pf->raw_components += "=%#x\\n"; pf->components = print_format::string_to_components(pf->raw_components); expr_statement* feb = new expr_statement; feb->value = pf; feb->tok = print_tok; if (l->type == pe_stats) { struct stat_op* so [5]; const stat_component_type stypes[] = {sc_count, sc_min, sc_max, sc_sum, sc_average}; for (unsigned si = 0; si < (sizeof(so)/sizeof(struct stat_op*)); si++) { so[si]= new stat_op; so[si]->ctype = stypes[si]; so[si]->type = pe_long; so[si]->stat = g_sym; so[si]->tok = l->tok; pf->args.push_back(so[si]); } } else pf->args.push_back(g_sym); /* PR7053: Checking empty aggregate for global variable */ if (l->type == pe_stats) { stat_op *so= new stat_op; so->ctype = sc_count; so->type = pe_long; so->stat = g_sym; so->tok = l->tok; comparison *be = new comparison; be->op = ">"; be->tok = l->tok; be->left = so; be->right = new literal_number(0); /* Create printf @count=0x0 in else block */ print_format* pf_0 = print_format::create(print_tok); pf_0->raw_components += l->name; pf_0->raw_components += " @count=0x0\\n"; pf_0->components = print_format::string_to_components(pf_0->raw_components); expr_statement* feb_else = new expr_statement; feb_else->value = pf_0; feb_else->tok = print_tok; if_statement *ifs = new if_statement; ifs->tok = l->tok; ifs->condition = be; ifs->thenblock = feb ; ifs->elseblock = feb_else; b->statements.push_back(ifs); } else /* other non-stat cases */ b->statements.push_back(feb); } else // Array { int idx_count = l->index_types.size(); symbol* idx_sym[idx_count]; vardecl* idx_v[idx_count]; // Create a foreach loop foreach_loop* fe = new foreach_loop; fe->sort_direction = -1; // imply decreasing sort on value fe->sort_column = 0; // as in foreach ([a,b,c] in array-) { } fe->sort_aggr = sc_none; // as in default @count fe->value = NULL; fe->limit = NULL; fe->tok = l->tok; // Create indices for the foreach loop for (int i=0; i < idx_count; i++) { char *idx_name; if (asprintf (&idx_name, "idx%d", i) < 0) { delete pf; delete b; delete p; delete g_sym; delete fe; return; } idx_sym[i] = new symbol; idx_sym[i]->name = idx_name; idx_sym[i]->tok = l->tok; idx_v[i] = new vardecl; idx_v[i]->name = idx_name; idx_v[i]->type = l->index_types[i]; idx_v[i]->tok = l->tok; idx_sym[i]->referent = idx_v[i]; fe->indexes.push_back (idx_sym[i]); } // Create a printf for the foreach loop pf->raw_components += "["; for (int i=0; i < idx_count; i++) { if (i > 0) pf->raw_components += ","; if (l->index_types[i] == pe_string) pf->raw_components += "\"%#s\""; else pf->raw_components += "%#d"; } pf->raw_components += "]"; if (l->type == pe_stats) if (strverscmp(s.compatible.c_str(), "1.4") >= 0) pf->raw_components += " @count=%#d @min=%#d @max=%#d @sum=%#d @avg=%#d\\n"; else pf->raw_components += " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n"; else if (l->type == pe_string) pf->raw_components += "=\"%#s\"\\n"; else pf->raw_components += "=%#x\\n"; // Create an index for the array struct arrayindex* ai = new arrayindex; ai->tok = l->tok; ai->base = g_sym; for (int i=0; i < idx_count; i++) { ai->indexes.push_back (idx_sym[i]); pf->args.push_back(idx_sym[i]); } if (l->type == pe_stats) { struct stat_op* so [5]; const stat_component_type stypes[] = {sc_count, sc_min, sc_max, sc_sum, sc_average}; ai->type = pe_stats; for (unsigned si = 0; si < (sizeof(so)/sizeof(struct stat_op*)); si++) { so[si]= new stat_op; so[si]->ctype = stypes[si]; so[si]->type = pe_long; so[si]->stat = ai; so[si]->tok = l->tok; pf->args.push_back(so[si]); } } else { // Create value for the foreach loop fe->value = new symbol; fe->value->name = "val"; fe->value->tok = l->tok; pf->args.push_back(fe->value); } pf->components = print_format::string_to_components(pf->raw_components); expr_statement* feb = new expr_statement; feb->value = pf; feb->tok = l->tok; fe->base = g_sym; fe->block = (statement*)feb; b->statements.push_back(fe); } // Add created probe p->body = b; derive_probes (s, p, dps); for (unsigned i = 0; i < dps.size(); i++) { derived_probe* dp = dps[i]; s.probes.push_back (dp); dp->join_group (s); } // Repopulate symbol and type info symresolution_info sym (s); sym.current_function = 0; sym.current_probe = dps[0]; dps[0]->body->visit (& sym); semantic_pass_types(s); // Mark that variable is read vut.read.insert (l); } } int semantic_pass (systemtap_session& s) { int rc = 0; try { s.register_library_aliases(); register_standard_tapsets(s); if (rc == 0) rc = semantic_pass_symbols (s); if (rc == 0) rc = semantic_pass_conditions (s); if (rc == 0) rc = semantic_pass_optimize1 (s); if (rc == 0) rc = semantic_pass_types (s); if (rc == 0) rc = gen_dfa_table(s); if (rc == 0) add_global_var_display (s); if (rc == 0) rc = semantic_pass_optimize2 (s); if (rc == 0) rc = semantic_pass_vars (s); if (rc == 0) rc = semantic_pass_stats (s); if (rc == 0) embeddedcode_info_pass (s); if (s.num_errors() == 0 && s.probes.size() == 0 && !s.listing_mode) throw semantic_error (_("no probes found")); } catch (const semantic_error& e) { s.print_error (e); rc ++; } // PR11443 // NB: listing mode only cares whether we have any probes, // so all previous error conditions are disregarded. if (s.listing_mode) rc = s.probes.empty(); return rc; } // ------------------------------------------------------------------------ // semantic processing: symbol resolution symresolution_info::symresolution_info (systemtap_session& s): session (s), current_function (0), current_probe (0) { } void symresolution_info::visit_block (block* e) { for (unsigned i=0; istatements.size(); i++) { try { e->statements[i]->visit (this); } catch (const semantic_error& e) { session.print_error (e); } } } void symresolution_info::visit_foreach_loop (foreach_loop* e) { for (unsigned i=0; iindexes.size(); i++) e->indexes[i]->visit (this); symbol *array = NULL; hist_op *hist = NULL; classify_indexable (e->base, array, hist); if (array) { if (!array->referent) { vardecl* d = find_var (array->name, e->indexes.size (), array->tok); if (d) array->referent = d; else { stringstream msg; msg << _F("unresolved arity-%zu global array %s, missing global declaration?", e->indexes.size(), array->name.c_str()); throw semantic_error (msg.str(), e->tok); } } } else { assert (hist); hist->visit (this); } if (e->value) e->value->visit (this); if (e->limit) e->limit->visit (this); e->block->visit (this); } struct delete_statement_symresolution_info: public traversing_visitor { symresolution_info *parent; delete_statement_symresolution_info (symresolution_info *p): parent(p) {} void visit_arrayindex (arrayindex* e) { parent->visit_arrayindex (e); } void visit_functioncall (functioncall* e) { parent->visit_functioncall (e); } void visit_symbol (symbol* e) { if (e->referent) return; vardecl* d = parent->find_var (e->name, -1, e->tok); if (d) e->referent = d; else throw semantic_error (_("unresolved array in delete statement"), e->tok); } }; void symresolution_info::visit_delete_statement (delete_statement* s) { delete_statement_symresolution_info di (this); s->value->visit (&di); } void symresolution_info::visit_symbol (symbol* e) { if (e->referent) return; vardecl* d = find_var (e->name, 0, e->tok); if (d) e->referent = d; else { // new local vardecl* v = new vardecl; v->name = e->name; v->tok = e->tok; v->set_arity(0, e->tok); if (current_function) current_function->locals.push_back (v); else if (current_probe) current_probe->locals.push_back (v); else // must be probe-condition expression throw semantic_error (_("probe condition must not reference undeclared global"), e->tok); e->referent = v; } } void symresolution_info::visit_arrayindex (arrayindex* e) { for (unsigned i=0; iindexes.size(); i++) e->indexes[i]->visit (this); symbol *array = NULL; hist_op *hist = NULL; classify_indexable(e->base, array, hist); if (array) { if (array->referent) return; vardecl* d = find_var (array->name, e->indexes.size (), array->tok); if (d) array->referent = d; else { stringstream msg; msg << _F("unresolved arity-%zu global array %s, missing global declaration?", e->indexes.size(), array->name.c_str()); throw semantic_error (msg.str(), e->tok); } } else { assert (hist); hist->visit (this); } } void symresolution_info::visit_functioncall (functioncall* e) { // XXX: we could relax this, if we're going to examine the // vartracking data recursively. See testsuite/semko/fortytwo.stp. if (! (current_function || current_probe)) { // must be probe-condition expression throw semantic_error (_("probe condition must not reference function"), e->tok); } for (unsigned i=0; iargs.size(); i++) e->args[i]->visit (this); if (e->referent) return; functiondecl* d = find_function (e->function, e->args.size ()); if (d) e->referent = d; else { stringstream msg; msg << _F("unresolved arity-%zu function", e->args.size()); throw semantic_error (msg.str(), e->tok); } } /*find_var will return an argument other than zero if the name matches the var * name ie, if the current local name matches the name passed to find_var*/ vardecl* symresolution_info::find_var (const string& name, int arity, const token* tok) { if (current_function || current_probe) { // search locals vector& locals = (current_function ? current_function->locals : current_probe->locals); for (unsigned i=0; iname == name) { locals[i]->set_arity (arity, tok); return locals[i]; } } // search function formal parameters (for scalars) if (arity == 0 && current_function) for (unsigned i=0; iformal_args.size(); i++) if (current_function->formal_args[i]->name == name) { // NB: no need to check arity here: formal args always scalar current_function->formal_args[i]->set_arity (0, tok); return current_function->formal_args[i]; } // search processed globals for (unsigned i=0; iname == name) { if (! session.suppress_warnings) { vardecl* v = session.globals[i]; // clog << "resolved " << *tok << " to global " << *v->tok << endl; if (v->tok->location.file != tok->location.file) { session.print_warning (_F("cross-file global variable reference to %s from", lex_cast(*v->tok).c_str()), tok); } } session.globals[i]->set_arity (arity, tok); return session.globals[i]; } // search library globals for (unsigned i=0; iglobals.size(); j++) { vardecl* g = f->globals[j]; if (g->name == name) { g->set_arity (arity, tok); // put library into the queue if not already there if (find (session.files.begin(), session.files.end(), f) == session.files.end()) session.files.push_back (f); return g; } } } return 0; } functiondecl* symresolution_info::find_function (const string& name, unsigned arity) { // the common path if (session.functions.find(name) != session.functions.end()) { functiondecl* fd = session.functions[name]; assert (fd->name == name); if (fd->formal_args.size() == arity) return fd; session.print_warning (_F("mismatched arity-%zu function found", fd->formal_args.size()), fd->tok); // and some semantic_error will shortly follow } // search library functions for (unsigned i=0; ifunctions.size(); j++) if (f->functions[j]->name == name && f->functions[j]->formal_args.size() == arity) { // put library into the queue if not already there if (0) // session.verbose_resolution cerr << _F(" function %s is defined from %s", name.c_str(), f->name.c_str()) << endl; if (find (session.files.begin(), session.files.end(), f) == session.files.end()) session.files.push_back (f); // else .. print different message? return f->functions[j]; } } return 0; } // ------------------------------------------------------------------------ // optimization // Do away with functiondecls that are never (transitively) called // from probes. void semantic_pass_opt1 (systemtap_session& s, bool& relaxed_p) { functioncall_traversing_visitor ftv; for (unsigned i=0; ibody->visit (& ftv); if (s.probes[i]->sole_location()->condition) s.probes[i]->sole_location()->condition->visit (& ftv); } vector new_unused_functions; for (map::iterator it = s.functions.begin(); it != s.functions.end(); it++) { functiondecl* fd = it->second; if (ftv.traversed.find(fd) == ftv.traversed.end()) { if (fd->tok->location.file->name == s.user_file->name && ! fd->synthetic)// !tapset s.print_warning (_F("Eliding unused function '%s'", fd->name.c_str()), fd->tok); // s.functions.erase (it); // NB: can't, since we're already iterating upon it new_unused_functions.push_back (fd); relaxed_p = false; } } for (unsigned i=0; i::iterator where = s.functions.find (new_unused_functions[i]->name); assert (where != s.functions.end()); s.functions.erase (where); if (s.tapset_compile_coverage) s.unused_functions.push_back (new_unused_functions[i]); } } // ------------------------------------------------------------------------ // Do away with local & global variables that are never // written nor read. void semantic_pass_opt2 (systemtap_session& s, bool& relaxed_p, unsigned iterations) { varuse_collecting_visitor vut(s); for (unsigned i=0; ibody->visit (& vut); if (s.probes[i]->sole_location()->condition) s.probes[i]->sole_location()->condition->visit (& vut); } // NB: Since varuse_collecting_visitor also traverses down // actually called functions, we don't need to explicitly // iterate over them. Uncalled ones should have been pruned // in _opt1 above. // // for (unsigned i=0; ibody->visit (& vut); // Now in vut.read/written, we have a mixture of all locals, globals for (unsigned i=0; ilocals.size(); /* see below */) { vardecl* l = s.probes[i]->locals[j]; // skip over "special" locals if (l->synthetic) { j++; continue; } if (vut.read.find (l) == vut.read.end() && vut.written.find (l) == vut.written.end()) { if (l->tok->location.file->name == s.user_file->name) // !tapset s.print_warning (_F("Eliding unused variable '%s'", l->name.c_str()), l->tok); if (s.tapset_compile_coverage) { s.probes[i]->unused_locals.push_back (s.probes[i]->locals[j]); } s.probes[i]->locals.erase(s.probes[i]->locals.begin() + j); relaxed_p = false; // don't increment j } else { if (vut.written.find (l) == vut.written.end()) if (iterations == 0 && ! s.suppress_warnings) { stringstream o; vector::iterator it; for (it = s.probes[i]->locals.begin(); it != s.probes[i]->locals.end(); it++) if (l->name != (*it)->name) o << " " << (*it)->name; for (it = s.globals.begin(); it != s.globals.end(); it++) if (l->name != (*it)->name) o << " " << (*it)->name; s.print_warning (_F("never-assigned local variable '%s' %s", l->name.c_str(), (o.str() == "" ? "" : (_("(alternatives:") + o.str() + ")")).c_str()), l->tok); } j++; } } for (map::iterator it = s.functions.begin(); it != s.functions.end(); it++) { functiondecl *fd = it->second; for (unsigned j=0; jlocals.size(); /* see below */) { vardecl* l = fd->locals[j]; if (vut.read.find (l) == vut.read.end() && vut.written.find (l) == vut.written.end()) { if (l->tok->location.file->name == s.user_file->name) // !tapset s.print_warning (_F("Eliding unused variable '%s'", l->name.c_str()), l->tok); if (s.tapset_compile_coverage) { fd->unused_locals.push_back (fd->locals[j]); } fd->locals.erase(fd->locals.begin() + j); relaxed_p = false; // don't increment j } else { if (vut.written.find (l) == vut.written.end()) if (iterations == 0 && ! s.suppress_warnings) { stringstream o; vector::iterator it; for (it = fd->formal_args.begin() ; it != fd->formal_args.end(); it++) if (l->name != (*it)->name) o << " " << (*it)->name; for (it = fd->locals.begin(); it != fd->locals.end(); it++) if (l->name != (*it)->name) o << " " << (*it)->name; for (it = s.globals.begin(); it != s.globals.end(); it++) if (l->name != (*it)->name) o << " " << (*it)->name; s.print_warning (_F("never-assigned local variable '%s' %s", l->name.c_str(), (o.str() == "" ? "" : (_("(alternatives:") + o.str() + ")")).c_str()), l->tok); } j++; } } } for (unsigned i=0; itok->location.file->name == s.user_file->name) // !tapset s.print_warning (_F("Eliding unused variable '%s'", l->name.c_str()), l->tok); if (s.tapset_compile_coverage) { s.unused_globals.push_back(s.globals[i]); } s.globals.erase(s.globals.begin() + i); relaxed_p = false; // don't increment i } else { if (vut.written.find (l) == vut.written.end() && ! l->init) // no initializer if (iterations == 0 && ! s.suppress_warnings) { stringstream o; vector::iterator it; for (it = s.globals.begin(); it != s.globals.end(); it++) if (l->name != (*it)->name) o << " " << (*it)->name; s.print_warning (_F("never assigned global variable '%s' %s", l->name.c_str(), (o.str() == "" ? "" : (_("(alternatives:") + o.str() + ")")).c_str()), l->tok); } i++; } } } // ------------------------------------------------------------------------ struct dead_assignment_remover: public update_visitor { systemtap_session& session; bool& relaxed_p; const varuse_collecting_visitor& vut; dead_assignment_remover(systemtap_session& s, bool& r, const varuse_collecting_visitor& v): session(s), relaxed_p(r), vut(v) {} void visit_assignment (assignment* e); void visit_try_block (try_block *s); }; void dead_assignment_remover::visit_assignment (assignment* e) { replace (e->left); replace (e->right); symbol* left = get_symbol_within_expression (e->left); vardecl* leftvar = left->referent; // NB: may be 0 for unresolved $target if (leftvar) // not unresolved $target, so intended sideeffect may be elided { if (vut.read.find(leftvar) == vut.read.end()) // var never read? { // NB: Not so fast! The left side could be an array whose // index expressions may have side-effects. This would be // OK if we could replace the array assignment with a // statement-expression containing all the index expressions // and the rvalue... but we can't. // Another possibility is that we have an unread global variable // which are kept for probe end value display. bool is_global = false; vector::iterator it; for (it = session.globals.begin(); it != session.globals.end(); it++) if (leftvar->name == (*it)->name) { is_global = true; break; } varuse_collecting_visitor lvut(session); e->left->visit (& lvut); if (lvut.side_effect_free () && !is_global // XXX: use _wrt() once we track focal_vars && !leftvar->synthetic) // don't elide assignment to synthetic $context variables { /* PR 1119: NB: This is not necessary here. A write-only variable will also be elided soon at the next _opt2 iteration. if (e->left->tok->location.file->name == session.user_file->name) // !tapset session.print_warning("eliding write-only ", *e->left->tok); else */ if (e->left->tok->location.file->name == session.user_file->name) // !tapset session.print_warning(_F("Eliding assignment to '%s'", leftvar->name.c_str()), e->tok); provide (e->right); // goodbye assignment* relaxed_p = false; return; } } } provide (e); } void dead_assignment_remover::visit_try_block (try_block *s) { replace (s->try_block); if (s->catch_error_var) { vardecl* errvar = s->catch_error_var->referent; if (vut.read.find(errvar) == vut.read.end()) // never read? { if (session.verbose>2) clog << _F("Eliding unused error string catcher %s at %s", errvar->name.c_str(), lex_cast(*s->tok).c_str()) << endl; s->catch_error_var = 0; } } replace (s->catch_block); provide (s); } // Let's remove assignments to variables that are never read. We // rewrite "(foo = expr)" as "(expr)". This makes foo a candidate to // be optimized away as an unused variable, and expr a candidate to be // removed as a side-effect-free statement expression. Wahoo! void semantic_pass_opt3 (systemtap_session& s, bool& relaxed_p) { // Recompute the varuse data, which will probably match the opt2 // copy of the computation, except for those totally unused // variables that opt2 removed. varuse_collecting_visitor vut(s); for (unsigned i=0; ibody->visit (& vut); // includes reachable functions too dead_assignment_remover dar (s, relaxed_p, vut); // This instance may be reused for multiple probe/function body trims. for (unsigned i=0; ibody); for (map::iterator it = s.functions.begin(); it != s.functions.end(); it++) dar.replace (it->second->body); // The rewrite operation is performed within the visitor. // XXX: we could also zap write-only globals here } // ------------------------------------------------------------------------ struct dead_stmtexpr_remover: public update_visitor { systemtap_session& session; bool& relaxed_p; set focal_vars; // vars considered subject to side-effects dead_stmtexpr_remover(systemtap_session& s, bool& r): session(s), relaxed_p(r) {} void visit_block (block *s); void visit_try_block (try_block *s); void visit_null_statement (null_statement *s); void visit_if_statement (if_statement* s); void visit_foreach_loop (foreach_loop *s); void visit_for_loop (for_loop *s); // XXX: and other places where stmt_expr's might be nested void visit_expr_statement (expr_statement *s); }; void dead_stmtexpr_remover::visit_null_statement (null_statement *s) { // easy! if (session.verbose>2) clog << _("Eliding side-effect-free null statement ") << *s->tok << endl; s = 0; provide (s); } void dead_stmtexpr_remover::visit_block (block *s) { vector new_stmts; for (unsigned i=0; istatements.size(); i++ ) { statement* new_stmt = require (s->statements[i], true); if (new_stmt != 0) { // flatten nested blocks into this one block *b = dynamic_cast(new_stmt); if (b) { if (session.verbose>2) clog << _("Flattening nested block ") << *b->tok << endl; new_stmts.insert(new_stmts.end(), b->statements.begin(), b->statements.end()); relaxed_p = false; } else new_stmts.push_back (new_stmt); } } if (new_stmts.size() == 0) { if (session.verbose>2) clog << _("Eliding side-effect-free empty block ") << *s->tok << endl; s = 0; } else if (new_stmts.size() == 1) { if (session.verbose>2) clog << _("Eliding side-effect-free singleton block ") << *s->tok << endl; provide (new_stmts[0]); return; } else s->statements = new_stmts; provide (s); } void dead_stmtexpr_remover::visit_try_block (try_block *s) { replace (s->try_block, true); replace (s->catch_block, true); // null catch{} is ok and useful if (s->try_block == 0) { if (session.verbose>2) clog << _("Eliding empty try {} block ") << *s->tok << endl; s = 0; } provide (s); } void dead_stmtexpr_remover::visit_if_statement (if_statement *s) { replace (s->thenblock, true); replace (s->elseblock, true); if (s->thenblock == 0) { if (s->elseblock == 0) { // We may be able to elide this statement, if the condition // expression is side-effect-free. varuse_collecting_visitor vct(session); s->condition->visit(& vct); if (vct.side_effect_free ()) { if (session.verbose>2) clog << _("Eliding side-effect-free if statement ") << *s->tok << endl; s = 0; // yeah, baby } else { // We can still turn it into a simple expr_statement though... if (session.verbose>2) clog << _("Creating simple evaluation from if statement ") << *s->tok << endl; expr_statement *es = new expr_statement; es->value = s->condition; es->tok = es->value->tok; provide (es); return; } } else { // For an else without a then, we can invert the condition logic to // avoid having a null statement in the thenblock if (session.verbose>2) clog << _("Inverting the condition of if statement ") << *s->tok << endl; unary_expression *ue = new unary_expression; ue->operand = s->condition; ue->tok = ue->operand->tok; ue->op = "!"; s->condition = ue; s->thenblock = s->elseblock; s->elseblock = 0; } } provide (s); } void dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s) { replace (s->block, true); if (s->block == 0) { // XXX what if s->limit has side effects? // XXX what about s->indexes or s->value used outside the loop? if(session.verbose > 2) clog << _("Eliding side-effect-free foreach statement ") << *s->tok << endl; s = 0; // yeah, baby } provide (s); } void dead_stmtexpr_remover::visit_for_loop (for_loop *s) { replace (s->block, true); if (s->block == 0) { // We may be able to elide this statement, if the condition // expression is side-effect-free. varuse_collecting_visitor vct(session); if (s->init) s->init->visit(& vct); s->cond->visit(& vct); if (s->incr) s->incr->visit(& vct); if (vct.side_effect_free ()) { if (session.verbose>2) clog << _("Eliding side-effect-free for statement ") << *s->tok << endl; s = 0; // yeah, baby } else { // Can't elide this whole statement; put a null in there. s->block = new null_statement(s->tok); } } provide (s); } void dead_stmtexpr_remover::visit_expr_statement (expr_statement *s) { // Run a varuse query against the operand expression. If it has no // side-effects, replace the entire statement expression by a null // statement with the provide() call. // // Unlike many other visitors, we do *not* traverse this outermost // one into the expression subtrees. There is no need - no // expr_statement nodes will be found there. (Function bodies // need to be visited explicitly by our caller.) // // NB. While we don't share nodes in the parse tree, let's not // deallocate *s anyway, just in case... varuse_collecting_visitor vut(session); s->value->visit (& vut); if (vut.side_effect_free_wrt (focal_vars)) { /* PR 1119: NB: this message is not a good idea here. It can name some arbitrary RHS expression of an assignment. if (s->value->tok->location.file->name == session.user_file->name) // not tapset session.print_warning("eliding never-assigned ", *s->value->tok); else */ if (s->value->tok->location.file->name == session.user_file->name) // not tapset session.print_warning("Eliding side-effect-free expression ", s->tok); // NB: this 0 pointer is invalid to leave around for any length of // time, but the parent parse tree objects above handle it. s = 0; relaxed_p = false; } provide (s); } void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) { // Finally, let's remove some statement-expressions that have no // side-effect. These should be exactly those whose private varuse // visitors come back with an empty "written" and "embedded" lists. dead_stmtexpr_remover duv (s, relaxed_p); // This instance may be reused for multiple probe/function body trims. for (unsigned i=0; ilocals.begin(), p->locals.end()); duv.replace (p->body, true); if (p->body == 0) { if (! s.timing) // PR10070 s.print_warning (_F("side-effect-free probe '%s'", p->name.c_str()), p->tok); p->body = new null_statement(p->tok); // XXX: possible duplicate warnings; see below } } for (map::iterator it = s.functions.begin(); it != s.functions.end(); it++) { assert_no_interrupts(); functiondecl* fn = it->second; duv.focal_vars.clear (); duv.focal_vars.insert (fn->locals.begin(), fn->locals.end()); duv.focal_vars.insert (fn->formal_args.begin(), fn->formal_args.end()); duv.focal_vars.insert (s.globals.begin(), s.globals.end()); duv.replace (fn->body, true); if (fn->body == 0) { s.print_warning (_F("side-effect-free function '%s'", fn->name.c_str()), fn->tok); fn->body = new null_statement(fn->tok); // XXX: the next iteration of the outer optimization loop may // take this new null_statement away again, and thus give us a // fresh warning. It would be better if this fixup was performed // only after the relaxation iterations. // XXX: or else see bug #6469. } } } // ------------------------------------------------------------------------ // The goal of this visitor is to reduce top-level expressions in void context // into separate statements that evaluate each subcomponent of the expression. // The dead-statement-remover can later remove some parts if they have no side // effects. // // All expressions must be overridden here so we never visit their subexpressions // accidentally. Thus, the only visited expressions should be value of an // expr_statement. // // For an expression to replace its expr_statement with something else, it will // let the new statement provide(), and then provide(0) for itself. The // expr_statement will take this as a sign that it's been replaced. struct void_statement_reducer: public update_visitor { systemtap_session& session; bool& relaxed_p; set focal_vars; // vars considered subject to side-effects void_statement_reducer(systemtap_session& s, bool& r): session(s), relaxed_p(r) {} void visit_expr_statement (expr_statement* s); // expressions in conditional / loop controls are definitely a side effect, // but still recurse into the child statements void visit_if_statement (if_statement* s); void visit_for_loop (for_loop* s); void visit_foreach_loop (foreach_loop* s); // these expressions get rewritten into their statement equivalents void visit_logical_or_expr (logical_or_expr* e); void visit_logical_and_expr (logical_and_expr* e); void visit_ternary_expression (ternary_expression* e); // all of these can (usually) be reduced into simpler statements void visit_binary_expression (binary_expression* e); void visit_unary_expression (unary_expression* e); void visit_regex_query (regex_query* e); // XXX depends on subexpr extraction void visit_comparison (comparison* e); void visit_concatenation (concatenation* e); void visit_functioncall (functioncall* e); void visit_print_format (print_format* e); void visit_target_symbol (target_symbol* e); void visit_atvar_op (atvar_op* e); void visit_cast_op (cast_op* e); void visit_defined_op (defined_op* e); // these are a bit hairy to grok due to the intricacies of indexables and // stats, so I'm chickening out and skipping them... void visit_array_in (array_in* e) { provide (e); } void visit_arrayindex (arrayindex* e) { provide (e); } void visit_stat_op (stat_op* e) { provide (e); } void visit_hist_op (hist_op* e) { provide (e); } // these can't be reduced because they always have an effect void visit_return_statement (return_statement* s) { provide (s); } void visit_delete_statement (delete_statement* s) { provide (s); } void visit_pre_crement (pre_crement* e) { provide (e); } void visit_post_crement (post_crement* e) { provide (e); } void visit_assignment (assignment* e) { provide (e); } }; void void_statement_reducer::visit_expr_statement (expr_statement* s) { replace (s->value, true); // if the expression provides 0, that's our signal that a new // statement has been provided, so we shouldn't provide this one. if (s->value != 0) provide(s); } void void_statement_reducer::visit_if_statement (if_statement* s) { // s->condition is never void replace (s->thenblock); replace (s->elseblock); provide (s); } void void_statement_reducer::visit_for_loop (for_loop* s) { // s->init/cond/incr are never void replace (s->block); provide (s); } void void_statement_reducer::visit_foreach_loop (foreach_loop* s) { // s->indexes/base/value/limit are never void replace (s->block); provide (s); } void void_statement_reducer::visit_logical_or_expr (logical_or_expr* e) { // In void context, the evaluation of "a || b" is exactly like // "if (!a) b", so let's do that instead. if (session.verbose>2) clog << _("Creating if statement from unused logical-or ") << *e->tok << endl; if_statement *is = new if_statement; is->tok = e->tok; is->elseblock = 0; unary_expression *ue = new unary_expression; ue->operand = e->left; ue->tok = e->tok; ue->op = "!"; is->condition = ue; expr_statement *es = new expr_statement; es->value = e->right; es->tok = es->value->tok; is->thenblock = es; is->visit(this); relaxed_p = false; e = 0; provide (e); } void void_statement_reducer::visit_logical_and_expr (logical_and_expr* e) { // In void context, the evaluation of "a && b" is exactly like // "if (a) b", so let's do that instead. if (session.verbose>2) clog << _("Creating if statement from unused logical-and ") << *e->tok << endl; if_statement *is = new if_statement; is->tok = e->tok; is->elseblock = 0; is->condition = e->left; expr_statement *es = new expr_statement; es->value = e->right; es->tok = es->value->tok; is->thenblock = es; is->visit(this); relaxed_p = false; e = 0; provide (e); } void void_statement_reducer::visit_ternary_expression (ternary_expression* e) { // In void context, the evaluation of "a ? b : c" is exactly like // "if (a) b else c", so let's do that instead. if (session.verbose>2) clog << _("Creating if statement from unused ternary expression ") << *e->tok << endl; if_statement *is = new if_statement; is->tok = e->tok; is->condition = e->cond; expr_statement *es = new expr_statement; es->value = e->truevalue; es->tok = es->value->tok; is->thenblock = es; es = new expr_statement; es->value = e->falsevalue; es->tok = es->value->tok; is->elseblock = es; is->visit(this); relaxed_p = false; e = 0; provide (e); } void void_statement_reducer::visit_binary_expression (binary_expression* e) { // When the result of a binary operation isn't needed, it's just as good to // evaluate the operands as sequential statements in a block. if (session.verbose>2) clog << _("Eliding unused binary ") << *e->tok << endl; block *b = new block; b->tok = e->tok; expr_statement *es = new expr_statement; es->value = e->left; es->tok = es->value->tok; b->statements.push_back(es); es = new expr_statement; es->value = e->right; es->tok = es->value->tok; b->statements.push_back(es); b->visit(this); relaxed_p = false; e = 0; provide (e); } void void_statement_reducer::visit_unary_expression (unary_expression* e) { // When the result of a unary operation isn't needed, it's just as good to // evaluate the operand directly if (session.verbose>2) clog << _("Eliding unused unary ") << *e->tok << endl; relaxed_p = false; e->operand->visit(this); } void void_statement_reducer::visit_regex_query (regex_query* e) { // TODOXXX After subexpression extraction is implemented, // regular expression matches *may* have side-effects in // terms of producing matched subexpressions, e.g.: // // str =~ "pat"; println(matched(0)); // // It's debatable if we want to actually allow this, though. // Treat e as a unary expression on the left operand -- since the // right hand side must be a literal (as verified by the parser), // evaluating it never has side effects. if (session.verbose>2) clog << _("Eliding regex query ") << *e->tok << endl; relaxed_p = false; e->left->visit(this); } void void_statement_reducer::visit_comparison (comparison* e) { visit_binary_expression(e); } void void_statement_reducer::visit_concatenation (concatenation* e) { visit_binary_expression(e); } void void_statement_reducer::visit_functioncall (functioncall* e) { // If a function call is pure and its result ignored, we can elide the call // and just evaluate the arguments in sequence if (!e->args.size()) { provide (e); return; } varuse_collecting_visitor vut(session); vut.traversed.insert (e->referent); vut.current_function = e->referent; e->referent->body->visit (& vut); if (!vut.side_effect_free_wrt (focal_vars)) { provide (e); return; } if (session.verbose>2) clog << _("Eliding side-effect-free function call ") << *e->tok << endl; block *b = new block; b->tok = e->tok; for (unsigned i=0; iargs.size(); i++ ) { expr_statement *es = new expr_statement; es->value = e->args[i]; es->tok = es->value->tok; b->statements.push_back(es); } b->visit(this); relaxed_p = false; e = 0; provide (e); } void void_statement_reducer::visit_print_format (print_format* e) { // When an sprint's return value is ignored, we can simply evaluate the // arguments in sequence if (e->print_to_stream || !e->args.size()) { provide (e); return; } if (session.verbose>2) clog << _("Eliding unused print ") << *e->tok << endl; block *b = new block; b->tok = e->tok; for (unsigned i=0; iargs.size(); i++ ) { expr_statement *es = new expr_statement; es->value = e->args[i]; es->tok = es->value->tok; b->statements.push_back(es); } b->visit(this); relaxed_p = false; e = 0; provide (e); } void void_statement_reducer::visit_atvar_op (atvar_op* e) { visit_target_symbol (e); } void void_statement_reducer::visit_target_symbol (target_symbol* e) { // When target_symbol isn't needed, it's just as good to // evaluate any array indexes directly block *b = new block; b->tok = e->tok; for (unsigned i=0; icomponents.size(); i++ ) { if (e->components[i].type != target_symbol::comp_expression_array_index) continue; expr_statement *es = new expr_statement; es->value = e->components[i].expr_index; es->tok = es->value->tok; b->statements.push_back(es); } if (b->statements.empty()) { delete b; provide (e); return; } if (session.verbose>2) clog << _("Eliding unused target symbol ") << *e->tok << endl; b->visit(this); relaxed_p = false; e = 0; provide (e); } void void_statement_reducer::visit_cast_op (cast_op* e) { // When the result of a cast operation isn't needed, it's just as good to // evaluate the operand and any array indexes directly block *b = new block; b->tok = e->tok; expr_statement *es = new expr_statement; es->value = e->operand; es->tok = es->value->tok; b->statements.push_back(es); for (unsigned i=0; icomponents.size(); i++ ) { if (e->components[i].type != target_symbol::comp_expression_array_index) continue; es = new expr_statement; es->value = e->components[i].expr_index; es->tok = es->value->tok; b->statements.push_back(es); } if (session.verbose>2) clog << _("Eliding unused typecast ") << *e->tok << endl; b->visit(this); relaxed_p = false; e = 0; provide (e); } void void_statement_reducer::visit_defined_op (defined_op* e) { // When the result of a @defined operation isn't needed, just elide // it entirely. Its operand $expression must already be // side-effect-free. if (session.verbose>2) clog << _("Eliding unused check ") << *e->tok << endl; relaxed_p = false; e = 0; provide (e); } void semantic_pass_opt5 (systemtap_session& s, bool& relaxed_p) { // Let's simplify statements with unused computed values. void_statement_reducer vuv (s, relaxed_p); // This instance may be reused for multiple probe/function body trims. vuv.focal_vars.insert (s.globals.begin(), s.globals.end()); for (unsigned i=0; ibody); for (map::iterator it = s.functions.begin(); it != s.functions.end(); it++) vuv.replace (it->second->body); } struct const_folder: public update_visitor { systemtap_session& session; bool& relaxed_p; const_folder(systemtap_session& s, bool& r): session(s), relaxed_p(r), last_number(0), last_string(0) {} literal_number* last_number; literal_number* get_number(expression*& e); void visit_literal_number (literal_number* e); literal_string* last_string; literal_string* get_string(expression*& e); void visit_literal_string (literal_string* e); void get_literal(expression*& e, literal_number*& n, literal_string*& s); void visit_if_statement (if_statement* s); void visit_for_loop (for_loop* s); void visit_foreach_loop (foreach_loop* s); void visit_binary_expression (binary_expression* e); void visit_unary_expression (unary_expression* e); void visit_logical_or_expr (logical_or_expr* e); void visit_logical_and_expr (logical_and_expr* e); // void visit_regex_query (regex_query* e); // XXX: would require executing dfa at compile-time void visit_comparison (comparison* e); void visit_concatenation (concatenation* e); void visit_ternary_expression (ternary_expression* e); void visit_defined_op (defined_op* e); void visit_target_symbol (target_symbol* e); }; void const_folder::get_literal(expression*& e, literal_number*& n, literal_string*& s) { replace (e); n = (e == last_number) ? last_number : NULL; s = (e == last_string) ? last_string : NULL; } literal_number* const_folder::get_number(expression*& e) { replace (e); return (e == last_number) ? last_number : NULL; } void const_folder::visit_literal_number (literal_number* e) { last_number = e; provide (e); } literal_string* const_folder::get_string(expression*& e) { replace (e); return (e == last_string) ? last_string : NULL; } void const_folder::visit_literal_string (literal_string* e) { last_string = e; provide (e); } void const_folder::visit_if_statement (if_statement* s) { literal_number* cond = get_number (s->condition); if (!cond) { replace (s->thenblock); replace (s->elseblock); provide (s); } else { if (session.verbose>2) clog << _F("Collapsing constant-%" PRIi64 " if-statement %s", cond->value, lex_cast(*s->tok).c_str()) << endl; relaxed_p = false; statement* n = cond->value ? s->thenblock : s->elseblock; if (n) n->visit (this); else provide (new null_statement (s->tok)); } } void const_folder::visit_for_loop (for_loop* s) { literal_number* cond = get_number (s->cond); if (!cond || cond->value) { replace (s->init); replace (s->incr); replace (s->block); provide (s); } else { if (session.verbose>2) clog << _("Collapsing constantly-false for-loop ") << *s->tok << endl; relaxed_p = false; if (s->init) s->init->visit (this); else provide (new null_statement (s->tok)); } } void const_folder::visit_foreach_loop (foreach_loop* s) { literal_number* limit = get_number (s->limit); if (!limit || limit->value > 0) { for (unsigned i = 0; i < s->indexes.size(); ++i) replace (s->indexes[i]); replace (s->base); replace (s->value); replace (s->block); provide (s); } else { if (session.verbose>2) clog << _("Collapsing constantly-limited foreach-loop ") << *s->tok << endl; relaxed_p = false; provide (new null_statement (s->tok)); } } void const_folder::visit_binary_expression (binary_expression* e) { int64_t value; literal_number* left = get_number (e->left); literal_number* right = get_number (e->right); if (right && !right->value && (e->op == "/" || e->op == "%")) { // Give divide-by-zero a chance to be optimized out elsewhere, // and if not it will be a runtime error anyway... provide (e); return; } if (left && right) { if (e->op == "+") value = left->value + right->value; else if (e->op == "-") value = left->value - right->value; else if (e->op == "*") value = left->value * right->value; else if (e->op == "&") value = left->value & right->value; else if (e->op == "|") value = left->value | right->value; else if (e->op == "^") value = left->value ^ right->value; else if (e->op == ">>") value = left->value >> max(min(right->value, (int64_t)64), (int64_t)0); else if (e->op == "<<") value = left->value << max(min(right->value, (int64_t)64), (int64_t)0); else if (e->op == "/") value = (left->value == LLONG_MIN && right->value == -1) ? LLONG_MIN : left->value / right->value; else if (e->op == "%") value = (left->value == LLONG_MIN && right->value == -1) ? 0 : left->value % right->value; else throw semantic_error (_("unsupported binary operator ") + e->op); } else if ((left && ((left->value == 0 && (e->op == "*" || e->op == "&" || e->op == ">>" || e->op == "<<" )) || (left->value ==-1 && (e->op == "|" || e->op == ">>")))) || (right && ((right->value == 0 && (e->op == "*" || e->op == "&")) || (right->value == 1 && (e->op == "%")) || (right->value ==-1 && (e->op == "%" || e->op == "|"))))) { expression* other = left ? e->right : e->left; varuse_collecting_visitor vu(session); other->visit(&vu); if (!vu.side_effect_free()) { provide (e); return; } if (left) value = left->value; else if (e->op == "%") value = 0; else value = right->value; } else if ((left && ((left->value == 0 && (e->op == "+" || e->op == "|" || e->op == "^")) || (left->value == 1 && (e->op == "*")) || (left->value ==-1 && (e->op == "&")))) || (right && ((right->value == 0 && (e->op == "+" || e->op == "-" || e->op == "|" || e->op == "^")) || (right->value == 1 && (e->op == "*" || e->op == "/")) || (right->value ==-1 && (e->op == "&")) || (right->value <= 0 && (e->op == ">>" || e->op == "<<"))))) { if (session.verbose>2) clog << _("Collapsing constant-identity binary operator ") << *e->tok << endl; relaxed_p = false; provide (left ? e->right : e->left); return; } else { provide (e); return; } if (session.verbose>2) clog << _F("Collapsing constant-%" PRIi64 " binary operator %s", value, lex_cast(*e->tok).c_str()) << endl; relaxed_p = false; literal_number* n = new literal_number(value); n->tok = e->tok; n->visit (this); } void const_folder::visit_unary_expression (unary_expression* e) { literal_number* operand = get_number (e->operand); if (!operand) provide (e); else { if (session.verbose>2) clog << _("Collapsing constant unary ") << *e->tok << endl; relaxed_p = false; literal_number* n = new literal_number (*operand); n->tok = e->tok; if (e->op == "+") ; // nothing to do else if (e->op == "-") n->value = -n->value; else if (e->op == "!") n->value = !n->value; else if (e->op == "~") n->value = ~n->value; else throw semantic_error (_("unsupported unary operator ") + e->op); n->visit (this); } } void const_folder::visit_logical_or_expr (logical_or_expr* e) { int64_t value; literal_number* left = get_number (e->left); literal_number* right = get_number (e->right); if (left && right) value = left->value || right->value; else if ((left && left->value) || (right && right->value)) { // If the const is on the left, we get to short-circuit the right // immediately. Otherwise, we can only eliminate the LHS if it's pure. if (right) { varuse_collecting_visitor vu(session); e->left->visit(&vu); if (!vu.side_effect_free()) { provide (e); return; } } value = 1; } // We might also get rid of useless "0||x" and "x||0", except it does // normalize x to 0 or 1. We could change it to "!!x", but it's not clear // that this would gain us much. else { provide (e); return; } if (session.verbose>2) clog << _("Collapsing constant logical-OR ") << *e->tok << endl; relaxed_p = false; literal_number* n = new literal_number(value); n->tok = e->tok; n->visit (this); } void const_folder::visit_logical_and_expr (logical_and_expr* e) { int64_t value; literal_number* left = get_number (e->left); literal_number* right = get_number (e->right); if (left && right) value = left->value && right->value; else if ((left && !left->value) || (right && !right->value)) { // If the const is on the left, we get to short-circuit the right // immediately. Otherwise, we can only eliminate the LHS if it's pure. if (right) { varuse_collecting_visitor vu(session); e->left->visit(&vu); if (!vu.side_effect_free()) { provide (e); return; } } value = 0; } // We might also get rid of useless "1&&x" and "x&&1", except it does // normalize x to 0 or 1. We could change it to "!!x", but it's not clear // that this would gain us much. else { provide (e); return; } if (session.verbose>2) clog << _("Collapsing constant logical-AND ") << *e->tok << endl; relaxed_p = false; literal_number* n = new literal_number(value); n->tok = e->tok; n->visit (this); } void const_folder::visit_comparison (comparison* e) { int comp; literal_number *left_num, *right_num; literal_string *left_str, *right_str; get_literal(e->left, left_num, left_str); get_literal(e->right, right_num, right_str); if (left_str && right_str) comp = left_str->value.compare(right_str->value); else if (left_num && right_num) comp = left_num->value < right_num->value ? -1 : left_num->value > right_num->value ? 1 : 0; else if ((left_num && ((left_num->value == LLONG_MIN && (e->op == "<=" || e->op == ">")) || (left_num->value == LLONG_MAX && (e->op == ">=" || e->op == "<")))) || (right_num && ((right_num->value == LLONG_MIN && (e->op == ">=" || e->op == "<")) || (right_num->value == LLONG_MAX && (e->op == "<=" || e->op == ">"))))) { expression* other = left_num ? e->right : e->left; varuse_collecting_visitor vu(session); other->visit(&vu); if (!vu.side_effect_free()) provide (e); else { if (session.verbose>2) clog << _("Collapsing constant-boundary comparison ") << *e->tok << endl; relaxed_p = false; // ops <= and >= are true, < and > are false literal_number* n = new literal_number( e->op.length() == 2 ); n->tok = e->tok; n->visit (this); } return; } else { provide (e); return; } if (session.verbose>2) clog << _("Collapsing constant comparison ") << *e->tok << endl; relaxed_p = false; int64_t value; if (e->op == "==") value = comp == 0; else if (e->op == "!=") value = comp != 0; else if (e->op == "<") value = comp < 0; else if (e->op == ">") value = comp > 0; else if (e->op == "<=") value = comp <= 0; else if (e->op == ">=") value = comp >= 0; else throw semantic_error (_("unsupported comparison operator ") + e->op); literal_number* n = new literal_number(value); n->tok = e->tok; n->visit (this); } void const_folder::visit_concatenation (concatenation* e) { literal_string* left = get_string (e->left); literal_string* right = get_string (e->right); if (left && right) { if (session.verbose>2) clog << _("Collapsing constant concatenation ") << *e->tok << endl; relaxed_p = false; literal_string* n = new literal_string (*left); n->tok = e->tok; n->value.append(right->value); n->visit (this); } else if ((left && left->value.empty()) || (right && right->value.empty())) { if (session.verbose>2) clog << _("Collapsing identity concatenation ") << *e->tok << endl; relaxed_p = false; provide(left ? e->right : e->left); } else provide (e); } void const_folder::visit_ternary_expression (ternary_expression* e) { literal_number* cond = get_number (e->cond); if (!cond) { replace (e->truevalue); replace (e->falsevalue); provide (e); } else { if (session.verbose>2) clog << _F("Collapsing constant-%" PRIi64 " ternary %s", cond->value, lex_cast(*e->tok).c_str()) << endl; relaxed_p = false; expression* n = cond->value ? e->truevalue : e->falsevalue; n->visit (this); } } void const_folder::visit_defined_op (defined_op* e) { // If a @defined makes it this far, then it is, de facto, undefined. if (session.verbose>2) clog << _("Collapsing untouched @defined check ") << *e->tok << endl; relaxed_p = false; literal_number* n = new literal_number (0); n->tok = e->tok; n->visit (this); } void const_folder::visit_target_symbol (target_symbol* e) { if (session.skip_badvars) { // Upon user request for ignoring context, the symbol is replaced // with a literal 0 and a warning message displayed // XXX this ignores possible side-effects, e.g. in array indexes literal_number* ln_zero = new literal_number (0); ln_zero->tok = e->tok; provide (ln_zero); session.print_warning (_("Bad $context variable being substituted with literal 0"), e->tok); relaxed_p = false; } else update_visitor::visit_target_symbol (e); } static void semantic_pass_const_fold (systemtap_session& s, bool& relaxed_p) { // Let's simplify statements with constant values. const_folder cf (s, relaxed_p); // This instance may be reused for multiple probe/function body trims. for (unsigned i=0; ibody); for (map::iterator it = s.functions.begin(); it != s.functions.end(); it++) cf.replace (it->second->body); } struct duplicate_function_remover: public functioncall_traversing_visitor { systemtap_session& s; map& duplicate_function_map; duplicate_function_remover(systemtap_session& sess, map&dfm): s(sess), duplicate_function_map(dfm) {}; void visit_functioncall (functioncall* e); }; void duplicate_function_remover::visit_functioncall (functioncall *e) { functioncall_traversing_visitor::visit_functioncall (e); // If the current function call reference points to a function that // is a duplicate, replace it. if (duplicate_function_map.count(e->referent) != 0) { if (s.verbose>2) clog << _F("Changing %s reference to %s reference\n", e->referent->name.c_str(), duplicate_function_map[e->referent]->name.c_str()); e->tok = duplicate_function_map[e->referent]->tok; e->function = duplicate_function_map[e->referent]->name; e->referent = duplicate_function_map[e->referent]; } } static string get_functionsig (functiondecl* f) { ostringstream s; // Get the "name:args body" of the function in s. We have to // include the args since the function 'x1(a, b)' is different than // the function 'x2(b, a)' even if the bodies of the two functions // are exactly the same. f->printsig(s); f->body->print(s); // printsig puts f->name + ':' on the front. Remove this // (otherwise, functions would never compare equal). string str = s.str().erase(0, f->name.size() + 1); // Return the function signature. return str; } void semantic_pass_opt6 (systemtap_session& s, bool& relaxed_p) { // Walk through all the functions, looking for duplicates. map functionsig_map; map duplicate_function_map; vector newly_zapped_functions; for (map::iterator it = s.functions.begin(); it != s.functions.end(); it++) { functiondecl *fd = it->second; string functionsig = get_functionsig(fd); if (functionsig_map.count(functionsig) == 0) { // This function is unique. Remember it. functionsig_map[functionsig] = fd; } else { // This function is a duplicate. duplicate_function_map[fd] = functionsig_map[functionsig]; newly_zapped_functions.push_back (fd); relaxed_p = false; } } for (unsigned i=0; i::iterator where = s.functions.find (newly_zapped_functions[i]->name); assert (where != s.functions.end()); s.functions.erase (where); } // If we have duplicate functions, traverse down the tree, replacing // the appropriate function calls. // duplicate_function_remover::visit_functioncall() handles the // details of replacing the function calls. if (duplicate_function_map.size() != 0) { duplicate_function_remover dfr (s, duplicate_function_map); for (unsigned i=0; i < s.probes.size(); i++) s.probes[i]->body->visit(&dfr); } } static int semantic_pass_optimize1 (systemtap_session& s) { // In this pass, we attempt to rewrite probe/function bodies to // eliminate some blatantly unnecessary code. This is run before // type inference, but after symbol resolution and derived_probe // creation. We run an outer "relaxation" loop that repeats the // optimizations until none of them find anything to remove. int rc = 0; // Save the old value of suppress_warnings, as we will be changing // it below. save_and_restore suppress_warnings(& s.suppress_warnings); bool relaxed_p = false; unsigned iterations = 0; while (! relaxed_p) { assert_no_interrupts(); relaxed_p = true; // until proven otherwise // If the verbosity is high enough, always print warnings (overrides -w), // or if not, always suppress warnings for every itteration after the first. if(s.verbose > 2) s.suppress_warnings = false; else if (iterations > 0) s.suppress_warnings = true; if (!s.unoptimized) { semantic_pass_opt1 (s, relaxed_p); semantic_pass_opt2 (s, relaxed_p, iterations); // produce some warnings only on iteration=0 semantic_pass_opt3 (s, relaxed_p); semantic_pass_opt4 (s, relaxed_p); semantic_pass_opt5 (s, relaxed_p); } // For listing mode, we need const-folding regardless of optimization so // that @defined expressions can be properly resolved. PR11360 // We also want it in case variables are used in if/case expressions, // so enable always. PR11366 semantic_pass_const_fold (s, relaxed_p); iterations ++; } return rc; } static int semantic_pass_optimize2 (systemtap_session& s) { // This is run after type inference. We run an outer "relaxation" // loop that repeats the optimizations until none of them find // anything to remove. int rc = 0; // Save the old value of suppress_warnings, as we will be changing // it below. save_and_restore suppress_warnings(& s.suppress_warnings); bool relaxed_p = false; unsigned iterations = 0; while (! relaxed_p) { assert_no_interrupts(); relaxed_p = true; // until proven otherwise // If the verbosity is high enough, always print warnings (overrides -w), // or if not, always suppress warnings for every itteration after the first. if(s.verbose > 2) s.suppress_warnings = false; else if (iterations > 0) s.suppress_warnings = true; if (!s.unoptimized) semantic_pass_opt6 (s, relaxed_p); iterations++; } return rc; } // ------------------------------------------------------------------------ // type resolution static int semantic_pass_types (systemtap_session& s) { int rc = 0; // next pass: type inference unsigned iterations = 0; typeresolution_info ti (s); ti.assert_resolvability = false; // XXX: maybe convert to exception-based error signalling while (1) { assert_no_interrupts(); iterations ++; ti.num_newly_resolved = 0; ti.num_still_unresolved = 0; for (map::iterator it = s.functions.begin(); it != s.functions.end(); it++) { assert_no_interrupts(); functiondecl* fd = it->second; ti.current_probe = 0; ti.current_function = fd; ti.t = pe_unknown; fd->body->visit (& ti); // NB: we don't have to assert a known type for // functions here, to permit a "void" function. // The translator phase will omit the "retvalue". // // if (fd->type == pe_unknown) // ti.unresolved (fd->tok); for (unsigned i=0; i < fd->locals.size(); ++i) ti.check_local (fd->locals[i]); } for (unsigned j=0; jbody->visit (& ti); for (unsigned i=0; i < pn->locals.size(); ++i) ti.check_local (pn->locals[i]); probe_point* pp = pn->sole_location(); if (pp->condition) { ti.current_function = 0; ti.current_probe = 0; ti.t = pe_long; // NB: expected type pp->condition->visit (& ti); } } for (unsigned j=0; jtype == pe_unknown) ti.unresolved (gd->tok); if(gd->arity == 0 && gd->wrap == true) { throw semantic_error (_("wrapping not supported for scalars"), gd->tok); } } if (ti.num_newly_resolved == 0) // converged { if (ti.num_still_unresolved == 0) break; // successfully else if (! ti.assert_resolvability) ti.assert_resolvability = true; // last pass, with error msgs else { // unsuccessful conclusion rc ++; break; } } } return rc + s.num_errors(); } typeresolution_info::typeresolution_info (systemtap_session& s): session(s), num_newly_resolved(0), num_still_unresolved(0), assert_resolvability(false), current_function(0), current_probe(0), t(pe_unknown) { } void typeresolution_info::visit_literal_number (literal_number* e) { assert (e->type == pe_long); if ((t == e->type) || (t == pe_unknown)) return; mismatch (e->tok, e->type, t); } void typeresolution_info::visit_literal_string (literal_string* e) { assert (e->type == pe_string); if ((t == e->type) || (t == pe_unknown)) return; mismatch (e->tok, e->type, t); } void typeresolution_info::visit_logical_or_expr (logical_or_expr *e) { visit_binary_expression (e); } void typeresolution_info::visit_logical_and_expr (logical_and_expr *e) { visit_binary_expression (e); } void typeresolution_info::visit_regex_query (regex_query *e) { // NB: result of regex query is an integer! if (t == pe_stats || t == pe_string) invalid (e->tok, t); t = pe_string; e->left->visit (this); t = pe_string; e->right->visit (this); // parser ensures this is a literal known at compile time if (e->type == pe_unknown) { e->type = pe_long; resolved (e->tok, e->type); } } void typeresolution_info::visit_comparison (comparison *e) { // NB: result of any comparison is an integer! if (t == pe_stats || t == pe_string) invalid (e->tok, t); t = (e->right->type != pe_unknown) ? e->right->type : pe_unknown; e->left->visit (this); t = (e->left->type != pe_unknown) ? e->left->type : pe_unknown; e->right->visit (this); if (e->left->type != pe_unknown && e->right->type != pe_unknown && e->left->type != e->right->type) mismatch (e->tok, e->left->type, e->right->type); if (e->type == pe_unknown) { e->type = pe_long; resolved (e->tok, e->type); } } void typeresolution_info::visit_concatenation (concatenation *e) { if (t != pe_unknown && t != pe_string) invalid (e->tok, t); t = pe_string; e->left->visit (this); t = pe_string; e->right->visit (this); if (e->type == pe_unknown) { e->type = pe_string; resolved (e->tok, e->type); } } void typeresolution_info::visit_assignment (assignment *e) { if (t == pe_stats) invalid (e->tok, t); if (e->op == "<<<") // stats aggregation { if (t == pe_string) invalid (e->tok, t); t = pe_stats; e->left->visit (this); t = pe_long; e->right->visit (this); if (e->type == pe_unknown || e->type == pe_stats) { e->type = pe_long; resolved (e->tok, e->type); } } else if (e->left->type == pe_stats) invalid (e->left->tok, e->left->type); else if (e->right->type == pe_stats) invalid (e->right->tok, e->right->type); else if (e->op == "+=" || // numeric only e->op == "-=" || e->op == "*=" || e->op == "/=" || e->op == "%=" || e->op == "&=" || e->op == "^=" || e->op == "|=" || e->op == "<<=" || e->op == ">>=" || false) { visit_binary_expression (e); } else if (e->op == ".=" || // string only false) { if (t == pe_long || t == pe_stats) invalid (e->tok, t); t = pe_string; e->left->visit (this); t = pe_string; e->right->visit (this); if (e->type == pe_unknown) { e->type = pe_string; resolved (e->tok, e->type); } } else if (e->op == "=") // overloaded = for string & numeric operands { // logic similar to ternary_expression exp_type sub_type = t; // Infer types across the l/r values if (sub_type == pe_unknown && e->type != pe_unknown) sub_type = e->type; t = (sub_type != pe_unknown) ? sub_type : (e->right->type != pe_unknown) ? e->right->type : pe_unknown; e->left->visit (this); t = (sub_type != pe_unknown) ? sub_type : (e->left->type != pe_unknown) ? e->left->type : pe_unknown; e->right->visit (this); if ((sub_type != pe_unknown) && (e->type == pe_unknown)) { e->type = sub_type; resolved (e->tok, e->type); } if ((sub_type == pe_unknown) && (e->left->type != pe_unknown)) { e->type = e->left->type; resolved (e->tok, e->type); } if (e->left->type != pe_unknown && e->right->type != pe_unknown && e->left->type != e->right->type) mismatch (e->tok, e->left->type, e->right->type); } else throw semantic_error (_("unsupported assignment operator ") + e->op); } void typeresolution_info::visit_embedded_expr (embedded_expr *e) { if (e->type == pe_unknown) { if (e->code.find ("/* string */") != string::npos) e->type = pe_string; else // if (e->code.find ("/* long */") != string::npos) e->type = pe_long; resolved (e->tok, e->type); } } void typeresolution_info::visit_binary_expression (binary_expression* e) { if (t == pe_stats || t == pe_string) invalid (e->tok, t); t = pe_long; e->left->visit (this); t = pe_long; e->right->visit (this); if (e->left->type != pe_unknown && e->right->type != pe_unknown && e->left->type != e->right->type) mismatch (e->tok, e->left->type, e->right->type); if (e->type == pe_unknown) { e->type = pe_long; resolved (e->tok, e->type); } } void typeresolution_info::visit_pre_crement (pre_crement *e) { visit_unary_expression (e); } void typeresolution_info::visit_post_crement (post_crement *e) { visit_unary_expression (e); } void typeresolution_info::visit_unary_expression (unary_expression* e) { if (t == pe_stats || t == pe_string) invalid (e->tok, t); t = pe_long; e->operand->visit (this); if (e->type == pe_unknown) { e->type = pe_long; resolved (e->tok, e->type); } } void typeresolution_info::visit_ternary_expression (ternary_expression* e) { exp_type sub_type = t; t = pe_long; e->cond->visit (this); // Infer types across the true/false arms of the ternary expression. if (sub_type == pe_unknown && e->type != pe_unknown) sub_type = e->type; t = sub_type; e->truevalue->visit (this); t = sub_type; e->falsevalue->visit (this); if ((sub_type == pe_unknown) && (e->type != pe_unknown)) ; // already resolved else if ((sub_type != pe_unknown) && (e->type == pe_unknown)) { e->type = sub_type; resolved (e->tok, e->type); } else if ((sub_type == pe_unknown) && (e->truevalue->type != pe_unknown)) { e->type = e->truevalue->type; resolved (e->tok, e->type); } else if ((sub_type == pe_unknown) && (e->falsevalue->type != pe_unknown)) { e->type = e->falsevalue->type; resolved (e->tok, e->type); } else if (e->type != sub_type) mismatch (e->tok, sub_type, e->type); } template void resolve_2types (Referrer* referrer, Referent* referent, typeresolution_info* r, exp_type t, bool accept_unknown = false) { exp_type& re_type = referrer->type; const token* re_tok = referrer->tok; exp_type& te_type = referent->type; const token* te_tok = referent->tok; if (t != pe_unknown && re_type == t && re_type == te_type) ; // do nothing: all three e->types in agreement else if (t == pe_unknown && re_type != pe_unknown && re_type == te_type) ; // do nothing: two known e->types in agreement else if (re_type != pe_unknown && te_type != pe_unknown && re_type != te_type) r->mismatch (re_tok, re_type, te_type); else if (re_type != pe_unknown && t != pe_unknown && re_type != t) r->mismatch (re_tok, re_type, t); else if (te_type != pe_unknown && t != pe_unknown && te_type != t) r->mismatch (te_tok, te_type, t); else if (re_type == pe_unknown && t != pe_unknown) { // propagate from upstream re_type = t; r->resolved (re_tok, re_type); // catch re_type/te_type mismatch later } else if (re_type == pe_unknown && te_type != pe_unknown) { // propagate from referent re_type = te_type; r->resolved (re_tok, re_type); // catch re_type/t mismatch later } else if (re_type != pe_unknown && te_type == pe_unknown) { // propagate to referent te_type = re_type; r->resolved (te_tok, te_type); // catch re_type/t mismatch later } else if (! accept_unknown) r->unresolved (re_tok); } void typeresolution_info::visit_symbol (symbol* e) { assert (e->referent != 0); resolve_2types (e, e->referent, this, t); } void typeresolution_info::visit_target_symbol (target_symbol* e) { // This occurs only if a target symbol was not resolved over in // tapset.cxx land, that error was properly suppressed, and the // later unused-expression-elimination pass didn't get rid of it // either. So we have a target symbol that is believed to be of // genuine use, yet unresolved by the provider. if (session.verbose > 2) { clog << _("Resolution problem with "); if (current_function) { clog << "function " << current_function->name << endl; current_function->body->print (clog); clog << endl; } else if (current_probe) { clog << "probe " << *current_probe->sole_location() << endl; current_probe->body->print (clog); clog << endl; } else //TRANSLATORS: simply saying not an issue with a probe or function clog << _("other") << endl; } if (e->saved_conversion_error) throw (* (e->saved_conversion_error)); else throw semantic_error(_("unresolved target-symbol expression"), e->tok); } void typeresolution_info::visit_atvar_op (atvar_op* e) { // This occurs only if an @var() was not resolved over in // tapset.cxx land, that error was properly suppressed, and the // later unused-expression-elimination pass didn't get rid of it // either. So we have an @var() that is believed to be of // genuine use, yet unresolved by the provider. if (session.verbose > 2) { clog << _("Resolution problem with "); if (current_function) { clog << "function " << current_function->name << endl; current_function->body->print (clog); clog << endl; } else if (current_probe) { clog << "probe " << *current_probe->sole_location() << endl; current_probe->body->print (clog); clog << endl; } else //TRANSLATORS: simply saying not an issue with a probe or function clog << _("other") << endl; } if (e->saved_conversion_error) throw (* (e->saved_conversion_error)); else throw semantic_error(_("unresolved @var() expression"), e->tok); } void typeresolution_info::visit_defined_op (defined_op* e) { throw semantic_error(_("unexpected @defined"), e->tok); } void typeresolution_info::visit_entry_op (entry_op* e) { throw semantic_error(_("@entry is only valid in .return probes"), e->tok); } void typeresolution_info::visit_cast_op (cast_op* e) { // Like target_symbol, a cast_op shouldn't survive this far // unless it was not resolved and its value is really needed. if (e->saved_conversion_error) throw (* (e->saved_conversion_error)); else throw semantic_error(_F("type definition '%s' not found in '%s'", e->type_name.c_str(), e->module.c_str()), e->tok); } void typeresolution_info::visit_perf_op (perf_op* e) { // A perf_op should already be resolved if (t == pe_stats || t == pe_string) invalid (e->tok, t); e->type = pe_long; // (There is no real need to visit our operand - by parser // construction, it's always a string literal, with its type already // set.) t = pe_string; e->operand->visit (this); } void typeresolution_info::visit_arrayindex (arrayindex* e) { symbol *array = NULL; hist_op *hist = NULL; classify_indexable(e->base, array, hist); // Every hist_op has type [int]:int, that is to say, every hist_op // is a pseudo-one-dimensional integer array type indexed by // integers (bucket numbers). if (hist) { if (e->indexes.size() != 1) unresolved (e->tok); t = pe_long; e->indexes[0]->visit (this); if (e->indexes[0]->type != pe_long) unresolved (e->tok); hist->visit (this); if (e->type != pe_long) { e->type = pe_long; resolved (e->tok, pe_long); } return; } // Now we are left with "normal" map inference and index checking. assert (array); assert (array->referent != 0); resolve_2types (e, array->referent, this, t); // now resolve the array indexes // if (e->referent->index_types.size() == 0) // // redesignate referent as array // e->referent->set_arity (e->indexes.size ()); if (e->indexes.size() != array->referent->index_types.size()) unresolved (e->tok); // symbol resolution should prevent this else for (unsigned i=0; iindexes.size(); i++) { expression* ee = e->indexes[i]; exp_type& ft = array->referent->index_types [i]; t = ft; ee->visit (this); exp_type at = ee->type; if ((at == pe_string || at == pe_long) && ft == pe_unknown) { // propagate to formal type ft = at; resolved (array->referent->tok, ft); // uses array decl as there is no token for "formal type" } if (at == pe_stats) invalid (ee->tok, at); if (ft == pe_stats) invalid (ee->tok, ft); if (at != pe_unknown && ft != pe_unknown && ft != at) mismatch (e->tok, at, ft); if (at == pe_unknown) unresolved (ee->tok); } } void typeresolution_info::visit_functioncall (functioncall* e) { assert (e->referent != 0); resolve_2types (e, e->referent, this, t, true); // accept unknown type if (e->type == pe_stats) invalid (e->tok, e->type); // now resolve the function parameters if (e->args.size() != e->referent->formal_args.size()) unresolved (e->tok); // symbol resolution should prevent this else for (unsigned i=0; iargs.size(); i++) { expression* ee = e->args[i]; exp_type& ft = e->referent->formal_args[i]->type; const token* fe_tok = e->referent->formal_args[i]->tok; t = ft; ee->visit (this); exp_type at = ee->type; if (((at == pe_string) || (at == pe_long)) && ft == pe_unknown) { // propagate to formal arg ft = at; resolved (e->referent->formal_args[i]->tok, ft); } if (at == pe_stats) invalid (e->tok, at); if (ft == pe_stats) invalid (fe_tok, ft); if (at != pe_unknown && ft != pe_unknown && ft != at) mismatch (e->tok, at, ft); if (at == pe_unknown) unresolved (e->tok); } } void typeresolution_info::visit_block (block* e) { for (unsigned i=0; istatements.size(); i++) { try { t = pe_unknown; e->statements[i]->visit (this); } catch (const semantic_error& e) { session.print_error (e); } } } void typeresolution_info::visit_try_block (try_block* e) { if (e->try_block) e->try_block->visit (this); if (e->catch_error_var) { t = pe_string; e->catch_error_var->visit (this); } if (e->catch_block) e->catch_block->visit (this); } void typeresolution_info::visit_embeddedcode (embeddedcode* s) { // PR11573. If we have survived thus far with a piece of embedded // code that requires uprobes, we need to track this. // // This is an odd place for this check, as opposed // to a separate 'optimization' pass, or c_unparser::visit_embeddedcode // over yonder in pass 3. However, we want to do it during pass 2 so // that cached sessions also get the uprobes treatment. if (! session.need_uprobes && s->code.find("/* pragma:uprobes */") != string::npos) { if (session.verbose > 2) clog << _("Activating uprobes support because /* pragma:uprobes */ seen.") << endl; session.need_uprobes = true; } // PR15065. Likewise, we need to detect /* pragma:tagged_dfa */ // before the gen_dfa_table pass. Again, the typechecking part of // pass 2 is a good place for this. if (! session.need_tagged_dfa && s->code.find("/* pragma:tagged_dfa */") != string::npos) { // if (session.verbose > 2) // clog << _F("Turning on DFA subexpressions, pragma:tagged_dfa found in %s", // current_function->name.c_str()) << endl; // session.need_tagged_dfa = true; throw semantic_error (_("Tagged DFA support is not yet available"), s->tok); } } void typeresolution_info::visit_if_statement (if_statement* e) { t = pe_long; e->condition->visit (this); t = pe_unknown; e->thenblock->visit (this); if (e->elseblock) { t = pe_unknown; e->elseblock->visit (this); } } void typeresolution_info::visit_for_loop (for_loop* e) { t = pe_unknown; if (e->init) e->init->visit (this); t = pe_long; e->cond->visit (this); t = pe_unknown; if (e->incr) e->incr->visit (this); t = pe_unknown; e->block->visit (this); } void typeresolution_info::visit_foreach_loop (foreach_loop* e) { // See also visit_arrayindex. // This is different in that, being a statement, we can't assign // a type to the outer array, only propagate to/from the indexes // if (e->referent->index_types.size() == 0) // // redesignate referent as array // e->referent->set_arity (e->indexes.size ()); exp_type wanted_value = pe_unknown; symbol *array = NULL; hist_op *hist = NULL; classify_indexable(e->base, array, hist); if (hist) { if (e->indexes.size() != 1) unresolved (e->tok); t = pe_long; e->indexes[0]->visit (this); if (e->indexes[0]->type != pe_long) unresolved (e->tok); hist->visit (this); wanted_value = pe_long; } else { assert (array); if (e->indexes.size() != array->referent->index_types.size()) unresolved (e->tok); // symbol resolution should prevent this else for (unsigned i=0; iindexes.size(); i++) { expression* ee = e->indexes[i]; exp_type& ft = array->referent->index_types [i]; t = ft; ee->visit (this); exp_type at = ee->type; if ((at == pe_string || at == pe_long) && ft == pe_unknown) { // propagate to formal type ft = at; resolved (array->referent->tok, ft); // uses array decl as there is no token for "formal type" } if (at == pe_stats) invalid (ee->tok, at); if (ft == pe_stats) invalid (ee->tok, ft); if (at != pe_unknown && ft != pe_unknown && ft != at) mismatch (e->tok, at, ft); if (at == pe_unknown) unresolved (ee->tok); } t = pe_unknown; array->visit (this); wanted_value = array->type; } if (e->value) { if (wanted_value == pe_stats) invalid(e->value->tok, wanted_value); else if (wanted_value != pe_unknown) check_arg_type(wanted_value, e->value); else { t = pe_unknown; e->value->visit (this); } } /* Prevent @sum etc. aggregate sorting on non-statistics arrays. */ if (wanted_value != pe_unknown) if (e->sort_aggr != sc_none && wanted_value != pe_stats) invalid (array->tok, wanted_value); if (e->limit) { t = pe_long; e->limit->visit (this); } t = pe_unknown; e->block->visit (this); } void typeresolution_info::visit_null_statement (null_statement*) { } void typeresolution_info::visit_expr_statement (expr_statement* e) { t = pe_unknown; e->value->visit (this); } struct delete_statement_typeresolution_info: public throwing_visitor { typeresolution_info *parent; delete_statement_typeresolution_info (typeresolution_info *p): throwing_visitor (_("invalid operand of delete expression")), parent (p) {} void visit_arrayindex (arrayindex* e) { parent->visit_arrayindex (e); } void visit_symbol (symbol* e) { exp_type ignored = pe_unknown; assert (e->referent != 0); resolve_2types (e, e->referent, parent, ignored); } }; void typeresolution_info::visit_delete_statement (delete_statement* e) { delete_statement_typeresolution_info di (this); t = pe_unknown; e->value->visit (&di); } void typeresolution_info::visit_next_statement (next_statement*) { } void typeresolution_info::visit_break_statement (break_statement*) { } void typeresolution_info::visit_continue_statement (continue_statement*) { } void typeresolution_info::visit_array_in (array_in* e) { // all unary operators only work on numerics exp_type t1 = t; t = pe_unknown; // array value can be anything e->operand->visit (this); if (t1 == pe_unknown && e->type != pe_unknown) ; // already resolved else if (t1 == pe_string || t1 == pe_stats) mismatch (e->tok, t1, pe_long); else if (e->type == pe_unknown) { e->type = pe_long; resolved (e->tok, e->type); } } void typeresolution_info::visit_return_statement (return_statement* e) { // This is like symbol, where the referent is // the return value of the function. // translation pass will print error if (current_function == 0) return; exp_type& e_type = current_function->type; t = current_function->type; e->value->visit (this); if (e_type != pe_unknown && e->value->type != pe_unknown && e_type != e->value->type) mismatch (current_function->tok, e_type, e->value->type); if (e_type == pe_unknown && (e->value->type == pe_long || e->value->type == pe_string)) { // propagate non-statistics from value e_type = e->value->type; resolved (current_function->tok, e->value->type); } if (e->value->type == pe_stats) invalid (e->value->tok, e->value->type); } void typeresolution_info::visit_print_format (print_format* e) { size_t unresolved_args = 0; if (e->hist) { e->hist->visit(this); } else if (e->print_with_format) { // If there's a format string, we can do both inference *and* // checking. // First we extract the subsequence of formatting components // which are conversions (not just literal string components) unsigned expected_num_args = 0; std::vector components; for (size_t i = 0; i < e->components.size(); ++i) { if (e->components[i].type == print_format::conv_unspecified) throw semantic_error (_("Unspecified conversion in print operator format string"), e->tok); else if (e->components[i].type == print_format::conv_literal) continue; components.push_back(e->components[i]); ++expected_num_args; if (e->components[i].widthtype == print_format::width_dynamic) ++expected_num_args; if (e->components[i].prectype == print_format::prec_dynamic) ++expected_num_args; } // Then we check that the number of conversions and the number // of args agree. if (expected_num_args != e->args.size()) throw semantic_error (_("Wrong number of args to formatted print operator"), e->tok); // Then we check that the types of the conversions match the types // of the args. unsigned argno = 0; for (size_t i = 0; i < components.size(); ++i) { // Check the dynamic width, if specified if (components[i].widthtype == print_format::width_dynamic) { check_arg_type (pe_long, e->args[argno]); ++argno; } // Check the dynamic precision, if specified if (components[i].prectype == print_format::prec_dynamic) { check_arg_type (pe_long, e->args[argno]); ++argno; } exp_type wanted = pe_unknown; switch (components[i].type) { case print_format::conv_unspecified: case print_format::conv_literal: assert (false); break; case print_format::conv_pointer: case print_format::conv_number: case print_format::conv_binary: case print_format::conv_char: case print_format::conv_memory: case print_format::conv_memory_hex: wanted = pe_long; break; case print_format::conv_string: wanted = pe_string; break; } assert (wanted != pe_unknown); check_arg_type (wanted, e->args[argno]); ++argno; } } else { // Without a format string, the best we can do is require that // each argument resolve to a concrete type. for (size_t i = 0; i < e->args.size(); ++i) { t = pe_unknown; e->args[i]->visit (this); if (e->args[i]->type == pe_unknown) { unresolved (e->args[i]->tok); ++unresolved_args; } } } if (unresolved_args == 0) { if (e->type == pe_unknown) { if (e->print_to_stream) e->type = pe_long; else e->type = pe_string; resolved (e->tok, e->type); } } else { e->type = pe_unknown; unresolved (e->tok); } } void typeresolution_info::visit_stat_op (stat_op* e) { t = pe_stats; e->stat->visit (this); if (e->type == pe_unknown) { e->type = pe_long; resolved (e->tok, e->type); } else if (e->type != pe_long) mismatch (e->tok, e->type, pe_long); } void typeresolution_info::visit_hist_op (hist_op* e) { t = pe_stats; e->stat->visit (this); } void typeresolution_info::check_arg_type (exp_type wanted, expression* arg) { t = wanted; arg->visit (this); if (arg->type == pe_unknown) { arg->type = wanted; resolved (arg->tok, wanted); } else if (arg->type != wanted) { mismatch (arg->tok, arg->type, wanted); } } void typeresolution_info::check_local (vardecl* v) { if (v->arity != 0) { num_still_unresolved ++; if (assert_resolvability) session.print_error (semantic_error (_("array locals not supported, missing global declaration? "), v->tok)); } if (v->type == pe_unknown) unresolved (v->tok); else if (v->type == pe_stats) { num_still_unresolved ++; if (assert_resolvability) session.print_error (semantic_error (_("stat locals not supported, missing global declaration? "), v->tok)); } else if (!(v->type == pe_long || v->type == pe_string)) invalid (v->tok, v->type); } void typeresolution_info::unresolved (const token* tok) { num_still_unresolved ++; if (assert_resolvability) { stringstream msg; msg << _("unresolved type "); session.print_error (semantic_error (msg.str(), tok)); } } void typeresolution_info::invalid (const token* tok, exp_type pe) { num_still_unresolved ++; if (assert_resolvability) { stringstream msg; if (tok && tok->type == tok_operator) msg << _("invalid operator"); else msg << _("invalid type ") << pe; session.print_error (semantic_error (msg.str(), tok)); } } void typeresolution_info::mismatch (const token* tok, exp_type t1, exp_type t2) { bool tok_resolved = false; size_t i; semantic_error* err1 = 0; num_still_unresolved ++; //BZ 9719: for improving type mismatch messages, a semantic error is //generated with the token where type was first resolved. All such //resolved tokens, stored in a vector, are matched against their //content. If an error for the matching token hasn't been printed out //already, it is and the token pushed in another printed_toks vector if (assert_resolvability) { stringstream msg; for (i=0; icontent == tok->content) { tok_resolved = true; break; } } if (!tok_resolved) { msg << _F("type mismatch (%s vs. %s)", lex_cast(t1).c_str(), lex_cast(t2).c_str()); } else { bool tok_printed = false; for (size_t j=0; j4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/elaborate.h000066400000000000000000000346621217430427200155330ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2005-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef ELABORATE_H #define ELABORATE_H #include "staptree.h" #include "parse.h" #include #include //#include #include #include #include #include extern "C" { #include } #include "privilege.h" struct recursive_expansion_error : public semantic_error { ~recursive_expansion_error () throw () {} recursive_expansion_error (const std::string& msg, const token* t1=0): semantic_error (msg, t1) {} recursive_expansion_error (const std::string& msg, const token* t1, const token* t2): semantic_error (msg, t1, t2) {} }; // ------------------------------------------------------------------------ struct derived_probe; class match_node; struct symresolution_info: public traversing_visitor { protected: systemtap_session& session; public: functiondecl* current_function; derived_probe* current_probe; symresolution_info (systemtap_session& s); vardecl* find_var (const std::string& name, int arity, const token *tok); functiondecl* find_function (const std::string& name, unsigned arity); void visit_block (block *s); void visit_symbol (symbol* e); void visit_foreach_loop (foreach_loop* e); void visit_arrayindex (arrayindex* e); void visit_functioncall (functioncall* e); void visit_delete_statement (delete_statement* s); }; struct typeresolution_info: public visitor { typeresolution_info (systemtap_session& s); systemtap_session& session; unsigned num_newly_resolved; unsigned num_still_unresolved; bool assert_resolvability; functiondecl* current_function; derived_probe* current_probe; std::vector resolved_toks; // account for type mis- std::vector printed_toks; // matches (BZ 9719) void check_arg_type (exp_type wanted, expression* arg); void check_local (vardecl* v); void mismatch (const token* tok, exp_type t1, exp_type t2); void unresolved (const token* tok); void resolved (const token* tok, exp_type t); void invalid (const token* tok, exp_type t); exp_type t; // implicit parameter for nested visit call; may clobber // Upon entry to one of the visit_* calls, the incoming // `t' value is the type inferred for that node from // context. It may match or conflict with the node's // preexisting type, or it may be unknown. void visit_block (block* s); void visit_try_block (try_block* s); void visit_embeddedcode (embeddedcode* s); void visit_null_statement (null_statement* s); void visit_expr_statement (expr_statement* s); void visit_if_statement (if_statement* s); void visit_for_loop (for_loop* s); void visit_foreach_loop (foreach_loop* s); void visit_return_statement (return_statement* s); void visit_delete_statement (delete_statement* s); void visit_next_statement (next_statement* s); void visit_break_statement (break_statement* s); void visit_continue_statement (continue_statement* s); void visit_literal_string (literal_string* e); void visit_literal_number (literal_number* e); void visit_embedded_expr (embedded_expr* e); void visit_binary_expression (binary_expression* e); void visit_unary_expression (unary_expression* e); void visit_pre_crement (pre_crement* e); void visit_post_crement (post_crement* e); void visit_logical_or_expr (logical_or_expr* e); void visit_logical_and_expr (logical_and_expr* e); void visit_array_in (array_in* e); void visit_regex_query (regex_query* e); void visit_comparison (comparison* e); void visit_concatenation (concatenation* e); void visit_ternary_expression (ternary_expression* e); void visit_assignment (assignment* e); void visit_symbol (symbol* e); void visit_target_symbol (target_symbol* e); void visit_arrayindex (arrayindex* e); void visit_functioncall (functioncall* e); void visit_print_format (print_format* e); void visit_stat_op (stat_op* e); void visit_hist_op (hist_op* e); void visit_cast_op (cast_op* e); void visit_atvar_op (atvar_op* e); void visit_defined_op (defined_op* e); void visit_entry_op (entry_op* e); void visit_perf_op (perf_op* e); }; // ------------------------------------------------------------------------ // A derived_probe is a probe that has been elaborated by // binding to a matching provider. The locations std::vector // may be smaller or larger than the base probe, since a // provider may transform it. class translator_output; struct derived_probe_group; struct derived_probe: public probe { derived_probe (probe* b, probe_point* l, bool rewrite_loc=false); probe* base; // the original parsed probe probe_point* base_pp; // the probe_point that led to this derivation virtual ~derived_probe () {} virtual void join_group (systemtap_session& s) = 0; virtual probe_point* sole_location () const; virtual probe_point* script_location () const; virtual void printsig (std::ostream &o) const; // return arguments of probe if there virtual void getargs (std::list &) const {} void printsig_nested (std::ostream &o) const; virtual void collect_derivation_chain (std::vector &probes_list) const; virtual void collect_derivation_pp_chain (std::vector &pp_list) const; std::string derived_locations (); virtual void print_dupe_stamp(std::ostream&) {} // To aid duplication elimination, print a stamp which uniquely identifies // the code that will be added to the probe body. (Doesn't need to be the // actual code...) virtual void initialize_probe_context_vars (translator_output*) {} // From within unparser::emit_probe, initialized any extra variables // in this probe's context locals. virtual void emit_probe_local_init (systemtap_session& s, translator_output*) {} // From within unparser::emit_probe, emit any extra processing block // for this probe. virtual void emit_privilege_assertion (translator_output*); // From within unparser::emit_probe, emit any unprivileged mode // checking for this probe. public: static void emit_common_header (translator_output* o); // from c_unparser::emit_common_header // XXX: probably can move this stuff to a probe_group::emit_module_decls static void emit_process_owner_assertion (translator_output*); // From within unparser::emit_probe, emit a check that the current // process belongs to the user. static void print_dupe_stamp_unprivileged(std::ostream& o); static void print_dupe_stamp_unprivileged_process_owner(std::ostream& o); virtual bool needs_global_locks () { return true; } // by default, probes need locks around global variables // Location of semaphores to activate sdt probes Dwarf_Addr sdt_semaphore_addr; // perf.counter probes that this probe references std::set perf_counter_refs; // index into session.probes[], set and used during translation unsigned session_index; }; // ------------------------------------------------------------------------ struct unparser; // Various derived classes derived_probe_group manage the // registration/invocation/unregistration of sibling probes. struct derived_probe_group { virtual ~derived_probe_group () {} virtual void emit_kernel_module_init (systemtap_session& s) {} // Similar to emit_module_init(), but code emitted here gets run // with root access. The _init-generated code may assume that it is // called only once. If that code fails at run time, it must set // rc=1 and roll back any partial initializations, for its _exit // friend will NOT be invoked. The generated code may use // pre-declared "int i, j;". Note that the message transport isn't // available, so printk()/errk() is the only output option. virtual void emit_kernel_module_exit (systemtap_session& s) {} // Similar to emit_module_exit(), but code emitted here gets run // with root access. The _exit-generated code may assume that it is // executed exactly zero times (if the _init-generated code failed) // or once. (_exit itself may be called a few times, to generate // the code in a few different places in the probe module.) The // generated code may use pre-declared "int i, j;". Note that the // message transport isn't available, so printk()/errk() is the only // output option. virtual void emit_module_decls (systemtap_session& s) = 0; // The _decls-generated code may assume that declarations such as // the context, embedded-C code, function and probe handler bodies // are all already generated. That is, _decls is called near the // end of the code generation process. It should minimize the // number of separate variables (and to a lesser extent, their // size). virtual void emit_module_init (systemtap_session& s) = 0; // The _init-generated code may assume that it is called only once. // If that code fails at run time, it must set rc=1 and roll back // any partial initializations, for its _exit friend will NOT be // invoked. The generated code may use pre-declared "int i, j;" // and set "const char* probe_point;". virtual void emit_module_post_init (systemtap_session& s) {} // The emit_module_post_init() code is called once session_state is // set to running. virtual void emit_module_refresh (systemtap_session& s) {} // The _refresh-generated code may be called multiple times during // a session run, bracketed by _init and _exit calls. // Upon failure, it must set enough state so that // a subsequent _exit call will clean up everything. // The generated code may use pre-declared "int i, j;". virtual void emit_module_exit (systemtap_session& s) = 0; // The _exit-generated code may assume that it is executed exactly // zero times (if the _init-generated code failed) or once. (_exit // itself may be called a few times, to generate the code in a few // different places in the probe module.) // The generated code may use pre-declared "int i, j;". }; // ------------------------------------------------------------------------ typedef std::map literal_map_t; struct derived_probe_builder { virtual void build(systemtap_session & sess, probe* base, probe_point* location, literal_map_t const & parameters, std::vector & finished_results) = 0; virtual void build_with_suffix(systemtap_session & sess, probe * use, probe_point * location, std::map const & parameters, std::vector & finished_results, std::vector const & suffix); virtual ~derived_probe_builder() {} virtual void build_no_more (systemtap_session &) {} virtual bool is_alias () const { return false; } static bool has_null_param (literal_map_t const & parameters, const std::string& key); static bool get_param (literal_map_t const & parameters, const std::string& key, std::string& value); static bool get_param (literal_map_t const & parameters, const std::string& key, int64_t& value); }; struct match_key { std::string name; bool have_parameter; exp_type parameter_type; match_key(std::string const & n); match_key(probe_point::component const & c); match_key & with_number(); match_key & with_string(); std::string str() const; bool operator<(match_key const & other) const; bool globmatch(match_key const & other) const; }; class match_node { typedef std::map sub_map_t; typedef std::map::iterator sub_map_iterator_t; sub_map_t sub; std::vector ends; public: match_node(); void find_and_build (systemtap_session& s, probe* p, probe_point *loc, unsigned pos, std::vector& results); void try_suffix_expansion (systemtap_session& s, probe *p, probe_point *loc, unsigned pos, std::vector& results); void build_no_more (systemtap_session &s); void dump (systemtap_session &s, const std::string &name = ""); match_node* bind(match_key const & k); match_node* bind(std::string const & k); match_node* bind_str(std::string const & k); match_node* bind_num(std::string const & k); match_node* bind_privilege(privilege_t p = privilege_t (pr_stapdev | pr_stapsys)); void bind(derived_probe_builder* e); private: privilege_t privilege; }; // ------------------------------------------------------------------------ struct alias_expansion_builder : public derived_probe_builder { probe_alias * alias; alias_expansion_builder(probe_alias * a) : alias(a) {} virtual void build(systemtap_session & sess, probe * use, probe_point * location, std::map const &, std::vector & finished_results); virtual void build_with_suffix(systemtap_session & sess, probe * use, probe_point * location, std::map const &, std::vector & finished_results, std::vector const & suffix); virtual bool is_alias () const { return true; } bool checkForRecursiveExpansion (probe *use); }; // ------------------------------------------------------------------------ /* struct systemtap_session moved to session.h */ int semantic_pass (systemtap_session& s); void derive_probes (systemtap_session& s, probe *p, std::vector& dps, bool optional = false, bool rethrow_errors = false); // A helper we use here and in translate, for pulling symbols out of lvalue // expressions. symbol * get_symbol_within_expression (expression *e); struct unparser; #endif // ELABORATE_H /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/emacs/000077500000000000000000000000001217430427200145015ustar00rootroot00000000000000systemtap-2.3/emacs/systemtap-init.el000066400000000000000000000003201217430427200200100ustar00rootroot00000000000000(autoload 'systemtap-mode "systemtap-mode.el") (setq auto-mode-alist (append '(("\\.stp$" . systemtap-mode)) auto-mode-alist)) (setq auto-mode-alist (append '(("\\.stpm$" . systemtap-mode)) auto-mode-alist)) systemtap-2.3/emacs/systemtap-mode.el000066400000000000000000000133001217430427200177730ustar00rootroot00000000000000;;; systemtap-mode.el --- A mode for SystemTap ;; Copyright (C) 2008 Tomoki Sekiyama ;; Copyright (C) 2012 Rüdiger Sonderfeld ;; Authors: 2008 Tomoki Sekiyama ;; 2012 Rüdiger Sonderfeld ;; Maintainer: ruediger@c-plusplus.de ;; Keywords: tools languages ;; Version: 0.02 ;; URL: https://github.com/ruediger/systemtap-mode ;; This file is NOT part of GNU Emacs. ;; 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; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Commentary: ;; This code is based on the original systemtap-mode.el written by ;; Tomoki Sekiyama. It can be found at ;; http://coderepos.org/share/browser/lang/elisp/systemtap-mode/systemtap-mode.el?format=txt ;; TODO: ;; - indent embedded-C %{ ... %} correctly ;; - add parameter for indentation ;; - ... ;;; Code: (defconst systemtap-mode-version "0.02" "SystemTap Mode version number.") (defgroup systemtap-mode nil "A mode for SystemTap." :prefix "systemtap-" :group 'tools :group 'languages) (require 'cc-mode) (require 'cc-awk) (eval-when-compile (require 'cc-langs) (require 'cc-fonts)) (eval-and-compile (c-add-language 'systemtap-mode 'awk-mode)) ;; Syntax definitions for SystemTap (c-lang-defconst c-primitive-type-kwds systemtap '("string" "long" "global")) (c-lang-defconst c-modifier-kwds systemtap (append '("probe" "function") (c-lang-const c-modifier-kwds))) (c-lang-defconst c-block-stmt-2-kwds systemtap '("else" "for" "foreach" "if" "while")) (c-lang-defconst c-simple-stmt-kwds systemtap '("break" "continue" "delete" "next" "return")) (c-lang-defconst c-identifier-syntax-modifications systemtap '((?. . "_") (?' . "."))) (defcustom systemtap-font-lock-extra-types nil "Font-lock extra types for SystemTap mode." :group 'systemtap-mode) (defconst systemtap-font-lock-keywords-1 (c-lang-const c-matchers-1 systemtap) "Minimal highlighting for SystemTap mode.") (defconst systemtap-font-lock-keywords-2 (c-lang-const c-matchers-2 systemtap) "Fast normal highlighting for SystemTap mode.") (defconst systemtap-font-lock-keywords-3 (c-lang-const c-matchers-3 systemtap) "Accurate normal highlighting for SystemTap mode.") (defvar systemtap-font-lock-keywords systemtap-font-lock-keywords-3 "Default expressions to highlight in SystemTap mode.") (defvar systemtap-mode-syntax-table nil "Syntax table used in systemtap-mode buffers.") (unless systemtap-mode-syntax-table (setq systemtap-mode-syntax-table (funcall (c-lang-const c-make-mode-syntax-table systemtap)))) (defvar systemtap-mode-abbrev-table nil "Abbreviation table used in systemtap-mode buffers.") (defvar systemtap-mode-map (let ((map (c-make-inherited-keymap))) (define-key map "\C-ce" 'systemtap-execute-script) (define-key map "\C-cc" 'systemtap-interrupt-script) map) "Keymap used in systemtap-mode buffers.") (easy-menu-define systemtap-menu systemtap-mode-map "SystemTap Mode Commands" (cons "SystemTap" (append '(["Execute This Script" systemtap-execute-script t] ["Interrupt Execution of Script" systemtap-interrupt-script (get-process "systemtap-script")] "----") (c-lang-const c-mode-menu systemtap)))) ;; Execution function of Current Script (defvar systemtap-buffer-name "*SystemTap*" "Name of the SystemTap execution buffer.") (defcustom systemtap-stap-program "stap" "SystemTap's stap program to execute scripts." :type 'file :group 'systemtap-mode) (defcustom systemtap-stap-options '("-v") "A list of options to give to stap." :type '(repeat string) :group 'systemtap-mode) (defun systemtap-execute-script () "Execute current SystemTap script." (interactive) (when (get-buffer systemtap-buffer-name) (kill-buffer systemtap-buffer-name)) (get-buffer-create systemtap-buffer-name) (display-buffer systemtap-buffer-name) (let* ((file-name (buffer-file-name)) (options (append systemtap-stap-options (list file-name)))) (apply #'start-process "systemtap-script" systemtap-buffer-name systemtap-stap-program options)) (message "Execution of SystemTap script started.")) (defun systemtap-interrupt-script () "Interrupt running SystemTap script." (interactive) (interrupt-process "systemtap-script") (message "SystemTap script is interrupted.")) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.stp\\'" . systemtap-mode)) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.stpm\\'" . systemtap-mode)) (require 'simple) ;;;###autoload ; prog-mode is newer than emacs 23 (define-derived-mode systemtap-mode fundamental-mode "SystemTap" "Major mode for editing SystemTap scripts. Key bindings: \\{systemtap-mode-map}" :group 'systemtap :syntax-table systemtap-mode-syntax-table :abbrev-table systemtap-mode-abbrev-table (c-initialize-cc-mode t) (use-local-map systemtap-mode-map) (c-init-language-vars systemtap-mode) (c-common-init 'systemtap-mode) (easy-menu-add systemtap-menu) (c-run-mode-hooks 'c-mode-common-hook) (c-update-modeline)) (provide 'systemtap-mode) ;;; systemtap-mode.el ends here systemtap-2.3/git_version.sh000077500000000000000000000267251217430427200163140ustar00rootroot00000000000000#!/bin/sh # # Generate some basic versioning information which can be piped to a header. # # Copyright (c) 2006-2007 Luc Verhaegen # Copyright (C) 2007 Hans Ulrich Niedermann # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. # # This script is based on the one written for xf86-video-unichrome by # Luc Verhaegen, but was rewritten almost completely by Hans Ulrich # Niedermann. The script contains a few bug fixes from Egbert Eich, # Matthias Hopf, Joerg Sonnenberger, and possibly others. # # The author thanks the nice people on #git for the assistance. # # Simple testing of this script: # /sbin/busybox sh git_version.sh --example > moo.c \ # && gcc -Wall -Wextra -Wno-unused -o moo moo.c \ # && ./moo # (bash should also do) # # For how to hook this up to your automake- and/or imake-based build # system, best take a look at how the RadeonHD.am and/or RadeonHD.tmpl # work in the xf86-video-radeonhd build system. For non-recursive make, # you can probably make things a little bit simpler. # # KNOWN BUGS: # * Uses hyphenated ("git-foo-bar") program names, which git upstream # have declared deprecated. # # Help messages USAGE="[
\n"; foreach $parameter (@{$args{'parameterlist'}}) { my $parameter_name = $parameter; $parameter_name =~ s/\[.*//; print " $parameter\n"; print " \n"; $lineprefix=" "; output_highlight($args{'parameterdescs'}{$parameter_name}); print " \n"; } print " \n"; } else { print " \n None\n \n"; } # print out each section $lineprefix=" "; foreach $section (@{$args{'sectionlist'}}) { print "\n $section\n"; if ($section =~ m/EXAMPLE/i) { print "\n"; } else { } print "\n"; output_highlight($args{'sections'}{$section}); print "\n"; if ($section =~ m/EXAMPLE/i) { print "\n"; } else { } print " \n"; } print "\n\n"; } ## # output function in man sub output_function_man(%) { my %args = %{$_[0]}; my ($parameter, $section); my $count; print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n"; print ".SH NAME\n"; print $args{'function'}." \\- ".$args{'purpose'}."\n"; print ".SH SYNOPSIS\n"; if ($args{'functiontype'} ne "") { print ".B \"".$args{'functiontype'}."\" ".$args{'function'}."\n"; } else { print ".B \"".$args{'function'}."\n"; } $count = 0; my $parenth = "("; my $post = ","; foreach my $parameter (@{$args{'parameterlist'}}) { if ($count == $#{$args{'parameterlist'}}) { $post = ");"; } $type = $args{'parametertypes'}{$parameter}; if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { # pointer-to-function print ".BI \"".$parenth.$1."\" ".$parameter." \") (".$2.")".$post."\"\n"; } else { $type =~ s/([^\*])$/$1 /; print ".BI \"".$parenth.$type."\" ".$parameter." \"".$post."\"\n"; } $count++; $parenth = ""; } print ".SH ARGUMENTS\n"; foreach $parameter (@{$args{'parameterlist'}}) { my $parameter_name = $parameter; $parameter_name =~ s/\[.*//; print ".IP \"".$parameter."\" 12\n"; output_highlight($args{'parameterdescs'}{$parameter_name}); } foreach $section (@{$args{'sectionlist'}}) { print ".SH \"", uc $section, "\"\n"; output_highlight($args{'sections'}{$section}); } } ## # output enum in man sub output_enum_man(%) { my %args = %{$_[0]}; my ($parameter, $section); my $count; print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n"; print ".SH NAME\n"; print "enum ".$args{'enum'}." \\- ".$args{'purpose'}."\n"; print ".SH SYNOPSIS\n"; print "enum ".$args{'enum'}." {\n"; $count = 0; foreach my $parameter (@{$args{'parameterlist'}}) { print ".br\n.BI \" $parameter\"\n"; if ($count == $#{$args{'parameterlist'}}) { print "\n};\n"; last; } else { print ", \n.br\n"; } $count++; } print ".SH Constants\n"; foreach $parameter (@{$args{'parameterlist'}}) { my $parameter_name = $parameter; $parameter_name =~ s/\[.*//; print ".IP \"".$parameter."\" 12\n"; output_highlight($args{'parameterdescs'}{$parameter_name}); } foreach $section (@{$args{'sectionlist'}}) { print ".SH \"$section\"\n"; output_highlight($args{'sections'}{$section}); } } ## # output struct in man sub output_struct_man(%) { my %args = %{$_[0]}; my ($parameter, $section); print ".TH \"$args{'module'}\" 9 \"".$args{'type'}." ".$args{'struct'}."\" \"$man_date\" \"API Manual\" LINUX\n"; print ".SH NAME\n"; print $args{'type'}." ".$args{'struct'}." \\- ".$args{'purpose'}."\n"; print ".SH SYNOPSIS\n"; print $args{'type'}." ".$args{'struct'}." {\n.br\n"; foreach my $parameter (@{$args{'parameterlist'}}) { if ($parameter =~ /^#/) { print ".BI \"$parameter\"\n.br\n"; next; } my $parameter_name = $parameter; $parameter_name =~ s/\[.*//; ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; $type = $args{'parametertypes'}{$parameter}; if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { # pointer-to-function print ".BI \" ".$1."\" ".$parameter." \") (".$2.")"."\"\n;\n"; } elsif ($type =~ m/^(.*?)\s*(:.*)/) { # bitfield print ".BI \" ".$1."\ \" ".$parameter.$2." \""."\"\n;\n"; } else { $type =~ s/([^\*])$/$1 /; print ".BI \" ".$type."\" ".$parameter." \""."\"\n;\n"; } print "\n.br\n"; } print "};\n.br\n"; print ".SH Members\n"; foreach $parameter (@{$args{'parameterlist'}}) { ($parameter =~ /^#/) && next; my $parameter_name = $parameter; $parameter_name =~ s/\[.*//; ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; print ".IP \"".$parameter."\" 12\n"; output_highlight($args{'parameterdescs'}{$parameter_name}); } foreach $section (@{$args{'sectionlist'}}) { print ".SH \"$section\"\n"; output_highlight($args{'sections'}{$section}); } } ## # output typedef in man sub output_typedef_man(%) { my %args = %{$_[0]}; my ($parameter, $section); print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n"; print ".SH NAME\n"; print "typedef ".$args{'typedef'}." \\- ".$args{'purpose'}."\n"; foreach $section (@{$args{'sectionlist'}}) { print ".SH \"$section\"\n"; output_highlight($args{'sections'}{$section}); } } sub output_blockhead_man(%) { my %args = %{$_[0]}; my ($parameter, $section); my $count; print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n"; foreach $section (@{$args{'sectionlist'}}) { print ".SH \"$section\"\n"; output_highlight($args{'sections'}{$section}); } } ## # output probe in man sub output_probe_man(%) { my %args = %{$_[0]}; my ($parameter, $section); } ## # output sfunction in man sub output_sfunction_man(%) { my %args = %{$_[0]}; my ($parameter, $section); } ## # output in text sub output_function_text(%) { my %args = %{$_[0]}; my ($parameter, $section); my $start; print "Name:\n\n"; print $args{'function'}." - ".$args{'purpose'}."\n"; print "\nSynopsis:\n\n"; if ($args{'functiontype'} ne "") { $start = $args{'functiontype'}." ".$args{'function'}." ("; } else { $start = $args{'function'}." ("; } print $start; my $count = 0; foreach my $parameter (@{$args{'parameterlist'}}) { $type = $args{'parametertypes'}{$parameter}; if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { # pointer-to-function print $1.$parameter.") (".$2; } else { print $type." ".$parameter; } if ($count != $#{$args{'parameterlist'}}) { $count++; print ",\n"; print " " x length($start); } else { print ");\n\n"; } } print "Arguments:\n\n"; foreach $parameter (@{$args{'parameterlist'}}) { my $parameter_name = $parameter; $parameter_name =~ s/\[.*//; print $parameter."\n\t".$args{'parameterdescs'}{$parameter_name}."\n"; } output_section_text(@_); } #output sections in text sub output_section_text(%) { my %args = %{$_[0]}; my $section; print "\n"; foreach $section (@{$args{'sectionlist'}}) { print "$section:\n\n"; output_highlight($args{'sections'}{$section}); } print "\n\n"; } # output enum in text sub output_enum_text(%) { my %args = %{$_[0]}; my ($parameter); my $count; print "Enum:\n\n"; print "enum ".$args{'enum'}." - ".$args{'purpose'}."\n\n"; print "enum ".$args{'enum'}." {\n"; $count = 0; foreach $parameter (@{$args{'parameterlist'}}) { print "\t$parameter"; if ($count != $#{$args{'parameterlist'}}) { $count++; print ","; } print "\n"; } print "};\n\n"; print "Constants:\n\n"; foreach $parameter (@{$args{'parameterlist'}}) { print "$parameter\n\t"; print $args{'parameterdescs'}{$parameter}."\n"; } output_section_text(@_); } # output typedef in text sub output_typedef_text(%) { my %args = %{$_[0]}; my ($parameter); my $count; print "Typedef:\n\n"; print "typedef ".$args{'typedef'}." - ".$args{'purpose'}."\n"; output_section_text(@_); } # output struct as text sub output_struct_text(%) { my %args = %{$_[0]}; my ($parameter); print $args{'type'}." ".$args{'struct'}." - ".$args{'purpose'}."\n\n"; print $args{'type'}." ".$args{'struct'}." {\n"; foreach $parameter (@{$args{'parameterlist'}}) { if ($parameter =~ /^#/) { print "$parameter\n"; next; } my $parameter_name = $parameter; $parameter_name =~ s/\[.*//; ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; $type = $args{'parametertypes'}{$parameter}; if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { # pointer-to-function print "\t$1 $parameter) ($2);\n"; } elsif ($type =~ m/^(.*?)\s*(:.*)/) { # bitfield print "\t$1 $parameter$2;\n"; } else { print "\t".$type." ".$parameter.";\n"; } } print "};\n\n"; print "Members:\n\n"; foreach $parameter (@{$args{'parameterlist'}}) { ($parameter =~ /^#/) && next; my $parameter_name = $parameter; $parameter_name =~ s/\[.*//; ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; print "$parameter\n\t"; print $args{'parameterdescs'}{$parameter_name}."\n"; } print "\n"; output_section_text(@_); } sub output_blockhead_text(%) { my %args = %{$_[0]}; my ($parameter, $section); foreach $section (@{$args{'sectionlist'}}) { print " $section:\n"; print " -> "; output_highlight($args{'sections'}{$section}); } } # output probe as text sub output_probe_text(%) { my %args = %{$_[0]}; my ($parameter); } # output sfunction as text sub output_sfunction_text(%) { my %args = %{$_[0]}; my ($parameter); } ## # generic output function for all types (function, struct/union, typedef, enum); # calls the generated, variable output_ function name based on # functype and output_mode sub output_declaration { no strict 'refs'; my $name = shift; my $functype = shift; my $func = "output_${functype}_$output_mode"; if (($function_only==0) || ( $function_only == 1 && defined($function_table{$name})) || ( $function_only == 2 && !defined($function_table{$name}))) { &$func(@_); $section_counter++; } } ## # generic output function - calls the right one based on current output mode. sub output_blockhead { no strict 'refs'; my $func = "output_blockhead_".$output_mode; &$func(@_); $section_counter++; } sub dump_probe($$) { my $x = shift; my $file = shift; @parameterlist = keys %parameterdescs; $declaration_name = $x; output_declaration($declaration_name, 'probe', {'probe' => $declaration_name, 'parameterlist' => \@parameterlist, 'module' => $modulename, 'parameterdescs' => \%parameterdescs, 'sectionlist' => \@sectionlist, 'sections' => \%sections, 'purpose' => $declaration_purpose }); } ## # takes a declaration (struct, union, enum, typedef) and # invokes the right handler. NOT called for functions. sub dump_declaration($$) { no strict 'refs'; my ($prototype, $file) = @_; my $func = "dump_".$decl_type; &$func(@_); } sub dump_union($$) { dump_struct(@_); } sub dump_struct($$) { my $x = shift; my $file = shift; if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) { $declaration_name = $2; my $members = $3; # ignore embedded structs or unions $members =~ s/{.*}//g; # ignore members marked private: $members =~ s/\/\*.*?private:.*?public:.*?\*\///gos; $members =~ s/\/\*.*?private:.*//gos; # strip comments: $members =~ s/\/\*.*?\*\///gos; create_parameterlist($members, ';', $file); output_declaration($declaration_name, 'struct', {'struct' => $declaration_name, 'module' => $modulename, 'parameterlist' => \@parameterlist, 'parameterdescs' => \%parameterdescs, 'parametertypes' => \%parametertypes, 'sectionlist' => \@sectionlist, 'sections' => \%sections, 'purpose' => $declaration_purpose, 'type' => $decl_type }); } else { print STDERR "Error(${file}:$.): Cannot parse struct or union!\n"; ++$errors; } } sub dump_enum($$) { my $x = shift; my $file = shift; $x =~ s@/\*.*?\*/@@gos; # strip comments. if ($x =~ /enum\s+(\w+)\s*{(.*)}/) { $declaration_name = $1; my $members = $2; foreach my $arg (split ',', $members) { $arg =~ s/^\s*(\w+).*/$1/; push @parameterlist, $arg; if (!$parameterdescs{$arg}) { $parameterdescs{$arg} = $undescribed; print STDERR "Warning(${file}:$.): Enum value '$arg' ". "not described in enum '$declaration_name'\n"; } } output_declaration($declaration_name, 'enum', {'enum' => $declaration_name, 'module' => $modulename, 'parameterlist' => \@parameterlist, 'parameterdescs' => \%parameterdescs, 'sectionlist' => \@sectionlist, 'sections' => \%sections, 'purpose' => $declaration_purpose }); } else { print STDERR "Error(${file}:$.): Cannot parse enum!\n"; ++$errors; } } sub dump_typedef($$) { my $x = shift; my $file = shift; $x =~ s@/\*.*?\*/@@gos; # strip comments. while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) { $x =~ s/\(*.\)\s*;$/;/; $x =~ s/\[*.\]\s*;$/;/; } if ($x =~ /typedef.*\s+(\w+)\s*;/) { $declaration_name = $1; output_declaration($declaration_name, 'typedef', {'typedef' => $declaration_name, 'module' => $modulename, 'sectionlist' => \@sectionlist, 'sections' => \%sections, 'purpose' => $declaration_purpose }); } else { print STDERR "Error(${file}:$.): Cannot parse typedef!\n"; ++$errors; } } sub create_parameterlist($$$) { my $args = shift; my $splitter = shift; my $file = shift; my $type; my $param; # temporarily replace commas inside function pointer definition while ($args =~ /(\([^\),]+),/) { $args =~ s/(\([^\),]+),/$1#/g; } foreach my $arg (split($splitter, $args)) { # strip comments $arg =~ s/\/\*.*\*\///; # strip leading/trailing spaces $arg =~ s/^\s*//; $arg =~ s/\s*$//; $arg =~ s/\s+/ /; if ($arg =~ /^#/) { # Treat preprocessor directive as a typeless variable just to fill # corresponding data structures "correctly". Catch it later in # output_* subs. push_parameter($arg, "", $file); } elsif ($arg =~ m/\(.+\)\s*\(/) { # pointer-to-function $arg =~ tr/#/,/; $arg =~ m/[^\(]+\(\*?\s*(\w*)\s*\)/; $param = $1; $type = $arg; $type =~ s/([^\(]+\(\*?)\s*$param/$1/; push_parameter($param, $type, $file); } elsif ($arg) { $arg =~ s/\s*:\s*/:/g; $arg =~ s/\s*\[/\[/g; my @args = split('\s*,\s*', $arg); if ($args[0] =~ m/\*/) { $args[0] =~ s/(\*+)\s*/ $1/; } my @first_arg; if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) { shift @args; push(@first_arg, split('\s+', $1)); push(@first_arg, $2); } else { @first_arg = split('\s+', shift @args); } unshift(@args, pop @first_arg); $type = join " ", @first_arg; foreach $param (@args) { if ($param =~ m/^(\*+)\s*(.*)/) { push_parameter($2, "$type $1", $file); } elsif ($param =~ m/(.*?):(\d+)/) { if ($type ne "") { # skip unnamed bit-fields push_parameter($1, "$type:$2", $file) } } else { push_parameter($param, $type, $file); } } } } } sub create_sparameterlist($$$) { my $args = shift; my $splitter = shift; my $file = shift; my $type; my $param; foreach my $arg (split($splitter, $args)) { if ($arg =~ m/\s*([\w]+)\s*:?\s*([\w]*)/) { $param = $1; $type = $2; push_parameter($param, $type, $file); } else { print STDERR "Error(${file}:$.): problem parsing parameters: '$prototype'\n"; ++$errors; return; } } } sub push_parameter($$$) { my $param = shift; my $type = shift; my $file = shift; if (($anon_struct_union == 1) && ($type eq "") && ($param eq "}")) { return; # ignore the ending }; from anon. struct/union } $anon_struct_union = 0; my $param_name = $param; $param_name =~ s/\[.*//; if ($type eq "" && $param =~ /\.\.\.$/) { $type=""; $parameterdescs{$param} = "variable arguments"; } elsif ($type eq "" && ($param eq "" or $param eq "void")) { $type=""; $param="void"; $parameterdescs{void} = "no arguments"; } elsif ($type eq "" && ($param eq "struct" or $param eq "union")) # handle unnamed (anonymous) union or struct: { $type = $param; $param = "{unnamed_" . $param . "}"; $parameterdescs{$param} = "anonymous\n"; $anon_struct_union = 1; } # warn if parameter has no description # (but ignore ones starting with # as these are not parameters # but inline preprocessor statements); # also ignore unnamed structs/unions; if (!$anon_struct_union) { if (!defined $parameterdescs{$param_name} && $param_name !~ /^#/) { $parameterdescs{$param_name} = $undescribed; if (($type eq 'function') || ($type eq 'enum')) { print STDERR "Warning(${file}:$.): Function parameter ". "or member '$param' not " . "described in '$declaration_name'\n"; } print STDERR "Warning(${file}:$.):". " No description found for parameter '$param'\n"; ++$warnings; } } push @parameterlist, $param; $parametertypes{$param} = $type; } ## # takes a function prototype and the name of the current file being # processed and spits out all the details stored in the global # arrays/hashes. sub dump_function($$) { my $prototype = shift; my $file = shift; $prototype =~ s/^static +//; $prototype =~ s/^extern +//; $prototype =~ s/^asmlinkage +//; $prototype =~ s/^inline +//; $prototype =~ s/^__inline__ +//; $prototype =~ s/^__inline +//; $prototype =~ s/^__always_inline +//; $prototype =~ s/^noinline +//; $prototype =~ s/__devinit +//; $prototype =~ s/__init +//; $prototype =~ s/^#\s*define\s+//; #ak added $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//; # Yes, this truly is vile. We are looking for: # 1. Return type (may be nothing if we're looking at a macro) # 2. Function name # 3. Function parameters. # # All the while we have to watch out for function pointer parameters # (which IIRC is what the two sections are for), C types (these # regexps don't even start to express all the possibilities), and # so on. # # If you mess with these regexps, it's a good idea to check that # the following functions' documentation still comes out right: # - parport_register_device (function pointer parameters) # - atomic_set (macro) # - pci_match_device, __copy_to_user (long return type) if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s*\*\s*\w+\s*\*\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) { $return_type = $1; $declaration_name = $2; my $args = $3; create_parameterlist($args, ',', $file); } else { print STDERR "Error(${file}:$.): cannot understand prototype: '$prototype'\n"; ++$errors; return; } output_declaration($declaration_name, 'function', {'function' => $declaration_name, 'module' => $modulename, 'functiontype' => $return_type, 'parameterlist' => \@parameterlist, 'parameterdescs' => \%parameterdescs, 'parametertypes' => \%parametertypes, 'sectionlist' => \@sectionlist, 'sections' => \%sections, 'purpose' => $declaration_purpose }); } ## # takes a stap function prototype and the name of the current file being # processed and spits out all the details stored in the global # arrays/hashes. sub dump_sfunction($$) { my $prototype = shift; my $file = shift; if ($prototype =~ m/^function\s+([\w]+)\s*:?\s*([\w]*)\s*\(([^\{]*)\)/) { $declaration_name = $1; $return_type = $2; my $args = $3; create_sparameterlist($args, ',', $file); } else { print STDERR "Error(${file}:$.): cannot understand prototype: '$prototype'\n"; ++$errors; return; } output_declaration($declaration_name, 'sfunction', {'sfunction' => $declaration_name, 'module' => $modulename, 'functiontype' => $return_type, 'parameterlist' => \@parameterlist, 'parameterdescs' => \%parameterdescs, 'parametertypes' => \%parametertypes, 'sectionlist' => \@sectionlist, 'sections' => \%sections, 'purpose' => $declaration_purpose }); } sub process_file($); # Read the file that maps relative names to absolute names for # separate source and object directories and for shadow trees. if (open(SOURCE_MAP, "<.tmp_filelist.txt")) { my ($relname, $absname); while() { chop(); ($relname, $absname) = (split())[0..1]; $relname =~ s:^/+::; $source_map{$relname} = $absname; } close(SOURCE_MAP); } if ($filelist) { open(FLIST,"<$filelist") or die "Can't open file list $filelist"; while() { chop; process_file($_); } } foreach (@ARGV) { chomp; process_file($_); } if ($verbose && $errors) { print STDERR "$errors errors\n"; } if ($verbose && $warnings) { print STDERR "$warnings warnings\n"; } exit($errors); sub reset_state { $function = ""; %constants = (); %parameterdescs = (); %parametertypes = (); @parameterlist = (); %sections = (); @sectionlist = (); $prototype = ""; $state = 0; } sub process_state3_function($$) { my $x = shift; my $file = shift; $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#\s*define/)) { # do nothing } elsif ($x =~ /([^\{]*)/) { $prototype .= $1; } if (($x =~ /\{/) || ($x =~ /\#\s*define/) || ($x =~ /;/)) { $prototype =~ s@/\*.*?\*/@@gos; # strip comments. $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's. $prototype =~ s@^\s+@@gos; # strip leading spaces dump_function($prototype,$file); reset_state(); } } sub process_state3_type($$) { my $x = shift; my $file = shift; $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's. $x =~ s@^\s+@@gos; # strip leading spaces $x =~ s@\s+$@@gos; # strip trailing spaces $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line if ($x =~ /^#/) { # To distinguish preprocessor directive from regular declaration later. $x .= ";"; } while (1) { if ( $x =~ /([^{};]*)([{};])(.*)/ ) { $prototype .= $1 . $2; ($2 eq '{') && $brcount++; ($2 eq '}') && $brcount--; if (($2 eq ';') && ($brcount == 0)) { dump_declaration($prototype,$file); reset_state(); last; } $x = $3; } else { $prototype .= $x; last; } } } sub process_state3_sfunction($$) { my $x = shift; my $file = shift; $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#\s*define/)) { # do nothing } elsif ($x =~ /([^\{]*)/) { $prototype .= $1; } $prototype =~ s@/\*.*?\*/@@gos; # strip comments. $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's. $prototype =~ s@^\s+@@gos; # strip leading spaces dump_sfunction($prototype,$file); reset_state(); } sub process_state3_probe($$) { my $prototype = shift; my $file = shift; $prototype =~ s@probe@@o; # strip off leading 'probe' $prototype =~ s@^\s+@@gos; # strip leading spaces dump_probe($prototype,$file); reset_state(); } # xml_escape: replace <, >, and & in the text stream; # # however, formatting controls that are generated internally/locally in the # kernel-doc script are not escaped here; instead, they begin life like # $blankline_html (4 of '\' followed by a mnemonic + ':'), then these strings # are converted to their mnemonic-expected output, without the 4 * '\' & ':', # just before actual output; (this is done by local_unescape()) sub xml_escape($) { my $text = shift; if (($output_mode eq "text") || ($output_mode eq "man")) { return $text; } $text =~ s/\&/\\\\\\amp;/g; $text =~ s/\/\\\\\\gt;/g; return $text; } # convert local escape strings to html # local escape strings look like: '\\\\menmonic:' (that's 4 backslashes) sub local_unescape($) { my $text = shift; if (($output_mode eq "text") || ($output_mode eq "man")) { return $text; } $text =~ s/\\\\\\\\lt://g; return $text; } sub process_file($) { my $file; my $identifier; my $func; my $descr; my $initial_section_counter = $section_counter; if (defined($ENV{'SRCTREE'})) { $file = "$ENV{'SRCTREE'}" . "/" . "@_"; } else { $file = "@_"; } if (defined($source_map{$file})) { $file = $source_map{$file}; } if (!open(IN,"<$file")) { print STDERR "Error: Cannot open file $file\n"; ++$errors; return; } $section_counter = 0; while () { if ($state == 0) { if (/$doc_start/o) { $state = 1; # next line is always the function name $in_doc_sect = 0; } } elsif ($state == 1) { # this line is the function name (always) if (/$doc_block/o) { $state = 4; $contents = ""; if ( $1 eq "" ) { $section = $section_intro; } else { $section = $1; } } elsif (/$doc_decl/o) { $identifier = $1; if (/\s*([\w\s\.]+?)\s*-/) { $identifier = $1; } $state = 2; if (/-(.*)/) { # strip leading/trailing/multiple spaces $descr= $1; $descr =~ s/^\s*//; $descr =~ s/\s*$//; $descr =~ s/\s+/ /; $declaration_purpose = xml_escape($descr); } else { $declaration_purpose = ""; } if (($declaration_purpose eq "") && $verbose) { print STDERR "Warning(${file}:$.): missing initial short description on line:\n"; print STDERR $_; ++$warnings; } if ($identifier =~ m/^struct/) { $decl_type = 'struct'; } elsif ($identifier =~ m/^union/) { $decl_type = 'union'; } elsif ($identifier =~ m/^enum/) { $decl_type = 'enum'; } elsif ($identifier =~ m/^typedef/) { $decl_type = 'typedef'; } elsif ($identifier =~ m/^probe/) { $decl_type = 'probe'; } elsif ($identifier =~ m/^sfunction/) { $decl_type = 'sfunction'; } else { $decl_type = 'function'; } if ($verbose) { print STDERR "Info(${file}:$.): Scanning doc for $decl_type $identifier\n"; } } else { print STDERR "Warning(${file}:$.): Cannot understand $_ on line $.", " - I thought it was a doc line\n"; ++$warnings; $state = 0; } } elsif ($state == 2) { # look for head: lines, and include content if (/$doc_sect/o) { $newsection = $1; $newcontents = $2; if (($contents ne "") && ($contents ne "\n")) { if (!$in_doc_sect && $verbose) { print STDERR "Warning(${file}:$.): contents before sections\n"; ++$warnings; } dump_section($file, $section, xml_escape($contents)); $section = $section_default; } $in_doc_sect = 1; $contents = $newcontents; if ($contents ne "") { while ((substr($contents, 0, 1) eq " ") || substr($contents, 0, 1) eq "\t") { $contents = substr($contents, 1); } $contents .= "\n"; } $section = $newsection; } elsif (/$doc_end/) { if ($contents ne "") { dump_section($file, $section, xml_escape($contents)); $section = $section_default; $contents = ""; } # look for doc_com + + doc_end: if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') { print STDERR "Warning(${file}:$.): suspicious ending line: $_"; ++$warnings; } $prototype = ""; $state = 3; $brcount = 0; # print STDERR "end of doc comment, looking for prototype\n"; } elsif (/$doc_content/) { # miguel-style comment kludge, look for blank lines after # @parameter line to signify start of description if ($1 eq "" && ($section =~ m/^@/ || $section eq $section_context)) { dump_section($file, $section, xml_escape($contents)); $section = $section_default; $contents = ""; } else { $contents .= $1."\n"; } } else { # i dont know - bad line? ignore. print STDERR "Warning(${file}:$.): bad line: $_"; ++$warnings; } } elsif ($state == 3) { # scanning for function '{' (end of prototype) if ($decl_type eq 'function') { process_state3_function($_, $file); } elsif ($decl_type eq 'probe') { process_state3_probe($identifier, $file); } elsif ($decl_type eq 'sfunction') { process_state3_sfunction($_, $file); } else { process_state3_type($_, $file); } } elsif ($state == 4) { # Documentation block if (/$doc_block/) { dump_doc_section($file, $section, xml_escape($contents)); $contents = ""; $function = ""; %constants = (); %parameterdescs = (); %parametertypes = (); @parameterlist = (); %sections = (); @sectionlist = (); $prototype = ""; if ( $1 eq "" ) { $section = $section_intro; } else { $section = $1; } } elsif (/$doc_end/) { dump_doc_section($file, $section, xml_escape($contents)); $contents = ""; $function = ""; %constants = (); %parameterdescs = (); %parametertypes = (); @parameterlist = (); %sections = (); @sectionlist = (); $prototype = ""; $state = 0; } elsif (/$doc_content/) { if ( $1 eq "" ) { $contents .= $blankline; } else { $contents .= $1 . "\n"; } } } } if ($initial_section_counter == $section_counter) { print STDERR "Warning(${file}): no structured comments found\n"; if ($output_mode eq "xml") { # The template wants at least one RefEntry here; make one. print "\n"; print " \n"; print " \n"; print " ${file}\n"; print " \n"; print " \n"; print " Document generation inconsistency\n"; print " \n"; print " \n"; print " \n"; print " \n"; print " Oops\n"; print " \n"; print " \n"; print " \n"; print " The template for this document tried to insert\n"; print " the structured comment from the file\n"; print " ${file} at this point,\n"; print " but none was found.\n"; print " This dummy section is inserted to allow\n"; print " generation to continue.\n"; print " \n"; print " \n"; print " \n"; print "\n"; } } } systemtap-2.3/scripts/kprobes_test/000077500000000000000000000000001217430427200176045ustar00rootroot00000000000000systemtap-2.3/scripts/kprobes_test/.gitignore000066400000000000000000000002251217430427200215730ustar00rootroot00000000000000*~ *.pyc .kprobe* *.log Module.symvers Module.markers kprobe_module.ko* kprobe_module.mod.c modules.order .tmp_versions probes.* kprobe_defs.h *.cfg systemtap-2.3/scripts/kprobes_test/README000066400000000000000000000047601217430427200204730ustar00rootroot00000000000000Here are the original instructions for 'gen_whitelist', which tested systemtap probe safety. This modified code tests the underlying kprobes themselves. To start a kprobes test run: runtest whitelist.exp ---- Here is an implementation of generating whitelist for safe-mode probes based on the discussion in former thread (http://sourceware.org/ml/systemtap/2006-q3/msg00574.html). Its main idea is: 1) Fetch a group of probe points from probes.pending, probe them and run some workloads(e.g. runltp) parallely meanwhile. 2) If the probe test ends without crash, those actually triggered probe points are moved into probes.passed and those untriggered are into probes.untriggered; If the probe test crashes the system, it will be resumed automatically after system reboot. Those probe points which have been triggered are also moved into probes.passed, but those untriggered ones are moved into probes.failed. 3) Repeat the above until probes.pending becomes empty, then: Normally, probes.pending is reinitialized from probes.failed and probes.untriggered, then start the next iteration; But if max running level (now 3) is reached, or probes.pending, probes.failed and probes.untriggered are all empty, stop the whole test. To be able to resume after a crash, this test will append its startup codes to the end of /etc/rc.d/rc.local at the beginning and remove them at the end of the test. The gen_tapset_all.sh is used to generate a "probes.all" file based on current tapset of systemtap. It is suggested to use a script in a remote server to restart the test machine automatically in case it is crashed by the probe test. Instructions: 0) Please jump to 6) directly if you use all default settings 1) Define your list of probe points in a file named "probes.all"; otherwise, it will be automatically extracted from stap -p2 -e 'probe kernel.function("*"){} 2) Define your own workloads by changing the "benchs" list variable; otherwise, several LTP testcases will be used 3) Define how may times you want the test to be iterated by changing MAX_RUNNING_LEVEL variable; otherwise, 3 is the default 4) Define the group size for different iteration level by changing proper_current_size() function; otherwise, they will be set in a decreasing order based on the length of probes.all 5) Remove /stp_genwhitelist_running if you want to start a test from the beginning after a system crash 6) Start a test: runtest whitelist.exp systemtap-2.3/scripts/kprobes_test/config_opts.py000066400000000000000000000045341217430427200224760ustar00rootroot00000000000000# Copyright (C) 2008, 2010 Red Hat Inc. # # This file is part of systemtap, and is free software. You can # redistribute it and/or modify it under the terms of the GNU General # Public License (GPL); either version 2, or (at your option) any # later version. import os import sys # Here we set up the default config options. These can be overridden # by the config file. config_opts = dict() # # Various file names # # PROBES_ALL is the file that contains the full list of kernel # functions to test. If it doesn't exist, it can be created by # readelf.py with a list of all kernel functions. config_opts['probes_all'] = 'probes.all' # PROBES_UNREGISTERED is a file that contains the list of kernel # functions where a kprobe couldn't be registered. config_opts['probes_unregistered'] = 'probes.unregistered' # PROBES_UNTRIGGERED is a file that contains the list of kernel # functions where a kprobe could be registered, but the kernel # function wasn't actually called. So, we don't really know whether # these functions passed or failed. config_opts['probes_untriggered'] = 'probes.untriggered' # PROBES_PASSED is a file that contains the list of kernel functions # where a kprobe was registered and the kerenel function was called # with no crash. config_opts['probes_passed'] = 'probes.passed' # PROBES_FAILED is a file that contains the list of kernel functions # where a kprobe was registered and the kerenel function was called # that caused a crash. config_opts['probes_failed'] = 'probes.failed' # PROBES_CURRENT is a file that contains the list of kernel functions # we're about to test. config_opts['probes_current'] = 'probes.current' # PROBES_RESULT is a file that contains the results of the current # test. config_opts['probes_result'] = 'probe.out' # PROBES_DB is a file that contains the current state (in python # 'pickled' format). config_opts['probes_db'] = 'probes.db' # LOG_FILE is the file that contains the testing log output. config_opts['log_file'] = 'kprobes_test.log' # RCLOCAL is the file we need to edit to get the test to automatically # run after a reboot. config_opts['rclocal'] = '/etc/rc.d/rc.local' # Read in the config file print "Reading config file..." cfg = os.path.join(os.getcwd(), 'default.cfg') if os.path.exists(cfg): execfile(cfg) else: print >>sys.stderr, ("Could not find required config file: %s" % cfg) sys.exit(1) systemtap-2.3/scripts/kprobes_test/default.cfg000066400000000000000000000013461217430427200217150ustar00rootroot00000000000000# -*-python-*- # Commands to run to generate a system load config_opts['load_cmds'] = [ [ '/usr/local/ltp/runltp', '-t', '600s', '-f', 'syscalls', ], # [ '/usr/local/ltp/runltp', '-t', '600s', '-f', 'nfs', ], # [ '/usr/local/ltp/runltp', '-t', '600s', '-f', 'rpc', ], [ '/usr/local/ltp/runltp', '-t', '600s', '-f', 'ipc', ], [ '/usr/local/ltp/runltp', '-t', '600s', '-f', 'dio', ], [ '/usr/local/ltp/runltp', '-t', '600s', '-f', 'fs', ], [ '/usr/local/ltp/runltp', '-t', '600s', '-f', 'mm', ], [ '/usr/local/ltp/runltp', '-t', '600s', '-f', 'tcp_cmds', ], # [ '/usr/local/ltp/runltp', '-t', '600s', '-f', 'ltp-aio-stress.part1', ], [ '/usr/local/ltp/runltp', '-t', '600s', '-f', 'lvm.part1' ], ] systemtap-2.3/scripts/kprobes_test/gen_code.py000077500000000000000000000045531217430427200217330ustar00rootroot00000000000000#!/usr/bin/python # Copyright (C) 2008, 2010 Red Hat Inc. # # This file is part of systemtap, and is free software. You can # redistribute it and/or modify it under the terms of the GNU General # Public License (GPL); either version 2, or (at your option) any # later version. import os import sys from config_opts import config_opts def gen_files(dir, subset): f = open('%s/kprobe_defs.h' % dir, 'w') # Output the array of kp_data structs print >>f, "static struct kp_data kp_data[] = {" i = 0 while i < len(subset): print >>f, ("\t{ .kp={ .symbol_name=\"%s\", .pre_handler=&handler_pre, }, .use_count=ATOMIC_INIT(0) }," % (subset[i])) i += 1 print >>f, "};" print >>f f.close() # Generate the Makefile f = open('Makefile', 'w') print >>f, """ EXTRA_CFLAGS := EXTRA_CFLAGS += -freorder-blocks EXTRA_CFLAGS += -Wno-unused -Werror obj-m := kprobe_module.o""" f.close() def run_make_cmd(cmd): # Before running make, fix up the environment a bit. Clean out a # few variables that /lib/modules/${KVER}/build/Makefile uses. os.unsetenv("ARCH") os.unsetenv("KBUILD_EXTMOD") os.unsetenv("CROSS_COMPILE") os.unsetenv("KBUILD_IMAGE") os.unsetenv("KCONFIG_CONFIG") os.unsetenv("INSTALL_PATH"); print "Running", cmd return os.system(cmd) def gen_module(): f = open(config_opts['probes_current']) probes = f.readlines() f.close() if len(probes) == 0: print >>sys.stderr, ("Error: no probe points in %s" % config_opts['probes_current']) return -1 # Cleanup each probe by stripping whitespace i = 0 while i < len(probes): probes[i] = probes[i].rstrip() i += 1 # Generate necessary files gen_files(os.getcwd(), probes) # Try to build the module - add "V=1" at the end for more verbosity os.system('rm -f ./kprobe_module.ko') (sysname, nodename, release, version, machine) = os.uname() cmd = ("make -C \"/lib/modules/%s/build\" M=\"%s\" modules CONFIG_MODULE_SIG=n >build.log 2>&1" % (release, os.getcwd())) rc = run_make_cmd(cmd) if os.WEXITSTATUS(rc) != 0: print >>sys.stderr, "Error: Make failed, see build.log for details" return -1 return 0 def main(): rc = gen_module() sys.exit(rc) if __name__ == "__main__": main() systemtap-2.3/scripts/kprobes_test/gen_code_all.sh000077500000000000000000000005371217430427200225430ustar00rootroot00000000000000#! /bin/sh set -e echo "Generating list of all kernel functions from /proc/kallsyms" grep ' [tT] ' /proc/kallsyms | fgrep -v '[' | awk '{print $3}' > probes.current echo "Found `wc -l < probes.current` of them: see probes.current" echo "Compiling module" python gen_code.py ls -al kprobe_module.ko echo "Run insmod kprobe_module.ko, if you dare." systemtap-2.3/scripts/kprobes_test/is_probed.py000077500000000000000000000033351217430427200221330ustar00rootroot00000000000000#!/usr/bin/python # Copyright (C) 2008, 2010 Red Hat Inc. # # This file is part of systemtap, and is free software. You can # redistribute it and/or modify it under the terms of the GNU General # Public License (GPL); either version 2, or (at your option) any # later version. import re import sys import os from config_opts import config_opts def parse_module_output(): # Parse the output file, looking for probe points pp_re = re.compile(": (-?\d+) (\S+)$") f = open(config_opts['probes_result'], 'r') pp = dict() line = f.readline() while line: match = pp_re.search(line) if match: pp[match.group(2)] = int(match.group(1)) line = f.readline() f.close() if len(pp.keys()) == 0: print >>sys.stderr, "No data found?" return 1 # Parse the list of probe points. f = open(config_opts['probes_current'], 'r') passed = open(config_opts['probes_passed'], 'a') failed = open(config_opts['probes_failed'], 'a') untriggered = open(config_opts['probes_untriggered'], 'a') unregistered = open(config_opts['probes_unregistered'], 'a') line = f.readline().strip() while line: if pp.has_key(line): if pp[line] > 0: passed.write(line + '\n') elif pp[line] == 0: untriggered.write(line + '\n') elif pp[line] == -1: unregistered.write(line + '\n') else: failed.write(line + '\n') line = f.readline().strip() f.close() passed.close() failed.close() untriggered.close() unregistered.close() return 0 def main(): rc = parse_module_output() sys.exit(rc) if __name__ == "__main__": main() systemtap-2.3/scripts/kprobes_test/kprobe_module.c000066400000000000000000000027351217430427200226060ustar00rootroot00000000000000#include #include #include struct kp_data { struct kprobe kp; atomic_t use_count; }; static int handler_pre(struct kprobe *p, struct pt_regs *regs); #include "kprobe_defs.h" /* kprobe pre_handler: called just before the probed instruction is executed */ static int handler_pre(struct kprobe *p, struct pt_regs *regs) { struct kp_data *k = container_of(p, struct kp_data, kp); atomic_inc(&k->use_count); return 0; } static int __init kprobe_init(void) { int ret; int probes_registered = 0; int i; for (i = 0; i < ARRAY_SIZE(kp_data); i++) { ret = register_kprobe(&kp_data[i].kp); if (ret != 0) atomic_set(&kp_data[i].use_count, -1); else probes_registered++; } if (probes_registered == 0) { for (i = 0; i < ARRAY_SIZE(kp_data); i++) { printk(KERN_INFO "-1 %s\n", kp_data[i].kp.symbol_name); } printk(KERN_INFO "kprobe_module unloaded\n"); return ret; } printk(KERN_INFO "Planted kprobes\n"); return 0; } static void __exit kprobe_exit(void) { int i; for (i = 0; i < ARRAY_SIZE(kp_data); i++) { if (atomic_read(&kp_data[i].use_count) != -1) unregister_kprobe(&kp_data[i].kp); } printk(KERN_INFO "kprobes unregistered\n"); for (i = 0; i < ARRAY_SIZE(kp_data); i++) { printk(KERN_INFO "%d %s\n", atomic_read(&kp_data[i].use_count), kp_data[i].kp.symbol_name); } printk(KERN_INFO "kprobe_module unloaded\n"); } module_init(kprobe_init) module_exit(kprobe_exit) MODULE_LICENSE("GPL"); systemtap-2.3/scripts/kprobes_test/kprobes_test.py000077500000000000000000000461661217430427200227020ustar00rootroot00000000000000#!/usr/bin/python # Copyright (C) 2010 Red Hat Inc. # # This file is part of systemtap, and is free software. You can # redistribute it and/or modify it under the terms of the GNU General # Public License (GPL); either version 2, or (at your option) any # later version. import os import pickle import re import sys import time from config_opts import config_opts from gen_code import gen_module from run_module import run_module class BucketSet(object): def __init__(self, bucketA=list(), bucketA_result=0, bucketB=list(), bucketB_result=0, buckets=list(), passed=list(), failed=list(), untriggered=list(), unregistered=list(), split=0): # bucketA is the list of probes to test. self.bucketA = bucketA # bucketA_result tells us what state bucketA is in self.bucketA_result = bucketA_result # bucketB is the 2nd (optional) list of probes to test self.bucketB = bucketB # bucketB_result tells us what state bucketB is in self.bucketB_result = bucketB_result # buckets is the full list of probes to test (originally # filled in by reading config_opts['probes_all']) self.buckets = buckets # passed is the list of probe points that were sucessfully # registered and triggered (actually called) self.passed = passed # failed is the list of probe points that were sucessfully # registered but caused a crash. The probe lists have been # bisected and singly eliminated. self.failed = failed # untriggered is the list of probe points that were sucessfully # registered and but never triggered (actually called) self.untriggered = untriggered # untriggered is the list of probe points that couldn't be # registered self.unregistered = unregistered # split tells us how to split a bucket. 0 means bisect # it, anything else is the number of times we've tried to do a # 1-by-1 split. self.split = split def bucketA_result_str(self): if self.bucketA_result == 0: return "untested" elif self.bucketA_result == 1: return "succeeded" elif self.bucketA_result == 2: return "failed" else: return "UNKNOWN" def bucketB_result_str(self): if self.bucketB_result == 0: return "untested" elif self.bucketB_result == 1: return "succeeded" elif self.bucketB_result == 2: return "failed" else: return "UNKNOWN" probes = BucketSet() # Install this script in config_opts['rclocal'] (typically # /etc/rc.d/rc.local). Returns true if the line wasn't already there # (which means this is the 1st time the script has been run). def register_script(install=True): rc = True regexp = re.compile("^.+/kprobes_test.py") f = open(config_opts['rclocal'], "r+") data = "" for line in f: if not regexp.match(line): data += line else: rc = False if install: data += "cd %s/ && ./kprobes_test.py &" % os.getcwd() f.seek(0, 0) f.write(data) f.truncate(f.tell()) f.close() return rc # Because it is very possible that we'll crash the system, we need to # make sure our data files are written to the disk sucessfully before # we run a module. sync_disks() makes sure everything written is # actually saved. def sync_disks(): os.system("sync; sync; sync") time.sleep(5) return def read_probe_list(): global probes # If the "pickled" file exists, read it in to recover our state if os.path.exists(config_opts['probes_db']): print "Reading state..." f = open(config_opts['probes_db']) p = pickle.Unpickler(f) probes = p.load() f.close() # if the 'probes_all' file exists, create the data from it elif os.path.exists(config_opts['probes_all']): # Read in the flat file f = open(config_opts['probes_all']) probe_lines = f.readlines() f.close() # Create the full bucket full_bucket = list() for line in probe_lines: full_bucket.append(line.rstrip()) probes.buckets.append(full_bucket) # create the probes_all file? else: print >>sys.stderr, ("Could not find probes file") sys.exit(1) def write_probe_list(): global probes print "Writing state..." f = open(config_opts['probes_db'], 'w') p = pickle.Pickler(f) p.dump(probes) f.close() def display_probe_list(): global probes i = 0 print "bucketA (%s) has %d entries" % \ (probes.bucketA_result_str(), len(probes.bucketA)) print "bucketB (%s) has %d entries" % \ (probes.bucketB_result_str(), len(probes.bucketB)) for bucket in probes.buckets: print "set %d has %d entries" % (i, len(bucket)) i += 1 print "passed set has %d entries" % len(probes.passed) total = 0 for bucket in probes.failed: total += len(bucket) print "failed set has %d entries (in %d buckets)" % \ (total, len(probes.failed)) print "untriggered set has %d entries" % len(probes.untriggered) print "unregistered set has %d entries" % len(probes.unregistered) def reset_buckets(): global probes probes.bucketA = list() probes.bucketA_result = 0 probes.bucketB = list() probes.bucketB_result = 0 probes.split = 0 def grab_bucket(): global probes reset_buckets() # Try to grab the 1st bucket from the list. if len(probes.buckets) > 0: bucket = probes.buckets[0] del probes.buckets[0] # if the bucket has more than 1000 probes, limit it to 1000 if len(bucket) > 1000: probes.bucketA = bucket[0:1000] probes.bucketA_result = 0 probes.bucketB_result = 0 rest = bucket[1000:] probes.buckets.insert(0, rest) # otherwise just use the bucket else: probes.bucketA = bucket return True else: print "no buckets left" return False def split_bucket(bucket): global probes if probes.split == 0: split = len(bucket) / 2 else: split = 1 bucketA = bucket[0:split] bucketB = bucket[split:] probes.bucketA = bucketA probes.bucketA_result = 0 probes.bucketB = bucketB probes.bucketB_result = 0 def update_buckets(failed=True): global probes ret = True # if we don't have a current set, get one if len(probes.bucketA) == 0: ret = grab_bucket() # if bucketA is set, we've just finished up with it (or bucketB). elif len(probes.bucketA) > 0: if probes.bucketA_result == 0: if not failed: probes.bucketA_result = 1 else: probes.bucketA_result = 2 print "bucketA %s with %d probes..." % \ (probes.bucketA_result_str(), len(probes.bucketA)) else: if not failed: probes.bucketB_result = 1 else: probes.bucketB_result = 2 print "bucketB %s with %d probes..." % \ (probes.bucketB_result_str(), len(probes.bucketB)) # OK, we've got several cases here. # (1) Only bucketA was set. if len(probes.bucketB) == 0: print "case (1)..." # (1a) If bucketA passed, put it on the passed list and grab # the next bucket. if not failed: probes.passed.extend(probes.bucketA) probes.split = 0 ret = grab_bucket() # (1b) If bucketA failed and is more than 1 probe, split it. elif len(probes.bucketA) > 1: split_bucket(probes.bucketA) # (1c) if bucketA failed and was only 1 probe, put it on # the failed list and grab the next bucket. else: probes.failed.append(probes.bucketA) ret = grab_bucket() # (2) Both bucketA and bucketB were set, but bucketB hasn't # been tested yet. elif probes.bucketB_result == 0: # Do nothing and let bucketB be tested. print "case (2)..." pass # (3) Both bucketA and bucketB have been tested. Figure out # what to do next. else: print "case (3)..." # (3a) bucketA passed, bucketB failed. Move bucketA to # the passed list and split bucketB. if probes.bucketA_result == 1 and probes.bucketB_result == 2: print "case (3a)..." probes.passed.extend(probes.bucketA) probes.split = 0 # (3a1) If bucketB failed and is more than 1 probe, # split it. if len(probes.bucketB) > 1: split_bucket(probes.bucketB) # (3a2) If bucketB failed and was only 1 probe, put it # on the failed list and grab the next bucket. else: probes.failed.append(probes.bucketB) ret = grab_bucket() # (3b) bucketA failed, bucketB passed. Move bucketB to # the passed list and split bucketA. elif probes.bucketA_result == 2 and probes.bucketB_result == 1: print "case (3b)..." probes.passed.extend(probes.bucketB) probes.split = 0 # (3b1) If bucketA failed and is more than 1 probe, # split it. if len(probes.bucketA) > 1: split_bucket(probes.bucketA) # (3b2) If bucketA failed and was only 1 probe, put it # on the failed list and grab the next bucket. else: probes.failed.append(probes.bucketA) ret = grab_bucket() # (3c) Both buckets failed. elif probes.bucketA_result == 2 and probes.bucketB_result == 2: print "case (3c)..." # (3c1) bucketA and bucketB were both just 1 probe # each. Put them both on the failed list and grab the # next bucket. if len(probes.bucketA) == 1 and len(probes.bucketB) == 1: print "case (3c1)..." probes.failed.append(probes.bucketA) probes.failed.append(probes.bucketB) ret = grab_bucket() # (3c2) bucketA was just 1 probe, but bucketB was more # than 1 probe elif len(probes.bucketA) == 1 and len(probes.bucketB) > 1: print "case (3c2)..." probes.failed.append(probes.bucketA) split_bucket(probes.bucketB) # (3c3) bucketA was more than 1 probe, but bucketB was # just 1 probe elif len(probes.bucketA) > 1 and len(probes.bucketB) == 1: print "case (3c3)..." probes.failed.append(probes.bucketB) split_bucket(probes.bucketA) # (3c4) Both buckets were more than 1 probe. In this # case, split bucketA and put bucketB back on the main # list. This will cause bucketB to get tested twice. else: print "case (3c4)..." probes.buckets.insert(0, probes.bucketB) split_bucket(probes.bucketA) # (3d) Both buckets passed. This sounds good, but this # means that together bucketA and bucketB failed, but # separately they passed. So, the combination of the sets # is the problem. else: print "case (3d)..." # (3d1) If both buckets are just 1 probe, combine the # buckets into one and put it on the failed list. # Then grab the next bucket. if len(probes.bucketA) == 1 and len(probes.bucketB) == 1: bucket = probes.bucketA + probes.bucketB probes.failed.append(bucket) ret = grab_bucket() # (3d2) Combine both buckets here, and try eliminating # the probes 1-by-1. We'll go back to bisecting if we # can remove 1 probe from this list or the list is # indivisible (case 3d3a). elif probes.split == 0: probes.split = 1 bucket = probes.bucketA + probes.bucketB split_bucket(bucket) # (3d3) We're eliminating the probes 1-by-1 and the # last attempt failed. Reverse the order and try # again. else: probes.split += 1 print "case (3d3): bucketA(%d) bucketB(%d)" % (len(probes.bucketA), len(probes.bucketB)) bucket = probes.bucketB + probes.bucketA print "case (3d3): combined bucket(%d)" % (len(bucket)) if len(bucket) > 500: print >>sys.stderr, "Error: bucket grew?" return -1 # (3d3a) If we've tried every probe singly, and # they all still worked, the combination is still # the problem. So, we're done trying 1-by-1 # elimination. if probes.split > len(bucket): probes.split = 0 probes.failed.append(bucket) ret = grab_bucket() # (3d3b) Keep trying 1-by-1 splits. else: split_bucket(bucket) write_probe_list() return ret def save_bucket(): global probes f = open(config_opts['probes_current'], 'w') if len(probes.bucketA) > 0 and probes.bucketA_result == 0: f.write("\n".join(probes.bucketA)) elif len(probes.bucketB) > 0 and probes.bucketB_result == 0: f.write("\n".join(probes.bucketB)) else: print "Error: no bucket to write?" f.close() def parse_module_output(): global probes # Parse the output file, looking for probe points pp_re = re.compile(": (-?\d+) (\S+)$") f = open(config_opts['probes_result'], 'r') pp = dict() line = f.readline() while line: match = pp_re.search(line) if match: pp[match.group(2)] = int(match.group(1)) line = f.readline() f.close() if len(pp.keys()) == 0: print >>sys.stderr, "No data found?" return 1 # We're done with the result file os.unlink(config_opts['probes_result']) # Parse the list of probe points. Since the result fields haven't # been updated yet, pick the 1st bucket that has a status of 0 # (untested). if probes.bucketA_result == 0: bucket = probes.bucketA else: bucket = probes.bucketB new_bucket = list() for probe in bucket: if pp.has_key(probe): # > 0 == passed (registered and triggered) if pp[probe] > 0: new_bucket.append(probe) # 0 == untriggered elif pp[probe] == 0: probes.untriggered.append(probe) # -1 == unregistered elif pp[probe] == -1: probes.unregistered.append(probe) else: print >>sys.stderr, "failed probe %s?" % probe else: print >>sys.stderr, "Couldn't find %s?" % probe # OK, we've gone through and removed all the # untriggered/unregistered probes from bucket. Update the # proper bucket. if probes.bucketA_result == 0: # Oops, all the probes were unregistered/untriggered. if len(new_bucket) == 0: # If we've got a bucketB, we'll think it just succeeded. # So, put it back on the bucket list so it will get # correctly processed. if len(probes.bucketB): print "Re-inserting bucketB..." probes.buckets.insert(0, probes.bucketB) # Reset everything reset_buckets() else: probes.bucketA = new_bucket else: # If bucketB ended up with 0 entries, we need to handle # bucketA. if len(new_bucket) == 0: # bucketA suceeded and bucketB ended up with 0 entries. # Put bucketA on the 'passed' list. if probes.bucketA_result == 1: probes.passed.extend(probes.bucketA) # bucketA failed and bucketB ended up with 0 entries. # Put bucketA on the bucket list to get processed again. # This will cause it to get tested twice, but it is the # easiest way out. else: print "Re-inserting bucketA..." probes.buckets.insert(0, probes.bucketA) # Reset everything. reset_buckets() else: probes.bucketB = new_bucket return 0 def run_tests(): status = True failed = True while status: status = update_buckets(failed) display_probe_list() if not status: break # Generate the module. save_bucket() rc = gen_module() if rc != 0: sys.exit(rc) # Run the module. sync_disks() rc = run_module() if rc != 0: sys.exit(rc) # Parse the module output. rc = parse_module_output() if rc != 0: sys.exit(rc) # If we're here, the current module was loaded and unloaded # successfully. failed = False def dump_output(): global probes f = open(config_opts['probes_passed'], 'w') if len(probes.passed) > 0: f.write("\n".join(probes.passed)) f.close() # probes.failed is a list of lists. f = open(config_opts['probes_failed'], 'w') for bucket in probes.failed: f.write("\n".join(bucket)) f.write("\n#\n") f.close() f = open(config_opts['probes_untriggered'], 'w') if len(probes.untriggered) > 0: f.write("\n".join(probes.untriggered)) f.close() f = open(config_opts['probes_unregistered'], 'w') if len(probes.unregistered) > 0: f.write("\n".join(probes.unregistered)) f.close() # Make sure we're running as root. if os.getuid() != 0: print >>sys.stderr, "Error: this script must be run by root" sys.exit(1) # Register this script. If this is the 1st time we've been run, start # from scratch by removing old state files. if register_script(): print >>sys.stderr, "Removing old state files..." if os.path.exists(config_opts['log_file']): os.unlink(config_opts['log_file']) if os.path.exists(config_opts['probes_db']): os.unlink(config_opts['probes_db']) # Redirect stdout and stderr sys.stdout.flush() sys.stderr.flush() so = open(config_opts['log_file'], 'a+', 0) # no buffering os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(so.fileno(), sys.stderr.fileno()) # Go! read_probe_list() run_tests() # Finish up. dump_output() register_script(False) print >>sys.stderr, "Finished." systemtap-2.3/scripts/kprobes_test/monitor_system.py000077500000000000000000000046721217430427200232650ustar00rootroot00000000000000#!/usr/bin/python # Copyright (C) 2008 Red Hat Inc. # # This file is part of systemtap, and is free software. You can # redistribute it and/or modify it under the terms of the GNU General # Public License (GPL); either version 2, or (at your option) any # later version. # This script monitors a remote system that is running the kprobes # test. If several consecutive 'ping's fail, the system is rebooted. # # This script takes as an argument a config filename, whose contents # should look like the following: # # config_opts['system_name'] = "SYSTEM_NAME" # config_opts['restart_cmds'] = [ # 'CMD1', # 'CMD2', # ] # # As an example, here is a config file used when monitoring a kvm # instance: # # config_opts['system_name'] = "dhcp-148" # config_opts['restart_cmds'] = [ # 'sudo virsh destroy kvm-rawhide-64-1', # 'sudo virsh start kvm-rawhide-64-1', # ] import sys import os import time if len(sys.argv) != 2: print >>sys.stderr, "Usage: %s config_file" % sys.argv[0] sys.exit(1) cfg = sys.argv[1] # Read in the config file if not os.path.exists(cfg): print >>sys.stderr, ("Could not find required config file: %s" % cfg) sys.exit(1) print "Reading config file %s..." % cfg config_opts = dict() execfile(cfg) if not config_opts.has_key('system_name'): print >>sys.stderr, "Missing required config opt 'system_name'" sys.exit(1) if not config_opts.has_key('restart_cmds'): print >>sys.stderr, "Missing required config opt 'restart_cmds'" sys.exit(1) errors = 0 while 1: rc = os.system("ping -c 1 %s" % config_opts['system_name']) # If ping worked, system is still up and running. Wait a minute # and try again. if os.WEXITSTATUS(rc) == 0: time.sleep(60) errors = 0 # If the ping failed, increase the error count. If we've got 3 # consecutive errors, assume the machine has crashed and restart # it. else: errors += 1 if errors < 3: time.sleep(30) else: print >>sys.stderr, "Restarting %s..." % config_opts['system_name'] # Run each restart command for cmd in config_opts['restart_cmds']: print >>sys.stderr, "Running '%s'..." % cmd os.system(cmd) # Sleep for 5 minutes to give the system a chance to boot print >>sys.stderr, "Sleeping for 5 minutes..." time.sleep(5 * 60) errors = 0 systemtap-2.3/scripts/kprobes_test/readelf.py000077500000000000000000000045761217430427200215770ustar00rootroot00000000000000#!/usr/bin/python # Copyright (C) 2008 Red Hat Inc. # # This file is part of systemtap, and is free software. You can # redistribute it and/or modify it under the terms of the GNU General # Public License (GPL); either version 2, or (at your option) any # later version. import re import sys import os #import pickle import subprocess from config_opts import config_opts # Read the output of eu-readelf on vmlinux (sysname, nodename, release, version, machine) = os.uname() cmd = "eu-readelf --symbols /usr/lib/debug/lib/modules/%s/vmlinux" % release print "Running", cmd p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) lines = p.stdout.readlines() p.wait() if p.returncode != 0: print >>sys.stderr, "Error: eu-readelf failed." sys.exit(p.returncode) # Parse the output kprobes_text_start = 0 kprobes_text_end = 0 syms = dict() func_re = re.compile("^\s*\d+:\s+([0-9a-f]+)\s+\d+\s+FUNC\s+\S+\s+\S+\s+\d+\s+(\S+)$") notype_re = re.compile("^\s*\d+:\s+([0-9a-f]+)\s+\d+\s+NOTYPE\s+\S+\s+\S+\s+\d+\s+(\S+)$") for line in lines: match = notype_re.match(line) if match: addr = match.group(1) name = match.group(2) if name == "__kprobes_text_start": kprobes_text_start = long(addr, 16) elif name == "__kprobes_text_end": kprobes_text_end = long(addr, 16) continue match = func_re.match(line) if match: addr = match.group(1) name = match.group(2) syms[name] = long(addr, 16) # Now we've parsed everything. Now we need to go back and remove all # symbols between '__kprobes_text_start' and '__kprobes_text_end', # since they are already protected from kprobes. We couldn't do this # in the loop above, since we might encounter symbols that need to be # removed before we found the start/end of the kprobes section. if kprobes_text_start == 0 or kprobes_text_end == 0: print "Error - didn't find kprobes_test_start(%d) or kprobes_text_end(%d)" \ % (kprobes_text_start, kprobes_text_end) sys.exit(1) for name in syms.keys(): if syms[name] >= kprobes_text_start and syms[name] < kprobes_text_end: print "deleting", name del syms[name] ## Save data #f = open('%s.syms' % (release), 'w') #p = pickle.Pickler(f) #p.dump(syms) #f.close() # Write the data out in text format f = open(config_opts['probes_all'], 'w') for name in syms.keys(): print >>f, name f.close() systemtap-2.3/scripts/kprobes_test/run_module.py000077500000000000000000000105371217430427200223400ustar00rootroot00000000000000#!/usr/bin/python # Copyright (C) 2008, 2010 Red Hat Inc. # # This file is part of systemtap, and is free software. You can # redistribute it and/or modify it under the terms of the GNU General # Public License (GPL); either version 2, or (at your option) any # later version. import sys import os import os.path import time import select from config_opts import config_opts def run_module(): # Find the current size of /var/log/messages logfile = '/var/log/messages' print >>sys.stderr, "Getting size of %s..." % logfile start_pos = os.path.getsize(logfile) l = open(logfile, 'r') l.seek(start_pos) # Insert the module print >>sys.stderr, "Inserting module..." rc = os.system("/sbin/insmod %s" % os.path.join(os.getcwd(), 'kprobe_module.ko')) if os.WEXITSTATUS(rc) != 0: # This is actually semi-OK, which is why there is no error # message here, only a notice. This might mean that every # probe tried cannot be registered. print >>sys.stderr, "Notice: insmod failed" else: # Run the load generate commands (if any). Note we ignore the # return values, since we don't really care if the commands # succeed or not. if config_opts.has_key('load_cmds'): print >>sys.stderr, "Running commands..." num_waits = 0 # Redirect the output to 'run_module.log' by modifying # what stdout/stderr points to. sys.stdout.flush() old_stdout = os.dup(sys.stdout.fileno()) sys.stderr.flush() old_stderr = os.dup(sys.stderr.fileno()) fd = os.open('run_module.log', os.O_CREAT | os.O_WRONLY) os.dup2(fd, sys.stdout.fileno()) os.dup2(fd, sys.stderr.fileno()) # Run the commands. pid_list = list() for cmd in config_opts['load_cmds']: pid = os.spawnvp(os.P_NOWAIT, cmd[0], cmd) pid_list.append(pid) for pid in pid_list: (childpid, status) = os.waitpid(pid, 0) # Restore old value of stdout/stderr. os.close(fd) os.dup2(old_stdout, sys.stdout.fileno()) os.dup2(old_stderr, sys.stderr.fileno()) # Remove the module print >>sys.stderr, "Removing module..." rc = os.system("/sbin/rmmod kprobe_module") if os.WEXITSTATUS(rc) != 0: print >>sys.stderr, "Error: rmmod failed" return -1 # Now we have to wait until everything is flushed to the logfile print >>sys.stderr, "Looking for output..." rc = 0 f = open(config_opts['probes_result'], 'w') attempts = 0 while 1: # Find the ending size of /var/log/messages end_pos = os.path.getsize(logfile) if end_pos < start_pos: # The log files have been rotated. Read any leftover data, # then reopen file. data = l.read() if data: f.write(data) # See if we can find 'kprobe_module unloaded' in the # data we just read. if data.find('kprobe_module unloaded') != -1: break l.close() l = open(logfile, 'r') start_pos = 0 continue # Try to wait until data is available while 1: try: input, output, exc = select.select([l.fileno()], [], [], 60) break except select.error, err: if err[0] != EINTR: raise # Get the new stuff logged to /var/log/messages data = l.read(end_pos - start_pos + 1) if not data: # ignore EOF time.sleep(2) attempts += 1 if attempts < 30: continue else: print >>sys.stderr, "Error: Couldn't find data" rc = -1 break # Write results data f.write(data) # See if we can find 'kprobe_module unloaded' in the data we # just read. if data.find('kprobe_module unloaded') == -1: start_pos = end_pos else: break l.close() f.close() return rc def main(): rc = run_module() sys.exit(rc) if __name__ == "__main__": main() systemtap-2.3/scripts/probe_perf/000077500000000000000000000000001217430427200172235ustar00rootroot00000000000000systemtap-2.3/scripts/probe_perf/.gitignore000066400000000000000000000000441217430427200212110ustar00rootroot00000000000000/bench_.h /bench-*.x /stapbench*.ko systemtap-2.3/scripts/probe_perf/bench.c000066400000000000000000000564071217430427200204620ustar00rootroot00000000000000# include # include # include # include # include # include # include "bench_.h" #define nil 0 #define false 0 #define true 1 #define bubblebase 1.61 #define dnfbase 3.5 #define permbase 1.75 #define queensbase 1.83 #define towersbase 2.39 #define quickbase 1.92 #define intmmbase 1.46 #define treebase 2.5 #define mmbase 0.0 #define fpmmbase 2.92 #define puzzlebase 0.5 #define fftbase 0.0 #define fpfftbase 4.44 /* Towers */ #define maxcells 18 /* Intmm, Mm */ #define rowsize 40 /* Puzzle */ #define SIZE 511 #define classmax 3 #define typemax 12 #define d 8 /* Bubble, Quick */ #define sortelements 5000 #define srtelements 500 /* fft */ #define fftsize 256 #define fftsize2 129 /* Perm */ #define permrange 10 /* tree */ struct node { struct node *left, *right; int val; }; /* Towers */ #define stackrange 3 struct element { int discsize; int next; }; /* FFT */ struct complex { float rp, ip; }; float value; float fixed, floated; /* global */ int seed; #define CYCLES_HBOUND 1000 long cycles_start; long permute_cycles_idx; long permute_cycles_avg; long (*permute_cycles) [CYCLES_HBOUND]; long tower_cycles_idx; long tower_cycles_avg; long (*tower_cycles) [CYCLES_HBOUND]; long try_cycles_idx; long try_cycles_avg; long (*try_cycles) [CYCLES_HBOUND]; long innerproduct_cycles_idx; long innerproduct_cycles_avg; long (*innerproduct_cycles) [CYCLES_HBOUND]; long trial_cycles_idx; long trial_cycles_avg; long (*trial_cycles) [CYCLES_HBOUND]; long quicksort_cycles_idx; long quicksort_cycles_avg; long (*quicksort_cycles) [CYCLES_HBOUND]; long insert_cycles_idx; long insert_cycles_avg; long (*insert_cycles) [CYCLES_HBOUND]; long bubble_cycles_idx; long bubble_cycles_avg; long (*bubble_cycles) [CYCLES_HBOUND]; long fft_cycles_idx; long fft_cycles_avg; long (*fft_cycles) [CYCLES_HBOUND]; /* Perm */ int permarray[permrange + 1]; int pctr; /* tree */ struct node *tree; /* Towers */ int stack[stackrange + 1]; struct element cellspace[maxcells + 1]; int freelist, movesdone; /* Intmm, Mm */ int ima[rowsize + 1][rowsize + 1], imb[rowsize + 1][rowsize + 1], imr[rowsize + 1][rowsize + 1]; float rma[rowsize + 1][rowsize + 1], rmb[rowsize + 1][rowsize + 1], rmr[rowsize + 1][rowsize + 1]; /* Puzzle */ int piececount[classmax + 1], class[typemax + 1], piecemax[typemax + 1], puzzl[SIZE + 1], p[typemax + 1][SIZE + 1], n, kount; /* Bubble, Quick */ int sortlist[sortelements + 1], biggest, littlest, top; /* FFT */ struct complex z[fftsize + 1], w[fftsize + 1], e[fftsize2 + 1]; float zr, zi; /* global procedures */ long rdtsc(void) __attribute__ ((__noinline__)); long rdtsc(void) { // XXX this only works on x86_64 // -- not i386 because the long result is only 32-bit // -- not other archs because they need other asm #if defined __x86_64__ int res[2]; __asm__ __volatile__ ("xorl %%eax,%%eax \n push %%rbx \n cpuid \n" ::: "%rax", "%rcx", "%rdx"); // read TSC, store edx:eax in res __asm__ __volatile__ ("rdtsc\n" : "=a" (res[0]), "=d" (res[1]) ); __asm__ __volatile__ ("xorl %%eax,%%eax \n cpuid \n pop %%rbx \n" ::: "%rax", "%rcx", "%rdx"); return *(long*)res; #else return 0; #endif } Initrand () { seed = 74755; } int Rand () { seed = (seed * 1309 + 13849) & 65535; return (seed); } /* Permutation program, heavily recursive, written by Denny Brown. */ Swap (a, b) int *a, *b; { int t; t = *a; *a = *b; *b = t; } Initialize () { int i; for (i = 1; i <= 7; i++) { permarray[i] = i - 1; }; } Permute (n) int n; { int k; pctr = pctr + 1; if (n != 1) { Permute (n - 1); for (k = n - 1; k >= 1; k--) { cycles_start = rdtsc(); #ifndef NO_STAP_SDT BENCH_PERMUTE (cycles_start,k); #else BENCH_PERMUTE: #endif if (__builtin_expect(permute_cycles_idx != CYCLES_HBOUND,0)) { permute_cycles_idx++; (*permute_cycles)[permute_cycles_idx] = rdtsc() - cycles_start; } Swap (&permarray[n], &permarray[k]); Permute (n - 1); Swap (&permarray[n], &permarray[k]); }; }; } Perm () { int i; pctr = 0; for (i = 1; i <= 5; i++) { Initialize (); Permute (7); }; if (pctr != 43300) printf (" Error in Perm.\n"); } /* Program to Solve the Towers of Hanoi */ Error (emsg) char *emsg; { printf (" Error in Towers: %s\n", emsg); } Makenull (s) { stack[s] = 0; } int Getelement () { int temp; if (freelist > 0) { temp = freelist; freelist = cellspace[freelist].next; } else Error ("out of space "); return (temp); } Push (i, s) int i, s; { int errorfound, localel; errorfound = false; if (stack[s] > 0) if (cellspace[stack[s]].discsize <= i) { errorfound = true; Error ("disc size error"); }; if (!errorfound) { localel = Getelement (); cellspace[localel].next = stack[s]; stack[s] = localel; cellspace[localel].discsize = i; } } Init (s, n) int s, n; { int discctr; Makenull (s); for (discctr = n; discctr >= 1; discctr--) Push (discctr, s); } int Pop (s) int s; { int temp, temp1; if (stack[s] > 0) { temp1 = cellspace[stack[s]].discsize; temp = cellspace[stack[s]].next; cellspace[stack[s]].next = freelist; freelist = stack[s]; stack[s] = temp; return (temp1); } else Error ("nothing to pop "); } Move (s1, s2) int s1, s2; { Push (Pop (s1), s2); movesdone = movesdone + 1; } tower (i, j, k) int i, j, k; { int other; cycles_start = rdtsc(); #ifndef NO_STAP_SDT BENCH_TOWER (cycles_start,i, j, k); #else BENCH_TOWER: #endif if (__builtin_expect(tower_cycles_idx != CYCLES_HBOUND,0)) { tower_cycles_idx++; (*tower_cycles)[tower_cycles_idx] = rdtsc() - cycles_start; } if (k == 1) Move (i, j); else { other = 6 - i - j; tower (i, other, k - 1); Move (i, j); tower (other, j, k - 1); } } Towers () { int i; for (i = 1; i <= maxcells; i++) cellspace[i].next = i - 1; freelist = maxcells; Init (1, 14); Makenull (2); Makenull (3); movesdone = 0; tower (1, 2, 14); if (movesdone != 16383) printf (" Error in Towers.\n"); } /* The eight queens problem, solved 50 times. */ /* type doubleboard = 2..16; doublenorm = -7..7; boardrange = 1..8; aarray = array [boardrange] of boolean; barray = array [doubleboard] of boolean; carray = array [doublenorm] of boolean; xarray = array [boardrange] of boardrange; */ Try (i, q, a, b, c, x) int i, *q, a[], b[], c[], x[]; { int j; j = 0; *q = false; while ((!*q) && (j != 8)) { j = j + 1; cycles_start = rdtsc(); #ifndef NO_STAP_SDT BENCH_TRY (cycles_start,i, q, a, b, c, x); #else BENCH_TRY: #endif if (__builtin_expect(try_cycles_idx != CYCLES_HBOUND,0)) { try_cycles_idx++; (*try_cycles)[try_cycles_idx] = rdtsc() - cycles_start; } *q = false; if (b[j] && a[i + j] && c[i - j + 7]) { x[i] = j; b[j] = false; a[i + j] = false; c[i - j + 7] = false; if (i < 8) { Try (i + 1, q, a, b, c, x); if (!*q) { b[j] = true; a[i + j] = true; c[i - j + 7] = true; } } else *q = true; } } } Doit () { int i, q; int a[9], b[17], c[15], x[9]; i = 0 - 7; while (i <= 16) { if ((i >= 1) && (i <= 8)) a[i] = true; if (i >= 2) b[i] = true; if (i <= 7) c[i + 7] = true; i = i + 1; } Try (1, &q, b, a, c, x); if (!q) printf (" Error in Queens.\n"); } Queens () { int i; for (i = 1; i <= 50; i++) Doit (); } /* Multiplies two integer matrices. */ Initmatrix (m) int m[rowsize + 1][rowsize + 1]; { int temp, i, j; for (i = 1; i <= rowsize; i++) for (j = 1; j <= rowsize; j++) temp = Rand (); m[i][j] = temp - (temp / 120) * 120 - 60; } Innerproduct (result, a, b, row, column) int *result, a[rowsize + 1][rowsize + 1], b[rowsize + 1][rowsize + 1], row, column; { int i; *result = 0; for (i = 1; i <= rowsize; i++) { cycles_start = rdtsc(); #ifndef NO_STAP_SDT BENCH_INNERPRODUCT (cycles_start,a, b, row, column); #else BENCH_INNERPRODUCT: #endif if (__builtin_expect(innerproduct_cycles_idx != CYCLES_HBOUND,0)) { innerproduct_cycles_idx++; (*innerproduct_cycles)[innerproduct_cycles_idx] = rdtsc() - cycles_start; } *result = *result + a[row][i] * b[i][column]; } } Intmm () { int i, j; Initrand (); Initmatrix (ima); Initmatrix (imb); for (i = 1; i <= rowsize; i++) for (j = 1; j <= rowsize; j++) Innerproduct (&imr[i][j], ima, imb, i, j); } /* Multiplies two real matrices. */ rInitmatrix (m) float m[rowsize + 1][rowsize + 1]; { int temp, i, j; for (i = 1; i <= rowsize; i++) for (j = 1; j <= rowsize; j++) temp = Rand (); m[i][j] = (temp - (temp / 120) * 120 - 60) / 3; } rInnerproduct (result, a, b, row, column) float *result, a[rowsize + 1][rowsize + 1], b[rowsize + 1][rowsize + 1]; int row, column; { int i; *result = 0.0; for (i = 1; i <= rowsize; i++) *result = *result + a[row][i] * b[i][column]; } Mm () { int i, j; Initrand (); rInitmatrix (rma); rInitmatrix (rmb); for (i = 1; i <= rowsize; i++) for (j = 1; j <= rowsize; j++) rInnerproduct (&rmr[i][j], rma, rmb, i, j); } int Fit (i, j) int i, j; { int k; for (k = 0; k <= piecemax[i]; k++) if (p[i][k]) if (puzzl[j + k]) return (false); return (true); } int Place (i, j) int i, j; { int k; for (k = 0; k <= piecemax[i]; k++) if (p[i][k]) puzzl[j + k] = true; piececount[class[i]] = piececount[class[i]] - 1; for (k = j; k <= SIZE; k++) if (!puzzl[k]) { return (k); } return (0); } Remove (i, j) int i, j; { int k; for (k = 0; k <= piecemax[i]; k++) if (p[i][k]) puzzl[j + k] = false; piececount[class[i]] = piececount[class[i]] + 1; } int Trial (j) int j; { int i, k; kount = kount + 1; for (i = 0; i <= typemax; i++) { if (piececount[class[i]] != 0) if (Fit (i, j)) { k = Place (i, j); cycles_start = rdtsc(); #ifndef NO_STAP_SDT BENCH_TRIAL (cycles_start,i, j, k); #else BENCH_TRIAL: #endif if (__builtin_expect(trial_cycles_idx != CYCLES_HBOUND,0)) { trial_cycles_idx++; (*trial_cycles)[trial_cycles_idx] = rdtsc() - cycles_start; } if (Trial (k) || (k == 0)) { return (true); } else Remove (i, j); } } return (false); } Puzzle () { int i, j, k, m; for (m = 0; m <= SIZE; m++) puzzl[m] = true; for (i = 1; i <= 5; i++) for (j = 1; j <= 5; j++) for (k = 1; k <= 5; k++) puzzl[i + d * (j + d * k)] = false; for (i = 0; i <= typemax; i++) for (m = 0; m <= SIZE; m++) p[i][m] = false; for (i = 0; i <= 3; i++) for (j = 0; j <= 1; j++) for (k = 0; k <= 0; k++) p[0][i + d * (j + d * k)] = true; class[0] = 0; piecemax[0] = 3 + d * 1 + d * d * 0; for (i = 0; i <= 1; i++) for (j = 0; j <= 0; j++) for (k = 0; k <= 3; k++) p[1][i + d * (j + d * k)] = true; class[1] = 0; piecemax[1] = 1 + d * 0 + d * d * 3; for (i = 0; i <= 0; i++) for (j = 0; j <= 3; j++) for (k = 0; k <= 1; k++) p[2][i + d * (j + d * k)] = true; class[2] = 0; piecemax[2] = 0 + d * 3 + d * d * 1; for (i = 0; i <= 1; i++) for (j = 0; j <= 3; j++) for (k = 0; k <= 0; k++) p[3][i + d * (j + d * k)] = true; class[3] = 0; piecemax[3] = 1 + d * 3 + d * d * 0; for (i = 0; i <= 3; i++) for (j = 0; j <= 0; j++) for (k = 0; k <= 1; k++) p[4][i + d * (j + d * k)] = true; class[4] = 0; piecemax[4] = 3 + d * 0 + d * d * 1; for (i = 0; i <= 0; i++) for (j = 0; j <= 1; j++) for (k = 0; k <= 3; k++) p[5][i + d * (j + d * k)] = true; class[5] = 0; piecemax[5] = 0 + d * 1 + d * d * 3; for (i = 0; i <= 2; i++) for (j = 0; j <= 0; j++) for (k = 0; k <= 0; k++) p[6][i + d * (j + d * k)] = true; class[6] = 1; piecemax[6] = 2 + d * 0 + d * d * 0; for (i = 0; i <= 0; i++) for (j = 0; j <= 2; j++) for (k = 0; k <= 0; k++) p[7][i + d * (j + d * k)] = true; class[7] = 1; piecemax[7] = 0 + d * 2 + d * d * 0; for (i = 0; i <= 0; i++) for (j = 0; j <= 0; j++) for (k = 0; k <= 2; k++) p[8][i + d * (j + d * k)] = true; class[8] = 1; piecemax[8] = 0 + d * 0 + d * d * 2; for (i = 0; i <= 1; i++) for (j = 0; j <= 1; j++) for (k = 0; k <= 0; k++) p[9][i + d * (j + d * k)] = true; class[9] = 2; piecemax[9] = 1 + d * 1 + d * d * 0; for (i = 0; i <= 1; i++) for (j = 0; j <= 0; j++) for (k = 0; k <= 1; k++) p[10][i + d * (j + d * k)] = true; class[10] = 2; piecemax[10] = 1 + d * 0 + d * d * 1; for (i = 0; i <= 0; i++) for (j = 0; j <= 1; j++) for (k = 0; k <= 1; k++) p[11][i + d * (j + d * k)] = true; class[11] = 2; piecemax[11] = 0 + d * 1 + d * d * 1; for (i = 0; i <= 1; i++) for (j = 0; j <= 1; j++) for (k = 0; k <= 1; k++) p[12][i + d * (j + d * k)] = true; class[12] = 3; piecemax[12] = 1 + d * 1 + d * d * 1; piececount[0] = 13; piececount[1] = 3; piececount[2] = 1; piececount[3] = 1; m = 1 + d * (1 + d * 1); kount = 0; if (Fit (0, m)) n = Place (0, m); else printf ("Error1 in Puzzle\n"); if (!Trial (n)) printf ("Error2 in Puzzle.\n"); else if (kount != 2005) printf ("Error3 in Puzzle.\n"); } /* Sorts an array using quicksort */ Initarr () { int i, temp; Initrand (); biggest = 0; littlest = 0; for (i = 1; i <= sortelements; i++) { temp = Rand (); sortlist[i] = temp - (temp / 100000) * 100000 - 50000; if (sortlist[i] > biggest) biggest = sortlist[i]; else if (sortlist[i] < littlest) littlest = sortlist[i]; } } Quicksort (a, l, r) int a[], l, r; { int i, j, x, w; i = l; j = r; x = a[(l + r) / 2]; do { while (a[i] < x) i = i + 1; while (x < a[j]) j = j - 1; cycles_start = rdtsc(); #ifndef NO_STAP_SDT BENCH_QUICKSORT (cycles_start,i, j, x); #else BENCH_QUICKSORT: #endif if (__builtin_expect(quicksort_cycles_idx != CYCLES_HBOUND,0)) { quicksort_cycles_idx++; (*quicksort_cycles)[quicksort_cycles_idx] = rdtsc() - cycles_start; } if (i <= j) { w = a[i]; a[i] = a[j]; a[j] = w; i = i + 1; j = j - 1; } } while (i <= j); if (l < j) Quicksort (a, l, j); if (i < r) Quicksort (a, i, r); } Quick () { Initarr (); Quicksort (sortlist, 1, sortelements); if ((sortlist[1] != littlest) || (sortlist[sortelements] != biggest)) printf (" Error in Quick.\n"); } tInitarr () { int i, temp; Initrand (); biggest = 0; littlest = 0; for (i = 1; i <= sortelements; i++) { temp = Rand (); sortlist[i] = temp - (temp / 100000) * 100000 - 50000; if (sortlist[i] > biggest) biggest = sortlist[i]; else if (sortlist[i] < littlest) littlest = sortlist[i]; } } CreateNode (t, n) struct node **t; int n; { *t = (struct node *) malloc (sizeof (struct node)); (*t)->left = nil; (*t)->right = nil; (*t)->val = n; } Insert (n, t) int n; struct node *t; { cycles_start = rdtsc(); #ifndef NO_STAP_SDT BENCH_INSERT (cycles_start,n, t); #else BENCH_INSERT: #endif if (__builtin_expect(insert_cycles_idx != CYCLES_HBOUND,0)) { insert_cycles_idx++; (*insert_cycles)[insert_cycles_idx] = rdtsc() - cycles_start; } if (n > t->val) if (t->left == nil) CreateNode (&t->left, n); else Insert (n, t->left); else if (n < t->val) if (t->right == nil) CreateNode (&t->right, n); else Insert (n, t->right); } int Checktree (p) struct node *p; { int result; result = true; if (p->left != nil) if (p->left->val <= p->val) result = false; else result = Checktree (p->left) && result; if (p->right != nil) if (p->right->val >= p->val) result = false; else result = Checktree (p->right) && result; return (result); } Trees () { int i; tInitarr (); tree = (struct node *) malloc (sizeof (struct node)); tree->left = nil; tree->right = nil; tree->val = sortlist[1]; for (i = 2; i <= sortelements; i++) Insert (sortlist[i], tree); if (!Checktree (tree)) printf (" Error in Tree.\n"); } /* Sorts an array using bubblesort */ bInitarr () { int i, temp; Initrand (); biggest = 0; littlest = 0; for (i = 1; i <= srtelements; i++) { temp = Rand (); sortlist[i] = temp - (temp / 100000) * 100000 - 50000; if (sortlist[i] > biggest) biggest = sortlist[i]; else if (sortlist[i] < littlest) littlest = sortlist[i]; } } Bubble () { int i, j; bInitarr (); top = srtelements; while (top > 1) { i = 1; while (i < top) { cycles_start = rdtsc(); #ifndef NO_STAP_SDT BENCH_BUBBLE (cycles_start,i, top); #else BENCH_BUBBLE: #endif if (__builtin_expect(bubble_cycles_idx != CYCLES_HBOUND,0)) { bubble_cycles_idx++; (*bubble_cycles)[bubble_cycles_idx] = rdtsc() - cycles_start; } if (sortlist[i] > sortlist[i + 1]) { j = sortlist[i]; sortlist[i] = sortlist[i + 1]; sortlist[i + 1] = j; } i = i + 1; } top = top - 1; } if ((sortlist[1] != littlest) || (sortlist[srtelements] != biggest)) printf ("Error3 in Bubble.\n"); } float Cos (x) float x; { int i, factor; float result, power; result = 1.0; factor = 1; power = x; for (i = 2; i <= 10; i++) { factor = factor * i; power = power * x; if ((i & 1) == 0) { if ((i & 3) == 0) result = result + power / factor; else result = result - power / factor; } } return (result); } int Min0 (arg1, arg2) int arg1, arg2; { if (arg1 < arg2) return (arg1); else return (arg2); } Printcomplex (arg1, arg2, zarray, start, finish, increment) int arg1, arg2, start, finish, increment; struct complex zarray[]; { int i; printf ("\n"); i = start; do { printf (" %15.3e%15.3e", zarray[i].rp, zarray[i].ip); i = i + increment; printf (" %15.3e%15.3e", zarray[i].rp, zarray[i].ip); printf ("\n"); i = i + increment; } while (i <= finish); } Uniform11 (iy, yfl) int iy; float yfl; { iy = (4855 * iy + 1731) & 8191; yfl = iy / 8192.0; } Exptab (n, e) int n; struct complex e[]; { float theta, divisor, h[26]; int i, j, k, l, m; theta = 3.1415926536; divisor = 4.0; for (i = 1; i <= 25; i++) { h[i] = 1 / (2 * Cos (theta / divisor)); divisor = divisor + divisor; } m = n / 2; l = m / 2; j = 1; e[1].rp = 1.0; e[1].ip = 0.0; e[l + 1].rp = 0.0; e[l + 1].ip = 1.0; e[m + 1].rp = -1.0; e[m + 1].ip = 0.0; do { i = l / 2; k = i; do { e[k + 1].rp = h[j] * (e[k + i + 1].rp + e[k - i + 1].rp); e[k + 1].ip = h[j] * (e[k + i + 1].ip + e[k - i + 1].ip); k = k + l; } while (k <= m); j = Min0 (j + 1, 25); l = i; } while (l > 1); } Fft (n, z, w, e, sqrinv) int n; struct complex z[], w[]; struct complex e[]; float sqrinv; { int i, j, k, l, m, index; m = n / 2; l = 1; do { k = 0; j = l; i = 1; do { do { cycles_start = rdtsc(); #ifndef NO_STAP_SDT BENCH_FFT (cycles_start,n, z, w, e); #else BENCH_FFT: #endif if (__builtin_expect(fft_cycles_idx != CYCLES_HBOUND,0)) { fft_cycles_idx++; (*fft_cycles)[fft_cycles_idx] = rdtsc() - cycles_start; } w[i + k].rp = z[i].rp + z[m + i].rp; w[i + k].ip = z[i].ip + z[m + i].ip; w[i + j].rp = e[k + 1].rp * (z[i].rp - z[i + m].rp) - e[k + 1].ip * (z[i].ip - z[i + m].ip); w[i + j].ip = e[k + 1].rp * (z[i].ip - z[i + m].ip) + e[k + 1].ip * (z[i].rp - z[i + m].rp); i = i + 1; } while (i <= j); k = j; j = k + l; } while (j <= m); index = 1; do { z[index] = w[index]; index = index + 1; } while (index <= n); l = l + l; } while (l <= m); for (i = 1; i <= n; i++) { z[i].rp = sqrinv * z[i].rp; z[i].ip = -sqrinv * z[i].ip; }; } Oscar () { int i; Exptab (fftsize, e); seed = 5767; for (i = 1; i <= fftsize; i++) { Uniform11 (seed, zr); Uniform11 (seed, zi); z[i].rp = 20.0 * zr - 10.0; z[i].ip = 20.0 * zi - 10.0; }; for (i = 1; i <= 20; i++) { Fft (fftsize, z, w, e, 0.0625); } } #define Start() #define Stop(a,b) #ifndef LOOP #define LOOP 500 #endif int main () { int i,j; permute_cycles = calloc(CYCLES_HBOUND,sizeof(long)); tower_cycles = calloc(CYCLES_HBOUND,sizeof(long)); try_cycles = calloc(CYCLES_HBOUND,sizeof(long)); innerproduct_cycles = calloc(CYCLES_HBOUND,sizeof(long)); trial_cycles = calloc(CYCLES_HBOUND,sizeof(long)); quicksort_cycles = calloc(CYCLES_HBOUND,sizeof(long)); insert_cycles = calloc(CYCLES_HBOUND,sizeof(long)); bubble_cycles = calloc(CYCLES_HBOUND,sizeof(long)); fft_cycles = calloc(CYCLES_HBOUND,sizeof(long)); Start (); for (i = 0; i < LOOP; i++) Perm (); Stop ("Perm", LOOP); Start (); for (i = 0; i < LOOP; i++) Towers (); Stop ("Towers", LOOP); Start (); for (i = 0; i < LOOP; i++) Queens (); Stop ("Queens", LOOP); Start (); for (i = 0; i < LOOP; i++) Intmm (); Stop ("Intmm", LOOP); Start (); for (i = 0; i < LOOP; i++) Mm (); Stop ("Mm", LOOP); Start (); for (i = 0; i < LOOP; i++) Puzzle (); Stop ("Puzzle", LOOP); Start (); for (i = 0; i < LOOP; i++) Quick (); Stop ("Quick", LOOP); Start (); for (i = 0; i < LOOP; i++) Bubble (); Stop ("Bubble", LOOP); Start (); for (i = 0; i < LOOP; i++) Trees (); Stop ("Trees", LOOP); Start (); for (i = 0; i < LOOP; i++) Oscar (); Stop ("Oscar", LOOP); for (j = 1; j <= permute_cycles_idx; j++) permute_cycles_avg += (*permute_cycles)[j]; printf ("permute_cycles %#lx\n", permute_cycles_avg / permute_cycles_idx); for (j = 1; j <= tower_cycles_idx; j++) tower_cycles_avg += (*tower_cycles)[j]; printf ("tower_cycles %#lx\n", tower_cycles_avg / tower_cycles_idx); for (j = 1; j <= try_cycles_idx; j++) try_cycles_avg += (*try_cycles)[j]; printf ("try_cycles %#lx\n", try_cycles_avg / try_cycles_idx); for (j = 1; j <= innerproduct_cycles_idx; j++) innerproduct_cycles_avg += (*innerproduct_cycles)[j]; printf ("innerproduct_cycles %#lx\n", innerproduct_cycles_avg / innerproduct_cycles_idx); for (j = 1; j <= trial_cycles_idx; j++) trial_cycles_avg += (*trial_cycles)[j]; printf ("trial_cycles %#lx\n", trial_cycles_avg / trial_cycles_idx); for (j = 1; j <= quicksort_cycles_idx; j++) quicksort_cycles_avg += (*quicksort_cycles)[j]; printf ("quicksort_cycles %#lx\n", quicksort_cycles_avg / quicksort_cycles_idx); for (j = 1; j <= insert_cycles_idx; j++) insert_cycles_avg += (*insert_cycles)[j]; printf ("insert_cycles %#lx\n", insert_cycles_avg / insert_cycles_idx); for (j = 1; j <= bubble_cycles_idx; j++) bubble_cycles_avg += (*bubble_cycles)[j]; printf ("bubble_cycles %#lx\n", bubble_cycles_avg / bubble_cycles_idx); for (j = 1; j <= fft_cycles_idx; j++) fft_cycles_avg += (*fft_cycles)[j]; printf ("fft_cycles %#lx\n", fft_cycles_avg / fft_cycles_idx); return 0; } systemtap-2.3/scripts/probe_perf/bench.sh000077500000000000000000000063251217430427200206470ustar00rootroot00000000000000# Measure probe performance. Currently measures: # static user uprobes, static user kprobes, dynamic user uprobes. # example use: # ./bench.sh -stapdir /foo/stap/install/ -gccdir /foo/gcc-4.4.3-10/install/ function stap_test() { # Compile bench $STAP/bin/dtrace -G -s bench_.d -D$1 $STAP/bin/dtrace --types -h -s bench_.d -D$1 $GCC/bin/gcc -D$1 -DLOOP=10 bench_.o bench.c -o bench-$2$3.x -I$TESTSRC -I. -isystem $STAP/include -g if [ $? -ne 0 ]; then echo "error compiling bench-$2$3"; return; fi ./bench-$2$3.x > /dev/null # Run bench with stap taskset 1 $STAP/bin/stap -DSTP_NO_OVERLOAD=1 -g -p4 -m stapbench_$2$3 bench.stp ./bench-$2$3.x $1 >/dev/null if [ $? -ne 0 ]; then echo "error running stapbench_$2$3 with stap"; return; fi # Parse /usr/bin/time, bench.x, bench.stp output to get statistics ( taskset 1 /usr/bin/time ./bench-$2$3.x 2>&1 >/dev/null # mute stdout, get times from stderr $STAP/bin/staprun stapbench_$2$3.ko -c "taskset 1 /usr/bin/time ./bench-$2$3.x" 2>&1 ) | awk --non-decimal-data ' function seconds(s) { if (index(s,":")) m=substr(s,0,index(s,":"))*60 else m=0 return m + substr(s,index(s,":")+1) } # probe count and average probe setup cycles from bench.stp /@count/ { n += 1 count += (substr($2,8)); avg += (substr($6,6)) } # elapsed time from /usr/bin/time /elapsed/ { elapsed=(seconds($3)) if (nostapet == 0) { nostapet=elapsed print "without stap elapsed time is " elapsed } else print "with stap elapsed time is " elapsed } # average probe cycles from bench.x /_cycles/ { cycles_n += 1 cycles += $2 } END { print "count of probe hits is " count if (cycles && n) { printf "average cycles/probe is %d\n", (cycles / cycles_n) printf "average setup cycles/probe is %d\n", (avg / n) } if (count) printf "seconds/probe (%s/%s) is %.9f\n", elapsed-nostapet, count, (elapsed-nostapet)/count }' } usage () { echo 'Usage $0 -testsrcdir /testsuite/src/top/dir [-k] [-stapdir /stap/top/dir] [-gccdir /gcc/top/dir] [-help]' exit } # Main while test ! -z "$1" ; do if [ "$1" = "-gccdir" ] ; then GCC=$2 ; shift elif [ "$1" = "-stapdir" ] ; then STAP=$2 ; shift elif [ "$1" = "-testsrcdir" ] ; then TESTSRC=$2 ; shift elif [ "$1" = "-k" ] ; then KEEP=1 ; elif [ "$1" = "-h" -o "$1" = "-help" -o "$1" = "?" ] ; then usage else echo Unrecognized arg "$1" exit fi shift done if [ ! -z "$GCC" ] ; then if [ ! -x "$GCC/bin/gcc" ] ; then echo $GCC/bin/gcc does not exist exit fi else GCC=/usr/ fi echo Using $GCC/bin/gcc if [ ! -z "$STAP" ] ; then if [ ! -x "$STAP/bin/stap" ] ; then echo $STAP/bin/stap does not exist exit fi else STAP=/usr/ fi echo Using $STAP/bin/stap if [ ! -z "$TESTSRC" ] ; then if [ ! -r "$TESTSRC/sys/sdt.h" ] ; then echo $TESTSRC/sys/sdt.h does not exist exit fi else echo -e 'The testsuite sources containing directory must be given\nso the compatible sdt.h can be found' usage fi echo Using $TESTSRC/sys/sdt.h echo -e "\n##### LABEL (NO SDT) #####\n" stap_test NO_STAP_SDT nosdt echo -e "\n##### UPROBE V1 #####\n" stap_test STAP_SDT_V1 uprobe echo -e "\n##### UPROBE V2 #####\n" stap_test STAP_SDT_V2 uprobe2 echo -e "\n##### UPROBE V3 #####\n" stap_test STAP_SDT_V3 uprobe3 systemtap-2.3/scripts/probe_perf/bench.stp000066400000000000000000000041361217430427200210360ustar00rootroot00000000000000global process_hits %( @2 == "NO_STAP_SDT" %? probe process(@1).function("*").label("BENCH_PERMUTE") { process_hits <<< (get_cycles() - $cycles_start) } %: probe process(@1).mark("permute") { process_hits <<< (get_cycles() - $arg1) } %) global tower_hits %( @2 == "NO_STAP_SDT" %? probe process(@1).function("*").label("BENCH_TOWER") { tower_hits <<< (get_cycles() - $cycles_start) } %: probe process(@1).mark("tower") { tower_hits <<< (get_cycles() - $arg1) } %) global try_hits %( @2 == "NO_STAP_SDT" %? probe process(@1).function("*").label("BENCH_TRY") { try_hits <<< (get_cycles() - $cycles_start) } %: probe process(@1).mark("try") { try_hits <<< (get_cycles() - $arg1) } %) global innerproduct_hits %( @2 == "NO_STAP_SDT" %? probe process(@1).function("*").label("BENCH_INNERPRODUCT") { innerproduct_hits <<< (get_cycles() - $cycles_start) } %: probe process(@1).mark("innerproduct") { innerproduct_hits <<< (get_cycles() - $arg1) } %) global trial_hits %( @2 == "NO_STAP_SDT" %? probe process(@1).function("*").label("BENCH_TRIAL") { trial_hits <<< (get_cycles() - $cycles_start) } %: probe process(@1).mark("trial") { trial_hits <<< (get_cycles() - $arg1) } %) global quicksort_hits %( @2 == "NO_STAP_SDT" %? probe process(@1).function("*").label("BENCH_QUICKSORT") { quicksort_hits <<< (get_cycles() - $cycles_start) } %: probe process(@1).mark("quicksort") { quicksort_hits <<< (get_cycles() - $arg1) } %) global bubble_hits %( @2 == "NO_STAP_SDT" %? probe process(@1).function("*").label("BENCH_BUBBLE") { bubble_hits <<< (get_cycles() - $cycles_start) } %: probe process(@1).mark("bubble") { bubble_hits <<< (get_cycles() - $arg1) } %) global insert_hits %( @2 == "NO_STAP_SDT" %? probe process(@1).function("*").label("BENCH_INSERT") { insert_hits <<< (get_cycles() - $cycles_start) } %: probe process(@1).mark("insert") { insert_hits <<< (get_cycles() - $arg1) } %) global fft_hits %( @2 == "NO_STAP_SDT" %? probe process(@1).function("*").label("BENCH_FFT") { fft_hits <<< (get_cycles() - $cycles_start) } %: probe process(@1).mark("fft") { fft_hits <<< (get_cycles() - $arg1) } %) systemtap-2.3/scripts/probe_perf/bench_.d000066400000000000000000000007421217430427200206110ustar00rootroot00000000000000provider bench { probe permute(long cycles,int arg1); probe tower(long cycles,int arg1, int arg2, int arg3); probe try(long cycles,int i, int q, int a, int b, int c, int x); probe innerproduct(long cycles,int a, int b, int row, int column); probe trial(long cycles,int i, int j, int k); probe quicksort(long cycles,int i, int j, int x); probe bubble(long cycles,int i, int top); probe insert(long cycles,int n, int t); probe fft(long cycles,int n, int z, int w, int e); } systemtap-2.3/scripts/spin-rawhide000077500000000000000000000055011217430427200174210ustar00rootroot00000000000000#!/usr/bin/bash function determine_apply_diff() { read ANSWER if [ "$ANSWER" == "no" ] then return 1 elif [ "$ANSWER" == "yes" ] then return 0 else echo "Please answer \"yes\" or \"no\"" determine_apply_diff return $? fi } ### Create the directory we'll be working in### DIR=`mktemp -d stapXXX -p /tmp/`; cd $DIR # We need to differenciate between upstream sources and the later used distro sources # hence the specific checkout to systemtap-git git clone git://sourceware.org/git/systemtap.git systemtap-git cd systemtap-git # We need to use --global for the NAME and USER vars as we're # assuming this script can be run from anywhere (ie, not in an # already existing git repo) APPLY_DIFF=1 DATE=`date +"%a %b %d %Y"` NAME=`git config --get-all user.name` EMAIL=`git config --get-all user.email` STAP_MAJOR_VERSION=`grep "^Version:" systemtap.spec` CHANGELOG_VERSION=`echo $STAP_MAJOR_VERSION | cut -f2 -d" "` GIT_VERSION_TAG=`echo 0.$(git describe | rev | cut -f1,2 -d- --output-delimiter=. | rev)` ### lets do a sanity check first if which fedpkg &>/dev/null; then : else echo "Please install the fedpkg package" exit fi # Checkout the fedora sources systemtap cd .. fedpkg co systemtap # Diff and check the differences between the two spec files, cd systemtap git diff systemtap.spec ../systemtap-git/systemtap.spec > ../spec-diff if [ -s ../spec-diff ]; then cat ../spec-diff echo "The above changes will apply to the fedora git tree," echo "would you like to apply the patch? (yes/no):" determine_apply_diff APPLY_DIFF=$? if [ "$APPLY_DIFF" == 0 ]; then patch -p1 systemtap.spec < ../spec-diff fi cd .. fi # create a tar.gz of the latest git sources from HEAD cd systemtap-git git archive --prefix=systemtap-$CHANGELOG_VERSION/ -o ../systemtap/systemtap-$CHANGELOG_VERSION-$GIT_VERSION_TAG.tar.gz HEAD # fedpackage stuff cd ../systemtap sed -i "s/Release: .*/Release: $GIT_VERSION_TAG\%\{\?dist\}/" systemtap.spec sed -i "s/^Source:.*/Source: %{name}-%{version}-$GIT_VERSION_TAG.tar.gz/" systemtap.spec # make note in the comments if any differences from upstream systemtap.spec have been merged if [ "$APPLY_DIFF" == 0 ]; then sed -i "s/\%changelog/\%changelog\n* $DATE $NAME <$EMAIL> - $CHANGELOG_VERSION-$GIT_VERSION_TAG\n- Automated weekly rawhide release\n- Applied spec changes from upstream git\n/" systemtap.spec else sed -i "s/\%changelog/\%changelog\n* $DATE $NAME <$EMAIL> - $CHANGELOG_VERSION-$GIT_VERSION_TAG\n- Automated weekly rawhide release\n/" systemtap.spec fi echo "Please ensure that you have an up to date fedoraproject SSL certificate, you can achieve this by running fedora-cert -n" fedpkg new-sources systemtap-$CHANGELOG_VERSION-$GIT_VERSION_TAG.tar.gz fedpkg commit -m "Automated weekly systemtap rawhide release: $GIT_VERSION_TAG" -p fedpkg build systemtap-2.3/scripts/update-docs000077500000000000000000000055471217430427200172510ustar00rootroot00000000000000#!/usr/bin/bash #check for man2html #TODO perhaps wget, untar, and automatically use, then remove if we want? # http://dcssrv1.oit.uci.edu/indiv/ehood/tar/man2html3.0.1.tar.gz if which man2html &>/dev/null; then : else echo "Please install man2html package" exit fi # Create the directory we'll be working in DIR=`mktemp -d stapdocsXXX -p /tmp/`; cd $DIR # We'll need to build the latest stap with docs, ensure a check that everything built properly or bail git clone git://sourceware.org/git/systemtap.git # Checkout the htdocs CVS cvs -d :ext:sourceware.org:/cvs/systemtap checkout htdocs BASEDIR=`pwd` cd systemtap mkdir build && mkdir local && cd build ../configure --enable-docs --enable-publican --prefix=$BASEDIR/systemtap/local #Not sure if we're really allowed to make assumptions about the machine we're running this on #Probably safer not using the -jX option make make install if [ $? -eq 0 ]; then : else echo "Make failed, please address build errors" exit fi ### LANGREF cp doc/langref.pdf $BASEDIR/htdocs/ #Something about publicanizing the langref? rm $BASEDIR/htdocs/langref/*.html cd $BASEDIR/htdocs cvs rm && cvs commit -m 'removed langref/*.html' cd $BASEDIR/systemtap/doc latex2html -noaddress -show_section_numbers -custom_titles -local_icons -split 4 langref.tex -dir $BASEDIR/htdocs/langref/ cd $BASEDIR/htdocs cvs add langref/*.html && cvs commit -m 'add new langref/*.html' cd - ### TUTORIAL cp $BASEDIR/systemtap/build/doc/tutorial.pdf $BASEDIR/htdocs/ rm $BASEDIR/htdocs/tutorial/*.html cd $BASEDIR/htdocs #cvs rm && cvs commit -m 'removed tutorial/*.html' cd $BASEDIR/systemtap/doc latex2html -noaddress -show_section_numbers -custom_titles -local_icons -split 4 tutorial.tex -dir $BASEDIR/htdocs/tutorial/ cd $BASEDIR/htdocs cvs add tutorial/*.html && cvs commit -m 'add new tutorial/*.html' # beginners guide # we require xmlto version newer than 0.0.23-3 # TODO add a version check cd $BASEDIR/systemtap/build/doc/beginners cp SystemTap_Beginners_Guide.pdf $BASEDIR/htdocs/ #echo 'systemtap_beginners_guide.pdf cp' rm $BASEDIR/htdocs/SystemTap_Beginners_Guide/*.html cp -R SystemTap_Beginners_Guide $BASEDIR/htdocs/ #echo 'systemtap_beginners_guide recursive cp' # tapsets cd ../.. cp $BASEDIR/systemtap/build/doc/SystemTap_Tapset_Reference/tapsets.pdf $BASEDIR/htdocs/ #echo 'tapsets.pdf cp' rm $BASEDIR/htdocs/tapsets/*.html cp -R $BASEDIR/systemtap/build/doc/SystemTap_Tapset_Reference/tapsets/*.html $BASEDIR/htdocs/tapsets/ cd $BASEDIR/htdocs cvs add tapsets/*.html && cvs commit -m 'add new tapsets/*.html' #echo 'tapsets html cp' # systemtap examples # run gitweb.php script? # run examples-index-gen.pl script if needed? rm man/*.html && cvs rm * && cvs commit -m 'removed man pages' cd $BASEDIR/htdocs/man ./REGEN.sh $BASEDIR/systemtap/local cd $BASEDIR/htdocs cvs add man/*.html && cvs commit -m 'added new man pages' echo -- $BASEDIR systemtap-2.3/sdt_types.h000066400000000000000000000015431217430427200156030ustar00rootroot00000000000000/* Copyright (C) 2005-2011 Red Hat Inc. This file is part of systemtap, and is free software in the public domain. */ #ifndef _SDT_TYPES_H #define _SDT_TYPES_H 1 #define UPROBE1_TYPE 0x31425250 /* "PRB1" (little-endian) */ #define UPROBE2_TYPE 0x32425055 /* "UPB2" */ #define UPROBE3_TYPE 0x33425055 /* "UPB3" */ typedef enum { uprobe1_type = UPROBE1_TYPE, uprobe2_type = UPROBE2_TYPE, uprobe3_type = UPROBE3_TYPE, unknown_probe_type = -1, } stap_sdt_probe_type; typedef struct { __uint32_t type_a; __uint32_t type_b; __uint64_t name; __uint64_t arg; } stap_sdt_probe_entry_v1; typedef struct { __uint32_t type_a; __uint32_t type_b; __uint64_t name; __uint64_t provider; __uint64_t arg_count; __uint64_t arg_string; __uint64_t pc; __uint64_t semaphore; } stap_sdt_probe_entry_v2; #endif /* _SDT_TYPES_H */ systemtap-2.3/session.cxx000066400000000000000000002442331217430427200156300ustar00rootroot00000000000000// session functions // Copyright (C) 2010-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "config.h" #include "session.h" #include "cache.h" #include "stapregex.h" #include "elaborate.h" #include "translate.h" #include "buildrun.h" #include "coveragedb.h" #include "hash.h" #include "task_finder.h" #include "csclient.h" #include "rpm_finder.h" #include "util.h" #include "cmdline.h" #include "git_version.h" #include "version.h" #include #include extern "C" { #include #include #include #include #include #include #include #include #include } #if HAVE_NSS extern "C" { #include } #endif #include using namespace std; /* getopt variables */ extern int optind; #define PATH_TBD string("__TBD__") #if HAVE_NSS bool systemtap_session::NSPR_Initialized = false; #endif systemtap_session::systemtap_session (): // NB: pointer members must be manually initialized! // NB: don't forget the copy constructor too! runtime_mode(kernel_runtime), base_hash(0), pattern_root(new match_node), user_file (0), dfa_counter (0), dfa_maxstate (0), dfa_maxtag (0), need_tagged_dfa (false), be_derived_probes(0), dwarf_derived_probes(0), kprobe_derived_probes(0), hwbkpt_derived_probes(0), perf_derived_probes(0), uprobe_derived_probes(0), utrace_derived_probes(0), itrace_derived_probes(0), task_finder_derived_probes(0), timer_derived_probes(0), netfilter_derived_probes(0), profile_derived_probes(0), mark_derived_probes(0), tracepoint_derived_probes(0), hrtimer_derived_probes(0), procfs_derived_probes(0), dynprobe_derived_probes(0), java_derived_probes(0), op (0), up (0), sym_kprobes_text_start (0), sym_kprobes_text_end (0), sym_stext (0), module_cache (0), benchmark_sdt_loops(0), benchmark_sdt_threads(0), last_token (0) { struct utsname buf; (void) uname (& buf); kernel_release = string (buf.release); release = kernel_release; kernel_build_tree = "/lib/modules/" + kernel_release + "/build"; architecture = machine = normalize_machine(buf.machine); for (unsigned i=0; i<5; i++) perpass_verbose[i]=0; verbose = 0; have_script = false; runtime_specified = false; include_arg_start = -1; timing = false; guru_mode = false; bulk_mode = false; unoptimized = false; suppress_warnings = false; panic_warnings = false; listing_mode = false; listing_mode_vars = false; dump_probe_types = false; #ifdef ENABLE_PROLOGUES prologue_searching = true; #else prologue_searching = false; #endif buffer_size = 0; last_pass = 5; module_name = "stap_" + lex_cast(getpid()); stapconf_name = "stapconf_" + lex_cast(getpid()) + ".h"; output_file = ""; // -o FILE tmpdir_opt_set = false; save_module = false; modname_given = false; keep_tmpdir = false; cmd = ""; target_pid = 0; use_cache = true; use_script_cache = true; poison_cache = false; tapset_compile_coverage = false; need_uprobes = false; need_unwind = false; need_symbols = false; uprobes_path = ""; consult_symtab = false; load_only = false; skip_badvars = false; privilege = pr_stapdev; privilege_set = false; omit_werror = false; compatible = VERSION; // XXX: perhaps also process GIT_SHAID if available? unwindsym_ldd = false; client_options = false; server_cache = NULL; automatic_server_mode = false; use_server_on_error = false; try_server_status = try_server_unset; use_remote_prefix = false; systemtap_v_check = false; download_dbinfo = 0; suppress_handler_errors = false; native_build = true; // presumed sysroot = ""; update_release_sysroot = false; suppress_time_limits = false; color_mode = color_auto; color_errors = isatty(STDERR_FILENO) // conditions for coloring when && strcmp(getenv("TERM") ?: "notdumb", "dumb"); // on auto // PR12443: put compiled-in / -I paths in front, to be preferred during // tapset duplicate-file elimination const char* s_p = getenv ("SYSTEMTAP_TAPSET"); if (s_p != NULL) { include_path.push_back (s_p); } else { include_path.push_back (string(PKGDATADIR) + "/tapset"); } /* adding in the XDG_DATA_DIRS variable path, * this searches in conjunction with SYSTEMTAP_TAPSET * to locate stap scripts, either can be disabled if * needed using env $PATH=/dev/null where $PATH is the * path you want disabled */ const char* s_p1 = getenv ("XDG_DATA_DIRS"); if ( s_p1 != NULL ) { vector dirs; tokenize(s_p1, dirs, ":"); for(vector::iterator i = dirs.begin(); i != dirs.end(); ++i) { include_path.push_back(*i + "/systemtap/tapset"); } } const char* s_r = getenv ("SYSTEMTAP_RUNTIME"); if (s_r != NULL) runtime_path = s_r; else runtime_path = string(PKGDATADIR) + "/runtime"; const char* s_d = getenv ("SYSTEMTAP_DIR"); if (s_d != NULL) data_path = s_d; else data_path = get_home_directory() + string("/.systemtap"); if (create_dir(data_path.c_str()) == 1) { const char* e = strerror (errno); print_warning("failed to create systemtap data directory \"" + data_path + "\" " + e + ", disabling cache support."); use_cache = use_script_cache = false; } if (use_cache) { cache_path = data_path + "/cache"; if (create_dir(cache_path.c_str()) == 1) { const char* e = strerror (errno); print_warning("failed to create cache directory (\" " + cache_path + " \") " + e + ", disabling cache support."); use_cache = use_script_cache = false; } } const char* s_tc = getenv ("SYSTEMTAP_COVERAGE"); if (s_tc != NULL) tapset_compile_coverage = true; const char* s_kr = getenv ("SYSTEMTAP_RELEASE"); if (s_kr != NULL) { setup_kernel_release(s_kr); } create_tmp_dir(); } systemtap_session::systemtap_session (const systemtap_session& other, const string& arch, const string& kern): // NB: pointer members must be manually initialized! // NB: this needs to consider everything that the base ctor does, // plus copying any wanted implicit fields (strings, vectors, etc.) runtime_mode(other.runtime_mode), base_hash(0), pattern_root(new match_node), user_file (other.user_file), dfa_counter(0), be_derived_probes(0), dwarf_derived_probes(0), kprobe_derived_probes(0), hwbkpt_derived_probes(0), perf_derived_probes(0), uprobe_derived_probes(0), utrace_derived_probes(0), itrace_derived_probes(0), task_finder_derived_probes(0), timer_derived_probes(0), netfilter_derived_probes(0), profile_derived_probes(0), mark_derived_probes(0), tracepoint_derived_probes(0), hrtimer_derived_probes(0), procfs_derived_probes(0), dynprobe_derived_probes(0), java_derived_probes(0), op (0), up (0), sym_kprobes_text_start (0), sym_kprobes_text_end (0), sym_stext (0), module_cache (0), benchmark_sdt_loops(other.benchmark_sdt_loops), benchmark_sdt_threads(other.benchmark_sdt_threads), last_token (0) { release = kernel_release = kern; kernel_build_tree = "/lib/modules/" + kernel_release + "/build"; architecture = machine = normalize_machine(arch); setup_kernel_release(kern.c_str()); native_build = false; // assumed; XXX: could be computed as in check_options() // These are all copied in the same order as the default ctor did above. copy(other.perpass_verbose, other.perpass_verbose + 5, perpass_verbose); verbose = other.verbose; have_script = other.have_script; runtime_specified = other.runtime_specified; include_arg_start = other.include_arg_start; timing = other.timing; guru_mode = other.guru_mode; bulk_mode = other.bulk_mode; unoptimized = other.unoptimized; suppress_warnings = other.suppress_warnings; panic_warnings = other.panic_warnings; listing_mode = other.listing_mode; listing_mode_vars = other.listing_mode_vars; dump_probe_types = other.dump_probe_types; prologue_searching = other.prologue_searching; buffer_size = other.buffer_size; last_pass = other.last_pass; module_name = other.module_name; stapconf_name = other.stapconf_name; output_file = other.output_file; // XXX how should multiple remotes work? tmpdir_opt_set = false; save_module = other.save_module; modname_given = other.modname_given; keep_tmpdir = other.keep_tmpdir; cmd = other.cmd; target_pid = other.target_pid; // XXX almost surely nonsense for multiremote use_cache = other.use_cache; use_script_cache = other.use_script_cache; poison_cache = other.poison_cache; tapset_compile_coverage = other.tapset_compile_coverage; need_uprobes = false; need_unwind = false; need_symbols = false; uprobes_path = ""; consult_symtab = other.consult_symtab; load_only = other.load_only; skip_badvars = other.skip_badvars; privilege = other.privilege; privilege_set = other.privilege_set; omit_werror = other.omit_werror; compatible = other.compatible; unwindsym_ldd = other.unwindsym_ldd; client_options = other.client_options; server_cache = NULL; use_server_on_error = other.use_server_on_error; try_server_status = other.try_server_status; use_remote_prefix = other.use_remote_prefix; systemtap_v_check = other.systemtap_v_check; download_dbinfo = other.download_dbinfo; suppress_handler_errors = other.suppress_handler_errors; sysroot = other.sysroot; update_release_sysroot = other.update_release_sysroot; sysenv = other.sysenv; suppress_time_limits = other.suppress_time_limits; color_errors = other.color_errors; color_mode = other.color_mode; include_path = other.include_path; runtime_path = other.runtime_path; // NB: assuming that "other" created these already data_path = other.data_path; cache_path = other.cache_path; tapset_compile_coverage = other.tapset_compile_coverage; // These are fields that were left to their default ctor, but now we want to // copy them from "other". In the same order as declared... script_file = other.script_file; cmdline_script = other.cmdline_script; c_macros = other.c_macros; args = other.args; kbuildflags = other.kbuildflags; globalopts = other.globalopts; modinfos = other.modinfos; client_options_disallowed_for_unprivileged = other.client_options_disallowed_for_unprivileged; server_status_strings = other.server_status_strings; specified_servers = other.specified_servers; server_trust_spec = other.server_trust_spec; server_args = other.server_args; unwindsym_modules = other.unwindsym_modules; automatic_server_mode = other.automatic_server_mode; create_tmp_dir(); } systemtap_session::~systemtap_session () { remove_tmp_dir(); delete_map(subsessions); delete pattern_root; } const string systemtap_session::module_filename() const { if (runtime_usermode_p()) return module_name + ".so"; return module_name + ".ko"; } #if HAVE_NSS void systemtap_session::NSPR_init () { if (! NSPR_Initialized) { PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); NSPR_Initialized = true; } } #endif // HAVE_NSS systemtap_session* systemtap_session::clone(const string& arch, const string& release) { const string norm_arch = normalize_machine(arch); if (this->architecture == norm_arch && this->kernel_release == release) return this; systemtap_session*& s = subsessions[make_pair(norm_arch, release)]; if (!s) s = new systemtap_session(*this, norm_arch, release); return s; } void systemtap_session::version () { clog << _F("Systemtap translator/driver (version %s/%s, %s)\n" "Copyright (C) 2005-2013 Red Hat, Inc. and others\n" "This is free software; see the source for copying conditions.", VERSION, dwfl_version(NULL), STAP_EXTENDED_VERSION) << endl; clog << _("enabled features:") #ifdef HAVE_AVAHI << " AVAHI" #endif #ifdef HAVE_LIBRPM << " LIBRPM" #endif #ifdef HAVE_LIBSQLITE3 << " LIBSQLITE3" #endif #ifdef HAVE_NSS << " NSS" #endif #ifdef HAVE_BOOST_SHARED_PTR_HPP << " BOOST_SHARED_PTR" #endif #ifdef HAVE_TR1_UNORDERED_MAP << " TR1_UNORDERED_MAP" #endif #ifdef ENABLE_PROLOGUES << " PROLOGUES" #endif #ifdef ENABLE_NLS << " NLS" #endif #ifdef HAVE_DYNINST << " DYNINST" #endif #ifdef HAVE_JAVA << " JAVA" #endif << endl; } void systemtap_session::usage (int exitcode) { // For error cases, just suggest --help, so we don't obscure // the actual error message with all the help text. if (exitcode != EXIT_SUCCESS) { clog << _("Try '--help' for more information.") << endl; throw exit_exception(exitcode); } version (); clog << endl << _F("Usage: stap [options] FILE Run script in file.\n" " or: stap [options] - Run script on stdin.\n" " or: stap [options] -e SCRIPT Run given script.\n" " or: stap [options] -l PROBE List matching probes.\n" " or: stap [options] -L PROBE List matching probes and local variables.\n\n" "Options (in %s/rc and on command line):\n" " -- end of translator options, script options follow\n" " -h --help show help\n" " -V --version show version\n" " -p NUM stop after pass NUM 1-5, instead of %d\n" " (parse, elaborate, translate, compile, run)\n" " -v add verbosity to all passes\n" " --vp {N}+ add per-pass verbosity [", data_path.c_str(), last_pass); for (unsigned i=0; i<5; i++) clog << (perpass_verbose[i] <= 9 ? perpass_verbose[i] : 9); clog << "]" << endl; clog << _F(" -k keep temporary directory\n" " -u unoptimized translation %s\n" " -w suppress warnings %s\n" " -W turn warnings into errors %s\n" " -g guru mode %s\n" " -P prologue-searching for function probes %s\n" " -b bulk (percpu file) mode %s\n" " -s NUM buffer size in megabytes, instead of %d\n" " -I DIR look in DIR for additional .stp script files", (unoptimized ? _(" [set]") : ""), (suppress_warnings ? _(" [set]") : ""), (panic_warnings ? _(" [set]") : ""), (guru_mode ? _(" [set]") : ""), (prologue_searching ? _(" [set]") : ""), (bulk_mode ? _(" [set]") : ""), buffer_size); if (include_path.size() == 0) clog << endl; else clog << _(", in addition to") << endl; for (unsigned i=0; i syms (unwindsym_modules.begin(), unwindsym_modules.end()); for (unsigned i=0; i\n" " --dump-probe-types\n" " show a list of available probe types.\n" " --sysroot=DIR\n" " specify sysroot directory where target files (executables,\n" " libraries, etc.) are located.\n" " --sysenv=VAR=VALUE\n" " provide an alternate value for an environment variable\n" " where the value on a remote system differs. Path\n" " variables (e.g. PATH, LD_LIBRARY_PATH) are assumed to be\n" " relative to the sysroot.\n" " --suppress-time-limits\n" " disable -DSTP_NO_OVERLOAD -DMAXACTION and -DMAXTRYACTION limits\n" , compatible.c_str()) << endl ; time_t now; time (& now); struct tm* t = localtime (& now); if (t && t->tm_mon*3 + t->tm_mday*173 == 0xb6) clog << morehelp << endl; throw exit_exception (exitcode); } int systemtap_session::parse_cmdline (int argc, char * const argv []) { client_options_disallowed_for_unprivileged = ""; struct rlimit our_rlimit; while (true) { char * num_endptr; int grc = getopt_long (argc, argv, STAP_SHORT_OPTIONS, stap_long_options, NULL); // NB: when adding new options, consider very carefully whether they // should be restricted from stap clients (after --client-options)! if (grc < 0) break; switch (grc) { case 'V': version (); throw exit_exception (EXIT_SUCCESS); case 'v': server_args.push_back (string ("-") + (char)grc); for (unsigned i=0; i<5; i++) perpass_verbose[i] ++; verbose ++; break; case 'G': // Make sure the global option is only composed of the // following chars: [_=a-zA-Z0-9] assert_regexp_match("-G parameter", optarg, "^[a-z_][a-z0-9_]*=[a-z0-9_-]+$"); globalopts.push_back (string(optarg)); break; case 't': server_args.push_back (string ("-") + (char)grc); timing = true; break; case 'w': server_args.push_back (string ("-") + (char)grc); suppress_warnings = true; break; case 'W': server_args.push_back (string ("-") + (char)grc); panic_warnings = true; break; case 'p': last_pass = (int)strtoul(optarg, &num_endptr, 10); if (*num_endptr != '\0' || last_pass < 1 || last_pass > 5) { cerr << _("Invalid pass number (should be 1-5).") << endl; return 1; } if (listing_mode && last_pass != 2) { cerr << _("Listing (-l) mode implies pass 2.") << endl; return 1; } server_args.push_back (string ("-") + (char)grc + optarg); break; case 'I': if (client_options) client_options_disallowed_for_unprivileged += client_options_disallowed_for_unprivileged.empty () ? "-I" : ", -I"; if (include_arg_start == -1) include_arg_start = include_path.size (); include_path.push_back (string (optarg)); break; case 'd': server_args.push_back (string ("-") + (char)grc + optarg); { // Make sure an empty data object wasn't specified (-d "") if (strlen (optarg) == 0) { cerr << _("Data object (-d) cannot be empty.") << endl; return 1; } // At runtime user module names are resolved through their // canonical (absolute) path. const char *mpath = canonicalize_file_name (optarg); if (mpath == NULL) // Must be a kernel module name mpath = optarg; unwindsym_modules.insert (string (mpath)); // NB: we used to enable_vma_tracker() here for PR10228, but now // we'll leave that to pragma:vma functions which actually use it. break; } case 'e': if (have_script) { cerr << _("Only one script can be given on the command line.") << endl; return 1; } server_args.push_back (string ("-") + (char)grc + optarg); cmdline_script = string (optarg); have_script = true; break; case 'o': // NB: client_options not a problem, since pass 1-4 does not use output_file. server_args.push_back (string ("-") + (char)grc + optarg); output_file = string (optarg); break; case 'R': if (client_options) { cerr << _F("ERROR: %s invalid with %s", "-R", "--client-options") << endl; return 1; } runtime_specified = true; runtime_path = string (optarg); break; case 'm': if (client_options) client_options_disallowed_for_unprivileged += client_options_disallowed_for_unprivileged.empty () ? "-m" : ", -m"; module_name = string (optarg); save_module = true; modname_given = true; { // If the module name ends with '.ko', chop it off since // modutils doesn't like modules named 'foo.ko.ko'. if (endswith(module_name, ".ko") || endswith(module_name, ".so")) { module_name.erase(module_name.size() - 3); cerr << _F("Truncating module name to '%s'", module_name.c_str()) << endl; } // Make sure an empty module name wasn't specified (-m "") if (module_name.empty()) { cerr << _("Module name cannot be empty.") << endl; return 1; } // Make sure the module name is only composed of the // following chars: [a-z0-9_] assert_regexp_match("-m parameter", module_name, "^[a-z0-9_]+$"); // Make sure module name isn't too long. if (module_name.size() >= (MODULE_NAME_LEN - 1)) { module_name.resize(MODULE_NAME_LEN - 1); cerr << _F("Truncating module name to '%s'", module_name.c_str()) << endl; } } server_args.push_back (string ("-") + (char)grc + optarg); use_script_cache = false; break; case 'r': if (client_options) // NB: no paths! assert_regexp_match("-r parameter from client", optarg, "^[a-z0-9_.-]+$"); server_args.push_back (string ("-") + (char)grc + optarg); setup_kernel_release(optarg); break; case 'a': assert_regexp_match("-a parameter", optarg, "^[a-z0-9_-]+$"); server_args.push_back (string ("-") + (char)grc + optarg); architecture = string(optarg); break; case 'k': if (client_options) { cerr << _F("ERROR: %s invalid with %s", "-k", "--client-options") << endl; return 1; } keep_tmpdir = true; use_script_cache = false; /* User wants to keep a usable build tree. */ break; case 'g': server_args.push_back (string ("-") + (char)grc); guru_mode = true; break; case 'P': server_args.push_back (string ("-") + (char)grc); prologue_searching = true; break; case 'b': server_args.push_back (string ("-") + (char)grc); bulk_mode = true; break; case 'u': server_args.push_back (string ("-") + (char)grc); unoptimized = true; break; case 's': buffer_size = (int) strtoul (optarg, &num_endptr, 10); if (*num_endptr != '\0' || buffer_size < 1 || buffer_size > 4095) { cerr << _("Invalid buffer size (should be 1-4095).") << endl; return 1; } server_args.push_back (string ("-") + (char)grc + optarg); break; case 'c': cmd = string (optarg); if (cmd == "") { // This would mess with later code deciding to pass -c // through to staprun cerr << _("Empty CMD string invalid.") << endl; return 1; } server_args.push_back (string ("-") + (char)grc + optarg); break; case 'x': target_pid = (int) strtoul(optarg, &num_endptr, 10); if (*num_endptr != '\0') { cerr << _("Invalid target process ID number.") << endl; return 1; } server_args.push_back (string ("-") + (char)grc + optarg); break; case 'D': assert_regexp_match ("-D parameter", optarg, "^[a-z_][a-z_0-9]*(=-?[a-z_0-9]+)?$"); if (client_options) client_options_disallowed_for_unprivileged += client_options_disallowed_for_unprivileged.empty () ? "-D" : ", -D"; server_args.push_back (string ("-") + (char)grc + optarg); c_macros.push_back (string (optarg)); break; case 'S': assert_regexp_match ("-S parameter", optarg, "^[0-9]+(,[0-9]+)?$"); server_args.push_back (string ("-") + (char)grc + optarg); size_option = string (optarg); break; case 'q': if (client_options) { cerr << _F("ERROR: %s invalid with %s", "-q", "--client-options") << endl; return 1; } server_args.push_back (string ("-") + (char)grc); tapset_compile_coverage = true; break; case 'h': usage (0); break; case 'L': listing_mode_vars = true; unoptimized = true; // This causes retention of variables for listing_mode // fallthrough case 'l': suppress_warnings = true; listing_mode = true; last_pass = 2; if (have_script) { cerr << _("Only one script can be given on the command line.") << endl; return 1; } server_args.push_back (string ("-") + (char)grc + optarg); cmdline_script = string("probe ") + string(optarg) + " {}"; have_script = true; break; case 'F': server_args.push_back (string ("-") + (char)grc); load_only = true; break; case 'B': if (client_options) { cerr << _F("ERROR: %s invalid with %s", "-B", "--client-options") << endl; return 1; } server_args.push_back (string ("-") + (char)grc + optarg); kbuildflags.push_back (string (optarg)); break; case LONG_OPT_VERSION: version (); throw exit_exception (EXIT_SUCCESS); case LONG_OPT_VERBOSE_PASS: { bool ok = true; if (strlen(optarg) < 1 || strlen(optarg) > 5) ok = false; if (ok) for (unsigned i=0; i 0) download_dbinfo = atoi(optarg); //Enable, Set timeout to optarg else if (strcmp(optarg, "ask") == 0) download_dbinfo = -1; //Enable, Ask for confirmation else { cerr << _F("ERROR: %s is not a valid value. Use 'yes', 'no', 'ask' or a timeout value.", optarg) << endl; return 1; } } else download_dbinfo = INT_MAX; //Enable, No Timeout break; case LONG_OPT_USE_SERVER: if (client_options) { cerr << _F("ERROR: %s is invalid with %s", "--use-server", "--client-options") << endl; return 1; } if (optarg) specified_servers.push_back (optarg); else specified_servers.push_back (""); break; case LONG_OPT_USE_SERVER_ON_ERROR: if (client_options) { cerr << _F("ERROR: %s is invalid with %s", "--use-server-on-error", "--client-options") << endl; return 1; } if (optarg) { string arg = optarg; for (unsigned i = 0; i < arg.size (); ++i) arg[i] = tolower (arg[i]); if (arg == "yes" || arg == "ye" || arg == "y") use_server_on_error = true; else if (arg == "no" || arg == "n") use_server_on_error = false; else cerr << _F("Invalid argument '%s' for --use-server-on-error.", optarg) << endl; } else use_server_on_error = true; break; case LONG_OPT_LIST_SERVERS: if (client_options) { cerr << _F("ERROR: %s is invalid with %s", "--list-servers", "--client-options") << endl; return 1; } if (optarg) server_status_strings.push_back (optarg); else server_status_strings.push_back (""); break; case LONG_OPT_TRUST_SERVERS: if (client_options) { cerr << _F("ERROR: %s is invalid with %s", "--trust-servers", "--client-options") << endl; return 1; } if (optarg) server_trust_spec = optarg; else server_trust_spec = "ssl"; break; case LONG_OPT_HELP: usage (0); break; // The caching options should not be available to server clients case LONG_OPT_DISABLE_CACHE: if (client_options) { cerr << _F("ERROR: %s is invalid with %s", "--disable-cache", "--client-options") << endl; return 1; } use_cache = use_script_cache = false; break; case LONG_OPT_POISON_CACHE: if (client_options) { cerr << _F("ERROR: %s is invalid with %s", "--poison-cache", "--client-options") << endl; return 1; } poison_cache = true; break; case LONG_OPT_CLEAN_CACHE: if (client_options) { cerr << _F("ERROR: %s is invalid with %s", "--clean-cache", "--client-options") << endl; return 1; } clean_cache(*this); throw exit_exception(EXIT_SUCCESS); case LONG_OPT_COMPATIBLE: server_args.push_back ("--compatible=" + string(optarg)); if (strverscmp(optarg, VERSION) > 0) { cerr << _F("ERROR: systemtap version %s cannot be compatible with future version %s", VERSION, optarg) << endl; return 1; } compatible = optarg; break; case LONG_OPT_LDD: if (client_options) { cerr << _F("ERROR: %s is invalid with %s", "--ldd", "--client-options") << endl; return 1; } unwindsym_ldd = true; break; case LONG_OPT_ALL_MODULES: if (client_options) { cerr << _F("ERROR: %s is invalid with %s", "--all-modules", "--client-options") << endl; return 1; } insert_loaded_modules(); break; case LONG_OPT_REMOTE: if (client_options) { cerr << _F("ERROR: %s is invalid with %s", "--remote", "--client-options") << endl; return 1; } remote_uris.push_back(optarg); break; case LONG_OPT_REMOTE_PREFIX: if (client_options) { cerr << _F("ERROR: %s is invalid with %s", "--remote-prefix", "--client-options") << endl; return 1; } use_remote_prefix = true; break; case LONG_OPT_CHECK_VERSION: server_args.push_back ("--check-version"); systemtap_v_check = true; break; case LONG_OPT_DUMP_PROBE_TYPES: server_args.push_back ("--dump-probe-types"); dump_probe_types = true; break; case LONG_OPT_SUPPRESS_HANDLER_ERRORS: suppress_handler_errors = true; break; case LONG_OPT_MODINFO: // Make sure the global option is only composed of the // following chars: [_=a-zA-Z0-9] if (client_options) { cerr << _F("ERROR: %s is invalid with %s", "--modinfo", "--client-options") << endl; return 1; } assert_regexp_match("--modinfo parameter", optarg, "^[a-z_][a-z0-9_]*=.+$"); modinfos.push_back (string(optarg)); break; case LONG_OPT_RLIMIT_AS: if(getrlimit(RLIMIT_AS, & our_rlimit)) cerr << _F("Unable to obtain resource limits for rlimit_as : %s", strerror (errno)) << endl; our_rlimit.rlim_max = our_rlimit.rlim_cur = strtoul (optarg, &num_endptr, 0); if(*num_endptr || setrlimit (RLIMIT_AS, & our_rlimit)) cerr << _F("Unable to set resource limits for rlimit_as : %s", strerror (errno)) << endl; /* Disable core dumps, since exhaustion results in uncaught bad_alloc etc. exceptions */ our_rlimit.rlim_max = our_rlimit.rlim_cur = 0; (void) setrlimit (RLIMIT_CORE, & our_rlimit); break; case LONG_OPT_RLIMIT_CPU: if(getrlimit(RLIMIT_CPU, & our_rlimit)) cerr << _F("Unable to obtain resource limits for rlimit_cpu : %s", strerror (errno)) << endl; our_rlimit.rlim_max = our_rlimit.rlim_cur = strtoul (optarg, &num_endptr, 0); if(*num_endptr || setrlimit (RLIMIT_CPU, & our_rlimit)) cerr << _F("Unable to set resource limits for rlimit_cpu : %s", strerror (errno)) << endl; break; case LONG_OPT_RLIMIT_NPROC: if(getrlimit(RLIMIT_NPROC, & our_rlimit)) cerr << _F("Unable to obtain resource limits for rlimit_nproc : %s", strerror (errno)) << endl; our_rlimit.rlim_max = our_rlimit.rlim_cur = strtoul (optarg, &num_endptr, 0); if(*num_endptr || setrlimit (RLIMIT_NPROC, & our_rlimit)) cerr << _F("Unable to set resource limits for rlimit_nproc : %s", strerror (errno)) << endl; break; case LONG_OPT_RLIMIT_STACK: if(getrlimit(RLIMIT_STACK, & our_rlimit)) cerr << _F("Unable to obtain resource limits for rlimit_stack : %s", strerror (errno)) << endl; our_rlimit.rlim_max = our_rlimit.rlim_cur = strtoul (optarg, &num_endptr, 0); if(*num_endptr || setrlimit (RLIMIT_STACK, & our_rlimit)) cerr << _F("Unable to set resource limits for rlimit_stack : %s", strerror (errno)) << endl; /* Disable core dumps, since exhaustion results in SIGSEGV */ our_rlimit.rlim_max = our_rlimit.rlim_cur = 0; (void) setrlimit (RLIMIT_CORE, & our_rlimit); break; case LONG_OPT_RLIMIT_FSIZE: if(getrlimit(RLIMIT_FSIZE, & our_rlimit)) cerr << _F("Unable to obtain resource limits for rlimit_fsize : %s", strerror (errno)) << endl; our_rlimit.rlim_max = our_rlimit.rlim_cur = strtoul (optarg, &num_endptr, 0); if(*num_endptr || setrlimit (RLIMIT_FSIZE, & our_rlimit)) cerr << _F("Unable to set resource limits for rlimit_fsize : %s", strerror (errno)) << endl; break; case LONG_OPT_SYSROOT: if (client_options) { cerr << _F("ERROR: %s invalid with %s", "--sysroot", "--client-options") << endl; return 1; } else if (!sysroot.empty()) { cerr << "ERROR: multiple --sysroot options not supported" << endl; return 1; } else { const char *spath = canonicalize_file_name (optarg); if (spath == NULL) { cerr << _F("ERROR: %s is an invalid directory for --sysroot", optarg) << endl; return 1; } sysroot = string(spath); if (sysroot[sysroot.size() - 1] != '/') sysroot.append("/"); break; } case LONG_OPT_SYSENV: if (client_options) { cerr << _F("ERROR: %s invalid with %s", "--sysenv", "--client-options") << endl; return 1; } else { string sysenv_str = optarg; string value; size_t pos; if (sysroot.empty()) { cerr << "ERROR: --sysenv must follow --sysroot" << endl; return 1; } pos = sysenv_str.find("="); if (pos == string::npos) { cerr << _F("ERROR: %s is an invalid argument for --sysenv", optarg) << endl; return 1; } value = sysenv_str.substr(pos + 1); sysenv[sysenv_str.substr(0, pos)] = value; break; } case LONG_OPT_SUPPRESS_TIME_LIMITS: //require guru_mode to use if (guru_mode == false) { cerr << _F("ERROR %s requires guru mode (-g)", "--suppress-time-limits") << endl; return 1; } else { suppress_time_limits = true; server_args.push_back (string ("--suppress-time-limits")); c_macros.push_back (string ("STAP_SUPPRESS_TIME_LIMITS_ENABLE")); break; } case LONG_OPT_RUNTIME: if (!parse_cmdline_runtime (optarg)) return 1; break; case LONG_OPT_RUNTIME_DYNINST: if (!parse_cmdline_runtime ("dyninst")) return 1; break; case LONG_OPT_BENCHMARK_SDT_LOOPS: // XXX This option is secret, not supported, subject to change at our whim benchmark_sdt_loops = strtoul(optarg, NULL, 10); break; case LONG_OPT_BENCHMARK_SDT_THREADS: // XXX This option is secret, not supported, subject to change at our whim benchmark_sdt_threads = strtoul(optarg, NULL, 10); break; case LONG_OPT_COLOR_ERRS: // --color without arg is equivalent to always if (!optarg || !strcmp(optarg, "always")) color_mode = color_always; else if (!strcmp(optarg, "auto")) color_mode = color_auto; else if (!strcmp(optarg, "never")) color_mode = color_never; else { cerr << _F("Invalid argument '%s' for --color.", optarg) << endl; return 1; } color_errors = color_mode == color_always || (color_mode == color_auto && isatty(STDERR_FILENO) && strcmp(getenv("TERM") ?: "notdumb", "dumb")); break; case '?': // Invalid/unrecognized option given or argument required, but // not given. In both cases getopt_long() will have printed the // appropriate error message to stderr already. usage(1); break; default: // NOTREACHED unless one added a getopt option but not a corresponding case: cerr << _F("Unhandled argument code %d", (char)grc) << endl; return 1; break; } } return 0; } bool systemtap_session::parse_cmdline_runtime (const string& opt_runtime) { if (opt_runtime == string("kernel")) runtime_mode = kernel_runtime; else if (opt_runtime == string("dyninst")) { #ifndef HAVE_DYNINST cerr << _("ERROR: --runtime=dyninst unavailable; this build lacks DYNINST feature") << endl; version(); return false; #endif if (privilege_set && pr_unprivileged != privilege) { cerr << _("ERROR: --runtime=dyninst implies unprivileged mode only") << endl; return false; } privilege = pr_unprivileged; privilege_set = true; runtime_mode = dyninst_runtime; } else { cerr << _F("ERROR: %s is an invalid argument for --runtime", opt_runtime.c_str()) << endl; return false; } return true; } void systemtap_session::check_options (int argc, char * const argv []) { for (int i = optind; i < argc; i++) { if (! have_script) { script_file = string (argv[i]); have_script = true; } else args.push_back (string (argv[i])); } // We don't need a script with --list-servers, --trust-servers, or --dump-probe-types. bool need_script = server_status_strings.empty () && server_trust_spec.empty () && ! dump_probe_types; if (benchmark_sdt_loops > 0 || benchmark_sdt_threads > 0) { // Secret benchmarking options are for local use only, not servers or --remote if (client_options || !remote_uris.empty()) { cerr << _("Benchmark options are only for local use.") << endl; usage(1); } // Fill defaults if either is unset. if (benchmark_sdt_loops == 0) benchmark_sdt_loops = 10000000; if (benchmark_sdt_threads == 0) benchmark_sdt_threads = 1; need_script = false; } // need a user file // NB: this is also triggered if stap is invoked with no arguments at all if (need_script && ! have_script) { cerr << _("A script must be specified.") << endl; usage(1); } #if ! HAVE_NSS if (client_options) print_warning("--client-options is not supported by this version of systemtap"); if (! server_status_strings.empty ()) { print_warning("--list-servers is not supported by this version of systemtap"); server_status_strings.clear (); } if (! server_trust_spec.empty ()) { print_warning("--trust-servers is not supported by this version of systemtap"); server_trust_spec.clear (); } #endif if (runtime_specified && ! specified_servers.empty ()) { print_warning("Ignoring --use-server due to the use of -R"); specified_servers.clear (); } if (client_options && last_pass > 4) { last_pass = 4; /* Quietly downgrade. Server passed through -p5 naively. */ } // If phase 5 has been requested, automatically adjust the --privilege setting to match the // user's actual privilege level and add --use-server, if necessary. // Do this only if we have a script and we are not the server. // Also do this only if we're running in the kernel (e.g. not --runtime=dyninst) // XXX Eventually we could check remote hosts, but disable that case for now. if (last_pass > 4 && have_script && ! client_options && runtime_mode == kernel_runtime && remote_uris.empty()) { // What is the user's privilege level? privilege_t credentials = get_privilege_credentials (); // Don't alter specifically-requested privilege levels if (! privilege_set && ! pr_contains (credentials, privilege)) { // We do not have the default privilege credentials (stapdev). Lower // the privilege level to match our credentials. if (pr_contains (credentials, pr_stapsys)) { if (perpass_verbose[0] > 1) cerr << _("Using --privilege=stapsys for member of the group stapsys") << endl; privilege = pr_stapsys; server_args.push_back ("--privilege=stapsys"); } else if (pr_contains (credentials, pr_stapusr)) { if (perpass_verbose[0] > 1) cerr << _("Using --privilege=stapusr for member of the group stapusr") << endl; privilege = pr_stapusr; server_args.push_back ("--privilege=stapusr"); } else { // Completely unprivileged user. cerr << _("You are trying to run systemtap as a normal user.\n" "You should either be root, or be part of " "the group \"stapusr\" and possibly one of the groups \"stapsys\" or \"stapdev\".\n"); #if HAVE_DYNINST cerr << _("Alternatively, you may specify --runtime=dyninst for userspace probing.\n"); #endif usage (1); // does not return. } } // Add --use-server if not already specified and the user's (lack of) credentials require // it for pass 5. if (! pr_contains (credentials, pr_stapdev)) { if (specified_servers.empty ()) { if (perpass_verbose[0] > 1) cerr << _F("Using --use-server for user with privilege level %s", pr_name (privilege)) << endl; specified_servers.push_back (""); } } } if (client_options && ! pr_contains (privilege, pr_stapdev) && ! client_options_disallowed_for_unprivileged.empty ()) { cerr << _F("You can't specify %s when --privilege=%s is specified.", client_options_disallowed_for_unprivileged.c_str(), pr_name (privilege)) << endl; usage (1); } if ((cmd != "") && (target_pid)) { cerr << _F("You can't specify %s and %s together.", "-c", "-x") << endl; usage (1); } // NB: In user-mode runtimes (dyninst), we can allow guru mode any time, but we // need to restrict guru by privilege level in the kernel runtime. if (! runtime_usermode_p () && ! pr_contains (privilege, pr_stapdev) && guru_mode) { cerr << _F("You can't specify %s and --privilege=%s together.", "-g", pr_name (privilege)) << endl; usage (1); } // Can't use --remote and --tmpdir together because with --remote, // there may be more than one tmpdir needed. if (!remote_uris.empty() && tmpdir_opt_set) { cerr << _F("You can't specify %s and %s together.", "--remote", "--tmpdir") << endl; usage(1); } // Warn in case the target kernel release doesn't match the running one. native_build = (release == kernel_release && machine == architecture); // NB: squashed ARCH by PR4186 logic // Non-native builds can't be loaded locally, but may still work on remotes if (last_pass > 4 && !native_build && remote_uris.empty()) { print_warning("kernel release/architecture mismatch with host forces last-pass 4."); last_pass = 4; } if(download_dbinfo != 0 && access ("/usr/bin/abrt-action-install-debuginfo-to-abrt-cache", X_OK) < 0 && access ("/usr/libexec/abrt-action-install-debuginfo-to-abrt-cache", X_OK) < 0) { print_warning("abrt-action-install-debuginfo-to-abrt-cache is not installed. Continuing without downloading debuginfo."); download_dbinfo = 0; } // translate path of runtime to absolute path if (runtime_path[0] != '/') { char cwd[PATH_MAX]; if (getcwd(cwd, sizeof(cwd))) { runtime_path = string(cwd) + "/" + runtime_path; } } // Abnormal characters in our temp path can break us, including parts out // of our control like Kbuild. Let's enforce nice, safe characters only. const char *tmpdir = getenv("TMPDIR"); if (tmpdir != NULL) assert_regexp_match("TMPDIR", tmpdir, "^[-/._0-9a-z]+$"); } int systemtap_session::parse_kernel_config () { // PR10702: pull config options string kernel_config_file = kernel_build_tree + "/.config"; struct stat st; int rc = stat(kernel_config_file.c_str(), &st); if (rc != 0) { clog << _F("Checking \"%s\" failed with error: %s", kernel_config_file.c_str(), strerror(errno)) << endl; find_devel_rpms(*this, kernel_build_tree.c_str()); missing_rpm_list_print(*this, "-devel"); return rc; } ifstream kcf (kernel_config_file.c_str()); string line; while (getline (kcf, line)) { if (!startswith(line, "CONFIG_")) continue; size_t off = line.find('='); if (off == string::npos) continue; string key = line.substr(0, off); string value = line.substr(off+1, string::npos); kernel_config[key] = value; } if (verbose > 2) clog << _F("Parsed kernel \"%s\", ", kernel_config_file.c_str()) << _NF("containing %zu tuple", "containing %zu tuples", kernel_config.size(), kernel_config.size()) << endl; kcf.close(); return 0; } int systemtap_session::parse_kernel_exports () { string kernel_exports_file = kernel_build_tree + "/Module.symvers"; struct stat st; int rc = stat(kernel_exports_file.c_str(), &st); if (rc != 0) { clog << _F("Checking \"%s\" failed with error: %s\nEnsure kernel development headers & makefiles are installed", kernel_exports_file.c_str(), strerror(errno)) << endl; return rc; } ifstream kef (kernel_exports_file.c_str()); string line; while (getline (kef, line)) { vector tokens; tokenize (line, tokens, "\t"); if (tokens.size() == 4 && tokens[2] == "vmlinux" && tokens[3].substr(0,13) == string("EXPORT_SYMBOL")) kernel_exports.insert (tokens[1]); // RHEL4 Module.symvers file only has 3 tokens. No // 'EXPORT_SYMBOL' token at the end of the line. else if (tokens.size() == 3 && tokens[2] == "vmlinux") kernel_exports.insert (tokens[1]); } if (verbose > 2) clog << _NF("Parsed kernel %s, which contained one vmlinux export", "Parsed kernel %s, which contained %zu vmlinux exports", kernel_exports.size(), kernel_exports_file.c_str(), kernel_exports.size()) << endl; kef.close(); return 0; } int systemtap_session::parse_kernel_functions () { string system_map_path = kernel_build_tree + "/System.map"; ifstream system_map; system_map.open(system_map_path.c_str(), ifstream::in); if (! system_map.is_open()) { if (verbose > 1) clog << _F("Kernel symbol table %s unavailable, (%s)", system_map_path.c_str(), strerror(errno)) << endl; string system_map_path2 = "/boot/System.map-" + kernel_release; system_map.clear(); system_map.open(system_map_path2.c_str(), ifstream::in); if (! system_map.is_open()) { if (verbose > 1) clog << _F("Kernel symbol table %s unavailable, (%s)", system_map_path2.c_str(), strerror(errno)) << endl; } } string address, type, name; while (system_map.good()) { system_map >> address >> type >> name; if (verbose > 3) clog << "'" << address << "' '" << type << "' '" << name << "'" << endl; // 'T'/'t' are text code symbols if (type != "t" && type != "T") continue; #ifdef __powerpc__ // XXX cross-compiling hazard // Map ".sys_foo" to "sys_foo". if (name[0] == '.') name.erase(0, 1); #endif // FIXME: better things to do here - look for _stext before // remembering symbols. Also: // - stop remembering names at ??? // - what about __kprobes_text_start/__kprobes_text_end? kernel_functions.insert(name); } system_map.close(); return 0; } void systemtap_session::init_try_server () { #if HAVE_NSS // If the option is disabled or we are a server or we are already using a // server, then never retry compilation using a server. if (! use_server_on_error || client_options || ! specified_servers.empty ()) try_server_status = dont_try_server; else try_server_status = try_server_unset; #else // No client, so don't bother. try_server_status = dont_try_server; #endif } void systemtap_session::set_try_server (int t) { if (try_server_status != dont_try_server) try_server_status = t; } void systemtap_session::insert_loaded_modules() { char line[1024]; ifstream procmods ("/proc/modules"); while (procmods.good()) { procmods.getline (line, sizeof(line)); strtok(line, " \t"); if (line[0] == '\0') break; // maybe print a warning? unwindsym_modules.insert (string (line)); } procmods.close(); unwindsym_modules.insert ("kernel"); } void systemtap_session::setup_kernel_release (const char* kstr) { // Sometimes we may get dupes here... e.g. a server may have a full // -r /path/to/kernel followed by a client's -r kernel. if (kernel_release == kstr) return; // nothing new here... kernel_release = kernel_build_tree = kernel_source_tree = ""; if (kstr[0] == '/') // fully specified path { kernel_build_tree = kstr; kernel_release = kernel_release_from_build_tree (kernel_build_tree, verbose); // PR10745 // Maybe it's a full kernel source tree, for purposes of PR10745. // In case CONFIG_DEBUG_INFO was set, we'd find it anyway with the // normal search in tapsets.cxx. Without CONFIG_DEBUG_INFO, we'd // need heuristics such as this one: string some_random_source_only_file = kernel_build_tree + "/COPYING"; ifstream epic (some_random_source_only_file.c_str()); if (! epic.fail()) { kernel_source_tree = kernel_build_tree; if (verbose > 2) clog << _F("Located kernel source tree (COPYING) at '%s'", kernel_source_tree.c_str()) << endl; } } else { update_release_sysroot = true; kernel_release = string (kstr); if (!kernel_release.empty()) kernel_build_tree = "/lib/modules/" + kernel_release + "/build"; // PR10745 // Let's not look for the kernel_source_tree; it's definitely // not THERE. tapsets.cxx might try to find it later if tracepoints // need it. } } // Register all the aliases we've seen in library files, and the user // file, as patterns. void systemtap_session::register_library_aliases() { vector files(library_files); files.push_back(user_file); for (unsigned f = 0; f < files.size(); ++f) { stapfile * file = files[f]; for (unsigned a = 0; a < file->aliases.size(); ++a) { probe_alias * alias = file->aliases[a]; try { for (unsigned n = 0; n < alias->alias_names.size(); ++n) { probe_point * name = alias->alias_names[n]; match_node * mn = pattern_root; for (unsigned c = 0; c < name->components.size(); ++c) { probe_point::component * comp = name->components[c]; // XXX: alias parameters if (comp->arg) throw semantic_error(_F("alias component %s contains illegal parameter", comp->functor.c_str())); mn = mn->bind(comp->functor); } // PR 12916: All probe aliases are OK for all users. The actual // referenced probe points will be checked when the alias is resolved. mn->bind_privilege (pr_all); mn->bind(new alias_expansion_builder(alias)); } } catch (const semantic_error& e) { semantic_error* er = new semantic_error (_("while registering probe alias"), alias->tok); er->chain = & e; print_error (* er); delete er; } } } } // Print this given token, but abbreviate it if the last one had the // same file name. void systemtap_session::print_token (ostream& o, const token* tok) { assert (tok); if (last_token && last_token->location.file == tok->location.file) { stringstream tmpo; tmpo << *tok; string ts = tmpo.str(); // search & replace the file name with nothing size_t idx = ts.find (tok->location.file->name); if (idx != string::npos) { ts.erase(idx, tok->location.file->name.size()); // remove path if (color_errors) { string src = ts.substr(idx); // keep line & col ts.erase(idx); // remove from output string ts += colorize(src, "source"); // re-add it colorized } } o << ts; } else o << colorize(*tok); last_token = tok; } void systemtap_session::print_error (const semantic_error& e) { string message_str[2]; string align_semantic_error (" "); // We generate two messages. The second one ([1]) is printed // without token compression, for purposes of duplicate elimination. // This way, the same message that may be generated once with a // compressed and once with an uncompressed token still only gets // printed once. for (int i=0; i<2; i++) { stringstream message; message << colorize(_("semantic error:"), "error") << ' ' << e.what (); if (e.tok1 || e.tok2) message << ": "; if (e.tok1) { if (i == 0) { print_token (message, e.tok1); message << endl; print_error_source (message, align_semantic_error, e.tok1); } else message << *e.tok1; } if (e.tok2) { if (i == 0) { print_token (message, e.tok2); message << endl; print_error_source (message, align_semantic_error, e.tok2); } else message << *e.tok2; } message << endl; message_str[i] = message.str(); } // skip error message printing for listing mode with low verbosity if (this->listing_mode && this->verbose <= 1) { seen_errors.insert (message_str[1]); // increment num_errors() return; } // Duplicate elimination if (seen_errors.find (message_str[1]) == seen_errors.end()) { seen_errors.insert (message_str[1]); cerr << message_str[0]; } if (e.chain) print_error (* e.chain); } void systemtap_session::print_error_source (std::ostream& message, std::string& align, const token* tok) { unsigned i = 0; assert (tok); if (!tok->location.file) //No source to print, silently exit return; unsigned line = tok->location.line; unsigned col = tok->location.column; const string &file_contents = tok->location.file->file_contents; size_t start_pos = 0, end_pos = 0; //Navigate to the appropriate line while (i != line && end_pos != std::string::npos) { start_pos = end_pos; end_pos = file_contents.find ('\n', start_pos) + 1; i++; } //TRANSLATORS: Here we are printing the source string of the error message << align << _("source: "); string srcline = file_contents.substr(start_pos, end_pos-start_pos-1); if (color_errors && // Only colorize tokens whose content is known to match the source // content. e.g. tok_string doesn't qualify because of the double-quotes. // tok_embedded lacks the %{ %}. tok_junk is just junky. (tok->type == tok_number || tok->type == tok_identifier || tok->type == tok_operator)) { // Split into before token, token, and after token string tok_content = tok->content; message << srcline.substr(0, col-1); message << colorize(tok_content, "token"); message << srcline.substr(col+tok_content.size()-1) << endl; } else message << srcline << endl; message << align << " "; //Navigate to the appropriate column for (i=start_pos; itype == tok_junk && tok->msg != "") { found_junk = true; cerr << colorize(_("parse error:"), "error") << ' ' << tok->msg << endl; } else { cerr << colorize(_("parse error:"), "error") << ' ' << pe.what() << endl; } // NB: It makes sense for lexer errors to always override parser // errors, since the original obvious scheme was for the lexer to // throw an exception before the token reached the parser. if (pe.tok || found_junk) { cerr << _("\tat: ") << colorize(*tok) << endl; print_error_source (cerr, align_parse_error, tok); } else if (tok) // "expected" type error { cerr << _("\tsaw: ") << colorize(*tok) << endl; print_error_source (cerr, align_parse_error, tok); } else { cerr << _("\tsaw: ") << input_name << " EOF" << endl; } // print chained macro invocations while (tok && tok->chain) { tok = tok->chain; cerr << _("\tin expansion of macro: ") << colorize(*tok) << endl; print_error_source (cerr, align_parse_error, tok); } } void systemtap_session::create_tmp_dir() { if (!tmpdir.empty()) return; // Create the temp directory const char * tmpdir_env = getenv("TMPDIR"); if (!tmpdir_env) tmpdir_env = "/tmp"; string stapdir = "/stapXXXXXX"; string tmpdirt = tmpdir_env + stapdir; const char *tmpdir_name = mkdtemp((char *)tmpdirt.c_str()); if (! tmpdir_name) { const char* e = strerror(errno); //TRANSLATORS: we can't make the directory due to the error throw runtime_error(_F("cannot create temporary directory (\" %s \"): %s", tmpdirt.c_str(), e)); } else tmpdir = tmpdir_name; } void systemtap_session::remove_tmp_dir() { if(tmpdir.empty()) return; // Remove temporary directory if (keep_tmpdir && !tmpdir_opt_set) clog << _F("Keeping temporary directory \"%s\"", tmpdir.c_str()) << endl; else if (!tmpdir_opt_set) { // Mask signals while we're deleting the temporary directory. stap_sigmasker masked; // Remove the temporary directory. vector cleanupcmd; cleanupcmd.push_back("rm"); cleanupcmd.push_back("-rf"); cleanupcmd.push_back(tmpdir); (void) stap_system(verbose, cleanupcmd); if (verbose>1) clog << _F("Removed temporary directory \"%s\"", tmpdir.c_str()) << endl; tmpdir.clear(); } } void systemtap_session::reset_tmp_dir() { remove_tmp_dir(); create_tmp_dir(); } translator_output* systemtap_session::op_create_auxiliary() { static int counter = 0; string tmpname = this->tmpdir + "/" + this->module_name + "_aux_" + lex_cast(counter++) + ".c"; translator_output* n = new translator_output (tmpname); auxiliary_outputs.push_back (n); return n; } // Wrapper for checking if there are pending interrupts void assert_no_interrupts() { if (pending_interrupts) throw interrupt_exception(); } std::string systemtap_session::colorize(std::string str, std::string type) { if (str.empty() || !color_errors) return str; else { // Check if this type is defined in SYSTEMTAP_COLORS std::string color = parse_stap_color(type); if (!color.empty()) // no need to pollute terminal if not necessary return "\033[" + color + "m\033[K" + str + "\033[m\033[K"; else return str; } } // Colorizes the path:row:col part of the token std::string systemtap_session::colorize(const token& tok) { stringstream tmp; tmp << tok; if (!color_errors) return tmp.str(); // Might as well stop now to save time else { string ts = tmp.str(); // Print token location, which is also the tail of ts stringstream loc; loc << tok.location; // Remove token location and re-add it colorized ts.erase(ts.size()-loc.str().size()); return ts + colorize(loc.str(), "source"); } } /* Parse SYSTEMTAP_COLORS and returns the SGR parameter(s) for the given type. The env var SYSTEMTAP_COLORS must be in the following format: 'key1=val1:key2=val2:' etc... where valid keys are 'error', 'warning', 'source', 'caret', 'token' and valid values constitute SGR parameter(s). For example, the default setting would be: 'error=01;31:warning=00;33:source=00;34:caret=01:token=01' */ std::string systemtap_session::parse_stap_color(std::string type) { const char *key, *col, *eq; int n = type.size(); int done = 0; key = getenv("SYSTEMTAP_COLORS"); if (key == NULL || *key == '\0') key = "error=01;31:warning=00;33:source=00;34:caret=01:token=01"; while (!done) { if (!(col = strchr(key, ':'))) { col = strchr(key, '\0'); done = 1; } if (!((eq = strchr(key, '=')) && eq < col)) return ""; /* invalid syntax: no = in range */ if (!(key < eq && eq < col-1)) return ""; /* invalid syntax: key or val empty */ if (strspn(eq+1, "0123456789;") < (size_t)(col-eq-1)) return ""; /* invalid syntax: invalid char in val */ if (eq-key == n && type.compare(0, n, key, n) == 0) return string(eq+1, col-eq-1); if (!done) key = col+1; /* advance to next key */ } // Could not find the key return ""; } // -------------------------------------------------------------------------- /* Perngrq sebz fzvyrlgnc.fit, rkcbegrq gb n 1484k1110 fzvyrlgnc.cat, gurapr catgbcnz | cazfpnyr -jvqgu 160 | cczqvgure -qvz 4 -erq 2 -terra 2 -oyhr 2 | cczgbnafv -2k4 | bq -i -j19 -g k1 | phg -s2- -q' ' | frq -r 'f,^,\\k,' -r 'f, ,\\k,t' -r 'f,^,",' -r 'f,$,",' */ const char* systemtap_session::morehelp = "\x1b\x5b\x30\x6d\x1b\x5b\x33\x37\x6d\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x20\x60\x20\x20\x2e\x60\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x1b\x5b" "\x33\x33\x6d\x20\x1b\x5b\x33\x37\x6d\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x1b\x5b\x33\x33\x6d\x20\x60" "\x2e\x60\x1b\x5b\x33\x37\x6d\x20\x3a\x2c\x3a\x2e\x60\x20\x60\x20\x60\x20\x60" "\x2c\x3b\x2c\x3a\x20\x1b\x5b\x33\x33\x6d\x60\x2e\x60\x20\x1b\x5b\x33\x37\x6d" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x1b\x5b\x33" "\x33\x6d\x20\x60\x20\x60\x20\x3a\x27\x60\x1b\x5b\x33\x37\x6d\x20\x60\x60\x60" "\x20\x20\x20\x60\x20\x60\x60\x60\x20\x1b\x5b\x33\x33\x6d\x60\x3a\x60\x20\x60" "\x20\x60\x20\x1b\x5b\x33\x37\x6d\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x2e\x1b\x5b\x33\x33\x6d\x60\x2e\x60\x20\x60\x20\x60\x20\x20\x1b\x5b\x33" "\x37\x6d\x20\x3a\x20\x20\x20\x60\x20\x20\x20\x60\x20\x20\x2e\x1b\x5b\x33\x33" "\x6d\x60\x20\x60\x2e\x60\x20\x60\x2e\x60\x20\x1b\x5b\x33\x37\x6d\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x2e\x3a\x20\x20" "\x20\x20\x20\x20\x20\x20\x2e\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x2e\x76\x53\x1b\x5b\x33\x34\x6d\x53\x1b\x5b\x33\x37\x6d\x53\x1b\x5b" "\x33\x31\x6d\x2b\x1b\x5b\x33\x33\x6d\x60\x20\x60\x20\x60\x20\x20\x20\x20\x1b" "\x5b\x33\x31\x6d\x3f\x1b\x5b\x33\x30\x6d\x53\x1b\x5b\x33\x33\x6d\x2b\x1b\x5b" "\x33\x37\x6d\x20\x20\x20\x20\x20\x20\x20\x2e\x1b\x5b\x33\x30\x6d\x24\x1b\x5b" "\x33\x37\x6d\x3b\x1b\x5b\x33\x31\x6d\x7c\x1b\x5b\x33\x33\x6d\x20\x60\x20\x60" "\x20\x60\x20\x60\x1b\x5b\x33\x31\x6d\x2c\x1b\x5b\x33\x32\x6d\x53\x1b\x5b\x33" "\x37\x6d\x53\x53\x3e\x2c\x2e\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x2e" "\x3b\x27\x20\x20\x20\x20\x20\x20\x20\x20\x20\x60\x3c\x20\x20\x20\x20\x20\x20" "\x20\x20\x20\x2e\x2e\x3a\x1b\x5b\x33\x30\x6d\x26\x46\x46\x46\x48\x46\x1b\x5b" "\x33\x33\x6d\x60\x2e\x60\x20\x60\x20\x60\x20\x60\x1b\x5b\x33\x30\x6d\x4d\x4d" "\x46\x1b\x5b\x33\x33\x6d\x20\x20\x1b\x5b\x33\x37\x6d\x20\x20\x20\x20\x1b\x5b" "\x33\x33\x6d\x20\x3a\x1b\x5b\x33\x30\x6d\x4d\x4d\x46\x1b\x5b\x33\x33\x6d\x20" "\x20\x20\x60\x20\x60\x2e\x60\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33\x30\x6d\x46" "\x46\x46\x24\x53\x46\x1b\x5b\x33\x37\x6d\x20\x20\x20\x20\x20\x0a\x20\x20\x20" "\x20\x2e\x3c\x3a\x60\x20\x20\x20\x20\x2e\x3a\x2e\x3a\x2e\x2e\x3b\x27\x20\x20" "\x20\x20\x20\x20\x2e\x60\x2e\x3a\x60\x60\x3c\x27\x1b\x5b\x33\x31\x6d\x3c\x27" "\x1b\x5b\x33\x33\x6d\x20\x60\x20\x60\x20\x60\x20\x20\x20\x60\x3c\x1b\x5b\x33" "\x30\x6d\x26\x1b\x5b\x33\x31\x6d\x3f\x1b\x5b\x33\x33\x6d\x20\x1b\x5b\x33\x37" "\x6d\x20\x1b\x5b\x33\x33\x6d\x20\x20\x20\x20\x20\x1b\x5b\x33\x37\x6d\x60\x1b" "\x5b\x33\x30\x6d\x2a\x46\x1b\x5b\x33\x37\x6d\x27\x1b\x5b\x33\x33\x6d\x20\x60" "\x20\x60\x20\x60\x20\x60\x20\x1b\x5b\x33\x31\x6d\x60\x3a\x1b\x5b\x33\x37\x6d" "\x27\x3c\x1b\x5b\x33\x30\x6d\x23\x1b\x5b\x33\x37\x6d\x3c\x60\x3a\x20\x20\x20" "\x0a\x20\x20\x20\x20\x3a\x60\x3a\x60\x20\x20\x20\x60\x3a\x2e\x2e\x2e\x2e\x3c" "\x3c\x20\x20\x20\x20\x20\x20\x3a\x2e\x60\x3a\x60\x20\x20\x20\x60\x1b\x5b\x33" "\x33\x6d\x3a\x1b\x5b\x33\x31\x6d\x60\x1b\x5b\x33\x33\x6d\x20\x60\x2e\x60\x20" "\x60\x20\x60\x20\x60\x20\x60\x1b\x5b\x33\x37\x6d\x20\x20\x1b\x5b\x33\x33\x6d" "\x20\x60\x20\x20\x20\x60\x1b\x5b\x33\x37\x6d\x20\x60\x20\x60\x1b\x5b\x33\x33" "\x6d\x20\x60\x2e\x60\x20\x60\x2e\x60\x20\x60\x3a\x1b\x5b\x33\x37\x6d\x20\x20" "\x20\x60\x3a\x2e\x60\x2e\x20\x0a\x20\x20\x20\x60\x3a\x60\x3a\x60\x20\x20\x20" "\x20\x20\x60\x60\x60\x60\x20\x3a\x2d\x20\x20\x20\x20\x20\x60\x20\x60\x20\x20" "\x20\x20\x20\x60\x1b\x5b\x33\x33\x6d\x3a\x60\x2e\x60\x20\x60\x20\x60\x20\x60" "\x20\x60\x20\x20\x2e\x3b\x1b\x5b\x33\x31\x6d\x76\x1b\x5b\x33\x30\x6d\x24\x24" "\x24\x1b\x5b\x33\x31\x6d\x2b\x53\x1b\x5b\x33\x33\x6d\x2c\x60\x20\x60\x20\x60" "\x20\x60\x20\x60\x20\x60\x2e\x1b\x5b\x33\x31\x6d\x60\x1b\x5b\x33\x33\x6d\x3a" "\x1b\x5b\x33\x37\x6d\x20\x20\x20\x20\x60\x2e\x60\x20\x20\x0a\x20\x20\x20\x60" "\x3a\x3a\x3a\x3a\x20\x20\x20\x20\x3a\x60\x60\x60\x60\x3a\x53\x20\x20\x20\x20" "\x20\x20\x3a\x2e\x60\x2e\x20\x20\x20\x20\x20\x1b\x5b\x33\x33\x6d\x3a\x1b\x5b" "\x33\x31\x6d\x3a\x1b\x5b\x33\x33\x6d\x2e\x60\x2e\x60\x20\x60\x2e\x60\x20\x60" "\x20\x3a\x1b\x5b\x33\x30\x6d\x24\x46\x46\x48\x46\x46\x46\x46\x46\x1b\x5b\x33" "\x31\x6d\x53\x1b\x5b\x33\x33\x6d\x2e\x60\x20\x60\x2e\x60\x20\x60\x2e\x60\x2e" "\x1b\x5b\x33\x31\x6d\x3a\x1b\x5b\x33\x33\x6d\x3a\x1b\x5b\x33\x37\x6d\x20\x20" "\x20\x2e\x60\x2e\x3a\x20\x20\x0a\x20\x20\x20\x60\x3a\x3a\x3a\x60\x20\x20\x20" "\x60\x3a\x20\x2e\x20\x3b\x27\x3a\x20\x20\x20\x20\x20\x20\x3a\x2e\x60\x3a\x20" "\x20\x20\x20\x20\x3a\x1b\x5b\x33\x33\x6d\x3c\x3a\x1b\x5b\x33\x31\x6d\x60\x1b" "\x5b\x33\x33\x6d\x2e\x60\x20\x60\x20\x60\x20\x60\x2e\x1b\x5b\x33\x30\x6d\x53" "\x46\x46\x46\x53\x46\x46\x46\x53\x46\x46\x1b\x5b\x33\x33\x6d\x20\x60\x20\x60" "\x20\x60\x2e\x60\x2e\x60\x3a\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33\x37\x6d\x20" "\x20\x20\x20\x3a\x60\x3a\x60\x20\x20\x0a\x20\x20\x20\x20\x60\x3c\x3b\x3c\x20" "\x20\x20\x20\x20\x60\x60\x60\x20\x3a\x3a\x20\x20\x20\x20\x20\x20\x20\x3a\x3a" "\x2e\x60\x20\x20\x20\x20\x20\x3a\x1b\x5b\x33\x33\x6d\x3b\x1b\x5b\x33\x31\x6d" "\x3c\x3a\x60\x1b\x5b\x33\x33\x6d\x2e\x60\x2e\x60\x20\x60\x3a\x1b\x5b\x33\x30" "\x6d\x53\x46\x53\x46\x46\x46\x53\x46\x46\x46\x53\x1b\x5b\x33\x33\x6d\x2e\x60" "\x20\x60\x2e\x60\x2e\x60\x3a\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33\x33\x6d\x3b" "\x1b\x5b\x33\x37\x6d\x27\x20\x20\x20\x60\x3a\x3a\x60\x20\x20\x20\x0a\x20\x20" "\x20\x20\x20\x60\x3b\x3c\x20\x20\x20\x20\x20\x20\x20\x3a\x3b\x60\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x60\x3a\x60\x2e\x20\x20\x20\x20\x20\x3a\x1b\x5b\x33" "\x33\x6d\x3c\x3b\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33\x33\x6d\x3a\x1b\x5b\x33" "\x31\x6d\x3a\x1b\x5b\x33\x33\x6d\x2e\x60\x2e\x60\x20\x1b\x5b\x33\x31\x6d\x3a" "\x1b\x5b\x33\x30\x6d\x46\x53\x46\x53\x46\x53\x46\x53\x46\x1b\x5b\x33\x31\x6d" "\x3f\x1b\x5b\x33\x33\x6d\x20\x60\x2e\x60\x2e\x3a\x3a\x1b\x5b\x33\x31\x6d\x3c" "\x1b\x5b\x33\x33\x6d\x3b\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33\x37\x6d\x60\x20" "\x20\x20\x3a\x3a\x3a\x60\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x53\x3c" "\x20\x20\x20\x20\x20\x20\x3a\x53\x3a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x60\x3a\x3a\x60\x2e\x20\x20\x20\x20\x60\x3a\x1b\x5b\x33\x31\x6d\x3c\x1b" "\x5b\x33\x33\x6d\x3b\x1b\x5b\x33\x31\x6d\x3c\x3b\x3c\x1b\x5b\x33\x33\x6d\x3a" "\x60\x2e\x60\x3c\x1b\x5b\x33\x30\x6d\x53\x46\x53\x24\x53\x46\x53\x24\x1b\x5b" "\x33\x33\x6d\x60\x3a\x1b\x5b\x33\x31\x6d\x3a\x1b\x5b\x33\x33\x6d\x3a\x1b\x5b" "\x33\x31\x6d\x3a\x3b\x3c\x1b\x5b\x33\x33\x6d\x3b\x1b\x5b\x33\x31\x6d\x3c\x1b" "\x5b\x33\x33\x6d\x3a\x1b\x5b\x33\x37\x6d\x60\x20\x20\x2e\x60\x3a\x3a\x60\x20" "\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x3b\x3c\x2e\x2e\x2c\x2e\x2e\x20" "\x3a\x3c\x3b\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x60\x3a\x3a\x3a" "\x60\x20\x20\x20\x20\x20\x60\x3a\x1b\x5b\x33\x33\x6d\x3c\x3b\x1b\x5b\x33\x31" "\x6d\x3c\x3b\x3c\x1b\x5b\x33\x33\x6d\x3b\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33" "\x33\x6d\x3b\x1b\x5b\x33\x31\x6d\x3c\x3c\x1b\x5b\x33\x30\x6d\x53\x24\x53\x1b" "\x5b\x33\x31\x6d\x53\x1b\x5b\x33\x37\x6d\x27\x1b\x5b\x33\x33\x6d\x2e\x3a\x3b" "\x1b\x5b\x33\x31\x6d\x3c\x3b\x3c\x1b\x5b\x33\x33\x6d\x3a\x1b\x5b\x33\x31\x6d" "\x3c\x1b\x5b\x33\x33\x6d\x3a\x1b\x5b\x33\x37\x6d\x60\x20\x20\x20\x60\x2e\x3a" "\x3a\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x2e\x3a\x3a\x3c\x53\x3c\x3a\x60" "\x3a\x3a\x3a\x3a\x53\x1b\x5b\x33\x32\x6d\x53\x1b\x5b\x33\x37\x6d\x3b\x27\x3a" "\x3c\x2c\x2e\x20\x20\x20\x20\x20\x20\x20\x20\x20\x60\x3a\x3a\x3a\x3a\x2e\x60" "\x2e\x60\x2e\x60\x3a\x1b\x5b\x33\x33\x6d\x3c\x3a\x1b\x5b\x33\x31\x6d\x3c\x1b" "\x5b\x33\x33\x6d\x53\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33\x33\x6d\x3b\x1b\x5b" "\x33\x31\x6d\x3c\x2c\x1b\x5b\x33\x33\x6d\x3c\x3b\x3a\x1b\x5b\x33\x31\x6d\x2c" "\x1b\x5b\x33\x33\x6d\x3c\x3b\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33\x33\x6d\x53" "\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33\x33\x6d\x3b\x3c\x1b\x5b\x33\x37\x6d\x3a" "\x60\x2e\x60\x2e\x3b\x1b\x5b\x33\x34\x6d\x53\x1b\x5b\x33\x37\x6d\x53\x3f\x27" "\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x2e\x60\x3a\x60\x3a\x3c\x53\x53\x3b\x3c" "\x3a\x60\x3a\x3a\x53\x53\x53\x3c\x3a\x60\x3a\x1b\x5b\x33\x30\x6d\x53\x1b\x5b" "\x33\x37\x6d\x2b\x20\x20\x20\x20\x20\x20\x60\x20\x20\x20\x3a\x1b\x5b\x33\x34" "\x6d\x53\x1b\x5b\x33\x30\x6d\x53\x46\x24\x1b\x5b\x33\x37\x6d\x2c\x60\x3a\x3a" "\x3a\x3c\x3a\x3c\x1b\x5b\x33\x33\x6d\x53\x1b\x5b\x33\x37\x6d\x3c\x1b\x5b\x33" "\x33\x6d\x53\x1b\x5b\x33\x31\x6d\x53\x1b\x5b\x33\x33\x6d\x3b\x1b\x5b\x33\x31" "\x6d\x53\x3b\x53\x1b\x5b\x33\x33\x6d\x3b\x1b\x5b\x33\x31\x6d\x53\x1b\x5b\x33" "\x33\x6d\x53\x1b\x5b\x33\x37\x6d\x3c\x1b\x5b\x33\x33\x6d\x53\x1b\x5b\x33\x37" "\x6d\x3c\x53\x3c\x3a\x3a\x3a\x3a\x3f\x1b\x5b\x33\x30\x6d\x53\x24\x48\x1b\x5b" "\x33\x37\x6d\x27\x60\x20\x60\x20\x20\x20\x20\x20\x20\x0a\x2e\x60\x3a\x60\x2e" "\x60\x3a\x60\x2e\x60\x3a\x60\x2e\x60\x3a\x60\x2e\x60\x3a\x60\x2e\x1b\x5b\x33" "\x30\x6d\x53\x46\x1b\x5b\x33\x37\x6d\x20\x20\x20\x20\x60\x20\x20\x20\x60\x20" "\x60\x3a\x1b\x5b\x33\x30\x6d\x3c\x46\x46\x46\x1b\x5b\x33\x37\x6d\x3f\x2e\x60" "\x3a\x60\x3a\x60\x3a\x60\x3a\x60\x3a\x3c\x3a\x60\x3a\x27\x3a\x60\x3a\x60\x3a" "\x60\x3a\x60\x3b\x1b\x5b\x33\x30\x6d\x53\x46\x48\x46\x1b\x5b\x33\x37\x6d\x27" "\x20\x60\x20\x60\x20\x60\x20\x20\x20\x20\x0a\x20\x3c\x3b\x3a\x2e\x60\x20\x60" "\x2e\x60\x20\x60\x2e\x60\x20\x60\x2e\x60\x2c\x53\x1b\x5b\x33\x32\x6d\x53\x1b" "\x5b\x33\x30\x6d\x53\x1b\x5b\x33\x37\x6d\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x60\x20\x60\x3c\x1b\x5b\x33\x30\x6d\x46\x46\x46\x1b\x5b\x33\x34\x6d" "\x2b\x1b\x5b\x33\x37\x6d\x3a\x20\x60\x20\x60\x20\x60\x2e\x60\x20\x60\x2e\x60" "\x20\x60\x2e\x60\x20\x60\x20\x60\x2c\x1b\x5b\x33\x30\x6d\x24\x46\x48\x46\x1b" "\x5b\x33\x37\x6d\x27\x20\x60\x20\x20\x20\x60\x20\x20\x20\x20\x20\x20\x0a\x20" "\x60\x3a\x1b\x5b\x33\x30\x6d\x53\x24\x1b\x5b\x33\x37\x6d\x53\x53\x53\x3b\x3c" "\x2c\x60\x2c\x3b\x3b\x53\x3f\x53\x1b\x5b\x33\x30\x6d\x24\x46\x3c\x1b\x5b\x33" "\x37\x6d\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x60\x20\x60" "\x3c\x1b\x5b\x33\x30\x6d\x48\x46\x46\x46\x1b\x5b\x33\x37\x6d\x3f\x2e\x60\x20" "\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x3b\x76\x1b\x5b\x33\x30\x6d" "\x48\x46\x48\x46\x1b\x5b\x33\x37\x6d\x27\x20\x60\x20\x20\x20\x60\x20\x20\x20" "\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x60\x3c\x1b\x5b\x33\x30\x6d\x46\x24\x1b" "\x5b\x33\x37\x6d\x53\x53\x53\x53\x53\x53\x1b\x5b\x33\x30\x6d\x53\x24\x53\x46" "\x46\x46\x1b\x5b\x33\x37\x6d\x27\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x60\x3c\x1b\x5b\x33\x30\x6d\x23\x46\x46\x46" "\x24\x1b\x5b\x33\x37\x6d\x76\x2c\x2c\x20\x2e\x20\x2e\x20\x2c\x2c\x76\x1b\x5b" "\x33\x30\x6d\x26\x24\x46\x46\x48\x3c\x1b\x5b\x33\x37\x6d\x27\x20\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x60" "\x3c\x1b\x5b\x33\x30\x6d\x53\x46\x46\x24\x46\x24\x46\x46\x48\x46\x53\x1b\x5b" "\x33\x37\x6d\x20\x20\x20\x20\x20\x20\x20\x20\x2e\x60\x20\x60\x2e\x60\x2e\x60" "\x2e\x60\x2e\x60\x3a\x3a\x3a\x3a\x3a\x1b\x5b\x33\x30\x6d\x2a\x46\x46\x46\x48" "\x46\x48\x46\x48\x46\x46\x46\x48\x46\x48\x46\x48\x1b\x5b\x33\x37\x6d\x3c\x22" "\x2e\x60\x2e\x60\x2e\x60\x2e\x60\x2e\x60\x20\x20\x20\x20\x20\x20\x20\x20\x0a" "\x20\x20\x20\x20\x20\x20\x20\x60\x3a\x1b\x5b\x33\x30\x6d\x48\x46\x46\x46\x48" "\x46\x46\x46\x1b\x5b\x33\x37\x6d\x27\x20\x20\x20\x60\x20\x60\x2e\x60\x20\x60" "\x2e\x60\x2e\x60\x3a\x60\x3a\x60\x3a\x60\x3a\x60\x3a\x3a\x3a\x60\x3a\x3c\x3c" "\x1b\x5b\x33\x30\x6d\x3c\x46\x48\x46\x46\x46\x48\x46\x46\x46\x1b\x5b\x33\x37" "\x6d\x27\x3a\x60\x3a\x60\x3a\x60\x3a\x60\x2e\x60\x2e\x60\x20\x60\x2e\x60\x20" "\x60\x20\x60\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x60\x22\x1b\x5b" "\x33\x30\x6d\x2a\x46\x48\x46\x1b\x5b\x33\x37\x6d\x3f\x20\x20\x20\x60\x20\x60" "\x2e\x60\x20\x60\x2e\x60\x2e\x60\x3a\x60\x2e\x60\x3a\x60\x3a\x60\x3a\x60\x3a" "\x60\x3a\x60\x3a\x60\x3a\x60\x3a\x1b\x5b\x33\x30\x6d\x46\x46\x48\x46\x48\x46" "\x1b\x5b\x33\x37\x6d\x27\x3a\x60\x3a\x60\x3a\x60\x3a\x60\x2e\x60\x3a\x60\x2e" "\x60\x2e\x60\x20\x60\x2e\x60\x20\x60\x20\x60\x0a\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x20\x20\x60\x3c\x1b\x5b\x33\x30\x6d\x48\x46\x46\x1b\x5b\x33\x37\x6d" "\x2b\x60\x20\x20\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x2e\x60\x20" "\x60\x2e\x60\x20\x60\x2e\x60\x20\x60\x3a\x60\x2e\x60\x3b\x1b\x5b\x33\x30\x6d" "\x48\x46\x46\x46\x1b\x5b\x33\x37\x6d\x27\x2e\x60\x2e\x60\x20\x60\x2e\x60\x20" "\x60\x2e\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x20\x20\x60\x20\x20\x0a\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x22\x1b\x5b\x33\x30\x6d\x3c" "\x48\x46\x53\x1b\x5b\x33\x37\x6d\x2b\x3a\x20\x20\x20\x60\x20\x60\x20\x60\x20" "\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x2c\x1b" "\x5b\x33\x30\x6d\x24\x46\x48\x46\x1b\x5b\x33\x37\x6d\x3f\x20\x60\x20\x60\x20" "\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x20\x20\x60" "\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x60\x22\x3c\x1b\x5b\x33\x30\x6d\x48\x24\x46\x46\x1b\x5b\x33\x37\x6d\x3e\x2c" "\x2e\x2e\x20\x20\x20\x20\x20\x20\x20\x20\x60\x20\x20\x20\x60\x20\x20\x20\x3b" "\x2c\x2c\x1b\x5b\x33\x30\x6d\x24\x53\x46\x46\x46\x1b\x5b\x33\x37\x6d\x27\x22" "\x20\x20\x60\x20\x20\x20\x60\x20\x20\x20\x60\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x60\x22\x1b\x5b\x33\x30\x6d\x2a\x3c\x48" "\x46\x46\x24\x53\x24\x1b\x5b\x33\x37\x6d\x53\x53\x53\x3e\x3e\x3e\x3e\x3e\x53" "\x3e\x53\x1b\x5b\x33\x30\x6d\x24\x53\x24\x46\x24\x48\x46\x23\x1b\x5b\x33\x37" "\x6d\x27\x22\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x60\x60\x22\x3c\x1b\x5b\x33\x30\x6d\x2a\x3c\x3c\x3c\x48\x46\x46\x46\x48\x46" "\x46\x46\x23\x3c\x1b\x5b\x33\x36\x6d\x3c\x1b\x5b\x33\x37\x6d\x3c\x27\x22\x22" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x1b" "\x5b\x30\x6d"; /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/session.h000066400000000000000000000330671217430427200152560ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2005-2012 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef SESSION_H #define SESSION_H #include "config.h" #if ENABLE_NLS #include #include #endif #include #include #include #include #include #include #include #include extern "C" { #include #include } #include "privilege.h" #include "util.h" // forward decls for all referenced systemtap types class stap_hash; class match_node; struct stapfile; struct vardecl; struct token; struct functiondecl; struct derived_probe; struct be_derived_probe_group; struct dwarf_derived_probe_group; struct kprobe_derived_probe_group; struct hwbkpt_derived_probe_group; struct perf_derived_probe_group; struct uprobe_derived_probe_group; struct utrace_derived_probe_group; struct itrace_derived_probe_group; struct task_finder_derived_probe_group; struct timer_derived_probe_group; struct netfilter_derived_probe_group; struct profile_derived_probe_group; struct mark_derived_probe_group; struct tracepoint_derived_probe_group; struct hrtimer_derived_probe_group; struct procfs_derived_probe_group; struct dynprobe_derived_probe_group; struct java_derived_probe_group; struct embeddedcode; struct stapdfa; class translator_output; struct unparser; struct semantic_error; struct module_cache; struct update_visitor; struct compile_server_cache; // XXX: a generalized form of this descriptor could be associated with // a vardecl instead of out here at the systemtap_session level. struct statistic_decl { statistic_decl() : type(none), linear_low(0), linear_high(0), linear_step(0) {} enum { none, linear, logarithmic } type; int64_t linear_low; int64_t linear_high; int64_t linear_step; bool operator==(statistic_decl const & other) { return type == other.type && linear_low == other.linear_low && linear_high == other.linear_high && linear_step == other.linear_step; } }; struct macrodecl; // defined in parse.h struct parse_error: public std::runtime_error { const token* tok; bool skip_some; parse_error (const std::string& msg): runtime_error (msg), tok (0), skip_some (true) {} parse_error (const std::string& msg, const token* t): runtime_error (msg), tok (t), skip_some (true) {} parse_error (const std::string& msg, bool skip): runtime_error (msg), tok (0), skip_some (skip) {} }; struct systemtap_session { private: // disable implicit constructors by not implementing these systemtap_session (const systemtap_session& other); systemtap_session& operator= (const systemtap_session& other); // copy constructor used by ::clone() systemtap_session (const systemtap_session& other, const std::string& arch, const std::string& kern); public: systemtap_session (); ~systemtap_session (); // To reset the tmp_dir void create_tmp_dir(); void remove_tmp_dir(); void reset_tmp_dir(); // NB: It is very important for all of the above (and below) fields // to be cleared in the systemtap_session ctor (session.cxx). void setup_kernel_release (const char* kstr); void insert_loaded_modules (); // command line parsing int parse_cmdline (int argc, char * const argv []); bool parse_cmdline_runtime (const std::string& opt_runtime); void version (); void usage (int exitcode); void check_options (int argc, char * const argv []); static const char* morehelp; // NB: It is very important for all of the above (and below) fields // to be cleared in the systemtap_session ctor (session.cxx). // command line args std::string script_file; // FILE std::string cmdline_script; // -e PROGRAM bool have_script; std::vector include_path; int include_arg_start; std::vector c_macros; std::vector args; std::vector kbuildflags; // -B var=val std::vector globalopts; // -G var=val std::vector modinfos; // --modinfo tag=value std::string release; std::string kernel_release; std::string kernel_base_release; std::string kernel_build_tree; std::string kernel_source_tree; std::map kernel_config; std::set kernel_exports; std::set kernel_functions; int parse_kernel_config (); int parse_kernel_exports (); int parse_kernel_functions (); std::string sysroot; std::map sysenv; bool update_release_sysroot; std::string machine; std::string architecture; bool native_build; std::string runtime_path; bool runtime_specified; std::string data_path; std::string module_name; const std::string module_filename() const; std::string stapconf_name; std::string output_file; std::string size_option; std::string cmd; std::string compatible; // use (strverscmp(s.compatible.c_str(), "N.M") >= 0) int target_pid; int last_pass; unsigned perpass_verbose[5]; unsigned verbose; bool timing; bool save_module; bool modname_given; bool keep_tmpdir; bool guru_mode; bool listing_mode; bool listing_mode_vars; bool bulk_mode; bool unoptimized; bool suppress_warnings; bool panic_warnings; int buffer_size; bool prologue_searching; bool tapset_compile_coverage; bool need_uprobes; bool need_unwind; bool need_symbols; std::string uprobes_path; std::string uprobes_hash; bool load_only; // flight recorder mode bool omit_werror; privilege_t privilege; bool privilege_set; bool systemtap_v_check; bool tmpdir_opt_set; bool dump_probe_types; int download_dbinfo; bool suppress_handler_errors; bool suppress_time_limits; bool color_errors; enum { color_never, color_auto, color_always } color_mode; enum { kernel_runtime, dyninst_runtime } runtime_mode; bool runtime_usermode_p() const { return runtime_mode == dyninst_runtime; } // NB: It is very important for all of the above (and below) fields // to be cleared in the systemtap_session ctor (session.cxx). // Client/server #if HAVE_NSS static bool NSPR_Initialized; // only once for all sessions void NSPR_init (); #endif bool client_options; std::string client_options_disallowed_for_unprivileged; std::vector server_status_strings; std::vector specified_servers; bool automatic_server_mode; std::string server_trust_spec; std::vector server_args; std::string winning_server; compile_server_cache* server_cache; // NB: It is very important for all of the above (and below) fields // to be cleared in the systemtap_session ctor (session.cxx). // Mechanism for retrying compilation with a compile server should it fail due // to lack of resources on the local host. // Once it has been decided not to try the server (e.g. syntax error), // that decision cannot be changed. int try_server_status; bool use_server_on_error; enum { try_server_unset, dont_try_server, do_try_server }; void init_try_server (); void set_try_server (int t = do_try_server); bool try_server () const { return try_server_status == do_try_server; } // NB: It is very important for all of the above (and below) fields // to be cleared in the systemtap_session ctor (session.cxx). // Remote execution std::vector remote_uris; bool use_remote_prefix; typedef std::map, systemtap_session*> session_map_t; session_map_t subsessions; systemtap_session* clone(const std::string& arch, const std::string& release); // NB: It is very important for all of the above (and below) fields // to be cleared in the systemtap_session ctor (session.cxx). // Cache data bool use_cache; // control all caching bool use_script_cache; // control caching of pass-3/4 output bool poison_cache; // consider the cache to be write-only std::string cache_path; // usually ~/.systemtap/cache std::string hash_path; // path to the cached script module std::string stapconf_path; // path to the cached stapconf stap_hash *base_hash; // hash common to all caching // dwarfless operation bool consult_symtab; std::string kernel_symtab_path; // Skip bad $ vars bool skip_badvars; // NB: It is very important for all of the above (and below) fields // to be cleared in the systemtap_session ctor (session.cxx). // temporary directory for module builds etc. // hazardous - it is "rm -rf"'d at exit std::string tmpdir; std::string translated_source; // C source code match_node* pattern_root; void register_library_aliases(); // data for various preprocessor library macros std::map library_macros; std::vector library_macro_files; // for error reporting purposes // parse trees for the various script files stapfile* user_file; std::vector library_files; // filters to run over all code before symbol resolution // e.g. @cast expansion std::vector code_filters; // resolved globals/functions/probes for the run as a whole std::vector files; std::vector globals; std::map functions; // probe counter name -> probe associated with counter std::map > perf_counters; std::vector probes; // see also *_probes groups below std::vector embeds; std::map stat_decls; // track things that are removed std::vector unused_globals; std::vector unused_probes; // see also *_probes groups below std::vector unused_functions; // XXX: vector<*> instead please? // resolved/compiled regular expressions for the run std::map dfas; unsigned dfa_counter; // used to give unique names unsigned dfa_maxstate; // used for subexpression-tracking data structure unsigned dfa_maxtag; // ditto bool need_tagged_dfa; // triggered by /* pragma:tagged_dfa */ // Every probe in these groups must also appear in the // session.probes vector. be_derived_probe_group* be_derived_probes; dwarf_derived_probe_group* dwarf_derived_probes; kprobe_derived_probe_group* kprobe_derived_probes; hwbkpt_derived_probe_group* hwbkpt_derived_probes; perf_derived_probe_group* perf_derived_probes; uprobe_derived_probe_group* uprobe_derived_probes; utrace_derived_probe_group* utrace_derived_probes; itrace_derived_probe_group* itrace_derived_probes; task_finder_derived_probe_group* task_finder_derived_probes; timer_derived_probe_group* timer_derived_probes; netfilter_derived_probe_group* netfilter_derived_probes; profile_derived_probe_group* profile_derived_probes; mark_derived_probe_group* mark_derived_probes; tracepoint_derived_probe_group* tracepoint_derived_probes; hrtimer_derived_probe_group* hrtimer_derived_probes; procfs_derived_probe_group* procfs_derived_probes; dynprobe_derived_probe_group* dynprobe_derived_probes; java_derived_probe_group* java_derived_probes; // NB: It is very important for all of the above (and below) fields // to be cleared in the systemtap_session ctor (session.cxx). // unparser data translator_output* op; std::vector auxiliary_outputs; unparser* up; // some symbol addresses // XXX: these belong elsewhere; perhaps the dwflpp instance Dwarf_Addr sym_kprobes_text_start; Dwarf_Addr sym_kprobes_text_end; Dwarf_Addr sym_stext; // List of libdwfl module names to extract symbol/unwind data for. std::set unwindsym_modules; bool unwindsym_ldd; struct module_cache* module_cache; std::vector build_ids; // Secret benchmarking options unsigned long benchmark_sdt_loops; unsigned long benchmark_sdt_threads; // NB: It is very important for all of the above (and below) fields // to be cleared in the systemtap_session ctor (session.cxx). std::set seen_errors; std::set seen_warnings; unsigned num_errors () { return seen_errors.size() + (panic_warnings ? seen_warnings.size() : 0); } std::set rpms_to_install; translator_output* op_create_auxiliary(); const token* last_token; void print_token (std::ostream& o, const token* tok); void print_error (const semantic_error& e); void print_error_source (std::ostream&, std::string&, const token* tok); void print_error (const parse_error &pe, const token* tok, const std::string &input_name); void print_warning (const std::string& w, const token* tok = 0); void printscript(std::ostream& o); // NB: It is very important for all of the above (and below) fields // to be cleared in the systemtap_session ctor (session.cxx). std::string colorize(std::string str, std::string type); std::string colorize(const token& tok); std::string parse_stap_color(std::string type); }; struct exit_exception: public std::runtime_error { int rc; exit_exception (int rc): runtime_error (_F("early exit requested, rc=%d", rc)), rc(rc) {} }; // global counter of SIGINT/SIGTERM's received extern int pending_interrupts; // Interrupt exception subclass for catching // interrupts (i.e. ctrl-c). struct interrupt_exception: public std::runtime_error { interrupt_exception (): runtime_error (_("interrupt received")){} }; void assert_no_interrupts(); #endif // SESSION_H /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/setupdwfl.cxx000066400000000000000000000635161217430427200161650ustar00rootroot00000000000000// Setup routines for creating fully populated DWFLs. Used in pass 2 and 3. // Copyright (C) 2009-2013 Red Hat, Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "config.h" #include "setupdwfl.h" #include "dwarf_wrappers.h" #include "dwflpp.h" #include "session.h" #include "util.h" #include #include #include #include #include #include extern "C" { #include #include #include #include #include #include #include #include #include #include #include #include } // XXX: also consider adding $HOME/.debug/ for perf build-id-cache static const char *debuginfo_path_arr = "+:.debug:/usr/lib/debug:/var/cache/abrt-di/usr/lib/debug:build"; static const char *debuginfo_env_arr = getenv("SYSTEMTAP_DEBUGINFO_PATH"); static char *debuginfo_path = (char *)(debuginfo_env_arr ?: debuginfo_path_arr); // NB: kernel_build_tree doesn't enter into this, as it's for // kernel-side modules only. // XXX: also consider adding $HOME/.debug/ for perf build-id-cache static const char *debuginfo_usr_path_arr = "+:.debug:/usr/lib/debug:/var/cache/abrt-di/usr/lib/debug"; static char *debuginfo_usr_path = (char *)(debuginfo_env_arr ?: debuginfo_usr_path_arr); // A pointer to the current systemtap session for use only by a few // dwfl calls. DO NOT rely on this, as it is cleared after use. // This is a kludge. static systemtap_session* current_session_for_find_debuginfo; static const Dwfl_Callbacks kernel_callbacks = { dwfl_linux_kernel_find_elf, internal_find_debuginfo, dwfl_offline_section_address, (char **) & debuginfo_path }; static const Dwfl_Callbacks user_callbacks = { NULL, internal_find_debuginfo, NULL, /* ET_REL not supported for user space, only ET_EXEC and ET_DYN. dwfl_offline_section_address, */ (char **) & debuginfo_usr_path }; using namespace std; // Store last kernel and user Dwfl for reuse since they are often // re-requested (in phase 2 and then in phase 3). static DwflPtr kernel_dwfl; static DwflPtr user_dwfl; // Setup in setup_dwfl_kernel(), for use in setup_dwfl_report_kernel_p(). // Either offline_search_modname or offline_search_names is // used. When offline_search_modname is not NULL then // offline_search_names is ignored. static const char *offline_search_modname; static set offline_search_names; static unsigned offline_modules_found; // Whether or not we are done reporting kernel modules in // set_dwfl_report_kernel_p(). static bool setup_dwfl_done; // Kept for user_dwfl cache, user modules don't allow wildcards, so // just keep the set of module strings. static set user_modset; // Determines whether or not we will make setup_dwfl_report_kernel_p // report true for all module dependencies. This is necessary for // correctly resolving some dwarf constructs that relocate against // symbols in vmlinux and/or other modules they depend on. See PR10678. static const bool setup_all_deps = true; // Where to find the kernel (and the Modules.dep file). Setup in // setup_dwfl_kernel(), used by dwfl_linux_kernel_report_offline() and // setup_mod_deps(). static string elfutils_kernel_path; static bool is_comma_dash(const char c) { return (c == ',' || c == '-'); } // The path to the abrt-action-install-debuginfo-to-abrt-cache program. static const string abrt_path = (access ("/usr/bin/abrt-action-install-debuginfo-to-abrt-cache", X_OK) == 0 ? "/usr/bin/abrt-action-install-debuginfo-to-abrt-cache" : (access ("/usr/libexec/abrt-action-install-debuginfo-to-abrt-cache", X_OK) == 0 ? "/usr/libexec/abrt-action-install-debuginfo-to-abrt-cache" : "")); // The module name is the basename (without the extension) of the // module path, with ',' and '-' replaced by '_'. static string modname_from_path(const string &path) { size_t dot = path.rfind('.'); size_t slash = path.rfind('/'); if (dot == string::npos || slash == string::npos || dot < slash) return ""; string name = path.substr(slash + 1, dot - slash - 1); replace_if(name.begin(), name.end(), is_comma_dash, '_'); return name; } static bool offline_search_names_find(const string &modpath) { if (offline_search_names.find(modpath) != offline_search_names.end()) return 1; string modname = modname_from_path (modpath); return offline_search_names.find(modname) != offline_search_names.end(); } // Try to parse modules.dep file, // Simple format: module path (either full or relative), colon, // (possibly empty) space delimited list of module (path) // dependencies. static void setup_mod_deps() { string modulesdep; string kernel_path; ifstream in; string l; if (elfutils_kernel_path[0] == '/') { kernel_path = elfutils_kernel_path; } else { string sysroot = ""; if (current_session_for_find_debuginfo) sysroot = current_session_for_find_debuginfo->sysroot; kernel_path = sysroot + "/lib/modules/" + elfutils_kernel_path; } modulesdep = kernel_path + "/modules.dep"; in.open(modulesdep.c_str()); if (in.fail ()) return; while (getline (in, l)) { size_t off = l.find (':'); if (off != string::npos) { string modpath, modname; modpath = l.substr (0, off); modname = modname_from_path (modpath); if (modname == "") continue; if (modpath[0] != '/') modpath = kernel_path + "/" + modpath; bool dep_needed = 0; if (offline_search_modname != NULL) { if (dwflpp::name_has_wildcard (offline_search_modname)) { dep_needed = !fnmatch (offline_search_modname, modname.c_str (), 0); if (dep_needed) offline_search_names.insert (modpath); } else { dep_needed = ! strcmp(modname.c_str (), offline_search_modname); if (dep_needed) offline_search_names.insert (modpath); } } else if (offline_search_names.find(modpath) != offline_search_names.end()) dep_needed = 1; else { set::iterator it = offline_search_names.begin(); while (it != offline_search_names.end()) { string modname; modname = modname_from_path(modpath); if (*it == modname) { dep_needed = 1; offline_search_names.erase(it); offline_search_names.insert(modpath); break; } it++; } } if (! dep_needed) continue; string depstring = l.substr (off + 1); if (depstring.size () > 0) { stringstream ss (depstring); string deppath; while (ss >> deppath) offline_search_names.insert (deppath); } } } // We always want kernel (needed in list so size checks match). // Everything needed now stored in offline_search_names. offline_search_names.insert ("kernel"); offline_search_modname = NULL; } // Set up our offline search for kernel modules. We don't want the // offline search iteration to do a complete search of the kernel // build tree, since that's wasteful, so create a predicate that // filters and stops reporting as soon as we got everything. static int setup_dwfl_report_kernel_p(const char* modname, const char* filename) { assert_no_interrupts(); if (setup_dwfl_done) return -1; assert (current_session_for_find_debuginfo); if (current_session_for_find_debuginfo->verbose > 4) clog << _F("checking pattern '%s' vs. module '%s' file '%s'\n", offline_search_modname ?: "", modname ?: "", filename ?: ""); // elfutils sends us NULL filenames sometimes if it can't find dwarf if (filename == NULL) return 0; // Check kernel first since it is often the only thing needed, // then we never have to parse and setup the module deps map. // It will be reported as the very first thing. if (setup_all_deps && ! strcmp (modname, "kernel")) { if ((offline_search_modname != NULL && ! strcmp (offline_search_modname, "kernel")) || (offline_search_names.size() == 1 && *offline_search_names.begin() == "kernel")) setup_dwfl_done = true; else setup_mod_deps(); offline_modules_found++; return 1; } // If offline_search_modname is setup use it (either as regexp or // explicit module/kernel name) and ignore offline_search_names. // Otherwise use offline_search_names exclusively. if (offline_search_modname != NULL) { if (dwflpp::name_has_wildcard (offline_search_modname)) { // XXX: see also dwflpp::module_name_matches() int match_p = !fnmatch(offline_search_modname, modname, 0); // In the wildcard case, we don't short-circuit (return -1) // analogously to dwflpp::module_name_final_match(). if (match_p) offline_modules_found++; return match_p; } else { /* non-wildcard mode, reject mismatching module names */ if (strcmp(modname, offline_search_modname)) return 0; else { // Done, only one name needed and found it. offline_modules_found++; setup_dwfl_done = true; return 1; } } } else { /* find all in set mode, reject mismatching module names */ if (!offline_search_names_find(filename)) return 0; else { offline_modules_found++; if (offline_search_names.size() == offline_modules_found) setup_dwfl_done = true; return 1; } } } static char * path_insert_sysroot(string sysroot, string path) { char * path_new; size_t pos = 1; if (path[0] == '/') path.replace(0, 1, sysroot); while (true) { pos = path.find(":/", pos); if (pos == string::npos) break; path.replace(pos, 2, ":" + sysroot); ++pos; } path_new = new char[path.size()+1]; strcpy (path_new, path.c_str()); return path_new; } void debuginfo_path_insert_sysroot(string sysroot) { debuginfo_path = path_insert_sysroot(sysroot, debuginfo_path); debuginfo_usr_path = path_insert_sysroot(sysroot, debuginfo_usr_path); } static DwflPtr setup_dwfl_kernel (unsigned *modules_found, systemtap_session &s) { Dwfl *dwfl = dwfl_begin (&kernel_callbacks); dwfl_assert ("dwfl_begin", dwfl); dwfl_report_begin (dwfl); // We have a problem with -r REVISION vs -r BUILDDIR here. If // we're running against a fedora/rhel style kernel-debuginfo // tree, s.kernel_build_tree is not the place where the unstripped // vmlinux will be installed. Rather, it's over yonder at // /usr/lib/debug/lib/modules/$REVISION/. It seems that there is // no way to set the dwfl_callback.debuginfo_path and always // passs the plain kernel_release here. So instead we have to // hard-code this magic here. if (s.kernel_build_tree == string(s.sysroot + "/lib/modules/" + s.kernel_release + "/build")) elfutils_kernel_path = s.kernel_release; else elfutils_kernel_path = s.kernel_build_tree; offline_modules_found = 0; // First try to report full path modules. set::iterator it = offline_search_names.begin(); int kernel = 0; while (it != offline_search_names.end()) { if ((*it)[0] == '/') { const char *cname = (*it).c_str(); Dwfl_Module *mod = dwfl_report_offline (dwfl, cname, cname, -1); if (mod) offline_modules_found++; } else if ((*it) == "kernel") kernel = 1; it++; } // We always need this, even when offline_search_modname is NULL // and offline_search_names is empty because we still might want // the kernel vmlinux reported. setup_dwfl_done = false; int rc = dwfl_linux_kernel_report_offline (dwfl, elfutils_kernel_path.c_str(), &setup_dwfl_report_kernel_p); (void) rc; /* Ignore since the predicate probably returned -1 at some point, And libdwfl interprets that as "whole query failed" rather than "found it already, stop looking". */ // NB: the result of an _offline call is the assignment of // virtualized addresses to relocatable objects such as // modules. These have to be converted to real addresses at // run time. See the dwarf_derived_probe ctor and its caller. // If no modules were found, and we are probing the kernel, // attempt to download the kernel debuginfo. if(kernel) { // Get the kernel build ID. We still need to call this even if we // already have the kernel debuginfo installed as it adds the // build ID to the script hash. string hex = get_kernel_build_id(s); if (offline_modules_found == 0 && s.download_dbinfo != 0 && !hex.empty()) { rc = download_kernel_debuginfo(s, hex); if(rc >= 0) return setup_dwfl_kernel (modules_found, s); } } dwfl_assert ("dwfl_report_end", dwfl_report_end(dwfl, NULL, NULL)); *modules_found = offline_modules_found; StapDwfl *stap_dwfl = new StapDwfl(dwfl); kernel_dwfl = DwflPtr(stap_dwfl); return kernel_dwfl; } DwflPtr setup_dwfl_kernel(const std::string &name, unsigned *found, systemtap_session &s) { current_session_for_find_debuginfo = &s; const char *modname = name.c_str(); set names; // Default to empty /* Support full path kernel modules, these cannot be regular expressions, so just put them in the search set. */ if (name[0] == '/' || ! dwflpp::name_has_wildcard (modname)) { names.insert(name); modname = NULL; } if (kernel_dwfl != NULL && offline_search_modname == modname && offline_search_names == names) { *found = offline_modules_found; return kernel_dwfl; } offline_search_modname = modname; offline_search_names = names; return setup_dwfl_kernel(found, s); } DwflPtr setup_dwfl_kernel(const std::set &names, unsigned *found, systemtap_session &s) { current_session_for_find_debuginfo = &s; if (kernel_dwfl != NULL && offline_search_modname == NULL && offline_search_names == names) { *found = offline_modules_found; return kernel_dwfl; } offline_search_modname = NULL; offline_search_names = names; return setup_dwfl_kernel(found, s); } DwflPtr setup_dwfl_user(const std::string &name) { if (user_dwfl != NULL && user_modset.size() == 1 && (*user_modset.begin()) == name) return user_dwfl; user_modset.clear(); user_modset.insert(name); Dwfl *dwfl = dwfl_begin (&user_callbacks); dwfl_assert("dwfl_begin", dwfl); dwfl_report_begin (dwfl); // XXX: should support buildid-based naming const char *cname = name.c_str(); Dwfl_Module *mod = dwfl_report_offline (dwfl, cname, cname, -1); dwfl_assert ("dwfl_report_end", dwfl_report_end(dwfl, NULL, NULL)); if (! mod) { dwfl_end(dwfl); dwfl = NULL; } StapDwfl *stap_dwfl = new StapDwfl(dwfl); user_dwfl = DwflPtr(stap_dwfl); return user_dwfl; } DwflPtr setup_dwfl_user(std::vector::const_iterator &begin, const std::vector::const_iterator &end, bool all_needed, systemtap_session &s) { current_session_for_find_debuginfo = &s; // See if we have this dwfl already cached set modset(begin, end); if (user_dwfl != NULL && modset == user_modset) return user_dwfl; user_modset = modset; Dwfl *dwfl = dwfl_begin (&user_callbacks); dwfl_assert("dwfl_begin", dwfl); dwfl_report_begin (dwfl); Dwfl_Module *mod = NULL; // XXX: should support buildid-based naming while (begin != end && dwfl != NULL) { const char *cname = (*begin).c_str(); mod = dwfl_report_offline (dwfl, cname, cname, -1); if (! mod && all_needed) { dwfl_end(dwfl); dwfl = NULL; } begin++; } /* Extract the build id and add it to the session variable * so it will be added to the script hash */ if (mod) { const unsigned char *bits; GElf_Addr vaddr; if(s.verbose > 2) clog << _("Extracting build ID.") << endl; int bits_length = dwfl_module_build_id(mod, &bits, &vaddr); /* Convert the binary bits to a hex string */ string hex = hex_dump(bits, bits_length); //Store the build ID in the session s.build_ids.push_back(hex); } if (dwfl) dwfl_assert ("dwfl_report_end", dwfl_report_end(dwfl, NULL, NULL)); StapDwfl *stap_dwfl = new StapDwfl(dwfl); user_dwfl = DwflPtr(stap_dwfl); return user_dwfl; } bool is_user_module(const std::string &m) { return m[0] == '/' && m.rfind(".ko", m.length() - 1) != m.length() - 3; } int internal_find_debuginfo (Dwfl_Module *mod, void **userdata __attribute__ ((unused)), const char *modname __attribute__ ((unused)), GElf_Addr base __attribute__ ((unused)), const char *file_name, const char *debuglink_file, GElf_Word debuglink_crc, char **debuginfo_file_name) { int bits_length; string hex; /* To Keep track of whether the abrt successfully installed the debuginfo */ static int install_dbinfo_failed = 0; /* Make sure the current session variable is not null */ if(current_session_for_find_debuginfo == NULL) goto call_dwfl_standard_find_debuginfo; /* Check to see if download-debuginfo=0 was set */ if(!current_session_for_find_debuginfo->download_dbinfo || abrt_path.empty()) goto call_dwfl_standard_find_debuginfo; /* Check that we haven't already run this */ if (install_dbinfo_failed < 0) { if(current_session_for_find_debuginfo->verbose > 1) current_session_for_find_debuginfo->print_warning(_F("We already tried running '%s'", abrt_path.c_str())); goto call_dwfl_standard_find_debuginfo; } /* Extract the build ID */ const unsigned char *bits; GElf_Addr vaddr; if(current_session_for_find_debuginfo->verbose > 2) clog << _("Extracting build ID.") << endl; bits_length = dwfl_module_build_id(mod, &bits, &vaddr); /* Convert the binary bits to a hex string */ hex = hex_dump(bits, bits_length); /* Search for the debuginfo with the build ID */ if(current_session_for_find_debuginfo->verbose > 2) clog << _F("Searching for debuginfo with build ID: '%s'.", hex.c_str()) << endl; if (bits_length > 0) { int fd = dwfl_build_id_find_debuginfo(mod, NULL, NULL, 0, NULL, NULL, 0, debuginfo_file_name); if (fd >= 0) return fd; } /* The above failed, so call abrt-action-install-debuginfo-to-abrt-cache to download and install the debuginfo */ if(current_session_for_find_debuginfo->verbose > 1) clog << _F("Downloading and installing debuginfo with build ID: '%s' using %s.", hex.c_str(), abrt_path.c_str()) << endl; struct tms tms_before; times (& tms_before); struct timeval tv_before; struct tms tms_after; unsigned _sc_clk_tck; struct timeval tv_after; gettimeofday (&tv_before, NULL); if(execute_abrt_action_install_debuginfo_to_abrt_cache (hex) < 0) { install_dbinfo_failed = -1; current_session_for_find_debuginfo->print_warning(_F("%s failed.", abrt_path.c_str())); goto call_dwfl_standard_find_debuginfo; } _sc_clk_tck = sysconf (_SC_CLK_TCK); times (& tms_after); gettimeofday (&tv_after, NULL); if(current_session_for_find_debuginfo->verbose > 1) clog << _("Download completed in ") << ((tms_after.tms_cutime + tms_after.tms_utime - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck)) << "usr/" << ((tms_after.tms_cstime + tms_after.tms_stime - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck)) << "sys/" << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms"<< endl; call_dwfl_standard_find_debuginfo: /* Call the original dwfl_standard_find_debuginfo */ return dwfl_standard_find_debuginfo(mod, userdata, modname, base, file_name, debuglink_file, debuglink_crc, debuginfo_file_name); } int execute_abrt_action_install_debuginfo_to_abrt_cache (string hex) { /* Be sure that abrt exists */ if (abrt_path.empty()) return -1; int timeout = current_session_for_find_debuginfo->download_dbinfo;; vector cmd; cmd.push_back ("/bin/sh"); cmd.push_back ("-c"); /* NOTE: abrt does not currently work with asking for confirmation * in version abrt-2.0.3-1.fc15.x86_64, Bugzilla: BZ726192 */ if(current_session_for_find_debuginfo->download_dbinfo == -1) { cmd.push_back ("echo " + hex + " | " + abrt_path + " --ids=-"); timeout = INT_MAX; current_session_for_find_debuginfo->print_warning(_("Due to bug in abrt, it may continue downloading anyway without asking for confirmation.")); } else cmd.push_back ("echo " + hex + " | " + abrt_path + " -y --ids=-"); /* NOTE: abrt does not allow canceling the download process at the moment * in version abrt-2.0.3-1.fc15.x86_64, Bugzilla: BZ730107 */ if(timeout != INT_MAX) current_session_for_find_debuginfo->print_warning(_("Due to a bug in abrt, it may continue downloading after stopping stap if download times out.")); int pid; if(current_session_for_find_debuginfo->verbose > 1 || current_session_for_find_debuginfo->download_dbinfo == -1) /* Execute abrt-action-install-debuginfo-to-abrt-cache, * showing output from abrt */ pid = stap_spawn(current_session_for_find_debuginfo->verbose, cmd, NULL); else { /* Execute abrt-action-install-debuginfo-to-abrt-cache, * without showing output from abrt */ posix_spawn_file_actions_t fa; if (posix_spawn_file_actions_init(&fa) != 0) return -1; if(posix_spawn_file_actions_addopen(&fa, 1, "/dev/null", O_WRONLY, 0) != 0) { posix_spawn_file_actions_destroy(&fa); return -1; } pid = stap_spawn(current_session_for_find_debuginfo->verbose, cmd, &fa); posix_spawn_file_actions_destroy(&fa); } /* Check to see if either the program successfully completed, or if it timed out. */ int rstatus = 0; int timer = 0; int rc = 0; while(timer < timeout) { sleep(1); rc = waitpid(pid, &rstatus, WNOHANG); if(rc < 0) return -1; if (rc > 0 && WIFEXITED(rstatus)) break; assert_no_interrupts(); timer++; } if(timer == timeout) { /* Timed out! */ kill(-pid, SIGINT); current_session_for_find_debuginfo->print_warning(_("Aborted downloading debuginfo: timed out.")); return -1; } /* Successfully finished downloading! */ #if 0 // Should not print this until BZ733690 is fixed as abrt could fail to download // and it would still print success. if(current_session_for_find_debuginfo->verbose > 1 || current_session_for_find_debuginfo->download_dbinfo == -1) clog << _("Download Completed Successfully!") << endl; #endif if(current_session_for_find_debuginfo->verbose > 1 || current_session_for_find_debuginfo->download_dbinfo == -1) clog << _("ABRT finished attempting to download debuginfo.") << endl; return 0; } /* Get the kernel build ID */ string get_kernel_build_id(systemtap_session &s) { bool found = false; string hex; // Try to find BuildID from vmlinux.id string kernel_buildID_path = s.kernel_build_tree + "/vmlinux.id"; if(s.verbose > 1) clog << _F("Attempting to extract kernel debuginfo build ID from %s", kernel_buildID_path.c_str()) << endl; ifstream buildIDfile; buildIDfile.open(kernel_buildID_path.c_str()); if(buildIDfile.is_open()) { getline(buildIDfile, hex); if(buildIDfile.good()) { found = true; } buildIDfile.close(); } // Try to find BuildID from the notes file if the above didn't work and we are // building a native module if(found == false && s.native_build) { if(s.verbose > 1) clog << _("Attempting to extract kernel debuginfo build ID from /sys/kernel/notes") << endl; const char *notesfile = "/sys/kernel/notes"; int fd = open64 (notesfile, O_RDONLY); if (fd < 0) return ""; assert (sizeof (Elf32_Nhdr) == sizeof (GElf_Nhdr)); assert (sizeof (Elf64_Nhdr) == sizeof (GElf_Nhdr)); union { GElf_Nhdr nhdr; unsigned char data[8192]; } buf; ssize_t n = read (fd, buf.data, sizeof buf); close (fd); if (n <= 0) return ""; unsigned char *p = buf.data; while (p < &buf.data[n]) { /* No translation required since we are reading the native kernel. */ GElf_Nhdr *nhdr = (GElf_Nhdr *) p; p += sizeof *nhdr; unsigned char *name = p; p += (nhdr->n_namesz + 3) & -4U; unsigned char *bits = p; p += (nhdr->n_descsz + 3) & -4U; if (p <= &buf.data[n] && nhdr->n_type == NT_GNU_BUILD_ID && nhdr->n_namesz == sizeof "GNU" && !memcmp (name, "GNU", sizeof "GNU")) { // Found it. hex = hex_dump(bits, nhdr->n_descsz); found = true; } } } if(found) { return hex; } else return ""; } /* Find the kernel build ID and attempt to download the matching debuginfo */ int download_kernel_debuginfo (systemtap_session &s, string hex) { // NOTE: At some point we want to base the // already_tried_downloading_kernel_debuginfo flag on the build ID rather // than just the stap process. // Don't try this again if we already did. static int already_tried_downloading_kernel_debuginfo = 0; if(already_tried_downloading_kernel_debuginfo) return -1; // Attempt to download the debuginfo if(s.verbose > 1) clog << _F("Success! Extracted kernel debuginfo build ID: %s", hex.c_str()) << endl; int rc = execute_abrt_action_install_debuginfo_to_abrt_cache(hex); already_tried_downloading_kernel_debuginfo = 1; if (rc < 0) return -1; // Success! return 0; } systemtap-2.3/setupdwfl.h000066400000000000000000000041771217430427200156100ustar00rootroot00000000000000// Setup routines for creating fully populated DWFLs. Used in pass 2 and 3. // Copyright (C) 2009-2011 Red Hat, Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // #ifndef SETUP_DWFLPP_H #define SETUP_DWFLPP_H #ifndef NT_GNU_BUILD_ID #define NT_GNU_BUILD_ID 3 #endif #include "config.h" #include "session.h" #include #include #include #if defined(HAVE_TR1_MEMORY) #include using std::tr1::shared_ptr; #elif defined(HAVE_BOOST_SHARED_PTR_HPP) #include using boost::shared_ptr; #else #error "No shared_ptr implementation found; get boost or modern g++" #endif extern "C" { #include } struct StapDwfl { public: StapDwfl(Dwfl *d) : dwfl(d) { } ~StapDwfl() { if (dwfl) dwfl_end (dwfl); } Dwfl *dwfl; }; typedef shared_ptr DwflPtr; DwflPtr setup_dwfl_kernel(const std::string &name, unsigned *found, systemtap_session &s); DwflPtr setup_dwfl_kernel(const std::set &names, unsigned *found, systemtap_session &s); DwflPtr setup_dwfl_user(const std::string &name); DwflPtr setup_dwfl_user(std::vector::const_iterator &begin, const std::vector::const_iterator &end, bool all_needed, systemtap_session &s); // user-space files must be full paths and not end in .ko bool is_user_module(const std::string &m); int internal_find_debuginfo (Dwfl_Module *mod, void **userdata __attribute__ ((unused)), const char *modname __attribute__ ((unused)), GElf_Addr base __attribute__ ((unused)), const char *file_name, const char *debuglink_file, GElf_Word debuglink_crc, char **debuginfo_file_name); int execute_abrt_action_install_debuginfo_to_abrt_cache (std::string hex); std::string get_kernel_build_id (systemtap_session &s); int download_kernel_debuginfo (systemtap_session &s, std::string hex); void debuginfo_path_insert_sysroot(std::string sysroot); #endif systemtap-2.3/smileytap.svg000066400000000000000000002202031217430427200161400ustar00rootroot00000000000000 image/svg+xml systemtap logo Andy Fitzsimon, Red Hat 2008 systemtap systemtap-2.3/stap-authorize-cert.cxx000066400000000000000000000041151217430427200200500ustar00rootroot00000000000000/* Add the certificate contained in the given file to the given certificate database. Copyright (C) 2011 Red Hat Inc. This file is part of systemtap, and 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, see . */ #include "config.h" extern "C" { #include } #include #include "util.h" #include "nsscommon.h" using namespace std; // Called by methods within nsscommon. extern "C" void nsscommon_error (const char *msg, int logit __attribute ((unused))) { clog << msg << endl << flush; } static void fatal (const char *msg) { nsscommon_error (msg); exit (1); } int main (int argc, char **argv) { // Obtain the filename of the certificate. if (argc < 2) { fatal (_("Certificate file must be specified")); return 1; } const char *certFileName = argv[1]; // Obtain the certificate database directory name. if (argc < 3) { fatal (_("Certificate database directory must be specified")); return 1; } const char *certDBName = argv[2]; // Make sure NSPR is initialized. Must be done before NSS is initialized PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); /* Set the cert database password callback. */ PK11_SetPasswordFunc (nssPasswordCallback); // Add the certificate to the database. SECStatus secStatus = add_client_cert (certFileName, certDBName); if (secStatus != SECSuccess) { // NSS message already issued. nsscommon_error (_("Unable to authorize certificate")); } // Clean up. PR_Cleanup (); return secStatus == SECSuccess; } systemtap-2.3/stap-env000077500000000000000000000031431217430427200150750ustar00rootroot00000000000000#!/bin/bash # Generate a certificate for the systemtap server and add it to the # database of trusted servers for the client. # # Copyright (C) 2009-2011 Red Hat Inc. # # This file is part of systemtap, and is free software. You can # redistribute it and/or modify it under the terms of the GNU General # Public License (GPL); either version 2, or (at your option) any # later version. # Common environment setup for stap scripts # Installation directories # INSTALL-HOOK These settings work for running the server from the source tree # INSTALL-HOOK using the dejagnu test harness and will be overridden at install # INSTALL-HOOK time. stap_sysconfdir=`pwd`/net stap_pkglibexecdir= stap_localstatedir=`pwd`/net/var # General configuration stap_avahi_service_tag=_stap._tcp # NSS certificate databases if test "X$SYSTEMTAP_DIR" = "X"; then stap_user_ssl_db=$HOME/.systemtap/ssl else stap_user_ssl_db=$SYSTEMTAP_DIR/ssl fi stap_certfile=stap.cert function stap_get_arch { # PR4186: Copy logic from coreutils uname (uname -i) to squash # i?86->i386. Actually, copy logic from linux top-level Makefile # to squash uname -m -> $(SUBARCH). # # This logic needs to match the logic in the systemtap_session # constructor in session.cxx. local machine=`uname -m` case $machine in i?86) machine="i386" ;; sun4u) machine="sparc64" ;; arm*) machine="arm" ;; sa1*) machine="arm" ;; s390*) machine="s390" ;; ppc*) machine="powerpc" ;; mips*) machine="mips" ;; sh?) machine="sh" ;; # the default is to just use the output of 'uname -m' esac echo $machine } systemtap-2.3/stap-gen-cert.cxx000066400000000000000000000060131217430427200166060ustar00rootroot00000000000000/* Generate the SSL/signing certificate used by the Systemtap Compile Server. Copyright (C) 2011 Red Hat Inc. This file is part of systemtap, and 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, see . */ #include "config.h" extern "C" { #include #include } #include #include "util.h" #include "nsscommon.h" using namespace std; // Called from methods within nsscommon.cxx. extern "C" void nsscommon_error (const char *msg, int logit __attribute ((unused))) { clog << msg << endl; } /* getopt variables */ extern int optind; /* File scope statics */ static bool use_db_password; static string cert_db_path; static string dnsNames; static void parse_options (int argc, char **argv) { // Examine the command line. while (true) { int grc = getopt (argc, argv, "P"); if (grc < 0) break; switch (grc) { case 'P': use_db_password = true; break; case '?': // Invalid/unrecognized option given. Message has already been issued. break; default: // Reached when one added a getopt option but not a corresponding switch/case: if (optarg) nsscommon_error (_F("%s : unhandled option '%c %s'", argv[0], (char)grc, optarg)); else nsscommon_error (_F("%s : unhandled option '%c'", argv[0], (char)grc)); break; } } if (optind < argc) { // The first non-option is the certificate database path. cert_db_path = argv[optind]; ++optind; // All other non options are additional dns names for the certificate. for (int i = optind; i < argc; i++) { if (! dnsNames.empty ()) dnsNames += ","; dnsNames += argv[i]; } } } int main (int argc, char **argv) { // Initial values. dnsNames.clear (); use_db_password = false; // Parse the arguments. parse_options (argc, argv); // Where is the ssl certificate/key database? if (cert_db_path.empty ()) cert_db_path = server_cert_db_path (); // Make sure NSPR is initialized. Must be done before NSS is initialized PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); /* Set the cert database password callback. */ PK11_SetPasswordFunc (nssPasswordCallback); // Generate the certificate database. int rc = gen_cert_db (cert_db_path, dnsNames, use_db_password); if (rc != 0) { // NSS message already issued. nsscommon_error (_("Unable to generate certificate")); } /* Exit NSPR gracefully. */ PR_Cleanup (); return rc; } systemtap-2.3/stap-prep000077500000000000000000000101451217430427200152530ustar00rootroot00000000000000#! /bin/bash LANG=C; export LANG check_error() { if test $1 != 0; then echo $2; exit $1; fi } prep_rpm_based() { # uname -r can produce different kinds of output: # 2.6.32-30.el6.x86_64 (no variant, but including ".arch") # 2.6.18-194.3.1.el5debug ("variant", without dot, no arch) # 2.6.33.4-95.fc13.i686.PAE (".arch.variant", two dots) if [ "$#" -lt 1 ]; then UNAME=`uname -r` # determine the kernel running on the machine else UNAME=$1 #user passed in uname value fi UNAME=`echo $UNAME | sed "s/ //"` #strip out any whitespace KERNEL="kernel" for VARIANT in debug kdump PAE xen; do # strip out ".variant" or else "variant" at end. TMP=`echo $UNAME | sed s/\\\\.$VARIANT\$// | sed s/$VARIANT\$//` if [ "$TMP" != "$UNAME" ]; then UNAME=$TMP; KERNEL="kernel-$VARIANT" fi done KERN_ARCH=`uname -m` KERN_REV=`echo $UNAME | sed s/.$KERN_ARCH//` # strip arch from uname CANDIDATES="$KERNEL-$KERN_REV.$KERN_ARCH \ $KERNEL-devel-$KERN_REV.$KERN_ARCH \ $KERNEL-debuginfo-$KERN_REV.$KERN_ARCH" NEEDED=`rpm --qf "%{name}-%{version}-%{release}.%{arch}\n" \ -q $CANDIDATES | grep "is not installed" | awk '{print $2}'` if [ "$NEEDED" != "" ]; then echo -e "Need to install the following packages:\n$NEEDED" if [ `id -u` = "0" ]; then #attempt download and install DIR=`mktemp -d` || exit 1 if [ ! -x /usr/bin/yumdownloader ]; then echo "Need to first install yum-utils for yumdownloader" yum install -y yum-utils fi yumdownloader --enablerepo="*debuginfo*" $NEEDED --destdir=$DIR \ --resolve check_error $? "problem downloading rpm(s) $NEEDED" rpm --force -ivh $DIR/*.rpm check_error $? "problem installing rpm(s) $NEEDED" rm -r $DIR #cleanup fi fi } prep_deb_based() { if [ $# -ne 0 ]; then echo "Specifying kernel version is not yet support on deb based systems." 1>&2 exit 1 fi # 2.6.32-5-amd64 # 2.6.32-37-generic ABINAME="$(cut -d " " -f 3 /proc/version)" # 2.6.32 BASEVERSION="$(echo "$ABINAME" | cut -d "-" -f 1)" case "$DISTRO" in Debian) # 2.6.32-39 if uname -v | grep -q Debian; then VERSION="$(uname -v | cut -d " " -f 4)" else VERSION="$(cut -d " " -f 5 /proc/version | cut -d ")" -f 1)" fi ;; Ubuntu) # 2.6.32-37.81 VERSION="$(cut -d " " -f 2 /proc/version_signature | cut -d "-" -f 1-2)" ;; esac ( echo "make >= 0" echo "linux-image-$ABINAME = $VERSION" echo "linux-headers-$ABINAME = $VERSION" case "$DISTRO" in Debian) echo "linux-image-$ABINAME-dbg = $VERSION" ;; Ubuntu) echo "linux-image-$ABINAME-dbgsym = $VERSION" ;; esac ) | while read package relation requiredversion; do installedversion="$(dpkg-query -W "$package" 2> /dev/null | cut -f 2)" if [ "$installedversion" = "" ]; then availableversion="$(apt-cache show $package 2> /dev/null | grep ^Version: | cut -d " " -f 2)" if [ "$availableversion" = "" ]; then echo "You need package $package but it does not seem to be available" if [ "$DISTRO" = "Ubuntu" -a "$(echo $package | grep dbgsym$)" ]; then echo " Ubuntu -dbgsym packages are typically in a separate repository" echo " Follow https://wiki.ubuntu.com/DebuggingProgramCrash to add this repository" elif [ "$DISTRO" = "Debian" -a "$(echo $package | grep dbg$)" ]; then echo " Debian does not have -dbg packages for all kernels. Consider switching to a kernel that has one." fi else echo "Please install $package" fi elif ! dpkg --compare-versions $installedversion $relation $requiredversion; then echo "Package $package version $installedversion does not match version of currently running kernel: $requiredversion" echo " Consider apt-get upgrade && reboot" fi done user="$(id --user --name)" if [ "$user" != "root" ]; then groups="$(id --groups --name)" for i in stapusr stapdev; do if [ "$(echo $groups | grep $i)" = "" ]; then echo "Be root or adduser $user $i" fi done fi } DISTRO="$(lsb_release --id --short 2> /dev/null)" if [ $? -ne 0 ]; then DISTRO="unknown" fi case "$DISTRO" in Debian|Ubuntu) prep_deb_based "$@" ;; *) prep_rpm_based "$@" ;; esac systemtap-2.3/stap-report000077500000000000000000000037721217430427200156300ustar00rootroot00000000000000#! /bin/sh run(){ echo "== $1 ==" sh -c "$@" || true } PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin export PATH exec 2>&1 if [ "`id -u`" -ne 0 ]; then echo echo WARNING: rerun $0 as root for fuller results. echo fi run "id" run "stap -V" run "which stap" run "locate --regex '/stap(run|io|dyn)?$' | xargs ls -ald" run "printenv | egrep '^PATH=|^LD_LIBRARY_PATH=|^SYSTEMTAP_.*=|^XDG_DATA.*='" run "stap -vv --poison-cache -p4 -e 'probe begin {exit()}'" run "gcc -v" run "uname -a" run "dmesg | egrep 'stap|systemtap' | tail -n 10" run "cat /proc/cpuinfo | egrep 'processor|vendor_id|model name'" if [ -x /usr/bin/dpkg ]; then # debian/ubuntu run "dpkg --list | egrep 'systemtap|elfutils|kernel|linux|gcc|dyninst|avahi|nss|nspr|dejagnu|libdw' | awk '{print \$2,\$3}' | sort" elif [ -x /usr/bin/rpm -o -x /bin/rpm ]; then # fedora/rhel/suse/... run "rpm -qa --qf '%{name}-%{version} %{release}.%{arch}\\t%{buildtime:date}@%{buildhost}\\n' | egrep 'systemtap|elfutils|kernel|gcc|dyninst|avahi|nss|nspr|dejagnu|libdw' | sort" elif [ -f /var/log/packages ]; then # slackware run "cat /var/log/packages | egrep 'systemtap|elfutils|kernel|gcc|dyninst|avahi|nss|nspr|dejagnu' | sort -k9" fi run "egrep 'PROBE|TRACE|MARKER|KALLSYM|_DEBUG_|MODULE|FENTRY|_SIG' /lib/modules/`uname -r`/build/.config | grep -v not.set | sort | fmt -w 80" run "find /debugfs /proc /sys /dev /sys/kernel/debug -path '*kprobe*' -o -path '*yama*' -type f 2>/dev/null | xargs grep -H ." run "lsmod" run "avahi-browse -r -t _stap._tcp" run "ifconfig -a" for file in /boot/vmlinuz-`uname -r` /usr/lib/debug/lib/modules/`uname -r`/vmlinux /lib/modules/`uname -r`/build/vmlinux do if [ -f $file ]; then run "eu-readelf -n $file | grep Build" fi done run "hexdump -C /sys/kernel/notes" for file in /sys/module/*/notes/.*build* do run "hexdump -C $file" done if [ -x /usr/bin/seinfo ]; then run "seinfo" fi if [ -x /usr/sbin/getenforce ]; then run "getenforce" fi if [ -x /usr/sbin/aa-status ]; then run "aa-status" fi systemtap-2.3/stap-server000066400000000000000000001103071217430427200156110ustar00rootroot00000000000000#!/bin/bash # # stap-server script for managing the systemtap compile server # # Copyright (C) 2008-2011 Red Hat Inc. # # This file is part of systemtap, and is free software. You can # redistribute it and/or modify it under the terms of the GNU General # Public License (GPL); either version 2, or (at your option) any # later version. # # This script provides management of systemtap compile servers as a service. # See stap-server(8) for more information. if [ -f /etc/rc.d/init.d/functions ]; then # Red Hat init functions . /etc/rc.d/init.d/functions else # Default init functions success () { echo -n "OK" } failure () { echo -n "FAILED" } fi # Systemtap function library . ${PKGLIBEXECDIR}stap-env prog=stap-server # Commands STAP_START_SERVER=${stap_pkglibexecdir}stap-start-server STAP_STOP_SERVER=${stap_pkglibexecdir}stap-stop-server UNAME=/bin/uname # Default Global Configuration CONFIG_FILE=$stap_sysconfdir/sysconfig/stap-server CONFIG_PATH=$stap_sysconfdir/stap-server/conf.d STAT_PATH=$stap_localstatedir/run/stap-server LOG_FILE=$stap_localstatedir/log/stap-server/log # Default option settings # Optional global config file OPT_CONFIG_FILE= OPT_OTHER= OPT_PORT_IX=0 OPT_LOG_IX=0 OPT_SSL_IX=0 OPT_MAXTHREADS_IX=0 echo_usage () { echo $"Usage: $prog {start|stop|restart|condrestart|try-restart|force-reload|status} [options]" echo $"Options:" echo $" -c configfile : specify additional global configuration file." echo $" -a arch : specify the target architecture." echo $" -r release : specify the kernel release." echo $" -I path : augment the search path for tapsets." echo $" -R path : specify the location of the systemtap runtime." echo $" -B options : specify 'make' options for building systemtap modules." echo $" -D name[=value] : add a macro definition for building systemtap modules." echo $" -u username : specify the user who will run the server(s)." echo $" -i : specify a server for each installed kernel release." echo $" -n nickname : specify a server configuration by nickname." echo $" -p pid : specify a server or server configuration by process id." echo $" -P : use a password for the server's NSS certificate database." echo $" -k : keep server temporary files." echo $" --port port : specify the network port to be used by the server." echo $" --log path : specify the location of the server's log file." echo $" --ssl path : specify the location of the server's certificate database." echo $" --max-threads threads : specify the maximum number of worker threads to handle concurrent requests." echo $"" echo $"All options may be specified more than once." echo $"" echo $"If -a is not specified, the default architecture is that of the host" echo $"platform." echo $"" echo $"If -r is not specified, the default kernel release is that currently" echo $"running on the host platform." echo $"" echo $"If -u is not specified, the default user is 'stap-server'" echo $"" echo $"If --port is not specified, the default is to use a randomly selected port." echo $"" echo $"If --log is not specified, the default is '$stap_localstatedir/log/stap-server/log'." echo $"" echo $"If --ssl is not specified, the default is '$stap_sysconfdir/ssl/server'." echo $"" echo $"If --max-threads is not specified, the default is the number of processors." echo $"" echo $"If --max-threads is specified with a value of 0, all requests are handled in the main thread." echo $"" echo $"Each -D, -I and -B option specifies an additional macro, path or option respectively" echo $"to be applied to subsequent servers specified." echo $"" echo $"Each --port, --log, --ssl and --max-threads option is added to an option-specific list" echo $"which will be applied, in turn, to each server specified. If more servers are specified" echo $"than options in a given list, the default for that option will be used for subsequent" echo $"servers." echo $"" echo $"For other options, each new instance overrides the previous setting." echo $"" echo $"The -i option is a shortcut which specifies one server for each kernel" echo $"release installed in /lib/modules/. Previous -D, -I, -R, -B and -u" echo $"options will be applied to each server, however previous -a options" echo $"are ignored and the default architecture is used." echo $"" echo $"The -n option allows the specification of a server configuration by" echo $"nickname. When -n is specified, a currently running server with the" echo $"given nickname will be searched for. If no currently running server" echo $"with the given nickname is found, a server configuration with the" echo $"given nickname will be searched for in" echo $"$stap_sysconfdir/stap-server/conf.d/*.conf." echo $"If a server configuration for the given nickname is found, the -a, -r," echo $"-D, -I, -R, -B and -u options for that server will be used as if they were" echo $"specified on the command line. If no configuration with the given" echo $"nickname is found, and the action is 'start' (or an action behaving" echo $"like 'start' (see below)), the server will be started with the given" echo $"nickname. If no configuration with the given nickname is found, and" echo $"the action is not 'start' (or an action behaving" "like 'start'," echo $"it is an error. If a nickname is not specified for a server, its" echo $"nickname will be its process id." echo $"" echo $"The -p option allows the specification of a server configuration by" echo $"process id. When -p is specified, a currently running server with the" echo $"given process id will be searched for. If no such server is found," echo $"it is an error. If a server with the given pid is found, the -a, -r," echo $"-D, -I, -R, -B and -u options for that server will be used as if they were" echo $"specified on the command line." echo $"" echo $"The -k option tells the server to keep the temporary directories it creates" echo $"during each transaction with a client." echo $"" echo $"The specified action is performed for the server(s) specified on the" echo $"command line. If no servers are specified on the command line, the" echo $"behavior is as follows:" echo $"" echo $" start: Start the servers configured in $stap_sysconfdir/stap-server/conf.d/*.conf." echo $" If none are configured, start a server for the kernel release" echo $" and architecture of the host platform." echo $"" echo $" stop: Stop all currently running servers." echo $"" echo $" restart: Restart all currently running servers. If no servers are running," echo $" behave as if 'start' was specified." echo $"" echo $" condrestart: Restart all currently running servers. If no servers are running," echo $" do nothing." echo $"" echo $" try-restart: Same as condrestart." echo $"" echo $" force-reload: Stop all currently running servers and behave as if 'start'" echo $" was specified." echo $"" echo $" status: Report the status of all current running servers." echo $"" } #----------------------------------------------------------------- # Helper functions #----------------------------------------------------------------- log () { # message echo `LC_ALL=en date +"%b %e %T"`": $1" >> "$LOG_FILE" } clog () { # message [-n] echo $2 "$1" log "$1" } slog () { # message logger "$1" # if syslogd is running, this message will be sent to syslog. log "$1" } logex () { # command eval log \"Exec: "$@"\" "$@" >> "$LOG_FILE" 2>&1 return $? } do_failure () { # message slog "Error: $1" failure "$1" } do_success () { # message log "Pass: $1" success "$1" } #------------------------------------------------------------------ # Parameter parsing and setup options #------------------------------------------------------------------ parse_args () { # arguments local rc=0 i_specified=0 while [ -n "$1" ]; do case "$1" in -k | -P) OPT_OTHER="$OPT_OTHER $1" shift 1 ;; -a) process_i SERVER_CMDS+=("ARCH=\"`quote_for_cmd "$2"`\"") shift 1 ;; -B) process_i SERVER_CMDS+=("BUILD+=(\"`quote_for_cmd "$2"`\")") shift 1 ;; -c) OPT_CONFIG_FILE="$2" shift 1 ;; -i) # Delay processing of -i in case a distributed option like --log is specified which could # apply to each server referenced by -i. We will process it just before handling other # options which describe a new server (e.g. -r). i_specified=$(($i_specified + 1)) ;; -D) process_i SERVER_CMDS+=("DEFINE+=(\"`quote_for_cmd "$2"`\")") shift 1 ;; -I) process_i SERVER_CMDS+=("INCLUDE+=(\"`quote_for_cmd "$2"`\")") shift 1 ;; -n) process_i process_n "$2" shift 1 ;; -p) process_i process_p "$2" test $? = 0 || rc=1 shift 1 ;; -r) process_i process_r "$2" test $? = 0 || rc=1 shift 1 ;; -R) process_i SERVER_CMDS+=("RUNTIME=\"`quote_for_cmd "$2"`\"") shift 1 ;; -u) process_i SERVER_CMDS+=("USER=\"`quote_for_cmd "$2"`\"") shift 1 ;; --log) OPT_LOG+=("$2") shift 1 ;; --port) OPT_PORT+=("$2") shift 1 ;; --ssl) OPT_SSL+=("$2") shift 1 ;; --max-threads) OPT_MAXTHREADS+=("$2") shift 1 ;; --) ;; *) rc=1 ;; esac shift 1 done # Process any lingering -i process_i # Add options from any lists and an EXEC command to the end if any server options were specified if test -n "$SERVER_CMDS"; then add_distributed_options SERVER_CMDS+=("EXEC") fi test $rc != 0 && echo_usage return $rc } # Some options accumulate into lists when specified more than once. The items in the each list # are the applied to each specified server in turn. If a list runs out, then the default for that # option is applied. add_distributed_options () { # The --log option if test -n "${OPT_LOG[$OPT_LOG_IX]}"; then SERVER_CMDS+=("LOG=\"`quote_for_cmd "${OPT_LOG[$OPT_LOG_IX]}"`\"") OPT_LOG_IX=$(($OPT_LOG_IX + 1)) else SERVER_CMDS+=("LOG=\"`quote_for_cmd "$LOG_FILE"`\"") fi # The --port option if test -n "${OPT_PORT[$OPT_PORT_IX]}"; then SERVER_CMDS+=("PORT=\"`quote_for_cmd "${OPT_PORT[$OPT_PORT_IX]}"`\"") OPT_PORT_IX=$(($OPT_PORT_IX + 1)) else SERVER_CMDS+=("PORT=\"\"") fi # The --ssl option if test -n "${OPT_SSL[$OPT_SSL_IX]}"; then SERVER_CMDS+=("SSL=\"`quote_for_cmd "${OPT_SSL[$OPT_SSL_IX]}"`\"") OPT_SSL_IX=$(($OPT_SSL_IX + 1)) else SERVER_CMDS+=("SSL=\"\"") fi # The --max-threads option if test -n "${OPT_MAXTHREADS[$OPT_MAXTHREADS_IX]}"; then SERVER_CMDS+=("MAXTHREADS=\"`quote_for_cmd "${OPT_MAXTHREADS[$OPT_MAXTHREADS_IX]}"`\"") OPT_MAXTHREADS_IX=$(($OPT_MAXTHREADS_IX + 1)) else SERVER_CMDS+=("MAXTHREADS=\"\"") fi } # Process the -i flag. process_i () { cd /lib/modules local release while test $i_specified -gt 0; do for release in `ls`; do if test -n "$SERVER_CMDS"; then add_distributed_options SERVER_CMDS+=("EXEC") fi process_r $release done i_specified=$(($i_specified - 1)) done return 0 } # Process the -n flag. process_n () { local target_NICKNAME="$1" # Is there a running server with this nickname? local pid=`get_server_pid_by_nickname "$target_NICKNAME"` if [ -n "$pid" ]; then # Read the configuration and add it to the configuration commands. interpret_server_status "$STAT_PATH/$pid.stat" || continue add_server_commands return fi # Is there a server configuration with this nickname? for f in "$CONFIG_PATH"/*.conf; do if [ -f "$f" ]; then interpret_server_config "$f" || continue test "X$NICKNAME" = "X$target_NICKNAME" || continue add_server_commands return fi done # No server configuration could be found for this nickname. Add a # NICKNAME_NOT_FOUND=... command to the configuration commands. SERVER_CMDS+=("NICKNAME_NOT_FOUND=\"`quote_for_cmd "$target_NICKNAME"`\"") } # Process the -p flag. process_p () { local pid="$1" # Are we managing a server with the given pid? test ! -f "$STAT_PATH/$pid.stat" && echo "No stap-server running as pid $pid" && \ exit 1 # Add the configuration of the server running as $pid to SERVER_CMDS interpret_server_status "$STAT_PATH/$pid.stat" || exit 1 add_server_commands return 0 } # Process the -r flag. process_r () { local first_char="${1:1:1}" if test "$first_char" = "/"; then # fully specified path local kernel_build_tree="$1" local version_file_name="$kernel_build_tree/include/config/kernel.release" # The file include/config/kernel.release within the kernel # build tree is used to pull out the version information local kernel_release=`cat $version_file_name 2>/dev/null` if test "X$kernel_release" = "X"; then echo "Missing $version_file_name" return 1 fi SERVER_CMDS+=("RELEASE=\"`quote_for_cmd "$1"`\"") # pass the path as-is return 0 fi # kernel release specified directly SERVER_CMDS+=("RELEASE=\"`quote_for_cmd "$1"`\"") return 0 } load_config () { # Include configs if [ -f "$CONFIG_FILE" ]; then interpret_config_file "$CONFIG_FILE" fi if [ -f "$OPT_CONFIG_FILE" ]; then interpret_config_file "$OPT_CONFIG_FILE" fi } # Default to the currently running kernel release get_release () { $UNAME -r } # Default to the currently running kernel release get_arch () { stap_get_arch } add_server_commands () { # Add commands based on the current state to SERVER_CMDS SERVER_CMDS+=("ARCH=\"`quote_for_cmd "$ARCH"`\"") SERVER_CMDS+=("RELEASE=\"`quote_for_cmd "$RELEASE"`\"") SERVER_CMDS+=("RUNTIME=\"`quote_for_cmd "$RUNTIME"`\"") SERVER_CMDS+=("DEFINE=()") for d in "${DEFINE[@]}"; do SERVER_CMDS+=("DEFINE+=(\"`quote_for_cmd "$d"`\")") done SERVER_CMDS+=("INCLUDE=()") for i in "${INCLUDE[@]}"; do SERVER_CMDS+=("INCLUDE+=(\"`quote_for_cmd "$i"`\")") done SERVER_CMDS+=("BUILD=()") for b in "${BUILD[@]}"; do SERVER_CMDS+=("BUILD+=(\"`quote_for_cmd "$b"`\")") done SERVER_CMDS+=("USER=\"`quote_for_cmd "$USER"`\"") SERVER_CMDS+=("NICKNAME=\"`quote_for_cmd "$NICKNAME"`\"") SERVER_CMDS+=("LOG=\"`quote_for_cmd "$LOG"`\"") test -n "$PORT" && SERVER_CMDS+=("PORT=\"`quote_for_cmd "$PORT"`\"") test -n "$SSL" && SERVER_CMDS+=("SSL=\"`quote_for_cmd "$SSL"`\"") test -n "$MAXTHREADS" && SERVER_CMDS+=("MAXTHREADS=\"`quote_for_cmd "$MAXTHREADS"`\"") } echo_server_options () { # Echo the current state. echo -n "-a \"`quote_for_cmd "$ARCH"`\"" echo -n " -r \"`quote_for_cmd "$RELEASE"`\"" test -n "$RUNTIME" && echo -n " -R \"`quote_for_cmd "$RUNTIME"`\"" for d in "${DEFINE[@]}"; do echo -n " -D \"`quote_for_cmd "$d"`\"" done for i in "${INCLUDE[@]}"; do echo -n " -I \"`quote_for_cmd "$i"`\"" done for b in "${BUILD[@]}"; do echo -n " -B \"`quote_for_cmd "$b"`\"" done echo -n " -u \"`quote_for_cmd "$USER"`\"" test -n "$NICKNAME" && echo -n " -n \"`quote_for_cmd "$NICKNAME"`\"" echo -n " --log \"`quote_for_cmd "$LOG"`\"" test -n "$PORT" && echo -n " --port \"`quote_for_cmd "$PORT"`\"" test -n "$SSL" && echo -n " --ssl \"`quote_for_cmd "$SSL"`\"" test -n "$MAXTHREADS" && echo -n " --max-threads \"`quote_for_cmd "$MAXTHREADS"`\"" echo } prepare_stat_dir () { if [ ! -d "$STAT_PATH" ]; then logex mkdir -p "$STAT_PATH" [ $? -ne 0 ] && return 1 fi return 0 } prepare_log_dir () { local log_path=`dirname "$1"` if [ ! -d "$log_path" ]; then mkdir -p "$log_path" [ $? -ne 0 ] && return 1 fi return 0 } init_server_opts () { ARCH=`get_arch` RELEASE=`get_release` unset DEFINE unset BUILD unset INCLUDE NICKNAME= NICKNAME_NOT_FOUND= RUNTIME= USER=$STAP_USER test -z "$USER" && USER=`id -un` LOG=$LOG_FILE PORT= SSL= MAXTHREADS= } # Double quotes, backslashes within generated command # arguments must be quoted. quote_for_cmd () { echo "$1" | \ sed -e 's/\\/\\\\/g' \ -e 's/"/\\"/g' } # Interpret the contents of a global config file. interpret_config_file () { local config_file="$1" # Save the results locally first, in case there is an error. local local_CONFIG_PATH= local local_STAT_PATH= local local_LOG_FILE= local local_STAP_USER= local input while read -r -u3 input do case "$input" in CONFIG_PATH=*) local_CONFIG_PATH="${input:12}" ;; STAT_PATH=*) local_STAT_PATH="${input:10}" ;; LOG_FILE=*) local_LOG_FILE="${input:9}" ;; STAP_USER=*) local_STAP_USER="${input:10}" ;; \#*) ;; # Comment, do nothing "") ;; # Empty line, do nothing *) echo $"Invalid input, \"$input\", in $config_file" >&2 exit 1 ;; esac done 3< "$config_file" # Now set the results globally test -n "$local_CONFIG_PATH" && CONFIG_PATH="$local_CONFIG_PATH" test -n "$local_STAT_PATH" && STAT_PATH="$local_STAT_PATH" test -n "$local_LOG_FILE" && LOG_FILE="$local_LOG_FILE" test -n "$local_STAP_USER" && STAP_USER="$local_STAP_USER" } # Interpret the contents of a server config file. interpret_server_config () { local config_file="$1" # Save the results locally first, in case there is an error. local local_ARCH= local local_RELEASE= local local_DEFINE=() local local_BUILD=() local local_INCLUDE=() local local_RUNTIME= local local_USER= local local_NICKNAME= local local_LOG= local local_PORT= local local_SSL= local local_MAXTHREADS= local input while read -r -u3 input do case "$input" in ARCH=*) local_ARCH="${input:5}" ;; RELEASE=*) local_RELEASE="${input:8}" ;; DEFINE=*) if [ -z "${input:7}" -o "${input:7}" = "()" ]; then local_DEFINE=() else local_DEFINE=("${input:7}") fi ;; DEFINE+=*) test -z "${input:8}" -o "${input:8}" = "()" || \ local_DEFINE+=("${input:8}") ;; BUILD=*) if [ -z "${input:6}" -o "${input:6}" = "()" ]; then local_BUILD=() else local_BUILD=("${input:6}") fi ;; BUILD+=*) test -z "${input:7}" -o "${input:7}" = "()" || \ local_BUILD+=("${input:7}") ;; INCLUDE=*) if [ -z "${input:8}" -o "${input:8}" = "()" ]; then local_INCLUDE=() else local_INCLUDE=("${input:8}") fi ;; INCLUDE+=*) test -z "${input:8}" -o "${input:8}" = "()" || \ local_INCLUDE+=("${input:9}") ;; RUNTIME=*) local_RUNTIME="${input:8}" ;; USER=*) local_USER="${input:5}" ;; NICKNAME=*) local_NICKNAME="${input:9}" ;; LOG=*) local_LOG="${input:4}" ;; PORT=*) local_PORT="${input:5}" ;; SSL=*) local_SSL="${input:4}" ;; MAXTHREADS=*) local_MAXTHREADS="${input:11}" ;; \#*) ;; # Comment, do nothing "") ;; # Empty line, do nothing *) echo $"Invalid input, \"$input\", in $config_file" >&2 exit 1 ;; esac done 3< "$config_file" # Now set the results globally. All variables are expected to be set, even # if to nothing. ARCH="$local_ARCH" RELEASE="$local_RELEASE" DEFINE=("${local_DEFINE[@]}") BUILD=("${local_BUILD[@]}") INCLUDE=("${local_INCLUDE[@]}") RUNTIME="$local_RUNTIME" USER="$local_USER" NICKNAME="$local_NICKNAME" LOG="$local_LOG" PORT="$local_PORT" SSL="$local_SSL" MAXTHREADS="$local_MAXTHREADS" } # Interpret the contents of a server status file. interpret_server_status () { # The contents of the server status files are currently the same as # that of server config files. interpret_server_config "$1" } # Load the default server config and add the results to SERVER_CMDS. load_server_config () { for f in "$CONFIG_PATH"/*.conf; do if [ -f "$f" ]; then # Obtain a configuration from each config file. # Ensure that we get the correct defaults for items not specified. local ARCH= local DEFINE=() local BUILD=() local INCLUDE=() local RUNTIME= local USER= local RELEASE= local LOG= local PORT= local SSL= local MAXTHREADS= interpret_server_config "$f" || continue # Other options default to empty. These ones don't. [ -z "$ARCH" ] && ARCH=`get_arch` [ -z "$RELEASE" ] && RELEASE=`get_release` [ -z "$USER" ] && USER=$STAP_USER [ -z "$USER" ] && USER=`id -un` [ -z "$LOG" ] && LOG="$LOG_FILE" add_server_commands SERVER_CMDS+=("EXEC") fi done } server_still_running () { # PID (ps -e | grep stap-serverd | grep -q $1) && return 0 # Still running rm -f "$STAT_PATH/$1.stat" return 1 # Not running } get_server_pid_by_config () { # Need to save the config, since the process of checking the running # servers alters it. local target_ARCH="$ARCH" local target_RELEASE="$RELEASE" local target_RUNTIME="$RUNTIME" local target_INCLUDE=("${INCLUDE[@]}") local target_BUILD=("${BUILD[@]}") local target_DEFINE=("${DEFINE[@]}") local target_USER="$USER" local target_NICKNAME="$NICKNAME" local target_LOG="$LOG" local target_PORT="$PORT" local target_SSL="$SSL" local target_MAXTHREADS="$MAXTHREADS" # Check the status file for each running server to see if it matches # the one currently configured. We're checking for a given configuration, # so don't compare the nickname. for f in "$STAT_PATH"/*.stat; do test ! -e "$f" && continue interpret_server_status "$f" || continue test "X$ARCH" = "X$target_ARCH" || continue test "X$RELEASE" = "X$target_RELEASE" || continue test "X$INCLUDE" = "X$target_INCLUDE" || continue test "X$RUNTIME" = "X$target_RUNTIME" || continue test "X$BUILD" = "X$target_BUILD" || continue test "X$DEFINE" = "X$target_DEFINE" || continue test "X$USER" = "X$target_USER" || continue test "X$LOG" = "X$target_LOG" || continue test "X$PORT" = "X$target_PORT" || continue test "X$SSL" = "X$target_SSL" || continue test "X$MAXTHREADS" = "X$target_MAXTHREADS" || continue echo `basename "$f" | sed 's/.stat//'` # Server has a pid return done ARCH="$target_ARCH" RELEASE="$target_RELEASE" RUNTIME="$target_RUNTIME" INCLUDE=("${target_INCLUDE[@]}") BUILD=("${target_BUILD[@]}") DEFINE=("${target_DEFINE[@]}") USER="$target_USER" NICKNAME="$target_NICKNAME" LOG="$target_LOG" PORT="$target_PORT" SSL="$target_SSL" MAXTHREADS="$target_MAXTHREADS" } get_server_pid_by_nickname () { # No need to save the current configuration. This function is not called # in a context requiring it. local target_NICKNAME="$1" # Check the status file for each running server to see if the nickname # matches the one we want. for f in "$STAT_PATH"/*.stat; do test ! -e "$f" && continue interpret_server_status "$f" || continue test "X$NICKNAME" = "X$target_NICKNAME" || continue echo `basename "$f" | sed 's/\.stat//'` # Server with nickname was found return done } managed_servers () { if [ ! -d "$STAT_PATH" ]; then echo "" return 1 fi cd "$STAT_PATH" local list=`ls | sed 's/\.stat//'` if [ -z "$list" ]; then echo "" return 1 fi echo "$list" } eval_server_command () { local cmd="$1" eval $cmd } start_server () { clog $"Starting $prog `echo_server_options`" # Is there already a server running for the requested kernel release # and arch? local server_pid=`get_server_pid_by_config` if test -n "$server_pid"; then if server_still_running $server_pid; then do_success $"$prog start `echo_server_options`" return 0 # Success fi fi # Create the log directory for this server prepare_log_dir "$LOG" if [ $? -ne 0 ]; then echo $"Failed to make log directory (`dirname "$LOG"`)" >&2 exit 1 fi # Construct the server start command. local server_cmd="$STAP_START_SERVER -r \"`quote_for_cmd "$RELEASE"`\" -a \"`quote_for_cmd "$ARCH"`\" $OPT_OTHER" for b in "${BUILD[@]}"; do server_cmd="$server_cmd -B \"`quote_for_cmd "$b"`\"" done for i in "${INCLUDE[@]}"; do server_cmd="$server_cmd -I \"`quote_for_cmd "$i"`\"" done for d in "${DEFINE[@]}"; do server_cmd="$server_cmd -D \"`quote_for_cmd "$d"`\"" done test -n "$RUNTIME" && server_cmd="$server_cmd -R \"`quote_for_cmd "$RUNTIME"`\"" server_cmd="$server_cmd --log=\"`quote_for_cmd "$LOG"`\"" test -n "$PORT" && server_cmd="$server_cmd --port \"`quote_for_cmd "$PORT"`\"" test -n "$SSL" && server_cmd="$server_cmd --ssl \"`quote_for_cmd "$SSL"`\"" test -n "$MAXTHREADS" && server_cmd="$server_cmd --max-threads \"`quote_for_cmd "$MAXTHREADS"`\"" # Start the server here. local pid if [ "$USER" != "`id -un`" ]; then pid=`runuser -s /bin/bash - $USER -c "$server_cmd"` else pid=`eval $server_cmd` fi if [ $? != 0 -o -z "$pid" ]; then if [ -n "$pid" ]; then rm -f "$STAT_PATH/$pid.stat" fi do_failure $"$prog start `echo_server_options`" return 1 # Failure fi # Nickname defaults to the pid. test -z "$NICKNAME" && NICKNAME="$pid" # Write the configuration to the status file. local server_status_file="$STAT_PATH/$pid.stat" echo "ARCH=$ARCH" > "$server_status_file" echo "USER=$USER" >> "$server_status_file" for b in "${BUILD[@]}"; do echo "BUILD+=$b" >> "$server_status_file" done for i in "${INCLUDE[@]}"; do echo "INCLUDE+=$i" >> "$server_status_file" done for d in "${DEFINE[@]}"; do echo "DEFINE+=$d" >> "$server_status_file" done echo "NICKNAME=$NICKNAME" >> "$server_status_file" echo "RUNTIME=$RUNTIME" >> "$server_status_file" echo "RELEASE=$RELEASE" >> "$server_status_file" echo "LOG=$LOG" >> "$server_status_file" echo "PORT=$PORT" >> "$server_status_file" echo "SSL=$SSL" >> "$server_status_file" echo "MAXTHREADS=$MAXTHREADS" >> "$server_status_file" do_success $"$prog start `echo_server_options`" } start () { # server-cmds prepare_stat_dir if [ $? -ne 0 ]; then do_failure $"Failed to make stat directory ($STAT_PATH)" return 1 fi # Start the specified servers local server_cmds=("$@") # If none specified, start the configured servers if [ -z "$server_cmds" ]; then unset SERVER_CMDS load_server_config server_cmds=("${SERVER_CMDS[@]}") # If none configured, start the default servers if test -z "$server_cmds"; then add_distributed_options server_cmds=("${SERVER_CMDS[@]}") server_cmds+=("EXEC") fi fi # Start each requested server in turn local rc=0 local first=1 init_server_opts local cmd local prevCmd for cmd in "${server_cmds[@]}"; do prevCmd="$cmd" # Evaluate commands until the EXEC command is found. if test "$cmd" != "EXEC"; then eval_server_command "$cmd" # A specified nickname only sticks if it is the final command. # Otherwise, we have a configuration based on a nicknamed # configuration. echo "$cmd" | grep -q "^NICKNAME=" || NICKNAME="" continue fi # If a nickname was specified, but the corresponding config was not found, # then it is the nickname for this new configuration. if test -n "$NICKNAME_NOT_FOUND"; then NICKNAME="$NICKNAME_NOT_FOUND" NICKNAME_NOT_FOUND= fi # Start the configured server test $first = 0 && echo first=0 start_server || rc=1 # Don't use the same nickname for the next server. NICKNAME= done return $rc } stop () { # server-cmds local first=1 local server_list= local server_cmds=("$@") if [ -n "$server_cmds" ]; then # Get the pids of all the requested servers. init_server_opts local cmd local prevCmd for cmd in "${server_cmds[@]}"; do prevCmd="$cmd" # Evaluate commands until the EXEC command is found. if test "$cmd" != "EXEC"; then eval_server_command "$cmd" # A specified nickname only sticks if it is the final command. # Otherwise, we have a configuration based on a nicknamed # configuration. echo "$cmd" | grep -q "^NICKNAME=" || NICKNAME="" continue fi # If a nickname was specified, but the corresponding config was not # found, it is an error. if test -n "$NICKNAME_NOT_FOUND"; then clog "No configuration found for the nickname '$NICKNAME_NOT_FOUND'" NICKNAME="$NICKNAME_NOT_FOUND" do_failure $"$prog stop `echo_server_options`" NICKNAME_NOT_FOUND= rc=1 continue fi # Get the pid for this server, if it's running local server_pid=`get_server_pid_by_config` if test -n "$server_pid"; then server_list="$server_list $server_pid" continue fi # This server is not running, but give a success stop status anyway. test $first = 0 && echo first=0 clog $"Stopping $prog `echo_server_options`" do_success $"$prog stop `echo_server_options`" done else server_list=`managed_servers` if [ -z "$server_list" ]; then clog $"Stopping $prog: " -n do_success $"$prog: No managed servers to stop" return 0 fi fi # Stop each server in turn local rc=0 local pid for pid in $server_list; do if ! interpret_server_status "$STAT_PATH/$pid.stat"; then rc=1 continue fi test $first = 0 && echo first=0 clog $"Stopping $prog `echo_server_options`" local this_rc=0 if server_still_running $pid; then if [ "$USER" != "`id -un`" ]; then runuser -s /bin/bash - $USER -c "$STAP_STOP_SERVER $pid" else eval $STAP_STOP_SERVER $pid fi if [ $? != 0 ]; then do_failure $"$prog stop `echo_server_options`" this_rc=1 rc=1 fi fi if [ $this_rc = 0 ]; then rm -f "$STAT_PATH/$pid.stat" do_success $"$prog stop `echo_server_options`" fi done return $rc } status () { # server-list local rc=0 # Report status for the specified servers or all running servers, if none # specified. local server_list= local server_cmds=("$@") if [ -n "$server_cmds" ]; then # Get the pids of all the requested servers. init_server_opts local cmd local prevCmd for cmd in "${server_cmds[@]}"; do prevCmd="$cmd" # Evaluate commands until the EXEC command is found. if test "$cmd" != "EXEC"; then eval_server_command "$cmd" # A specified nickname only sticks if it is the final command. # Otherwise, we have a configuration based on a nicknamed # configuration. echo "$cmd" | grep -q "^NICKNAME=" || NICKNAME="" continue fi # If a nickname was specified, but the corresponding config was not # found, say so. if test -n "$NICKNAME_NOT_FOUND"; then echo "No configuration found for the nickname '$NICKNAME_NOT_FOUND'" NICKNAME_NOT_FOUND= rc=3 continue fi # Get the pid for this server, if it's running local server_pid=`get_server_pid_by_config` if test -n "$server_pid"; then server_list="$server_list $server_pid" continue fi # This server is not running echo "stap-server `echo_server_options` is not running" rc=3 done else server_list=`managed_servers` if [ -z "$server_list" ]; then echo "No managed stap-server is running" return 3 fi fi # Get status of each server in turn local pid for pid in $server_list; do if ! interpret_server_status "$STAT_PATH/$pid.stat"; then rc=1 continue fi if ! server_still_running $pid; then echo "stap-server `echo_server_options` started as PID $pid is no longer running" rc=1 continue fi echo "stap-server `echo_server_options` running as PID $pid" done return $rc } # Restart or start if not running function restart () { # server-cmds # Restart the specified servers or all servers, if none specified. local rc=0 local server_cmds=("$@") if [ -z "$server_cmds" ]; then local server_list=`managed_servers` local pid for pid in $server_list; do if ! interpret_server_status "$STAT_PATH/$pid.stat"; then rc=1 continue fi unset SERVER_CMDS add_server_commands server_cmds+=("${SERVER_CMDS[@]}") server_cmds+=("EXEC") done fi # Stop the specified servers, or all if none specified stop "${server_cmds[@]}" || rc=1 echo # Restart the same servers. If none were specified then # start the configured or default server(s)). start "${server_cmds[@]}" local this_rc=$? [ $this_rc != 0 ] && rc=$this_rc return $rc } # Restart only if running function condrestart () { # server-list # Restart the specified servers or all servers, if none specified, # but only if they are already running. local rc=0 local server_cmds=("$@") if [ -z "$server_cmds" ]; then local server_list=`managed_servers` local pid for pid in $server_list; do if ! interpret_server_status "$STAT_PATH/$pid.stat"; then rc=1 continue fi unset SERVER_CMDS add_server_commands server_cmds+=("${SERVER_CMDS[@]}") server_cmds+=("EXEC") done # No server specified or running? if [ -z "$server_cmds" ]; then clog "No managed stap-server is running" -n do_success "No managed stap-server is running" return 0 fi fi # For each server in the list, stop it if it is running local first=1 local this_server_cmds local cmd for cmd in "${server_cmds[@]}"; do # Execute and collect commands until the EXEC command is found. this_server_cmds+=("$cmd") if test "$cmd" != "EXEC"; then eval_server_command "$cmd" continue fi test $first = 0 && echo first=0 # Now see if this server is running if ! status "${this_server_cmds[@]}" >/dev/null 2>&1; then clog $"$prog `echo_server_options` is not running" do_success "$prog `echo_server_options` is not running" unset this_server_cmds continue fi start_cmds+=("${this_server_cmds[@]}") stop "${this_server_cmds[@]}" this_rc=$? [ $this_rc != 0 ] && rc=$this_rc unset this_server_cmds done # Now restart the servers that were running if [ -n "$start_cmds" ]; then echo start "${start_cmds[@]}" local this_rc=$? [ $this_rc != 0 ] && rc=$this_rc fi return $rc } #------------------------------------------------------------------ # Mainline script #------------------------------------------------------------------ CMD=$1 shift 1 prepare_log_dir "$LOG_FILE" if [ $? -ne 0 ]; then echo $"Failed to make log directory (`dirname $LOG_FILE`)" >&2 exit 1 fi OPTS=`getopt -s bash -u --options 'a:B:c:D:iI:n:p:kPr:R:u:' \ --longoptions 'log:' \ --longoptions 'port:' \ --longoptions 'ssl:' \ --longoptions 'max-threads:' \ -- "$@"` if [ $? -ne 0 ]; then echo "Error: Argument parse error: $@" >&2 echo_usage exit 2 fi # Initialize server specs parse_args "$@" || exit 2 load_config RETVAL=0 case $CMD in start) # Start specified servers. If none specified, start configured servers start "${SERVER_CMDS[@]}" RETVAL=$? ;; stop) # Stop specified servers stop "${SERVER_CMDS[@]}" RETVAL=$? ;; restart) # Restart specified servers restart "${SERVER_CMDS[@]}" RETVAL=$? ;; condrestart|try-restart) # Restart specified servers if they are running condrestart "${SERVER_CMDS[@]}" RETVAL=$? ;; status) # Give status on specified servers status "${SERVER_CMDS[@]}" exit $? ;; reload) # Reloading config without stop/restart is not supported RETVAL=3 ;; force-reload) # Reload config with stop/start # stop all running servers stop echo # Restart specified servers # If none specified, restart configured servers start "${SERVER_CMDS[@]}" RETVAL=$? ;; usage|*) echo_usage RETVAL=0 ;; esac echo exit $RETVAL systemtap-2.3/stap-server.conf000066400000000000000000000000651217430427200165340ustar00rootroot00000000000000D /var/run/stap-server 0755 stap-server stap-server -systemtap-2.3/stap-server.service000066400000000000000000000005471217430427200172540ustar00rootroot00000000000000[Unit] Description=Systemtap Compile Server Documentation=man:stap-server(8) Wants=avahi-daemon.service After=network.target avahi-daemon.service [Service] Type=oneshot User=stap-server ExecStart=/usr/bin/stap-server start ExecReload=/usr/bin/stap-server restart ExecStop=/usr/bin/stap-server stop RemainAfterExit=yes [Install] WantedBy=multi-user.targetsystemtap-2.3/stap-serverd.cxx000066400000000000000000001616431217430427200165670ustar00rootroot00000000000000/* SSL server program listens on a port, accepts client connection, reads the data into a temporary file, calls the systemtap translator and then transmits the resulting file back to the client. Copyright (C) 2011-2013 Red Hat Inc. This file is part of systemtap, and 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, see . */ #include "config.h" #include #include #include #include #include #include #include extern "C" { #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_AVAHI #include #include #include #include #include #endif } #include "util.h" #include "nsscommon.h" #include "cscommon.h" #include "cmdline.h" using namespace std; static void cleanup (); static PRStatus spawn_and_wait (const vector &argv, const char* fd0, const char* fd1, const char* fd2, const char *pwd, const vector& envVec = vector ()); /* getopt variables */ extern int optind; /* File scope statics. Set during argument parsing and initialization. */ static bool use_db_password; static unsigned short port; static long max_threads; static string cert_db_path; static string stap_options; static string uname_r; static string arch; static string cert_serial_number; static string B_options; static string I_options; static string R_option; static string D_options; static bool keep_temp; sem_t sem_client; static int pending_interrupts; #define CONCURRENCY_TIMEOUT_S 3 // Message handling. // Server_error messages are printed to stderr and logged, if requested. static void server_error (const string &msg, int logit = true) { cerr << msg << endl << flush; // Log it, but avoid repeated messages to the terminal. if (logit && log_ok ()) log (msg); } // client_error messages are treated as server errors and also printed to the client's stderr. static void client_error (const string &msg, string stapstderr) { server_error (msg); if (! stapstderr.empty ()) { ofstream errfile; errfile.open (stapstderr.c_str (), ios_base::app); if (! errfile.good ()) server_error (_F("Could not open client stderr file %s: %s", stapstderr.c_str (), strerror (errno))); else errfile << "Server: " << msg << endl; // NB: No need to close errfile } } // Messages from the nss common code are treated as server errors. extern "C" void nsscommon_error (const char *msg, int logit) { server_error (msg, logit); } // Fatal errors are treated as server errors but also result in termination // of the server. static void fatal (const string &msg) { server_error (msg); cleanup (); exit (1); } // Argument handling static void process_a (const string &arg) { arch = arg; stap_options += " -a " + arg; } static void process_r (const string &arg) { if (arg[0] == '/') // fully specified path uname_r = kernel_release_from_build_tree (arg); else uname_r = arg; stap_options += " -r " + arg; // Pass the argument to stap directly. } static void process_log (const char *arg) { start_log (arg); } static void parse_options (int argc, char **argv) { // Examine the command line. This is the command line for us (stap-serverd) not the command // line for spawned stap instances. optind = 1; while (true) { char *num_endptr; long port_tmp; // NB: The values of these enumerators must not conflict with the values of ordinary // characters, since those are returned by getopt_long for short options. enum { LONG_OPT_PORT = 256, LONG_OPT_SSL, LONG_OPT_LOG, LONG_OPT_MAXTHREADS }; static struct option long_options[] = { { "port", 1, NULL, LONG_OPT_PORT }, { "ssl", 1, NULL, LONG_OPT_SSL }, { "log", 1, NULL, LONG_OPT_LOG }, { "max-threads", 1, NULL, LONG_OPT_MAXTHREADS }, { NULL, 0, NULL, 0 } }; int grc = getopt_long (argc, argv, "a:B:D:I:kPr:R:", long_options, NULL); if (grc < 0) break; switch (grc) { case 'a': process_a (optarg); break; case 'B': B_options += string (" -") + (char)grc + optarg; stap_options += string (" -") + (char)grc + optarg; break; case 'D': D_options += string (" -") + (char)grc + optarg; stap_options += string (" -") + (char)grc + optarg; break; case 'I': I_options += string (" -") + (char)grc + optarg; stap_options += string (" -") + (char)grc + optarg; break; case 'k': keep_temp = true; break; case 'P': use_db_password = true; break; case 'r': process_r (optarg); break; case 'R': R_option = string (" -") + (char)grc + optarg; stap_options += string (" -") + (char)grc + optarg; break; case LONG_OPT_PORT: port_tmp = strtol (optarg, &num_endptr, 10); if (*num_endptr != '\0') fatal (_F("%s: cannot parse number '--port=%s'", argv[0], optarg)); else if (port_tmp < 0 || port_tmp > 65535) fatal (_F("%s: invalid entry: port must be between 0 and 65535 '--port=%s'", argv[0], optarg)); else port = (unsigned short) port_tmp; break; case LONG_OPT_SSL: cert_db_path = optarg; break; case LONG_OPT_LOG: process_log (optarg); break; case LONG_OPT_MAXTHREADS: max_threads = strtol (optarg, &num_endptr, 0); if (*num_endptr != '\0') fatal (_F("%s: cannot parse number '--max-threads=%s'", argv[0], optarg)); else if (max_threads < 0) fatal (_F("%s: invalid entry: max threads must not be negative '--max-threads=%s'", argv[0], optarg)); break; case '?': // Invalid/unrecognized option given. Message has already been issued. break; default: // Reached when one added a getopt option but not a corresponding switch/case: if (optarg) server_error (_F("%s: unhandled option '%c %s'", argv[0], (char)grc, optarg)); else server_error (_F("%s: unhandled option '%c'", argv[0], (char)grc)); break; } } for (int i = optind; i < argc; i++) server_error (_F("%s: unrecognized argument '%s'", argv[0], argv[i])); } static string server_cert_file () { return server_cert_db_path () + "/stap.cert"; } // Signal handling. When an interrupt is received, kill any spawned processes // and exit. extern "C" void handle_interrupt (int sig) { pending_interrupts++; if(pending_interrupts >= 2) { log (_F("Received another signal %d, exiting (forced)", sig)); _exit(0); } log (_F("Received signal %d, exiting", sig)); } static void setup_signals (sighandler_t handler) { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = handler; sigemptyset (&sa.sa_mask); if (handler != SIG_IGN) { sigaddset (&sa.sa_mask, SIGHUP); sigaddset (&sa.sa_mask, SIGPIPE); sigaddset (&sa.sa_mask, SIGINT); sigaddset (&sa.sa_mask, SIGTERM); sigaddset (&sa.sa_mask, SIGTTIN); sigaddset (&sa.sa_mask, SIGTTOU); sigaddset (&sa.sa_mask, SIGXFSZ); sigaddset (&sa.sa_mask, SIGXCPU); } sa.sa_flags = SA_RESTART; sigaction (SIGHUP, &sa, NULL); sigaction (SIGPIPE, &sa, NULL); sigaction (SIGINT, &sa, NULL); sigaction (SIGTERM, &sa, NULL); sigaction (SIGTTIN, &sa, NULL); sigaction (SIGTTOU, &sa, NULL); sigaction (SIGXFSZ, &sa, NULL); sigaction (SIGXCPU, &sa, NULL); } #if HAVE_AVAHI static AvahiEntryGroup *avahi_group = NULL; static AvahiThreadedPoll *avahi_threaded_poll = NULL; static char *avahi_service_name = NULL; static AvahiClient *avahi_client = 0; static void create_services (AvahiClient *c); static void entry_group_callback ( AvahiEntryGroup *g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata ) { assert(g == avahi_group || avahi_group == NULL); avahi_group = g; // Called whenever the entry group state changes. switch (state) { case AVAHI_ENTRY_GROUP_ESTABLISHED: // The entry group has been established successfully. log (_F("Service '%s' successfully established.", avahi_service_name)); break; case AVAHI_ENTRY_GROUP_COLLISION: { char *n; // A service name collision with a remote service. // happened. Let's pick a new name. n = avahi_alternative_service_name (avahi_service_name); avahi_free (avahi_service_name); avahi_service_name = n; server_error (_F("Avahi service name collision, renaming service to '%s'", avahi_service_name)); // And recreate the services. create_services (avahi_entry_group_get_client (g)); break; } case AVAHI_ENTRY_GROUP_FAILURE: server_error (_F("Avahi entry group failure: %s", avahi_strerror (avahi_client_errno (avahi_entry_group_get_client (g))))); // Some kind of failure happened while we were registering our services. avahi_threaded_poll_stop (avahi_threaded_poll); break; case AVAHI_ENTRY_GROUP_UNCOMMITED: case AVAHI_ENTRY_GROUP_REGISTERING: break; } } static void create_services (AvahiClient *c) { assert (c); // If this is the first time we're called, let's create a new // entry group if necessary. if (! avahi_group) if (! (avahi_group = avahi_entry_group_new (c, entry_group_callback, NULL))) { server_error (_F("avahi_entry_group_new () failed: %s", avahi_strerror (avahi_client_errno (c)))); goto fail; } // If the group is empty (either because it was just created, or // because it was reset previously, add our entries. if (avahi_entry_group_is_empty (avahi_group)) { log (_F("Adding Avahi service '%s'", avahi_service_name)); // Create the txt tags that will be registered with our service. string sysinfo = "sysinfo=" + uname_r + " " + arch; string certinfo = "certinfo=" + cert_serial_number; string version = string ("version=") + CURRENT_CS_PROTOCOL_VERSION;; string optinfo = "optinfo="; string separator; // These option strings already have a leading space. if (! R_option.empty ()) { optinfo += R_option.substr(1); separator = " "; } if (! B_options.empty ()) { optinfo += separator + B_options.substr(1); separator = " "; } if (! D_options.empty ()) { optinfo += separator + D_options.substr(1); separator = " "; } if (! I_options.empty ()) optinfo += separator + I_options.substr(1); // We will now add our service to the entry group. Only services with the // same name should be put in the same entry group. int ret; if ((ret = avahi_entry_group_add_service (avahi_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, (AvahiPublishFlags)0, avahi_service_name, "_stap._tcp", NULL, NULL, port, sysinfo.c_str (), optinfo.c_str (), version.c_str (), certinfo.c_str (), NULL)) < 0) { if (ret == AVAHI_ERR_COLLISION) goto collision; server_error (_F("Failed to add _stap._tcp service: %s", avahi_strerror (ret))); goto fail; } // Tell the server to register the service. if ((ret = avahi_entry_group_commit (avahi_group)) < 0) { server_error (_F("Failed to commit avahi entry group: %s", avahi_strerror (ret))); goto fail; } } return; collision: // A service name collision with a local service happened. Let's // pick a new name. char *n; n = avahi_alternative_service_name (avahi_service_name); avahi_free(avahi_service_name); avahi_service_name = n; server_error (_F("Avahi service name collision, renaming service to '%s'", avahi_service_name)); avahi_entry_group_reset (avahi_group); create_services (c); return; fail: avahi_entry_group_reset (avahi_group); avahi_threaded_poll_stop (avahi_threaded_poll); } static void client_callback (AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) { assert(c); // Called whenever the client or server state changes. switch (state) { case AVAHI_CLIENT_S_RUNNING: // The server has startup successfully and registered its host // name on the network, so it's time to create our services. create_services (c); break; case AVAHI_CLIENT_FAILURE: server_error (_F("Avahi client failure: %s", avahi_strerror (avahi_client_errno (c)))); avahi_threaded_poll_stop (avahi_threaded_poll); break; case AVAHI_CLIENT_S_COLLISION: // Let's drop our registered services. When the server is back // in AVAHI_SERVER_RUNNING state we will register them // again with the new host name. // Fall through ... case AVAHI_CLIENT_S_REGISTERING: // The server records are now being established. This // might be caused by a host name change. We need to wait // for our own records to register until the host name is // properly esatblished. if (avahi_group) avahi_entry_group_reset (avahi_group); break; case AVAHI_CLIENT_CONNECTING: break; } } static void avahi_cleanup () { if (avahi_service_name) log (_F("Removing Avahi service '%s'", avahi_service_name)); // Stop the avahi client, if it's running if (avahi_threaded_poll) avahi_threaded_poll_stop (avahi_threaded_poll); // Clean up the avahi objects. The order of freeing these is significant. if (avahi_group) { avahi_entry_group_reset (avahi_group); avahi_entry_group_free (avahi_group); avahi_group = 0; } if (avahi_client) { avahi_client_free (avahi_client); avahi_client = 0; } if (avahi_threaded_poll) { avahi_threaded_poll_free (avahi_threaded_poll); avahi_threaded_poll = 0; } if (avahi_service_name) { avahi_free (avahi_service_name); avahi_service_name = 0; } } // The entry point for the avahi client thread. static void avahi_publish_service (CERTCertificate *cert) { cert_serial_number = get_cert_serial_number (cert); string buf; try { buf = "Systemtap Compile Server, pid=" + lex_cast (getpid ()); } catch (const runtime_error &e) { server_error(_F("Failed to cast pid '%d' to a string: %s", getpid(), e.what())); return; } avahi_service_name = avahi_strdup (buf.c_str ()); // Allocate main loop object. if (! (avahi_threaded_poll = avahi_threaded_poll_new ())) { server_error (_("Failed to create avahi threaded poll object.")); return; } // Always allocate a new client. int error; avahi_client = avahi_client_new (avahi_threaded_poll_get (avahi_threaded_poll), (AvahiClientFlags)0, client_callback, NULL, & error); // Check whether creating the client object succeeded. if (! avahi_client) { server_error (_F("Failed to create avahi client: %s", avahi_strerror(error))); return; } // Run the main loop. avahi_threaded_poll_start (avahi_threaded_poll); return; } #endif // HAVE_AVAHI static void advertise_presence (CERTCertificate *cert __attribute ((unused))) { #if HAVE_AVAHI avahi_publish_service (cert); #else server_error (_("Unable to advertise presence on the network. Avahi is not available")); #endif } static void unadvertise_presence () { #if HAVE_AVAHI avahi_cleanup (); #endif } static void initialize (int argc, char **argv) { pending_interrupts = 0; setup_signals (& handle_interrupt); // Seed the random number generator. Used to generate noise used during key generation. srand (time (NULL)); // Initial values. use_db_password = false; port = 0; max_threads = sysconf( _SC_NPROCESSORS_ONLN ); // Default to number of processors keep_temp = false; struct utsname utsname; uname (& utsname); uname_r = utsname.release; arch = normalize_machine (utsname.machine); // Parse the arguments. This also starts the server log, if any, and should be done before // any messages are issued. parse_options (argc, argv); // PR11197: security prophylactics. // Reject use as root, except via a special environment variable. if (! getenv ("STAP_PR11197_OVERRIDE")) { if (geteuid () == 0) fatal ("For security reasons, invocation of stap-serverd as root is not supported."); } struct passwd *pw = getpwuid (geteuid ()); if (! pw) fatal (_F("Unable to determine effective user name: %s", strerror (errno))); string username = pw->pw_name; pid_t pid = getpid (); log (_F("===== compile server pid %d starting as %s =====", pid, username.c_str ())); // Where is the ssl certificate/key database? if (cert_db_path.empty ()) cert_db_path = server_cert_db_path (); // Make sure NSPR is initialized. Must be done before NSS is initialized PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); /* Set the cert database password callback. */ PK11_SetPasswordFunc (nssPasswordCallback); } static void cleanup () { unadvertise_presence (); end_log (); } /* Function: readDataFromSocket() * * Purpose: Read data from the socket into a temporary file. * */ static PRInt32 readDataFromSocket(PRFileDesc *sslSocket, const char *requestFileName) { PRFileDesc *local_file_fd = 0; PRInt32 numBytesExpected; PRInt32 numBytesRead; PRInt32 numBytesWritten; PRInt32 totalBytes = 0; #define READ_BUFFER_SIZE 4096 char buffer[READ_BUFFER_SIZE]; // Read the number of bytes to be received. /* XXX: impose a limit to prevent disk space consumption DoS */ numBytesRead = PR_Read_Complete (sslSocket, & numBytesExpected, (PRInt32)sizeof (numBytesExpected)); if (numBytesRead == 0) /* EOF */ { server_error (_("Error reading size of request file")); goto done; } if (numBytesRead < 0) { server_error (_("Error in PR_Read")); nssError (); goto done; } /* Convert numBytesExpected from network byte order to host byte order. */ numBytesExpected = ntohl (numBytesExpected); /* If 0 bytes are expected, then we were contacted only to obtain our certificate. There is no client request. */ if (numBytesExpected == 0) return 0; /* Open the output file. */ local_file_fd = PR_Open(requestFileName, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, PR_IRUSR | PR_IWUSR); if (local_file_fd == NULL) { server_error (_F("Could not open output file %s", requestFileName)); nssError (); return -1; } // Read until EOF or until the expected number of bytes has been read. for (totalBytes = 0; totalBytes < numBytesExpected; totalBytes += numBytesRead) { // No need for PR_Read_Complete here, since we're already managing multiple // reads to a fixed size buffer. numBytesRead = PR_Read (sslSocket, buffer, READ_BUFFER_SIZE); if (numBytesRead == 0) break; /* EOF */ if (numBytesRead < 0) { server_error (_("Error in PR_Read")); nssError (); goto done; } /* Write to the request file. */ numBytesWritten = PR_Write(local_file_fd, buffer, numBytesRead); if (numBytesWritten < 0 || (numBytesWritten != numBytesRead)) { server_error (_F("Could not write to output file %s", requestFileName)); nssError (); goto done; } } if (totalBytes != numBytesExpected) { server_error (_F("Expected %d bytes, got %d while reading client request from socket", numBytesExpected, totalBytes)); goto done; } done: if (local_file_fd) PR_Close (local_file_fd); return totalBytes; } /* Function: setupSSLSocket() * * Purpose: Configure a socket for SSL. * * */ static PRFileDesc * setupSSLSocket (PRFileDesc *tcpSocket, CERTCertificate *cert, SECKEYPrivateKey *privKey) { PRFileDesc *sslSocket; SSLKEAType certKEA; SECStatus secStatus; /* Inport the socket into SSL. */ sslSocket = SSL_ImportFD (NULL, tcpSocket); if (sslSocket == NULL) { server_error (_("Could not import socket into SSL")); nssError (); return NULL; } /* Set the appropriate flags. */ secStatus = SSL_OptionSet (sslSocket, SSL_SECURITY, PR_TRUE); if (secStatus != SECSuccess) { server_error (_("Error setting SSL security for socket")); nssError (); return NULL; } secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_SERVER, PR_TRUE); if (secStatus != SECSuccess) { server_error (_("Error setting handshake as server for socket")); nssError (); return NULL; } secStatus = SSL_OptionSet(sslSocket, SSL_REQUEST_CERTIFICATE, PR_FALSE); if (secStatus != SECSuccess) { server_error (_("Error setting SSL client authentication mode for socket")); nssError (); return NULL; } secStatus = SSL_OptionSet(sslSocket, SSL_REQUIRE_CERTIFICATE, PR_FALSE); if (secStatus != SECSuccess) { server_error (_("Error setting SSL client authentication mode for socket")); nssError (); return NULL; } /* Set the appropriate callback routines. */ #if 0 /* use the default */ secStatus = SSL_AuthCertificateHook (sslSocket, myAuthCertificate, CERT_GetDefaultCertDB()); if (secStatus != SECSuccess) { nssError (); server_error (_("Error in SSL_AuthCertificateHook")); return NULL; } #endif #if 0 /* Use the default */ secStatus = SSL_BadCertHook(sslSocket, (SSLBadCertHandler)myBadCertHandler, &certErr); if (secStatus != SECSuccess) { nssError (); server_error (_("Error in SSL_BadCertHook")); return NULL; } #endif #if 0 /* no handshake callback */ secStatus = SSL_HandshakeCallback(sslSocket, myHandshakeCallback, NULL); if (secStatus != SECSuccess) { server_error (_("Error in SSL_HandshakeCallback")); nssError (); return NULL; } #endif certKEA = NSS_FindCertKEAType (cert); secStatus = SSL_ConfigSecureServer (sslSocket, cert, privKey, certKEA); if (secStatus != SECSuccess) { server_error (_("Error configuring SSL server")); nssError (); return NULL; } return sslSocket; } #if 0 /* No client authentication (for now) and not authenticating after each transaction. */ /* Function: authenticateSocket() * * Purpose: Perform client authentication on the socket. * */ static SECStatus authenticateSocket (PRFileDesc *sslSocket, PRBool requireCert) { CERTCertificate *cert; SECStatus secStatus; /* Returns NULL if client authentication is not enabled or if the * client had no certificate. */ cert = SSL_PeerCertificate(sslSocket); if (cert) { /* Client had a certificate, so authentication is through. */ CERT_DestroyCertificate(cert); return SECSuccess; } /* Request client to authenticate itself. */ secStatus = SSL_OptionSet(sslSocket, SSL_REQUEST_CERTIFICATE, PR_TRUE); if (secStatus != SECSuccess) { server_error (_("Error in SSL_OptionSet:SSL_REQUEST_CERTIFICATE")); nssError (); return SECFailure; } /* If desired, require client to authenticate itself. Note * SSL_REQUEST_CERTIFICATE must also be on, as above. */ secStatus = SSL_OptionSet(sslSocket, SSL_REQUIRE_CERTIFICATE, requireCert); if (secStatus != SECSuccess) { server_error (_("Error in SSL_OptionSet:SSL_REQUIRE_CERTIFICATE")); nssError (); return SECFailure; } /* Having changed socket configuration parameters, redo handshake. */ secStatus = SSL_ReHandshake(sslSocket, PR_TRUE); if (secStatus != SECSuccess) { server_error (_("Error in SSL_ReHandshake")); nssError (); return SECFailure; } /* Force the handshake to complete before moving on. */ secStatus = SSL_ForceHandshake(sslSocket); if (secStatus != SECSuccess) { server_error (_("Error in SSL_ForceHandshake")); nssError (); return SECFailure; } return SECSuccess; } #endif /* No client authentication and not authenticating after each transaction. */ /* Function: writeDataToSocket * * Purpose: Write the server's response back to the socket. * */ static SECStatus writeDataToSocket(PRFileDesc *sslSocket, const char *responseFileName) { PRFileDesc *local_file_fd = PR_Open (responseFileName, PR_RDONLY, 0); if (local_file_fd == NULL) { server_error (_F("Could not open input file %s", responseFileName)); nssError (); return SECFailure; } /* Transmit the local file across the socket. */ int numBytes = PR_TransmitFile (sslSocket, local_file_fd, NULL, 0, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); /* Error in transmission. */ SECStatus secStatus = SECSuccess; if (numBytes < 0) { server_error (_("Error writing response to socket")); nssError (); secStatus = SECFailure; } PR_Close (local_file_fd); return secStatus; } static void get_stap_locale (const string &staplang, vector &envVec, string stapstderr, cs_protocol_version *client_version) { // If the client version is < 1.6, then no file containing environment // variables defining the locale has been passed. if (*client_version < "1.6") return; /* Go through each line of the file, verify it, then add it to the vector */ ifstream langfile; langfile.open(staplang.c_str()); if (!langfile.is_open()) { // Not fatal. Proceed with the environment we have. server_error(_F("Unable to open file %s for reading: %s", staplang.c_str(), strerror (errno))); return; } /* Unpackage internationalization variables and verify their contents */ map envMap; /* To temporarily store the entire array of strings */ string line; const set &locVars = localization_variables(); /* Copy the global environ variable into the map */ if(environ != NULL) { for (unsigned i=0; environ[i]; i++) { string line = (string)environ[i]; /* Find the first '=' sign */ size_t pos = line.find("="); /* Make sure it found an '=' sign */ if(pos != string::npos) /* Everything before the '=' sign is the key, and everything after is the value. */ envMap[line.substr(0, pos)] = line.substr(pos+1); } } /* Create regular expression objects to verify lines read from file. Should not allow spaces, ctrl characters, etc */ regex_t checkre; if ((regcomp(&checkre, "^[a-zA-Z0-9@_.=-]*$", REG_EXTENDED | REG_NOSUB) != 0)) { // Not fatal. Proceed with the environment we have. server_error(_F("Error in regcomp: %s", strerror (errno))); return; } while (1) { getline(langfile, line); if (!langfile.good()) break; /* Extract key and value from the line. Note: value may contain "=". */ string key; string value; size_t pos; pos = line.find("="); if (pos == string::npos) { client_error(_F("Localization key=value line '%s' cannot be parsed", line.c_str()), stapstderr); continue; } key = line.substr(0, pos); pos++; value = line.substr(pos); /* Make sure the key is found in the localization variables global set */ if (locVars.find(key) == locVars.end()) { // Not fatal. Just ignore it. client_error(_F("Localization key '%s' not found in global list", key.c_str()), stapstderr); continue; } /* Make sure the value does not contain illegal characters */ if ((regexec(&checkre, value.c_str(), (size_t) 0, NULL, 0) != 0)) { // Not fatal. Just ignore it. client_error(_F("Localization value '%s' contains illegal characters", value.c_str()), stapstderr); continue; } /* All is good, copy line into envMap, replacing if already there */ envMap[key] = value; } if (!langfile.eof()) { // Not fatal. Proceed with what we have. server_error(_F("Error reading file %s: %s", staplang.c_str(), strerror (errno))); } regfree(&checkre); /* Copy map into vector */ for (map::iterator it = envMap.begin(); it != envMap.end(); it++) envVec.push_back(it->first + "=" + it->second); } // Filter paths prefixed with the server's home directory from the given file. // static void filter_response_file (const string &file_name, const string &responseDirName) { vector cmd; // Filter the server's home directory name cmd.clear(); cmd.push_back ("sed"); cmd.push_back ("-i"); cmd.push_back (string ("s,") + get_home_directory () + ",,g"); cmd.push_back (file_name); stap_system (0, cmd); // Filter the server's response directory name cmd.clear(); cmd.push_back ("sed"); cmd.push_back ("-i"); cmd.push_back (string ("s,") + responseDirName + ",,g"); cmd.push_back (file_name); stap_system (0, cmd); } static privilege_t getRequestedPrivilege (const vector &stapargv) { // The purpose of this function is to find the --privilege or --unprivileged option specified // by the user on the client side. We need to parse the command line completely, but we can // exit when we find the first --privilege or --unprivileged option, since stap does not allow // multiple privilege levels to specified on the same command line. // // Note that we need not do any options consistency checking since our spawned stap instance // will do that. // // Create an argv/argc for use by getopt_long. int argc = stapargv.size(); char ** argv = new char *[argc + 1]; for (unsigned i = 0; i < stapargv.size(); ++i) argv[i] = (char *)stapargv[i].c_str(); argv[argc] = NULL; privilege_t privilege = pr_highest; // Until specified otherwise. optind = 1; while (true) { // We need only allow getopt to parse the options until we find a // --privilege or --unprivileged option. int grc = getopt_long (argc, argv, STAP_SHORT_OPTIONS, stap_long_options, NULL); if (grc < 0) break; switch (grc) { default: // We can ignore all options other than --privilege and --unprivileged. break; case LONG_OPT_PRIVILEGE: if (strcmp (optarg, "stapdev") == 0) privilege = pr_stapdev; else if (strcmp (optarg, "stapsys") == 0) privilege = pr_stapsys; else if (strcmp (optarg, "stapusr") == 0) privilege = pr_stapusr; else { server_error (_F("Invalid argument '%s' for --privilege", optarg)); privilege = pr_highest; } // We have discovered the client side --privilege option. We can exit now since // stap only tolerates one privilege setting option. goto done; // break 2 switches and a loop case LONG_OPT_UNPRIVILEGED: privilege = pr_unprivileged; // We have discovered the client side --unprivileged option. We can exit now since // stap only tolerates one privilege setting option. goto done; // break 2 switches and a loop } } done: delete[] argv; return privilege; } /* Run the translator on the data in the request directory, and produce output in the given output directory. */ static void handleRequest (const string &requestDirName, const string &responseDirName, string stapstderr) { vector stapargv; cs_protocol_version client_version = "1.0"; // Assumed until discovered otherwise int rc; wordexp_t words; unsigned u; unsigned i; FILE* f; // Save the server version. Do this early, so the client knows what version of the server // it is dealing with, even if the request is not fully completed. string stapversion = responseDirName + "/version"; f = fopen (stapversion.c_str (), "w"); if (f) { fputs (CURRENT_CS_PROTOCOL_VERSION, f); fclose(f); } else server_error (_F("Unable to open client version file %s", stapversion.c_str ())); // Get the client version. The default version is already set. Use it if we fail here. string filename = requestDirName + "/version"; if (file_exists (filename)) read_from_file (filename, client_version); log (_F("Client version is %s", client_version.v)); // The name of the translator executable. stapargv.push_back ((char *)(getenv ("SYSTEMTAP_STAP") ?: STAP_PREFIX "/bin/stap")); /* Transcribe stap_options. We use plain wordexp(3), since these options are coming from the local trusted user, so malicious content is not a concern. */ // TODO: Use tokenize here. rc = wordexp (stap_options.c_str (), & words, WRDE_NOCMD|WRDE_UNDEF); if (rc) { server_error (_("Cannot parse stap options")); return; } for (u=0; u envVec; get_stap_locale (staplang, envVec, stapstderr, &client_version); /* All ready, let's run the translator! */ rc = spawn_and_wait(stapargv, "/dev/null", stapstdout.c_str (), stapstderr.c_str (), requestDirName.c_str (), envVec); /* Save the RC */ string staprc = responseDirName + "/rc"; f = fopen(staprc.c_str (), "w"); if (f) { /* best effort basis */ fprintf(f, "%d", rc); fclose(f); } // In unprivileged modes, if we have a module built, we need to sign the sucker. privilege_t privilege = getRequestedPrivilege (stapargv); if (pr_contains (privilege, pr_stapusr) || pr_contains (privilege, pr_stapsys)) { glob_t globber; char pattern[PATH_MAX]; snprintf (pattern, PATH_MAX, "%s/*.ko", new_staptmpdir.c_str()); rc = glob (pattern, GLOB_ERR, NULL, &globber); if (rc) server_error (_F("Unable to find a module in %s", new_staptmpdir.c_str())); else if (globber.gl_pathc != 1) server_error (_F("Too many modules (%zu) in %s", globber.gl_pathc, new_staptmpdir.c_str())); else { sign_file (cert_db_path, server_cert_nickname(), globber.gl_pathv[0], string(globber.gl_pathv[0]) + ".sgn"); } } /* If uprobes.ko is required, it will have been built or cache-copied into * the temp directory. We need to pack it into the response where the client * can find it, and sign, if necessary, for unprivileged users. */ string uprobes_ko = new_staptmpdir + "/uprobes/uprobes.ko"; if (get_file_size(uprobes_ko) > 0) { /* uprobes.ko is required. * * It's already underneath the stap tmpdir, but older stap clients * don't know to look for it there, so, for these clients, we end up packing uprobes twice * into the zip. We could move instead of symlink. */ string uprobes_response; if (client_version < "1.6") { uprobes_response = (string)responseDirName + "/uprobes.ko"; rc = symlink(uprobes_ko.c_str(), uprobes_response.c_str()); if (rc != 0) server_error (_F("Could not link to %s from %s", uprobes_ko.c_str(), uprobes_response.c_str())); } else uprobes_response = uprobes_ko; /* In unprivileged mode, we need a signature on uprobes as well. */ if (! pr_contains (privilege, pr_stapdev)) { sign_file (cert_db_path, server_cert_nickname(), uprobes_response, uprobes_response + ".sgn"); } } /* Free up all the arg string copies. Note that the first few were alloc'd by wordexp(), which wordfree() frees; others were hand-set to literal strings. */ wordfree (& words); // Filter paths prefixed with the server's home directory from the stdout and stderr // files in the response. filter_response_file (stapstdout, responseDirName); filter_response_file (stapstderr, responseDirName); /* Sorry about the inconvenience. C string/file processing is such a pleasure. */ } /* A front end for stap_spawn that handles stdin, stdout, stderr, switches to a working directory and returns overall success or failure. */ static PRStatus spawn_and_wait (const vector &argv, const char* fd0, const char* fd1, const char* fd2, const char *pwd, const vector& envVec) { pid_t pid; int rc; posix_spawn_file_actions_t actions; int dotfd = -1; #define CHECKRC(msg) do { if (rc) { server_error (_(msg)); return PR_FAILURE; } } while (0) rc = posix_spawn_file_actions_init (& actions); CHECKRC ("Error in spawn file actions ctor"); if (fd0) { rc = posix_spawn_file_actions_addopen(& actions, 0, fd0, O_RDONLY, 0600); CHECKRC ("Error in spawn file actions fd0"); } if (fd1) { rc = posix_spawn_file_actions_addopen(& actions, 1, fd1, O_WRONLY|O_CREAT, 0600); CHECKRC ("Error in spawn file actions fd1"); } if (fd2) { // Use append mode for stderr because it gets written to in other places in the server. rc = posix_spawn_file_actions_addopen(& actions, 2, fd2, O_WRONLY|O_APPEND|O_CREAT, 0600); CHECKRC ("Error in spawn file actions fd2"); } /* change temporarily to a directory if requested */ if (pwd) { dotfd = open (".", O_RDONLY); if (dotfd < 0) { server_error (_("Error in spawn getcwd")); return PR_FAILURE; } rc = chdir (pwd); if (rc) { close(dotfd); server_error(_("Error in spawn chdir")); return PR_FAILURE; } } pid = stap_spawn (0, argv, & actions, envVec); /* NB: don't react to pid==-1 right away; need to chdir back first. */ if (pwd && dotfd >= 0) { int subrc; subrc = fchdir (dotfd); subrc |= close (dotfd); if (subrc) server_error (_("Error in spawn unchdir")); } if (pid == -1) { server_error (_F("Error in spawn: %s", strerror (errno))); return PR_FAILURE; } rc = stap_waitpid (0, pid); if (rc == -1) { server_error (_("Error in waitpid")); return PR_FAILURE; } rc = posix_spawn_file_actions_destroy (&actions); CHECKRC ("Error in spawn file actions dtor"); return PR_SUCCESS; #undef CHECKRC } /* Function: void *handle_connection() * * Purpose: Handle a connection to a socket. Copy in request zip * file, process it, copy out response. Temporary directories are * created & destroyed here. */ void * handle_connection (void *arg) { PRFileDesc * sslSocket = NULL; SECStatus secStatus = SECFailure; PRStatus prStatus; int rc; char *rc1; char tmpdir[PATH_MAX]; char requestFileName[PATH_MAX]; char requestDirName[PATH_MAX]; char responseDirName[PATH_MAX]; char responseFileName[PATH_MAX]; string stapstderr; /* Cannot be global since we need a unique copy for each connection.*/ vector argv; PRInt32 bytesRead; /* Detatch to avoid a memory leak */ if(max_threads > 0) pthread_detach(pthread_self()); /* Unpack the arg */ thread_arg *t_arg = (thread_arg *) arg; PRFileDesc *tcpSocket = t_arg->tcpSocket; CERTCertificate *cert = t_arg->cert; SECKEYPrivateKey *privKey = t_arg->privKey; PRNetAddr addr = t_arg->addr; tmpdir[0]='\0'; /* prevent cleanup-time /bin/rm of uninitialized directory */ #if 0 // already done on the listenSocket /* Make sure the socket is blocking. */ PRSocketOptionData socketOption; socketOption.option = PR_SockOpt_Nonblocking; socketOption.value.non_blocking = PR_FALSE; PR_SetSocketOption (tcpSocket, &socketOption); #endif secStatus = SECFailure; sslSocket = setupSSLSocket (tcpSocket, cert, privKey); if (sslSocket == NULL) { // Message already issued. goto cleanup; } secStatus = SSL_ResetHandshake(sslSocket, /* asServer */ PR_TRUE); if (secStatus != SECSuccess) { server_error (_("Error resetting SSL handshake")); nssError (); goto cleanup; } #if 0 // The client authenticates the server, so the client initiates the handshake /* Force the handshake to complete before moving on. */ secStatus = SSL_ForceHandshake(sslSocket); if (secStatus != SECSuccess) { server_error (_("Error forcing SSL handshake")); nssError (); goto cleanup; } #endif secStatus = SECFailure; snprintf(tmpdir, PATH_MAX, "%s/stap-server.XXXXXX", getenv("TMPDIR") ?: "/tmp"); rc1 = mkdtemp(tmpdir); if (! rc1) { server_error (_F("Could not create temporary directory %s: %s", tmpdir, strerror(errno))); tmpdir[0]=0; /* prevent /bin/rm */ goto cleanup; } /* Create a temporary files names and directories. */ snprintf (requestFileName, PATH_MAX, "%s/request.zip", tmpdir); snprintf (requestDirName, PATH_MAX, "%s/request", tmpdir); rc = mkdir(requestDirName, 0700); if (rc) { server_error (_F("Could not create temporary directory %s: %s", requestDirName, strerror (errno))); goto cleanup; } snprintf (responseDirName, PATH_MAX, "%s/response", tmpdir); rc = mkdir(responseDirName, 0700); if (rc) { server_error (_F("Could not create temporary directory %s: %s", responseDirName, strerror (errno))); goto cleanup; } // Set this early, since it gets used for errors to be returned to the client. stapstderr = string(responseDirName) + "/stderr"; snprintf (responseFileName, PATH_MAX, "%s/response.zip", tmpdir); /* Read data from the socket. * If the user is requesting/requiring authentication, authenticate * the socket. */ bytesRead = readDataFromSocket(sslSocket, requestFileName); if (bytesRead < 0) // Error goto cleanup; if (bytesRead == 0) // No request -- not an error { secStatus = SECSuccess; goto cleanup; } #if 0 /* Don't authenticate after each transaction */ if (REQUEST_CERT_ALL) { secStatus = authenticateSocket(sslSocket); if (secStatus != SECSuccess) goto cleanup; } #endif /* Unzip the request. */ secStatus = SECFailure; argv.push_back ("unzip"); argv.push_back ("-q"); argv.push_back ("-d"); argv.push_back (requestDirName); argv.push_back (requestFileName); rc = stap_system (0, argv); if (rc != 0) { server_error (_("Unable to extract client request")); goto cleanup; } /* Handle the request zip file. An error therein should still result in a response zip file (containing stderr etc.) so we don't have to have a result code here. */ handleRequest(requestDirName, responseDirName, stapstderr); /* Zip the response. */ argv.clear (); argv.push_back ("zip"); argv.push_back ("-q"); argv.push_back ("-r"); argv.push_back (responseFileName); argv.push_back ("."); rc = spawn_and_wait (argv, NULL, NULL, NULL, responseDirName); if (rc != PR_SUCCESS) { server_error (_("Unable to compress server response")); goto cleanup; } secStatus = writeDataToSocket (sslSocket, responseFileName); cleanup: if (sslSocket) if (PR_Close (sslSocket) != PR_SUCCESS) { server_error (_("Error closing ssl socket")); nssError (); } if (tmpdir[0]) { // Remove the whole tmpdir and all that lies beneath, unless -k was specified. if (keep_temp) log (_F("Keeping temporary directory %s", tmpdir)); else { argv.clear (); argv.push_back ("rm"); argv.push_back ("-r"); argv.push_back (tmpdir); rc = stap_system (0, argv); if (rc != 0) server_error (_("Error in tmpdir cleanup")); } } if (secStatus != SECSuccess) server_error (_("Error processing client request")); // Log the end of the request. char buf[1024]; prStatus = PR_NetAddrToString (& addr, buf, sizeof (buf)); if (prStatus == PR_SUCCESS) { if (addr.raw.family == PR_AF_INET) log (_F("Request from %s:%d complete", buf, addr.inet.port)); else if (addr.raw.family == PR_AF_INET6) log (_F("Request from [%s]:%d complete", buf, addr.ipv6.port)); } /* Increment semephore to indicate this thread is finished. */ free(t_arg); if (max_threads > 0) { sem_post(&sem_client); pthread_exit(0); } else return 0; } /* Function: int accept_connection() * * Purpose: Accept a connection to the socket. * */ static SECStatus accept_connections (PRFileDesc *listenSocket, CERTCertificate *cert) { PRNetAddr addr; PRFileDesc *tcpSocket; PRStatus prStatus; SECStatus secStatus; CERTCertDBHandle *dbHandle; pthread_t tid; thread_arg *t_arg; dbHandle = CERT_GetDefaultCertDB (); // cert_db_path gets passed to nssPasswordCallback. SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert (cert, (void*)cert_db_path.c_str ()); if (privKey == NULL) { server_error (_("Unable to obtain certificate private key")); nssError (); return SECFailure; } while (pending_interrupts == 0) { /* Accept a connection to the socket. */ tcpSocket = PR_Accept (listenSocket, &addr, PR_INTERVAL_MIN); if (tcpSocket == NULL) { if(PR_GetError() == PR_IO_TIMEOUT_ERROR) continue; else { server_error (_("Error accepting client connection")); break; } } /* Log the accepted connection. */ char buf[1024]; prStatus = PR_NetAddrToString (&addr, buf, sizeof (buf)); if (prStatus == PR_SUCCESS) { if (addr.raw.family == PR_AF_INET) log (_F("Accepted connection from %s:%d", buf, addr.inet.port)); else if (addr.raw.family == PR_AF_INET6) log (_F("Accepted connection from [%s]:%d", buf, addr.ipv6.port)); } /* XXX: alarm() or somesuch to set a timeout. */ /* Accepted the connection, now handle it. */ /* Wait for a thread to finish if there are none available */ if(max_threads >0) { int idle_threads; sem_getvalue(&sem_client, &idle_threads); if(idle_threads <= 0) log(_("Server is overloaded. Processing times may be longer than normal.")); else if (idle_threads == max_threads) log(_("Processing 1 request...")); else log(_F("Processing %d concurrent requests...", ((int)max_threads - idle_threads) + 1)); sem_wait(&sem_client); } /* Create the argument structure to pass to pthread_create * (or directly to handle_connection if max_threads == 0 */ t_arg = (thread_arg *)malloc(sizeof(*t_arg)); if (t_arg == 0) fatal(_("No memory available for new thread arg!")); t_arg->tcpSocket = tcpSocket; t_arg->cert = cert; t_arg->privKey = privKey; t_arg->addr = addr; /* Handle the conncection */ if (max_threads > 0) /* Create the worker thread and handle the connection. */ pthread_create(&tid, NULL, handle_connection, t_arg); else /* Since max_threads == 0, don't spawn a new thread, * just handle in the current thread. */ handle_connection(t_arg); // If our certificate is no longer valid (e.g. has expired), then exit. secStatus = CERT_VerifyCertNow (dbHandle, cert, PR_TRUE/*checkSig*/, certUsageSSLServer, NULL/*wincx*/); if (secStatus != SECSuccess) { // Not an error. Exit the loop so a new cert can be generated. break; } } SECKEY_DestroyPrivateKey (privKey); return SECSuccess; } /* Function: void server_main() * * Purpose: This is the server's main function. It configures a socket * and listens to it. * */ static SECStatus server_main (PRFileDesc *listenSocket) { int idle_threads; int timeout = 0; // Initialize NSS. SECStatus secStatus = nssInit (cert_db_path.c_str ()); if (secStatus != SECSuccess) { // Message already issued. return secStatus; } // Preinitialized here due to jumps to the label 'done'. CERTCertificate *cert = NULL; bool serverCacheConfigured = false; // Enable cipher suites which are allowed by U.S. export regulations. // NB: The NSS docs say that SSL_ClearSessionCache is required for the new settings to take // effect, however, calling it puts NSS in a state where it will not shut down cleanly. // We need to be able to shut down NSS cleanly if we are to generate a new certificate when // ours expires. It should be noted however, thet SSL_ClearSessionCache only clears the // client cache, and we are a server. secStatus = NSS_SetExportPolicy (); // SSL_ClearSessionCache (); if (secStatus != SECSuccess) { server_error (_("Unable to set NSS export policy")); nssError (); goto done; } // Configure the SSL session cache for a single process server with the default settings. secStatus = SSL_ConfigServerSessionIDCache (0, 0, 0, NULL); if (secStatus != SECSuccess) { server_error (_("Unable to configure SSL server session ID cache")); nssError (); goto done; } serverCacheConfigured = true; /* Get own certificate. */ cert = PK11_FindCertFromNickname (server_cert_nickname (), NULL); if (cert == NULL) { server_error (_F("Unable to find our certificate in the database at %s", cert_db_path.c_str ())); nssError (); goto done; } // Tell the world that we're listening. advertise_presence (cert); /* Handle connections to the socket. */ secStatus = accept_connections (listenSocket, cert); // Tell the world we're no longer listening. unadvertise_presence (); sem_getvalue(&sem_client, &idle_threads); /* Wait for requests to finish or the timeout to be reached. * If we got here from an interrupt, exit immediately if * the timeout is reached. Otherwise, wait indefinitiely * until the threads exit (or an interrupt is recieved).*/ if(idle_threads < max_threads) log(_F("Waiting for %d outstanding requests to complete...", (int)max_threads - idle_threads)); while(idle_threads < max_threads) { if(pending_interrupts && timeout++ > CONCURRENCY_TIMEOUT_S) { log(_("Timeout reached, exiting (forced)")); kill_stap_spawn (SIGTERM); cleanup (); _exit(0); } sleep(1); sem_getvalue(&sem_client, &idle_threads); } done: // Clean up if (cert) CERT_DestroyCertificate (cert); // Shutdown NSS if (serverCacheConfigured && SSL_ShutdownServerSessionIDCache () != SECSuccess) { server_error (_("Unable to shut down server session ID cache")); nssError (); } nssCleanup (cert_db_path.c_str ()); return secStatus; } static void listen () { // Create a new socket. PRFileDesc *listenSocket = PR_OpenTCPSocket (PR_AF_INET6); // Accepts IPv4 too if (listenSocket == NULL) { server_error (_("Error creating socket")); nssError (); return; } // Set socket to be blocking - on some platforms the default is nonblocking. PRSocketOptionData socketOption; socketOption.option = PR_SockOpt_Nonblocking; socketOption.value.non_blocking = PR_FALSE; PRStatus prStatus = PR_SetSocketOption (listenSocket, & socketOption); if (prStatus != PR_SUCCESS) { server_error (_("Error setting socket properties")); nssError (); goto done; } // Allow the socket address to be reused, in case we want the same port across a // 'service stap-server restart' socketOption.option = PR_SockOpt_Reuseaddr; socketOption.value.reuse_addr = PR_TRUE; prStatus = PR_SetSocketOption (listenSocket, & socketOption); if (prStatus != PR_SUCCESS) { server_error (_("Error setting socket properties")); nssError (); goto done; } // Configure the network connection. PRNetAddr addr; memset (& addr, 0, sizeof(addr)); prStatus = PR_InitializeNetAddr (PR_IpAddrAny, port, & addr); addr.ipv6.family = PR_AF_INET6; #if 0 // addr.inet.ip = PR_htonl(PR_INADDR_ANY); PR_StringToNetAddr ("::", & addr); // PR_StringToNetAddr ("fe80::5eff:35ff:fe07:55ca", & addr); // PR_StringToNetAddr ("::1", & addr); addr.ipv6.port = PR_htons (port); #endif // Bind the socket to an address. Retry if the selected port is busy, unless the port was // specified directly. for (;;) { /* Bind the address to the listener socket. */ prStatus = PR_Bind (listenSocket, & addr); if (prStatus == PR_SUCCESS) break; // If the selected port is busy. Try another, but only if a specific port was not specified. PRErrorCode errorNumber = PR_GetError (); switch (errorNumber) { case PR_ADDRESS_NOT_AVAILABLE_ERROR: if (port == 0) { server_error (_F("Network port %hu is unavailable. Trying another port", port)); continue; } break; case PR_ADDRESS_IN_USE_ERROR: if (port == 0) { server_error (_F("Network port %hu is busy. Trying another port", port)); continue; } break; default: break; } server_error (_("Error setting socket address")); nssError (); goto done; } // Query the socket for the port that was assigned. prStatus = PR_GetSockName (listenSocket, &addr); if (prStatus != PR_SUCCESS) { server_error (_("Unable to obtain socket address")); nssError (); goto done; } char buf[1024]; prStatus = PR_NetAddrToString (&addr, buf, sizeof (buf)); port = PR_ntohs (addr.ipv6.port); log (_F("Using network address [%s]:%hu", buf, port)); if (max_threads > 0) log (_F("Using a maximum of %ld threads", max_threads)); else log (_("Concurrency disabled")); // Listen for connection on the socket. The second argument is the maximum size of the queue // for pending connections. prStatus = PR_Listen (listenSocket, 5); if (prStatus != PR_SUCCESS) { server_error (_("Error listening on socket")); nssError (); goto done; } /* Initialize semephore with the maximum number of threads * defined by --max-threads. If it is not defined, the * default is the number of processors */ sem_init(&sem_client, 0, max_threads); // Loop forever. We check our certificate (and regenerate, if necessary) and then start the // server. The server will go down when our certificate is no longer valid (e.g. expired). We // then generate a new one and start the server again. while(!pending_interrupts) { // Ensure that our certificate is valid. Generate a new one if not. if (check_cert (cert_db_path, server_cert_nickname (), use_db_password) != 0) { // Message already issued goto done; } // Ensure that our certificate is trusted by our local client. // Construct the client database path relative to the server database path. SECStatus secStatus = add_client_cert (server_cert_file (), local_client_cert_db_path ()); if (secStatus != SECSuccess) { server_error (_("Unable to authorize certificate for the local client")); goto done; } // Launch the server. secStatus = server_main (listenSocket); } // loop forever done: sem_destroy(&sem_client); /*Not really necessary, as we are shutting down...but for correctness */ if (PR_Close (listenSocket) != PR_SUCCESS) { server_error (_("Error closing listen socket")); nssError (); } } int main (int argc, char **argv) { initialize (argc, argv); listen (); cleanup (); return 0; } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stap-sign-module.cxx000066400000000000000000000044211217430427200173260ustar00rootroot00000000000000/* This program signs the given file using the named certificate and private key in the given certificate database and places the signature in the named output file. Copyright (C) 2009-2011 Red Hat Inc. This file is part of systemtap, and 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, see . */ #include "config.h" extern "C" { #include #include } #include #include "util.h" #include "nsscommon.h" using namespace std; // Called by methods within nsscommon.cxx. extern "C" void nsscommon_error (const char *msg, int logit __attribute ((unused))) { clog << msg << endl << flush; } int main (int argc, char **argv) { #if ENABLE_NLS setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); #endif if (argc < 2) { nsscommon_error (_("Module name was not specified.")); return 1; } string module_name = argv[1]; string cert_db_path; if (argc >= 3) cert_db_path = argv[2]; else cert_db_path = server_cert_db_path (); const char *nickName = server_cert_nickname (); if (check_cert (cert_db_path, nickName) != 0) return 1; /* Call the NSPR initialization routines. */ PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); /* Set the cert database password callback. */ PK11_SetPasswordFunc (nssPasswordCallback); /* Initialize NSS. */ SECStatus secStatus = nssInit (cert_db_path.c_str()); if (secStatus != SECSuccess) { // Message already issued. return 1; } sign_file (cert_db_path, nickName, module_name, module_name + ".sgn"); /* Shutdown NSS and exit NSPR gracefully. */ nssCleanup (cert_db_path.c_str ()); PR_Cleanup (); return 0; } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stap-start-server000077500000000000000000000020111217430427200167370ustar00rootroot00000000000000#!/bin/bash # Start a systemtap server # # Copyright (C) 2008-2011 Red Hat Inc. # # This file is part of systemtap, and is free software. You can # redistribute it and/or modify it under the terms of the GNU General # Public License (GPL); either version 2, or (at your option) any # later version. # This script attempts to start a systemtap server and echoes the # process id, if successful. # Initialize the environment . ${PKGLIBEXECDIR}stap-env startup_timeout=10 # start the server ${stap_pkglibexecdir}stap-serverd "$@" /dev/null 2>/dev/null & server_pid=$! # Make sure the server is started for ((attempt=0; $attempt < $startup_timeout; ++attempt)) do # Has the server started? if ! (ps -e | grep stap-serverd | grep $server_pid) >/dev/null 2>&1; then sleep 1 continue fi # The server is ready echo $server_pid exit 0 done echo -n "Unable to start a systemtap server: " >&2 echo "${stap_pkglibexecdir}stap-serverd did not start" >&2 exit 1 # server did not start systemtap-2.3/stap-stop-server000077500000000000000000000012551217430427200166000ustar00rootroot00000000000000#!/bin/bash # Start a systemtap server # # Copyright (C) 2008 Red Hat Inc. # # This file is part of systemtap, and is free software. You can # redistribute it and/or modify it under the terms of the GNU General # Public License (GPL); either version 2, or (at your option) any # later version. # This script attempts to stop a systemtap server with the # given pid. # Get the process id. pid=$1 if test "X$pid" = "X"; then echo "Usage: $0 PROCESS_ID" >&2 exit 1 fi # Verify that it is a systemtap server (ps -e | grep stap-serverd | grep -q $pid) if test $? != 0; then echo "$pid is not a systemtap server" >&2 exit 1 fi # Try to kill the server kill -s SIGTERM $pid systemtap-2.3/stapdyn/000077500000000000000000000000001217430427200150735ustar00rootroot00000000000000systemtap-2.3/stapdyn/Makefile.am000066400000000000000000000026741217430427200171400ustar00rootroot00000000000000# Makefile.am --- automake input file for systemtap dyninst tools AM_CFLAGS = -Wall -Werror -Wunused -W -Wformat=2 -Wno-format-nonliteral AM_CXXFLAGS = -Wall -Werror -Wunused -W -Wformat=2 -Wno-format-nonliteral AM_CPPFLAGS = -D_GNU_SOURCE AM_CPPFLAGS += -I$(srcdir)/../includes AM_CPPFLAGS += -I$(builddir)/../includes/sys AM_CPPFLAGS += -DBINDIR='"$(bindir)"' -DSYSCONFDIR='"$(sysconfdir)"' -DPKGDATADIR='"${pkgdatadir}"' -DPKGLIBDIR='"$(pkglibexecdir)"' -DLOCALEDIR='"$(localedir)"' AM_CFLAGS += @PIECFLAGS@ AM_CXXFLAGS += @PIECXXFLAGS@ AM_LDFLAGS = @PIELDFLAGS@ if HAVE_SELINUX AM_CPPFLAGS += $(selinux_CFLAGS) AM_LDFLAGS += $(selinux_LIBS) endif bin_PROGRAMS = noinst_PROGRAMS = if HAVE_DYNINST bin_PROGRAMS += stapdyn noinst_PROGRAMS += dynsdt man_MANS = stapdyn.8 stapdyn_SOURCES = stapdyn.cxx mutator.cxx mutatee.cxx \ dynprobe.cxx dynutil.cxx ../util.cxx stapdyn_CXXFLAGS = $(AM_CXXFLAGS) @DYNINST_CXXFLAGS@ stapdyn_LDFLAGS = $(AM_LDFLAGS) @DYNINST_LDFLAGS@ stapdyn_LDADD = -ldl -ldyninstAPI -lsymtabAPI -lpthread dynsdt_SOURCES = dynsdt.cxx dynutil.cxx ../util.cxx dynsdt_CXXFLAGS = $(AM_CXXFLAGS) @DYNINST_CXXFLAGS@ dynsdt_LDFLAGS = $(AM_LDFLAGS) @DYNINST_LDFLAGS@ dynsdt_LDADD = -ldl -lelf -ldyninstAPI -lsymtabAPI -lpthread endif # HAVE_DYNINST BUILT_SOURCES = # Arrange for the top-level git_version.h to be regenerated at every "make". BUILT_SOURCES += git_version.stamp git_version.stamp ../git_version.h: $(MAKE) -C .. $(notdir $@) systemtap-2.3/stapdyn/Makefile.in000066400000000000000000001160641217430427200171500ustar00rootroot00000000000000# Makefile.in generated by automake 1.12.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Makefile.am --- automake input file for systemtap dyninst tools VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ @HAVE_SELINUX_TRUE@am__append_1 = $(selinux_CFLAGS) @HAVE_SELINUX_TRUE@am__append_2 = $(selinux_LIBS) bin_PROGRAMS = $(am__EXEEXT_1) noinst_PROGRAMS = $(am__EXEEXT_2) @HAVE_DYNINST_TRUE@am__append_3 = stapdyn @HAVE_DYNINST_TRUE@am__append_4 = dynsdt subdir = stapdyn DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @HAVE_DYNINST_TRUE@am__EXEEXT_1 = stapdyn$(EXEEXT) am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man8dir)" @HAVE_DYNINST_TRUE@am__EXEEXT_2 = dynsdt$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) @HAVE_DYNINST_TRUE@am_dynsdt_OBJECTS = dynsdt-dynsdt.$(OBJEXT) \ @HAVE_DYNINST_TRUE@ dynsdt-dynutil.$(OBJEXT) \ @HAVE_DYNINST_TRUE@ dynsdt-util.$(OBJEXT) dynsdt_OBJECTS = $(am_dynsdt_OBJECTS) dynsdt_DEPENDENCIES = dynsdt_LINK = $(CXXLD) $(dynsdt_CXXFLAGS) $(CXXFLAGS) \ $(dynsdt_LDFLAGS) $(LDFLAGS) -o $@ @HAVE_DYNINST_TRUE@am_stapdyn_OBJECTS = stapdyn-stapdyn.$(OBJEXT) \ @HAVE_DYNINST_TRUE@ stapdyn-mutator.$(OBJEXT) \ @HAVE_DYNINST_TRUE@ stapdyn-mutatee.$(OBJEXT) \ @HAVE_DYNINST_TRUE@ stapdyn-dynprobe.$(OBJEXT) \ @HAVE_DYNINST_TRUE@ stapdyn-dynutil.$(OBJEXT) \ @HAVE_DYNINST_TRUE@ stapdyn-util.$(OBJEXT) stapdyn_OBJECTS = $(am_stapdyn_OBJECTS) stapdyn_DEPENDENCIES = stapdyn_LINK = $(CXXLD) $(stapdyn_CXXFLAGS) $(CXXFLAGS) \ $(stapdyn_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(dynsdt_SOURCES) $(stapdyn_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) ETAGS = etags CTAGS = ctags ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DATE = @DATE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DYNINST_CXXFLAGS = @DYNINST_CXXFLAGS@ DYNINST_LDFLAGS = @DYNINST_LDFLAGS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_NLS = @ENABLE_NLS@ EXEEXT = @EXEEXT@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ JAVADIR = @JAVADIR@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PIECFLAGS = @PIECFLAGS@ PIECXXFLAGS = @PIECXXFLAGS@ PIELDFLAGS = @PIELDFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POSUB = @POSUB@ PUBLICAN_BRAND = @PUBLICAN_BRAND@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STAP_EXTRA_VERSION = @STAP_EXTRA_VERSION@ STAP_PREFIX = @STAP_PREFIX@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ elfutils_abs_srcdir = @elfutils_abs_srcdir@ exec_prefix = @exec_prefix@ have_dvips = @have_dvips@ have_fop = @have_fop@ have_jar = @have_jar@ have_javac = @have_javac@ have_latex = @have_latex@ have_latex2html = @have_latex2html@ have_ps2pdf = @have_ps2pdf@ have_publican = @have_publican@ have_xmlto = @have_xmlto@ have_xvfb = @have_xvfb@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ nss_CFLAGS = @nss_CFLAGS@ nss_LIBS = @nss_LIBS@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ selinux_CFLAGS = @selinux_CFLAGS@ selinux_LIBS = @selinux_LIBS@ sharedstatedir = @sharedstatedir@ sqlite3_LIBS = @sqlite3_LIBS@ srcdir = @srcdir@ stap_LIBS = @stap_LIBS@ staplog_CPPFLAGS = @staplog_CPPFLAGS@ staprun_LIBS = @staprun_LIBS@ subdirs = @subdirs@ support_section_question = @support_section_question@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = -Wall -Werror -Wunused -W -Wformat=2 \ -Wno-format-nonliteral @PIECFLAGS@ AM_CXXFLAGS = -Wall -Werror -Wunused -W -Wformat=2 \ -Wno-format-nonliteral @PIECXXFLAGS@ AM_CPPFLAGS = -D_GNU_SOURCE -I$(srcdir)/../includes \ -I$(builddir)/../includes/sys -DBINDIR='"$(bindir)"' \ -DSYSCONFDIR='"$(sysconfdir)"' -DPKGDATADIR='"${pkgdatadir}"' \ -DPKGLIBDIR='"$(pkglibexecdir)"' -DLOCALEDIR='"$(localedir)"' \ $(am__append_1) AM_LDFLAGS = @PIELDFLAGS@ $(am__append_2) @HAVE_DYNINST_TRUE@man_MANS = stapdyn.8 @HAVE_DYNINST_TRUE@stapdyn_SOURCES = stapdyn.cxx mutator.cxx mutatee.cxx \ @HAVE_DYNINST_TRUE@ dynprobe.cxx dynutil.cxx ../util.cxx @HAVE_DYNINST_TRUE@stapdyn_CXXFLAGS = $(AM_CXXFLAGS) @DYNINST_CXXFLAGS@ @HAVE_DYNINST_TRUE@stapdyn_LDFLAGS = $(AM_LDFLAGS) @DYNINST_LDFLAGS@ @HAVE_DYNINST_TRUE@stapdyn_LDADD = -ldl -ldyninstAPI -lsymtabAPI -lpthread @HAVE_DYNINST_TRUE@dynsdt_SOURCES = dynsdt.cxx dynutil.cxx ../util.cxx @HAVE_DYNINST_TRUE@dynsdt_CXXFLAGS = $(AM_CXXFLAGS) @DYNINST_CXXFLAGS@ @HAVE_DYNINST_TRUE@dynsdt_LDFLAGS = $(AM_LDFLAGS) @DYNINST_LDFLAGS@ @HAVE_DYNINST_TRUE@dynsdt_LDADD = -ldl -lelf -ldyninstAPI -lsymtabAPI -lpthread # Arrange for the top-level git_version.h to be regenerated at every "make". BUILT_SOURCES = git_version.stamp all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .cxx .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign stapdyn/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign stapdyn/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) dynsdt$(EXEEXT): $(dynsdt_OBJECTS) $(dynsdt_DEPENDENCIES) $(EXTRA_dynsdt_DEPENDENCIES) @rm -f dynsdt$(EXEEXT) $(AM_V_CXXLD)$(dynsdt_LINK) $(dynsdt_OBJECTS) $(dynsdt_LDADD) $(LIBS) stapdyn$(EXEEXT): $(stapdyn_OBJECTS) $(stapdyn_DEPENDENCIES) $(EXTRA_stapdyn_DEPENDENCIES) @rm -f stapdyn$(EXEEXT) $(AM_V_CXXLD)$(stapdyn_LINK) $(stapdyn_OBJECTS) $(stapdyn_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynsdt-dynsdt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynsdt-dynutil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynsdt-util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stapdyn-dynprobe.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stapdyn-dynutil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stapdyn-mutatee.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stapdyn-mutator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stapdyn-stapdyn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stapdyn-util.Po@am__quote@ .cxx.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cxx.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` dynsdt-dynsdt.o: dynsdt.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dynsdt_CXXFLAGS) $(CXXFLAGS) -MT dynsdt-dynsdt.o -MD -MP -MF $(DEPDIR)/dynsdt-dynsdt.Tpo -c -o dynsdt-dynsdt.o `test -f 'dynsdt.cxx' || echo '$(srcdir)/'`dynsdt.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dynsdt-dynsdt.Tpo $(DEPDIR)/dynsdt-dynsdt.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dynsdt.cxx' object='dynsdt-dynsdt.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dynsdt_CXXFLAGS) $(CXXFLAGS) -c -o dynsdt-dynsdt.o `test -f 'dynsdt.cxx' || echo '$(srcdir)/'`dynsdt.cxx dynsdt-dynsdt.obj: dynsdt.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dynsdt_CXXFLAGS) $(CXXFLAGS) -MT dynsdt-dynsdt.obj -MD -MP -MF $(DEPDIR)/dynsdt-dynsdt.Tpo -c -o dynsdt-dynsdt.obj `if test -f 'dynsdt.cxx'; then $(CYGPATH_W) 'dynsdt.cxx'; else $(CYGPATH_W) '$(srcdir)/dynsdt.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dynsdt-dynsdt.Tpo $(DEPDIR)/dynsdt-dynsdt.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dynsdt.cxx' object='dynsdt-dynsdt.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dynsdt_CXXFLAGS) $(CXXFLAGS) -c -o dynsdt-dynsdt.obj `if test -f 'dynsdt.cxx'; then $(CYGPATH_W) 'dynsdt.cxx'; else $(CYGPATH_W) '$(srcdir)/dynsdt.cxx'; fi` dynsdt-dynutil.o: dynutil.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dynsdt_CXXFLAGS) $(CXXFLAGS) -MT dynsdt-dynutil.o -MD -MP -MF $(DEPDIR)/dynsdt-dynutil.Tpo -c -o dynsdt-dynutil.o `test -f 'dynutil.cxx' || echo '$(srcdir)/'`dynutil.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dynsdt-dynutil.Tpo $(DEPDIR)/dynsdt-dynutil.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dynutil.cxx' object='dynsdt-dynutil.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dynsdt_CXXFLAGS) $(CXXFLAGS) -c -o dynsdt-dynutil.o `test -f 'dynutil.cxx' || echo '$(srcdir)/'`dynutil.cxx dynsdt-dynutil.obj: dynutil.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dynsdt_CXXFLAGS) $(CXXFLAGS) -MT dynsdt-dynutil.obj -MD -MP -MF $(DEPDIR)/dynsdt-dynutil.Tpo -c -o dynsdt-dynutil.obj `if test -f 'dynutil.cxx'; then $(CYGPATH_W) 'dynutil.cxx'; else $(CYGPATH_W) '$(srcdir)/dynutil.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dynsdt-dynutil.Tpo $(DEPDIR)/dynsdt-dynutil.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dynutil.cxx' object='dynsdt-dynutil.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dynsdt_CXXFLAGS) $(CXXFLAGS) -c -o dynsdt-dynutil.obj `if test -f 'dynutil.cxx'; then $(CYGPATH_W) 'dynutil.cxx'; else $(CYGPATH_W) '$(srcdir)/dynutil.cxx'; fi` dynsdt-util.o: ../util.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dynsdt_CXXFLAGS) $(CXXFLAGS) -MT dynsdt-util.o -MD -MP -MF $(DEPDIR)/dynsdt-util.Tpo -c -o dynsdt-util.o `test -f '../util.cxx' || echo '$(srcdir)/'`../util.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dynsdt-util.Tpo $(DEPDIR)/dynsdt-util.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../util.cxx' object='dynsdt-util.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dynsdt_CXXFLAGS) $(CXXFLAGS) -c -o dynsdt-util.o `test -f '../util.cxx' || echo '$(srcdir)/'`../util.cxx dynsdt-util.obj: ../util.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dynsdt_CXXFLAGS) $(CXXFLAGS) -MT dynsdt-util.obj -MD -MP -MF $(DEPDIR)/dynsdt-util.Tpo -c -o dynsdt-util.obj `if test -f '../util.cxx'; then $(CYGPATH_W) '../util.cxx'; else $(CYGPATH_W) '$(srcdir)/../util.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dynsdt-util.Tpo $(DEPDIR)/dynsdt-util.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../util.cxx' object='dynsdt-util.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dynsdt_CXXFLAGS) $(CXXFLAGS) -c -o dynsdt-util.obj `if test -f '../util.cxx'; then $(CYGPATH_W) '../util.cxx'; else $(CYGPATH_W) '$(srcdir)/../util.cxx'; fi` stapdyn-stapdyn.o: stapdyn.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -MT stapdyn-stapdyn.o -MD -MP -MF $(DEPDIR)/stapdyn-stapdyn.Tpo -c -o stapdyn-stapdyn.o `test -f 'stapdyn.cxx' || echo '$(srcdir)/'`stapdyn.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stapdyn-stapdyn.Tpo $(DEPDIR)/stapdyn-stapdyn.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stapdyn.cxx' object='stapdyn-stapdyn.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -c -o stapdyn-stapdyn.o `test -f 'stapdyn.cxx' || echo '$(srcdir)/'`stapdyn.cxx stapdyn-stapdyn.obj: stapdyn.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -MT stapdyn-stapdyn.obj -MD -MP -MF $(DEPDIR)/stapdyn-stapdyn.Tpo -c -o stapdyn-stapdyn.obj `if test -f 'stapdyn.cxx'; then $(CYGPATH_W) 'stapdyn.cxx'; else $(CYGPATH_W) '$(srcdir)/stapdyn.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stapdyn-stapdyn.Tpo $(DEPDIR)/stapdyn-stapdyn.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stapdyn.cxx' object='stapdyn-stapdyn.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -c -o stapdyn-stapdyn.obj `if test -f 'stapdyn.cxx'; then $(CYGPATH_W) 'stapdyn.cxx'; else $(CYGPATH_W) '$(srcdir)/stapdyn.cxx'; fi` stapdyn-mutator.o: mutator.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -MT stapdyn-mutator.o -MD -MP -MF $(DEPDIR)/stapdyn-mutator.Tpo -c -o stapdyn-mutator.o `test -f 'mutator.cxx' || echo '$(srcdir)/'`mutator.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stapdyn-mutator.Tpo $(DEPDIR)/stapdyn-mutator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='mutator.cxx' object='stapdyn-mutator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -c -o stapdyn-mutator.o `test -f 'mutator.cxx' || echo '$(srcdir)/'`mutator.cxx stapdyn-mutator.obj: mutator.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -MT stapdyn-mutator.obj -MD -MP -MF $(DEPDIR)/stapdyn-mutator.Tpo -c -o stapdyn-mutator.obj `if test -f 'mutator.cxx'; then $(CYGPATH_W) 'mutator.cxx'; else $(CYGPATH_W) '$(srcdir)/mutator.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stapdyn-mutator.Tpo $(DEPDIR)/stapdyn-mutator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='mutator.cxx' object='stapdyn-mutator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -c -o stapdyn-mutator.obj `if test -f 'mutator.cxx'; then $(CYGPATH_W) 'mutator.cxx'; else $(CYGPATH_W) '$(srcdir)/mutator.cxx'; fi` stapdyn-mutatee.o: mutatee.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -MT stapdyn-mutatee.o -MD -MP -MF $(DEPDIR)/stapdyn-mutatee.Tpo -c -o stapdyn-mutatee.o `test -f 'mutatee.cxx' || echo '$(srcdir)/'`mutatee.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stapdyn-mutatee.Tpo $(DEPDIR)/stapdyn-mutatee.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='mutatee.cxx' object='stapdyn-mutatee.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -c -o stapdyn-mutatee.o `test -f 'mutatee.cxx' || echo '$(srcdir)/'`mutatee.cxx stapdyn-mutatee.obj: mutatee.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -MT stapdyn-mutatee.obj -MD -MP -MF $(DEPDIR)/stapdyn-mutatee.Tpo -c -o stapdyn-mutatee.obj `if test -f 'mutatee.cxx'; then $(CYGPATH_W) 'mutatee.cxx'; else $(CYGPATH_W) '$(srcdir)/mutatee.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stapdyn-mutatee.Tpo $(DEPDIR)/stapdyn-mutatee.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='mutatee.cxx' object='stapdyn-mutatee.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -c -o stapdyn-mutatee.obj `if test -f 'mutatee.cxx'; then $(CYGPATH_W) 'mutatee.cxx'; else $(CYGPATH_W) '$(srcdir)/mutatee.cxx'; fi` stapdyn-dynprobe.o: dynprobe.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -MT stapdyn-dynprobe.o -MD -MP -MF $(DEPDIR)/stapdyn-dynprobe.Tpo -c -o stapdyn-dynprobe.o `test -f 'dynprobe.cxx' || echo '$(srcdir)/'`dynprobe.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stapdyn-dynprobe.Tpo $(DEPDIR)/stapdyn-dynprobe.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dynprobe.cxx' object='stapdyn-dynprobe.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -c -o stapdyn-dynprobe.o `test -f 'dynprobe.cxx' || echo '$(srcdir)/'`dynprobe.cxx stapdyn-dynprobe.obj: dynprobe.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -MT stapdyn-dynprobe.obj -MD -MP -MF $(DEPDIR)/stapdyn-dynprobe.Tpo -c -o stapdyn-dynprobe.obj `if test -f 'dynprobe.cxx'; then $(CYGPATH_W) 'dynprobe.cxx'; else $(CYGPATH_W) '$(srcdir)/dynprobe.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stapdyn-dynprobe.Tpo $(DEPDIR)/stapdyn-dynprobe.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dynprobe.cxx' object='stapdyn-dynprobe.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -c -o stapdyn-dynprobe.obj `if test -f 'dynprobe.cxx'; then $(CYGPATH_W) 'dynprobe.cxx'; else $(CYGPATH_W) '$(srcdir)/dynprobe.cxx'; fi` stapdyn-dynutil.o: dynutil.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -MT stapdyn-dynutil.o -MD -MP -MF $(DEPDIR)/stapdyn-dynutil.Tpo -c -o stapdyn-dynutil.o `test -f 'dynutil.cxx' || echo '$(srcdir)/'`dynutil.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stapdyn-dynutil.Tpo $(DEPDIR)/stapdyn-dynutil.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dynutil.cxx' object='stapdyn-dynutil.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -c -o stapdyn-dynutil.o `test -f 'dynutil.cxx' || echo '$(srcdir)/'`dynutil.cxx stapdyn-dynutil.obj: dynutil.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -MT stapdyn-dynutil.obj -MD -MP -MF $(DEPDIR)/stapdyn-dynutil.Tpo -c -o stapdyn-dynutil.obj `if test -f 'dynutil.cxx'; then $(CYGPATH_W) 'dynutil.cxx'; else $(CYGPATH_W) '$(srcdir)/dynutil.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stapdyn-dynutil.Tpo $(DEPDIR)/stapdyn-dynutil.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dynutil.cxx' object='stapdyn-dynutil.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -c -o stapdyn-dynutil.obj `if test -f 'dynutil.cxx'; then $(CYGPATH_W) 'dynutil.cxx'; else $(CYGPATH_W) '$(srcdir)/dynutil.cxx'; fi` stapdyn-util.o: ../util.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -MT stapdyn-util.o -MD -MP -MF $(DEPDIR)/stapdyn-util.Tpo -c -o stapdyn-util.o `test -f '../util.cxx' || echo '$(srcdir)/'`../util.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stapdyn-util.Tpo $(DEPDIR)/stapdyn-util.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../util.cxx' object='stapdyn-util.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -c -o stapdyn-util.o `test -f '../util.cxx' || echo '$(srcdir)/'`../util.cxx stapdyn-util.obj: ../util.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -MT stapdyn-util.obj -MD -MP -MF $(DEPDIR)/stapdyn-util.Tpo -c -o stapdyn-util.obj `if test -f '../util.cxx'; then $(CYGPATH_W) '../util.cxx'; else $(CYGPATH_W) '$(srcdir)/../util.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stapdyn-util.Tpo $(DEPDIR)/stapdyn-util.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../util.cxx' object='stapdyn-util.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapdyn_CXXFLAGS) $(CXXFLAGS) -c -o stapdyn-util.obj `if test -f '../util.cxx'; then $(CYGPATH_W) '../util.cxx'; else $(CYGPATH_W) '$(srcdir)/../util.cxx'; fi` install-man8: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man8dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.8[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(PROGRAMS) $(MANS) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man8dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-noinstPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man8 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-man uninstall-man: uninstall-man8 .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-noinstPROGRAMS cscopelist ctags distclean \ distclean-compile distclean-generic distclean-tags dvi dvi-am \ html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-man8 install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ ps ps-am tags uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-man uninstall-man8 git_version.stamp ../git_version.h: $(MAKE) -C .. $(notdir $@) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: systemtap-2.3/stapdyn/README000066400000000000000000000047551217430427200157660ustar00rootroot00000000000000=== SystemTap pure userspace backend, using Dyninst === ** This is still a work in progress, quite experimental! ** The goal of stapdyn is to create a backend of SystemTap that can operate entirely in userspace. Users should be able to run scripts on their own processes without any special privilege on the system. The set of available probes is of course limited from what a traditional kernel-mode SystemTap can access. So far there are the plain begin/end/error, timers, uprobes-like process probes, and utrace-like process/thread begin/end. Because Dyninst operates on top of ptrace, the usual systemwide mode of operation is not really feasible, even on just one's own processes. Instead, stapdyn operates more like other ptracers (gdb, strace), where target apps are launched directly, or attached to specific PIDs. This code requires Dyninst 8.0 or later, including their development head. More information about Dyninst can be found here: - website: http://www.dyninst.org/ and http://www.paradyn.org/ - discussion: https://lists.cs.wisc.edu/mailman/options/dyninst-api/ - source: http://git.dyninst.org/?p=dyninst.git;a=summary or: git clone http://git.dyninst.org/dyninst.git - bug tracker: https://bugs.dyninst.org/ Note that Dyninst uses the environment variable DYNINSTAPI_RT_LIB pointing to your build of libdyninstAPI_RT.so. We try to calculate it at runtime relative to the dynamic libdyninstAPI.so location, but you can set this manually if needed. You may also need LD_LIBRARY_PATH to include the other libraries if they're not installed in the system paths. Major stapdyn known issues: - PR14702 - dyninst breaks exception handling - PR15049 - stapdyn mishandling interrupts - PR15136 - stapdyn doesn't fill registers on 32-bit x86 - PR15614 - stapdyn only partially fills registers on ppc See also sourceware.org/bugzilla product:systemtap component:dyninst. For some more background on this project, see the presentations: - PD Week 2012: Josh Stone Scripted Introspection with Dyninst http://www.dyninst.org/meetings/2012/monday - LF Collab Summit 2012: Josh Stone SystemTap Sans Kernel https://events.linuxfoundation.org/events/collaboration-summit/slides-and-video - Tracing Summit 2012: David Smith & Josh Stone Systemtap and new connections: dyninst, pcp, uprobes http://www.tracingsummit.org/wiki/TracingSummit2012 - PD Week 2013: Josh Stone & David Smith stapdyn: Porting SystemTap onto Dyninst http://research.cs.wisc.edu/htcondor/HTCondorWeek2013/monday_paradyn.html systemtap-2.3/stapdyn/dynprobe.cxx000066400000000000000000000074061217430427200174500ustar00rootroot00000000000000// stapdyn probe functions // Copyright (C) 2012-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "dynprobe.h" #include "dynutil.h" #include "../util.h" extern "C" { #include "../runtime/dyninst/stapdyn.h" } using namespace std; // Look for probes in the stap module which need Dyninst instrumentation. int find_dynprobes(void* module, vector& targets) { // We query for probes with a function interface, so first we have // to get function pointers from the stap module. typeof(&stp_dyninst_target_count) target_count = NULL; typeof(&stp_dyninst_target_path) target_path = NULL; typeof(&stp_dyninst_probe_count) probe_count = NULL; typeof(&stp_dyninst_probe_target) probe_target = NULL; typeof(&stp_dyninst_probe_offset) probe_offset = NULL; typeof(&stp_dyninst_probe_semaphore) probe_semaphore = NULL; // If we don't even have this, then there aren't any uprobes in the module. set_dlsym(target_count, module, "stp_dyninst_target_count", false); if (target_count == NULL) return 0; try { // If target_count exists, the rest of these should too. set_dlsym(target_path, module, "stp_dyninst_target_path"); set_dlsym(probe_count, module, "stp_dyninst_probe_count"); set_dlsym(probe_target, module, "stp_dyninst_probe_target"); set_dlsym(probe_offset, module, "stp_dyninst_probe_offset"); set_dlsym(probe_semaphore, module, "stp_dyninst_probe_semaphore"); } catch (runtime_error& e) { staperror() << e.what() << endl; return 1; } // This is optional - was only added post-2.0 typeof(&stp_dyninst_probe_flags) probe_flags = NULL; set_dlsym(probe_flags, module, "stp_dyninst_probe_flags", false); // Construct all the targets in the module. const uint64_t ntargets = target_count(); for (uint64_t i = 0; i < ntargets; ++i) { const char* path = target_path(i); if (path == NULL) path = ""; dynprobe_target target(path); targets.push_back(target); } // Construct all the probes in the module, // and associate each with their target. const uint64_t nprobes = probe_count(); for (uint64_t i = 0; i < nprobes; ++i) { uint64_t target_index = probe_target(i); uint64_t offset = probe_offset(i); uint64_t semaphore = probe_semaphore(i); uint64_t flags = probe_flags ? probe_flags(i) : 0; dynprobe_location p(i, offset, semaphore, flags); if (p.validate() && target_index < ntargets) targets[target_index].probes.push_back(p); } // For debugging, dump what we found. for (uint64_t i = 0; i < ntargets; ++i) { dynprobe_target& t = targets[i]; staplog(3) << "target \"" << t.path << "\" has " << t.probes.size() << " probes" << endl; for (uint64_t j = 0; j < t.probes.size(); ++j) staplog(3) << " offset:" << lex_cast_hex(t.probes[j].offset) << " semaphore:" << lex_cast_hex(t.probes[j].semaphore) << " flags:" << t.probes[j].flags << endl; } return 0; } dynprobe_location::dynprobe_location(uint64_t index, uint64_t offset, uint64_t semaphore, uint64_t flags): index(index), offset(offset), semaphore(semaphore), flags(flags), return_p(flags & STAPDYN_PROBE_FLAG_RETURN) { } bool dynprobe_location::validate() { if (flags & ~STAPDYN_PROBE_ALL_FLAGS) { stapwarn() << "Unknown flags " << lex_cast_hex(flags) << " in probe " << index << endl; return false; } return true; } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stapdyn/dynprobe.h000066400000000000000000000026371217430427200170760ustar00rootroot00000000000000// stapdyn probe declarations // Copyright (C) 2012-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef DYNPROBE_H #define DYNPROBE_H #include #include extern "C" { #include } // The individual probes' info read from the stap module. struct dynprobe_location { uint64_t index; // The index as counted by the module. uint64_t offset; // The file offset of the probe's address. uint64_t semaphore; // The file offset of the probe's semaphore. uint64_t flags; // The probe's flags. bool return_p; // This is flagged as a return probe dynprobe_location(uint64_t index, uint64_t offset, uint64_t semaphore, uint64_t flags); bool validate(); }; // The probe target info read from the stap module. struct dynprobe_target { std::string path; // The fully resolved path to the file. std::vector probes; // All probes in this target. dynprobe_target(const char* path): path(path) {} }; // Look for probes in the stap module which need Dyninst instrumentation. int find_dynprobes(void* module, std::vector& targets); #endif // DYNPROBE_H /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stapdyn/dynsdt.cxx000066400000000000000000000242431217430427200171310ustar00rootroot00000000000000// dyninst example program // Copyright (C) 2012 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include #include #include extern "C" { #define __STDC_LIMIT_MACROS #define __STDC_CONSTANT_MACROS #define __STDC_FORMAT_MACROS #include #include #include #include #include #include #include #include #include } #include #include #include #include #include "dynutil.h" #include "../util.h" using namespace std; struct sdt_point { string provider; string name; vector > args; GElf_Addr pc_offset; GElf_Addr sem_offset; }; static vector > split_sdt_args(const string& args) { vector > vargs; size_t size_idx = 0; size_t at_idx = args.find('@'); while (at_idx != string::npos) { size_t size_idx2 = string::npos; size_t at_idx2 = args.find('@', at_idx + 1); if (at_idx2 != string::npos) { size_idx2 = args.rfind(' ', at_idx2); if (size_idx2 == string::npos || size_idx2 <= size_idx) size_idx2 = at_idx2 = string::npos; else ++size_idx2; } string size_str = args.substr(size_idx, at_idx - size_idx); int size = atoi(size_str.c_str()); string arg = args.substr(at_idx + 1, size_idx2 - at_idx - 2); vargs.push_back(make_pair(size, arg)); size_idx = size_idx2; at_idx = at_idx2; } return vargs; } static vector find_sdt(const string& file) { int fd = -1; size_t shstrndx; GElf_Addr sdt_base_addr = 0; GElf_Off sdt_base_offset = 0; GElf_Addr sdt_probes_addr = 0; GElf_Off sdt_probes_offset = 0; GElf_Off sdt_probes_virt_offset = 0; Elf* elf = NULL; Elf_Scn* scn = NULL; vector points; fd = open(file.c_str(), O_RDONLY); if (fd < 0) { warn("can't open %s", file.c_str()); goto ret; } elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); if (!elf) { warn("can't read elf %s", file.c_str()); goto ret_fd; } elf_getshdrstrndx (elf, &shstrndx); scn = NULL; while ((scn = elf_nextscn(elf, scn))) { GElf_Shdr shdr; if (gelf_getshdr (scn, &shdr) == NULL) continue; if (shdr.sh_type != SHT_PROGBITS) continue; if (!(shdr.sh_flags & SHF_ALLOC)) continue; const char* sh_name = elf_strptr(elf, shstrndx, shdr.sh_name); if (sh_name && !strcmp(".stapsdt.base", sh_name)) { sdt_base_addr = shdr.sh_addr; sdt_base_offset = shdr.sh_offset; warnx("SDT base addr:%#" PRIx64 " offset:%#" PRIx64 "", sdt_base_addr, sdt_base_offset); } if (sh_name && !strcmp(".probes", sh_name)) { sdt_probes_addr = shdr.sh_addr; sdt_probes_offset = shdr.sh_offset; warnx("SDT probes addr:%#" PRIx64 " offset:%#" PRIx64 "", sdt_probes_addr, sdt_probes_offset); } } // Data is usually loaded in a separate segment from text, with padding // between, so this computes the extra padding to subtract from semaphores. if (sdt_probes_offset) sdt_probes_virt_offset = (sdt_probes_addr - sdt_probes_offset) - (sdt_base_addr - sdt_base_offset); scn = NULL; while ((scn = elf_nextscn(elf, scn))) { GElf_Shdr shdr; if (gelf_getshdr (scn, &shdr) == NULL) continue; if (shdr.sh_type != SHT_NOTE) continue; if (shdr.sh_flags & SHF_ALLOC) continue; Elf_Data *data = elf_getdata (scn, NULL); size_t next; GElf_Nhdr nhdr; size_t name_off; size_t desc_off; for (size_t offset = 0; (next = gelf_getnote (data, offset, &nhdr, &name_off, &desc_off)) > 0; offset = next) { char* cdata = ((char*)data->d_buf); if (strcmp(cdata + name_off, "stapsdt") || nhdr.n_type != 3) continue; union { Elf64_Addr a64[3]; Elf32_Addr a32[3]; } buf; Elf_Data dst = { &buf, ELF_T_ADDR, EV_CURRENT, gelf_fsize (elf, ELF_T_ADDR, 3, EV_CURRENT), 0, 0 }; assert (dst.d_size <= sizeof buf); if (nhdr.n_descsz < dst.d_size + 3) continue; Elf_Data src = { cdata + desc_off, ELF_T_ADDR, EV_CURRENT, dst.d_size, 0, 0 }; if (gelf_xlatetom (elf, &dst, &src, elf_getident (elf, NULL)[EI_DATA]) == NULL) warnx ("gelf_xlatetom: %s", elf_errmsg (-1)); sdt_point p; const char* provider = cdata + desc_off + dst.d_size; p.provider = provider; const char* name = provider + p.provider.size() + 1; p.name = name; const char* args = name + p.name.size() + 1; if (args < cdata + desc_off + nhdr.n_descsz) p.args = split_sdt_args(args); GElf_Addr base_ref; if (gelf_getclass (elf) == ELFCLASS32) { p.pc_offset = buf.a32[0]; base_ref = buf.a32[1]; p.sem_offset = buf.a32[2]; } else { p.pc_offset = buf.a64[0]; base_ref = buf.a64[1]; p.sem_offset = buf.a64[2]; } // Convert to its relative position in the file p.pc_offset += sdt_base_offset - base_ref; if (p.sem_offset) p.sem_offset += sdt_base_offset - base_ref - sdt_probes_virt_offset; stringstream joined_args; for (size_t i = 0; i < p.args.size(); ++i) { if (i > 0) joined_args << ", "; joined_args << p.args[i].first << "@\"" << p.args[i].second << "\""; } warnx("SDT offset:%#" PRIx64 " semaphore:%#" PRIx64 " %s:%s(%s)", p.pc_offset, p.sem_offset, p.provider.c_str(), p.name.c_str(), joined_args.str().c_str()); points.push_back(p); } } elf_end(elf); ret_fd: close(fd); ret: return points; } static void instrument_sdt(BPatch_process* process, BPatch_object* object, sdt_point& p) { BPatch_image* image = process->getImage(); Dyninst::Address address = object->fileOffsetToAddr(p.pc_offset); if (address == BPatch_object::E_OUT_OF_BOUNDS) { warnx("couldn't convert %s:%s at %#" PRIx64 " to an address", p.provider.c_str(), p.name.c_str(), p.pc_offset); return; } vector points; object->findPoints(address, points); if (points.empty()) { warnx("couldn't find %s:%s at %#" PRIx64 " -> %#lx", p.provider.c_str(), p.name.c_str(), p.pc_offset, address); return; } ostringstream format; format << "SDT %s:%s"; BPatch_Vector regs; process->getRegisters(regs); for (size_t i = 0; i < regs.size(); ++i) if (regs[i].name()[2] == 'x') format << " " << regs[i].name() << ":%#lx"; format << "\n"; vector printfArgs; printfArgs.push_back(new BPatch_constExpr(format.str().c_str())); printfArgs.push_back(new BPatch_constExpr(p.provider.c_str())); printfArgs.push_back(new BPatch_constExpr(p.name.c_str())); for (size_t i = 0; i < regs.size(); ++i) if (regs[i].name()[2] == 'x') printfArgs.push_back(new BPatch_registerExpr(regs[i])); vector printfFuncs; image->findFunction("printf", printfFuncs); BPatch_funcCallExpr printfCall(*(printfFuncs[0]), printfArgs); warnx("inserting %s:%s at %#" PRIx64 " -> %#lx [%zu]", p.provider.c_str(), p.name.c_str(), p.pc_offset, address, points.size()); process->insertSnippet(printfCall, points); if (p.sem_offset) { Dyninst::Address sem_address = object->fileOffsetToAddr(p.sem_offset); if (sem_address == BPatch_object::E_OUT_OF_BOUNDS) warnx("couldn't convert %s:%s semaphore %#" PRIx64 " to an address", p.provider.c_str(), p.name.c_str(), p.sem_offset); else { warnx("incrementing semaphore for %s:%s at %#" PRIx64 " -> %#lx", p.provider.c_str(), p.name.c_str(), p.sem_offset, sem_address); BPatch_type *sem_type = image->findType("unsigned short"); BPatch_variableExpr *semaphore = process->createVariable(sem_address, sem_type); BPatch_arithExpr addOne(BPatch_assign, *semaphore, BPatch_arithExpr(BPatch_plus, *semaphore, BPatch_constExpr(1))); process->oneTimeCode(addOne); } } } static void instrument_sdt_points(BPatch_process* process, BPatch_object* object, vector& points) { process->beginInsertionSet(); for (size_t i = 0; i < points.size(); ++i) instrument_sdt(process, object, points[i]); process->finalizeInsertionSet(false); } int main(int argc, const char* argv[]) { if (argc < 2) errx(1, "usage: %s PROGRAM [ARGS..]", argv[0]); warnx("got args:"); for (int i = 1; i < argc; ++i) warnx(" [%i] %s", i - 1, argv[i]); if (!check_dyninst_rt()) return 1; if (!check_dyninst_sebools()) return 1; BPatch patch; warnx("creating the process"); string fullpath = find_executable(argv[1]); BPatch_process *app = patch.processCreate(fullpath.c_str(), &argv[1]); BPatch_image *image = app->getImage(); warnx("scanning the process for sdt with BPatch_object"); vector objects; image->getObjects(objects); for (size_t i = 0; i < objects.size(); ++i) { BPatch_object* obj = objects[i]; string file = obj->pathName(); warnx(" found mapped object %s", file.c_str()); vector sdt_points = find_sdt(file); if (sdt_points.empty()) continue; warnx("inserting sdt instrumentation in %s", file.c_str()); instrument_sdt_points(app, obj, sdt_points); } warnx("**** running the process"); app->continueExecution(); while (!app->isTerminated()) { patch.waitForStatusChange(); } warnx("done!"); return check_dyninst_exit(app) ? EXIT_SUCCESS : EXIT_FAILURE; } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stapdyn/dynutil.cxx000066400000000000000000000174361217430427200173220ustar00rootroot00000000000000// stapdyn utility functions // Copyright (C) 2012 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "config.h" #include #include #include extern "C" { #include #include #include } #ifdef HAVE_SELINUX #include #endif #include "dynutil.h" #include "../util.h" using namespace std; // Callback for dl_iterate_phdr to look for libdyninstAPI.so static int guess_dyninst_rt_callback(struct dl_phdr_info *info, size_t size __attribute__ ((unused)), void *data) { string& libdyninstAPI = *static_cast(data); const string name = info->dlpi_name ?: "(null)"; if (name.find("libdyninstAPI.so") != string::npos) libdyninstAPI = name; return 0; } // Look for libdyninstAPI.so in our own process, and use that // to guess the path for libdyninstAPI_RT.so static const string guess_dyninst_rt(void) { string libdyninstAPI; dl_iterate_phdr(guess_dyninst_rt_callback, &libdyninstAPI); string libdyninstAPI_RT; size_t so = libdyninstAPI.rfind(".so"); if (so != string::npos) { libdyninstAPI_RT = libdyninstAPI; libdyninstAPI_RT.insert(so, "_RT"); } return libdyninstAPI_RT; } // Check that environment DYNINSTAPI_RT_LIB exists and is a valid file. // If not, try to guess a good value and set it. bool check_dyninst_rt(void) { static const char rt_env_name[] = "DYNINSTAPI_RT_LIB"; const char* rt_env = getenv(rt_env_name); if (rt_env) { if (file_exists(rt_env)) return true; staperror() << "Invalid " << rt_env_name << ": \"" << rt_env << "\"" << endl; } const string rt = guess_dyninst_rt(); if (rt.empty() || !file_exists(rt)) { staperror() << "Can't find libdyninstAPI_RT.so; try setting " << rt_env_name << endl; return false; } if (setenv(rt_env_name, rt.c_str(), 1) != 0) { int olderrno = errno; staperror() << "Can't set " << rt_env_name << ": " << strerror(olderrno); return false; } return true; } // Check that SELinux settings are ok for Dyninst operation. bool check_dyninst_sebools(bool attach) { #ifdef HAVE_SELINUX // For all these checks, we could examine errno on failure to act differently // for e.g. ENOENT vs. EPERM. But since these are just early diagnostices, // I'm only going worry about successful bools for now. // deny_ptrace is definitely a blocker for us to attach at all if (security_get_boolean_active("deny_ptrace") > 0) { staperror() << "SELinux boolean 'deny_ptrace' is active, " "which blocks Dyninst" << endl; return false; } // We might have to get more nuanced about allow_execstack, especially if // Dyninst is later enhanced to work around this restriction. But for now, // this is also a blocker. if (security_get_boolean_active("allow_execstack") == 0) { staperror() << "SELinux boolean 'allow_execstack' is disabled, " "which blocks Dyninst" << endl; return false; } // In process-attach mode, SELinux will trigger "avc: denied { execmod }" // on ld.so, when the mutator is injecting the dlopen for libdyninstAPI_RT.so. if (attach && security_get_boolean_active("allow_execmod") == 0) { staperror() << "SELinux boolean 'allow_execmod' is disabled, " "which blocks Dyninst" << endl; return false; } #else (void)attach; // unused #endif return true; } // Check whether a process exited cleanly bool check_dyninst_exit(BPatch_process *process) { int code; switch (process->terminationStatus()) { case ExitedNormally: code = process->getExitCode(); if (code == EXIT_SUCCESS) return true; stapwarn() << "Child process exited with status " << code << endl; return false; case ExitedViaSignal: code = process->getExitSignal(); stapwarn() << "Child process exited with signal " << code << " (" << strsignal(code) << ")" << endl; return false; case NoExit: if (process->isTerminated()) stapwarn() << "Child process exited in an unknown manner" << endl; else stapwarn() << "Child process has not exited" << endl; return false; default: return false; } } // Get an untyped symbol from a dlopened module. // If flagged as 'required', throw an exception if missing or NULL. void * get_dlsym(void* handle, const char* symbol, bool required) { const char* err = dlerror(); // clear previous errors void *pointer = dlsym(handle, symbol); if (required) { if ((err = dlerror())) throw std::runtime_error("dlsym " + std::string(err)); if (pointer == NULL) throw std::runtime_error("dlsym " + std::string(symbol) + " is NULL"); } return pointer; } // // Logging, warnings, and errors, oh my! // // A null-sink output stream, similar to /dev/null // (no buffer -> badbit -> quietly suppressed output) static ostream nullstream(NULL); // verbosity, increased by -v unsigned stapdyn_log_level = 0; // Whether to suppress warnings, set by -w bool stapdyn_suppress_warnings = false; // Output file name, set by -o char *stapdyn_outfile_name = NULL; // Return a stream for logging at the given verbosity level. ostream& staplog(unsigned level) { if (level > stapdyn_log_level) return nullstream; return clog << program_invocation_short_name << ": "; } // Return a stream for warning messages. ostream& stapwarn(void) { if (stapdyn_suppress_warnings) return nullstream; return clog << program_invocation_short_name << ": " << colorize("WARNING:", "warning") << " "; } // Return a stream for error messages. ostream& staperror(void) { return clog << program_invocation_short_name << ": " << colorize("ERROR:", "error") << " "; } // Whether to color error and warning messages bool color_errors; // Initialized in main() // Adds coloring to strings std::string colorize(std::string str, std::string type) { if (str.empty() || !color_errors) return str; else { // Check if this type is defined in SYSTEMTAP_COLORS std::string color = parse_stap_color(type); if (!color.empty()) // no need to pollute terminal if not necessary return "\033[" + color + "m\033[K" + str + "\033[m\033[K"; else return str; } } /* Parse SYSTEMTAP_COLORS and returns the SGR parameter(s) for the given type. The env var SYSTEMTAP_COLORS must be in the following format: 'key1=val1:key2=val2:' etc... where valid keys are 'error', 'warning', 'source', 'caret', 'token' and valid values constitute SGR parameter(s). For example, the default setting would be: 'error=01;31:warning=00;33:source=00;34:caret=01:token=01' */ std::string parse_stap_color(std::string type) { const char *key, *col, *eq; int n = type.size(); int done = 0; key = getenv("SYSTEMTAP_COLORS"); if (key == NULL || *key == '\0') key = "error=01;31:warning=00;33:source=00;34:caret=01:token=01"; while (!done) { if (!(col = strchr(key, ':'))) { col = strchr(key, '\0'); done = 1; } if (!((eq = strchr(key, '=')) && eq < col)) return ""; /* invalid syntax: no = in range */ if (!(key < eq && eq < col-1)) return ""; /* invalid syntax: key or val empty */ if (strspn(eq+1, "0123456789;") < (size_t)(col-eq-1)) return ""; /* invalid syntax: invalid char in val */ if (eq-key == n && type.compare(0, n, key, n) == 0) return string(eq+1, col-eq-1); if (!done) key = col+1; /* advance to next key */ } // Could not find the key return ""; } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stapdyn/dynutil.h000066400000000000000000000040601217430427200167340ustar00rootroot00000000000000// stapdyn utility functions // Copyright (C) 2012 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef DYNUTIL_H #define DYNUTIL_H #include #include #include #include // Check that environment DYNINSTAPI_RT_LIB exists and is a valid file. // If not, try to guess a good value and set it. bool check_dyninst_rt(void); // Check that SELinux settings are ok for Dyninst operation. bool check_dyninst_sebools(bool attach=false); // Check whether a process exited cleanly bool check_dyninst_exit(BPatch_process *process); // Get an untyped symbol from a dlopened module. // If flagged as 'required', throw an exception if missing or NULL. void* get_dlsym(void* handle, const char* symbol, bool required=true); // Set a typed pointer by looking it up in a dlopened module. // If flagged as 'required', throw an exception if missing or NULL. template void set_dlsym(T*& pointer, void* handle, const char* symbol, bool required=true) { pointer = reinterpret_cast(get_dlsym(handle, symbol, required)); } // // Logging, warnings, and errors, oh my! // // verbosity, increased by -v extern unsigned stapdyn_log_level; // Whether to suppress warnings, set by -w extern bool stapdyn_suppress_warnings; // Output file name, set by -o extern char *stapdyn_outfile_name; // Return a stream for logging at the given verbosity level. std::ostream& staplog(unsigned level=0); // Return a stream for warning messages. std::ostream& stapwarn(void); // Return a stream for error messages. std::ostream& staperror(void); // Whether to color error and warning messages extern bool color_errors; // Adds coloring to strings std::string colorize(std::string str, std::string type); // Parse SYSTEMTAP_COLORS std::string parse_stap_color(std::string type); #endif // DYNUTIL_H /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stapdyn/mutatee.cxx000066400000000000000000000505751217430427200172770ustar00rootroot00000000000000// stapdyn mutatee functions // Copyright (C) 2012-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "mutatee.h" extern "C" { #include #include } #include #include #include #include #include #include "dynutil.h" #include "../util.h" extern "C" { #include "../runtime/dyninst/stapdyn.h" } using namespace std; // Create snippets for all the DWARF registers, // in their architecture-specific order. static void get_dwarf_registers(BPatch_process *app, vector& registers) { static const char* const names[] = { #if defined(__i386__) "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", #elif defined(__x86_64__) "rax", "rdx", "rcx", "rbx", "rsi", "rdi", "rbp", "rsp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", #elif defined(__powerpc__) || defined(__powerpc64__) "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", #endif NULL }; // First push the original PC, before instrumentation mucked anything up. // (There's also BPatch_actualAddressExpr for the instrumented result...) registers.push_back(new BPatch_originalAddressExpr()); vector bpregs; app->getRegisters(bpregs); ostream& debug_reg = staplog(4); debug_reg << "pid " << app->getPid() << " has " << bpregs.size() << " registers available:"; for (size_t i = 0; i < bpregs.size(); ++i) debug_reg << " " << bpregs[i].name(); debug_reg << endl; // Look for each DWARF register in BPatch's register set. // O(m*n) loop, but neither array is very large for (const char* const* name = names; *name; ++name) { size_t i; for (i = 0; i < bpregs.size(); ++i) if (bpregs[i].name() == *name) { // Found it, add a snippet. registers.push_back(new BPatch_registerExpr(bpregs[i])); break; } // If we didn't find it, put a zero in its place. if (i >= bpregs.size()) registers.push_back(new BPatch_constExpr((unsigned long)0)); } #if defined(__powerpc__) || defined(__powerpc64__) // In EmitterPOWER::emitCall(), Dyninst enforces a limit that "only 8 // arguments can (currently) be passed on the POWER architecture." // We start with the probe index and nregs, leaving just 6 more... while (registers.size() > 6) { delete registers.back(); registers.pop_back(); } #endif } // Simple object to temporarily make sure a process is stopped class mutatee_freezer { mutatee& m; bool already_stopped; public: mutatee_freezer(mutatee& m): m(m), already_stopped(m.is_stopped()) { // If process is currently running, stop it. if (!already_stopped && !m.stop_execution()) { staplog(3) << "stopping process failed, stopped=" << m.is_stopped() << ", terminated=" << m.is_terminated() << endl; } } ~mutatee_freezer() { // Let the process continue (if it wasn't stopped when we started). if (!already_stopped) m.continue_execution(); } }; mutatee::mutatee(BPatch_process* process): pid(process? process->getPid() : 0), process(process), stap_dso(NULL), utrace_enter_function(NULL) { get_dwarf_registers(process, registers); } mutatee::~mutatee() { remove_instrumentation(); unload_stap_dso(); if (process) process->detach(true); } // Inject the stap module into the target process bool mutatee::load_stap_dso(const string& filename) { stap_dso = process->loadLibrary(filename.c_str()); if (!stap_dso) { staperror() << "Couldn't load " << filename << " into the target process" << endl; return false; } return true; } // Unload the stap module from the target process void mutatee::unload_stap_dso() { if (!process || !stap_dso) return; // XXX Dyninst has no unloadLibrary() yet, as of 8.0 stap_dso = NULL; } void mutatee::update_semaphores(unsigned short delta, size_t start) { if (!process || process->isTerminated()) return; for (size_t i=start; i < semaphores.size(); ++i) { unsigned short value = 0; BPatch_variableExpr* semaphore = semaphores[i]; // Read-modify-write the semaphore remotely. semaphore->readValue(&value, (int)sizeof(value)); value += delta; semaphore->writeValue(&value, (int)sizeof(value)); } // NB: Alternatively, we could build up a oneTimeCode snippet to do them all // at once within the target process. For now, remote seems good enough. } void mutatee::call_utrace_dynprobe(const dynprobe_location& probe, BPatch_thread* thread) { if (utrace_enter_function != NULL) { vector args; args.push_back(new BPatch_constExpr((int64_t)probe.index)); args.push_back(new BPatch_constExpr((void*)NULL)); // pt_regs staplog(1) << "calling function with " << args.size() << " args" << endl; BPatch_funcCallExpr call(*utrace_enter_function, args); if (thread) thread->oneTimeCode(call); else process->oneTimeCode(call); } else staplog(1) << "no utrace enter function!" << endl; } // Remember utrace probes. They get handled when the associated // callback hits. void mutatee::instrument_utrace_dynprobe(const dynprobe_location& probe) { if (!stap_dso) return; if (utrace_enter_function == NULL) { vector functions; stap_dso->findFunction("enter_dyninst_utrace_probe", functions); if (!functions.empty()) utrace_enter_function = functions[0]; } // Remember this probe. It will get called from a callback function. attached_probes.push_back(probe); } // Handle "global" targets. They aren't really global, but non-path // based probes, like: // probe process.begin { ... } // probe process(PID).begin { ... } void mutatee::instrument_global_dynprobe_target(const dynprobe_target& target) { staplog(1) << "found global target, inserting " << target.probes.size() << " probes" << endl; for (size_t j = 0; j < target.probes.size(); ++j) { const dynprobe_location& probe = target.probes[j]; // We already know this isn't a path-based probe. We've got 2 // other qualifications here: // (1) Make sure this is a utrace probe by checking the flags. // (2) If PID was specified, does the pid match? if (((probe.flags & (STAPDYN_PROBE_FLAG_PROC_BEGIN | STAPDYN_PROBE_FLAG_PROC_END | STAPDYN_PROBE_FLAG_THREAD_BEGIN | STAPDYN_PROBE_FLAG_THREAD_END)) != 0) && (probe.offset == 0 || (int)probe.offset == process->getPid())) instrument_utrace_dynprobe(probe); } } // Given a target and the matching object, instrument all of the probes // with calls to the stap_dso's entry function. void mutatee::instrument_dynprobe_target(BPatch_object* object, const dynprobe_target& target) { if (!process || !stap_dso || !object) return; vector functions; BPatch_function* enter_function = NULL; bool use_pt_regs = false; staplog(1) << "found target \"" << target.path << "\", inserting " << target.probes.size() << " probes" << endl; for (size_t j = 0; j < target.probes.size(); ++j) { const dynprobe_location& probe = target.probes[j]; if ((probe.flags & (STAPDYN_PROBE_FLAG_PROC_BEGIN | STAPDYN_PROBE_FLAG_PROC_END | STAPDYN_PROBE_FLAG_THREAD_BEGIN | STAPDYN_PROBE_FLAG_THREAD_END)) != 0) { instrument_utrace_dynprobe(probe); continue; } if (! enter_function) { // XXX Until we know how to build pt_regs from here, we'll // try the entry function for individual registers first. if (!registers.empty()) stap_dso->findFunction("enter_dyninst_uprobe_regs", functions, false); if (!functions.empty()) enter_function = functions[0]; // If the other entry wasn't found, or we don't have // registers for it anyway, try the form that takes pt_regs* // and we'll just pass NULL. if (!enter_function) { stap_dso->findFunction("enter_dyninst_uprobe", functions, false); if (functions.empty()) { stapwarn() << "Couldn't find the uprobe entry function (either " << endl << "\"enter_dyninst_uprobe_regs\" or \"enter_dyninst_uprobe\"). Uprobe probes" << endl << "disabled." << endl; return; } use_pt_regs = true; enter_function = functions[0]; } } // Convert the file offset to a memory address. Dyninst::Address address = object->fileOffsetToAddr(probe.offset); if (address == BPatch_object::E_OUT_OF_BOUNDS) { stapwarn() << "Couldn't convert " << target.path << "+" << lex_cast_hex(probe.offset) << " to an address" << endl; continue; } // Turn the address into instrumentation points. // NB: There may be multiple results if Dyninst determined that multiple // concrete functions have overlapping ranges. Rare, but possible. vector points; object->findPoints(address, points); if (points.empty()) { stapwarn() << "Couldn't find an instrumentation point at " << lex_cast_hex(address) << ", " << target.path << "+" << lex_cast_hex(probe.offset) << endl; continue; } // TODO check each point->getFunction()->isInstrumentable() if (probe.return_p) { // Transform the address points into function exits vector return_points; for (size_t i = 0; i < points.size(); ++i) { vector* exits = points[i]->getFunction()->findPoint(BPatch_locExit); if (!exits || exits->empty()) { stapwarn() << "Couldn't find a return point from " << lex_cast_hex(address) << ", " << target.path << "+" << lex_cast_hex(probe.offset) << endl; continue; } return_points.insert(return_points.end(), exits->begin(), exits->end()); } points.swap(return_points); } // The entry function needs the index of this particular probe, then // the registers in whatever form we chose above. vector args; args.push_back(new BPatch_constExpr((int64_t)probe.index)); if (use_pt_regs) args.push_back(new BPatch_constExpr((void*)NULL)); // pt_regs else { args.push_back(new BPatch_constExpr((unsigned long)registers.size())); args.insert(args.end(), registers.begin(), registers.end()); } BPatch_funcCallExpr call(*enter_function, args); // Finally write the instrumentation for the probe! BPatchSnippetHandle* handle = process->insertSnippet(call, points); if (handle) snippets.push_back(handle); // Update SDT semaphores as needed. if (probe.semaphore) { Dyninst::Address sem_address = object->fileOffsetToAddr(probe.semaphore); if (sem_address == BPatch_object::E_OUT_OF_BOUNDS) stapwarn() << "Couldn't convert semaphore " << target.path << "+" << lex_cast_hex(probe.offset) << " to an address" << endl; else { // Create a variable to represent this semaphore BPatch_type *sem_type = process->getImage()->findType("unsigned short"); BPatch_variableExpr *semaphore = process->createVariable(sem_address, sem_type); if (semaphore) semaphores.push_back(semaphore); } } } } // Look for "global" (non-path based) probes and handle them. void mutatee::instrument_global_dynprobes(const vector& targets) { if (!process || !stap_dso || targets.empty()) return; // Look for global (non path-based probes), and remember them. for (size_t i = 0; i < targets.size(); ++i) { const dynprobe_target& target = targets[i]; // Do the real work... if (target.path.empty()) instrument_global_dynprobe_target(target); } } // Look for all matches between this object and the targets // we want to probe, then do the instrumentation. void mutatee::instrument_object_dynprobes(BPatch_object* object, const vector& targets) { if (!process || !stap_dso || !object || targets.empty()) return; // We want to map objects by their full path, but the pathName from // Dyninst might be relative, so fill it out. string path = resolve_path(object->pathName()); staplog(2) << "found object " << path << endl; size_t semaphore_start = semaphores.size(); // Match the object to our targets, and instrument matches. process->beginInsertionSet(); for (size_t i = 0; i < targets.size(); ++i) { const dynprobe_target& target = targets[i]; // Do the real work... if (path == target.path) instrument_dynprobe_target(object, target); } process->finalizeInsertionSet(false); // Increment new semaphores update_semaphores(1, semaphore_start); } void mutatee::begin_callback() { // process->oneTimeCode() requires that the process be stopped mutatee_freezer mf(*this); if (!is_stopped()) return; for (size_t i = 0; i < attached_probes.size(); ++i) { const dynprobe_location& probe = attached_probes[i]; if (probe.flags & STAPDYN_PROBE_FLAG_PROC_BEGIN) { staplog(1) << "found begin proc probe, index = " << probe.index << endl; call_utrace_dynprobe(probe); } } } // FIXME: We have a problem with STAPDYN_PROBE_FLAG_PROC_END // (i.e. 'process.end' probes). // // If we use dyninst's registerExitCallback(), when that callback // hits, we can't stop the process before it exits. So, we can't call // oneTimeCode() as we've done for the thread callbacks. So, that // doesn't work. // // When registerExitCallback() hits, we could just run the probe // locally, but then the probe context wouldn't be correct. void mutatee::exit_callback(BPatch_thread *thread) { for (size_t i = 0; i < attached_probes.size(); ++i) { const dynprobe_location& probe = attached_probes[i]; if (probe.flags & STAPDYN_PROBE_FLAG_PROC_END) { staplog(1) << "found end proc probe, index = " << probe.index << endl; call_utrace_dynprobe(probe, thread); } } } void mutatee::thread_callback(BPatch_thread *thread, bool create_p) { // If 'thread' is the main process, just return. We can't stop the // process before it terminates. if (thread->getLWP() == process->getPid()) return; // thread->oneTimeCode() requires that the process (not just the // thread) be stopped. So, stop the process if needed. mutatee_freezer mf(*this); if (!is_stopped()) return; for (size_t i = 0; i < attached_probes.size(); ++i) { const dynprobe_location& probe = attached_probes[i]; if ((create_p && probe.flags & STAPDYN_PROBE_FLAG_THREAD_BEGIN) || (!create_p && probe.flags & STAPDYN_PROBE_FLAG_THREAD_END)) { staplog(1) << "found " << (create_p ? "begin" : "end") << " thread probe, index = " << probe.index << endl; call_utrace_dynprobe(probe, thread); } } } void mutatee::find_attached_probes(uint64_t flag, vector&probes) { for (size_t i = 0; i < attached_probes.size(); ++i) { const dynprobe_location& probe = attached_probes[i]; if (probe.flags & flag) probes.push_back(&probe); } } // Look for probe matches in all objects. void mutatee::instrument_dynprobes(const vector& targets, bool after_exec_p) { if (!process || !stap_dso || targets.empty()) return; BPatch_image* image = process->getImage(); if (!image) return; // If this is post-exec, run any process.end from the pre-exec process if (after_exec_p && !attached_probes.empty()) { exit_callback(NULL); attached_probes.clear(); } // Match non object/path specific probes. instrument_global_dynprobes(targets); // Read all of the objects in the process. vector objects; image->getObjects(objects); for (size_t i = 0; i < objects.size(); ++i) instrument_object_dynprobes(objects[i], targets); } // Copy data for forked instrumentation void mutatee::copy_forked_instrumentation(mutatee& other) { if (!process) return; // Freeze both processes, so we have a stable base. mutatee_freezer mf_parent(other), mf(*this); // Find the same stap module in the fork if (other.stap_dso) { BPatch_image* image = process->getImage(); if (!image) return; string dso_path = other.stap_dso->pathName(); vector objects; image->getObjects(objects); for (size_t i = 0; i < objects.size(); ++i) if (objects[i]->pathName() == dso_path) { stap_dso = objects[i]; break; } } // Get new handles for all inserted snippets for (size_t i = 0; i < other.snippets.size(); ++i) { BPatchSnippetHandle *handle = process->getInheritedSnippet(*other.snippets[i]); if (handle) snippets.push_back(handle); } // Get new variable representations of semaphores for (size_t i = 0; i < other.semaphores.size(); ++i) { BPatch_variableExpr *semaphore = process->getInheritedVariable(*other.semaphores[i]); if (semaphore) semaphores.push_back(semaphore); } // Update utrace probes to match for (size_t i = 0; i < other.attached_probes.size(); ++i) instrument_utrace_dynprobe(other.attached_probes[i]); } // Reset instrumentation after an exec void mutatee::exec_reset_instrumentation() { // Reset members that are now out of date stap_dso = NULL; snippets.clear(); semaphores.clear(); // NB: the utrace attached_probes are saved, so process.end can run as the // new process is instrumented. Thus, no attached_probes.clear() yet. utrace_enter_function = NULL; } // Remove all BPatch snippets we've instrumented in the target void mutatee::remove_instrumentation() { if (!process || snippets.empty()) return; process->beginInsertionSet(); for (size_t i = 0; i < snippets.size(); ++i) process->deleteSnippet(snippets[i]); process->finalizeInsertionSet(false); snippets.clear(); // Decrement all semaphores update_semaphores(-1); semaphores.clear(); unload_stap_dso(); } // Look up a function by name in the target and invoke it without parameters. void mutatee::call_function(const string& name) { vector args; call_function(name, args); } // Look up a function by name in the target and invoke it with parameters. void mutatee::call_function(const string& name, const vector& args) { if (!stap_dso) return; vector functions; stap_dso->findFunction(name.c_str(), functions); // XXX Dyninst can return multiple results, but we're not really // expecting that... should we really call them all anyway? for (size_t i = 0; i < functions.size(); ++i) { BPatch_funcCallExpr call(*functions[i], args); process->oneTimeCode(call); } } // Send a signal to the process. int mutatee::kill(int signal) { return pid ? ::kill(pid, signal) : -2; } void mutatee::continue_execution() { if (is_stopped()) process->continueExecution(); } bool mutatee::stop_execution() { if (process->isStopped()) { // Process is already stopped, no need to do anything else. return true; } staplog(1) << "stopping process" << endl; if (! process->stopExecution()) { staplog(1) << "stopExecution failed!" << endl; return false; } if (! process->isStopped() || process->isTerminated()) { staplog(1) << "couldn't stop proc!" << endl; return false; } return true; } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stapdyn/mutatee.h000066400000000000000000000075241217430427200167200ustar00rootroot00000000000000// stapdyn mutatee declarations // Copyright (C) 2012-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef MUTATEE_H #define MUTATEE_H #include #include #include #include #include #include "dynprobe.h" #include "dynutil.h" // A mutatee is created for each attached process class mutatee { private: pid_t pid; // The system's process ID. BPatch_process* process; // Dyninst's handle for this process BPatch_object* stap_dso; // the injected stap module std::vector registers; // PC + DWARF registers std::vector snippets; // handles from insertSnippet std::vector semaphores; // SDT semaphore variables std::vector attached_probes; BPatch_function* utrace_enter_function; // disable implicit constructors by not implementing these mutatee (const mutatee& other); mutatee& operator= (const mutatee& other); void update_semaphores(unsigned short delta, size_t start=0); void call_utrace_dynprobe(const dynprobe_location& probe, BPatch_thread* thread=NULL); void instrument_utrace_dynprobe(const dynprobe_location& probe); void instrument_global_dynprobe_target(const dynprobe_target& target); void instrument_global_dynprobes(const std::vector& targets); public: mutatee(BPatch_process* process); ~mutatee(); pid_t process_id() { return pid; } bool operator==(BPatch_process* other) { return process == other; } // Inject the stap module into the target process bool load_stap_dso(const std::string& filename); // Unload the stap module from the target process void unload_stap_dso(); // Given a target and the matching object, instrument all of the probes // with calls to the stap_dso's entry function. void instrument_dynprobe_target(BPatch_object* object, const dynprobe_target& target); // Look for all matches between this object and the targets // we want to probe, then do the instrumentation. void instrument_object_dynprobes(BPatch_object* object, const std::vector& targets); // Look for probe matches in all objects. void instrument_dynprobes(const std::vector& targets, bool after_exec_p=false); // Copy data for forked instrumentation void copy_forked_instrumentation(mutatee& other); // Reset instrumentation after an exec void exec_reset_instrumentation(); // Remove all BPatch snippets we've instrumented in the target void remove_instrumentation(); // Look up a stap function by name and invoke it, optionally with parameters. void call_function(const std::string& name); void call_function(const std::string& name, const std::vector& args); // Send a signal to the process. int kill(int signal); bool stop_execution(); void continue_execution(); void terminate_execution() { process->terminateExecution(); } bool is_stopped() { return process->isStopped(); } bool is_terminated() { return process->isTerminated(); } bool check_exit() { return check_dyninst_exit(process); } void begin_callback(); void exit_callback(BPatch_thread *thread); void thread_callback(BPatch_thread *thread, bool create_p); void find_attached_probes(uint64_t flag, std::vector&probes); }; #endif // MUTATEE_H /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stapdyn/mutator.cxx000066400000000000000000000526611217430427200173240ustar00rootroot00000000000000// stapdyn mutator functions // Copyright (C) 2012-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "mutator.h" #include extern "C" { #include #include #include #include } #include #include "dynutil.h" #include "../util.h" extern "C" { #include "../runtime/dyninst/stapdyn.h" } using namespace std; // NB: since Dyninst callbacks have no context, we have to demux it // to every mutator we've created, tracked by this vector. static vector g_mutators; static void g_dynamic_library_callback(BPatch_thread *thread, BPatch_module *module, bool load) { for (size_t i = 0; i < g_mutators.size(); ++i) g_mutators[i]->dynamic_library_callback(thread, module, load); } static void g_post_fork_callback(BPatch_thread *parent, BPatch_thread *child) { for (size_t i = 0; i < g_mutators.size(); ++i) g_mutators[i]->post_fork_callback(parent, child); } static void g_exec_callback(BPatch_thread *thread) { for (size_t i = 0; i < g_mutators.size(); ++i) g_mutators[i]->exec_callback(thread); } static void g_exit_callback(BPatch_thread *thread, BPatch_exitType type) { for (size_t i = 0; i < g_mutators.size(); ++i) g_mutators[i]->exit_callback(thread, type); } static void g_thread_create_callback(BPatch_process *proc, BPatch_thread *thread) { for (size_t i = 0; i < g_mutators.size(); ++i) g_mutators[i]->thread_create_callback(proc, thread); } static void g_thread_destroy_callback(BPatch_process *proc, BPatch_thread *thread) { for (size_t i = 0; i < g_mutators.size(); ++i) g_mutators[i]->thread_destroy_callback(proc, thread); } static pthread_t g_main_thread = pthread_self(); static const sigset_t *g_signal_mask; static void g_signal_handler(int signal) { /* We only want the signal on our main thread, so it will interrupt the ppoll * loop. If we get it on a different thread, just forward it. */ if (!pthread_equal(pthread_self(), g_main_thread)) { pthread_kill(g_main_thread, signal); return; } for (size_t i = 0; i < g_mutators.size(); ++i) g_mutators[i]->signal_callback(signal); } __attribute__((constructor)) static void setup_signals (void) { struct sigaction sa; static sigset_t mask; static const int signals[] = { SIGHUP, SIGINT, SIGTERM, SIGQUIT, }; /* Prepare the global sigmask for future use. */ sigemptyset (&mask); for (size_t i = 0; i < sizeof(signals) / sizeof(*signals); ++i) sigaddset (&mask, signals[i]); g_signal_mask = &mask; /* Prepare the common signal handler. */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = g_signal_handler; sa.sa_flags = SA_RESTART; sigemptyset (&sa.sa_mask); for (size_t i = 0; i < sizeof(signals) / sizeof(*signals); ++i) sigaddset (&sa.sa_mask, signals[i]); /* Activate the handler for every signal. */ for (size_t i = 0; i < sizeof(signals) / sizeof(*signals); ++i) sigaction (signals[i], &sa, NULL); } mutator::mutator (const string& module_name, vector& module_options): module(NULL), module_name(resolve_path(module_name)), modoptions(module_options), p_target_created(false), p_target_error(false), utrace_enter_fn(NULL) { // NB: dlopen does a library-path search if the filename doesn't have any // path components, which is why we use resolve_path(module_name) sigemptyset(&signals_received); g_mutators.push_back(this); } mutator::~mutator () { // Explicitly drop our mutatee references, so we better // control when their instrumentation is removed. target_mutatee.reset(); mutatees.clear(); if (module) { dlclose(module); module = NULL; } g_mutators.erase(find(g_mutators.begin(), g_mutators.end(), this)); } // Do probes matching 'flag' exist? bool mutator::matching_probes_exist(uint64_t flag) { for (size_t i = 0; i < targets.size(); ++i) { for (size_t j = 0; j < targets[i].probes.size(); ++j) { if (targets[i].probes[j].flags & flag) return true; } } return false; } // Load the stap module and initialize all probe info. bool mutator::load () { int rc; // Open the module directly, so we can query probes or run simple ones. (void)dlerror(); // clear previous errors module = dlopen(module_name.c_str(), RTLD_NOW); if (!module) { staperror() << "dlopen " << dlerror() << endl; return false; } if ((rc = find_dynprobes(module, targets))) return rc; if (!targets.empty()) { // Always watch for new libraries to probe. patch.registerDynLibraryCallback(g_dynamic_library_callback); // Always watch for new child processes, even if we don't have // STAPDYN_PROBE_FLAG_PROC_BEGIN, because we might want to trigger // any of the other types of probes in new processes too. patch.registerPostForkCallback(g_post_fork_callback); patch.registerExecCallback(g_exec_callback); // Do we need a exit callback? if (matching_probes_exist(STAPDYN_PROBE_FLAG_PROC_END)) patch.registerExitCallback(g_exit_callback); // Do we need a thread create callback? if (matching_probes_exist(STAPDYN_PROBE_FLAG_THREAD_BEGIN)) patch.registerThreadEventCallback(BPatch_threadCreateEvent, g_thread_create_callback); // Do we need a thread destroy callback? if (matching_probes_exist(STAPDYN_PROBE_FLAG_THREAD_END)) patch.registerThreadEventCallback(BPatch_threadDestroyEvent, g_thread_destroy_callback); } return true; } // Create a new process with the given command line bool mutator::create_process(const string& command) { if (target_mutatee) { staperror() << "Already attached to a target process!" << endl; return false; } // Split the command into words. If wordexp can't do it, // we'll just run via "sh -c" instead. const char** child_argv; const char* sh_argv[] = { "/bin/sh", "-c", command.c_str(), NULL }; wordexp_t words; int rc = wordexp (command.c_str(), &words, WRDE_NOCMD|WRDE_UNDEF); if (rc == 0) child_argv = (/*cheater*/ const char**) words.we_wordv; else if (rc == WRDE_BADCHAR) child_argv = sh_argv; else { staperror() << "wordexp parsing error (" << rc << ")" << endl; return false; } // Search the PATH if necessary, then create the target process! string fullpath = find_executable(child_argv[0]); BPatch_process* app = patch.processCreate(fullpath.c_str(), child_argv); if (!app) { staperror() << "Couldn't create the target process" << endl; return false; } boost::shared_ptr m(new mutatee(app)); mutatees.push_back(m); target_mutatee = m; p_target_created = true; if (!m->load_stap_dso(module_name)) return false; if (!targets.empty()) m->instrument_dynprobes(targets); return true; } // Attach to a specific existing process. bool mutator::attach_process(pid_t pid) { if (target_mutatee) { staperror() << "Already attached to a target process!" << endl; return false; } BPatch_process* app = patch.processAttach(NULL, pid); if (!app) { staperror() << "Couldn't attach to the target process" << endl; return false; } boost::shared_ptr m(new mutatee(app)); mutatees.push_back(m); target_mutatee = m; p_target_created = false; if (!m->load_stap_dso(module_name)) return false; if (!targets.empty()) m->instrument_dynprobes(targets); return true; } bool mutator::init_modoptions() { typeof(&stp_global_setter) global_setter = NULL; set_dlsym(global_setter, module, "stp_global_setter", false); if (global_setter == NULL) { // Hypothetical backwards compatibility with older stapdyn: stapwarn() << "Compiled module does not support -G globals" << endl; return false; } for (vector::iterator it = modoptions.begin(); it != modoptions.end(); it++) { string modoption = *it; // Parse modoption as "name=value" // XXX: compare whether this behaviour fits safety regex in buildrun.cxx string::size_type separator = modoption.find('='); if (separator == string::npos) { stapwarn() << "Could not parse module option '" << modoption << "'" << endl; return false; // XXX: perhaps ignore the option instead? } string name = modoption.substr(0, separator); string value = modoption.substr(separator+1); int rc = global_setter(name.c_str(), value.c_str()); if (rc != 0) { stapwarn() << "Incorrect module option '" << modoption << "'" << endl; return false; // XXX: perhaps ignore the option instead? } } return true; } void mutator::init_session_attributes() { typeof(&stp_global_setter) global_setter = NULL; set_dlsym(global_setter, module, "stp_global_setter", false); if (global_setter == NULL) { // Just return. return; } // Note that the list of supported attributes should match with the // list in 'struct _stp_sesion_attributes' in // runtime/dyninst/session_attributes.h. int rc = global_setter("@log_level", lex_cast(stapdyn_log_level).c_str()); if (rc != 0) stapwarn() << "Couldn't set 'log_level' global" << endl; rc = global_setter("@suppress_warnings", lex_cast(stapdyn_suppress_warnings).c_str()); if (rc != 0) stapwarn() << "Couldn't set 'suppress_warnings' global" << endl; rc = global_setter("@stp_pid", lex_cast(getpid()).c_str()); if (rc != 0) stapwarn() << "Couldn't set 'stp_pid' global" << endl; if (target_mutatee) { rc = global_setter("@target", lex_cast(target_mutatee->process_id()).c_str()); if (rc != 0) stapwarn() << "Couldn't set 'target' global" << endl; } size_t module_endpath = module_name.rfind('/'); size_t module_basename_start = (module_endpath != string::npos) ? module_endpath + 1 : 0; size_t module_basename_end = module_name.find('.', module_basename_start); size_t module_basename_len = module_basename_end - module_basename_start; string module_basename(module_name, module_basename_start, module_basename_len); rc = global_setter("@module_name", module_basename.c_str()); if (rc != 0) stapwarn() << "Couldn't set 'module_name' global" << endl; time_t now_t = time(NULL); struct tm* now = localtime(&now_t); if (now) { rc = global_setter("@tz_gmtoff", lex_cast(-now->tm_gmtoff).c_str()); if (rc != 0) stapwarn() << "Couldn't set 'tz_gmtoff' global" << endl; rc = global_setter("@tz_name", now->tm_zone); if (rc != 0) stapwarn() << "Couldn't set 'tz_name' global" << endl; } else stapwarn() << "Couldn't discover local timezone info" << endl; if (stapdyn_outfile_name) { rc = global_setter("@outfile_name", lex_cast(stapdyn_outfile_name).c_str()); if (rc != 0) stapwarn() << "Couldn't set 'outfile_name' global" << endl; } return; } // Initialize the module session bool mutator::run_module_init() { if (!module) return false; // First see if this is a shared-memory, multiprocess-capable module typeof(&stp_dyninst_shm_init) shm_init = NULL; typeof(&stp_dyninst_shm_connect) shm_connect = NULL; set_dlsym(shm_init, module, "stp_dyninst_shm_init", false); set_dlsym(shm_connect, module, "stp_dyninst_shm_connect", false); if (shm_init && shm_connect) { // Initialize the shared-memory locally. const char* shmem = shm_init(); if (shmem == NULL) { stapwarn() << "stp_dyninst_shm_init failed!" << endl; return false; } module_shmem = shmem; // After the session is initilized, then we'll map shmem in the target } else if (target_mutatee) { // For modules that don't support shared-memory, but still have a target // process, we'll run init/exit in the target. target_mutatee->call_function("stp_dyninst_session_init"); return true; } // From here, either this is a shared-memory module, // or we have no target and thus run init directly anyway. typeof(&stp_dyninst_session_init) session_init = NULL; try { set_dlsym(session_init, module, "stp_dyninst_session_init"); } catch (runtime_error& e) { staperror() << e.what() << endl; return false; } // Before init runs, set any custom variables if (!modoptions.empty() && !init_modoptions()) return false; init_session_attributes(); int rc = session_init(); if (rc) { stapwarn() << "stp_dyninst_session_init returned " << rc << endl; return false; } // Now we map the shared-memory into the target if (target_mutatee && !module_shmem.empty()) { vector args; args.push_back(new BPatch_constExpr(module_shmem.c_str())); target_mutatee->call_function("stp_dyninst_shm_connect", args); } return true; } // Shutdown the module session bool mutator::run_module_exit() { if (!module) return false; if (target_mutatee && module_shmem.empty()) { // For modules that don't support shared-memory, but still have a target // process, we'll run init/exit in the target. // XXX This may already have been done in its deconstructor if the process exited. target_mutatee->call_function("stp_dyninst_session_exit"); return true; } // From here, either this is a shared-memory module, // or we have no target and thus run exit directly anyway. typeof(&stp_dyninst_session_exit) session_exit = NULL; try { set_dlsym(session_exit, module, "stp_dyninst_session_exit"); } catch (runtime_error& e) { staperror() << e.what() << endl; return false; } session_exit(); return true; } // Check the status of all mutatees bool mutator::update_mutatees() { // We'll always break right away for SIGQUIT. We'll also break for any other // signal if we didn't create the process. Otherwise, we should give the // created process a chance to finish. if (sigismember(&signals_received, SIGQUIT) || (!sigisemptyset(&signals_received) && !p_target_created)) return false; if (target_mutatee && target_mutatee->is_terminated()) return false; for (size_t i = 0; i < mutatees.size();) { boost::shared_ptr m = mutatees[i]; if (m != target_mutatee && m->is_terminated()) { mutatees.erase(mutatees.begin() + i); continue; // NB: without ++i } ++i; } return true; } // Start the actual systemtap session! bool mutator::run () { // Get the stap module ready... run_module_init(); // And away we go! if (target_mutatee) { // For our first event, fire the target's process.begin probes (if any) target_mutatee->begin_callback(); target_mutatee->continue_execution(); // Dyninst's notification FD was fixed in 8.1; for earlier versions we'll // fall back to the fully-blocking wait for now. #ifdef DYNINST_8_1 // mask signals while we're preparing to poll stap_sigmasker masked(g_signal_mask); // Polling with a notification FD lets us wait on Dyninst while still // letting signals break us out of the loop. while (update_mutatees()) { pollfd pfd; pfd.fd = patch.getNotificationFD(); pfd.events = POLLIN; pfd.revents = 0; struct timespec timeout = { 10, 0 }; int rc = ppoll (&pfd, 1, &timeout, &masked.old); if (rc < 0 && errno != EINTR) break; // Acknowledge and activate whatever events are waiting patch.pollForStatusChange(); } #else while (update_mutatees()) patch.waitForStatusChange(); #endif } else // !target_mutatee { // With no mutatees, we just wait for a signal to exit. stap_sigmasker masked(g_signal_mask); while (sigisemptyset(&signals_received)) sigsuspend(&masked.old); } // Indicate failure if the target had anything but EXIT_SUCCESS if (target_mutatee && target_mutatee->is_terminated()) p_target_error = !target_mutatee->check_exit(); // Detach from everything target_mutatee.reset(); mutatees.clear(); // Shutdown the stap module. return run_module_exit(); } // Get the final exit status of this mutator int mutator::exit_status () { if (!module) return EXIT_FAILURE; // NB: Only shm modules are new enough to have stp_dyninst_exit_status at // all, so we don't need to try in-target for old modules like session_exit. typeof(&stp_dyninst_exit_status) get_exit_status = NULL; set_dlsym(get_exit_status, module, "stp_dyninst_exit_status", false); if (get_exit_status) { int status = get_exit_status(); if (status != EXIT_SUCCESS) return status; } return p_target_error ? EXIT_FAILURE : EXIT_SUCCESS; } // Find a mutatee which matches the given process, else return NULL boost::shared_ptr mutator::find_mutatee(BPatch_process* process) { for (size_t i = 0; i < mutatees.size(); ++i) if (*mutatees[i] == process) return mutatees[i]; return boost::shared_ptr(); } // Callback to respond to dynamically loaded libraries. // Check if it matches our targets, and instrument accordingly. void mutator::dynamic_library_callback(BPatch_thread *thread, BPatch_module *module, bool load) { if (!load || !thread || !module) return; BPatch_process* process = thread->getProcess(); staplog(1) << "dlopen \"" << module->libraryName() << "\", pid = " << process->getPid() << endl; boost::shared_ptr mut = find_mutatee(process); if (mut) mut->instrument_object_dynprobes(module->getObject(), targets); } // Callback to respond to post fork events. Check if it matches our // targets, and handle accordingly. void mutator::post_fork_callback(BPatch_thread *parent, BPatch_thread *child) { if (!child || !parent) return; BPatch_process* child_process = child->getProcess(); BPatch_process* parent_process = parent->getProcess(); staplog(1) << "post fork, parent " << parent_process->getPid() << ", child " << child_process->getPid() << endl; boost::shared_ptr mut = find_mutatee(parent_process); if (mut) { // Clone the mutatee for the new process. boost::shared_ptr m(new mutatee(child_process)); mutatees.push_back(m); m->copy_forked_instrumentation(*mut); // Trigger any process.begin probes. m->begin_callback(); } } // Callback to respond to exec events. Check if it matches our // targets, and handle accordingly. void mutator::exec_callback(BPatch_thread *thread) { if (!thread) return; BPatch_process* process = thread->getProcess(); staplog(1) << "exec, pid = " << process->getPid() << endl; boost::shared_ptr mut = find_mutatee(process); if (mut) { // Clear previous instrumentation mut->exec_reset_instrumentation(); // FIXME the loadLibrary is hanging in Dyninst waiting for IRPC. // I've tried deferring this until update_mutatees() too - same hang. #if 0 // Load our module again in the new process if (mut->load_stap_dso(module_name)) mut->instrument_dynprobes(targets, true); #endif } } void mutator::exit_callback(BPatch_thread *thread, BPatch_exitType type __attribute__((unused))) { if (!thread) return; // 'thread' is the thread that requested the exit, not necessarily the // main thread. BPatch_process* process = thread->getProcess(); if (utrace_enter_fn == NULL) { try { set_dlsym(utrace_enter_fn, module, "enter_dyninst_utrace_probe"); } catch (runtime_error& e) { staperror() << e.what() << endl; return; } } staplog(1) << "exit callback, pid = " << process->getPid() << endl; boost::shared_ptr mut = find_mutatee(process); if (mut) { // FIXME: We'd like to call the mutatee's exit_callback() // function, but we've got a problem. The mutatee can't stop the // process to call the exit probe within the target (it finishes // exiting before we can). So, we'll call the probe(s) locally // here. This works, but the context is wrong (the mutator, not // the mutatee). vector exit_probes; mut->find_attached_probes(STAPDYN_PROBE_FLAG_PROC_END, exit_probes); for (size_t p = 0; p < exit_probes.size(); ++p) { const dynprobe_location *probe = exit_probes[p]; staplog(1) << "found end proc probe, index = " << probe->index << endl; int rc = utrace_enter_fn(probe->index, NULL); if (rc) stapwarn() << "enter_dyninst_utrace_probe returned " << rc << endl; } } } void mutator::thread_create_callback(BPatch_process *proc, BPatch_thread *thread) { if (!proc || !thread) return; boost::shared_ptr mut = find_mutatee(proc); if (mut) mut->thread_callback(thread, true); } void mutator::thread_destroy_callback(BPatch_process *proc, BPatch_thread *thread) { if (!proc || !thread) return; boost::shared_ptr mut = find_mutatee(proc); if (mut) mut->thread_callback(thread, false); } // Callback to respond to signals. void mutator::signal_callback(int signal) { sigaddset(&signals_received, signal); } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stapdyn/mutator.h000066400000000000000000000073431217430427200167460ustar00rootroot00000000000000// stapdyn mutator functions // Copyright (C) 2012-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef MUTATOR_H #define MUTATOR_H #include #include #include #include #include #include #include #include "dynprobe.h" #include "dynutil.h" #include "mutatee.h" extern "C" { #include "../runtime/dyninst/stapdyn.h" } // The mutator drives all instrumentation. class mutator { private: BPatch patch; void* module; // the locally dlopened probe module std::string module_name; // the filename of the probe module std::vector modoptions; // custom globals from -G option std::string module_shmem; // the global name of this module's shared memory std::vector targets; // the probe targets in the module std::vector > mutatees; // all attached target processes boost::shared_ptr target_mutatee; // the main target process we created or attached bool p_target_created; // we only kill and wait on the target we created bool p_target_error; // indicates whether the target exited non-zero; sigset_t signals_received; // record all signals we've caught // disable implicit constructors by not implementing these mutator (const mutator& other); mutator& operator= (const mutator& other); // Initialize the module global variables bool init_modoptions(); // Initialize the session attributes void init_session_attributes(); // Initialize the module session bool run_module_init(); // Shutdown the module session bool run_module_exit(); // Check the status of all mutatees bool update_mutatees(); // Do probes matching 'flag' exist? bool matching_probes_exist(uint64_t flag); // Find a mutatee which matches the given process, else return NULL boost::shared_ptr find_mutatee(BPatch_process* process); // Stashed utrace probe enter function pointer. typeof(&enter_dyninst_utrace_probe) utrace_enter_fn; public: mutator (const std::string& module_name, std::vector& module_options); ~mutator (); // Load the stap module and initialize all probe info. bool load (); // Create a new process with the given command line. bool create_process(const std::string& command); // Attach to a specific existing process. bool attach_process(BPatch_process* process); bool attach_process(pid_t pid); // Start the actual systemtap session! bool run (); // Get the final exit status of this mutator int exit_status(); // Callback to respond to dynamically loaded libraries. // Check if it matches our targets, and instrument accordingly. void dynamic_library_callback(BPatch_thread *thread, BPatch_module *module, bool load); // Callback to respond to post fork events. Check if it matches // our targets, and handle accordingly. void post_fork_callback(BPatch_thread *parent, BPatch_thread *child); void exec_callback(BPatch_thread *thread); void exit_callback(BPatch_thread *thread, BPatch_exitType type); void thread_create_callback(BPatch_process *proc, BPatch_thread *thread); void thread_destroy_callback(BPatch_process *proc, BPatch_thread *thread); // Callback to respond to signals. void signal_callback(int signal); }; #endif // MUTATOR_H /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stapdyn/stapdyn.8000066400000000000000000000072311217430427200166510ustar00rootroot00000000000000.\" -*- nroff -*- .TH STAPDYN 8 .SH NAME stapdyn \- systemtap dyninst runtime .SH SYNOPSIS .br .B stapdyn [ .I OPTIONS ] .I MODULE [ .I MODULE-OPTIONS ] .SH DESCRIPTION The .I stapdyn program is the dyninst back-end of the Systemtap tool. It expects a shared library produced by the front-end .I stap tool, when run with .IR \-\-dyninst . .PP Splitting the systemtap tool into a front-end and a back-end allows a user to compile a systemtap script on a development machine that has the debugging information (need to compile the script) and then transfer the resulting shared objevct to a production machine that doesn't have any development tools or debugging information installed. .PP Please refer to stappaths (7) for the version number, or run rpm \-q systemtap (fedora/red hat) apt\-get \-v systemtap (ubuntu) .SH OPTIONS The .I stapdyn program supports the following options. Any other option prints a list of supported options. .TP .B \-v Verbose mode. .TP .B \-V Print version number and exit. .TP .B \-w Suppress warnings from the script. .TP .B \-c CMD Command CMD will be run and the .I stapdyn program will exit when CMD does. The '_stp_target' variable will contain the pid for CMD. .TP .B \-x PID The '_stp_target' variable will be set to PID. .TP .B \-o FILE Send output to FILE. If the module uses bulk mode, the output will be in percpu files FILE_x(FILE_cpux in background and bulk mode) where 'x' is the cpu number. This supports strftime(3) formats for FILE. .TP .B \-C WHEN Control coloring of error messages. WHEN must be either .nh "never", "always", or "auto" .hy (i.e. enable only if at a terminal). If the option is missing, then "auto" is assumed. Colors can be modified using the SYSTEMTAP_COLORS environment variable. See the .IR stap (1) manual page for more information on syntax and behaviour. .TP .B var1=val Sets the value of global variable var1 to val. Global variables contained within a script are treated as options and can be set from the stapdyn command line. .SH ARGUMENTS .B MODULE is either a module path or a module name. If it is a module name, the module will be looked for in the following directory (where 'VERSION' is the output of "uname \-r"): .IP /lib/modules/VERSION/systemtap .PP \& $ stap \-\-dyninst \-p4 \-m mod1 \-e\ \[aq]global var1="foo"; probe begin{printf("%s\\n", var1); exit()}\[aq] .br .PP Running this with an additional module argument: .PP \& $ stapdyn mod1.so var1="HelloWorld" .br \& HelloWorld .PP Spaces and exclamation marks currently cannot be passed into global variables this way. .SH EXAMPLES See the .IR stapex (3stap) manual page for a collection of sample scripts. .PP Here is a very basic example of how to use .I stapdyn. First, use .I stap to compile a script. The .I stap program will report the pathname to the resulting module. .PP \& $ stap \-\-dyninst \-p4 \-e \[aq]probe begin { printf("Hello World!\\n"); exit() }\[aq] .br \& /home/user/.systemtap/cache/85/stap_8553d83f78c_265.so .PP Run .I stapdyn with the pathname to the module as an argument. .PP \& $ stapdyn /home/user/.systemtap/cache/85/stap_8553d83f78c_265.so .br \& Hello World! .SH SAFETY AND SECURITY Systemtap, in DynInst mode, is a developer tool, and runs completely unprivileged. The Linux kernel will only permit one's own processes to be accessed, which is enforced by the .IR ptrace (2) system call. See the .IR stap (1) manual page for additional information on safety and security. .SH SEE ALSO .IR stap (1), .IR stapprobes (3stap), .IR stap\-server (8), .IR staprun (8), .IR stapex (3stap) .SH BUGS Use the Bugzilla link of the project web page or our mailing list. .nh .BR http://sourceware.org/systemtap/ ", " . .hy systemtap-2.3/stapdyn/stapdyn.cxx000066400000000000000000000105221217430427200173010ustar00rootroot00000000000000// stapdyn main program // Copyright (C) 2012-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include #include extern "C" { #include #include #include #include #include #include #include } #include "config.h" #include "../git_version.h" #include "../version.h" #include "mutator.h" #include "dynutil.h" #define _STRINGIFY(s) #s #define STRINGIFY(s) _STRINGIFY(s) #define DYNINST_FULL_VERSION \ ( STRINGIFY(DYNINST_MAJOR) "." \ STRINGIFY(DYNINST_MINOR) "." \ STRINGIFY(DYNINST_SUBMINOR) ) using namespace std; // Print the obligatory usage message. static void __attribute__ ((noreturn)) usage (int rc) { clog << "Usage: " << program_invocation_short_name << " MODULE [-v] [-c CMD | -x PID] [-o FILE] [-C WHEN] [globalname=value ...]" << endl << "-v Increase verbosity." << endl << "-c cmd Command \'cmd\' will be run and " << program_invocation_short_name << " will" << endl << " exit when it does. The '_stp_target' variable" << endl << " will contain the pid for the command." << endl << "-x pid Sets the '_stp_target' variable to pid." << endl << "-o FILE Send output to FILE. This supports strftime(3)" << endl << " formats for FILE." << endl << "-C WHEN Enable colored errors. WHEN must be either 'auto'," << endl << " 'never', or 'always'. Set to 'auto' by default." << endl; exit (rc); } // This is main, the heart and soul of stapdyn, oh yeah! int main(int argc, char * const argv[]) { pid_t pid = 0; const char* command = NULL; const char* module = NULL; // Check if error/warning msgs should be colored color_errors = isatty(STDERR_FILENO) && strcmp(getenv("TERM") ?: "notdumb", "dumb"); // First, option parsing. int opt; while ((opt = getopt (argc, argv, "c:x:vwo:VC:")) != -1) { switch (opt) { case 'c': command = optarg; break; case 'x': pid = atoi(optarg); break; case 'v': ++stapdyn_log_level; break; case 'w': stapdyn_suppress_warnings = true; break; case 'o': stapdyn_outfile_name = optarg; break; case 'V': fprintf(stderr, "Systemtap Dyninst loader/runner (version %s/%s, %s)\n" "Copyright (C) 2012-2013 Red Hat, Inc. and others\n" "This is free software; see the source for copying conditions.\n", VERSION, DYNINST_FULL_VERSION, STAP_EXTENDED_VERSION); return 0; case 'C': if (!strcmp(optarg, "never")) color_errors = false; else if (!strcmp(optarg, "auto")) color_errors = isatty(STDERR_FILENO) && strcmp(getenv("TERM") ?: "notdumb", "dumb"); else if (!strcmp(optarg, "always")) color_errors = true; else { staperror() << "Invalid option '" << optarg << "' for -C." << endl; usage (1); } break; default: usage (1); } } // The first non-option is our stap module, required. if (optind < argc) module = argv[optind++]; // Remaining non-options, if any, specify global variables. vector modoptions; while (optind < argc) { modoptions.push_back(string(argv[optind++])); } if (!module || (command && pid)) usage (1); // Make sure that environment variables and selinux are set ok. if (!check_dyninst_rt()) return 1; if (!check_dyninst_sebools(pid != 0)) return 1; auto_ptr session(new mutator(module, modoptions)); if (!session.get() || !session->load()) { staperror() << "Failed to create the mutator!" << endl; return 1; } if (command && !session->create_process(command)) return 1; if (pid && !session->attach_process(pid)) return 1; if (!session->run()) return 1; return session->exit_status(); } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/staplog.c000066400000000000000000000344451217430427200152400ustar00rootroot00000000000000/* crash shared object for retrieving systemtap buffer Copyright (c) 2007, Hitachi, Ltd., Copyright (C) 2009-2011, Red Hat Inc. Created by Satoru Moriya Updated by Masami Hiramatsu 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, see . */ /* crash/defs.h defines NR_CPUS based upon architecture macros X86, X86_64, etc. See crash/configure.c (!). */ #if defined(__alpha__) #define ALPHA #elif defined(__x86_64__) #define X86_64 #elif defined(__i386__) #define X86 #elif defined(__powerpc64__) #define PPC64 #elif defined(__powerpc__) #define PPC #elif defined(__ia64__) #define IA64 #elif defined(__s390x__) #define S390X #elif defined(__s390__) #define S390 #elif defined(__arm__) #define ARM #else #warn "unknown architecture for crash/staplog support" #endif #include struct rchan_offsets { long subbuf_size; long n_subbufs; long buf; long buf_start; long buf_offset; long buf_subbufs_produced; long buf_padding; }; struct fake_rchan_buf { void *start; size_t offset; size_t subbufs_produced; size_t *padding; }; struct fake_rchan { size_t subbuf_size; size_t n_subbufs; }; struct per_cpu_data { struct fake_rchan_buf buf; }; static struct rchan_offsets rchan_offsets; static struct fake_rchan chan; static struct per_cpu_data per_cpu[NR_CPUS]; static FILE *outfp = NULL; static char *subbuf = NULL; static int is_global = 0; static int old_format = 0; static int retrieve_all = 0; void cmd_staplog(void); void cmd_staplog_cleanup(void); char *help_staplog[]; char *help_staplog_cleanup[]; static struct command_table_entry command_table[] = { {"staplog", cmd_staplog, help_staplog, 0}, {"staplog_cleanup", cmd_staplog_cleanup, help_staplog_cleanup, CLEANUP}, {NULL, NULL, NULL, 0}, }; static void get_rchan_offsets(void) { rchan_offsets.subbuf_size = MEMBER_OFFSET("rchan", "subbuf_size"); if (rchan_offsets.subbuf_size < 0) goto ERR; rchan_offsets.n_subbufs = MEMBER_OFFSET("rchan", "n_subbufs"); if (rchan_offsets.n_subbufs < 0) goto ERR; rchan_offsets.buf = MEMBER_OFFSET("rchan", "buf"); if (rchan_offsets.buf < 0) goto ERR; rchan_offsets.buf_start = MEMBER_OFFSET("rchan_buf", "start"); if (rchan_offsets.buf_start < 0) goto ERR; rchan_offsets.buf_offset = MEMBER_OFFSET("rchan_buf", "offset"); if (rchan_offsets.buf_offset < 0) goto ERR; rchan_offsets.buf_subbufs_produced = MEMBER_OFFSET("rchan_buf", "subbufs_produced"); if (rchan_offsets.buf_subbufs_produced < 0) goto ERR; rchan_offsets.buf_padding = MEMBER_OFFSET("rchan_buf", "padding"); if (rchan_offsets.buf_padding < 0) goto ERR; return; ERR: error(FATAL, "cannot get rchan offset\n"); } /* * Here's a description of 'readmem()' from crash: * * ==== * readmem() is by far *the* workhorse of this whole program. It * reads memory from /dev/kmem, /dev/mem the dumpfile or /proc/kcore, * whichever is appropriate: * * addr a user, kernel or physical memory address. * memtype addr type: UVADDR, KVADDR, PHYSADDR, XENMACHADDR or * FILEADDR * buffer supplied buffer to read the data into. * size number of bytes to read. * type string describing the request -- helpful when the * read fails. * error_handle what to do if the read fails: FAULT_ON_ERROR kills * the command immediately; RETURN_ON_ERROR returns * FALSE; QUIET suppresses the error message. * ==== */ static ulong get_rchan(ulong rchan_addr) { ulong rchan; readmem(rchan_addr, KVADDR, &rchan, sizeof(void*), "rchan", FAULT_ON_ERROR); if (old_format == 1) { readmem(rchan + rchan_offsets.subbuf_size, KVADDR, &chan.subbuf_size, sizeof(unsigned), "rchan.subbuf_size", FAULT_ON_ERROR); readmem(rchan + rchan_offsets.n_subbufs, KVADDR, &chan.n_subbufs, sizeof(unsigned), "rchan.n_subbufs", FAULT_ON_ERROR); } else { readmem(rchan + rchan_offsets.subbuf_size, KVADDR, &chan.subbuf_size, sizeof(size_t), "rchan.subbuf_size", FAULT_ON_ERROR); readmem(rchan + rchan_offsets.n_subbufs, KVADDR, &chan.n_subbufs, sizeof(size_t), "rchan.n_subbufs", FAULT_ON_ERROR); } return rchan; } static void get_rchan_buf(int cpu, ulong rchan) { ulong rchan_buf; struct per_cpu_data *pcd; pcd = &per_cpu[cpu]; readmem(rchan + rchan_offsets.buf + sizeof(void*) * cpu, KVADDR, &rchan_buf, sizeof(void*), "rchan.buf", FAULT_ON_ERROR); readmem(rchan_buf + rchan_offsets.buf_start, KVADDR, &pcd->buf.start, sizeof(void*), "rchan.buf.start", FAULT_ON_ERROR); if (old_format == 1) { readmem(rchan_buf + rchan_offsets.buf_offset, KVADDR, &pcd->buf.offset, sizeof(unsigned), "rchan.buf.offset", FAULT_ON_ERROR); readmem(rchan_buf + rchan_offsets.buf_subbufs_produced, KVADDR, &pcd->buf.subbufs_produced, sizeof(int32_t), "rchan.buf.subbufs_produced", FAULT_ON_ERROR); readmem(rchan_buf + rchan_offsets.buf_padding, KVADDR, &pcd->buf.padding, sizeof(unsigned*), "rchan.buf.padding", FAULT_ON_ERROR); } else { readmem(rchan_buf + rchan_offsets.buf_offset, KVADDR, &pcd->buf.offset, sizeof(size_t), "rchan.buf.offset", FAULT_ON_ERROR); readmem(rchan_buf + rchan_offsets.buf_subbufs_produced, KVADDR, &pcd->buf.subbufs_produced, sizeof(size_t), "rchan.buf.subbufs_produced", FAULT_ON_ERROR); readmem(rchan_buf + rchan_offsets.buf_padding, KVADDR, &pcd->buf.padding, sizeof(size_t*), "rchan.buf.padding", FAULT_ON_ERROR); } return; } static ulong get_rchan_addr(ulong stp_relay_data) { long offset; /* * If we can get the member offset of struct * stp_relay_data.flushing, we'll assume this is a system * using STP_TRANSPORT_VERSION 1. Note that this will fail if * the debuginfo of the trace module isn't available. */ if ((offset = MEMBER_OFFSET("_stp_relay_data_type", "flushing")) > 0) { old_format = 1; } /* * If we can't get the member offset of struct * stp_relay_data.rchan, i.e. the debuginfo of the trace * module isn't available, we use 0 as the offset * instead. Currently struct _stp_relay_data_type is defined * as below: * * struct _stp_relay_data_type { * struct rchan *rchan; * ... * } * * If the definision of struct _stp_relay_data_type changes, * we must check if this code is correct. */ if ((offset = MEMBER_OFFSET("_stp_relay_data_type", "rchan")) < 0) { error(WARNING, "The debuginfo of the trace module hasn't been loaded.\n" "You may not be able to retrieve the correct trace data.\n"); offset = 0; } return (stp_relay_data + (ulong)offset); } static int check_global_buffer(ulong rchan) { int cpu; ulong rchan_buf[2]; for (cpu = 0; cpu < 2; cpu++) { readmem(rchan + rchan_offsets.buf + sizeof(void*) * cpu, KVADDR, &rchan_buf[cpu], sizeof(void*), "rchan.buf", FAULT_ON_ERROR); } if (rchan_buf[0] == rchan_buf[1]) return 1; return 0; } static void setup_global_data(char *module) { int i; ulong stp_relay_data = 0; ulong stp_rchan_addr = 0; ulong rchan; stp_relay_data = symbol_value_module("_stp_relay_data", module); if (stp_relay_data == 0) { error(FATAL, "Failed to find _stp_relay_data in module '%s'.\n", module); } stp_rchan_addr = get_rchan_addr(stp_relay_data); if (stp_rchan_addr == 0) { error(FATAL, "Failed to find '_stp_relay_data' in module '%s'.\n", module); } rchan = get_rchan(stp_rchan_addr); for (i = 0; i < kt->cpus; i++) get_rchan_buf(i, rchan); if (kt->cpus > 1) { is_global = check_global_buffer(rchan); } return; } static void create_output_filename(char *buf, int len, int cpu) { if (is_global) { snprintf(buf, len, "global"); } else { snprintf(buf, len, "cpu%d", cpu); } } static void create_output_dir(const char *dirname) { DIR *dir; dir = opendir(dirname); if (dir) { closedir(dir); } else { if (mkdir(dirname, S_IRWXU) < 0) { error(FATAL, "cannot create log directory '%s\n'", dirname); } } } static FILE *open_output_file(const char *dname, const char *fname) { FILE *filp = NULL; char *output_file; output_file = GETBUF(sizeof(char) * (strlen(dname) + strlen(fname) + 2)); if (output_file == NULL) { error(FATAL, "cannot allocate memory for logfile name '%s%s'\n", dname, fname); } create_output_dir(dname); sprintf(output_file,"%s/%s", dname, fname); filp = fopen(output_file, "w"); if (!filp) { error(FATAL, "cannot create log file '%s'\n", output_file); } FREEBUF(output_file); return filp; } #define MAX_FNAME 128 static void output_cpu_logs(char *dirname) { int i; struct per_cpu_data *pcd; size_t n, idx, start, end, len; size_t padding; char *source, fname[MAX_FNAME + 1]; /* allocate subbuf memory */ subbuf = GETBUF(chan.subbuf_size); if (!subbuf) { error(FATAL, "cannot allocate memory\n"); } for (i = 0; i < kt->cpus; i++) { pcd = &per_cpu[i]; if (pcd->buf.subbufs_produced == 0 && pcd->buf.offset == 0) { if (is_global == 1) { error(WARNING, "There is no data in the relay buffer.\n"); break; } else { error(WARNING, "[cpu:%d]There is no data in the relay buffer.\n", i); continue; } } end = pcd->buf.subbufs_produced + 1; if (pcd->buf.subbufs_produced >= chan.n_subbufs) { start = end - chan.n_subbufs; } else { start = 0; } create_output_filename(fname, MAX_FNAME, i); fprintf(fp, "--- generating '%s/%s' ---\n", dirname, fname); fprintf(fp, " subbufs ready on relayfs:%ld\n", (long)end); fprintf(fp, " n_subbufs:%ld, read subbuf from:%ld(%ld) " "to:%ld(%ld) (offset:0-%ld)\n\n", (long)chan.n_subbufs, (long)start, (long)(start % chan.n_subbufs), (long)end-1, (long)((end-1) % chan.n_subbufs), (long) pcd->buf.offset); outfp = open_output_file(dirname, fname); for (n = start; n < end; n++) { /* read relayfs subbufs and write to log file */ idx = n % chan.n_subbufs; source = pcd->buf.start + idx * chan.subbuf_size; if (old_format == 1) { readmem((ulong)pcd->buf.padding + sizeof(unsigned) * idx, KVADDR, &padding, sizeof(unsigned), "padding", FAULT_ON_ERROR); } else { readmem((ulong)pcd->buf.padding + sizeof(padding) * idx, KVADDR, &padding, sizeof(padding), "padding", FAULT_ON_ERROR); } if (n == end - 1) { len = pcd->buf.offset; } else { len = chan.subbuf_size; } if (old_format == 1) { source += sizeof(unsigned int); len -= sizeof(unsigned int) + padding; } else { len -= padding; } if (len > 0) { readmem((ulong)source, KVADDR, subbuf, len, "subbuf", FAULT_ON_ERROR); if (fwrite(subbuf, len, 1, outfp) != 1) { error(FATAL, "cannot write log data\n"); } } } fclose(outfp); outfp = NULL; /* * -a option retrieve the old data of subbuffer where the * probe record is written at that time. */ if (retrieve_all == 1 && start != 0) { strncat(fname, ".may_broken", MAX_FNAME); fprintf(fp, "--- generating '%s/%s' ---\n", dirname, fname); fprintf(fp, " read subbuf %ld(%ld) (offset:%ld-%ld)\n", (long)start-1, (long)((start-1) % chan.n_subbufs), (long)pcd->buf.offset, (long)chan.subbuf_size); outfp = open_output_file(dirname, fname); idx = (start - 1) % chan.n_subbufs; source = pcd->buf.start + idx * chan.subbuf_size + pcd->buf.offset; len = chan.subbuf_size - pcd->buf.offset; if (len) { readmem((ulong)source, KVADDR, subbuf, len, "may_broken_subbuf", FAULT_ON_ERROR); if (fwrite(subbuf, len, 1, outfp) != 1) { error(FATAL, "cannot write log data(may_broken)\n"); } } fclose(outfp); outfp = NULL; } if (is_global == 1) break; } if (subbuf) { FREEBUF(subbuf); subbuf = NULL; } return; } void cmd_staplog(void) { int c; char *module = NULL; char *dirname = NULL; while ((c = getopt(argcnt, args, "+ao:")) != EOF) { switch (c) { case 'a': retrieve_all = 1; break; case 'o': dirname = optarg; break; default: argerrs++; break; } } module = args[optind]; if (!module || argerrs) cmd_usage(pc->curcmd, SYNOPSIS); if (dirname == NULL && module != NULL) dirname = module; setup_global_data(module); assert(dirname); output_cpu_logs(dirname); return; } void cmd_staplog_cleanup(void) { if (outfp) { fclose(outfp); outfp = NULL; } return; } char *help_staplog[] = { "systemtaplog", "Retrieve SystemTap log data", "[-a] [-o dir_name] module_name", " Retrieve SystemTap's log data and write them to files.\n", " All valid SystemTap's log data made by the trace module which name", " is 'module_name' are written into log files. This command starts", " to retrieve log data from the subbuffer which is next to current", " written subbuffer. Therefore some old data in the current written", " subbuffer may not be retrieved. But -a option retrieves these data", " and write them into another log file which have the special ", " postfix `.may_broken`.", " If you don't use -o option, the log files are created in", " `module_name` directory. The name of each log file is cpu0, cpu1..", " ...cpuN. This command doesn't change the log data format, but remove", " only padding.", "", " -a Retrieve the old data which is recorded in", " current written subbuffer and create another files", " which have the special postfix `.may_broken`", " for these data.", " -o file_name Specify the output directory.", NULL, }; char *help_staplog_cleanup[] = { "systemtaplog cleanup (hidden)", "Cleanup command for staplog", "", " This command is called during restore_sanity() prior to each ", " command prompt to close the files which was opened and failed to", " close by staplog command.", NULL, }; static void __attribute__ ((constructor)) _init(void) { get_rchan_offsets(); register_extension(command_table); return; } static void __attribute__ ((destructor)) _fini(void) { return; } systemtap-2.3/stapregex-dfa.cxx000066400000000000000000000507351217430427200167010ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2012-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // --- // // This file incorporates code from the re2c project; please see // the file README.stapregex for details. #include #include #include #include #include #include #include #include #include #include "translator-output.h" #include "stapregex-parse.h" #include "stapregex-tree.h" #include "stapregex-dfa.h" // Uncomment to show result of ins (NFA) compilation: //#define STAPREGEX_DEBUG_INS // Uncomment to display result of DFA compilation in a compact format: //#define STAPREGEX_DEBUG_DFA // Uncomment to have the generated engine do a trace of visited states: //#define STAPREGEX_DEBUG_MATCH using namespace std; namespace stapregex { regexp *pad_re = NULL; regexp *fail_re = NULL; dfa * stapregex_compile (regexp *re, const std::string& match_snippet, const std::string& fail_snippet) { if (pad_re == NULL) { // build regexp for ".*" pad_re = make_dot (); pad_re = new close_op (pad_re, true); // -- prefer shorter match pad_re = new alt_op (pad_re, new null_op, true); // -- prefer second match } if (fail_re == NULL) { // build regexp for ".*$", but allow '\0' and support fail outcome fail_re = make_dot (true); // -- allow '\0' fail_re = new close_op (fail_re, true); // -- prefer shorter match fail_re = new alt_op (fail_re, new null_op, true); // -- prefer second match fail_re = new cat_op (fail_re, new anchor_op('$')); fail_re = new rule_op(fail_re, 0); // XXX: this approach creates one extra spurious-but-safe state // (safe because the matching procedure stops after encountering '\0') } vector outcomes(2); outcomes[0] = fail_snippet; outcomes[1] = match_snippet; int num_tags = re->num_tags; // Pad & wrap re in appropriate rule_ops to control match behaviour: bool anchored = re->anchored (); if (!anchored) re = new cat_op(pad_re, re); // -- left-padding re = new rule_op(re, 1); re = new alt_op(re, fail_re); #ifdef STAPREGEX_DEBUG_INS cerr << "RESULTING INS FROM REGEX " << re << ":" << endl; #endif ins *i = re->compile(); #ifdef STAPREGEX_DEBUG_INS for (const ins *j = i; (j - i) < re->ins_size() + 1; ) { j = show_ins(cerr, j, i); cerr << endl; } cerr << endl; #endif // TODOXXX optimize ins as in re2c dfa *d = new dfa(i, num_tags, outcomes); // Carefully deallocate temporary scaffolding: if (!anchored) delete ((rule_op*) ((alt_op*) re)->a)->re; // -- new cat_op delete ((alt_op*) re)->a; // -- new rule_op delete re; // -- new alt_op // NB: deleting a regular expression DOES NOT deallocate its // children. The original re parameter is presumed to be retained // indefinitely as part of a stapdfa table, or such.... return d; } // ------------------------------------------------------------------------ /* Now follows the heart of the tagged-DFA algorithm. This is a basic implementation of the algorithm described in Ville Laurikari's Masters thesis and summarized in the paper "NFAs with Tagged Transitions, their Conversion to Deterministic Automata and Application to Regular Expressions" (http://laurikari.net/ville/spire2000-tnfa.pdf). TODOXXX: The following does not contain a fully working implementation of the tagging support, but only of the regex matching. HERE BE DRAGONS (and not the friendly kind) */ /* Functions to deal with relative transition priorities: */ arc_priority refine_higher(const arc_priority& a) { return make_pair(2 * a.first + 1, a.second + 1); } arc_priority refine_lower (const arc_priority& a) { return make_pair(2 * a.first, a.second + 1); } int arc_compare (const arc_priority& a, const arc_priority& b) { unsigned long x = a.first; unsigned long y = b.first; if (a.second > b.second) x = x << (a.second - b.second); else if (a.second < b.second) y = y << (b.second - a.second); return ( x == y ? 0 : x < y ? -1 : 1 ); } /* Manage the linked list of states in a DFA: */ state::state (state_kernel *kernel) : next(NULL), kernel(kernel), accepts(false), accept_outcome(0) {} state * dfa::add_state (state *s) { s->label = nstates++; if (last == NULL) { last = s; first = last; } else { // append to the end last->next = s; last = last->next; } return last; } /* Operations to build a simple kernel prior to taking closure: */ void add_kernel (state_kernel *kernel, ins *i) { kernel_point point; point.i = i; point.priority = make_pair(0,0); // NB: point->map_items is empty kernel->push_back(point); } state_kernel * make_kernel (ins *i) { state_kernel *kernel = new state_kernel; add_kernel (kernel, i); return kernel; } /* Compute the set of kernel_points that are 'tag-wise unambiguously reachable' from a given initial set of points. Absent tagging, this becomes a bog-standard NFA e_closure construction. */ state_kernel * te_closure (state_kernel *start, int ntags, bool is_initial = false) { state_kernel *closure = new state_kernel(*start); queue worklist; /* To avoid searching through closure incessantly when retrieving information about existing elements, the following caches are needed: */ vector max_tags (ntags, 0); map > closure_map; /* Reset priorities and cache initial elements of closure: */ for (state_kernel::iterator it = closure->begin(); it != closure->end(); it++) { it->priority = make_pair(0,0); worklist.push(*it); // Store the element in relevant caches: for (list::const_iterator jt = it->map_items.begin(); jt != it->map_items.end(); jt++) max_tags[jt->first] = max(jt->second, max_tags[jt->first]); closure_map[it->i].push_back(*it); } while (!worklist.empty()) { kernel_point point = worklist.front(); worklist.pop(); // Identify e-transitions depending on the opcode. // There are at most two e-transitions emerging from an insn. // If we have two e-transitions, the 'other' has higher priority. ins *target = NULL; int tag = -1; ins *other_target = NULL; int other_tag = -1; // TODOXXX line-by-line proceeds below bool do_split = false; if (point.i->i.tag == TAG) { target = &point.i[1]; tag = (int) point.i->i.param; } else if (point.i->i.tag == FORK && point.i == (ins *) point.i->i.link) { /* Workaround for a FORK that points to itself: */ target = &point.i[1]; } else if (point.i->i.tag == FORK) { do_split = true; // Relative priority of two e-transitions depends on param: if (point.i->i.param) { // Prefer jumping to link. target = &point.i[1]; other_target = (ins *) point.i->i.link; } else { // Prefer stepping to next instruction. target = (ins *) point.i->i.link; other_target = &point.i[1]; } } else if (point.i->i.tag == GOTO) { target = (ins *) point.i->i.link; } else if (point.i->i.tag == INIT && is_initial) { target = &point.i[1]; } bool already_found; // Data for the endpoint of the first transition: kernel_point next; next.i = target; next.priority = do_split ? refine_lower(point.priority) : point.priority; next.map_items = point.map_items; // Date for the endpoint of the second transition: kernel_point other_next; other_next.i = other_target; other_next.priority = do_split ? refine_higher(point.priority) : point.priority; other_next.map_items = point.map_items; // Do infinite-loop-check: other_next.parents = point.parents; if (point.parents.find(other_next.i) != point.parents.end()) { other_target = NULL; other_tag = -1; } other_next.parents.insert(other_next.i); next.parents = point.parents; if (point.parents.find(next.i) != point.parents.end()) { target = NULL; tag = -1; goto next_target; } next.parents.insert(next.i); another_transition: if (target == NULL) continue; // Deal with the current e-transition: if (tag >= 0) { /* Delete all existing next.map_items of the form m[tag,x]. */ for (list::iterator it = next.map_items.begin(); it != next.map_items.end(); it++) if (it->first == (unsigned) tag) next.map_items.erase (it); /* Add m[tag,x] to next.map_items, where x is the smallest nonnegative integer such that m[tag,x] does not occur anywhere in closure. Then update the cache. */ unsigned x = max_tags[tag]; next.map_items.push_back(make_pair(tag, ++x)); max_tags[tag] = x; } already_found = false; /* Deal with similar transitions that have a different priority. */ for (list::iterator it = closure_map[next.i].begin(); it != closure_map[next.i].end(); ) { int result = arc_compare(it->priority, next.priority); if (result > 0) { // obnoxious shuffle to avoid iterator invalidation list::iterator old_it = it; it++; closure_map[next.i].erase(old_it); continue; } else if (result == 0) { already_found = true; } it++; } if (!already_found) { // Store the element in relevant caches: closure_map[next.i].push_back(next); for (list::iterator jt = next.map_items.begin(); jt != next.map_items.end(); jt++) max_tags[jt->first] = max(jt->second, max_tags[jt->first]); // Store the element in closure: closure->push_back(next); worklist.push(next); } next_target: // Now move to dealing with the second e-transition, if any. target = other_target; other_target = NULL; tag = other_tag; other_tag = -1; next = other_next; goto another_transition; } return closure; } /* Find the set of reordering commands (if any) that will get us from state s to some existing state in the dfa (returns the state in question, appends reordering commands to r). Returns NULL is no suitable state is found. */ state * dfa::find_equivalent (state *s, tdfa_action &r) { state *answer = NULL; for (state_kernel::iterator it = s->kernel->begin(); it != s->kernel->end(); it++) mark(it->i); /* Check kernels of existing states for size equivalence and for unmarked items (similar to re2c's original algorithm): */ unsigned n = s->kernel->size(); for (state *t = first; t != NULL; t = t->next) { if (t->kernel->size() == n) { for (state_kernel::iterator it = t->kernel->begin(); it != t->kernel->end(); it++) if (!marked(it->i)) goto next_state; // TODOXXX check for existence of reordering r answer = t; goto cleanup; } next_state: ; } cleanup: for (state_kernel::iterator it = s->kernel->begin(); it != s->kernel->end(); it++) unmark(it->i); return answer; } dfa::dfa (ins *i, int ntags, vector& outcome_snippets) : orig_nfa(i), nstates(0), ntags(ntags), outcome_snippets(outcome_snippets) { /* Initialize empty linked list of states: */ first = last = NULL; ins *start = &i[0]; state_kernel *initial_kernel = te_closure(make_kernel(start), ntags, true); state *initial = add_state(new state(initial_kernel)); queue worklist; worklist.push(initial); while (!worklist.empty()) { state *curr = worklist.front(); worklist.pop(); vector > edges(NUM_REAL_CHARS); /* Using the CHAR instructions in kernel, build the initial table of spans for curr. Also check for final states. */ for (list::iterator it = curr->kernel->begin(); it != curr->kernel->end(); it++) { if (it->i->i.tag == CHAR) { for (ins *j = &it->i[1]; j < (ins *) it->i->i.link; j++) edges[j->c.value].push_back((ins *) it->i->i.link); } else if (it->i->i.tag == ACCEPT) { /* Always prefer the highest numbered outcome: */ curr->accepts = true; curr->accept_outcome = max(it->i->i.param, curr->accept_outcome); } } for (unsigned c = 0; c < NUM_REAL_CHARS; ) { list e = edges[c]; assert (!e.empty()); // XXX: ensured by fail_re in stapregex_compile span s; s.lb = c; while (++c < NUM_REAL_CHARS && edges[c] == e) ; s.ub = c - 1; s.reach_pairs = new state_kernel; for (list::iterator it = e.begin(); it != e.end(); it++) add_kernel (s.reach_pairs, *it); curr->spans.push_back(s); } /* For each of the spans in curr, determine the reachable points assuming a character in the span. */ for (list::iterator it = curr->spans.begin(); it != curr->spans.end(); it++) { state_kernel *reach_pairs = it->reach_pairs; /* Set up candidate target state: */ state_kernel *u_pairs = te_closure(reach_pairs, ntags); state *target = new state(u_pairs); tdfa_action c; /* Generate position-save commands for any map items that do not appear in curr->kernel: */ set all_items; for (state_kernel::const_iterator jt = curr->kernel->begin(); jt != curr->kernel->end(); jt++) for (list::const_iterator kt = jt->map_items.begin(); kt != jt->map_items.end(); jt++) all_items.insert(*kt); list store_items; for (state_kernel::const_iterator jt = u_pairs->begin(); jt != u_pairs->end(); jt++) for (list::const_iterator kt = jt->map_items.begin(); kt != jt->map_items.end(); kt++) if (all_items.find(*kt) == all_items.end()) store_items.push_back(*kt); for (list::iterator jt = store_items.begin(); jt != store_items.end(); jt++) { // append m[i,n] <- to c tdfa_insn insn; insn.to = *jt; insn.save_pos = true; c.push_back(insn); } /* If there is a state t_prime in states such that some sequence of reordering commands r produces t_prime from target, use t_prime as the target state, appending the reordering commands to c. */ state *t_prime = find_equivalent(target, c); if (t_prime != NULL) { delete target; } else { /* We need to actually add target to the dfa: */ t_prime = target; add_state(t_prime); worklist.push(t_prime); if (t_prime->accepts) { // TODOXXX set the finisher of t_prime } } /* Set the transition: */ it->to = t_prime; it->action = c; } } } dfa::~dfa () { state * s; while ((s = first)) { first = s->next; delete s; } delete orig_nfa; } // ------------------------------------------------------------------------ // TODOXXX add emission instructions for tag_ops void span::emit_jump (translator_output *o, const dfa *d) const { #ifdef STAPREGEX_DEBUG_MATCH o->newline () << "printf(\" --> GOTO yystate%d\\n\", " << to->label << ");"; #endif // TODOXXX tags feature allows proper longest-match priority if (to->accepts) { emit_final(o, d); } else { o->newline () << "YYCURSOR++;"; o->newline () << "goto yystate" << to->label << ";"; } } /* Assuming the target DFA of the span is a final state, emit code to (TODOXXX) cleanup tags and exit with a final answer. */ void span::emit_final (translator_output *o, const dfa *d) const { assert (to->accepts); // XXX: must guarantee correct usage of emit_final() o->newline() << d->outcome_snippets[to->accept_outcome]; o->newline() << "goto yyfinish;"; } string c_char(char c) { stringstream o; o << "'"; print_escaped(o, c); o << "'"; return o.str(); } void state::emit (translator_output *o, const dfa *d) const { o->newline() << "yystate" << label << ": "; #ifdef STAPREGEX_DEBUG_MATCH o->newline () << "printf(\"READ '%s' %c\", cur, *YYCURSOR);"; #endif o->newline() << "switch (*YYCURSOR) {"; o->indent(1); for (list::const_iterator it = spans.begin(); it != spans.end(); it++) { // If we see a '\0', go immediately into an accept state: if (it->lb == '\0') { o->newline() << "case " << c_char('\0') << ":"; it->emit_final(o, d); // TODOXXX extra function may be unneeded } // Emit labels to handle all the other elements of the span: for (unsigned c = max('\1', it->lb); c <= (unsigned) it->ub; c++) { o->newline() << "case " << c_char((char) c) << ":"; } it->emit_jump(o, d); // TODOXXX handle a 'default' set of characters for the largest span... // TODOXXX optimize by accepting before end of string whenever possible... (also necessary for proper first-matched-substring selection) } o->newline(-1) << "}"; } void dfa::emit (translator_output *o) const { #ifdef STAPREGEX_DEBUG_DFA print(o); #else o->newline() << "{"; o->newline(1); // XXX: workaround for empty regex if (first->accepts) { o->newline() << outcome_snippets[first->accept_outcome]; o->newline() << "goto yyfinish;"; } for (state *s = first; s; s = s->next) s->emit(o, this); o->newline() << "yyfinish: ;"; o->newline(-1) << "}"; #endif } void dfa::emit_tagsave (translator_output *o, std::string tag_states, std::string tag_vals, std::string tag_count) const { // TODOXXX implement after testing the preceding algorithms } // ------------------------------------------------------------------------ std::ostream& operator << (std::ostream &o, const tdfa_action& a) { for (list::const_iterator it = a.begin(); it != a.end(); it++) { if (it != a.begin()) o << "; "; o << "m[" << it->to.first << "," << it->to.second << "] <- "; if (it->save_pos) o << "p"; else o << "m[" << it->from.first << "," << it->from.second << "]"; } return o; } std::ostream& operator << (std::ostream &o, const arc_priority& p) { o << p.first << "/" << (1 << p.second); return o; } void state::print (translator_output *o) const { o->line() << "state " << label; if (accepts) o->line() << " accepts " << accept_outcome; if (!finalizer.empty()) o->line() << " [" << finalizer << "]"; o->indent(1); for (list::const_iterator it = spans.begin(); it != spans.end(); it++) { o->newline() << "'"; if (it->lb == it->ub) { print_escaped (o->line(), it->lb); o->line() << " "; } else { print_escaped (o->line(), it->lb); o->line() << "-"; print_escaped (o->line(), it->ub); } o->line() << "' -> " << it->to->label; if (!it->action.empty()) o->line() << " [" << it->action << "]"; } o->newline(-1); } void dfa::print (std::ostream& o) const { translator_output to(o); print(&to); } void dfa::print (translator_output *o) const { o->newline(); for (state *s = first; s; s = s->next) { s->print(o); o->newline(); } o->newline(); } std::ostream& operator << (std::ostream& o, const dfa& d) { d.print(o); return o; } std::ostream& operator << (std::ostream &o, const dfa *d) { o << *d; return o; } }; /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stapregex-dfa.h000066400000000000000000000122021217430427200163110ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2012-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // --- // // This file incorporates code from the re2c project; please see // the file README.stapregex for details. #ifndef STAPREGEX_DFA_H #define STAPREGEX_DFA_H #include #include #include #include #include #include #include struct translator_output; /* from translator-output.h */ namespace stapregex { struct regexp; /* from stapregex-tree.h */ union ins; /* from stapregex-tree.h */ struct dfa; struct state; /* Coordinates of a subexpression map item m[t,s]: */ typedef std::pair map_item; /* A tagged DFA transition can have a number of these instructions attached, which are able to assign the current position to specific map items, or to reorder the existing elements of the map: */ struct tdfa_insn { map_item to, from; bool save_pos; // -- if true, assign position; if false, copy from's value }; typedef std::list tdfa_action; std::ostream& operator << (std::ostream &o, const tdfa_action& a); /* The arc_priority data type is a cunning way to represent transition priorities, necessitated by the fact that we have FORK opcodes (two outgoing e-transitions) which can lead to further FORK opcodes, &c, requiring a binary-subdivision style of priority assignment: -> 3/4 ... and so forth / -> 1/2 --> 2/4 ... and so forth / / ---> 1/4 ... and so forth / / 0 ----> 0 ----> 0 ... and so forth Our trick is pretty much just to allocate the possible values of an unsigned long in binary-search fashion. XXX: For a 64-bit unsigned long type, this allows a chain of FORK opcodes around 64 units long (without intervening CHAR match insns), at which point things start to get funky. Be sure to keep an eye on whether this turns out to be enough in practice. */ typedef std::pair arc_priority; arc_priority refine_higher(const arc_priority& a); arc_priority refine_lower(const arc_priority& a); int arc_compare(const arc_priority& a, const arc_priority& b); std::ostream& operator << (std::ostream &o, const arc_priority& p); /* When constructing tagged DFA sets from ins, we need to keep track of a set of instructions together with further bookkeeping information (relative preference/priority, map items affected). */ struct kernel_point { ins *i; arc_priority priority; // -- used in tagged e-closure computation std::list map_items; std::set parents; // -- used for infinite-loop-detection }; typedef std::list state_kernel; /* Corresponds to a tagged-DFA transition arc, complete with subexpression map reordering and such. */ struct span { char lb, ub; // -- segment [lb, ub] state *to; tdfa_action action; state_kernel *reach_pairs; // -- for the subset-construction // -- algorithm void emit_jump (translator_output *o, const dfa *d) const; void emit_final (translator_output *o, const dfa *d) const; }; struct state { unsigned label; // -- index of state in dfa state *next; // -- store dfa states as a linked list state_kernel *kernel; // -- set of corresponding ins coordinates /* NB: our usage of the term 'kernel' differs from re2c's slightly -- there is no real need to distinguish NFA edges inside the state from outgoing edges, (XXX) as far as I am aware. */ bool accepts; // -- is this a final state? unsigned accept_outcome; tdfa_action finalizer; // -- run after accepting std::list spans; state (state_kernel *kernel); void emit (translator_output *o, const dfa *d) const; void print (translator_output *o) const; }; // ------------------------------------------------------------------------ struct dfa { ins *orig_nfa; state *first, *last; // -- store dfa states as a linked list unsigned nstates; // Infrastructure to deal with tagging: unsigned ntags; tdfa_action initializer; // -- run before entering start state std::vector outcome_snippets; dfa (ins *i, int ntags, std::vector& outcome_snippets); ~dfa (); void emit (translator_output *o) const; void emit_tagsave (translator_output *o, std::string tag_states, std::string tag_vals, std::string tag_count) const; void print (translator_output *o) const; void print (std::ostream& o) const; private: state *add_state (state* s); state *find_equivalent (state *s, tdfa_action &r); }; std::ostream& operator << (std::ostream &o, const dfa& d); std::ostream& operator << (std::ostream &o, const dfa* d); /* Produces a dfa that runs the specified code snippets based on match or fail outcomes for an unanchored (by default) match of re. */ dfa *stapregex_compile (regexp *re, const std::string& match_snippet, const std::string& fail_snippet); }; #endif /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stapregex-parse.cxx000066400000000000000000000401541217430427200172530ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2012-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // --- // // This file incorporates code from the re2c project; please see // the file README.stapregex for details. #include "util.h" #include "stapregex-tree.h" #include "stapregex-parse.h" #include #include #include using namespace std; namespace stapregex { // TODOXXX compress / eliminate / move to util // void prtChOrHex(std::ostream& o, unsigned c) // { // if (eFlag) // { // prtHex(o, c); // } // else if ((c < 256u) && (isprint(c) || isspace(c))) // { // prtCh(o, c); // } // else // { // prtHex(o, c); // } // } // void prtHex(std::ostream& o, unsigned c) // { // int oc = (int)(c); // if (re2c::uFlag) // { // o << "0x" // << hexCh(oc >> 28) // << hexCh(oc >> 24) // << hexCh(oc >> 20) // << hexCh(oc >> 16) // << hexCh(oc >> 12) // << hexCh(oc >> 8) // << hexCh(oc >> 4) // << hexCh(oc); // } // else if (re2c::wFlag) // { // o << "0x" // << hexCh(oc >> 12) // << hexCh(oc >> 8) // << hexCh(oc >> 4) // << hexCh(oc); // } // else // { // o << "0x" // << hexCh(oc >> 4) // << hexCh(oc); // } // } char octCh(unsigned c) { return '0' + c % 8; } void prtCh(std::ostream& o, unsigned c) { int oc = (int)(c); switch (oc) { case '\'': o << "\\'"; break; case '"': o << "\\\""; break; case '\n': o << "\\n"; break; case '\t': o << "\\t"; break; case '\v': o << "\\v"; break; case '\b': o << "\\b"; break; case '\r': o << "\\r"; break; case '\f': o << "\\f"; break; case '\a': o << "\\a"; break; case '\\': o << "\\\\"; break; default: if ((oc < 256) && isprint(oc)) { o << (char) oc; } else { o << '\\' << octCh(oc / 64) << octCh(oc / 8) << octCh(oc); } } } void print_escaped(std::ostream& o, char c) { prtCh(o, c); } // ------------------------------------------------------------------------ cursor::cursor() : input(NULL), pos(~0) {} cursor::cursor(const std::string *input, bool do_unescape) : input(input), do_unescape(do_unescape), pos(0) { next_c = 0; last_c = 0; finished = ( pos >= input->length() ); } char cursor::next () { if (! next_c && finished) throw regex_error(_("unexpected end of regex"), pos); if (! next_c) get_unescaped(); last_c = next_c; // advance by zeroing next_c next_c = 0; return last_c; } char cursor::peek () { if (! next_c && ! finished) get_unescaped(); // don't advance by zeroing next_c last_c = next_c; return next_c; } bool cursor::has (unsigned n) { return ( pos <= input->length() - n ); } /* Systemtap doesn't unescape string literals for us, presuming to pass the backslashes intact to a C compiler; hence we need to do our own unescaping here. This functionality needs to be handled as part of cursor, in order to correctly retain the original positions in the string when doing error reporting. */ void cursor::get_unescaped () { static const char *hex = "0123456789abcdef"; static const char *oct = "01234567"; last_pos = pos; char c = (*input)[pos]; if (c != '\\' || !do_unescape) { next_c = c; pos++; finished = ( pos >= input->length() ); return; } pos++; /* Check for improper string end: */ if (pos >= input->length()) throw regex_error(_("unexpected end of regex"), pos); /* The logic is based on re2c's Scanner::unescape() method; the set of accepted escape codes should correspond to lexer::scan() in parse.cxx. */ c = (*input)[pos]; switch (c) { case 'a': c = '\a'; break; case 'b': c = '\b'; break; case 't': c = '\t'; break; case 'n': c = '\n'; break; case 'v': c = '\v'; break; case 'f': c = '\f'; break; case 'r': c = '\r'; break; case 'x': { if (pos >= input->length() - 2) throw regex_error(_("two hex digits required in escape sequence"), pos); const char *d1 = strchr(hex, tolower((*input)[pos+1])); const char *d2 = strchr(hex, tolower((*input)[pos+2])); if (!d1 || !d2) throw regex_error(_("two hex digits required in escape sequence"), pos + (d1 ? 1 : 2)); c = (char)((d1-hex) << 4) + (char)(d2-hex); pos += 2; // skip two chars more than usual break; } case '4' ... '7': // XXX: perhaps perform error recovery (slurp 3 octal chars)? throw regex_error(_("octal escape sequence out of range"), pos); case '0' ... '3': { if (pos >= input->length() - 2) throw regex_error(_("three octal digits required in escape sequence"), pos); const char *d0 = strchr(oct, (*input)[pos]); const char *d1 = strchr(oct, (*input)[pos+1]); const char *d2 = strchr(oct, (*input)[pos+2]); if (!d0 || !d1 || !d2) throw regex_error(_("three octal digits required in escape sequence"), pos + (d1 ? 1 : 2)); c = (char)((d0-oct) << 6) + (char)((d1-oct) << 3) + (char)(d2-oct); pos += 2; // skip two chars more than usual break; } default: // do nothing; this removes the backslash from c ; } next_c = c; pos++; finished = ( pos >= input->length() ); } // ------------------------------------------------------------------------ regexp * regex_parser::parse (bool do_tag) { cur = cursor(&input, do_unescape); num_tags = 0; this->do_tag = do_tag; regexp *result = parse_expr (); // PR15065 glom appropriate tag_ops onto the expr (subexpression 0) if (do_tag) { result = new cat_op(new tag_op(num_tags++), result); result = new cat_op(result, new tag_op(num_tags++)); } if (! cur.finished) { char c = cur.peek (); if (c == ')') parse_error (_("unbalanced ')'"), cur.pos); else // This should not be possible: parse_error ("BUG -- regex parse failed to finish for unknown reasons", cur.pos); } // PR15065 store num_tags in result result->num_tags = num_tags; return result; } bool regex_parser::isspecial (char c) { return ( c == '.' || c == '[' || c == '{' || c == '(' || c == ')' || c == '\\' || c == '*' || c == '+' || c == '?' || c == '|' || c == '^' || c == '$' ); } void regex_parser::expect (char expected) { char c = 0; try { c = cur.next (); } catch (const regex_error &e) { parse_error (_F("expected %c, found end of regex", expected)); } if (c != expected) parse_error (_F("expected %c, found %c", expected, c)); } void regex_parser::parse_error (const string& msg, unsigned pos) { throw regex_error(msg, pos); } void regex_parser::parse_error (const string& msg) { parse_error (msg, cur.last_pos); } // ------------------------------------------------------------------------ regexp * regex_parser::parse_expr () { regexp *result = parse_term (); char c = cur.peek (); while (c && c == '|') { cur.next (); regexp *alt = parse_term (); result = make_alt (result, alt); c = cur.peek (); } return result; } regexp * regex_parser::parse_term () { regexp *result = parse_factor (); char c = cur.peek (); while (c && c != '|' && c != ')') { regexp *next = parse_factor (); result = new cat_op(result, next); c = cur.peek (); } return result; } regexp * regex_parser::parse_factor () { regexp *result; regexp *old_result = NULL; char c = cur.peek (); if (! c || c == '|' || c == ')') { result = new null_op; return result; } else if (c == '*' || c == '+' || c == '?' || c == '{') { parse_error(_F("unexpected '%c'", c)); } if (isspecial (c) && c != '\\') cur.next (); // c is guaranteed to be swallowed if (c == '.') { result = make_dot (); } else if (c == '[') { result = parse_char_range (); expect (']'); } else if (c == '(') { result = parse_expr (); // PR15065 glom appropriate tag_ops onto the expr if (do_tag) { result = new cat_op(new tag_op(num_tags++), result); result = new cat_op(result, new tag_op(num_tags++)); } else { // XXX: workaround for certain error checking test cases which // would otherwise produce divergent behaviour // (e.g. "^*" vs "(^)*"). result = new cat_op(result, new null_op); } expect (')'); } else if (c == '^' || c == '$') { result = new anchor_op(c); } else // escaped or ordinary character -- not yet swallowed { string accumulate; char d = 0; while (c && ( ! isspecial (c) || c == '\\' )) { if (c == '\\') { cur.next (); c = cur.peek (); } cur.next (); d = cur.peek (); /* if we end in a closure, it should only govern the last character */ if (d == '*' || d == '+' || d == '?' || d == '{') { /* save the last character */ d = c; break; } accumulate.push_back (c); c = d; d = 0; } result = str_to_re (accumulate); /* separately deal with the last character before a closure */ if (d != 0) { old_result = result; /* will add it back outside closure at the end */ result = str_to_re (string(1,d)); } } /* parse closures or other postfix operators */ c = cur.peek (); while (c == '*' || c == '+' || c == '?' || c == '{') { cur.next (); /* closure-type operators applied to $^ are definitely not kosher */ if (result->type_of() == "anchor_op") { parse_error(_F("postfix closure '%c' applied to anchoring operator", c)); } if (c == '*') { result = make_alt (new close_op(result), new null_op); } else if (c == '+') { result = new close_op(result); } else if (c == '?') { result = make_alt (result, new null_op); } else if (c == '{') { int minsize = parse_number (); int maxsize = -1; c = cur.next (); if (c == ',') { c = cur.peek (); if (c == '}') { cur.next (); maxsize = -1; } else if (isdigit (c)) { maxsize = parse_number (); expect ('}'); } else parse_error(_("expected '}' or number"), cur.pos); } else if (c == '}') { maxsize = minsize; } else parse_error(_("expected ',' or '}'")); /* optimize {0,0}, {0,} and {1,} */ if (!do_tag && minsize == 0 && maxsize == 0) { // XXX: this optimization is only used when // subexpression-extraction is disabled delete result; result = new null_op; } else if (minsize == 0 && maxsize == -1) { result = make_alt (new close_op(result), new null_op); } else if (minsize == 1 && maxsize == -1) { result = new close_op(result); } else { result = new closev_op(result, minsize, maxsize); } } c = cur.peek (); } if (old_result) result = new cat_op(old_result, result); return result; } regexp * regex_parser::parse_char_range () { range *ran = NULL; // check for inversion bool inv = false; char c = cur.peek (); if (c == '^') { inv = true; cur.next (); c = cur.peek (); } for (;;) { // break on string end whenever we encounter it if (cur.finished) parse_error(_("unclosed character class")); // TODOXXX doublecheck that this is triggered correctly range *add = stapregex_getrange (cur); range *new_ran = ( ran != NULL ? range_union(ran, add) : add ); delete ran; if (new_ran != add) delete add; ran = new_ran; // break on ']' (except at the start of the class) c = cur.peek (); if (c == ']') break; } if (inv) { range *new_ran = range_invert(ran); delete ran; ran = new_ran; } if (ran == NULL) return new null_op; return new match_op(ran); } unsigned regex_parser::parse_number () { string digits; char c = cur.peek (); while (c && isdigit (c)) { cur.next (); digits.push_back (c); c = cur.peek (); } if (digits == "") parse_error(_("expected number"), cur.pos); char *endptr = NULL; int val = strtol (digits.c_str (), &endptr, 10); if (*endptr != '\0' || errno == ERANGE) // paranoid error checking parse_error(_F("could not parse number %s", digits.c_str()), cur.pos); #define MAX_DFA_REPETITIONS 12345 if (val >= MAX_DFA_REPETITIONS) // XXX: is there a more sensible max size? parse_error(_F("%s is too large", digits.c_str()), cur.pos); return atoi (digits.c_str ()); } // ------------------------------------------------------------------------ std::map named_char_classes; range * named_char_class (const string& name) { // static initialization of table if (named_char_classes.empty()) { // original source for these is http://www.regular-expressions.info/posixbrackets.html // also checked against (intended to match) the c stdlib isFOO() chr class functions named_char_classes["alpha"] = new range("A-Za-z"); named_char_classes["alnum"] = new range("A-Za-z0-9"); named_char_classes["blank"] = new range(" \t"); named_char_classes["cntrl"] = new range("\x01-\x1F\x7F"); // XXX: include \x00 in range? -- probably not! named_char_classes["d"] = named_char_classes["digit"] = new range("0-9"); named_char_classes["xdigit"] = new range("0-9a-fA-F"); named_char_classes["graph"] = new range("\x21-\x7E"); named_char_classes["l"] = named_char_classes["lower"] = new range("a-z"); named_char_classes["print"] = new range("\x20-\x7E"); named_char_classes["punct"] = new range("!\"#$%&'()*+,./:;<=>?@[\\]^_`{|}~-"); named_char_classes["s"] = named_char_classes["space"] = new range(" \t\r\n\v\f"); named_char_classes["u"] = named_char_classes["upper"] = new range("A-Z"); } if (named_char_classes.find(name) == named_char_classes.end()) { throw regex_error (_F("unknown character class '%s'", name.c_str())); // XXX: position unknown } return new range(*named_char_classes[name]); } range * stapregex_getrange (cursor& cur) { char c = cur.peek (); if (c == '\\') { // Grab escaped char regardless of what it is. cur.next (); c = cur.peek (); cur.next (); } else if (c == '[') { // Check for '[:' digraph. char old_c = c; cur.next (); c = cur.peek (); if (c == ':') { cur.next (); c = cur.peek (); // skip ':' string charclass; for (;;) { if (cur.finished) throw regex_error (_F("unclosed character class '[:%s'", charclass.c_str()), cur.pos); if (cur.has(2) && c == ':' && (*cur.input)[cur.pos] == ']') { cur.next (); cur.next (); // skip ':]' return named_char_class(charclass); } charclass.push_back(c); cur.next(); c = cur.peek(); } } else { // Backtrack; fall through to processing c. c = old_c; } } else cur.next (); char lb = c, ub; if (!cur.has(2) || cur.peek () != '-' || (*cur.input)[cur.pos] == ']') { ub = lb; } else { cur.next (); // skip '-' ub = cur.peek (); if (ub < lb) throw regex_error (_F("Inverted character range %c-%c", lb, ub), cur.pos); cur.next (); } return new range(lb, ub); } }; /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stapregex-parse.h000066400000000000000000000037041217430427200167000ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2012-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // --- // // This file incorporates code from the re2c project; please see // the file README.stapregex for details. #ifndef STAPREGEX_PARSE_H #define STAPREGEX_PARSE_H #include #include namespace stapregex { struct range; /* from stapregex-tree.h */ struct regexp; /* from stapregex-tree.h */ void print_escaped(std::ostream& o, char c); struct cursor { const std::string *input; bool do_unescape; unsigned pos; // pos of next char to be returned by next unsigned last_pos; // pos of last returned char bool finished; bool has(unsigned n); // n characters remaining? cursor(); cursor(const std::string *input, bool do_unescape = false); char peek(); char next(); private: char next_c; char last_c; void get_unescaped(); }; class regex_parser { public: regex_parser (const std::string& input, bool do_unescape = true) : input(input), do_unescape(do_unescape) {} regexp *parse (bool do_tag = true); private: std::string input; bool do_unescape; cursor cur; bool do_tag; unsigned num_tags; void parse_error (const std::string& msg, unsigned pos); void parse_error (const std::string& msg); // report error at last_pos // character classes bool isspecial (char c); // any of .[{()\*+?|^$ // expectations void expect (char expected); private: // nonterminals regexp *parse_expr (); regexp *parse_term (); regexp *parse_factor (); regexp *parse_char_range (); unsigned parse_number (); }; /* Methods for parsing character classes: */ range *named_char_class (const std::string& name); range *stapregex_getrange (cursor& cur); }; #endif /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stapregex-tree.cxx000066400000000000000000000243641217430427200171050ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2012-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // --- // // This file incorporates code from the re2c project; please see // the file README.stapregex for details. #include #include #include #include #include #include "stapregex-parse.h" #include "stapregex-tree.h" using namespace std; namespace stapregex { range::range (char lb, char ub) { segments.push_back(make_pair(lb,ub)); } range::range (const string& str) { cursor cur(&str); // no unescaping if (cur.finished) return; range *ran = stapregex_getrange(cur); while (!cur.finished) { range *add = stapregex_getrange(cur); range *new_ran = ( ran != NULL ? range_union(ran, add) : add ); delete ran; if (new_ran != add) delete add; ran = new_ran; } segments = ran->segments; delete ran; } void range::print (std::ostream& o) const { if (segments.empty()) { o << "{none}"; // XXX: pick a better pseudo-notation? return; } if (segments.size() == 1 && segments[0].first == segments[0].second) { print_escaped (o, segments[0].first); return; } o << "["; for (deque::const_iterator it = segments.begin(); it != segments.end(); it++) { char lb = it->first; char ub = it->second; if (lb == ub) { print_escaped (o, lb); } else { print_escaped (o, lb); o << "-"; print_escaped (o, ub); } } o << "]"; } std::ostream& operator << (std::ostream& o, const range& ran) { ran.print(o); return o; } std::ostream& operator << (std::ostream& o, const range* ran) { if (ran) o << *ran; else o << "{none}"; // XXX: pick a better pseudo-notation? return o; } // ------------------------------------------------------------------------ range * range_union(range *old_a, range *old_b) { if (old_a == NULL && old_b == NULL) return NULL; if (old_a == NULL || old_a->segments.empty()) return new range(*old_b); if (old_b == NULL || old_b->segments.empty()) return new range(*old_a); range a(*old_a); range b(*old_b); /* First, gather the segments from both ranges into one sorted pile: */ deque s; while (!a.segments.empty()) { while (!b.segments.empty() && b.segments.front().first < a.segments.front().first) { s.push_back(b.segments.front()); b.segments.pop_front(); } s.push_back(a.segments.front()); a.segments.pop_front(); } while (!b.segments.empty()) { s.push_back(b.segments.front()); b.segments.pop_front(); } /* Now go through and merge overlapping segments. */ range *ran = new range; while (!s.empty()) { /* Merge adjacent overlapping segments. */ while (s.size() >= 2 && s[0].second >= s[1].first) { segment merged = make_pair(min(s[0].first, s[1].first), max(s[0].second, s[1].second)); s.pop_front(); s.pop_front(); s.push_front(merged); } /* Place non-overlapping segment in range. */ ran->segments.push_back(s.front()); s.pop_front(); } return ran; } range * range_invert(range *old_ran) { range ran(*old_ran); range *new_ran = new range; char start = '\1'; // exclude '\0' while (!ran.segments.empty()) { char end = ran.segments.front().first - 1; if (start <= end) new_ran->segments.push_back(make_pair(start, end)); start = ran.segments.front().second + 1; ran.segments.pop_front(); } if ((unsigned)start < (unsigned)NUM_REAL_CHARS) new_ran->segments.push_back(make_pair(start, NUM_REAL_CHARS-1)); return new_ran; } // ------------------------------------------------------------------------ const ins* show_ins (std::ostream &o, const ins *i, const ins *base) { o.width(3); o << (i - base) << ": "; const ins *ret = &i[1]; switch (i->i.tag) { case CHAR: o << "match "; for (; ret < (ins *) i->i.link; ++ret) print_escaped(o, ret->c.value); break; case GOTO: o << "goto " << ((ins *) i->i.link - base); break; case FORK: o << "fork(" << ( i->i.param ? "prefer" : "avoid" ) << ") " << ((ins *) i->i.link - base); break; case ACCEPT: o << "accept(" << i->i.param << ")"; break; case TAG: o << "tag(" << i->i.param << ")"; break; case INIT: o << "init"; break; } return ret; } // ------------------------------------------------------------------------ ins * regexp::compile() { unsigned k = ins_size(); ins *i = new ins[k + 1]; compile(i); // Append an infinite-loop GOTO to avoid edges going outside the array: i[k].i.tag = GOTO; i[k].i.link = &i[k]; return i; } std::ostream& operator << (std::ostream &o, const regexp& re) { re.print (o); return o; } std::ostream& operator << (std::ostream &o, const regexp* re) { o << *re; return o; } // ------------------------------------------------------------------------ void null_op::calc_size() { size = 0; } void null_op::compile(ins *i) { ; } anchor_op::anchor_op(char type) : type(type) {} void anchor_op::calc_size() { size = ( type == '^' ? 1 : 2 ); } void anchor_op::compile(ins *i) { if (type == '^') { i->i.tag = INIT; i->i.link = &i[1]; } else // type == '$' { i->i.tag = CHAR; i->i.link = &i[2]; ins *j = &i[1]; j->c.value = '\0'; j->c.bump = 1; } } tag_op::tag_op(unsigned id) : id(id) {} void tag_op::calc_size() { size = 1; } void tag_op::compile(ins *i) { i->i.tag = TAG; i->i.param = id; } match_op::match_op(range *ran) : ran(ran) {} void match_op::calc_size() { size = 1; for (deque::iterator it = ran->segments.begin(); it != ran->segments.end(); it++) { size += it->second - it->first + 1; } } void match_op::compile(ins *i) { unsigned bump = ins_size(); i->i.tag = CHAR; i->i.link = &i[bump]; // mark end of table ins *j = &i[1]; for (deque::iterator it = ran->segments.begin(); it != ran->segments.end(); it++) { for (unsigned c = it->first; c <= (unsigned) it->second; c++) { j->c.value = c; j->c.bump = --bump; // mark end of table j++; } } } alt_op::alt_op(regexp *a, regexp *b, bool prefer_second) : a(a), b(b), prefer_second(prefer_second) {} void alt_op::calc_size() { size = a->ins_size() + b->ins_size() + 2; } void alt_op::compile(ins *i) { i->i.tag = FORK; i->i.param = prefer_second ? 1 : 0; // preferred alternative to match ins *j = &i[a->ins_size() + 1]; i->i.link = &j[1]; a->compile(&i[1]); j->i.tag = GOTO; j->i.link = &j[b->ins_size() + 1]; b->compile(&j[1]); } cat_op::cat_op(regexp *a, regexp *b) : a(a), b(b) {} void cat_op::calc_size() { size = a->ins_size() + b->ins_size(); } void cat_op::compile(ins *i) { a->compile(&i[0]); b->compile(&i[a->ins_size()]); } close_op::close_op(regexp *re, bool prefer_shorter) : re(re), prefer_shorter(prefer_shorter) {} void close_op::calc_size() { size = re->ins_size() + 1; } void close_op::compile(ins *i) { re->compile(&i[0]); i += re->ins_size(); i->i.tag = FORK; i->i.param = prefer_shorter ? 0 : 1; // XXX: match greedily by default i->i.link = i - re->ins_size(); } closev_op::closev_op(regexp *re, int nmin, int nmax) : re(re), nmin(nmin), nmax(nmax) {} void closev_op::calc_size() { unsigned k = re->ins_size(); if (nmax >= 0) size = k * nmin + (nmax - nmin) * (1 + k); else size = k * nmin + 1; } void closev_op::compile(ins *i) { unsigned k = re->ins_size(); ins *jumppoint = i + ((nmax - nmin) * (1 + k)); for (int st = nmin; st < nmax; st++) { i->i.tag = FORK; i->i.param = 0; // XXX: this matches greedily i->i.link = jumppoint; i++; re->compile(&i[0]); i += k; } for (int st = 0; st < nmin; st++) { re->compile(&i[0]); i += k; if (nmax < 0 && st == 0) { i->i.tag = FORK; i->i.param = 1; // XXX: this matches greedily i->i.link = i - k; i++; } } } rule_op::rule_op(regexp *re, unsigned outcome) : re(re), outcome(outcome) {} void rule_op::calc_size() { size = re->ins_size() + 1; } void rule_op::compile(ins *i) { re->compile(&i[0]); i += re->ins_size(); i->i.tag = ACCEPT; i->i.param = outcome; } // ------------------------------------------------------------------------ regexp * match_char(char c) { return new match_op(new range(c,c)); } regexp * str_to_re(const string& str) { if (str.empty()) return new null_op; regexp *re = match_char(str[0]); for (unsigned i = 1; i < str.length(); i++) re = new cat_op(re, match_char(str[i])); return re; } regexp * do_alt(regexp *a, regexp *b) { if (a == NULL) return b; if (b == NULL) return a; return new alt_op(a,b); } regexp * make_alt(regexp *a, regexp *b) { /* Optimize the case of building alternatives of match_op. */ regexp *e1 = NULL, *e2 = NULL; range *r1 = NULL, *r2 = NULL; if (a->type_of() == "alt_op") { alt_op *aa = (alt_op *)a; if (aa->a->type_of() == "match_op") { r1 = ((match_op *) aa->a)->ran; e1 = aa->b; } else e1 = a; } else if (a->type_of() == "match_op") { r1 = ((match_op *) a)->ran; e1 = NULL; } else e1 = a; if (b->type_of() == "alt_op") { alt_op *bb = (alt_op *)b; if (bb->a->type_of() == "match_op") { r2 = ((match_op *) bb->a)->ran; e2 = bb->b; } else e2 = b; } else if (b->type_of() == "match_op") { r2 = ((match_op *) b)->ran; e2 = NULL; } else e2 = b; range *u = range_union(r1, r2); delete r1; delete r2; match_op *m = u != NULL ? new match_op(u) : NULL; regexp *r = do_alt(m, do_alt(e1, e2)); assert (r != NULL); return r; } regexp * make_dot(bool allow_zero) { return new match_op(new range(allow_zero ? 0 : 1, NUM_REAL_CHARS-1)); } }; /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stapregex-tree.h000066400000000000000000000211001217430427200165130ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2012-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // --- // // This file incorporates code from the re2c project; please see // the file README.stapregex for details. #ifndef STAPREGEX_TREE_H #define STAPREGEX_TREE_H #include #include #include #include // XXX: currently we only support ASCII #define NUM_REAL_CHARS 128 namespace stapregex { typedef std::pair segment; struct range { std::deque segments; // -- [lb, ub], sorted ascending // TODOXXX range () {} // -- empty range range (char lb, char ub); // -- a segment [lb, ub] range (const std::string& str); // -- character class (no named entities) void print(std::ostream& o) const; }; std::ostream& operator<< (std::ostream&, const range&); std::ostream& operator<< (std::ostream&, const range*); // NB: be sure to deallocate the old ranges if they are no longer used range *range_union(range *a, range *b); range *range_invert(range *ran); // ------------------------------------------------------------------------ /* For the NFA representation, re2c uses an assembler-like notation, which should be easy enough to understand based on the meaning of FORK. An NFA is considered to be a tagged-NFA if it uses the TAG opcode. The only tricky thing here is instituting sensible defaults for tagged-NFA transition priorities. This is done by setting i->param = 0 on a FORK instruction if the FORK-target has lower priority, and i->param = 1 if it has higher priority. FORK is the only place where discriminating between transitions needs to be done. */ /* Opcodes for the assembly notation: */ const unsigned CHAR = 0; // -- match character set (one successful outcome) const unsigned GOTO = 1; const unsigned FORK = 2; // -- nondeterministic choice; param marks priority const unsigned ACCEPT = 3; // -- final states; param marks success/fail const unsigned TAG = 4; // -- subexpression tracking; param marks tag # const unsigned INIT = 5; // -- opcode for ^ operator /* To represent an NFA, allocate a continuous array of these ins units: */ union ins { struct { unsigned int tag:3; // -- opcode unsigned int marked:1; // -- internal use; for algorithmic manipulation unsigned int param:8; // -- numerical operand, e.g. tag # void *link; // -- other instruction, e.g. FORK/GOTO target } i; /* For the CHAR opcodes, we follow the instruction with a sequence of these special character-matching units, in ascending order: */ struct { char value; // -- character to match unsigned short bump; // -- relative address of success-outcome insn } c; }; inline bool marked(ins *i) { return i->i.marked != 0; } inline void mark(ins *i) { i->i.marked = 1; } inline void unmark(ins *i) { i->i.marked = 0; } /* Helper function for printing out one ins element in a sequence: */ const ins* show_ins(std::ostream &o, const ins *i, const ins *base); // ------------------------------------------------------------------------ struct regexp { int num_tags; // -- number of tag_op id's used in expression, -1 if unknown int size; // -- number of instructions required for ins representation regexp () : num_tags(-1), size(-1) {} virtual ~regexp () {} virtual const std::string type_of() const = 0; /* Is regexp left-anchored? This function is used for optimization purposes, so it's always safe to return false. */ virtual bool anchored() const { return false; } /* Length of array needed for ins array representation: */ virtual void calc_size() = 0; unsigned ins_size() { if (size < 0) calc_size(); return size; } /* Compile to (part of) an already-allocated ins array: */ virtual void compile(ins *i) = 0; /* Allocate a fresh ins array and compile: */ ins *compile(); /* Print out, with a careful eye as to bracketing: priority == 0 -- don't bracket anything priority == 1 -- bracket alt_op, but not cat_op priority == 2 -- bracket all compound operators */ virtual void print(std::ostream& o, unsigned priority = 0) const = 0; }; std::ostream& operator << (std::ostream &o, const regexp& re); std::ostream& operator << (std::ostream &o, const regexp* re); // ------------------------------------------------------------------------ struct null_op : public regexp { const std::string type_of() const { return "null_op"; } void calc_size(); void compile(ins *i); void print (std::ostream &o, unsigned priority) const { o << "{null}"; // XXX: pick a better pseudo-notation? } }; struct anchor_op : public regexp { char type; anchor_op (char type); const std::string type_of() const { return "anchor_op"; } bool anchored () const { return type == '^'; } void calc_size(); void compile(ins *i); void print (std::ostream &o, unsigned priority) const { o << type; } }; struct tag_op : public regexp { unsigned id; tag_op (unsigned id); const std::string type_of() const { return "tag_op"; } void calc_size(); void compile(ins *i); void print (std::ostream &o, unsigned priority) const { o << "{t_" << id << "}"; } }; struct match_op : public regexp { range *ran; match_op (range *ran); const std::string type_of() const { return "match_op"; } void calc_size(); void compile(ins *i); void print (std::ostream &o, unsigned priority) const { o << ran; } }; struct alt_op : public regexp { regexp *a, *b; bool prefer_second; alt_op (regexp *a, regexp *b, bool prefer_second = false); const std::string type_of() const { return "alt_op"; } bool anchored () const { return a->anchored() && b->anchored(); } void calc_size(); void compile(ins *i); void print (std::ostream &o, unsigned priority) const { if (priority >= 1) o << "("; a->print(o, 0); o << "|"; b->print(o, 0); if (priority >= 1) o << ")"; } }; struct cat_op : public regexp { regexp *a, *b; cat_op (regexp *a, regexp *b); const std::string type_of() const { return "cat_op"; } bool anchored () const { return a->anchored(); // XXX: doesn't catch all cases, but that's all right } void calc_size(); void compile(ins *i); void print (std::ostream &o, unsigned priority) const { if (priority >= 2) o << "("; a->print(o, 1); b->print(o, 1); if (priority >= 2) o << ")"; } }; struct close_op : public regexp { regexp *re; bool prefer_shorter; close_op (regexp *re, bool prefer_shorter = false); const std::string type_of() const { return "close_op"; } bool anchored () const { return re->anchored(); } void calc_size(); void compile(ins *i); void print (std::ostream &o, unsigned priority) const { re->print(o, 2); o << "+"; } }; struct closev_op : public regexp { regexp *re; int nmin, nmax; // -- use -1 to denote unboundedness in that direction closev_op (regexp *re, int nmin, int nmax); const std::string type_of() const { return "closev_op"; } bool anchored () const { return nmin > 0 && re->anchored(); } void calc_size(); void compile(ins *i); void print (std::ostream &o, unsigned priority) const { re->print(o, 2); o << "{" << nmin << "," << nmax << "}"; } }; /* The following is somewhat generalized to allow implementing support for multiple distinct success outcomes, like in the original re2c: */ struct rule_op : public regexp { regexp *re; unsigned outcome; // -- 0 -> failure; 1 -> success; prefer success outcomes rule_op (regexp *re, unsigned outcome); const std::string type_of() const { return "rule_op"; } bool anchored () const { return re->anchored(); } void calc_size(); void compile(ins *i); void print (std::ostream &o, unsigned priority) const { re->print(o, 1); if (outcome) o << "{success_" << outcome << "}"; else o << "{failure_0}"; } }; // ------------------------------------------------------------------------ regexp *str_to_re(const std::string& str); regexp *make_alt(regexp* a, regexp* b); regexp *make_dot(bool allow_zero = false); // ------------------------------------------------------------------------ struct regex_error: public std::runtime_error { int pos; // -1 denotes error at unknown/indeterminate position regex_error (const std::string& msg): runtime_error(msg), pos(-1) {} regex_error (const std::string& msg, int pos): runtime_error(msg), pos(pos) {} ~regex_error () throw () {} }; }; #endif /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stapregex.cxx000066400000000000000000000134021217430427200161370ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2012-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // --- // // This file incorporates code from the re2c project; please see // the file README.stapregex for details. #include "util.h" #include "translator-output.h" #ifndef STAPREGEX_STANDALONE #include "session.h" #include "staptree.h" // needed to use semantic_error #else #include #include struct stapdfa; struct systemtap_session { // -- placeholder for testing std::map dfas; unsigned dfa_counter; bool need_tagged_dfa; unsigned dfa_maxstate; unsigned dfa_maxtag; }; #endif #include #include #include #include using namespace std; #include "stapregex-parse.h" #include "stapregex-tree.h" #include "stapregex-dfa.h" #include "stapregex.h" using namespace stapregex; // ------------------------------------------------------------------------ stapdfa * regex_to_stapdfa (systemtap_session *s, const string& input, const token *tok) { // Tags are disabled when not used, for the extra bit of efficiency. bool do_tag = s->need_tagged_dfa; if (s->dfas.find(input) != s->dfas.end()) return s->dfas[input]; stapdfa *dfa = new stapdfa ("__stp_dfa" + lex_cast(s->dfa_counter++), input, tok, true, do_tag); // Update required size of subexpression-tracking data structure: s->dfa_maxstate = max(s->dfa_maxstate, dfa->num_states()); s->dfa_maxtag = max(s->dfa_maxtag, dfa->num_tags()); s->dfas[input] = dfa; return dfa; } // ------------------------------------------------------------------------ stapdfa::stapdfa (const string& func_name, const string& re, const token *tok, bool do_unescape, bool do_tag) : func_name(func_name), orig_input(re), tok(tok), do_tag(do_tag) { try { regex_parser p(re, do_unescape); ast = p.parse (do_tag); content = stapregex_compile (ast, "goto match_success;", "goto match_fail;"); } catch (const regex_error &e) { #ifdef STAPREGEX_STANDALONE cerr << "ERROR: " << e.what() << " (at " << e.pos << ")" << endl; exit (1); #else if (e.pos >= 0) throw semantic_error(_F("regex compilation error (at position %d): %s", e.pos, e.what()), tok); else throw semantic_error(_F("regex compilation error: %s", e.what()), tok); #endif } } stapdfa::~stapdfa () { delete content; delete ast; } unsigned stapdfa::num_states () const { return content->nstates; } unsigned stapdfa::num_tags () const { return content->ntags; } void stapdfa::emit_declaration (translator_output *o) const { o->newline() << "// DFA for \"" << orig_input << "\""; #ifdef STAPREGEX_STANDALONE o->newline() << "int " << func_name << " (const char *str) {"; #else o->newline() << "int " << func_name << " (struct context * __restrict__ c, const char *str) {"; #endif o->indent(1); // Emit a SystemTap function body (as if an embedded-C snippet) that // invokes the DFA on the argument named 'str', saves a boolean // value (0 or 1) in the return value, and updates the probe // context's match object with subexpression contents as // appropriate. o->newline() << "const char *cur = str;"; o->newline() << "const char *mar;"; #ifndef STAPREGEX_STANDALONE if (do_tag) o->newline() << "#define YYTAG(t,s,n) {c->last_match.tag_states[(t)][(s)] = (n);}"; #endif o->newline() << "#define YYCTYPE char"; o->newline() << "#define YYCURSOR cur"; o->newline() << "#define YYLIMIT cur"; o->newline() << "#define YYMARKER mar"; // XXX: YYFILL is disabled as it doesn't play well with ^ o->newline(); try { content->emit(o); } catch (const regex_error &e) { #ifdef STAPREGEX_STANDALONE cerr << "ERROR: " << e.what() << " (at " << e.pos << ")" << endl; exit (1); #else if (e.pos >= 0) throw semantic_error(_F("regex compilation error (at position %d): %s", e.pos, e.what()), tok); else throw semantic_error(_F("regex compilation error: %s", e.what()), tok); #endif } o->newline() << "#undef YYCTYPE"; o->newline() << "#undef YYCURSOR"; o->newline() << "#undef YYLIMIT"; o->newline() << "#undef YYMARKER"; o->newline() << "match_success:"; #ifndef STAPREGEX_STANDALONE if (do_tag) { o->newline() << "strlcpy (c->last_match.matched_str, str, MAXSTRINGLEN);"; o->newline() << "c->last_match.result = 1"; content->emit_tagsave(o, "c->last_match.tag_states", "c->last_match.tag_vals", "c->last_match.num_final_tags"); } #endif o->newline() << "return 1;"; o->newline() << "match_fail:"; #ifndef STAPREGEX_STANDALONE if (do_tag) { o->newline() << "strlcpy (c->last_match.matched_str, str, MAXSTRINGLEN);"; o->newline() << "c->last_match.result = 0;"; } #endif o->newline() << "return 0;"; o->newline(-1) << "}"; } void stapdfa::emit_matchop_start (translator_output *o) const { #ifdef STAPREGEX_STANDALONE o->line() << "(" << func_name << "(("; #else o->line() << "(" << func_name << "(c, ("; // XXX: assumes context is available #endif } void stapdfa::emit_matchop_end (translator_output *o) const { o->line() << ")))"; } void stapdfa::print (std::ostream& o) const { translator_output to(o); print(&to); } void stapdfa::print (translator_output *o) const { o->line() << "STAPDFA (" << func_name << ", \"" << orig_input << "\") {"; content->print(o); o->newline(-1) << "}"; } std::ostream& operator << (std::ostream &o, const stapdfa& d) { d.print (o); return o; } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stapregex.h000066400000000000000000000033021217430427200155620ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2012-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // --- // // This file incorporates code from the re2c project; please see // the file README.stapregex for details. #ifndef STAPREGEX_H #define STAPREGEX_H #include #include struct systemtap_session; /* from session.h */ struct token; /* from parse.h */ struct translator_output; /* from translator-output.h */ namespace stapregex { struct regexp; /* from stapregex-tree.h */ class dfa; /* from stapregex-dfa.h */ }; struct stapdfa { std::string func_name; std::string orig_input; const token *tok; stapdfa (const std::string& func_name, const std::string& re, const token *tok = NULL, bool do_unescape = true, bool do_tag = true); ~stapdfa (); unsigned num_states() const; unsigned num_tags() const; void emit_declaration (translator_output *o) const; void emit_matchop_start (translator_output *o) const; void emit_matchop_end (translator_output *o) const; void print(translator_output *o) const; void print(std::ostream& o) const; private: stapregex::regexp *ast; stapregex::dfa *content; bool do_tag; }; std::ostream& operator << (std::ostream &o, const stapdfa& d); /* Creates a dfa if no dfa for the corresponding regex exists yet; retrieves the corresponding dfa from s->dfas if already there: */ stapdfa *regex_to_stapdfa (systemtap_session *s, const std::string& input, const token* tok); #endif /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/staprun/000077500000000000000000000000001217430427200151055ustar00rootroot00000000000000systemtap-2.3/staprun/Makefile.am000066400000000000000000000041471217430427200171470ustar00rootroot00000000000000# Makefile.am --- automake input file for systemtap runtime tools AM_CFLAGS = -Wall -Werror -Wunused -W -Wformat=2 -Wno-format-nonliteral AM_CXXFLAGS = -Wall -Werror -Wunused -W -Wformat=2 -Wno-format-nonliteral AM_CPPFLAGS = -D_GNU_SOURCE AM_CPPFLAGS += -I$(srcdir)/../includes AM_CPPFLAGS += -I$(builddir)/../includes/sys AM_CPPFLAGS += -DBINDIR='"$(bindir)"' -DSYSCONFDIR='"$(sysconfdir)"' -DPKGDATADIR='"${pkgdatadir}"' -DPKGLIBDIR='"$(pkglibexecdir)"' -DLOCALEDIR='"$(localedir)"' AM_CFLAGS += @PIECFLAGS@ AM_CXXFLAGS += @PIECXXFLAGS@ AM_LDFLAGS = @PIELDFLAGS@ bin_PROGRAMS = staprun stap-merge stapsh pkglibexec_PROGRAMS = stapio staprun_SOURCES = staprun.c staprun_funcs.c ctl.c common.c ../privilege.cxx ../util.cxx staprun_CFLAGS = $(AM_CFLAGS) -DSINGLE_THREADED staprun_CXXFLAGS = $(AM_CXXFLAGS) -DSINGLE_THREADED staprun_CPPFLAGS = $(AM_CPPFLAGS) staprun_LDADD = $(staprun_LIBS) staprun_LDFLAGS = $(AM_LDFLAGS) if BUILD_ELFUTILS staprun_CPPFLAGS += -I../include-elfutils staprun_LDFLAGS += -L../lib-elfutils -Wl,-rpath-link,lib-elfutils \ -Wl,--enable-new-dtags,-rpath,$(pkglibdir) endif if HAVE_NSS staprun_SOURCES += modverify.c ../nsscommon.cxx staprun_CFLAGS += $(nss_CFLAGS) staprun_CXXFLAGS += $(nss_CFLAGS) staprun_LDADD += $(nss_LIBS) endif stapio_SOURCES = stapio.c mainloop.c common.c ctl.c relay.c relay_old.c stapio_LDADD = -lpthread man_MANS = staprun.8 stap_merge_SOURCES = stap_merge.c stap_merge_CFLAGS = $(AM_CFLAGS) stap_merge_LDFLAGS = $(AM_LDFLAGS) stap_merge_LDADD = stapsh_SOURCES = stapsh.c stapsh_CFLAGS = $(AM_CFLAGS) stapsh_LDFLAGS = $(AM_LDFLAGS) stapsh_LDADD = BUILT_SOURCES = CLEANFILES = # Arrange for the top-level git_version.h to be regenerated at every "make". BUILT_SOURCES += git_version.stamp git_version.stamp ../git_version.h: $(MAKE) -C .. $(notdir $@) # Why the "id -u" condition? This way, an unprivileged user can run # make install, and have "sudo stap ...." or "sudo staprun ...." work later. install-exec-hook: if [ `id -u` -eq 0 ]; then \ getent group stapusr >/dev/null && chgrp stapusr "$(DESTDIR)$(bindir)/staprun"; \ chmod 04110 "$(DESTDIR)$(bindir)/staprun"; \ fi systemtap-2.3/staprun/Makefile.in000066400000000000000000001343761217430427200171700ustar00rootroot00000000000000# Makefile.in generated by automake 1.12.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Makefile.am --- automake input file for systemtap runtime tools VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = staprun$(EXEEXT) stap-merge$(EXEEXT) stapsh$(EXEEXT) pkglibexec_PROGRAMS = stapio$(EXEEXT) @BUILD_ELFUTILS_TRUE@am__append_1 = -I../include-elfutils @BUILD_ELFUTILS_TRUE@am__append_2 = -L../lib-elfutils -Wl,-rpath-link,lib-elfutils \ @BUILD_ELFUTILS_TRUE@ -Wl,--enable-new-dtags,-rpath,$(pkglibdir) @HAVE_NSS_TRUE@am__append_3 = modverify.c ../nsscommon.cxx @HAVE_NSS_TRUE@am__append_4 = $(nss_CFLAGS) @HAVE_NSS_TRUE@am__append_5 = $(nss_CFLAGS) @HAVE_NSS_TRUE@am__append_6 = $(nss_LIBS) subdir = staprun DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/run-staprun.in $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = run-staprun CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkglibexecdir)" \ "$(DESTDIR)$(man8dir)" PROGRAMS = $(bin_PROGRAMS) $(pkglibexec_PROGRAMS) am_stap_merge_OBJECTS = stap_merge-stap_merge.$(OBJEXT) stap_merge_OBJECTS = $(am_stap_merge_OBJECTS) stap_merge_DEPENDENCIES = stap_merge_LINK = $(CCLD) $(stap_merge_CFLAGS) $(CFLAGS) \ $(stap_merge_LDFLAGS) $(LDFLAGS) -o $@ am_stapio_OBJECTS = stapio.$(OBJEXT) mainloop.$(OBJEXT) \ common.$(OBJEXT) ctl.$(OBJEXT) relay.$(OBJEXT) \ relay_old.$(OBJEXT) stapio_OBJECTS = $(am_stapio_OBJECTS) stapio_DEPENDENCIES = @HAVE_NSS_TRUE@am__objects_1 = staprun-modverify.$(OBJEXT) \ @HAVE_NSS_TRUE@ staprun-nsscommon.$(OBJEXT) am_staprun_OBJECTS = staprun-staprun.$(OBJEXT) \ staprun-staprun_funcs.$(OBJEXT) staprun-ctl.$(OBJEXT) \ staprun-common.$(OBJEXT) staprun-privilege.$(OBJEXT) \ staprun-util.$(OBJEXT) $(am__objects_1) staprun_OBJECTS = $(am_staprun_OBJECTS) am__DEPENDENCIES_1 = @HAVE_NSS_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) staprun_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) staprun_LINK = $(CXXLD) $(staprun_CXXFLAGS) $(CXXFLAGS) \ $(staprun_LDFLAGS) $(LDFLAGS) -o $@ am_stapsh_OBJECTS = stapsh-stapsh.$(OBJEXT) stapsh_OBJECTS = $(am_stapsh_OBJECTS) stapsh_DEPENDENCIES = stapsh_LINK = $(CCLD) $(stapsh_CFLAGS) $(CFLAGS) $(stapsh_LDFLAGS) \ $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(stap_merge_SOURCES) $(stapio_SOURCES) $(staprun_SOURCES) \ $(stapsh_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) ETAGS = etags CTAGS = ctags ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DATE = @DATE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DYNINST_CXXFLAGS = @DYNINST_CXXFLAGS@ DYNINST_LDFLAGS = @DYNINST_LDFLAGS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_NLS = @ENABLE_NLS@ EXEEXT = @EXEEXT@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ JAVADIR = @JAVADIR@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PIECFLAGS = @PIECFLAGS@ PIECXXFLAGS = @PIECXXFLAGS@ PIELDFLAGS = @PIELDFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POSUB = @POSUB@ PUBLICAN_BRAND = @PUBLICAN_BRAND@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STAP_EXTRA_VERSION = @STAP_EXTRA_VERSION@ STAP_PREFIX = @STAP_PREFIX@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ elfutils_abs_srcdir = @elfutils_abs_srcdir@ exec_prefix = @exec_prefix@ have_dvips = @have_dvips@ have_fop = @have_fop@ have_jar = @have_jar@ have_javac = @have_javac@ have_latex = @have_latex@ have_latex2html = @have_latex2html@ have_ps2pdf = @have_ps2pdf@ have_publican = @have_publican@ have_xmlto = @have_xmlto@ have_xvfb = @have_xvfb@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ nss_CFLAGS = @nss_CFLAGS@ nss_LIBS = @nss_LIBS@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ selinux_CFLAGS = @selinux_CFLAGS@ selinux_LIBS = @selinux_LIBS@ sharedstatedir = @sharedstatedir@ sqlite3_LIBS = @sqlite3_LIBS@ srcdir = @srcdir@ stap_LIBS = @stap_LIBS@ staplog_CPPFLAGS = @staplog_CPPFLAGS@ staprun_LIBS = @staprun_LIBS@ subdirs = @subdirs@ support_section_question = @support_section_question@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = -Wall -Werror -Wunused -W -Wformat=2 \ -Wno-format-nonliteral @PIECFLAGS@ AM_CXXFLAGS = -Wall -Werror -Wunused -W -Wformat=2 \ -Wno-format-nonliteral @PIECXXFLAGS@ AM_CPPFLAGS = -D_GNU_SOURCE -I$(srcdir)/../includes \ -I$(builddir)/../includes/sys -DBINDIR='"$(bindir)"' \ -DSYSCONFDIR='"$(sysconfdir)"' -DPKGDATADIR='"${pkgdatadir}"' \ -DPKGLIBDIR='"$(pkglibexecdir)"' -DLOCALEDIR='"$(localedir)"' AM_LDFLAGS = @PIELDFLAGS@ staprun_SOURCES = staprun.c staprun_funcs.c ctl.c common.c \ ../privilege.cxx ../util.cxx $(am__append_3) staprun_CFLAGS = $(AM_CFLAGS) -DSINGLE_THREADED $(am__append_4) staprun_CXXFLAGS = $(AM_CXXFLAGS) -DSINGLE_THREADED $(am__append_5) staprun_CPPFLAGS = $(AM_CPPFLAGS) $(am__append_1) staprun_LDADD = $(staprun_LIBS) $(am__append_6) staprun_LDFLAGS = $(AM_LDFLAGS) $(am__append_2) stapio_SOURCES = stapio.c mainloop.c common.c ctl.c relay.c relay_old.c stapio_LDADD = -lpthread man_MANS = staprun.8 stap_merge_SOURCES = stap_merge.c stap_merge_CFLAGS = $(AM_CFLAGS) stap_merge_LDFLAGS = $(AM_LDFLAGS) stap_merge_LDADD = stapsh_SOURCES = stapsh.c stapsh_CFLAGS = $(AM_CFLAGS) stapsh_LDFLAGS = $(AM_LDFLAGS) stapsh_LDADD = # Arrange for the top-level git_version.h to be regenerated at every "make". BUILT_SOURCES = git_version.stamp CLEANFILES = all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .cxx .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign staprun/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign staprun/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): run-staprun: $(top_builddir)/config.status $(srcdir)/run-staprun.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) install-pkglibexecPROGRAMS: $(pkglibexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(pkglibexec_PROGRAMS)'; test -n "$(pkglibexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkglibexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(pkglibexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(pkglibexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-pkglibexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(pkglibexec_PROGRAMS)'; test -n "$(pkglibexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(pkglibexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(pkglibexecdir)" && rm -f $$files clean-pkglibexecPROGRAMS: -test -z "$(pkglibexec_PROGRAMS)" || rm -f $(pkglibexec_PROGRAMS) stap-merge$(EXEEXT): $(stap_merge_OBJECTS) $(stap_merge_DEPENDENCIES) $(EXTRA_stap_merge_DEPENDENCIES) @rm -f stap-merge$(EXEEXT) $(AM_V_CCLD)$(stap_merge_LINK) $(stap_merge_OBJECTS) $(stap_merge_LDADD) $(LIBS) stapio$(EXEEXT): $(stapio_OBJECTS) $(stapio_DEPENDENCIES) $(EXTRA_stapio_DEPENDENCIES) @rm -f stapio$(EXEEXT) $(AM_V_CCLD)$(LINK) $(stapio_OBJECTS) $(stapio_LDADD) $(LIBS) staprun$(EXEEXT): $(staprun_OBJECTS) $(staprun_DEPENDENCIES) $(EXTRA_staprun_DEPENDENCIES) @rm -f staprun$(EXEEXT) $(AM_V_CXXLD)$(staprun_LINK) $(staprun_OBJECTS) $(staprun_LDADD) $(LIBS) stapsh$(EXEEXT): $(stapsh_OBJECTS) $(stapsh_DEPENDENCIES) $(EXTRA_stapsh_DEPENDENCIES) @rm -f stapsh$(EXEEXT) $(AM_V_CCLD)$(stapsh_LINK) $(stapsh_OBJECTS) $(stapsh_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mainloop.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/relay.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/relay_old.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap_merge-stap_merge.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stapio.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/staprun-common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/staprun-ctl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/staprun-modverify.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/staprun-nsscommon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/staprun-privilege.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/staprun-staprun.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/staprun-staprun_funcs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/staprun-util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stapsh-stapsh.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` stap_merge-stap_merge.o: stap_merge.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_merge_CFLAGS) $(CFLAGS) -MT stap_merge-stap_merge.o -MD -MP -MF $(DEPDIR)/stap_merge-stap_merge.Tpo -c -o stap_merge-stap_merge.o `test -f 'stap_merge.c' || echo '$(srcdir)/'`stap_merge.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_merge-stap_merge.Tpo $(DEPDIR)/stap_merge-stap_merge.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stap_merge.c' object='stap_merge-stap_merge.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_merge_CFLAGS) $(CFLAGS) -c -o stap_merge-stap_merge.o `test -f 'stap_merge.c' || echo '$(srcdir)/'`stap_merge.c stap_merge-stap_merge.obj: stap_merge.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_merge_CFLAGS) $(CFLAGS) -MT stap_merge-stap_merge.obj -MD -MP -MF $(DEPDIR)/stap_merge-stap_merge.Tpo -c -o stap_merge-stap_merge.obj `if test -f 'stap_merge.c'; then $(CYGPATH_W) 'stap_merge.c'; else $(CYGPATH_W) '$(srcdir)/stap_merge.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stap_merge-stap_merge.Tpo $(DEPDIR)/stap_merge-stap_merge.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stap_merge.c' object='stap_merge-stap_merge.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stap_merge_CFLAGS) $(CFLAGS) -c -o stap_merge-stap_merge.obj `if test -f 'stap_merge.c'; then $(CYGPATH_W) 'stap_merge.c'; else $(CYGPATH_W) '$(srcdir)/stap_merge.c'; fi` staprun-staprun.o: staprun.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -MT staprun-staprun.o -MD -MP -MF $(DEPDIR)/staprun-staprun.Tpo -c -o staprun-staprun.o `test -f 'staprun.c' || echo '$(srcdir)/'`staprun.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/staprun-staprun.Tpo $(DEPDIR)/staprun-staprun.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='staprun.c' object='staprun-staprun.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -c -o staprun-staprun.o `test -f 'staprun.c' || echo '$(srcdir)/'`staprun.c staprun-staprun.obj: staprun.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -MT staprun-staprun.obj -MD -MP -MF $(DEPDIR)/staprun-staprun.Tpo -c -o staprun-staprun.obj `if test -f 'staprun.c'; then $(CYGPATH_W) 'staprun.c'; else $(CYGPATH_W) '$(srcdir)/staprun.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/staprun-staprun.Tpo $(DEPDIR)/staprun-staprun.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='staprun.c' object='staprun-staprun.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -c -o staprun-staprun.obj `if test -f 'staprun.c'; then $(CYGPATH_W) 'staprun.c'; else $(CYGPATH_W) '$(srcdir)/staprun.c'; fi` staprun-staprun_funcs.o: staprun_funcs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -MT staprun-staprun_funcs.o -MD -MP -MF $(DEPDIR)/staprun-staprun_funcs.Tpo -c -o staprun-staprun_funcs.o `test -f 'staprun_funcs.c' || echo '$(srcdir)/'`staprun_funcs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/staprun-staprun_funcs.Tpo $(DEPDIR)/staprun-staprun_funcs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='staprun_funcs.c' object='staprun-staprun_funcs.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -c -o staprun-staprun_funcs.o `test -f 'staprun_funcs.c' || echo '$(srcdir)/'`staprun_funcs.c staprun-staprun_funcs.obj: staprun_funcs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -MT staprun-staprun_funcs.obj -MD -MP -MF $(DEPDIR)/staprun-staprun_funcs.Tpo -c -o staprun-staprun_funcs.obj `if test -f 'staprun_funcs.c'; then $(CYGPATH_W) 'staprun_funcs.c'; else $(CYGPATH_W) '$(srcdir)/staprun_funcs.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/staprun-staprun_funcs.Tpo $(DEPDIR)/staprun-staprun_funcs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='staprun_funcs.c' object='staprun-staprun_funcs.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -c -o staprun-staprun_funcs.obj `if test -f 'staprun_funcs.c'; then $(CYGPATH_W) 'staprun_funcs.c'; else $(CYGPATH_W) '$(srcdir)/staprun_funcs.c'; fi` staprun-ctl.o: ctl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -MT staprun-ctl.o -MD -MP -MF $(DEPDIR)/staprun-ctl.Tpo -c -o staprun-ctl.o `test -f 'ctl.c' || echo '$(srcdir)/'`ctl.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/staprun-ctl.Tpo $(DEPDIR)/staprun-ctl.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctl.c' object='staprun-ctl.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -c -o staprun-ctl.o `test -f 'ctl.c' || echo '$(srcdir)/'`ctl.c staprun-ctl.obj: ctl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -MT staprun-ctl.obj -MD -MP -MF $(DEPDIR)/staprun-ctl.Tpo -c -o staprun-ctl.obj `if test -f 'ctl.c'; then $(CYGPATH_W) 'ctl.c'; else $(CYGPATH_W) '$(srcdir)/ctl.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/staprun-ctl.Tpo $(DEPDIR)/staprun-ctl.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctl.c' object='staprun-ctl.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -c -o staprun-ctl.obj `if test -f 'ctl.c'; then $(CYGPATH_W) 'ctl.c'; else $(CYGPATH_W) '$(srcdir)/ctl.c'; fi` staprun-common.o: common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -MT staprun-common.o -MD -MP -MF $(DEPDIR)/staprun-common.Tpo -c -o staprun-common.o `test -f 'common.c' || echo '$(srcdir)/'`common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/staprun-common.Tpo $(DEPDIR)/staprun-common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common.c' object='staprun-common.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -c -o staprun-common.o `test -f 'common.c' || echo '$(srcdir)/'`common.c staprun-common.obj: common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -MT staprun-common.obj -MD -MP -MF $(DEPDIR)/staprun-common.Tpo -c -o staprun-common.obj `if test -f 'common.c'; then $(CYGPATH_W) 'common.c'; else $(CYGPATH_W) '$(srcdir)/common.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/staprun-common.Tpo $(DEPDIR)/staprun-common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common.c' object='staprun-common.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -c -o staprun-common.obj `if test -f 'common.c'; then $(CYGPATH_W) 'common.c'; else $(CYGPATH_W) '$(srcdir)/common.c'; fi` staprun-modverify.o: modverify.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -MT staprun-modverify.o -MD -MP -MF $(DEPDIR)/staprun-modverify.Tpo -c -o staprun-modverify.o `test -f 'modverify.c' || echo '$(srcdir)/'`modverify.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/staprun-modverify.Tpo $(DEPDIR)/staprun-modverify.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='modverify.c' object='staprun-modverify.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -c -o staprun-modverify.o `test -f 'modverify.c' || echo '$(srcdir)/'`modverify.c staprun-modverify.obj: modverify.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -MT staprun-modverify.obj -MD -MP -MF $(DEPDIR)/staprun-modverify.Tpo -c -o staprun-modverify.obj `if test -f 'modverify.c'; then $(CYGPATH_W) 'modverify.c'; else $(CYGPATH_W) '$(srcdir)/modverify.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/staprun-modverify.Tpo $(DEPDIR)/staprun-modverify.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='modverify.c' object='staprun-modverify.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -c -o staprun-modverify.obj `if test -f 'modverify.c'; then $(CYGPATH_W) 'modverify.c'; else $(CYGPATH_W) '$(srcdir)/modverify.c'; fi` stapsh-stapsh.o: stapsh.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapsh_CFLAGS) $(CFLAGS) -MT stapsh-stapsh.o -MD -MP -MF $(DEPDIR)/stapsh-stapsh.Tpo -c -o stapsh-stapsh.o `test -f 'stapsh.c' || echo '$(srcdir)/'`stapsh.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stapsh-stapsh.Tpo $(DEPDIR)/stapsh-stapsh.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stapsh.c' object='stapsh-stapsh.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapsh_CFLAGS) $(CFLAGS) -c -o stapsh-stapsh.o `test -f 'stapsh.c' || echo '$(srcdir)/'`stapsh.c stapsh-stapsh.obj: stapsh.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapsh_CFLAGS) $(CFLAGS) -MT stapsh-stapsh.obj -MD -MP -MF $(DEPDIR)/stapsh-stapsh.Tpo -c -o stapsh-stapsh.obj `if test -f 'stapsh.c'; then $(CYGPATH_W) 'stapsh.c'; else $(CYGPATH_W) '$(srcdir)/stapsh.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stapsh-stapsh.Tpo $(DEPDIR)/stapsh-stapsh.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stapsh.c' object='stapsh-stapsh.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapsh_CFLAGS) $(CFLAGS) -c -o stapsh-stapsh.obj `if test -f 'stapsh.c'; then $(CYGPATH_W) 'stapsh.c'; else $(CYGPATH_W) '$(srcdir)/stapsh.c'; fi` .cxx.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cxx.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` staprun-privilege.o: ../privilege.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CXXFLAGS) $(CXXFLAGS) -MT staprun-privilege.o -MD -MP -MF $(DEPDIR)/staprun-privilege.Tpo -c -o staprun-privilege.o `test -f '../privilege.cxx' || echo '$(srcdir)/'`../privilege.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/staprun-privilege.Tpo $(DEPDIR)/staprun-privilege.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../privilege.cxx' object='staprun-privilege.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CXXFLAGS) $(CXXFLAGS) -c -o staprun-privilege.o `test -f '../privilege.cxx' || echo '$(srcdir)/'`../privilege.cxx staprun-privilege.obj: ../privilege.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CXXFLAGS) $(CXXFLAGS) -MT staprun-privilege.obj -MD -MP -MF $(DEPDIR)/staprun-privilege.Tpo -c -o staprun-privilege.obj `if test -f '../privilege.cxx'; then $(CYGPATH_W) '../privilege.cxx'; else $(CYGPATH_W) '$(srcdir)/../privilege.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/staprun-privilege.Tpo $(DEPDIR)/staprun-privilege.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../privilege.cxx' object='staprun-privilege.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CXXFLAGS) $(CXXFLAGS) -c -o staprun-privilege.obj `if test -f '../privilege.cxx'; then $(CYGPATH_W) '../privilege.cxx'; else $(CYGPATH_W) '$(srcdir)/../privilege.cxx'; fi` staprun-util.o: ../util.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CXXFLAGS) $(CXXFLAGS) -MT staprun-util.o -MD -MP -MF $(DEPDIR)/staprun-util.Tpo -c -o staprun-util.o `test -f '../util.cxx' || echo '$(srcdir)/'`../util.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/staprun-util.Tpo $(DEPDIR)/staprun-util.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../util.cxx' object='staprun-util.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CXXFLAGS) $(CXXFLAGS) -c -o staprun-util.o `test -f '../util.cxx' || echo '$(srcdir)/'`../util.cxx staprun-util.obj: ../util.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CXXFLAGS) $(CXXFLAGS) -MT staprun-util.obj -MD -MP -MF $(DEPDIR)/staprun-util.Tpo -c -o staprun-util.obj `if test -f '../util.cxx'; then $(CYGPATH_W) '../util.cxx'; else $(CYGPATH_W) '$(srcdir)/../util.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/staprun-util.Tpo $(DEPDIR)/staprun-util.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../util.cxx' object='staprun-util.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CXXFLAGS) $(CXXFLAGS) -c -o staprun-util.obj `if test -f '../util.cxx'; then $(CYGPATH_W) '../util.cxx'; else $(CYGPATH_W) '$(srcdir)/../util.cxx'; fi` staprun-nsscommon.o: ../nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CXXFLAGS) $(CXXFLAGS) -MT staprun-nsscommon.o -MD -MP -MF $(DEPDIR)/staprun-nsscommon.Tpo -c -o staprun-nsscommon.o `test -f '../nsscommon.cxx' || echo '$(srcdir)/'`../nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/staprun-nsscommon.Tpo $(DEPDIR)/staprun-nsscommon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../nsscommon.cxx' object='staprun-nsscommon.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CXXFLAGS) $(CXXFLAGS) -c -o staprun-nsscommon.o `test -f '../nsscommon.cxx' || echo '$(srcdir)/'`../nsscommon.cxx staprun-nsscommon.obj: ../nsscommon.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CXXFLAGS) $(CXXFLAGS) -MT staprun-nsscommon.obj -MD -MP -MF $(DEPDIR)/staprun-nsscommon.Tpo -c -o staprun-nsscommon.obj `if test -f '../nsscommon.cxx'; then $(CYGPATH_W) '../nsscommon.cxx'; else $(CYGPATH_W) '$(srcdir)/../nsscommon.cxx'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/staprun-nsscommon.Tpo $(DEPDIR)/staprun-nsscommon.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../nsscommon.cxx' object='staprun-nsscommon.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CXXFLAGS) $(CXXFLAGS) -c -o staprun-nsscommon.obj `if test -f '../nsscommon.cxx'; then $(CYGPATH_W) '../nsscommon.cxx'; else $(CYGPATH_W) '$(srcdir)/../nsscommon.cxx'; fi` install-man8: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man8dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.8[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(PROGRAMS) $(MANS) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkglibexecdir)" "$(DESTDIR)$(man8dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-pkglibexecPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-pkglibexecPROGRAMS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man8 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-man \ uninstall-pkglibexecPROGRAMS uninstall-man: uninstall-man8 .MAKE: all check install install-am install-exec-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-pkglibexecPROGRAMS cscopelist ctags \ distclean distclean-compile distclean-generic distclean-tags \ dvi dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-exec-hook \ install-html install-html-am install-info install-info-am \ install-man install-man8 install-pdf install-pdf-am \ install-pkglibexecPROGRAMS install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-man uninstall-man8 uninstall-pkglibexecPROGRAMS git_version.stamp ../git_version.h: $(MAKE) -C .. $(notdir $@) # Why the "id -u" condition? This way, an unprivileged user can run # make install, and have "sudo stap ...." or "sudo staprun ...." work later. install-exec-hook: if [ `id -u` -eq 0 ]; then \ getent group stapusr >/dev/null && chgrp stapusr "$(DESTDIR)$(bindir)/staprun"; \ chmod 04110 "$(DESTDIR)$(bindir)/staprun"; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: systemtap-2.3/staprun/common.c000066400000000000000000000450521217430427200165470ustar00rootroot00000000000000/* -*- linux-c -*- * * common.c - staprun suid/user common code * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. * * Copyright (C) 2007-2013 Red Hat Inc. */ #include "staprun.h" #include #include #include #include #include #include "../git_version.h" #include "../version.h" /* variables needed by parse_args() */ int verbose; int suppress_warnings; int target_pid; unsigned int buffer_size; unsigned int reader_timeout_ms; char *target_cmd; char *outfile_name; int rename_mod; int attach_mod; int delete_mod; int load_only; int need_uprobes; const char *uprobes_path = NULL; int daemon_mode; off_t fsize_max; int fnum_max; int remote_id; const char *remote_uri; int relay_basedir_fd; int color_errors; color_modes color_mode; /* module variables */ char *modname = NULL; char *modpath = ""; char *modoptions[MAXMODOPTIONS]; int control_channel = -1; /* NB: fd==0 possible */ static char path_buf[PATH_MAX]; static char *get_abspath(char *path) { int len; if (path[0] == '/') return path; len = strlen(getcwd(path_buf, PATH_MAX)); if (len + 2 + strlen(path) >= PATH_MAX) return NULL; path_buf[len] = '/'; /* Note that this strcpy() call is OK, since we checked * the length earlier to make sure the string would fit. */ strcpy(&path_buf[len + 1], path); return path_buf; } int stap_strfloctime(char *buf, size_t max, const char *fmt, time_t t) { struct tm tm; size_t ret; if (buf == NULL || fmt == NULL || max <= 1) return -EINVAL; localtime_r(&t, &tm); /* NB: this following invocation is the reason for staprun's being built with -Wno-format-nonliteral. strftime parsing does not have security implications AFAIK, but gcc still wants to check them. */ ret = strftime(buf, max, fmt, &tm); if (ret == 0) return -EINVAL; return (int)ret; } int make_outfile_name(char *buf, int max, int fnum, int cpu, time_t t, int bulk) { int len; if (PATH_MAX < max) max = PATH_MAX; len = stap_strfloctime(buf, max, outfile_name, t); if (len < 0) { err(_("Invalid FILE name format\n")); return -1; } /* special case: for testing we sometimes want to write to /dev/null */ if (strcmp(outfile_name, "/dev/null") == 0) { /* This strcpy() call is OK since we know that the * buffer is at least PATH_MAX bytes long at this * point. */ strcpy(buf, "/dev/null"); } else { if (bulk) { if (snprintf_chk(&buf[len], max - len, "_cpu%d.%d", cpu, fnum)) return -1; } else { /* stream mode */ if (snprintf_chk(&buf[len], max - len, ".%d", fnum)) return -1; } } return 0; } void parse_args(int argc, char **argv) { int c; char *s; /* Initialize option variables. */ verbose = 0; suppress_warnings = 0; target_pid = 0; buffer_size = 0; reader_timeout_ms = 0; target_cmd = NULL; outfile_name = NULL; rename_mod = 0; attach_mod = 0; delete_mod = 0; load_only = 0; need_uprobes = 0; daemon_mode = 0; fsize_max = 0; fnum_max = 0; remote_id = -1; remote_uri = NULL; relay_basedir_fd = -1; color_mode = color_auto; color_errors = isatty(STDERR_FILENO) && strcmp(getenv("TERM") ?: "notdumb", "dumb"); while ((c = getopt(argc, argv, "ALu::vb:t:dc:o:x:S:DwRr:VT:C:" #ifdef HAVE_OPENAT "F:" #endif )) != EOF) { switch (c) { case 'u': need_uprobes = 1; if (optarg) uprobes_path = strdup (optarg); break; case 'v': verbose++; break; case 'w': suppress_warnings=1; break; case 'b': buffer_size = (unsigned)atoi(optarg); if (buffer_size < 1 || buffer_size > 4095) { err(_("Invalid buffer size '%d' (should be 1-4095).\n"), buffer_size); usage(argv[0]); } break; case 't': case 'x': target_pid = atoi(optarg); break; case 'd': /* delete module */ delete_mod = 1; break; case 'c': target_cmd = optarg; break; case 'o': outfile_name = optarg; break; case 'R': rename_mod = 1; break; case 'A': attach_mod = 1; break; case 'L': load_only = 1; break; case 'D': daemon_mode = 1; break; case 'F': relay_basedir_fd = atoi(optarg); if (relay_basedir_fd < 0) { err(_("Invalid file descriptor option '%s'.\n"), optarg); usage(argv[0]); } break; case 'S': fsize_max = strtoul(optarg, &s, 10); fsize_max <<= 20; if (s[0] == ',') fnum_max = (int)strtoul(&s[1], &s, 10); if (s[0] != '\0') { err(_("Invalid file size option '%s'.\n"), optarg); usage(argv[0]); } break; case 'r': /* parse ID:URL */ remote_id = strtoul(optarg, &s, 10); if (s[0] == ':') remote_uri = strdup (& s[1]); if (remote_id < 0 || remote_uri == 0 || remote_uri[0] == '\0') { err(_("Cannot process remote id option '%s'.\n"), optarg); usage(argv[0]); } break; case 'V': eprintf(_("Systemtap module loader/runner (version %s, %s)\n" "Copyright (C) 2005-2013 Red Hat, Inc. and others\n" "This is free software; see the source for copying conditions.\n"), VERSION, STAP_EXTENDED_VERSION); _exit(1); break; case 'T': reader_timeout_ms = (unsigned)atoi(optarg); if (reader_timeout_ms < 1) { err(_("Invalid reader timeout value '%d' (should be >= 1).\n"), reader_timeout_ms); usage(argv[0]); } break; case 'C': if (!strcmp(optarg, "never")) color_mode = color_never; else if (!strcmp(optarg, "auto")) color_mode = color_auto; else if (!strcmp(optarg, "always")) color_mode = color_always; else { err(_("Invalid option '%s' for -C."), optarg); usage(argv[0]); } color_errors = color_mode == color_always || (color_mode == color_auto && isatty(STDERR_FILENO) && strcmp(getenv("TERM") ?: "notdumb", "dumb")); break; default: usage(argv[0]); } } if (outfile_name) { char tmp[PATH_MAX]; int ret; outfile_name = get_abspath(outfile_name); if (outfile_name == NULL) { err(_("File name is too long.\n")); usage(argv[0]); } ret = stap_strfloctime(tmp, PATH_MAX - 18, /* = _cpuNNN.SSSSSSSSSS */ outfile_name, time(NULL)); if (ret < 0) { err(_("Filename format is invalid or too long.\n")); usage(argv[0]); } } if (attach_mod && load_only) { err(_("You can't specify the '-A' and '-L' options together.\n")); usage(argv[0]); } if (attach_mod && buffer_size) { err(_("You can't specify the '-A' and '-b' options together. The '-b'\n" "buffer size option only has an effect when the module is inserted.\n")); usage(argv[0]); } if (attach_mod && target_cmd) { err(_("You can't specify the '-A' and '-c' options together. The '-c cmd'\n" "option used to start a command only has an effect when the module\n" "is inserted.\n")); usage(argv[0]); } if (attach_mod && target_pid) { err(_("You can't specify the '-A' and '-x' options together. The '-x pid'\n" "option only has an effect when the module is inserted.\n")); usage(argv[0]); } if (target_cmd && target_pid) { err(_("You can't specify the '-c' and '-x' options together.\n")); usage(argv[0]); } if (daemon_mode && load_only) { err(_("You can't specify the '-D' and '-L' options together.\n")); usage(argv[0]); } if (daemon_mode && delete_mod) { err(_("You can't specify the '-D' and '-d' options together.\n")); usage(argv[0]); } if (daemon_mode && target_cmd) { err(_("You can't specify the '-D' and '-c' options together.\n")); usage(argv[0]); } if (daemon_mode && outfile_name == NULL) { err(_("You have to specify output FILE with '-D' option.\n")); usage(argv[0]); } if (outfile_name == NULL && fsize_max != 0) { err(_("You have to specify output FILE with '-S' option.\n")); usage(argv[0]); } } void usage(char *prog) { eprintf(_("\n%s [-v] [-w] [-V] [-u] [-c cmd ] [-x pid] [-u user] [-A|-L|-d] [-C WHEN]\n" "\t[-b bufsize] [-R] [-r N:URI] [-o FILE [-D] [-S size[,N]]] MODULE [module-options]\n"), prog); eprintf(_("-v Increase verbosity.\n" "-V Print version number and exit.\n" "-w Suppress warnings.\n" "-u Load uprobes.ko\n" "-c cmd Command \'cmd\' will be run and staprun will\n" " exit when it does. The '_stp_target' variable\n" " will contain the pid for the command.\n" "-x pid Sets the '_stp_target' variable to pid.\n" "-o FILE Send output to FILE. This supports strftime(3)\n" " formats for FILE.\n" "-b buffer size The systemtap module specifies a buffer size.\n" " Setting one here will override that value. The\n" " value should be an integer between 1 and 4095 \n" " which be assumed to be the buffer size in MB.\n" " That value will be per-cpu in bulk mode.\n" "-L Load module and start probes, then detach.\n" "-A Attach to loaded systemtap module.\n" "-C WHEN Enable colored errors. WHEN must be either 'auto',\n" " 'never', or 'always'. Set to 'auto' by default.\n" "-d Delete a module. Only detached or unused modules\n" " the user has permission to access will be deleted. Use \"*\"\n" " (quoted) to delete all unused modules.\n" #ifdef HAVE_ELF_GETSHDRSTRNDX "-R Have staprun create a new name for the module before\n" " inserting it. This allows the same module to be inserted\n" " more than once.\n" #else "-R (Module renaming is not available in this configuration.)\n" #endif "-r N:URI Pass N:URI data to tapset functions remote_id()/remote_uri().\n" "-D Run in background. This requires '-o' option.\n" "-S size[,N] Switches output file to next file when the size\n" " of file reaches the specified size. The value\n" " should be an integer greater than 1 which is\n" " assumed to be the maximum file size in MB.\n" " When the number of output files reaches N, it\n" " switches to the first output file. You can omit\n" " the second argument.\n" "-T timeout Specifies upper limit on amount of time reader thread\n" " will wait for new full trace buffer. Value should be an\n" " integer >= 1, which is timeout value in ms. Default 200ms.\n" #ifdef HAVE_OPENAT "-F fd Specifies file descriptor for module relay directory\n" #endif "\n" "MODULE can be either a module name or a module path. If a\n" "module name is used, it is searched in the following directory:\n")); { struct utsname utsbuf; int rc = uname (& utsbuf); if (! rc) eprintf("/lib/modules/%s/systemtap\n", utsbuf.release); else eprintf("/lib/modules/`uname -r`/systemtap\n"); } exit(1); } /* * parse_modpath. Here's how this code interprets the global modpath: * * (1) If modpath contains a '/', it is assumed to be an absolute or * relative file path to a module (such as "../foo.ko" or * "/tmp/stapXYZ/stap_foo.ko"). * * (2) If modpath doesn't contain a '/' and ends in '.ko', it is a file * path to a module in the current directory (such as "foo.ko"). * * (3) If modpath doesn't contain a '/' and doesn't end in '.ko', then * it is a module name and the full pathname of the module is * '/lib/modules/`uname -r`/systemtap/PATH.ko'. For instance, if * modpath was "foo", the full module pathname would be * '/lib/modules/`uname -r`/systemtap/foo.ko'. */ void parse_modpath(const char *inpath) { const char *mptr = strrchr(inpath, '/'); char *ptr; dbug(3, "inpath=%s\n", inpath); /* If we couldn't find a '/', ... */ if (mptr == NULL) { size_t plen = strlen(inpath); /* If the path ends with the '.ko' file extension, * then we've got a module in the current * directory. */ if (plen > 3 && strcmp(&inpath[plen - 3], ".ko") == 0) { mptr = inpath; modpath = strdup(inpath); if (!modpath) { err(_("Memory allocation failed. Exiting.\n")); exit(1); } } else { /* If we didn't find the '.ko' file extension, then * we've just got a module name, not a module path. * Look for the module in /lib/modules/`uname * -r`/systemtap. */ struct utsname utsbuf; int len; #define MODULE_PATH "/lib/modules/%s/systemtap/%s.ko" /* First, we need to figure out what the * kernel version. */ if (uname(&utsbuf) != 0) { perr(_("Unable to determine kernel version, uname failed")); exit(-1); } /* Build the module path, which will look like * '/lib/modules/KVER/systemtap/{path}.ko'. */ len = sizeof(MODULE_PATH) + sizeof(utsbuf.release) + strlen(inpath); modpath = malloc(len); if (!modpath) { err(_("Memory allocation failed. Exiting.\n")); exit(1); } if (snprintf_chk(modpath, len, MODULE_PATH, utsbuf.release, inpath)) exit(-1); dbug(2, "modpath=\"%s\"\n", modpath); mptr = strrchr(modpath, '/'); mptr++; } } else { /* We found a '/', so the module name starts with the next * character. */ mptr++; modpath = strdup(inpath); if (!modpath) { err(_("Memory allocation failed. Exiting.\n")); exit(1); } } modname = strdup(mptr); if (!modname) { err(_("Memory allocation failed. Exiting.\n")); exit(1); } ptr = strrchr(modname, '.'); if (ptr) *ptr = '\0'; /* We've finally got a real modname. Make sure it isn't too * long. If it is too long, init_module() will appear to * work, but the module can't be removed (because you end up * with control characters in the module name). */ if (strlen(modname) > MODULE_NAME_LEN) { err(_("Module name ('%s') is too long.\n"), modname); exit(1); } } #define ERR_MSG "\nUNEXPECTED FATAL ERROR in staprun. Please file a bug report.\n" static void fatal_handler (int signum) { int rc; char *str = strsignal(signum); rc = write (STDERR_FILENO, ERR_MSG, sizeof(ERR_MSG)); rc = write (STDERR_FILENO, str, strlen(str)); rc = write (STDERR_FILENO, "\n", 1); (void) rc; /* notused */ _exit(1); } void setup_signals(void) { sigset_t s; struct sigaction a; /* blocking all signals while we set things up */ sigfillset(&s); #ifdef SINGLE_THREADED sigprocmask(SIG_SETMASK, &s, NULL); #else pthread_sigmask(SIG_SETMASK, &s, NULL); #endif /* set some of them to be ignored */ memset(&a, 0, sizeof(a)); sigfillset(&a.sa_mask); a.sa_handler = SIG_IGN; sigaction(SIGPIPE, &a, NULL); sigaction(SIGUSR2, &a, NULL); /* for serious errors, handle them in fatal_handler */ a.sa_handler = fatal_handler; sigaction(SIGBUS, &a, NULL); sigaction(SIGFPE, &a, NULL); sigaction(SIGILL, &a, NULL); sigaction(SIGSEGV, &a, NULL); sigaction(SIGXCPU, &a, NULL); sigaction(SIGXFSZ, &a, NULL); /* unblock all signals */ sigemptyset(&s); #ifdef SINGLE_THREADED sigprocmask(SIG_SETMASK, &s, NULL); #else pthread_sigmask(SIG_SETMASK, &s, NULL); #endif } /* * set FD_CLOEXEC for any file descriptor */ int set_clexec(int fd) { int val; if ((val = fcntl(fd, F_GETFD, 0)) < 0) goto err; if ((val = fcntl(fd, F_SETFD, val | FD_CLOEXEC)) < 0) goto err; return 0; err: perr("fcntl failed"); close(fd); return -1; } /** * send_request - send request to kernel over control channel * @type: the relay-app command id * @data: pointer to the data to be sent * @len: length of the data to be sent * * Returns 0 on success, non-zero otherwise. */ int send_request(int type, void *data, int len) { char buf[1024]; int rc = 0; PROBE3(stapio, send__ctlmsg, type, data, len); /* Before doing memcpy, make sure 'buf' is big enough. */ if ((len + sizeof(type)) > (int)sizeof(buf)) { _err(_("exceeded maximum send_request size.\n")); return -1; } memcpy(buf, &type, sizeof (type)); memcpy(&buf[sizeof (type)], data, len); errno = 0; assert (control_channel >= 0); rc = write (control_channel, buf, len + sizeof (type)); if (rc < 0) return rc; /* A bug in the transport layer of older modules causes them to return sizeof (type) fewer bytes written than actual. This is fixed in newer modules. So accept both. */ return (rc != len && rc != len + (int)sizeof (type)); } #include static int use_syslog = 0; void eprintf(const char *fmt, ...) { va_list va; va_start(va, fmt); if (use_syslog) vsyslog(LOG_ERR, fmt, va); else vfprintf(stderr, fmt, va); va_end(va); } void switch_syslog(const char *name) { openlog(name, LOG_PID, LOG_DAEMON); use_syslog = 1; color_errors = 0; } void print_color(const char *type) { if (!color_errors) return; if (type == NULL) // Reset eprintf("\033[m\033[K"); else { char *seq = parse_stap_color(type); if (seq != NULL) { eprintf("\033["); eprintf(seq); eprintf("m\033[K"); free(seq); } } } /* Parse SYSTEMTAP_COLORS and returns the SGR parameter(s) for the given type. The env var SYSTEMTAP_COLORS must be in the following format: 'key1=val1:key2=val2:' etc... where valid keys are 'error', 'warning', 'source', 'caret', 'token' and valid values constitute SGR parameter(s). For example, the default setting would be: 'error=01;31:warning=00;33:source=00;34:caret=01:token=01' */ char *parse_stap_color(const char *type) { const char *key, *col, *eq; int n = strlen(type); int done = 0; key = getenv("SYSTEMTAP_COLORS"); if (key == NULL || *key == '\0') key = "error=01;31:warning=00;33:source=00;34:caret=01:token=01"; while (!done) { if (!(col = strchr(key, ':'))) { col = strchr(key, '\0'); done = 1; } if (!((eq = strchr(key, '=')) && eq < col)) return NULL; /* invalid syntax: no = in range */ if (!(key < eq && eq < col-1)) return NULL; /* invalid syntax: key or val empty */ if (strspn(eq+1, "0123456789;") < (size_t)(col-eq-1)) return NULL; /* invalid syntax: invalid char in val */ if (eq-key == n && !strncmp(key, type, n)) return strndup(eq+1, col-eq-1); if (!done) key = col+1; /* advance to next key */ } return NULL; /* key not found */ } systemtap-2.3/staprun/ctl.c000066400000000000000000000102351217430427200160340ustar00rootroot00000000000000/* -*- linux-c -*- * * ctl.c - staprun control channel * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. * * Copyright (C) 2012 Red Hat Inc. */ #include "staprun.h" #define CTL_CHANNEL_NAME ".cmd" int init_ctl_channel(const char *name, int verb) { char buf[PATH_MAX]; struct statfs st; int old_transport = 0; (void) verb; if (0) goto out; /* just to defeat gcc warnings */ #ifdef HAVE_OPENAT if (relay_basedir_fd >= 0) { strncpy(buf, CTL_CHANNEL_NAME, PATH_MAX); control_channel = openat(relay_basedir_fd, CTL_CHANNEL_NAME, O_RDWR); dbug(2, "Opened %s (%d)\n", CTL_CHANNEL_NAME, control_channel); /* NB: Extra real-id access check as below */ if (faccessat(relay_basedir_fd, CTL_CHANNEL_NAME, R_OK|W_OK, 0) != 0){ close(control_channel); return -5; } if (control_channel >= 0) goto out; /* It's OK to bypass the [f]access[at] check below, since this would only occur the *second* time staprun tries this gig, or within unprivileged stapio. */ } /* PR14245, NB: we fall through to /sys ... /proc searching, in case the relay_basedir_fd option wasn't given (i.e., for early in staprun), or if errors out for some reason. */ #endif if (statfs("/sys/kernel/debug", &st) == 0 && (int)st.f_type == (int)DEBUGFS_MAGIC) { /* PR14245: allow subsequent operations, and if necessary, staprun->stapio forks, to reuse an fd for directory lookups (even if some parent directories have perms 0700. */ #ifdef HAVE_OPENAT if (! sprintf_chk(buf, "/sys/kernel/debug/systemtap/%s", name)) { relay_basedir_fd = open (buf, O_DIRECTORY | O_RDONLY); /* If this fails, we don't much care; the negative return value will just keep us looking up by name again next time. */ /* NB: we don't plan to close this fd, so that we can pass it across staprun->stapio fork/execs. */ } #endif if (sprintf_chk(buf, "/sys/kernel/debug/systemtap/%s/%s", name, CTL_CHANNEL_NAME)) return -1; } else { old_transport = 1; if (sprintf_chk(buf, "/proc/systemtap/%s/%s", name, CTL_CHANNEL_NAME)) return -2; } control_channel = open(buf, O_RDWR); dbug(2, "Opened %s (%d)\n", buf, control_channel); /* NB: Even if open() succeeded with effective-UID permissions, we * need the access() check to make sure real-UID permissions are also * sufficient. When we run under the setuid staprun, effective and * real UID may not be the same. Specifically, we want to prevent * a local stapusr from trying to attach to a different stapusr's module. * * The access() is done *after* open() to avoid any TOCTOU-style race * condition. We believe it's probably safe either way, as the file * we're trying to access connot be modified by a typical user, but * better safe than sorry. */ #ifdef HAVE_OPENAT if (control_channel >= 0 && relay_basedir_fd >= 0) { if (faccessat (relay_basedir_fd, CTL_CHANNEL_NAME, R_OK|W_OK, 0) == 0) goto out; /* else fall through */ } #endif if (control_channel >= 0 && access(buf, R_OK|W_OK) != 0) { close(control_channel); return -5; } out: if (control_channel < 0) { err(_("Cannot attach to module %s control channel; not running?\n"), name); return -3; } if (set_clexec(control_channel) < 0) return -4; return old_transport; } void close_ctl_channel(void) { if (control_channel >= 0) { dbug(2, "Closed ctl fd %d\n", control_channel); close(control_channel); control_channel = -1; } } systemtap-2.3/staprun/mainloop.c000066400000000000000000000574041217430427200171010ustar00rootroot00000000000000/* -*- linux-c -*- * * mainloop - stapio main loop * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. * * Copyright (C) 2005-2010 Red Hat Inc. */ #include "staprun.h" #include #include #include #include #include #define WORKAROUND_BZ467568 1 /* PR 6964; XXX: autoconf when able */ /* globals */ int ncpus; static int use_old_transport = 0; static int pending_interrupts = 0; static int target_pid_failed_p = 0; /* Setup by setup_main_signals, used by signal_thread to notify the main thread of interruptable events. */ static pthread_t main_thread; static void *signal_thread(void *arg) { sigset_t *s = (sigset_t *) arg; int signum = 0; while (1) { if (sigwait(s, &signum) < 0) { _perr("sigwait"); continue; } dbug(2, "sigproc %d (%s)\n", signum, strsignal(signum)); if (signum == SIGQUIT) { pending_interrupts += 2; break; } else if (signum == SIGINT || signum == SIGHUP || signum == SIGTERM) { pending_interrupts ++; break; } } /* Notify main thread (interrupts select). */ pthread_kill (main_thread, SIGURG); return NULL; } static void urg_proc(int signum) { /* This handler is just notified from the signal_thread whenever an interruptable condition is detected. The handler itself doesn't do anything. But this will result select to detect an EINTR event. */ dbug(2, "urg_proc %d (%s)\n", signum, strsignal(signum)); } static void chld_proc(int signum) { int32_t rc, btype = STP_EXIT; int chld_stat = 0; dbug(2, "chld_proc %d (%s)\n", signum, strsignal(signum)); pid_t pid = waitpid(-1, &chld_stat, WNOHANG); if (pid != target_pid) { return; } if (chld_stat) { // our child exited with a non-zero status if (WIFSIGNALED(chld_stat)) { warn(_("Child process exited with signal %d (%s)\n"), WTERMSIG(chld_stat), strsignal(WTERMSIG(chld_stat))); target_pid_failed_p = 1; } if (WIFEXITED(chld_stat) && WEXITSTATUS(chld_stat)) { warn(_("Child process exited with status %d\n"), WEXITSTATUS(chld_stat)); target_pid_failed_p = 1; } } rc = write(control_channel, &btype, sizeof(btype)); // send STP_EXIT (void) rc; /* XXX: notused */ } #if WORKAROUND_BZ467568 /* When a SIGUSR1 signal arrives, set this variable. */ volatile sig_atomic_t usr1_interrupt = 0; static void signal_usr1(int signum) { (void) signum; usr1_interrupt = 1; } #endif /* WORKAROUND_BZ467568 */ static void setup_main_signals(void) { pthread_t tid; struct sigaction sa; sigset_t *s = malloc(sizeof(*s)); if (!s) { _perr("malloc failed"); exit(1); } /* The main thread will only handle SIGCHLD and SIGURG. SIGURG is send from the signal thread in case the interrupt flag is set. This will then interrupt any select call. */ main_thread = pthread_self(); sigfillset(s); pthread_sigmask(SIG_SETMASK, s, NULL); memset(&sa, 0, sizeof(sa)); /* select will report EINTR even when SA_RESTART is set. */ sa.sa_flags = SA_RESTART; sigfillset(&sa.sa_mask); /* Ignore all these events on the main thread. */ sa.sa_handler = SIG_IGN; sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); sigaction(SIGHUP, &sa, NULL); sigaction(SIGQUIT, &sa, NULL); /* This is to notify when our child process (-c) ends. */ sa.sa_handler = chld_proc; sigaction(SIGCHLD, &sa, NULL); /* This signal handler is notified from the signal_thread whenever a interruptable event is detected. It will result in an EINTR event for select or sleep. */ sa.sa_handler = urg_proc; sigaction(SIGURG, &sa, NULL); /* Everything else is handled on a special signal_thread. */ sigemptyset(s); sigaddset(s, SIGINT); sigaddset(s, SIGTERM); sigaddset(s, SIGHUP); sigaddset(s, SIGQUIT); pthread_sigmask(SIG_SETMASK, s, NULL); if (pthread_create(&tid, NULL, signal_thread, s) < 0) { _perr(_("failed to create thread")); exit(1); } } /* * start_cmd forks the command given on the command line with the "-c" * option. It will wait just at the cusp of the exec until we get the * signal from the kernel to let it run. We do it this way because we * must have the pid of the forked command so it can be set to the * module and made available internally as _stp_target. PTRACE_DETACH * is sent from stp_main_loop() below when it receives STP_START from * the module. */ void start_cmd(void) { pid_t pid; struct sigaction a; #if WORKAROUND_BZ467568 struct sigaction usr1_action, old_action; sigset_t blockmask, oldmask; #endif /* WORKAROUND_BZ467568 */ /* if we are execing a target cmd, ignore ^C in stapio */ /* and let the target cmd get it. */ memset(&a, 0, sizeof(a)); sigemptyset(&a.sa_mask); a.sa_flags = 0; a.sa_handler = SIG_IGN; sigaction(SIGINT, &a, NULL); #if WORKAROUND_BZ467568 /* Set up the mask of signals to temporarily block. */ sigemptyset (&blockmask); sigaddset (&blockmask, SIGUSR1); /* Establish the SIGUSR1 signal handler. */ memset(&usr1_action, 0, sizeof(usr1_action)); sigfillset (&usr1_action.sa_mask); usr1_action.sa_flags = 0; usr1_action.sa_handler = signal_usr1; sigaction (SIGUSR1, &usr1_action, &old_action); /* Block SIGUSR1 */ sigprocmask(SIG_BLOCK, &blockmask, &oldmask); #endif /* WORKAROUND_BZ467568 */ if ((pid = fork()) < 0) { _perr("fork"); exit(1); } else if (pid == 0) { /* We're in the target process. Let's start the execve of target_cmd, */ int rc; wordexp_t words; char *sh_c_argv[4] = { NULL, NULL, NULL, NULL }; a.sa_handler = SIG_DFL; sigaction(SIGINT, &a, NULL); /* Formerly, we just execl'd(sh,-c,$target_cmd). But this does't work well if target_cmd is a shell builtin. We really want to probe a new child process, not a mishmash of shell-interpreted stuff. */ rc = wordexp (target_cmd, & words, WRDE_NOCMD|WRDE_UNDEF); if (rc == WRDE_BADCHAR) { /* The user must have used a shell metacharacter, thinking that we use system(3) to evaluate 'stap -c CMD'. We could generate an error message ... but let's just do what the user meant. rhbz 467652. */ sh_c_argv[0] = "sh"; sh_c_argv[1] = "-c"; sh_c_argv[2] = target_cmd; sh_c_argv[3] = NULL; } else { switch (rc) { case 0: break; case WRDE_SYNTAX: _err (_("wordexp: syntax error (unmatched quotes?) in -c COMMAND\n")); _exit(1); default: _err (_("wordexp: parsing error (%d)\n"), rc); _exit (1); } if (words.we_wordc < 1) { _err ("empty -c COMMAND"); _exit (1); } } /* PR 6964: when tracing all the user space process including the child the signal will be messed due to uprobe module or utrace bug. The kernel sometimes crashes. So as an alternative approximation, we just wait here for a signal from the parent. */ dbug(1, "blocking briefly\n"); #if WORKAROUND_BZ467568 { /* Wait for the SIGUSR1 */ while (!usr1_interrupt) sigsuspend(&oldmask); /* Restore the old SIGUSR1 signal handler. */ sigaction (SIGUSR1, &old_action, NULL); /* Restore the original signal mask */ sigprocmask(SIG_SETMASK, &oldmask, NULL); } #else /* !WORKAROUND_BZ467568 */ rc = ptrace (PTRACE_TRACEME, 0, 0, 0); if (rc < 0) perror ("ptrace me"); raise (SIGCONT); /* Harmless; just passes control to parent. */ #endif /* !WORKAROUND_BZ467568 */ dbug(1, "execing target_cmd %s\n", target_cmd); /* Note that execvp() is not a direct system call; it does a $PATH search in glibc. We would like to filter out these dummy syscalls from the utrace events seen by scripts. This filtering would be done for us for free, if we used ptrace ... but see PR6964. XXX: Instead, we could open-code the $PATH search here; put the pause() afterward; and run a direct execve instead of execvp(). */ if (execvp ((sh_c_argv[0] == NULL ? words.we_wordv[0] : sh_c_argv[0]), (sh_c_argv[0] == NULL ? words.we_wordv : sh_c_argv)) < 0) perror(target_cmd); /* (There is no need to wordfree() words; they are or will be gone.) */ _exit(1); } else { /* We're in the parent. The child will parse target_cmd and execv() the result. It will be stopped thereabouts and send us a SIGTRAP. Or rather, due to PR 6964, it will stop itself and wait for us to release it. */ target_pid = pid; #if WORKAROUND_BZ467568 /* Restore the old SIGUSR1 signal handler. */ sigaction (SIGUSR1, &old_action, NULL); /* Restore the original signal mask */ sigprocmask(SIG_SETMASK, &oldmask, NULL); #else /* !WORKAROUND_BZ467568 */ int status; waitpid (target_pid, &status, 0); dbug(1, "waited for target_cmd %s pid %d status %x\n", target_cmd, target_pid, (unsigned) status); #endif /* !WORKAROUND_BZ467568 */ } } /** * system_cmd() executes system commands in response * to an STP_SYSTEM message from the module. These * messages are sent by the system() systemtap function. */ void system_cmd(char *cmd) { pid_t pid; dbug(2, "system %s\n", cmd); if ((pid = fork()) < 0) { _perr("fork"); } else if (pid == 0) { if (execlp("sh", "sh", "-c", cmd, NULL) < 0) perr("%s", cmd); _exit(1); } } /* This is only used in the old relayfs code */ static void read_buffer_info(void) { char buf[PATH_MAX]; struct statfs st; int fd, len, ret; /* NB: we don't have to worry about PR14245 on old_transport aka rhel4; no HAVE_OPENAT, and thus no -F fd option. */ if (!use_old_transport) return; if (statfs("/sys/kernel/debug", &st) == 0 && (int)st.f_type == (int)DEBUGFS_MAGIC) return; if (sprintf_chk(buf, "/proc/systemtap/%s/bufsize", modname)) return; fd = open(buf, O_RDONLY); if (fd < 0) return; len = read(fd, buf, sizeof(buf)); if (len <= 0) { perr(_("Couldn't read bufsize")); close(fd); return; } ret = sscanf(buf, "%u,%u", &n_subbufs, &subbuf_size); if (ret != 2) perr(_("Couldn't read bufsize")); dbug(2, "n_subbufs= %u, size=%u\n", n_subbufs, subbuf_size); close(fd); return; } /** * init_stapio - initialize the app * @print_summary: boolean, print summary or not at end of run * * Returns 0 on success, negative otherwise. */ int init_stapio(void) { dbug(2, "init_stapio\n"); /* create control channel */ use_old_transport = init_ctl_channel(modname, 1); if (use_old_transport < 0) { err(_("Failed to initialize control channel.\n")); return -1; } read_buffer_info(); if (attach_mod) { dbug(2, "Attaching\n"); if (use_old_transport) { if (init_oldrelayfs() < 0) { close_ctl_channel(); return -1; } } else { if (init_relayfs() < 0) { close_ctl_channel(); return -1; } } return 0; } /* fork target_cmd if requested. */ /* It will not actually exec until signalled. */ if (target_cmd) start_cmd(); /* Run in background */ if (daemon_mode) { pid_t pid; int ret; dbug(2, "daemonizing stapio\n"); /* daemonize */ ret = daemon(0, 1); /* don't close stdout at this time. */ if (ret) { err(_("Failed to daemonize stapio\n")); return -1; } /* change error messages to syslog. */ switch_syslog("stapio"); /* show new pid */ pid = getpid(); fprintf(stdout, "%d\n", pid); fflush(stdout); /* redirect all outputs to /dev/null */ ret = open("/dev/null", O_RDWR); if (ret < 0) { err(_("Failed to open /dev/null\n")); return -1; } close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); dup2(ret, STDOUT_FILENO); dup2(ret, STDERR_FILENO); close(ret); } return 0; } /* cleanup_and_exit() closed channels, frees memory, * removes the module (if necessary) and exits. */ void cleanup_and_exit(int detach, int rc) { static int exiting = 0; const char *staprun; pid_t pid; int rstatus; struct sigaction sa; if (exiting) return; exiting = 1; setup_main_signals(); dbug(1, "detach=%d\n", detach); /* NB: We don't really need to wait for child processes. Any that were started by the system() tapset function (system_cmd() above) can run loose. Or, a target_cmd (stap -c CMD) may have already started and stopped. */ /* OTOH, it may be still be running - but there's no need for us to wait for it, considering that the script must have exited for another reason. So, we no longer while(...wait()...); here. XXX: we could consider killing it. */ if (use_old_transport) close_oldrelayfs(detach); else close_relayfs(); dbug(1, "closing control channel\n"); close_ctl_channel(); if (detach) { eprintf(_("\nDisconnecting from systemtap module.\n" "To reconnect, type \"staprun -A %s\"\n"), modname); _exit(0); } else if (rename_mod) dbug(2, "\nRenamed module to: %s\n", modname); /* At this point, we're committed to calling staprun -d MODULE to * unload the thing and exit. */ /* Due to PR9788, we fork and exec the setuid staprun only in a child process. */ staprun = getenv ("SYSTEMTAP_STAPRUN") ?: BINDIR "/staprun"; dbug(2, "removing %s\n", modname); // So that waitpid() below will work correctly, we need to clear // out our SIGCHLD handler. memset(&sa, 0, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = SIG_DFL; sigaction(SIGCHLD, &sa, NULL); pid = fork(); if (pid < 0) { _perr("fork"); _exit(-1); } if (pid == 0) { /* child process */ /* Run the command. */ char *cmd; int rc = asprintf(&cmd, "%s %s %s -d -C %s '%s'", staprun, (verbose >= 1) ? "-v" : "", (verbose >= 2) ? "-v" : "", color_mode == color_always ? "always" : color_mode == color_auto ? "auto" : "never", modname); if (rc >= 1) { execlp("sh", "sh", "-c", cmd, NULL); /* should not return */ perror(staprun); _exit(-1); } else { perror("asprintf"); _exit(-1); } } /* parent process */ if (waitpid(pid, &rstatus, 0) < 0) { _perr("waitpid"); _exit(-1); } if (WIFEXITED(rstatus)) { if(rc || target_pid_failed_p || rstatus) // if we have an error _exit(1); else _exit(0); //success } _exit(-1); } /** * stp_main_loop - loop forever reading data */ int stp_main_loop(void) { ssize_t nb; FILE *ofp = stdout; struct { uint32_t type; union { char data[8192]; struct _stp_msg_start start; struct _stp_msg_cmd cmd; } payload; } recvbuf; int error_detected = 0; int select_supported; int flags; int res; int rc; struct timeval tv; fd_set fds; sigset_t blockset, mainset; setvbuf(ofp, (char *)NULL, _IONBF, 0); setup_main_signals(); dbug(2, "in main loop\n"); rc = send_request(STP_READY, NULL, 0); if (rc != 0) { perror ("Unable to send STP_READY"); cleanup_and_exit (1, rc); } flags = fcntl(control_channel, F_GETFL); /* Make select return immediately. We just check whether there is an exception available on the control_channel, which is how we know the module supports select. */ tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(control_channel, &fds); res = select(control_channel + 1, NULL, NULL, &fds, &tv); select_supported = (res == 1 && FD_ISSET(control_channel, &fds)); dbug(2, "select_supported: %d\n", select_supported); if (select_supported) { /* We block SIGURG to the main thread, except when we call pselect(). This makes sure we won't miss any signals. All other calls are non-blocking, so we defer till pselect() time, which is when we are "sleeping". */ sigemptyset(&blockset); sigaddset(&blockset, SIGURG); pthread_sigmask(SIG_BLOCK, &blockset, &mainset); } /* handle messages from control channel */ while (1) { if (pending_interrupts) { int btype = STP_EXIT; int rc = write(control_channel, &btype, sizeof(btype)); dbug(2, "signal-triggered %d exit rc %d\n", pending_interrupts, rc); if (pending_interrupts >= 2) { cleanup_and_exit (1, 0); } } /* If the runtime does not implement select() on the command filehandle, we have to poll periodically. The polling interval can be relatively large, since we don't receive EAGAIN during the time-sensitive startup period (packets go back-to-back). */ flags |= O_NONBLOCK; fcntl(control_channel, F_SETFL, flags); nb = read(control_channel, &recvbuf, sizeof(recvbuf)); flags &= ~O_NONBLOCK; fcntl(control_channel, F_SETFL, flags); dbug(3, "nb=%ld\n", (long)nb); if (nb < (ssize_t) sizeof(recvbuf.type)) { if (nb >= 0 || (errno != EINTR && errno != EAGAIN)) { _perr(_("Unexpected EOF in read (nb=%ld)"), (long)nb); cleanup_and_exit(0, 1); } if (!select_supported) { dbug(4, "sleeping\n"); usleep (250*1000); /* sleep 250ms between polls */ } else { FD_ZERO(&fds); FD_SET(control_channel, &fds); res = pselect(control_channel + 1, &fds, NULL, NULL, NULL, &mainset); if (res < 0 && errno != EINTR) { _perr(_("Unexpected error in select")); cleanup_and_exit(0, 1); } } continue; } nb -= sizeof(recvbuf.type); PROBE3(staprun, recv__ctlmsg, recvbuf.type, recvbuf.payload.data, nb); switch (recvbuf.type) { #if STP_TRANSPORT_VERSION == 1 case STP_REALTIME_DATA: if (write_realtime_data(recvbuf.payload.data, nb)) { _perr(_("write error (nb=%ld)"), (long)nb); cleanup_and_exit(0, 1); } break; #endif case STP_OOB_DATA: /* Note that "WARNING:" should not be translated, since it is * part of the module cmd protocol. */ if (strncmp(recvbuf.payload.data, "WARNING: ", 9) == 0) { if (suppress_warnings) break; if (verbose) { /* don't eliminate duplicates */ /* trim "WARNING: " */ warn("%.*s", (int) nb-9, recvbuf.payload.data+9); break; } else { /* eliminate duplicates */ static void *seen = 0; static unsigned seen_count = 0; char *dupstr = strndup (recvbuf.payload.data, (int) nb); char *retval; if (! dupstr) { /* OOM, should not happen. */ /* trim "WARNING: " */ warn("%.*s", (int) nb-9, recvbuf.payload.data+9); break; } retval = tfind (dupstr, & seen, (int (*)(const void*, const void*))strcmp); if (! retval) { /* new message */ /* trim "WARNING: " */ warn("%.*s", strlen(dupstr)-9, dupstr+9); /* We set a maximum for stored warning messages, to prevent a misbehaving script/environment from emitting countless _stp_warn()s, and overflow staprun's memory. */ #define MAX_STORED_WARNINGS 1024 if (seen_count++ == MAX_STORED_WARNINGS) { eprintf(_("WARNING deduplication table full\n")); free (dupstr); } else if (seen_count > MAX_STORED_WARNINGS) { /* Be quiet in the future, but stop counting to preclude overflow. */ free (dupstr); seen_count = MAX_STORED_WARNINGS+1; } else if (seen_count < MAX_STORED_WARNINGS) { /* NB: don't free dupstr; it's going into the tree. */ retval = tsearch (dupstr, & seen, (int (*)(const void*, const void*))strcmp); if (retval == 0) { /* OOM, should not happen */ /* Next time we should get the 'full' message. */ free (dupstr); seen_count = MAX_STORED_WARNINGS; } } } else { /* old message */ free (dupstr); } } /* duplicate elimination */ /* Note that "ERROR:" should not be translated, since it is * part of the module cmd protocol. */ } else if (strncmp(recvbuf.payload.data, "ERROR: ", 7) == 0) { /* trim "ERROR: " */ err("%.*s", (int) nb-7, recvbuf.payload.data+7); error_detected = 1; } else { /* neither warning nor error */ eprintf("%.*s", (int) nb, recvbuf.payload.data); } break; case STP_EXIT: { /* module asks us to unload it and exit */ dbug(2, "got STP_EXIT\n"); cleanup_and_exit(0, error_detected); break; } case STP_REQUEST_EXIT: { /* module asks us to start exiting, so send STP_EXIT */ dbug(2, "got STP_REQUEST_EXIT\n"); int32_t rc, btype = STP_EXIT; rc = write(control_channel, &btype, sizeof(btype)); (void) rc; /* XXX: notused */ break; } case STP_START: { struct _stp_msg_start *t = &recvbuf.payload.start; dbug(2, "systemtap_module_init() returned %d\n", t->res); if (t->res < 0) { if (target_cmd) kill(target_pid, SIGKILL); cleanup_and_exit(0, 1); } else if (target_cmd) { dbug(1, "detaching pid %d\n", target_pid); #if WORKAROUND_BZ467568 /* Let's just send our pet signal to the child process that should be waiting for us, mid-pause(). */ kill (target_pid, SIGUSR1); #else /* Were it not for PR6964, we'd like to do it this way: */ int rc = ptrace (PTRACE_DETACH, target_pid, 0, 0); if (rc < 0) { perror (_("ptrace detach")); if (target_cmd) kill(target_pid, SIGKILL); cleanup_and_exit(0, 1); } #endif } break; } case STP_SYSTEM: { struct _stp_msg_cmd *c = &recvbuf.payload.cmd; dbug(2, "STP_SYSTEM: %s\n", c->cmd); system_cmd(c->cmd); break; } case STP_TRANSPORT: { struct _stp_msg_start ts; if (use_old_transport) { if (init_oldrelayfs() < 0) cleanup_and_exit(0, 1); } else { if (init_relayfs() < 0) cleanup_and_exit(0, 1); } ts.target = target_pid; rc = send_request(STP_START, &ts, sizeof(ts)); if (rc != 0) { perror ("Unable to send STP_START"); cleanup_and_exit (1, rc); } if (load_only) cleanup_and_exit(1, 0); break; } default: warn(_("Ignored message of type %d\n"), recvbuf.type); } } fclose(ofp); return 0; } systemtap-2.3/staprun/modverify.c000066400000000000000000000303101217430427200172520ustar00rootroot00000000000000/* This program verifies the given file using the given signature, the named certificate and public key in the given certificate database. Copyright (C) 2009-2013 Red Hat Inc. This file is part of systemtap, and 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, see . */ #include "../config.h" #include "staprun.h" #include #include #include #include #include #include #include #include #include #include #include "../nsscommon.h" #include "modverify.h" // Called by some of the functions in nsscommon.cxx. void nsscommon_error (const char *msg, int logit __attribute ((unused))) { fprintf (stderr, "%s\n", msg); fflush (stderr); } /* Function: int check_cert_db_permissions (const char *cert_db_path); * * Check that the given certificate directory and its contents have * the correct permissions. * * Returns 0 if there is an error, 1 otherwise. */ static int check_db_file_permissions (const char *cert_db_file) { struct stat info; int rc; rc = stat (cert_db_file, & info); if (rc) { fprintf (stderr, "Could not obtain information on certificate database file %s.\n", cert_db_file); perror (""); return 0; } rc = 1; /* ok */ /* The owner of the file must be root. */ if (info.st_uid != 0) { fprintf (stderr, "Certificate database file %s must be owned by root.\n", cert_db_file); rc = 0; } /* Check the access permissions of the file. */ if ((info.st_mode & S_IRUSR) == 0) fprintf (stderr, "Certificate database file %s should be readable by the owner.\n", cert_db_file); if ((info.st_mode & S_IWUSR) == 0) fprintf (stderr, "Certificate database file %s should be writable by the owner.\n", cert_db_file); if ((info.st_mode & S_IXUSR) != 0) { fprintf (stderr, "Certificate database file %s must not be executable by the owner.\n", cert_db_file); rc = 0; } if ((info.st_mode & S_IRGRP) == 0) { fprintf (stderr, "Certificate database file %s should be readable by the group.\n", cert_db_file); rc = 0; } if ((info.st_mode & S_IWGRP) != 0) { fprintf (stderr, "Certificate database file %s must not be writable by the group.\n", cert_db_file); rc = 0; } if ((info.st_mode & S_IXGRP) != 0) { fprintf (stderr, "Certificate database file %s must not be executable by the group.\n", cert_db_file); rc = 0; } if ((info.st_mode & S_IROTH) == 0) { fprintf (stderr, "Certificate database file %s should be readable by others.\n", cert_db_file); rc = 0; } if ((info.st_mode & S_IWOTH) != 0) { fprintf (stderr, "Certificate database file %s must not be writable by others.\n", cert_db_file); rc = 0; } if ((info.st_mode & S_IXOTH) != 0) { fprintf (stderr, "Certificate database file %s must not be executable by others.\n", cert_db_file); rc = 0; } return rc; } /* Function: int check_cert_db_permissions (const char *cert_db_path); * * Check that the given certificate directory and its contents have * the correct permissions. * * Returns 0 if there is an error, 1 otherwise. */ static int check_cert_db_permissions (const char *cert_db_path) { struct stat info; char *fileName; int rc; rc = stat (cert_db_path, & info); if (rc) { /* It is ok if the directory does not exist. This simply means that no signing certificates have been authorized yet. */ if (errno == ENOENT) return 0; fprintf (stderr, "Could not obtain information on certificate database directory %s.\n", cert_db_path); perror (""); return 0; } if (! S_ISDIR (info.st_mode)) { fprintf (stderr, "Certificate database %s is not a directory.\n", cert_db_path); return 0; } /* The owner of the database must be root. */ if (info.st_uid != 0) { fprintf (stderr, "Certificate database directory %s must be owned by root.\n", cert_db_path); return 0; } rc = 1; /* ok */ /* Check the database directory access permissions */ if ((info.st_mode & S_IRUSR) == 0) fprintf (stderr, "Certificate database %s should be readable by the owner.\n", cert_db_path); if ((info.st_mode & S_IWUSR) == 0) fprintf (stderr, "Certificate database %s should be writable by the owner.\n", cert_db_path); if ((info.st_mode & S_IXUSR) == 0) fprintf (stderr, "Certificate database %s should be searchable by the owner.\n", cert_db_path); if ((info.st_mode & S_IRGRP) == 0) fprintf (stderr, "Certificate database %s should be readable by the group.\n", cert_db_path); if ((info.st_mode & S_IWGRP) != 0) { fprintf (stderr, "Certificate database %s must not be writable by the group.\n", cert_db_path); rc = 0; } if ((info.st_mode & S_IXGRP) == 0) fprintf (stderr, "Certificate database %s should be searchable by the group.\n", cert_db_path); if ((info.st_mode & S_IROTH) == 0) fprintf (stderr, "Certificate database %s should be readable by others.\n", cert_db_path); if ((info.st_mode & S_IWOTH) != 0) { fprintf (stderr, "Certificate database %s must not be writable by others.\n", cert_db_path); rc = 0; } if ((info.st_mode & S_IXOTH) == 0) fprintf (stderr, "Certificate database %s should be searchable by others.\n", cert_db_path); /* Now check the permissions of the critical files. */ fileName = PORT_Alloc (strlen (cert_db_path) + 11); if (! fileName) { fprintf (stderr, "Unable to allocate memory for certificate database file names\n"); return 0; } /* These uses of sprintf() are OK, since we just allocated the * string to be the correct length. */ sprintf (fileName, "%s/cert8.db", cert_db_path); rc &= check_db_file_permissions (fileName); sprintf (fileName, "%s/key3.db", cert_db_path); rc &= check_db_file_permissions (fileName); sprintf (fileName, "%s/secmod.db", cert_db_path); rc &= check_db_file_permissions (fileName); PORT_Free (fileName); if (rc == 0) fprintf (stderr, "Unable to use certificate database %s due to errors.\n", cert_db_path); return rc; } static int verify_it (const char *signatureName, const SECItem *signature, const char *module_name, const void *module_data, off_t module_size, const SECKEYPublicKey *pubKey) { VFYContext *vfy; SECStatus secStatus; int rc = MODULE_OK; /* Create a verification context. */ vfy = VFY_CreateContextDirect (pubKey, signature, SEC_OID_PKCS1_RSA_ENCRYPTION, SEC_OID_UNKNOWN, NULL, NULL); if (! vfy) { /* The key does not match the signature. This is not an error. It just means we are currently trying the wrong certificate/key. i.e. the module remains untrusted for now. */ rc = MODULE_UNTRUSTED; goto done; } /* Begin the verification process. */ secStatus = VFY_Begin(vfy); if (secStatus != SECSuccess) { fprintf (stderr, "Unable to initialize verification context while verifying %s using the signature in %s.\n", module_name, signatureName); nssError (); rc = MODULE_CHECK_ERROR; goto done; } /* Add the data to be verified. */ secStatus = VFY_Update (vfy, module_data, module_size); if (secStatus != SECSuccess) { fprintf (stderr, "Error while verifying %s using the signature in %s.\n", module_name, signatureName); nssError (); rc = MODULE_CHECK_ERROR; goto done; } /* Complete the verification. */ secStatus = VFY_End (vfy); if (secStatus != SECSuccess) { fprintf (stderr, "Unable to verify the signed module %s. It may have been altered since it was created.\n", module_name); nssError (); rc = MODULE_ALTERED; } done: if (vfy) VFY_DestroyContext(vfy, PR_TRUE /*freeit*/); return rc; } int verify_module (const char *signatureName, const char* module_name, const void *module_data, off_t module_size) { const char *dbdir = SYSCONFDIR "/systemtap/staprun"; SECKEYPublicKey *pubKey; SECStatus secStatus; CERTCertList *certList; CERTCertListNode *certListNode; CERTCertificate *cert; PRStatus prStatus; PRFileInfo info; PRInt32 numBytes; PRFileDesc *local_file_fd; SECItem signature; int rc = 0; /* Call the NSPR initialization routines. */ /* XXX: We shouldn't be using NSPR for a lot of this. */ PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); /* Get the size of the signature file. */ prStatus = PR_GetFileInfo (signatureName, &info); if (prStatus != PR_SUCCESS || info.type != PR_FILE_FILE || info.size < 0) { if (verbose>1) fprintf (stderr, "Signature file %s not found\n", signatureName); PR_Cleanup (); return MODULE_UNTRUSTED; /* Not signed */ } /* Open the signature file. */ local_file_fd = PR_Open (signatureName, PR_RDONLY, 0); if (local_file_fd == NULL) { fprintf (stderr, "Could not open the signature file %s\n.", signatureName); nssError (); PR_Cleanup (); return MODULE_CHECK_ERROR; } /* Allocate space to read the signature file. */ signature.data = PORT_Alloc (info.size); if (! signature.data) { fprintf (stderr, "Unable to allocate memory for the signature in %s.\n", signatureName); nssError (); PR_Cleanup (); return MODULE_CHECK_ERROR; } numBytes = PR_Read_Complete (local_file_fd, signature.data, info.size); if (numBytes == 0) /* EOF */ { fprintf (stderr, "EOF reading signature file %s.\n", signatureName); PR_Cleanup (); return MODULE_CHECK_ERROR; } if (numBytes < 0) { fprintf (stderr, "Error reading signature file %s.\n", signatureName); nssError (); PR_Cleanup (); return MODULE_CHECK_ERROR; } if (numBytes != info.size) { fprintf (stderr, "Incomplete data while reading signature file %s.\n", signatureName); PR_Cleanup (); return MODULE_CHECK_ERROR; } signature.len = info.size; /* Done with the signature file. */ PR_Close (local_file_fd); /* Verify the permissions of the certificate database and its files. */ if (! check_cert_db_permissions (dbdir)) { if (verbose>1) fprintf (stderr, "Certificate db %s permissions too loose\n", dbdir); PR_Cleanup (); return MODULE_UNTRUSTED; } /* Initialize NSS. */ secStatus = nssInit (dbdir, 0/*readwrite*/, 1/*issueMessage*/); if (secStatus != SECSuccess) { // Message already issued. return MODULE_CHECK_ERROR; } certList = PK11_ListCerts (PK11CertListAll, NULL); if (certList == NULL) { fprintf (stderr, "Unable to find certificates in the certificate database in %s.\n", dbdir); nssError (); nssCleanup (dbdir); return MODULE_UNTRUSTED; } /* We need to look at each certificate in the database. */ for (certListNode = CERT_LIST_HEAD (certList); ! CERT_LIST_END (certListNode, certList); certListNode = CERT_LIST_NEXT (certListNode)) { cert = certListNode->cert; pubKey = CERT_ExtractPublicKey (cert); if (pubKey == NULL) { fprintf (stderr, "Unable to extract public key from the certificate with nickname %s from the certificate database in %s.\n", cert->nickname, dbdir); nssError (); rc = MODULE_CHECK_ERROR; break; } /* Verify the file. */ rc = verify_it (signatureName, & signature, module_name, module_data, module_size, pubKey); if (rc == MODULE_OK || rc == MODULE_ALTERED || rc == MODULE_CHECK_ERROR) break; /* resolved or error */ } CERT_DestroyCertList (certList); /* Shutdown NSS and exit NSPR gracefully. */ nssCleanup (dbdir); PR_Cleanup (); return rc; } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/staprun/modverify.h000066400000000000000000000005301217430427200172600ustar00rootroot00000000000000int verify_module (const char *signature_name, const char *module_name, const void *module_data, off_t module_size); /* return codes for verify_module. */ #define MODULE_OK 1 #define MODULE_UNTRUSTED 0 #define MODULE_CHECK_ERROR -1 #define MODULE_ALTERED -2 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/staprun/relay.c000066400000000000000000000225731217430427200163760ustar00rootroot00000000000000/* -*- linux-c -*- * * relay.c - staprun relayfs functions * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. * * Copyright (C) 2007-2012 Red Hat Inc. */ #include "staprun.h" int out_fd[NR_CPUS]; static pthread_t reader[NR_CPUS]; static int relay_fd[NR_CPUS]; static int switch_file[NR_CPUS]; static int bulkmode = 0; static volatile int stop_threads = 0; static time_t *time_backlog[NR_CPUS]; static int backlog_order=0; #define BACKLOG_MASK ((1 << backlog_order) - 1) #ifdef NEED_PPOLL int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, const sigset_t *sigmask) { sigset_t origmask; int ready; int tim; if (timeout == NULL) tim = -1; else tim = timeout->tv_sec * 1000 + timeout->tv_nsec / 1000000; sigprocmask(SIG_SETMASK, sigmask, &origmask); ready = poll(fds, nfds, tim); sigprocmask(SIG_SETMASK, &origmask, NULL); return ready; } #endif int init_backlog(int cpu) { int order = 0; if (!fnum_max) return 0; while (fnum_max >> order) order++; if (fnum_max == 1<<(order-1)) order--; time_backlog[cpu] = (time_t *)calloc(1<= fnum_max) remove_file = 1; if (open_outfile(*fnum, cpu, remove_file) < 0) { perr("Couldn't open file for cpu %d, exiting.", cpu); return -1; } return 0; } /** * reader_thread - per-cpu channel buffer reader */ static void *reader_thread(void *data) { char buf[131072]; int rc, cpu = (int)(long)data; struct pollfd pollfd; struct timespec tim = {.tv_sec=0, .tv_nsec=200000000}, *timeout = &tim; sigset_t sigs; off_t wsize = 0; int fnum = 0; sigemptyset(&sigs); sigaddset(&sigs,SIGUSR2); pthread_sigmask(SIG_BLOCK, &sigs, NULL); sigfillset(&sigs); sigdelset(&sigs,SIGUSR2); if (bulkmode) { cpu_set_t cpu_mask; CPU_ZERO(&cpu_mask); CPU_SET(cpu, &cpu_mask); if( sched_setaffinity( 0, sizeof(cpu_mask), &cpu_mask ) < 0 ) _perr("sched_setaffinity"); #ifdef NEED_PPOLL /* Without a real ppoll, there is a small race condition that could */ /* block ppoll(). So use a timeout to prevent that. */ timeout->tv_sec = 10; timeout->tv_nsec = 0; #else timeout = NULL; #endif } if (reader_timeout_ms && timeout) { timeout->tv_sec = reader_timeout_ms / 1000; timeout->tv_nsec = (reader_timeout_ms - timeout->tv_sec * 1000) * 1000000; } pollfd.fd = relay_fd[cpu]; pollfd.events = POLLIN; do { dbug(3, "thread %d start ppoll\n", cpu); rc = ppoll(&pollfd, 1, timeout, &sigs); dbug(3, "thread %d end ppoll:%d\n", cpu, rc); if (rc < 0) { dbug(3, "cpu=%d poll=%d errno=%d\n", cpu, rc, errno); if (errno == EINTR) { if (stop_threads) break; if (switch_file[cpu]) { if (switch_outfile(cpu, &fnum) < 0) goto error_out; switch_file[cpu] = 0; wsize = 0; } } else { _perr("poll error"); goto error_out; } } while ((rc = read(relay_fd[cpu], buf, sizeof(buf))) > 0) { /* Switching file */ if ((fsize_max && wsize + rc > fsize_max) || switch_file[cpu]) { if (switch_outfile(cpu, &fnum) < 0) goto error_out; switch_file[cpu] = 0; wsize = 0; } if (write(out_fd[cpu], buf, rc) != rc) { if (errno != EPIPE) perr("Couldn't write to output %d for cpu %d, exiting.", out_fd[cpu], cpu); goto error_out; } wsize += rc; } } while (!stop_threads); dbug(3, "exiting thread for cpu %d\n", cpu); return(NULL); error_out: /* Signal the main thread that we need to quit */ kill(getpid(), SIGTERM); dbug(2, "exiting thread for cpu %d after error\n", cpu); return(NULL); } static void switchfile_handler(int sig) { int i; if (stop_threads) return; for (i = 0; i < ncpus; i++) if (reader[i] && switch_file[i]) { dbug(2, "file switching is progressing, signal ignored.\n", sig); return; } for (i = 0; i < ncpus; i++) { if (reader[i]) { switch_file[i] = 1; pthread_kill(reader[i], SIGUSR2); } else break; } } /** * init_relayfs - create files and threads for relayfs processing * * Returns 0 if successful, negative otherwise */ int init_relayfs(void) { int i, len; struct statfs st; char rqbuf[128]; char buf[PATH_MAX], relay_filebase[PATH_MAX]; struct sigaction sa; dbug(2, "initializing relayfs\n"); reader[0] = (pthread_t)0; relay_fd[0] = 0; out_fd[0] = 0; if (relay_basedir_fd >= 0) strcpy(relay_filebase, "\0"); else if (statfs("/sys/kernel/debug", &st) == 0 && (int) st.f_type == (int) DEBUGFS_MAGIC) { if (sprintf_chk(relay_filebase, "/sys/kernel/debug/systemtap/%s/", modname)) return -1; } else { err("Cannot find relayfs or debugfs mount point.\n"); return -1; } if (send_request(STP_BULK, rqbuf, sizeof(rqbuf)) == 0) bulkmode = 1; for (i = 0; i < NR_CPUS; i++) { if (sprintf_chk(buf, "%strace%d", relay_filebase, i)) return -1; dbug(2, "attempting to open %s\n", buf); relay_fd[i] = -1; #ifdef HAVE_OPENAT if (relay_basedir_fd >= 0) relay_fd[i] = openat(relay_basedir_fd, buf, O_RDONLY | O_NONBLOCK); #endif if (relay_fd[i] < 0) relay_fd[i] = open(buf, O_RDONLY | O_NONBLOCK); if (relay_fd[i] < 0 || set_clexec(relay_fd[i]) < 0) break; } ncpus = i; dbug(2, "ncpus=%d, bulkmode = %d\n", ncpus, bulkmode); if (ncpus == 0) { _err("couldn't open %s.\n", buf); return -1; } if (ncpus > 1 && bulkmode == 0) { _err("ncpus=%d, bulkmode = %d\n", ncpus, bulkmode); _err("This is inconsistent! Please file a bug report. Exiting now.\n"); return -1; } /* PR7097 */ if (load_only) return 0; if (fsize_max) { /* switch file mode */ for (i = 0; i < ncpus; i++) { if (init_backlog(i) < 0) return -1; if (open_outfile(0, i, 0) < 0) return -1; } } else if (bulkmode) { for (i = 0; i < ncpus; i++) { if (outfile_name) { /* special case: for testing we sometimes want to write to /dev/null */ if (strcmp(outfile_name, "/dev/null") == 0) { /* This strcpy() is OK, since * we know buf is PATH_MAX * bytes long. */ strcpy(buf, "/dev/null"); } else { len = stap_strfloctime(buf, PATH_MAX, outfile_name, time(NULL)); if (len < 0) { err("Invalid FILE name format\n"); return -1; } if (snprintf_chk(&buf[len], PATH_MAX - len, "_%d", i)) return -1; } } else { if (sprintf_chk(buf, "stpd_cpu%d", i)) return -1; } out_fd[i] = open (buf, O_CREAT|O_TRUNC|O_WRONLY, 0666); if (out_fd[i] < 0) { perr("Couldn't open output file %s", buf); return -1; } if (set_clexec(out_fd[i]) < 0) return -1; } } else { /* stream mode */ if (outfile_name) { len = stap_strfloctime(buf, PATH_MAX, outfile_name, time(NULL)); if (len < 0) { err("Invalid FILE name format\n"); return -1; } out_fd[0] = open (buf, O_CREAT|O_TRUNC|O_WRONLY, 0666); if (out_fd[0] < 0) { perr("Couldn't open output file %s", buf); return -1; } if (set_clexec(out_fd[i]) < 0) return -1; } else out_fd[0] = STDOUT_FILENO; } memset(&sa, 0, sizeof(sa)); sa.sa_handler = switchfile_handler; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(SIGUSR2, &sa, NULL); dbug(2, "starting threads\n"); for (i = 0; i < ncpus; i++) { if (pthread_create(&reader[i], NULL, reader_thread, (void *)(long)i) < 0) { _perr("failed to create thread"); return -1; } } return 0; } void close_relayfs(void) { int i; stop_threads = 1; dbug(2, "closing\n"); for (i = 0; i < ncpus; i++) { if (reader[i]) pthread_kill(reader[i], SIGUSR2); else break; } for (i = 0; i < ncpus; i++) { if (reader[i]) pthread_join(reader[i], NULL); else break; } for (i = 0; i < ncpus; i++) { if (relay_fd[i] >= 0) close(relay_fd[i]); else break; } dbug(2, "done\n"); } systemtap-2.3/staprun/relay_old.c000066400000000000000000000277771217430427200172470ustar00rootroot00000000000000/* -*- linux-c -*- * * relay_old.c - staprun relayfs functions for kernels with * old relayfs implementations. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. * * Copyright (C) 2005-2007 Red Hat Inc. */ #include "staprun.h" /* temporary per-cpu output written here for relayfs, filebase0...N */ static int relay_fd[NR_CPUS]; static int proc_fd[NR_CPUS]; static FILE *percpu_tmpfile[NR_CPUS]; static char *relay_buffer[NR_CPUS]; static pthread_t reader[NR_CPUS]; static int switch_file[NR_CPUS]; static int bulkmode = 0; unsigned subbuf_size = 0; unsigned n_subbufs = 0; struct switchfile_ctrl_block { off_t wsize; int fnum; int rmfile; }; static struct switchfile_ctrl_block global_scb = {0, 0, 0}; /* per-cpu buffer info */ static struct buf_status { struct _stp_buf_info info; unsigned max_backlog; /* max # sub-buffers ready at one time */ } status[NR_CPUS]; /** * close_relayfs_files - close and munmap buffer and open output file */ static void close_relayfs_files(int cpu) { size_t total_bufsize = subbuf_size * n_subbufs; if (relay_fd[cpu] >= 0) { munmap(relay_buffer[cpu], total_bufsize); close(relay_fd[cpu]); close(proc_fd[cpu]); relay_fd[cpu] = -1; fclose(percpu_tmpfile[cpu]); } } /** * close_all_relayfs_files - close and munmap buffers and output files */ void close_oldrelayfs(int detach) { int i; if (!bulkmode) return; dbug(2, "detach=%d, ncpus=%d\n", detach, ncpus); if (detach) { for (i = 0; i < ncpus; i++) if (reader[i]) pthread_cancel(reader[i]); } else { for (i = 0; i < ncpus; i++) if (reader[i]) pthread_join(reader[i], NULL); } for (i = 0; i < ncpus; i++) close_relayfs_files(i); } static int open_oldoutfile(int fnum, int cpu, int remove_file) { char buf[PATH_MAX]; time_t t; if (outfile_name) { time(&t); if (fnum_max) { if (remove_file) { /* remove oldest file */ if (make_outfile_name(buf, PATH_MAX, fnum - fnum_max, cpu, read_backlog(cpu, fnum - fnum_max), bulkmode) < 0) return -1; remove(buf); /* don't care */ } write_backlog(cpu, fnum, t); } if (make_outfile_name(buf, PATH_MAX, fnum, cpu, t, bulkmode) < 0) return -1; } else if (bulkmode) { if (sprintf_chk(buf, "stpd_cpu%d.%d", cpu, fnum)) return -1; } else { /* stream mode */ percpu_tmpfile[cpu] = stdout; return 0; } if((percpu_tmpfile[cpu] = fopen(buf, "w+")) == NULL) { perr("Couldn't open output file %s", buf); return -1; } out_fd[cpu] = fileno(percpu_tmpfile[cpu]); if (set_clexec(out_fd[cpu]) < 0) { perr("Couldn't clear exec bit of open output file %s", buf); return -1; } return 0; } /** * open_relayfs_files - open and mmap buffer and open output file. * Returns -1 on unexpected failure, 0 if file not found, 1 on success. */ static int open_relayfs_files(int cpu, const char *relay_filebase, const char *proc_filebase) { size_t total_bufsize; char tmp[PATH_MAX]; memset(&status[cpu], 0, sizeof(struct buf_status)); status[cpu].info.cpu = cpu; if (sprintf_chk(tmp, "%s%d", relay_filebase, cpu)) return -1; dbug(2, "Opening %s.\n", tmp); relay_fd[cpu] = open(tmp, O_RDONLY | O_NONBLOCK); if (relay_fd[cpu] < 0 || set_clexec(relay_fd[cpu]) < 0) { relay_fd[cpu] = -1; return 0; } if (sprintf_chk(tmp, "%s%d", proc_filebase, cpu)) goto err1; dbug(2, "Opening %s.\n", tmp); proc_fd[cpu] = open(tmp, O_RDWR | O_NONBLOCK); if (proc_fd[cpu] < 0) { perr("Couldn't open proc file %s", tmp); goto err1; } if (set_clexec(relay_fd[cpu]) < 0) { relay_fd[cpu] = -1; return -1; } if (fsize_max) { if (init_backlog(cpu) < 0) goto err2; if (open_oldoutfile(0, cpu, 0) < 0) goto err2; goto opened; } if (outfile_name) { /* special case: for testing we sometimes want to * write to /dev/null */ if (strcmp(outfile_name, "/dev/null") == 0) { /* This strcpy() is OK, since we know tmp is * PATH_MAX bytes long. */ strcpy(tmp, "/dev/null"); } else { int len; len = stap_strfloctime(tmp, PATH_MAX, outfile_name, time(NULL)); if (len < 0) { err("Invalid FILE name format\n"); goto err2; } if (snprintf_chk(&tmp[len], PATH_MAX - len, "_%d", cpu)) goto err2; } } else { if (sprintf_chk(tmp, "stpd_cpu%d", cpu)) goto err2; } if((percpu_tmpfile[cpu] = fopen(tmp, "w+")) == NULL) { perr("Couldn't open output file %s", tmp); goto err2; } out_fd[cpu] = fileno(percpu_tmpfile[cpu]); if (set_clexec(out_fd[cpu]) < 0) { perr("Couldn't open output file %s", tmp); goto err2; } opened: total_bufsize = subbuf_size * n_subbufs; relay_buffer[cpu] = mmap(NULL, total_bufsize, PROT_READ, MAP_PRIVATE | MAP_POPULATE, relay_fd[cpu], 0); if(relay_buffer[cpu] == MAP_FAILED) { _perr("Couldn't mmap relay file, total_bufsize (%d)" \ "= subbuf_size (%d) * n_subbufs(%d)", (int)total_bufsize, (int)subbuf_size, (int)n_subbufs); goto err3; } return 1; err3: fclose(percpu_tmpfile[cpu]); err2: close (proc_fd[cpu]); err1: close (relay_fd[cpu]); relay_fd[cpu] = -1; return -1; } static int switch_oldoutfile(int cpu, struct switchfile_ctrl_block *scb) { dbug(3, "thread %d switching file\n", cpu); if (percpu_tmpfile[cpu]) fclose(percpu_tmpfile[cpu]); else close(out_fd[cpu]); scb->fnum ++; if (fnum_max && scb->fnum == fnum_max) scb->rmfile = 1; if (open_oldoutfile(scb->fnum, cpu, scb->rmfile) < 0) { perr("Couldn't open file for cpu %d, exiting.", cpu); return -1; } return 0; } /** * process_subbufs - write ready subbufs to disk */ static int process_subbufs(struct _stp_buf_info *info, struct switchfile_ctrl_block *scb) { unsigned subbufs_ready, start_subbuf, end_subbuf, subbuf_idx, i; int len, cpu = info->cpu; char *subbuf_ptr; int subbufs_consumed = 0; unsigned padding; subbufs_ready = info->produced - info->consumed; start_subbuf = info->consumed % n_subbufs; end_subbuf = start_subbuf + subbufs_ready; for (i = start_subbuf; i < end_subbuf; i++) { subbuf_idx = i % n_subbufs; subbuf_ptr = relay_buffer[cpu] + subbuf_idx * subbuf_size; padding = *((unsigned *)subbuf_ptr); subbuf_ptr += sizeof(padding); len = (subbuf_size - sizeof(padding)) - padding; scb->wsize += len; if (fsize_max && scb->wsize > fsize_max) { if (switch_oldoutfile(cpu, scb) < 0) { perr("Couldn't open file for cpu %d, exiting.", cpu); return -1; } scb->wsize = len; } if (len) { if (fwrite_unlocked (subbuf_ptr, len, 1, percpu_tmpfile[cpu]) != 1) { if (errno != EPIPE) _perr("Couldn't write to output file for cpu %d, exiting:", cpu); return -1; } } subbufs_consumed++; } return subbufs_consumed; } /** * reader_thread - per-cpu channel buffer reader */ static void *reader_thread(void *data) { int rc; int cpu = (long)data; struct pollfd pollfd; struct _stp_consumed_info consumed_info; unsigned subbufs_consumed; cpu_set_t cpu_mask; struct timespec tim = {.tv_sec=0, .tv_nsec=200000000}, *timeout = &tim; struct switchfile_ctrl_block scb = {0, 0, 0}; sigset_t sigs; sigemptyset(&sigs); sigaddset(&sigs,SIGUSR2); pthread_sigmask(SIG_BLOCK, &sigs, NULL); sigfillset(&sigs); sigdelset(&sigs,SIGUSR2); CPU_ZERO(&cpu_mask); CPU_SET(cpu, &cpu_mask); if( sched_setaffinity( 0, sizeof(cpu_mask), &cpu_mask ) < 0 ) _perr("sched_setaffinity"); pollfd.fd = relay_fd[cpu]; pollfd.events = POLLIN; #ifdef NEED_PPOLL /* Without a real ppoll, there is a small race condition that could */ /* block ppoll(). So use a timeout to prevent that. */ timeout->tv_sec = 10; timeout->tv_nsec = 0; #else timeout = NULL; #endif do { rc = ppoll(&pollfd, 1, timeout, &sigs); if (rc < 0) { if (errno == EINTR) { if (switch_file[cpu]) { switch_file[cpu] = 0; if (switch_oldoutfile(cpu, &scb) < 0) break; scb.wsize = 0; } } else { _perr("poll error"); break; } rc = 0; } rc = read(proc_fd[cpu], &status[cpu].info, sizeof(struct _stp_buf_info)); rc = process_subbufs(&status[cpu].info, &scb); if (rc < 0) break; subbufs_consumed = rc; if (subbufs_consumed) { if (subbufs_consumed > status[cpu].max_backlog) status[cpu].max_backlog = subbufs_consumed; status[cpu].info.consumed += subbufs_consumed; consumed_info.cpu = cpu; consumed_info.consumed = subbufs_consumed; if (write (proc_fd[cpu], &consumed_info, sizeof(struct _stp_consumed_info)) < 0) perr("writing consumed info failed"); } if (status[cpu].info.flushing) pthread_exit(NULL); } while (1); /* Signal the main thread that we need to quit */ kill(getpid(), SIGTERM); pthread_exit(NULL); } /** * write_realtime_data - write realtime data packet to disk */ int write_realtime_data(void *data, ssize_t nb) { ssize_t bw; global_scb.wsize += nb; if (fsize_max && global_scb.wsize > fsize_max) { if (switch_oldoutfile(0, &global_scb) < 0) { perr("Couldn't open file, exiting."); return -1; } global_scb.wsize = nb; } bw = write(out_fd[0], data, nb); if (bw >= 0 && bw != nb) { nb = nb - bw; bw = write(out_fd[0], data, nb); } return bw != nb; } static void switchfile_handler(int sig) { int i; for (i = 0; i < ncpus; i++) if (reader[i] && switch_file[i]) { dbug(2, "file switching is progressing, signal ignored.\n", sig); return; } for (i = 0; i < ncpus; i++) { if (reader[i]) { switch_file[i] = 1; pthread_kill(reader[i], SIGUSR2); } else break; } } /** * init_relayfs - create files and threads for relayfs processing * * Returns 0 if successful, negative otherwise */ int init_oldrelayfs(void) { int i, j; struct statfs st; char relay_filebase[PATH_MAX], proc_filebase[PATH_MAX]; struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = switchfile_handler; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(SIGUSR2, &sa, NULL); dbug(2, "initializing relayfs.n_subbufs=%d subbuf_size=%d\n", n_subbufs, subbuf_size); if (n_subbufs) bulkmode = 1; if (!bulkmode) { int len; char tmp[PATH_MAX]; if (fsize_max) { if (init_backlog(0)) return -1; return open_oldoutfile(0, 0, 0); } if (outfile_name) { len = stap_strfloctime(tmp, PATH_MAX, outfile_name, time(NULL)); if (len < 0) { err("Invalid FILE name format\n"); return -1; } out_fd[0] = open (tmp, O_CREAT|O_TRUNC|O_WRONLY, 0666); if (out_fd[0] < 0 || set_clexec(out_fd[0]) < 0) { perr("Couldn't open output file '%s'", tmp); return -1; } } else out_fd[0] = STDOUT_FILENO; return 0; } if (statfs("/sys/kernel/debug", &st) == 0 && (int) st.f_type == (int) DEBUGFS_MAGIC) { if (sprintf_chk(relay_filebase, "/sys/kernel/debug/systemtap/%s/trace", modname)) return -1; if (sprintf_chk(proc_filebase, "/sys/kernel/debug/systemtap/%s/", modname)) return -1; } else if (statfs("/mnt/relay", &st) == 0 && (int) st.f_type == (int) RELAYFS_MAGIC) { if (sprintf_chk(relay_filebase, "/mnt/relay/systemtap/%s/trace", modname)) return -1; if (sprintf_chk(proc_filebase, "/proc/systemtap/%s/", modname)) return -1; } else { err("Cannot find relayfs or debugfs mount point.\n"); return -1; } reader[0] = (pthread_t)0; relay_fd[0] = -1; out_fd[0] = 0; for (i = 0; i < NR_CPUS; i++) { int ret = open_relayfs_files(i, relay_filebase, proc_filebase); if (ret == 0) break; if (ret < 0) { err("Couldn't open relayfs files, cpu = %d\n", i); goto err; } } ncpus = i; dbug(2, "ncpus=%d\n", ncpus); if (ncpus == 0) { err("Couldn't open relayfs files.\n"); return -1; } if (!load_only) { dbug(2, "starting threads\n"); for (i = 0; i < ncpus; i++) { /* create a thread for each per-cpu buffer */ if (pthread_create(&reader[i], NULL, reader_thread, (void *)(long)i) < 0) { int saved_errno = errno; close_relayfs_files(i); err("Couldn't create reader thread, cpu = %d: %s\n", i, strerror(saved_errno)); goto err; } } } return 0; err: for (j = 0; j < i; j++) close_relayfs_files(j); for (j = 0; j < i; j++) if (reader[j]) pthread_cancel(reader[j]); return -1; } systemtap-2.3/staprun/run-staprun.in000066400000000000000000000024041217430427200177330ustar00rootroot00000000000000#!/bin/sh srcdir='@abs_top_srcdir@' builddir='@abs_top_builddir@' rundir="${0%/*}" [ "$rundir" == "$0" ] || builddir="$rundir" # Absolutify the paths. case "$srcdir" in /*) ;; *) srcdir=`cd "$srcdir" && pwd` || exit ;; esac case "$builddir" in /*) ;; *) builddir=`cd "$builddir" && pwd` || exit ;; esac # If there were private elfutils libs built, use them. if [ -d "$rundir/lib-elfutils" ]; then lib_elfutils="$rundir/lib-elfutils" elfutils_path="${lib_elfutils}:${lib_elfutils}/systemtap" LD_LIBRARY_PATH="${elfutils_path}${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH" export LD_LIBRARY_PATH fi # Passing LD_LIBRARY_PATH to sudo is a bit unusual, and possibly dangerous, but # we'll trust that pro users with sudo access know how to keep their noses^W # environment clean. Ditto for PATH and HOME, which help -c CMD work nonroot. exec sudo -P "SYSTEMTAP_STAPIO=${builddir}/stapio" \ "SYSTEMTAP_STAPRUN=${builddir}/run-staprun" \ "SYSTEMTAP_RUNTIME=${srcdir}/../runtime" \ "SYSTEMTAP_REAL_UID=`id -ru`" \ "SYSTEMTAP_REAL_GID=`id -rg`" \ ${LD_LIBRARY_PATH:+"LD_LIBRARY_PATH=$LD_LIBRARY_PATH"} \ ${PATH:+"PATH=$PATH"} \ ${HOME:+"HOME=$HOME"} \ ${builddir}/staprun ${1+"$@"} systemtap-2.3/staprun/stap_merge.c000066400000000000000000000062631217430427200174060ustar00rootroot00000000000000/* * stap_merge.c - systemtap merge program * * 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, see . * * Copyright (C) Red Hat Inc, 2005-2007 * */ #include #include #include #include #include static void usage (char *prog) { fprintf(stderr, "%s [-v] [-o output_filename] input_files ...\n", prog); exit(-1); } #define TIMESTAMP_SIZE (sizeof(int)) #define NR_CPUS 256 int main (int argc, char *argv[]) { char *buf, *outfile_name = NULL; int c, i, j, rc, dropped=0; long count=0, min, num[NR_CPUS]; FILE *ofp = NULL; FILE *fp[NR_CPUS] = { 0 }; int ncpus, len, verbose = 0; int bufsize = 65536; buf = malloc(bufsize); if (buf == NULL) { fprintf(stderr, "Memory allocation failed.\n"); exit(-2); } while ((c = getopt (argc, argv, "vo:")) != EOF) { switch (c) { case 'v': verbose = 1; break; case 'o': outfile_name = optarg; break; default: usage(argv[0]); } } if (optind == argc) usage (argv[0]); i = 0; while (optind < argc) { fp[i] = fopen(argv[optind++], "r"); if (!fp[i]) { fprintf(stderr, "error opening file %s.\n", argv[optind - 1]); return -1; } if (fread (buf, TIMESTAMP_SIZE, 1, fp[i])) num[i] = *((int *)buf); else num[i] = 0; i++; } ncpus = i; if (!outfile_name) ofp = stdout; else { ofp = fopen(outfile_name, "w"); if (!ofp) { fprintf(stderr, "ERROR: couldn't open output file %s: errcode = %s\n", outfile_name, strerror(errno)); return -1; } } do { min = num[0]; j = 0; for (i = 1; i < ncpus; i++) { if (min == 0 || (num[i] && num[i] < min)) { min = num[i]; j = i; } } if (fread(&len, sizeof(int), 1, fp[j])) { if (verbose) fprintf(stdout, "[CPU:%d, seq=%ld, length=%d]\n", j, min, len); if (len > bufsize) { bufsize = len; if (verbose) fprintf(stderr, "reallocating %d bytes\n", bufsize); buf = realloc(buf, bufsize); if (buf == NULL) { fprintf(stderr, "Memory allocation failed.\n"); exit(-2); } } if ((rc = fread(buf, len, 1, fp[j])) <= 0 ) { fprintf(stderr, "fread error: got %d\n", rc); exit(-3); } if ((rc = fwrite(buf, len, 1, ofp)) <= 0 ) { fprintf(stderr, "fread error: got %d\n", rc); exit(-3); } } if (min && ++count != min) { fprintf(stderr, "got %ld. expected %ld\n", min, count); dropped += min - count ; count = min; } if (fread (buf, TIMESTAMP_SIZE, 1, fp[j])) num[j] = *((int *)buf); else num[j] = 0; } while (min); for (i = 0; i < ncpus; i++) fclose (fp[i]); fclose (ofp); printf ("sequence had %d drops\n", dropped); return 0; } systemtap-2.3/staprun/stap_merge.tcl000077500000000000000000000046531217430427200177520ustar00rootroot00000000000000#!/usr/bin/env tclsh # # stap_merge.tcl - systemtap merge program # # 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, see . # # Copyright (C) Red Hat Inc, 2007 # # proc usage {} { puts stderr "$::argv0 \[-v\] \[-o output_filename\] input_files ...\n" exit 1 } set outfile "stdout" set verbose 0 set index 0 while {[string match -* [lindex $argv $index]]} { switch -glob -- [lindex $argv $index] { -v {set verbose 1} -o {incr index; set outfile [lindex $argv $index]} default {usage} } incr index } if {$tcl_platform(byteOrder) == "littleEndian"} { set int_format i } else { set int_format I } set files [lrange $argv $index end] set n 0 foreach file $files { if {[catch {open $file} fd($n)]} { puts stderr $fd($n) exit 1 } fconfigure $fd($n) -translation binary if {![binary scan [read $fd($n) 4] $int_format timestamp($n)]} { continue } set timestamp($n) [expr $timestamp($n) & 0xFFFFFFFF] incr n } set ncpus $n if {$outfile != "stdout"} { if {[catch {open $outfile w} outfile]} { puts stderr $outfile exit 1 } } fconfigure $outfile -translation binary while {1} { set mincpu -1 for {set n 0} {$n < $ncpus} {incr n} { if {[info exists fd($n)] && (![info exists min] || $timestamp($n) <= $min)} { set min $timestamp($n) set mincpu $n } } if {![info exists min]} {break} if {![binary scan [read $fd($mincpu) 4] $int_format len]} { puts stderr "Error reading length from channel $mincpu" exit 1 } if {$verbose == 1} { puts stderr "\[CPU:$mincpu, seq=$min, length=$len\]" } set data [read $fd($mincpu) $len] puts -nonewline $outfile $data set data [read $fd($mincpu) 4] if {$data == ""} { unset fd($mincpu) } else { binary scan $data $int_format timestamp($mincpu) set timestamp($mincpu) [expr $timestamp($mincpu) & 0xFFFFFFFF] } unset min } systemtap-2.3/staprun/stapio.c000066400000000000000000000040661217430427200165560ustar00rootroot00000000000000/* -*- linux-c -*- * * stapio.c - SystemTap module io handler. * * 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, see . * * Copyright (C) 2005-2012 Red Hat, Inc. * */ #include "staprun.h" #include char *__name__ = "stapio"; int main(int argc, char **argv) { #if ENABLE_NLS setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); #endif setup_signals(); parse_args(argc, argv); /* If we inherited a relay_basedir_fd, we want to keep it to ourselves - i.e., FD_CLOEXEC the bad boy. */ if (relay_basedir_fd >= 0) { int rc = set_clexec(relay_basedir_fd); if (rc) exit(-1); } if (buffer_size) dbug(1, "Using a buffer of %u MB.\n", buffer_size); if (optind < argc) { parse_modpath(argv[optind++]); dbug(2, "modpath=\"%s\", modname=\"%s\"\n", modpath, modname); } if (optind < argc) { if (attach_mod) { err(_("Cannot have module options with attach (-A).\n")); usage(argv[0]); } else { unsigned start_idx = 3; /* reserve three slots in modoptions[] */ while (optind < argc && start_idx + 1 < MAXMODOPTIONS) modoptions[start_idx++] = argv[optind++]; modoptions[start_idx] = NULL; } } if (modpath == NULL || *modpath == '\0') { err(_("Need a module name or path to load.\n")); usage(argv[0]); } if (init_stapio()) exit(1); if (stp_main_loop()) { err(_("Couldn't enter main loop. Exiting.\n")); exit(1); } return 0; } systemtap-2.3/staprun/staprun.8000066400000000000000000000175461217430427200167070ustar00rootroot00000000000000.\" -*- nroff -*- .TH STAPRUN 8 .SH NAME staprun \- systemtap runtime .SH SYNOPSIS .br .B staprun [ .I OPTIONS ] .I MODULE [ .I MODULE-OPTIONS ] .SH DESCRIPTION The .I staprun program is the back-end of the Systemtap tool. It expects a kernel module produced by the front-end .I stap tool. .PP Splitting the systemtap tool into a front-end and a back-end allows a user to compile a systemtap script on a development machine that has the kernel development tools (needed to compile the script) and then transfer the resulting kernel module to a production machine that doesn't have any development tools installed. .PP Please refer to stappaths (7) for the version number, or run rpm \-q systemtap (fedora/red hat) apt\-get \-v systemtap (ubuntu) .SH OPTIONS The .I staprun program supports the following options. Any other option prints a list of supported options. .TP .B \-v Verbose mode. .TP .B \-V Print version number and exit. .TP .B \-w Suppress warnings from the script. .TP .B \-u Load the uprobes.ko module. .TP .B \-c CMD Command CMD will be run and the .I staprun program will exit when CMD does. The '_stp_target' variable will contain the pid for CMD. .TP .B \-x PID The '_stp_target' variable will be set to PID. .TP .B \-o FILE Send output to FILE. If the module uses bulk mode, the output will be in percpu files FILE_x(FILE_cpux in background and bulk mode) where 'x' is the cpu number. This supports strftime(3) formats for FILE. .TP .B \-b BUFFER_SIZE The systemtap module will specify a buffer size. Setting one here will override that value. The value should be an integer between 1 and 4095 which be assumed to be the buffer size in MB. That value will be per-cpu if bulk mode is used. .TP .B \-L Load module and start probes, then detach from the module leaving the probes running. The module can be attached to later by using the .B \-A option. .TP .B \-A Attach to loaded systemtap module. .TP .B \-C WHEN Control coloring of error messages. WHEN must be either .nh "never", "always", or "auto" .hy (i.e. enable only if at a terminal). If the option is missing, then "auto" is assumed. Colors can be modified using the SYSTEMTAP_COLORS environment variable. See the .IR stap (1) manual page for more information on syntax and behaviour. .TP .B \-d Delete a module. Only detached or unused modules the user has permission to access will be deleted. Use "*" (quoted) to delete all unused modules. .TP .BI \-D Run staprun in background as a daemon and show it's pid. .TP .B \-R Rename the module to a unique name before inserting it. .TP .B \-r N:URI Pass the given number and URI data to the tapset functions remote_id() and remote_uri(). .TP .BI \-S " size[,N]" Sets the maximum size of output file and the maximum number of output files. If the size of output file will exceed .B size , systemtap switches output file to the next file. And if the number of output files exceed .B N , systemtap removes the oldest output file. You can omit the second argument. .TP .B \-T timeout Sets maximum time reader thread will wait before dumping trace buffer. Value is in ms, default is 200ms. Setting this to a high value decreases number of stapio wake-ups, allowing deeper sleep for embedded platforms. But it impacts interactivity on terminal as traces are dumped less often in case of low throughput. There is no interactivity or performance impact for high throughput as trace is dumped when buffer is full, before this timeout expires. .TP .B var1=val Sets the value of global variable var1 to val. Global variables contained within a module are treated as module options and can be set from the staprun command line. .SH ARGUMENTS .B MODULE is either a module path or a module name. If it is a module name, the module will be looked for in the following directory (where 'VERSION' is the output of "uname \-r"): .IP /lib/modules/VERSION/systemtap .PP .\" TODO - we probably need a better description here. Any additional arguments on the command line are passed to the module. One use of these additional module arguments is to set the value of global variables declared within the module. .PP \& $ stap \-p4 \-m mod1 \-e\ \[aq]global var1="foo"; probe begin{printf("%s\\n", var1); exit()}\[aq] .br .PP Running this with an additional module argument: .PP \& $ staprun mod1.ko var1="HelloWorld" .br \& HelloWorld .PP Spaces and exclamation marks currently cannot be passed into global variables this way. .SH EXAMPLES See the .IR stapex (3stap) manual page for a collection of sample scripts. .PP Here is a very basic example of how to use .I staprun. First, use .I stap to compile a script. The .I stap program will report the pathname to the resulting module. .PP \& $ stap \-p4 \-e \[aq]probe begin { printf("Hello World!\\n"); exit() }\[aq] .br \& /home/user/.systemtap/cache/85/stap_8553d83f78c_265.ko .PP Run .I staprun with the pathname to the module as an argument. .PP \& $ staprun /home/user/.systemtap/cache/85/stap_8553d83f78c_265.ko .br \& Hello World! .SH MODULE DETACHING AND ATTACHING After the .I staprun program installs a Systemtap kernel module, users can detach from the kernel module and reattach to it later. The .B \-L option loads the module and automatically detaches. Users can also detach from the kernel module interactively by sending the SIGQUIT signal from the keyboard (typically by typing Ctrl\-\\). .PP To reattach to a kernel module, the .I staprun .B \-A option would be used. .SH FILE SWITCHING BY SIGNAL After .I staprun launched the .I stapio program, users can command it to switch output file to next file when it outputs to file(s) (running staprun with .B \-o option) by sending a .B SIGUSR2 signal to the .I stapio process. When it receives SIGUSR2, it will switch output file to new file with suffix .I .N where N is the sequential number. For example, .PP \& $ staprun \-o foo ... .PP outputs trace logs to .I foo and if it receives .B SIGUSR2 signal, it switches output to .I foo.1 file. And receiving .B SIGUSR2 again, it switches to .I foo.2 file. .SH SAFETY AND SECURITY Systemtap, in the default kernel-module runtime mode, is an administrative tool. It exposes kernel internal data structures and potentially private user information. See the .IR stap (1) manual page for additional information on safety and security. .PP To increase system security, users of systemtap must be root, or in the .I staprun group in order to execute this setuid .I staprun program. A user may select a particular privilege level with the stap .I \-\-privilege= option, which .I staprun will later enforce. .TP stapdev Members of the .I stapdev group can write and load script modules with root-equivalent privileges, without particular security constraints. (Many safety constraints remain.) .TP stapsys Members of the .I stapsys group have almost all the privileges of .IR stapdev , except for guru mode constructs. .TP staprun Members only of the .I stapusr group may any-privileged modules placed into the /lib/modules/VERSION/systemtap by the system administrator. .TP staprun Members only of the .I stapusr group may also write and load low-privilege script modules, which are normally limited to manipulating their own processes (and not the kernel nor other users' processes). .PP Part of the privilege enforcement mechanism may require using a stap-server and administrative trust in its cryptographic signer; see the .IR stap\-server (8) manual page for a for more information. .SH FILES .TP /lib/modules/VERSION/systemtap If MODULE is a module name, the module will be looked for in this directory. Users who are only in the .I 'stapusr' group can install modules located in this directory. This directory must be owned by the root user and not be world writable. .SH SEE ALSO .IR stap (1), .IR stapprobes (3stap), .IR stap\-server (8), .IR stapdyn (8), .IR stapex (3stap) .SH BUGS Use the Bugzilla link of the project web page or our mailing list. .nh .BR http://sourceware.org/systemtap/ ", " . .hy systemtap-2.3/staprun/staprun.c000066400000000000000000000511061217430427200167500ustar00rootroot00000000000000/* -*- linux-c -*- * * staprun.c - SystemTap module loader * * Copyright (C) 2005-2013 Red Hat, Inc. * * 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, see . * */ #define _XOPEN_SOURCE #define _BSD_SOURCE #include "staprun.h" #include "../privilege.h" #include "../runtime/k_syms.h" #include #include #include #include #include #include /* used in dbug, _err and _perr */ char *__name__ = "staprun"; extern long delete_module(const char *, unsigned int); int send_relocations (); int send_tzinfo (); int send_privilege_credentials (privilege_t user_credentials); int send_remote_id (); static int remove_module(const char *name, int verb); static int stap_module_inserted = -1; static void term_signal_handler(int signum __attribute ((unused))) { if (stap_module_inserted == 0) { // We have to close the control channel so that // remove_module() can open it back up (which it does // to make sure the module is a systemtap module). close_ctl_channel(); remove_module(modname, 1); free(modname); } _exit(1); } void setup_term_signals(void) { sigset_t s; struct sigaction a; /* blocking all signals while we set things up */ sigfillset(&s); sigprocmask(SIG_SETMASK, &s, NULL); /* handle signals */ memset(&a, 0, sizeof(a)); sigfillset(&a.sa_mask); a.sa_handler = term_signal_handler; sigaction(SIGHUP, &a, NULL); sigaction(SIGINT, &a, NULL); sigaction(SIGTERM, &a, NULL); sigaction(SIGQUIT, &a, NULL); /* unblock all signals */ sigemptyset(&s); sigprocmask(SIG_SETMASK, &s, NULL); } static int run_as(int exec_p, uid_t uid, gid_t gid, const char *path, char *const argv[]) { pid_t pid; int rstatus; if (verbose >= 2) { int i = 0; eprintf(exec_p ? "execing: ": "spawning: "); while (argv[i]) { eprintf("%s ", argv[i]); i++; } eprintf("\n"); } if (exec_p) pid = 0; else pid = fork(); if (pid < 0) { _perr("fork"); return -1; } if (pid == 0) /* child process, or exec_p */ { /* Make sure we run as the full user. If we're * switching to a non-root user, this won't allow * that process to switch back to root (since the * original process is setuid). */ if (setresgid (gid, gid, gid) < 0) { _perr("setresgid"); exit(1); } if (setresuid (uid, uid, uid) < 0) { _perr("setresuid"); exit(1); } /* Actually run the command. */ if (execv(path, argv) < 0) perror(path); _exit(1); } if (waitpid(pid, &rstatus, 0) < 0) return -1; if (WIFEXITED(rstatus)) return WEXITSTATUS(rstatus); return -1; } /* * Module to be inserted has one or more user-space probes. Make sure * uprobes is enabled. * If /proc/kallsyms lists a symbol in uprobes (e.g. unregister_uprobe), * we're done. * Else try "modprobe uprobes" to load the uprobes module (if any) * built with the kernel. * If that fails, load the uprobes module built in runtime/uprobes. */ static int enable_uprobes(void) { char *argv[10]; char runtimeko[2048]; int rc; /* Formerly, we did a grep /proc/kallsyms search to see if uprobes was already loaded into the kernel. But this is a race waiting to happen. Just try to load the thing. Quietly accept a -EEXIST error. */ /* NB: don't use /sbin/modprobe, without more env. sanitation. */ /* Try the specified module or the one from the runtime. */ if (uprobes_path) snprintf (runtimeko, sizeof(runtimeko), "%s", uprobes_path); else /* NB: since PR5163, share/runtime/uprobes/uprobes.ko is not built by systemtap. */ snprintf (runtimeko, sizeof(runtimeko), "%s/uprobes/uprobes.ko", (getenv("SYSTEMTAP_RUNTIME") ?: PKGDATADIR "/runtime")); dbug(2, "Inserting uprobes module from %s.\n", runtimeko); /* This module may be signed, so use insert_module to load it. */ argv[0] = NULL; rc = insert_module(runtimeko, NULL, argv, assert_uprobes_module_permissions, NULL); if ((rc == 0) || /* OK */ (rc == -EEXIST)) /* Someone else might have loaded it */ return 0; err("Couldn't insert module '%s': %s\n", runtimeko, moderror(errno)); return 1; /* failure */ } static int insert_stap_module(privilege_t *user_credentials) { char special_options[128]; /* Add the _stp_bufsize option. */ if (snprintf_chk(special_options, sizeof (special_options), "_stp_bufsize=%d", buffer_size)) return -1; stap_module_inserted = insert_module(modpath, special_options, modoptions, assert_stap_module_permissions, user_credentials); if (stap_module_inserted != 0) err("Couldn't insert module '%s': %s\n", modpath, moderror(errno)); return stap_module_inserted; } static void remove_all_modules(void) { char *base; struct statfs st; struct dirent *d; DIR *moddir; /* NB: nothing to do with PR14245 */ if (statfs("/sys/kernel/debug", &st) == 0 && (int)st.f_type == (int)DEBUGFS_MAGIC) base = "/sys/kernel/debug/systemtap"; else base = "/proc/systemtap"; moddir = opendir(base); if (moddir) { while ((d = readdir(moddir))) if (remove_module(d->d_name, 0) == 0) printf("Module %s removed.\n", d->d_name); closedir(moddir); } } static int remove_module(const char *name, int verb) { int ret; dbug(2, "%s\n", name); #ifdef PR_SET_NAME /* Make self easier to identify in vmcrash images */ prctl (PR_SET_NAME, "staprun-d"); #endif (void) verb; /* XXX: ignore */ if (strcmp(name, "*") == 0) { remove_all_modules(); return 0; } /* We call init_ctl_channel/close_ctl_channel to check whether the module is a systemtap-built one (having the right files), and that it's already unattached (because otherwise it'd EBUSY the opens. */ ret = init_ctl_channel (name, 0); if (ret < 0) { err("'%s' is not a zombie systemtap module.\n", name); return ret; } close_ctl_channel (); dbug(2, "removing module %s\n", name); PROBE1(staprun, remove__module, name); ret = delete_module (name, O_NONBLOCK); if (ret != 0) { /* XXX: maybe we should just accept this, with a diagnostic, but without an error. Might it be possible for the same module to be started up just as we're shutting down? */ err("Couldn't remove module '%s': %s.\n", name, strerror(errno)); return 1; } dbug(1, "Module %s removed.\n", name); return 0; } /* As per PR13193 & PR1548, some kernels have a buggy kprobes-optimization code, which results in BUG/panics in certain circumstances. We turn off kprobes optimization as a conservative measure, unless told otherwise by an environment variable. */ void disable_kprobes_optimization() { /* Test if the file exists at all. */ const char* proc_kprobes = "/proc/sys/debug/kprobes-optimization"; char prev; int rc, fd; struct utsname uts; /* PR13814; disable this facility for new enough kernels, containing * these fix commits: 86b4ce31 46484688 3f33ab1c */ /* PR15484; whoops, not enough, problem still seen on Debian * 3.8.12 kernel. */ if (0 && (uname (&uts) == 0) && (strverscmp (uts.release, "3.4") >= 0)) return; if (getenv ("STAP_PR13193_OVERRIDE")) return; /* See the initial state; if it's already disabled, we do nothing. */ fd = open (proc_kprobes, O_RDONLY); if (fd < 0) return; rc = read (fd, &prev, sizeof(prev)); (void) close (fd); if (rc < 1 || prev == '0') /* Already disabled or unavailable */ return; fd = open (proc_kprobes, O_WRONLY); if (fd < 0) return; prev = '0'; /* really, next */ rc = write (fd, &prev, sizeof(prev)); (void) close (fd); if (rc == 1) dbug(1, "Disabled %s.\n", proc_kprobes); else dbug(1, "Error %d/%d disabling %s.\n", rc, errno, proc_kprobes); } int init_staprun(void) { privilege_t user_credentials = pr_unknown; int rc; dbug(2, "init_staprun\n"); if (mountfs() < 0) return -1; rc = 0; if (delete_mod) exit(remove_module(modname, 1)); if (attach_mod) { /* PR14245: prime the relay_basedir_fd pump. */ rc = init_ctl_channel (modname, 0); if (rc >= 0) close_ctl_channel (); } else /* if (!attach_mod) */ { if (need_uprobes && enable_uprobes() != 0) return -1; disable_kprobes_optimization(); if (insert_stap_module(& user_credentials) < 0) { #ifdef HAVE_ELF_GETSHDRSTRNDX if(!rename_mod && errno == EEXIST) err("Rerun with staprun option '-R' to rename this module.\n"); #endif /* Without a working rename_module(), we shan't advise people to use -R. */ return -1; } rc = init_ctl_channel (modname, 0); if (rc >= 0) { /* If we are unable to send privilege credentials then we have an old (pre 1.7) stap module or a non-stap module. In either case, the privilege credentials required for loading the module have already been determined and checked (see check_groups, get_module_required_credentials). */ send_privilege_credentials(user_credentials); rc = send_relocations(); if (rc == 0) { rc = send_tzinfo(); if (rc == 0 && remote_id >= 0) send_remote_id(); } close_ctl_channel (); } if (rc != 0) remove_module(modname, 1); } return rc; } int main(int argc, char **argv) { int rc; /* NB: Don't do the geteuid()!=0 check here, since we want to test command-line error-handling while running non-root. */ /* Get rid of a few standard environment variables (which */ /* might cause us to do unintended things). */ rc = unsetenv("IFS") || unsetenv("CDPATH") || unsetenv("ENV") || unsetenv("BASH_ENV"); if (rc) { _perr("unsetenv failed"); exit(-1); } if (getuid() != geteuid()) { /* setuid? */ rc = unsetenv("SYSTEMTAP_STAPRUN") || unsetenv("SYSTEMTAP_STAPIO") || unsetenv("SYSTEMTAP_RUNTIME"); if (rc) { _perr("unsetenv failed"); exit(-1); } } setup_signals(); setup_term_signals(); parse_args(argc, argv); /* PR14245, For security reasons, preclude "staprun -F fd". The -F option is only for stapio, but the overzealous quest for commonality doesn't let us express that nicer. */ if (relay_basedir_fd >= 0) { err(_("Relay basedir -F option is invalid for staprun\n")); exit(1); } /* NB: later on, some of our own code may set relay_basedir_fd, for passing onto stapio - or for our own reuse. That's OK. */ if (buffer_size) dbug(2, "Using a buffer of %u MB.\n", buffer_size); int mod_optind = optind; if (optind < argc) { parse_modpath(argv[optind++]); dbug(2, "modpath=\"%s\", modname=\"%s\"\n", modpath, modname); } if (optind < argc) { if (attach_mod) { err("Cannot have module options with attach (-A).\n"); usage(argv[0]); } else { unsigned start_idx = 0; while (optind < argc && start_idx + 1 < MAXMODOPTIONS) modoptions[start_idx++] = argv[optind++]; modoptions[start_idx] = NULL; } } if (modpath == NULL || *modpath == '\0') { err("Need a module name or path to load.\n"); usage(argv[0]); } if (geteuid() != 0) { err("The effective user ID of staprun must be set to the root user.\n" " Check permissions on staprun and ensure it is a setuid root program.\n"); exit(1); } if (init_staprun()) exit(1); argv[0] = getenv ("SYSTEMTAP_STAPIO") ?: PKGLIBDIR "/stapio"; /* Copy nenamed modname into argv */ if(rename_mod) argv[mod_optind] = modname; /* PR14245: pass -F fd to stapio. Unfortunately, this requires us to extend argv[], with all the C fun that entails. */ #ifdef HAVE_OPENAT if (relay_basedir_fd >= 0) { char ** new_argv = calloc(sizeof(char *),argc+1); const int new_Foption_size = 10; /* -FNNNNN */ char * new_Foption = malloc(new_Foption_size); int i; if (new_argv && new_Foption) { snprintf (new_Foption, new_Foption_size, "-F%d", relay_basedir_fd); for (i=0; argv[i] != NULL; i++) new_argv[i] = argv[i]; new_argv[i++] = new_Foption; /* overwrite the NULL */ new_argv[i++] = NULL; /* ensconce a new NULL */ argv = new_argv; } } #endif /* Run stapio */ if (run_as (1, getuid(), getgid(), argv[0], argv) < 0) { perror(argv[0]); goto err; } free(modname); return 0; err: remove_module(modname, 1); free(modname); return 1; } /* Send a variety of relocation-related data to the kernel: for the kernel proper, just the "_stext" symbol address; for all loaded modules, a variety of symbol base addresses. We do this under protest. The kernel ought expose this data to modules such as ourselves, but instead the upstream community continually shrinks its module-facing interfaces, including this stuff, even when users exist. */ int send_a_relocation (const char* module, const char* reloc, unsigned long long address) { struct _stp_msg_relocation msg; int rc; if (strlen(module) >= STP_MODULE_NAME_LEN-1) { dbug (1, "module name too long: %s\n", module); return -EINVAL; } strncpy (msg.module, module, STP_MODULE_NAME_LEN); if (strlen(reloc) >= STP_SYMBOL_NAME_LEN-1) { dbug (1, "reloc name too long: %s\n", reloc); return -EINVAL; } strncpy (msg.reloc, reloc, STP_MODULE_NAME_LEN); msg.address = address; rc = send_request (STP_RELOCATION, & msg, sizeof (msg)); if (rc != 0) perror ("Unable to send relocation"); return rc; } int send_relocation_kernel () { FILE* kallsyms; int rc = 0; errno = 0; kallsyms = fopen ("/proc/kallsyms", "r"); if (kallsyms == NULL) { perror("cannot open /proc/kallsyms"); // ... and the kernel module will almost certainly fail to initialize. return errno; } else { int done_with_kallsyms = 0; char *line = NULL; size_t linesz = 0; while (! feof(kallsyms) && !done_with_kallsyms) { ssize_t linesize = getline (& line, & linesz, kallsyms); if (linesize > 0) { unsigned long long address; int pos = -1; if (sscanf (line, "%llx %*c %n", &address, &pos) == 1 && pos != -1 && linesize - pos == sizeof KERNEL_RELOC_SYMBOL && !strcmp(line + pos, KERNEL_RELOC_SYMBOL "\n")) { /* NB: even on ppc, we use the _stext relocation name. */ rc = send_a_relocation ("kernel", "_stext", address); if (rc != 0) break; /* We need nothing more from the kernel. */ done_with_kallsyms=1; } } } free (line); fclose (kallsyms); if (!done_with_kallsyms) return rc; /* detect note section, send flag if there * NB: address=2 represents existed note, the real one in _stp_module */ if (!access("/sys/kernel/notes", R_OK)) rc = send_a_relocation ("kernel", ".note.gnu.build-id", 2); } return rc; } int send_relocation_modules () { unsigned i = 0; glob_t globbuf; globbuf.gl_pathc = 0; int r = glob("/sys/module/*/sections/*", GLOB_PERIOD, NULL, &globbuf); if (r == GLOB_NOSPACE || r == GLOB_ABORTED) return r; for (i=0; itm_gmtoff; strncpy (tzi.tz_name, now->tm_zone, STP_TZ_NAME_LEN); rc = send_request(STP_TZINFO, & tzi, sizeof(tzi)); if (rc != 0) perror ("Unable to send time zone information"); return rc; } int send_privilege_credentials (privilege_t user_credentials) { struct _stp_msg_privilege_credentials pc; int rc; pc.pc_group_mask = user_credentials; rc = send_request(STP_PRIVILEGE_CREDENTIALS, & pc, sizeof(pc)); if (rc != 0) { /* Not an error. Happens when pre 1.7 modules are loaded. */ dbug (1, "Unable to send user privilege credentials\n"); } return rc; } int send_remote_id () { struct _stp_msg_remote_id rem; int rc; rem.remote_id = remote_id; strncpy (rem.remote_uri, remote_uri, STP_REMOTE_URI_LEN); rem.remote_uri [STP_REMOTE_URI_LEN-1]='\0'; /* XXX: quietly truncate */ rc = send_request(STP_REMOTE_ID, & rem, sizeof(rem)); if (rc != 0) perror ("Unable to send remote id"); return rc; } systemtap-2.3/staprun/staprun.h000066400000000000000000000173241217430427200167610ustar00rootroot00000000000000/* -*- linux-c -*- * * staprun.h - include file for staprun and stapio * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. * * Copyright (C) 2005-2008 Red Hat Inc. */ #define _FILE_OFFSET_BITS 64 /* kernel-headers and glibc like to stomp on each other. We include this early * so we can ensure glibc's own definitions will win. rhbz 837641 & 840902 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Include config.h to pick up dependency for --prefix usage. */ #include "../config.h" #include "../privilege.h" #if ENABLE_NLS #include #include #endif /* define gettext options if NLS is set */ #if ENABLE_NLS #define _(string) gettext(string) #define _N(string, string_plural, count) \ ngettext((string), (string_plural), (count)) #else #define _(string) (string) #define _N(string, string_plural, count) \ ( (count) == 1 ? (string) : (string_plural) ) #endif /* NB: _F and _NF not available for staprun, since autosprintf() is defined in c++ in ../util.cxx, in a memory-leak-free way. */ #if 0 #define _F(format, ...) autosprintf(_(format), __VA_ARGS__) #define _NF(format, format_plural, count, ...) \ autosprintf(_N((format), (format_plural), (count)), __VA_ARGS__) #endif /* For probes in staprun.c, staprun_funcs.c, mainloop.c and common.c */ #include "stap-probe.h" extern void eprintf(const char *fmt, ...); extern void switch_syslog(const char *name); extern void print_color(const char *type); extern char *parse_stap_color(const char *type); #define dbug(level, args...) do {if (verbose>=level) {eprintf("%s:%s:%d ",__name__,__FUNCTION__, __LINE__); eprintf(args);}} while (0) extern char *__name__; /* print to stderr */ #define err(args...) do { \ print_color("error"); \ eprintf(_("ERROR:")); \ print_color(NULL); \ eprintf(" "); \ eprintf(args); \ } while (0) #define warn(args...) do { \ if (suppress_warnings) \ break; \ print_color("warning"); \ eprintf(_("WARNING:")); \ print_color(NULL); \ eprintf(" "); \ eprintf(args); \ } while (0) /* better perror() */ #define perr(args...) do { \ int _errno = errno; \ err(args); \ eprintf(": %s\n", strerror(_errno)); \ } while (0) /* Error messages. Use these for serious errors, not informational messages to stderr. */ #define _err(args...) do {eprintf("%s:%s:%d: ERROR: ",__name__, __FUNCTION__, __LINE__); eprintf(args);} while(0) #define _perr(args...) do { \ int _errno = errno; \ _err(args); \ eprintf(": %s\n", strerror(_errno)); \ } while (0) #define overflow_error() _err("Internal buffer overflow. Please file a bug report.\n") /* Error checking version of sprintf() - returns 1 if overflow error */ #define sprintf_chk(str, args...) ({ \ int _rc; \ _rc = snprintf(str, sizeof(str), args); \ if (_rc >= (int)sizeof(str)) { \ overflow_error(); \ _rc = 1; \ } \ else \ _rc = 0; \ _rc; \ }) /* Error checking version of snprintf() - returns 1 if overflow error */ #define snprintf_chk(str, size, args...) ({ \ int _rc; \ _rc = snprintf(str, size, args); \ if (_rc >= (int)size) { \ overflow_error(); \ _rc = 1; \ } \ else \ _rc = 0; \ _rc; \ }) /* Grabbed from linux/module.h kernel include. */ #define MODULE_NAME_LEN (64 - sizeof(unsigned long)) /* We define this so we are compatible with old transport, but we * don't have to use it. */ #define STP_TRANSPORT_VERSION 1 #include "../runtime/transport/transport_msgs.h" #define RELAYFS_MAGIC 0xF0B4A981 #define DEBUGFS_MAGIC 0x64626720 #define DEBUGFSDIR "/sys/kernel/debug" #define RELAYFSDIR "/mnt/relay" /* * function prototypes */ int init_staprun(void); int init_stapio(void); int stp_main_loop(void); int send_request(int type, void *data, int len); void cleanup_and_exit (int, int); int init_ctl_channel(const char *name, int verb); void close_ctl_channel(void); int init_relayfs(void); void close_relayfs(void); int init_oldrelayfs(void); void close_oldrelayfs(int); int write_realtime_data(void *data, ssize_t nb); void setup_signals(void); int make_outfile_name(char *buf, int max, int fnum, int cpu, time_t t, int bulk); int init_backlog(int cpu); void write_backlog(int cpu, int fnum, time_t t); time_t read_backlog(int cpu, int fnum); /* staprun_funcs.c */ void setup_staprun_signals(void); const char *moderror(int err); /* insert_module helper functions. */ typedef void (*assert_permissions_func) ( const char *module_path __attribute__ ((unused)), int module_fd __attribute__ ((unused)), const void *module_data __attribute__ ((unused)), off_t module_size __attribute__ ((unused)), privilege_t *user_credentials __attribute__ ((unused)) ); void assert_stap_module_permissions ( const char *module_path __attribute__ ((unused)), int module_fd __attribute__ ((unused)), const void *module_data __attribute__ ((unused)), off_t module_size __attribute__ ((unused)), privilege_t *user_credentials __attribute__ ((unused)) ); void assert_uprobes_module_permissions ( const char *module_path __attribute__ ((unused)), int module_fd __attribute__ ((unused)), const void *module_data __attribute__ ((unused)), off_t module_size __attribute__ ((unused)), privilege_t *user_credentials __attribute__ ((unused)) ); int insert_module(const char *path, const char *special_options, char **options, assert_permissions_func apf, privilege_t *user_credentials ); int rename_module(void* module_file, const __off_t st_size); int mountfs(void); void start_symbol_thread(void); void stop_symbol_thread(void); /* common.c functions */ int stap_strfloctime(char *buf, size_t max, const char *fmt, time_t t); void parse_args(int argc, char **argv); void usage(char *prog); void parse_modpath(const char *); void setup_signals(void); int set_clexec(int fd); /* * variables */ extern int control_channel; extern int ncpus; extern int initialized; extern int kernel_ptr_size; /* flags */ extern int verbose; extern int suppress_warnings; extern unsigned int buffer_size; extern unsigned int reader_timeout_ms; extern char *modname; extern char *modpath; #define MAXMODOPTIONS 64 extern char *modoptions[MAXMODOPTIONS]; extern int target_pid; extern char *target_cmd; extern char *outfile_name; extern int rename_mod; extern int attach_mod; extern int delete_mod; extern int load_only; extern int need_uprobes; extern const char *uprobes_path; extern int daemon_mode; extern off_t fsize_max; extern int fnum_max; extern int remote_id; extern const char *remote_uri; extern int relay_basedir_fd; extern int color_errors; typedef enum {color_never, color_auto, color_always} color_modes; extern color_modes color_mode; /* getopt variables */ extern char *optarg; extern int optopt; extern int optind; /* maximum number of CPUs we can handle */ #define NR_CPUS 256 /* relay*.c uses these */ extern int out_fd[NR_CPUS]; /* relay_old uses these. Set in ctl.c */ extern unsigned subbuf_size; extern unsigned n_subbufs; /* * ppoll exists in glibc >= 2.4 */ #if (__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 4)) #define NEED_PPOLL extern int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, const sigset_t *sigmask); #endif systemtap-2.3/staprun/staprun_funcs.c000066400000000000000000000660221217430427200201510ustar00rootroot00000000000000/* -*- linux-c -*- * * staprun_funcs.c - staprun functions * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. * * Copyright (C) 2007-2012 Red Hat Inc. */ #include "../config.h" #include "staprun.h" #include #include #include #include #include /* The module-renaming facility only works with new enough elfutils: 0.142+. */ #ifdef HAVE_LIBELF_H #include #include #endif #include #include "modverify.h" #include "../privilege.h" typedef int (*check_module_path_func)(const char *module_path, int module_fd); extern long init_module(void *, unsigned long, const char *); extern gid_t get_gid (const char *group_name); /* Module errors get translated. */ const char *moderror(int err) { switch (err) { case ENOEXEC: return "Invalid module format"; case ENOENT: return "Unknown symbol in module"; case ESRCH: return "Module has wrong symbol version"; case EINVAL: return "Invalid parameters"; default: return strerror(err); } } int insert_module( const char *path, const char *special_options, char **options, assert_permissions_func assert_permissions, privilege_t *user_credentials ) { int i; long ret, module_read; void *module_file; char *opts; int saved_errno; char module_realpath[PATH_MAX]; int module_fd; struct stat sbuf; int rename_this_module; dbug(2, "inserting module %s\n", path); /* Rename the script module if '-R' was passed, but not other modules * like uprobes. We can tell which this is by comparing to the global * modpath, but we must do it before it's transformed by realpath. */ rename_this_module = rename_mod && (strcmp(path, modpath) == 0); if (special_options) opts = strdup(special_options); else opts = strdup(""); if (opts == NULL) { _perr("allocating memory failed"); return -1; } for (i = 0; options[i] != NULL; i++) { opts = realloc(opts, strlen(opts) + strlen(options[i]) + 2); if (opts == NULL) { _perr("[re]allocating memory failed"); return -1; } /* Note that these strcat() calls are OK, since we just * allocated space for the resulting string. */ strcat(opts, " "); strcat(opts, options[i]); } dbug(2, "module options: %s\n", opts); /* Use realpath() to canonicalize the module path. */ if (realpath(path, module_realpath) == NULL) { perr("Unable to canonicalize path \"%s\"", path); free(opts); return -1; } dbug(2, "module path canonicalized to '%s'\n", module_realpath); /* Use module_realpath from this point on. "Poison" 'path' by setting it to NULL so that it doesn't get used again by mistake. */ path = NULL; /* Open the module file. Work with the open file descriptor from this point on to avoid TOCTOU problems. */ module_fd = open(module_realpath, O_RDONLY); if (module_fd < 0) { perr("Couldn't open '%s'", module_realpath); free(opts); return -1; } /* Now that the file is open, figure out how big it is. */ if (fstat(module_fd, &sbuf) < 0) { _perr("Error stat'ing '%s'", module_realpath); close(module_fd); free(opts); return -1; } /* Allocate memory for the entire module. */ module_file = calloc(1, sbuf.st_size); if (module_file == NULL) { _perr("Error allocating memory to read '%s'", module_realpath); close(module_fd); free(opts); return -1; } /* Read in the entire module. Work with this copy of the data from this point on to avoid a TOCTOU race between path and signature checking below and module loading. */ module_read = 0; while (module_read < sbuf.st_size) { ret = read(module_fd, module_file + module_read, sbuf.st_size - module_read); if (ret > 0) module_read += ret; else if (ret == 0) { _err("Unexpected EOF reading '%s'", module_realpath); free(module_file); close(module_fd); free(opts); return -1; } else if (errno != EINTR) { _perr("Error reading '%s'", module_realpath); free(module_file); close(module_fd); free(opts); return -1; } } /* Check whether this module can be loaded by the current user. * check_permissions will exit(-1) if permissions are insufficient*/ assert_permissions (module_realpath, module_fd, module_file, sbuf.st_size, user_credentials); /* Rename Module if '-R' was passed */ if (rename_this_module) { dbug(2,"Renaming module '%s'\n", modname); if(rename_module(module_file, sbuf.st_size) < 0) { _err("Error renaming module"); close(module_fd); free(opts); return -1; } dbug(2,"Renamed module to '%s'\n", modname); } /* As a debugging aid for testing risky stap modules. */ if (getenv ("SYSTEMTAP_SYNC") != NULL) sync(); dbug(1,"Module %s inserted from file %s\n", modname, module_realpath); PROBE1(staprun, insert__module, (char*)module_realpath); /* Actually insert the module */ ret = init_module(module_file, sbuf.st_size, opts); saved_errno = errno; /* Cleanup. */ free(opts); free(module_file); close(module_fd); if (ret != 0) { errno = saved_errno; return -errno; } return 0; } #ifdef HAVE_ELF_GETSHDRSTRNDX static Elf_Scn * find_section_in_module(const void* module_file, const __off_t st_size, const char *section_name) { char *name; size_t shstrndx; Elf* elf; Elf_Scn *scn = 0; GElf_Shdr shdr_mem; /* Create descriptor for memory region. */ if((elf = elf_memory ((void *)module_file, st_size))== NULL) { _err("Error creating Elf object.\n"); return NULL; } /* Get the string section index */ if(elf_getshdrstrndx (elf, &shstrndx) < 0) { _err("Error getting section index.\n"); return NULL; } /* Go through the sections looking for the given section" */ while ((scn = elf_nextscn (elf, scn))) { if((gelf_getshdr (scn, &shdr_mem))==NULL) { _err("Error getting section header.\n"); return NULL; } name = elf_strptr (elf, shstrndx, shdr_mem.sh_name); if (name == NULL) { _err("Error getting section name.\n"); return NULL; } if(strcmp(name, section_name) == 0) { break; } } return scn; } #endif /* HAVE_ELF_GETSHDRSTRNDX */ int rename_module(void* module_file, const __off_t st_size) { #ifdef HAVE_ELF_GETSHDRSTRNDX int length_to_replace; char newname[MODULE_NAME_LEN]; char *p; pid_t pid; Elf_Scn *scn = 0; Elf_Data *data = 0; scn = find_section_in_module (module_file, st_size, ".gnu.linkonce.this_module"); if(!scn) { _err("Section name \".gnu.linkonce.this_module\" not found in module.\n"); return -1; } /* Get access to raw data from section; do not translate/copy. */ if ((data = elf_rawdata (scn, data)) == NULL) { _err("Error getting Elf data from section.\n"); return -1; } /* Generate new module name with the same length as the old name. The new name is of the form: stap__*/ if (strlen(modname) >= MODULE_NAME_LEN) { _err("Old module name is too long.\n"); return -1; } pid = getpid(); length_to_replace = (int)strlen(modname)-((int)log10(pid)+1) - 1; if(length_to_replace < 0 || length_to_replace > (int)strlen(modname)) { _err("Error getting length of oldname to replace in newname.\n"); return -1; } if (snprintf(newname, sizeof(newname), "%.*s_%d", length_to_replace, modname, pid) < 0) { _err("Creating newname failed./n"); return -1; } /* Find where it is in the module structure. To our knowledge, this section is always completely zeroed apart from the module name, so a simple search and replace should suffice. A signed module from any stapusr or stapsys user will already have been proven untampered. An unsigned module from a stapdev user could try to do naughty things, but we're already trusting these users so much that they can shoot their feet however they like. */ for (p = data->d_buf; p < (char *)data->d_buf + data->d_size - strlen(modname); p++) { if (memcmp(p, modname, strlen(modname)) == 0) { strncpy(p, newname, strlen(p)); /* Actually replace the oldname in memory with the newname */ modname = strdup(newname); /* This is just to update the global variable containing the current module name */ if (modname == NULL) { _perr("allocating memory failed"); return -1; } return 0; } } _err("Could not find old name to replace!\n"); return -1; #else /* Old or no elfutils? Pretend to have renamed. This means a greater likelihood for module-name collisions, but so be it. */ (void) module_file; (void) st_size; return 0; #endif } int mountfs(void) { struct stat sb; struct statfs st; int rc; /* If the debugfs dir is already mounted correctly, we're done. */ if (statfs(DEBUGFSDIR, &st) == 0 && (int) st.f_type == (int) DEBUGFS_MAGIC) return 0; /* If DEBUGFSDIR exists (and is a directory), try to mount * DEBUGFSDIR. */ rc = stat(DEBUGFSDIR, &sb); if (rc == 0 && S_ISDIR(sb.st_mode)) { /* If we can mount the debugfs dir correctly, we're done. */ rc = mount ("debugfs", DEBUGFSDIR, "debugfs", 0, NULL); if (rc == 0) return 0; /* If we got ENODEV, that means that debugfs isn't * supported, so we'll need try try relayfs. If we * didn't get ENODEV, we got a real error. */ else if (errno != ENODEV) { perr("Couldn't mount %s", DEBUGFSDIR); return -1; } } /* DEBUGFSDIR couldn't be mounted. So, try RELAYFSDIR. */ /* If the relayfs dir is already mounted correctly, we're done. */ if (statfs(RELAYFSDIR, &st) == 0 && (int)st.f_type == (int)RELAYFS_MAGIC) return 0; /* Ensure that RELAYFSDIR exists and is a directory. */ rc = stat(RELAYFSDIR, &sb); if (rc == 0 && ! S_ISDIR(sb.st_mode)) { err("%s exists but isn't a directory.\n", RELAYFSDIR); return -1; } else if (rc < 0) { mode_t old_umask; int saved_errno; gid_t gid = getgid(); uid_t uid = getuid(); /* To ensure the directory gets created with the proper * permissions, set umask to a known value. */ old_umask = umask(0002); /* To ensure the directory gets created with the * proper group, we'll have to temporarily switch to * root. */ /* XXX: Why not just chown() the thing? */ if (setuid (0) < 0) { _perr("Couldn't change user while creating %s", RELAYFSDIR); return -1; } if (setgid (0) < 0) { _perr("Couldn't change group while creating %s", RELAYFSDIR); return -1; } /* Try to create the directory, saving the return * status and errno value. */ rc = mkdir(RELAYFSDIR, 0755); saved_errno = errno; /* Restore everything we changed. */ if (setgid (gid) < 0) { _perr("Couldn't restore group while creating %s", RELAYFSDIR); return -1; } if (setuid (uid) < 0) { _perr("Couldn't restore user while creating %s", RELAYFSDIR); return -1; } umask(old_umask); /* If creating the directory failed, error out. */ if (rc < 0) { err("Couldn't create %s: %s\n", RELAYFSDIR, strerror(saved_errno)); return -1; } } /* Now that we're sure the directory exists, try mounting RELAYFSDIR. */ if (mount ("relayfs", RELAYFSDIR, "relayfs", 0, NULL) < 0) { perr("Couldn't mount %s", RELAYFSDIR); return -1; } return 0; } /* * Check the signature of the given module. * * Returns: -1 on errors, 0 on failure, 1 on success. */ #if ! HAVE_NSS static int check_signature(const char *path __attribute__((unused)), const void *module_data __attribute__((unused)), off_t module_size __attribute__((unused))) { return MODULE_UNTRUSTED; } #else static int check_signature(const char *path, const void *module_data, off_t module_size) { char signature_realpath[PATH_MAX]; int rc; dbug(2, "checking signature for %s\n", path); /* Add the .sgn suffix to the canonicalized module path to get the signature file path. */ if (strlen (path) >= PATH_MAX - 5) { err("Path \"%s.sgn\" is too long.", path); return -1; } /* This use of sprintf() is OK, since we just checked the final * string's length. */ sprintf (signature_realpath, "%s.sgn", path); rc = verify_module (signature_realpath, path, module_data, module_size); dbug(2, "verify_module returns %d\n", rc); return rc; } #endif /* HAVE_NSS */ /* * For stap modules which have not been signed by a trusted signer, * members of the 'stapusr' group can only use the "blessed" modules - * ones in the '/lib/modules/KVER/systemtap' directory. Make sure the * module path is in that directory. * * Returns: -1 on errors, 1 on success. */ static int check_stap_module_path(const char *module_path, int module_fd) { char staplib_dir_path[PATH_MAX]; char staplib_dir_realpath[PATH_MAX]; struct utsname utsbuf; struct stat sb; int rc = 1; /* First, we need to figure out what the kernel * version is and build the '/lib/modules/KVER/systemtap' path. */ if (uname(&utsbuf) != 0) { _perr("ERROR: Unable to determine kernel version, uname failed"); return -1; } if (sprintf_chk(staplib_dir_path, "/lib/modules/%s/systemtap", utsbuf.release)) return -1; /* Use realpath() to canonicalize the module directory path. */ if (realpath(staplib_dir_path, staplib_dir_realpath) == NULL) { perr("Members of the \"stapusr\" and \"stapsys\" groups can only use unsigned modules within\n" " the \"%s\" directory.\n" " Unable to canonicalize that directory", staplib_dir_path); return -1; } /* To make sure the user can't specify something like * /lib/modules/`uname -r`/systemtapmod.ko, put a '/' on the * end of staplib_dir_realpath. */ if (strlen(staplib_dir_realpath) < (PATH_MAX - 1)) /* Note that this strcat() is OK, since we just * checked the length of the resulting string. */ strcat(staplib_dir_realpath, "/"); else { err("Path \"%s\" is too long.", staplib_dir_realpath); return -1; } /* Validate /lib/modules/KVER/systemtap. No need to use fstat on an open file descriptor to avoid TOCTOU, since the path will not be used to access the file system. */ if (stat(staplib_dir_path, &sb) < 0) { perr("Members of the \"stapusr\" and \"stapsys\" groups can only use unsigned modules within\n" " the \"%s\" directory.\n" " Error getting information on that directory", staplib_dir_path); return -1; } /* Make sure it is a directory. */ if (! S_ISDIR(sb.st_mode)) { err("Members of the \"stapusr\" and \"stapsys\" groups can only use unsigned modules within\n" " the \"%s\" directory.\n" " That path must refer to a directory.\n", staplib_dir_path); return -1; } /* Make sure it is owned by root. */ if (sb.st_uid != 0) { err("Members of the \"stapusr\" and \"stapsys\" groups can only use unsigned modules within\n" " the \"%s\" directory.\n" " That directory should be owned by root.\n", staplib_dir_path); return -1; } /* Make sure it isn't world writable. */ if (sb.st_mode & S_IWOTH) { err("Members of the \"stapusr\" and \"stapsys\" groups can only use unsigned modules within\n" " the \"%s\" directory.\n" " That directory should not be world writable.\n", staplib_dir_path); return -1; } /* Now we've got two canonicalized paths. Make sure * module_path starts with staplib_dir_realpath. */ if (strncmp(staplib_dir_realpath, module_path, strlen(staplib_dir_realpath)) != 0) { err("Members of the \"stapusr\" and \"stapsys\" groups can only use unsigned modules within\n" " the \"%s\" directory.\n" " Module \"%s\" does not exist within that directory.\n", staplib_dir_path, module_path); return -1; } /* Validate the module permisions. */ if (fstat(module_fd, &sb) < 0) { perr("Couldn't get information on the module\"%s\"", module_path); return -1; } /* Make sure it is owned by root. */ if (sb.st_uid != 0) { err("The module \"%s\" must be owned by root.\n", module_path); rc = -1; } /* Make sure it isn't world writable. */ if (sb.st_mode & S_IWOTH) { err("The module \"%s\" must not be world writable.\n", module_path); rc = -1; } return rc; } /* * Don't allow path-based authorization for the uprobes module at all. * Members of the 'stapusr' group can load a signed uprobes module, but * nothing else. Later we could consider allowing specific paths, like * the installed runtime or /lib/modules/... * * Returns: -1 on errors, 0 on failure, 1 on success. */ static int check_uprobes_module_path ( const char *module_path __attribute__ ((unused)), int module_fd __attribute__ ((unused)) ) { return 0; } /* * Obtain the privilege credentials required to load the given module from the module itself. * * Returns the required credentials if they can be determined or the default safe required * credentials otherwise. */ static privilege_t get_module_required_credentials ( const char *module_path, const void* module_file __attribute__ ((unused)), const __off_t st_size __attribute__ ((unused)) ) { #ifndef HAVE_ELF_GETSHDRSTRNDX /* Without the proper ELF support, we can't determine the credentials required to run this module. However, we know that it has been correctly signed (we only check privilege credentials for correctly signed modules). It is therefore either a) a dual-privilege-level era module compiled with stapusr privileges enforced or, b) a multi-privilege-level era module with built-in privilege level checking. In either case, we can load it for stapusr level users and above. In case a, it requires exactly that privilege level. In case b, the module will self check against the user's actual privilege level. */ if (verbose >= 1) { eprintf ("Unable to determine the privilege level required for the module %s. Assuming %s.\n", module_path, pr_name (pr_stapusr)); } return pr_stapusr; #else Elf_Scn *scn = 0; Elf_Data *data = 0; GElf_Shdr shdr; privilege_t privilege; /* Look for the section containing the privilege information in the module. If we can't find the section, then we can assume that it is an old stap module, correctly signed, because: 1) We only check privilege credentials for correctly signed modules 2) A newer module would contain the required section. We can therefore assume that pr_stapusr is the required privilege level. */ scn = find_section_in_module (module_file, st_size, STAP_PRIVILEGE_SECTION); if (! scn) { if (verbose >= 1) { eprintf ("Section name \"%s\" not found in module %s.\n", STAP_PRIVILEGE_SECTION, module_path); eprintf ("Assuming required privilege level of %s.\n", pr_name (pr_stapusr)); } return pr_stapusr; } /* From here on if there is an error in the data, then it is most likely caused by a newer module containing data that we don't understand. We must then assume the highest privilege requirement. Get the section header. */ if (gelf_getshdr (scn, & shdr) == NULL) { if (verbose >= 1) { eprintf ("Error getting section header from section %s in module %s.\n", STAP_PRIVILEGE_SECTION, module_path); eprintf ("Assuming required privilege level of %s.\n", pr_name (pr_highest)); } return pr_highest; } /* The section should have at least one data item. */ if (shdr.sh_size < 1) { if (verbose >= 1) { eprintf ("Section header from section %s in module %s has no items\n", STAP_PRIVILEGE_SECTION, module_path); eprintf ("Assuming required privilege level of %s.\n", pr_name (pr_highest)); } return pr_highest; } /* The first data item contains the privilege requirement of the module. */ if ((data = elf_getdata (scn, data)) == NULL) { if (verbose >= 1) { eprintf ("Error getting data from section %s in module %s\n", STAP_PRIVILEGE_SECTION, module_path); eprintf ("Assuming required privilege level of %s.\n", pr_name (pr_highest)); } return pr_highest; } /* Make sure the data is the correct size. */ if (data->d_size != sizeof (privilege)) { if (verbose >= 1) { eprintf ("Data in section %s is in module %s not the correct size\n", STAP_PRIVILEGE_SECTION, module_path); eprintf ("Assuming required privilege level of %s.\n", pr_name (pr_highest)); } return pr_highest; } /* Obtain the data. It should already be in host byte order. */ privilege = *(privilege_t*)data->d_buf; /* Make sure that the data is coherent. */ switch (privilege) { case pr_stapusr: case pr_stapsys: case pr_stapdev: break; /* ok */ default: if (verbose >= 1) { eprintf ("Unknown privilege data, 0x%x in section %s in module %s\n", (int)privilege, STAP_PRIVILEGE_SECTION, module_path); err ("Assuming required privilege level of %s.\n", pr_name (pr_highest)); } return pr_highest; } /* ALl is ok. Return the extracted privilege data. */ return privilege; #endif /* HAVE_ELF_GETSHDRSTRNDX */ } /* * Check the user's group membership. * * o root and members of stapdev can do anything * o members of stapsys and stapusr can load signed modules compiled for their privilege levels * o all users can load modules from certain module-specific paths * * Returns: * -2 user has no privilege credentials * 0 on failure * 1 on success */ static int check_groups ( const char *module_path, int module_fd, int module_signature_status, check_module_path_func check_path, const void *module_data, off_t module_size, privilege_t *assigned_user_credentials ) { privilege_t user_credentials, module_required_credentials; int rc; /* Lookup the user's privilege credentials. */ user_credentials = get_privilege_credentials (); if (assigned_user_credentials) *assigned_user_credentials = user_credentials; /* Users with stapdev credentials (includes root) can do anything. */ if (pr_contains (user_credentials, pr_stapdev)) return 1; /* Users with stapsys and stapusr credentials may be able to load a signed module. */ if (module_signature_status == MODULE_OK) { /* We must verify that the module was compiled for that privilege level. */ module_required_credentials = get_module_required_credentials (module_path, module_data, module_size); if (pr_contains (user_credentials, module_required_credentials)) { /* Our credentials are sufficient */ return 1; } /* Our credentials are insufficient to load this module. */ err("Your privilege credentials (%s) are insufficient to load the module %s (%s required)\n", pr_name (user_credentials), module_path, pr_name (module_required_credentials)); if (user_credentials == pr_none) return -2; return 0; } /* Not fatal. The module could still be on a blessed path. */ assert (module_signature_status == MODULE_UNTRUSTED || module_signature_status == MODULE_CHECK_ERROR); /* Check whether this module can be loaded based on its path. check_path is a pointer to a module-specific function which will do this. If we can load this module due to its path, then assign all privilege credentials to the user, since the module may require them. */ rc = check_path (module_path, module_fd); if (rc == 1) { if (assigned_user_credentials) *assigned_user_credentials = pr_all; } else err("Unable to verify the signature for the module %s.\n", module_path); return rc; } /* * Check the user's permissions. Is he allowed to run staprun, or is * he limited to "blessed" modules? * * There are several levels of possible permission: * * 1) root can do anything * 2) members of stapdev can do anything * 3) members of stapsys and stapusr can load signed modules compiled for their privilege levels * 4) all users can load unsigned modules from /lib/modules/KVER/systemtap * * It is only an error if all 4 levels of checking fail */ void assert_stap_module_permissions( const char *module_path, int module_fd, const void *module_data, off_t module_size, privilege_t *user_credentials ) { int check_groups_rc; int check_signature_rc; /* Attempt to verify the module against its signature. Exit immediately if the module has been tampered with (altered). */ check_signature_rc = check_signature (module_path, module_data, module_size); if (check_signature_rc == MODULE_ALTERED) exit(-1); /* If we're root, we can do anything. */ if (getuid() == 0) { /* ... like overriding the real UID */ const char *env_id = getenv("SYSTEMTAP_REAL_UID"); if (env_id && setreuid(atoi(env_id), -1)) warn("Couldn't set staprun UID to '%s': %s", env_id, strerror(errno)); /* ... or overriding the real GID */ env_id = getenv("SYSTEMTAP_REAL_GID"); if (env_id && setregid(atoi(env_id), -1)) warn("Couldn't set staprun GID to '%s': %s", env_id, strerror(errno)); if (user_credentials) *user_credentials = pr_all; return; } /* Check permissions for group membership. */ check_groups_rc = check_groups (module_path, module_fd, check_signature_rc, check_stap_module_path, module_data, module_size, user_credentials); if (check_groups_rc == 1) return; /* Are we are an ordinary user?. */ if (check_groups_rc == -2) { err("You are trying to run systemtap as a normal user.\n" "You should either be root, or be part of " "group \"stapusr\" and possibly the groups \"stapsys\" or \"stapdev\".\n"); } exit(-1); } /* * Check the user's permissions. Is he allowed to load the uprobes module? * * There are several levels of possible permission: * * 1) root can do anything * 2) members of stapdev can do anything * 3) members of stapusr can load a uprobes module which has been signed by a * trusted signer * * It is only an error if all 3 levels of checking fail */ void assert_uprobes_module_permissions( const char *module_path, int module_fd, const void *module_data, off_t module_size, privilege_t *user_credentials ) { int check_groups_rc; int check_signature_rc; /* Attempt to verify the module against its signature. Return failure if the module has been tampered with (altered). */ check_signature_rc = check_signature (module_path, module_data, module_size); if (check_signature_rc == MODULE_ALTERED) exit(-1); /* root can still load this module. */ if (getuid() == 0) { if (user_credentials) *user_credentials = pr_all; return; } /* Members of the groups stapdev and stapusr can still load this module. */ check_groups_rc = check_groups (module_path, module_fd, check_signature_rc, check_uprobes_module_path, module_data, module_size, user_credentials); if (check_groups_rc == 1) return; /* Check permissions for group membership. */ if (check_groups_rc == -2) { err("You are trying to load the module %s as a normal user.\n" "You should either be root, or be part of " "group \"stapusr\" and possibly the groups \"stapsys\" or \"stapdev\".\n", module_path); } exit(-1); } systemtap-2.3/staprun/stapsh.c000066400000000000000000000251051217430427200165560ustar00rootroot00000000000000// stapsh - systemtap remote shell // Copyright (C) 2011 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // stapsh implements a minimal protocol for a remote stap client to transfer a // systemtap module to a temporary location and invoke staprun on it. It is // not meant to be invoked directly by the user. Commands are simply // whitespace-delimited strings, terminated by newlines. // // command: stap VERSION // reply: stapsh VERSION MACHINE RELEASE // desc: This is the initial handshake. The VERSION exchange is intended // to facilitate compatibility checks, in case the protocol needs to // change. MACHINE and RELEASE are reported as given by uname. // // command: file SIZE NAME // DATA // reply: OK / error message // desc: Create a file of SIZE bytes, called NAME. The NAME is a basename // only, and limited to roughly "[a-z0-9][a-z0-9._]*". The DATA is // read as raw bytes following the command's newline. // // command: run ARG1 ARG2 ... // reply: OK / error message // desc: Start staprun with the given quoted-printable arguments. When // the child exits, stapsh will clean up and then exit with the same // return code. Note that whitespace has significance in stapsh // command parsing, all tabs, spaces, and newlines must be escaped // in the arguments. Any embedded NIL (=00) will truncate the // argument in the actual command invocation. // // command: quit // reply: (none) // desc: Signal the child process to quit, then cleanup and exit. // // If stapsh reaches EOF on its standard input, it will send SIGHUP to the // child process, wait for completion, then cleanup and exit normally. #include "../config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #define STAPSH_TOK_DELIM " \t\r\n" #define STAPSH_MAX_FILE_SIZE 32000000 // XXX should be cumulative? #define STAPSH_MAX_ARGS 256 struct stapsh_handler { const char* name; int (*fn)(void); }; static int do_hello(void); static int do_file(void); static int do_run(void); static int do_quit(void); static const int signals[] = { SIGHUP, SIGPIPE, SIGINT, SIGTERM, SIGCHLD }; static const struct stapsh_handler commands[] = { { "stap", do_hello }, { "file", do_file }, { "run", do_run }, { "quit", do_quit }, }; static const unsigned ncommands = sizeof(commands) / sizeof(*commands); static char tmpdir[FILENAME_MAX] = ""; static pid_t staprun_pid = -1; static unsigned verbose = 0; #define dbug(level, format, args...) do { if (verbose >= level) \ fprintf (stderr, "stapsh:%s:%d " format, __FUNCTION__, __LINE__, ## args); \ } while (0) #define vdbug(level, format, args) do { if (verbose >= level) { \ fprintf (stderr, "stapsh:%s:%d ", __FUNCTION__, __LINE__); \ vfprintf (stderr, format, args); \ } } while (0) #define die(format, args...) ({ dbug(1, format, ## args); cleanup(2); }) static void __attribute__ ((noreturn)) cleanup(int status) { // Mask signals, so if called from non-signal context, we // won't get a reentry (especially for SIGCHLD). unsigned i; sigset_t mask; sigemptyset (&mask); for (i = 0; i < sizeof(signals) / sizeof(*signals); ++i) sigaddset (&mask, signals[i]); sigprocmask(SIG_BLOCK, &mask, 0); if (staprun_pid > 0) { int rc, ret; kill(staprun_pid, SIGHUP); ret = waitpid(staprun_pid, &rc, 0); if (status == 0) { if (ret == staprun_pid) status = WIFEXITED(rc) ? WEXITSTATUS(rc) : 128 + WTERMSIG(rc); else status = 2; } } if (tmpdir[0]) { pid_t pid = 0; const char* argv[] = {"rm", "-rf", "--", tmpdir, NULL}; if (chdir("/")) {} // ignore failure, rm will probably work anyway if (!posix_spawnp(&pid, argv[0], NULL, NULL, (char* const*)argv, environ)) waitpid(pid, NULL, 0); } exit(status); } static void handle_signal(int sig) { dbug(1, "received signal %d: %s\n", sig, strsignal(sig)); cleanup(0); } static void setup_signals (void) { unsigned i; struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = handle_signal; sigemptyset (&sa.sa_mask); for (i = 0; i < sizeof(signals) / sizeof(*signals); ++i) sigaddset (&sa.sa_mask, signals[i]); for (i = 0; i < sizeof(signals) / sizeof(*signals); ++i) sigaction (signals[i], &sa, NULL); } static void __attribute__ ((noreturn)) usage (char *prog, int status) { fprintf (stderr, "%s [-v]\n", prog); exit (status); } static void parse_args(int argc, char* const argv[]) { int c; while ((c = getopt (argc, argv, "v")) != -1) switch (c) { case 'v': ++verbose; break; case '?': default: usage (argv[0], 2); } if (optind < argc) { fprintf (stderr, "%s: invalid extraneous arguments\n", argv[0]); usage (argv[0], 2); } } // Decode a quoted-printable string in-place static int qpdecode(char* s) { char* o = s; while (*s) if (*s != '=') *o++ = *s++; else { if (s[1] == '\r' || s[1] == '\n') s += 2; else if (s[1] == '\r' && s[2] == '\n') s += 3; else if (!s[1] || !s[2]) { dbug(2, "truncated quoted-printable escape \"%s\"\n", s); return 1; } else { errno = 0; char *end = 0, hex[] = { s[1], s[2], 0 }; unsigned char c = strtol(hex, &end, 16); if (errno || end != hex + 2) { dbug(2, "invalid quoted-printable escape \"=%s\"\n", hex); return 1; } *o++ = c; s += 3; } } *o = '\0'; return 0; } // Send a reply back to the client on stdout static int __attribute__ ((format (printf, 1, 2))) reply(const char* format, ...) { va_list args, dbug_args; va_start (args, format); va_copy (dbug_args, args); vdbug (1, format, dbug_args); int ret = vprintf (format, args); fflush (stdout); va_end (dbug_args); va_end (args); return ret; } static int do_hello() { if (staprun_pid > 0) return 1; // XXX check caller's version compatibility struct utsname uts; if (uname(&uts)) return 1; reply ("stapsh %s %s %s\n", VERSION, uts.machine, uts.release); return 0; } static int do_file() { if (staprun_pid > 0) return 1; int ret = 0; int size = -1; const char* arg = strtok(NULL, STAPSH_TOK_DELIM); if (arg) size = atoi(arg); if (size <= 0 || size > STAPSH_MAX_FILE_SIZE) return reply ("ERROR: bad file size %d\n", size); const char* name = strtok(NULL, STAPSH_TOK_DELIM); if (!name) return reply ("ERROR: missing file name\n"); for (arg = name; *arg; ++arg) if (!isalnum(*arg) && !(arg > name && (*arg == '.' || *arg == '_'))) return reply ("ERROR: bad character '%c' in file name\n", *arg); FILE* f = fopen(name, "w"); if (!f) return reply ("ERROR: can't open file \"%s\" for writing\n", name); while (size > 0 && ret == 0) { char buf[1024]; size_t r = sizeof(buf); if ((size_t)size < sizeof(buf)) r = size; r = fread(buf, 1, r, stdin); if (!r && feof(stdin)) ret = reply ("ERROR: reached EOF while reading file data\n"); else if (!r) ret = reply ("ERROR: unable to read file data\n"); else { size -= r; const char* bufp = buf; while (bufp < buf + r && ret == 0) { size_t w = (buf + r) - bufp; w = fwrite(bufp, 1, w, f); if (!w) ret = reply ("ERROR: unable to write file data\n"); else bufp += w; } } } fclose(f); if (ret == 0) reply ("OK\n"); return ret; } static int do_run() { if (staprun_pid > 0) return 1; char staprun[] = BINDIR "/staprun"; char* args[STAPSH_MAX_ARGS + 1] = { staprun, 0 }; unsigned nargs = 1; char* arg; while ((arg = strtok(NULL, STAPSH_TOK_DELIM))) { if (nargs + 1 > STAPSH_MAX_ARGS) return reply ("ERROR: too many arguments\n"); if (qpdecode(arg) != 0) return reply ("ERROR: invalid encoding in argument \"%s\"\n", arg); args[nargs++] = arg; } // Explicitly check execute permissions here, because posix_spawn will only // report that failure through a process exit code. if (access(staprun, X_OK) != 0) return reply ("ERROR: can't execute %s (%s)\n", staprun, strerror(errno)); int ret = 0; posix_spawn_file_actions_t fa; if (posix_spawn_file_actions_init(&fa) != 0) return reply ("ERROR: can't initialize posix_spawn actions\n"); // no stdin for staprun if (posix_spawn_file_actions_addopen(&fa, 0, "/dev/null", O_RDONLY, 0) != 0) ret = reply ("ERROR: can't set posix_spawn actions\n"); else { pid_t pid; ret = posix_spawn(&pid, args[0], &fa, NULL, args, environ); if (ret == 0) staprun_pid = pid; else reply("ERROR: can't launch staprun\n"); } posix_spawn_file_actions_destroy(&fa); if (ret == 0) reply ("OK\n"); return ret; } static int do_quit() { cleanup(0); } int main(int argc, char* const argv[]) { parse_args(argc, argv); setup_signals(); umask(0077); snprintf(tmpdir, sizeof(tmpdir), "%s/stapsh.XXXXXX", getenv("TMPDIR") ?: "/tmp"); if (!mkdtemp(tmpdir)) die ("Can't make a temporary working directory!\n"); if (chdir(tmpdir)) die ("Can't change to temporary working directory \"%s\"!\n", tmpdir); char command[4096]; while (fgets(command, sizeof(command), stdin)) { dbug(1, "command: %s", command); int rc = -1; unsigned i; const char* arg = strtok(command, STAPSH_TOK_DELIM) ?: "(null)"; for (i = 0; i < ncommands; ++i) if (strcmp(arg, commands[i].name) == 0) { rc = commands[i].fn(); if (rc) dbug(2, "failed command %s, rc=%d\n", arg, rc); break; } if (i >= ncommands) dbug(2, "invalid command %s\n", arg); } cleanup(0); } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/stapsslerr.h000066400000000000000000000713261217430427200157750ustar00rootroot00000000000000/* scraped from http://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslerr.html */ /* and mozilla security/manager/locales/en-US/chrome/pipnss/nsserrors.properties */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is the Netscape security libraries. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1994-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * ***** END LICENSE BLOCK ***** */ /* For systemtap's purposes, GPLv2 is the winning license. */ NSSYERROR(SSL_ERROR_EXPORT_ONLY_SERVER,"Unable to communicate securely. Peer does not support high-grade encryption."); NSSYERROR(SSL_ERROR_US_ONLY_SERVER,"Unable to communicate securely. Peer requires high-grade encryption which is not supported."); NSSYERROR(SSL_ERROR_NO_CYPHER_OVERLAP,"Cannot communicate securely with peer: no common encryption algorithm(s)."); NSSYERROR(SSL_ERROR_NO_CERTIFICATE,"Unable to find the certificate or key necessary for authentication."); NSSYERROR(SSL_ERROR_BAD_CERTIFICATE,"Unable to communicate securely with peer: peers's certificate was rejected."); NSSYERROR(SSL_ERROR_BAD_CLIENT,"The server has encountered bad data from the client."); NSSYERROR(SSL_ERROR_BAD_SERVER,"The client has encountered bad data from the server."); NSSYERROR(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE,"Unsupported certificate type."); NSSYERROR(SSL_ERROR_UNSUPPORTED_VERSION,"Peer using unsupported version of security protocol."); NSSYERROR(SSL_ERROR_WRONG_CERTIFICATE,"Client authentication failed: private key in key database does not correspond to public key in certificate database."); NSSYERROR(SSL_ERROR_BAD_CERT_DOMAIN,"Unable to communicate securely with peer: requested domain name does not match the server's certificate."); NSSYERROR(SSL_ERROR_SSL2_DISABLED,"Peer only supports SSL version 2, which is locally disabled."); NSSYERROR(SSL_ERROR_BAD_MAC_READ,"SSL received a record with an incorrect Message Authentication Code."); NSSYERROR(SSL_ERROR_BAD_MAC_ALERT,"SSL peer reports incorrect Message Authentication Code."); NSSYERROR(SSL_ERROR_BAD_CERT_ALERT,"SSL peer cannot verify your certificate."); NSSYERROR(SSL_ERROR_REVOKED_CERT_ALERT,"SSL peer rejected your certificate as revoked."); NSSYERROR(SSL_ERROR_EXPIRED_CERT_ALERT,"SSL peer rejected your certificate as expired."); NSSYERROR(SSL_ERROR_SSL_DISABLED,"Cannot connect: SSL is disabled."); NSSYERROR(SSL_ERROR_FORTEZZA_PQG,"Cannot connect: SSL peer is in another FORTEZZA domain."); NSSYERROR(SSL_ERROR_UNKNOWN_CIPHER_SUITE,"An unknown SSL cipher suite has been requested."); NSSYERROR(SSL_ERROR_NO_CIPHERS_SUPPORTED,"No cipher suites are present and enabled in this program."); NSSYERROR(SSL_ERROR_BAD_BLOCK_PADDING,"SSL received a record with bad block padding."); NSSYERROR(SSL_ERROR_RX_RECORD_TOO_LONG,"SSL received a record that exceeded the maximum permissible length."); NSSYERROR(SSL_ERROR_TX_RECORD_TOO_LONG,"SSL attempted to send a record that exceeded the maximum permissible length."); NSSYERROR(SSL_ERROR_CLOSE_NOTIFY_ALERT,"SSL peer has closed this connection."); NSSYERROR(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED,"SSL Server attempted to use domestic-grade public key with export cipher suite."); NSSYERROR(SSL_ERROR_NO_SERVER_KEY_FOR_ALG,"Server has no key for the attempted key exchange algorithm."); NSSYERROR(SSL_ERROR_TOKEN_INSERTION_REMOVAL,"PKCS #11 token was inserted or removed while operation was in progress."); NSSYERROR(SSL_ERROR_TOKEN_SLOT_NOT_FOUND,"No PKCS#11 token could be found to do a required operation."); NSSYERROR(SSL_ERROR_NO_COMPRESSION_OVERLAP,"Cannot communicate securely with peer: no common compression algorithm(s)."); NSSYERROR(SSL_ERROR_HANDSHAKE_NOT_COMPLETED,"Cannot initiate another SSL handshake until current handshake is complete."); NSSYERROR(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE,"Received incorrect handshakes hash values from peer."); NSSYERROR(SSL_ERROR_CERT_KEA_MISMATCH,"The certificate provided cannot be used with the selected key exchange algorithm."); NSSYERROR(SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA,"No certificate authority is trusted for SSL client authentication."); NSSYERROR(SSL_ERROR_SESSION_NOT_FOUND,"Client's SSL session ID not found in server's session cache."); NSSYERROR(SSL_ERROR_RX_MALFORMED_HELLO_REQUEST,"SSL received a malformed Hello Request handshake message."); NSSYERROR(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO,"SSL received a malformed Client Hello handshake message."); NSSYERROR(SSL_ERROR_RX_MALFORMED_SERVER_HELLO,"SSL received a malformed Server Hello handshake message."); NSSYERROR(SSL_ERROR_RX_MALFORMED_CERTIFICATE,"SSL received a malformed Certificate handshake message."); NSSYERROR(SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH,"SSL received a malformed Server Key Exchange handshake message."); NSSYERROR(SSL_ERROR_RX_MALFORMED_CERT_REQUEST,"SSL received a malformed Certificate Request handshake message."); NSSYERROR(SSL_ERROR_RX_MALFORMED_HELLO_DONE,"SSL received a malformed Server Hello Done handshake message."); NSSYERROR(SSL_ERROR_RX_MALFORMED_CERT_VERIFY,"SSL received a malformed Certificate Verify handshake message."); NSSYERROR(SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH,"SSL received a malformed Client Key Exchange handshake message."); NSSYERROR(SSL_ERROR_RX_MALFORMED_FINISHED,"SSL received a malformed Finished handshake message."); NSSYERROR(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER,"SSL received a malformed Change Cipher Spec record."); NSSYERROR(SSL_ERROR_RX_MALFORMED_ALERT,"SSL received a malformed Alert record."); NSSYERROR(SSL_ERROR_RX_MALFORMED_HANDSHAKE,"SSL received a malformed Handshake record."); NSSYERROR(SSL_ERROR_RX_MALFORMED_APPLICATION_DATA,"SSL received a malformed Application Data record."); NSSYERROR(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST,"SSL received an unexpected Hello Request handshake message."); NSSYERROR(SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO,"SSL received an unexpected Client Hello handshake message."); NSSYERROR(SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO,"SSL received an unexpected Server Hello handshake message."); NSSYERROR(SSL_ERROR_RX_UNEXPECTED_CERTIFICATE,"SSL received an unexpected Certificate handshake message."); NSSYERROR(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH,"SSL received an unexpected Server Key Exchange handshake message."); NSSYERROR(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST,"SSL received an unexpected Certificate Request handshake message."); NSSYERROR(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE,"SSL received an unexpected Server Hello Done handshake message."); NSSYERROR(SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY,"SSL received an unexpected Certificate Verify handshake message."); NSSYERROR(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH,"SSL received an unexpected Client Key Exchange handshake message."); NSSYERROR(SSL_ERROR_RX_UNEXPECTED_FINISHED,"SSL received an unexpected Finished handshake message."); NSSYERROR(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER,"SSL received an unexpected Change Cipher Spec record."); NSSYERROR(SSL_ERROR_RX_UNEXPECTED_ALERT,"SSL received an unexpected Alert record."); NSSYERROR(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE,"SSL received an unexpected Handshake record."); NSSYERROR(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA,"SSL received an unexpected Application Data record."); NSSYERROR(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE,"SSL received a record with an unknown content type."); NSSYERROR(SSL_ERROR_RX_UNKNOWN_HANDSHAKE,"SSL received a handshake message with an unknown message type."); NSSYERROR(SSL_ERROR_RX_UNKNOWN_ALERT,"SSL received an alert record with an unknown alert description."); NSSYERROR(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT,"SSL peer was not expecting a handshake message it received."); NSSYERROR(SSL_ERROR_DECOMPRESSION_FAILURE_ALERT,"SSL peer was unable to successfully decompress an SSL record it received."); NSSYERROR(SSL_ERROR_HANDSHAKE_FAILURE_ALERT,"SSL peer was unable to negotiate an acceptable set of security parameters."); NSSYERROR(SSL_ERROR_ILLEGAL_PARAMETER_ALERT,"SSL peer rejected a handshake message for unacceptable content."); NSSYERROR(SSL_ERROR_UNSUPPORTED_CERT_ALERT,"SSL peer does not support certificates of the type it received."); NSSYERROR(SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT,"SSL peer had some unspecified issue with the certificate it received."); NSSYERROR(SSL_ERROR_DECRYPTION_FAILED_ALERT,"Peer was unable to decrypt an SSL record it received."); NSSYERROR(SSL_ERROR_RECORD_OVERFLOW_ALERT,"Peer received an SSL record that was longer than is permitted."); NSSYERROR(SSL_ERROR_UNKNOWN_CA_ALERT,"Peer does not recognize and trust the CA that issued your certificate."); NSSYERROR(SSL_ERROR_ACCESS_DENIED_ALERT,"Peer received a valid certificate, but access was denied."); NSSYERROR(SSL_ERROR_DECODE_ERROR_ALERT,"Peer could not decode an SSL handshake message."); NSSYERROR(SSL_ERROR_DECRYPT_ERROR_ALERT,"Peer reports failure of signature verification or key exchange."); NSSYERROR(SSL_ERROR_EXPORT_RESTRICTION_ALERT,"Peer reports negotiation not in compliance with export regulations."); NSSYERROR(SSL_ERROR_PROTOCOL_VERSION_ALERT,"Peer reports incompatible or unsupported protocol version."); NSSYERROR(SSL_ERROR_INSUFFICIENT_SECURITY_ALERT,"Server requires ciphers more secure than those supported by client."); NSSYERROR(SSL_ERROR_INTERNAL_ERROR_ALERT,"Peer reports it experienced an internal error."); NSSYERROR(SSL_ERROR_USER_CANCELED_ALERT,"Peer user canceled handshake."); NSSYERROR(SSL_ERROR_NO_RENEGOTIATION_ALERT,"Peer does not permit renegotiation of SSL security parameters."); NSSYERROR(SSL_ERROR_GENERATE_RANDOM_FAILURE,"SSL experienced a failure of its random number generator."); NSSYERROR(SSL_ERROR_SIGN_HASHES_FAILURE,"Unable to digitally sign data required to verify your certificate."); NSSYERROR(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE,"SSL was unable to extract the public key from the peer's certificate."); NSSYERROR(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE,"Unspecified failure while processing SSL Server Key Exchange handshake."); NSSYERROR(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE,"Unspecified failure while processing SSL Client Key Exchange handshake."); NSSYERROR(SSL_ERROR_ENCRYPTION_FAILURE,"Bulk data encryption algorithm failed in selected cipher suite."); NSSYERROR(SSL_ERROR_DECRYPTION_FAILURE,"Bulk data decryption algorithm failed in selected cipher suite."); NSSYERROR(SSL_ERROR_MD5_DIGEST_FAILURE,"MD5 digest function failed."); NSSYERROR(SSL_ERROR_SHA_DIGEST_FAILURE,"SHA - 1 digest function failed."); NSSYERROR(SSL_ERROR_MAC_COMPUTATION_FAILURE,"Message Authentication Code computation failed."); NSSYERROR(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE,"Failure to create Symmetric Key context."); NSSYERROR(SSL_ERROR_SYM_KEY_UNWRAP_FAILURE,"Failure to unwrap the Symmetric key in Client Key Exchange message."); NSSYERROR(SSL_ERROR_IV_PARAM_FAILURE,"PKCS11 code failed to translate an IV into a param."); NSSYERROR(SSL_ERROR_INIT_CIPHER_SUITE_FAILURE,"Failed to initialize the selected cipher suite."); NSSYERROR(SSL_ERROR_SOCKET_WRITE_FAILURE,"Attempt to write encrypted data to underlying socket failed."); NSSYERROR(SSL_ERROR_SESSION_KEY_GEN_FAILURE,"Failed to generate session keys for SSL session."); NSSYERROR(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED,"SSL server cache not configured and not disabled for this socket."); NSSYERROR(SSL_ERROR_UNSUPPORTED_EXTENSION_ALERT,"SSL peer does not support requested TLS hello extension."); NSSYERROR(SSL_ERROR_CERTIFICATE_UNOBTAINABLE_ALERT,"SSL peer could not obtain your certificate from the supplied URL."); NSSYERROR(SSL_ERROR_UNRECOGNIZED_NAME_ALERT,"SSL peer has no certificate for the requested DNS name."); NSSYERROR(SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT,"SSL peer was unable to get an OCSP response for its certificate."); NSSYERROR(SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT,"SSL peer reported bad certificate hash value."); NSSYERROR(SEC_ERROR_IO,"An I / O error occurred during authentication) or an error occurred during crypto operation (other than signature verification)."); NSSYERROR(SEC_ERROR_LIBRARY_FAILURE,"Security library failure."); NSSYERROR(SEC_ERROR_BAD_DATA,"Security library: received bad data."); NSSYERROR(SEC_ERROR_OUTPUT_LEN,"Security library: output length error."); NSSYERROR(SEC_ERROR_INPUT_LEN,"Security library: input length error."); NSSYERROR(SEC_ERROR_INVALID_ARGS,"Security library: invalid arguments."); NSSYERROR(SEC_ERROR_INVALID_ALGORITHM,"Security library: invalid algorithm."); NSSYERROR(SEC_ERROR_INVALID_AVA,"Security library: invalid AVA."); NSSYERROR(SEC_ERROR_INVALID_TIME,"Security library: invalid time."); NSSYERROR(SEC_ERROR_BAD_DER,"Security library:improperly formatted DER - encoded message."); NSSYERROR(SEC_ERROR_BAD_SIGNATURE,"Peer's certificate has an invalid signature."); NSSYERROR(SEC_ERROR_EXPIRED_CERTIFICATE,"Peer's certificate has expired."); NSSYERROR(SEC_ERROR_REVOKED_CERTIFICATE,"Peer's certificate has been revoked."); NSSYERROR(SEC_ERROR_UNKNOWN_ISSUER,"Peer's certificate issuer is not recognized."); NSSYERROR(SEC_ERROR_BAD_KEY,"Peer's public key is invalid"); NSSYERROR(SEC_ERROR_BAD_PASSWORD,"The password entered is incorrect."); NSSYERROR(SEC_ERROR_RETRY_PASSWORD,"New password entered incorrectly."); NSSYERROR(SEC_ERROR_NO_NODELOCK,"Security library: no nodelock."); NSSYERROR(SEC_ERROR_BAD_DATABASE,"Security library: bad database."); NSSYERROR(SEC_ERROR_NO_MEMORY,"Security library: memory allocation failure."); NSSYERROR(SEC_ERROR_UNTRUSTED_ISSUER,"Peer's certificate issuer has been marked as not trusted by the user."); NSSYERROR(SEC_ERROR_UNTRUSTED_CERT,"Peer's certificate has been marked as not trusted by the user."); NSSYERROR(SEC_ERROR_DUPLICATE_CERT,"Certificate already exists in your database."); NSSYERROR(SEC_ERROR_DUPLICATE_CERT_NAME,"Downloaded certificate's name duplicates one already in your database."); NSSYERROR(SEC_ERROR_ADDING_CERT,"Error adding certificate to database."); NSSYERROR(SEC_ERROR_FILING_KEY,"Error refiling the key for this certificate."); NSSYERROR(SEC_ERROR_NO_KEY,"The private key for this certificate cannot be found in key database."); NSSYERROR(SEC_ERROR_CERT_VALID,"This certificate is valid."); NSSYERROR(SEC_ERROR_CERT_NOT_VALID,"This certificate is not valid."); NSSYERROR(SEC_ERROR_CERT_NO_RESPONSE,"Certificate library:no response."); NSSYERROR(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE,"The certificate issuer's certificate has expired."); NSSYERROR(SEC_ERROR_CRL_EXPIRED,"The CRL for the certificate's issuer has expired."); NSSYERROR(SEC_ERROR_CRL_BAD_SIGNATURE,"The CRL for the certificate's issuer has an invalid signature."); NSSYERROR(SEC_ERROR_CRL_INVALID,"New CRL has an invalid format."); NSSYERROR(SEC_ERROR_EXTENSION_VALUE_INVALID,"Certificate extension value is invalid."); NSSYERROR(SEC_ERROR_EXTENSION_NOT_FOUND,"Certificate extension not found."); NSSYERROR(SEC_ERROR_CA_CERT_INVALID,"Issuer certificate is invalid."); NSSYERROR(SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID,"Certificate path length constraint is invalid."); NSSYERROR(SEC_ERROR_CERT_USAGES_INVALID,"Certificate usages field is invalid."); NSSYERROR(SEC_INTERNAL_ONLY,"Internal-only module."); NSSYERROR(SEC_ERROR_INVALID_KEY,"The key does not support the requested operation."); NSSYERROR(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION,"Certificate contains unknown critical extension."); NSSYERROR(SEC_ERROR_OLD_CRL,"New CRL is not later than the current one."); NSSYERROR(SEC_ERROR_NO_EMAIL_CERT,"Not encrypted or signed: you do not yet have an email certificate."); NSSYERROR(SEC_ERROR_NO_RECIPIENT_CERTS_QUERY,"Not encrypted: you do not have certificates for each of the recipients."); NSSYERROR(SEC_ERROR_NOT_A_RECIPIENT,"Cannot decrypt: you are not a recipient, or matching certificate and private key not found."); NSSYERROR(SEC_ERROR_PKCS7_KEYALG_MISMATCH,"Cannot decrypt: key encryption algorithm does not match your certificate."); NSSYERROR(SEC_ERROR_PKCS7_BAD_SIGNATURE,"Signature verification failed: no signer found, too many signers found, or improper or corrupted data. "); NSSYERROR(SEC_ERROR_UNSUPPORTED_KEYALG,"Unsupported or unknown key algorithm."); NSSYERROR(SEC_ERROR_DECRYPTION_DISALLOWED,"Cannot decrypt: encrypted using a disallowed algorithm or key size."); NSSYERROR(XP_SEC_FORTEZZA_BAD_CARD,"FORTEZZA card has not been properly initialized."); NSSYERROR(XP_SEC_FORTEZZA_NO_CARD,"No FORTEZZA cards found."); NSSYERROR(XP_SEC_FORTEZZA_NONE_SELECTED,"No FORTEZZA card selected."); NSSYERROR(XP_SEC_FORTEZZA_MORE_INFO,"Please select a personality to get more info on."); NSSYERROR(XP_SEC_FORTEZZA_PERSON_NOT_FOUND,"Personality not found"); NSSYERROR(XP_SEC_FORTEZZA_NO_MORE_INFO,"No more information on that personality."); NSSYERROR(XP_SEC_FORTEZZA_BAD_PIN,"Invalid PIN."); NSSYERROR(XP_SEC_FORTEZZA_PERSON_ERROR,"Couldn' t initialize FORTEZZA personalities."); NSSYERROR(SEC_ERROR_NO_KRL,"No KRL for this site's certificate has been found."); NSSYERROR(SEC_ERROR_KRL_EXPIRED,"The KRL for this site's certificate has expired."); NSSYERROR(SEC_ERROR_KRL_BAD_SIGNATURE,"The KRL for this site's certificate has an invalid signature."); NSSYERROR(SEC_ERROR_REVOKED_KEY,"The key for this site's certificate has been revoked."); NSSYERROR(SEC_ERROR_KRL_INVALID,"New KRL has an invalid format."); NSSYERROR(SEC_ERROR_NEED_RANDOM,"Security library: need random data."); NSSYERROR(SEC_ERROR_NO_MODULE,"Security library: no security module can perform the requested operation."); NSSYERROR(SEC_ERROR_NO_TOKEN,"The security card or token does not exist, needs to be initialized, or has been removed."); NSSYERROR(SEC_ERROR_READ_ONLY,"Security library:read - only database."); NSSYERROR(SEC_ERROR_NO_SLOT_SELECTED,"No slot or token was selected."); NSSYERROR(SEC_ERROR_CERT_NICKNAME_COLLISION,"A certificate with the same nickname already exists."); NSSYERROR(SEC_ERROR_KEY_NICKNAME_COLLISION,"A key with the same nickname already exists. "); NSSYERROR(SEC_ERROR_SAFE_NOT_CREATED,"Error while creating safe object."); NSSYERROR(SEC_ERROR_BAGGAGE_NOT_CREATED,"Error while creating baggage object."); NSSYERROR(XP_JAVA_REMOVE_PRINCIPAL_ERROR,"Couldn 't remove the principal."); NSSYERROR(XP_JAVA_DELETE_PRIVILEGE_ERROR,"Couldn' t delete the privilege "); NSSYERROR(XP_JAVA_CERT_NOT_EXISTS_ERROR,"This principal doesn 't have a certificate."); NSSYERROR(SEC_ERROR_BAD_EXPORT_ALGORITHM,"Required algorithm is not allowed."); NSSYERROR(SEC_ERROR_EXPORTING_CERTIFICATES,"Error attempting to export certificates."); NSSYERROR(SEC_ERROR_IMPORTING_CERTIFICATES,"Error attempting to import certificates."); NSSYERROR(SEC_ERROR_PKCS12_DECODING_PFX,"Unable to import. Decoding error. File not valid."); NSSYERROR(SEC_ERROR_PKCS12_INVALID_MAC,"Unable to import. Invalid MAC. Incorrect password or corrupt file."); NSSYERROR(SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM,"Unable to import. MAC algorithm not supported."); NSSYERROR(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE,"Unable to import. Only password integrity and privacy modes supported."); NSSYERROR(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE,"Unable to import. File structure is corrupt."); NSSYERROR(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM,"Unable to import. Encryption algorithm not supported."); NSSYERROR(SEC_ERROR_PKCS12_UNSUPPORTED_VERSION,"Unable to import. File version not supported."); NSSYERROR(SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT,"Unable to import. Incorrect privacy password."); NSSYERROR(SEC_ERROR_PKCS12_CERT_COLLISION,"Unable to import. Same nickname already exists in database."); NSSYERROR(SEC_ERROR_USER_CANCELLED,"The user clicked cancel."); NSSYERROR(SEC_ERROR_PKCS12_DUPLICATE_DATA,"Not imported, already in database."); NSSYERROR(SEC_ERROR_MESSAGE_SEND_ABORTED,"Message not sent."); NSSYERROR(SEC_ERROR_INADEQUATE_KEY_USAGE,"Certificate key usage inadequate for attempted operation."); NSSYERROR(SEC_ERROR_INADEQUATE_CERT_TYPE,"Certificate type not approved for application."); NSSYERROR(SEC_ERROR_CERT_ADDR_MISMATCH,"Address in signing certificate does not match address in message headers."); NSSYERROR(SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY,"Unable to import. Error attempting to import private key."); NSSYERROR(SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN,"Unable to import. Error attempting to import certificate chain."); NSSYERROR(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME,"Unable to export. Unable to locate certificate or key by nickname."); NSSYERROR(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY,"Unable to export. Private key could not be located and exported."); NSSYERROR(SEC_ERROR_PKCS12_UNABLE_TO_WRITE,"Unable to export. Unable to write the export file."); NSSYERROR(SEC_ERROR_PKCS12_UNABLE_TO_READ,"Unable to import. Unable to read the import file."); NSSYERROR(SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED,"Unable to export. Key database corrupt or deleted."); NSSYERROR(SEC_ERROR_KEYGEN_FAIL,"Unable to generate public-private key pair."); NSSYERROR(SEC_ERROR_INVALID_PASSWORD,"Password entered is invalid."); NSSYERROR(SEC_ERROR_RETRY_OLD_PASSWORD,"Old password entered incorrectly."); NSSYERROR(SEC_ERROR_BAD_NICKNAME,"Certificate nickname already in use."); NSSYERROR(SEC_ERROR_NOT_FORTEZZA_ISSUER,"Peer FORTEZZA chain has a non-FORTEZZA Certificate."); NSSYERROR(SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY,"A sensitive key cannot be moved to the slot where it is needed."); NSSYERROR(SEC_ERROR_JS_INVALID_MODULE_NAME,"Invalid module name."); NSSYERROR(SEC_ERROR_JS_INVALID_DLL,"Invalid module path/filename."); NSSYERROR(SEC_ERROR_JS_ADD_MOD_FAILURE,"Unable to add module."); NSSYERROR(SEC_ERROR_JS_DEL_MOD_FAILURE,"Unable to delete module."); NSSYERROR(SEC_ERROR_OLD_KRL,"New KRL is not later than the current one."); NSSYERROR(SEC_ERROR_CKL_CONFLICT,"New CKL has different issuer than current CKL."); NSSYERROR(SEC_ERROR_CERT_NOT_IN_NAME_SPACE,"Certificate issuer is not permitted to issue a certificate with this name."); NSSYERROR(SEC_ERROR_KRL_NOT_YET_VALID,"The key revocation list for this certificate is not yet valid."); NSSYERROR(SEC_ERROR_CRL_NOT_YET_VALID,"The certificate revocation list for this certificate is not yet valid."); NSSYERROR(SEC_ERROR_UNKNOWN_CERT,"The requested certificate could not be found."); NSSYERROR(SEC_ERROR_UNKNOWN_SIGNER,"The signer's certificate could not be found."); NSSYERROR(SEC_ERROR_CERT_BAD_ACCESS_LOCATION,"The location for the certificate status server has invalid format."); NSSYERROR(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE,"The OCSP response cannot be fully decoded) it is of an unknown type."); NSSYERROR(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE,"The OCSP server returned unexpected / invalid HTTP data."); NSSYERROR(SEC_ERROR_OCSP_MALFORMED_REQUEST,"The OCSP server found the request to be corrupted or improperly formed."); NSSYERROR(SEC_ERROR_OCSP_SERVER_ERROR,"The OCSP server experienced an internal error."); NSSYERROR(SEC_ERROR_OCSP_TRY_SERVER_LATER,"The OCSP server suggests trying again later."); NSSYERROR(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG,"The OCSP server requires a signature on this request."); NSSYERROR(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST,"The OCSP server has refused this request as unauthorized."); NSSYERROR(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS,"The OCSP server returned an unrecognizable status."); NSSYERROR(SEC_ERROR_OCSP_UNKNOWN_CERT,"The OCSP server has no status for the certificate."); NSSYERROR(SEC_ERROR_OCSP_NOT_ENABLED,"You must enable OCSP before performing this operation."); NSSYERROR(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER,"You must set the OCSP default responder before performing this operation."); NSSYERROR(SEC_ERROR_OCSP_MALFORMED_RESPONSE,"The response from the OCSP server was corrupted or improperly formed."); NSSYERROR(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE,"The signer of the OCSP response is not authorized to give status for this certificate."); NSSYERROR(SEC_ERROR_OCSP_FUTURE_RESPONSE,"The OCSP response is not yet valid (contains a date in the future) . "); NSSYERROR(SEC_ERROR_OCSP_OLD_RESPONSE,"The OCSP response contains out - of - date information."); NSSYERROR(SEC_ERROR_DIGEST_NOT_FOUND,"The CMS or PKCS #7 Digest was not found in signed message."); NSSYERROR(SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE,"The CMS or PKCS #7 Message type is unsupported."); NSSYERROR(SEC_ERROR_MODULE_STUCK,"PKCS #11 module could not be removed because it is still in use."); NSSYERROR(SEC_ERROR_BAD_TEMPLATE,"Could not decode ASN .1 data.Specified template was invalid."); NSSYERROR(SEC_ERROR_CRL_NOT_FOUND,"No matching CRL was found."); NSSYERROR(SEC_ERROR_REUSED_ISSUER_AND_SERIAL,"You are attempting to import a cert with the same issuer / serial as an existing cert, but that is not the same cert."); NSSYERROR(SEC_ERROR_BUSY,"NSS could not shutdown.Objects are still in use."); NSSYERROR(SEC_ERROR_EXTRA_INPUT,"DER - encoded message contained extra unused data."); NSSYERROR(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE,"Unsupported elliptic curve."); NSSYERROR(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM,"Unsupported elliptic curve point form."); NSSYERROR(SEC_ERROR_UNRECOGNIZED_OID,"Unrecognized Object IDentifier."); NSSYERROR(SEC_ERROR_OCSP_INVALID_SIGNING_CERT,"Invalid OCSP signing certificate in OCSP response."); NSSYERROR(SEC_ERROR_REVOKED_CERTIFICATE_CRL,"Certificate is revoked in issuer's certificate revocation list."); NSSYERROR(SEC_ERROR_REVOKED_CERTIFICATE_OCSP,"Issuer's OCSP responder reports certificate is revoked."); NSSYERROR(SEC_ERROR_CRL_INVALID_VERSION,"Issuer's Certificate Revocation List has an unknown version number."); NSSYERROR(SEC_ERROR_CRL_V1_CRITICAL_EXTENSION,"Issuer's V1 Certificate Revocation List has a critical extension."); NSSYERROR(SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION,"Issuer's V2 Certificate Revocation List has an unknown critical extension."); NSSYERROR(SEC_ERROR_UNKNOWN_OBJECT_TYPE,"Unknown object type specified."); NSSYERROR(SEC_ERROR_INCOMPATIBLE_PKCS11,"PKCS #11 driver violates the spec in an incompatible way."); NSSYERROR(SEC_ERROR_NO_EVENT,"No new slot event is available at this time."); NSSYERROR(SEC_ERROR_CRL_ALREADY_EXISTS,"CRL already exists."); NSSYERROR(SEC_ERROR_NOT_INITIALIZED,"NSS is not initialized."); NSSYERROR(SEC_ERROR_TOKEN_NOT_LOGGED_IN,"The operation failed because the PKCS #11 token is not logged in."); NSSYERROR(SEC_ERROR_OCSP_RESPONDER_CERT_INVALID,"The configured OCSP responder's certificate is invalid."); NSSYERROR(SEC_ERROR_OCSP_BAD_SIGNATURE,"OCSP response has an invalid signature."); NSSYERROR(SEC_ERROR_OUT_OF_SEARCH_LIMITS,"Certification validation search is out of search limits."); NSSYERROR(SEC_ERROR_INVALID_POLICY_MAPPING,"Policy mapping contains any - policy."); NSSYERROR(SEC_ERROR_POLICY_VALIDATION_FAILED,"Certificate chain fails policy validation."); NSSYERROR(SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE,"Unknown location type in certificate AIA extension."); NSSYERROR(SEC_ERROR_BAD_HTTP_RESPONSE,"Server returned a bad HTTP response."); NSSYERROR(SEC_ERROR_BAD_LDAP_RESPONSE,"Server returned a bad LDAP response."); NSSYERROR(SEC_ERROR_FAILED_TO_ENCODE_DATA,"Failed to encode data with ASN .1 encoder."); NSSYERROR(SEC_ERROR_BAD_INFO_ACCESS_LOCATION,"Bad information access location in certificate extension."); NSSYERROR(SEC_ERROR_LIBPKIX_INTERNAL,"Libpkix internal error occurred during cert validation."); NSSYERROR(SEC_ERROR_PKCS11_GENERAL_ERROR,"A PKCS #11 module returned CKR_GENERAL_ERROR, indicating that an unrecoverable error has occurred."); NSSYERROR(SEC_ERROR_PKCS11_FUNCTION_FAILED,"A PKCS #11 module returned CKR_FUNCTION_FAILED, indicating that the requested function could not be performed.Trying the same operation again might succeed."); NSSYERROR(SEC_ERROR_PKCS11_DEVICE_ERROR,"A PKCS #11 module returned CKR_DEVICE_ERROR, indicating that a problem has occurred with the token or slot."); /* 3.12.4 and later */ #if (NSS_VMAJOR > 3) || (NSS_VMAJOR == 3 && NSS_VMINOR > 12) || (NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH >= 4) NSSYERROR(SEC_ERROR_BAD_INFO_ACCESS_METHOD,"Unknown information access method in certificate extension."); NSSYERROR(SEC_ERROR_CRL_IMPORT_FAILED,"Error attempting to import a CRL."); #endif systemtap-2.3/staptree.cxx000066400000000000000000001634351217430427200160000ustar00rootroot00000000000000// parse tree functions // Copyright (C) 2005-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "config.h" #include "staptree.h" #include "parse.h" #include "util.h" #include "session.h" #include #include #include #include #include #include #include #include using namespace std; visitable::~visitable () { } expression::expression (): type (pe_unknown), tok (0) { } expression::~expression () { } statement::statement (): tok (0) { } statement::statement (const token* tok): tok (tok) { } null_statement::null_statement (const token* tok): statement(tok) { } statement::~statement () { } symbol::symbol (): referent (0) { } arrayindex::arrayindex (): base (0) { } functioncall::functioncall (): referent (0) { } symboldecl::symboldecl (): tok (0), systemtap_v_conditional (0), type (pe_unknown) { } symboldecl::~symboldecl () { } probe_point::probe_point (std::vector const & comps): components(comps), optional (false), sufficient (false), condition (0) { } // NB: shallow-copy of compoonents & condition! probe_point::probe_point (const probe_point& pp): components(pp.components), optional (pp.optional), sufficient (pp.sufficient), condition (pp.condition) { } probe_point::probe_point (): optional (false), sufficient (false), condition (0) { } unsigned probe::last_probeidx = 0; probe::probe (): body (0), base (0), tok (0), systemtap_v_conditional (0), privileged (false) { this->name = string ("probe_") + lex_cast(last_probeidx ++); } // Copy constructor, but with overriding probe-point. To be used when // mapping script-level probe points to another one, early during pass // 2. There should be no symbol resolution done yet. probe::probe(probe* p, probe_point* l) { this->base = p; this->name = string ("probe_") + lex_cast(last_probeidx ++); this->tok = p->tok; this->locations.push_back(l); this->body = deep_copy_visitor::deep_copy(p->body); this->privileged = p->privileged; this->systemtap_v_conditional = p->systemtap_v_conditional; assert (p->locals.size() == 0); assert (p->unused_locals.size() == 0); } probe_point::component::component (): arg (0), tok(0) { } probe_point::component::component (std::string const & f, literal * a): functor(f), arg(a), tok(0) { } vardecl::vardecl (): arity_tok(0), arity (-1), maxsize(0), init(NULL), synthetic(false), wrap(false) { } void vardecl::set_arity (int a, const token* t) { if (a < 0) return; if (a == 0 && maxsize > 0) throw semantic_error (_("inconsistent arity"), tok); if (arity != a && arity >= 0) { semantic_error err (_F("inconsistent arity (%s vs %d)", lex_cast(arity).c_str(), a), t?:tok); if (arity_tok) err.chain = new semantic_error (_F("arity %s first inferred here", lex_cast(arity).c_str()), arity_tok); throw err; } if (arity != a) { arity_tok = t; arity = a; index_types.resize (arity); for (int i=0; i 0) return false; if (arity == -1 || a == -1) return true; return arity == a; } functiondecl::functiondecl (): body (0), synthetic (false), mangle_oldstyle (false) { } void functiondecl::join (systemtap_session& s) { if (!synthetic) throw semantic_error (_("internal error, joining a non-synthetic function"), tok); if (!s.functions.insert (make_pair (name, this)).second) throw semantic_error (_F("synthetic function '%s' conflicts with an existing function", name.c_str()), tok); tok->location.file->functions.push_back (this); } literal_number::literal_number (int64_t v, bool hex) { value = v; print_hex = hex; type = pe_long; } literal_string::literal_string (const string& v) { value = v; type = pe_string; } ostream& operator << (ostream& o, const exp_type& e) { switch (e) { case pe_unknown: o << "unknown"; break; case pe_long: o << "long"; break; case pe_string: o << "string"; break; case pe_stats: o << "stats"; break; default: o << "???"; break; } return o; } void target_symbol::assert_no_components(const std::string& tapset, bool pretty_ok) { if (components.empty()) return; switch (components[0].type) { case comp_literal_array_index: case comp_expression_array_index: throw semantic_error(_F("%s variable '%s' may not be used as array", tapset.c_str(), name.c_str()), components[0].tok); case comp_struct_member: throw semantic_error(_F("%s variable '%s' may not be used as a structure", tapset.c_str(), name.c_str()), components[0].tok); case comp_pretty_print: if (!pretty_ok) throw semantic_error(_F("%s variable '%s' may not be pretty-printed", tapset.c_str(), name.c_str()), components[0].tok); return; default: throw semantic_error (_F("invalid use of %s variable '%s'", tapset.c_str(), name.c_str()), components[0].tok); } } void target_symbol::chain (const semantic_error &er) { semantic_error* e = new semantic_error(er); if (!e->tok1) e->tok1 = this->tok; assert (e->chain == 0); e->chain = this->saved_conversion_error; this->saved_conversion_error = e; } string target_symbol::sym_name () { return name.substr(1); } string atvar_op::sym_name () { if (cu_name == "") return target_name; else return target_name.substr(0, target_name.length() - cu_name.length() - 1); } // ------------------------------------------------------------------------ // parse tree printing ostream& operator << (ostream& o, const expression& k) { k.print (o); return o; } void literal_string::print (ostream& o) const { o << '"'; for (unsigned i=0; iindexes.size(); i++) { if (i > 0) o << ", "; operand->indexes[i]->print (o); } o << "] in "; operand->base->print (o); } void post_crement::print (ostream& o) const { o << '(' << *operand << ")" << op; } void ternary_expression::print (ostream& o) const { o << "(" << *cond << ")?(" << *truevalue << "):(" << *falsevalue << ")"; } void symbol::print (ostream& o) const { o << name; } void target_symbol::component::print (ostream& o) const { switch (type) { case comp_pretty_print: case comp_struct_member: o << "->" << member; break; case comp_literal_array_index: o << '[' << num_index << ']'; break; case comp_expression_array_index: o << '[' << *expr_index << ']'; break; } } std::ostream& operator << (std::ostream& o, const target_symbol::component& c) { c.print (o); return o; } void target_symbol::print (ostream& o) const { if (addressof) o << "&"; o << name; for (unsigned i = 0; i < components.size(); ++i) o << components[i]; } void atvar_op::print (ostream& o) const { if (addressof) o << "&"; o << name << "(\"" << target_name << "\")"; for (unsigned i = 0; i < components.size(); ++i) o << components[i]; } void cast_op::print (ostream& o) const { if (addressof) o << "&"; o << name << '(' << *operand; o << ", " << lex_cast_qstring (type_name); if (module.length() > 0) o << ", " << lex_cast_qstring (module); o << ')'; for (unsigned i = 0; i < components.size(); ++i) o << components[i]; } void defined_op::print (ostream& o) const { o << "@defined(" << *operand << ")"; } void entry_op::print (ostream& o) const { o << "@entry(" << *operand << ")"; } void perf_op::print (ostream& o) const { o << "@perf(" << *operand << ")"; } void vardecl::print (ostream& o) const { o << name; if(wrap) o << "%"; if (maxsize > 0) o << "[" << maxsize << "]"; if (arity > 0 || index_types.size() > 0) o << "[...]"; if (init) { o << " = "; init->print(o); } } void vardecl::printsig (ostream& o) const { o << name; if(wrap) o << "%"; if (maxsize > 0) o << "[" << maxsize << "]"; o << ":" << type; if (index_types.size() > 0) { o << " ["; for (unsigned i=0; i0 ? ", " : "") << index_types[i]; o << "]"; } } void functiondecl::print (ostream& o) const { o << "function " << name << " ("; for (unsigned i=0; i0 ? ", " : "") << *formal_args[i]; o << ")" << endl; body->print(o); } void functiondecl::printsig (ostream& o) const { o << name << ":" << type << " ("; for (unsigned i=0; i0 ? ", " : "") << *formal_args[i] << ":" << formal_args[i]->type; o << ")"; } void arrayindex::print (ostream& o) const { base->print (o); o << "["; for (unsigned i=0; i0 ? ", " : "") << *indexes[i]; o << "]"; } void functioncall::print (ostream& o) const { o << function << "("; for (unsigned i=0; i0 ? ", " : "") << *args[i]; o << ")"; } print_format* print_format::create(const token *t) { bool stream, format, delim, newline, _char; const char *n = t->content.c_str(); stream = true; format = delim = newline = _char = false; if (strcmp(n, "print_char") == 0) _char = true; else { if (*n == 's') { stream = false; ++n; } if (0 != strncmp(n, "print", 5)) return NULL; n += 5; if (*n == 'f') { format = true; ++n; } else { if (*n == 'd') { delim = true; ++n; } if (*n == 'l' && *(n+1) == 'n') { newline = true; n += 2; } } if (*n != '\0') return NULL; } print_format *pf = new print_format(stream, format, delim, newline, _char); pf->tok = t; return pf; } string print_format::components_to_string(vector const & components) { ostringstream oss; for (vector::const_iterator i = components.begin(); i != components.end(); ++i) { assert (i->type != conv_unspecified); if (i->type == conv_literal) { assert(!i->literal_string.empty()); for (string::const_iterator j = i->literal_string.begin(); j != i->literal_string.end(); ++j) { // See also: c_unparser::visit_literal_string and lex_cast_qstring if (*j == '%') oss << '%'; else if(*j == '"') oss << '\\'; oss << *j; } } else { oss << '%'; if (i->test_flag (fmt_flag_zeropad)) oss << '0'; if (i->test_flag (fmt_flag_plus)) oss << '+'; if (i->test_flag (fmt_flag_space)) oss << ' '; if (i->test_flag (fmt_flag_left)) oss << '-'; if (i->test_flag (fmt_flag_special)) oss << '#'; if (i->widthtype == width_dynamic) oss << '*'; else if (i->widthtype != width_unspecified && i->width > 0) oss << i->width; if (i->prectype == prec_dynamic) oss << ".*"; else if (i->prectype != prec_unspecified && i->precision > 0) oss << '.' << i->precision; switch (i->type) { case conv_binary: oss << "b"; break; case conv_char: oss << "llc"; break; case conv_number: if (i->base == 16) { if (i->test_flag (fmt_flag_large)) oss << "llX"; else oss << "llx"; } else if (i->base == 8) oss << "llo"; else if (i->test_flag (fmt_flag_sign)) oss << "lld"; else oss << "llu"; break; case conv_pointer: oss << "p"; break; case conv_string: oss << 's'; break; case conv_memory: oss << 'm'; break; case conv_memory_hex: oss << 'M'; break; default: break; } } } return oss.str (); } vector print_format::string_to_components(string const & str) { format_component curr; vector res; curr.clear(); string::const_iterator i = str.begin(); while (i != str.end()) { if (*i != '%') { assert (curr.type == conv_unspecified || curr.type == conv_literal); curr.type = conv_literal; curr.literal_string += *i; ++i; continue; } else if (i+1 == str.end() || *(i+1) == '%') { assert(*i == '%'); // *i == '%' and *(i+1) == '%'; append only one '%' to the literal string assert (curr.type == conv_unspecified || curr.type == conv_literal); curr.type = conv_literal; curr.literal_string += '%'; i += 2; continue; } else { assert(*i == '%'); if (curr.type != conv_unspecified) { // Flush any component we were previously accumulating assert (curr.type == conv_literal); res.push_back(curr); curr.clear(); } } ++i; if (i == str.end()) break; // Now we are definitely parsing a conversion. // Begin by parsing flags (which are optional). switch (*i) { case '0': curr.set_flag (fmt_flag_zeropad); ++i; break; case '+': curr.set_flag (fmt_flag_plus); ++i; break; case '-': curr.set_flag (fmt_flag_left); ++i; break; case ' ': curr.set_flag (fmt_flag_space); ++i; break; case '#': curr.set_flag (fmt_flag_special); ++i; break; default: break; } if (i == str.end()) break; // Parse optional width if (*i == '*') { curr.widthtype = width_dynamic; ++i; } else if (isdigit(*i)) { curr.widthtype = width_static; curr.width = 0; do { curr.width *= 10; curr.width += (*i - '0'); ++i; } while (i != str.end() && isdigit(*i)); } if (i == str.end()) break; // Parse optional precision if (*i == '.') { ++i; if (i == str.end()) break; if (*i == '*') { curr.prectype = prec_dynamic; ++i; } else if (isdigit(*i)) { curr.prectype = prec_static; curr.precision = 0; do { curr.precision *= 10; curr.precision += (*i - '0'); ++i; } while (i != str.end() && isdigit(*i)); } } if (i == str.end()) break; // Parse the type modifier switch (*i) { case 'l': ++i; break; } if (i == str.end()) break; // Parse the actual conversion specifier (bcsmdioupxXn) switch (*i) { // Valid conversion types case 'b': curr.type = conv_binary; break; case 'c': curr.type = conv_char; break; case 's': curr.type = conv_string; break; case 'm': curr.type = conv_memory; break; case 'M': curr.type = conv_memory_hex; break; case 'd': case 'i': curr.set_flag (fmt_flag_sign); case 'u': curr.type = conv_number; curr.base = 10; break; case 'o': curr.type = conv_number; curr.base = 8; break; case 'X': curr.set_flag (fmt_flag_large); case 'x': curr.type = conv_number; curr.base = 16; break; case 'p': // Since stap 1.3, %p == %#x. curr.set_flag (fmt_flag_special); curr.type = conv_pointer; curr.base = 16; // Oddness for stap < 1.3 is handled in translation break; default: break; } if (curr.type == conv_unspecified) throw parse_error(_("invalid or missing conversion specifier")); ++i; res.push_back(curr); curr.clear(); } // If there's a remaining partly-composed conversion, fail. if (!curr.is_empty()) { if (curr.type == conv_literal) res.push_back(curr); else throw parse_error(_("trailing incomplete print format conversion")); } return res; } void print_format::print (ostream& o) const { o << tok->content << "("; if (print_with_format) o << lex_cast_qstring (raw_components); if (print_with_delim) o << lex_cast_qstring (delimiter.literal_string); if (hist) hist->print(o); for (vector::const_iterator i = args.begin(); i != args.end(); ++i) { if (i != args.begin() || print_with_format || print_with_delim) o << ", "; (*i)->print(o); } o << ")"; } void stat_op::print (ostream& o) const { o << '@'; switch (ctype) { case sc_average: o << "avg("; break; case sc_count: o << "count("; break; case sc_sum: o << "sum("; break; case sc_min: o << "min("; break; case sc_max: o << "max("; break; case sc_none: assert (0); // should not happen, as sc_none is only used in foreach sorts break; } stat->print(o); o << ")"; } void hist_op::print (ostream& o) const { o << '@'; switch (htype) { case hist_linear: assert(params.size() == 3); o << "hist_linear("; stat->print(o); for (size_t i = 0; i < params.size(); ++i) { o << ", " << params[i]; } o << ")"; break; case hist_log: assert(params.size() == 0); o << "hist_log("; stat->print(o); o << ")"; break; } } ostream& operator << (ostream& o, const statement& k) { k.print (o); return o; } void embeddedcode::print (ostream &o) const { o << "%{"; o << code; o << "%}"; } void block::print (ostream& o) const { o << "{" << endl; for (unsigned i=0; itok = car->tok; } void try_block::print (ostream& o) const { o << "try {" << endl; if (try_block) o << *try_block << endl; o << "} catch "; if (catch_error_var) o << "(" << *catch_error_var << ") "; o << "{" << endl; if (catch_block) o << *catch_block << endl; o << "}" << endl; } void for_loop::print (ostream& o) const { o << "for ("; if (init) init->print (o); o << "; "; cond->print (o); o << "; "; if (incr) incr->print (o); o << ") "; block->print (o); } void foreach_loop::print (ostream& o) const { o << "foreach ("; if (value) { value->print (o); o << " = "; } o << "["; for (unsigned i=0; i 0) o << ", "; indexes[i]->print (o); if (sort_direction != 0 && sort_column == i+1) o << (sort_direction > 0 ? "+" : "-"); } o << "] in "; base->print (o); if (sort_direction != 0 && sort_column == 0) { switch (sort_aggr) { case sc_count: o << " @count"; break; case sc_average: o << " @avg"; break; case sc_min: o << " @min"; break; case sc_max: o << " @max"; break; case sc_sum: o << " @sum"; break; case sc_none: default: ; } o << (sort_direction > 0 ? "+" : "-"); } if (limit) { o << " limit "; limit->print (o); } o << ") "; block->print (o); } void null_statement::print (ostream& o) const { o << ";"; } void expr_statement::print (ostream& o) const { o << *value; } void return_statement::print (ostream& o) const { o << "return " << *value; } void delete_statement::print (ostream& o) const { o << "delete " << *value; } void next_statement::print (ostream& o) const { o << "next"; } void break_statement::print (ostream& o) const { o << "break"; } void continue_statement::print (ostream& o) const { o << "continue"; } void if_statement::print (ostream& o) const { o << "if (" << *condition << ") " << *thenblock << endl; if (elseblock) o << "else " << *elseblock << endl; } void stapfile::print (ostream& o) const { o << "# file " << name << endl; for (unsigned i=0; iprint (o); for (unsigned i=0; iprint (o); o << endl; } for (unsigned i=0; iprint (o); o << endl; } for (unsigned i=0; iprint (o); o << endl; } for (unsigned j = 0; j < functions.size(); j++) { functions[j]->print (o); o << endl; } } void probe::print (ostream& o) const { o << "probe "; printsig (o); o << *body; } void probe::printsig (ostream& o) const { const probe_alias *alias = get_alias (); if (alias) { alias->printsig (o); return; } for (unsigned i=0; i 0) o << ","; locations[i]->print (o); } } void probe::collect_derivation_chain (std::vector &probes_list) const { probes_list.push_back(const_cast(this)); if (base) base->collect_derivation_chain(probes_list); } void probe::collect_derivation_pp_chain (std::vector &pp_list) const { pp_list.push_back(const_cast(this->locations[0])); if (base) base->collect_derivation_pp_chain(pp_list); } void probe_point::print (ostream& o, bool print_extras) const { for (unsigned i=0; i0) o << "."; probe_point::component* c = components[i]; o << c->functor; if (c->arg) o << "(" << *c->arg << ")"; } if (!print_extras) return; if (sufficient) o << "!"; else if (optional) // sufficient implies optional o << "?"; if (condition) o<< " if (" << *condition << ")"; } string probe_point::str (bool print_extras) const { ostringstream o; print(o, print_extras); return o.str(); } probe_alias::probe_alias(std::vector const & aliases): probe (), alias_names (aliases), epilogue_style(false) { } void probe_alias::printsig (ostream& o) const { for (unsigned i=0; i0 ? " = " : ""); alias_names[i]->print (o); } o << " = "; for (unsigned i=0; i 0) o << ", "; locations[i]->print (o); } } ostream& operator << (ostream& o, const probe_point& k) { k.print (o); return o; } ostream& operator << (ostream& o, const symboldecl& k) { k.print (o); return o; } // ------------------------------------------------------------------------ // visitors void block::visit (visitor* u) { u->visit_block (this); } void try_block::visit (visitor* u) { u->visit_try_block (this); } void embeddedcode::visit (visitor* u) { u->visit_embeddedcode (this); } void for_loop::visit (visitor* u) { u->visit_for_loop (this); } void foreach_loop::visit (visitor* u) { u->visit_foreach_loop (this); } void null_statement::visit (visitor* u) { u->visit_null_statement (this); } void expr_statement::visit (visitor* u) { u->visit_expr_statement (this); } void return_statement::visit (visitor* u) { u->visit_return_statement (this); } void delete_statement::visit (visitor* u) { u->push_active_lvalue (this->value); u->visit_delete_statement (this); u->pop_active_lvalue (); } void if_statement::visit (visitor* u) { u->visit_if_statement (this); } void next_statement::visit (visitor* u) { u->visit_next_statement (this); } void break_statement::visit (visitor* u) { u->visit_break_statement (this); } void continue_statement::visit (visitor* u) { u->visit_continue_statement (this); } void literal_string::visit(visitor* u) { u->visit_literal_string (this); } void literal_number::visit(visitor* u) { u->visit_literal_number (this); } void binary_expression::visit (visitor* u) { u->visit_binary_expression (this); } void embedded_expr::visit (visitor* u) { u->visit_embedded_expr (this); } void unary_expression::visit (visitor* u) { u->visit_unary_expression (this); } void pre_crement::visit (visitor* u) { u->push_active_lvalue (this->operand); u->visit_pre_crement (this); u->pop_active_lvalue (); } void post_crement::visit (visitor* u) { u->push_active_lvalue (this->operand); u->visit_post_crement (this); u->pop_active_lvalue (); } void logical_or_expr::visit (visitor* u) { u->visit_logical_or_expr (this); } void logical_and_expr::visit (visitor* u) { u->visit_logical_and_expr (this); } void array_in::visit (visitor* u) { u->visit_array_in (this); } void regex_query::visit (visitor* u) { u->visit_regex_query (this); } void comparison::visit (visitor* u) { u->visit_comparison (this); } void concatenation::visit (visitor* u) { u->visit_concatenation (this); } void ternary_expression::visit (visitor* u) { u->visit_ternary_expression (this); } void assignment::visit (visitor* u) { u->push_active_lvalue (this->left); u->visit_assignment (this); u->pop_active_lvalue (); } void symbol::visit (visitor* u) { u->visit_symbol (this); } void target_symbol::visit (visitor* u) { u->visit_target_symbol(this); } void target_symbol::visit_components (visitor* u) { for (unsigned i = 0; i < components.size(); ++i) if (components[i].type == comp_expression_array_index) components[i].expr_index->visit (u); } void target_symbol::visit_components (update_visitor* u) { for (unsigned i = 0; i < components.size(); ++i) if (components[i].type == comp_expression_array_index) u->replace (components[i].expr_index); } void cast_op::visit (visitor* u) { u->visit_cast_op(this); } void atvar_op::visit (visitor* u) { u->visit_atvar_op(this); } void defined_op::visit (visitor* u) { u->visit_defined_op(this); } void entry_op::visit (visitor* u) { u->visit_entry_op(this); } void perf_op::visit (visitor* u) { u->visit_perf_op(this); } void arrayindex::visit (visitor* u) { u->visit_arrayindex (this); } void functioncall::visit (visitor* u) { u->visit_functioncall (this); } void print_format::visit (visitor *u) { u->visit_print_format (this); } void stat_op::visit (visitor *u) { u->visit_stat_op (this); } void hist_op::visit (visitor *u) { u->visit_hist_op (this); } bool indexable::is_symbol(symbol *& sym_out) { sym_out = NULL; return false; } bool indexable::is_hist_op(hist_op *& hist_out) { hist_out = NULL; return false; } bool symbol::is_symbol(symbol *& sym_out) { sym_out = this; return true; } bool hist_op::is_hist_op(hist_op *& hist_out) { hist_out = this; return true; } void classify_indexable(indexable* ix, symbol *& array_out, hist_op *& hist_out) { array_out = NULL; hist_out = NULL; assert(ix != NULL); if (!(ix->is_symbol (array_out) || ix->is_hist_op (hist_out))) throw semantic_error(_("Expecting symbol or histogram operator"), ix->tok); if (!(hist_out || array_out)) throw semantic_error(_("Failed to classify indexable"), ix->tok); } // ------------------------------------------------------------------------ bool visitor::is_active_lvalue(expression *e) { for (unsigned i = 0; i < active_lvalues.size(); ++i) { if (active_lvalues[i] == e) return true; } return false; } void visitor::push_active_lvalue(expression *e) { active_lvalues.push_back(e); } void visitor::pop_active_lvalue() { assert(!active_lvalues.empty()); active_lvalues.pop_back(); } // ------------------------------------------------------------------------ void traversing_visitor::visit_block (block* s) { for (unsigned i=0; istatements.size(); i++) s->statements[i]->visit (this); } void traversing_visitor::visit_try_block (try_block* s) { if (s->try_block) s->try_block->visit (this); if (s->catch_error_var) s->catch_error_var->visit (this); if (s->catch_block) s->catch_block->visit (this); } void traversing_visitor::visit_embeddedcode (embeddedcode*) { } void traversing_visitor::visit_null_statement (null_statement*) { } void traversing_visitor::visit_expr_statement (expr_statement* s) { s->value->visit (this); } void traversing_visitor::visit_if_statement (if_statement* s) { s->condition->visit (this); s->thenblock->visit (this); if (s->elseblock) s->elseblock->visit (this); } void traversing_visitor::visit_for_loop (for_loop* s) { if (s->init) s->init->visit (this); s->cond->visit (this); if (s->incr) s->incr->visit (this); s->block->visit (this); } void traversing_visitor::visit_foreach_loop (foreach_loop* s) { s->base->visit(this); for (unsigned i=0; iindexes.size(); i++) s->indexes[i]->visit (this); if (s->value) s->value->visit (this); if (s->limit) s->limit->visit (this); s->block->visit (this); } void traversing_visitor::visit_return_statement (return_statement* s) { s->value->visit (this); } void traversing_visitor::visit_delete_statement (delete_statement* s) { s->value->visit (this); } void traversing_visitor::visit_next_statement (next_statement*) { } void traversing_visitor::visit_break_statement (break_statement*) { } void traversing_visitor::visit_continue_statement (continue_statement*) { } void traversing_visitor::visit_literal_string (literal_string*) { } void traversing_visitor::visit_literal_number (literal_number*) { } void traversing_visitor::visit_embedded_expr (embedded_expr*) { } void traversing_visitor::visit_binary_expression (binary_expression* e) { e->left->visit (this); e->right->visit (this); } void traversing_visitor::visit_unary_expression (unary_expression* e) { e->operand->visit (this); } void traversing_visitor::visit_pre_crement (pre_crement* e) { e->operand->visit (this); } void traversing_visitor::visit_post_crement (post_crement* e) { e->operand->visit (this); } void traversing_visitor::visit_logical_or_expr (logical_or_expr* e) { e->left->visit (this); e->right->visit (this); } void traversing_visitor::visit_logical_and_expr (logical_and_expr* e) { e->left->visit (this); e->right->visit (this); } void traversing_visitor::visit_array_in (array_in* e) { e->operand->visit (this); } void traversing_visitor::visit_regex_query (regex_query* e) { e->left->visit (this); e->right->visit (this); } void traversing_visitor::visit_comparison (comparison* e) { e->left->visit (this); e->right->visit (this); } void traversing_visitor::visit_concatenation (concatenation* e) { e->left->visit (this); e->right->visit (this); } void traversing_visitor::visit_ternary_expression (ternary_expression* e) { e->cond->visit (this); e->truevalue->visit (this); e->falsevalue->visit (this); } void traversing_visitor::visit_assignment (assignment* e) { e->left->visit (this); e->right->visit (this); } void traversing_visitor::visit_symbol (symbol*) { } void traversing_visitor::visit_target_symbol (target_symbol* e) { e->visit_components (this); } void traversing_visitor::visit_cast_op (cast_op* e) { e->operand->visit (this); e->visit_components (this); } void traversing_visitor::visit_atvar_op (atvar_op* e) { e->visit_components (this); } void traversing_visitor::visit_defined_op (defined_op* e) { e->operand->visit (this); } void traversing_visitor::visit_entry_op (entry_op* e) { e->operand->visit (this); } void traversing_visitor::visit_perf_op (perf_op* e) { e->operand->visit (this); } void traversing_visitor::visit_arrayindex (arrayindex* e) { for (unsigned i=0; iindexes.size(); i++) e->indexes[i]->visit (this); e->base->visit(this); } void traversing_visitor::visit_functioncall (functioncall* e) { for (unsigned i=0; iargs.size(); i++) e->args[i]->visit (this); } void traversing_visitor::visit_print_format (print_format* e) { for (unsigned i=0; iargs.size(); i++) e->args[i]->visit (this); if (e->hist) e->hist->visit(this); } void traversing_visitor::visit_stat_op (stat_op* e) { e->stat->visit (this); } void traversing_visitor::visit_hist_op (hist_op* e) { e->stat->visit (this); } void functioncall_traversing_visitor::visit_functioncall (functioncall* e) { traversing_visitor::visit_functioncall (e); // prevent infinite recursion if (traversed.find (e->referent) == traversed.end ()) { traversed.insert (e->referent); // recurse functiondecl* last_current_function = current_function; current_function = e->referent; e->referent->body->visit (this); current_function = last_current_function; } } void varuse_collecting_visitor::visit_try_block (try_block *s) { if (s->try_block) s->try_block->visit (this); if (s->catch_error_var) written.insert (s->catch_error_var->referent); if (s->catch_block) s->catch_block->visit (this); // NB: don't functioncall_traversing_visitor::visit_try_block (s); // since that would count s->catch_error_var as a read also. } void varuse_collecting_visitor::visit_embeddedcode (embeddedcode *s) { assert (current_function); // only they get embedded code // Don't allow embedded C functions in unprivileged mode unless // they are tagged with /* unprivileged */ or /* myproc-unprivileged */ // or we're in a usermode runtime. if (! pr_contains (session.privilege, pr_stapdev) && ! pr_contains (session.privilege, pr_stapsys) && ! session.runtime_usermode_p () && s->code.find ("/* unprivileged */") == string::npos && s->code.find ("/* myproc-unprivileged */") == string::npos) throw semantic_error (_F("function may not be used when --privilege=%s is specified", pr_name (session.privilege)), current_function->tok); // Don't allow /* guru */ functions unless -g is active. if (!session.guru_mode && s->code.find ("/* guru */") != string::npos) throw semantic_error (_("function may not be used unless -g is specified"), current_function->tok); // PR14524: Support old-style THIS->local syntax on per-function basis. if (s->code.find ("/* unmangled */") != string::npos) current_function->mangle_oldstyle = true; // We want to elide embedded-C functions when possible. For // example, each $target variable access is expanded to an // embedded-C function call. Yet, for safety reasons, we should // presume that embedded-C functions have intentional side-effects. // // To tell these two types of functions apart, we apply a // Kludge(tm): we look for a magic string within the function body. // $target variables as rvalues will have this; lvalues won't. // Also, explicit side-effect-free tapset functions will have this. if (s->code.find ("/* pure */") != string::npos) return; embedded_seen = true; } // About the same case as above. void varuse_collecting_visitor::visit_embedded_expr (embedded_expr *e) { // Don't allow embedded C expressions in unprivileged mode unless // they are tagged with /* unprivileged */ or /* myproc-unprivileged */ // or we're in a usermode runtime. if (! pr_contains (session.privilege, pr_stapdev) && ! pr_contains (session.privilege, pr_stapsys) && ! session.runtime_usermode_p () && e->code.find ("/* unprivileged */") == string::npos && e->code.find ("/* myproc-unprivileged */") == string::npos) throw semantic_error (_F("embedded expression may not be used when --privilege=%s is specified", pr_name (session.privilege)), e->tok); // Don't allow /* guru */ functions unless -g is active. if (!session.guru_mode && e->code.find ("/* guru */") != string::npos) throw semantic_error (_("embedded expression may not be used unless -g is specified"), e->tok); // We want to elide embedded-C functions when possible. For // example, each $target variable access is expanded to an // embedded-C function call. Yet, for safety reasons, we should // presume that embedded-C functions have intentional side-effects. // // To tell these two types of functions apart, we apply a // Kludge(tm): we look for a magic string within the function body. // $target variables as rvalues will have this; lvalues won't. // Also, explicit side-effect-free tapset functions will have this. if (e->code.find ("/* pure */") != string::npos) return; embedded_seen = true; } void varuse_collecting_visitor::visit_target_symbol (target_symbol *e) { // Still-unresolved target symbol assignments get treated as // generating side-effects like embedded-C, to prevent premature // elision and later error message suppression (PR5516). rvalue use // of unresolved target symbols is OTOH not considered a side-effect. if (is_active_lvalue (e)) embedded_seen = true; functioncall_traversing_visitor::visit_target_symbol (e); } void varuse_collecting_visitor::visit_atvar_op (atvar_op *e) { // Similar to visit_target_symbol if (is_active_lvalue (e)) embedded_seen = true; functioncall_traversing_visitor::visit_atvar_op (e); } void varuse_collecting_visitor::visit_cast_op (cast_op *e) { // As with target_symbols, unresolved cast assignments need to preserved // for later error handling. if (is_active_lvalue (e)) embedded_seen = true; functioncall_traversing_visitor::visit_cast_op (e); } void varuse_collecting_visitor::visit_defined_op (defined_op *e) { // XXX functioncall_traversing_visitor::visit_defined_op (e); } void varuse_collecting_visitor::visit_entry_op (entry_op *e) { // XXX functioncall_traversing_visitor::visit_entry_op (e); } void varuse_collecting_visitor::visit_perf_op (perf_op *e) { functioncall_traversing_visitor::visit_perf_op (e); } void varuse_collecting_visitor::visit_print_format (print_format* e) { // NB: Instead of being top-level statements, "print" and "printf" // are implemented as statement-expressions containing a // print_format. They have side-effects, but not via the // embedded-code detection method above. // // But sprint and sprintf don't have side-effects. bool last_lvalue_read = current_lvalue_read; current_lvalue_read = true; if (e->print_to_stream) embedded_seen = true; // a proxy for "has unknown side-effects" functioncall_traversing_visitor::visit_print_format (e); current_lvalue_read = last_lvalue_read; } void varuse_collecting_visitor::visit_assignment (assignment *e) { if (e->op == "=" || e->op == "<<<") // pure writes { expression* last_lvalue = current_lvalue; bool last_lvalue_read = current_lvalue_read; current_lvalue = e->left; // leave a mark for ::visit_symbol current_lvalue_read = true; functioncall_traversing_visitor::visit_assignment (e); current_lvalue = last_lvalue; current_lvalue_read = last_lvalue_read; } else // read-modify-writes { expression* last_lrvalue = current_lrvalue; current_lrvalue = e->left; // leave a mark for ::visit_symbol functioncall_traversing_visitor::visit_assignment (e); current_lrvalue = last_lrvalue; } } void varuse_collecting_visitor::visit_symbol (symbol *e) { if (e->referent == 0) throw semantic_error (_("symbol without referent"), e->tok); // We could handle initialized globals by marking them as "written". // However, this current visitor may be called for a function or // probe body, from the point of view of which this global is // already initialized, so not written. /* if (e->referent->init) written.insert (e->referent); */ if (current_lvalue == e || current_lrvalue == e) { written.insert (e->referent); } if (current_lvalue != e || current_lrvalue == e) { read.insert (e->referent); } if (current_lrvalue == e) { if (current_lvalue_read) used.insert (e->referent); } else if (current_lvalue != e) used.insert (e->referent); } // NB: stat_op need not be overridden, since it will get to // visit_symbol and only as a possible rvalue. void varuse_collecting_visitor::visit_arrayindex (arrayindex *e) { // Hooking this callback is necessary because of the hacky // statistics representation. For the expression "i[4] = 5", the // incoming lvalue will point to this arrayindex. However, the // symbol corresponding to the "i[4]" is multiply inherited with // arrayindex. If the symbol base part of this object is not at // offset 0, then static_cast(e) may result in a different // address, and not match lvalue by number when we recurse that way. // So we explicitly override the incoming lvalue/lrvalue values to // point at the embedded objects' actual base addresses. expression* last_lrvalue = current_lrvalue; expression* last_lvalue = current_lvalue; symbol *array = NULL; hist_op *hist = NULL; classify_indexable(e->base, array, hist); expression *value = array ?: hist->stat; if (current_lrvalue == e) current_lrvalue = value; if (current_lvalue == e) current_lvalue = value; functioncall_traversing_visitor::visit_arrayindex (e); current_lrvalue = last_lrvalue; current_lvalue = last_lvalue; } void varuse_collecting_visitor::visit_pre_crement (pre_crement *e) { expression* last_lrvalue = current_lrvalue; current_lrvalue = e->operand; // leave a mark for ::visit_symbol functioncall_traversing_visitor::visit_pre_crement (e); current_lrvalue = last_lrvalue; } void varuse_collecting_visitor::visit_post_crement (post_crement *e) { expression* last_lrvalue = current_lrvalue; current_lrvalue = e->operand; // leave a mark for ::visit_symbol functioncall_traversing_visitor::visit_post_crement (e); current_lrvalue = last_lrvalue; } void varuse_collecting_visitor::visit_foreach_loop (foreach_loop* s) { // NB: we duplicate so don't bother call // functioncall_traversing_visitor::visit_foreach_loop (s); s->base->visit(this); // If the collection is sorted, imply a "write" access to the // array in addition to the "read" one already noted above. if (s->sort_direction) { symbol *array = NULL; hist_op *hist = NULL; classify_indexable (s->base, array, hist); if (array) this->written.insert (array->referent); // XXX: Can hist_op iterations be sorted? } // NB: don't forget to visit the index expressions, which are lvalues. for (unsigned i=0; iindexes.size(); i++) { expression* last_lvalue = current_lvalue; current_lvalue = s->indexes[i]; // leave a mark for ::visit_symbol s->indexes[i]->visit (this); current_lvalue = last_lvalue; } // The value is an lvalue too if (s->value) { expression* last_lvalue = current_lvalue; current_lvalue = s->value; // leave a mark for ::visit_symbol s->value->visit (this); current_lvalue = last_lvalue; } if (s->limit) s->limit->visit (this); s->block->visit (this); } void varuse_collecting_visitor::visit_delete_statement (delete_statement* s) { // Ideally, this would be treated like an assignment: a plain write // to the underlying value ("lvalue"). XXX: However, the // optimization pass is not smart enough to remove an unneeded // "delete" yet, so we pose more like a *crement ("lrvalue"). This // should protect the underlying value from optimizional mischief. expression* last_lrvalue = current_lrvalue; bool last_lvalue_read = current_lvalue_read; current_lrvalue = s->value; // leave a mark for ::visit_symbol current_lvalue_read = true; functioncall_traversing_visitor::visit_delete_statement (s); current_lrvalue = last_lrvalue; current_lvalue_read = last_lvalue_read; } bool varuse_collecting_visitor::side_effect_free () { return (written.empty() && !embedded_seen); } bool varuse_collecting_visitor::side_effect_free_wrt (const set& vars) { // A looser notion of side-effect-freeness with respect to a given // list of variables. // That's useful because the written list may consist of local // variables of called functions. But visible side-effects only // occur if the client's locals, or any globals are written-to. set intersection; insert_iterator > int_it (intersection, intersection.begin()); set_intersection (written.begin(), written.end(), vars.begin(), vars.end(), int_it); return (intersection.empty() && !embedded_seen); } // ------------------------------------------------------------------------ throwing_visitor::throwing_visitor (const std::string& m): msg (m) {} throwing_visitor::throwing_visitor (): msg (_("invalid element")) {} void throwing_visitor::throwone (const token* t) { throw semantic_error (msg, t); } void throwing_visitor::visit_block (block* s) { throwone (s->tok); } void throwing_visitor::visit_try_block (try_block* s) { throwone (s->tok); } void throwing_visitor::visit_embeddedcode (embeddedcode* s) { throwone (s->tok); } void throwing_visitor::visit_null_statement (null_statement* s) { throwone (s->tok); } void throwing_visitor::visit_expr_statement (expr_statement* s) { throwone (s->tok); } void throwing_visitor::visit_if_statement (if_statement* s) { throwone (s->tok); } void throwing_visitor::visit_for_loop (for_loop* s) { throwone (s->tok); } void throwing_visitor::visit_foreach_loop (foreach_loop* s) { throwone (s->tok); } void throwing_visitor::visit_return_statement (return_statement* s) { throwone (s->tok); } void throwing_visitor::visit_delete_statement (delete_statement* s) { throwone (s->tok); } void throwing_visitor::visit_next_statement (next_statement* s) { throwone (s->tok); } void throwing_visitor::visit_break_statement (break_statement* s) { throwone (s->tok); } void throwing_visitor::visit_continue_statement (continue_statement* s) { throwone (s->tok); } void throwing_visitor::visit_literal_string (literal_string* e) { throwone (e->tok); } void throwing_visitor::visit_literal_number (literal_number* e) { throwone (e->tok); } void throwing_visitor::visit_embedded_expr (embedded_expr* e) { throwone (e->tok); } void throwing_visitor::visit_binary_expression (binary_expression* e) { throwone (e->tok); } void throwing_visitor::visit_unary_expression (unary_expression* e) { throwone (e->tok); } void throwing_visitor::visit_pre_crement (pre_crement* e) { throwone (e->tok); } void throwing_visitor::visit_post_crement (post_crement* e) { throwone (e->tok); } void throwing_visitor::visit_logical_or_expr (logical_or_expr* e) { throwone (e->tok); } void throwing_visitor::visit_logical_and_expr (logical_and_expr* e) { throwone (e->tok); } void throwing_visitor::visit_array_in (array_in* e) { throwone (e->tok); } void throwing_visitor::visit_regex_query (regex_query* e) { throwone (e->tok); } void throwing_visitor::visit_comparison (comparison* e) { throwone (e->tok); } void throwing_visitor::visit_concatenation (concatenation* e) { throwone (e->tok); } void throwing_visitor::visit_ternary_expression (ternary_expression* e) { throwone (e->tok); } void throwing_visitor::visit_assignment (assignment* e) { throwone (e->tok); } void throwing_visitor::visit_symbol (symbol* e) { throwone (e->tok); } void throwing_visitor::visit_target_symbol (target_symbol* e) { throwone (e->tok); } void throwing_visitor::visit_atvar_op (atvar_op* e) { throwone (e->tok); } void throwing_visitor::visit_cast_op (cast_op* e) { throwone (e->tok); } void throwing_visitor::visit_defined_op (defined_op* e) { throwone (e->tok); } void throwing_visitor::visit_entry_op (entry_op* e) { throwone (e->tok); } void throwing_visitor::visit_perf_op (perf_op* e) { throwone (e->tok); } void throwing_visitor::visit_arrayindex (arrayindex* e) { throwone (e->tok); } void throwing_visitor::visit_functioncall (functioncall* e) { throwone (e->tok); } void throwing_visitor::visit_print_format (print_format* e) { throwone (e->tok); } void throwing_visitor::visit_stat_op (stat_op* e) { throwone (e->tok); } void throwing_visitor::visit_hist_op (hist_op* e) { throwone (e->tok); } // ------------------------------------------------------------------------ void update_visitor::visit_block (block* s) { for (unsigned i = 0; i < s->statements.size(); ++i) replace (s->statements[i]); provide (s); } void update_visitor::visit_try_block (try_block* s) { replace (s->try_block); replace (s->catch_error_var); replace (s->catch_block); provide (s); } void update_visitor::visit_embeddedcode (embeddedcode* s) { provide (s); } void update_visitor::visit_null_statement (null_statement* s) { provide (s); } void update_visitor::visit_expr_statement (expr_statement* s) { replace (s->value); provide (s); } void update_visitor::visit_if_statement (if_statement* s) { replace (s->condition); replace (s->thenblock); replace (s->elseblock); provide (s); } void update_visitor::visit_for_loop (for_loop* s) { replace (s->init); replace (s->cond); replace (s->incr); replace (s->block); provide (s); } void update_visitor::visit_foreach_loop (foreach_loop* s) { for (unsigned i = 0; i < s->indexes.size(); ++i) replace (s->indexes[i]); replace (s->base); replace (s->value); replace (s->limit); replace (s->block); provide (s); } void update_visitor::visit_return_statement (return_statement* s) { replace (s->value); provide (s); } void update_visitor::visit_delete_statement (delete_statement* s) { replace (s->value); provide (s); } void update_visitor::visit_next_statement (next_statement* s) { provide (s); } void update_visitor::visit_break_statement (break_statement* s) { provide (s); } void update_visitor::visit_continue_statement (continue_statement* s) { provide (s); } void update_visitor::visit_literal_string (literal_string* e) { provide (e); } void update_visitor::visit_literal_number (literal_number* e) { provide (e); } void update_visitor::visit_embedded_expr (embedded_expr* e) { provide (e); } void update_visitor::visit_binary_expression (binary_expression* e) { replace (e->left); replace (e->right); provide (e); } void update_visitor::visit_unary_expression (unary_expression* e) { replace (e->operand); provide (e); } void update_visitor::visit_pre_crement (pre_crement* e) { replace (e->operand); provide (e); } void update_visitor::visit_post_crement (post_crement* e) { replace (e->operand); provide (e); } void update_visitor::visit_logical_or_expr (logical_or_expr* e) { replace (e->left); replace (e->right); provide (e); } void update_visitor::visit_logical_and_expr (logical_and_expr* e) { replace (e->left); replace (e->right); provide (e); } void update_visitor::visit_array_in (array_in* e) { replace (e->operand); provide (e); } void update_visitor::visit_regex_query (regex_query* e) { replace (e->left); replace (e->right); // TODOXXX do we need to replace literal in RHS? provide (e); } void update_visitor::visit_comparison (comparison* e) { replace (e->left); replace (e->right); provide (e); } void update_visitor::visit_concatenation (concatenation* e) { replace (e->left); replace (e->right); provide (e); } void update_visitor::visit_ternary_expression (ternary_expression* e) { replace (e->cond); replace (e->truevalue); replace (e->falsevalue); provide (e); } void update_visitor::visit_assignment (assignment* e) { replace (e->left); replace (e->right); provide (e); } void update_visitor::visit_symbol (symbol* e) { provide (e); } void update_visitor::visit_target_symbol (target_symbol* e) { e->visit_components (this); provide (e); } void update_visitor::visit_cast_op (cast_op* e) { replace (e->operand); e->visit_components (this); provide (e); } void update_visitor::visit_atvar_op (atvar_op* e) { e->visit_components (this); provide (e); } void update_visitor::visit_defined_op (defined_op* e) { replace (e->operand); provide (e); } void update_visitor::visit_entry_op (entry_op* e) { replace (e->operand); provide (e); } void update_visitor::visit_perf_op (perf_op* e) { replace (e->operand); provide (e); } void update_visitor::visit_arrayindex (arrayindex* e) { replace (e->base); for (unsigned i = 0; i < e->indexes.size(); ++i) replace (e->indexes[i]); provide (e); } void update_visitor::visit_functioncall (functioncall* e) { for (unsigned i = 0; i < e->args.size(); ++i) replace (e->args[i]); provide (e); } void update_visitor::visit_print_format (print_format* e) { for (unsigned i = 0; i < e->args.size(); ++i) replace (e->args[i]); replace (e->hist); provide (e); } void update_visitor::visit_stat_op (stat_op* e) { replace (e->stat); provide (e); } void update_visitor::visit_hist_op (hist_op* e) { replace (e->stat); provide (e); } // ------------------------------------------------------------------------ void deep_copy_visitor::visit_block (block* s) { update_visitor::visit_block(new block(*s)); } void deep_copy_visitor::visit_try_block (try_block* s) { update_visitor::visit_try_block(new try_block(*s)); } void deep_copy_visitor::visit_embeddedcode (embeddedcode* s) { update_visitor::visit_embeddedcode(new embeddedcode(*s)); } void deep_copy_visitor::visit_null_statement (null_statement* s) { update_visitor::visit_null_statement(new null_statement(*s)); } void deep_copy_visitor::visit_expr_statement (expr_statement* s) { update_visitor::visit_expr_statement(new expr_statement(*s)); } void deep_copy_visitor::visit_if_statement (if_statement* s) { update_visitor::visit_if_statement(new if_statement(*s)); } void deep_copy_visitor::visit_for_loop (for_loop* s) { update_visitor::visit_for_loop(new for_loop(*s)); } void deep_copy_visitor::visit_foreach_loop (foreach_loop* s) { update_visitor::visit_foreach_loop(new foreach_loop(*s)); } void deep_copy_visitor::visit_return_statement (return_statement* s) { update_visitor::visit_return_statement(new return_statement(*s)); } void deep_copy_visitor::visit_delete_statement (delete_statement* s) { update_visitor::visit_delete_statement(new delete_statement(*s)); } void deep_copy_visitor::visit_next_statement (next_statement* s) { update_visitor::visit_next_statement(new next_statement(*s)); } void deep_copy_visitor::visit_break_statement (break_statement* s) { update_visitor::visit_break_statement(new break_statement(*s)); } void deep_copy_visitor::visit_continue_statement (continue_statement* s) { update_visitor::visit_continue_statement(new continue_statement(*s)); } void deep_copy_visitor::visit_literal_string (literal_string* e) { update_visitor::visit_literal_string(new literal_string(*e)); } void deep_copy_visitor::visit_literal_number (literal_number* e) { update_visitor::visit_literal_number(new literal_number(*e)); } void deep_copy_visitor::visit_embedded_expr (embedded_expr* e) { update_visitor::visit_embedded_expr(new embedded_expr(*e)); } void deep_copy_visitor::visit_binary_expression (binary_expression* e) { update_visitor::visit_binary_expression(new binary_expression(*e)); } void deep_copy_visitor::visit_unary_expression (unary_expression* e) { update_visitor::visit_unary_expression(new unary_expression(*e)); } void deep_copy_visitor::visit_pre_crement (pre_crement* e) { update_visitor::visit_pre_crement(new pre_crement(*e)); } void deep_copy_visitor::visit_post_crement (post_crement* e) { update_visitor::visit_post_crement(new post_crement(*e)); } void deep_copy_visitor::visit_logical_or_expr (logical_or_expr* e) { update_visitor::visit_logical_or_expr(new logical_or_expr(*e)); } void deep_copy_visitor::visit_logical_and_expr (logical_and_expr* e) { update_visitor::visit_logical_and_expr(new logical_and_expr(*e)); } void deep_copy_visitor::visit_array_in (array_in* e) { update_visitor::visit_array_in(new array_in(*e)); } void deep_copy_visitor::visit_regex_query (regex_query* e) { update_visitor::visit_regex_query(new regex_query(*e)); } void deep_copy_visitor::visit_comparison (comparison* e) { update_visitor::visit_comparison(new comparison(*e)); } void deep_copy_visitor::visit_concatenation (concatenation* e) { update_visitor::visit_concatenation(new concatenation(*e)); } void deep_copy_visitor::visit_ternary_expression (ternary_expression* e) { update_visitor::visit_ternary_expression(new ternary_expression(*e)); } void deep_copy_visitor::visit_assignment (assignment* e) { update_visitor::visit_assignment(new assignment(*e)); } void deep_copy_visitor::visit_symbol (symbol* e) { symbol* n = new symbol(*e); n->referent = NULL; // don't copy! update_visitor::visit_symbol(n); } void deep_copy_visitor::visit_target_symbol (target_symbol* e) { target_symbol* n = new target_symbol(*e); n->referent = NULL; // don't copy! update_visitor::visit_target_symbol(n); } void deep_copy_visitor::visit_cast_op (cast_op* e) { update_visitor::visit_cast_op(new cast_op(*e)); } void deep_copy_visitor::visit_atvar_op (atvar_op* e) { update_visitor::visit_atvar_op(new atvar_op(*e)); } void deep_copy_visitor::visit_defined_op (defined_op* e) { update_visitor::visit_defined_op(new defined_op(*e)); } void deep_copy_visitor::visit_entry_op (entry_op* e) { update_visitor::visit_entry_op(new entry_op(*e)); } void deep_copy_visitor::visit_perf_op (perf_op* e) { update_visitor::visit_perf_op(new perf_op(*e)); } void deep_copy_visitor::visit_arrayindex (arrayindex* e) { update_visitor::visit_arrayindex(new arrayindex(*e)); } void deep_copy_visitor::visit_functioncall (functioncall* e) { functioncall* n = new functioncall(*e); n->referent = NULL; // don't copy! update_visitor::visit_functioncall(n); } void deep_copy_visitor::visit_print_format (print_format* e) { update_visitor::visit_print_format(new print_format(*e)); } void deep_copy_visitor::visit_stat_op (stat_op* e) { update_visitor::visit_stat_op(new stat_op(*e)); } void deep_copy_visitor::visit_hist_op (hist_op* e) { update_visitor::visit_hist_op(new hist_op(*e)); } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/staptree.h000066400000000000000000000750351217430427200154230ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2005-2013 Red Hat Inc. // Copyright (C) 2006 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef STAPTREE_H #define STAPTREE_H #include #include #include #include #include #include #include #include #include extern "C" { #include } #include "util.h" struct token; // parse.h struct systemtap_session; // session.h struct semantic_error: public std::runtime_error { const token* tok1; const token* tok2; const semantic_error *chain; ~semantic_error () throw () {} semantic_error (const std::string& msg, const token* t1=0): runtime_error (msg), tok1 (t1), tok2 (0), chain (0) {} semantic_error (const std::string& msg, const token* t1, const token* t2): runtime_error (msg), tok1 (t1), tok2 (t2), chain (0) {} }; // ------------------------------------------------------------------------ /* struct statistic_decl moved to session.h */ // ------------------------------------------------------------------------ enum exp_type { pe_unknown, pe_long, // int64_t pe_string, // std::string pe_stats }; std::ostream& operator << (std::ostream& o, const exp_type& e); struct token; struct visitor; struct update_visitor; struct visitable { virtual ~visitable (); }; struct expression : public visitable { exp_type type; const token* tok; expression (); virtual ~expression (); virtual void print (std::ostream& o) const = 0; virtual void visit (visitor* u) = 0; }; std::ostream& operator << (std::ostream& o, const expression& k); struct literal: public expression { }; struct literal_string: public literal { std::string value; literal_string (const std::string& v); void print (std::ostream& o) const; void visit (visitor* u); }; struct literal_number: public literal { int64_t value; bool print_hex; literal_number (int64_t v, bool hex=false); void print (std::ostream& o) const; void visit (visitor* u); }; struct embedded_expr: public expression { std::string code; void print (std::ostream& o) const; void visit (visitor* u); }; struct binary_expression: public expression { expression* left; std::string op; expression* right; void print (std::ostream& o) const; void visit (visitor* u); }; struct unary_expression: public expression { std::string op; expression* operand; void print (std::ostream& o) const; void visit (visitor* u); }; struct pre_crement: public unary_expression { void visit (visitor* u); }; struct post_crement: public unary_expression { void print (std::ostream& o) const; void visit (visitor* u); }; struct logical_or_expr: public binary_expression { void visit (visitor* u); }; struct logical_and_expr: public binary_expression { void visit (visitor* u); }; struct arrayindex; struct array_in: public expression { arrayindex* operand; void print (std::ostream& o) const; void visit (visitor* u); }; struct regex_query: public expression { expression* left; std::string op; literal_string* right; void visit (visitor* u); void print (std::ostream& o) const; }; struct comparison: public binary_expression { void visit (visitor* u); }; struct concatenation: public binary_expression { void visit (visitor* u); }; struct ternary_expression: public expression { expression* cond; expression* truevalue; expression* falsevalue; void print (std::ostream& o) const; void visit (visitor* u); }; struct assignment: public binary_expression { void visit (visitor* u); }; struct symbol; struct hist_op; struct indexable : public expression { // This is a helper class which, type-wise, acts as a disjoint union // of symbols and histograms. You can ask it whether it's a // histogram or a symbol, and downcast accordingly. virtual bool is_symbol(symbol *& sym_out); virtual bool is_hist_op(hist_op *& hist_out); virtual ~indexable() {} }; // Perform a downcast to one out-value and NULL the other, throwing an // exception if neither downcast succeeds. This is (sadly) about the // best we can accomplish in C++. void classify_indexable(indexable* ix, symbol *& array_out, hist_op *& hist_out); struct vardecl; struct symbol: public indexable { std::string name; vardecl *referent; symbol (); void print (std::ostream& o) const; void visit (visitor* u); // overrides of type 'indexable' bool is_symbol(symbol *& sym_out); }; struct target_symbol: public symbol { enum component_type { comp_struct_member, comp_literal_array_index, comp_expression_array_index, comp_pretty_print, // must be final }; struct component { const token* tok; component_type type; std::string member; // comp_struct_member, comp_pretty_print int64_t num_index; // comp_literal_array_index expression* expr_index; // comp_expression_array_index component(const token* t, const std::string& m, bool pprint=false): tok(t), type(pprint ? comp_pretty_print : comp_struct_member), member(m), num_index(0), expr_index(0) {} component(const token* t, int64_t n): tok(t), type(comp_literal_array_index), num_index(n), expr_index(0) {} component(const token* t, expression* e): tok(t), type(comp_expression_array_index), num_index(0), expr_index(e) {} void print (std::ostream& o) const; }; bool addressof; std::vector components; semantic_error* saved_conversion_error; // hand-made linked list target_symbol(): addressof(false), saved_conversion_error (0) {} virtual std::string sym_name (); void chain (const semantic_error& er); void print (std::ostream& o) const; void visit (visitor* u); void visit_components (visitor* u); void visit_components (update_visitor* u); void assert_no_components(const std::string& tapset, bool pretty_ok=false); }; std::ostream& operator << (std::ostream& o, const target_symbol::component& c); struct cast_op: public target_symbol { expression *operand; std::string type_name, module; void print (std::ostream& o) const; void visit (visitor* u); }; struct atvar_op: public target_symbol { std::string target_name, cu_name, module; virtual std::string sym_name (); void print (std::ostream& o) const; void visit (visitor* u); }; struct defined_op: public expression { target_symbol *operand; void print (std::ostream& o) const; void visit (visitor* u); }; struct entry_op: public expression { expression *operand; void print (std::ostream& o) const; void visit (visitor* u); }; struct perf_op: public expression { literal_string *operand; void print (std::ostream& o) const; void visit (visitor* u); }; struct arrayindex: public expression { std::vector indexes; indexable *base; arrayindex (); void print (std::ostream& o) const; void visit (visitor* u); }; struct functiondecl; struct functioncall: public expression { std::string function; std::vector args; functiondecl *referent; functioncall (); void print (std::ostream& o) const; void visit (visitor* u); }; struct print_format: public expression { bool print_to_stream; bool print_with_format; bool print_with_delim; bool print_with_newline; bool print_char; // XXX match runtime/vsprintf.c's print_flag // ... for use with number() & number_size() enum format_flag { fmt_flag_zeropad = 1, fmt_flag_sign = 2, fmt_flag_plus = 4, fmt_flag_space = 8, fmt_flag_left = 16, fmt_flag_special = 32, fmt_flag_large = 64, }; enum conversion_type { conv_unspecified, conv_pointer, conv_number, conv_string, conv_char, conv_memory, conv_memory_hex, conv_literal, conv_binary }; enum width_type { width_unspecified, width_static, width_dynamic }; enum precision_type { prec_unspecified, prec_static, prec_dynamic }; struct format_component { unsigned long flags; unsigned base; unsigned width; unsigned precision; width_type widthtype; precision_type prectype; conversion_type type; std::string literal_string; bool is_empty() const { return flags == 0 && widthtype == width_unspecified && prectype == prec_unspecified && type == conv_unspecified && literal_string.empty(); } void clear() { flags = 0; widthtype = width_unspecified; prectype = prec_unspecified; type = conv_unspecified; literal_string.clear(); } inline void set_flag(format_flag f) { flags |= f; } inline bool test_flag(format_flag f) const { return flags & f; } }; std::string raw_components; std::vector components; format_component delimiter; std::vector args; hist_op *hist; static std::string components_to_string(std::vector const & components); static std::vector string_to_components(std::string const & str); static print_format* create(const token *t); void print (std::ostream& o) const; void visit (visitor* u); private: print_format(bool stream, bool format, bool delim, bool newline, bool _char): print_to_stream(stream), print_with_format(format), print_with_delim(delim), print_with_newline(newline), print_char(_char), hist(NULL) {} }; enum stat_component_type { sc_average, sc_count, sc_sum, sc_min, sc_max, sc_none, }; struct stat_op: public expression { stat_component_type ctype; expression* stat; void print (std::ostream& o) const; void visit (visitor* u); }; enum histogram_type { hist_linear, hist_log }; struct hist_op: public indexable { histogram_type htype; expression* stat; std::vector params; void print (std::ostream& o) const; void visit (visitor* u); // overrides of type 'indexable' bool is_hist_op(hist_op *& hist_out); }; // ------------------------------------------------------------------------ struct symboldecl // unique object per (possibly implicit) // symbol declaration { const token* tok; const token* systemtap_v_conditional; //checking systemtap compatibility std::string name; exp_type type; symboldecl (); virtual ~symboldecl (); virtual void print (std::ostream &o) const = 0; virtual void printsig (std::ostream &o) const = 0; }; std::ostream& operator << (std::ostream& o, const symboldecl& k); struct vardecl: public symboldecl { void print (std::ostream& o) const; void printsig (std::ostream& o) const; vardecl (); void set_arity (int arity, const token* t); bool compatible_arity (int a); const token* arity_tok; // site where arity was first resolved int arity; // -1: unknown; 0: scalar; >0: array int maxsize; // upperbound on size for arrays std::vector index_types; // for arrays only literal *init; // for global scalars only bool synthetic; // for probe locals only, don't init on entry bool wrap; }; struct vardecl_builtin: public vardecl { }; struct statement; struct functiondecl: public symboldecl { std::vector formal_args; std::vector locals; std::vector unused_locals; statement* body; bool synthetic; bool mangle_oldstyle; functiondecl (); void print (std::ostream& o) const; void printsig (std::ostream& o) const; void join (systemtap_session& s); // for synthetic functions only }; // ------------------------------------------------------------------------ struct statement : public visitable { virtual void print (std::ostream& o) const = 0; virtual void visit (visitor* u) = 0; const token* tok; statement (); statement (const token* tok); virtual ~statement (); }; std::ostream& operator << (std::ostream& o, const statement& k); struct embeddedcode: public statement { std::string code; void print (std::ostream& o) const; void visit (visitor* u); }; struct block: public statement { std::vector statements; void print (std::ostream& o) const; void visit (visitor* u); block () {} block (statement* car, statement* cdr); virtual ~block () {} }; struct try_block: public statement { statement* try_block; // may be 0 statement* catch_block; // may be 0 symbol* catch_error_var; // may be 0 void print (std::ostream& o) const; void visit (visitor* u); }; struct expr_statement; struct for_loop: public statement { expr_statement* init; // may be 0 expression* cond; expr_statement* incr; // may be 0 statement* block; void print (std::ostream& o) const; void visit (visitor* u); }; struct foreach_loop: public statement { // this part is a specialization of arrayindex std::vector indexes; indexable *base; int sort_direction; // -1: decreasing, 0: none, 1: increasing unsigned sort_column; // 0: value, 1..N: index enum stat_component_type sort_aggr; // for aggregate arrays, which aggregate to sort on symbol* value; // optional iteration value expression* limit; // optional iteration limit statement* block; void print (std::ostream& o) const; void visit (visitor* u); }; struct null_statement: public statement { void print (std::ostream& o) const; void visit (visitor* u); null_statement (const token* tok); }; struct expr_statement: public statement { expression* value; // executed for side-effects void print (std::ostream& o) const; void visit (visitor* u); }; struct if_statement: public statement { expression* condition; statement* thenblock; statement* elseblock; // may be 0 void print (std::ostream& o) const; void visit (visitor* u); }; struct return_statement: public expr_statement { void print (std::ostream& o) const; void visit (visitor* u); }; struct delete_statement: public expr_statement { void print (std::ostream& o) const; void visit (visitor* u); }; struct break_statement: public statement { void print (std::ostream& o) const; void visit (visitor* u); }; struct continue_statement: public statement { void print (std::ostream& o) const; void visit (visitor* u); }; struct next_statement: public statement { void print (std::ostream& o) const; void visit (visitor* u); }; struct probe; struct derived_probe; struct probe_alias; struct embeddedcode; struct stapfile { std::string name; std::vector probes; std::vector aliases; std::vector functions; std::vector globals; std::vector embeds; std::string file_contents; bool privileged; stapfile (): file_contents (""), privileged (false) {} void print (std::ostream& o) const; }; struct probe_point { struct component // XXX: sort of a restricted functioncall { std::string functor; literal* arg; // optional component (); const token* tok; // points to component's functor component(std::string const & f, literal * a = NULL); }; std::vector components; bool optional; bool sufficient; expression* condition; void print (std::ostream& o, bool print_extras=true) const; probe_point (); probe_point(const probe_point& pp); probe_point(std::vector const & comps); std::string str(bool print_extras=true) const; }; std::ostream& operator << (std::ostream& o, const probe_point& k); struct probe { std::vector locations; statement* body; struct probe* base; const token* tok; const token* systemtap_v_conditional; //checking systemtap compatibility std::vector locals; std::vector unused_locals; static unsigned last_probeidx; probe (); probe (probe* p, probe_point *l); void print (std::ostream& o) const; virtual void printsig (std::ostream &o) const; virtual void collect_derivation_chain (std::vector &probes_list) const; virtual void collect_derivation_pp_chain (std::vector &) const; virtual const probe_alias *get_alias () const { return 0; } virtual probe_point *get_alias_loc () const { return 0; } virtual probe* create_alias(probe_point* l, probe_point* a); virtual ~probe() {} bool privileged; std::string name; }; struct probe_alias: public probe { probe_alias(std::vector const & aliases); std::vector alias_names; virtual void printsig (std::ostream &o) const; bool epilogue_style; }; // A derived visitor instance is used to visit the entire // statement/expression tree. struct visitor { // Machinery for differentiating lvalue visits from non-lvalue. std::vector active_lvalues; bool is_active_lvalue(expression *e); void push_active_lvalue(expression *e); void pop_active_lvalue(); virtual ~visitor () {} virtual void visit_block (block *s) = 0; virtual void visit_try_block (try_block *s) = 0; virtual void visit_embeddedcode (embeddedcode *s) = 0; virtual void visit_null_statement (null_statement *s) = 0; virtual void visit_expr_statement (expr_statement *s) = 0; virtual void visit_if_statement (if_statement* s) = 0; virtual void visit_for_loop (for_loop* s) = 0; virtual void visit_foreach_loop (foreach_loop* s) = 0; virtual void visit_return_statement (return_statement* s) = 0; virtual void visit_delete_statement (delete_statement* s) = 0; virtual void visit_next_statement (next_statement* s) = 0; virtual void visit_break_statement (break_statement* s) = 0; virtual void visit_continue_statement (continue_statement* s) = 0; virtual void visit_literal_string (literal_string* e) = 0; virtual void visit_literal_number (literal_number* e) = 0; virtual void visit_embedded_expr (embedded_expr* e) = 0; virtual void visit_binary_expression (binary_expression* e) = 0; virtual void visit_unary_expression (unary_expression* e) = 0; virtual void visit_pre_crement (pre_crement* e) = 0; virtual void visit_post_crement (post_crement* e) = 0; virtual void visit_logical_or_expr (logical_or_expr* e) = 0; virtual void visit_logical_and_expr (logical_and_expr* e) = 0; virtual void visit_array_in (array_in* e) = 0; virtual void visit_regex_query (regex_query* e) = 0; virtual void visit_comparison (comparison* e) = 0; virtual void visit_concatenation (concatenation* e) = 0; virtual void visit_ternary_expression (ternary_expression* e) = 0; virtual void visit_assignment (assignment* e) = 0; virtual void visit_symbol (symbol* e) = 0; virtual void visit_target_symbol (target_symbol* e) = 0; virtual void visit_arrayindex (arrayindex* e) = 0; virtual void visit_functioncall (functioncall* e) = 0; virtual void visit_print_format (print_format* e) = 0; virtual void visit_stat_op (stat_op* e) = 0; virtual void visit_hist_op (hist_op* e) = 0; virtual void visit_cast_op (cast_op* e) = 0; virtual void visit_atvar_op (atvar_op* e) = 0; virtual void visit_defined_op (defined_op* e) = 0; virtual void visit_entry_op (entry_op* e) = 0; virtual void visit_perf_op (perf_op* e) = 0; }; // A simple kind of visitor, which travels down to the leaves of the // statement/expression tree, up to but excluding following vardecls // and functioncalls. struct traversing_visitor: public visitor { void visit_block (block *s); void visit_try_block (try_block *s); void visit_embeddedcode (embeddedcode *s); void visit_null_statement (null_statement *s); void visit_expr_statement (expr_statement *s); void visit_if_statement (if_statement* s); void visit_for_loop (for_loop* s); void visit_foreach_loop (foreach_loop* s); void visit_return_statement (return_statement* s); void visit_delete_statement (delete_statement* s); void visit_next_statement (next_statement* s); void visit_break_statement (break_statement* s); void visit_continue_statement (continue_statement* s); void visit_literal_string (literal_string* e); void visit_literal_number (literal_number* e); void visit_embedded_expr (embedded_expr* e); void visit_binary_expression (binary_expression* e); void visit_unary_expression (unary_expression* e); void visit_pre_crement (pre_crement* e); void visit_post_crement (post_crement* e); void visit_logical_or_expr (logical_or_expr* e); void visit_logical_and_expr (logical_and_expr* e); void visit_array_in (array_in* e); void visit_regex_query (regex_query* e); void visit_comparison (comparison* e); void visit_concatenation (concatenation* e); void visit_ternary_expression (ternary_expression* e); void visit_assignment (assignment* e); void visit_symbol (symbol* e); void visit_target_symbol (target_symbol* e); void visit_arrayindex (arrayindex* e); void visit_functioncall (functioncall* e); void visit_print_format (print_format* e); void visit_stat_op (stat_op* e); void visit_hist_op (hist_op* e); void visit_cast_op (cast_op* e); void visit_atvar_op (atvar_op* e); void visit_defined_op (defined_op* e); void visit_entry_op (entry_op* e); void visit_perf_op (perf_op* e); }; // A kind of traversing visitor, which also follows function calls. // It uses an internal set object to prevent infinite recursion. struct functioncall_traversing_visitor: public traversing_visitor { std::set traversed; functiondecl* current_function; functioncall_traversing_visitor(): current_function(0) {} void visit_functioncall (functioncall* e); }; // A kind of traversing visitor, which also follows function calls, // and stores the vardecl* referent of each variable read and/or // written and other such sundry side-effect data. It's used by // the elaboration-time optimizer pass. struct varuse_collecting_visitor: public functioncall_traversing_visitor { systemtap_session& session; std::set read; std::set written; std::set used; bool embedded_seen; bool current_lvalue_read; expression* current_lvalue; expression* current_lrvalue; varuse_collecting_visitor(systemtap_session& s): session (s), embedded_seen (false), current_lvalue_read (false), current_lvalue(0), current_lrvalue(0) {} void visit_embeddedcode (embeddedcode *s); void visit_embedded_expr (embedded_expr *e); void visit_try_block (try_block *s); void visit_delete_statement (delete_statement *s); void visit_print_format (print_format *e); void visit_assignment (assignment *e); void visit_arrayindex (arrayindex *e); void visit_target_symbol (target_symbol *e); void visit_symbol (symbol *e); void visit_pre_crement (pre_crement *e); void visit_post_crement (post_crement *e); void visit_foreach_loop (foreach_loop *s); void visit_cast_op (cast_op* e); void visit_atvar_op (atvar_op *e); void visit_defined_op (defined_op* e); void visit_entry_op (entry_op* e); void visit_perf_op (perf_op* e); bool side_effect_free (); bool side_effect_free_wrt (const std::set& vars); }; // A kind of visitor that throws an semantic_error exception // whenever a non-overridden method is called. struct throwing_visitor: public visitor { std::string msg; throwing_visitor (const std::string& m); throwing_visitor (); virtual void throwone (const token* t); void visit_block (block *s); void visit_try_block (try_block *s); void visit_embeddedcode (embeddedcode *s); void visit_null_statement (null_statement *s); void visit_expr_statement (expr_statement *s); void visit_if_statement (if_statement* s); void visit_for_loop (for_loop* s); void visit_foreach_loop (foreach_loop* s); void visit_return_statement (return_statement* s); void visit_delete_statement (delete_statement* s); void visit_next_statement (next_statement* s); void visit_break_statement (break_statement* s); void visit_continue_statement (continue_statement* s); void visit_literal_string (literal_string* e); void visit_literal_number (literal_number* e); void visit_embedded_expr (embedded_expr* e); void visit_binary_expression (binary_expression* e); void visit_unary_expression (unary_expression* e); void visit_pre_crement (pre_crement* e); void visit_post_crement (post_crement* e); void visit_logical_or_expr (logical_or_expr* e); void visit_logical_and_expr (logical_and_expr* e); void visit_array_in (array_in* e); void visit_regex_query (regex_query* e); void visit_comparison (comparison* e); void visit_concatenation (concatenation* e); void visit_ternary_expression (ternary_expression* e); void visit_assignment (assignment* e); void visit_symbol (symbol* e); void visit_target_symbol (target_symbol* e); void visit_arrayindex (arrayindex* e); void visit_functioncall (functioncall* e); void visit_print_format (print_format* e); void visit_stat_op (stat_op* e); void visit_hist_op (hist_op* e); void visit_cast_op (cast_op* e); void visit_atvar_op (atvar_op* e); void visit_defined_op (defined_op* e); void visit_entry_op (entry_op* e); void visit_perf_op (perf_op* e); }; // A visitor similar to a traversing_visitor, but with the ability to rewrite // parts of the tree through require/provide. struct update_visitor: public visitor { template T* require (T* src, bool clearok=false) { T* dst = NULL; if (src != NULL) { src->visit(this); if (values.empty()) throw std::runtime_error(_("update_visitor wasn't provided a value")); visitable *v = values.top(); values.pop(); if (v == NULL && !clearok) throw std::runtime_error(_("update_visitor was provided a NULL value")); dst = dynamic_cast(v); if (v != NULL && dst == NULL) throw std::runtime_error(_F("update_visitor can't set type \"%s\" with a \"%s\"", typeid(T).name(), typeid(*v).name())); } return dst; } template void provide (T* src) { values.push(src); } template void replace (T*& src, bool clearok=false) { src = require(src, clearok); } virtual ~update_visitor() { assert(values.empty()); } virtual void visit_block (block *s); virtual void visit_try_block (try_block *s); virtual void visit_embeddedcode (embeddedcode *s); virtual void visit_null_statement (null_statement *s); virtual void visit_expr_statement (expr_statement *s); virtual void visit_if_statement (if_statement* s); virtual void visit_for_loop (for_loop* s); virtual void visit_foreach_loop (foreach_loop* s); virtual void visit_return_statement (return_statement* s); virtual void visit_delete_statement (delete_statement* s); virtual void visit_next_statement (next_statement* s); virtual void visit_break_statement (break_statement* s); virtual void visit_continue_statement (continue_statement* s); virtual void visit_literal_string (literal_string* e); virtual void visit_literal_number (literal_number* e); virtual void visit_embedded_expr (embedded_expr* e); virtual void visit_binary_expression (binary_expression* e); virtual void visit_unary_expression (unary_expression* e); virtual void visit_pre_crement (pre_crement* e); virtual void visit_post_crement (post_crement* e); virtual void visit_logical_or_expr (logical_or_expr* e); virtual void visit_logical_and_expr (logical_and_expr* e); virtual void visit_array_in (array_in* e); virtual void visit_regex_query (regex_query* e); virtual void visit_comparison (comparison* e); virtual void visit_concatenation (concatenation* e); virtual void visit_ternary_expression (ternary_expression* e); virtual void visit_assignment (assignment* e); virtual void visit_symbol (symbol* e); virtual void visit_target_symbol (target_symbol* e); virtual void visit_arrayindex (arrayindex* e); virtual void visit_functioncall (functioncall* e); virtual void visit_print_format (print_format* e); virtual void visit_stat_op (stat_op* e); virtual void visit_hist_op (hist_op* e); virtual void visit_cast_op (cast_op* e); virtual void visit_atvar_op (atvar_op* e); virtual void visit_defined_op (defined_op* e); virtual void visit_entry_op (entry_op* e); virtual void visit_perf_op (perf_op* e); private: std::stack values; }; // A visitor which performs a deep copy of the root node it's applied // to. NB: It does not copy any of the variable or function // declarations; those fields are set to NULL, assuming you want to // re-infer the declarations in a new context (the one you're copying // to). struct deep_copy_visitor: public update_visitor { template static T* deep_copy (T* e) { deep_copy_visitor v; return v.require (e); } virtual void visit_block (block *s); virtual void visit_try_block (try_block *s); virtual void visit_embeddedcode (embeddedcode *s); virtual void visit_null_statement (null_statement *s); virtual void visit_expr_statement (expr_statement *s); virtual void visit_if_statement (if_statement* s); virtual void visit_for_loop (for_loop* s); virtual void visit_foreach_loop (foreach_loop* s); virtual void visit_return_statement (return_statement* s); virtual void visit_delete_statement (delete_statement* s); virtual void visit_next_statement (next_statement* s); virtual void visit_break_statement (break_statement* s); virtual void visit_continue_statement (continue_statement* s); virtual void visit_literal_string (literal_string* e); virtual void visit_literal_number (literal_number* e); virtual void visit_embedded_expr (embedded_expr* e); virtual void visit_binary_expression (binary_expression* e); virtual void visit_unary_expression (unary_expression* e); virtual void visit_pre_crement (pre_crement* e); virtual void visit_post_crement (post_crement* e); virtual void visit_logical_or_expr (logical_or_expr* e); virtual void visit_logical_and_expr (logical_and_expr* e); virtual void visit_array_in (array_in* e); virtual void visit_regex_query (regex_query* e); virtual void visit_comparison (comparison* e); virtual void visit_concatenation (concatenation* e); virtual void visit_ternary_expression (ternary_expression* e); virtual void visit_assignment (assignment* e); virtual void visit_symbol (symbol* e); virtual void visit_target_symbol (target_symbol* e); virtual void visit_arrayindex (arrayindex* e); virtual void visit_functioncall (functioncall* e); virtual void visit_print_format (print_format* e); virtual void visit_stat_op (stat_op* e); virtual void visit_hist_op (hist_op* e); virtual void visit_cast_op (cast_op* e); virtual void visit_atvar_op (atvar_op* e); virtual void visit_defined_op (defined_op* e); virtual void visit_entry_op (entry_op* e); virtual void visit_perf_op (perf_op* e); }; #endif // STAPTREE_H /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/systemtap.spec000066400000000000000000000763571217430427200163400ustar00rootroot00000000000000%{!?with_sqlite: %global with_sqlite 1} %{!?with_docs: %global with_docs 1} # crash is not available %ifarch ppc ppc64 %{sparc} %{!?with_crash: %global with_crash 0} %else %{!?with_crash: %global with_crash 1} %endif %{!?with_rpm: %global with_rpm 1} %{!?with_bundled_elfutils: %global with_bundled_elfutils 0} %{!?elfutils_version: %global elfutils_version 0.142} %{!?pie_supported: %global pie_supported 1} %{!?with_boost: %global with_boost 0} %ifarch ppc ppc64 %{sparc} %{!?with_publican: %global with_publican 0} %else %{!?with_publican: %global with_publican 1} %endif %if 0%{?rhel} %{!?publican_brand: %global publican_brand RedHat} %else %{!?publican_brand: %global publican_brand fedora} %endif %ifnarch s390 s390x %{arm} %{!?with_dyninst: %global with_dyninst 0%{?fedora} >= 18 || 0%{?rhel} >= 7} %else %{!?with_dyninst: %global with_dyninst 0} %endif %{!?with_systemd: %global with_systemd 0%{?fedora} >= 19} %{!?with_emacsvim: %global with_emacsvim 1} %{!?with_java: %global with_java 1} Name: systemtap Version: 2.3 Release: 1%{?dist} # for version, see also configure.ac # Packaging abstract: # # systemtap empty req:-client req:-devel # systemtap-server /usr/bin/stap-server*, req:-devel # systemtap-devel /usr/bin/stap, runtime, tapset, req:kernel-devel # systemtap-runtime /usr/bin/staprun, /usr/bin/stapsh, /usr/bin/stapdyn # systemtap-client /usr/bin/stap, samples, docs, tapset(bonus), req:-runtime # systemtap-initscript /etc/init.d/systemtap, req:systemtap # systemtap-sdt-devel /usr/include/sys/sdt.h /usr/bin/dtrace # systemtap-testsuite /usr/share/systemtap/testsuite*, req:systemtap, req:sdt-devel # systemtap-runtime-java libHelperSDT.so, HelperSDT.jar, stapbm, req:-runtime # # Typical scenarios: # # stap-client: systemtap-client # stap-server: systemtap-server # local user: systemtap # # Unusual scenarios: # # intermediary stap-client for --remote: systemtap-client (-runtime unused) # intermediary stap-server for --use-server: systemtap-server (-devel unused) Summary: Programmable system-wide instrumentation system Group: Development/System License: GPLv2+ URL: http://sourceware.org/systemtap/ Source: ftp://sourceware.org/pub/systemtap/releases/systemtap-%{version}.tar.gz # Build* BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: gcc-c++ BuildRequires: gettext-devel BuildRequires: nss-devel avahi-devel pkgconfig %if %{with_dyninst} BuildRequires: dyninst-devel >= 8.0 BuildRequires: libselinux-devel %endif %if %{with_sqlite} BuildRequires: sqlite-devel %endif # Needed for libstd++ < 4.0, without %if %{with_boost} BuildRequires: boost-devel %endif %if %{with_crash} BuildRequires: crash-devel zlib-devel %endif %if %{with_rpm} BuildRequires: rpm-devel glibc-headers %endif %if %{with_bundled_elfutils} Source1: elfutils-%{elfutils_version}.tar.gz Patch1: elfutils-portability.patch BuildRequires: m4 %global setup_elfutils -a1 %else BuildRequires: elfutils-devel >= %{elfutils_version} %endif %if %{with_docs} BuildRequires: /usr/bin/latex /usr/bin/dvips /usr/bin/ps2pdf latex2html %if 0%{?fedora} >= 18 || 0%{?rhel} >= 7 BuildRequires: tex(fullpage.sty) tex(fancybox.sty) tex(bchr7t.tfm) %endif # On F10, xmlto's pdf support was broken off into a sub-package, # called 'xmlto-tex'. To avoid a specific F10 BuildReq, we'll do a # file-based buildreq on '/usr/share/xmlto/format/fo/pdf'. BuildRequires: xmlto /usr/share/xmlto/format/fo/pdf %if %{with_publican} BuildRequires: publican BuildRequires: /usr/share/publican/Common_Content/%{publican_brand}/defaults.cfg %endif %endif %if %{with_emacsvim} BuildRequires: emacs %endif %if %{with_java} BuildRequires: jpackage-utils java-devel %endif # A workaround for BZ920216 which requires an X server to build docs BuildRequires: /usr/bin/xvfb-run # Install requirements Requires: systemtap-client = %{version}-%{release} Requires: systemtap-devel = %{version}-%{release} %description SystemTap is an instrumentation system for systems running Linux. Developers can write instrumentation scripts to collect data on the operation of the system. The base systemtap package contains/requires the components needed to locally develop and execute systemtap scripts. # ------------------------------------------------------------------------ %package server Summary: Instrumentation System Server Group: Development/System License: GPLv2+ URL: http://sourceware.org/systemtap/ Requires: systemtap-devel = %{version}-%{release} # On RHEL[45], /bin/mktemp comes from the 'mktemp' package. On newer # distributions, /bin/mktemp comes from the 'coreutils' package. To # avoid a specific RHEL[45] Requires, we'll do a file-based require. Requires: nss /bin/mktemp Requires: zip unzip Requires(pre): shadow-utils Requires(post): chkconfig Requires(preun): chkconfig Requires(preun): initscripts Requires(postun): initscripts BuildRequires: nss-devel avahi-devel %description server This is the remote script compilation server component of systemtap. It announces itself to nearby clients with avahi (if available), and compiles systemtap scripts to kernel objects on their demand. %package devel Summary: Programmable system-wide instrumentation system - development headers, tools Group: Development/System License: GPLv2+ URL: http://sourceware.org/systemtap/ Requires: kernel >= 2.6.9-11 # Alternate kernel packages kernel-PAE-devel et al. have a virtual # provide for kernel-devel, so this requirement does the right thing, # at least past RHEL4. Requires: kernel-devel Requires: gcc make # Suggest: kernel-debuginfo %description devel This package contains the components needed to compile a systemtap script from source form into executable (.ko) forms. It may be installed on a self-contained developer workstation (along with the systemtap-client and systemtap-runtime packages), or on a dedicated remote server (alongside the systemtap-server package). It includes a copy of the standard tapset library and the runtime library C files. %package runtime Summary: Programmable system-wide instrumentation system - runtime Group: Development/System License: GPLv2+ URL: http://sourceware.org/systemtap/ Requires: kernel >= 2.6.9-11 Requires(pre): shadow-utils %description runtime SystemTap runtime contains the components needed to execute a systemtap script that was already compiled into a module using a local or remote systemtap-devel installation. %package client Summary: Programmable system-wide instrumentation system - client Group: Development/System License: GPLv2+ URL: http://sourceware.org/systemtap/ Requires: zip unzip Requires: systemtap-runtime = %{version}-%{release} Requires: coreutils grep sed unzip zip Requires: openssh-clients %description client This package contains/requires the components needed to develop systemtap scripts, and compile them using a local systemtap-devel or a remote systemtap-server installation, then run them using a local or remote systemtap-runtime. It includes script samples and documentation, and a copy of the tapset library for reference. %package initscript Summary: Systemtap Initscripts Group: Development/System License: GPLv2+ URL: http://sourceware.org/systemtap/ Requires: systemtap = %{version}-%{release} Requires(post): chkconfig Requires(preun): chkconfig Requires(preun): initscripts Requires(postun): initscripts %description initscript Sysvinit scripts to launch selected systemtap scripts at system startup. %package sdt-devel Summary: Static probe support tools Group: Development/System License: GPLv2+ and Public Domain URL: http://sourceware.org/systemtap/ %description sdt-devel This package includes the header file used for static instrumentation compiled into userspace programs and libraries, along with the optional dtrace-compatibility preprocessor to process related .d files into tracing-macro-laden .h headers. %package testsuite Summary: Instrumentation System Testsuite Group: Development/System License: GPLv2+ URL: http://sourceware.org/systemtap/ Requires: systemtap = %{version}-%{release} Requires: systemtap-sdt-devel = %{version}-%{release} Requires: systemtap-server = %{version}-%{release} Requires: dejagnu which elfutils grep nc Requires: gcc gcc-c++ make glibc-devel %ifnarch ia64 Requires: prelink %endif # testsuite/systemtap.server/client.exp needs avahi Requires: avahi %if %{with_crash} # testsuite/systemtap.base/crash.exp needs crash Requires: crash %endif %if %{with_java} Requires: systemtap-runtime-java = %{version}-%{release} %endif %ifarch x86_64 Requires: /usr/lib/libc.so # ... and /usr/lib/libgcc_s.so.* # ... and /usr/lib/libstdc++.so.* %endif %description testsuite This package includes the dejagnu-based systemtap stress self-testing suite. This may be used by system administrators to thoroughly check systemtap on the current system. %if %{with_java} %package runtime-java Summary: Systemtap Java Runtime Support Group: Development/System License: GPLv2+ URL: http://sourceware.org/systemtap/ Requires: systemtap-runtime = %{version}-%{release} Requires: byteman > 2.0 %description runtime-java This package includes support files needed to run systemtap scripts that probe Java processes running on the OpenJDK 1.6 and OpenJDK 1.7 runtimes using Byteman. %endif # ------------------------------------------------------------------------ %prep %setup -q %{?setup_elfutils} %if %{with_bundled_elfutils} cd elfutils-%{elfutils_version} %patch1 -p1 sleep 1 find . \( -name Makefile.in -o -name aclocal.m4 \) -print | xargs touch sleep 1 find . \( -name configure -o -name config.h.in \) -print | xargs touch cd .. %endif %build %if %{with_bundled_elfutils} # Build our own copy of elfutils. %global elfutils_config --with-elfutils=elfutils-%{elfutils_version} # We have to prevent the standard dependency generation from identifying # our private elfutils libraries in our provides and requires. %global _use_internal_dependency_generator 0 %global filter_eulibs() /bin/sh -c "%{1} | sed '/libelf/d;/libdw/d;/libebl/d'" %global __find_provides %{filter_eulibs /usr/lib/rpm/find-provides} %global __find_requires %{filter_eulibs /usr/lib/rpm/find-requires} # This will be needed for running stap when not installed, for the test suite. %global elfutils_mflags LD_LIBRARY_PATH=`pwd`/lib-elfutils %endif # Enable/disable the dyninst pure-userspace backend %if %{with_dyninst} %global dyninst_config --with-dyninst %else %global dyninst_config --without-dyninst %endif # Enable/disable the sqlite coverage testing support %if %{with_sqlite} %global sqlite_config --enable-sqlite %else %global sqlite_config --disable-sqlite %endif # Enable/disable the crash extension %if %{with_crash} %global crash_config --enable-crash %else %global crash_config --disable-crash %endif # Enable/disable the code to find and suggest needed rpms %if %{with_rpm} %global rpm_config --with-rpm %else %global rpm_config --without-rpm %endif %if %{with_docs} %global docs_config --enable-docs %else %global docs_config --disable-docs %endif # Enable pie as configure defaults to disabling it %if %{pie_supported} %global pie_config --enable-pie %else %global pie_config --disable-pie %endif %if %{with_publican} %global publican_config --enable-publican --with-publican-brand=%{publican_brand} %else %global publican_config --disable-publican %endif %if %{with_java} %global java_config --with-java=%{_jvmdir}/java %else %global java_config --without-java %endif %configure %{?elfutils_config} %{dyninst_config} %{sqlite_config} %{crash_config} %{docs_config} %{pie_config} %{publican_config} %{rpm_config} %{java_config} --disable-silent-rules --with-extra-version="rpm %{version}-%{release}" make %{?_smp_mflags} %if %{with_emacsvim} %{_emacs_bytecompile} emacs/systemtap-mode.el %endif %install rm -rf ${RPM_BUILD_ROOT} make DESTDIR=$RPM_BUILD_ROOT install %find_lang %{name} # We want the examples in the special doc dir, not the build install dir. # We build it in place and then move it away so it doesn't get installed # twice. rpm can specify itself where the (versioned) docs go with the # %doc directive. mv $RPM_BUILD_ROOT%{_datadir}/doc/systemtap/examples examples # Fix paths in the example & testsuite scripts find examples testsuite -type f -name '*.stp' -print0 | xargs -0 sed -i -r -e '1s@^#!.+stap@#!%{_bindir}/stap@' # To make rpmlint happy, remove any .gitignore files in the testsuite. find testsuite -type f -name '.gitignore' -print0 | xargs -0 rm -f # Because "make install" may install staprun with whatever mode, the # post-processing programs rpmbuild runs won't be able to read it. # So, we change permissions so that they can read it. We'll set the # permissions back to 04110 in the %files section below. chmod 755 $RPM_BUILD_ROOT%{_bindir}/staprun #install the useful stap-prep script install -c -m 755 stap-prep $RPM_BUILD_ROOT%{_bindir}/stap-prep # Copy over the testsuite cp -rp testsuite $RPM_BUILD_ROOT%{_datadir}/systemtap %if %{with_docs} # We want the manuals in the special doc dir, not the generic doc install dir. # We build it in place and then move it away so it doesn't get installed # twice. rpm can specify itself where the (versioned) docs go with the # %doc directive. mkdir docs.installed mv $RPM_BUILD_ROOT%{_datadir}/doc/systemtap/*.pdf docs.installed/ mv $RPM_BUILD_ROOT%{_datadir}/doc/systemtap/tapsets docs.installed/ %if %{with_publican} mv $RPM_BUILD_ROOT%{_datadir}/doc/systemtap/SystemTap_Beginners_Guide docs.installed/ %endif %endif mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/stap-server mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/lib/stap-server mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/lib/stap-server/.systemtap mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/log/stap-server touch $RPM_BUILD_ROOT%{_localstatedir}/log/stap-server/log mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/cache/systemtap mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/run/systemtap mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d install -m 644 initscript/logrotate.stap-server $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/stap-server mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/rc.d/init.d/ install -m 755 initscript/systemtap $RPM_BUILD_ROOT%{_sysconfdir}/rc.d/init.d/ mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/systemtap mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/systemtap/conf.d mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/systemtap/script.d install -m 644 initscript/config.systemtap $RPM_BUILD_ROOT%{_sysconfdir}/systemtap/config %if %{with_systemd} mkdir -p $RPM_BUILD_ROOT%{_unitdir} touch $RPM_BUILD_ROOT%{_unitdir}/stap-server.service install -m 644 stap-server.service $RPM_BUILD_ROOT%{_unitdir}/stap-server.service mkdir -p $RPM_BUILD_ROOT%{_tmpfilesdir} install -m 644 stap-server.conf $RPM_BUILD_ROOT%{_tmpfilesdir}/stap-server.conf %else install -m 755 initscript/stap-server $RPM_BUILD_ROOT%{_sysconfdir}/rc.d/init.d/ mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/stap-server/conf.d mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig install -m 644 initscript/config.stap-server $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/stap-server %endif %if %{with_emacsvim} mkdir -p $RPM_BUILD_ROOT%{_emacs_sitelispdir} install -p -m 644 emacs/systemtap-mode.el* $RPM_BUILD_ROOT%{_emacs_sitelispdir} mkdir -p $RPM_BUILD_ROOT%{_emacs_sitestartdir} install -p -m 644 emacs/systemtap-init.el $RPM_BUILD_ROOT%{_emacs_sitestartdir}/systemtap-init.el for subdir in ftdetect ftplugin indent syntax do mkdir -p $RPM_BUILD_ROOT%{_datadir}/vim/vimfiles/$subdir install -p -m 644 vim/$subdir/*.vim $RPM_BUILD_ROOT%{_datadir}/vim/vimfiles/$subdir done %endif %clean rm -rf ${RPM_BUILD_ROOT} %pre runtime getent group stapusr >/dev/null || groupadd -g 156 -r stapusr 2>/dev/null || groupadd -r stapusr getent group stapsys >/dev/null || groupadd -g 157 -r stapsys 2>/dev/null || groupadd -r stapsys getent group stapdev >/dev/null || groupadd -g 158 -r stapdev 2>/dev/null || groupadd -r stapdev exit 0 %pre server getent group stap-server >/dev/null || groupadd -g 155 -r stap-server 2>/dev/null || groupadd -r stap-server getent passwd stap-server >/dev/null || \ useradd -c "Systemtap Compile Server" -u 155 -g stap-server -d %{_localstatedir}/lib/stap-server -r -s /sbin/nologin stap-server 2>/dev/null || \ useradd -c "Systemtap Compile Server" -g stap-server -d %{_localstatedir}/lib/stap-server -r -s /sbin/nologin stap-server %post server test -e ~stap-server && chmod 755 ~stap-server if [ ! -f ~stap-server/.systemtap/rc ]; then mkdir -p ~stap-server/.systemtap chown stap-server:stap-server ~stap-server/.systemtap echo "--rlimit-as=614400000 --rlimit-cpu=60 --rlimit-nproc=20 --rlimit-stack=1024000 --rlimit-fsize=51200000" > ~stap-server/.systemtap/rc chown stap-server:stap-server ~stap-server/.systemtap/rc fi test -e %{_localstatedir}/log/stap-server/log || { touch %{_localstatedir}/log/stap-server/log chmod 664 %{_localstatedir}/log/stap-server/log chown stap-server:stap-server %{_localstatedir}/log/stap-server/log } # If it does not already exist, as stap-server, generate the certificate # used for signing and for ssl. if test ! -e ~stap-server/.systemtap/ssl/server/stap.cert; then runuser -s /bin/sh - stap-server -c %{_libexecdir}/systemtap/stap-gen-cert >/dev/null fi # Activate the service %if %{with_systemd} /bin/systemctl enable stap-server.service >/dev/null 2>&1 || : /bin/systemd-tmpfiles --create >/dev/null 2>&1 || : %else /sbin/chkconfig --add stap-server %endif exit 0 %triggerin client -- systemtap-server if test -e ~stap-server/.systemtap/ssl/server/stap.cert; then # echo Authorizing ssl-peer/trusted-signer certificate for local systemtap-server %{_libexecdir}/systemtap/stap-authorize-cert ~stap-server/.systemtap/ssl/server/stap.cert %{_sysconfdir}/systemtap/ssl/client >/dev/null %{_libexecdir}/systemtap/stap-authorize-cert ~stap-server/.systemtap/ssl/server/stap.cert %{_sysconfdir}/systemtap/staprun >/dev/null fi exit 0 # XXX: corresponding %triggerun? %preun server # Check that this is the actual deinstallation of the package, as opposed to # just removing the old package on upgrade. if [ $1 = 0 ] ; then %if %{with_systemd} /bin/systemctl --no-reload disable stap-server.service >/dev/null 2>&1 || : /bin/systemctl stop stap-server.service >/dev/null 2>&1 || : %else /sbin/service stap-server stop >/dev/null 2>&1 /sbin/chkconfig --del stap-server %endif fi exit 0 %postun server # Check whether this is an upgrade of the package. # If so, restart the service if it's running if [ "$1" -ge "1" ] ; then %if %{with_systemd} /bin/systemctl restart stap-server.service >/dev/null 2>&1 || : %else /sbin/service stap-server condrestart >/dev/null 2>&1 || : %endif fi exit 0 %post initscript %if %{with_systemd} /bin/systemctl enable stap-server.service >/dev/null 2>&1 || : /bin/systemd-tmpfiles --create >/dev/null 2>&1 || : %else /sbin/chkconfig --add systemtap %endif exit 0 %preun initscript # Check that this is the actual deinstallation of the package, as opposed to # just removing the old package on upgrade. if [ $1 = 0 ] ; then %if %{with_systemd} /bin/systemctl --no-reload disable stap-server.service >/dev/null 2>&1 || : /bin/systemctl stop stap-server.service >/dev/null 2>&1 || : %else /sbin/service systemtap stop >/dev/null 2>&1 /sbin/chkconfig --del systemtap %endif fi exit 0 %postun initscript # Check whether this is an upgrade of the package. # If so, restart the service if it's running if [ "$1" -ge "1" ] ; then %if %{with_systemd} /bin/systemctl restart stap-server.service >/dev/null 2>&1 || : %else /sbin/service systemtap condrestart >/dev/null 2>&1 || : %endif fi exit 0 %post # Remove any previously-built uprobes.ko materials (make -C %{_datadir}/systemtap/runtime/uprobes clean) >/dev/null 2>&1 || true (/sbin/rmmod uprobes) >/dev/null 2>&1 || true %preun # Ditto (make -C %{_datadir}/systemtap/runtime/uprobes clean) >/dev/null 2>&1 || true (/sbin/rmmod uprobes) >/dev/null 2>&1 || true # ------------------------------------------------------------------------ %if %{with_java} %triggerin runtime-java -- java-1.7.0-openjdk, java-1.6.0-openjdk for f in %{_libexecdir}/systemtap/libHelperSDT_*.so; do arch=`basename $f | cut -f2 -d_ | cut -f1 -d.` for archdir in %{_jvmdir}/*openjdk*/jre/lib/${arch}; do ln -sf %{_libexecdir}/systemtap/libHelperSDT_${arch}.so ${archdir}/libHelperSDT_${arch}.so ln -sf %{_libexecdir}/systemtap/HelperSDT.jar ${archdir}/../ext/HelperSDT.jar done done %triggerun runtime-java -- java-1.7.0-openjdk, java-1.6.0-openjdk for f in %{_libexecdir}/systemtap/libHelperSDT_*.so; do arch=`basename $f | cut -f2 -d_ | cut -f1 -d.` for archdir in %{_jvmdir}/*openjdk*/jre/lib/${arch}; do rm -f ${archdir}/libHelperSDT_${arch}.so rm -f ${archdir}/../ext/HelperSDT.jar done done %triggerpostun runtime-java -- java-1.7.0-openjdk, java-1.6.0-openjdk # Restore links for any JDKs remaining after a package removal: for f in %{_libexecdir}/systemtap/libHelperSDT_*.so; do arch=`basename $f | cut -f2 -d_ | cut -f1 -d.` for archdir in %{_jvmdir}/*openjdk*/jre/lib/${arch}; do ln -sf %{_libexecdir}/systemtap/libHelperSDT_${arch}.so ${archdir}/libHelperSDT_${arch}.so ln -sf %{_libexecdir}/systemtap/HelperSDT.jar ${archdir}/../ext/HelperSDT.jar done done # XXX: analogous support for other types of JRE/JDK?? %endif # ------------------------------------------------------------------------ %files -f systemtap.lang # The master "systemtap" rpm doesn't include any files. %files server -f systemtap.lang %defattr(-,root,root) %{_bindir}/stap-server %dir %{_libexecdir}/systemtap %{_libexecdir}/systemtap/stap-serverd %{_libexecdir}/systemtap/stap-start-server %{_libexecdir}/systemtap/stap-stop-server %{_libexecdir}/systemtap/stap-gen-cert %{_libexecdir}/systemtap/stap-sign-module %{_libexecdir}/systemtap/stap-authorize-cert %{_libexecdir}/systemtap/stap-env %{_mandir}/man7/error* %{_mandir}/man7/stappaths.7* %{_mandir}/man7/warning* %{_mandir}/man8/stap-server.8* %if %{with_systemd} %{_unitdir}/stap-server.service %{_tmpfilesdir}/stap-server.conf %else %{_sysconfdir}/rc.d/init.d/stap-server %dir %{_sysconfdir}/stap-server/conf.d %config(noreplace) %{_sysconfdir}/sysconfig/stap-server %endif %config(noreplace) %{_sysconfdir}/logrotate.d/stap-server %dir %{_sysconfdir}/stap-server %dir %attr(0750,stap-server,stap-server) %{_localstatedir}/lib/stap-server %dir %attr(0700,stap-server,stap-server) %{_localstatedir}/lib/stap-server/.systemtap %dir %attr(0755,stap-server,stap-server) %{_localstatedir}/log/stap-server %ghost %config(noreplace) %attr(0644,stap-server,stap-server) %{_localstatedir}/log/stap-server/log %ghost %attr(0755,stap-server,stap-server) %{_localstatedir}/run/stap-server %doc initscript/README.stap-server %doc README README.unprivileged AUTHORS NEWS COPYING %files devel -f systemtap.lang %{_bindir}/stap %{_bindir}/stap-prep %{_bindir}/stap-report %dir %{_datadir}/systemtap %{_datadir}/systemtap/runtime %{_datadir}/systemtap/tapset %{_mandir}/man1/stap.1* %{_mandir}/man1/stap-prep.1* %{_mandir}/man1/stap-report.1* %{_mandir}/man7/error* %{_mandir}/man7/stappaths.7* %{_mandir}/man7/warning* %doc README README.unprivileged AUTHORS NEWS COPYING %if %{with_java} %dir %{_libexecdir}/systemtap %{_libexecdir}/systemtap/libHelperSDT_*.so %endif %if %{with_bundled_elfutils} %dir %{_libdir}/systemtap %{_libdir}/systemtap/lib*.so* %endif %if %{with_emacsvim} %{_emacs_sitelispdir}/*.el* %{_emacs_sitestartdir}/systemtap-init.el %{_datadir}/vim/vimfiles/*/*.vim %endif %files runtime -f systemtap.lang %defattr(-,root,root) %attr(4110,root,stapusr) %{_bindir}/staprun %{_bindir}/stapsh %{_bindir}/stap-merge %{_bindir}/stap-report %if %{with_dyninst} %{_bindir}/stapdyn %endif %dir %{_libexecdir}/systemtap %{_libexecdir}/systemtap/stapio %{_libexecdir}/systemtap/stap-authorize-cert %if %{with_crash} %dir %{_libdir}/systemtap %{_libdir}/systemtap/staplog.so* %endif %{_mandir}/man1/stap-report.1* %{_mandir}/man7/error* %{_mandir}/man7/stappaths.7* %{_mandir}/man7/warning* %{_mandir}/man8/stapsh.8* %{_mandir}/man8/staprun.8* %if %{with_dyninst} %{_mandir}/man8/stapdyn.8* %endif %doc README README.security AUTHORS NEWS COPYING %files client -f systemtap.lang %defattr(-,root,root) %doc README README.unprivileged AUTHORS NEWS COPYING examples %if %{with_docs} %doc docs.installed/*.pdf %doc docs.installed/tapsets/*.html %if %{with_publican} %doc docs.installed/SystemTap_Beginners_Guide %endif %endif %{_bindir}/stap %{_bindir}/stap-prep %{_bindir}/stap-report %{_mandir}/man1/stap.1* %{_mandir}/man1/stap-prep.1* %{_mandir}/man1/stap-merge.1* %{_mandir}/man1/stap-report.1* %{_mandir}/man3/* %{_mandir}/man7/error* %{_mandir}/man7/stappaths.7* %{_mandir}/man7/warning* %dir %{_datadir}/systemtap %{_datadir}/systemtap/tapset %files initscript %defattr(-,root,root) %{_sysconfdir}/rc.d/init.d/systemtap %dir %{_sysconfdir}/systemtap %dir %{_sysconfdir}/systemtap/conf.d %dir %{_sysconfdir}/systemtap/script.d %config(noreplace) %{_sysconfdir}/systemtap/config %dir %{_localstatedir}/cache/systemtap %ghost %{_localstatedir}/run/systemtap %doc initscript/README.systemtap %files sdt-devel %defattr(-,root,root) %{_bindir}/dtrace %{_includedir}/sys/sdt.h %{_includedir}/sys/sdt-config.h %{_mandir}/man1/dtrace.1* %doc README AUTHORS NEWS COPYING %files testsuite %defattr(-,root,root) %dir %{_datadir}/systemtap %{_datadir}/systemtap/testsuite %if %{with_java} %files runtime-java %dir %{_libexecdir}/systemtap %{_libexecdir}/systemtap/libHelperSDT_*.so %{_libexecdir}/systemtap/HelperSDT.jar %{_libexecdir}/systemtap/stapbm %endif # ------------------------------------------------------------------------ %changelog * Thu May 16 2013 Frank Ch. Eigler - 2.2.1-1 - Upstream release. * Tue May 14 2013 Frank Ch. Eigler - 2.2-1 - Upstream release. * Wed Feb 13 2013 Serguei Makarov - 2.1-1 - Upstream release. * Tue Oct 09 2012 Josh Stone - 2.0-1 - Upstream release. * Fri Jul 13 2012 Peter Robinson - Fix ifarch statement - use file based requires for glibc-devel on x86_64 so that we work in koji * Sun Jun 17 2012 Frank Ch. Eigler - 1.8-1 - Upstream release. * Wed Feb 01 2012 Frank Ch. Eigler - 1.7-1 - Upstream release. * Fri Jan 13 2012 David Smith - 1.6-2 - Fixed /bin/mktemp require. * Mon Jul 25 2011 Stan Cox - 1.6-1 - Upstream release. * Mon May 23 2011 Stan Cox - 1.5-1 - Upstream release. * Mon Jan 17 2011 Frank Ch. Eigler - 1.4-1 - Upstream release. * Wed Jul 21 2010 Josh Stone - 1.3-1 - Upstream release. * Mon Mar 22 2010 Frank Ch. Eigler - 1.2-1 - Upstream release. * Mon Dec 21 2009 David Smith - 1.1-1 - Upstream release. * Tue Sep 22 2009 Josh Stone - 1.0-1 - Upstream release. * Tue Aug 4 2009 Josh Stone - 0.9.9-1 - Upstream release. * Thu Jun 11 2009 Josh Stone - 0.9.8-1 - Upstream release. * Thu Apr 23 2009 Josh Stone - 0.9.7-1 - Upstream release. * Fri Mar 27 2009 Josh Stone - 0.9.5-1 - Upstream release. * Wed Mar 18 2009 Will Cohen - 0.9-2 - Add location of man pages. * Tue Feb 17 2009 Frank Ch. Eigler - 0.9-1 - Upstream release. * Thu Nov 13 2008 Frank Ch. Eigler - 0.8-1 - Upstream release. * Tue Jul 15 2008 Frank Ch. Eigler - 0.7-1 - Upstream release. * Fri Feb 1 2008 Frank Ch. Eigler - 0.6.1-3 - Add zlib-devel to buildreq; missing from crash-devel - Process testsuite .stp files for #!stap->#!/usr/bin/stap * Fri Jan 18 2008 Frank Ch. Eigler - 0.6.1-1 - Add crash-devel buildreq to build staplog.so crash(8) module. - Many robustness & functionality improvements: * Wed Dec 5 2007 Will Cohen - 0.6-2 - Correct Source to point to location contain code. * Thu Aug 9 2007 David Smith - 0.6-1 - Bumped version, added libcap-devel BuildRequires. * Wed Jul 11 2007 Will Cohen - 0.5.14-2 - Fix Requires and BuildRequires for sqlite. * Mon Jul 2 2007 Frank Ch. Eigler - 0.5.14-1 - Many robustness improvements: 1117, 1134, 1305, 1307, 1570, 1806, 2033, 2116, 2224, 2339, 2341, 2406, 2426, 2438, 2583, 3037, 3261, 3282, 3331, 3428 3519, 3545, 3625, 3648, 3880, 3888, 3911, 3952, 3965, 4066, 4071, 4075, 4078, 4081, 4096, 4119, 4122, 4127, 4146, 4171, 4179, 4183, 4221, 4224, 4254, 4281, 4319, 4323, 4326, 4329, 4332, 4337, 4415, 4432, 4444, 4445, 4458, 4467, 4470, 4471, 4518, 4567, 4570, 4579, 4589, 4609, 4664 * Mon Mar 26 2007 Frank Ch. Eigler - 0.5.13-1 - An emergency / preliminary refresh, mainly for compatibility with 2.6.21-pre kernels. * Mon Jan 1 2007 Frank Ch. Eigler - 0.5.12-1 - Many changes, see NEWS file. * Tue Sep 26 2006 David Smith - 0.5.10-1 - Added 'systemtap-runtime' subpackage. * Wed Jul 19 2006 Roland McGrath - 0.5.9-1 - PRs 2669, 2913 * Fri Jun 16 2006 Roland McGrath - 0.5.8-1 - PRs 2627, 2520, 2228, 2645 * Fri May 5 2006 Frank Ch. Eigler - 0.5.7-1 - PRs 2511 2453 2307 1813 1944 2497 2538 2476 2568 1341 2058 2220 2437 1326 2014 2599 2427 2438 2465 1930 2149 2610 2293 2634 2506 2433 * Tue Apr 4 2006 Roland McGrath - 0.5.5-1 - Many changes, affected PRs include: 2068, 2293, 1989, 2334, 1304, 2390, 2425, 953. * Wed Feb 1 2006 Frank Ch. Eigler - 0.5.4-1 - PRs 1916, 2205, 2142, 2060, 1379 * Mon Jan 16 2006 Roland McGrath - 0.5.3-1 - Many changes, affected PRs include: 2056, 1144, 1379, 2057, 2060, 1972, 2140, 2148 * Mon Dec 19 2005 Roland McGrath - 0.5.2-1 - Fixed build with gcc 4.1, various tapset changes. * Wed Dec 7 2005 Roland McGrath - 0.5.1-1 - elfutils update, build changes * Fri Dec 02 2005 Frank Ch. Eigler - 0.5-1 - Many fixes and improvements: 1425, 1536, 1505, 1380, 1329, 1828, 1271, 1339, 1340, 1345, 1837, 1917, 1903, 1336, 1868, 1594, 1564, 1276, 1295 * Mon Oct 31 2005 Roland McGrath - 0.4.2-1 - Many fixes and improvements: PRs 1344, 1260, 1330, 1295, 1311, 1368, 1182, 1131, 1332, 1366, 1456, 1271, 1338, 1482, 1477, 1194. * Wed Sep 14 2005 Roland McGrath - 0.4.1-1 - Many fixes and improvements since 0.2.2; relevant PRs include: 1122, 1134, 1155, 1172, 1174, 1175, 1180, 1186, 1187, 1191, 1193, 1195, 1197, 1205, 1206, 1209, 1213, 1244, 1257, 1258, 1260, 1265, 1268, 1270, 1289, 1292, 1306, 1335, 1257 * Wed Sep 7 2005 Frank Ch. Eigler - Bump version. * Tue Aug 16 2005 Frank Ch. Eigler - Bump version. * Wed Aug 3 2005 Martin Hunt - 0.2.2-1 - Add directory /var/cache/systemtap - Add stp_check to /usr/libexec/systemtap * Wed Aug 3 2005 Roland McGrath - 0.2.1-1 - New version 0.2.1, various fixes. * Fri Jul 29 2005 Roland McGrath - 0.2-1 - New version 0.2, requires elfutils 0.111 * Mon Jul 25 2005 Roland McGrath - Clean up spec file, build bundled elfutils. * Thu Jul 21 2005 Martin Hunt - Set Version to use version from autoconf. - Fix up some of the path names. - Add Requires and BuildRequires. * Tue Jul 19 2005 Will Cohen - Initial creation of RPM. systemtap-2.3/tapset-been.cxx000066400000000000000000000167541217430427200163610ustar00rootroot00000000000000// tapset for begin/end/error/never // Copyright (C) 2005-2011 Red Hat Inc. // Copyright (C) 2005-2007 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "session.h" #include "tapsets.h" #include "translate.h" #include "util.h" #include #include using namespace std; using namespace __gnu_cxx; static const string TOK_BEGIN("begin"); static const string TOK_END("end"); static const string TOK_ERROR("error"); static const string TOK_NEVER("never"); // ------------------------------------------------------------------------ // begin/end/error probes are run right during registration / deregistration // ------------------------------------------------------------------------ enum be_t { BEGIN, END, ERROR }; struct be_derived_probe: public derived_probe { be_t type; int64_t priority; be_derived_probe (probe* p, probe_point* l, be_t t, int64_t pr): derived_probe (p, l), type (t), priority (pr) {} void join_group (systemtap_session& s); static inline bool comp(be_derived_probe const *a, be_derived_probe const *b) { // This allows the BEGIN/END/ERROR probes to intermingle. // But that's OK - they're always treversed with a nested // "if (type==FOO)" conditional. return a->priority < b->priority; } // No assertion need be emitted, since these probes are allowed for // unprivileged users. void emit_privilege_assertion (translator_output*) {} void print_dupe_stamp(ostream& o) { print_dupe_stamp_unprivileged (o); } bool needs_global_locks () { return false; } // begin/end probes don't need locks around global variables, since // they aren't run concurrently with any other probes }; struct be_derived_probe_group: public generic_dpg { public: void emit_module_decls (systemtap_session& s); void emit_module_init (systemtap_session& s); void emit_module_exit (systemtap_session& s); }; struct be_builder: public derived_probe_builder { be_t type; be_builder(be_t t) : type(t) {} virtual void build(systemtap_session &, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results) { int64_t priority; if ((type == BEGIN && !get_param(parameters, TOK_BEGIN, priority)) || (type == END && !get_param(parameters, TOK_END, priority)) || (type == ERROR && !get_param(parameters, TOK_ERROR, priority))) priority = 0; finished_results.push_back (new be_derived_probe(base, location, type, priority)); } }; void be_derived_probe::join_group (systemtap_session& s) { if (! s.be_derived_probes) s.be_derived_probes = new be_derived_probe_group (); s.be_derived_probes->enroll (this); } void be_derived_probe_group::emit_module_decls (systemtap_session& s) { if (probes.empty()) return; map states; states[BEGIN] = "STAP_SESSION_STARTING"; states[END] = "STAP_SESSION_STOPPING"; states[ERROR] = "STAP_SESSION_ERROR"; s.op->newline() << "/* ---- begin/end/error probes ---- */"; // NB: We emit the table in sorted order here, so we don't have to // store the priority numbers as integers and sort at run time. sort(probes.begin(), probes.end(), be_derived_probe::comp); s.op->newline() << "static struct stap_be_probe {"; s.op->newline(1) << "const struct stap_probe * const probe;"; s.op->newline() << "int state, type;"; s.op->newline(-1) << "} stap_be_probes[] = {"; s.op->indent(1); for (unsigned i=0; i < probes.size(); i++) { s.op->newline () << "{"; s.op->line() << " .probe=" << common_probe_init (probes[i]) << ","; s.op->line() << " .state=" << states[probes[i]->type] << ","; s.op->line() << " .type=" << probes[i]->type; s.op->line() << " },"; } s.op->newline(-1) << "};"; s.op->newline() << "static void enter_be_probe (struct stap_be_probe *stp) {"; s.op->indent(1); common_probe_entryfn_prologue (s, "stp->state", "stp->probe", "stp_probe_type_been", false); s.op->newline() << "(*stp->probe->ph) (c);"; common_probe_entryfn_epilogue (s, false); s.op->newline(-1) << "}"; } void be_derived_probe_group::emit_module_init (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {"; s.op->newline(1) << "struct stap_be_probe* stp = & stap_be_probes [i];"; s.op->newline() << "if (stp->type == " << BEGIN << ")"; s.op->newline(1) << "enter_be_probe (stp); /* rc = 0 */"; // NB: begin probes that cause errors do not constitute registration // failures. An error message will probably get printed and if // MAXERRORS was left at 1, we'll get an stp_exit. The // error-handling probes will be run during the ordinary // unregistration phase. s.op->newline(-2) << "}"; } void be_derived_probe_group::emit_module_exit (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {"; s.op->newline(1) << "struct stap_be_probe* stp = & stap_be_probes [i];"; s.op->newline() << "if (stp->type == " << END << ")"; s.op->newline(1) << "enter_be_probe (stp);"; s.op->newline(-2) << "}"; s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {"; s.op->newline(1) << "struct stap_be_probe* stp = & stap_be_probes [i];"; s.op->newline() << "if (stp->type == " << ERROR << ")"; s.op->newline(1) << "enter_be_probe (stp);"; s.op->newline(-2) << "}"; } // ------------------------------------------------------------------------ // never probes are never run // ------------------------------------------------------------------------ struct never_derived_probe: public derived_probe { never_derived_probe (probe* p, probe_point* l): derived_probe (p, l) {} void join_group (systemtap_session&) { /* thus no probe_group */ } void emit_privilege_assertion (translator_output*) {} void print_dupe_stamp(ostream& o) { print_dupe_stamp_unprivileged (o); } }; struct never_builder: public derived_probe_builder { never_builder() {} virtual void build(systemtap_session &, probe * base, probe_point * location, literal_map_t const &, vector & finished_results) { finished_results.push_back(new never_derived_probe(base, location)); } }; // ------------------------------------------------------------------------ // unified registration for begin/end/error/never // ------------------------------------------------------------------------ void register_tapset_been(systemtap_session& s) { match_node* root = s.pattern_root; root->bind(TOK_BEGIN) ->bind_privilege(pr_all) ->bind(new be_builder(BEGIN)); root->bind_num(TOK_BEGIN) ->bind_privilege(pr_all) ->bind(new be_builder(BEGIN)); root->bind(TOK_END) ->bind_privilege(pr_all) ->bind(new be_builder(END)); root->bind_num(TOK_END) ->bind_privilege(pr_all) ->bind(new be_builder(END)); root->bind(TOK_ERROR) ->bind_privilege(pr_all) ->bind(new be_builder(ERROR)); root->bind_num(TOK_ERROR) ->bind_privilege(pr_all) ->bind(new be_builder(ERROR)); root->bind(TOK_NEVER) ->bind_privilege(pr_all) ->bind(new never_builder()); } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/tapset-dynprobe.cxx000066400000000000000000000144341217430427200172630ustar00rootroot00000000000000// Synthetic derived probe group that enables merging probes from // difference derived probe groups for dyninst. // // Copyright (C) 2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "session.h" #include "tapsets.h" #include "tapset-dynprobe.h" #include "translate.h" #include #include using namespace std; using namespace __gnu_cxx; // ------------------------------------------------------------------------ // dynprobe derived 'probes': These don't really exist. The purpose of // the dynprobe_derived_probe_group is allow multiple // *_derived_probe_group classes to output only one set of // 'stapdu_target'/'stapdu_probe' arrays. This class also includes // "dyninst/uprobes.c" only once and in the correct place. // ------------------------------------------------------------------------ struct dynprobe_derived_probe: public derived_probe { // Dummy constructor for gcc 3.4 compatibility dynprobe_derived_probe (): derived_probe (0, 0) { assert(0); } }; struct dynprobe_info { bool has_path; const Dwarf_Addr offset; const Dwarf_Addr semaphore_addr; const string flags_string; const string probe_init; dynprobe_info(bool hp, const Dwarf_Addr o, const Dwarf_Addr sa, const string fs, const string pi): has_path(hp), offset(o), semaphore_addr(sa), flags_string(fs), probe_init(pi) { } }; struct dynprobe_derived_probe_group: public generic_dpg { private: map > info_by_path; typedef map >::iterator i_b_path_iterator; map > info_by_pid; typedef map >::iterator i_b_pid_iterator; void emit_info(systemtap_session& s, unsigned tgt_idx, dynprobe_info *info); public: void emit_module_decls (systemtap_session& s); void emit_module_init (systemtap_session& ) { } void emit_module_post_init (systemtap_session& ) { } void emit_module_exit (systemtap_session& ) { } void add(const string& path, const Dwarf_Addr offset, const Dwarf_Addr semaphore_addr, const string& flags_string, const string& probe_init); }; void dynprobe_derived_probe_group::add(const string& path, const Dwarf_Addr offset, const Dwarf_Addr semaphore_addr, const string& flags_string, const string& probe_init) { struct dynprobe_info *info = new dynprobe_info(!path.empty(), offset, semaphore_addr, flags_string, probe_init); if (!path.empty()) info_by_path[path].push_back(info); else info_by_pid[offset].push_back(info); } void dynprobe_derived_probe_group::emit_info(systemtap_session& s, unsigned tgt_idx, dynprobe_info *info) { s.op->newline() << "{"; s.op->line() << " .target=" << tgt_idx << ","; // We have to force path vs. pid probes into // stapdu_target/stapdu_probe. So, here's how we'll do it. // // For path probes, stapdu_target will hold the path, and the // stapdu_probe with the correct index will point to it. // // For pid probes, stapdu_target will have an empty path, and the // 'offset' field of stapdu_probe will really be the pid. if (info->has_path) s.op->line() << " .offset=" << lex_cast_hex(info->offset) << "ULL,"; else s.op->line() << " .offset=" << info->offset << "ULL/*pid*/,"; if (info->semaphore_addr) s.op->line() << " .semaphore=" << lex_cast_hex(info->semaphore_addr) << "ULL,"; s.op->line() << " .flags=" << info->flags_string << ","; s.op->line() << " .probe=" << info->probe_init << ","; s.op->line() << " },"; } void dynprobe_derived_probe_group::emit_module_decls (systemtap_session& s) { if (! s.runtime_usermode_p()) return; s.op->newline() << "#include \"dyninst/uprobes.h\""; s.op->newline() << "static const struct stapdu_target stapdu_targets[] = {"; s.op->indent(1); for (i_b_path_iterator it = info_by_path.begin(); it != info_by_path.end(); it++) { s.op->newline() << "{"; s.op->line() << " .path=" << lex_cast_qstring(it->first) << ","; s.op->line() << " },"; } if (! info_by_pid.empty()) { s.op->newline() << "{"; s.op->line() << " .path=NULL,"; s.op->line() << " },"; } s.op->newline(-1) << "};"; s.op->assert_0_indent(); s.op->newline() << "static struct stapdu_probe stapdu_probes[] = {"; s.op->indent(1); unsigned tgt_idx = 0; for (i_b_path_iterator it = info_by_path.begin(); it != info_by_path.end(); it++, tgt_idx++) { for (unsigned i = 0; i < it->second.size(); i++) { dynprobe_info *info = it->second[i]; emit_info(s, tgt_idx, info); } } if (! info_by_pid.empty()) { for (i_b_pid_iterator it = info_by_pid.begin(); it != info_by_pid.end(); it++) { for (unsigned i = 0; i < it->second.size(); i++) { dynprobe_info *info = it->second[i]; emit_info(s, tgt_idx, info); } } } s.op->newline(-1) << "};"; s.op->assert_0_indent(); s.op->newline() << "#include \"dyninst/uprobes.c\""; } // Declare that dynprobes are needed in this session void enable_dynprobes(systemtap_session& s) { if (! s.dynprobe_derived_probes) s.dynprobe_derived_probes = new dynprobe_derived_probe_group(); } void dynprobe_add_uprobe(systemtap_session& s, const string& path, const Dwarf_Addr offset, const Dwarf_Addr semaphore_addr, const string flags_string, const string probe_init) { enable_dynprobes(s); s.dynprobe_derived_probes->add(path, offset, semaphore_addr, flags_string, probe_init); } void dynprobe_add_utrace_path(systemtap_session& s, const std::string& path, const std::string flags_string, const std::string probe_init) { enable_dynprobes(s); s.dynprobe_derived_probes->add(path, 0, 0, flags_string, probe_init); } void dynprobe_add_utrace_pid(systemtap_session& s, const Dwarf_Addr pid, const std::string flags_string, const std::string probe_init) { enable_dynprobes(s); // Notice we're passing the pid as the offset. Stapdyn is expecting // this when the path is empty. s.dynprobe_derived_probes->add("", pid, 0, flags_string, probe_init); } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/tapset-dynprobe.h000066400000000000000000000023141217430427200167020ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef TAPSET_DYNPROBE_H #define TAPSET_DYNPROBE_H // Declare that dynprobes are needed in this session void enable_dynprobes(systemtap_session& s); void dynprobe_add_uprobe(systemtap_session& s, const std::string& path, const Dwarf_Addr offset, const Dwarf_Addr semaphore_addr, const std::string flags_string, const std::string probe_init); void dynprobe_add_utrace_path(systemtap_session& s, const std::string& path, const std::string flags_string, const std::string probe_init); void dynprobe_add_utrace_pid(systemtap_session& s, const Dwarf_Addr pid, const std::string flags_string, const std::string probe_init); void dynprobe_add(systemtap_session& s, const std::string& path, const Dwarf_Addr offset, const Dwarf_Addr semaphore_addr, const std::string flags_string, const std::string probe_init); #endif // TAPSET_DYNPROBE_H /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/tapset-itrace.cxx000066400000000000000000000220401217430427200167000ustar00rootroot00000000000000// tapset for timers // Copyright (C) 2005-2013 Red Hat Inc. // Copyright (C) 2005-2007 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "session.h" #include "tapsets.h" #include "task_finder.h" #include "translate.h" #include "util.h" #include #include using namespace std; using namespace __gnu_cxx; static const string TOK_PROCESS("process"); static const string TOK_INSN("insn"); static const string TOK_BLOCK("block"); // ------------------------------------------------------------------------ // itrace user-space probes // ------------------------------------------------------------------------ struct itrace_derived_probe: public derived_probe { bool has_path; string path; int64_t pid; int single_step; itrace_derived_probe (systemtap_session &s, probe* p, probe_point* l, bool hp, string &pn, int64_t pd, int ss ); void join_group (systemtap_session& s); }; struct itrace_derived_probe_group: public generic_dpg { private: map > probes_by_path; typedef map >::iterator p_b_path_iterator; map > probes_by_pid; typedef map >::iterator p_b_pid_iterator; unsigned num_probes; void emit_probe_decl (systemtap_session& s, itrace_derived_probe *p); public: itrace_derived_probe_group(): num_probes(0) { } void enroll (itrace_derived_probe* probe); void emit_module_decls (systemtap_session& s); void emit_module_init (systemtap_session& s); void emit_module_exit (systemtap_session& s); }; itrace_derived_probe::itrace_derived_probe (systemtap_session &s, probe* p, probe_point* l, bool hp, string &pn, int64_t pd, int ss ): derived_probe(p, l), has_path(hp), path(pn), pid(pd), single_step(ss) { if (s.kernel_config["CONFIG_UTRACE"] != string("y")) throw semantic_error (_("process probes not available without kernel CONFIG_UTRACE")); } void itrace_derived_probe::join_group (systemtap_session& s) { if (! s.itrace_derived_probes) s.itrace_derived_probes = new itrace_derived_probe_group (); s.itrace_derived_probes->enroll (this); enable_task_finder(s); } struct itrace_builder: public derived_probe_builder { itrace_builder() {} virtual void build(systemtap_session & sess, probe * base, probe_point * location, std::map const & parameters, vector & finished_results) { string path, path_tgt; int64_t pid = 0; int single_step; bool has_path = get_param (parameters, TOK_PROCESS, path); bool has_pid = get_param (parameters, TOK_PROCESS, pid); // XXX: PR 6445 needs !has_path && !has_pid support assert (has_path || has_pid); single_step = ! has_null_param (parameters, TOK_BLOCK); // If we have a path, we need to validate it. if (has_path) { path = find_executable (path, sess.sysroot, sess.sysenv); sess.unwindsym_modules.insert (path); path_tgt = path_remove_sysroot(sess, path); } finished_results.push_back(new itrace_derived_probe(sess, base, location, has_path, path_tgt, pid, single_step )); } }; void itrace_derived_probe_group::enroll (itrace_derived_probe* p) { if (p->has_path) probes_by_path[p->path].push_back(p); else probes_by_pid[p->pid].push_back(p); num_probes++; // XXX: multiple exec probes (for instance) for the same path (or // pid) should all share a itrace report function, and have their // handlers executed sequentially. } void itrace_derived_probe_group::emit_probe_decl (systemtap_session& s, itrace_derived_probe *p) { s.op->newline() << "{"; s.op->line() << " .tgt={"; s.op->line() << " .purpose=\"itrace\","; if (p->has_path) { s.op->line() << " .procname=\"" << p->path << "\","; s.op->line() << " .pid=0,"; } else { s.op->line() << " .procname=NULL,"; s.op->line() << " .pid=" << p->pid << ","; } s.op->line() << " .callback=&_stp_itrace_probe_cb,"; s.op->line() << " },"; s.op->line() << " .probe=" << common_probe_init (p) << ","; s.op->line() << " .single_step=" << p->single_step << ","; s.op->line() << " },"; } void itrace_derived_probe_group::emit_module_decls (systemtap_session& s) { if (probes_by_path.empty() && probes_by_pid.empty()) return; s.op->newline(); s.op->newline() << "/* ---- itrace probes ---- */"; s.op->newline() << "struct stap_itrace_probe {"; s.op->indent(1); s.op->newline() << "struct stap_task_finder_target tgt;"; s.op->newline() << "const struct stap_probe * const probe;"; s.op->newline() << "int single_step;"; s.op->newline(-1) << "};"; s.op->newline() << "static void enter_itrace_probe(struct stap_itrace_probe *p, struct pt_regs *regs, void *data);"; s.op->newline() << "#include \"linux/itrace.c\""; // output routine to call itrace probe s.op->newline() << "static void enter_itrace_probe(struct stap_itrace_probe *p, struct pt_regs *regs, void *data) {"; s.op->indent(1); common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "p->probe", "stp_probe_type_itrace"); s.op->newline() << "c->uregs = regs;"; s.op->newline() << "c->user_mode_p = 1;"; // call probe function s.op->newline() << "(*p->probe->ph) (c);"; common_probe_entryfn_epilogue (s, true); s.op->newline() << "return;"; s.op->newline(-1) << "}"; // Output task finder callback routine that gets called for all // itrace probe types. s.op->newline() << "static int _stp_itrace_probe_cb(struct stap_task_finder_target *tgt, struct task_struct *tsk, int register_p, int process_p) {"; s.op->indent(1); s.op->newline() << "int rc = 0;"; s.op->newline() << "struct stap_itrace_probe *p = container_of(tgt, struct stap_itrace_probe, tgt);"; s.op->newline() << "if (register_p) "; s.op->indent(1); s.op->newline() << "rc = usr_itrace_init(p->single_step, tsk, p);"; s.op->newline(-1) << "else"; s.op->newline(1) << "remove_usr_itrace_info(find_itrace_info(tsk));"; s.op->newline(-1) << "return rc;"; s.op->newline(-1) << "}"; s.op->newline() << "static struct stap_itrace_probe stap_itrace_probes[] = {"; s.op->indent(1); // Set up 'process(PATH)' probes if (! probes_by_path.empty()) { for (p_b_path_iterator it = probes_by_path.begin(); it != probes_by_path.end(); it++) { for (unsigned i = 0; i < it->second.size(); i++) { itrace_derived_probe *p = it->second[i]; emit_probe_decl(s, p); } } } // Set up 'process(PID)' probes if (! probes_by_pid.empty()) { for (p_b_pid_iterator it = probes_by_pid.begin(); it != probes_by_pid.end(); it++) { for (unsigned i = 0; i < it->second.size(); i++) { itrace_derived_probe *p = it->second[i]; emit_probe_decl(s, p); } } } s.op->newline(-1) << "};"; } void itrace_derived_probe_group::emit_module_init (systemtap_session& s) { if (probes_by_path.empty() && probes_by_pid.empty()) return; s.op->newline(); s.op->newline() << "/* ---- itrace probes ---- */"; s.op->newline() << "for (i=0; i<" << num_probes << "; i++) {"; s.op->indent(1); s.op->newline() << "struct stap_itrace_probe *p = &stap_itrace_probes[i];"; // 'arch_has_single_step' needs to be defined for either single step mode // or branch mode. s.op->newline() << "if (!arch_has_single_step()) {"; s.op->indent(1); s.op->newline() << "_stp_error (\"insn probe init: arch does not support step mode\");"; s.op->newline() << "rc = -EPERM;"; s.op->newline() << "break;"; s.op->newline(-1) << "}"; s.op->newline() << "if (!p->single_step && !arch_has_block_step()) {"; s.op->indent(1); s.op->newline() << "_stp_error (\"insn probe init: arch does not support block step mode\");"; s.op->newline() << "rc = -EPERM;"; s.op->newline() << "break;"; s.op->newline(-1) << "}"; s.op->newline() << "rc = stap_register_task_finder_target(&p->tgt);"; s.op->newline(-1) << "}"; } void itrace_derived_probe_group::emit_module_exit (systemtap_session& s) { if (probes_by_path.empty() && probes_by_pid.empty()) return; s.op->newline(); s.op->newline() << "/* ---- itrace probes ---- */"; s.op->newline() << "cleanup_usr_itrace();"; } void register_tapset_itrace(systemtap_session& s) { match_node* root = s.pattern_root; derived_probe_builder *builder = new itrace_builder(); root->bind_str(TOK_PROCESS)->bind(TOK_INSN) ->bind(builder); root->bind_num(TOK_PROCESS)->bind(TOK_INSN) ->bind(builder); root->bind_str(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK) ->bind(builder); root->bind_num(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK) ->bind(builder); } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/tapset-mark.cxx000066400000000000000000000457001217430427200163730ustar00rootroot00000000000000// tapset for kernel static markers // Copyright (C) 2005-2010 Red Hat Inc. // Copyright (C) 2005-2007 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "session.h" #include "tapsets.h" #include "translate.h" #include "util.h" #include #include #include #include extern "C" { #include } using namespace std; using namespace __gnu_cxx; static const string TOK_KERNEL("kernel"); static const string TOK_MARK("mark"); static const string TOK_FORMAT("format"); // ------------------------------------------------------------------------ // statically inserted macro-based derived probes // ------------------------------------------------------------------------ struct mark_arg { bool str; bool isptr; string c_type; exp_type stp_type; }; struct mark_derived_probe: public derived_probe { mark_derived_probe (systemtap_session &s, const string& probe_name, const string& probe_format, probe* base_probe, probe_point* location); systemtap_session& sess; string probe_name, probe_format; vector mark_args; bool target_symbol_seen; void join_group (systemtap_session& s); void print_dupe_stamp (ostream& o); void initialize_probe_context_vars (translator_output* o); void getargs (std::list &arg_set) const; void parse_probe_format (); }; struct mark_derived_probe_group: public generic_dpg { public: void emit_module_decls (systemtap_session& s); void emit_module_init (systemtap_session& s); void emit_module_exit (systemtap_session& s); }; struct mark_var_expanding_visitor: public var_expanding_visitor { mark_var_expanding_visitor(systemtap_session& s, const string& pn, vector &mark_args): sess (s), probe_name (pn), mark_args (mark_args), target_symbol_seen (false) {} systemtap_session& sess; string probe_name; vector &mark_args; bool target_symbol_seen; void visit_target_symbol (target_symbol* e); void visit_target_symbol_arg (target_symbol* e); void visit_target_symbol_context (target_symbol* e); }; void mark_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) { string argnum_s = e->name.substr(4,e->name.length()-4); int argnum = atoi (argnum_s.c_str()); if (argnum < 1 || argnum > (int)mark_args.size()) throw semantic_error (_("invalid marker argument number"), e->tok); if (is_active_lvalue (e)) throw semantic_error(_("write to marker parameter not permitted"), e->tok); e->assert_no_components("marker"); // Remember that we've seen a target variable. target_symbol_seen = true; symbol* sym = new symbol; sym->tok = e->tok; sym->name = "__mark_arg" + lex_cast(argnum); provide (sym); } void mark_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) { string sname = e->name; if (is_active_lvalue (e)) throw semantic_error(_F("write to marker '%s' not permitted", sname.c_str()), e->tok); e->assert_no_components("marker"); if (e->name == "$format" || e->name == "$name") { // Synthesize an embedded expression. embedded_expr *expr = new embedded_expr; expr->tok = e->tok; if (e->name == "$format") expr->code = string("/* string */ /* pure */ ") + string("c->ips.kmark.marker_format ? c->ips.kmark.marker_format : \"\""); else expr->code = string("/* string */ /* pure */ ") + string("c->ips.kmark.marker_name ? c->ips.kmark.marker_name : \"\""); provide (expr); } else if (e->name == "$$vars" || e->name == "$$parms") { //copy from tracepoint token* pf_tok = new token(*e->tok); pf_tok->content = "sprintf"; print_format* pf = print_format::create(pf_tok); for (unsigned i = 0; i < mark_args.size(); ++i) { if (i > 0) pf->raw_components += " "; pf->raw_components += "$arg" + lex_cast(i+1); target_symbol *tsym = new target_symbol; tsym->tok = e->tok; tsym->name = "$arg" + lex_cast(i+1); tsym->saved_conversion_error = 0; expression *texp = require (tsym); //same treatment as tracepoint assert (!tsym->saved_conversion_error); switch (mark_args[i]->stp_type) { case pe_long: pf->raw_components += mark_args[i]->isptr ? "=%p" : "=%#x"; break; case pe_string: pf->raw_components += "=%s"; break; default: pf->raw_components += "=%#x"; break; } pf->args.push_back(texp); } pf->components = print_format::string_to_components(pf->raw_components); provide (pf); } } void mark_var_expanding_visitor::visit_target_symbol (target_symbol* e) { assert(e->name.size() > 0 && e->name[0] == '$'); try { if (e->addressof) throw semantic_error(_("cannot take address of marker variable"), e->tok); if (startswith(e->name, "$arg")) visit_target_symbol_arg (e); else if (e->name == "$format" || e->name == "$name" || e->name == "$$parms" || e->name == "$$vars") visit_target_symbol_context (e); else throw semantic_error (_("invalid target symbol for marker, $argN, $name, $format, $$parms or $$vars expected"), e->tok); } catch (const semantic_error &er) { e->chain (er); provide (e); } } mark_derived_probe::mark_derived_probe (systemtap_session &s, const string& p_n, const string& p_f, probe* base, probe_point* loc): derived_probe (base, loc, true /* .components soon rewritten */), sess (s), probe_name (p_n), probe_format (p_f), target_symbol_seen (false) { // create synthetic probe point name; preserve condition vector comps; comps.push_back (new probe_point::component (TOK_KERNEL)); comps.push_back (new probe_point::component (TOK_MARK, new literal_string (probe_name))); comps.push_back (new probe_point::component (TOK_FORMAT, new literal_string (probe_format))); this->sole_location()->components = comps; // expand the marker format parse_probe_format(); // Now expand the local variables in the probe body mark_var_expanding_visitor v (sess, name, mark_args); v.replace (this->body); target_symbol_seen = v.target_symbol_seen; if (target_symbol_seen) for (unsigned i = 0; i < mark_args.size(); ++i) { vardecl* v = new vardecl; v->name = "__mark_arg" + lex_cast(i+1); v->tok = this->tok; v->set_arity(0, this->tok); v->type = mark_args[i]->stp_type; v->synthetic = true; this->locals.push_back (v); } if (sess.verbose > 2) clog << "marker-based " << name << " mark=" << probe_name << " fmt='" << probe_format << "'" << endl; } static int skip_atoi(const char **s) { int i = 0; while (isdigit(**s)) i = i * 10 + *((*s)++) - '0'; return i; } void mark_derived_probe::parse_probe_format() { const char *fmt = probe_format.c_str(); int qualifier; // 'h', 'l', or 'L' for integer fields mark_arg *arg; for (; *fmt ; ++fmt) { if (*fmt != '%') { /* Skip text */ continue; } repeat: ++fmt; // skip conversion flags (if present) switch (*fmt) { case '-': case '+': case ' ': case '#': case '0': goto repeat; } // skip minimum field witdh (if present) if (isdigit(*fmt)) skip_atoi(&fmt); // skip precision (if present) if (*fmt == '.') { ++fmt; if (isdigit(*fmt)) skip_atoi(&fmt); } // get the conversion qualifier (if present) qualifier = -1; if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { qualifier = *fmt; ++fmt; if (qualifier == 'l' && *fmt == 'l') { qualifier = 'L'; ++fmt; } } // get the conversion type switch (*fmt) { case 'c': arg = new mark_arg; arg->str = false; arg->isptr = false; arg->c_type = "int"; arg->stp_type = pe_long; mark_args.push_back(arg); continue; case 's': arg = new mark_arg; arg->str = true; arg->isptr = false; arg->c_type = "char *"; arg->stp_type = pe_string; mark_args.push_back(arg); continue; case 'p': arg = new mark_arg; arg->str = false; arg->isptr = true; // This should really be 'void *'. But, then we'll get a // compile error when we assign the void pointer to an // integer without a cast. So, we use 'long' instead, since // it should have the same size as 'void *'. arg->c_type = "long"; arg->stp_type = pe_long; mark_args.push_back(arg); continue; case '%': continue; case 'o': case 'X': case 'x': case 'd': case 'i': case 'u': // fall through... break; default: if (!*fmt) --fmt; continue; } arg = new mark_arg; arg->str = false; arg->isptr = false; arg->stp_type = pe_long; switch (qualifier) { case 'L': arg->c_type = "long long"; break; case 'l': arg->c_type = "long"; break; case 'h': arg->c_type = "short"; break; default: arg->c_type = "int"; break; } mark_args.push_back(arg); } } void mark_derived_probe::join_group (systemtap_session& s) { if (! s.mark_derived_probes) { s.mark_derived_probes = new mark_derived_probe_group (); // Make sure is included early. embeddedcode *ec = new embeddedcode; ec->tok = NULL; ec->code = string("#if ! defined(CONFIG_MARKERS)\n") + string("#error \"Need CONFIG_MARKERS!\"\n") + string("#endif\n") + string("#include \n"); s.embeds.push_back(ec); } s.mark_derived_probes->enroll (this); } void mark_derived_probe::print_dupe_stamp (ostream& o) { if (target_symbol_seen) for (unsigned i = 0; i < mark_args.size(); i++) o << mark_args[i]->c_type << " __mark_arg" << (i+1) << endl; } void mark_derived_probe::initialize_probe_context_vars (translator_output* o) { // If we haven't seen a target symbol for this probe, quit. if (! target_symbol_seen) return; bool deref_fault_needed = false; for (unsigned i = 0; i < mark_args.size(); i++) { string localname = "l->" + sess.up->c_localname("__mark_arg" + lex_cast(i+1)); switch (mark_args[i]->stp_type) { case pe_long: o->newline() << localname << " = va_arg(*c->ips.kmark.mark_va_list, " << mark_args[i]->c_type << ");"; break; case pe_string: // We're assuming that this is a kernel string (this code is // basically the guts of kernel_string), not a user string. o->newline() << "{ " << mark_args[i]->c_type << " tmp_str = va_arg(*c->ips.kmark.mark_va_list, " << mark_args[i]->c_type << ");"; o->newline() << "kderef_string (" << localname << ", tmp_str, MAXSTRINGLEN); }"; deref_fault_needed = true; break; default: throw semantic_error (_("cannot expand unknown type")); break; } } if (deref_fault_needed) // Need to report errors? o->newline() << "deref_fault: ;"; } void mark_derived_probe::getargs(std::list &arg_set) const { //PR11761: hard-coded the basic variables arg_set.push_back("$name:string"); arg_set.push_back("$format:string"); for (unsigned i = 0; i < mark_args.size(); i++) { string localname = "$arg" + lex_cast(i+1); switch (mark_args[i]->stp_type) { case pe_long: arg_set.push_back(localname+":long"); break; case pe_string: arg_set.push_back(localname+":string"); break; default: arg_set.push_back(localname+":unknown"); break; } } } void mark_derived_probe_group::emit_module_decls (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "/* ---- marker probes ---- */"; s.op->newline() << "static struct stap_marker_probe {"; s.op->newline(1) << "const char * const name;"; s.op->newline() << "const char * const format;"; s.op->newline() << "const struct stap_probe * const probe;"; s.op->newline(-1) << "} stap_marker_probes [" << probes.size() << "] = {"; s.op->indent(1); for (unsigned i=0; i < probes.size(); i++) { s.op->newline () << "{"; s.op->line() << " .name=" << lex_cast_qstring(probes[i]->probe_name) << ","; s.op->line() << " .format=" << lex_cast_qstring(probes[i]->probe_format) << ","; s.op->line() << " .probe=" << common_probe_init (probes[i]) << ","; s.op->line() << " },"; } s.op->newline(-1) << "};"; s.op->newline(); // Emit the marker callback function s.op->newline(); s.op->newline() << "static void enter_marker_probe (void *probe_data, void *call_data, const char *fmt, va_list *args) {"; s.op->newline(1) << "struct stap_marker_probe *smp = (struct stap_marker_probe *)probe_data;"; common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "smp->probe", "stp_probe_type_marker"); s.op->newline() << "c->ips.kmark.marker_name = smp->name;"; s.op->newline() << "c->ips.kmark.marker_format = smp->format;"; s.op->newline() << "c->ips.kmark.mark_va_list = args;"; s.op->newline() << "(*smp->probe->ph) (c);"; s.op->newline() << "c->ips.kmark.mark_va_list = NULL;"; common_probe_entryfn_epilogue (s, true); s.op->newline(-1) << "}"; return; } void mark_derived_probe_group::emit_module_init (systemtap_session &s) { if (probes.size () == 0) return; s.op->newline() << "/* init marker probes */"; s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {"; s.op->newline(1) << "struct stap_marker_probe *smp = &stap_marker_probes[i];"; s.op->newline() << "probe_point = smp->probe->pp;"; s.op->newline() << "rc = marker_probe_register(smp->name, smp->format, enter_marker_probe, smp);"; s.op->newline() << "if (rc) {"; s.op->newline(1) << "for (j=i-1; j>=0; j--) {"; // partial rollback s.op->newline(1) << "struct stap_marker_probe *smp2 = &stap_marker_probes[j];"; s.op->newline() << "marker_probe_unregister(smp2->name, enter_marker_probe, smp2);"; s.op->newline(-1) << "}"; s.op->newline() << "break;"; // don't attempt to register any more probes s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; // for loop } void mark_derived_probe_group::emit_module_exit (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "/* deregister marker probes */"; s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {"; s.op->newline(1) << "struct stap_marker_probe *smp = &stap_marker_probes[i];"; s.op->newline() << "marker_probe_unregister(smp->name, enter_marker_probe, smp);"; s.op->newline(-1) << "}"; // for loop } struct mark_builder: public derived_probe_builder { private: bool cache_initialized; typedef multimap mark_cache_t; typedef multimap::const_iterator mark_cache_const_iterator_t; typedef pair mark_cache_const_iterator_pair_t; mark_cache_t mark_cache; public: mark_builder(): cache_initialized(false) {} void build_no_more (systemtap_session &s) { if (! mark_cache.empty()) { if (s.verbose > 3) clog << _("mark_builder releasing cache") << endl; mark_cache.clear(); } } void build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results); }; void mark_builder::build(systemtap_session & sess, probe * base, probe_point *loc, literal_map_t const & parameters, vector & finished_results) { string mark_str_val; bool has_mark_str = get_param (parameters, TOK_MARK, mark_str_val); string mark_format_val; bool has_mark_format = get_param (parameters, TOK_FORMAT, mark_format_val); assert (has_mark_str); (void) has_mark_str; if (! cache_initialized) { cache_initialized = true; string module_markers_path = sess.kernel_build_tree + "/Module.markers"; ifstream module_markers; module_markers.open(module_markers_path.c_str(), ifstream::in); if (! module_markers) { if (sess.verbose>3) //TRANSLATORS: specific path cannot be opened clog << module_markers_path << _(" cannot be opened: ") << strerror(errno) << endl; return; } string name, module, format; do { module_markers >> name >> module; getline(module_markers, format); // trim leading whitespace string::size_type notwhite = format.find_first_not_of(" \t"); format.erase(0, notwhite); // If the format is empty, make sure we add back a space // character, which is what MARK_NOARGS expands to. if (format.length() == 0) format = " "; if (sess.verbose>3) clog << "'" << name << "' '" << module << "' '" << format << "'" << endl; if (mark_cache.count(name) > 0) { // If we have 2 markers with the same we've got 2 cases: // different format strings or duplicate format strings. // If an existing marker in the cache doesn't have the // same format string, add this marker. mark_cache_const_iterator_pair_t ret; mark_cache_const_iterator_t it; bool matching_format_string = false; ret = mark_cache.equal_range(name); for (it = ret.first; it != ret.second; ++it) { if (format == it->second) { matching_format_string = true; break; } } if (! matching_format_string) mark_cache.insert(pair(name, format)); } else mark_cache.insert(pair(name, format)); } while (! module_markers.eof()); module_markers.close(); } // Search marker list for matching markers for (mark_cache_const_iterator_t it = mark_cache.begin(); it != mark_cache.end(); it++) { // Below, "rc" has negative polarity: zero iff matching. int rc = fnmatch(mark_str_val.c_str(), it->first.c_str(), 0); if (! rc) { bool add_result = true; // Match format strings (if the user specified one) if (has_mark_format && fnmatch(mark_format_val.c_str(), it->second.c_str(), 0)) add_result = false; if (add_result) { derived_probe *dp = new mark_derived_probe (sess, it->first, it->second, base, loc); finished_results.push_back (dp); } } } } void register_tapset_mark(systemtap_session& s) { match_node* root = s.pattern_root; derived_probe_builder *builder = new mark_builder(); root = root->bind(TOK_KERNEL); root = root->bind_str(TOK_MARK); root->bind(builder); root->bind_str(TOK_FORMAT)->bind(builder); } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/tapset-method.cxx000066400000000000000000000341631217430427200167220ustar00rootroot00000000000000// Tapset for per-method based probes // Copyright (C) 2013 Red Hat Inc. // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "session.h" #include "tapsets.h" #include "translate.h" #include "util.h" #include "config.h" #include "unistd.h" #include "sys/wait.h" #include "sys/types.h" #include #include #include #include #include extern "C" { #include } using namespace std; using namespace __gnu_cxx; static const string TOK_CLASS ("class"); static const string TOK_METHOD ("method"); static const string TOK_PROCESS ("process"); static const string TOK_PROVIDER ("provider"); static const string TOK_MARK ("mark"); static const string TOK_JAVA ("java"); static const string TOK_RETURN ("return"); static const string TOK_BEGIN ("begin"); static const string TOK_END ("end"); static const string TOK_ERROR ("error"); /* Escape all double quotes with a backslash in the string s: */ string bmoption_escape (string s) { size_t n = 0; for (;;) { n = s.find('"', n); if (n == string::npos) break; s.insert(n, 1, '\\'); n++; } return s; } // -------------------------------------------------------------------------- struct java_builder: public derived_probe_builder { private: bool cache_initialized; typedef multimap java_cache_t; typedef multimap::const_iterator java_cache_const_iterator_t; typedef pair java_cache_const_iterator_pair_t; java_cache_t java_cache; public: java_builder (): cache_initialized (false) {} void build (systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results); bool has_null_param (literal_map_t const & params, string const & k); bool get_number_param (literal_map_t const & params, string const & k, int & v); bool get_param (std::map const & params, const std::string& key, std::string& value); std::string mark_param(int i); }; bool java_builder::has_null_param(literal_map_t const & params, string const & k) { return derived_probe_builder::has_null_param(params, k); } bool java_builder::get_number_param (literal_map_t const & params, string const & k, int & v) { int64_t value; bool present = derived_probe_builder::get_param (params, k, value); v = (int) value; return present; } bool java_builder::get_param (std::map const & params, const std::string& key, std::string& value) { map::const_iterator i = params.find (key); if (i == params.end()) return false; literal_string * ls = dynamic_cast(i->second); if (!ls) return false; value = ls->value; return true; } std::string java_builder::mark_param(int i) { switch (i) { case 0: return "method__0"; case 1: return "method__1"; case 2: return "method__2"; case 3: return "method__3"; case 4: return "method__4"; case 5: return "method__5"; case 6: return "method__6"; case 7: return "method__7"; case 8: return "method__8"; case 9: return "method__9"; case 10: return "method__10"; default: return "*"; } } void java_builder::build (systemtap_session & sess, probe * base, probe_point * loc, literal_map_t const & parameters, vector & finished_results) { string method_str_val = ""; string method_line_val = ""; bool has_method_str = get_param (parameters, TOK_METHOD, method_str_val); int short_method_pos = method_str_val.find ('('); //only if it exists, run check bool one_arg = false; // used to check if there is an argument in the method if (short_method_pos) { int second_method_pos = 0; second_method_pos = method_str_val.find (')'); if ((second_method_pos - short_method_pos) > 1) one_arg = true; } int _java_pid = 0; string _java_proc_class = ""; string short_method_str = method_str_val.substr (0, short_method_pos); string class_str_val; // fully qualified class string bool has_class_str = get_param (parameters, TOK_CLASS, class_str_val); bool has_pid_int = get_number_param (parameters, TOK_JAVA, _java_pid); bool has_pid_str = get_param (parameters, TOK_JAVA, _java_proc_class); bool has_return = has_null_param (parameters, TOK_RETURN); bool has_line_number = false; //find if we're probing at a specific line number size_t line_position = 0; size_t method_end_pos = method_str_val.size(); line_position = method_str_val.find_first_of(":"); //this will return the position ':' is found at if (line_position == string::npos) has_line_number = false; else { has_line_number = true; method_line_val = method_str_val.substr(line_position+1, method_end_pos); method_str_val = method_str_val.substr(0, line_position); line_position = method_line_val.find_first_of(":"); if (line_position != string::npos) throw semantic_error (_("maximum of one line number (:NNN)")); if (has_line_number && has_return) throw semantic_error (_("conflict :NNN and .return probe")); } //need to count the number of parameters, exit if more than 10 int method_params_count = count (method_str_val.begin (), method_str_val.end (), ','); if (one_arg) method_params_count++; // in this case we know there was at least a var, but no ',' if (method_params_count > 10) throw semantic_error (_("maximum of 10 java method parameters may be specified")); assert (has_method_str); (void) has_method_str; assert (has_class_str); (void) has_class_str; string java_pid_str = ""; if(has_pid_int) java_pid_str = lex_cast(_java_pid); else java_pid_str = _java_proc_class; if (! (has_pid_int || has_pid_str) ) throw semantic_error (_("missing JVMID")); /* The overall flow of control during a probed java method is something like this: (java) java-method -> (java) byteman -> (java) HelperSDT::METHOD_STAP_PROBENN -> (JNI) HelperSDT_arch.so -> (C) sys/sdt.h marker STAP_PROBEN(hotspot,method__N,...,rulename) To catch the java-method hit that belongs to this very systemtap probe, we use the rulename string as the identifier. It has to have some cool properties: - be unique system-wide, so as to avoid collisions between concurrent users, even if they run the same stap script - be unique within the script, so distinct probe handlers get run if specified - be computable from systemtap at run-time (since compile-time can't be unique enough) - be passable to stapbm, back through a .btm (byteman rule) file, back through sdt.h parameters The rulename is thusly synthesized as the string-concatenation expression (module_name() . "probe_NNN") */ string helper_location = PKGLIBDIR; // probe process("$pkglibdir/libHelperSDT_*.so").provider("HelperSDT").mark("method_NNN") helper_location.append("/libHelperSDT_*.so"); // wildcard deliberate: want to catch all arches // probe_point* new_loc = new probe_point(*loc); vector java_marker; java_marker.push_back(new probe_point::component (TOK_PROCESS, new literal_string (helper_location))); java_marker.push_back(new probe_point::component (TOK_PROVIDER, new literal_string ("HelperSDT"))); java_marker.push_back(new probe_point::component (TOK_MARK, new literal_string (mark_param(method_params_count)))); probe_point * derived_loc = new probe_point (java_marker); block *b = new block; b->tok = base->body->tok; functioncall* rulename_fcall = new functioncall; // module_name() rulename_fcall->tok = b->tok; rulename_fcall->function = "module_name"; literal_string* rulename_suffix = new literal_string(base->name); // "probeNNNN" rulename_suffix->tok = b->tok; concatenation* rulename_expr = new concatenation; // module_name()."probeNN" rulename_expr->tok = b->tok; rulename_expr->left = rulename_fcall; rulename_expr->op = "."; rulename_expr->right = rulename_suffix; // the rulename arrives as sys/sdt.h $argN (for last arg) target_symbol *cc = new target_symbol; // $argN cc->tok = b->tok; cc->name = "$arg" + lex_cast(method_params_count+1); functioncall *ccus = new functioncall; // user_string($argN) ccus->function = "user_string"; ccus->type = pe_string; ccus->tok = b->tok; ccus->args.push_back(cc); // rulename comparison: (user_string($argN) != module_name()."probeNN") comparison *ce = new comparison; ce->op = "!="; ce->tok = b->tok; ce->left = ccus; ce->right = rulename_expr; ce->right->tok = b->tok; // build if statement: if (user_string($argN) != module_name()."probeNN") next; if_statement *ifs = new if_statement; ifs->thenblock = new next_statement; ifs->elseblock = NULL; ifs->tok = b->tok; ifs->thenblock->tok = b->tok; ifs->condition = ce; b->statements.push_back(ifs); b->statements.push_back(base->body); derived_loc->components = java_marker; probe* new_mark_probe = new probe (base, derived_loc); new_mark_probe->body = b; derive_probes (sess, new_mark_probe, finished_results); // the begin portion of the probe to install byteman rules in the target jvm vector java_begin_marker; java_begin_marker.push_back( new probe_point::component (TOK_BEGIN)); probe_point * der_begin_loc = new probe_point(java_begin_marker); /* stapbm takes the following arguments: $1 - install/uninstall $2 - JVM PID/unique name $3 - RULE name <--- identifies this probe uniquely at run time $4 - class $5 - method $6 - number of args $7 - entry/exit/line */ literal_string* leftbits = new literal_string(string(PKGLIBDIR)+string("/stapbm ") + string("install ") + (has_pid_int ? lex_cast_qstring(java_pid_str) : lex_cast_qstring(_java_proc_class)) + string(" ")); // RULENAME_EXPR goes here literal_string* rightbits = new literal_string(" " + lex_cast_qstring(class_str_val) + " " + lex_cast_qstring(method_str_val) + " " + lex_cast(method_params_count) + " " + ((!has_return && !has_line_number) ? string("entry") : ((has_return && !has_line_number) ? string("exit") : method_line_val))); concatenation* leftmid = new concatenation; leftmid->left = leftbits; leftmid->right = rulename_expr; // NB: we're reusing the same tree; 's ok due to copying leftmid->op = "."; leftmid->tok = base->body->tok; concatenation* midright = new concatenation; midright->left = leftmid; midright->right = rightbits; midright->op = "."; midright->tok = base->body->tok; block *bb = new block; bb->tok = base->body->tok; functioncall *fc = new functioncall; fc->function = "system"; fc->tok = bb->tok; fc->args.push_back(midright); expr_statement* bs = new expr_statement; bs->tok = bb->tok; bs->value = fc; bb->statements.push_back(bs); der_begin_loc->components = java_begin_marker; probe* new_begin_probe = new probe(base, der_begin_loc); new_begin_probe->body = bb; // overwrite derive_probes (sess, new_begin_probe, finished_results); // the end/error portion of the probe to uninstall byteman rules from the target jvm vector java_end_marker; java_end_marker.push_back(new probe_point::component (TOK_END)); probe_point *der_end_loc = new probe_point (java_end_marker); vector java_error_marker; java_error_marker.push_back(new probe_point::component (TOK_ERROR)); probe_point *der_error_loc = new probe_point (java_error_marker); bb = new block; bb->tok = base->body->tok; leftbits = new literal_string(string(PKGLIBDIR)+string("/stapbm ") + string("uninstall ") + (has_pid_int ? lex_cast_qstring(java_pid_str) : lex_cast_qstring(_java_proc_class)) + string(" ")); // RULENAME_EXPR goes here (void) rightbits; // same as before leftmid = new concatenation; leftmid->left = leftbits; leftmid->right = rulename_expr; // NB: we're reusing the same tree; 's ok due to copying leftmid->op = "."; leftmid->tok = bb->tok; midright = new concatenation; midright->left = leftmid; midright->right = rightbits; midright->op = "."; midright->tok = bb->tok; fc = new functioncall; fc->function = "system"; fc->tok = bb->tok; fc->args.push_back(midright); bs = new expr_statement; bs->tok = bb->tok; bs->value = fc; bb->statements.push_back(bs); probe* new_end_probe = new probe(base, der_end_loc); new_end_probe->body = bb; // overwrite (void) der_error_loc; // new_end_probe->locations.push_back (der_error_loc); derive_probes (sess, new_end_probe, finished_results); } void register_tapset_java (systemtap_session& s) { (void) s; #ifdef HAVE_JAVA match_node* root = s.pattern_root; derived_probe_builder *builder = new java_builder (); root->bind_str (TOK_JAVA) ->bind_str (TOK_CLASS)->bind_str (TOK_METHOD) ->bind_privilege(pr_all) ->bind(builder); root->bind_str (TOK_JAVA) ->bind_str (TOK_CLASS)->bind_str (TOK_METHOD) ->bind (TOK_RETURN) ->bind_privilege(pr_all) ->bind(builder); root->bind_num (TOK_JAVA) ->bind_str (TOK_CLASS)->bind_str (TOK_METHOD) ->bind_privilege(pr_all) ->bind (builder); root->bind_num (TOK_JAVA) ->bind_str (TOK_CLASS)->bind_str (TOK_METHOD) ->bind (TOK_RETURN) ->bind_privilege(pr_all) ->bind (builder); #endif } systemtap-2.3/tapset-netfilter.cxx000066400000000000000000000450341217430427200174350ustar00rootroot00000000000000// tapset for netfilter hooks // Copyright (C) 2012 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "session.h" #include "tapsets.h" #include "translate.h" #include "util.h" #include #include #include using namespace std; using namespace __gnu_cxx; static const string TOK_NETFILTER("netfilter"); static const string TOK_HOOK("hook"); static const string TOK_PF("pf"); static const string TOK_PRIORITY("priority"); // ------------------------------------------------------------------------ // netfilter derived probes // ------------------------------------------------------------------------ struct netfilter_derived_probe: public derived_probe { string hook; string pf; string priority; unsigned nf_index; set context_vars; netfilter_derived_probe (systemtap_session &, probe* p, probe_point* l, string h, string protof, string pri); virtual void join_group (systemtap_session& s); }; struct netfilter_derived_probe_group: public generic_dpg { public: void emit_module_decls (systemtap_session& s); void emit_module_init (systemtap_session& s); void emit_module_exit (systemtap_session& s); }; struct netfilter_var_expanding_visitor: public var_expanding_visitor { netfilter_var_expanding_visitor(systemtap_session& s, const string& pn); systemtap_session& sess; string probe_name; set context_vars; void visit_target_symbol (target_symbol* e); }; netfilter_derived_probe::netfilter_derived_probe (systemtap_session &s, probe* p, probe_point* l, string h, string protof, string pri): derived_probe (p, l), hook (h), pf (protof), priority (pri) { static unsigned nf_index_ctr = 0; this->nf_index = nf_index_ctr++; // PR14137: need to generate unique // identifier, since p->name may be // shared in c_unparser::emit_probe() bool hook_error = false; bool pf_error = false; // Map the strings passed in to the actual values defined in netfilter_*.h // NOTE: We need to hard code all the following // constants rather than just include the // appropriate kernel headers because in different // versions of the kernel, certain constants are not // defined. This was the best method at the time to // get them to compile properly. // Validate hook, pf, priority if(pf == "NFPROTO_IPV4") { // Protocol Family pf = "2"; // Hook if (hook == "NF_INET_PRE_ROUTING") hook = "0"; else if (hook == "NF_INET_LOCAL_IN") hook = "1"; else if (hook == "NF_INET_FORWARD") hook = "2"; else if (hook == "NF_INET_LOCAL_OUT") hook = "3"; else if (hook == "NF_INET_POST_ROUTING") hook = "4"; else if (hook == "NF_IP_PRE_ROUTING") hook = "0"; else if (hook == "NF_IP_LOCAL_IN") hook = "1"; else if (hook == "NF_IP_FORWARD") hook = "2"; else if (hook == "NF_IP_LOCAL_OUT") hook = "3"; else if (hook == "NF_IP_POST_ROUTING") hook = "4"; else hook_error = true; // Priority if (priority == "NF_IP_PRI_FIRST") priority = lex_cast(INT_MIN); else if (priority == "NF_IP_PRI_CONNTRACK_DEFRAG") priority = "-400"; else if (priority == "NF_IP_PRI_RAW") priority = "-300"; else if (priority == "NF_IP_PRI_SELINUX_FIRST") priority = "-225"; else if (priority == "NF_IP_PRI_CONNTRACK") priority = "-200"; else if (priority == "NF_IP_PRI_MANGLE") priority = "-150"; else if (priority == "NF_IP_PRI_NAT_DST") priority = "-100"; else if (priority == "NF_IP_PRI_FILTER") priority = "0"; else if (priority == "NF_IP_PRI_SECURITY") priority = "50"; else if (priority == "NF_IP_PRI_NAT_SRC") priority = "100"; else if (priority == "NF_IP_PRI_SELINUX_LAST") priority = "225"; else if (priority == "NF_IP_PRI_CONNTRACK_CONFIRM") priority = lex_cast(INT_MAX); else if (priority == "NF_IP_PRI_LAST") priority = lex_cast(INT_MAX); } else if(pf=="NFPROTO_IPV6") { // Protocol Family pf = "10"; // Hook if (hook == "NF_IP6_PRE_ROUTING") hook = "0"; else if (hook == "NF_IP6_LOCAL_IN") hook = "1"; else if (hook == "NF_IP6_FORWARD") hook = "2"; else if (hook == "NF_IP6_LOCAL_OUT") hook = "3"; else if (hook == "NF_IP6_POST_ROUTING") hook = "4"; else hook_error = true; // Priority if (priority == "NF_IP6_PRI_FIRST") priority = lex_cast(INT_MIN); else if (priority == "NF_IP6_PRI_CONNTRACK_DEFRAG") priority = "-400"; else if (priority == "NF_IP6_PRI_RAW") priority = "-300"; else if (priority == "NF_IP6_PRI_SELINUX_FIRST") priority = "-225"; else if (priority == "NF_IP6_PRI_CONNTRACK") priority = "-200"; else if (priority == "NF_IP6_PRI_MANGLE") priority = "-150"; else if (priority == "NF_IP6_PRI_NAT_DST") priority = "-100"; else if (priority == "NF_IP6_PRI_FILTER") priority = "0"; else if (priority == "NF_IP6_PRI_SECURITY") priority = "50"; else if (priority == "NF_IP6_PRI_NAT_SRC") priority = "100"; else if (priority == "NF_IP6_PRI_SELINUX_LAST") priority = "225"; else if (priority == "NF_IP6_PRI_LAST") priority = lex_cast(INT_MAX); } else if (pf == "NFPROTO_ARP") { // Protocol Family pf = "3"; // Hook if (hook == "NF_ARP_IN") hook = "0"; else if (hook == "NF_ARP_OUT") hook = "1"; else if (hook == "NF_ARP_FORWARD") hook = "2"; else hook_error = true; } else if (pf == "NFPROTO_BRIDGE") { // Protocol Family pf = "7"; // Hook if (hook == "NF_BR_PRE_ROUTING") hook = "0"; else if (hook == "NF_BR_LOCAL_IN") hook = "1"; else if (hook == "NF_BR_FORWARD") hook = "2"; else if (hook == "NF_BR_LOCAL_OUT") hook = "3"; else if (hook == "NF_BR_POST_ROUTING") hook = "4"; else hook_error = true; } else pf_error = true; // If not running in guru mode, we need more strict checks on hook name, // protocol family and priority to avoid people putting in wacky embedded c // nastiness. Otherwise, and if it didn't match any of the above lists, // pass the string in as is. if(!s.guru_mode) { // At this point the priority should be a 32 bit integer encoded as a string. // Ensure that this is the case. try { int prio = lex_cast(priority); (void) prio; } catch (const runtime_error&) { throw semantic_error (_F("unsupported netfilter priority \"%s\" for protocol family \"%s\"; need stap -g", priority.c_str(), pf.c_str())); } // Complain and abort if there were any hook name errors if (hook_error) throw semantic_error (_F("unsupported netfilter hook \"%s\" for protocol family \"%s\"; need stap -g", hook.c_str(), pf.c_str())); // Complain and abort if there were any pf errors if (pf_error) throw semantic_error (_F("unsupported netfilter protocol family \"%s\"; need stap -g", pf.c_str())); } // Expand local variables in the probe body netfilter_var_expanding_visitor v (s, name); v.replace (this->body); // Create probe-local vardecls, before symbol resolution might make // one for us, so that we can set the all-important synthetic flag. for (set::iterator it = v.context_vars.begin(); it != v.context_vars.end(); it++) { string name = *it; this->context_vars.insert(name); vardecl *v = new vardecl; v->name = name; v->tok = this->tok; /* XXX: but really the $context var. */ v->set_arity (0, this->tok); v->type = pe_long; v->synthetic = true; // suppress rvalue or lvalue optimizations this->locals.push_back (v); } } void netfilter_derived_probe::join_group (systemtap_session& s) { if (! s.netfilter_derived_probes) s.netfilter_derived_probes = new netfilter_derived_probe_group (); s.netfilter_derived_probes->enroll (this); } void netfilter_derived_probe_group::emit_module_decls (systemtap_session& s) { if (probes.empty()) return; // Here we emit any global data structures and functions, including callback functions // to be invoked by netfilter. // // For other kernel callbacks, a token is passed back to help identify a particular // probe-point registration. For netfilter, nope, so once we're in a notification callback, // we can't find out exactly on whose (which probe point's) behalf we were called. // // So, we just emit one netfilter callback function per systemtap probe, each with its // own nf_hook_ops structure. Note that the translator already emits a stp_probes[] array, // pre-filled with probe names and handler functions and that sort of stuff. s.op->newline() << "/* ---- netfilter probes ---- */"; s.op->newline() << "#include "; s.op->newline() << "#include "; s.op->newline() << "#include "; s.op->newline() << "#include "; s.op->newline() << "#include "; for (unsigned i=0; i < probes.size(); i++) { netfilter_derived_probe *np = probes[i]; s.op->newline() << "static unsigned int enter_netfilter_probe_" << np->nf_index; // Previous to kernel 2.6.22, the hookfunction definition takes a struct sk_buff **skb, // whereas currently it uses a *skb. We need emit the right version so this will // compile on RHEL5, for example. s.op->newline() << "#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)"; s.op->newline() << "(unsigned int nf_hooknum, struct sk_buff *nf_skb, const struct net_device *nf_in, const struct net_device *nf_out, int (*nf_okfn)(struct sk_buff *))"; s.op->newline() << "{"; s.op->newline() << "#else"; s.op->newline() << "(unsigned int nf_hooknum, struct sk_buff **nf_pskb, const struct net_device *nf_in, const struct net_device *nf_out, int (*nf_okfn)(struct sk_buff *))"; s.op->newline() << "{"; s.op->newline(1) << "struct sk_buff *nf_skb = nf_pskb ? *nf_pskb : NULL;"; s.op->newline(-1) << "#endif"; s.op->newline(1) << "const struct stap_probe * const stp = & stap_probes[" << np->session_index << "];"; s.op->newline() << "int nf_verdict = NF_ACCEPT;"; // default NF_ACCEPT, to be used by $verdict context var common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "stp", "stp_probe_type_netfilter", false); // Copy or pretend-to-touch each incoming parameter. string c_p = "c->probe_locals." + lex_cast(np->name); // this is where the $context vars show up // NB: PR14137: this should be the potentially shared name, // since the generated probe handler body refers to that name. if (np->context_vars.find("__nf_hooknum") != np->context_vars.end()) s.op->newline() << c_p + "." + s.up->c_localname("__nf_hooknum") + " = (int64_t)(uintptr_t) nf_hooknum;"; else s.op->newline() << "(void) nf_hooknum;"; if (np->context_vars.find("__nf_skb") != np->context_vars.end()) s.op->newline() << c_p + "." + s.up->c_localname("__nf_skb") + " = (int64_t)(uintptr_t) nf_skb;"; else s.op->newline() << "(void) nf_skb;"; if (np->context_vars.find("__nf_in") != np->context_vars.end()) s.op->newline() << c_p + "." + s.up->c_localname("__nf_in") + " = (int64_t)(uintptr_t) nf_in;"; else s.op->newline() << "(void) nf_in;"; if (np->context_vars.find("__nf_out") != np->context_vars.end()) s.op->newline() << c_p + "." + s.up->c_localname("__nf_in") + " = (int64_t)(uintptr_t) nf_out;"; else s.op->newline() << "(void) nf_out;"; if (np->context_vars.find("__nf_verdict") != np->context_vars.end()) s.op->newline() << c_p + "." + s.up->c_localname("__nf_verdict") + " = (int64_t) nf_verdict;"; else s.op->newline() << "(void) nf_out;"; // Invoke the probe handler s.op->newline() << "(*stp->ph) (c);"; common_probe_entryfn_epilogue (s, false); if (np->context_vars.find("__nf_verdict") != np->context_vars.end()) s.op->newline() << "nf_verdict = (int) "+c_p+"." + s.up->c_localname("__nf_verdict") + ";"; s.op->newline() << "return nf_verdict;"; s.op->newline(-1) << "}"; // now emit the nf_hook_ops struct for this probe. s.op->newline() << "static struct nf_hook_ops netfilter_opts_" << np->nf_index << " = {"; s.op->newline() << ".hook = enter_netfilter_probe_" << np->nf_index << ","; s.op->newline() << ".owner = THIS_MODULE,"; // XXX: if these strings/numbers are not range-limited / validated before we get here, // ie during the netfilter_derived_probe ctor, then we will emit potential trash here, // leading to all kinds of horror. Like zombie women eating roach-filled walnuts. Dogs // and cats living together. Foreign foods taking over the refrigerator. Don't let this // happen to you! s.op->newline() << ".hooknum = " << np->hook << ","; s.op->newline() << ".pf = " << np->pf << ","; s.op->newline() << ".priority = " << np->priority << ","; s.op->newline() << "};"; } s.op->newline(); } void netfilter_derived_probe_group::emit_module_init (systemtap_session& s) { if (probes.empty()) return; // We register (do not execute) the probes here. // NB: since we anticipate only a few netfilter/hook type probes, there is no need to // emit an initialization loop into the generated C code. We can simply unroll it. for (unsigned i=0; i < probes.size(); i++) { netfilter_derived_probe *np = probes[i]; s.op->newline() << "rc = nf_register_hook (& netfilter_opts_" << np->nf_index << ");"; if (i > 0) // unregister others upon failure { s.op->newline() << "if (rc < 0) {"; s.op->indent(1); for (int j=i-1; j>=0; j--) // XXX: j must be signed for loop to work { netfilter_derived_probe *np2 = probes[j]; s.op->newline() << "nf_unregister_hook (& netfilter_opts_" << np2->nf_index << ");"; } s.op->newline(-1) << "}"; } } } void netfilter_derived_probe_group::emit_module_exit (systemtap_session& s) { if (probes.empty()) return; // We register (do not execute) the probes here. for (unsigned i=0; i < probes.size(); i++) { netfilter_derived_probe *np = probes[i]; s.op->newline() << "nf_unregister_hook (& netfilter_opts_" << np->nf_index << ");"; } } netfilter_var_expanding_visitor::netfilter_var_expanding_visitor (systemtap_session& s, const string& pn): sess (s), probe_name (pn) { } void netfilter_var_expanding_visitor::visit_target_symbol (target_symbol* e) { try { assert(e->name.size() > 0 && e->name[0] == '$'); if (e->addressof) throw semantic_error(_("cannot take address of netfilter hook context variable"), e->tok); // We map all $context variables to similarly named probe locals. // See emit_module_decls for how the parameters & result are handled. string c_var; bool lvalue_ok = false; bool need_guru = false; if (e->name == "$hooknum") { c_var = "__nf_hooknum"; } else if (e->name == "$skb") { c_var = "__nf_skb"; } else if (e->name == "$in") { c_var = "__nf_in"; } else if (e->name == "$out") { c_var = "__nf_out"; } else if (e->name == "$okfn") { c_var = "__nf_okfn"; } else if (e->name == "$verdict") { c_var = "__nf_verdict"; lvalue_ok = true; need_guru = true; } // XXX: also support $$vars / $$parms else throw semantic_error(_("unsupported context variable"), e->tok); if (! lvalue_ok && is_active_lvalue (e)) throw semantic_error(_("write to netfilter parameter not permitted"), e->tok); // Writing to variables like $verdict requires guru mode, for obvious reasons if(need_guru && !sess.guru_mode) throw semantic_error(_("write to netfilter verdict requires guru mode; need stap -g"), e->tok); context_vars.insert (c_var); // Synthesize a symbol to reference those variables symbol* sym = new symbol; sym->type = pe_long; sym->tok = e->tok; sym->name = c_var; provide (sym); } catch (const semantic_error &er) { e->chain (er); provide (e); } } // ------------------------------------------------------------------------ // unified probe builder for netfilter probes // ------------------------------------------------------------------------ struct netfilter_builder: public derived_probe_builder { virtual void build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results); static void register_patterns(systemtap_session& s); }; void netfilter_builder::build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results) { string hook; // no default string pf; // no default string priority = "0"; // Default: somewhere in the middle if(!get_param(parameters, TOK_HOOK, hook)) throw semantic_error (_("missing hooknum")); if(!get_param(parameters, TOK_PF, pf)) throw semantic_error (_("missing protocol family")); get_param(parameters, TOK_PRIORITY, priority); finished_results.push_back(new netfilter_derived_probe(sess, base, location, hook, pf, priority)); } void register_tapset_netfilter(systemtap_session& s) { match_node* root = s.pattern_root; derived_probe_builder *builder = new netfilter_builder(); //netfilter.hook().pf() root->bind(TOK_NETFILTER)->bind_str(TOK_HOOK)->bind_str(TOK_PF)->bind(builder); //netfilter.pf().hook() root->bind(TOK_NETFILTER)->bind_str(TOK_PF)->bind_str(TOK_HOOK)->bind(builder); //netfilter.hook().pf().priority() root->bind(TOK_NETFILTER)->bind_str(TOK_HOOK)->bind_str(TOK_PF)->bind_str(TOK_PRIORITY)->bind(builder); //netfilter.pf().hook().priority() root->bind(TOK_NETFILTER)->bind_str(TOK_PF)->bind_str(TOK_HOOK)->bind_str(TOK_PRIORITY)->bind(builder); } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/tapset-perfmon.cxx000066400000000000000000000327051217430427200171100ustar00rootroot00000000000000// tapset for HW performance monitoring // Copyright (C) 2005-2013 Red Hat Inc. // Copyright (C) 2005-2007 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "session.h" #include "tapsets.h" #include "task_finder.h" #include "translate.h" #include "util.h" #include #include extern "C" { #define __STDC_FORMAT_MACROS #include } using namespace std; using namespace __gnu_cxx; static const string TOK_PERF("perf"); static const string TOK_TYPE("type"); static const string TOK_CONFIG("config"); static const string TOK_SAMPLE("sample"); static const string TOK_PROCESS("process"); static const string TOK_COUNTER("counter"); // ------------------------------------------------------------------------ // perf event derived probes // ------------------------------------------------------------------------ // This is a new interface to the perfmon hw. // struct perf_derived_probe: public derived_probe { int64_t event_type; int64_t event_config; int64_t interval; bool has_process; bool has_counter; string process_name; string counter; perf_derived_probe (probe* p, probe_point* l, int64_t type, int64_t config, int64_t i, bool pp, bool cp, string pn, string cv); virtual void join_group (systemtap_session& s); }; struct perf_derived_probe_group: public generic_dpg { void emit_module_decls (systemtap_session& s); void emit_module_init (systemtap_session& s); void emit_module_exit (systemtap_session& s); }; perf_derived_probe::perf_derived_probe (probe* p, probe_point* l, int64_t type, int64_t config, int64_t i, bool process_p, bool counter_p, string process_n, string counter): derived_probe (p, l, true /* .components soon rewritten */), event_type (type), event_config (config), interval (i), has_process (process_p), has_counter (counter_p), process_name (process_n), counter (counter) { vector& comps = this->sole_location()->components; comps.clear(); comps.push_back (new probe_point::component (TOK_PERF)); comps.push_back (new probe_point::component (TOK_TYPE, new literal_number(type))); comps.push_back (new probe_point::component (TOK_CONFIG, new literal_number (config))); comps.push_back (new probe_point::component (TOK_SAMPLE, new literal_number (interval))); comps.push_back (new probe_point::component (TOK_PROCESS, new literal_string (process_name))); comps.push_back (new probe_point::component (TOK_COUNTER, new literal_string (counter))); } void perf_derived_probe::join_group (systemtap_session& s) { if (! s.perf_derived_probes) s.perf_derived_probes = new perf_derived_probe_group (); s.perf_derived_probes->enroll (this); if (has_process && !has_counter) enable_task_finder(s); } void perf_derived_probe_group::emit_module_decls (systemtap_session& s) { bool have_a_process_tag = false; for (unsigned i=0; i < probes.size(); i++) if (probes[i]->has_process && !probes[i]->has_counter) { have_a_process_tag = true; break; } if (probes.empty()) return; s.op->newline() << "/* ---- perf probes ---- */"; s.op->newline() << "#include "; s.op->newline() << "#include \"linux/perf.h\""; s.op->newline(); /* declarations */ s.op->newline() << "static void handle_perf_probe (unsigned i, struct pt_regs *regs);"; for (unsigned i=0; i < probes.size(); i++) { s.op->newline() << "#ifdef STAPCONF_PERF_HANDLER_NMI"; s.op->newline() << "static void enter_perf_probe_" << i << " (struct perf_event *e, int nmi, " << "struct perf_sample_data *data, " << "struct pt_regs *regs);"; s.op->newline() << "#else"; s.op->newline() << "static void enter_perf_probe_" << i << " (struct perf_event *e, " << "struct perf_sample_data *data, " << "struct pt_regs *regs);"; s.op->newline() << "#endif"; } s.op->newline(); // Output task finder callback routine if (have_a_process_tag) { s.op->newline() << "static int _stp_perf_probe_cb(struct stap_task_finder_target *tgt, struct task_struct *tsk, int register_p, int process_p) {"; s.op->indent(1); s.op->newline() << "int rc = 0;"; s.op->newline() << "struct stap_perf_probe *p = container_of(tgt, struct stap_perf_probe, e.t.tgt);"; s.op->newline() << "if (register_p) "; s.op->indent(1); s.op->newline() << "rc = _stp_perf_init(p, tsk);"; s.op->newline(-1) << "else"; s.op->newline(1) << "_stp_perf_del(p);"; s.op->newline(-1) << "return rc;"; s.op->newline(-1) << "}"; } /* data structures */ s.op->newline() << "static struct stap_perf_probe stap_perf_probes [" << probes.size() << "] = {"; s.op->indent(1); for (unsigned i=0; i < probes.size(); i++) { s.op->newline() << "{"; s.op->newline(1) << ".attr={ " << ".type=" << probes[i]->event_type << "ULL, " << ".config=" << probes[i]->event_config << "ULL, " << "{ .sample_period=" << probes[i]->interval << "ULL }},"; s.op->newline() << ".callback=enter_perf_probe_" << i << ", "; s.op->newline() << ".probe=" << common_probe_init (probes[i]) << ", "; string l_process_name; if (probes[i]->has_process && !probes[i]->has_counter) { if (probes[i]->process_name.length() == 0) { wordexp_t words; int rc = wordexp(s.cmd.c_str(), &words, WRDE_NOCMD|WRDE_UNDEF); if (rc || words.we_wordc <= 0) throw semantic_error(_("unspecified process probe is invalid without a -c COMMAND")); l_process_name = words.we_wordv[0]; wordfree (& words); } else l_process_name = probes[i]->process_name; s.op->line() << " .e={"; s.op->line() << " .t={"; s.op->line() << " .tgt={"; s.op->line() << " .purpose=\"perfctr\","; s.op->line() << " .procname=\"" << l_process_name << "\","; s.op->line() << " .pid=0,"; s.op->line() << " .callback=&_stp_perf_probe_cb,"; s.op->line() << " },"; s.op->line() << " },"; s.op->line() << " },"; s.op->newline() << ".per_thread=" << "1, "; } else if (probes[i]->has_counter) s.op->newline() << ".per_thread=" << "1, "; else s.op->newline() << ".per_thread=" << "0, "; s.op->newline(-1) << "},"; } s.op->newline(-1) << "};"; s.op->newline(); /* wrapper functions */ for (unsigned i=0; i < probes.size(); i++) { s.op->newline() << "#ifdef STAPCONF_PERF_HANDLER_NMI"; s.op->newline() << "static void enter_perf_probe_" << i << " (struct perf_event *e, int nmi, " << "struct perf_sample_data *data, " << "struct pt_regs *regs)"; s.op->newline() << "#else"; s.op->newline() << "static void enter_perf_probe_" << i << " (struct perf_event *e, " << "struct perf_sample_data *data, " << "struct pt_regs *regs)"; s.op->newline() << "#endif"; s.op->newline() << "{"; s.op->newline(1) << "handle_perf_probe(" << i << ", regs);"; s.op->newline(-1) << "}"; } s.op->newline(); s.op->newline() << "static void handle_perf_probe (unsigned i, struct pt_regs *regs)"; s.op->newline() << "{"; s.op->newline(1) << "struct stap_perf_probe* stp = & stap_perf_probes [i];"; common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "stp->probe", "stp_probe_type_perf"); s.op->newline() << "if (user_mode(regs)) {"; s.op->newline(1)<< "c->user_mode_p = 1;"; s.op->newline() << "c->uregs = regs;"; s.op->newline(-1) << "} else {"; s.op->newline(1) << "c->kregs = regs;"; s.op->newline(-1) << "}"; s.op->newline() << "(*stp->probe->ph) (c);"; common_probe_entryfn_epilogue (s, true); s.op->newline(-1) << "}"; s.op->newline(); s.op->newline() << "#include \"linux/perf.c\""; s.op->newline(); } void perf_derived_probe_group::emit_module_init (systemtap_session& s) { bool have_a_process_tag = false; for (unsigned i=0; i < probes.size(); i++) if (probes[i]->has_process) { have_a_process_tag = true; break; } if (probes.empty()) return; s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {"; s.op->newline(1) << "struct stap_perf_probe* stp = & stap_perf_probes [i];"; s.op->newline() << "rc = _stp_perf_init(stp, 0);"; s.op->newline() << "if (rc) {"; s.op->newline(1) << "probe_point = stp->probe->pp;"; s.op->newline() << "for (j=0; jnewline(1) << "_stp_perf_del(& stap_perf_probes [j]);"; s.op->newline(-1) << "}"; // for unwind loop s.op->newline() << "break;"; s.op->newline(-1) << "}"; // if-error if (have_a_process_tag) s.op->newline() << "rc = stap_register_task_finder_target(&stp->e.t.tgt);"; s.op->newline(-1) << "}"; // for loop } void perf_derived_probe_group::emit_module_exit (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {"; s.op->newline(1) << "_stp_perf_del(& stap_perf_probes [i]);"; s.op->newline(-1) << "}"; // for loop } struct perf_builder: public derived_probe_builder { virtual void build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results); static void register_patterns(systemtap_session& s); }; struct statement_counter: public update_visitor { bool empty; const token* first_tok; statement_counter () {} void visit_block (block *b) { if (b->statements.size() > 0) { empty = false; first_tok = b->statements[0]->tok; } else empty = true; }; }; void perf_builder::build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results) { // XXX need additional version checks too? // --- perhaps look for export of perf_event_create_kernel_counter if (sess.kernel_exports.find("perf_event_create_kernel_counter") == sess.kernel_exports.end()) throw semantic_error (_("perf probes not available without exported perf_event_create_kernel_counter")); if (sess.kernel_config["CONFIG_PERF_EVENTS"] != "y") throw semantic_error (_("perf probes not available without CONFIG_PERF_EVENTS")); int64_t type; bool has_type = get_param(parameters, TOK_TYPE, type); assert(has_type); int64_t config; bool has_config = get_param(parameters, TOK_CONFIG, config); assert(has_config); int64_t period; bool has_period = get_param(parameters, TOK_SAMPLE, period); if (!has_period) period = 1000000; // XXX: better parametrize this default else if (period < 1) throw semantic_error(_("invalid perf sample period ") + lex_cast(period), parameters.find(TOK_SAMPLE)->second->tok); bool proc_p; string proc_n; proc_p = has_null_param(parameters, TOK_PROCESS) || get_param(parameters, TOK_PROCESS, proc_n); if (proc_p) proc_n = find_executable (proc_n, sess.sysroot, sess.sysenv); string var; bool has_counter = get_param(parameters, TOK_COUNTER, var); if (var.find_first_of("*?[") != string::npos) throw semantic_error(_("wildcard not allowed with perf probe counter component")); if (has_counter) { if (var.length() == 0) throw semantic_error(_("missing perf probe counter component name")); period = 0; // perf_event_attr.sample_freq should be 0 map >::iterator it; for (it=sess.perf_counters.begin(); it != sess.perf_counters.end(); it++) if ((*it).first == var) throw semantic_error(_("duplicate counter name")); struct statement_counter sc; base->body->visit(&sc); if (! sc.empty) sess.print_warning(_("Statements in perf counter probe will never be reached."), sc.first_tok); if_statement *ifs = new if_statement (); ifs->tok = base->tok; ifs->thenblock = new next_statement (); ifs->thenblock->tok = base->tok; ifs->elseblock = NULL; ifs->condition = new literal_number(0); base->body = new block (ifs, base->body); } if (sess.verbose > 1) clog << _F("perf probe type=%" PRId64 " config=%" PRId64 " period=%" PRId64, type, config, period) << endl; finished_results.push_back (new perf_derived_probe(base, location, type, config, period, proc_p, has_counter, proc_n, var)); sess.perf_counters[var] = make_pair(proc_n,finished_results.back()); } void register_tapset_perf(systemtap_session& s) { // NB: at this point, the binding is *not* unprivileged. derived_probe_builder *builder = new perf_builder(); match_node* perf = s.pattern_root->bind(TOK_PERF); match_node* event = perf->bind_num(TOK_TYPE)->bind_num(TOK_CONFIG); event->bind(builder); event->bind_num(TOK_SAMPLE)->bind(builder); event->bind_str(TOK_PROCESS)->bind(builder); event->bind(TOK_PROCESS)->bind(builder); event->bind_str(TOK_COUNTER)->bind(builder); event->bind_str(TOK_PROCESS)->bind_str(TOK_COUNTER)->bind(builder); } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/tapset-procfs.cxx000066400000000000000000000514411217430427200167340ustar00rootroot00000000000000// tapset for procfs // Copyright (C) 2005-2010 Red Hat Inc. // Copyright (C) 2005-2007 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "session.h" #include "tapsets.h" #include "translate.h" #include "util.h" #include #include using namespace std; using namespace __gnu_cxx; static const string TOK_PROCFS("procfs"); static const string TOK_READ("read"); static const string TOK_WRITE("write"); static const string TOK_MAXSIZE("maxsize"); static const string TOK_UMASK("umask"); // ------------------------------------------------------------------------ // procfs file derived probes // ------------------------------------------------------------------------ struct procfs_derived_probe: public derived_probe { string path; bool write; bool target_symbol_seen; int64_t maxsize_val; int64_t umask; procfs_derived_probe (systemtap_session &, probe* p, probe_point* l, string ps, bool w, int64_t m, int64_t umask); void join_group (systemtap_session& s); }; struct procfs_probe_set { procfs_derived_probe* read_probe; procfs_derived_probe* write_probe; procfs_probe_set () : read_probe (NULL), write_probe (NULL) {} }; struct procfs_derived_probe_group: public generic_dpg { private: map probes_by_path; typedef map::iterator p_b_p_iterator; bool has_read_probes; bool has_write_probes; public: procfs_derived_probe_group () : has_read_probes(false), has_write_probes(false) {} void enroll (procfs_derived_probe* probe); void emit_kernel_module_init (systemtap_session& s); void emit_kernel_module_exit (systemtap_session& s); void emit_module_decls (systemtap_session& s); void emit_module_init (systemtap_session& s); void emit_module_exit (systemtap_session& s); }; struct procfs_var_expanding_visitor: public var_expanding_visitor { procfs_var_expanding_visitor(systemtap_session& s, const string& pn, string path, bool write_probe); systemtap_session& sess; string probe_name; string path; bool write_probe; bool target_symbol_seen; void visit_target_symbol (target_symbol* e); }; procfs_derived_probe::procfs_derived_probe (systemtap_session &s, probe* p, probe_point* l, string ps, bool w, int64_t m, int64_t umask): derived_probe(p, l), path(ps), write(w), target_symbol_seen(false), maxsize_val(m), umask(umask) { // Expand local variables in the probe body procfs_var_expanding_visitor v (s, name, path, write); v.replace (this->body); target_symbol_seen = v.target_symbol_seen; } void procfs_derived_probe::join_group (systemtap_session& s) { if (! s.procfs_derived_probes) { s.procfs_derived_probes = new procfs_derived_probe_group (); // Make sure 'struct _stp_procfs_data' is defined early. embeddedcode *ec = new embeddedcode; ec->tok = NULL; ec->code = string("struct _stp_procfs_data {\n") + string(" char *buffer;\n") + string(" size_t bufsize;\n") + string(" size_t count;\n") + string("};\n") + string("#ifndef STP_PROCFS_BUFSIZE\n") + string("#define STP_PROCFS_BUFSIZE MAXSTRINGLEN\n") + string("#endif\n"); s.embeds.push_back(ec); } s.procfs_derived_probes->enroll (this); } void procfs_derived_probe_group::enroll (procfs_derived_probe* p) { procfs_probe_set *pset; if (probes_by_path.count(p->path) == 0) { pset = new procfs_probe_set; probes_by_path[p->path] = pset; } else { pset = probes_by_path[p->path]; // You can only specify 1 read and 1 write probe. if (p->write && pset->write_probe != NULL) throw semantic_error(_("only one write procfs probe can exist for procfs path \"") + p->path + "\""); else if (! p->write && pset->read_probe != NULL) throw semantic_error(_("only one read procfs probe can exist for procfs path \"") + p->path + "\""); // XXX: multiple writes should be acceptable } if (p->write) { pset->write_probe = p; has_write_probes = true; } else { pset->read_probe = p; has_read_probes = true; } } void procfs_derived_probe_group::emit_kernel_module_init (systemtap_session& s) { if (probes_by_path.empty()) return; s.op->newline() << "rc = _stp_mkdir_proc_module();"; } void procfs_derived_probe_group::emit_kernel_module_exit (systemtap_session& s) { if (probes_by_path.empty()) return; // If we're using the original transport, it uses the // '/proc/systemtap/{module_name}' directory to store control // files. Let the transport layer clean up that directory. s.op->newline() << "#if (STP_TRANSPORT_VERSION != 1)"; s.op->newline() << "_stp_rmdir_proc_module();"; s.op->newline() << "#endif"; } void procfs_derived_probe_group::emit_module_decls (systemtap_session& s) { if (probes_by_path.empty()) return; s.op->newline() << "/* ---- procfs probes ---- */"; s.op->newline() << "#include \"procfs.c\""; s.op->newline() << "#include \"procfs-probes.c\""; // Emit the procfs probe buffer structure s.op->newline() << "static struct stap_procfs_probe_buffer {"; s.op->indent(1); unsigned buf_index = 0; // used for buffer naming for (p_b_p_iterator it = probes_by_path.begin(); it != probes_by_path.end(); it++) { procfs_probe_set *pset = it->second; s.op->newline() << "char buf_" << buf_index++; if (pset->read_probe != NULL) { if (pset->read_probe->maxsize_val == 0) s.op->line() << "[STP_PROCFS_BUFSIZE];"; else s.op->line() << "[" << pset->read_probe->maxsize_val << "];"; } else s.op->line() << "[MAXSTRINGLEN];"; } s.op->newline(-1) << "} stap_procfs_probe_buffers;"; // Emit the procfs probe data list s.op->newline() << "static struct stap_procfs_probe stap_procfs_probes[] = {"; s.op->indent(1); buf_index = 0; for (p_b_p_iterator it = probes_by_path.begin(); it != probes_by_path.end(); it++) { procfs_probe_set *pset = it->second; s.op->newline() << "{"; s.op->line() << " .path=" << lex_cast_qstring (it->first) << ","; if (pset->read_probe != NULL) s.op->line() << " .read_probe=" << common_probe_init (pset->read_probe) << ","; if (pset->write_probe != NULL) s.op->line() << " .write_probe=" << common_probe_init (pset->write_probe) << ","; s.op->line() << " .buffer=stap_procfs_probe_buffers.buf_" << buf_index++ << ","; if (pset->read_probe != NULL) { if (pset->read_probe->maxsize_val == 0) s.op->line() << " .bufsize=STP_PROCFS_BUFSIZE,"; else s.op->line() << " .bufsize=" << pset->read_probe->maxsize_val << ","; } else s.op->line() << " .bufsize=MAXSTRINGLEN,"; s.op->line() << " .permissions=" << (((pset->read_probe ? 0444 : 0) | (pset->write_probe ? 0222 : 0)) &~ ((pset->read_probe ? pset->read_probe->umask : 0) | (pset->write_probe ? pset->write_probe->umask : 0))) << ","; s.op->line() << " },"; } s.op->newline(-1) << "};"; // Output routine to fill in the buffer with our data. Note that we // need to do this even in the case where we have no read probes, // but we can skip most of it then. s.op->newline(); s.op->newline() << "static int _stp_proc_fill_read_buffer(struct stap_procfs_probe *spp) {"; s.op->indent(1); if (has_read_probes) { s.op->newline() << "struct _stp_procfs_data pdata;"; common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "spp->read_probe", "stp_probe_type_procfs"); s.op->newline() << "pdata.buffer = spp->buffer;"; s.op->newline() << "pdata.bufsize = spp->bufsize;"; s.op->newline() << "if (c->ips.procfs_data == NULL)"; s.op->newline(1) << "c->ips.procfs_data = &pdata;"; s.op->newline(-1) << "else {"; s.op->newline(1) << "if (unlikely (atomic_inc_return (skipped_count()) > MAXSKIPPED)) {"; s.op->newline(1) << "atomic_set (session_state(), STAP_SESSION_ERROR);"; s.op->newline() << "_stp_exit ();"; s.op->newline(-1) << "}"; s.op->newline() << "atomic_dec (& c->busy);"; s.op->newline() << "goto probe_epilogue;"; s.op->newline(-1) << "}"; // call probe function s.op->newline() << "(*spp->read_probe->ph) (c);"; // Note that _procfs_value_set copied string data into spp->buffer s.op->newline() << "c->ips.procfs_data = NULL;"; s.op->newline() << "spp->needs_fill = 0;"; s.op->newline() << "spp->count = strlen(spp->buffer);"; common_probe_entryfn_epilogue (s, true); s.op->newline() << "if (spp->needs_fill) {"; s.op->newline(1) << "spp->needs_fill = 0;"; s.op->newline() << "return -EIO;"; s.op->newline(-1) << "}"; } s.op->newline() << "return 0;"; s.op->newline(-1) << "}"; // Output routine to read data. Note that we need to do this even // in the case where we have no write probes, but we can skip most // of it then. s.op->newline() << "static int _stp_process_write_buffer(struct stap_procfs_probe *spp, const char __user *buf, size_t count) {"; s.op->indent(1); s.op->newline() << "int retval = 0;"; if (has_write_probes) { s.op->newline() << "struct _stp_procfs_data pdata;"; common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "spp->write_probe", "stp_probe_type_procfs"); // We've got 2 problems here. The data count could be greater // than MAXSTRINGLEN or greater than the bufsize (if the same // procfs file had a size less than MAXSTRINGLEN). s.op->newline() << "if (count >= MAXSTRINGLEN)"; s.op->newline(1) << "count = MAXSTRINGLEN - 1;"; s.op->indent(-1); s.op->newline() << "pdata.bufsize = spp->bufsize;"; s.op->newline() << "if (count >= pdata.bufsize)"; s.op->newline(1) << "count = pdata.bufsize - 1;"; s.op->indent(-1); s.op->newline() << "pdata.buffer = (char *)buf;"; s.op->newline() << "pdata.count = count;"; s.op->newline() << "if (c->ips.procfs_data == NULL)"; s.op->newline(1) << "c->ips.procfs_data = &pdata;"; s.op->newline(-1) << "else {"; s.op->newline(1) << "if (unlikely (atomic_inc_return (skipped_count()) > MAXSKIPPED)) {"; s.op->newline(1) << "atomic_set (session_state(), STAP_SESSION_ERROR);"; s.op->newline() << "_stp_exit ();"; s.op->newline(-1) << "}"; s.op->newline() << "atomic_dec (& c->busy);"; s.op->newline() << "goto probe_epilogue;"; s.op->newline(-1) << "}"; // call probe function s.op->newline() << "(*spp->write_probe->ph) (c);"; s.op->newline() << "c->ips.procfs_data = NULL;"; s.op->newline() << "if (c->last_error == 0) {"; s.op->newline(1) << "retval = count;"; s.op->newline(-1) << "}"; common_probe_entryfn_epilogue (s, true); } s.op->newline() << "return retval;"; s.op->newline(-1) << "}"; } void procfs_derived_probe_group::emit_module_init (systemtap_session& s) { if (probes_by_path.empty()) return; s.op->newline() << "for (i = 0; i < " << probes_by_path.size() << "; i++) {"; s.op->newline(1) << "struct stap_procfs_probe *spp = &stap_procfs_probes[i];"; s.op->newline() << "if (spp->read_probe)"; s.op->newline(1) << "probe_point = spp->read_probe->pp;"; s.op->newline(-1) << "else"; s.op->newline(1) << "probe_point = spp->write_probe->pp;"; s.op->indent(-1); s.op->newline() << "_spp_init(spp);"; s.op->newline() << "rc = _stp_create_procfs(spp->path, i, &_stp_proc_fops, spp->permissions, spp);"; s.op->newline() << "if (rc) {"; s.op->newline(1) << "_stp_close_procfs();"; s.op->newline() << "for (i = 0; i < " << probes_by_path.size() << "; i++) {"; s.op->newline(1) << "spp = &stap_procfs_probes[i];"; s.op->newline() << "_spp_shutdown(spp);"; s.op->newline(-1) << "}"; s.op->newline() << "break;"; s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; // for loop } void procfs_derived_probe_group::emit_module_exit (systemtap_session& s) { if (probes_by_path.empty()) return; s.op->newline() << "_stp_close_procfs();"; s.op->newline() << "for (i = 0; i < " << probes_by_path.size() << "; i++) {"; s.op->newline(1) << "struct stap_procfs_probe *spp = &stap_procfs_probes[i];"; s.op->newline() << "_spp_shutdown(spp);"; s.op->newline(-1) << "}"; } procfs_var_expanding_visitor::procfs_var_expanding_visitor (systemtap_session& s, const string& pn, string path, bool write_probe): sess (s), probe_name (pn), path (path), write_probe (write_probe), target_symbol_seen (false) { // procfs probes can also handle '.='. valid_ops.insert (".="); } void procfs_var_expanding_visitor::visit_target_symbol (target_symbol* e) { try { assert(e->name.size() > 0 && e->name[0] == '$'); if (e->name != "$value") throw semantic_error (_("invalid target symbol for procfs probe, $value expected"), e->tok); e->assert_no_components("procfs"); bool lvalue = is_active_lvalue(e); if (write_probe && lvalue) throw semantic_error(_("procfs $value variable is read-only in a procfs write probe"), e->tok); else if (! write_probe && ! lvalue) throw semantic_error(_("procfs $value variable cannot be read in a procfs read probe"), e->tok); if (e->addressof) throw semantic_error(_("cannot take address of procfs variable"), e->tok); // Remember that we've seen a target variable. target_symbol_seen = true; // Synthesize a function. functiondecl *fdecl = new functiondecl; fdecl->synthetic = true; fdecl->tok = e->tok; embeddedcode *ec = new embeddedcode; ec->tok = e->tok; string fname; string locvalue = "CONTEXT->ips.procfs_data"; if (! lvalue) { fname = "_procfs_value_get"; ec->code = string(" struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue + string("); /* pure */\n") + string(" _stp_copy_from_user(STAP_RETVALUE, data->buffer, data->count);\n") + string(" STAP_RETVALUE[data->count] = '\\0';\n"); } else // lvalue { if (*op == "=") { fname = "_procfs_value_set"; ec->code = string("struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue + string(");\n") + string(" strlcpy(data->buffer, STAP_ARG_value, data->bufsize);\n") + string(" data->count = strlen(data->buffer);\n"); } else if (*op == ".=") { fname = "_procfs_value_append"; ec->code = string("struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue + string(");\n") + string(" strlcat(data->buffer, STAP_ARG_value, data->bufsize);\n") + string(" data->count = strlen(data->buffer);\n"); } else { throw semantic_error (_("Only the following assign operators are" " implemented on procfs read target variables:" " '=', '.='"), e->tok); } } fname += lex_cast(++tick); fdecl->name = fname; fdecl->body = ec; fdecl->type = pe_string; if (lvalue) { // Modify the fdecl so it carries a single pe_string formal // argument called "value". vardecl *v = new vardecl; v->type = pe_string; v->name = "value"; v->tok = e->tok; fdecl->formal_args.push_back(v); } fdecl->join (sess); // Synthesize a functioncall. functioncall* n = new functioncall; n->tok = e->tok; n->function = fname; if (lvalue) { // Provide the functioncall to our parent, so that it can be // used to substitute for the assignment node immediately above // us. assert(!target_symbol_setter_functioncalls.empty()); *(target_symbol_setter_functioncalls.top()) = n; } provide (n); } catch (const semantic_error &er) { e->chain (er); provide (e); } } struct procfs_builder: public derived_probe_builder { procfs_builder() {} virtual void build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results); }; void procfs_builder::build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results) { string path; bool has_procfs = get_param(parameters, TOK_PROCFS, path); bool has_read = (parameters.find(TOK_READ) != parameters.end()); bool has_write = (parameters.find(TOK_WRITE) != parameters.end()); bool has_umask = (parameters.find(TOK_UMASK) != parameters.end()); int64_t maxsize_val = 0; int64_t umask_val; if(has_umask) get_param(parameters, TOK_UMASK, umask_val); else /* no .umask */ { if(has_read) umask_val = 0044; else if(has_write) umask_val = 0022; else assert(0); } // Validate '.maxsize(NNN)', if it exists. if (get_param(parameters, TOK_MAXSIZE, maxsize_val)) { if (maxsize_val <= 0) throw semantic_error (_("maxsize must be greater than 0")); } // If no procfs path, default to "command". The runtime will do // this for us, but if we don't do it here, we'll think the // following 2 probes are attached to different paths: // // probe procfs("command").read {}" // probe procfs.write {} if (! has_procfs) path = "command"; // If we have a path, we need to validate it. else { string::size_type start_pos, end_pos; string component; start_pos = 0; while ((end_pos = path.find('/', start_pos)) != string::npos) { // Make sure it doesn't start with '/'. if (end_pos == 0) throw semantic_error (_("procfs path cannot start with a '/'"), location->components.front()->tok); component = path.substr(start_pos, end_pos - start_pos); // Make sure it isn't empty. if (component.size() == 0) throw semantic_error (_("procfs path component cannot be empty"), location->components.front()->tok); // Make sure it isn't relative. else if (component == "." || component == "..") throw semantic_error (_("procfs path cannot be relative (and contain '.' or '..')"), location->components.front()->tok); start_pos = end_pos + 1; } component = path.substr(start_pos); // Make sure it doesn't end with '/'. if (component.size() == 0) throw semantic_error (_("procfs path cannot end with a '/'"), location->components.front()->tok); // Make sure it isn't relative. else if (component == "." || component == "..") throw semantic_error (_("procfs path cannot be relative (and contain '.' or '..')"), location->components.front()->tok); } if (!(has_read ^ has_write)) throw semantic_error (_("need read/write component"), location->components.front()->tok); finished_results.push_back(new procfs_derived_probe(sess, base, location, path, has_write, maxsize_val, umask_val)); } void register_tapset_procfs(systemtap_session& s) { match_node* root = s.pattern_root; derived_probe_builder *builder = new procfs_builder(); root->bind(TOK_PROCFS)->bind(TOK_READ)->bind(builder); root->bind(TOK_PROCFS)->bind_num(TOK_UMASK)->bind(TOK_READ)->bind(builder); root->bind(TOK_PROCFS)->bind(TOK_READ)->bind_num(TOK_MAXSIZE)->bind(builder); root->bind(TOK_PROCFS)->bind_num(TOK_UMASK)->bind(TOK_READ)->bind_num(TOK_MAXSIZE)->bind(builder); root->bind_str(TOK_PROCFS)->bind(TOK_READ)->bind(builder); root->bind_str(TOK_PROCFS)->bind_num(TOK_UMASK)->bind(TOK_READ)->bind(builder); root->bind_str(TOK_PROCFS)->bind(TOK_READ)->bind_num(TOK_MAXSIZE)->bind(builder); root->bind_str(TOK_PROCFS)->bind_num(TOK_UMASK)->bind(TOK_READ)->bind_num(TOK_MAXSIZE)->bind(builder); root->bind(TOK_PROCFS)->bind(TOK_WRITE)->bind(builder); root->bind(TOK_PROCFS)->bind_num(TOK_UMASK)->bind(TOK_WRITE)->bind(builder); root->bind_str(TOK_PROCFS)->bind(TOK_WRITE)->bind(builder); root->bind_str(TOK_PROCFS)->bind_num(TOK_UMASK)->bind(TOK_WRITE)->bind(builder); } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/tapset-timers.cxx000066400000000000000000000556731217430427200167560ustar00rootroot00000000000000// tapset for timers // Copyright (C) 2005-2011 Red Hat Inc. // Copyright (C) 2005-2007 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "session.h" #include "tapsets.h" #include "translate.h" #include "util.h" #include #include using namespace std; using namespace __gnu_cxx; static const string TOK_TIMER("timer"); // ------------------------------------------------------------------------ // timer derived probes // ------------------------------------------------------------------------ struct timer_derived_probe: public derived_probe { int64_t interval, randomize; bool time_is_msecs; // NB: hrtimers get ms-based probes on modern kernels instead timer_derived_probe (probe* p, probe_point* l, int64_t i, int64_t r, bool ms=false); virtual void join_group (systemtap_session& s); // No assertion need be emitted, since this probe is allowed for unprivileged // users. void emit_privilege_assertion (translator_output*) {} void print_dupe_stamp(ostream& o) { print_dupe_stamp_unprivileged (o); } }; struct timer_derived_probe_group: public generic_dpg { void emit_interval (translator_output* o); public: void emit_module_decls (systemtap_session& s); void emit_module_init (systemtap_session& s); void emit_module_exit (systemtap_session& s); }; timer_derived_probe::timer_derived_probe (probe* p, probe_point* l, int64_t i, int64_t r, bool ms): derived_probe (p, l), interval (i), randomize (r), time_is_msecs(ms) { if (interval <= 0 || interval > 1000000) // make i and r fit into plain ints //TRANSLATORS: 'timer' is the name of a probe point throw semantic_error (_("invalid interval for jiffies timer")); // randomize = 0 means no randomization if (randomize < 0 || randomize > interval) //TRANSLATORS: 'randomize' is a key word throw semantic_error (_("invalid randomize for jiffies timer")); if (locations.size() != 1) throw semantic_error (_("only expect one probe point")); // so we don't have to loop over them in the other functions } void timer_derived_probe::join_group (systemtap_session& s) { if (! s.timer_derived_probes) s.timer_derived_probes = new timer_derived_probe_group (); s.timer_derived_probes->enroll (this); } void timer_derived_probe_group::emit_interval (translator_output* o) { o->line() << "({"; o->newline(1) << "unsigned i = stp->intrv;"; o->newline() << "if (stp->rnd != 0)"; o->newline(1) << "i += _stp_random_pm(stp->rnd);"; o->newline(-1) << "stp->ms ? msecs_to_jiffies(i) : i;"; o->newline(-1) << "})"; } void timer_derived_probe_group::emit_module_decls (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "/* ---- timer probes ---- */"; s.op->newline() << "static struct stap_timer_probe {"; s.op->newline(1) << "struct timer_list timer_list;"; s.op->newline() << "const struct stap_probe * const probe;"; s.op->newline() << "unsigned intrv, ms, rnd;"; s.op->newline(-1) << "} stap_timer_probes [" << probes.size() << "] = {"; s.op->indent(1); for (unsigned i=0; i < probes.size(); i++) { s.op->newline () << "{"; s.op->line() << " .probe=" << common_probe_init (probes[i]) << ","; s.op->line() << " .intrv=" << probes[i]->interval << ","; s.op->line() << " .ms=" << probes[i]->time_is_msecs << ","; s.op->line() << " .rnd=" << probes[i]->randomize; s.op->line() << " },"; } s.op->newline(-1) << "};"; s.op->newline(); s.op->newline() << "static void enter_timer_probe (unsigned long val) {"; s.op->newline(1) << "struct stap_timer_probe* stp = & stap_timer_probes [val];"; s.op->newline() << "if ((atomic_read (session_state()) == STAP_SESSION_STARTING) ||"; s.op->newline() << " (atomic_read (session_state()) == STAP_SESSION_RUNNING))"; s.op->newline(1) << "mod_timer (& stp->timer_list, jiffies + "; emit_interval (s.op); s.op->line() << ");"; s.op->newline(-1) << "{"; s.op->indent(1); common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "stp->probe", "stp_probe_type_timer"); s.op->newline() << "(*stp->probe->ph) (c);"; common_probe_entryfn_epilogue (s, true); s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; } void timer_derived_probe_group::emit_module_init (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {"; s.op->newline(1) << "struct stap_timer_probe* stp = & stap_timer_probes [i];"; s.op->newline() << "probe_point = stp->probe->pp;"; s.op->newline() << "init_timer (& stp->timer_list);"; s.op->newline() << "stp->timer_list.function = & enter_timer_probe;"; s.op->newline() << "stp->timer_list.data = i;"; // NB: important! // copy timer renew calculations from above :-( s.op->newline() << "stp->timer_list.expires = jiffies + "; emit_interval (s.op); s.op->line() << ";"; s.op->newline() << "add_timer (& stp->timer_list);"; // note: no partial failure rollback is needed: add_timer cannot fail. s.op->newline(-1) << "}"; // for loop } void timer_derived_probe_group::emit_module_exit (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "for (i=0; i<" << probes.size() << "; i++)"; s.op->newline(1) << "del_timer_sync (& stap_timer_probes[i].timer_list);"; s.op->indent(-1); } // ------------------------------------------------------------------------ // hrtimer derived probes // ------------------------------------------------------------------------ // This is a new timer interface that provides more flexibility in specifying // intervals, and uses the hrtimer APIs when available for greater precision. // While hrtimers were added in 2.6.16, the API's weren't exported until // 2.6.17, so we must check this kernel version before attempting to use // hrtimers. // // * hrtimer_derived_probe: creates a probe point based on the hrtimer APIs. struct hrtimer_derived_probe: public derived_probe { // set a (generous) maximum of one day in ns static const int64_t max_ns_interval = 1000000000LL * 60LL * 60LL * 24LL; // 100us seems like a reasonable minimum static const int64_t min_ns_interval = 100000LL; int64_t interval, randomize; hrtimer_derived_probe (probe* p, probe_point* l, int64_t i, int64_t r, int64_t scale): derived_probe (p, l), interval (i), randomize (r) { if ((i < min_ns_interval) || (i > max_ns_interval)) throw semantic_error(_F("interval value out of range (%s, %s)", (lex_cast(scale < min_ns_interval ? min_ns_interval/scale : 1).c_str()), lex_cast(max_ns_interval/scale).c_str())); // randomize = 0 means no randomization if ((r < 0) || (r > i)) throw semantic_error(_("randomization value out of range")); } void join_group (systemtap_session& s); // No assertion need be emitted, since these probes are allowed for // unprivileged users. void emit_privilege_assertion (translator_output*) {} void print_dupe_stamp(ostream& o) { print_dupe_stamp_unprivileged (o); } }; struct hrtimer_derived_probe_group: public generic_dpg { public: void emit_module_decls (systemtap_session& s); void emit_module_init (systemtap_session& s); void emit_module_exit (systemtap_session& s); }; void hrtimer_derived_probe::join_group (systemtap_session& s) { if (! s.hrtimer_derived_probes) s.hrtimer_derived_probes = new hrtimer_derived_probe_group (); s.hrtimer_derived_probes->enroll (this); } void hrtimer_derived_probe_group::emit_module_decls (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "/* ---- hrtimer probes ---- */"; s.op->newline() << "#include \"timer.c\""; s.op->newline() << "static struct stap_hrtimer_probe stap_hrtimer_probes [" << probes.size() << "] = {"; s.op->indent(1); for (unsigned i=0; i < probes.size(); i++) { s.op->newline () << "{"; s.op->line() << " .probe=" << common_probe_init (probes[i]) << ","; s.op->line() << " .intrv=" << probes[i]->interval << "LL,"; s.op->line() << " .rnd=" << probes[i]->randomize << "LL"; s.op->line() << " },"; } s.op->newline(-1) << "};"; s.op->newline(); if (!s.runtime_usermode_p()) { s.op->newline() << "static hrtimer_return_t _stp_hrtimer_notify_function (struct hrtimer *timer) {"; s.op->newline(1) << "int rc = HRTIMER_NORESTART;"; s.op->newline() << "struct stap_hrtimer_probe *stp = container_of(timer, struct stap_hrtimer_probe, hrtimer);"; // Update the timer with the next trigger time s.op->newline() << "if ((atomic_read (session_state()) == STAP_SESSION_STARTING) ||"; s.op->newline() << " (atomic_read (session_state()) == STAP_SESSION_RUNNING)) {"; s.op->newline(1) << "_stp_hrtimer_update(stp);"; s.op->newline() << "rc = HRTIMER_RESTART;"; s.op->newline(-1) << "}"; s.op->newline() << "{"; s.op->indent(1); common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "stp->probe", "stp_probe_type_hrtimer"); s.op->newline() << "(*stp->probe->ph) (c);"; common_probe_entryfn_epilogue (s, true); s.op->newline(-1) << "}"; s.op->newline() << "return rc;"; s.op->newline(-1) << "}"; } else { s.op->newline() << "static void _stp_hrtimer_notify_function (sigval_t value)"; s.op->newline(1) << "{"; s.op->newline() << "struct stap_hrtimer_probe *stp = value.sival_ptr;"; // Update the timer with the next trigger time s.op->newline() << "if ((atomic_read (session_state()) == STAP_SESSION_STARTING) ||"; s.op->newline() << " (atomic_read (session_state()) == STAP_SESSION_RUNNING)) {"; s.op->newline(1) << "_stp_hrtimer_update(stp);"; s.op->newline(-1) << "}"; s.op->newline() << "{"; s.op->indent(1); common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "stp->probe", "stp_probe_type_hrtimer"); s.op->newline() << "(*stp->probe->ph) (c);"; common_probe_entryfn_epilogue (s, true); s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; } } void hrtimer_derived_probe_group::emit_module_init (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "_stp_hrtimer_init();"; s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {"; s.op->newline(1) << "struct stap_hrtimer_probe* stp = & stap_hrtimer_probes [i];"; s.op->newline() << "probe_point = stp->probe->pp;"; // Note: no partial failure rollback is needed for kernel hrtimer // probes (hrtimer_start only "fails" if the timer was already // active, which cannot be). But, stapdyn timer probes need a // rollback, and it won't hurt the kernel hrtimers. s.op->newline() << "rc = _stp_hrtimer_create(stp, _stp_hrtimer_notify_function);"; s.op->newline() << "if (rc) {"; s.op->indent(1); s.op->newline() << "for (j=i-1; j>=0; j--)"; // partial rollback s.op->newline(1) << "_stp_hrtimer_cancel(& stap_hrtimer_probes[j]);"; s.op->newline(-1) << "break;"; // don't attempt to register any more s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; // for loop } void hrtimer_derived_probe_group::emit_module_exit (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "for (i=0; i<" << probes.size() << "; i++)"; s.op->indent(1); s.op->newline() << "_stp_hrtimer_cancel(& stap_hrtimer_probes[i]);"; s.op->indent(-1); } // ------------------------------------------------------------------------ // profile derived probes // ------------------------------------------------------------------------ // On kernels < 2.6.10, this uses the register_profile_notifier API to // generate the timed events for profiling; on kernels >= 2.6.10 this // uses the register_timer_hook API. The latter doesn't currently allow // simultaneous users, so insertion will fail if the profiler is busy. // (Conflicting users may include OProfile, other SystemTap probes, etc.) struct profile_derived_probe: public derived_probe { profile_derived_probe (systemtap_session &s, probe* p, probe_point* l); void join_group (systemtap_session& s); }; struct profile_derived_probe_group: public generic_dpg { public: void emit_module_decls (systemtap_session& s); void emit_module_init (systemtap_session& s); void emit_module_exit (systemtap_session& s); }; profile_derived_probe::profile_derived_probe (systemtap_session &, probe* p, probe_point* l): derived_probe(p, l) { } void profile_derived_probe::join_group (systemtap_session& s) { if (! s.profile_derived_probes) s.profile_derived_probes = new profile_derived_probe_group (); s.profile_derived_probes->enroll (this); } // timer.profile probe handlers are hooked up in an entertaining way // to the underlying kernel facility. The fact that 2.6.11+ era // "register_timer_hook" API allows only one consumer *system-wide* // will give a hint. We will have a single entry function (and thus // trivial registration / unregistration), and it will call all probe // handler functions in sequence. void profile_derived_probe_group::emit_module_decls (systemtap_session& s) { if (probes.empty()) return; // kernels < 2.6.10: use register_profile_notifier API // kernels >= 2.6.10: use register_timer_hook API s.op->newline() << "/* ---- profile probes ---- */"; // This function calls all the profiling probe handlers in sequence. // The only tricky thing is that the context will be reused amongst // them. While a simple sequence of calls to the individual probe // handlers is unlikely to go terribly wrong (with c->last_error // being set causing an early return), but for extra assurance, we // open-code the same logic here. s.op->newline() << "static void enter_all_profile_probes (struct pt_regs *regs) {"; s.op->newline(1) << "const struct stap_probe * probe = " << common_probe_init (probes[0]) << ";"; common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "probe", "stp_probe_type_profile_timer"); // Timer interrupts save all registers, so if the interrupt happened // in user space we can rely on it being the full user pt_regs. s.op->newline() << "if (user_mode(regs)) {"; s.op->newline(1) << "c->user_mode_p = 1;"; s.op->newline() << "c->uregs = regs;"; s.op->newline(-1) << "} else {"; s.op->newline(1) << "c->kregs = regs;"; s.op->newline(-1) << "}"; for (unsigned i=0; i 0) { // Some lightweight inter-probe context resetting // XXX: not quite right: MAXERRORS not respected // XXX: STP_TIMING stats are also not correct s.op->newline() << "probe = " << common_probe_init (probes[i]) << ";"; s.op->newline() << "#ifdef STP_NEED_PROBE_NAME"; s.op->newline() << "c->probe_name = probe->pn;"; s.op->newline() << "#endif"; if(!s.suppress_time_limits) { s.op->newline() << "c->actionremaining = MAXACTION;"; } } s.op->newline() << "if (c->last_error == NULL) probe->ph (c);"; } common_probe_entryfn_epilogue (s, true); s.op->newline(-1) << "}"; s.op->newline() << "#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)"; // == using_rpn of yore s.op->newline() << "static int enter_profile_probes (struct notifier_block *self," << " unsigned long val, void *data) {"; s.op->newline(1) << "(void) self; (void) val;"; s.op->newline() << "enter_all_profile_probes ((struct pt_regs *) data);"; s.op->newline() << "return 0;"; s.op->newline(-1) << "}"; s.op->newline() << "struct notifier_block stap_profile_notifier = {" << " .notifier_call = & enter_profile_probes };"; s.op->newline() << "#else"; s.op->newline() << "static int enter_profile_probes (struct pt_regs *regs) {"; s.op->newline(1) << "enter_all_profile_probes (regs);"; s.op->newline() << "return 0;"; s.op->newline(-1) << "}"; s.op->newline() << "#endif"; } void profile_derived_probe_group::emit_module_init (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "probe_point = \"timer.profile\";"; // NB: hard-coded for convenience s.op->newline() << "#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)"; // == using_rpn of yore s.op->newline() << "rc = register_profile_notifier (& stap_profile_notifier);"; s.op->newline() << "#else"; s.op->newline() << "rc = register_timer_hook (& enter_profile_probes);"; s.op->newline() << "#endif"; } void profile_derived_probe_group::emit_module_exit (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)"; // == using_rpn of yore s.op->newline() << "unregister_profile_notifier (& stap_profile_notifier);"; s.op->newline() << "#else"; s.op->newline() << "unregister_timer_hook (& enter_profile_probes);"; s.op->newline() << "#endif"; } // ------------------------------------------------------------------------ // unified probe builder for timer probes // ------------------------------------------------------------------------ struct timer_builder: public derived_probe_builder { virtual void build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results); static void register_patterns(systemtap_session& s); }; void timer_builder::build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results) { int64_t scale=1, period, rand=0; if (has_null_param(parameters, "profile")) { if (sess.runtime_usermode_p()) throw semantic_error (_("profile timer probes not available with the dyninst runtime")); /* As the latest mechanism for timer hook support has been removed, we need to bail explicitly if the corresponding symbols are missing: */ if ((sess.kernel_exports.find("register_timer_hook") == sess.kernel_exports.end() || sess.kernel_exports.find("unregister_timer_hook") == sess.kernel_exports.end()) && (sess.kernel_exports.find("register_profile_notifier") == sess.kernel_exports.end() || sess.kernel_exports.find("unregister_profile_notifier") == sess.kernel_exports.end())) throw semantic_error (_("profiling timer support (register_timer_hook) not found in kernel!")); sess.unwindsym_modules.insert ("kernel"); finished_results.push_back (new profile_derived_probe(sess, base, location)); return; } if (!get_param(parameters, "randomize", rand)) rand = 0; if (get_param(parameters, "jiffies", period)) { if (sess.runtime_usermode_p()) throw semantic_error (_("jiffies timer probes not available with the dyninst runtime")); // always use basic timers for jiffies finished_results.push_back (new timer_derived_probe(base, location, period, rand, false)); return; } else if (get_param(parameters, "hz", period)) { if (period <= 0) throw semantic_error (_("frequency must be greater than 0")); period = (1000000000 + period - 1)/period; } else if (get_param(parameters, "s", period) || get_param(parameters, "sec", period)) { scale = 1000000000; period *= scale; rand *= scale; } else if (get_param(parameters, "ms", period) || get_param(parameters, "msec", period)) { scale = 1000000; period *= scale; rand *= scale; } else if (get_param(parameters, "us", period) || get_param(parameters, "usec", period)) { scale = 1000; period *= scale; rand *= scale; } else if (get_param(parameters, "ns", period) || get_param(parameters, "nsec", period)) { // ok } else throw semantic_error (_("unrecognized timer variant")); // Redirect wallclock-time based probes to hrtimer code on recent // enough kernels. if (strverscmp(sess.kernel_base_release.c_str(), "2.6.17") < 0) { // hrtimers didn't exist, so use the old-school timers period = (period + 1000000 - 1)/1000000; rand = (rand + 1000000 - 1)/1000000; finished_results.push_back (new timer_derived_probe(base, location, period, rand, true)); } else finished_results.push_back (new hrtimer_derived_probe(base, location, period, rand, scale)); } void register_tapset_timers(systemtap_session& s) { match_node* root = s.pattern_root; derived_probe_builder *builder = new timer_builder(); root = root->bind(TOK_TIMER); root->bind_num("s") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("s")->bind_num("randomize") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("sec") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("sec")->bind_num("randomize") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("ms") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("ms")->bind_num("randomize") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("msec") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("msec")->bind_num("randomize") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("us") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("us")->bind_num("randomize") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("usec") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("usec")->bind_num("randomize") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("ns") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("ns")->bind_num("randomize") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("nsec") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("nsec")->bind_num("randomize") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("jiffies") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("jiffies")->bind_num("randomize") ->bind_privilege(pr_all) ->bind(builder); root->bind_num("hz") ->bind_privilege(pr_all) ->bind(builder); // Not ok for unprivileged users, because register_timer_hook only // allows a single attached callback. No resource-sharing -> no // unprivileged access. // // Sigh, but for dyninst users, we want a semantic error that // profile probes aren't supported (which will come from // timer_builder::build()), not a privilege error. So, we'll fake // it so that profile probes are allowed for all. if (!s.runtime_usermode_p()) { root->bind("profile") ->bind("tick") ->bind(builder); } else { root->bind("profile") ->bind("tick") ->bind_privilege(pr_all) ->bind(builder); } } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/tapset-utrace.cxx000066400000000000000000001215701217430427200167240ustar00rootroot00000000000000// utrace tapset // Copyright (C) 2005-2013 Red Hat Inc. // Copyright (C) 2005-2007 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "session.h" #include "tapsets.h" #include "task_finder.h" #include "tapset-dynprobe.h" #include "translate.h" #include "util.h" #include #include using namespace std; using namespace __gnu_cxx; static const string TOK_PROCESS("process"); static const string TOK_BEGIN("begin"); static const string TOK_END("end"); static const string TOK_THREAD("thread"); static const string TOK_SYSCALL("syscall"); static const string TOK_RETURN("return"); // ------------------------------------------------------------------------ // utrace user-space probes // ------------------------------------------------------------------------ // Note that these flags don't match up exactly with UTRACE_EVENT // flags (and that's OK). enum utrace_derived_probe_flags { UDPF_NONE, UDPF_BEGIN, // process begin UDPF_END, // process end UDPF_THREAD_BEGIN, // thread begin UDPF_THREAD_END, // thread end UDPF_SYSCALL, // syscall entry UDPF_SYSCALL_RETURN, // syscall exit UDPF_NFLAGS }; struct utrace_derived_probe: public derived_probe { bool has_path; string path; bool has_library; string library; int64_t pid; enum utrace_derived_probe_flags flags; bool target_symbol_seen; utrace_derived_probe (systemtap_session &s, probe* p, probe_point* l, bool hp, string &pn, int64_t pd, enum utrace_derived_probe_flags f); void join_group (systemtap_session& s); void emit_privilege_assertion (translator_output*); void print_dupe_stamp(ostream& o); void getargs (std::list &arg_set) const; }; struct utrace_derived_probe_group: public generic_dpg { private: map > probes_by_path; typedef map >::iterator p_b_path_iterator; map > probes_by_pid; typedef map >::iterator p_b_pid_iterator; unsigned num_probes; bool flags_seen[UDPF_NFLAGS]; // Using the linux backend void emit_linux_probe_decl (systemtap_session& s, utrace_derived_probe *p); void emit_module_linux_decls (systemtap_session& s); void emit_module_linux_init (systemtap_session& s); void emit_module_linux_exit (systemtap_session& s); // Using the dyninst backend (via stapdyn) void emit_dyninst_probe_decl (systemtap_session& s, const string& path, utrace_derived_probe *p); void emit_module_dyninst_decls (systemtap_session& s); void emit_module_dyninst_init (systemtap_session& s); void emit_module_dyninst_exit (systemtap_session& s); public: utrace_derived_probe_group(): num_probes(0), flags_seen() { } void enroll (utrace_derived_probe* probe); void emit_module_decls (systemtap_session& s); void emit_module_init (systemtap_session& s); void emit_module_exit (systemtap_session& s); }; struct utrace_var_expanding_visitor: public var_expanding_visitor { utrace_var_expanding_visitor(systemtap_session& s, probe_point* l, const string& pn, enum utrace_derived_probe_flags f): sess (s), base_loc (l), probe_name (pn), flags (f), target_symbol_seen (false), add_block(NULL), add_probe(NULL) {} systemtap_session& sess; probe_point* base_loc; string probe_name; enum utrace_derived_probe_flags flags; bool target_symbol_seen; block *add_block; probe *add_probe; std::map return_ts_map; void visit_target_symbol_arg (target_symbol* e); void visit_target_symbol_context (target_symbol* e); void visit_target_symbol_cached (target_symbol* e); void visit_target_symbol (target_symbol* e); }; utrace_derived_probe::utrace_derived_probe (systemtap_session &s, probe* p, probe_point* l, bool hp, string &pn, int64_t pd, enum utrace_derived_probe_flags f): derived_probe (p, l, true /* .components soon rewritten */ ), has_path(hp), path(pn), has_library(false), pid(pd), flags(f), target_symbol_seen(false) { check_process_probe_kernel_support(s); // Expand local variables in the probe body utrace_var_expanding_visitor v (s, l, name, flags); v.replace (this->body); target_symbol_seen = v.target_symbol_seen; // If during target-variable-expanding the probe, we added a new block // of code, add it to the start of the probe. if (v.add_block) this->body = new block(v.add_block, this->body); // If when target-variable-expanding the probe, we added a new // probe, add it in a new file to the list of files to be processed. if (v.add_probe) { stapfile *f = new stapfile; f->probes.push_back(v.add_probe); s.files.push_back(f); } // Reset the sole element of the "locations" vector as a // "reverse-engineered" form of the incoming (q.base_loc) probe // point. This allows a user to see what program etc. // number any particular match of the wildcards. vector comps; if (hp) comps.push_back (new probe_point::component(TOK_PROCESS, new literal_string(path))); else if (pid != 0) comps.push_back (new probe_point::component(TOK_PROCESS, new literal_number(pid))); else comps.push_back (new probe_point::component(TOK_PROCESS)); switch (flags) { case UDPF_THREAD_BEGIN: comps.push_back (new probe_point::component(TOK_THREAD)); comps.push_back (new probe_point::component(TOK_BEGIN)); break; case UDPF_THREAD_END: comps.push_back (new probe_point::component(TOK_THREAD)); comps.push_back (new probe_point::component(TOK_END)); break; case UDPF_SYSCALL: comps.push_back (new probe_point::component(TOK_SYSCALL)); break; case UDPF_SYSCALL_RETURN: comps.push_back (new probe_point::component(TOK_SYSCALL)); comps.push_back (new probe_point::component(TOK_RETURN)); break; case UDPF_BEGIN: comps.push_back (new probe_point::component(TOK_BEGIN)); break; case UDPF_END: comps.push_back (new probe_point::component(TOK_END)); break; default: assert (0); } // Overwrite it. this->sole_location()->components = comps; } void utrace_derived_probe::join_group (systemtap_session& s) { if (! s.utrace_derived_probes) { s.utrace_derived_probes = new utrace_derived_probe_group (); } s.utrace_derived_probes->enroll (this); if (s.runtime_usermode_p()) enable_dynprobes(s); else enable_task_finder(s); } void utrace_derived_probe::emit_privilege_assertion (translator_output* o) { // Process end probes can fire for unprivileged users even if the process // does not belong to the user. On example is that process.end will fire // at the end of a process which executes execve on an executable which // has the setuid bit set. When the setuid executable ends, the process.end // will fire even though the owner of the process is different than the // original owner. // Unprivileged users must use check is_myproc() from within any // process.end variant in their script before doing anything "dangerous". if (flags == UDPF_END) return; // Other process probes should only fire for unprivileged users in the // context of processes which they own. Generate an assertion to this effect // as a safety net. emit_process_owner_assertion (o); } void utrace_derived_probe::print_dupe_stamp(ostream& o) { // Process end probes can fire for unprivileged users even if the process // does not belong to the user. On example is that process.end will fire // at the end of a process which executes execve on an executable which // has the setuid bit set. When the setuid executable ends, the process.end // will fire even though the owner of the process is different than the // original owner. // Unprivileged users must use check is_myproc() from within any // process.end variant in their script before doing anything "dangerous". // // Other process probes should only fire for unprivileged users in the // context of processes which they own. if (flags == UDPF_END) print_dupe_stamp_unprivileged (o); else print_dupe_stamp_unprivileged_process_owner (o); } void utrace_derived_probe::getargs(std::list &arg_set) const { arg_set.push_back("$syscall:long"); arg_set.push_back("$arg1:long"); arg_set.push_back("$arg2:long"); arg_set.push_back("$arg3:long"); arg_set.push_back("$arg4:long"); arg_set.push_back("$arg5:long"); arg_set.push_back("$arg6:long"); } void utrace_var_expanding_visitor::visit_target_symbol_cached (target_symbol* e) { // Get the full name of the target symbol. stringstream ts_name_stream; e->print(ts_name_stream); string ts_name = ts_name_stream.str(); // Check and make sure we haven't already seen this target // variable in this return probe. If we have, just return our // last replacement. map::iterator i = return_ts_map.find(ts_name); if (i != return_ts_map.end()) { provide (i->second); return; } // We've got to do several things here to handle target // variables in return probes. // (1) Synthesize a global array which is the cache of the // target variable value. We don't need a nesting level counter // like the dwarf_var_expanding_visitor::visit_target_symbol() // does since a particular thread can only be in one system // calls at a time. The array will look like this: // // _utrace_tvar_{name}_{num} string aname = (string("_utrace_tvar_") + e->sym_name() + "_" + lex_cast(tick++)); vardecl* vd = new vardecl; vd->name = aname; vd->tok = e->tok; sess.globals.push_back (vd); // (2) Create a new code block we're going to insert at the // beginning of this probe to get the cached value into a // temporary variable. We'll replace the target variable // reference with the temporary variable reference. The code // will look like this: // // _utrace_tvar_tid = tid() // _utrace_tvar_{name}_{num}_tmp // = _utrace_tvar_{name}_{num}[_utrace_tvar_tid] // delete _utrace_tvar_{name}_{num}[_utrace_tvar_tid] // (2a) Synthesize the tid temporary expression, which will look // like this: // // _utrace_tvar_tid = tid() symbol* tidsym = new symbol; tidsym->name = string("_utrace_tvar_tid"); tidsym->tok = e->tok; if (add_block == NULL) { add_block = new block; add_block->tok = e->tok; // Synthesize a functioncall to grab the thread id. functioncall* fc = new functioncall; fc->tok = e->tok; fc->function = string("tid"); // Assign the tid to '_utrace_tvar_tid'. assignment* a = new assignment; a->tok = e->tok; a->op = "="; a->left = tidsym; a->right = fc; expr_statement* es = new expr_statement; es->tok = e->tok; es->value = a; add_block->statements.push_back (es); } // (2b) Synthesize an array reference and assign it to a // temporary variable (that we'll use as replacement for the // target variable reference). It will look like this: // // _utrace_tvar_{name}_{num}_tmp // = _utrace_tvar_{name}_{num}[_utrace_tvar_tid] arrayindex* ai_tvar = new arrayindex; ai_tvar->tok = e->tok; symbol* sym = new symbol; sym->name = aname; sym->tok = e->tok; ai_tvar->base = sym; ai_tvar->indexes.push_back(tidsym); symbol* tmpsym = new symbol; tmpsym->name = aname + "_tmp"; tmpsym->tok = e->tok; assignment* a = new assignment; a->tok = e->tok; a->op = "="; a->left = tmpsym; a->right = ai_tvar; expr_statement* es = new expr_statement; es->tok = e->tok; es->value = a; add_block->statements.push_back (es); // (2c) Delete the array value. It will look like this: // // delete _utrace_tvar_{name}_{num}[_utrace_tvar_tid] delete_statement* ds = new delete_statement; ds->tok = e->tok; ds->value = ai_tvar; add_block->statements.push_back (ds); // (3) We need an entry probe that saves the value for us in the // global array we created. Create the entry probe, which will // look like this: // // probe process(PATH_OR_PID).syscall { // _utrace_tvar_tid = tid() // _utrace_tvar_{name}_{num}[_utrace_tvar_tid] = ${param} // } // // Why the temporary for tid()? If we end up caching more // than one target variable, we can reuse the temporary instead // of calling tid() multiple times. if (add_probe == NULL) { add_probe = new probe; add_probe->tok = e->tok; // We need the name of the current probe point, minus the // ".return". Create a new probe point, copying all the // components, stopping when we see the ".return" // component. probe_point* pp = new probe_point; for (unsigned c = 0; c < base_loc->components.size(); c++) { if (base_loc->components[c]->functor == "return") break; else pp->components.push_back(base_loc->components[c]); } pp->optional = base_loc->optional; add_probe->locations.push_back(pp); add_probe->body = new block; add_probe->body->tok = e->tok; // Synthesize a functioncall to grab the thread id. functioncall* fc = new functioncall; fc->tok = e->tok; fc->function = string("tid"); // Assign the tid to '_utrace_tvar_tid'. assignment* a = new assignment; a->tok = e->tok; a->op = "="; a->left = tidsym; a->right = fc; expr_statement* es = new expr_statement; es->tok = e->tok; es->value = a; add_probe->body = new block(add_probe->body, es); vardecl* vd = new vardecl; vd->tok = e->tok; vd->name = tidsym->name; vd->type = pe_long; vd->set_arity(0, e->tok); add_probe->locals.push_back(vd); } // Save the value, like this: // // _utrace_tvar_{name}_{num}[_utrace_tvar_tid] = ${param} a = new assignment; a->tok = e->tok; a->op = "="; a->left = ai_tvar; a->right = e; es = new expr_statement; es->tok = e->tok; es->value = a; add_probe->body = new block(add_probe->body, es); // (4) Provide the '_utrace_tvar_{name}_{num}_tmp' variable to // our parent so it can be used as a substitute for the target // symbol. provide (tmpsym); // (5) Remember this replacement since we might be able to reuse // it later if the same return probe references this target // symbol again. return_ts_map[ts_name] = tmpsym; return; } void utrace_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) { if (flags != UDPF_SYSCALL) throw semantic_error (_("only \"process(PATH_OR_PID).syscall\" support $argN or $$parms."), e->tok); if (e->name == "$$parms") { // copy from tracepoint token* pf_tok = new token(*e->tok); pf_tok->content = "sprintf"; print_format* pf = print_format::create(pf_tok); target_symbol_seen = true; for (unsigned i = 0; i < 6; ++i) { if (i > 0) pf->raw_components += " "; pf->raw_components += "$arg" + lex_cast(i+1); target_symbol *tsym = new target_symbol; tsym->tok = e->tok; tsym->name = "$arg" + lex_cast(i+1); tsym->saved_conversion_error = 0; pf->raw_components += "=%#x"; //FIXME: missing type info functioncall* n = new functioncall; //same as the following n->tok = e->tok; n->function = "_utrace_syscall_arg"; n->referent = 0; literal_number *num = new literal_number(i); num->tok = e->tok; n->args.push_back(num); pf->args.push_back(n); } pf->components = print_format::string_to_components(pf->raw_components); provide (pf); } else // $argN { string argnum_s = e->name.substr(4,e->name.length()-4); int argnum = 0; try { argnum = lex_cast(argnum_s); } catch (const runtime_error& f) // non-integral $arg suffix: e.g. $argKKKSDF { throw semantic_error (_("invalid syscall argument number (1-6)"), e->tok); } e->assert_no_components("utrace"); // FIXME: max argnument number should not be hardcoded. if (argnum < 1 || argnum > 6) throw semantic_error (_("invalid syscall argument number (1-6)"), e->tok); bool lvalue = is_active_lvalue(e); if (lvalue) throw semantic_error(_("utrace '$argN' variable is read-only"), e->tok); // Remember that we've seen a target variable. target_symbol_seen = true; // We're going to substitute a synthesized '_utrace_syscall_arg' // function call for the '$argN' reference. functioncall* n = new functioncall; n->tok = e->tok; n->function = "_utrace_syscall_arg"; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session literal_number *num = new literal_number(argnum - 1); num->tok = e->tok; n->args.push_back(num); provide (n); } } void utrace_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) { const string& sname = e->name; e->assert_no_components("utrace"); bool lvalue = is_active_lvalue(e); if (lvalue) throw semantic_error(_F("utrace '%s' variable is read-only", sname.c_str()), e->tok); string fname; if (sname == "$return") { if (flags != UDPF_SYSCALL_RETURN) throw semantic_error (_("only \"process(PATH_OR_PID).syscall.return\" support $return."), e->tok); fname = "_utrace_syscall_return"; } else if (sname == "$syscall") { // If we've got a syscall entry probe, we can just call the // right function. if (flags == UDPF_SYSCALL) { fname = "_utrace_syscall_nr"; } // If we're in a syscal return probe, we can't really access // $syscall. So, similar to what // dwarf_var_expanding_visitor::visit_target_symbol() does, // we'll create an syscall entry probe to cache $syscall, then // we'll access the cached value in the syscall return probe. else { visit_target_symbol_cached (e); // Remember that we've seen a target variable. target_symbol_seen = true; return; } } else { throw semantic_error (_("unknown target variable"), e->tok); } // Remember that we've seen a target variable. target_symbol_seen = true; // We're going to substitute a synthesized '_utrace_syscall_nr' // function call for the '$syscall' reference. functioncall* n = new functioncall; n->tok = e->tok; n->function = fname; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session provide (n); } void utrace_var_expanding_visitor::visit_target_symbol (target_symbol* e) { assert(e->name.size() > 0 && e->name[0] == '$'); try { if (flags != UDPF_SYSCALL && flags != UDPF_SYSCALL_RETURN) throw semantic_error (_("only \"process(PATH_OR_PID).syscall\"" " and \"process(PATH_OR_PID).syscall.return\" probes support target symbols"), e->tok); if (e->addressof) throw semantic_error(_("cannot take address of utrace variable"), e->tok); if (startswith(e->name, "$arg") || e->name == "$$parms") visit_target_symbol_arg(e); else if (e->name == "$syscall" || e->name == "$return") visit_target_symbol_context(e); else throw semantic_error (_("invalid target symbol for utrace probe," " $syscall, $return, $argN or $$parms expected"), e->tok); } catch (const semantic_error &er) { e->chain (er); provide(e); return; } } struct utrace_builder: public derived_probe_builder { utrace_builder() {} virtual void build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results) { string path, path_tgt; int64_t pid; bool has_path = get_param (parameters, TOK_PROCESS, path); bool has_pid = get_param (parameters, TOK_PROCESS, pid); enum utrace_derived_probe_flags flags = UDPF_NONE; if (has_null_param (parameters, TOK_THREAD)) { if (has_null_param (parameters, TOK_BEGIN)) flags = UDPF_THREAD_BEGIN; else if (has_null_param (parameters, TOK_END)) flags = UDPF_THREAD_END; } else if (has_null_param (parameters, TOK_SYSCALL)) { if (sess.runtime_usermode_p()) throw semantic_error (_("process.syscall probes not available with the dyninst runtime")); if (has_null_param (parameters, TOK_RETURN)) flags = UDPF_SYSCALL_RETURN; else flags = UDPF_SYSCALL; } else if (has_null_param (parameters, TOK_BEGIN)) flags = UDPF_BEGIN; else if (has_null_param (parameters, TOK_END)) flags = UDPF_END; // If we didn't get a path or pid, this means to probe everything. // Convert this to a pid-based probe. if (! has_path && ! has_pid) { has_path = false; path.clear(); has_pid = true; pid = 0; } else if (has_path) { path = find_executable (path, sess.sysroot, sess.sysenv); sess.unwindsym_modules.insert (path); path_tgt = path_remove_sysroot(sess, path); } else if (has_pid) { // We can't probe 'init' (pid 1). XXX: where does this limitation come from? if (pid < 2) throw semantic_error (_("process pid must be greater than 1"), location->components.front()->tok); // XXX: could we use /proc/$pid/exe in unwindsym_modules and elsewhere? } finished_results.push_back(new utrace_derived_probe(sess, base, location, has_path, path_tgt, pid, flags)); } }; void utrace_derived_probe_group::enroll (utrace_derived_probe* p) { if (p->has_path) probes_by_path[p->path].push_back(p); else probes_by_pid[p->pid].push_back(p); num_probes++; flags_seen[p->flags] = true; // XXX: multiple exec probes (for instance) for the same path (or // pid) should all share a utrace report function, and have their // handlers executed sequentially. } void utrace_derived_probe_group::emit_linux_probe_decl (systemtap_session& s, utrace_derived_probe *p) { s.op->newline() << "{"; s.op->line() << " .tgt={"; s.op->line() << " .purpose=\"lifecycle tracking\","; if (p->has_path) { s.op->line() << " .procname=\"" << p->path << "\","; s.op->line() << " .pid=0,"; } else { s.op->line() << " .procname=NULL,"; s.op->line() << " .pid=" << p->pid << ","; } s.op->line() << " .callback=&_stp_utrace_probe_cb,"; s.op->line() << " .mmap_callback=NULL,"; s.op->line() << " .munmap_callback=NULL,"; s.op->line() << " .mprotect_callback=NULL,"; s.op->line() << " },"; s.op->line() << " .probe=" << common_probe_init (p) << ","; // Handle flags switch (p->flags) { // Notice that we'll just call the probe directly when we get // notified, since the task_finder layer stops the thread for us. case UDPF_BEGIN: // process begin s.op->line() << " .flags=(UDPF_BEGIN),"; break; case UDPF_THREAD_BEGIN: // thread begin s.op->line() << " .flags=(UDPF_THREAD_BEGIN),"; break; // Notice we're not setting up a .ops/.report_death handler for // either UDPF_END or UDPF_THREAD_END. Instead, we'll just call // the probe directly when we get notified. case UDPF_END: // process end s.op->line() << " .flags=(UDPF_END),"; break; case UDPF_THREAD_END: // thread end s.op->line() << " .flags=(UDPF_THREAD_END),"; break; // For UDPF_SYSCALL/UDPF_SYSCALL_RETURN probes, the .report_death // handler isn't strictly necessary. However, it helps to keep // our attaches/detaches symmetrical. Since the task_finder layer // stops the thread, that works around bug 6841. case UDPF_SYSCALL: s.op->line() << " .flags=(UDPF_SYSCALL),"; s.op->line() << " .ops={ .report_syscall_entry=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death },"; s.op->line() << " .events=(UTRACE_EVENT(SYSCALL_ENTRY)|UTRACE_EVENT(DEATH)),"; break; case UDPF_SYSCALL_RETURN: s.op->line() << " .flags=(UDPF_SYSCALL_RETURN),"; s.op->line() << " .ops={ .report_syscall_exit=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death },"; s.op->line() << " .events=(UTRACE_EVENT(SYSCALL_EXIT)|UTRACE_EVENT(DEATH)),"; break; case UDPF_NONE: s.op->line() << " .flags=(UDPF_NONE),"; s.op->line() << " .ops={ },"; s.op->line() << " .events=0,"; break; default: throw semantic_error ("bad utrace probe flag"); break; } s.op->line() << " .engine_attached=0,"; s.op->line() << " },"; } void utrace_derived_probe_group::emit_module_linux_decls (systemtap_session& s) { if (probes_by_path.empty() && probes_by_pid.empty()) return; s.op->newline(); s.op->newline() << "/* ---- utrace probes ---- */"; s.op->newline() << "enum utrace_derived_probe_flags {"; s.op->indent(1); s.op->newline() << "UDPF_NONE,"; s.op->newline() << "UDPF_BEGIN,"; s.op->newline() << "UDPF_END,"; s.op->newline() << "UDPF_THREAD_BEGIN,"; s.op->newline() << "UDPF_THREAD_END,"; s.op->newline() << "UDPF_SYSCALL,"; s.op->newline() << "UDPF_SYSCALL_RETURN,"; s.op->newline() << "UDPF_NFLAGS"; s.op->newline(-1) << "};"; s.op->newline() << "struct stap_utrace_probe {"; s.op->indent(1); s.op->newline() << "struct stap_task_finder_target tgt;"; s.op->newline() << "const struct stap_probe * const probe;"; s.op->newline() << "int engine_attached;"; s.op->newline() << "enum utrace_derived_probe_flags flags;"; s.op->newline() << "struct utrace_engine_ops ops;"; s.op->newline() << "unsigned long events;"; s.op->newline(-1) << "};"; // Output handler function for UDPF_BEGIN, UDPF_THREAD_BEGIN, // UDPF_END, and UDPF_THREAD_END if (flags_seen[UDPF_BEGIN] || flags_seen[UDPF_THREAD_BEGIN] || flags_seen[UDPF_END] || flags_seen[UDPF_THREAD_END]) { s.op->newline() << "static void stap_utrace_probe_handler(struct task_struct *tsk, struct stap_utrace_probe *p) {"; s.op->indent(1); common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "p->probe", "stp_probe_type_utrace"); // call probe function s.op->newline() << "(*p->probe->ph) (c);"; common_probe_entryfn_epilogue (s, true); s.op->newline() << "return;"; s.op->newline(-1) << "}"; } // Output handler function for SYSCALL_ENTRY and SYSCALL_EXIT events if (flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN]) { s.op->newline() << "#ifdef UTRACE_ORIG_VERSION"; s.op->newline() << "static u32 stap_utrace_probe_syscall(struct utrace_engine *engine, struct task_struct *tsk, struct pt_regs *regs) {"; s.op->newline() << "#else"; s.op->newline() << "#if defined(UTRACE_API_VERSION) && (UTRACE_API_VERSION >= 20091216)"; s.op->newline() << "static u32 stap_utrace_probe_syscall(u32 action, struct utrace_engine *engine, struct pt_regs *regs) {"; s.op->newline() << "#else"; s.op->newline() << "static u32 stap_utrace_probe_syscall(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *tsk, struct pt_regs *regs) {"; s.op->newline() << "#endif"; s.op->newline() << "#endif"; s.op->indent(1); s.op->newline() << "struct stap_utrace_probe *p = (struct stap_utrace_probe *)engine->data;"; common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "p->probe", "stp_probe_type_utrace_syscall"); s.op->newline() << "c->uregs = regs;"; s.op->newline() << "c->user_mode_p = 1;"; // call probe function s.op->newline() << "(*p->probe->ph) (c);"; common_probe_entryfn_epilogue (s, true); s.op->newline() << "if ((atomic_read (session_state()) != STAP_SESSION_STARTING) && (atomic_read (session_state()) != STAP_SESSION_RUNNING)) {"; s.op->indent(1); s.op->newline() << "debug_task_finder_detach();"; s.op->newline() << "return UTRACE_DETACH;"; s.op->newline(-1) << "}"; s.op->newline() << "return UTRACE_RESUME;"; s.op->newline(-1) << "}"; } // Output task_finder callback routine that gets called for all // utrace probe types. s.op->newline() << "static int _stp_utrace_probe_cb(struct stap_task_finder_target *tgt, struct task_struct *tsk, int register_p, int process_p) {"; s.op->indent(1); s.op->newline() << "int rc = 0;"; s.op->newline() << "struct stap_utrace_probe *p = container_of(tgt, struct stap_utrace_probe, tgt);"; s.op->newline() << "struct utrace_engine *engine;"; s.op->newline() << "if (register_p) {"; s.op->indent(1); s.op->newline() << "switch (p->flags) {"; s.op->indent(1); // When receiving a UTRACE_EVENT(CLONE) event, we can't call the // begin/thread.begin probe directly. So, we'll just attach an // engine that waits for the thread to quiesce. When the thread // quiesces, then call the probe. if (flags_seen[UDPF_BEGIN]) { s.op->newline() << "case UDPF_BEGIN:"; s.op->indent(1); s.op->newline() << "if (process_p) {"; s.op->indent(1); s.op->newline() << "stap_utrace_probe_handler(tsk, p);"; s.op->newline(-1) << "}"; s.op->newline() << "break;"; s.op->indent(-1); } if (flags_seen[UDPF_THREAD_BEGIN]) { s.op->newline() << "case UDPF_THREAD_BEGIN:"; s.op->indent(1); s.op->newline() << "if (! process_p) {"; s.op->indent(1); s.op->newline() << "stap_utrace_probe_handler(tsk, p);"; s.op->newline(-1) << "}"; s.op->newline() << "break;"; s.op->indent(-1); } // For end/thread_end probes, do nothing at registration time. // We'll handle these in the 'register_p == 0' case. if (flags_seen[UDPF_END] || flags_seen[UDPF_THREAD_END]) { s.op->newline() << "case UDPF_END:"; s.op->newline() << "case UDPF_THREAD_END:"; s.op->indent(1); s.op->newline() << "break;"; s.op->indent(-1); } // Attach an engine for SYSCALL_ENTRY and SYSCALL_EXIT events. if (flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN]) { s.op->newline() << "case UDPF_SYSCALL:"; s.op->newline() << "case UDPF_SYSCALL_RETURN:"; s.op->indent(1); s.op->newline() << "rc = stap_utrace_attach(tsk, &p->ops, p, p->events);"; s.op->newline() << "if (rc == 0) {"; s.op->indent(1); s.op->newline() << "p->engine_attached = 1;"; s.op->newline(-1) << "}"; s.op->newline() << "break;"; s.op->indent(-1); } s.op->newline() << "default:"; s.op->indent(1); s.op->newline() << "_stp_error(\"unhandled flag value %d at %s:%d\", p->flags, __FUNCTION__, __LINE__);"; s.op->newline() << "break;"; s.op->indent(-1); s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; // Since this engine could be attached to multiple threads, don't // call stap_utrace_detach_ops() here, only call // stap_utrace_detach() as necessary. s.op->newline() << "else {"; s.op->indent(1); s.op->newline() << "switch (p->flags) {"; s.op->indent(1); // For end probes, go ahead and call the probe directly. if (flags_seen[UDPF_END]) { s.op->newline() << "case UDPF_END:"; s.op->indent(1); s.op->newline() << "if (process_p) {"; s.op->indent(1); s.op->newline() << "stap_utrace_probe_handler(tsk, p);"; s.op->newline(-1) << "}"; s.op->newline() << "break;"; s.op->indent(-1); } if (flags_seen[UDPF_THREAD_END]) { s.op->newline() << "case UDPF_THREAD_END:"; s.op->indent(1); s.op->newline() << "if (! process_p) {"; s.op->indent(1); s.op->newline() << "stap_utrace_probe_handler(tsk, p);"; s.op->newline(-1) << "}"; s.op->newline() << "break;"; s.op->indent(-1); } // For begin/thread_begin probes, we don't need to do anything. if (flags_seen[UDPF_BEGIN] || flags_seen[UDPF_THREAD_BEGIN]) { s.op->newline() << "case UDPF_BEGIN:"; s.op->newline() << "case UDPF_THREAD_BEGIN:"; s.op->indent(1); s.op->newline() << "break;"; s.op->indent(-1); } if (flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN]) { s.op->newline() << "case UDPF_SYSCALL:"; s.op->newline() << "case UDPF_SYSCALL_RETURN:"; s.op->indent(1); s.op->newline() << "stap_utrace_detach(tsk, &p->ops);"; s.op->newline() << "break;"; s.op->indent(-1); } s.op->newline() << "default:"; s.op->indent(1); s.op->newline() << "_stp_error(\"unhandled flag value %d at %s:%d\", p->flags, __FUNCTION__, __LINE__);"; s.op->newline() << "break;"; s.op->indent(-1); s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; s.op->newline() << "return rc;"; s.op->newline(-1) << "}"; s.op->newline() << "static struct stap_utrace_probe stap_utrace_probes[] = {"; s.op->indent(1); // Set up 'process(PATH)' probes if (! probes_by_path.empty()) { for (p_b_path_iterator it = probes_by_path.begin(); it != probes_by_path.end(); it++) { for (unsigned i = 0; i < it->second.size(); i++) { utrace_derived_probe *p = it->second[i]; emit_linux_probe_decl(s, p); } } } // Set up 'process(PID)' probes if (! probes_by_pid.empty()) { for (p_b_pid_iterator it = probes_by_pid.begin(); it != probes_by_pid.end(); it++) { for (unsigned i = 0; i < it->second.size(); i++) { utrace_derived_probe *p = it->second[i]; emit_linux_probe_decl(s, p); } } } s.op->newline(-1) << "};"; } void utrace_derived_probe_group::emit_dyninst_probe_decl (systemtap_session& s, const string& path, utrace_derived_probe *p) { string flags_str; // Handle flags switch (p->flags) { case UDPF_BEGIN: // process begin flags_str = "STAPDYN_PROBE_FLAG_PROC_BEGIN"; break; case UDPF_THREAD_BEGIN: // thread begin flags_str = "STAPDYN_PROBE_FLAG_THREAD_BEGIN"; break; case UDPF_END: // process end flags_str = "STAPDYN_PROBE_FLAG_PROC_END"; break; case UDPF_THREAD_END: // thread end flags_str = "STAPDYN_PROBE_FLAG_THREAD_END"; break; // FIXME: No handling of syscall probes for dyninst yet. #if 0 case UDPF_SYSCALL: break; case UDPF_SYSCALL_RETURN: break; case UDPF_NONE: s.op->line() << " .flags=(UDPF_NONE),"; s.op->line() << " .ops={ },"; s.op->line() << " .events=0,"; break; #endif default: throw semantic_error ("bad utrace probe flag"); break; } if (p->has_path) dynprobe_add_utrace_path(s, path, flags_str, common_probe_init(p)); else dynprobe_add_utrace_pid(s, p->pid, flags_str, common_probe_init(p)); } void utrace_derived_probe_group::emit_module_dyninst_decls (systemtap_session& s) { if (probes_by_path.empty() && probes_by_pid.empty()) return; s.op->newline(); s.op->newline() << "/* ---- dyninst utrace probes ---- */"; s.op->newline() << "#include \"dyninst/uprobes.h\""; s.op->newline() << "#define STAPDYN_UTRACE_PROBES"; // Let the dynprobe_derived_probe_group handle outputting targets // and probes. This allows us to merge different types of probes. s.op->newline() << "static struct stapdu_probe stapdu_probes[];"; // Set up 'process(PATH)' probes if (! probes_by_path.empty()) { for (p_b_path_iterator it = probes_by_path.begin(); it != probes_by_path.end(); it++) { for (unsigned i = 0; i < it->second.size(); i++) { utrace_derived_probe *p = it->second[i]; emit_dyninst_probe_decl(s, it->first, p); } } } // Set up 'process(PID)' probes if (! probes_by_pid.empty()) { for (p_b_pid_iterator it = probes_by_pid.begin(); it != probes_by_pid.end(); it++) { for (unsigned i = 0; i < it->second.size(); i++) { utrace_derived_probe *p = it->second[i]; emit_dyninst_probe_decl(s, "", p); } } } // loc2c-generated code assumes pt_regs are available, so use this to make // sure we always have *something* for it to dereference... s.op->newline() << "static struct pt_regs stapdu_dummy_uregs;"; // Write the probe handler. // NB: not static, so dyninst can find it s.op->newline() << "int enter_dyninst_utrace_probe " << "(uint64_t index, struct pt_regs *regs) {"; s.op->newline(1) << "struct stapdu_probe *sup = &stapdu_probes[index];"; common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sup->probe", "stp_probe_type_utrace"); s.op->newline() << "c->uregs = regs ?: &stapdu_dummy_uregs;"; s.op->newline() << "c->user_mode_p = 1;"; // XXX: once we have regs, check how dyninst sets the IP // XXX: the way that dyninst rewrites stuff is probably going to be // ... very confusing to our backtracer (at least if we stay in process) s.op->newline() << "(*sup->probe->ph) (c);"; common_probe_entryfn_epilogue (s, true); s.op->newline() << "return 0;"; s.op->newline(-1) << "}"; s.op->assert_0_indent(); } void utrace_derived_probe_group::emit_module_decls (systemtap_session& s) { if (s.runtime_usermode_p()) emit_module_dyninst_decls (s); else emit_module_linux_decls (s); } void utrace_derived_probe_group::emit_module_linux_init (systemtap_session& s) { if (probes_by_path.empty() && probes_by_pid.empty()) return; s.op->newline() << "/* ---- utrace probes ---- */"; s.op->newline() << "for (i=0; inewline(1) << "struct stap_utrace_probe *p = &stap_utrace_probes[i];"; s.op->newline() << "probe_point = p->probe->pp;"; // for error messages s.op->newline() << "rc = stap_register_task_finder_target(&p->tgt);"; // NB: if (rc), there is no need (XXX: nor any way) to clean up any // finders already registered, since mere registration does not // cause any utrace or memory allocation actions. That happens only // later, once the task finder engine starts running. So, for a // partial initialization requiring unwind, we need do nothing. s.op->newline() << "if (rc) break;"; s.op->newline(-1) << "}"; } void utrace_derived_probe_group::emit_module_dyninst_init (systemtap_session& s) { if (probes_by_path.empty() && probes_by_pid.empty()) return; /* stapdyn handles the dirty work via dyninst */ s.op->newline() << "/* ---- dyninst utrace probes ---- */"; s.op->newline() << "/* this section left intentionally blank */"; } void utrace_derived_probe_group::emit_module_init (systemtap_session& s) { if (s.runtime_usermode_p()) emit_module_dyninst_init (s); else emit_module_linux_init(s); } void utrace_derived_probe_group::emit_module_linux_exit (systemtap_session& s) { if (probes_by_path.empty() && probes_by_pid.empty()) return; s.op->newline(); s.op->newline() << "/* ---- utrace probes ---- */"; s.op->newline() << "for (i=0; inewline(1) << "struct stap_utrace_probe *p = &stap_utrace_probes[i];"; s.op->newline() << "if (p->engine_attached) {"; s.op->newline(1) << "stap_utrace_detach_ops(&p->ops);"; s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; } void utrace_derived_probe_group::emit_module_dyninst_exit (systemtap_session& s) { if (probes_by_path.empty() && probes_by_pid.empty()) return; /* stapdyn handles the dirty work via dyninst */ s.op->newline() << "/* ---- dyninst utrace probes ---- */"; s.op->newline() << "/* this section left intentionally blank */"; } void utrace_derived_probe_group::emit_module_exit (systemtap_session& s) { if (s.runtime_usermode_p()) emit_module_dyninst_exit (s); else emit_module_linux_exit(s); } void register_tapset_utrace(systemtap_session& s) { match_node* root = s.pattern_root; derived_probe_builder *builder = new utrace_builder(); vector roots; roots.push_back(root->bind(TOK_PROCESS)); roots.push_back(root->bind_str(TOK_PROCESS)); roots.push_back(root->bind_num(TOK_PROCESS)); for (unsigned i = 0; i < roots.size(); ++i) { roots[i]->bind(TOK_BEGIN) ->bind_privilege(pr_all) ->bind(builder); roots[i]->bind(TOK_END) ->bind_privilege(pr_all) ->bind(builder); roots[i]->bind(TOK_THREAD)->bind(TOK_BEGIN) ->bind_privilege(pr_all) ->bind(builder); roots[i]->bind(TOK_THREAD)->bind(TOK_END) ->bind_privilege(pr_all) ->bind(builder); roots[i]->bind(TOK_SYSCALL) ->bind_privilege(pr_all) ->bind(builder); roots[i]->bind(TOK_SYSCALL)->bind(TOK_RETURN) ->bind_privilege(pr_all) ->bind(builder); } } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/tapset/000077500000000000000000000000001217430427200147115ustar00rootroot00000000000000systemtap-2.3/tapset/DEVGUIDE000066400000000000000000000315201217430427200160310ustar00rootroot00000000000000// Copyright (C) IBM Corp. 2007 // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. TAPSET DEVELOPER'S GUIDE ------------------------ Tapsets are scripts that encapsulate knowledge about a kernel subsystem into pre-written probes and functions that can be used by other scripts. Tapsets are analogous to libraries for C programs. They hide the underlying details of a kernel area while exposing the key information needed to manage and monitor that aspect of the kernel. They are typically developed by kernel subject-matter experts. This document assumes you are already familiar with SystemTap and the basics of writing a SystemTap script. The REFERENCE MATERIAL section below lists other sources of SystemTap information. At a minimum, you should study the SystemTap Tutorial, the HACKING file and some of the existing tapsets before attempting to write a tapset yourself. WHAT SHOULD A TAPSET CONTAIN? A tapset should expose the high-level data and state transitions of a subsystem. Assume the audience knows little to nothing about the subsystem's low-level details and probably doesn't care. Users who need low-level data typically bypass the tapsets and write custom scripts targeted to a specific problem. The first step is to create a simple model of your subject area. For example, a model of the process subsystem might include the following: Key data: * process ID * parent process ID * process group ID State transitions: * forked * execed * running * stopped * terminated NOTE: This is a simple example and not meant to be a complete list. Use your subsystem expertise to find probe points (function entries and exits) that expose the elements of the model, then define probe aliases for those points. Be aware that some state transitions can occur in more than one place. In those cases, an alias can place a probe in multiple locations. For example, process execs can occur in either the do_execve() or the compat_do_execve() functions. The following alias inserts probes at the beginning of those functions: probe kprocess.exec = kernel.function("do_execve"), kernel.function("compat_do_execve") { < probe body > } Try to place probes on stable interfaces whenever possible (i.e., functions that are unlikely to change at the interface level). This makes it less likely that the tapset will break due to changes in the kernel. Where kernel version or architecture dependencies are unavoidable, use preprocessor conditionals (see the stap(1) man page for details). Fill in the probe bodies with the key data available at the probe points. Function entry probes can access the entry parameters specified to the function, while exit probes can access the entry parameters and the return value. Convert the data into meaningful forms where appropriate (e.g., bytes to kilobytes, state values to strings, etc). You may need to use auxiliary functions to access or convert some of the data. Auxiliary functions often use embedded C to do things that cannot be done in the SystemTap language, like access structure fields in some contexts, follow linked lists, etc. You can use auxiliary functions defined in other tapsets or write your own. In the following example, copy_process() returns a pointer to the task_struct for the new process. Note that the process ID of the new process is retrieved by calling task_pid() and passing it the task_struct pointer. In this case, the auxiliary function is an embedded C function that's defined in the task tapset (task.stp). probe kprocess.create = kernel.function("copy_process").return { task = $return new_pid = task_pid(task) } Avoid the temptation to write probes for every function. Most SystemTap users won't need or understand them. Keep your tapset simple and high- level. ELEMENTS OF A TAPSET The following sections describe the most important aspects of writing a tapset and contributing it to the project. If you're writing a tapset for personal use, most of these sections can be ignored, with the exception of "Tapset files", "Namespace" and "Embedded C & Safety." Tapset files ------------ Tapset files are stored in src/tapset in the SystemTap GIT directory. Most are kept at that level. If you have code that only works on a specific architecture or kernel-version, you may choose to put that in the corresponding subdirectories. Installed tapsets are located in /usr/share/systemtap/tapset/ or /usr/local/share/systemtap/tapset. Personal tapsets can be stored anywhere, but you must use "-I to specify their location when invoking the stap command. Namespace --------- Probe alias names should take the form .. For example, the probe for sending a signal could be named "signal.send". Global symbol names (probes, functions and variables) should be unique across all tapsets. This helps avoid namespace collisions in scripts that use multiple tapsets. To ensure this, use tapset-specific prefixes in your global symbols. Internal symbol names should be prefixed with "_". Comments -------- All probes and functions should include comment blocks that describe their purpose, the data they provide and the context in which they run (e.g., interrupt, process, etc.). Also use comments in areas where your intent may not be clear from reading the code. The comments preceding the functions and probes should be written in the format described in the Documentation section to allow automatic generation of the tapset documentation. Documentation ------------- SystemTap now documents the tapset functions and probe points in a manner similar to the Linux kernel. The tapset files have comments before each function and probe point that are processed by a modified kernel-doc script and pulled into an XML document. HTML, PDF, and man pages are generated from that document during the build process. For systemtap functions the structure of the documentation comment is: /** * sfunction function_name(:)? (- short description)? (* @parameter(space)*: (description of function parameter x)?)* (* a blank line)? * (Description:)? (Description of function)? * (section header: (section description)? )* (*)?*/ For sytemtap probes the structure of the documentation comment is the following: /** * probe probe_name(:)? (- short description)? (* @variable(space)*: (description of probe variable x)?)* (* a blank line)? * (Description:)? (Description of probe)? * (section header: (section description)? )* (*)?*/ The document extraction keys off the "/**" at the start of the comment; normal comments starting with "/*" are ignored. The next line of the comment describes whether the following code is for a SystemTap function or a probe and title descript. Following lines that have an '@' preceding the first word describe the parameters or variables available in the function or probe. There can be zero or more "section headers" after the variables or parameters. After each section there can be multiple lines of text. The comment is closed with "*/". The xml tapsets.tmpl in src/doc/SystemTap_Tapset_Reference makes use of those special comments. This xml file has place holders to extract the documentation from the tapsets like the following for ioscheduler.stp: !Itapset/ioscheduler.stp When a new tapset file is created you will need make a similar addition to tapsets.tmpl to pull the documentation in from the new tapset file. If configured to build reference documentation (--enable-refdocs) and the needed software is available, the build process will automatic generated PDF, HTML, and man pages. The creation of new man pages for the tapsets and functions is depricated and all the documentation should be migrated over to the tapsets.tmpl. Config & Makefiles ------------------ Add your tapset man page to the AC_CONFIG_FILES line in src/configure.ac, then regenerate the src/configure script by running autoconf. Add your tapset man page to dist_man_MANS line in src/Makefile.am, then regenerate src/Makefile.in by running automake. Update other Makefiles as necessary. Test cases ---------- All tapsets should be accompanied by test scripts. The tests are kept in src/testsuite in GIT and based on dejagnu. You must have dejagnu and expect installed on your system to run the tests. Your tests should validate that: - the tapset can be parsed and built - all probes and functions work as expected - all potential errors are handled appropriately See the "test suites" section of the HACKING file and the existing tests for details. Example Scripts --------------- Provide at least one example script that uses the probe aliases and functions in your tapset. This serves two purposes. First, it shows script writers how you envisioned the tapset being used. Second, and most important, it validates that the tapset can actually be used for something useful. If you can't write a script that uses the tapset in a meaningful way, perhaps you should rethink what the tapset provides. Example scripts are stored in testsuite/systemtap.examples/ in GIT. Embedded C & Safety ------------------- As mentioned previously, you can use embedded C (raw C code) to do things not supported by the SystemTap language. Please do this carefully and sparingly, as embedded C bypasses all the safety features built into SystemTap. There are a few style conventions that make writing robust embedded C code easier: - Be especially careful when dereferencing pointers. Use the kread() macro to dereference any pointers that could potentially be invalid. If you're not sure, err on the side of caution. The cost of using kread() is small compared to the cost of your tapset inadvertently crashing a system! - Use the macros STAP_RETVALUE and STAP_ARG_* to access the function's arguments and return slot. This ensures that the function will not break if the internal naming scheme for local variables changes between SystemTap versions. - It is absolutely necessary to rigorously test embedded-C functions in the testsuite, particularly to ensure that they fail gracefully in unexpected situations instead of causing a kernel panic. Add the string /* pure */ into the body of the embedded-C function if it has no side-effects such as changing external state, so that systemtap could elide (optimize away) a call to the function if its results are unused. Add the string /* unprivileged */ into the body of the embedded-C function, only if it is safe for use by unprivileged users. In general, this requires the function to be absolutely robust with respect to its inputs, and expose/modify no information except that belonging to the user's own processes. (The assert_is_myproc() macro may help enforce this.) Roughly speaking, it should only perform operations that the same user could already do from ordinary userspace interfaces. Add the string /* myproc-unprivileged */ into the body of the embedded-C function, to mark it as /* unprivileged */ (see above) and to have the systemtap translator automatically add a call to assert_is_myproc() to the beginning of the function. Add the string /* unmangled */ into a legacy (pre-SystemTap 1.8) embedded-C function that needs to use the old argument / return slot access syntax (namely, THIS->foo and THIS->__retvalue). This is useful for migrating tapsets to work with the new syntax. Review & Submission ------------------- All new tapsets and major changes should be reviewed "early and often" by the SystemTap community. You can sign up for the systemtap mailing list at http://sourceware.org/systemtap/getinvolved.html. The mailing list archive is found at http://sourceware.org/ml/systemtap/. The systemtap-cvs mailing list archive is at http://sourceware.org/ml/systemtap-cvs/. You can request GIT write access at http://sourceware.org/cgi-bin/pdw/ps_form.cgi. REFERENCE MATERIAL The following documents, web sites and mailing lists will familiarize you with SystemTap: - SystemTap Tutorial. A good introduction to SystemTap. (html format: http://sourceware.org/systemtap/tutorial/, PDF format: http://sourceware.org/systemtap/tutorial.pdf) - SystemTap project home page (http://sourceware.org/systemtap/index.html) - SystemTap mailing lists, IRC channels and GIT instructions (http://sourceware.org/systemtap/getinvolved.html) - GIT repository (http://sourceware.org/git/?p=systemtap.git;a=summary) - HACKING file in the source directory. This file outlines what's expected of project contributors. - SystemTap Wiki. Contains papers and presentations, setup instructions for various distributions, and a growing set of example scripts. (http://sourceware.org/systemtap/wiki) - Existing tapsets - SystemTap Language Reference. (html format: http://sourceware.org/systemtap/langref/, PDF format: http://sourceware.org/systemtap/langref.pdf) - SystemTap Man Pages (use "man -k stap" to print a list) systemtap-2.3/tapset/README000066400000000000000000000005631217430427200155750ustar00rootroot00000000000000Systemtap scripts under this directory are NOT meant for direct execution. They are not sample end-user scripts, but rather constitute the "standard library" from which other scripts can pull in definitions from. For samples of end-user scripts, see the web http://sourceware.org/systemtap/documentation.html See also http://sourceware.org/systemtap/wiki/TapsetStatus systemtap-2.3/tapset/ansi.stp000066400000000000000000000076661217430427200164120ustar00rootroot00000000000000# ANSI escape sequences tapset # Copyright (C) 2009 Red Hat, Inc., Eugene Teo # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. # # Based on some previous work done by Masami Hiramatsu for stapgames. # Reference: http://en.wikipedia.org/wiki/ANSI_escape_code # /** * sfunction ansi_clear_screen - Move cursor to top left and clear screen. * * Description: Sends ansi code for moving cursor to top left and then the * ansi code for clearing the screen from the cursor position to the end. **/ function ansi_clear_screen() { print("\033[1;1H\033[J") } /** * sfunction ansi_set_color - Set the ansi Select Graphic Rendition mode. * @fg: Foreground color to set. * * Description: Sends ansi code for Select Graphic Rendition mode for the * given forground color. Black (30), Blue (34), Green (32), Cyan (36), * Red (31), Purple (35), Brown (33), Light Gray (37). */ function ansi_set_color(fg:long) { printf("\033[%dm", fg) } /** * sfunction ansi_set_color2 - Set the ansi Select Graphic Rendition mode. * @fg: Foreground color to set. * @bg: Background color to set. * * Description: Sends ansi code for Select Graphic Rendition mode for the * given forground color, Black (30), Blue (34), Green (32), Cyan (36), * Red (31), Purple (35), Brown (33), Light Gray (37) and the given * background color, Black (40), Red (41), Green (42), Yellow (43), * Blue (44), Magenta (45), Cyan (46), White (47). */ function ansi_set_color2(fg:long, bg:long) { printf("\033[%d;%dm", bg, fg) } /** * sfunction ansi_set_color3 - Set the ansi Select Graphic Rendition mode. * @fg: Foreground color to set. * @bg: Background color to set. * @attr: Color attribute to set. * * Description: Sends ansi code for Select Graphic Rendition mode for the * given forground color, Black (30), Blue (34), Green (32), Cyan (36), * Red (31), Purple (35), Brown (33), Light Gray (37), the given * background color, Black (40), Red (41), Green (42), Yellow (43), * Blue (44), Magenta (45), Cyan (46), White (47) and the color attribute * All attributes off (0), Intensity Bold (1), Underline Single (4), * Blink Slow (5), Blink Rapid (6), Image Negative (7). */ function ansi_set_color3(fg:long, bg:long, attr:long) { attr_str = attr ? sprintf(";%dm", attr) : "m" printf("\033[%d;%d%s", bg, fg, attr_str) } /** * sfunction ansi_reset_color - Resets Select Graphic Rendition mode. * * Description: Sends ansi code to reset foreground, background and color * attribute to default values. */ function ansi_reset_color() { ansi_set_color3(0, 0, 0) } /** * sfunction ansi_new_line - Move cursor to new line. * * Description: Sends ansi code new line. */ function ansi_new_line() { printf("\12") } /** * sfunction ansi_cursor_move - Move cursor to new coordinates. * @x: Row to move the cursor to. * @y: Colomn to move the cursor to. * * Description: Sends ansi code for positioning the cursor at row x * and column y. Coordinates start at one, (1,1) is the top-left corner. */ function ansi_cursor_move(x:long, y:long) { printf("\033[%d;%dH", y, x) } /** * sfunction ansi_cursor_hide - Hides the cursor. * * Description: Sends ansi code for hiding the cursor. */ function ansi_cursor_hide() { print("\033[>5I") } /** * sfunction ansi_cursor_save - Saves the cursor position. * * Description: Sends ansi code for saving the current cursor position. */ function ansi_cursor_save() { print("\033[s") } /** * sfunction ansi_cursor_restore - Restores a previously saved cursor position. * * Description: Sends ansi code for restoring the current cursor position * previously saved with ansi_cursor_save(). */ function ansi_cursor_restore() { print("\033[u") } /** * sfunction ansi_cursor_show - Shows the cursor. * * Description: Sends ansi code for showing the cursor. */ function ansi_cursor_show() { print("\033[>5h") } systemtap-2.3/tapset/argv.stp000066400000000000000000000032271217430427200164040ustar00rootroot00000000000000// argument vector tapset // Copyright (C) 2008 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. global argc = $# global argv %( $# >= 1 %? [$#] %: [1] %) probe begin(-1) { %( $# == 0 %? argv[0] = "nothing"; delete argv[0] %) # ensure argv is set sometime %( $# >= 1 %? argv[1]=@1 %) %( $# >= 2 %? argv[2]=@2 %) %( $# >= 3 %? argv[3]=@3 %) %( $# >= 4 %? argv[4]=@4 %) %( $# >= 5 %? argv[5]=@5 %) %( $# >= 6 %? argv[6]=@6 %) %( $# >= 7 %? argv[7]=@7 %) %( $# >= 8 %? argv[8]=@8 %) %( $# >= 9 %? argv[9]=@9 %) %( $# >= 10 %? argv[10]=@10 %) %( $# >= 11 %? argv[11]=@11 %) %( $# >= 12 %? argv[12]=@12 %) %( $# >= 13 %? argv[13]=@13 %) %( $# >= 14 %? argv[14]=@14 %) %( $# >= 15 %? argv[15]=@15 %) %( $# >= 16 %? argv[16]=@16 %) %( $# >= 17 %? argv[17]=@17 %) %( $# >= 18 %? argv[18]=@18 %) %( $# >= 19 %? argv[19]=@19 %) %( $# >= 20 %? argv[20]=@20 %) %( $# >= 21 %? argv[21]=@21 %) %( $# >= 22 %? argv[22]=@22 %) %( $# >= 23 %? argv[23]=@23 %) %( $# >= 24 %? argv[24]=@24 %) %( $# >= 25 %? argv[25]=@25 %) %( $# >= 26 %? argv[26]=@26 %) %( $# >= 27 %? argv[27]=@27 %) %( $# >= 28 %? argv[28]=@28 %) %( $# >= 29 %? argv[29]=@29 %) %( $# >= 30 %? argv[30]=@30 %) %( $# >= 31 %? argv[31]=@31 %) %( $# >= 32 %? argv[32]=@32 %) %( $# >= 33 %? warn(sprintf("argv is limited to 32 arguments")) %) } systemtap-2.3/tapset/arm/000077500000000000000000000000001217430427200154705ustar00rootroot00000000000000systemtap-2.3/tapset/arm/registers.stp000066400000000000000000000100371217430427200202300ustar00rootroot00000000000000/* Dwarfless register access for arm */ global _reg_offsets, _stp_regs_registered function _stp_register_regs() { /* Same order as pt_regs */ _reg_offsets["r0"] = 0 _reg_offsets["a1"] = 0 _reg_offsets["r1"] = 4 _reg_offsets["a2"] = 4 _reg_offsets["r2"] = 8 _reg_offsets["a3"] = 8 _reg_offsets["r3"] = 12 _reg_offsets["a4"] = 12 _reg_offsets["r4"] = 16 _reg_offsets["v1"] = 16 _reg_offsets["r5"] = 20 _reg_offsets["v2"] = 20 _reg_offsets["r6"] = 24 _reg_offsets["v3"] = 24 _reg_offsets["r7"] = 28 _reg_offsets["v4"] = 28 _reg_offsets["r8"] = 32 _reg_offsets["v5"] = 32 _reg_offsets["r9"] = 36 _reg_offsets["v6"] = 36 _reg_offsets["r10"] = 40 _reg_offsets["v7"] = 40 _reg_offsets["fp"] = 44 _reg_offsets["v8"] = 44 _reg_offsets["ip"] = 48 _reg_offsets["sp"] = 52 _reg_offsets["lr"] = 56 _reg_offsets["pc"] = 60 _reg_offsets["cpsr"] = 64 _reg_offsets["orig_r0"] = 68 _stp_regs_registered = 1 } function _stp_get_register_by_offset:long (offset:long) %{ /* pure */ long value; struct pt_regs *regs; if (CONTEXT->user_mode_p) { regs = CONTEXT->uregs; } else { regs = CONTEXT->kregs; } if (!regs) { CONTEXT->last_error = "No registers available in this context"; return; } if (STAP_ARG_offset < 0 || STAP_ARG_offset > sizeof(struct pt_regs) - sizeof(long)) { snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "Bad register offset: %lld", STAP_ARG_offset); CONTEXT->last_error = CONTEXT->error_buffer; return; } memcpy(&value, ((char *)regs) + STAP_ARG_offset, sizeof(value)); STAP_RETVALUE = value; %} function _stp_probing_kernel:long () { return !user_mode(); } /* Return the named register value as a signed value. */ function register:long (name:string) { if (!registers_valid()) { error("cannot access CPU registers in this context") return 0 } if (!_stp_regs_registered) _stp_register_regs() offset = _reg_offsets[name] if (offset == 0 && !(name in _reg_offsets)) { error("Unknown register: " . name) return 0 } return _stp_get_register_by_offset(offset) } /* * Return the named register value as an unsigned value. Specifically, * don't sign-extend the register value when promoting it to 64 bits. */ function u_register:long (name:string) { return register(name) & 0xffffffff; } /* Return the value of function arg #argnum (1=first arg) as a signed value. * * We don't yet support extracting arg #5 and beyond, which are passed * on stack */ function _stp_arg:long (argnum:long) { val = 0 if (argnum < 1 || argnum > 4) { error(sprintf("Cannot access arg(%d)", argnum)) return 0 } if (argnum == 1) val = register("r0") else if (argnum == 2) val = register("r1") else if (argnum == 3) val = register("r2") else if (argnum == 4) val = register("r3") return val; } /* Return the value of function arg #argnum as a signed int. */ function int_arg:long (argnum:long) { return _stp_arg(argnum) } /* Return the value of function arg #argnum as an unsigned int. */ function uint_arg:long (argnum:long) { return _stp_arg(argnum) & 0xffffffff; } function long_arg:long (argnum:long) { return int_arg(argnum) } function ulong_arg:long (argnum:long) { return uint_arg(argnum) } function longlong_arg:long (argnum:long) { /* * TODO: If argnum == nr_regarg, gcc puts the whole 64-bit arg * on the stack. */ lowbits = uint_arg(argnum) highbits = uint_arg(argnum+1) return ((highbits << 32) | lowbits) } function ulonglong_arg:long (argnum:long) { return longlong_arg(argnum) } function pointer_arg:long (argnum:long) { return ulong_arg(argnum) } function s32_arg:long (argnum:long) { return int_arg(argnum) } function u32_arg:long (argnum:long) { return uint_arg(argnum) } function s64_arg:long (argnum:long) { return longlong_arg(argnum) } function u64_arg:long (argnum:long) { return ulonglong_arg(argnum) } function asmlinkage() %{ /* pure */ %} function fastcall() %{ /* pure */ %} function regparm(n:long) %{ snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "regparm is invalid on arm."); CONTEXT->last_error = CONTEXT->error_buffer; %} systemtap-2.3/tapset/choose_defined.stpm000066400000000000000000000003201217430427200205470ustar00rootroot00000000000000// Use the first parameter if it's @defined, otherwise use the second parameter @define choose_defined(value_if_defined, alternate) %( ( @defined(@value_if_defined) ? (@value_if_defined) : (@alternate) ) %) systemtap-2.3/tapset/context.stp000066400000000000000000000116451217430427200171340ustar00rootroot00000000000000// context tapset // Copyright (C) 2005-2011 Red Hat Inc. // Copyright (C) 2006 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // Context functions provide additional information about where an event occurred. These functions can //provide information such as a backtrace to where the event occurred and the current register values for the //processor. // /** * sfunction print_regs - Print a register dump * * Description: This function prints a register dump. Does nothing if no registers are available for the probe point. */ function print_regs () %{ if (c->user_mode_p && CONTEXT->uregs) { _stp_print_regs (CONTEXT->uregs); } else if (CONTEXT->kregs) { _stp_print_regs (CONTEXT->kregs); } %} /** * sfunction pp - Returns the active probe point * * Description: This function returns the fully-resolved probe point * associated with a currently running probe handler, including alias * and wild-card expansion effects. Context: The current probe point. */ function pp:string () %{ /* pure */ /* unprivileged */ strlcpy (STAP_RETVALUE, CONTEXT->probe_point, MAXSTRINGLEN); %} /** * sfunction ppfunc - Returns the function name parsed from pp() * * Description: This returns the function name from the current pp(). * Not all pp() have functions in them, in which case "" is returned. */ function ppfunc:string () %{ /* pure */ /* unprivileged */ char *ptr, *start; /* This is based on the pre-2.0 behavior of probefunc(), but without * the _stp_snprint_addr fallback, so we're purely pp()-based. * * The obsolete inline("...") syntax is dropped, but in its place we'll * look for function names in statement("...") form. */ STAP_RETVALUE[0] = '\0'; start = strstr(CONTEXT->probe_point, "function(\""); ptr = start + 10; if (!start) { start = strstr(CONTEXT->probe_point, "statement(\""); ptr = start + 11; } if (start) { int len = MAXSTRINGLEN; char *dst = STAP_RETVALUE; while (*ptr != '@' && *ptr != '"' && --len > 0 && *ptr) *dst++ = *ptr++; *dst = 0; } %} /** * sfunction probe_type - The low level probe handler type of the current probe. * * Description: Returns a short string describing the low level probe handler * type for the current probe point. This is for informational purposes only. * Depending on the low level probe handler different context functions can * or cannot provide information about the current event (for example some * probe handlers only trigger in user space and have no associated kernel * context). High-level probes might map to the same or different low-level * probes (depending on systemtap version and/or kernel used). */ function probe_type:string() %{ /* pure */ /* unprivileged */ switch (CONTEXT->probe_type) { case stp_probe_type_been: strlcpy (STAP_RETVALUE, "begin_end", MAXSTRINGLEN); break; case stp_probe_type_itrace: strlcpy (STAP_RETVALUE, "itrace", MAXSTRINGLEN); break; case stp_probe_type_marker: strlcpy (STAP_RETVALUE, "kernel_marker", MAXSTRINGLEN); break; case stp_probe_type_perf: strlcpy (STAP_RETVALUE, "perf_event", MAXSTRINGLEN); break; case stp_probe_type_procfs: strlcpy (STAP_RETVALUE, "procfs", MAXSTRINGLEN); break; case stp_probe_type_timer: strlcpy (STAP_RETVALUE, "timer", MAXSTRINGLEN); break; case stp_probe_type_hrtimer: strlcpy (STAP_RETVALUE, "hrtimer", MAXSTRINGLEN); break; case stp_probe_type_profile_timer: strlcpy (STAP_RETVALUE, "profile_timer", MAXSTRINGLEN); break; case stp_probe_type_netfilter: strlcpy (STAP_RETVALUE, "netfilter", MAXSTRINGLEN); break; case stp_probe_type_utrace: strlcpy (STAP_RETVALUE, "utrace", MAXSTRINGLEN); break; case stp_probe_type_utrace_syscall: strlcpy (STAP_RETVALUE, "utrace_syscall", MAXSTRINGLEN); break; case stp_probe_type_kprobe: strlcpy (STAP_RETVALUE, "kprobe", MAXSTRINGLEN); break; case stp_probe_type_kretprobe: strlcpy (STAP_RETVALUE, "kretprobe", MAXSTRINGLEN); break; case stp_probe_type_uprobe: strlcpy (STAP_RETVALUE, "uprobe", MAXSTRINGLEN); break; case stp_probe_type_uretprobe: strlcpy (STAP_RETVALUE, "uretprobe", MAXSTRINGLEN); break; case stp_probe_type_hwbkpt: strlcpy (STAP_RETVALUE, "hardware_data_breakpoint", MAXSTRINGLEN); break; case stp_probe_type_tracepoint: strlcpy (STAP_RETVALUE, "kernel_tracepoint", MAXSTRINGLEN); break; default: /* This should never happen. */ snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "Unknown probe-type state %d", CONTEXT->probe_type); CONTEXT->last_error = CONTEXT->error_buffer; break; } %} systemtap-2.3/tapset/doc/000077500000000000000000000000001217430427200154565ustar00rootroot00000000000000systemtap-2.3/tapset/doc/discrepancies.txt000066400000000000000000000021031217430427200210270ustar00rootroot000000000000002.6.14 - All syscalls resolve, profiled & tested 2.6.15-rc6 - All syscalls resolve, profiled & tested 2.6.13-1.1532_FC4smp - sys_epoll_ctl cannot resolve parameters $op & $event sys_epoll_wait cannot resolve parameter $maxevents 2.6.14-1.1653_FC4smp - All syscalls resolve, profiled & tested 2.6.9-20.ELsmp - exit_group cannot resolve parameters $error_code getrusage cannot resolve parameters $who & $ru sys_inotify_add_watch no match for probe point sys_inotify_init no match for probe point sys_inotify_rm_watch no match for probe point sys_ioprio_get no match for probe point sys_ioprio_set no match for probe point do_sched_setscheduler no match for probe point set_zone_reclaim no match for probe point shmat no match for probe point sigaltstack cannot resolve parameters $ebx sys_sysfs cannot resolve parameters $option & $arg1 & $arg2 sys_umask cannot resolve parameters $mask systemtap-2.3/tapset/dyninst/000077500000000000000000000000001217430427200164015ustar00rootroot00000000000000systemtap-2.3/tapset/dyninst/context-envvar.stp000066400000000000000000000011551217430427200221160ustar00rootroot00000000000000// context-envvar tapset // Copyright (C) 2012 Red Hat, Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // NB: functionally equivalent to linux/context-envvar.stp %{ #include %} function env_var:string(name:string) %{ /* pure */ // XXX getenv may not be reentrant! const char* env = getenv(STAP_ARG_name); if (env) strlcpy (STAP_RETVALUE, env, MAXSTRINGLEN); else STAP_RETVALUE[0] = '\0'; %} systemtap-2.3/tapset/dyninst/context.stp000066400000000000000000000057171217430427200206270ustar00rootroot00000000000000// context tapset // Copyright (C) 2012 Red Hat, Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // NB: functionally equivalent to linux/context.stp %{ #include #include #include #include #include %} function execname:string () %{ /* Need a 16-byte buffer, which will be 0-terminated only if shorter. * Use 17 bytes to make sure we always have termination. */ char arg2[17] = {0}; if (prctl(PR_GET_NAME, (unsigned long)arg2, 0, 0, 0) == 0) strlcpy (STAP_RETVALUE, arg2, MAXSTRINGLEN); %} function pid:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = getpid(); %} function tid:long () %{ /* pure */ /* unprivileged */ /* NB: no glibc wrapper available */ STAP_RETVALUE = syscall(SYS_gettid); %} function ppid:long() %{ /* pure */ /* unprivileged */ STAP_RETVALUE = getppid(); %} function pgrp:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = getpgrp(); %} function sid:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = getsid(0); %} // TODO function pexecname:string () function gid:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = getgid(); %} function egid:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = getegid(); %} function uid:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = getuid(); %} function euid:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = geteuid(); %} // TODO function is_myproc:long () // NB: dyninst by nature is myproc-only, *except if you're root* function cpu:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = _stp_sched_getcpu(); %} function registers_valid:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = (CONTEXT->uregs != NULL); %} function user_mode:long () { return 1; } function is_return:long () %{ /* pure */ /* unprivileged */ if (CONTEXT->probe_type == stp_probe_type_uretprobe) STAP_RETVALUE = 1; else STAP_RETVALUE = 0; %} function target:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = stp_session_attributes()->target; %} function module_name:string () %{ /* pure */ /* unprivileged */ strlcpy(STAP_RETVALUE, stp_session_attributes()->module_name, MAXSTRINGLEN); %} function stp_pid:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = stp_session_attributes()->stp_pid; %} // TODO function remote_id:long () // TODO function remote_uri:string () // TODO function stack_size:long () // TODO function stack_used:long () // TODO function stack_unused:long () function addr:long () { return uaddr() } function uaddr:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = (intptr_t)(CONTEXT->uregs ? REG_IP(CONTEXT->uregs) : 0); %} // TODO function cmdline_args:string(n:long, m:long, delim:string) // TODO function cmdline_arg:string(n:long) // TODO function cmdline_str:string() systemtap-2.3/tapset/dyninst/ctime.stp000066400000000000000000000015121217430427200202310ustar00rootroot00000000000000/* ctime.stp - Convert seconds to human readable date string. * * Copyright (C) 2012 Red Hat, Inc. */ /* NB: functionally equivalent to linux/ctime.stp * This means unlike normal userspace ctime(), this version * returns time in UTC, without a final newline. */ %{ #include #include %} function ctime:string(epochsecs:long) %{ /* pure */ struct tm gmt; char buf[26]; const time_t t = STAP_ARG_epochsecs; if (gmtime_r(&t, &gmt) && asctime_r(&gmt, buf)) { char* newline = strchr(buf, '\n'); if (newline) *newline = '\0'; strlcpy (STAP_RETVALUE, buf, MAXSTRINGLEN); } else { #if STAP_COMPAT_VERSION <= STAP_VERSION(2,2) strlcpy(STAP_RETVALUE, "", MAXSTRINGLEN); #else CONTEXT->last_error = "Time cannot be converted"; #endif } %} systemtap-2.3/tapset/dyninst/endian.stp000066400000000000000000000013151217430427200203670ustar00rootroot00000000000000// NB: functionally equivalent to linux/endian.stp %{ #include %} function big_endian2:long (val:long) %{ /* pure */ STAP_RETVALUE = htobe16((uint16_t)STAP_ARG_val); %} function big_endian4:long (val:long) %{ /* pure */ STAP_RETVALUE = htobe32((uint32_t)STAP_ARG_val); %} function big_endian8:long (val:long) %{ /* pure */ STAP_RETVALUE = htobe64((uint64_t)STAP_ARG_val); %} function little_endian2:long (val:long) %{ /* pure */ STAP_RETVALUE = htole16((uint16_t)STAP_ARG_val); %} function little_endian4:long (val:long) %{ /* pure */ STAP_RETVALUE = htole32((uint32_t)STAP_ARG_val); %} function little_endian8:long (val:long) %{ /* pure */ STAP_RETVALUE = htole64((uint64_t)STAP_ARG_val); %} systemtap-2.3/tapset/dyninst/guru-delay.stp000066400000000000000000000010611217430427200212050ustar00rootroot00000000000000// Copyright (C) 2012 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // NB: functionally equivalent to linux/guru-delay.stp %{ #include %} function mdelay(ms:long) { udelay(ms * 1000); } function udelay(us:long) %{ /* guru */ struct timespec ts = { STAP_ARG_us / 1000000, STAP_ARG_us % 1000000, }; nanosleep(&ts, NULL); // XXX spin on EINTR? %} systemtap-2.3/tapset/dyninst/inet.stp000066400000000000000000000014341217430427200200720ustar00rootroot00000000000000/* Some functions from libc */ /* NB: functionally equivalent to linux/inet.stp * ... but we have the advantage of using (mostly) direct equivalents! */ %{ #include #include %} function htonll:long (x:long) %{ /* pure */ STAP_RETVALUE = htobe64 ((uint64_t) STAP_ARG_x); %} function htonl:long (x:long) %{ /* pure */ STAP_RETVALUE = htonl ((uint32_t) STAP_ARG_x); %} function htons:long (x:long) %{ /* pure */ STAP_RETVALUE = htons ((uint16_t) STAP_ARG_x); %} function ntohll:long (x:long) %{ /* pure */ STAP_RETVALUE = be64toh ((uint64_t) STAP_ARG_x); %} function ntohl:long (x:long) %{ /* pure */ STAP_RETVALUE = ntohl ((uint32_t) STAP_ARG_x); %} function ntohs:long (x:long) %{ /* pure */ STAP_RETVALUE = ntohs ((uint16_t) STAP_ARG_x); %} systemtap-2.3/tapset/dyninst/target_set.stp000066400000000000000000000011671217430427200212770ustar00rootroot00000000000000// NB: functionally equivalent to linux/target_set.stp global _target_set # map: target-set-pid -> ancestor-pid function target_set_pid (pid) { return ([pid] in _target_set) } probe begin { if (target()) _target_set[target()] = stp_pid() } probe process.begin { // NB: by definition, every process we see in stapdyn is part of the // target set, so we don't need to filter like linux/target_set.stp. _target_set[pid()] = ppid() } probe process.end { delete _target_set[pid()] } function target_set_report () { printf("target set:\n") foreach (pid in _target_set+) printf("%d begat %d\n", _target_set[pid], pid) } systemtap-2.3/tapset/dyninst/timestamp_gtod.stp000066400000000000000000000015241217430427200221530ustar00rootroot00000000000000// timestamp tapset -- gettimeofday variants // Copyright (C) 2012 Red Hat, Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // NB: functionally equivalent to linux/timestamp_gtod.stp %{ #include %} function gettimeofday_ns:long () { return gettimeofday_us() * 1000; // XXX available resolution isn't this high! } function gettimeofday_us:long () %{ /* pure */ /* unprivileged */ struct timeval tv; if (gettimeofday(&tv, NULL) == 0) STAP_RETVALUE = (uint64_t)tv.tv_sec * 1000000 + tv.tv_usec; %} function gettimeofday_ms:long () { return gettimeofday_us() / 1000; } function gettimeofday_s:long () { return gettimeofday_us() / 1000000; } systemtap-2.3/tapset/dyninst/tzinfo.stp000066400000000000000000000010751217430427200204450ustar00rootroot00000000000000// timezone tapset // Copyright (C) 2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // NB: functionally equivalent to linux/tzinfo.stp function tz_gmtoff() %{ /* pure */ /* unprivileged */ STAP_RETVALUE = stp_session_attributes()->tz_gmtoff; %} function tz_name() %{ /* pure */ /* unprivileged */ strlcpy(STAP_RETVALUE, stp_session_attributes()->tz_name, MAXSTRINGLEN); %} systemtap-2.3/tapset/errno.stp000066400000000000000000000202271217430427200165710ustar00rootroot00000000000000// errno tapset // Copyright (C) 2006 Red Hat Inc. // // This file is part of SystemTap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. %{ #define N(a) [a]=#a static const char * const errlist[] = { /* from asm-generic/errno-base.h */ [1] = "EPERM", [2] = "ENOENT", [3] = "ESRCH", [4] = "EINTR", [5] = "EIO", [6] = "ENXIO", [7] = "E2BIG", [8] = "ENOEXEC", [9] = "EBADF", [10]= "ECHILD", [11]= "EAGAIN", [12]= "ENOMEM", [13]= "EACCES", [14]= "EFAULT", [15]= "ENOTBLK", [16]= "EBUSY", [17]= "EEXIST", [18]= "EXDEV", [19]= "ENODEV", [20]= "ENOTDIR", [21]= "EISDIR", [22]= "EINVAL", [23]= "ENFILE", [24]= "EMFILE", [25]= "ENOTTY", [26]= "ETXTBSY", [27]= "EFBIG", [28]= "ENOSPC", [29]= "ESPIPE", [30]= "EROFS", [31]= "EMLINK", [32]= "EPIPE", [33]= "EDOM", [34]= "ERANGE", /* end of errno-base.h */ /* The rest of this is arch-dependent */ #ifdef EDEADLK N(EDEADLK), #endif #ifdef ENAMETOOLONG N(ENAMETOOLONG), #endif #ifdef ENOLCK N(ENOLCK), #endif #ifdef ENOSYS N(ENOSYS), #endif #ifdef ENOTEMPTY N(ENOTEMPTY), #endif #ifdef ELOOP N(ELOOP), #endif #ifdef ENOMSG N(ENOMSG), #endif #ifdef EIDRM N(EIDRM), #endif #ifdef ECHRNG N(ECHRNG), #endif #ifdef EL2NSYNC N(EL2NSYNC), #endif #ifdef EL3HLT N(EL3HLT), #endif #ifdef EL3RST N(EL3RST), #endif #ifdef ELNRNG N(ELNRNG), #endif #ifdef EUNATCH N(EUNATCH), #endif #ifdef ENOCSI N(ENOCSI), #endif #ifdef EL2HLT N(EL2HLT), #endif #ifdef EBADE N(EBADE), #endif #ifdef EBADR N(EBADR), #endif #ifdef EXFULL N(EXFULL), #endif #ifdef ENOANO N(ENOANO), #endif #ifdef EBADRQC N(EBADRQC), #endif #ifdef EBADSLT N(EBADSLT), #endif #ifdef EBFONT N(EBFONT), #endif #ifdef ENOSTR N(ENOSTR), #endif #ifdef ENODATA N(ENODATA), #endif #ifdef ETIME N(ETIME), #endif #ifdef ENOSR N(ENOSR), #endif #ifdef ENONET N(ENONET), #endif #ifdef ENOPKG N(ENOPKG), #endif #ifdef EREMOTE N(EREMOTE), #endif #ifdef ENOLINK N(ENOLINK), #endif #ifdef EADV N(EADV), #endif #ifdef ESRMNT N(ESRMNT), #endif #ifdef ECOMM N(ECOMM), #endif #ifdef EPROTO N(EPROTO), #endif #ifdef EMULTIHOP N(EMULTIHOP), #endif #ifdef EDOTDOT N(EDOTDOT), #endif #ifdef EBADMSG N(EBADMSG), #endif #ifdef EOVERFLOW N(EOVERFLOW), #endif #ifdef ENOTUNIQ N(ENOTUNIQ), #endif #ifdef EBADFD N(EBADFD), #endif #ifdef EREMCHG N(EREMCHG), #endif #ifdef ELIBACC N(ELIBACC), #endif #ifdef ELIBBAD N(ELIBBAD), #endif #ifdef ELIBSCN N(ELIBSCN), #endif #ifdef ELIBMAX N(ELIBMAX), #endif #ifdef ELIBEXEC N(ELIBEXEC), #endif #ifdef EILSEQ N(EILSEQ), #endif #ifdef ERESTART N(ERESTART), #endif #ifdef ESTRPIPE N(ESTRPIPE), #endif #ifdef EUSERS N(EUSERS), #endif #ifdef ENOTSOCK N(ENOTSOCK), #endif #ifdef EDESTADDRREQ N(EDESTADDRREQ), #endif #ifdef EMSGSIZE N(EMSGSIZE), #endif #ifdef EPROTOTYPE N(EPROTOTYPE), #endif #ifdef ENOPROTOOPT N(ENOPROTOOPT), #endif #ifdef EPROTONOSUPPORT N(EPROTONOSUPPORT), #endif #ifdef ESOCKTNOSUPPORT N(ESOCKTNOSUPPORT), #endif #ifdef EOPNOTSUPP N(EOPNOTSUPP), #endif #ifdef EPFNOSUPPORT N(EPFNOSUPPORT), #endif #ifdef EAFNOSUPPORT N(EAFNOSUPPORT), #endif #ifdef EADDRINUSE N(EADDRINUSE), #endif #ifdef EADDRNOTAVAIL N(EADDRNOTAVAIL), #endif #ifdef ENETDOWN N(ENETDOWN), #endif #ifdef ENETUNREACH N(ENETUNREACH), #endif #ifdef ENETRESET N(ENETRESET), #endif #ifdef ECONNABORTED N(ECONNABORTED), #endif #ifdef ECONNRESET N(ECONNRESET), #endif #ifdef ENOBUFS N(ENOBUFS), #endif #ifdef EISCONN N(EISCONN), #endif #ifdef ENOTCONN N(ENOTCONN), #endif #ifdef ESHUTDOWN N(ESHUTDOWN), #endif #ifdef ETOOMANYREFS N(ETOOMANYREFS), #endif #ifdef ETIMEDOUT N(ETIMEDOUT), #endif #ifdef ECONNREFUSED N(ECONNREFUSED), #endif #ifdef EHOSTDOWN N(EHOSTDOWN), #endif #ifdef EHOSTUNREACH N(EHOSTUNREACH), #endif #ifdef EALREADY N(EALREADY), #endif #ifdef EINPROGRESS N(EINPROGRESS), #endif #ifdef ESTALE N(ESTALE), #endif #ifdef EUCLEAN N(EUCLEAN), #endif #ifdef ENOTNAM N(ENOTNAM), #endif #ifdef ENAVAIL N(ENAVAIL), #endif #ifdef EISNAM N(EISNAM), #endif #ifdef EREMOTEIO N(EREMOTEIO), #endif #ifdef EDQUOT N(EDQUOT), #endif #ifdef ENOMEDIUM N(ENOMEDIUM), #endif #ifdef EMEDIUMTYPE N(EMEDIUMTYPE), #endif #ifdef ECANCELED N(ECANCELED), #endif #ifdef ENOKEY N(ENOKEY), #endif #ifdef EKEYEXPIRED N(EKEYEXPIRED), #endif #ifdef EKEYREVOKED N(EKEYREVOKED), #endif #ifdef EKEYREJECTED N(EKEYREJECTED), #endif #ifdef EOWNERDEAD N(EOWNERDEAD), #endif #ifdef ENOTRECOVERABLE N(ENOTRECOVERABLE), #endif #if defined (EDEADLOCK) && EDEADLOCK != EDEADLK N(EDEADLOCK), #endif #ifdef E N(EADV), #endif }; #undef N static const int Maxerrno = sizeof(errlist)/sizeof(char *); %} /** * sfunction errno_str - Symbolic string associated with error code * * @err: The error number received * * Description: This function returns the symbolic string associated * with the giver error code, such as ENOENT for the number 2, or * E#3333 for an out-of-range value such as 3333. */ function errno_str:string (err:long) %{ /* pure */ long e = STAP_ARG_err; e = (e > 0 ? e : -e); if (e > 0 && e < Maxerrno && errlist[e]) strlcpy (STAP_RETVALUE, errlist[e], MAXSTRINGLEN); %} function errno_p:long (err:long) %{ /* pure */ long e = STAP_ARG_err; e = (e > 0 ? e : -e); if (e > 0 && e < Maxerrno && errlist[e]) STAP_RETVALUE = e; else STAP_RETVALUE = 0; %} %{ static long _stp_returnval(struct pt_regs *regs) { if (regs) { #if defined (STAPCONF_X86_UNIREGS) && (defined (__x86_64__) || defined (__i386__)) return regs->ax; #elif defined (__i386__) return regs->eax; #elif defined (__x86_64__) // TODO: Handle -m32 apps. return regs->rax; #elif defined (__powerpc__) return regs->gpr[3]; #elif defined (__ia64__) return regs->r8; #elif defined (__sparc64__) return regs->u_regs[UREG_RETPC]; #elif defined (__s390x__) return regs->gprs[2]; #elif defined (__arm__) return regs->ARM_r0; #else _stp_error("returnval() not defined for this architecture"); return 0; #endif } else { _stp_error("returnval() not defined in this context"); return 0; } } %} /** * sfunction returnval - Possible return value of probed function * * Description: Return the value of the register in which function values * are typically returned. Can be used in probes where $return isn't * available. This is only a guess of the actual return value and can be * totally wrong. Normally only used in dwarfless probes. */ function returnval:long () %{ /* pure */ struct pt_regs *regs; regs = (CONTEXT->user_mode_p ? CONTEXT->uregs : CONTEXT->kregs); STAP_RETVALUE = _stp_returnval(regs); %} /** * sfunction returnstr - Formats the return value as a string * * @format: Variable to determine return type base value * * Description: This function is used by the nd_syscall tapset, and * returns a string. Set format equal to 1 for a decimal, * 2 for hex, 3 for octal. * * Note that this function should only be used in dwarfless probes * (i.e. 'kprobe.function("foo")'). Other probes should use * return_str(). */ function returnstr:string (format:long) %{ /* pure */ struct pt_regs *regs; regs = (CONTEXT->user_mode_p ? CONTEXT->uregs : CONTEXT->kregs); if (regs) { long ret = _stp_returnval(regs); if (ret < 0 && ret > -Maxerrno && errlist[-ret]) snprintf (STAP_RETVALUE, MAXSTRINGLEN, "%ld (%s)", ret, errlist[-ret]); else if (STAP_ARG_format == 2) snprintf (STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", ret); else if (STAP_ARG_format == 3) snprintf (STAP_RETVALUE, MAXSTRINGLEN, "%#lo", ret); else snprintf (STAP_RETVALUE, MAXSTRINGLEN, "%ld", ret); } else { no_ret: strlcpy(STAP_RETVALUE, "N/A", MAXSTRINGLEN); } %} /** * sfunction return_str - Formats the return value as a string * * @format: Variable to determine return type base value * @ret: Return value (typically $return) * * Description: This function is used by the syscall tapset, and * returns a string. Set format equal to 1 for a decimal, * 2 for hex, 3 for octal. * * Note that this function is preferred over returnstr(). */ function return_str:string(format:long, ret:long) { if (ret < 0 && errno_p(ret)) return sprintf("%d (%s)", ret, errno_str(ret)) if (format == 2) return sprintf("0x%x", ret) else if (format == 3) return sprintf("%#o", ret) else return sprintf("%d", ret) } systemtap-2.3/tapset/i386/000077500000000000000000000000001217430427200154025ustar00rootroot00000000000000systemtap-2.3/tapset/i386/registers.stp000066400000000000000000000151671217430427200201530ustar00rootroot00000000000000%{ /* Set to include regparm field in probe context in translate.cxx. */ #ifndef STAP_NEED_REGPARM #define STAP_NEED_REGPARM 1 #endif %} global _reg_offsets, _stp_regs_registered, _sp_offset, _ss_offset function test_x86_gs:long() %{ /* pure */ #ifdef STAPCONF_X86_GS STAP_RETVALUE = 1; #else STAP_RETVALUE = 0; #endif %} function _stp_register_regs() { /* Same order as pt_regs */ _reg_offsets["ebx"] = 0 _reg_offsets["bx"] = 0 _reg_offsets["ecx"] = 4 _reg_offsets["cx"] = 4 _reg_offsets["edx"] = 8 _reg_offsets["dx"] = 8 _reg_offsets["esi"] = 12 _reg_offsets["si"] = 12 _reg_offsets["edi"] = 16 _reg_offsets["di"] = 16 _reg_offsets["ebp"] = 20 _reg_offsets["bp"] = 20 _reg_offsets["eax"] = 24 _reg_offsets["ax"] = 24 _reg_offsets["xds"] = 28 _reg_offsets["ds"] = 28 _reg_offsets["xes"] = 32 _reg_offsets["es"] = 32 _reg_offsets["xfs"] = 36 _reg_offsets["fs"] = 36 gs_incr = 0 if (test_x86_gs()) { gs_incr = 4 _reg_offsets["xgs"] = 40 _reg_offsets["gs"] = 40 } _reg_offsets["orig_eax"] = 40 + gs_incr _reg_offsets["orig_ax"] = 40 + gs_incr _reg_offsets["eip"] = 44 + gs_incr _reg_offsets["ip"] = 44 + gs_incr _reg_offsets["xcs"] = 48 + gs_incr _reg_offsets["cs"] = 48 + gs_incr _reg_offsets["eflags"] = 52 + gs_incr _reg_offsets["flags"] = 52 + gs_incr _reg_offsets["esp"] = 56 + gs_incr _reg_offsets["sp"] = 56 + gs_incr _reg_offsets["xss"] = 60 + gs_incr _reg_offsets["ss"] = 60 + gs_incr _sp_offset = 56 + gs_incr _ss_offset = 60 + gs_incr _stp_regs_registered = 1 } function _stp_get_register_by_offset:long (offset:long) %{ /* pure */ long value; struct pt_regs *regs; regs = (CONTEXT->user_mode_p ? CONTEXT->uregs : CONTEXT->kregs); if (!regs) { CONTEXT->last_error = "No registers available in this context"; return; } if (STAP_ARG_offset < 0 || STAP_ARG_offset > sizeof(struct pt_regs) - sizeof(long)) { snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "Bad register offset: %lld", STAP_ARG_offset); CONTEXT->last_error = CONTEXT->error_buffer; return; } memcpy(&value, ((char *)regs) + STAP_ARG_offset, sizeof(value)); STAP_RETVALUE = value; %} function _stp_probing_kernel:long () { return !user_mode(); } /* * esp and ss aren't saved on a breakpoint in kernel mode, so * the pre-trap stack pointer is ®s->sp. */ function _stp_kernel_sp:long (sp_offset:long) %{ /* pure */ STAP_RETVALUE = ((long) CONTEXT->kregs) + STAP_ARG_sp_offset; %} /* Assume ss register hasn't changed since we took the trap. */ function _stp_kernel_ss:long () %{ /* pure */ unsigned short ss; asm volatile("movw %%ss, %0" : : "m" (ss)); STAP_RETVALUE = ss; %} /* Return the named register value as a signed value. */ function register:long (name:string) { if (!registers_valid()) { error("cannot access CPU registers in this context") return 0 } if (!_stp_regs_registered) _stp_register_regs() offset = _reg_offsets[name] if (offset == 0 && !(name in _reg_offsets)) { error("Unknown register: " . name) return 0 } if (_stp_probing_kernel()) { if (offset == _sp_offset) return _stp_kernel_sp(_sp_offset) else if (offset == _ss_offset) return _stp_kernel_ss() } return _stp_get_register_by_offset(offset) } /* * Return the named register value as an unsigned value. Specifically, * don't sign-extend the register value when promoting it to 64 bits. */ function u_register:long (name:string) { return register(name) & 0xffffffff; } /* Return the value of function arg #argnum (1=first arg) as a signed value. */ function _stp_arg:long (argnum:long) %{ /* pure */ long val; int n, nr_regargs, result; struct pt_regs *regs; regs = (CONTEXT->user_mode_p ? CONTEXT->uregs : CONTEXT->kregs); STAP_RETVALUE = 0; if (!regs) { snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "cannot access function args in this context"); CONTEXT->last_error = CONTEXT->error_buffer; return; } if (STAP_ARG_argnum < 1) goto bad_argnum; n = (int) STAP_ARG_argnum; if (CONTEXT->regparm == 0) { /* Default */ if (CONTEXT->user_mode_p) nr_regargs = 0; else nr_regargs = 3; } else nr_regargs = (CONTEXT->regparm & _STP_REGPARM_MASK); result = _stp_get_arg32_by_number(n, nr_regargs, regs, &val); switch (result) { case 0: /* Arg is in register. */ STAP_RETVALUE = (int64_t) val; break; case 1: /* Arg is on kernel stack. */ STAP_RETVALUE = kread((long *) val); break; case 2: { /* Arg is on user stack. */ const char __user *vaddr = (const char __user*) val; if (_stp_copy_from_user((char*)&val, vaddr, sizeof(val)) != 0) { /* Stack page not resident. */ _stp_warn("cannot access arg(%d) " "at user stack address %p\n", n, vaddr); STAP_RETVALUE = 0; } else STAP_RETVALUE = (int64_t) val; break; } default: goto bad_argnum; } return; bad_argnum: snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "cannot access arg(%lld)", STAP_ARG_argnum); CONTEXT->last_error = CONTEXT->error_buffer; return; if (0) { deref_fault: /* branched to from kread() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel fault at %#lx accessing arg(%lld)", val, STAP_ARG_argnum); CONTEXT->last_error = CONTEXT->error_buffer; } %} /* Return the value of function arg #argnum as a signed int. */ function int_arg:long (argnum:long) { return _stp_arg(argnum) } /* Return the value of function arg #argnum as an unsigned int. */ function uint_arg:long (argnum:long) { return _stp_arg(argnum) & 0xffffffff; } function long_arg:long (argnum:long) { return int_arg(argnum) } function ulong_arg:long (argnum:long) { return uint_arg(argnum) } function longlong_arg:long (argnum:long) { /* * TODO: If argnum == nr_regarg, gcc puts the whole 64-bit arg * on the stack. */ lowbits = uint_arg(argnum) highbits = uint_arg(argnum+1) return ((highbits << 32) | lowbits) } function ulonglong_arg:long (argnum:long) { return longlong_arg(argnum) } function pointer_arg:long (argnum:long) { return ulong_arg(argnum) } function s32_arg:long (argnum:long) { return int_arg(argnum) } function u32_arg:long (argnum:long) { return uint_arg(argnum) } function s64_arg:long (argnum:long) { return longlong_arg(argnum) } function u64_arg:long (argnum:long) { return ulonglong_arg(argnum) } function asmlinkage() %{ CONTEXT->regparm = _STP_REGPARM | 0; %} function fastcall() %{ CONTEXT->regparm = _STP_REGPARM | 3; %} function regparm(n:long) %{ if (STAP_ARG_n < 0 || STAP_ARG_n > 3) { snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "For i386, regparm value must be in the range 0-3."); CONTEXT->last_error = CONTEXT->error_buffer; } else CONTEXT->regparm = _STP_REGPARM | (int) STAP_ARG_n; %} systemtap-2.3/tapset/ia64/000077500000000000000000000000001217430427200154545ustar00rootroot00000000000000systemtap-2.3/tapset/ia64/registers.stp000066400000000000000000000007221217430427200202140ustar00rootroot00000000000000/* * Dwarfless register access for ia64. Unfortunately, getting * registers/arguments on the ia64 is unimplemented (because it is * non-trivial retrieving the arguments from the stack). * * Note that using syscall_get_arguments() (as the s390x does) doesn't * work on ia64. * * The rest of this file would be intentionally blank until ia64 * register/argument support is added, but tapset files can't be * completely empty. */ global __stp_unused_global systemtap-2.3/tapset/indent-default.stp000066400000000000000000000000731217430427200203440ustar00rootroot00000000000000function __indent_timestamp() { return gettimeofday_us() } systemtap-2.3/tapset/indent.stp000066400000000000000000000060231217430427200167230ustar00rootroot00000000000000/* * The indent tapset provides functions to generate indented lines for * nested kinds of trace messages. Each line contains a relative * timestamp, and the process name / pid. * */ global _indent_counters, _indent_timestamps function _generic_indent (idx, desc, delta) { ts = __indent_timestamp () if (! _indent_counters[idx]) _indent_timestamps[idx] = ts # pre-increment for positive delta and post-decrement for negative delta x = _indent_counters[idx] + (delta > 0 ? delta : 0) _indent_counters[idx] += delta return sprintf("%6d %s:%-*s", (ts - _indent_timestamps[idx]), desc, (x>0 ? x-1 : 0), "") } /** * sfunction thread_indent - returns an amount of space with the current task information * * @delta: the amount of space added/removed for each call * * Description: This function returns a string with appropriate * indentation for a thread. Call it with a small positive or * matching negative delta. If this is the real outermost, * initial level of indentation, then the function resets the * relative timestamp base to zero. An example is shown at the * end of this file. */ function thread_indent:string (delta:long) { return _generic_indent (tid(), sprintf("%s(%d)", execname(), tid()), delta) } /** * sfunction indent - returns an amount of space to indent * * @delta: the amount of space added/removed for each call * * Description: This function returns a string with appropriate * indentation. Call it with a small positive or matching negative * delta. Unlike the thread_indent function, the indent does not * track individual indent values on a per thread basis. */ function indent:string (delta:long){ return _generic_indent(-1, "", delta) } /* The following example uses thread_indent() to trace the functions * called in the drivers/usb/core kernel source. It prints a relative * timestamp and the name and ID of the current process, followed by * the appropriate indent and the function name. Note that * 'char' swapper(0) indicates the kernel is running in interrupt * context and there is no valid current process. * * probe kernel.function("*@drivers/usb/core/*") { * printf("%s -> %s\n, thread_indent(1), probefunc()) * } * probe kernel.function("*@drivers/usb/core/*").return { * printf("%s <- %s\n", thread_indent(-1), probefunc()) * } * * //This prints: * 0 swapper(0): -> usb_hcd_irq * 8 swapper(0): <- usb_hcd_irq * 0 swapper(0): -> usb_hcd_irq * 10 swapper(0): -> usb_hcd_giveback_urb * 16 swapper(0): -> urb_unlink * 22 swapper(0): <- usb_unlink * 29 swapper(0): -> usb_free_urb * 35 swapper(0): <- usb_hcd_urb * 39 swapper(0): <- usb_hcd_giveback_urb * 45 swapper(0): <- usb_hcd_irq * 0 usb-storage(1338): -> usb_submit_urb * 6 usb-storage(1338): -> usb_hcd_submit_urb * 12 usb-storage(1338): -> usb_get_urb * 18 usb-storage(1338): <- usb_get_urb * 25 usb-storage(1338): <- usb_hcd_submit_urb * 29 usb-storage(1338): -> usb_submit_urb * 0 swapper(0): -> usb_hcd_irq * 7 swapper(0): <- usb_hcd_irq */ systemtap-2.3/tapset/linux/000077500000000000000000000000001217430427200160505ustar00rootroot00000000000000systemtap-2.3/tapset/linux/arm/000077500000000000000000000000001217430427200166275ustar00rootroot00000000000000systemtap-2.3/tapset/linux/arm/aux_syscalls.stp000066400000000000000000000032731217430427200220760ustar00rootroot00000000000000# arch-specific requests of ptrace ___________________________ # function _arch_ptrace_argstr(request, pid, addr, data) { if (request == %{ PTRACE_GETREGS %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GETREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_SETREGS %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SETREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_GETFPREGS %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GETFPREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_SETFPREGS %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SETFPREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_GETWMMXREGS %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GETWMMXREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_SETWMMXREGS %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SETWMMXREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_OLDSETOPTIONS %}) return sprintf ("PTRACE_OLDSETOPTIONS, %d, %s", pid, _ptrace_options_str (data)) if (request == %{ PTRACE_GET_THREAD_AREA %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GET_THREAD_AREA, %d, index=%d, data=%p", pid, addr, data) if (request == %{ PTRACE_SET_SYSCALL %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SET_SYSCALL, %d, index=%p, data=%p", pid, addr, data) if (request == %{ PTRACE_GETCRUNCHREGS %}) return sprintf ("PTRACE_GETCRUNCHREGS, %d, %s", pid, _signal_name (data)) if (request == %{ PTRACE_SETCRUNCHREGS %}) return sprintf ("PTRACE_SETCRUNCHREGS, %d, %s", pid, _signal_name (data)) } function _ptrace_return_arch_prctl_addr:long(request:long, addr:long, data:long) { return 0 } systemtap-2.3/tapset/linux/atomic.stp000066400000000000000000000030211217430427200200500ustar00rootroot00000000000000// Atomic functions. // Copyright (C) 2010 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /** * sfunction atomic_read - Retrieves an atomic variable from kernel memory * * @addr: pointer to atomic variable * * Safely perform the read of an atomic variable. */ function atomic_read:long(addr:long) %{ /* pure */ atomic_t *a = (atomic_t *)(long)STAP_ARG_addr; /* We call deref() here to ensure the memory is valid to read. * Note the result is thrown away, then we use the "real" * atomic read function now that we know the address is safe. */ (void)kderef(sizeof(*a), a); STAP_RETVALUE = atomic_read(a); CATCH_DEREF_FAULT(); %} /** * sfunction atomic_long_read - Retrieves an atomic long variable from kernel memory * * @addr: pointer to atomic long variable * * Safely perform the read of an atomic long variable. This will be a * NOP on kernels that do not have ATOMIC_LONG_INIT set on the kernel config. */ function atomic_long_read:long(addr:long) %{ /* pure */ #ifdef ATOMIC_LONG_INIT atomic_long_t *a = (atomic_long_t *)(long)STAP_ARG_addr; /* We call deref() here to ensure the memory is valid to read. * Note the result is thrown away, then we use the "real" * atomic read function now that we know the address is safe. */ (void)kderef(sizeof(*a), a); STAP_RETVALUE = atomic_long_read(a); CATCH_DEREF_FAULT(); #endif %} systemtap-2.3/tapset/linux/aux_syscalls.stp000066400000000000000000001745531217430427200213310ustar00rootroot00000000000000%{ #ifdef CONFIG_COMPAT #include #ifndef STAPCONF_SIGSET_FROM_COMPAT_EXPORTED void sigset_from_compat(sigset_t *set, compat_sigset_t *compat) { switch (_NSIG_WORDS) { case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32 ); case 3: set->sig[2] = compat->sig[4] | (((long)compat->sig[5]) << 32 ); case 2: set->sig[1] = compat->sig[2] | (((long)compat->sig[3]) << 32 ); case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32 ); } } #endif /* STAPCONF_SIGSET_FROM_COMPAT_EXPORTED */ #endif /* CONFIG_COMPAT */ %} # # Given a userspace pointer to a timeval, # copy and decode it and return a string. # function _struct_timeval_u:string(uaddr:long, n:long) %{ /* pure */ int n = (int)STAP_ARG_n; struct timeval tv[n]; char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; if (ptr == NULL || n > 2) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char*)&tv, ptr, n*sizeof(struct timeval)) == 0) { if (n == 2) snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%ld.%06ld][%ld.%.06ld]", tv[0].tv_sec, tv[0].tv_usec, tv[1].tv_sec, tv[1].tv_usec); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%ld.%06ld]", tv[0].tv_sec, tv[0].tv_usec); } else strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); } %} function _struct_compat_timeval_u:string(uaddr:long, n:long) %{ /* pure */ #ifdef CONFIG_COMPAT int n = (int)STAP_ARG_n; struct compat_timeval tv[n]; char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; if (ptr == NULL || n > 2) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char*)&tv, ptr, n*sizeof(struct compat_timeval)) == 0) if (n == 2) snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%ld.%06ld][%ld.%.06ld]", (long)tv[0].tv_sec, (long)tv[0].tv_usec, (long)tv[1].tv_sec, (long)tv[1].tv_usec); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%ld.%06ld]", (long)tv[0].tv_sec, (long)tv[0].tv_usec); else strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); } #endif %} function _struct_timezone_u:string(uaddr:long) %{ /* pure */ struct timezone tz; char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char*)&tz,ptr,sizeof(struct timezone)) == 0) snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%d, %d]", tz.tz_minuteswest, tz.tz_dsttime); else strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); } %} %{ // Needed for the following four functions // _struct_utimbuf_actime, _struct_utimbuf_modtime, // _struct_compat_utimbuf_actime, _struct_compat_utimbuf_modtime #include %} // Returns the value of the actime field of a utimbuf in user space // at the given address, or zero on when userspace data is not accessible. function _struct_utimbuf_actime:long(uaddr:long) %{ /* pure */ struct utimbuf ubuf; char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; if (ptr == NULL) STAP_RETVALUE = 0; else if(_stp_copy_from_user((char*)&ubuf,ptr,sizeof(ubuf)) == 0) STAP_RETVALUE = ubuf.actime; else STAP_RETVALUE = 0; %} // Returns the value of the modtime field of a utimbuf in user space // at the given address, or zero on when userspace data is not accessible. function _struct_utimbuf_modtime:long(uaddr:long) %{ /* pure */ struct utimbuf ubuf; char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; if (ptr == NULL) STAP_RETVALUE = 0; else if(_stp_copy_from_user((char*)&ubuf,ptr,sizeof(ubuf)) == 0) STAP_RETVALUE = ubuf.modtime; else STAP_RETVALUE = 0; %} // Returns the value of the actime field of a compat_utimbuf in user space // at the given address, or zero on when userspace data is not accessible. function _struct_compat_utimbuf_actime:long(uaddr:long) %{ /* pure */ #ifdef CONFIG_COMPAT struct compat_utimbuf ubuf; char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; if (ptr == NULL) STAP_RETVALUE = 0; else if(_stp_copy_from_user((char*)&ubuf,ptr,sizeof(ubuf)) == 0) STAP_RETVALUE = ubuf.actime; else STAP_RETVALUE = 0; #endif %} // Returns the value of the modtime field of a compat_utimbuf in user space // at the given address, or zero on when userspace data is not accessible. function _struct_compat_utimbuf_modtime:long(uaddr:long) %{ /* pure */ #ifdef CONFIG_COMPAT struct compat_utimbuf ubuf; char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; if (ptr == NULL) STAP_RETVALUE = 0; else if(_stp_copy_from_user((char*)&ubuf,ptr,sizeof(ubuf)) == 0) STAP_RETVALUE = ubuf.modtime; else STAP_RETVALUE = 0; #endif %} function _struct_timespec_u:string(uaddr:long, n:long) %{ /* pure */ #define STP_UTIME_NOW ((1l << 30) - 1l) #define STP_UTIME_OMIT ((1l << 30) - 2l) int n = (int)STAP_ARG_n; struct timespec ts[n]; char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; if (ptr == NULL || n > 2) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char *)&ts, ptr, n*sizeof(struct timespec))) { strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); } else { char *str; int len, i = 0; ptr = STAP_RETVALUE; while (i < n) { str = NULL; if (ts[i].tv_nsec == STP_UTIME_NOW) str = "UTIME_NOW"; else if (ts[i].tv_nsec == STP_UTIME_OMIT) str = "UTIME_OMIT"; if (str) len = snprintf(ptr, MAXSTRINGLEN, "[%s]", str); else len = snprintf(ptr, MAXSTRINGLEN, "[%ld.%09ld]", (long)ts[i].tv_sec, ts[i].tv_nsec); ptr += len; i++; } } } #undef STP_UTIME_NOW #undef STP_UTIME_OMIT %} function _struct_compat_timespec_u:string(uaddr:long, n:long) %{ /* pure */ #ifdef CONFIG_COMPAT #define STP_UTIME_NOW ((1l << 30) - 1l) #define STP_UTIME_OMIT ((1l << 30) - 2l) int n = (int)STAP_ARG_n; struct compat_timespec ts[n]; char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; if (ptr == NULL || n > 2) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char *)&ts, ptr, n*sizeof(struct compat_timespec))) { strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); } else { char *str; int len, i = 0; ptr = STAP_RETVALUE; while (i < n) { str = NULL; if (ts[i].tv_nsec == STP_UTIME_NOW) str = "UTIME_NOW"; else if (ts[i].tv_nsec == STP_UTIME_OMIT) str = "UTIME_OMIT"; if (str) len = snprintf(ptr, MAXSTRINGLEN, "[%s]", str); else len = snprintf(ptr, MAXSTRINGLEN, "[%ld.%09ld]", (long)ts[i].tv_sec, (long)ts[i].tv_nsec); ptr += len; i++; } } } #undef STP_UTIME_NOW #undef STP_UTIME_OMIT #endif %} function _struct_itimerspec_u:string(uaddr:long) %{ /* pure */ struct itimerspec its; char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char *)&its, ptr,sizeof(struct itimerspec))) strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%d.%06d,%d.%06d]", (int)its.it_interval.tv_sec, (int)its.it_interval.tv_nsec, (int)its.it_value.tv_sec, (int)its.it_value.tv_nsec); } %} function _struct_itimerval_u:string(uaddr:long) %{ /* pure */ struct itimerval itv; char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char *)&itv,ptr,sizeof(struct itimerval))) strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%d.%06d,%d.%06d]", (int)itv.it_interval.tv_sec, (int)itv.it_interval.tv_usec, (int)itv.it_value.tv_sec, (int)itv.it_value.tv_usec); } %} function _struct_compat_itimerval_u:string(uaddr:long) %{ /* pure */ #ifdef CONFIG_COMPAT struct compat_itimerval itv; char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char *)&itv,ptr,sizeof(struct compat_itimerval))) strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%d.%06d,%d.%06d]", (int)itv.it_interval.tv_sec, (int)itv.it_interval.tv_usec, (int)itv.it_value.tv_sec, (int)itv.it_value.tv_usec); } #endif %} %{ // Needed for function _struct_sockaddr_u. Unfortunately cannot be // inlined into the function since these header files define static // functions themselves. #include #include #include %} function _struct_sockaddr_u:string(uaddr:long, len:long) %{ /* pure */ #include #include #include #include char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; char buf[128]; size_t len = STAP_ARG_len < 128 ? STAP_ARG_len : 128; struct sockaddr *sa = (struct sockaddr *)buf; if (ptr == NULL) { strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); return; } if (_stp_copy_from_user(buf, ptr, len)) { strlcpy (STAP_RETVALUE, "[...]", MAXSTRINGLEN); return; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) #define LPORT (inet->inet.num) #define DADDR (&inet->inet.daddr) #else #define LPORT (inet->num) #define DADDR (&inet->daddr) #endif // Use kernel builtin instead of picking up user space ntohs (function). #define _stp_ntohs be16_to_cpu if ((sa->sa_family == AF_INET) && (len == sizeof(struct sockaddr_in))) { struct sockaddr_in *sin = (struct sockaddr_in *)buf; #ifndef NIPQUAD_FMT // kver >= 2.6.36 snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_INET, %pI4, %d}", &sin->sin_addr, _stp_ntohs(sin->sin_port)); #else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_INET, " NIPQUAD_FMT ", %d}", NIPQUAD(sin->sin_addr), _stp_ntohs(sin->sin_port)); #endif } else if ((sa->sa_family == AF_UNIX) && (len == sizeof(struct sockaddr_un))) { struct sockaddr_un *sun = (struct sockaddr_un *)buf; snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_UNIX, %s}", sun->sun_path); } else if ((sa->sa_family == AF_NETLINK) && (len == sizeof(struct sockaddr_nl))) { struct sockaddr_nl *nl = (struct sockaddr_nl *)buf; snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_NETLINK, pid=%d, groups=%08x}", nl->nl_pid, nl->nl_groups); } else if ((sa->sa_family == AF_INET6) && (len == sizeof(struct sockaddr_in6))) { struct sockaddr_in6 *sin = (struct sockaddr_in6 *)buf; #ifndef NIP6_FMT // kver >= 2.6.36 snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_INET6, %pI6, %d}", &sin->sin6_addr, _stp_ntohs(sin->sin6_port)); #else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_INET6, " NIP6_FMT ", %d}", NIP6(sin->sin6_addr), _stp_ntohs(sin->sin6_port)); #endif } else if ((sa->sa_family == AF_PACKET) && (len == sizeof(struct sockaddr_ll))) { struct sockaddr_ll *sll = (struct sockaddr_ll *)buf; snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_PACKET, proto=%d, ind=%d, hatype=%d, pkttype=%d, halen=%d, addr=0x%llx}", (int)sll->sll_protocol, sll->sll_ifindex, (int)sll->sll_hatype, (int)sll->sll_pkttype, (int)sll->sll_halen, (long long)(*(uint64_t *)sll->sll_addr)); } else { if (len >= sizeof(sa_family_t)) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{unknown sockaddr with sa=%d, salen=%d}", sa->sa_family, (int) len); } else { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{unknown sockaddr with salen=%d}", (int)len); } } %} function _struct_rlimit_u:string(uaddr:long) %{ /* pure */ struct rlimit rl; char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char *)&rl, ptr, sizeof(struct rlimit)) == 0) snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%ld,%ld]", rl.rlim_cur, rl.rlim_max); else strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); } %} function _fildes_index_u:long (uaddr:long, index:long) %{ /* pure */ int fd[2]; char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; if (ptr == NULL || !(STAP_ARG_index == 0 || STAP_ARG_index == 1)) STAP_RETVALUE = 0; else { if (_stp_copy_from_user((char *)&fd, ptr, 2*sizeof(int)) == 0) STAP_RETVALUE = fd[STAP_ARG_index]; else STAP_RETVALUE = 0; } %} function __sem_flags:string(semflg:long) %{ /* pure */ long semflg = STAP_ARG_semflg; char *str = STAP_RETVALUE; int mode = semflg & S_IRWXUGO; int len; str[0] = '\0'; if (mode) snprintf(str, MAXSTRINGLEN, "%#o|", mode); if (semflg & IPC_CREAT) strlcat(str, "IPC_CREAT|", MAXSTRINGLEN); if (semflg & IPC_EXCL) strlcat(str, "IPC_EXCL|", MAXSTRINGLEN); len = strlen(str); if (len) str[len-1] = 0; %} /* This function copies an argv from userspace. */ function __get_argv:string(argv:long, first:long) { %( CONFIG_64BIT == "y" %? if (first && argv) argv += 8 while (argv) { vstr = user_long(argv) if (!vstr) break if (len) str .= " " str .= user_string_quoted(vstr) newlen = strlen(str) if (newlen == len) break len = newlen argv += 8 } return str %: return __get_compat_argv(argv, first) %) } /* This function copies an argv from userspace. */ function __get_compat_argv:string(argv:long, first:long) { if (first && argv) argv += 4 while (argv) { vstr = user_int(argv) & 0xffffffff if (!vstr) break if (len) str .= " " str .= user_string_quoted(vstr) newlen = strlen(str) if (newlen == len) break len = newlen argv += 4 } return str } /* * Return the symbolic string representation * of the struct timex.mode member of adjtimex * consult `man adjtimex` for more information * CALLERS: * syscall.adjtimex */ function _adjtx_mode_str(f) { if((f & 32769) == 32769) bs="ADJ_OFFSET_SINGLESHOT|".bs if(f & 16384) bs="ADJ_TICK|".bs if(f & 32) bs="ADJ_TIMECONST|".bs if(f & 16) bs="ADJ_STATUS|".bs if(f & 8) bs="ADJ_ESTERROR|".bs if(f & 4) bs="ADJ_MAXERROR|".bs if(f & 2) bs="ADJ_FREQUENCY|".bs if(f & 1 && ((f & 32769) != 32769)) bs="ADJ_OFFSET|".bs return substr(bs,0,strlen(bs)-1) } function _inotify_watch_mask_str(f) { if (f & 0x00000001) bs="IN_ACCESS|" if (f & 0x00000002) bs=bs."IN_MODIFY|" if (f & 0x00000004) bs=bs."IN_ATTRIB|" if (f & 0x00000008) bs=bs."IN_CLOSE_WRITE|" if (f & 0x00000010) bs=bs."IN_CLOSE_NOWRITE|" if (f & 0x00000020) bs=bs."IN_OPEN|" if (f & 0x00000040) bs=bs."IN_MOVED_FROM|" if (f & 0x00000080) bs=bs."IN_MOVED_TO|" if (f & 0x00000100) bs=bs."IN_CREATE|" if (f & 0x00000200) bs=bs."IN_DELETE|" if (f & 0x00000400) bs=bs."IN_DELETE_SELF|" if (f & 0x00000800) bs=bs."IN_MOVE_SELF|" return substr(bs,0,strlen(bs)-1) } /* * Return the symbolic string representation * of the how argument given in *sigprocmask * consult `man sigprocmask` for more info * CALLERS: * syscall.sigprocmask * syscall.rt_sigprocmask */ function _sigprocmask_how_str:string(how:long) %{ /* pure */ int len; char *str = STAP_RETVALUE; switch (STAP_ARG_how) { case SIG_BLOCK: strlcpy(str, "SIG_BLOCK", MAXSTRINGLEN); break; case SIG_UNBLOCK: strlcpy(str, "SIG_UNBLOCK", MAXSTRINGLEN); break; case SIG_SETMASK: strlcpy(str, "SIG_SETMASK", MAXSTRINGLEN); break; default: snprintf(str, MAXSTRINGLEN, "0x%lx", (long)STAP_ARG_how); } %} /* * Return the symbolic string representation * of the which argument given to setitimer * consult `man setitimer` for more info * CALLERS: * syscall.getitimer * syscall.setitimer * INCLUDE: */ function _itimer_which_str(which) { if(which==0) return "ITIMER_REAL" if(which==1) return "ITIMER_VIRTUAL" if(which==2) return "ITIMER_PROF" return sprintf("BAD VALUE: %d", which) } /* * Return the command name for nfsservctl() * nfsservctl was removed in kernel 3.0/2.6.40. */ %( kernel_v < "2.6.40" && CONFIG_NFSD == "[ym]" %? function _nfsctl_cmd_str(cmd) { if(cmd == 0) return "NFSCTL_SVC" if(cmd == 1) return "NFSCTL_ADDCLIENT" if(cmd == 2) return "NFSCTL_DELCLIENT" if(cmd == 3) return "NFSCTL_EXPORT" if(cmd == 4) return "NFSCTL_UNEXPORT" if(cmd == 5) return "NFSCTL_UGIDUPDATE" if(cmd == 6) return "NFSCTL_GETFH" if(cmd == 7) return "NFSCTL_GETFD" if(cmd == 8) return "NFSCTL_GETFS" return sprintf("UNRECOGNIZED VALUE: %d", cmd) } %) /* * Return the symbolic string representation * of the clockid argument given to create_timer * consult `man create_timer` for more info * CALLERS: * syscall.timer_create * syscall.clock_settime * syscall.clock_gettime * syscall.clock_getres * syscall.clock_nanosleep */ function _get_wc_str(wc) { if(wc==0) return "CLOCK_REALTIME" if(wc==1) return "CLOCK_MONOTONIC" if(wc==2) return "CLOCK_PROCESS_CPUTIME_ID" if(wc==3) return "CLOCK_THREAD_CPUTIME_ID" if(wc==4) return "CLOCK_REALTIME_HR" if(wc==5) return "CLOCK_MONOTONIC_HR" return sprintf("BAD VALUE: %d", wc) } function _flock_cmd_str(c) { if(c & 1) bs="LOCK_SH|".bs if(c & 2) bs="LOCK_EX|".bs if(c & 8) bs="LOCK_UN|".bs if(c & 4) bs="LOCK_NB|".bs return substr(bs,0,strlen(bs)-1) } /* `man 2 pipe2` for more information */ function _sys_pipe2_flag_str:string (f:long) %{ /* pure */ /* unprivileged */ long flags = STAP_ARG_f; char *str = STAP_RETVALUE; int len; str[0] = '\0'; #if defined(O_NONBLOCK) if (flags & O_NONBLOCK) strlcat(str, "O_NONBLOCK|", MAXSTRINGLEN); #endif #if defined(O_CLOEXEC) if (flags & O_CLOEXEC) strlcat(str, "O_CLOEXEC|", MAXSTRINGLEN); #endif len = strlen(str); if (len) str[strlen(str)-1] = 0; %} /* `man 2 open` for more information */ function _sys_open_flag_str:string (f:long) %{ /* pure */ int flags = (int)STAP_ARG_f; int acc = flags & O_ACCMODE; switch (acc) { case O_WRONLY: strlcpy (STAP_RETVALUE, "O_WRONLY", MAXSTRINGLEN); break; case O_RDWR: strlcpy (STAP_RETVALUE, "O_RDWR", MAXSTRINGLEN); break; default: strlcpy (STAP_RETVALUE, "O_RDONLY", MAXSTRINGLEN); } #ifdef O_APPEND if (flags & O_APPEND) strlcat (STAP_RETVALUE, "|O_APPEND", MAXSTRINGLEN); #endif #ifdef O_ASYNC if (flags & O_ASYNC) strlcat (STAP_RETVALUE, "|O_ASYNC", MAXSTRINGLEN); #elif defined(FASYNC) if (flags & FASYNC) strlcat (STAP_RETVALUE, "|O_ASYNC", MAXSTRINGLEN); #endif #ifdef O_CLOEXEC if (flags & O_CLOEXEC) strlcat (STAP_RETVALUE, "|O_CLOEXEC", MAXSTRINGLEN); #endif #ifdef O_CREAT if (flags & O_CREAT) strlcat (STAP_RETVALUE, "|O_CREAT", MAXSTRINGLEN); #endif #ifdef O_DIRECT if (flags & O_DIRECT) strlcat (STAP_RETVALUE, "|O_DIRECT", MAXSTRINGLEN); #endif #ifdef O_DIRECTORY if (flags & O_DIRECTORY) strlcat (STAP_RETVALUE, "|O_DIRECTORY", MAXSTRINGLEN); #endif #ifdef O_EXCL if (flags & O_EXCL) strlcat (STAP_RETVALUE, "|O_EXCL", MAXSTRINGLEN); #endif #ifdef O_LARGEFILE if (flags & O_LARGEFILE) strlcat (STAP_RETVALUE, "|O_LARGEFILE", MAXSTRINGLEN); #endif #ifdef O_NOATIME if (flags & O_NOATIME) strlcat (STAP_RETVALUE, "|O_NOATIME", MAXSTRINGLEN); #endif #ifdef O_NOCTTY if (flags & O_NOCTTY) strlcat (STAP_RETVALUE, "|O_NOCTTY", MAXSTRINGLEN); #endif #ifdef O_NOFOLLOW if (flags & O_NOFOLLOW) strlcat (STAP_RETVALUE, "|O_NOFOLLOW", MAXSTRINGLEN); #endif #ifdef O_NONBLOCK if (flags & O_NONBLOCK) strlcat (STAP_RETVALUE, "|O_NONBLOCK", MAXSTRINGLEN); #endif #ifdef O_SYNC if (flags & O_SYNC) strlcat (STAP_RETVALUE, "|O_SYNC", MAXSTRINGLEN); #endif #ifdef O_TRUNC if (flags & O_TRUNC) strlcat (STAP_RETVALUE, "|O_TRUNC", MAXSTRINGLEN); #endif %} /* `man 2 open` for more information */ function _access_mode_str(m) { if((m & 7) == 0) return "F_OK" if(m & 4) bs="R_OK |".bs if(m & 2) bs="W_OK |".bs if(m & 1) bs="X_OK |".bs return substr(bs,0,strlen(bs)-2) } /* `man 2 open` for more information */ function _sys_open_mode_str(f) { if((f & 448) == 448) bs="S_IRWXU|".bs else { if(f & 256) bs="S_IRUSR|".bs if(f & 128) bs="S_IWUSR|".bs if(f & 64) bs="S_IXUSR|".bs } if((f & 56) == 56) bs="S_IRWXG|".bs else { if(f & 32) bs="S_IRGRP|".bs if(f & 16) bs="S_IWGRP|".bs if(f & 8) bs="S_IXGRP|".bs } if((f & 7) == 7) bs="S_IRWXO|".bs else { if(f & 4) bs="S_IROTH|".bs if(f & 2) bs="S_IWOTH|".bs if(f & 1) bs="S_IXOTH|".bs } return substr(bs,0,strlen(bs)-1) } /* `man 2 mknod` for more information */ function _mknod_mode_str(mode) { if((mode & 0xF000)==0x8000) return "S_IFREG|"._sys_open_mode_str(mode) if((mode & 0xF000)==0x2000) return "S_IFCHR|"._sys_open_mode_str(mode) if((mode & 0xF000)==0x6000) return "S_IFBLK|"._sys_open_mode_str(mode) if((mode & 0xF000)==0x1000) return "S_IFIFO|"._sys_open_mode_str(mode) if((mode & 0xF000)==0xC000) return "S_IFSOCK|"._sys_open_mode_str(mode) return "" } /* `man msync` for more information */ function _msync_flag_str(f) { if (f & 7 == 0) return "" if(f & 4) bs="MS_SYNC|".bs if(f & 2) bs="MS_INVALIDATE|".bs if(f & 1) bs="MS_ASYNC|".bs return substr(bs,0,strlen(bs)-1) } function _internal_wait_opt_str(f,bit_num,bit_str) { retval="" if (f & %{ WNOHANG %}) { f&=%{ ~WNOHANG %} retval=retval."|WNOHANG" } if (f & bit_num) { f&=~bit_num retval=retval."|".bit_str } if (f & %{ WEXITED %}) { f&=%{ ~WEXITED %} retval=retval."|WEXITED" } if (f & %{ WCONTINUED %}) { f&=%{ ~WCONTINUED %} retval=retval."|WCONTINUED" } if (f & %{ WNOWAIT %}) { f&=%{ ~WNOWAIT %} retval=retval."|WNOWAIT" } if (f & %{ __WNOTHREAD %}) { f&=%{ ~__WNOTHREAD %} retval=retval."|__WNOTHREAD" } if (f & %{ __WALL %}) { f&=%{ ~__WALL %} retval=retval."|__WALL" } if (f & %{ __WCLONE %}) { f&=%{ ~__WCLONE %} retval=retval."|__WCLONE" } if (f != 0) retval=retval.sprintf ("|0x%x", f) else if (retval == "") return "0" return substr(retval,1,strlen(retval)-1) } /* `man wait4` for more information */ function _wait4_opt_str(f) { return _internal_wait_opt_str(f,%{ WUNTRACED %},"WUNTRACED") } /* `man waitid` for more information */ function _waitid_opt_str(f) { return _internal_wait_opt_str(f,%{ WSTOPPED %},"WSTOPPED") } function WIFEXITED(f) { return (f & 0x7f) == 0 } function WEXITSTATUS(f) { return (f & 0xff00) >> 8 } function WIFSIGNALED(f) { return (f & 0x7f) != 0 && (f & 0x7f) != 0x7f } function WCOREDUMP(f) { return f & 0x80 } function WTERMSIG(f) { return f & 0x7f } function WIFSTOPPED(f) { return (f & 0xff) == 0x7f } function WSTOPSIG(f) { return (f & 0xff00) >> 8 } function WIFCONTINUED(f) { return f == 0xffff } function _ptrace_event_name(f) { if (f == %{ PTRACE_EVENT_FORK %}) return "PTRACE_EVENT_FORK" if (f == %{ PTRACE_EVENT_VFORK %}) return "PTRACE_EVENT_VFORK" if (f == %{ PTRACE_EVENT_CLONE %}) return "PTRACE_EVENT_CLONE" if (f == %{ PTRACE_EVENT_EXEC %}) return "PTRACE_EVENT_EXEC" if (f == %{ PTRACE_EVENT_VFORK_DONE %}) return "PTRACE_EVENT_VFORK_DONE" if (f == %{ PTRACE_EVENT_EXIT %}) return "PTRACE_EVENT_EXIT" return "" } /* `man 2 wait` for more information */ function _wait_status_str(f) { if ((f >> 16) != 0) tail = sprintf (" | 0x%x", f & ~0xffff) else tail = "" if (WIFEXITED(f)) return sprintf ("WEXITSTATUS=%d", WEXITSTATUS(f)).tail if (WIFSIGNALED(f)) { if (WCOREDUMP(f)) return "WCOREDUMP".tail return sprintf ("WTERMSIG=%s", _signal_name(WTERMSIG(f))).tail } if (WIFSTOPPED(f)) { if (WSTOPSIG(f) == %{ SIGTRAP %}) { event = _ptrace_event_name (f >> 16) if (event != "") tail = " | ".event." << 8" } return sprintf ("WSTOPSIG=%s", _signal_name(WSTOPSIG(f))).tail } if (WIFCONTINUED(f)) return "WIFCONTINUED".tail return sprintf ("?=0x%x", f) } /* `man sendmsg` for more information */ function _sendflags_str(f) { if(f & 0x0001) bs="MSG_OOB|".bs if(f & 0x0080) bs="MSG_EOR|".bs if(f & 0x0004) bs="MSG_DONTROUTE|".bs if(f & 0x0040) bs="MSG_DONTWAIT|".bs if(f & 0x4000) bs="MSG_NOSIGNAL|".bs if(f & 0x0800) bs="MSG_CONFIRM|".bs if(f & 0x8000) bs="MSG_MORE|".bs return substr(bs,0,strlen(bs)-1) } /* `man recv` for more information */ function _recvflags_str(f) { if(f & 1) bs="MSG_OOB|".bs if(f & 2) bs="MSG_PEEK|".bs if(f & 32) bs="MSG_TRUNC|".bs if(f & 64) bs="MSG_DONTWAIT|".bs if(f & 256) bs="MSG_WAITALL|".bs if(f & 8192) bs="MSG_ERRQUEUE|".bs if(f & 0x40000000) bs="MSG_CMSG_CLOEXEC|".bs return substr(bs,0,strlen(bs)-1) } /* `man mlockall` for more information */ function _mlockall_flags_str:string(flags:long) %{ /* pure */ #include int len; long f = STAP_ARG_flags; char *str = STAP_RETVALUE; str[0] = '\0'; if (f & MCL_CURRENT) strlcat(str, "MCL_CURRENT|", MAXSTRINGLEN); if (f & MCL_FUTURE) strlcat(str, "MCL_FUTURE|", MAXSTRINGLEN); len = strlen(str); if (len) str[strlen(str)-1] = '\0'; else snprintf(str, MAXSTRINGLEN, "0x%lx", f); %} /* used by sys_delete_module */ function _module_flags_str:string(flags:long) %{ /* pure */ int len; long flags = STAP_ARG_flags; char *str = STAP_RETVALUE; str[0] = '\0'; if (flags & O_TRUNC) strlcat(str,"O_TRUNC|", MAXSTRINGLEN); if (flags & O_NONBLOCK) strlcat(str,"O_NONBLOCK|", MAXSTRINGLEN); len = strlen(str); if (len) str[strlen(str)-1] = '\0'; %} function _sched_policy_str(policy) { if(policy==0) return "SCHED_OTHER" if(policy==1) return "SCHED_FIFO" if(policy==2) return "SCHED_RR" if(policy==3) return "SCHED_BATCH" return sprintf("UNKNOWN VALUE: %d", policy) } function _priority_which_str(which) { if(which==0) return "PRIO_PROCESS" if(which==1) return "PRIO_PGRP" if(which==2) return "PRIO_USER" return sprintf("UNKNOWN VALUE: %d", which) } function _shutdown_how_str(how) { if(how==0) return "SHUT_RD" if(how==1) return "SHUT_WR" if(how==2) return "SHUT_RDWR" return sprintf("UNKNOWN VALUE: %d", how) } %{ // Needed for function __reboot_magic_str:string. Unfortunately cannot // be inlined into the function since these header file defines static // functions on some architectures. #include %} function _reboot_magic_str:string(magic:long) %{ /* pure */ int magic = (int)STAP_ARG_magic; switch (magic) { case LINUX_REBOOT_MAGIC1: strlcpy(STAP_RETVALUE, "LINUX_REBOOT_MAGIC1", MAXSTRINGLEN); break; case LINUX_REBOOT_MAGIC2: strlcpy(STAP_RETVALUE, "LINUX_REBOOT_MAGIC2", MAXSTRINGLEN); break; case LINUX_REBOOT_MAGIC2A: strlcpy(STAP_RETVALUE, "LINUX_REBOOT_MAGIC2A", MAXSTRINGLEN); break; case LINUX_REBOOT_MAGIC2B: strlcpy(STAP_RETVALUE, "LINUX_REBOOT_MAGIC2B", MAXSTRINGLEN); break; /* LINUX_REBOOT_MAGIC2C is supported from kernel 2.6 */ #ifdef LINUX_REBOOT_MAGIC2C case LINUX_REBOOT_MAGIC2C: strlcpy(STAP_RETVALUE, "LINUX_REBOOT_MAGIC2C", MAXSTRINGLEN); break; #endif default: snprintf(STAP_RETVALUE, MAXSTRINGLEN, "UNKNOWN VALUE: %d", magic); } %} function _reboot_flag_str(flag) { if(flag==0x01234567) return "LINUX_REBOOT_CMD_RESTART" if(flag==0xCDEF0123) return "LINUX_REBOOT_CMD_HALT" if(flag==0x4321FEDC) return "LINUX_REBOOT_CMD_POWER_OFF" if(flag==0xA1B2C3D4) return "LINUX_REBOOT_CMD_RESTART2" if(flag==0x89ABCDEF) return "LINUX_REBOOT_CMD_CAD_ON" if(flag==0x00000000) return "LINUX_REBOOT_CMD_CAD_OFF" if(flag==0xD000FCE2) return "LINUX_REBOOT_CMD_SW_SUSPEND" if(flag==0x45584543) return "LINUX_REBOOT_CMD_KEXEC" return sprintf("UNKNOWN VALUE: %d", flag) } function _waitid_which_str(flag) { if(flag==0) return "P_ALL" if(flag==1) return "P_PID" if(flag==2) return "P_PGID" return sprintf("UNKNOWN VALUE: %d", flag) } function _futex_op_str(op) { if(op==0) return "FUTEX_WAIT" if(op==1) return "FUTEX_WAKE" if(op==2) return "FUTEX_FD" if(op==3) return "FUTEX_REQUEUE" if(op==4) return "FUTEX_CMP_REQUEUE" if(op==5) return "FUTEX_WAKE_OP" if(op==6) return "FUTEX_LOCK_PI" if(op==7) return "FUTEX_UNLOCK_PI" if(op==8) return "FUTEX_TRYLOCK_PI" if(op==128) return "FUTEX_WAIT_PRIVATE" if(op==129) return "FUTEX_WAKE_PRIVATE" if(op==131) return "FUTEX_REQUEUE_PRIVATE" if(op==132) return "FUTEX_CMP_REQUEUE_PRIVATE" if(op==133) return "FUTEX_WAKE_OP_PRIVATE" if(op==134) return "FUTEX_LOCK_PI_PRIVATE" if(op==135) return "FUTEX_UNLOCK_PI_PRIVATE" if(op==136) return "FUTEX_TRYLOCK_PI_PRIVATE" return sprintf("UNKNOWN VALUE: %d", op) } function _mountflags_str:string(op:long) %{ /* pure */ int len, op = STAP_ARG_op; char *str = STAP_RETVALUE; str[0] = '\0'; if (op & MS_BIND) strlcat(str,"MS_BIND|",MAXSTRINGLEN); if (op & MS_DIRSYNC) strlcat(str,"MS_DIRSYNC|",MAXSTRINGLEN); if (op & MS_MANDLOCK) strlcat(str,"MS_MANDLOCK|",MAXSTRINGLEN); if (op & MS_MOVE) strlcat(str,"MS_MOVE|",MAXSTRINGLEN); if (op & MS_NOATIME) strlcat(str,"MS_NOATIME|",MAXSTRINGLEN); if (op & MS_NODEV) strlcat(str,"MS_NODEV|",MAXSTRINGLEN); if (op & MS_NODIRATIME) strlcat(str,"MS_NODIRATIME|",MAXSTRINGLEN); if (op & MS_NOEXEC) strlcat(str,"MS_NOEXEC|",MAXSTRINGLEN); if (op & MS_NOSUID) strlcat(str,"MS_NOSUID|",MAXSTRINGLEN); if (op & MS_RDONLY) strlcat(str,"MS_RDONLY|",MAXSTRINGLEN); if (op & MS_REC) strlcat(str,"MS_REC|",MAXSTRINGLEN); if (op & MS_REMOUNT) strlcat(str,"MS_REMOUNT|",MAXSTRINGLEN); if (op & MS_SYNCHRONOUS) strlcat(str,"MS_SYNCHRONOUS|",MAXSTRINGLEN); if (op & MS_VERBOSE) strlcat(str,"MS_VERBOSE|",MAXSTRINGLEN); len = strlen(str); if (len) str[strlen(str)-1] = '\0'; %} function _umountflags_str:string(op:long) %{ /* pure */ int len, op = STAP_ARG_op; char *str = STAP_RETVALUE; if (op == 0) strlcpy(str,"0",MAXSTRINGLEN); else { str[0] = '\0'; if (op & MNT_FORCE) strlcat(str,"MNT_FORCE|",MAXSTRINGLEN); if (op & MNT_DETACH) strlcat(str,"MNT_DETACH|",MAXSTRINGLEN); if (op & MNT_EXPIRE) strlcat(str,"MNT_EXPIRE|",MAXSTRINGLEN); len = strlen(str); if (len) str[strlen(str)-1] = '\0'; } %} function _statfs_f_type_str(f) { if(f==0xadf5) return "ADFS_SUPER_MAGIC" if(f==0xADFF) return "AFFS_SUPER_MAGIC" if(f==0x42465331) return "BEFS_SUPER_MAGIC" if(f==0x1BADFACE) return "BFS_MAGIC" if(f==0xFF534D42) return "CIFS_MAGIC_NUMBER" if(f==0x73757245) return "CODA_SUPER_MAGIC" if(f==0x012FF7B7) return "COH_SUPER_MAGIC" if(f==0x28cd3d45) return "CRAMFS_MAGIC" if(f==0x1373) return "DEVFS_SUPER_MAGIC" if(f==0x00414A53) return "EFS_SUPER_MAGIC" if(f==0x137D) return "EXT_SUPER_MAGIC" if(f==0xEF51) return "EXT2_OLD_SUPER_MAGIC" if(f==0xEF53) return "EXT2_SUPER_MAGIC" if(f==0xEF53) return "EXT3_SUPER_MAGIC" if(f==0x4244) return "HFS_SUPER_MAGIC" if(f==0xF995E849) return "HPFS_SUPER_MAGIC" if(f==0x958458f6) return "HUGETLBFS_MAGIC" if(f==0x9660) return "ISOFS_SUPER_MAGIC" if(f==0x72b6) return "JFFS2_SUPER_MAGIC" if(f==0x3153464a) return "JFS_SUPER_MAGIC" if(f==0x137F) return "MINIX_SUPER_MAGIC" if(f==0x138F) return "MINIX_SUPER_MAGIC2" if(f==0x2468) return "MINIX2_SUPER_MAGIC" if(f==0x2478) return "MINIX2_SUPER_MAGIC2" if(f==0x4d44) return "MSDOS_SUPER_MAGIC" if(f==0x564c) return "NCP_SUPER_MAGIC" if(f==0x6969) return "NFS_SUPER_MAGIC" if(f==0x5346544e) return "NTFS_SB_MAGIC" if(f==0x9fa1) return "OPENPROM_SUPER_MAGIC" if(f==0x9fa0) return "PROC_SUPER_MAGIC" if(f==0x002f) return "QNX4_SUPER_MAGIC" if(f==0x52654973) return "REISERFS_SUPER_MAGIC" if(f==0x7275) return "ROMFS_MAGIC" if(f==0x517B) return "SMB_SUPER_MAGIC" if(f==0x012FF7B6) return "SYSV2_SUPER_MAGIC" if(f==0x012FF7B5) return "SYSV4_SUPER_MAGIC" if(f==0x01021994) return "TMPFS_MAGIC" if(f==0x15013346) return "UDF_SUPER_MAGIC" if(f==0x00011954) return "UFS_MAGIC" if(f==0x9fa2) return "USBDEVICE_SUPER_MAGIC" if(f==0xa501FCF5) return "VXFS_SUPER_MAGIC" if(f==0x012FF7B4) return "XENIX_SUPER_MAGIC" if(f==0x58465342) return "XFS_SUPER_MAGIC" if(f==0x012FD16D) return "_XIAFS_SUPER_MAGIC" return sprintf("UNKNOWN VALUE: %d", f) } function _mremap_flags(flags) { if (flags & 1) msg="MREMAP_MAYMOVE|" if (flags & 2) msg="MREMAP_FIXED|".msg return substr(msg,0,strlen(msg)-1) } function _madvice_advice_str(behavior) { if(behavior==0x00000000) return "MADV_NORMAL" if(behavior==0x00000001) return "MADV_RANDOM" if(behavior==0x00000002) return "MADV_SEQUENTIAL" if(behavior==0x00000003) return "MADV_WILLNEED" if(behavior==0x00000004) return "MADV_DONTNEED" return sprintf("UNKNOWN VALUE: %d", behavior) } function _fadvice_advice_str(behavior) { if(behavior==0x00000000) return "FADV_NORMAL" if(behavior==0x00000001) return "FADV_RANDOM" if(behavior==0x00000002) return "FADV_SEQUENTIAL" if(behavior==0x00000003) return "FADV_WILLNEED" if(behavior==0x00000004) return "FADV_DONTNEED" return sprintf("UNKNOWN VALUE: %d", behavior) } function _fcntl_cmd_str(cmd) { if(cmd==0) return "F_DUPFD" if(cmd==1) return "F_GETFD" if(cmd==2) return "F_SETFD" if(cmd==3) return "F_GETFL" if(cmd==4) return "F_SETFL" if(cmd==5) return "F_GETLK" if(cmd==6) return "F_SETLK" if(cmd==7) return "F_SETLKW" if(cmd==8) return "F_SETOWN" if(cmd==9) return "F_GETOWN" if(cmd==10) return "F_SETSIG" if(cmd==11) return "F_GETSIG" if(cmd==12) return "F_GETLK64" if(cmd==13) return "F_SETLK64" if(cmd==14) return "F_SETLKW64" if(cmd==1030) return "F_DUPFD_CLOEXEC" return sprintf("UNKNOWN VALUE: %d", cmd) } %{ #include #ifndef SEEK_SET #define SEEK_SET 0 #endif #ifndef SEEK_CUR #define SEEK_CUR 1 #endif #ifndef SEEK_END #define SEEK_END 2 #endif #ifndef SEEK_DATA #define SEEK_DATA 3 #endif #ifndef SEEK_HOLE #define SEEK_HOLE 4 #endif %} function _seek_whence_str(w) { if (w == %{ SEEK_SET %}) return "SEEK_SET" if (w == %{ SEEK_CUR %}) return "SEEK_CUR" if (w == %{ SEEK_END %}) return "SEEK_END" if (w == %{ SEEK_DATA %}) return "SEEK_DATA" if (w == %{ SEEK_HOLE %}) return "SEEK_HOLE" return sprintf("UNKNOWN VALUE: %d", w) } function _quotactl_cmd_str(cmd) { if(cmd==0x800002) return "Q_QUOTAON" if(cmd==0x800003) return "Q_QUOTAOFF" if(cmd==0x800007) return "Q_GETQUOTA" if(cmd==0x800008) return "Q_SETQUOTA" if(cmd==0x800005) return "Q_GETINFO" if(cmd==0x800006) return "Q_SETINFO" if(cmd==0x800004) return "Q_GETFMT" if(cmd==0x800001) return "Q_SYNC" /* XFS Quota Manager (XQM) Codes */ if(cmd==0x5801) return "Q_XQUOTAON" if(cmd==0x5802) return "Q_XQUOTAOFF" if(cmd==0x5803) return "Q_XGETQUOTA" if(cmd==0x5804) return "Q_XSETQLIM" if(cmd==0x5805) return "Q_XGETQSTAT" if(cmd==0x5806) return "Q_XQUOTARM" if(cmd==0x5807) return "Q_XQUOTASYNC" return sprintf("UNKNOWN VALUE: %d", cmd) } /* see sys/socket.h (for setsockopt) */ function _sockopt_optname_str(opt) { if(opt==1) return "SO_DEBUG" if(opt==2) return "SO_REUSEADDR" if(opt==3) return "SO_TYPE" if(opt==4) return "SO_ERROR" if(opt==5) return "SO_DONTROUTE" if(opt==6) return "SO_BROADCAST" if(opt==7) return "SO_SNDBUF" if(opt==8) return "SO_RCVBUF" if(opt==9) return "SO_KEEPALIVE" if(opt==10) return "SO_OOBINLINE" if(opt==11) return "SO_NO_CHECK" if(opt==12) return "SO_PRIORITY" if(opt==13) return "SO_LINGER" if(opt==14) return "SO_BSDCOMPAT" if(opt==16) return "SO_PASSCRED" if(opt==17) return "SO_PEERCRED" if(opt==18) return "SO_RCVLOWAT" if(opt==19) return "SO_SNDLOWAT" if(opt==20) return "SO_RCVTIMEO" if(opt==21) return "SO_SNDTIMEO" if(opt==32) return "SO_SNDBUFFORCE" if(opt==33) return "SO_RCVBUFFORCE" return sprintf("UNKNOWN VALUE: %d", opt) } /* `man 2 setsockopt` for more information */ function _sockopt_level_str(l) { if(l==0) return "IP" if(l==1) return "SOL_SOCKET" # not ICMP if(l==2) return "IGMP" if(l==3) return "GGP" if(l==4) return "IP-ENCAP" if(l==5) return "ST" if(l==6) return "TCP" if(l==7) return "CBT" if(l==8) return "EGP" if(l==9) return "IGP" if(l==10) return "BBN-RCC-MON" if(l==11) return "NVP-II" if(l==12) return "PUP" if(l==13) return "ARGUS" if(l==14) return "EMCON" if(l==15) return "XNET" if(l==16) return "CHAOS" if(l==17) return "UDP" if(l==18) return "MUX" if(l==19) return "DCN-MEAS" if(l==20) return "HMP" if(l==21) return "PRM" if(l==22) return "XNS-IDP" if(l==23) return "TRUNK-1" if(l==24) return "TRUNK-2" if(l==25) return "LEAF-1" if(l==26) return "LEAF-2" if(l==27) return "RDP" if(l==28) return "IRTP" if(l==29) return "ISO-TP4" if(l==30) return "NETBLT" if(l==31) return "MFE-NSP" if(l==32) return "MERIT-INP" if(l==33) return "SEP" if(l==34) return "3PC" if(l==35) return "IDPR" if(l==36) return "XTP" if(l==37) return "DDP" if(l==38) return "IDPR-CMTP" if(l==39) return "TP++" if(l==40) return "IL" if(l==41) return "IPv6" if(l==42) return "SDRP" if(l==43) return "IPv6-Route" if(l==44) return "IPv6-Frag" if(l==45) return "IDRP" if(l==46) return "RSVP" if(l==47) return "GRE" if(l==48) return "MHRP" if(l==49) return "BNA" if(l==50) return "IPv6-Crypt" if(l==51) return "IPv6-Auth" if(l==52) return "I-NLSP" if(l==53) return "SWIPE" if(l==54) return "NARP" if(l==55) return "MOBILE" if(l==56) return "TLSP" if(l==57) return "SKIP" if(l==58) return "IPv6-ICMP" if(l==59) return "IPv6-NoNxt" if(l==60) return "IPv6-Opts" if(l==62) return "CFTP" if(l==64) return "SAT-EXPAK" if(l==65) return "KRYPTOLAN" if(l==66) return "RVD" if(l==67) return "IPPC" if(l==69) return "SAT-MON" if(l==70) return "VISA" if(l==71) return "IPCV" if(l==72) return "CPNX" if(l==73) return "CPHB" if(l==74) return "WSN" if(l==75) return "PVP" if(l==76) return "BR-SAT-MON" if(l==77) return "SUN-ND" if(l==78) return "WB-MON" if(l==79) return "WB-EXPAK" if(l==80) return "ISO-IP" if(l==81) return "VMTP" if(l==82) return "SECURE-VMTP" if(l==83) return "VINES" if(l==84) return "TTP" if(l==85) return "NSFNET-IGP" if(l==86) return "DGP" if(l==87) return "TCF" if(l==88) return "EIGRP" if(l==89) return "OSPFIGP" if(l==90) return "Sprite-RPC" if(l==91) return "LARP" if(l==92) return "MTP" if(l==93) return "AX.25" if(l==94) return "IPIP" if(l==95) return "MICP" if(l==96) return "SCC-SP" if(l==97) return "ETHERIP" if(l==98) return "ENCAP" if(l==100) return "GMTP" if(l==101) return "IFMP" if(l==102) return "PNNI" if(l==103) return "PIM" if(l==104) return "ARIS" if(l==105) return "SCPS" if(l==106) return "QNX" if(l==107) return "A/N" if(l==108) return "IPComp" if(l==109) return "SNP" if(l==110) return "Compaq-Peer" if(l==111) return "IPX-in-IP" if(l==112) return "VRRP" if(l==113) return "PGM" if(l==115) return "L2TP" if(l==116) return "DDX" if(l==117) return "IATP" if(l==118) return "STP" if(l==119) return "SRP" if(l==120) return "UTI" if(l==121) return "SMP" if(l==122) return "SM" if(l==123) return "PTP" if(l==124) return "ISIS" if(l==125) return "FIRE" if(l==126) return "CRTP" if(l==127) return "CRUDP" if(l==128) return "SSCOPMCE" if(l==129) return "IPLT" if(l==130) return "SPS" if(l==131) return "PIPE" if(l==132) return "SCTP" if(l==133) return "FC" if(l==134) return "RSVP-E2E-IGNORE" if(l==135) return "Mobility-Header" if(l==136) return "UDPLite" if(l==137) return "MPLS-IN-IP" return sprintf("UNKNOWN VALUE: %d", l) } function _sock_family_str(f) { if(f==0) return "PF_UNSPEC" if(f==1) return "PF_LOCAL" if(f==2) return "PF_INET" if(f==3) return "PF_AX25" if(f==4) return "PF_IPX" if(f==5) return "PF_APPLETALK" if(f==6) return "PF_NETROM" if(f==7) return "PF_BRIDGE" if(f==8) return "PF_ATMPVC" if(f==9) return "PF_X25" if(f==10) return "PF_INET6" if(f==11) return "PF_ROSE" if(f==12) return "PF_DECnet" if(f==13) return "PF_NETBEUI" if(f==14) return "PF_SECURITY" if(f==15) return "PF_KEY" if(f==16) return "PF_NETLINK" if(f==17) return "PF_PACKET" if(f==18) return "PF_ASH" if(f==19) return "PF_ECONET" if(f==20) return "PF_ATMSVC" if(f==22) return "PF_SNA" if(f==23) return "PF_IRDA" if(f==24) return "PF_PPPOX" if(f==25) return "PF_WANPIPE" if(f==26) return "PF_LLC" if(f==30) return "PF_TIPC" if(f==31) return "PF_BLUETOOTH" if(f==32) return "PF_IUCV" if(f==33) return "PF_RXRPC" return sprintf("UNKNOWN VALUE: %d", f) } function _sock_type_str:string(type:long) %{ /* pure */ #ifdef SOCK_TYPE_MASK int flags = (int)STAP_ARG_type & ~SOCK_TYPE_MASK; int t = (int)STAP_ARG_type & SOCK_TYPE_MASK; #else int t = (int)STAP_ARG_type; #endif switch (t) { case SOCK_STREAM: strlcpy (STAP_RETVALUE, "SOCK_STREAM", MAXSTRINGLEN); break; case SOCK_DGRAM: strlcpy (STAP_RETVALUE, "SOCK_DGRAM", MAXSTRINGLEN); break; case SOCK_RAW: strlcpy (STAP_RETVALUE, "SOCK_RAW", MAXSTRINGLEN); break; case SOCK_RDM: strlcpy (STAP_RETVALUE, "SOCK_RDM", MAXSTRINGLEN); break; case SOCK_SEQPACKET: strlcpy (STAP_RETVALUE, "SOCK_SEQPACKET", MAXSTRINGLEN); break; #ifdef SOL_DCCP case SOCK_DCCP: strlcpy (STAP_RETVALUE, "SOCK_DCCP", MAXSTRINGLEN); break; #endif case SOCK_PACKET: strlcpy (STAP_RETVALUE, "SOCK_PACKET", MAXSTRINGLEN); break; default: snprintf (STAP_RETVALUE, MAXSTRINGLEN, "UNKNOWN VALUE: %d", t); break; } #ifdef SOCK_TYPE_MASK if (flags & SOCK_CLOEXEC) { strlcat (STAP_RETVALUE, "|SOCK_CLOEXEC", MAXSTRINGLEN); } if (flags & SOCK_NONBLOCK) { strlcat (STAP_RETVALUE, "|SOCK_NONBLOCK", MAXSTRINGLEN); } #endif %} function _sock_flags_str:string(f:long) %{ /* pure */ #ifdef SOCK_TYPE_MASK int flags = (int)STAP_ARG_f; int len; STAP_RETVALUE[0] = '\0'; if (flags & SOCK_CLOEXEC) { strlcat (STAP_RETVALUE, "SOCK_CLOEXEC|", MAXSTRINGLEN); } if (flags & SOCK_NONBLOCK) { strlcat (STAP_RETVALUE, "SOCK_NONBLOCK|", MAXSTRINGLEN); } len = strlen(STAP_RETVALUE); if (len) { STAP_RETVALUE[len - 1] = '\0'; } else { strlcat (STAP_RETVALUE, "0", MAXSTRINGLEN); } #endif %} function _opoll_op_str(o) { if(o==1) return "EPOLL_CTL_ADD" if(o==3) return "EPOLL_CTL_MOD" if(o==2) return "EPOLL_CTL_DEL" return sprintf("UNKNOWN VALUE: %d", o) } function _epoll_events_str(e) { if(e==1) return "EPOLLIN" if(e==4) return "EPOLLOUT" if(e==2) return "EPOLLPRI" if(e==8) return "EPOLLERR" if(e==16) return "EPOLLHUP" if(e==-2147483648) return "EPOLLET" if(e==1073741824) return "EPOLLONESHOT" return sprintf("UNKNOWN VALUE: %d", e) } function _rlimit_resource_str(r) { if(r==-1) return "RLIM_INFINITY" if(r==9) return "RLIMIT_AS" if(r==4) return "RLIMIT_CORE" if(r==0) return "RLIMIT_CPU" if(r==2) return "RLIMIT_DATA" if(r==1) return "RLIMIT_FSIZE" if(r==10) return "RLIMIT_LOCKS" if(r==8) return "RLIMIT_MEMLOCK" if(r==7) return "RLIMIT_NOFILE" if(r==6) return "RLIMIT_NPROC" if(r==5) return "RLIMIT_RSS" if(r==3) return "RLIMIT_STACK" %( kernel_v >= "2.6.8" %? if(r==11) return "RLIMIT_SIGPENDING" if(r==12) return "RLIMIT_MSGQUEUE" %) %( kernel_v >= "2.6.12" %? if(r==13) return "RLIMIT_NICE" if(r==14) return "RLIMIT_RTPRIO" %) return sprintf("UNKNOWN VALUE: %d", r) } function _rusage_who_str(w) { if(w==0) return "RUSAGE_SELF" if(w==-1) return "RUSAGE_CHILDREN" if(w==-2) return "RUSAGE_BOTH" return sprintf("UNKNOWN VALUE: %d", w) } /* for accessing 16-bit values encoded in a long */ function __short:long(val:long) %{ /* pure */ STAP_RETVALUE = (short)STAP_ARG_val; %} /* uid_t is unsigned, but calling functions take "-1" as a parameter */ /* so this hack is necessary to correct that mismatch. */ function __int32:long(val:long) %{ /* pure */ STAP_RETVALUE = (int32_t)STAP_ARG_val; %} /* Unsigned values can get get sign-extended and become negative. */ function __ulong:long(val:long) %{ /* pure */ STAP_RETVALUE = (unsigned long)STAP_ARG_val; %} # For utimensat and futimesat, the directory fd can have a special value function _dfd_str(d) { # 0xffffff9c is a 32-bit -100, for compatability mode. if((d == -100) || (d == 0xffffff9c)) return "AT_FDCWD" return sprint(d) } function _adjtimex_return_str(ret) { if (ret == 0) val = "OK" else if (ret == 1) val = "INS" else if (ret == 2) val = "DEL" else if (ret == 3) val = "OOP" else if (ret == 4) val = "WAIT" else if (ret == 5) val = "BAD" if (val != "") return sprintf("%d (TIME_%s)", ret, val) else return return_str(1, ret) } %{ /* * Simple lookup functions for mapping values to names * using embedded C. Use these functions to create safe, * consistent lookups. */ /* Convenient macro to add defines to an array */ #define V(a) {a,#a} typedef struct { long val; char *name; } _stp_val_array; static void _stp_lookup_str(const _stp_val_array * const array, long val, char *ptr, int len) { int i = 0, slen; while (array[i].name) { if (array[i].val == val) { strlcat (ptr, array[i].name, len); return; } i++; } slen = strlen(ptr); _stp_snprintf(ptr + slen, len - slen, "0x%lx", val); } static void _stp_lookup_or_str(const _stp_val_array * const array, long val, char *ptr, int len) { int i = 0, flag = 0, slen; if (val == 0) { _stp_lookup_str(array, val, ptr, len); return; } while (array[i].name) { if (array[i].val & val) { if (flag) strlcat(ptr, "|", len); strlcat(ptr, array[i].name, len); val &= (~array[i].val); flag = 1; } i++; } if (val) { if (flag) strlcat(ptr, "|", len); slen = strlen(ptr); _stp_snprintf(ptr + slen, len - slen, "0x%lx", val); } } %} %{ static const _stp_val_array const _stp_signal_list[] = { {0, "SIG_0"}, V(SIGHUP), V(SIGINT), V(SIGQUIT), V(SIGILL), V(SIGTRAP), V(SIGABRT), V(SIGBUS), V(SIGFPE), V(SIGKILL), V(SIGUSR1), V(SIGSEGV), V(SIGPIPE), V(SIGUSR2), V(SIGALRM), V(SIGTERM), V(SIGCHLD), V(SIGCONT), V(SIGSTOP), V(SIGTSTP), V(SIGTTIN), V(SIGTTOU), V(SIGURG), V(SIGPROF), V(SIGWINCH), V(SIGVTALRM), {SIGIO,"SIGIO/SIGPOLL"}, V(SIGPWR), {0, NULL} }; static void _stp_sigset_str(sigset_t *mask, char *ptr, int len) { const _stp_val_array * const array = _stp_signal_list; int i = 0, flag = 0; while (array[i].name) { if (array[i].val && sigismember(mask, array[i].val)) { if (flag) strlcat(ptr, "|", len); strlcat(ptr, array[i].name, len); flag = 1; } i++; } if (flag == 0) strlcat(ptr, "EMPTY", len); } %} function _signal_name:string(sig:long) %{ /* pure */ _stp_lookup_str(_stp_signal_list, STAP_ARG_sig, STAP_RETVALUE, MAXSTRINGLEN); %} %{ static const _stp_val_array const _stp_semctl_list[] = { V(IPC_INFO), V(SEM_INFO), V(SEM_STAT), V(GETALL), V(GETVAL), V(GETPID), V(GETNCNT), V(GETZCNT), V(IPC_STAT), V(SETVAL), V(SETALL), V(IPC_RMID), V(IPC_SET), {0, NULL} }; %} function _semctl_cmd:string(cmd:long) %{ /* pure */ _stp_lookup_str(_stp_semctl_list, STAP_ARG_cmd, STAP_RETVALUE, MAXSTRINGLEN); %} function _stp_sigset_u:string(setptr:long) %{ /* pure */ char *ptr = (char *)(unsigned long)STAP_ARG_setptr; sigset_t set; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char*)&set,ptr,sizeof(sigset_t)) == 0) _stp_sigset_str(&set, STAP_RETVALUE, MAXSTRINGLEN); else strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); } %} function _stp_compat_sigset_u:string(setptr:long) %{ /* pure */ #ifdef CONFIG_COMPAT char *ptr = (char *)(unsigned long)STAP_ARG_setptr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { compat_sigset_t set; if (_stp_copy_from_user((char*)&set, ptr, sizeof(compat_sigset_t)) == 0) { sigset_t new_set; sigset_from_compat(&new_set, &set); _stp_sigset_str(&new_set, STAP_RETVALUE, MAXSTRINGLEN); } else strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); } #endif %} %{ static const _stp_val_array const _stp_fork_list[] = { V(CLONE_VM), V(CLONE_FS), V(CLONE_FILES), V(CLONE_SIGHAND), V(CLONE_PTRACE), V(CLONE_VFORK), V(CLONE_PARENT), V(CLONE_THREAD), V(CLONE_NEWNS), V(CLONE_SYSVSEM), V(CLONE_SETTLS), V(CLONE_PARENT_SETTID), V(CLONE_CHILD_CLEARTID), V(CLONE_DETACHED), V(CLONE_UNTRACED), V(CLONE_CHILD_SETTID), #ifdef CLONE_STOPPED V(CLONE_STOPPED), #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) V(CLONE_NEWUTS), V(CLONE_NEWIPC), #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) V(CLONE_NEWUSER), #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) V(CLONE_NEWPID), V(CLONE_NEWNET), #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) V(CLONE_IO), #endif {0, NULL} }; %} function __fork_flags:string(flags:long) %{ /* pure */ _stp_lookup_or_str(_stp_fork_list, STAP_ARG_flags & ~0xff, STAP_RETVALUE, MAXSTRINGLEN); if ( STAP_ARG_flags & 0xff ) { /* flags contains the termination signal */ if (*STAP_RETVALUE) strlcat(STAP_RETVALUE, "|", MAXSTRINGLEN); _stp_lookup_str(_stp_signal_list, STAP_ARG_flags & 0xff, STAP_RETVALUE, MAXSTRINGLEN); } %} %{ static const _stp_val_array const _stp_atflag_list[] = { #ifdef AT_SYMLINK_NOFOLLOW V(AT_SYMLINK_NOFOLLOW), #endif #ifdef AT_REMOVEDIR V(AT_REMOVEDIR), #endif #ifdef AT_SYMLINK_FOLLOW V(AT_SYMLINK_FOLLOW), #endif {0, NULL} }; %} function _at_flag_str:string(f:long) %{ /* pure */ _stp_lookup_str(_stp_atflag_list, STAP_ARG_f, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include %} function _epoll_create1_flag_str:string(f:long) %{ /* pure */ #ifdef EPOLL_CLOEXEC if (STAP_ARG_f == EPOLL_CLOEXEC) strlcpy (STAP_RETVALUE, "EPOLL_CLOEXEC", MAXSTRINGLEN); #endif %} %{ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) #include #endif %} function _eventfd2_flag_str:string(f:long) %{ /* pure */ long flags = STAP_ARG_f; char *str = STAP_RETVALUE; int len; str[0] = '\0'; #if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK) if (flags & EFD_NONBLOCK) strlcat(str, "EFD_NONBLOCK|", MAXSTRINGLEN); if (flags & EFD_CLOEXEC) strlcat(str, "EFD_CLOEXEC|", MAXSTRINGLEN); #endif len = strlen(str); if (len) str[strlen(str)-1] = '\0'; %} %{ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) #include #endif %} function _signalfd4_flags_str:string(f:long) %{ /* pure */ long flags = STAP_ARG_f; char *str = STAP_RETVALUE; int len; str[0] = '\0'; #if defined(SFD_CLOEXEC) && defined(SFD_NONBLOCK) if (flags & SFD_NONBLOCK) strlcat(str, "SFD_NONBLOCK|", MAXSTRINGLEN); if (flags & SFD_CLOEXEC) strlcat(str, "SFD_CLOEXEC|", MAXSTRINGLEN); #endif len = strlen(str); if (len) str[strlen(str)-1] = '\0'; %} %{ #if (defined(CONFIG_INOTIFY) || defined(CONFIG_INOTIFY_USER)) #include #endif %} function _inotify_init1_flag_str:string(f:long) %{ /* pure */ long flags = STAP_ARG_f; char *str = STAP_RETVALUE; int len; str[0] = '\0'; #if defined(IN_CLOEXEC) && defined(IN_NONBLOCK) if (flags & IN_NONBLOCK) strlcat(str, "IN_NONBLOCK|", MAXSTRINGLEN); if (flags & IN_CLOEXEC) strlcat(str, "IN_CLOEXEC|", MAXSTRINGLEN); #endif len = strlen(str); if (len) str[strlen(str)-1] = '\0'; %} function _dup3_flag_str:string(f:long) %{ /* pure */ #ifdef O_CLOEXEC if (STAP_ARG_f == O_CLOEXEC) strlcpy (STAP_RETVALUE, "O_CLOEXEC", MAXSTRINGLEN); else #endif strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); %} %{ #include static const _stp_val_array const _stp_shmat_list[] = { V(SHM_RDONLY), V(SHM_RND), V(SHM_REMAP), V(SHM_EXEC), {0, NULL} }; %} function _shmat_flags_str:string(f:long) %{ /* pure */ _stp_lookup_or_str(_stp_shmat_list, STAP_ARG_f, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include static const _stp_val_array const _stp_mprotect_list[] = { {0, "PROT_NONE"}, V(PROT_READ), V(PROT_WRITE), V(PROT_EXEC), V(PROT_SEM), {0, NULL} }; %} function _mprotect_prot_str:string(prot:long) %{ /* pure */ _stp_lookup_or_str(_stp_mprotect_list, STAP_ARG_prot, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include static const _stp_val_array const _stp_mmap_list[] = { V(MAP_SHARED), V(MAP_PRIVATE), V(MAP_FIXED), V(MAP_ANONYMOUS), V(MAP_GROWSDOWN), V(MAP_DENYWRITE), V(MAP_EXECUTABLE), V(MAP_LOCKED), V(MAP_NORESERVE), V(MAP_POPULATE), V(MAP_NONBLOCK), {0, NULL} }; %} function _mmap_flags:string(flags:long) %{ /* pure */ _stp_lookup_or_str(_stp_mmap_list, STAP_ARG_flags, STAP_RETVALUE, MAXSTRINGLEN); %} # old mmap functions passed in a struct like this. # function get_mmap_args:string (args:long) %{ /* pure */ #if defined (__x86_64__) || defined (__ia64__) struct mmap_arg_struct { unsigned int addr; unsigned int len; unsigned int prot; unsigned int flags; int fd; unsigned int offset; } a; #else struct mmap_arg_struct { unsigned long addr; unsigned long len; unsigned long prot; unsigned long flags; long fd; unsigned long offset; } a; #endif if(_stp_copy_from_user((char *)&a,(char *)(unsigned long)STAP_ARG_args, sizeof(a))== 0) { int len; _stp_snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx, %ld, ", (long)a.addr, (long)a.len); _stp_lookup_or_str(_stp_mprotect_list, a.prot, STAP_RETVALUE, MAXSTRINGLEN); strlcat (STAP_RETVALUE, ", ", MAXSTRINGLEN); _stp_lookup_or_str(_stp_mmap_list, a.flags, STAP_RETVALUE, MAXSTRINGLEN); strlcat (STAP_RETVALUE, ", ", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); _stp_snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, "%ld, %ld", (long)a.fd, (long)a.offset); } else strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); %} function _sighandler_str:string(uaddr:long) %{ /* pure */ static const _stp_val_array const _stp_sa_handler_list[] = { {0, "SIG_DFL"}, {1, "SIG_IGN"}, {0, NULL} }; _stp_lookup_str(_stp_sa_handler_list, (long)STAP_ARG_uaddr, STAP_RETVALUE, MAXSTRINGLEN); %} %{ static void _stp_sigaction_str(struct sigaction *act, char *ptr, int len) { static const _stp_val_array const _stp_sa_handler_list[] = { {0, "SIG_DFL"}, {1, "SIG_IGN"}, {0, NULL} }; static const _stp_val_array const _stp_sa_flags_list[] = { V(SA_NOCLDSTOP), V(SA_NOCLDWAIT), V(SA_RESETHAND), V(SA_ONSTACK), V(SA_RESTART), V(SA_NODEFER), V(SA_SIGINFO), V(SA_RESTORER), {0, NULL} }; int slen; _stp_lookup_str(_stp_sa_handler_list, (long)act->sa_handler, ptr, len); if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL) { strlcat (ptr, ", ", len); _stp_lookup_or_str(_stp_sa_flags_list, act->sa_flags, ptr, len); strlcat (ptr, ", ", len); #if !defined (__ia64__) slen = strlen(ptr); _stp_snprintf(ptr + slen, len - slen, "0x%lx, [", (long)act->sa_restorer); #else strlcat (ptr, "[", len); #endif _stp_sigset_str(&act->sa_mask, ptr, len); strlcat (ptr, "]", len); } } %} function _struct_sigaction_u:string(uaddr:long) %{ /* pure */ struct sigaction act; char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char*)&act, ptr, sizeof(struct sigaction)) == 0) _stp_sigaction_str(&act, STAP_RETVALUE, MAXSTRINGLEN); else strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); } %} function _struct_sigaction32_u:string(uaddr:long) %{ /* pure */ #ifdef CONFIG_COMPAT #include #ifdef AUTOCONF_COMPAT_SIGACTION struct compat_sigaction act32; #else // There seems to be no public cross arch header that defines this. // For x86, you can find it in asm/ia32.h. For s390x, it is defined // in a private header. struct sigaction32 { compat_uptr_t sa_handler; unsigned int sa_flags; unsigned int sa_restorer; /* Another 32 bit pointer */ compat_sigset_t sa_mask; /* A 32 bit mask */ }; struct sigaction32 act32; #endif char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char*)&act32, ptr, sizeof(act32)) == 0) { struct sigaction act; act.sa_handler = (void *)compat_ptr(act32.sa_handler); act.sa_flags = (unsigned long)act32.sa_flags; act.sa_restorer = (void *)compat_ptr(act32.sa_restorer); /* swap words around to get right endian order. */ switch (_NSIG_WORDS) { case 4: act.sa_mask.sig[3] = act32.sa_mask.sig[6] | (((long)act32.sa_mask.sig[7]) << 32); case 3: act.sa_mask.sig[2] = act32.sa_mask.sig[4] | (((long)act32.sa_mask.sig[5]) << 32); case 2: act.sa_mask.sig[1] = act32.sa_mask.sig[2] | (((long)act32.sa_mask.sig[3]) << 32); case 1: act.sa_mask.sig[0] = act32.sa_mask.sig[0] | (((long)act32.sa_mask.sig[1]) << 32); } _stp_sigaction_str(&act, STAP_RETVALUE, MAXSTRINGLEN); } else strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); } #endif %} function _struct_old_sigaction32_u:string(uaddr:long) %{ /* pure */ #ifdef CONFIG_COMPAT #include #ifdef CONFIG_COMPAT_OLD_SIGACTION struct compat_old_sigaction act32; #else // There seems to be no public cross arch header that defines this. // For x86, you can find it in asm/ia32.h. For s390x, it is defined // in a private header. struct old_sigaction32 { compat_uptr_t sa_handler; compat_old_sigset_t sa_mask; /* A 32 bit mask */ unsigned int sa_flags; unsigned int sa_restorer; /* Another 32 bit pointer */ }; struct old_sigaction32 act32; #endif char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char*)&act32, ptr, sizeof(act32)) == 0) { struct sigaction act; act.sa_handler = (void *)compat_ptr(act32.sa_handler); act.sa_restorer = (void *)compat_ptr(act32.sa_restorer); act.sa_flags = (unsigned long)act32.sa_flags; siginitset(&act.sa_mask, act32.sa_mask); _stp_sigaction_str(&act, STAP_RETVALUE, MAXSTRINGLEN); } else strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); } #endif %} /* * Function irqflags_str : * Returns the symbolic string representation of the IRQ flags. * */ %{ #include #ifndef IRQF_ONESHOT #define IRQF_ONESHOT 0x00002000 #endif static const _stp_val_array const _stp_irq_list[] = { #ifdef IRQF_DISABLED V(IRQF_DISABLED), #endif #ifdef IRQF_SAMPLE_RANDOM V(IRQF_SAMPLE_RANDOM), #endif #ifdef IRQF_SHARED V(IRQF_SHARED), #endif #ifdef IRQF_PROBE_SHARED V(IRQF_PROBE_SHARED), #endif #ifdef IRQF_TIMER V(IRQF_TIMER), #endif #ifdef IRQF_PERCPU V(IRQF_PERCPU), #endif #ifdef IRQF_NOBALANCING V(IRQF_NOBALANCING), #endif #ifdef IRQF_IRQPOLL V(IRQF_IRQPOLL), #endif V(IRQF_ONESHOT), {0, NULL} }; %} function irqflags_str:string(f:long) %{ /* pure */ _stp_lookup_or_str(_stp_irq_list, STAP_ARG_f, STAP_RETVALUE, MAXSTRINGLEN); %} /* PTRACE_SETOPTIONS parser of the DATA parameter. */ function _ptrace_options_str(f) { retval="" if (f & %{ PTRACE_O_TRACESYSGOOD %}) { f&=%{ ~PTRACE_O_TRACESYSGOOD %} retval=retval."|PTRACE_O_TRACESYSGOOD" } if (f & %{ PTRACE_O_TRACEFORK %}) { f&=%{ ~PTRACE_O_TRACEFORK %} retval=retval."|PTRACE_O_TRACEFORK" } if (f & %{ PTRACE_O_TRACEVFORK %}) { f&=%{ ~PTRACE_O_TRACEVFORK %} retval=retval."|PTRACE_O_TRACEVFORK" } if (f & %{ PTRACE_O_TRACECLONE %}) { f&=%{ ~PTRACE_O_TRACECLONE %} retval=retval."|PTRACE_O_TRACECLONE" } if (f & %{ PTRACE_O_TRACEEXEC %}) { f&=%{ ~PTRACE_O_TRACEEXEC %} retval=retval."|PTRACE_O_TRACEEXEC" } if (f & %{ PTRACE_O_TRACEVFORKDONE %}) { f&=%{ ~PTRACE_O_TRACEVFORKDONE %} retval=retval."|PTRACE_O_TRACEVFORKDONE" } if (f & %{ PTRACE_O_TRACEEXIT %}) { f&=%{ ~PTRACE_O_TRACEEXIT %} retval=retval."|PTRACE_O_TRACEEXIT" } if (f != 0) retval=retval.sprintf("|0x%x",f) else if (retval == "") return "0" return substr(retval,1,strlen(retval)-1) } /* ptrace syscall provisioning of argstr. */ %{ #ifndef PTRACE_GETREGSET # define PTRACE_GETREGSET 0x4204 #endif #ifndef PTRACE_SETREGSET # define PTRACE_SETREGSET 0x4205 #endif %} function _ptrace_argstr(request, pid, addr, data) { retval=_arch_ptrace_argstr(request, pid, addr, data) if (retval != "") return retval if (request == %{ PTRACE_TRACEME %}) return "PTRACE_TRACEME" if (request == %{ PTRACE_PEEKTEXT %}) return sprintf ("PTRACE_PEEKTEXT, %d, addr=%p", pid, addr) if (request == %{ PTRACE_PEEKDATA %}) return sprintf ("PTRACE_PEEKDATA, %d, addr=%p", pid, addr) if (request == %{ PTRACE_PEEKUSR %}) return sprintf ("PTRACE_PEEKUSR, %d, addr=%p", pid, addr) if (request == %{ PTRACE_POKETEXT %}) return sprintf ("PTRACE_POKETEXT, %d, addr=%p, data=%p", pid, addr, data) if (request == %{ PTRACE_POKEDATA %}) return sprintf ("PTRACE_POKEDATA, %d, addr=%p, data=%p", pid, addr, data) if (request == %{ PTRACE_POKEUSR %}) return sprintf ("PTRACE_POKEUSR, %d, addr=%p, data=%p", pid, addr, data) if (request == %{ PTRACE_CONT %}) return sprintf ("PTRACE_CONT, %d, %s", pid, _signal_name (data)) if (request == %{ PTRACE_KILL %}) return sprintf ("PTRACE_KILL, %d", pid) if (request == %{ PTRACE_SINGLESTEP %}) return sprintf ("PTRACE_SINGLESTEP, %d, %s", pid, _signal_name (data)) if (request == %{ PTRACE_ATTACH %}) return sprintf ("PTRACE_ATTACH, %d", pid) if (request == %{ PTRACE_DETACH %}) return sprintf ("PTRACE_DETACH, %d, %s", pid, _signal_name (data)) if (request == %{ PTRACE_SYSCALL %}) return sprintf ("PTRACE_SYSCALL, %d, %s", pid, _signal_name (data)) if (request == %{ PTRACE_SETOPTIONS %}) return sprintf ("PTRACE_SETOPTIONS, %d, %s", pid, _ptrace_options_str (data)) if (request == %{ PTRACE_GETEVENTMSG %}) return sprintf ("PTRACE_GETEVENTMSG, %d, data=%p", pid, data) if (request == %{ PTRACE_GETSIGINFO %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GETSIGINFO, %d, data=%p", pid, data) if (request == %{ PTRACE_SETSIGINFO %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SETSIGINFO, %d, data=%p", pid, data) if (request == %{ PTRACE_GETREGSET %}) // TODO return sprintf ("PTRACE_GETREGSET, %d, addr=%p, data=%p", pid, addr, data) if (request == %{ PTRACE_SETREGSET %}) // TODO return sprintf ("PTRACE_SETREGSET, %d, addr=%p, data=%p", pid, addr, data) return sprintf("?=%d, %d, %p, %p", request, pid, addr, data) } /* ptrace.return syscall decoder for PTRACE_GETEVENTMSG. */ function _ptrace_return_geteventmsg_data(request,data) { if (request == %{ PTRACE_GETEVENTMSG %}) return user_long(data) } /* do_fork helper function to determine fork type. */ function __is_user_regs:long (regs:long) %{ /* pure */ struct pt_regs * regs = (void *)((unsigned long)STAP_ARG_regs); /* copied from asm/ptrace.h */ #if defined(__i386__) #ifdef STAPCONF_X86_UNIREGS int cs = kread(®s->cs); #else int cs = kread(®s->xcs); #endif STAP_RETVALUE = (!!((cs & 3))); #elif defined(__x86_64__) unsigned long cs = kread(®s->cs); STAP_RETVALUE = (!!((cs & 3))); #elif defined(__ia64__) unsigned long psr = kread(®s->cr_ipsr); STAP_RETVALUE = (((struct ia64_psr *) &psr)->cpl != 0); #elif defined(__powerpc64__) unsigned long msr = kread(®s->msr); STAP_RETVALUE = ((msr >> MSR_PR_LG) & 0x1); #elif defined(__powerpc__) unsigned long msr = kread(®s->msr); STAP_RETVALUE = ((msr >> MSR_PR) != 0); #elif defined(__arm__) long cpsr = kread(®s->ARM_cpsr); STAP_RETVALUE = ((cpsr & 0xf) == 0); #elif defined(__s390__) || defined(__s390x__) unsigned long mask = kread(®s->psw.mask); STAP_RETVALUE = ((mask & PSW_MASK_PSTATE) != 0); #else #error "Unimplemented architecture" #endif CATCH_DEREF_FAULT(); %} systemtap-2.3/tapset/linux/context-caller.stp000066400000000000000000000037341217430427200215330ustar00rootroot00000000000000// context-caller tapset // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // Provides caller and caller_addr function for context for kernel and user // space. // %{ /* caller_addr() might be user caller, so needs at least uprobes structs. */ #include "linux/uprobes-inc.h" %} /** * sfunction callers - Return first n elements of kernel stack backtrace * * @n: number of levels to descend in the stack (not counting the top * level). If n is -1, print the entire stack. * * Description: This function returns a string of the first n hex * addresses from the backtrace of the kernel stack. Output may be * truncated as per maximum string length (MAXSTRINGLEN). */ function callers:string (n:long) { str = ""; l = 0 for (i = 0; i <= n || n == -1; i++) { foo = i > 0 ? " " : "" try { foo .= sprintf("0x%x", stack(i)) } catch { /* assume we've hit the end of the stack */ if (n == -1) break @__context_unwind_error(n) } // ensure string cuts off cleanly at MAXSTRINGLEN: l += strlen(foo); if (l > %{ MAXSTRINGLEN %}) break str .= foo } return str } /** * sfunction caller - Return name and address of calling function * * Description: This function returns the address and name of the * calling function. This is equivalent to calling: * sprintf("%s 0x%x", symname(caller_addr()), caller_addr()) */ function caller:string() { return sprintf("%s 0x%x", symname(caller_addr()), caller_addr()); } /** * sfunction caller_addr - Return caller address * * Description: This function returns the address of the calling function. */ function caller_addr:long () { return stack(1) } systemtap-2.3/tapset/linux/context-envvar.stp000066400000000000000000000035331217430427200215670ustar00rootroot00000000000000// context-envvar tapset // Copyright (C) 2010 Pixar Inc. and/or Lars R. Damerow // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // Context functions provide additional information about where an event occurred. These functions can //provide information such as a backtrace to where the event occurred and the current register values for the //processor. // /** * sfunction env_var - Fetch environment variable from current process * @name: Name of the environment variable to fetch * * Description: Returns the contents of the specified environment value * for the current process. If the variable isn't set an empty string * is returned. */ function env_var:string(name:string) { if (name == "") return "" env_value = ""; mm = @cast(task_current(), "task_struct", "kernel")->mm; if (mm) { env_start = @cast(mm, "mm_struct", "kernel")->env_start; env_end = @cast(mm, "mm_struct", "kernel")->env_end; if (env_start != 0 && env_end != 0) { len = env_end - env_start; cur = user_string2(env_start, ""); env_name = tokenize(cur, "="); while (env_name != name && len > 0) { env_len = strlen(cur); env_start += env_len + 1; len -= env_len + 1; if (len > 0) { cur = user_string2(env_start, ""); env_name = tokenize(cur, "="); } else env_name = ""; } if (len > 0) env_value = tokenize("", ""); } } return env_value; } systemtap-2.3/tapset/linux/context-symbols.stp000066400000000000000000000246021217430427200217560ustar00rootroot00000000000000// context-symbols tapset // Copyright (C) 2005-2012 Red Hat Inc. // Copyright (C) 2006 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // Context functions provide additional information about where an event occurred. These functions can //provide information such as a backtrace to where the event occurred and the current register values for the //processor. // function __stack_raw (n:long) %{ /* pragma:unwind */ /* pure */ /* basic sanity check for bounds: */ if (unlikely(STAP_ARG_n < 0 || STAP_ARG_n >= MAXBACKTRACE)) STAP_RETVALUE = 0; else STAP_RETVALUE = _stp_stack_kernel_get (CONTEXT, (unsigned)STAP_ARG_n); %} /** * sfunction stack - Return address at given depth of kernel stack backtrace * @n: number of levels to descend in the stack. * * Description: Performs a simple (kernel) backtrace, and returns the * element at the specified position. The results of the backtrace itself * are cached, so that the backtrace computation is performed at most once * no matter how many times stack() is called, or in what order. */ function stack:long (n:long) { __r = __stack_raw(n); if (__r != 0) return __r /* fallback: parse backtrace() to go deeper in the stack */ __b = backtrace (); __orig_n = __n; __sym = tokenize (__b, " "); if (__sym == "") @__context_unwind_error(__orig_n); while (__n > 0) { __sym = tokenize ("", " "); if (__sym == "") @__context_unwind_error(__orig_n); __n--; } return strtol(__sym, 16) } /** * sfunction print_stack - Print out kernel stack from string * @stk: String with list of hexadecimal addresses * * Description: This function performs a symbolic lookup of the addresses * in the given string, * which is assumed to be the result of a prior call to * backtrace(). * * Print one line per address, including the address, the * name of the function containing the address, and an estimate of * its position within that function. Return nothing. * * NOTE: it is recommended to use print_syms() instead of this function. */ function print_stack(stk:string) { print_syms(stk) } /** * sfunction sprint_stack - Return stack for kernel addresses from string * @stk: String with list of hexadecimal (kernel) addresses * * Perform a symbolic lookup of the addresses in the given string, * which is assumed to be the result of a prior call to backtrace(). * * Returns a simple backtrace from the given hex string. One line per * address. Includes the symbol name (or hex address if symbol * couldn't be resolved) and module name (if found). Includes the * offset from the start of the function if found, otherwise the * offset will be added to the module (if found, between * brackets). Returns the backtrace as string (each line terminated by * a newline character). Note that the returned stack will be * truncated to MAXSTRINGLEN, to print fuller and richer stacks use * print_stack. * * NOTE: it is recommended to use sprint_syms() instead of this function. */ function sprint_stack:string(stk:string) { return sprint_syms(stk) } /** * sfunction probefunc - Return the probe point's function name, if known * * Description: This function returns the name of the function being probed * based on the current address, as computed by symname(addr()) or * usymname(uaddr()) depending on probe context (whether the probe is * a user probe or a kernel probe). * * Please note: this function's behaviour differs between SystemTap 2.0 * and earlier versions. Prior to 2.0, probefunc() obtained the function * name from the probe point string as returned by pp(), and used the * current address as a fallback. */ function probefunc:string () %( systemtap_v < "2.0" %? %{ /* pure */ /* pragma:symbols */ char *ptr, *start; STAP_RETVALUE[0] = '\0'; start = strstr(CONTEXT->probe_point, "function(\""); ptr = start + 10; if (!start) { start = strstr(CONTEXT->probe_point, "inline(\""); ptr = start + 8; } if (start) { int len = MAXSTRINGLEN; char *dst = STAP_RETVALUE; while (*ptr != '@' && *ptr != '"' && --len > 0 && *ptr) *dst++ = *ptr++; *dst = 0; } else { struct pt_regs *regs; int user_mode; user_mode = c->user_mode_p; regs = user_mode ? CONTEXT->uregs : CONTEXT->kregs; if (regs) { _stp_snprint_addr(STAP_RETVALUE, MAXSTRINGLEN, REG_IP(regs), _STP_SYM_SYMBOL, (user_mode ? current : NULL)); } } %} %: { %( systemtap_privilege != "stapusr" %? return user_mode() ? usymname(uaddr()) : symname(addr()) %: return user_mode() ? usymname(uaddr()) : error("kernel probefunc() query from unprivileged script") /* XXX should be impossible */ %) } %) /** * sfunction probemod - Return the probe point's kernel module name * * Description: This function returns the name of the kernel module * containing the probe point, if known. */ function probemod:string () %{ /* pure */ char *ptr, *start; start = strstr(CONTEXT->probe_point, "module(\""); ptr = start + 8; if (start) { int len = MAXSTRINGLEN; char *dst = STAP_RETVALUE; while (*ptr != '"' && --len && *ptr) *dst++ = *ptr++; *dst = 0; } else if (CONTEXT->kregs && ! CONTEXT->user_mode_p) { struct _stp_module *m; m = _stp_kmod_sec_lookup (REG_IP(CONTEXT->kregs), NULL); if (m && m->name) strlcpy (STAP_RETVALUE, m->name, MAXSTRINGLEN); else #if STAP_COMPAT_VERSION <= STAP_VERSION(2,2) strlcpy (STAP_RETVALUE, "", MAXSTRINGLEN); #else CONTEXT->last_error = "Cannot determine kernel module name"; #endif } else #if STAP_COMPAT_VERSION <= STAP_VERSION(2,2) strlcpy (STAP_RETVALUE, "", MAXSTRINGLEN); #else CONTEXT->last_error = "Cannot determine kernel module name"; #endif %} /** * sfunction modname - Return the kernel module name loaded at the address * @addr: The address to map to a kernel module name * * Description: Returns the module name associated with the given * address if known. If not known it will raise an error. If the * address was not in a kernel module, but in the kernel itself, then * the string "kernel" will be returned. */ function modname:string (addr: long) %{ /* pure */ struct _stp_module *m; #ifdef STAPCONF_MODULE_TEXT_ADDRESS struct module *ko; #endif m = _stp_kmod_sec_lookup (STAP_ARG_addr, NULL); if (m && m->name) { strlcpy (STAP_RETVALUE, m->name, MAXSTRINGLEN); return; } #ifdef STAPCONF_MODULE_TEXT_ADDRESS preempt_disable(); ko = __module_text_address (STAP_ARG_addr); if (ko && ko->name) { strlcpy (STAP_RETVALUE, ko->name, MAXSTRINGLEN); preempt_enable_no_resched(); return; } preempt_enable_no_resched(); #endif #if STAP_COMPAT_VERSION <= STAP_VERSION(2,2) strlcpy (STAP_RETVALUE, "", MAXSTRINGLEN); #else CONTEXT->last_error = "Cannot determine kernel module name"; #endif %} /** * sfunction symname - Return the kernel symbol associated with the given address * @addr: The address to translate * * Description: Returns the (function) symbol name associated with the * given address if known. If not known it will return the hex string * representation of addr. */ function symname:string (addr: long) %{ /* pure */ /* pragma:symbols */ _stp_snprint_addr(STAP_RETVALUE, MAXSTRINGLEN, STAP_ARG_addr, _STP_SYM_SYMBOL, NULL); %} /** * sfunction symdata - Return the kernel symbol and module offset for the address * @addr: The address to translate * * Description: Returns the (function) symbol name associated with the * given address if known, the offset from the start and size of the * symbol, plus module name (between brackets). If symbol is unknown, * but module is known, the offset inside the module, plus the size of * the module is added. If any element is not known it will be * omitted and if the symbol name is unknown it will return the hex * string for the given address. */ function symdata:string (addr: long) %{ /* pure */ /* pragma:symbols */ _stp_snprint_addr(STAP_RETVALUE, MAXSTRINGLEN, STAP_ARG_addr, _STP_SYM_DATA, NULL); %} /** * sfunction print_syms - Print out kernel stack from string * @callers: String with list of hexadecimal (kernel) addresses * * Description: This function performs a symbolic lookup of the addresses * in the given string, * which are assumed to be the result of prior calls to stack(), * callers(), and similar functions. * * Prints one line per address, including the address, the * name of the function containing the address, and an estimate of * its position within that function, as obtained by symdata(). * Returns nothing. */ function print_syms (callers:string) { __sym = tokenize (callers, " "); while (__sym != "") { printf (" %s : %s\n", __sym, symdata (strtol(__sym,16))); __sym = tokenize ("", " "); } } /** * sfunction sprint_syms - Return stack for kernel addresses from string * * @callers: String with list of hexadecimal (kernel) addresses * * Perform a symbolic lookup of the addresses in the given string, * which are assumed to be the result of a prior calls to stack(), * callers(), and similar functions. * * Returns a simple backtrace from the given hex string. One line per * address. Includes the symbol name (or hex address if symbol * couldn't be resolved) and module name (if found), as obtained from * symdata(). Includes the offset from the start of the function if * found, otherwise the offset will be added to the module (if found, between * brackets). Returns the backtrace as string (each line terminated by * a newline character). Note that the returned stack will be * truncated to MAXSTRINGLEN, to print fuller and richer stacks use * print_syms(). */ function sprint_syms (callers:string) { __sym = tokenize (callers, " "); __foo = ""; __l = 0 while (__sym != "") { // cleanly handle overflow instead of printing partial line: __line = sprintf (" %s : %s\n", __sym, symdata (strtol(__sym,16))); __l += strlen(__line) if (__l > %{ MAXSTRINGLEN %}) break __foo .= __line __sym = tokenize ("", " ") } return __foo } systemtap-2.3/tapset/linux/context-unwind.stp000066400000000000000000000054471217430427200216000ustar00rootroot00000000000000// context-unwind tapset // Copyright (C) 2005-2013 Red Hat Inc. // Copyright (C) 2006 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // Context functions provide additional information about where an event occurred. These functions can //provide information such as a backtrace to where the event occurred and the current register values for the //processor. // /** * sfunction print_backtrace - Print kernel stack back trace * * Description: This function is equivalent to print_stack(backtrace()), * except that deeper stack nesting may be supported. See print_ubacktrace * for user-space backtrace. * The function does not return a value. */ function print_backtrace () %{ /* pragma:unwind */ /* pragma:symbols */ _stp_stack_kernel_print(CONTEXT, _STP_SYM_FULL); %} /** * sfunction sprint_backtrace - Return stack back trace as string * * Returns a simple (kernel) backtrace. One line per address. * Includes the symbol name (or hex address if symbol * couldn't be resolved) and module name (if found). Includes the * offset from the start of the function if found, otherwise the * offset will be added to the module (if found, between * brackets). Returns the backtrace as string (each line terminated by * a newline character). Note that the returned stack will be * truncated to MAXSTRINGLEN, to print fuller and richer stacks use * print_backtrace(). Equivalent to sprint_stack(backtrace()), * but more efficient (no need to translate between hex strings and * final backtrace string). */ function sprint_backtrace:string () %{ /* pure */ /* pragma:unwind */ /* pragma:symbols */ _stp_stack_kernel_sprint (STAP_RETVALUE, MAXSTRINGLEN, CONTEXT, _STP_SYM_SIMPLE); %} /** * sfunction backtrace - Hex backtrace of current kernel stack * * Description: This function returns a string of hex addresses * that are a backtrace of the kernel stack. Output may be truncated * as per maximum string length (MAXSTRINGLEN). See * ubacktrace() for user-space backtrace. */ function backtrace:string () %{ /* pure */ /* pragma:unwind */ _stp_stack_kernel_sprint (STAP_RETVALUE, MAXSTRINGLEN, CONTEXT, _STP_SYM_NONE); %} %( systemtap_v <= "1.6" %? /** * sfunction task_backtrace - Hex backtrace of an arbitrary task * @task: pointer to task_struct * * Description: This function returns a string of hex addresses * that are a backtrace of the stack of a particular task * Output may be truncated as per maximum string length. * Deprecated in SystemTap 1.6. */ function task_backtrace:string (task:long) { warn("task_backtrace unsupported") } %) systemtap-2.3/tapset/linux/context.stp000066400000000000000000000316161217430427200202730ustar00rootroot00000000000000// context tapset // Copyright (C) 2005-2011 Red Hat Inc. // Copyright (C) 2006 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // NB: tapsetdescription is in tapset/context.stp /** * sfunction execname - Returns the execname of a target process (or group of processes) * * Description: Returns the execname of a target process (or group of processes). */ function execname:string () %{ /* pure */ /* unprivileged */ strlcpy (STAP_RETVALUE, current->comm, MAXSTRINGLEN); %} /** * sfunction pid - Returns the ID of a target process * * Description: This function returns the ID of a target process. */ function pid:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = current->tgid; %} /** * sfunction tid - Returns the thread ID of a target process * * Description: This function returns the thread ID of the target process. */ function tid:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = current->pid; %} /** * sfunction ppid - Returns the process ID of a target process's parent process * * Description: This function return the process ID of the target proccess's parent process. */ function ppid:long() %{ /* pure */ /* unprivileged */ #if defined(STAPCONF_REAL_PARENT) STAP_RETVALUE = current->real_parent->tgid; #else STAP_RETVALUE = current->parent->tgid; #endif %} /** * sfunction pgrp - Returns the process group ID of the current process * * Description: This function returns the process group ID of the * current process. */ function pgrp:long () %{ /* pure */ /* unprivileged */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) struct signal_struct *ss = kread( &(current->signal) ); STAP_RETVALUE = kread ( &(ss->pgrp) ); CATCH_DEREF_FAULT(); #else STAP_RETVALUE = task_pgrp_nr_ns(current, &init_pid_ns); #endif %} /** * sfunction sid - Returns the session ID of the current process * * Description: The session ID of a process is the process group ID * of the session leader. Session ID is stored in the signal_struct * since Kernel 2.6.0. */ function sid:long () %{ /* pure */ /* unprivileged */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) struct signal_struct *ss = kread( &(current->signal) ); STAP_RETVALUE = kread ( &(ss->session) ); CATCH_DEREF_FAULT(); #else STAP_RETVALUE = task_session_nr_ns(current, &init_pid_ns); #endif %} /** * sfunction pexecname - Returns the execname of a target process's parent process * * Description: This function returns the execname of a target * process's parent procces. */ function pexecname:string () %{ /* pure */ /* unprivileged */ #if defined(STAPCONF_REAL_PARENT) strlcpy (STAP_RETVALUE, current->real_parent->comm, MAXSTRINGLEN); #else strlcpy (STAP_RETVALUE, current->parent->comm, MAXSTRINGLEN); #endif %} /** * sfunction gid - Returns the group ID of a target process * * Description: This function returns the group ID of a target process. */ function gid:long () %{ /* pure */ /* unprivileged */ #ifdef STAPCONF_TASK_UID STAP_RETVALUE = current->gid; #else STAP_RETVALUE = current_gid(); #endif %} /** * sfunction egid - Returns the effective gid of a target process * * Description: This function returns the effective gid of a target process */ function egid:long () %{ /* pure */ /* unprivileged */ #ifdef STAPCONF_TASK_UID STAP_RETVALUE = current->egid; #else STAP_RETVALUE = current_egid(); #endif %} /** * sfunction uid - Returns the user ID of a target process * * Description: This function returns the user ID of the target process. */ function uid:long () %{ /* pure */ /* unprivileged */ #ifdef STAPCONF_TASK_UID STAP_RETVALUE = current->uid; #else STAP_RETVALUE = current_uid(); #endif %} /** * sfunction euid - Return the effective uid of a target process * * Description: Returns the effective user ID of the target process. */ function euid:long () %{ /* pure */ /* unprivileged */ #ifdef STAPCONF_TASK_UID STAP_RETVALUE = current->euid; #else STAP_RETVALUE = current_euid(); #endif %} /** * sfunction is_myproc - Determines if the current probe point has occurred in the user's own process * * Description: This function returns 1 if the current probe * point has occurred in the user's own process. */ function is_myproc:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = is_myproc(); %} %( systemtap_v <= "1.4" %? /** * sfunction cpuid - Returns the current cpu number * * Description: This function returns the current cpu number. * Deprecated in SystemTap 1.4 and removed in SystemTap 1.5. */ function cpuid:long () %{ /* pure */ STAP_RETVALUE = smp_processor_id(); %} %) /** * sfunction cpu - Returns the current cpu number * * Description: This function returns the current cpu number. */ function cpu:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = smp_processor_id(); %} /** * sfunction registers_valid - Determines validity of register() and u_register() in current context * * Description: This function returns 1 if register() and u_register() * can be used in the current context, or 0 otherwise. * For example, registers_valid() returns 0 * when called from a begin or end probe. */ function registers_valid:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = (c->user_mode_p ? (CONTEXT->uregs != NULL) : (CONTEXT->kregs != NULL)); %} /** * sfunction user_mode - Determines if probe point occurs in user-mode * * Return 1 if the probe point occurred in user-mode. */ function user_mode:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = CONTEXT->user_mode_p ? 1 : 0; %} /** * sfunction is_return - Whether the current probe context is a return probe * * Description: Returns 1 if the current probe context is a return probe, * returns 0 otherwise. */ function is_return:long () %{ /* pure */ if (CONTEXT->probe_type == stp_probe_type_kretprobe || CONTEXT->probe_type == stp_probe_type_uretprobe) STAP_RETVALUE = 1; else STAP_RETVALUE = 0; %} /** * sfunction target - Return the process ID of the target process * * Description: This function returns the process ID of the target * process. This is useful in conjunction with the -x PID or * -c CMD command-line options to stap. An example of its use is * to create scripts that filter on a specific process. * * -x * target() returns the pid specified by -x * * -c * target() returns the pid for the executed command specified by -c */ function target:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = _stp_target; %} /** * sfunction module_name - The module name of the current script * * Description: This function returns the name of the stap module. * Either generated randomly (stap_[0-9a-f]+_[0-9a-f]+) * or set by stap -m . */ function module_name:string () %{ /* pure */ /* unprivileged */ strlcpy(STAP_RETVALUE, THIS_MODULE->name, MAXSTRINGLEN); %} /** * sfunction stp_pid - The process id of the stapio process * * Description: This function returns the process id of the * stapio process that launched this script. There could be * other SystemTap scripts and stapio processes running on * the system. */ function stp_pid:long () %{ /* pure */ STAP_RETVALUE = _stp_pid; %} /** * sfunction remote_id - The index of this instance in a remote execution. * * Description: This function returns a number 0..N, which is the unique * index of this particular script execution from a swarm of * "stap --remote A --remote B ..." runs, and is the same number * "stap --remote-prefix" would print. The function returns -1 if the * script was not launched with "stap --remote", or if the remote * staprun/stapsh are older than version 1.7. */ function remote_id:long () { return %{ /* pure */ /* unprivileged */ _stp_remote_id %} } /** * sfunction remote_uri - The name of this instance in a remote execution. * * Description: This function returns the remote host used to invoke * this particular script execution from a swarm of "stap --remote" runs. * It may not be unique among the swarm. * The function returns an empty string if the script was not launched with * "stap --remote". */ function remote_uri:string () { return %{ /* string */ /* pure */ /* unprivileged */ _stp_remote_uri %} } /** * sfunction stack_size - Return the size of the kernel stack * * Description: This function returns the size of the kernel stack. */ function stack_size:long () %{ /* pure */ STAP_RETVALUE = THREAD_SIZE; %} /** * sfunction stack_used - Returns the amount of kernel stack used * * Description: This function determines how many bytes are * currently used in the kernel stack. */ function stack_used:long () %{ /* pure */ char a; STAP_RETVALUE = THREAD_SIZE - ((long)&a & (THREAD_SIZE-1)); %} /** * sfunction stack_unused - Returns the amount of kernel stack currently available * * Description: This function determines how many bytes are * currently available in the kernel stack. */ function stack_unused:long () %{ /* pure */ char a; STAP_RETVALUE = (long)&a & (THREAD_SIZE-1); %} /** * sfunction addr - Address of the current probe point. * * Description: Returns the instruction pointer from the current probe's * register state. Not all probe types have registers though, in which case * zero is returned. The returned address is suitable for use with functions * like symname() and symdata(). */ function addr:long () %{ /* pure */ if (CONTEXT->user_mode_p) { STAP_RETVALUE = (intptr_t)(CONTEXT->uregs ? REG_IP(CONTEXT->uregs) : 0); } else { STAP_RETVALUE = (intptr_t)(CONTEXT->kregs ? REG_IP(CONTEXT->kregs) : 0); } %} /** * sfunction uaddr - User space address of current running task * * Description: Returns the address in userspace that the current * task was at when the probe occurred. When the current running task * isn't a user space thread, or the address cannot be found, zero * is returned. Can be used to see where the current task is combined * with usymname() or usymdata(). Often the task will be in the VDSO * where it entered the kernel. */ function uaddr:long () %{ /* pure */ /* myproc-unprivileged */ struct pt_regs *uregs; if (CONTEXT->user_mode_p) uregs = CONTEXT->uregs; else uregs = _stp_current_pt_regs(); if (uregs) STAP_RETVALUE = (int64_t) REG_IP(uregs); else STAP_RETVALUE = 0; %} /** * sfunction cmdline_args - Fetch command line arguments from current process * @n: First argument to get (zero is the command itself) * @m: Last argument to get (or minus one for all arguments after n) * @delim: String to use to delimit arguments when more than one. * * Description: Returns arguments from the current process starting * with argument number n, up to argument m. If there are less than n * arguments, or the arguments cannot be retrieved from the current * process, the empty string is returned. If m is smaller than n then * all arguments starting from argument n are returned. Argument zero * is traditionally the command itself. */ function cmdline_args:string(n:long, m:long, delim:string) { __args = ""; __mm = @cast(task_current(), "task_struct", "kernel")->mm; if (__mm) { __arg_start = @cast(__mm, "mm_struct", "kernel")->arg_start; __arg_end = @cast(__mm, "mm_struct", "kernel")->arg_end; if (__arg_start != 0 && __arg_end != 0) { __nr = 0; __len = __arg_end - __arg_start; __arg = user_string2(__arg_start, ""); while (__len > 0) { if (__nr == n) __args = __arg; else if (__nr > n) { if (__arg == "") __args .= delim . "\"\"" else __args .= delim . __arg; } __arg_len = strlen(__arg); __arg_start += __arg_len + 1; __len -= __arg_len + 1; if (__len > 0 && __nr != m) __arg = user_string2(__arg_start, ""); else __arg = ""; __nr++; } } } return __args; } /** * sfunction cmdline_arg - Fetch a command line argument * @n: Argument to get (zero is the command itself) * * Description: Returns argument the requested argument from the * current process or the empty string when there are not that many * arguments or there is a problem retrieving the argument. Argument * zero is traditionally the command itself. */ function cmdline_arg:string(n:long) { return cmdline_args(n, n, ""); } /** * sfunction cmdline_str - Fetch all command line arguments from current process * * Description: Returns all arguments from the current process * delimited by spaces. Returns the empty string when the arguments * cannot be retrieved. */ function cmdline_str:string() { return cmdline_args(0, -1, " "); } systemtap-2.3/tapset/linux/context.stpm000066400000000000000000000001751217430427200204440ustar00rootroot00000000000000@define __context_unwind_error(depth) %( error(sprint("reached end of stack before unwinding to level ", @depth)) %) systemtap-2.3/tapset/linux/conversions-guru.stp000066400000000000000000000126671217430427200221440ustar00rootroot00000000000000// guru-mode conversions tapset // Copyright (C) 2010 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /** * sfunction set_kernel_string - Writes a string to kernel memory * @addr: The kernel address to write the string to * @val: The string which is to be written * * Description: Writes the given string to a given kernel * memory address. Reports an error on string copy fault. * Requires the use of guru mode (-g). */ function set_kernel_string (addr:long, val:string) %{ /* guru */ store_kderef_string (STAP_ARG_val, STAP_ARG_addr, MAXSTRINGLEN); if (0) { deref_fault: /* branched to from store_deref_string() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel string copy fault at 0x%p", (void *) (uintptr_t) STAP_ARG_addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} /** * sfunction set_kernel_string_n - Writes a string of given length to kernel memory * @addr: The kernel address to write the string to * @n: The maximum length of the string * @val: The string which is to be written * * Description: Writes the given string up to a maximum given length to a * given kernel memory address. Reports an error on string copy fault. * Requires the use of guru mode (-g). */ function set_kernel_string_n (addr:long, n:long, val:string) %{ /* guru */ int64_t len = clamp_t(int64_t, STAP_ARG_n + 1, 1, MAXSTRINGLEN); store_kderef_string (STAP_ARG_val, STAP_ARG_addr, len); if (0) { deref_fault: /* branched to from store_deref_string() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel string copy fault at 0x%p", (void *) (uintptr_t) STAP_ARG_addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} /** * sfunction set_kernel_long - Writes a long value to kernel memory * @addr: The kernel address to write the long to * @val: The long which is to be written * * Description: Writes the long value to a given kernel memory address. * Reports an error when writing to the given address fails. * Requires the use of guru mode (-g). */ function set_kernel_long (addr:long, val:long) %{ /* guru */ kwrite((long *) (intptr_t) STAP_ARG_addr, STAP_ARG_val); if (0) { deref_fault: /* branched to from kwrite() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel long copy fault at 0x%p", (void *) (uintptr_t) STAP_ARG_addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} /** * sfunction set_kernel_int - Writes an int value to kernel memory * @addr: The kernel address to write the int to * @val: The int which is to be written * * Description: Writes the int value to a given kernel memory address. * Reports an error when writing to the given address fails. * Requires the use of guru mode (-g). */ function set_kernel_int (addr:long, val:long) %{ /* guru */ kwrite((int *) (intptr_t) STAP_ARG_addr, STAP_ARG_val); if (0) { deref_fault: /* branched to from kwrite() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel int copy fault at 0x%p", (void *) (uintptr_t) STAP_ARG_addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} /** * sfunction set_kernel_short - Writes a short value to kernel memory * @addr: The kernel address to write the short to * @val: The short which is to be written * * Description: Writes the short value to a given kernel memory address. * Reports an error when writing to the given address fails. * Requires the use of guru mode (-g). */ function set_kernel_short (addr:long, val:long) %{ /* guru */ kwrite((short *) (intptr_t) STAP_ARG_addr, STAP_ARG_val); if (0) { deref_fault: /* branched to from kwrite() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel short copy fault at 0x%p", (void *) (uintptr_t) STAP_ARG_addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} /** * sfunction set_kernel_char - Writes a char value to kernel memory * @addr: The kernel address to write the char to * @val: The char which is to be written * * Description: Writes the char value to a given kernel memory address. * Reports an error when writing to the given address fails. * Requires the use of guru mode (-g). */ function set_kernel_char (addr:long, val:long) %{ /* guru */ kwrite((char *) (intptr_t) STAP_ARG_addr, STAP_ARG_val); if (0) { deref_fault: /* branched to from kwrite() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel char copy fault at 0x%p", (void *) (uintptr_t) STAP_ARG_addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} /** * sfunction set_kernel_pointer - Writes a pointer value to kernel memory. * @addr: The kernel address to write the pointer to * @val: The pointer which is to be written * * Description: Writes the pointer value to a given kernel memory address. * Reports an error when writing to the given address fails. * Requires the use of guru mode (-g). */ function set_kernel_pointer (addr:long, val:long) %{ /* guru */ kwrite((void **) (uintptr_t) STAP_ARG_addr, (uintptr_t)STAP_ARG_val); if (0) { deref_fault: /* branched to from kwrite() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel pointer copy fault at 0x%p", (void *) (uintptr_t) STAP_ARG_addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} systemtap-2.3/tapset/linux/conversions.stp000066400000000000000000000231271217430427200211550ustar00rootroot00000000000000// conversions tapset // Copyright (C) 2005-2010 Red Hat Inc. // Copyright (C) 2007 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /** * sfunction kernel_string - Retrieves string from kernel memory * @addr: The kernel address to retrieve the string from * * Description: This function returns the null terminated C string * from a given kernel memory address. Reports an error on string * copy fault. */ function kernel_string:string (addr:long) %{ /* pure */ char *destination = STAP_RETVALUE; kderef_string (destination, STAP_ARG_addr, MAXSTRINGLEN); if (0) { deref_fault: /* branched to from deref_string() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel string copy fault at 0x%p", (void *) (uintptr_t) STAP_ARG_addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} /** * sfunction kernel_string2 - Retrieves string from kernel memory with alternative error string * @addr: The kernel address to retrieve the string from * @err_msg: The error message to return when data isn't available * * Description: This function returns the null terminated C string * from a given kernel memory address. Reports the given error message * on string copy fault. */ function kernel_string2:string (addr:long, err_msg:string) { try { return kernel_string(addr) } catch { return err_msg } } /** * sfunction kernel_string_n - Retrieves string of given length from kernel memory * @addr: The kernel address to retrieve the string from * @n: The maximum length of the string (if not null terminated) * * Description: Returns the C string of a maximum given length from a * given kernel memory address. Reports an error on string copy fault. */ function kernel_string_n:string (addr:long, n:long) %{ /* pure */ char *destination = STAP_RETVALUE; int64_t len = clamp_t(int64_t, STAP_ARG_n + 1, 1, MAXSTRINGLEN); kderef_string (destination, STAP_ARG_addr, len); if (0) { deref_fault: /* branched to from deref_string() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel string copy fault at 0x%p", (void *) (uintptr_t) STAP_ARG_addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} /** * sfunction kernel_string_utf32 - Retrieves UTF-32 string from kernel memory * @addr: The kernel address to retrieve the string from * * Description: This function returns a null terminated UTF-8 string converted * from the UTF-32 string at a given kernel memory address. Reports an error on * string copy fault or conversion error. */ function kernel_string_utf32:string (addr:long) %{ /* pure */ int rc = 0, len = MAXSTRINGLEN; uint32_t c32, *source = (uint32_t*)(intptr_t)STAP_ARG_addr; char *destination = STAP_RETVALUE; *destination = '\0'; while (len > 1 && (c32 = kread(source))) { if ((rc = _stp_convert_utf32(destination, len, c32)) <= 0) { if (rc < 0) { snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "invalid UTF-32 character U+%X at 0x%p", c32, source); CONTEXT->last_error = CONTEXT->error_buffer; } break; } ++source; destination += rc; len -= rc; } if (0) { deref_fault: /* branched to from deref_string() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel string copy fault at 0x%p", source); CONTEXT->last_error = CONTEXT->error_buffer; } %} /** * sfunction kernel_string2_utf32 - Retrieves UTF-32 string from kernel memory with alternative error string * @addr: The kernel address to retrieve the string from * @err_msg: The error message to return when data isn't available * * Description: This function returns a null terminated UTF-8 string converted * from the UTF-32 string at a given kernel memory address. Reports the given * error message on string copy fault or conversion error. */ function kernel_string2_utf32:string (addr:long, err_msg:string) { try { return kernel_string_utf32(addr) } catch { return err_msg } } /** * sfunction kernel_string_utf16 - Retrieves UTF-16 string from kernel memory * @addr: The kernel address to retrieve the string from * * Description: This function returns a null terminated UTF-8 string converted * from the UTF-16 string at a given kernel memory address. Reports an error on * string copy fault or conversion error. */ function kernel_string_utf16:string (addr:long) %{ /* pure */ int rc = 0, len = MAXSTRINGLEN; uint32_t c32; uint16_t c16low, *source = (uint16_t*)(intptr_t)STAP_ARG_addr; char *destination = STAP_RETVALUE; *destination = '\0'; while (len > 1 && (c32 = kread(source))) { /* Check for a UTF-16 high surrogate, then its low pair, and combine them. * Broken surrogates will just fall through to _stp_convert_utf32 and get * flagged as an error there. (Or even allowed, if we decide to be lax.) */ if (c32 >= 0xD800 && c32 <= 0xDBFF) { ++source; c16low = kread(source); if (c16low >= 0xDC00 && c16low <= 0xDFFF) c32 = 0x10000 + ((c32 & 0x3FF) << 10) + (c16low & 0x3FF); else --source; } if ((rc = _stp_convert_utf32(destination, len, c32)) <= 0) { if (rc < 0) { snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "invalid UTF-16 character U+%X at 0x%p", c32, source); CONTEXT->last_error = CONTEXT->error_buffer; } break; } ++source; destination += rc; len -= rc; } if (0) { deref_fault: /* branched to from deref_string() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel string copy fault at 0x%p", source); CONTEXT->last_error = CONTEXT->error_buffer; } %} /** * sfunction kernel_string2_utf16 - Retrieves UTF-16 string from kernel memory with alternative error string * @addr: The kernel address to retrieve the string from * @err_msg: The error message to return when data isn't available * * Description: This function returns a null terminated UTF-8 string converted * from the UTF-16 string at a given kernel memory address. Reports the given * error message on string copy fault or conversion error. */ function kernel_string2_utf16:string (addr:long, err_msg:string) { try { return kernel_string_utf16(addr) } catch { return err_msg } } /** * sfunction kernel_long - Retrieves a long value stored in kernel memory * @addr: The kernel address to retrieve the long from * * Description: Returns the long value from a given kernel memory address. * Reports an error when reading from the given address fails. */ function kernel_long:long (addr:long) %{ /* pure */ STAP_RETVALUE = kread((long *) (intptr_t) STAP_ARG_addr); if (0) { deref_fault: /* branched to from kread() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel long copy fault at 0x%p", (void *) (uintptr_t) STAP_ARG_addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} /** * sfunction kernel_int - Retrieves an int value stored in kernel memory * @addr: The kernel address to retrieve the int from * * Description: Returns the int value from a given kernel memory address. * Reports an error when reading from the given address fails. */ function kernel_int:long (addr:long) %{ /* pure */ STAP_RETVALUE = kread((int *) (intptr_t) STAP_ARG_addr); if (0) { deref_fault: /* branched to from kread() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel int copy fault at 0x%p", (void *) (uintptr_t) STAP_ARG_addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} /** * sfunction kernel_short - Retrieves a short value stored in kernel memory * @addr: The kernel address to retrieve the short from * * Description: Returns the short value from a given kernel memory address. * Reports an error when reading from the given address fails. */ function kernel_short:long (addr:long) %{ /* pure */ STAP_RETVALUE = kread((short *) (intptr_t) STAP_ARG_addr); if (0) { deref_fault: /* branched to from kread() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel short copy fault at 0x%p", (void *) (uintptr_t) STAP_ARG_addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} /** * sfunction kernel_char - Retrieves a char value stored in kernel memory * @addr: The kernel address to retrieve the char from * * Description: Returns the char value from a given kernel memory address. * Reports an error when reading from the given address fails. */ function kernel_char:long (addr:long) %{ /* pure */ STAP_RETVALUE = kread((char *) (intptr_t) STAP_ARG_addr); if (0) { deref_fault: /* branched to from kread() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel char copy fault at 0x%p", (void *) (uintptr_t) STAP_ARG_addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} /** * sfunction kernel_pointer - Retrieves a pointer value stored in kernel memory * @addr: The kernel address to retrieve the pointer from * * Description: Returns the pointer value from a given kernel memory * address. Reports an error when reading from the given address * fails. */ function kernel_pointer:long (addr:long) %{ /* pure */ STAP_RETVALUE = (uintptr_t) kread((void **) (uintptr_t) STAP_ARG_addr); if (0) { deref_fault: /* branched to from kread() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel pointer copy fault at 0x%p", (void *) (uintptr_t) STAP_ARG_addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} systemtap-2.3/tapset/linux/ctime.stp000066400000000000000000000125061217430427200177050ustar00rootroot00000000000000/* ctime.stp - Convert seconds to human readable date string. * * This code was adapted from the newlib mktm_r() and asctime_r() * functions. In newlib, mktm_r.c states that it was adapted from * tzcode maintained by Arthur David Olson. In newlib, asctime_r.c * doesn't have any author/copyright information. * * Changes copyright (C) 2006, 2008 Red Hat Inc. */ /** * sfunction ctime - Convert seconds since epoch into human readable date/time string * * @epochsecs: Number of seconds since epoch (as returned by gettimeofday_s()) * * Description: Takes an argument of seconds since the epoch as returned by * gettimeofday_s(). Returns a string of the form * * "Wed Jun 30 21:49:08 1993" * * The string will always be exactly 24 characters. If the time would * be unreasonable far in the past (before what can be represented * with a 32 bit offset in seconds from the epoch) an error will occur * (which can be avoided with try/catch). If the time would be * unreasonable far in the future, an error will also occur. * * Note that the epoch (zero) corresponds to * * "Thu Jan 1 00:00:00 1970" * * The earliest full date given by ctime, corresponding to epochsecs * -2147483648 is "Fri Dec 13 20:45:52 1901". The latest full date * given by ctime, corresponding to epochsecs 2147483647 is * "Tue Jan 19 03:14:07 2038". * * The abbreviations for the days of the week are ‘Sun’, ‘Mon’, ‘Tue’, * ‘Wed’, ‘Thu’, ‘Fri’, and ‘Sat’. The abbreviations for the months * are ‘Jan’, ‘Feb’, ‘Mar’, ‘Apr’, ‘May’, ‘Jun’, ‘Jul’, ‘Aug’, ‘Sep’, * ‘Oct’, ‘Nov’, and ‘Dec’. * * Note that the real C library ctime() function puts a newline ('\n') * character at the end of the string that this function does not. * Also note that since the kernel has no concept of timezones, the * returned time is always in GMT. */ function ctime:string(epochsecs:long) %{ /* pure */ #define SECSPERMIN 60L #define MINSPERHOUR 60L #define HOURSPERDAY 24L #define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) #define SECSPERDAY (SECSPERHOUR * HOURSPERDAY) #define DAYSPERWEEK 7 #define MONSPERYEAR 12 #define EPOCH_YEAR 1970 #define EPOCH_WDAY 4 #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) static const int mon_lengths[2][MONSPERYEAR] = { {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} } ; static const int year_lengths[2] = { 365, 366 } ; static const char day_name[7][3] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; static const char mon_name[12][3] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; long days, rem; time_t lcltime; int yleap; const int *ip; int tm_sec; /* seconds */ int tm_min; /* minutes */ int tm_hour; /* hours */ int tm_mday; /* day of the month */ int tm_mon; /* month */ int tm_year; /* year */ int tm_wday; /* day of the week */ // Check that the numer of seconds is "reasonable". // Otherwise (especially on 64bit machines) we will be spending // way too much time calculating the correct year, month and // day. Also we would like the returned string to always be 24 chars. // So cap to what can be represented normally on a 32bit machine. int64_t MAX_POS_SECS = 2147483647LL; int64_t MIN_NEG_SECS = -2147483648LL; if (STAP_ARG_epochsecs > MAX_POS_SECS) { #if STAP_COMPAT_VERSION <= STAP_VERSION(2,2) strlcpy(STAP_RETVALUE, "far far in the future...", MAXSTRINGLEN); #else CONTEXT->last_error = "Time too far in the future to be converted"; #endif return; } if (STAP_ARG_epochsecs < MIN_NEG_SECS) { #if STAP_COMPAT_VERSION <= STAP_VERSION(2,2) strlcpy(STAP_RETVALUE, "a long, long time ago...", MAXSTRINGLEN); #else CONTEXT->last_error = "Time too far in the past to be converted"; #endif return; } lcltime = STAP_ARG_epochsecs; days = ((long)lcltime) / SECSPERDAY; rem = ((long)lcltime) % SECSPERDAY; while (rem < 0) { rem += SECSPERDAY; --days; } while (rem >= SECSPERDAY) { rem -= SECSPERDAY; ++days; } /* compute hour, min, and sec */ tm_hour = (int) (rem / SECSPERHOUR); rem %= SECSPERHOUR; tm_min = (int) (rem / SECSPERMIN); tm_sec = (int) (rem % SECSPERMIN); /* compute day of week */ if ((tm_wday = ((EPOCH_WDAY + days) % DAYSPERWEEK)) < 0) tm_wday += DAYSPERWEEK; /* compute year & day of year */ tm_year = EPOCH_YEAR; if (days >= 0) { for (;;) { yleap = isleap(tm_year); if (days < year_lengths[yleap]) break; tm_year++; days -= year_lengths[yleap]; } } else { do { --tm_year; yleap = isleap(tm_year); days += year_lengths[yleap]; } while (days < 0); } ip = mon_lengths[yleap]; for (tm_mon = 0; days >= ip[tm_mon]; ++tm_mon) days -= ip[tm_mon]; tm_mday = days + 1; /* * At this point we have all our information. Now we need to * convert it to an ascii representation. */ snprintf (STAP_RETVALUE, MAXSTRINGLEN, "%.3s %.3s%3d %.2d:%.2d:%.2d %d", day_name[tm_wday], mon_name[tm_mon], tm_mday, tm_hour, tm_min, tm_sec, tm_year); %} systemtap-2.3/tapset/linux/dentry.stp000066400000000000000000000123151217430427200201070ustar00rootroot00000000000000// dentry tapset // Copyright (c) 2009-2010, 2012 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. function __dentry_IS_ROOT:long(dentry:long) { return (@cast(dentry, "dentry")->d_parent == dentry) } function __dentry_prepend:string(dentry:long,name:string) { dname = d_name(dentry) /* * In case we are following down a mount point trigger, we can get * multiple instances of a root mount. */ c = substr(name, strlen(name)-1, strlen(name)-1) if (dname == "/" && c == "/") return name; if (name == "") { return dname; } else { return sprintf("%s/%s", dname, name); } } /** * sfunction d_name - get the dirent name * * Returns the dirent name (path basename). * @dentry: Pointer to dentry. */ function d_name:string(dentry:long) { len = @cast(dentry, "dentry")->d_name->len; return kernel_string_n(@cast(dentry, "dentry")->d_name->name, len); } /** * sfunction inode_name - get the inode name * * Returns the first path basename associated with the given inode. * @inode: Pointer to inode. */ function inode_name:string(inode:long) { i_dentry = & @cast(inode, "struct inode")->i_dentry; d_alias = @cast(i_dentry, "struct list_head")->next; dentry = d_alias - (& @cast(0, "struct dentry")->d_alias); return reverse_path_walk(dentry); } /** * sfunction reverse_path_walk - get the full dirent path * * Returns the path name (partial path to mount point). * @dentry: Pointer to dentry. */ function reverse_path_walk:string(dentry:long) { while(1) { name = __dentry_prepend(dentry, name); dentry = @cast(dentry, "dentry")->d_parent; if (__dentry_IS_ROOT(dentry)) return name; } } /** * sfunction real_mount - get the 'struct mount' pointer * * Returns the 'struct mount' pointer value for a 'struct vfsmount' * pointer. * @vfsmnt: Pointer to 'struct vfsmount' */ function real_mount:long(vfsmnt:long) { if (@defined(@cast(0, "mount")->mnt_parent)) { /* * The following is the script language equivalent of: * * return container_of(vfsmnt, struct mount, mnt); * * We can't do the above because 'struct mount' is * defined in a private header (in fs/mount.h). But, * we can do the script language equivalent (because * we've got dwarf info). * * More spelled out in C, the above would look like: * * return (vfsmnt - offsetof(struct mount, mnt)); * * Notice we're casting 0 here on purpose to find the * offset of the 'mnt' member of 'struct mount. */ offset = &@cast(0, "mount")->mnt if (vfsmnt > offset) return (vfsmnt - offset) } return 0 } /** * sfunction task_dentry_path - get the full dentry path * * Returns the full dirent name (full path to the root), like * the kernel d_path function. * @task: task_struct pointer. * @dentry: direntry pointer. * @vfsmnt: vfsmnt pointer. */ function task_dentry_path:string(task:long,dentry:long,vfsmnt:long) { root = & @cast(task, "task_struct")->fs->root while (1) { # If we've found the right dentry/vfsmnt, we're done. # # (Why check for 'struct path' and 'struct vfs_path'? # Later RHEL5 kernels renamed 'struct path' to 'struct # vfs_path'.) if (@defined(@cast(0, "path")->dentry) ? (dentry == @cast(root, "path")->dentry && vfsmnt == @cast(root, "path")->mnt) : (dentry == @cast(root, "vfs_path")->dentry && vfsmnt == @cast(root, "vfs_path")->mnt)) break; if (dentry == @cast(vfsmnt, "vfsmount")->mnt_root || __dentry_IS_ROOT(dentry)) { if (! @defined(@cast(0, "vfsmount")->mnt_parent)) { mnt = real_mount(vfsmnt) if (mnt == 0) return "" /* Global root? */ if (@cast(mnt, "mount")->mnt_parent == vfsmnt) return sprintf("/%s", name); dentry = @cast(mnt, "mount")->mnt_mountpoint vfsmnt = @cast(mnt, "mount")->mnt_parent } else { /* Global root? */ if (@cast(vfsmnt, "vfsmount")->mnt_parent == vfsmnt) return sprintf("/%s", name); dentry = @cast(vfsmnt, "vfsmount")->mnt_mountpoint vfsmnt = @cast(vfsmnt, "vfsmount")->mnt_parent } continue; } name = __dentry_prepend(dentry, name); dentry = @cast(dentry, "dentry")->d_parent; } return sprintf("/%s", name); } /** * sfunction d_path - get the full nameidata path * * Returns the full dirent name (full path to the root), like * the kernel d_path function. * @nd: Pointer to nameidata. */ function d_path:string(nd:long) { dentry = @choose_defined(@cast(nd,"nameidata")->path->dentry, @cast(nd,"nameidata")->dentry) vfsmnt = @choose_defined(@cast(nd,"nameidata")->path->mnt, @cast(nd,"nameidata")->mnt) return sprintf("%s/", task_dentry_path(task_current(), dentry, vfsmnt)) } systemtap-2.3/tapset/linux/dev.stp000066400000000000000000000036461217430427200173670ustar00rootroot00000000000000// Device tapset // Copyright (C) 2008, 2010 Red Hat Corp. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. %{ #include %} /** * sfunction MAJOR - Extract major device number from a kernel device number (kdev_t) * * @dev: Kernel device number to query. */ function MAJOR:long(dev:long) %{ /* pure */ STAP_RETVALUE = MAJOR(STAP_ARG_dev); %} /** * sfunction MINOR - Extract minor device number from a kernel device number (kdev_t) * * @dev: Kernel device number to query. */ function MINOR:long(dev:long) %{ /* pure */ STAP_RETVALUE = MINOR(STAP_ARG_dev); %} /** * sfunction MKDEF - Creates a value that can be compared to a kernel device number (kdev_t) * * @major: Intended major device number. * @minor: Intended minor device number. */ function MKDEV:long(major:long, minor:long) %{ /* pure */ STAP_RETVALUE = MKDEV(STAP_ARG_major,STAP_ARG_minor); %} /** * sfunction usrdev2kerndev - Converts a user-space device number into the format used in the kernel * * @dev: Device number in user-space format. */ function usrdev2kerndev:long(dev:long) %{ /* pure */ STAP_RETVALUE = new_decode_dev(STAP_ARG_dev); %} function bdevname:string(bdev:long) { if (bdev == 0) return "N/A" hd = @cast(bdev, "block_device")->bd_disk if (@cast(bdev, "block_device")->bd_part) partno = @cast(bdev, "block_device")->bd_part->partno else partno = MINOR(@cast(bdev, "block_device")->bd_dev) - @cast(bdev, "block_device")->bd_disk->first_minor; if (!partno) return kernel_string(@cast(hd, "gendisk")->disk_name) disk_name = kernel_string(@cast(hd, "gendisk")->disk_name) if (isdigit(substr(disk_name, strlen(disk_name) - 1, 1))) return sprintf("%sp%d", disk_name, partno) else return sprintf("%s%d", disk_name, partno) } systemtap-2.3/tapset/linux/endian.stp000066400000000000000000000011321217430427200200330ustar00rootroot00000000000000function big_endian2:long (val:long) %{ /* pure */ STAP_RETVALUE = cpu_to_be16(STAP_ARG_val); %} function big_endian4:long (val:long) %{ /* pure */ STAP_RETVALUE = cpu_to_be32(STAP_ARG_val); %} function big_endian8:long (val:long) %{ /* pure */ STAP_RETVALUE = cpu_to_be64(STAP_ARG_val); %} function little_endian2:long (val:long) %{ /* pure */ STAP_RETVALUE = cpu_to_le16(STAP_ARG_val); %} function little_endian4:long (val:long) %{ /* pure */ STAP_RETVALUE = cpu_to_le32(STAP_ARG_val); %} function little_endian8:long (val:long) %{ /* pure */ STAP_RETVALUE = cpu_to_le64(STAP_ARG_val); %} systemtap-2.3/tapset/linux/guru-delay.stp000066400000000000000000000023161217430427200206600ustar00rootroot00000000000000// Copyright (C) 2012 Red Hat Inc., Bryn M. Reeves // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // // Functions in the guru-delay tapset allow a probe handler to insert // deliberate delays. This is sometimes useful as a fault-injection // aid. Due to its likelihood of interference with the kernel, guru // mode is required, and overload-prevention is suppressed. // %{ /* guru */ #undef STP_OVERLOAD #include %} /** * sfunction mdelay - millisecond delay * @ms: Number of milliseconds to delay. * * Description: This function inserts a multi-millisecond busy-delay into a probe handler. * It requires guru mode. */ function mdelay(ms:long) %{ /* guru */ mdelay(STAP_ARG_ms); %} /** * sfunction udelay - microsecond delay * @us: Number of microseconds to delay. * * Description: This function inserts a multi-microsecond busy-delay into a probe handler. * It requires guru mode. */ function udelay(us:long) %{ /* guru */ udelay(STAP_ARG_us); %} systemtap-2.3/tapset/linux/guru-signal.stp000066400000000000000000000021041217430427200210320ustar00rootroot00000000000000// Copyright (C) 2013 Red Hat Inc., // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // // Functions in the guru-signal tapset allow a probe handler to queue // a user-space signals. Such operations may only be safe from some // kinds of probe points, therefore are guru-mode only. // /** * sfunction raise - raise a signal in the current thread * @signo: signal number * * Description: This function calls the kernel send_sig routine on * the current thread, with the given raw unchecked signal number. * It may raise an error if send_sig() failed. * It requires guru mode. */ function raise(signo:long) %{ /* guru */ int rc = send_sig ((int) STAP_ARG_signo, current, 1); if (rc) { snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "raise/send_sig error %d", rc); CONTEXT->last_error = CONTEXT->error_buffer; } %} systemtap-2.3/tapset/linux/i386/000077500000000000000000000000001217430427200165415ustar00rootroot00000000000000systemtap-2.3/tapset/linux/i386/aux_syscalls.stp000066400000000000000000000040721217430427200220060ustar00rootroot00000000000000# arch-specific requests of ptrace ___________________________ # = like tapset/x86_64/syscalls.stp but without PTRACE_ARCH_PRCTL # %{ #ifndef PTRACE_SYSEMU # define PTRACE_SYSEMU 31 #endif #ifndef PTRACE_SYSEMU_SINGLESTEP # define PTRACE_SYSEMU_SINGLESTEP 32 #endif #ifndef PTRACE_SINGLEBLOCK # define PTRACE_SINGLEBLOCK 33 #endif %} function _arch_ptrace_argstr(request, pid, addr, data) { if (request == %{ PTRACE_GETREGS %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GETREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_SETREGS %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SETREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_GETFPREGS %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GETFPREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_SETFPREGS %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SETFPREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_GETFPXREGS %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GETFPXREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_SETFPXREGS %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SETFPXREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_OLDSETOPTIONS %}) return sprintf ("PTRACE_OLDSETOPTIONS, %d, %s", pid, _ptrace_options_str (data)) if (request == %{ PTRACE_GET_THREAD_AREA %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GET_THREAD_AREA, %d, index=%d, data=%p", pid, addr, data) if (request == %{ PTRACE_SET_THREAD_AREA %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SET_THREAD_AREA, %d, index=%p, data=%p", pid, addr, data) if (request == %{ PTRACE_SYSEMU %}) return sprintf ("PTRACE_SYSEMU, %d, %s", pid, _signal_name (data)) if (request == %{ PTRACE_SYSEMU_SINGLESTEP %}) return sprintf ("PTRACE_SYSEMU_SINGLESTEP, %d, %s", pid, _signal_name (data)) if (request == %{ PTRACE_SINGLEBLOCK %}) return sprintf ("PTRACE_SINGLEBLOCK, %d, %s", pid, _signal_name (data)) } function _ptrace_return_arch_prctl_addr:long(request:long, addr:long, data:long) { return 0 } systemtap-2.3/tapset/linux/i386/nd_syscalls.stp000066400000000000000000000131701217430427200216110ustar00rootroot00000000000000# 32-bit x86-specific system calls # These are typically defined in arch/i386 # # get_thread_area ____________________________________________ /* * asmlinkage int * sys_get_thread_area(struct user_desc __user *u_info) */ probe nd_syscall.get_thread_area = kprobe.function("sys_get_thread_area") { name = "get_thread_area" // u_info_uaddr = $u_info asmlinkage() u_info_uaddr = pointer_arg(1) argstr = sprintf("%p", u_info_uaddr) } probe nd_syscall.get_thread_area.return = kprobe.function("sys_get_thread_area").return { name = "get_thread_area" retstr = returnstr(1) } # iopl _______________________________________________________ # long sys_iopl(unsigned long unused) # NOTE. This function is only in i386 and x86_64 and its args vary # between those two archs. # probe nd_syscall.iopl = kprobe.function("sys_iopl") { name = "iopl" argstr = "" } probe nd_syscall.iopl.return = kprobe.function("sys_iopl").return { name = "iopl" retstr = returnstr(1) } # ipc ________________________________________________________ # int sys_ipc (uint call, int first, int second, int third, void __user *ptr, long fifth) # probe nd_syscall.ipc = kprobe.function("sys_ipc") ? { name = "ipc" // call = $call // first = $first // second = $second // third = $third // ptr_uaddr = $ptr // fifth = $fifth // argstr = sprintf("%d, %d, %d, %d, %p, %d", $call, $first, // $second, $third, $ptr, $fifth) asmlinkage() call = uint_arg(1) first = int_arg(2) second = int_arg(3) third = int_arg(4) ptr_uaddr = pointer_arg(5) fifth = long_arg(6) argstr = sprintf("%d, %d, %d, %d, %p, %d", call, first, second, third, ptr_uaddr, fifth) } probe nd_syscall.ipc.return = kprobe.function("sys_ipc").return ? { name = "ipc" retstr = returnstr(1) } # In kernels < 2.6.33, mmap()/mmap2() was handled by arch-specific # code. In kernels >= 2.6.33, the arch-specific code just calls # generic sys_mmap_pgoff(). %( kernel_v < "2.6.33" %? # mmap2 ____________________________________________ # sys_mmap2(unsigned long addr, unsigned long len, # unsigned long prot, unsigned long flags, # unsigned long fd, unsigned long pgoff) # probe nd_syscall.mmap2 = kprobe.function("sys_mmap_pgoff") ?, kprobe.function("sys_mmap2") ? { name = "mmap2" // start = $addr // length = $len // prot = $prot // flags = $flags // fd = __int32($fd) // pgoffset = $pgoff // argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, // $len, _mprotect_prot_str($prot), _mmap_flags($flags), // __int32($fd), $pgoff) asmlinkage() start = ulong_arg(1) length = ulong_arg(2) prot = ulong_arg(3) flags = ulong_arg(4) # Although the kernel gets an unsigned long fd, on the # user-side it is a signed int. Fix this. fd = int_arg(5) pgoffset = ulong_arg(6) argstr = sprintf("%p, %d, %s, %s, %d, %d", start, length, _mprotect_prot_str(prot), _mmap_flags(flags), fd, pgoffset) } probe nd_syscall.mmap2.return = kprobe.function("sys_mmap_pgoff").return ?, kprobe.function("sys_mmap2").return ? { name = "mmap2" retstr = returnstr(2) } %) # set_thread_area ____________________________________________ /* * asmlinkage int * sys_set_thread_area(struct user_desc __user *u_info) */ probe nd_syscall.set_thread_area = kprobe.function("sys_set_thread_area") { name = "set_thread_area" // u_info_uaddr = $u_info asmlinkage() u_info_uaddr = pointer_arg(1) argstr = sprintf("%p", u_info_uaddr) } probe nd_syscall.set_thread_area.return = kprobe.function("sys_set_thread_area").return { name = "set_thread_area" retstr = returnstr(1) } # set_zone_reclaim ___________________________________________ /* * asmlinkage long * sys_set_zone_reclaim(unsigned int node, * unsigned int zone, * unsigned int state) */ probe nd_syscall.set_zone_reclaim = kprobe.function("sys_set_zone_reclaim") ? { name = "set_zone_reclaim" // node = $node // zone = $zone // state = $state // argstr = sprintf("%d, %d, %d", $node, $zone, $state) asmlinkage() node = uint_arg(1) zone = uint_arg(2) state = uint_arg(3) argstr = sprintf("%d, %d, %d", node, zone, state) } probe nd_syscall.set_zone_reclaim.return = kprobe.function("sys_set_zone_reclaim").return ? { name = "set_zone_reclaim" retstr = returnstr(1) } %( CONFIG_GENERIC_SIGALTSTACK == "n" || kernel_v < "3.8" %? # sigaltstack ________________________________________________ # int sys_sigaltstack(unsigned long ebx) # # NOTE: args vary between archs. # probe nd_syscall.sigaltstack = kprobe.function("sys_sigaltstack") { name = "sigaltstack" // ussp = %( kernel_vr < "2.6.25" %? $ebx %: %( kernel_vr < "2.6.30" %? $bx %: $regs->bx %) %) // NB: no asmlinkage() ussp = %( kernel_vr < "2.6.30" %? ulong_arg(1) %: @cast(ulong_arg(1), "pt_regs", "kernel")->bx %) argstr = sprintf("%p", ussp) } probe nd_syscall.sigaltstack.return = kprobe.function("sys_sigaltstack").return { name = "sigaltstack" retstr = returnstr(1) } %) # vm86 _______________________________________________________ # # int sys_vm86(struct pt_regs regs) # probe nd_syscall.vm86 = kprobe.function("sys_vm86") ? { name = "vm86" /* * unsupported type identifier '$regs' * regs = $regs */ argstr = "" } probe nd_syscall.vm86.return = kprobe.function("sys_vm86").return ? { name = "vm86" retstr = returnstr(1) } # vm86old ____________________________________________________ # # int sys_vm86old(struct pt_regs regs) # probe nd_syscall.vm86old = kprobe.function("sys_vm86old") ? { name = "vm86old" /* * unsupported type identifier '$regs' * regs = $regs */ argstr = "" } probe nd_syscall.vm86old.return = kprobe.function("sys_vm86old").return ? { name = "vm86old" retstr = returnstr(1) } systemtap-2.3/tapset/linux/i386/syscalls.stp000066400000000000000000000130721217430427200211310ustar00rootroot00000000000000# 32-bit x86-specific system calls # These are typically defined in arch/i386 # # get_thread_area ____________________________________________ /* * asmlinkage int * sys_get_thread_area(struct user_desc __user *u_info) */ probe syscall.get_thread_area = kernel.function("sys_get_thread_area") { name = "get_thread_area" u_info_uaddr = $u_info argstr = sprintf("%p", u_info_uaddr) } probe syscall.get_thread_area.return = kernel.function("sys_get_thread_area").return { name = "get_thread_area" retstr = return_str(1, $return) } # iopl _______________________________________________________ # long sys_iopl(unsigned long unused) # NOTE. This function is only in i386 and x86_64 and its args vary # between those two archs. # probe syscall.iopl = kernel.function("sys_iopl") { name = "iopl" argstr = "" } probe syscall.iopl.return = kernel.function("sys_iopl").return { name = "iopl" retstr = return_str(1, $return) } # ipc ________________________________________________________ # int sys_ipc (uint call, int first, int second, int third, void __user *ptr, long fifth) # probe syscall.ipc = kernel.function("sys_ipc") ? { name = "ipc" call = $call first = $first second = $second third = $third ptr_uaddr = $ptr fifth = $fifth argstr = sprintf("%d, %d, %d, %d, %p, %d", $call, $first, $second, $third, $ptr, $fifth) } probe syscall.ipc.return = kernel.function("sys_ipc").return ? { name = "ipc" retstr = return_str(1, $return) } # In kernels < 2.6.33, mmap()/mmap2() was handled by arch-specific # code. In kernels >= 2.6.33, the arch-specific code just calls # generic sys_mmap_pgoff(). %( kernel_v < "2.6.33" %? # mmap2 ____________________________________________ # sys_mmap2(unsigned long addr, unsigned long len, # unsigned long prot, unsigned long flags, # unsigned long fd, unsigned long pgoff) # probe syscall.mmap2 = kernel.function("sys_mmap_pgoff") ?, kernel.function("sys_mmap2") ? { name = "mmap2" start = $addr length = $len prot = $prot flags = $flags # Although the kernel gets an unsigned long fd, on the # user-side it is a signed int. Fix this. fd = __int32($fd) pgoffset = $pgoff argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len, _mprotect_prot_str($prot), _mmap_flags($flags), __int32($fd), $pgoff) } probe syscall.mmap2.return = kernel.function("sys_mmap_pgoff").return ?, kernel.function("sys_mmap2").return ? { name = "mmap2" retstr = return_str(2, $return) } %) # set_thread_area ____________________________________________ /* * asmlinkage int * sys_set_thread_area(struct user_desc __user *u_info) */ probe syscall.set_thread_area = kernel.function("sys_set_thread_area") { name = "set_thread_area" u_info_uaddr = $u_info argstr = sprintf("%p", u_info_uaddr) } probe syscall.set_thread_area.return = kernel.function("sys_set_thread_area").return { name = "set_thread_area" retstr = return_str(1, $return) } # set_zone_reclaim ___________________________________________ /* * asmlinkage long * sys_set_zone_reclaim(unsigned int node, * unsigned int zone, * unsigned int state) */ probe syscall.set_zone_reclaim = kernel.function("sys_set_zone_reclaim") ? { name = "set_zone_reclaim" node = $node zone = $zone state = $state argstr = sprintf("%d, %d, %d", $node, $zone, $state) } probe syscall.set_zone_reclaim.return = kernel.function("sys_set_zone_reclaim").return ? { name = "set_zone_reclaim" retstr = return_str(1, $return) } %( CONFIG_GENERIC_SIGALTSTACK == "n" || kernel_v < "3.8" %? # sigaltstack ________________________________________________ # int sys_sigaltstack(unsigned long ebx) # # NOTE: args vary between archs. # probe syscall.sigaltstack = kernel.function("sys_sigaltstack") { name = "sigaltstack" # 'ussp' should have been 'uss_uaddr. Deprecate the old name. %(systemtap_v <= "1.4" %? ussp = %( kernel_vr < "2.6.25" %? $ebx %: %( kernel_vr < "2.6.30" %? $bx %: $regs->bx %) %) %) if (@defined($regs)) { uss_uaddr = @choose_defined($uss, $regs->bx) uoss_uaddr = @choose_defined($uoss, $regs->cx) %(systemtap_v < "2.3" %? regs = $regs %) } else if (@defined($bx)) { # kernels < "2.6.30" uss_uaddr = $bx # Make sure the register value didn't get sign extended. uoss_uaddr = __ulong(@cast(&$bx, "pt_regs", "kernel")->cx) %(systemtap_v < "2.3" %? regs = &$bx %) } else { # kernels < "2.6.25" uss_uaddr = $ebx # Make sure the register value didn't get sign extended. uoss_uaddr = __ulong(@cast(&$ebx, "pt_regs", "kernel")->ecx) %(systemtap_v < "2.3" %? regs = &$ebx %) } argstr = sprintf("%p, %p", uss_uaddr, uoss_uaddr) } probe syscall.sigaltstack.return = kernel.function("sys_sigaltstack").return { name = "sigaltstack" retstr = return_str(1, $return) } %) # vm86 _______________________________________________________ # # int sys_vm86(struct pt_regs regs) # probe syscall.vm86 = kernel.function("sys_vm86") ? { name = "vm86" /* * unsupported type identifier '$regs' * regs = $regs */ argstr = "" } probe syscall.vm86.return = kernel.function("sys_vm86").return ? { name = "vm86" retstr = return_str(1, $return) } # vm86old ____________________________________________________ # # int sys_vm86old(struct pt_regs regs) # probe syscall.vm86old = kernel.function("sys_vm86old") ? { name = "vm86old" /* * unsupported type identifier '$regs' * regs = $regs */ argstr = "" } probe syscall.vm86old.return = kernel.function("sys_vm86old").return ? { name = "vm86old" retstr = return_str(1, $return) } systemtap-2.3/tapset/linux/ia64/000077500000000000000000000000001217430427200166135ustar00rootroot00000000000000systemtap-2.3/tapset/linux/ia64/aux_syscalls.stp000066400000000000000000000017351217430427200220630ustar00rootroot00000000000000# arch-specific requests of ptrace ___________________________ # function _arch_ptrace_argstr(request, pid, addr, data) { if (request == %{ PTRACE_SINGLEBLOCK %}) return sprintf ("PTRACE_SINGLEBLOCK, %d, %s", pid, _signal_name (data)) if (request == %{ PTRACE_OLD_GETSIGINFO %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_OLD_GETSIGINFO, %d, data=%p", pid, data) if (request == %{ PTRACE_OLD_SETSIGINFO %}) // TODO: Retrieve *data here return sprintf ("PTRACE_OLD_SETSIGINFO, %d, data=%p", pid, data) if (request == %{ PTRACE_GETREGS %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GETREGS, %d", pid) if (request == %{ PTRACE_SETREGS %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SETREGS, %d", pid) if (request == %{ PTRACE_OLDSETOPTIONS %}) return sprintf ("PTRACE_OLDSETOPTIONS, %d, %s", pid, _ptrace_options_str (data)) } function _ptrace_return_arch_prctl_addr:long(request:long, addr:long, data:long) { return 0 } systemtap-2.3/tapset/linux/ia64/nd_syscalls.stp000066400000000000000000000055711217430427200216710ustar00rootroot00000000000000# IA64 system calls # In kernels < 2.6.33, mmap()/mmap2() was handled by arch-specific # code. In kernels >= 2.6.33, the arch-specific code just calls # generic sys_mmap_pgoff(). %( kernel_v < "2.6.33" %? # mmap # sys_mmap (unsigned long addr, unsigned long len, int prot, int flags, int fd, long off) # probe nd_syscall.mmap = kprobe.function("sys_mmap") ? { name = "mmap" // start = $addr // len = $len // prot = $prot // flags = $flags // fd = $fd // offset = $off // argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len, // _mprotect_prot_str($prot), _mmap_flags($flags), $fd, $off) asmlinkage() start = ulong_arg(1) len = ulong_arg(2) prot = int_arg(3) flags = int_arg(4) fd = int_arg(5) offset = long_arg(6) argstr = sprintf("%p, %d, %s, %s, %d, %d", start, len, _mprotect_prot_str(prot), _mmap_flags(flags), fd, offset) } probe nd_syscall.mmap.return = kprobe.function("sys_mmap").return ? { name = "mmap" retstr = returnstr(2) } # mmap2 # sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff) probe nd_syscall.mmap2 = kprobe.function("sys_mmap2") ? { name = "mmap2" // start = $addr // length = $len // prot = $prot // flags = $flags // fd = $fd // pgoffset = $pgoff // argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, // $len, _mprotect_prot_str($prot), _mmap_flags($flags), // $fd, $pgoff) asmlinkage() start = ulong_arg(1) length = ulong_arg(2) prot = int_arg(3) flags = int_arg(4) fd = int_arg(5) pgoffset = long_arg(6) argstr = sprintf("%p, %d, %s, %s, %d, %d", start, length, _mprotect_prot_str(prot), _mmap_flags(flags), fd, pgoffset) } probe nd_syscall.mmap2.return = kprobe.function("sys_mmap2").return ? { name = "mmap2" retstr = returnstr(2) } %) %( CONFIG_GENERIC_SIGALTSTACK == "n" || kernel_v < "3.8" %? # sigaltstack _______________________________________________ # asmlinkage long # sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, # long arg3, long arg4, long arg5, long arg6, long arg7, # struct pt_regs regs) # probe nd_syscall.sigaltstack = kprobe.function("sys_sigaltstack") { name = "sigaltstack"; // ss_uaddr = $uss // oss_uaddr = $uoss // argstr = sprintf("%p, %p", $uss, $uoss) asmlinkage() ss_uaddr = pointer_arg(1) oss_uaddr = pointer_arg(2) argstr = sprintf("%p, %p", ss_uaddr, oss_uaddr) } probe nd_syscall.sigaltstack.return = kprobe.function("sys_sigaltstack").return { name = "sigaltstack"; retstr = returnstr(1) } %) # sysctl _____________________________________________________ # # long sys32_sysctl (struct sysctl32 __user *args) # probe nd_syscall.sysctl32 = kprobe.function("sys32_sysctl") ? { name = "sysctl" // argstr = sprintf("%p", $args) asmlinkage() argstr = sprintf("%p", pointer_arg(1)) } probe nd_syscall.sysctl32.return = kprobe.function("sys32_sysctl").return ? { name = "sysctl" retstr = returnstr(1) } systemtap-2.3/tapset/linux/ia64/syscalls.stp000066400000000000000000000050601217430427200212010ustar00rootroot00000000000000# IA64 system calls # In kernels < 2.6.33, mmap()/mmap2() was handled by arch-specific # code. In kernels >= 2.6.33, the arch-specific code just calls # generic sys_mmap_pgoff(). %( kernel_v < "2.6.33" %? # mmap # sys_mmap (unsigned long addr, unsigned long len, int prot, int flags, int fd, long off) # probe syscall.mmap = kernel.function("sys_mmap") ? { name = "mmap" start = $addr len = $len prot = $prot flags = $flags # Although the kernel gets an unsigned long fd, on the # user-side it is a signed int. Fix this. fd = __int32($fd) offset = $off argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len, _mprotect_prot_str($prot), _mmap_flags($flags), __int32($fd), $off) } probe syscall.mmap.return = kernel.function("sys_mmap").return ? { name = "mmap" retstr = return_str(2, $return) } # mmap2 # sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff) probe syscall.mmap2 = kernel.function("sys_mmap2") ? { name = "mmap2" start = $addr length = $len prot = $prot flags = $flags fd = $fd pgoffset = $pgoff argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len, _mprotect_prot_str($prot), _mmap_flags($flags), $fd, $pgoff) } probe syscall.mmap2.return = kernel.function("sys_mmap2").return ? { name = "mmap2" retstr = return_str(2, $return) } %) %( CONFIG_GENERIC_SIGALTSTACK == "n" || kernel_v < "3.8" %? # sigaltstack _______________________________________________ # asmlinkage long # sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, # long arg3, long arg4, long arg5, long arg6, long arg7, # struct pt_regs regs) # probe syscall.sigaltstack = kernel.function("sys_sigaltstack") { name = "sigaltstack"; %(systemtap_v <= "1.4" %? ss_uaddr = $uss oss_uaddr = $uoss %) uss_uaddr = $uss uoss_uaddr = $uoss %(systemtap_v < "2.3" %? regs = &$regs %) argstr = sprintf("%p, %p", $uss, $uoss) } probe syscall.sigaltstack.return = kernel.function("sys_sigaltstack").return { name = "sigaltstack"; retstr = return_str(1, $return) } %) # sysctl _____________________________________________________ # # long sys32_sysctl (struct sysctl32 __user *args) # probe syscall.sysctl32 = kernel.function("sys32_sysctl") ? { name = "sysctl" argstr = sprintf("%p", $args) } probe syscall.sysctl32.return = kernel.function("sys32_sysctl").return ? { name = "sysctl" retstr = return_str(1, $return) } systemtap-2.3/tapset/linux/inet.stp000066400000000000000000000026601217430427200175430ustar00rootroot00000000000000/* Some functions from libc */ /* * These functions convert between network (big-endian) and host byte * order, like their namesake C functions. * */ /** * sfunction htonll - Convert 64-bit long long from host to network order * @x: Value to convert */ function htonll:long (x:long) %{ /* pure */ STAP_RETVALUE = (int64_t) cpu_to_be64 ((u64) STAP_ARG_x); %} /** * sfunction htonl - Convert 32-bit long from host to network order * @x: Value to convert */ function htonl:long (x:long) %{ /* pure */ STAP_RETVALUE = (int64_t) cpu_to_be32 ((u32) STAP_ARG_x); %} /** * sfunction htons - Convert 16-bit short from host to network order * @x: Value to convert */ function htons:long (x:long) %{ /* pure */ STAP_RETVALUE = (int64_t) cpu_to_be16 ((u16) STAP_ARG_x); %} /** * sfunction ntohll - Convert 64-bit long long from network to host order * @x: Value to convert */ function ntohll:long (x:long) %{ /* pure */ STAP_RETVALUE = (int64_t) be64_to_cpu ((u64) STAP_ARG_x); %} /** * sfunction ntohl - Convert 32-bit long from network to host order * @x: Value to convert */ function ntohl:long (x:long) %{ /* pure */ STAP_RETVALUE = (int64_t) be32_to_cpu ((u32) STAP_ARG_x); %} /** * sfunction ntohs - Convert 16-bit short from network to host order * @x: Value to convert */ function ntohs:long (x:long) %{ /* pure */ STAP_RETVALUE = (int64_t) be16_to_cpu ((u16) STAP_ARG_x); %} systemtap-2.3/tapset/linux/inet_sock.stp000066400000000000000000000024741217430427200205650ustar00rootroot00000000000000// inet_sock information tapset // Copyright (C) 2006 IBM Corp. // Copyright (C) 2006 Intel Corporation. // Copyright (C) 2009-2012 Red Hat, Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /** * sfunction inet_get_local_port - Provide local port number for a kernel socket * @sock: pointer to the kernel socket */ function inet_get_local_port:long(sock:long) { return @choose_defined(@cast(sock, "inet_sock")->sk->__sk_common->skc_num, # kernel >= 2.6.33 @choose_defined(@cast(sock, "inet_sock")->inet_num, # kernel >= 2.6.11 @choose_defined(@cast(sock, "inet_sock")->num, @cast(sock, "inet_sock", "kernel")->inet->num))) } /** * sfunction inet_get_ip_source - Provide IP source address string for a kernel socket * * @sock: pointer to the kernel socket * */ function inet_get_ip_source:string(sock:long) { return format_ipaddr(__ip_sock_daddr(sock), __ip_sock_family(sock)) } %(systemtap_v < "2.0" %? // Turns a daddr as found in an inet_sock into a dotted ip string. function daddr_to_string:string(daddr:long) { return format_ipaddr(daddr, %{ /* pure */ /* unprivileged */ AF_INET %}) } %) systemtap-2.3/tapset/linux/ioblock.stp000066400000000000000000000274061217430427200202330ustar00rootroot00000000000000// Block I/O tapset // Copyright (C) 2006 Intel Corp. // Copyright (C) 2006 IBM Corp. // Copyright (C) 2010 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. %{ #include #include #ifdef STAPCONF_BLK_TYPES #include #else #define REQ_WRITE (1 << BIO_RW) #endif %} /* get i-node number of mapped file */ function __bio_ino:long(bio:long) %{ /* pure */ struct bio *bio = (struct bio *)(long)STAP_ARG_bio; struct page *bv_page = (bio && bio->bi_vcnt) ? kread(&(bio->bi_io_vec[0].bv_page)) : NULL; struct address_space *mapping; struct inode *host; STAP_RETVALUE = -1; if (bv_page && !PageSlab(bv_page) && !PageSwapCache(bv_page)) { mapping = kread(&(bv_page->mapping)); if (mapping && ((unsigned long)mapping & PAGE_MAPPING_ANON) == 0) { host = kread(&(mapping->host)); if (host) STAP_RETVALUE = kread(&(host->i_ino)); } } CATCH_DEREF_FAULT(); %} /* returns 0 for read, 1 for write */ function bio_rw_num:long(rw:long) %{ /* pure */ long rw = (long)STAP_ARG_rw; STAP_RETVALUE = (rw & REQ_WRITE); %} /* returns R for read, W for write */ function bio_rw_str(rw:long) { return bio_rw_num(rw) == BIO_READ ? "R" : "W" } /* returns start sector */ function __bio_start_sect:long(bio:long) { bi_bdev = bio ? @cast(bio, "bio")->bi_bdev : 0 bd_part = bi_bdev ? @cast(bi_bdev, "block_device")->bd_part : 0 return bd_part ? @cast(bd_part, "hd_struct")->start_sect : -1 } /* returns the block device name */ function __bio_devname:string(bio:long) { return bdevname(@cast(bio, "bio")->bi_bdev) } global BIO_READ = 0, BIO_WRITE = 1 /** * probe ioblock.request - Fires whenever making a generic block I/O request. * * @name - name of the probe point * @devname - block device name * @ino - i-node number of the mapped file * @sector - beginning sector for the entire bio * @flags - see below * BIO_UPTODATE 0 ok after I/O completion * BIO_RW_BLOCK 1 RW_AHEAD set, and read/write would block * BIO_EOF 2 out-out-bounds error * BIO_SEG_VALID 3 nr_hw_seg valid * BIO_CLONED 4 doesn't own data * BIO_BOUNCED 5 bio is a bounce bio * BIO_USER_MAPPED 6 contains user pages * BIO_EOPNOTSUPP 7 not supported * * @rw - binary trace for read/write request * @vcnt - bio vector count which represents number of array element (page, offset, length) which make up this I/O request * @idx - offset into the bio vector array * @phys_segments - number of segments in this bio after physical address coalescing is performed * @hw_segments - number of segments after physical and DMA remapping hardware coalescing is performed * @size - total size in bytes * @bdev - target block device * @bdev_contains - points to the device object which contains the partition (when bio structure represents a partition) * @p_start_sect - points to the start sector of the partition structure of the device * * Context: * The process makes block I/O request */ probe ioblock.request = kernel.function ("generic_make_request") { name = "ioblock.request" devname = __bio_devname($bio) ino = __bio_ino($bio) sector = $bio->bi_sector flags = $bio->bi_flags rw = $bio->bi_rw vcnt = $bio->bi_vcnt idx = $bio->bi_idx phys_segments = $bio->bi_phys_segments hw_segments = @choose_defined($bio->bi_hw_segments, 0) size = $bio->bi_size bdev = $bio->bi_bdev bdev_contains = $bio->bi_bdev->bd_contains p_start_sect = __bio_start_sect($bio) } /** * probe ioblock.end - Fires whenever a block I/O transfer is complete. * * @name - name of the probe point * @devname - block device name * @ino - i-node number of the mapped file * @bytes_done - number of bytes transferred * @sector - beginning sector for the entire bio * @flags - see below * BIO_UPTODATE 0 ok after I/O completion * BIO_RW_BLOCK 1 RW_AHEAD set, and read/write would block * BIO_EOF 2 out-out-bounds error * BIO_SEG_VALID 3 nr_hw_seg valid * BIO_CLONED 4 doesn't own data * BIO_BOUNCED 5 bio is a bounce bio * BIO_USER_MAPPED 6 contains user pages * BIO_EOPNOTSUPP 7 not supported * @error - 0 on success * @rw - binary trace for read/write request * @vcnt - bio vector count which represents number of array element (page, offset, length) which makes up this I/O request * @idx - offset into the bio vector array * @phys_segments - number of segments in this bio after physical address coalescing is performed. * @hw_segments - number of segments after physical and DMA remapping hardware coalescing is performed * @size - total size in bytes * * Context: * The process signals the transfer is done. */ probe ioblock.end = kernel.function("bio_endio") { name = "ioblock.end" devname = __bio_devname($bio) ino = __bio_ino($bio) bytes_done = @choose_defined($bytes_done, $bio->bi_size) error = $error sector = $bio->bi_sector flags = $bio->bi_flags rw = $bio->bi_rw vcnt = $bio->bi_vcnt idx = $bio->bi_idx phys_segments = $bio->bi_phys_segments hw_segments = @choose_defined($bio->bi_hw_segments, 0) size = $bio->bi_size } /** * probe ioblock_trace.bounce - Fires whenever a buffer bounce is needed for at least one page of a block IO request. * * @name - name of the probe point * @q - request queue on which this bio was queued. * @devname - device for which a buffer bounce was needed. * @ino - i-node number of the mapped file * @bytes_done - number of bytes transferred * @sector - beginning sector for the entire bio * @flags - see below * BIO_UPTODATE 0 ok after I/O completion * BIO_RW_BLOCK 1 RW_AHEAD set, and read/write would block * BIO_EOF 2 out-out-bounds error * BIO_SEG_VALID 3 nr_hw_seg valid * BIO_CLONED 4 doesn't own data * BIO_BOUNCED 5 bio is a bounce bio * BIO_USER_MAPPED 6 contains user pages * BIO_EOPNOTSUPP 7 not supported * @rw - binary trace for read/write request * @vcnt - bio vector count which represents number of array element (page, offset, length) which makes up this I/O request * @idx - offset into the bio vector array * @phys_segments - number of segments in this bio after physical address coalescing is performed. * @size - total size in bytes * @bdev - target block device * @bdev_contains - points to the device object which contains the partition (when bio structure represents a partition) * @p_start_sect - points to the start sector of the partition structure of the device * * Context : * The process creating a block IO request. */ probe ioblock_trace.bounce = kernel.trace("block_bio_bounce") { name = "ioblock_trace.bounce" q = $q devname = __bio_devname($bio) ino = __bio_ino($bio) bytes_done = $bio->bi_size sector = $bio->bi_sector flags = $bio->bi_flags rw = $bio->bi_rw vcnt = $bio->bi_vcnt idx = $bio->bi_idx phys_segments = $bio->bi_phys_segments size = $bio->bi_size bdev_contains = $bio->bi_bdev->bd_contains bdev = $bio->bi_bdev p_start_sect = __bio_start_sect($bio) } /** * probe ioblock_trace.request - Fires just as a generic block I/O request is created for a bio. * * @name - name of the probe point * @q - request queue on which this bio was queued. * @devname - block device name * @ino - i-node number of the mapped file * @bytes_done - number of bytes transferred * @sector - beginning sector for the entire bio * @flags - see below * BIO_UPTODATE 0 ok after I/O completion * BIO_RW_BLOCK 1 RW_AHEAD set, and read/write would block * BIO_EOF 2 out-out-bounds error * BIO_SEG_VALID 3 nr_hw_seg valid * BIO_CLONED 4 doesn't own data * BIO_BOUNCED 5 bio is a bounce bio * BIO_USER_MAPPED 6 contains user pages * BIO_EOPNOTSUPP 7 not supported * * @rw - binary trace for read/write request * @vcnt - bio vector count which represents number of array element (page, offset, length) which make up this I/O request * @idx - offset into the bio vector array * @phys_segments - number of segments in this bio after physical address coalescing is performed. * @size - total size in bytes * @bdev - target block device * @bdev_contains - points to the device object which contains the partition (when bio structure represents a partition) * @p_start_sect - points to the start sector of the partition structure of the device * * Context: * The process makes block I/O request */ probe ioblock_trace.request = kernel.trace("block_bio_queue") { name = "ioblock_trace.request" q = $q devname = __bio_devname($bio) ino = __bio_ino($bio) bytes_done = $bio->bi_size sector = $bio->bi_sector flags = $bio->bi_flags rw = $bio->bi_rw vcnt = $bio->bi_vcnt idx = $bio->bi_idx phys_segments = $bio->bi_phys_segments size = $bio->bi_size bdev_contains = $bio->bi_bdev->bd_contains bdev = $bio->bi_bdev p_start_sect = __bio_start_sect($bio) } /** * probe ioblock_trace.end - Fires whenever a block I/O transfer is complete. * * @name - name of the probe point * @q - request queue on which this bio was queued. * @devname - block device name * @ino - i-node number of the mapped file * @bytes_done - number of bytes transferred * @sector - beginning sector for the entire bio * @flags - see below * BIO_UPTODATE 0 ok after I/O completion * BIO_RW_BLOCK 1 RW_AHEAD set, and read/write would block * BIO_EOF 2 out-out-bounds error * BIO_SEG_VALID 3 nr_hw_seg valid * BIO_CLONED 4 doesn't own data * BIO_BOUNCED 5 bio is a bounce bio * BIO_USER_MAPPED 6 contains user pages * BIO_EOPNOTSUPP 7 not supported * * @rw - binary trace for read/write request * @vcnt - bio vector count which represents number of array element (page, offset, length) which makes up this I/O request * @idx - offset into the bio vector array * @phys_segments - number of segments in this bio after physical address coalescing is performed. * @size - total size in bytes * @bdev - target block device * @bdev_contains - points to the device object which contains the partition (when bio structure represents a partition) * @p_start_sect - points to the start sector of the partition structure of the device * * Context: * The process signals the transfer is done. */ probe ioblock_trace.end = kernel.trace("block_bio_complete") { name = "ioblock_trace.end" q = $q devname = __bio_devname($bio) ino = __bio_ino($bio) bytes_done = $bio->bi_size sector = $bio->bi_sector flags = $bio->bi_flags rw = $bio->bi_rw vcnt = $bio->bi_vcnt idx = $bio->bi_idx phys_segments = $bio->bi_phys_segments size = $bio->bi_size bdev_contains = $bio->bi_bdev->bd_contains bdev = $bio->bi_bdev p_start_sect = __bio_start_sect($bio) } systemtap-2.3/tapset/linux/ioscheduler.stp000066400000000000000000000266541217430427200211230ustar00rootroot00000000000000// IO scheduler tapset // Copyright (C) 2005, 2006 IBM Corp. // Copyright (C) 2010 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // This family of probe points is used to probe IO scheduler activities. // %{ #include #include %} /** * probe ioscheduler.elv_next_request - Fires when a request is retrieved from the request queue * @name: Name of the probe point * @elevator_name: The type of I/O elevator currently enabled */ probe ioscheduler.elv_next_request = kernel.function("blk_peek_request") !, kernel.function("elv_next_request") { name = "elv_next_request" elevator_name = kernel_string( @choose_defined($q->elevator->type->elevator_name, @choose_defined($q->elevator->elevator_type->elevator_name, $q->elevator->elevator_name))) } /** * probe ioscheduler.elv_next_request.return - Fires when a request retrieval issues a return signal * @name: Name of the probe point * @rq: Address of the request * @rq_flags: Request flags * @disk_major: Disk major number of the request * @disk_minor: Disk minor number of the request */ probe ioscheduler.elv_next_request.return = kernel.function("blk_peek_request").return !, kernel.function("elv_next_request").return { name = "elv_next_request" if ($return == 0) { rq = 0 rq_flags = 0 disk_major = -1 disk_minor = -1 } else { rq = $return rq_flags = @choose_defined($return->cmd_flags, $return->flags) if ($return->rq_disk == 0) { disk_major = -1 disk_minor = -1 } else { disk_major = $return->rq_disk->major disk_minor = $return->rq_disk->first_minor } } } /** * probe ioscheduler.elv_completed_request - Fires when a request is completed * @name: Name of the probe point * @elevator_name: The type of I/O elevator currently enabled * @rq: Address of the request * @rq_flags: Request flags * @disk_major: Disk major number of the request * @disk_minor: Disk minor number of the request */ probe ioscheduler.elv_completed_request = kernel.function("elv_completed_request") { name = "elv_completed_request" elevator_name = kernel_string( @choose_defined($q->elevator->type->elevator_name, @choose_defined($q->elevator->elevator_type->elevator_name, $q->elevator->elevator_name))) if($rq == 0) { disk_major = -1 disk_minor = -1 } else { if($rq->rq_disk == 0) { disk_major = -1 disk_minor = -1 } else { disk_major = $rq->rq_disk->major disk_minor = $rq->rq_disk->first_minor } } rq = $rq rq_flags = ($rq == 0) ? 0 : @choose_defined($rq->cmd_flags, $rq->flags) } /** * probe ioscheduler.elv_add_request.kp - kprobe based probe to indicate that a request was added to the request queue * @name: Name of the probe point * @elevator_name: The type of I/O elevator currently enabled * @q: pointer to request queue * @rq: Address of the request * @rq_flags: Request flags * @disk_major: Disk major number of the request * @disk_minor: Disk minor number of the request */ // when a request is added to the request queue probe ioscheduler.elv_add_request.kp = kernel.function("elv_insert") !, kernel.function("__elv_add_request") { name = "elv_add_request" elevator_name = kernel_string( @choose_defined($q->elevator->type->elevator_name, @choose_defined($q->elevator->elevator_type->elevator_name, $q->elevator->elevator_name))) q = $q if($rq == 0) { disk_major = -1 disk_minor = -1 } else { if($rq->rq_disk == 0) { disk_major = -1 disk_minor = -1 } else { disk_major = $rq->rq_disk->major disk_minor = $rq->rq_disk->first_minor } } rq = $rq rq_flags = ($rq == 0) ? 0 : @choose_defined($rq->cmd_flags, $rq->flags) } /** * probe ioscheduler.elv_add_request.tp - tracepoint based probe to indicate a request is added to the request queue. * @name : Name of the probe point * @elevator_name : The type of I/O elevator currently enabled. * @q : Pointer to request queue. * @rq : Address of request. * @rq_flags : Request flags. * @disk_major : Disk major no of request. * @disk_minor : Disk minor number of request. * */ probe ioscheduler.elv_add_request.tp = kernel.trace("block_rq_insert") ? { name = "elv_add_request" q = $q elevator_name = kernel_string( @choose_defined($q->elevator->type->elevator_name, @choose_defined($q->elevator->elevator_type->elevator_name, $q->elevator->elevator_name))) rq = $rq if ($rq == 0 || $rq->rq_disk ==0) { disk_major = -1 disk_minor = -1 } else { disk_major = $rq->rq_disk->major disk_minor = $rq->rq_disk->first_minor } rq_flags = ($rq == 0) ? 0 : @choose_defined($rq->cmd_flags, $rq->flags) } /** * probe ioscheduler.elv_add_request - probe to indicate request is added to the request queue. * @elevator_name : The type of I/O elevator currently enabled. * @q : Pointer to request queue. * @rq : Address of request. * @rq_flags : Request flags. * @disk_major : Disk major no of request. * @disk_minor : Disk minor number of request. * */ probe ioscheduler.elv_add_request = ioscheduler.elv_add_request.tp !, ioscheduler.elv_add_request.kp {} /** * probe ioscheduler_trace.elv_completed_request - Fires when a request is * completed. * @name : Name of the probe point * @elevator_name : The type of I/O elevator currently enabled. * @rq : Address of request. * @rq_flags : Request flags. * @disk_major : Disk major no of request. * @disk_minor : Disk minor number of request. * */ probe ioscheduler_trace.elv_completed_request = kernel.trace("block_rq_complete") ? { name = "elv_completed_request" elevator_name = kernel_string( @choose_defined($q->elevator->type->elevator_name, @choose_defined($q->elevator->elevator_type->elevator_name, $q->elevator->elevator_name))) rq = $rq if ($rq == 0 || $rq->rq_disk ==0) { disk_major = -1 disk_minor = -1 } else { disk_major = $rq->rq_disk->major disk_minor = $rq->rq_disk->first_minor } rq_flags = ($rq == 0) ? 0 : @choose_defined($rq->cmd_flags, $rq->flags) } /** * probe ioscheduler_trace.elv_issue_request - Fires when a request is * scheduled. * @name : Name of the probe point * @elevator_name : The type of I/O elevator currently enabled. * @rq : Address of request. * @rq_flags : Request flags. * @disk_major : Disk major no of request. * @disk_minor : Disk minor number of request. * */ probe ioscheduler_trace.elv_issue_request = kernel.trace("block_rq_issue") ? { name = "elv_issue_request" elevator_name = kernel_string( @choose_defined($q->elevator->type->elevator_name, @choose_defined($q->elevator->elevator_type->elevator_name, $q->elevator->elevator_name))) rq = $rq if ($rq == 0 || $rq->rq_disk ==0) { disk_major = -1 disk_minor = -1 } else { disk_major = $rq->rq_disk->major disk_minor = $rq->rq_disk->first_minor } rq_flags = ($rq == 0) ? 0 : @choose_defined($rq->cmd_flags, $rq->flags) } /** * probe ioscheduler_trace.elv_requeue_request - Fires when a request is * put back on the queue, when the hadware cannot accept more requests. * @name : Name of the probe point * @elevator_name : The type of I/O elevator currently enabled. * @rq : Address of request. * @rq_flags : Request flags. * @disk_major : Disk major no of request. * @disk_minor : Disk minor number of request. * */ probe ioscheduler_trace.elv_requeue_request = kernel.trace("block_rq_requeue") ? { name = "elv_requeue_request" elevator_name = kernel_string( @choose_defined($q->elevator->type->elevator_name, @choose_defined($q->elevator->elevator_type->elevator_name, $q->elevator->elevator_name))) rq = $rq if ($rq == 0 || $rq->rq_disk ==0) { disk_major = -1 disk_minor = -1 } else { disk_major = $rq->rq_disk->major disk_minor = $rq->rq_disk->first_minor } rq_flags = ($rq == 0) ? 0 : @choose_defined($rq->cmd_flags, $rq->flags) } /** * probe ioscheduler_trace.elv_abort_request - Fires when a request is aborted. * @name : Name of the probe point * @elevator_name : The type of I/O elevator currently enabled. * @rq : Address of request. * @rq_flags : Request flags. * @disk_major : Disk major no of request. * @disk_minor : Disk minor number of request. * */ probe ioscheduler_trace.elv_abort_request = kernel.trace("block_rq_abort") ? { name = "elv_abort_request" elevator_name = kernel_string( @choose_defined($q->elevator->type->elevator_name, @choose_defined($q->elevator->elevator_type->elevator_name, $q->elevator->elevator_name))) rq = $rq if ($rq == 0 || $rq->rq_disk ==0) { disk_major = -1 disk_minor = -1 } else { disk_major = $rq->rq_disk->major disk_minor = $rq->rq_disk->first_minor } rq_flags = ($rq == 0) ? 0 : @choose_defined($rq->cmd_flags, $rq->flags) } /** * probe ioscheduler_trace.plug - Fires when a request queue is plugged; * ie, requests in the queue cannot be serviced by block driver. * @name : Name of the probe point * @rq_queue : request queue * */ probe ioscheduler_trace.plug = kernel.trace("block_plug") ? { name = "plug" rq_queue = $q } /** * probe ioscheduler_trace.unplug_io - Fires when a request queue is unplugged; * Either, when number of pending requests in the queue exceeds threshold * or, upon expiration of timer that was activated when queue was plugged. * @name : Name of the probe point * @rq_queue : request queue * */ probe ioscheduler_trace.unplug_io = kernel.trace("block_unplug_io") ? { name = "unplug_io" rq_queue = $q } /** * probe ioscheduler_trace.unplug_timer - Fires when unplug timer associated * with a request queue expires. * @name : Name of the probe point * @rq_queue : request queue * */ probe ioscheduler_trace.unplug_timer = kernel.trace("block_unplug_timer") ? { name = "unplug_timer" rq_queue = $q } function disk_major_from_request:long(var_q:long) %{ /* pure */ struct request_queue *q = (struct request_queue *)((long)STAP_ARG_var_q); /* We need to make sure there isn't a deref hazard here when * reading 'q->queue_head'. However, kread() wants a pointer to * a pointer, and we can't provide that for 'q->queue_head' * since the list_head structure is directly embedded in the * 'struct request_queue'. So, we validate all the members of * the list_head structure instead. */ (void) kread(&(q->queue_head.next)); (void) kread(&(q->queue_head.prev)); if (list_empty(&(q->queue_head))) STAP_RETVALUE = -1; else { struct request *rq = list_entry_rq(q->queue_head.next); struct gendisk *rq_disk = kread(&(rq->rq_disk)); STAP_RETVALUE = kread(&(rq_disk->major)); } CATCH_DEREF_FAULT(); %} function disk_minor_from_request:long(var_q:long) %{ /* pure */ struct request_queue *q = (struct request_queue *)((long)STAP_ARG_var_q); /* We need to make sure there isn't a deref hazard here when * reading 'q->queue_head'. However, kread() wants a pointer to * a pointer, and we can't provide that for 'q->queue_head' * since the list_head structure is directly embedded in the * 'struct request_queue'. So, we validate all the members of * the list_head structure instead. */ (void) kread(&(q->queue_head.next)); (void) kread(&(q->queue_head.prev)); if (list_empty(&(q->queue_head))) STAP_RETVALUE = -1; else { struct request *rq = list_entry_rq(q->queue_head.next); struct gendisk *rq_disk = kread(&(rq->rq_disk)); STAP_RETVALUE = kread(&(rq_disk->first_minor)); } CATCH_DEREF_FAULT(); %} systemtap-2.3/tapset/linux/ip.stp000066400000000000000000000120441217430427200172110ustar00rootroot00000000000000// IP tapset // // Copyright (C) 2009, IBM Inc. // Copyright (C) 2010, 2012 Red Hat Inc. // // Author : Breno Leitao // // This file is free software. You can redistribute it and/or modify it under // the terms of the GNU General Public License (GPL), version 2. // // Based on previous work done by Arnaldo Carvalho de Melo %{ #include #include // For AF_INET & AF_INET6 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #include #include #endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */ %} /** * sfunction format_ipaddr - Returns a string representation for an IP address * * @addr: the IP address * @family: the IP address family (either AF_INET or AF_INET6) */ function format_ipaddr:string (addr:long, family:long) %{ /* pure */ if (STAP_ARG_family == AF_INET) { __be32 ip = (__be32)STAP_ARG_addr; #ifndef NIPQUAD_FMT // kver >= 2.6.36 snprintf(STAP_RETVALUE, MAXSTRINGLEN, "%pI4", &ip); #else snprintf(STAP_RETVALUE, MAXSTRINGLEN, NIPQUAD_FMT, NIPQUAD(ip)); #endif } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) else if (STAP_ARG_family == AF_INET6) { struct in6_addr *ipv6 = (struct in6_addr *)(uintptr_t)STAP_ARG_addr; // We need to derefence the memory safely from the // address passed to us that contains the IPv6 address. // However, kderef()/kread() only handle data with a // size of 1, 2, 4, or 8. So, we'll use // kderef_buffer() which goes byte by byte. kderef_buffer(NULL, ipv6, sizeof(struct in6_addr)); #ifndef NIP6_FMT // kver >= 2.6.36 snprintf(STAP_RETVALUE, MAXSTRINGLEN, "%pI6", ipv6); #else snprintf(STAP_RETVALUE, MAXSTRINGLEN, NIP6_FMT, NIP6(*ipv6)); #endif } #endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */ else strncpy(STAP_RETVALUE, "*unknown address family*", MAXSTRINGLEN); #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) CATCH_DEREF_FAULT(); #endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */ %} /** * sfunction ip_ntop - Returns a string representation for an IPv4 address * * @addr: the IPv4 address represented as an integer */ function ip_ntop:string (addr:long) { return format_ipaddr(addr, %{ /* pure */ /* unprivileged */ AF_INET %}) } /* * Return the source IP address for a given sock. * * Note that the probes that use this function typically get a 'struct * sock' pointer, not a 'struct inet_sock' pointer. This is expected. * To use a 'struct sock' pointer, you typically call inet_sk() on the * pointer, which just returns the pointer (since the 1st member of * 'struct inet_sock' is a 'struct sock'). */ function __ip_sock_saddr:long (sock:long) { family = @cast(sock, "inet_sock", "kernel")->sk->__sk_common->skc_family if (family == %{ /* pure */ /* unprivileged */ AF_INET %}) { return @choose_defined(@cast(sock, "inet_sock")->inet_saddr, # kernel >= 2.6.33 @choose_defined(@cast(sock, "inet_sock")->saddr, # kernel >= 2.6.11 @cast(sock, "inet_sock", "kernel")->inet->saddr)) } %( CONFIG_IPV6 == "[ym]" %? else if (family == %{ /* pure */ /* unprivileged */ AF_INET6 %}) { return (&@cast(sock, "inet_sock", "kernel")->pinet6->saddr) } %) return 0 } /* return the destination IP address for a given sock */ function __ip_sock_daddr:long (sock:long) { family = @cast(sock, "inet_sock", "kernel")->sk->__sk_common->skc_family if (family == %{ /* pure */ /* unprivileged */ AF_INET %}) { return @choose_defined(@cast(sock, "inet_sock")->sk->__sk_common->skc_daddr, # kernel >= 2.6.38 @choose_defined(@cast(sock, "inet_sock")->inet_daddr, # kernel >= 2.6.33 @choose_defined(@cast(sock, "inet_sock")->daddr, # kernel >= 2.6.11 @cast(sock, "inet_sock", "kernel")->inet->daddr))) } %( CONFIG_IPV6 == "[ym]" %? else if (family == %{ /* pure */ /* unprivileged */ AF_INET6 %}) { return (&@cast(sock, "inet_sock", "kernel")->pinet6->daddr) } %) return 0 } /* return the IP address family for a given sock */ function __ip_sock_family:long (sock:long) { return (@cast(sock, "inet_sock", "kernel")->sk->__sk_common->skc_family) } /* Get the IP header from a sk_buff struct */ function __get_skb_iphdr:long(skb:long) %( kernel_v < "2.6.21" %? { iphdr = @cast(skb, "sk_buff")->nh->raw return iphdr } %: %{ /* pure */ struct sk_buff *skb; skb = (struct sk_buff *)(long)STAP_ARG_skb; /* as done by skb_network_header() */ #ifdef NET_SKBUFF_DATA_USES_OFFSET STAP_RETVALUE = (long)(kread(&(skb->head)) + kread(&(skb->network_header))); #else STAP_RETVALUE = (long)kread(&(skb->network_header)); #endif CATCH_DEREF_FAULT(); %} %) /* return the source next layer protocol for a given sk_buff structure */ function __ip_skb_proto:long (iphdr) { return @cast(iphdr, "iphdr")->protocol } /* return the source IP address for a given sk_buff structure */ function __ip_skb_saddr:long (iphdr) { return @cast(iphdr, "iphdr")->saddr } /* return the destination IP address for a given skb */ function __ip_skb_daddr:long (iphdr) { return @cast(iphdr, "iphdr")->daddr } systemtap-2.3/tapset/linux/ipmib-filter-default.stp000066400000000000000000000017051217430427200226100ustar00rootroot00000000000000/* * Copyright (C) 2009 IBM Corp. * Copyright (C) 2010 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. */ /** * sfunction ipmib_filter_key - Default filter function for ipmib.* probes * * @skb: pointer to the struct sk_buff * @op: value to be counted if @skb passes the filter * @SourceIsLocal: 1 is local operation and 0 is non-local operation * * This function is a default filter function. * The user can replace this function with their own. * The user-supplied filter function returns an index key based on the values * in @skb. * A return value of 0 means this particular @skb should be not be counted. */ function ipmib_filter_key:long (skb:long, op:long, SourceIsLocal:long) { if (!skb) return 0 return 1 } systemtap-2.3/tapset/linux/ipmib.stp000066400000000000000000000306611217430427200177060ustar00rootroot00000000000000/* * Copyright (C) 2009 IBM Corp. * Copyright (C) 2010 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. * * Version 1.0 wilder@us.ibm.com 2009-07-06 */ %{ /* pure */ #include #include #include #include #include %} /* Commented globals represent statistics that are not supported in this * version. */ global InReceives // global InHdrErrors // global InTooBigErrors global InNoRoutes global InAddrErrors global InUnknownProtos // global InTruncatedPkts global InDiscards // included counts of InHdrErrors InTruncatedPkts // global InDelivers %( kernel_v >= "2.6.24" %? global ForwDatagrams %) global OutRequests // global OutDiscards // global OutNoRoutes global ReasmTimeout global ReasmReqds //global ReasmOKs // global ReasmFails global FragOKs global FragFails // global FragCreates // global InMcastPkts // global OutMcastPkts // global InBcastPkts // global OutBcastPkts /** * sfunction ipmib_remote_addr - Get the remote ip address * @skb: pointer to a struct sk_buff * @SourceIsLocal: flag to indicate whether local operation * * Returns the remote ip address from @skb. */ function ipmib_remote_addr:long (skb:long, SourceIsLocal:long) { iphdr = __get_skb_iphdr(skb); if ( SourceIsLocal ) return ntohl(__ip_skb_daddr(iphdr)); return ntohl(__ip_skb_saddr(iphdr)); } /** * sfunction ipmib_local_addr - Get the local ip address * @skb: pointer to a struct sk_buff * @SourceIsLocal: flag to indicate whether local operation * * Returns the local ip address @skb. */ function ipmib_local_addr:long (skb:long, SourceIsLocal:long) { iphdr = __get_skb_iphdr(skb); if ( SourceIsLocal ) return ntohl(__ip_skb_saddr(iphdr)); return ntohl(__ip_skb_daddr(iphdr)); } /** * sfunction ipmib_tcp_remote_port - Get the remote tcp port * @skb: pointer to a struct sk_buff * @SourceIsLocal: flag to indicate whether local operation * * Returns the remote tcp port from @skb. */ function ipmib_tcp_remote_port:long (skb:long, SourceIsLocal:long) { th = _plunge_into_tcphdr(skb); if ( SourceIsLocal ) return __tcp_skb_dport(th); return __tcp_skb_sport(th); } /** * sfunction ipmib_tcp_local_port - Get the local tcp port * @skb: pointer to a struct sk_buff * @SourceIsLocal: flag to indicate whether local operation * * Returns the local tcp port from @skb. */ function ipmib_tcp_local_port:long (skb:long, SourceIsLocal:long) { th = _plunge_into_tcphdr(skb); if ( SourceIsLocal ) return __tcp_skb_sport(th); return __tcp_skb_dport(th); } /** * sfunction ipmib_get_proto - Get the protocol value * @skb: pointer to a struct sk_buff * * Returns the protocol value from @skb. */ function ipmib_get_proto:long (skb:long) { iphdr = __get_skb_iphdr(skb); return __ip_skb_proto(iphdr); } /* Internal functions */ /* * We can't assume the pointer to the sk_buff->transport_header * has been updated, so we must calculate the value from the network_header. * The caller must verify the skb is for a tcpip packet. */ function _plunge_into_tcphdr:long (skb:long) %{ struct sk_buff *skb = (struct sk_buff *)(long)STAP_ARG_skb; /* as done by skb_network_header() */ #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21) STAP_RETVALUE=(long)kread(&(skb->nh.raw)) + (long)sizeof(struct tcphdr); #else #ifdef NET_SKBUFF_DATA_USES_OFFSET STAP_RETVALUE=(long)kread(&(skb->network_header)) + (long)(kread(&(skb->head))) + (long)sizeof(struct tcphdr); #else STAP_RETVALUE=(long)kread(&(skb->network_header)) + (long)sizeof(struct tcphdr); #endif #endif CATCH_DEREF_FAULT(); %} function _ehostunreach:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = EHOSTUNREACH; %} function _enetunreach:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = ENETUNREACH; %} function _icmp_dest_unreach:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = ICMP_DEST_UNREACH; %} function _icmp_prot_unreach:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = ICMP_PROT_UNREACH; %} function _net_rx_drop:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = NET_RX_DROP; %} function _icmp_time_exceeded:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = ICMP_TIME_EXCEEDED; %} function _icmp_exc_fragtime:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = ICMP_EXC_FRAGTIME; %} function _rtn_multicast:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = RTN_MULTICAST; %} function _rtn_broadcast:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = RTN_BROADCAST; %} /** * probe ipmib.InReceives - Count an arriving packet * @skb: pointer to the struct sk_buff being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * ipmib_filter_key(). If the packet passes the filter is is * counted in the global @InReceives (equivalent to SNMP's MIB * IPSTATS_MIB_INRECEIVES) */ probe ipmib.InReceives=kernel.function("ip_rcv") { skb = $skb; op = 1; SourceIsLocal = 0; key = ipmib_filter_key(skb,op,SourceIsLocal); if ( key ) InReceives[key] += op; } /** * probe ipmib.InNoRoutes - Count an arriving packet with no matching socket * @skb: pointer to the struct sk_buff being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * ipmib_filter_key(). If the packet passes the filter is is * counted in the global @InNoRoutes (equivalent to SNMP's MIB * IPSTATS_MIB_INNOROUTES) */ probe ipmib.InNoRoutes=kernel.function("ip_route_input_noref").return!, kernel.function("ip_route_input_common").return!, kernel.function("ip_route_input").return { skb = $skb; op = 1; SourceIsLocal = 0; if ( $return != -_enetunreach()) next; key = ipmib_filter_key(skb,op,SourceIsLocal); if ( key ) InNoRoutes[key] += op; } /** * probe ipmib.InAddrErrors - Count arriving packets with an incorrect address * @skb: pointer to the struct sk_buff being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * ipmib_filter_key(). If the packet passes the filter is is * counted in the global @InAddrErrors (equivalent to SNMP's MIB * IPSTATS_MIB_INADDRERRORS) */ probe ipmib.InAddrErrors=kernel.function("ip_route_input_noref").return!, kernel.function("ip_route_input_common").return!, kernel.function("ip_route_input").return { skb = $skb; op = 1; SourceIsLocal = 0; if ( $return != -_ehostunreach()) next; key = ipmib_filter_key(skb,op,SourceIsLocal); if ( key ) InAddrErrors[key] += op; } /** * probe ipmib.InUnknownProtos - Count arriving packets with an unbound proto * @skb: pointer to the struct sk_buff being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * ipmib_filter_key(). If the packet passes the filter is is * counted in the global @InUnknownProtos (equivalent to SNMP's MIB * IPSTATS_MIB_INUNKNOWNPROTOS) */ /* icmp_send() is called by ip_local_deliver_finish() */ probe ipmib.InUnknownProtos=kernel.function("icmp_send") { skb = $skb_in; op = 1; SourceIsLocal = 0; if (($type==_icmp_dest_unreach())&&($code==_icmp_prot_unreach())){ key = ipmib_filter_key(skb,op,SourceIsLocal); if ( key ) InUnknownProtos[key] += op; } } /** * probe ipmib.InDiscards - Count discarded inbound packets * @skb: pointer to the struct sk_buff being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * ipmib_filter_key(). If the packet passes the filter is is * counted in the global @InDiscards (equivalent to SNMP's MIB * STATS_MIB_INDISCARDS) */ /* This stat combines all instances of IPSTATS_MIB_INHDRERRORS, IPSTATS_MIB_INTRUNCATEDPKTS, and STATS_MIB_INDISCARDS. */ probe ipmib.InDiscards=kernel.function("ip_rcv").return { skb = $skb; op = 1; SourceIsLocal = 0; if ( $return != _net_rx_drop() ) next; key = ipmib_filter_key(skb,op,SourceIsLocal); if ( key ) InDiscards[key] += op; } /** * probe ipmib.ForwDatagrams - Count forwarded packet * @skb: pointer to the struct sk_buff being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * ipmib_filter_key(). If the packet passes the filter is is * counted in the global @ForwDatagrams (equivalent to SNMP's MIB * IPSTATS_MIB_OUTFORWDATAGRAMS) */ %( kernel_v >= "2.6.24" %? probe ipmib.ForwDatagrams=kernel.function("ip_forward_finish") { skb = $skb; op = 1; SourceIsLocal = 0; key = ipmib_filter_key(skb,op,SourceIsLocal); if ( key ) ForwDatagrams[key] += op; } %) /** * probe ipmib.OutRequests - Count a request to send a packet * @skb: pointer to the struct sk_buff being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * ipmib_filter_key(). If the packet passes the filter is is * counted in the global @OutRequests (equivalent to SNMP's MIB * IPSTATS_MIB_OUTREQUESTS) */ probe ipmib.OutRequests=kernel.function("ip_output"), kernel.function("ip_mc_output") { skb = @choose_defined($skb, kernel_pointer($pskb)); op = 1; SourceIsLocal = 1; key = ipmib_filter_key(skb,op,SourceIsLocal); if ( key ) OutRequests[key] += op; } /** * probe ipmib.ReasmTimeout - Count Reassembly Timeouts * @skb: pointer to the struct sk_buff being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * ipmib_filter_key(). If the packet passes the filter is is * counted in the global @ReasmTimeout (equivalent to SNMP's MIB * IPSTATS_MIB_REASMTIMEOUT) */ probe ipmib.ReasmTimeout=kernel.function("icmp_send") { skb = $skb_in; op = 0; SourceIsLocal = 1; if(($type==_icmp_time_exceeded())&&($code==_icmp_exc_fragtime())){ key = ipmib_filter_key(skb,op,SourceIsLocal); if ( key ) ReasmTimeout[key] += op; } } /** * probe ipmib.ReasmReqds - Count number of packet fragments reassembly requests * @skb: pointer to the struct sk_buff being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * ipmib_filter_key(). If the packet passes the filter is is * counted in the global @ReasmReqds (equivalent to SNMP's MIB * IPSTATS_MIB_REASMREQDS) */ probe ipmib.ReasmReqds=kernel.function("ip_defrag") { skb = $skb; op = 0; SourceIsLocal = 1; key = ipmib_filter_key(skb,op,SourceIsLocal); if ( key ) ReasmReqds[key] += op; } /** * probe ipmib.FragOKs - Count datagram fragmented successfully * @skb: pointer to the struct sk_buff being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * ipmib_filter_key(). If the packet passes the filter is is * counted in the global @FragOKs (equivalent to SNMP's MIB * IPSTATS_MIB_FRAGOKS) */ probe ipmib.FragOKs=kernel.function("ip_fragment").return { skb = $skb; op = 1; SourceIsLocal = 1; if ( $return ) next key = ipmib_filter_key(skb,op,SourceIsLocal); if ( key ) FragOKs [key] += op; } /** * probe ipmib.FragFails - Count datagram fragmented unsuccessfully * @skb: pointer to the struct sk_buff being acted on * @op: Value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * ipmib_filter_key(). If the packet passes the filter is is * counted in the global @FragFails (equivalent to SNMP's MIB * IPSTATS_MIB_FRAGFAILS) */ probe ipmib.FragFails=kernel.function("ip_fragment").return { skb = $skb; op = 1; SourceIsLocal = 1; if (!$return ) next key = ipmib_filter_key(skb,op,SourceIsLocal); if ( key ) FragFails [key] += op; } function _rtn_unspec:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = RTN_UNSPEC; %} function _input_route_type:long (skb:long) { rt = @choose_defined(@cast(skb, "sk_buff")->_skb_dst, @choose_defined(@cast(skb, "sk_buff")->rtable, 0)) return rt ? @cast(rt, "rtable")->rt_type : _rtn_unspec() } function _output_route_type:long (skb:long) { rt = @choose_defined(@cast(skb, "sk_buff")->_skb_dst, @choose_defined(@cast(skb, "sk_buff")->dst, 0)) return rt ? @cast(rt, "rtable")->rt_type : _rtn_unspec() } systemtap-2.3/tapset/linux/irq.stp000066400000000000000000000131521217430427200173750ustar00rootroot00000000000000/* * Copyright (C) 2009 IBM Corp. * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. * * Version 1.0 prerna@linux.vnet.ibm.com 2009-10-28 * * Tracepoint based tapset for IRQs, Workqueues, etc * */ // Probes for workqueues. /** * probe workqueue.create - Creating a new workqueue * @wq_thread: task_struct of the workqueue thread * @cpu: cpu for which the worker thread is created */ probe workqueue.create = kernel.trace("workqueue_creation") ? { wq_thread = $wq_thread cpu = $cpu } /** * probe workqueue.insert - Queuing work on a workqueue * @wq_thread: task_struct of the workqueue thread * @work: work_struct* being queued * @work_func: pointer to handler function */ probe workqueue.insert = kernel.trace("workqueue_insertion") ? { wq_thread = $wq_thread work = $work work_func = $work->func } /** * probe workqueue.execute - Executing deferred work * @wq_thread: task_struct of the workqueue thread * @work: work_struct* being executed * @work_func: pointer to handler function */ probe workqueue.execute = kernel.trace("workqueue_execution") ? { wq_thread = $wq_thread work = $work work_func = $work->func } /** * probe workqueue.destroy - Destroying workqueue * @wq_thread: task_struct of the workqueue thread */ probe workqueue.destroy = kernel.trace("workqueue_destruction") ? { wq_thread = $wq_thread } // Probes for IRQ handlers. /** * probe irq_handler.entry - Execution of interrupt handler starting * @irq: irq number * @action: struct irqaction* for this interrupt num * @handler: interrupt handler function * @flags: Flags for IRQ handler * @flags_str: symbolic string representation of IRQ flags * @dev_name: name of device * @dev_id: Cookie to identify device * @next_irqaction: pointer to next irqaction for shared interrupts * @dir: pointer to the proc/irq/NN/name entry * @thread_fn: interrupt handler function for threaded interrupts * @thread: thread pointer for threaded interrupts * @thread_flags: Flags related to thread */ probe irq_handler.entry = kernel.trace("irq_handler_entry") ? { irq = $irq action = $action handler = @cast($action,"irqaction","kernel")->handler flags = @cast($action,"irqaction","kernel")->flags flags_str = irqflags_str(flags) dev_name = @cast($action,"irqaction","kernel")->name dev_id = @cast($action,"irqaction","kernel")->dev_id next_irqaction = @cast($action,"irqaction","kernel")->next dir = @cast($action,"irqaction","kernel")->dir thread_fn = @cast($action,"irqaction","kernel")->thread_fn thread = @cast($action,"irqaction","kernel")->thread thread_flags = @cast($action,"irqaction","kernel")->thread_flags } /** * probe irq_handler.exit - Execution of interrupt handler completed * @irq: interrupt number * @action: struct irqaction* * @ret: return value of the handler * @handler: interrupt handler function that was executed * @flags: flags for IRQ handler * @flags_str: symbolic string representation of IRQ flags * @dev_name: name of device * @dev_id: Cookie to identify device * @next_irqaction: pointer to next irqaction for shared interrupts * @dir: pointer to the proc/irq/NN/name entry * @thread_fn: interrupt handler function for threaded interrupts * @thread: thread pointer for threaded interrupts * @thread_flags: Flags related to thread */ probe irq_handler.exit = kernel.trace("irq_handler_exit") ? { irq = $irq action = $action ret = $ret handler = @cast($action,"irqaction","kernel")->handler flags = @cast($action,"irqaction","kernel")->flags flags_str = irqflags_str(flags) dev_name = @cast($action,"irqaction","kernel")->name dev_id = @cast($action,"irqaction","kernel")->dev_id next_irqaction = @cast($action,"irqaction","kernel")->next dir = @cast($action,"irqaction","kernel")->dir thread_fn = @cast($action,"irqaction","kernel")->thread_fn thread = @cast($action,"irqaction","kernel")->thread thread_flags = @cast($action,"irqaction","kernel")->thread_flags } // Softirq based probes. /** * probe softirq.entry - Execution of handler for a pending softirq starting * @h: struct softirq_action* for current pending softirq * @vec: softirq_action vector * @action: pointer to softirq handler just about to execute * @vec_nr: softirq vector number */ probe softirq.entry = kernel.trace("irq_softirq_entry") !, kernel.trace("softirq_entry") ? { # kernels < 2.6.37 h = @choose_defined($h, 0) vec = @choose_defined($vec, 0) action = (@defined($h) ? @cast($h,"softirq_action","kernel")->action : 0) # kernels >= 2.6.37 vec_nr = @choose_defined($vec_nr, 0) } /** * probe softirq.exit - Execution of handler for a pending softirq completed * @h: struct softirq_action* for just executed softirq * @vec: softirq_action vector * @action: pointer to softirq handler that just finished execution * @vec_nr: softirq vector number */ probe softirq.exit = kernel.trace("irq_softirq_exit") !, kernel.trace("softirq_exit") ? { # kernels < 2.6.37 h = @choose_defined($h, 0) vec = @choose_defined($vec, 0) action = (@defined($h) ? @cast($h,"softirq_action","kernel")->action : 0) # kernels >= 2.6.37 vec_nr = @choose_defined($vec_nr, 0) } systemtap-2.3/tapset/linux/kprocess.stp000066400000000000000000000065011217430427200204330ustar00rootroot00000000000000// kernel process tapset // Copyright (C) 2006 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // This family of probe points is used to probe process-related activities. // function _IS_ERR:long(ptr:long) %{ /* pure */ STAP_RETVALUE = IS_ERR((const void *)(long)STAP_ARG_ptr); %} /** * probe kprocess.create - Fires whenever a new process or thread is successfully created * @new_pid: The PID of the newly created process * @new_tid: The TID of the newly created task * * Context: * Parent of the created process. * * Fires whenever a new process is successfully created, either as a result of * fork (or one of its syscall variants), or a new kernel thread. */ probe kprocess.create = kernel.function("copy_process").return { task = $return if (_IS_ERR(task)) next new_pid = task_pid(task) new_tid = task_tid(task) } /** * probe kprocess.start - Starting new process * * Context: * Newly created process. * * Fires immediately before a new process begins execution. * */ probe kprocess.start = kernel.function("schedule_tail") { } /** * probe kprocess.exec - Attempt to exec to a new program * @filename: The path to the new executable * * Context: * The caller of exec. * * Fires whenever a process attempts to exec to a new program. */ probe kprocess.exec = kernel.function("do_execve"), kernel.function("compat_do_execve") ? { filename = kernel_string($filename) } /** * probe kprocess.exec_complete - Return from exec to a new program * @errno: The error number resulting from the exec * @success: A boolean indicating whether the exec was successful * * Context: * On success, the context of the new executable. * On failure, remains in the context of the caller. * * Fires at the completion of an exec call. */ probe kprocess.exec_complete = kernel.function("do_execve").return, kernel.function("compat_do_execve").return ? { errno = $return success = (errno >= 0) } /** * probe kprocess.exit - Exit from process * @code: The exit code of the process * * Context: * The process which is terminating. * * Fires when a process terminates. This will always be followed by a * kprocess.release, though the latter may be delayed if the process waits in a * zombie state. */ probe kprocess.exit = kernel.function("do_exit") { code = $code } /** * probe kprocess.release - Process released * @task: A task handle to the process being released * @released_pid: PID of the process being released * @released_tid: TID of the task being released * @pid: Same as @released_pid for compatibility (deprecated) * * Context: * The context of the parent, if it wanted notification of this process' * termination, else the context of the process itself. * * Fires when a process is released from the kernel. This always follows a * kprocess.exit, though it may be delayed somewhat if the process waits in a * zombie state. */ probe kprocess.release = kernel.function("release_task") { task = $p %(systemtap_v <= "1.7" %? pid = task_pid($p) %) released_pid = task_pid($p) released_tid = task_tid($p) } systemtap-2.3/tapset/linux/kretprobe.stp000066400000000000000000000035151217430427200206010ustar00rootroot00000000000000// kretprobe data tapset // Copyright (C) 2009, 2011 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // This is an internally-used tapset for sharing data between kretprobe // entry / return handlers. See the function // dwarf_var_expanding_visitor::gen_kretprobe_saved_return // for details. // // Note, invalid calls are silently ignored... %{ static void * _kretprobe_data(struct kretprobe_instance *pi, size_t offset, size_t length) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) size_t end = offset + length; if (end > offset && pi && end <= pi->rp->data_size) return &pi->data[offset]; #endif return NULL; } %} function _get_kretprobe_long:long(i:long) %{ /* pure */ size_t offset = STAP_ARG_i * sizeof(int64_t); const int64_t *data = _kretprobe_data(CONTEXT->ips.krp.pi, offset, sizeof(int64_t)); STAP_RETVALUE = data ? *data : 0; %} function _set_kretprobe_long(i:long, value:long) %{ /* impure */ size_t offset = STAP_ARG_i * sizeof(int64_t); int64_t *data = _kretprobe_data(CONTEXT->ips.krp.pi, offset, sizeof(int64_t)); if (data) *data = STAP_ARG_value; %} function _get_kretprobe_string:string(i:long) %{ /* pure */ size_t offset = CONTEXT->ips.krp.pi_longs * sizeof(int64_t) + STAP_ARG_i * MAXSTRINGLEN; const char *data = _kretprobe_data(CONTEXT->ips.krp.pi, offset, MAXSTRINGLEN); strlcpy(STAP_RETVALUE, data ?: "", MAXSTRINGLEN); %} function _set_kretprobe_string(i:long, value:string) %{ /* impure */ size_t offset = CONTEXT->ips.krp.pi_longs * sizeof(int64_t) + STAP_ARG_i * MAXSTRINGLEN; char *data = _kretprobe_data(CONTEXT->ips.krp.pi, offset, MAXSTRINGLEN); if (data) strlcpy(data, STAP_ARG_value, MAXSTRINGLEN); %} systemtap-2.3/tapset/linux/linuxmib-filter-default.stp000066400000000000000000000015541217430427200233410ustar00rootroot00000000000000/* * Copyright (C) 2009 IBM Corp. * Copyright (C) 2010 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. */ /** * sfunction linuxmib_filter_key - Default filter function for linuxmib.* probes * * @sk: pointer to the struct sock * @op: value to be counted if @sk passes the filter * * This function is a default filter function. * The user can replace this function with their own. * The user-supplied filter function returns an index key based on the values * in @sk. * A return value of 0 means this particular @sk should be not be counted. */ function linuxmib_filter_key:long (sk:long, op:long) { if (!sk) return 0 return 1 } systemtap-2.3/tapset/linux/linuxmib.stp000066400000000000000000000066011217430427200204320ustar00rootroot00000000000000/* * Copyright (C) 2009 IBM Corp. * Copyright (C) 2010 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. * * Version 1.0 wilder@us.ibm.com 2009-07-06 */ global DelayedACKs /* LINUX_MIB_DELAYEDACKS */ global ListenOverflows /* LINUX_MIB_LISTENOVERFLOWS */ global ListenDrops /* LINUX_MIB_LISTENDROPS */ global TCPMemoryPressures /* LINUX_MIB_TCPMEMORYPRESSURES */ /** * probe linuxmib.DelayedACKs - Count of delayed acks * @sk: Pointer to the struct sock being acted on * @op: Value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * linuxmib_filter_key(). If the packet passes the filter is is * counted in the global @DelayedACKs (equivalent to SNMP's MIB * LINUX_MIB_DELAYEDACKS) */ global indelack_timer probe linuxmib.DelayedACKs = _linuxmib.DelayedACKs.* {} probe _linuxmib.DelayedACKs.A = kernel.function("tcp_send_ack") { sk=$sk if ( !indelack_timer[sk] ) next op=1 key = linuxmib_filter_key(sk,op); if ( key ) DelayedACKs[key] += op; } probe _linuxmib.DelayedACKs.B = kernel.function("tcp_delack_timer") { sk=$data indelack_timer[sk]=1 op=0 } probe _linuxmib.DelayedACKs.C = kernel.function("tcp_delack_timer").return { sk=$data indelack_timer[sk]=0; op=0 } /** * probe linuxmib.ListenOverflows - Count of times a listen queue overflowed * @sk: Pointer to the struct sock being acted on * @op: Value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * linuxmib_filter_key(). If the packet passes the filter is is * counted in the global @ListenOverflows (equivalent to SNMP's MIB * LINUX_MIB_LISTENOVERFLOWS) */ probe linuxmib.ListenOverflows=kernel.function("tcp_v4_syn_recv_sock").return { sk = $sk if ( $return ) next if ( $sk->sk_ack_backlog <= $sk->sk_max_ack_backlog ) next op = 1; key = linuxmib_filter_key(sk,op); if ( key ) ListenOverflows[key] += op; } /** * probe linuxmib.ListenDrops - Count of times conn request that were dropped * @sk: Pointer to the struct sock being acted on * @op: Value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * linuxmib_filter_key(). If the packet passes the filter is is * counted in the global @ListenDrops (equivalent to SNMP's MIB * LINUX_MIB_LISTENDROPS) */ probe linuxmib.ListenDrops=kernel.function("tcp_v4_syn_recv_sock").return { sk = $sk if ( $return ) next op = 1; key = linuxmib_filter_key(sk,op); if ( key ) ListenDrops[key] += op; } /** * probe linuxmib.TCPMemoryPressures - Count of times memory pressure was used * @sk: Pointer to the struct sock being acted on * @op: Value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * linuxmib_filter_key(). If the packet passes the filter is is * counted in the global @TCPMemoryPressures (equivalent to SNMP's MIB * LINUX_MIB_TCPMEMORYPRESSURES) */ probe linuxmib.TCPMemoryPressures=kernel.function("tcp_enter_memory_pressure") { sk = @choose_defined($sk, 0) op = 1; if ( $tcp_memory_pressure ) next key = linuxmib_filter_key(sk,op); if ( key ) TCPMemoryPressures[key] += op; } systemtap-2.3/tapset/linux/logging.stp000066400000000000000000000040371217430427200202320ustar00rootroot00000000000000// logging tapset // Copyright (C) 2005-2011 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /** * sfunction ftrace - Send a message to the ftrace ring-buffer * * @msg: The formatted message string * * Description: If the ftrace ring-buffer is configured & available, * see /debugfs/tracing/trace for the message. Otherwise, the * message may be quietly dropped. An implicit end-of-line is added. */ function ftrace (msg:string) %{ #ifdef STAPCONF_TRACE_PRINTK static char *fmt = "%s\n"; trace_printk (fmt, STAP_ARG_msg); /* The "fmt" is designed to be non __builtin_constant_p(), so as to defeat trace_printk -> __trace_bprintk optimization. That's because bprintk doesn't save the incoming strings, only their addresses. */ #endif %} /** * sfunction printk - Send a message to the kernel trace buffer * * @level: an integer for the severity level (0=KERN_EMERG ... 7=KERN_DEBUG) * @msg: The formatted message string * * Description: Print a line of text to the kernel dmesg/console with the * given severity. An implicit end-of-line is added. This function may * not be safely called from all kernel probe contexts, so is restricted * to guru mode only. */ function printk (level:long,msg:string) %{ /* guru */ printk (STAP_ARG_level == 0 ? KERN_EMERG "%s\n": STAP_ARG_level == 1 ? KERN_ALERT "%s\n": STAP_ARG_level == 2 ? KERN_CRIT "%s\n": STAP_ARG_level == 3 ? KERN_ERR "%s\n": STAP_ARG_level == 4 ? KERN_WARNING "%s\n": STAP_ARG_level == 5 ? KERN_NOTICE "%s\n": STAP_ARG_level == 6 ? KERN_INFO "%s\n": STAP_ARG_level == 7 ? KERN_DEBUG "%s\n": #ifdef KERN_DEFAULT KERN_DEFAULT "%s\n" #else KERN_INFO "%s\n" #endif , STAP_ARG_msg); %} systemtap-2.3/tapset/linux/memory.stp000066400000000000000000000426211217430427200201150ustar00rootroot00000000000000// memory/vm related tapset // Copyright (C) 2005, 2006 IBM Corp. // Copyright (C) 2006 Intel Corporation. // Copyright (C) 2010 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // This family of probe points is used to probe memory-related events. // %{ #include %} global VM_FAULT_OOM=0, VM_FAULT_SIGBUS=1, VM_FAULT_MINOR=2, VM_FAULT_MAJOR=3 global VM_FAULT_NOPAGE=4, VM_FAULT_LOCKED=5, VM_FAULT_ERROR=6 global FAULT_FLAG_WRITE=1 /** * sfunction vm_fault_contains - Test return value for page fault reason * * @value: the fault_type returned by vm.page_fault.return * @test: the type of fault to test for (VM_FAULT_OOM or similar) */ function vm_fault_contains:long (value:long, test:long) %{ int res; switch (STAP_ARG_test){ case 0: res = STAP_ARG_value & VM_FAULT_OOM; break; case 1: res = STAP_ARG_value & VM_FAULT_SIGBUS; break; #if defined(VM_FAULT_MINOR) && VM_FAULT_MINOR != 0 case 2: /* VM_FAULT_MINOR infered by that flags off */ res = !((VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_MAJOR) & STAP_ARG_value); break; #else case 2: res = STAP_ARG_value == VM_FAULT_MINOR; break; #endif case 3: res = STAP_ARG_value & VM_FAULT_MAJOR; break; #ifdef VM_FAULT_NOPAGE case 4: res = STAP_ARG_value & VM_FAULT_NOPAGE; break; #endif #ifdef VM_FAULT_LOCKED case 5: res = STAP_ARG_value & VM_FAULT_LOCKED; break; #endif #ifdef VM_FAULT_ERROR case 6: res = STAP_ARG_value & VM_FAULT_ERROR; break; #endif default: res = 0; break; } STAP_RETVALUE = (res != 0); return; %} /** * probe vm.pagefault - Records that a page fault occurred * * @name: name of the probe point * @address: the address of the faulting memory access; i.e. the address that caused the page fault * @write_access: indicates whether this was a write or read access; 1 indicates a write, * while 0 indicates a read * * Context: The process which triggered the fault */ probe vm.pagefault = kernel.function("__handle_mm_fault@mm/memory.c") ?, kernel.function("handle_mm_fault@mm/memory.c") ? { name = "pagefault" write_access = (@defined($flags) ? $flags & FAULT_FLAG_WRITE : $write_access) address = $address } /** * probe vm.pagefault.return - Indicates what type of fault occurred * * @name: name of the probe point * @fault_type: returns either * 0 (VM_FAULT_OOM) for out of memory faults, * 2 (VM_FAULT_MINOR) for minor faults, 3 (VM_FAULT_MAJOR) for * major faults, or 1 (VM_FAULT_SIGBUS) if the fault was neither OOM, minor fault, * nor major fault. */ probe vm.pagefault.return = kernel.function("__handle_mm_fault@mm/memory.c").return ?, kernel.function("handle_mm_fault@mm/memory.c").return ? { name = "pagefault" fault_type = $return } /** * sfunction addr_to_node - Returns which node a given address belongs to within a NUMA system * * @addr: the address of the faulting memory access * * Description: This function accepts an address, and returns the * node that the given address belongs to in a NUMA system. */ function addr_to_node:long(addr:long) %{ /* pure */ int pfn = __pa(STAP_ARG_addr) >> PAGE_SHIFT; int nid; #ifdef for_each_online_node for_each_online_node(nid) #else for (nid=0; nidnode_start_pfn <= pfn && pfn < (NODE_DATA(nid)->node_start_pfn + NODE_DATA(nid)->node_spanned_pages) ) { STAP_RETVALUE = nid; break; } %} // Return whether a page to be copied is a zero page. function _IS_ZERO_PAGE:long(from:long, vaddr:long) %{ /* pure */ STAP_RETVALUE = (STAP_ARG_from == (long) ZERO_PAGE(STAP_ARG_vaddr)); %} /** * probe vm.write_shared - Attempts at writing to a shared page * * @name: name of the probe point * @address: the address of the shared write * * Context: * The context is the process attempting the write. * * Fires when a process attempts to write to a shared page. * If a copy is necessary, this will be followed by a * vm.write_shared_copy. */ probe vm.write_shared = kernel.function("do_wp_page") { name = "write_shared" address = $address } /** * probe vm.write_shared_copy - Page copy for shared page write * * @name: Name of the probe point * @address: The address of the shared write * @zero: boolean indicating whether it is a zero page * (can do a clear instead of a copy) * * Context: * The process attempting the write. * * Fires when a write to a shared page requires a page copy. This is * always preceded by a vm.write_shared. */ probe vm.write_shared_copy = kernel.function("cow_user_page") ?, kernel.function("copy_cow_page") ? { name = "write_shared_copy" if (@defined($va)) { address = $va zero = _IS_ZERO_PAGE($src, $va); } else { address = $address zero = _IS_ZERO_PAGE($from, $address); } } /** * probe vm.mmap - Fires when an mmap is requested * * @name: name of the probe point * @address: the requested address * @length: the length of the memory segment * * Context: * The process calling mmap. */ probe vm.mmap = kernel.function("vm_mmap")?, kernel.function("do_mmap")?, kernel.function("do_mmap2")? { name = "mmap" address = $addr length = $len } /** * probe vm.munmap - Fires when an munmap is requested * * @name: name of the probe point * @address: the requested address * @length: the length of the memory segment * * Context: * The process calling munmap. */ probe vm.munmap = kernel.function("do_munmap") { name = "munmap" address = $start length = $len } /** * probe vm.brk - Fires when a brk is requested (i.e. the heap will be resized) * * @name: name of the probe point * @address: the requested address * @length: the length of the memory segment * * Context: * The process calling brk. */ probe vm.brk = kernel.function("do_brk") { name = "brk" address = $addr length = $len } /** * probe vm.oom_kill - Fires when a thread is selected for termination by the OOM killer * * @name: name of the probe point * @task: the task being killed * * Context: * The process that tried to consume excessive memory, and thus * triggered the OOM. */ probe vm.oom_kill = kernel.function("oom_kill_process") !, kernel.function("__oom_kill_task") { name = "oom_kill" task = $p } function GFP_KERNEL:long() %{ /* pure */ /* unprivileged */ STAP_RETVALUE = GFP_KERNEL; %} function __gfp_flag_str:string(gfp_flag:long) %{ long gfp_flag = STAP_ARG_gfp_flag; STAP_RETVALUE[0] = '\0'; /* Older kernels < 2.6.32 didn't have some of these GFP defines yet. */ #ifndef __GFP_DMA32 #define __GFP_DMA32 ((__force gfp_t)0x04u) #endif #ifndef GFP_DMA32 #define GFP_DMA32 __GFP_DMA32 #endif #ifndef __GFP_MOVABLE #define __GFP_MOVABLE ((__force gfp_t)0x08u) /* Page is movable */ #endif #ifndef GFP_ZONEMASK #define GFP_ZONEMASK (__GFP_DMA|__GFP_HIGHMEM|__GFP_DMA32|__GFP_MOVABLE) #endif #ifndef __GFP_NOTRACK #ifdef CONFIG_KMEMCHECK #define __GFP_NOTRACK ((__force gfp_t)0x200000u) /* Don't track with kmemcheck */ #else #define __GFP_NOTRACK ((__force gfp_t)0) #endif #endif #ifndef __GFP_THISNODE #define __GFP_THISNODE ((__force gfp_t)0x40000u) #endif #ifndef __GFP_RECLAIMABLE #define __GFP_RECLAIMABLE ((__force gfp_t)0x80000u) #endif #ifndef __GFP_ZERO #define __GFP_ZERO ((__force gfp_t)0x8000u) #endif #ifndef __GFP_NOMEMALLOC #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) #endif #ifndef __GFP_HARDWALL #define __GFP_HARDWALL ((__force gfp_t)0x20000u) #endif #ifndef GFP_TEMPORARY #define GFP_TEMPORARY (__GFP_WAIT | __GFP_IO | __GFP_FS | \ __GFP_RECLAIMABLE) #endif #ifndef GFP_HIGHUSER_MOVABLE #define GFP_HIGHUSER_MOVABLE (__GFP_WAIT | __GFP_IO | __GFP_FS | \ __GFP_HARDWALL | __GFP_HIGHMEM | \ __GFP_MOVABLE) #endif #ifndef GFP_THISNODE #ifdef CONFIG_NUMA #define GFP_THISNODE (__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY) #else #define GFP_THISNODE ((__force gfp_t)0) #endif #endif /* Macro for GFP Bitmasks. */ /* The resulted GFP_FLAGS may be either single or concatenation of the multiple bitmasks. */ #define __GFP_BITMASKS(FLAG) if(gfp_flag & FLAG) { if(STAP_RETVALUE[0] != '\0') \ strlcat(STAP_RETVALUE, " | "#FLAG, MAXSTRINGLEN); \ else strlcat(STAP_RETVALUE, #FLAG, MAXSTRINGLEN); } /* Macro for Composite Flags. */ /* Each Composite GFP_FLAG is the combination of multiple bitmasks. */ #define __GFP_COMPOSITE_FLAG(FLAG) if(gfp_flag == FLAG) { \ strlcat(STAP_RETVALUE, #FLAG, MAXSTRINGLEN); return; } /* Composite GFP FLAGS of the BitMasks. */ __GFP_COMPOSITE_FLAG(GFP_ZONEMASK) __GFP_COMPOSITE_FLAG(GFP_ATOMIC) __GFP_COMPOSITE_FLAG(GFP_NOIO) __GFP_COMPOSITE_FLAG(GFP_NOFS) __GFP_COMPOSITE_FLAG(GFP_KERNEL) __GFP_COMPOSITE_FLAG(GFP_TEMPORARY) __GFP_COMPOSITE_FLAG(GFP_USER) __GFP_COMPOSITE_FLAG(GFP_HIGHUSER) __GFP_COMPOSITE_FLAG(GFP_HIGHUSER_MOVABLE) __GFP_COMPOSITE_FLAG(GFP_THISNODE) __GFP_COMPOSITE_FLAG(GFP_DMA) __GFP_COMPOSITE_FLAG(GFP_DMA32) /* GFP BitMasks */ __GFP_BITMASKS(__GFP_DMA) __GFP_BITMASKS(__GFP_HIGHMEM) __GFP_BITMASKS(__GFP_MOVABLE) __GFP_BITMASKS(__GFP_WAIT) __GFP_BITMASKS(__GFP_HIGH) __GFP_BITMASKS(__GFP_IO) __GFP_BITMASKS(__GFP_FS) __GFP_BITMASKS(__GFP_COLD) __GFP_BITMASKS(__GFP_NOWARN) __GFP_BITMASKS(__GFP_REPEAT) __GFP_BITMASKS(__GFP_NOFAIL) __GFP_BITMASKS(__GFP_COMP) __GFP_BITMASKS(__GFP_ZERO) __GFP_BITMASKS(__GFP_NOMEMALLOC) __GFP_BITMASKS(__GFP_HARDWALL) __GFP_BITMASKS(__GFP_THISNODE) __GFP_BITMASKS(__GFP_RECLAIMABLE) __GFP_BITMASKS(__GFP_NOTRACK) #undef __GFP_BITMASKS #undef __GFP_COMPOSITE_FLAG %} /* The Formal Parameters will be displayed if available, otherwise \ "0" or "unknown" will be displayed */ probe __vm.kmalloc.tp = kernel.trace("kmalloc") { call_site = $call_site caller_function = symname(call_site) bytes_req = $bytes_req bytes_alloc = $bytes_alloc gfp_flags = $gfp_flags gfp_flag_name = __gfp_flag_str($gfp_flags) ptr = $ptr } /* * It is unsafe to invoke __builtin_return_address() presently (to get * call_site for kprobe based probes) and that it can be improved * later when fix for bugs bz#6961 and bz#6580 is available. */ probe __vm.kmalloc.kp = kernel.function("kmem_cache_alloc_notrace").return !, kernel.function("kmem_cache_alloc").return { call_site = 0 caller_function = "unknown" // Note that 'bytes_req' could be wrong. By the time // kmem_cache_alloc* gets called the requested size could have // rounded up to the nearest cache alloc size. if (@defined($s)) { bytes_req = $s->size bytes_alloc = $s->size } else if (@defined($cachep->buffer_size)) { bytes_req = $cachep->buffer_size bytes_alloc = $cachep->buffer_size } else { bytes_req = $cachep->objsize bytes_alloc = $cachep->objsize } if (@defined($gfpflags)) { gfp_flags = $gfpflags gfp_flag_name = __gfp_flag_str($gfpflags) } else { gfp_flags = $flags gfp_flag_name = __gfp_flag_str($flags) } ptr = $return } /** * probe vm.kmalloc - Fires when kmalloc is requested * * @name: name of the probe point * @call_site: address of the kmemory function * @caller_function: name of the caller function * @bytes_req: requested Bytes * @bytes_alloc: allocated Bytes * @gfp_flags: type of kmemory to allocate * @gfp_flag_name: type of kmemory to allocate (in String format) * @ptr: pointer to the kmemory allocated */ probe vm.kmalloc = __vm.kmalloc.tp !, __vm.kmalloc.kp { name = "kmalloc" } probe __vm.kmem_cache_alloc.tp = kernel.trace("kmem_cache_alloc") { call_site = $call_site caller_function = symname(call_site) bytes_req = $bytes_req bytes_alloc = $bytes_alloc gfp_flags = $gfp_flags gfp_flag_name = __gfp_flag_str($gfp_flags) ptr = $ptr } probe __vm.kmem_cache_alloc.kp = kernel.function("kmem_cache_alloc").return { call_site = 0 caller_function = "unknown" // Note that 'bytes_req' could be wrong. By the time // kmem_cache_alloc* gets called the requested size could have // rounded up to the nearest cache alloc size. if (@defined($s)) { bytes_req = $s->size bytes_alloc = $s->size } else if (@defined($cachep->buffer_size)) { bytes_req = $cachep->buffer_size bytes_alloc = $cachep->buffer_size } else { bytes_req = $cachep->objsize bytes_alloc = $cachep->objsize } if (@defined($gfpflags)) { gfp_flags = $gfpflags gfp_flag_name = __gfp_flag_str($gfpflags) } else { gfp_flags = $flags gfp_flag_name = __gfp_flag_str($flags) } ptr = $return } /** * probe vm.kmem_cache_alloc - Fires when kmem_cache_alloc is requested * * @name: name of the probe point * @call_site: address of the function calling this kmemory function. * @caller_function: name of the caller function. * @bytes_req: requested Bytes * @bytes_alloc: allocated Bytes * @gfp_flags: type of kmemory to allocate * @gfp_flag_name: type of kmemory to allocate(in string format) * @ptr: pointer to the kmemory allocated */ probe vm.kmem_cache_alloc = __vm.kmem_cache_alloc.tp !, __vm.kmem_cache_alloc.kp { name = "kmem_cache_alloc" } probe __vm.kmalloc_node.tp = kernel.trace("kmalloc_node") ? { call_site = $call_site caller_function = symname(call_site) bytes_req = $bytes_req bytes_alloc = $bytes_alloc gfp_flags = $gfp_flags gfp_flag_name = __gfp_flag_str($gfp_flags) ptr = $ptr } probe __vm.kmalloc_node.kp = kernel.function("kmalloc_node").return ? { call_site = 0 caller_function = "unknown" bytes_req = $size bytes_alloc = bytes_req // pretend they are always the same # Unfortunately, on i686 f11 (2.6.29.4-167.fc11.i686.PAE), we # can't see the '$flags' argument (even though we can see the # '$size' argument above). Note that we can see the '$flags' # argument on x86_64 f11 (2.6.29.4-167.fc11.x86_64). So, the # best we can do here is just use 0 when $flags isn't defined. gfp_flags = @choose_defined($flags, 0) gfp_flag_name = __gfp_flag_str(@choose_defined($flags, 0)) ptr = $return } /** * probe vm.kmalloc_node - Fires when kmalloc_node is requested * * @name: name of the probe point * @call_site: address of the function caling this kmemory function * @caller_function: name of the caller function * @bytes_req: requested Bytes * @bytes_alloc: allocated Bytes * @gfp_flags: type of kmemory to allocate * @gfp_flag_name: type of kmemory to allocate(in string format) * @ptr: pointer to the kmemory allocated */ probe vm.kmalloc_node = __vm.kmalloc_node.tp !, __vm.kmalloc_node.kp ? { name = "kmalloc_node" } probe __vm.kmem_cache_alloc_node.tp = kernel.trace("kmem_cache_alloc_node") ? { call_site = $call_site caller_function = symname(call_site) bytes_req = $bytes_req bytes_alloc = $bytes_alloc gfp_flags = $gfp_flags gfp_flag_name = __gfp_flag_str($gfp_flags) ptr = $ptr } probe __vm.kmem_cache_alloc_node.kp = kernel.function("kmem_cache_alloc_node").return ? { call_site = 0 caller_function = "unknown" // Note that 'bytes_req' could be wrong. By the time // kmem_cache_alloc* gets called the requested size could have // rounded up to the nearest cache alloc size. if (@defined($s)) { bytes_req = $s->size bytes_alloc = $s->size } else if (@defined($cachep->buffer_size)) { bytes_req = $cachep->buffer_size bytes_alloc = $cachep->buffer_size } else { bytes_req = $cachep->objsize bytes_alloc = $cachep->objsize } // kmem_cache_alloc_node() doesn't get a flags argument. But, // internally it uses GFP_KERNEL(). gfp_flags = GFP_KERNEL() gfp_flag_name = __gfp_flag_str(gfp_flags) ptr = $return } /** * probe vm.kmem_cache_alloc_node - Fires when kmem_cache_alloc_node is requested * * @name: name of the probe point * @call_site: address of the function calling this kmemory function * @caller_function: name of the caller function * @bytes_req: requested Bytes * @bytes_alloc: allocated Bytes * @gfp_flags: type of kmemory to allocate * @gfp_flag_name: type of kmemory to allocate(in string format) * @ptr: pointer to the kmemory allocated */ probe vm.kmem_cache_alloc_node = __vm.kmem_cache_alloc_node.tp !, __vm.kmem_cache_alloc_node.kp ? { name = "kmem_cache_alloc_node" } probe __vm.kfree.tp = kernel.trace("kfree") { call_site = $call_site caller_function = symname(call_site) ptr = $ptr } probe __vm.kfree.kp = kernel.function("kfree").return { call_site = 0 caller_function = "unknown" ptr = @choose_defined($x, $objp) } /** * probe vm.kfree - Fires when kfree is requested * * @name: name of the probe point * @call_site: address of the function calling this kmemory function * @caller_function: name of the caller function. * @ptr: pointer to the kmemory allocated which is returned by kmalloc */ probe vm.kfree = __vm.kfree.tp !, __vm.kfree.kp { name = "kfree" } probe __vm.kmem_cache_free.tp = kernel.trace("kmem_cache_free") { call_site = $call_site caller_function = symname(call_site) ptr = $ptr } probe __vm.kmem_cache_free.kp = kernel.function("kmem_cache_free").return { call_site = 0 caller_function = "unknown" ptr = @choose_defined($x, $objp) } /** * probe vm.kmem_cache_free - Fires when kmem_cache_free is requested * * @name: Name of the probe point * @call_site: Address of the function calling this kmemory function * @caller_function: Name of the caller function. * @ptr: Pointer to the kmemory allocated which is returned by kmem_cache */ probe vm.kmem_cache_free = __vm.kmem_cache_free.tp !, __vm.kmem_cache_free.kp { name = "kmem_cache_free" } systemtap-2.3/tapset/linux/nd_syscalls.stp000066400000000000000000003675301217430427200211340ustar00rootroot00000000000000// syscalls tapset part 1 [A-M] // Copyright (C) 2005 IBM Corp. // Copyright (C) 2005, 2006, 2007, 2010 Red Hat Inc. // Copyright (C) 2007 Quentin Barnes. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /* * nd_syscalls.stp is a copy of syscalls.stp, modified to refer to * function arguments by number rather than name, so that this tapset * can be used even when the probed kernel lacks debugging information. */ /* Each syscall returns the calls parameters. In addition, the following * variables are set: * * name - generally the syscall name minus the "sys_". * * argstr - a string containing the decoded args in an easy-to-read format. * It doesn't need to contain everything, but should have all the * important args. Set in entry probes only. Values enclosed in * square brackets are user-space pointers. Values in curly * braces are decoded structs. * * retstr - a string containing the return value in an easy-to-read format. * Set in return probes only. */ # accept _____________________________________________________ # long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, # int __user *upeer_addrlen) %( kernel_v >= "2.6.28" %? probe nd_syscall.accept = kprobe.function("sys_accept4") ? %: probe nd_syscall.accept = kprobe.function("sys_accept") ? %) { name = "accept" // sockfd = $fd // addr_uaddr = $upeer_sockaddr // addrlen_uaddr = $upeer_addrlen // argstr = sprintf("%d, %p, %p", $fd, $upeer_sockaddr, $upeer_addrlen) asmlinkage() sockfd = int_arg(1) addr_uaddr = pointer_arg(2) addrlen_uaddr = pointer_arg(3) flags = 0 # 'flag_str should have been 'flags_str'. Deprecate the old name. %(systemtap_v <= "1.4" %? flag_str = "0" %) flags_str = "0" argstr = sprintf("%d, %p, %p, %s", sockfd, addr_uaddr, addrlen_uaddr, flags_str) } %( kernel_v >= "2.6.28" %? probe nd_syscall.accept.return = kprobe.function("sys_accept4").return ? %: probe nd_syscall.accept.return = kprobe.function("sys_accept").return ? %) { name = "accept" retstr = returnstr(1) } # access _____________________________________________________ # long sys_access(const char __user * filename, int mode) probe nd_syscall.access = kprobe.function("sys_access") ? { name = "access" // pathname = user_string($filename) // mode = $mode // mode_str = _access_mode_str($mode) // argstr = sprintf("%s, %s", user_string_quoted($filename), mode_str) asmlinkage() pathname = user_string_quoted(pointer_arg(1)) mode = int_arg(2) mode_str = _access_mode_str(mode) argstr = sprintf("%s, %s", user_string_quoted(pointer_arg(1)), mode_str) } probe nd_syscall.access.return = kprobe.function("sys_access").return ? { name = "access" retstr = returnstr(1) } # acct _______________________________________________________ # long sys_acct(const char __user *name) probe nd_syscall.acct = kprobe.function("sys_acct") ? { name = "acct" // filename = user_string($name) // argstr = user_string_quoted($name) asmlinkage() filename = user_string_quoted(pointer_arg(1)) argstr = user_string_quoted(pointer_arg(1)) } probe nd_syscall.acct.return = kprobe.function("sys_acct").return ? { name = "acct" retstr = returnstr(1) } # add_key ____________________________________________________ # long sys_add_key(const char __user *_type, # const char __user *_description, # const void __user *_payload, # size_t plen, # key_serial_t ringid) # probe nd_syscall.add_key = kprobe.function("sys_add_key") ? { name = "add_key" // type_uaddr = $_type // description_auddr = $_description // payload_uaddr = $_payload // plen = $plen // ringid = $ringid // argstr = sprintf("%s, %s, %s, %d, %d", // user_string_quoted($_type), // user_string_quoted($_description), // text_strn(user_string($_payload), syscall_string_trunc, 1), // $plen, $ringid) asmlinkage() type_uaddr = pointer_arg(1) description_uaddr = pointer_arg(2) payload_uaddr = pointer_arg(3) plen = ulong_arg(4) ringid = int_arg(5) argstr = sprintf("%s, %s, %s, %d, %d", user_string_quoted(type_uaddr), user_string_quoted(description_uaddr), user_string_n_quoted(payload_uaddr, syscall_string_trunc), plen, ringid) } probe nd_syscall.add_key.return = kprobe.function("sys_add_key").return ? { name = "add_key" retstr = returnstr(1) } # adjtimex ___________________________________________________ # long sys_adjtimex(struct timex __user *txc_p) probe nd_syscall.adjtimex = kprobe.function("sys_adjtimex") ? { name = "adjtimex" /* * buf_offset = __uget_timex_m($txc_p, 1) * buf_freq = __uget_timex_m($txc_p, 2) * buf_maxerror = __uget_timex_m($txc_p, 3) * buf_esterror = __uget_timex_m($txc_p, 4) * buf_status = __uget_timex_m($txc_p, 5) * buf_constant = __uget_timex_m($txc_p, 6) * buf_precision = __uget_timex_m($txc_p, 7) * buf_tolerance = __uget_timex_m($txc_p, 8) * buf_time_tv_sec = __uget_timex_m($txc_p, 9) * buf_time_tv_usec = __uget_timex_m($txc_p, 10) * buf_tick = __uget_timex_m($txc_p, 11) */ // argstr = sprintf("%p", $txc_p) asmlinkage() argstr = sprintf("%p", pointer_arg(1)) } probe nd_syscall.adjtimex.return = kprobe.function("sys_adjtimex").return ? { name = "adjtimex" // retstr = _adjtimex_return_str($return) retstr = _adjtimex_return_str(returnval()) } # long compat_sys_adjtimex(struct compat_timex __user *utp) probe nd_syscall.compat_adjtimex = kprobe.function("compat_sys_adjtimex") ? { name = "compat_adjtimex" // argstr = sprintf("%p", $utp) asmlinkage() argstr = sprintf("%p", pointer_arg(1)) } probe nd_syscall.compat_adjtimex.return = kprobe.function("compat_sys_adjtimex").return ? { name = "compat_adjtimex" retstr = returnstr(1) } # alarm ______________________________________________________ # unsigned long sys_alarm (unsigned int seconds) # long sys32_alarm(unsigned int seconds) # probe nd_syscall.alarm = kprobe.function("sys32_alarm") ?, kprobe.function("sys_alarm") ? { name = "alarm" // seconds = $seconds // argstr = sprint($seconds) asmlinkage() seconds = uint_arg(1) argstr = sprint(seconds) } probe nd_syscall.alarm.return = kprobe.function("sys32_alarm").return ?, kprobe.function("sys_alarm").return ? { name = "alarm" retstr = returnstr(1) } # bdflush ____________________________________________________ # long sys_bdflush(int func, long data) probe nd_syscall.bdflush = kprobe.function("sys_bdflush") ? { name = "bdflush" // func = $func // data = $data // if (($func >= 2) && ($func % 2 == 0)) // data_str = sprintf("%p", $data) // else // data_str = sprintf("%d", $data) asmlinkage() func = int_arg(1) data = long_arg(2) if ((func >= 2) && (func % 2 == 0)) data_str = sprintf("%p", data) else data_str = sprintf("%d", data) argstr = sprintf("%d, %s", func, data_str) } probe nd_syscall.bdflush.return = kprobe.function("sys_bdflush").return ? { name = "bdflush" retstr = returnstr(1) } # bind _______________________________________________________ # long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) probe nd_syscall.bind = kprobe.function("sys_bind") ? { name = "bind" // sockfd = $fd // my_addr_uaddr = $umyaddr // addrlen = $addrlen // argstr = sprintf("%d, %s, %d", $fd, _struct_sockaddr_u($umyaddr, $addrlen), $addrlen) asmlinkage() sockfd = int_arg(1) my_addr_uaddr = pointer_arg(2) addrlen = int_arg(3) argstr = sprintf("%d, %s, %d", sockfd, _struct_sockaddr_u(my_addr_uaddr, addrlen), addrlen) } probe nd_syscall.bind.return = kprobe.function("sys_bind").return ? { name = "bind" retstr = returnstr(1) } # brk ________________________________________________________ # unsigned long sys_brk(unsigned long brk) probe nd_syscall.brk = kprobe.function("ia64_brk") ?, kprobe.function("sys_brk") ? { name = "brk" // brk = $brk asmlinkage() brk = ulong_arg(1) argstr = sprintf("%p", brk) } probe nd_syscall.brk.return = kprobe.function("ia64_brk").return ?, kprobe.function("sys_brk").return ? { name = "brk" retstr = returnstr(1) } # capget _____________________________________________________ /* * NOTE * this is probably not a good function * to probe. The structures are always * changing. It also seems like it is * not really used. Cscope produced no * reference of this function in the * kernel (returned no callers). Perhaps * cap_get_proc / cap_set_proc are better * functions to export. */ # long sys_capget(cap_user_header_t header, cap_user_data_t dataptr) probe nd_syscall.capget = kprobe.function("sys_capget") ? { name = "capget" // header_uaddr = $header // data_uaddr = $dataptr // argstr = sprintf("%p, %p", $header, $dataptr) asmlinkage() header_uaddr = pointer_arg(1) data_uaddr = pointer_arg(2) argstr = sprintf("%p, %p", header_uaddr, data_uaddr) } probe nd_syscall.capget.return = kprobe.function("sys_capget").return ? { name = "capget" retstr = returnstr(1) } # capset _____________________________________________________ /* * NOTE * this is probably not a good function * to probe. The structures are always * changing. It also seems like it is * not really used. Cscope produced no * reference of this function in the * kernel (returned no callers). Perhaps * cap_get_proc / cap_set_proc are better * functions to export. */ # long sys_capset(cap_user_header_t header, const cap_user_data_t data) probe nd_syscall.capset = kprobe.function("sys_capset") ? { name = "capset" // header_uaddr = $header // data_uaddr = $data // argstr = sprintf("%p, %p", $header, $data) asmlinkage() header_uaddr = pointer_arg(1) data_uaddr = pointer_arg(2) argstr = sprintf("%p, %p", header_uaddr, data_uaddr) } probe nd_syscall.capset.return = kprobe.function("sys_capset").return ? { name = "capset" retstr = returnstr(1) } # chdir ______________________________________________________ # long sys_chdir(const char __user * filename) probe nd_syscall.chdir = kprobe.function("sys_chdir") ? { name = "chdir" // path = user_string($filename) // argstr = user_string_quoted($filename) asmlinkage() path = user_string_quoted(pointer_arg(1)) argstr = user_string_quoted(pointer_arg(1)) } probe nd_syscall.chdir.return = kprobe.function("sys_chdir").return ? { name = "chdir" retstr = returnstr(1) } # chmod ______________________________________________________ # long sys_chmod(const char __user * filename, mode_t mode) probe nd_syscall.chmod = kprobe.function("sys_chmod") ? { name = "chmod" // path = user_string($filename) // mode = $mode // argstr = sprintf("%s, %#o", user_string_quoted($filename), mode) asmlinkage() path = user_string_quoted(pointer_arg(1)) mode = uint_arg(2) argstr = sprintf("%s, %#o", user_string_quoted(pointer_arg(1)), mode) } probe nd_syscall.chmod.return = kprobe.function("sys_chmod").return ? { name = "chmod" retstr = returnstr(1) } # chown ______________________________________________________ # long sys_chown(const char __user * filename, uid_t user, gid_t group) probe nd_syscall.chown = kprobe.function("sys_chown") ? { name = "chown" // path = user_string($filename) // owner = __int32($user) // group = __int32($group) // argstr = sprintf("%s, %d, %d", user_string_quoted($filename), owner, group) asmlinkage() path = user_string_quoted(pointer_arg(1)) owner = __int32(uint_arg(2)) group = __int32(uint_arg(3)) argstr = sprintf("%s, %d, %d", user_string_quoted(pointer_arg(1)), owner, group) } probe nd_syscall.chown.return = kprobe.function("sys_chown").return ? { name = "chown" retstr = returnstr(1) } # chown16 ___________________________________________________ # long sys_chown16(const char __user * filename, old_uid_t user, # old_gid_t group) # probe nd_syscall.chown16 = kprobe.function("sys_chown16") ? { name = "chown16" // path = user_string($filename) // owner = __short($user) // group = __short($group) // argstr = sprintf("%s, %d, %d", user_string_quoted($filename), owner, group) asmlinkage() path = user_string_quoted(pointer_arg(1)) owner = __short(uint_arg(2)) group = __short(uint_arg(3)) argstr = sprintf("%s, %d, %d", user_string_quoted(pointer_arg(1)), owner, group) } probe nd_syscall.chown16.return = kprobe.function("sys_chown16").return ? { name = "chown16" retstr = returnstr(1) } # chroot _____________________________________________________ # long sys_chroot(const char __user * filename) probe nd_syscall.chroot = kprobe.function("sys_chroot") ? { name = "chroot" // path = user_string($filename) // argstr = user_string_quoted($filename) asmlinkage() path = user_string_quoted(pointer_arg(1)) argstr = user_string_quoted(pointer_arg(1)) } probe nd_syscall.chroot.return = kprobe.function("sys_chroot").return ? { name = "chroot" retstr = returnstr(1) } # clock_getres _______________________________________________ # long sys_clock_getres(clockid_t which_clock, struct timespec __user *tp) # long compat_clock_getres(clockid_t which_clock, struct compat_timespec __user *tp) # probe nd_syscall.clock_getres = kprobe.function("compat_clock_getres") ?, kprobe.function("sys_clock_getres") ? { name = "clock_getres" // clk_id = $which_clock // clk_id_str = _get_wc_str($which_clock) // res_uaddr = $tp // argstr = sprintf("%s, %p", _get_wc_str($which_clock), $tp) asmlinkage() clk_id = int_arg(1) clk_id_str = _get_wc_str(clk_id) res_uaddr = pointer_arg(2) argstr = sprintf("%s, %p", clk_id_str, res_uaddr) } probe nd_syscall.clock_getres.return = kprobe.function("compat_clock_getres").return ?, kprobe.function("sys_clock_getres").return ? { name = "clock_getres" retstr = returnstr(1) } # clock_gettime ______________________________________________ # long sys_clock_gettime(clockid_t which_clock, struct timespec __user *tp) # probe nd_syscall.clock_gettime = kprobe.function("sys_clock_gettime") ? { name = "clock_gettime" // clk_id = $which_clock // clk_id_str = _get_wc_str($which_clock) // argstr = sprintf("%s, %p", _get_wc_str($which_clock), $tp) asmlinkage() clk_id = int_arg(1) clk_id_str = _get_wc_str(clk_id) argstr = sprintf("%s, %p", clk_id_str, pointer_arg(2)) } probe nd_syscall.clock_gettime.return = kprobe.function("sys_clock_gettime").return ? { name = "clock_gettime" retstr = returnstr(1) } # clock_nanosleep ____________________________________________ # long sys_clock_nanosleep(clockid_t which_clock, # int flags, # const struct timespec __user *rqtp, # struct timespec __user *rmtp) # probe nd_syscall.clock_nanosleep = kprobe.function("sys_clock_nanosleep") ? { name = "clock_nanosleep" // if ($flags == 1) // flag_str = "TIMER_ABSTIME" // else // flag_str = sprintf("0x%x", $flags) // argstr = sprintf("%s, %s, %s, %p", _get_wc_str($which_clock), flag_str, // _struct_timespec_u($rqtp, 1), $rmtp) asmlinkage() flags = int_arg(2) if (flags == 1) flag_str = "TIMER_ABSTIME" else flag_str = sprintf("0x%x", flags) argstr = sprintf("%s, %s, %s, %p", _get_wc_str(int_arg(1)), flag_str, _struct_timespec_u(pointer_arg(3), 1), pointer_arg(4)) } probe nd_syscall.clock_nanosleep.return = kprobe.function("sys_clock_nanosleep").return ? { name = "clock_nanosleep" retstr = returnstr(1) } # compat_clock_nanosleep ________________________________________ # # long compat_clock_nanosleep(clockid_t which_clock, int flags, # struct compat_timespec __user *rqtp, # struct compat_timespec __user *rmtp) # probe nd_syscall.compat_clock_nanosleep = kprobe.function("compat_clock_nanosleep") ?, kprobe.function("compat_sys_clock_nanosleep") ? { name = "compat_clock_nanosleep" // if ($flags == 1) // flag_str = "TIMER_ABSTIME" // else // flag_str = sprintf("0x%x", $flags) // argstr = sprintf("%s, %s, %s, %p", _get_wc_str($which_clock), flag_str, // _struct_compat_timespec_u($rqtp, 1), $rmtp) asmlinkage() flags = int_arg(2) if (flags == 1) flag_str = "TIMER_ABSTIME" else flag_str = sprintf("0x%x", flags) argstr = sprintf("%s, %s, %s, %p", _get_wc_str(int_arg(1)), flag_str, _struct_compat_timespec_u(pointer_arg(3), 1), pointer_arg(4)) } probe nd_syscall.compat_clock_nanosleep.return = kprobe.function("compat_clock_nanosleep").return ?, kprobe.function("compat_sys_clock_nanosleep").return ? { name = "compat_clock_nanosleep" retstr = returnstr(1) } # clock_settime ______________________________________________ # long sys_clock_settime(clockid_t which_clock, # const struct timespec __user *tp) # probe nd_syscall.clock_settime = kprobe.function("sys_clock_settime") ? { name = "clock_settime" // clk_id = $which_clock // clk_id_str = _get_wc_str($which_clock) // tp_uaddr = $tp // argstr = sprintf("%s, %s", clk_id_str, _struct_timespec_u($tp, 1)) asmlinkage() clk_id = int_arg(1) clk_id_str = _get_wc_str(clk_id) tp_uaddr = pointer_arg(2) argstr = sprintf("%s, %s", clk_id_str, _struct_timespec_u(tp_uaddr, 1)) } probe nd_syscall.clock_settime.return = kprobe.function("sys_clock_settime").return ? { name = "clock_settime" retstr = returnstr(1) } # close ______________________________________________________ # long sys_close(unsigned int fd) probe nd_syscall.close = kprobe.function("sys_close") ? { name = "close" // fd = $fd asmlinkage() fd = int_arg(1) argstr = sprint(fd) } probe nd_syscall.close.return = kprobe.function("sys_close").return ? { name = "close" retstr = returnstr(1) } # connect ____________________________________________________ # long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen) probe nd_syscall.connect = kprobe.function("sys_connect") ? { name = "connect" // sockfd = $fd // serv_addr_uaddr = $uservaddr // addrlen = $addrlen // argstr = sprintf("%d, %s, %d", $fd, _struct_sockaddr_u($uservaddr, $addrlen), $addrlen) asmlinkage() sockfd = int_arg(1) serv_addr_uaddr = pointer_arg(2) addrlen = int_arg(3) argstr = sprintf("%d, %s, %d", sockfd, _struct_sockaddr_u(serv_addr_uaddr, addrlen), addrlen) } probe nd_syscall.connect.return = kprobe.function("sys_connect").return ? { name = "connect" retstr = returnstr(1) } # creat # long sys_creat(const char __user * pathname, int mode) probe nd_syscall.creat = kprobe.function("sys_creat") ? { name = "creat" // mode = $mode // pathname = user_string($pathname) // argstr = sprintf("%s, %#o", user_string_quoted($pathname), $mode) asmlinkage() mode = int_arg(2) pathname = user_string_quoted(pointer_arg(1)) argstr = sprintf("%s, %#o", user_string_quoted(pointer_arg(1)), mode) } probe nd_syscall.creat.return = kprobe.function("sys_creat").return ? { name = "creat" retstr = returnstr(1) } # delete_module ______________________________________________ # long sys_delete_module(const char __user *name_user, unsigned int flags) probe nd_syscall.delete_module = kprobe.function("sys_delete_module") ? { name = "delete_module" // name_user = user_string($name_user) // flags = $flags // argstr = sprintf("%s, %s", user_string_quoted($name_user), _module_flags_str($flags)) asmlinkage() name_user = user_string_quoted(pointer_arg(1)) flags = uint_arg(2) argstr = sprintf("%s, %s", user_string_quoted(pointer_arg(1)), _module_flags_str(uint_arg(2))) } probe nd_syscall.delete_module.return = kprobe.function("sys_delete_module").return ? { name = "delete_module" retstr = returnstr(1) } # dup ________________________________________________________ # long sys_dup(unsigned int fildes) probe nd_syscall.dup = kprobe.function("sys_dup") ? { name = "dup" // oldfd = $fildes // argstr = sprint($fildes) asmlinkage() # 'old_fd' should have been 'oldfd. Deprecate the old name. %(systemtap_v <= "1.4" %? old_fd = int_arg(1) %) oldfd = int_arg(1) argstr = sprint(oldfd) } probe nd_syscall.dup.return = kprobe.function("sys_dup").return ? { name = "dup" retstr = returnstr(1) } # dup2 _______________________________________________________ # long sys_dup2(unsigned int oldfd, unsigned int newfd) # Only handles corner case, others handled by dup3. probe nd_syscall.dup2 = kprobe.function("sys_dup2") { // if ($oldfd != $newfd) next; // name = "dup2" // oldfd = $oldfd // newfd = $newfd // flags = 0 // argstr = sprintf("%d, %d", $oldfd, $newfd) asmlinkage() oldfd = int_arg(1) newfd = int_arg(2) if (oldfd != newfd) next; name = "dup2" flags = 0 argstr = sprintf("%d, %d", oldfd, newfd) } probe nd_syscall.dup2.return = kprobe.function("sys_dup2").return { // if ($oldfd != $newfd) next; // name = "dup2" // retstr = return_str(1, $return) if (@entry(__asmlinkage_int_arg(1)) != @entry(int_arg(2))) next; name = "dup2" retstr = returnstr(1) } # dup3 (handles both dup2 and dup3 except for corner case)___________ # long sys_dup2(unsigned int oldfd, unsigned int newfd) # SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags) probe nd_syscall.dup2 = __nd_syscall.dup3 !, __nd_syscall.dup2 { } probe __nd_syscall.dup3 = kprobe.function("sys_dup3") { // oldfd = $oldfd // newfd = $newfd // flags = @defined($flags) ? $flags : 0; asmlinkage() oldfd = int_arg(1) newfd = int_arg(2) flags = int_arg(3) # Corner case handled by dup2 // if ($oldfd == $newfd && flags == 0) next if (oldfd == newfd && flags == 0) next // if (flags == 0) { // name = "dup2"; // argstr = sprintf("%d, %d", $oldfd, $newfd); // } else { // name = "dup3"; // argstr = sprintf("%d, %d, %s", $oldfd, $newfd, // _dup3_flag_str(flags)); // } if (flags == 0) { name = "dup2"; argstr = sprintf("%d, %d", oldfd, newfd); } else { name = "dup3"; argstr = sprintf("%d, %d, %s", oldfd, newfd, _dup3_flag_str(flags)); } } probe __nd_syscall.dup2 = kprobe.function("sys_dup2") { // oldfd = $oldfd // newfd = $newfd // flags = @defined($flags) ? $flags : 0; asmlinkage() oldfd = int_arg(1) newfd = int_arg(2) flags = 0 # Corner case handled by dup2 // if ($oldfd == $newfd && flags == 0) next if (oldfd == newfd) next // if (flags == 0) { // name = "dup2"; // argstr = sprintf("%d, %d", $oldfd, $newfd); // } else { // name = "dup3"; // argstr = sprintf("%d, %d, %s", $oldfd, $newfd, // _dup3_flag_str(flags)); // } name = "dup2"; argstr = sprintf("%d, %d", oldfd, newfd); } probe nd_syscall.dup2.return = __nd_syscall.dup3.return !, __nd_syscall.dup2.return { } probe __nd_syscall.dup3.return = kprobe.function("sys_dup3").return { // flags = @defined($flags) ? $flags : 0; flags = @entry(__asmlinkage_int_arg(3)) # Corner case handled by dup2 // if ($oldfd == $newfd && flags == 0) next if (@entry(int_arg(1)) == @entry(int_arg(2)) && flags == 0) next name = flags == 0 ? "dup2" : "dup3"; // retstr = return_str(1, $return) retstr = returnstr(1) } probe __nd_syscall.dup2.return = kprobe.function("sys_dup2").return { # Corner case handled by dup2 // if ($oldfd == $newfd && flags == 0) next if (@entry(__asmlinkage_int_arg(1)) == @entry(int_arg(2))) next // name = flags == 0 ? "dup2" : "dup3"; // retstr = return_str(1, $return) name = "dup2" retstr = returnstr(1) } # epoll_create _______________________________________________ # long sys_epoll_create(int size) # SYSCALL_DEFINE1(epoll_create1, int, flags) probe nd_syscall.epoll_create = __nd_syscall.epoll_create1 !, __nd_syscall.epoll_create ? { } probe __nd_syscall.epoll_create1 = kprobe.function("sys_epoll_create1") { // size = @defined($size) ? $size : 0; // flags = @defined($flags) ? $flags : 0; asmlinkage() size = 0; flags = int_arg(1) if (flags == 0) { name = "epoll_create"; argstr = sprint(size); } else { name = "epoll_create1"; argstr = _epoll_create1_flag_str(flags); } } probe __nd_syscall.epoll_create = kprobe.function("sys_epoll_create") { name = "epoll_create" // size = $size // argstr = sprint($size) asmlinkage() size = int_arg(1) flags = 0 argstr = sprint(size) } probe nd_syscall.epoll_create.return = __nd_syscall.epoll_create1.return !, __nd_syscall.epoll_create.return ? { } probe __nd_syscall.epoll_create1.return = kprobe.function("sys_epoll_create1").return { flags = @entry(__asmlinkage_int_arg(1)) name = (flags == 0) ? "epoll_create" : "epoll_create1"; retstr = returnstr(1) } probe __nd_syscall.epoll_create.return = kprobe.function("sys_epoll_create").return { flags = 0 name = "epoll_create" retstr = returnstr(1) } # epoll_ctl __________________________________________________ # # long sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event) # long compat_sys_epoll_ctl(int epfd, int op, int fd, # struct compat_epoll_event __user *event) # probe nd_syscall.epoll_ctl = kprobe.function("compat_sys_epoll_ctl") ?, kprobe.function("sys_epoll_ctl") ? { name = "epoll_ctl" // epfd = $epfd // eop = $op // eop_str = _opoll_op_str($op) // efd = $fd // eevent_uaddr = $event // eargstr = sprintf("%d, %s, %d, %p", $epfd, _opoll_op_str($op), $fd, $event) asmlinkage() epfd = int_arg(1) op = int_arg(2) op_str = _opoll_op_str(op) fd = int_arg(3) event_uaddr = pointer_arg(4) argstr = sprintf("%d, %s, %d, %p", epfd, op_str, fd, event_uaddr) } probe nd_syscall.epoll_ctl.return = kprobe.function("compat_sys_epoll_ctl").return ?, kprobe.function("sys_epoll_ctl").return ? { name = "epoll_ctl" retstr = returnstr(1) } # epoll_pwait _________________________________________________ # # long sys_epoll_pwait(int epfd, struct epoll_event __user *events, # int maxevents, int timeout, const sigset_t __user *sigmask, # size_t sigsetsize) # long compat_sys_epoll_pwait(int epfd, # struct compat_epoll_event __user *events, # int maxevents, int timeout, # const compat_sigset_t __user *sigmask, # compat_size_t sigsetsize) # probe nd_syscall.epoll_pwait = kprobe.function("compat_sys_epoll_pwait") ?, kprobe.function("sys_epoll_pwait") ? { name = "epoll_pwait" asmlinkage() argstr = sprintf("%d, %p, %d, %d, %p, %d", // $epfd, $events, $maxevents, $timeout, $sigmask, $sigsetsize) int_arg(1), pointer_arg(2), int_arg(3), int_arg(4), pointer_arg(5), ulong_arg(6)) } probe nd_syscall.epoll_pwait.return = kprobe.function("compat_sys_epoll_pwait").return ?, kprobe.function("sys_epoll_pwait").return ? { name = "epoll_pwait" retstr = returnstr(1) } # epoll_wait _________________________________________________ # # long sys_epoll_wait(int epfd, struct epoll_event __user *events, # int maxevents, int timeout) # long compat_sys_epoll_wait(int epfd, # struct compat_epoll_event __user *events, # int maxevents, int timeout) # probe nd_syscall.epoll_wait = kprobe.function("compat_sys_epoll_wait") ?, kprobe.function("sys_epoll_wait") ? { name = "epoll_wait" // epfd = $epfd // events_uaddr = $events // maxevents = $maxevents // timeout = $timeout // argstr = sprintf("%d, %p, %d, %d", $epfd, $events, $maxevents, $timeout) asmlinkage() epfd = int_arg(1) events_uaddr = pointer_arg(2) maxevents = int_arg(3) timeout = int_arg(4) argstr = sprintf("%d, %p, %d, %d", epfd, events_uaddr, maxevents, timeout) } probe nd_syscall.epoll_wait.return = kprobe.function("compat_sys_epoll_wait").return ?, kprobe.function("sys_epoll_wait").return ? { name = "epoll_wait" retstr = returnstr(1) } # eventfd _____________________________________________________ # long sys_eventfd(unsigned int count) # SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags) probe nd_syscall.eventfd = __nd_syscall.eventfd2 !, __nd_syscall.eventfd ? { } probe __nd_syscall.eventfd2 = kprobe.function("sys_eventfd2") { asmlinkage() flags = int_arg(2) if (flags == 0) { name = "eventfd" argstr = sprint(uint_arg(1)) } else { name = "eventfd2" argstr = sprintf("%d, %s", uint_arg(1), _eventfd2_flag_str(flags)) } } probe __nd_syscall.eventfd = kprobe.function("sys_eventfd") { name = "eventfd" // argstr = sprint($count) asmlinkage() flags = 0 argstr = sprint(uint_arg(1)) } probe nd_syscall.eventfd.return = __nd_syscall.eventfd2.return !, __nd_syscall.eventfd.return ? { } probe __nd_syscall.eventfd2.return = kprobe.function("sys_eventfd2").return { flags = @entry(__asmlinkage_int_arg(2)) name = flags == 0 ? "eventfd" : "eventfd2" retstr = returnstr(1) } probe __nd_syscall.eventfd.return = kprobe.function("sys_eventfd").return { flags = 0 name = "eventfd" retstr = returnstr(1) } # execve _____________________________________________________ # SYSCALL_DEFINE3(execve, # const char __user *, filename, # const char __user *const __user *, argv, # const char __user *const __user *, envp) probe nd_syscall.execve = kprobe.function("sys_execve") { name = "execve" // filename = kernel_string($filename) // args = __get_argv($argv, 0) // argstr = sprintf("%s %s", filename, __get_argv($argv, 1)) filename = user_string(pointer_arg(1)) args = __get_argv(pointer_arg(2), 0) argstr = sprintf("%s %s", filename, __get_argv(pointer_arg(2), 1)) } probe nd_syscall.execve.return = kprobe.function("sys_execve").return { name = "execve" retstr = returnstr(1) } # asmlinkage long compat_sys_execve(const char __user * filename, # const compat_uptr_t __user * argv, # const compat_uptr_t __user * envp) # static int compat_do_execve(const char *filename, # const compat_uptr_t __user *__argv, # const compat_uptr_t __user *__envp) probe nd_syscall.compat_execve = _nd_syscall.compat_sys_execve !, _nd_syscall.compat_do_execve ? { name = "compat_execve" // args = __get_compat_argv($argv, 0) // argstr = sprintf("%s %s", filename, __get_compat_argv($argv, 1)) args = __get_compat_argv(pointer_arg(2), 0) argstr = sprintf("%s %s", filename, __get_compat_argv(pointer_arg(2), 1)) } probe _nd_syscall.compat_sys_execve = kprobe.function("compat_sys_execve").call { asmlinkage() filename = user_string(pointer_arg(1)) } probe _nd_syscall.compat_do_execve = kprobe.function("compat_do_execve").call { filename = kernel_string(pointer_arg(1)) } probe nd_syscall.compat_execve.return = kprobe.function("compat_sys_execve").return !, kprobe.function("compat_do_execve").return ? { name = "compat_execve" retstr = returnstr(1) } # exit _______________________________________________________ # long sys_exit(int error_code) probe nd_syscall.exit = kprobe.function("do_exit").call { name = "exit" // status = $code // argstr = sprint($code) asmlinkage() status = int_arg(1) argstr = sprint(status) } # sys_exit() never returns, and is blacklisted for return probes, # so no alias here. See bz6588. # NB: the explicit .call ensures that alias suffixes can't infer .return # exit_group _________________________________________________ # void sys_exit_group(int error_code) # probe nd_syscall.exit_group = kprobe.function("sys_exit_group").call ? { name = "exit_group" // status = $error_code // argstr = sprint($error_code) asmlinkage() status = int_arg(1) argstr = sprint(status) } # sys_exit_group() never returns, and is blacklisted for return probes, # so no alias here. See bz6588. # NB: the explicit .call ensures that alias suffixes can't infer .return # faccessat __________________________________________________ # new function with 2.6.16 # long sys_faccessat(int dfd, const char __user *filename, int mode) probe nd_syscall.faccessat = kprobe.function("sys_faccessat") ? { name = "faccessat" // dirfd = $dfd // dirfd_str = _dfd_str($dfd) // pathname = user_string($filename) // mode = $mode // mode_str = _access_mode_str($mode) // argstr = sprintf("%s, %s, %s", dirfd_str, user_string_quoted($filename), mode_str) asmlinkage() dirfd = int_arg(1) dirfd_str = _dfd_str(dirfd) pathname = user_string_quoted(pointer_arg(2)) mode = int_arg(3) mode_str = _access_mode_str(mode) argstr = sprintf("%s, %s, %s", dirfd_str, user_string_quoted(pointer_arg(2)), mode_str) } probe nd_syscall.faccessat.return = kprobe.function("sys_faccessat").return ? { name = "faccessat" retstr = returnstr(1) } # fadvise64 __________________________________________________ # long sys_fadvise64(int fd, loff_t offset, size_t len, int advice) # probe nd_syscall.fadvise64 = kprobe.function("sys_fadvise64") ? { name = "fadvise64" // fd = $fd // offset = $offset // len = $len // advice = $advice // argstr = sprintf("%d, %d, %d, %s", $fd, $offset, $len, _fadvice_advice_str($advice)) asmlinkage() fd = int_arg(1) offset = longlong_arg(2) len = ulong_arg(3) advice = int_arg(4) argstr = sprintf("%d, %d, %d, %s", fd, offset, len, _fadvice_advice_str(advice)) } probe nd_syscall.fadvise64.return = kprobe.function("sys_fadvise64").return ? { name = "fadvise64" retstr = returnstr(1) } # fadvise64_64 _______________________________________________ # long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) # probe nd_syscall.fadvise64_64 = kprobe.function("sys_fadvise64_64") ? { name = "fadvise64_64" // fd = $fd // offset = $offset // len = $len // advice = $advice // argstr = sprintf("%d, %d, %d, %s", $fd, $offset, $len, _fadvice_advice_str($advice)) asmlinkage() fd = int_arg(1) offset = longlong_arg(2) len = ulong_arg(3) advice = int_arg(4) argstr = sprintf("%d, %d, %d, %s", fd, offset, len, _fadvice_advice_str(advice)) } probe nd_syscall.fadvise64_64.return = kprobe.function("sys_fadvise64_64").return ? { name = "fadvise64_64" retstr = returnstr(1) } # fchdir _____________________________________________________ # long sys_fchdir(unsigned int fd) probe nd_syscall.fchdir = kprobe.function("sys_fchdir") ? { name = "fchdir" // fd = $fd // argstr = sprint($fd) asmlinkage() fd = int_arg(1) argstr = sprint(fd) } probe nd_syscall.fchdir.return = kprobe.function("sys_fchdir").return ? { name = "fchdir" retstr = returnstr(1) } # fchmod _____________________________________________________ # long sys_fchmod(unsigned int fd, mode_t mode) probe nd_syscall.fchmod = kprobe.function("sys_fchmod") ? { name = "fchmod" // fildes = $fd // mode = $mode asmlinkage() fildes = int_arg(1) mode = uint_arg(2) # SAFE? argstr = sprintf("%d, %#o", fildes, mode) } probe nd_syscall.fchmod.return = kprobe.function("sys_fchmod").return ? { name = "fchmod" retstr = returnstr(1) } # fchmodat ___________________________________________________ # new function with 2.6.16 # long sys_fchmodat(int dfd, const char __user *filename, # mode_t mode) probe nd_syscall.fchmodat = kprobe.function("sys_fchmodat") ? { name = "fchmodat" // dirfd = $dfd // dirfd_str = _dfd_str($dfd) // pathname = user_string($filename) // mode = $mode // argstr = sprintf("%s, %s, %#o", dirfd_str, user_string_quoted($filename), $mode) asmlinkage() dirfd = int_arg(1) dirfd_str = _dfd_str(dirfd) pathname = user_string_quoted(pointer_arg(2)) mode = uint_arg(3) argstr = sprintf("%s, %s, %#o", dirfd_str, user_string_quoted(pointer_arg(2)), mode) } probe nd_syscall.fchmodat.return = kprobe.function("sys_fchmodat").return ? { name = "fchmodat" retstr = returnstr(1) } # fchown _____________________________________________________ # long sys_fchown(unsigned int fd, uid_t user, gid_t group) probe nd_syscall.fchown = kprobe.function("sys_fchown") ? { name = "fchown" // fd = $fd // owner = __int32($user) // group = __int32($group) // argstr = sprintf("%d, %d, %d", $fd, owner, group) asmlinkage() fd = int_arg(1) owner = __int32(uint_arg(2)) group = __int32(uint_arg(3)) argstr = sprintf("%d, %d, %d", fd, owner, group) } probe nd_syscall.fchown.return = kprobe.function("sys_fchown").return ? { name = "fchown" retstr = returnstr(1) } # fchown16 ___________________________________________________ # long sys_fchown16(unsigned int fd, old_uid_t user, old_gid_t group) probe nd_syscall.fchown16 = kprobe.function("sys_fchown16") ? { name = "fchown16" // fd = $fd // owner = __short($user) // group = __short($group) // argstr = sprintf("%d, %d, %d", $fd, owner, group) asmlinkage() fd = int_arg(1) owner = __short(uint_arg(2)) group = __short(uint_arg(3)) argstr = sprintf("%d, %d, %d", fd, owner, group) } probe nd_syscall.fchown16.return = kprobe.function("sys_fchown16").return ? { name = "fchown16" retstr = returnstr(1) } # fchownat ___________________________________________________ # new function with 2.6.16 # long sys_fchownat(int dfd, const char __user *filename, # uid_t user, gid_t group, int flag) probe nd_syscall.fchownat = kprobe.function("sys_fchownat") ? { name = "fchownat" // dirfd = $dfd // dirfd_str = _dfd_str($dfd) // pathname = user_string($filename) // owner = __int32($user) // group = __int32($group) // flags = $flag // flags_str = _at_flag_str($flag) // argstr = sprintf("%s, %s, %d, %d, %s", // dirfd_str, user_string_quoted($filename), owner, group, flags_str) asmlinkage() dirfd = int_arg(1) dirfd_str = _dfd_str(dirfd) pathname = user_string_quoted(pointer_arg(2)) owner = __int32(uint_arg(3)) group = __int32(uint_arg(4)) flags = int_arg(5) flags_str = _at_flag_str(flags) argstr = sprintf("%s, %s, %d, %d, %s", dirfd_str, user_string_quoted(pointer_arg(2)), owner, group, flags_str) } probe nd_syscall.fchownat.return = kprobe.function("sys_fchownat").return ? { name = "fchownat" retstr = returnstr(1) } # fcntl ______________________________________________________ # long sys_fcntl(int fd, unsigned int cmd, unsigned long arg) # long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) # long compat_sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) # long compat_sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) # probe nd_syscall.fcntl = kprobe.function("compat_sys_fcntl") ?, kprobe.function("compat_sys_fcntl64") ?, kprobe.function("sys_fcntl64") ?, kprobe.function("sys_fcntl") ? { name = "fcntl" // fd = $fd // cmd = $cmd // cmd_str = _fcntl_cmd_str($cmd) // arg = $arg // argstr = sprintf("%d, %s, %p", $fd, _fcntl_cmd_str($cmd), $arg) asmlinkage() fd = int_arg(1) cmd = int_arg(2) cmd_str = _fcntl_cmd_str(cmd) arg = long_arg(3) argstr = sprintf("%d, %s, %p", fd, cmd_str, arg) } probe nd_syscall.fcntl.return = kprobe.function("compat_sys_fcntl").return ?, kprobe.function("compat_sys_fcntl64").return ?, kprobe.function("sys_fcntl64").return ?, kprobe.function("sys_fcntl").return ? { name = "fcntl" retstr = returnstr(1) } # fdatasync __________________________________________________ # long sys_fdatasync(unsigned int fd) probe nd_syscall.fdatasync = kprobe.function("sys_fdatasync") ? { name = "fdatasync" // fd = $fd asmlinkage() fd = int_arg(1) argstr = sprint(fd) } probe nd_syscall.fdatasync.return = kprobe.function("sys_fdatasync").return ? { name = "fdatasync" retstr = returnstr(1) } # fgetxattr __________________________________________________ # ssize_t sys_fgetxattr(int fd, char __user *name, # void __user *value, size_t size) probe nd_syscall.fgetxattr = kprobe.function("sys_fgetxattr") ? { name = "fgetxattr" // filedes = $fd // name2 = user_string($name) // value_uaddr = $value // size = $size // argstr = sprintf("%d, %s, %p, %d", $fd, user_string_quoted($name), value_uaddr, size) asmlinkage() filedes = int_arg(1) # 'name2' should have been 'name_str'. Deprecate the old name. %(systemtap_v <= "1.4" %? name2 = user_string_quoted(pointer_arg(2)) %) name_str = user_string_quoted(pointer_arg(2)) value_uaddr = pointer_arg(3) size = ulong_arg(4) argstr = sprintf("%d, %s, %p, %d", filedes, user_string_quoted(pointer_arg(2)), value_uaddr, size) } probe nd_syscall.fgetxattr.return = kprobe.function("sys_fgetxattr").return ? { name = "fgetxattr" retstr = returnstr(1) } # flistxattr _________________________________________________ # ssize_t sys_flistxattr(int fd, char __user *list, size_t size) probe nd_syscall.flistxattr = kprobe.function("sys_flistxattr") ? { name = "flistxattr" // filedes = $fd // list_uaddr = $list // size = $size asmlinkage() filedes = int_arg(1) list_uaddr = pointer_arg(2) size = ulong_arg(3) argstr = sprintf("%d, %p, %d", filedes, list_uaddr, size) } probe nd_syscall.flistxattr.return = kprobe.function("sys_flistxattr").return ? { name = "flistxattr" retstr = returnstr(1) } # flock ______________________________________________________ # long sys_flock(unsigned int fd, unsigned int cmd) probe nd_syscall.flock = kprobe.function("sys_flock") ? { name = "flock" // fd = $fd // operation = $cmd asmlinkage() fd = int_arg(1) operation = int_arg(2) argstr = sprintf("%d, %s", fd, _flock_cmd_str(operation)) } probe nd_syscall.flock.return = kprobe.function("sys_flock").return ? { name = "flock" retstr = returnstr(1) } # fork _______________________________________________________ # long do_fork(unsigned long clone_flags, # unsigned long stack_start, # unsigned long stack_size, # int __user *parent_tidptr, # int __user *child_tidptr) probe nd_syscall.fork = kprobe.function("do_fork") { // clone_flags = $clone_flags // stack_start = $stack_start // regs = $regs // stack_size = $stack_size // parent_tid_uaddr = $parent_tidptr // child_tid_uaddr = $child_tidptr clone_flags = ulong_arg(1) stack_start = ulong_arg(2) %(kernel_v >= "3.8.0" %? %(systemtap_v < "2.3" %? regs = 0 %) stack_size = ulong_arg(3) parent_tid_uaddr = pointer_arg(4) child_tid_uaddr = pointer_arg(5) %: %(systemtap_v < "2.3" %? regs = pointer_arg(3) %) stack_size = ulong_arg(4) parent_tid_uaddr = pointer_arg(5) child_tid_uaddr = pointer_arg(6) %) %(kernel_v >= "3.8.0" %? if (clone_flags & %{ CLONE_VM | CLONE_UNTRACED %}) { %: if (!__is_user_regs(pointer_arg(3))) { %) name = "fork_kernel_thread" argstr = __fork_flags(clone_flags) } else if (clone_flags & %{ CLONE_VFORK %}) { name = "vfork" } else if ((clone_flags & %{ CSIGNAL %}) != %{ SIGCHLD %}) { name = "clone" argstr = __fork_flags(clone_flags) } else { name = "fork" } } probe nd_syscall.fork.return = kprobe.function("do_fork").return { name = "fork" retstr = returnstr(1) } # fremovexattr _______________________________________________ # long sys_fremovexattr(int fd, char __user *name) probe nd_syscall.fremovexattr = kprobe.function("sys_fremovexattr") ? { name = "fremovexattr" // filedes = $fd // name2 = user_string($name) // argstr = sprintf("%d, %s", $fd, user_string_quoted($name)) asmlinkage() filedes = int_arg(1) # 'name2' should have been 'name_str'. Deprecate the old name. %(systemtap_v <= "1.4" %? name2 = user_string_quoted(pointer_arg(2)) %) name_uaddr = pointer_arg(2) name_str = user_string_quoted(pointer_arg(2)) argstr = sprintf("%d, %s", filedes, user_string_quoted(pointer_arg(2))) } probe nd_syscall.fremovexattr.return = kprobe.function("sys_fremovexattr").return ? { name = "fremovexattr" retstr = returnstr(1) } # fsetxattr __________________________________________________ /* * asmlinkage long * sys_fsetxattr(int fd, * char __user *name, * void __user *value, * size_t size, * int flags) */ probe nd_syscall.fsetxattr = kprobe.function("sys_fsetxattr") ? { name = "fsetxattr" // filedes = $fd // name2 = user_string($name) // value_uaddr = $value // size = $size // flags = $flags // argstr = sprintf("%d, %s, %p, %d, %p", filedes, user_string_quoted($name), value_uaddr, size, flags) asmlinkage() filedes = int_arg(1) # 'name2' should have been 'name_str'. Deprecate the old name. %(systemtap_v <= "1.4" %? name2 = user_string_quoted(pointer_arg(2)) %) name_uaddr = pointer_arg(2) name_str = user_string_quoted(pointer_arg(2)) value_uaddr = pointer_arg(3) size = ulong_arg(4) flags = int_arg(5) argstr = sprintf("%d, %s, %p, %d, %p", filedes, user_string_quoted(pointer_arg(2)), value_uaddr, size, flags) } probe nd_syscall.fsetxattr.return = kprobe.function("sys_fsetxattr").return ? { name = "fsetxattr" retstr = returnstr(1) } # fstat ______________________________________________________ # long sys_fstat(unsigned int fd, struct __old_kernel_stat __user * statbuf) # long sys_fstat64(unsigned long fd, struct stat64 __user * statbuf) # long sys32_fstat64(unsigned int fd, struct stat64 __user *statbuf) # long sys_newfstat(unsigned int fd, struct stat __user * statbuf) # long sys_oabi_fstat64(char __user * filename, # struct oldabi_stat64 __user * statbuf) # long compat_sys_newfstat(unsigned int fd, struct compat_stat __user * statbuf) # probe nd_syscall.fstat = kprobe.function("sys_fstat") ?, kprobe.function("sys_fstat64") ?, kprobe.function("sys32_fstat64") ?, kprobe.function("sys_newfstat") ?, kprobe.function("sys_oabi_fstat64") ?, kprobe.function("compat_sys_newfstat") ? { name = "fstat" // filedes = $fd // buf_uaddr = $statbuf // argstr = sprintf("%d, %p", $fd, $statbuf) asmlinkage() filedes = int_arg(1) buf_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", filedes, buf_uaddr) } probe nd_syscall.fstat.return = kprobe.function("sys_fstat").return ?, kprobe.function("sys_fstat64").return ?, kprobe.function("sys32_fstat64").return ?, kprobe.function("sys_newfstat").return ?, kprobe.function("sys_oabi_fstat64").return ?, kprobe.function("compat_sys_newfstat").return ? { name = "fstat" retstr = returnstr(1) } # fstatat ____________________________________________________ # sys32_fstatat64(unsigned int dfd, char __user *filename, struct stat64_emu31 __user* statbuf, int flag) # long sys_newfstatat(int dfd, char __user *filename, struct stat __user *statbuf, int flag) # long sys_fstatat64(int dfd, char __user *filename, struct stat64 __user *statbuf, int flag) # long compat_sys_newfstatat(unsigned int dfd, char __user *filename, struct compat_stat __user *statbuf, int flag) probe nd_syscall.fstatat = kprobe.function("sys_fstatat64") ?, kprobe.function("sys_newfstatat") ?, kprobe.function("compat_sys_newfstatat") ?, kprobe.function("sys32_fstatat64") ? { name = "fstatat" // dirfd = $dfd // path = user_string($filename) // buf_uaddr = $statbuf // argstr = sprintf("%s, %s, %p, %s", _dfd_str($dfd), user_string_quoted($filename), $statbuf, _at_flag_str($flag)) asmlinkage() dirfd = int_arg(1) path = user_string_quoted(pointer_arg(2)) buf_uaddr = pointer_arg(3) argstr = sprintf("%s, %s, %p, %s", _dfd_str(dirfd), user_string_quoted(pointer_arg(2)), buf_uaddr, _at_flag_str(int_arg(4))) } probe nd_syscall.fstatat.return = kprobe.function("sys_fstatat64").return ?, kprobe.function("sys_newfstatat").return ?, kprobe.function("compat_sys_newfstatat").return ?, kprobe.function("sys32_fstatat64").return ? { name = "fstatat" retstr = returnstr(1) } # fstatfs ____________________________________________________ # long sys_fstatfs(unsigned int fd, struct statfs __user * buf) # long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user *buf) # probe nd_syscall.fstatfs = kprobe.function("compat_sys_fstatfs") ?, kprobe.function("sys_fstatfs") ? { name = "fstatfs" // fd = $fd // buf_uaddr = $buf // argstr = sprintf("%d, %p", $fd, $buf) asmlinkage() fd = int_arg(1) buf_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", fd, buf_uaddr) } probe nd_syscall.fstatfs.return = kprobe.function("compat_sys_fstatfs").return ?, kprobe.function("sys_fstatfs").return ? { name = "fstatfs" retstr = returnstr(1) } # fstatfs64 __________________________________________________ # long sys_fstatfs64(unsigned int fd, size_t sz, struct statfs64 __user *buf) # long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf) # probe nd_syscall.fstatfs64 = kprobe.function("compat_sys_fstatfs64") ?, kprobe.function("sys_fstatfs64") ? { name = "fstatfs" // fd = $fd // sz = $sz // buf_uaddr = $buf // argstr = sprintf("%d, %d, %p", $fd, $sz, $buf) asmlinkage() fd = int_arg(1) sz = ulong_arg(2) buf_uaddr = pointer_arg(3) argstr = sprintf("%d, %d, %p", fd, sz, buf_uaddr) } probe nd_syscall.fstatfs64.return = kprobe.function("compat_sys_fstatfs64").return ?, kprobe.function("sys_fstatfs64").return ? { name = "fstatfs" retstr = returnstr(1) } # fsync ______________________________________________________ # long sys_fsync(unsigned int fd) probe nd_syscall.fsync = kprobe.function("sys_fsync") ? { name = "fsync" // fd = $fd asmlinkage() fd = int_arg(1) argstr = sprint(fd) } probe nd_syscall.fsync.return = kprobe.function("sys_fsync").return ? { name = "fsync" retstr = returnstr(1) } # ftruncate __________________________________________________ # long sys_ftruncate(unsigned int fd, unsigned long length) probe nd_syscall.ftruncate = kprobe.function("sys_ftruncate") ? { name = "ftruncate" // fd = $fd // length = $length asmlinkage() fd = int_arg(1) length = ulong_arg(2) argstr = sprintf("%d, %d", fd, length) } probe nd_syscall.ftruncate.return = kprobe.function("sys_ftruncate").return ? { name = "ftruncate" retstr = returnstr(1) } # ftruncate64 ________________________________________________ # long sys_ftruncate64(unsigned int fd, loff_t length) probe nd_syscall.ftruncate64 = kprobe.function("sys_ftruncate64") ? { name = "ftruncate" // fd = $fd // length = $length asmlinkage() fd = int_arg(1) length = longlong_arg(2) argstr = sprintf("%d, %d", fd, length) } probe nd_syscall.ftruncate64.return = kprobe.function("sys_ftruncate64").return ? { name = "ftruncate" retstr = returnstr(1) } # futex ______________________________________________________ # long sys_futex(u32 __user *uaddr, # int op, # int val, # struct timespec __user *utime, # u32 __user *uaddr2, # int val3) # long compat_sys_futex(u32 __user *uaddr, int op, u32 val, # struct compat_timespec __user *utime, u32 __user *uaddr2, # u32 val3) # probe nd_syscall.futex = kprobe.function("sys_futex") ? { name = "futex" // futex_uaddr = $uaddr // op = $op // val = $val // utime_uaddr = $utime // uaddr2_uaddr = $uaddr2 // val3 = $val3 // if (op == 0) // argstr = sprintf("%p, %s, %d, %s", $uaddr, _futex_op_str($op), // $val, _struct_timespec_u($utime, 1)) // else // argstr = sprintf("%p, %s, %d", $uaddr, _futex_op_str($op), // $val) asmlinkage() futex_uaddr = pointer_arg(1) op = int_arg(2) val = u32_arg(3) utime_uaddr = pointer_arg(4) uaddr2_uaddr = pointer_arg(5) val3 = u32_arg(6) if (op == 0) argstr = sprintf("%p, %s, %d, %s", futex_uaddr, _futex_op_str(op), val, _struct_timespec_u(utime_uaddr, 1)) else argstr = sprintf("%p, %s, %d", futex_uaddr, _futex_op_str(op), val) } probe nd_syscall.futex.return = kprobe.function("sys_futex").return ? { name = "futex" retstr = returnstr(1) } probe nd_syscall.compat_futex = kprobe.function("compat_sys_futex") ? { name = "futex" // futex_uaddr = $uaddr // op = $op // val = $val // utime_uaddr = $utime // uaddr2_uaddr = $uaddr2 // val3 = $val3 // if (op == 0) // argstr = sprintf("%p, %s, %d, %s", $uaddr, _futex_op_str($op), // $val, _struct_compat_timespec_u($utime, 1)) // else // argstr = sprintf("%p, %s, %d", $uaddr, _futex_op_str($op), // $val) asmlinkage() futex_uaddr = pointer_arg(1) op = int_arg(2) val = u32_arg(3) utime_uaddr = pointer_arg(4) uaddr2_uaddr = pointer_arg(5) val3 = u32_arg(6) if (op == 0) argstr = sprintf("%p, %s, %d, %s", futex_uaddr, _futex_op_str(op), val, _struct_compat_timespec_u(utime_uaddr, 1)) else argstr = sprintf("%p, %s, %d", futex_uaddr, _futex_op_str(op), val) } probe nd_syscall.compat_futex.return = kprobe.function("compat_sys_futex").return ? { name = "futex" retstr = returnstr(1) } # futimesat _____________________________________________________ # # long sys_futimesat(int dfd, char __user *filename, struct timeval __user *utimes) # long compat_sys_futimesat(unsigned int dfd, char __user *filename, struct compat_timeval __user *t) # probe nd_syscall.futimesat = kprobe.function("sys_futimesat") ? { name = "futimesat" // dirfd = $dfd // filename_uaddr = $filename // filename = user_string($filename) // tvp_uaddr = $utimes // argstr = sprintf("%s, %s, %s", _dfd_str($dfd), user_string_quoted($filename), // _struct_timeval_u($utimes, 2)) asmlinkage() dirfd = int_arg(1) filename_uaddr = pointer_arg(2) filename = user_string_quoted(filename_uaddr) tvp_uaddr = pointer_arg(3) argstr = sprintf("%s, %s, %s", _dfd_str(dirfd), user_string_quoted(filename_uaddr), _struct_timeval_u(tvp_uaddr, 2)) } probe nd_syscall.compat_futimesat = kprobe.function("compat_sys_futimesat") ? { name = "futimesat" // dirfd = $dfd // filename_uaddr = $filename // filename = user_string($filename) // tvp_uaddr = $utimes // argstr = sprintf("%s, %s, %s", _dfd_str($dfd), user_string_quoted($filename), // _struct_timeval_u($utimes, 2)) asmlinkage() dirfd = uint_arg(1) filename_uaddr = pointer_arg(2) filename = user_string_quoted(pointer_arg(2)) tvp_uaddr = pointer_arg(3) argstr = sprintf("%s, %s, %s", _dfd_str(uint_arg(1)), user_string_quoted(pointer_arg(2)), _struct_compat_timeval_u(pointer_arg(3), 2)) } probe nd_syscall.futimesat.return = kprobe.function("sys_futimesat").return ? { name = "futimesat" retstr = returnstr(1) } probe nd_syscall.compat_futimesat.return = kprobe.function("compat_sys_futimesat").return ? { name = "futimesat" retstr = returnstr(1) } # getcwd _____________________________________________________ # long sys_getcwd(char __user *buf, unsigned long size) probe nd_syscall.getcwd = kprobe.function("sys_getcwd") ? { name = "getcwd" // buf_uaddr = $buf // size = $size asmlinkage() buf_uaddr = pointer_arg(1) size = ulong_arg(2) argstr = sprintf("%p, %d", buf_uaddr, size) } probe nd_syscall.getcwd.return = kprobe.function("sys_getcwd").return ? { name = "getcwd" retstr = returnstr(1) } # getdents ___________________________________________________ # long sys_getdents(unsigned int fd, struct linux_dirent __user * dirent, unsigned int count) # long compat_sys_getdents(unsigned int fd, struct compat_linux_dirent __user *dirent, unsigned int count) # long sys_getdents64(unsigned int fd, struct linux_dirent64 __user * dirent, unsigned int count) # long compat_sys_getdents64(unsigned int fd, struct linux_dirent64 __user * dirent, unsigned int count) # probe nd_syscall.getdents = kprobe.function("sys_getdents") ?, kprobe.function("sys_getdents64") ?, kprobe.function("compat_sys_getdents") ?, kprobe.function("compat_sys_getdents64") ? { name = "getdents" // fd = $fd // dirp_uaddr = $dirent // count = $count // argstr = sprintf("%d, %p, %d", $fd, $dirent, $count) asmlinkage() fd = int_arg(1) dirp_uaddr = pointer_arg(2) count = uint_arg(3) argstr = sprintf("%d, %p, %d", fd, dirp_uaddr, count) } probe nd_syscall.getdents.return = kprobe.function("sys_getdents").return ?, kprobe.function("sys_getdents64").return ?, kprobe.function("compat_sys_getdents").return ?, kprobe.function("compat_sys_getdents64").return ? { name = "getdents" retstr = returnstr(1) } # getegid ____________________________________________________ # long sys_getegid(void) # long sys_getegid16(void) # long sys32_getegid16(void) # probe nd_syscall.getegid = kprobe.function("sys_getegid16") ?, kprobe.function("sys32_getegid16") ?, kprobe.function("sys_getegid") { name = "getegid" argstr = "" } probe nd_syscall.getegid.return = kprobe.function("sys_getegid16").return ?, kprobe.function("sys32_getegid16").return ?, kprobe.function("sys_getegid").return { name = "getegid" retstr = returnstr(1) } # geteuid ____________________________________________________ # long sys_geteuid(void) # long sys32_geteuid16(void) # probe nd_syscall.geteuid = kprobe.function("sys_geteuid16") ?, kprobe.function("sys32_geteuid16") ?, kprobe.function("sys_geteuid") { name = "geteuid" argstr = "" } probe nd_syscall.geteuid.return = kprobe.function("sys_geteuid16").return ?, kprobe.function("sys32_geteuid16").return ?, kprobe.function("sys_geteuid").return { name = "geteuid" retstr = returnstr(1) } # getgid _____________________________________________________ # long sys_getgid(void) # long sys32_getgid16(void) # probe nd_syscall.getgid = kprobe.function("sys_getgid16") ?, kprobe.function("sys32_getgid16") ?, kprobe.function("sys_getgid") { name = "getgid" argstr = "" } probe nd_syscall.getgid.return = kprobe.function("sys_getgid16").return ?, kprobe.function("sys32_getgid16").return ?, kprobe.function("sys_getgid").return { name = "getgid" retstr = returnstr(1) } # getgroups __________________________________________________ # long sys_getgroups(int gidsetsize, gid_t __user *grouplist) # long sys_getgroups16(int gidsetsize, old_gid_t __user *grouplist) # long sys32_getgroups16(int gidsetsize, u16 __user *grouplist) # probe nd_syscall.getgroups = kprobe.function("sys_getgroups16") ?, kprobe.function("sys32_getgroups16") ?, kprobe.function("sys_getgroups") ? { name = "getgroups" // size = $gidsetsize // list_uaddr = $grouplist // argstr = sprintf("%d, %p", $gidsetsize, $grouplist) asmlinkage() size = int_arg(1) list_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", size, list_uaddr) } probe nd_syscall.getgroups.return = kprobe.function("sys_getgroups16").return ?, kprobe.function("sys32_getgroups16").return ?, kprobe.function("sys_getgroups").return ? { name = "getgroups" retstr = returnstr(1) } # gethostname ________________________________________________ # long sys_gethostname(char __user *name, int len) probe nd_syscall.gethostname = kprobe.function("sys_gethostname") ? { name = "gethostname" // name_uaddr = $name // len = $len asmlinkage() name_uaddr = pointer_arg(1) len = int_arg(2) argstr = sprintf ("%p, %d", name_uaddr, len) } probe nd_syscall.gethostname.return = kprobe.function("sys_gethostname").return ? { name = "gethostname" retstr = returnstr(1) } # getitimer __________________________________________________ # sys_getitimer(int which, struct itimerval __user *value) # probe nd_syscall.getitimer = kprobe.function("sys_getitimer") ? { name = "getitimer" // which = $which // value_uaddr = $value // argstr = sprintf("%s, %p", _itimer_which_str($which), $value) asmlinkage() which = int_arg(1) value_uaddr = pointer_arg(2) argstr = sprintf("%s, %p", _itimer_which_str(which), value_uaddr) } probe nd_syscall.getitimer.return = kprobe.function("sys_getitimer").return ? { name = "getitimer" retstr = returnstr(1) } # long compat_sys_getitimer(int which, struct compat_itimerval __user *it probe nd_syscall.compat_getitimer = kprobe.function("compat_sys_getitimer") ? { name = "getitimer" // which = $which // value_uaddr = $it // argstr = sprintf("%s, %p", _itimer_which_str($which), $it) asmlinkage() which = int_arg(1) value_uaddr = pointer_arg(2) argstr = sprintf("%s, %p", _itimer_which_str(which), value_uaddr) } probe nd_syscall.compat_getitimer.return = kprobe.function("compat_sys_getitimer").return ? { name = "getitimer" retstr = returnstr(1) } # get_mempolicy ______________________________________________ # long sys_get_mempolicy(int __user *policy, # unsigned long __user *nmask, # unsigned long maxnode, # unsigned long addr, # unsigned long flags) # long compat_sys_get_mempolicy(int __user *policy, # compat_ulong_t __user *nmask, # compat_ulong_t maxnode, # compat_ulong_t addr, compat_ulong_t flags) # probe nd_syscall.get_mempolicy = kprobe.function("compat_sys_get_mempolicy") ?, kprobe.function("sys_get_mempolicy") ? { name = "get_mempolicy" // policy_uaddr = $policy // nmask_uaddr = $nmask // maxnode = $maxnode // addr = $addr // flags = $flags // argstr = sprintf("%p, %p, %d, %p, 0x%x", $policy, // $nmask, $maxnode, $addr, $flags) asmlinkage() policy_uaddr = pointer_arg(1) nmask_uaddr = pointer_arg(2) maxnode = ulong_arg(3) addr = ulong_arg(4) flags = ulong_arg(5) argstr = sprintf("%p, %p, %d, %p, 0x%x", policy_uaddr, nmask_uaddr, maxnode, addr, flags) } probe nd_syscall.get_mempolicy.return = kprobe.function("compat_sys_get_mempolicy").return ?, kprobe.function("sys_get_mempolicy").return ? { name = "get_mempolicy" retstr = returnstr(1) } # getpeername ________________________________________________ # long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len) # probe nd_syscall.getpeername = kprobe.function("sys_getpeername") ? { name = "getpeername" // s = $fd // name_uaddr = $usockaddr // namelen_uaddr = $usockaddr_len // argstr = sprintf("%d, %p, %p", $fd, $usockaddr, $usockaddr_len) asmlinkage() s = int_arg(1) name_uaddr = pointer_arg(2) namelen_uaddr = pointer_arg(3) argstr = sprintf("%d, %p, %p", s, name_uaddr, namelen_uaddr) } probe nd_syscall.getpeername.return = kprobe.function("sys_getpeername").return ? { name = "getpeername" retstr = returnstr(1) } # getpgid ____________________________________________________ # long sys_getpgid(pid_t pid) probe nd_syscall.getpgid = kprobe.function("sys_getpgid") ? { name = "getpgid" // pid = $pid // argstr = sprintf("%d", $pid) asmlinkage() pid = int_arg(1) argstr = sprintf("%d", pid) } probe nd_syscall.getpgid.return = kprobe.function("sys_getpgid").return ? { name = "getpgid" retstr = returnstr(1) } # getpgrp ____________________________________________________ # long sys_getpgrp(void) probe nd_syscall.getpgrp = kprobe.function("sys_getpgrp") ? { name = "getpgrp" argstr = "" } probe nd_syscall.getpgrp.return = kprobe.function("sys_getpgrp").return ? { name = "getpgrp" retstr = returnstr(1) } # getpid _____________________________________________________ # long sys_getpid(void) probe nd_syscall.getpid = kprobe.function("sys_getpid") { name = "getpid" argstr = "" } probe nd_syscall.getpid.return = kprobe.function("sys_getpid").return { name = "getpid" retstr = returnstr(1) } # getppid ____________________________________________________ # long sys_getppid(void) probe nd_syscall.getppid = kprobe.function("sys_getppid") { name = "getppid" argstr = "" } probe nd_syscall.getppid.return = kprobe.function("sys_getppid").return { name = "getppid" retstr = returnstr(1) } # getpriority ________________________________________________ # long sys_getpriority(int which, int who) probe nd_syscall.getpriority = kprobe.function("sys_getpriority") ? { name = "getpriority" // which = $which // who = $who asmlinkage() which = int_arg(1) who = int_arg(2) argstr = sprintf("%s, %d", _priority_which_str(which), who) } probe nd_syscall.getpriority.return = kprobe.function("sys_getpriority").return ? { name = "getpriority" retstr = returnstr(1) } # getresgid __________________________________________________ # long sys_getresgid(gid_t __user *rgid, # gid_t __user *egid, # gid_t __user *sgid) # long sys_getresgid16(old_uid_t __user *rgid, # old_uid_t __user *egid, # old_uid_t __user *sgid) probe nd_syscall.getresgid = kprobe.function("sys_getresgid16") ?, kprobe.function("sys_getresgid") ? { name = "getresgid" // rgid_uaddr = $rgid // egid_uaddr = $egid // sgid_uaddr = $sgid // argstr = sprintf("%p, %p, %p", $rgid, $egid, $sgid) asmlinkage() rgid_uaddr = pointer_arg(1) egid_uaddr = pointer_arg(2) sgid_uaddr = pointer_arg(3) argstr = sprintf("%p, %p, %p", rgid_uaddr, egid_uaddr, sgid_uaddr) } probe nd_syscall.getresgid.return = kprobe.function("sys_getresgid16").return ?, kprobe.function("sys_getresgid").return ? { name = "getresgid" retstr = returnstr(1) } # getresuid __________________________________________________ # long sys_getresuid(uid_t __user *ruid, # uid_t __user *euid, # uid_t __user *suid) probe nd_syscall.getresuid = kprobe.function("sys_getresuid16") ?, kprobe.function("sys_getresuid") ? { name = "getresuid" // ruid_uaddr = $ruid // euid_uaddr = $euid // suid_uaddr = $suid // argstr = sprintf("%p, %p, %p", $ruid, $euid, $suid) asmlinkage() ruid_uaddr = pointer_arg(1) euid_uaddr = pointer_arg(2) suid_uaddr = pointer_arg(3) argstr = sprintf("%p, %p, %p", ruid_uaddr, euid_uaddr, suid_uaddr) } probe nd_syscall.getresuid.return = kprobe.function("sys_getresuid16").return ?, kprobe.function("sys_getresuid").return ? { name = "getresuid" retstr = returnstr(1) } # getrlimit __________________________________________________ # long sys_getrlimit(unsigned int resource, struct rlimit __user *rlim) # long sys_old_getrlimit(unsigned int resource, struct rlimit __user *rlim) # long compat_sys_getrlimit (unsigned int resource, struct compat_rlimit __user *rlim) probe nd_syscall.getrlimit = kprobe.function("sys_getrlimit") ?, kprobe.function("sys_old_getrlimit") ?, kprobe.function("compat_sys_getrlimit") ? { name = "getrlimit" // resource = $resource // rlim_uaddr = $rlim // argstr = sprintf("%s, %p", _rlimit_resource_str($resource), $rlim) asmlinkage() resource = uint_arg(1) rlim_uaddr = pointer_arg(2) argstr = sprintf("%s, %p", _rlimit_resource_str(resource), rlim_uaddr) } probe nd_syscall.getrlimit.return = kprobe.function("sys_getrlimit").return ?, kprobe.function("sys_old_getrlimit").return ?, kprobe.function("compat_sys_getrlimit").return ? { name = "getrlimit" retstr = returnstr(1) } # getrusage __________________________________________________ # long sys_getrusage(int who, struct rusage __user *ru) probe nd_syscall.getrusage = kprobe.function("sys_getrusage") ? { name = "getrusage" // who = $who // if ($who == -2) { // # RUSAGE_BOTH is not valid argument for sys_getrusage // who_str = sprintf("UNKNOWN VALUE: %d", $who) // } else // who_str = _rusage_who_str($who) // usage_uaddr = $ru asmlinkage() who = int_arg(1) if (who == -2) { # RUSAGE_BOTH is not valid argument for sys_getrusage who_str = sprintf("UNKNOWN VALUE: %d", who) } else who_str = _rusage_who_str(who) usage_uaddr = pointer_arg(2) argstr = sprintf("%s, %p", who_str, usage_uaddr) } probe nd_syscall.getrusage.return = kprobe.function("sys_getrusage").return ? { name = "getrusage" retstr = returnstr(1) } # getsid _____________________________________________________ # long sys_getsid(pid_t pid) probe nd_syscall.getsid = kprobe.function("sys_getsid") ? { name = "getsid" // pid = $pid asmlinkage() pid = int_arg(1) argstr = sprint(pid) } probe nd_syscall.getsid.return = kprobe.function("sys_getsid").return ? { name = "getsid" retstr = returnstr(1) } # getsockname ________________________________________________ # long sys_getsockname(int fd, # struct sockaddr __user *usockaddr, # int __user *usockaddr_len) probe nd_syscall.getsockname = kprobe.function("sys_getsockname") ? { name = "getsockname" // s = $fd // name_uaddr = $usockaddr // namelen_uaddr = $usockaddr_len // argstr = sprintf("%d, %p, %p", $fd, $usockaddr, $usockaddr_len) asmlinkage() s = int_arg(1) name_uaddr = pointer_arg(2) namelen_uaddr = pointer_arg(3) argstr = sprintf("%d, %p, %p", s, name_uaddr, namelen_uaddr) } probe nd_syscall.getsockname.return = kprobe.function("sys_getsockname").return ? { name = "getsockname" retstr = returnstr(1) } # getsockopt _________________________________________________ # long sys_getsockopt(int fd, # int level, # int optname, # char __user *optval, # int __user *optlen) # probe nd_syscall.getsockopt = kprobe.function("compat_sys_getsockopt") ?, kprobe.function("sys_getsockopt") ? { name = "getsockopt" // fd = $fd // level = $level // level_str = _sockopt_level_str($level) // optname = $optname // optname_str = _sockopt_optname_str($optname) // optval_uaddr = $optval // optlen_uaddr = $optlen // argstr = sprintf("%d, %s, %s, %p, %p", $fd, _sockopt_level_str($level), // _sockopt_optname_str($optname), $optval, $optlen) asmlinkage() fd = int_arg(1) level = int_arg(2) level_str = _sockopt_level_str(level) optname = int_arg(3) optname_str = _sockopt_optname_str(optname) optval_uaddr = pointer_arg(4) optlen_uaddr = pointer_arg(5) argstr = sprintf("%d, %s, %s, %p, %p", fd, _sockopt_level_str(level), _sockopt_optname_str(optname), optval_uaddr, optlen_uaddr) } probe nd_syscall.getsockopt.return = kprobe.function("compat_sys_getsockopt").return ?, kprobe.function("sys_getsockopt").return ? { name = "getsockopt" retstr = returnstr(1) } # gettid _____________________________________________________ # long sys_gettid(void) probe nd_syscall.gettid = kprobe.function("sys_gettid") { name = "gettid" argstr = "" } probe nd_syscall.gettid.return = kprobe.function("sys_gettid").return { name = "gettid" retstr = returnstr(1) } # gettimeofday _______________________________________________ # long sys_gettimeofday(struct timeval __user *tv, # struct timezone __user *tz) # long sys32_gettimeofday(struct compat_timeval __user *tv, # struct timezone __user *tz) # long compat_sys_gettimeofday(struct compat_timeval __user *tv, # struct timezone __user *tz) probe nd_syscall.gettimeofday = kprobe.function("compat_sys_gettimeofday") ?, kprobe.function("sys32_gettimeofday") ?, kprobe.function("sys_gettimeofday") ? { name = "gettimeofday" // tv_uaddr = $tv // tz_uaddr = $tz // argstr = sprintf("%p, %p", $tv, $tz) asmlinkage() tv_uaddr = pointer_arg(1) tz_uaddr = pointer_arg(2) argstr = sprintf("%p, %p", tv_uaddr, tz_uaddr) } probe nd_syscall.gettimeofday.return = kprobe.function("compat_sys_gettimeofday").return ?, kprobe.function("sys32_gettimeofday").return ?, kprobe.function("sys_gettimeofday").return ? { name = "gettimeofday" retstr = returnstr(1) } # getuid _____________________________________________________ # long sys_getuid(void # long sys_getuid16(void) # long sys32_getuid16(void) # probe nd_syscall.getuid = kprobe.function("sys_getuid16") ?, kprobe.function("sys32_getuid16") ?, kprobe.function("sys_getuid") { name = "getuid" argstr = "" } probe nd_syscall.getuid.return = kprobe.function("sys_getuid16").return ?, kprobe.function("sys32_getuid16").return ?, kprobe.function("sys_getuid").return { name = "getuid" retstr = returnstr(1) } # getxattr ___________________________________________________ # ssize_t sys_getxattr(char __user *path, char __user *name, # void __user *value, size_t size) probe nd_syscall.getxattr = kprobe.function("sys_getxattr") ? { name = "getxattr" // path = user_string(@defined($pathname) ? $pathname : $path) // name2 = user_string($name) // value_uaddr = $value // size = $size // argstr = sprintf("%s, %s, %p, %d", // user_string_quoted(@defined($pathname) ? $pathname : $path), // user_string_quoted($name), // value_uaddr, size) asmlinkage() path = user_string_quoted(pointer_arg(1)) # 'name2' should have been 'name_str'. Deprecate the old name. %(systemtap_v <= "1.4" %? name2 = user_string_quoted(pointer_arg(2)) %) name_str = user_string_quoted(pointer_arg(2)) value_uaddr = pointer_arg(3) size = ulong_arg(4) argstr = sprintf("%s, %s, %p, %d", user_string_quoted(pointer_arg(1)), user_string_quoted(pointer_arg(2)), value_uaddr, size) } probe nd_syscall.getxattr.return = kprobe.function("sys_getxattr").return ? { name = "getxattr" retstr = returnstr(1) } # init_module ________________________________________________ # long sys_init_module(void __user *umod, # unsigned long len, # const char __user *uargs) # probe nd_syscall.init_module = kprobe.function("sys_init_module") ? { name = "init_module" // umod_uaddr = $umod // len = $len // uargs = user_string($uargs) // argstr = sprintf("%p, %d, %s", $umod, $len, user_string_quoted($uargs)) asmlinkage() umod_uaddr = pointer_arg(1) len = ulong_arg(2) uargs = user_string_quoted(pointer_arg(3)) argstr = sprintf("%p, %d, %s", umod_uaddr, len, user_string_quoted(pointer_arg(4))) } probe nd_syscall.init_module.return = kprobe.function("sys_init_module").return ? { name = "init_module" retstr = returnstr(1) } # inotify_add_watch __________________________________________ # # long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) # probe nd_syscall.inotify_add_watch = kprobe.function("sys_inotify_add_watch") ? { name = "inotify_add_watch" // fd = $fd // mask = $mask // path_uaddr = (@defined($pathname) ? $pathname : $path) // path = user_string(@defined($pathname) ? $pathname : $path) // argstr = sprintf("%d, %s, %s", $fd, // user_string_quoted(@defined($pathname) ? $pathname : $path), // _inotify_watch_mask_str($mask)) asmlinkage() fd = int_arg(1) path_uaddr = pointer_arg(2) path = user_string_quoted(path_uaddr) mask = uint_arg(3) argstr = sprintf("%d, %s, %s", fd, user_string_quoted(path_uaddr), _inotify_watch_mask_str(mask)) } probe nd_syscall.inotify_add_watch.return = kprobe.function("sys_inotify_add_watch").return ? { name = "inotify_add_watch" retstr = returnstr(1) } # inotify_init _______________________________________________ # # long sys_inotify_init(void) # probe nd_syscall.inotify_init = __nd_syscall.inotify_init1 !, __nd_syscall.inotify_init ? { } probe __nd_syscall.inotify_init1 = kprobe.function("sys_inotify_init1") { asmlinkage() flags = int_arg(1) if (flags == 0) { name = "inotify_init" argstr = "" } else { name = "inotify_init1" argstr = _inotify_init1_flag_str(flags) } } probe __nd_syscall.inotify_init = kprobe.function("sys_inotify_init") { name = "inotify_init" flags = 0 argstr = "" } probe nd_syscall.inotify_init.return = __nd_syscall.inotify_init1.return !, __nd_syscall.inotify_init.return ? { } probe __nd_syscall.inotify_init1.return = kprobe.function("sys_inotify_init1").return { flags = @entry(__asmlinkage_int_arg(1)) name = (flags == 0) ? "inotify_init" : "inotify_init1" retstr = returnstr(1) } probe __nd_syscall.inotify_init.return = kprobe.function("sys_inotify_init").return { name = "inotify_init" flags = 0 retstr = returnstr(1) } # inotify_rm_watch ___________________________________________ # # long sys_inotify_rm_watch(int fd, u32 wd) # probe nd_syscall.inotify_rm_watch = kprobe.function("sys_inotify_rm_watch") ? { name = "inotify_rm_watch" // fd = $fd // wd = $wd // argstr = sprintf("%d, %d", $fd, $wd) asmlinkage() fd = int_arg(1) wd = uint_arg(2) argstr = sprintf("%d, %d", fd, wd) } probe nd_syscall.inotify_rm_watch.return = kprobe.function("sys_inotify_rm_watch").return ? { name = "inotify_rm_watch" retstr = returnstr(1) } # io_cancel __________________________________________________ # long sys_io_cancel(aio_context_t ctx_id, # struct iocb __user *iocb, # struct io_event __user *result) probe nd_syscall.io_cancel = kprobe.function("sys_io_cancel") ? { name = "io_cancel" // ctx_id = $ctx_id // iocb_uaddr = $iocb // result_uaddr = $result asmlinkage() ctx_id = ulong_arg(1) iocb_uaddr = pointer_arg(2) result_uaddr = pointer_arg(3) argstr = sprintf("%d, %p, %p", ctx_id, iocb_uaddr, result_uaddr) } probe nd_syscall.io_cancel.return = kprobe.function("sys_io_cancel").return ? { name = "io_cancel" retstr = returnstr(1) } # ioctl ______________________________________________________ # long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) # long compat_sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) # probe nd_syscall.ioctl = kprobe.function("compat_sys_ioctl") ?, kprobe.function("sys_ioctl") ? { name = "ioctl" // fd = $fd // request = $cmd // argp = $arg // argstr = sprintf("%d, %d, %p", $fd, $cmd, $arg) asmlinkage() fd = int_arg(1) request = int_arg(2) argp = ulong_arg(3) argstr = sprintf("%d, %d, %p", fd, request, argp) } probe nd_syscall.ioctl.return = kprobe.function("compat_sys_ioctl").return ?, kprobe.function("sys_ioctl").return ? { name = "ioctl" retstr = returnstr(1) } # io_destroy _________________________________________________ # long sys_io_destroy(aio_context_t ctx) probe nd_syscall.io_destroy = kprobe.function("sys_io_destroy") ? { name = "io_destroy" // ctx = $ctx asmlinkage() ctx = ulong_arg(1) argstr = sprintf("%d", ctx) } probe nd_syscall.io_destroy.return = kprobe.function("sys_io_destroy").return ? { name = "io_destroy" retstr = returnstr(1) } # io_getevents _______________________________________________ # long sys_io_getevents(aio_context_t ctx_id, # long min_nr, # long nr, # struct io_event __user *events, # struct timespec __user *timeout) # long compat_sys_io_getevents(aio_context_t ctx_id, # unsigned long min_nr, # unsigned long nr, # struct io_event __user *events, # struct compat_timespec __user *timeout) # probe nd_syscall.io_getevents = kprobe.function("sys_io_getevents") ? { name = "io_getevents" // ctx_id = $ctx_id // min_nr = $min_nr // nr = $nr // events_uaddr = $events // timeout_uaddr = $timeout // timestr = _struct_timespec_u($timeout, 1) // argstr = sprintf("%d, %d, %d, %p, %p, %s", $ctx_id, $min_nr, // $nr, $events, $timeout, timestr) asmlinkage() ctx_id = ulong_arg(1) min_nr = long_arg(2) nr = long_arg(3) events_uaddr = pointer_arg(4) timeout_uaddr = pointer_arg(5) timestr = _struct_timespec_u(timeout_uaddr, 1) argstr = sprintf("%d, %d, %d, %p, %p, %s", ctx_id, min_nr, nr, events_uaddr, timeout_uaddr, timestr) } probe nd_syscall.io_getevents.return = kprobe.function("sys_io_getevents").return ? { name = "io_getevents" retstr = returnstr(1) } probe nd_syscall.compat_io_getevents = kprobe.function("compat_sys_io_getevents") ? { name = "io_getevents" // ctx_id = $ctx_id // min_nr = $min_nr // nr = $nr // events_uaddr = $events // timeout_uaddr = $timeout // timestr = _struct_compat_compat_timespec_u($timeout, 1) // argstr = sprintf("%d, %d, %d, %p, %p, %s", $ctx_id, $min_nr, // $nr, $events, $timeout, timestr) asmlinkage() ctx_id = ulong_arg(1) min_nr = long_arg(2) nr = long_arg(3) events_uaddr = pointer_arg(4) timeout_uaddr = pointer_arg(5) timestr = _struct_compat_timespec_u(timeout_uaddr, 1) argstr = sprintf("%d, %d, %d, %p, %p, %s", ctx_id, min_nr, nr, events_uaddr, timeout_uaddr, timestr) } probe nd_syscall.compat_io_getevents.return = kprobe.function("compat_sys_io_getevents").return ? { name = "io_getevents" retstr = returnstr(1) } # ioperm _____________________________________________________ # long sys_ioperm(unsigned long from, unsigned long num, int turn_on) # probe nd_syscall.ioperm = kprobe.function("sys_ioperm") ? { name = "ioperm" // from = $from // num = $num // turn_on = $turn_on // argstr = sprintf("%d, %d, %d", $from, $num, $turn_on) asmlinkage() from = ulong_arg(1) num = ulong_arg(2) turn_on = int_arg(3) argstr = sprintf("%d, %d, %d", from, num, turn_on) } probe nd_syscall.ioperm.return = kprobe.function("sys_ioperm").return ? { name = "ioperm" retstr = returnstr(1) } # io_setup ___________________________________________________ # long sys_io_setup(unsigned nr_events, aio_context_t __user *ctxp) # probe nd_syscall.io_setup = kprobe.function("sys_io_setup") ? { name = "io_setup" // maxevents = $nr_events // ctxp_uaddr = $ctxp // argstr = sprintf("%d, %p", $nr_events, $ctxp) asmlinkage() maxevents = uint_arg(1) ctxp_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", maxevents, ctxp_uaddr) } probe nd_syscall.io_setup.return = kprobe.function("sys_io_setup").return ? { name = "io_setup" retstr = returnstr(1) } # long compat_sys_io_setup(unsigned nr_reqs, u32 __user *ctx32p) # probe nd_syscall.compat_io_setup = kprobe.function("compat_sys_io_setup") ? { name = "io_setup" // maxevents = $nr_reqs // ctxp_uaddr = $ctx32p // argstr = sprintf("%d, %p", $nr_reqs, $ctx32p) asmlinkage() maxevents = uint_arg(1) ctxp_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", maxevents, ctxp_uaddr) } probe nd_syscall.compat_io_setup.return = kprobe.function("compat_sys_io_setup").return ? { name = "io_setup" retstr = returnstr(1) } # io_submit __________________________________________________ # long sys_io_submit(aio_context_t ctx_id, long nr, struct iocb __user * __user *iocbpp) # probe nd_syscall.io_submit = kprobe.function("sys_io_submit") ? { name = "io_submit" // ctx_id = $ctx_id // nr = $nr // iocbpp_uaddr = $iocbpp // argstr = sprintf("%d, %d, %p", $ctx_id, $nr, $iocbpp) asmlinkage() ctx_id = ulong_arg(1) nr = long_arg(2) iocbpp_uaddr = pointer_arg(3) argstr = sprintf("%d, %d, %p", ctx_id, nr, iocbpp_uaddr) } probe nd_syscall.io_submit.return = kprobe.function("sys_io_submit").return ? { name = "io_submit" retstr = returnstr(1) } # long compat_sys_io_submit(aio_context_t ctx_id, int nr, u32 __user *iocb) # probe nd_syscall.compat_io_submit = kprobe.function("compat_sys_io_submit") ? { name = "io_submit" // ctx_id = $ctx_id // nr = $nr // iocbpp_uaddr = $iocb // argstr = sprintf("%d, %d, %p", $ctx_id, $nr, $iocb) asmlinkage() ctx_id = ulong_arg(1) nr = int_arg(2) iocbpp_uaddr = pointer_arg(3) argstr = sprintf("%d, %d, %p", ctx_id, nr, iocbpp_uaddr) } probe nd_syscall.compat_io_submit.return = kprobe.function("compat_sys_io_submit").return ? { name = "io_submit" retstr = returnstr(1) } # ioprio_get _________________________________________________ # long sys_ioprio_get(int which, int who) # probe nd_syscall.ioprio_get = kprobe.function("sys_ioprio_get") ? { name = "ioprio_get" // which = $which // who = $who // argstr = sprintf("%d, %d", $which, $who) asmlinkage() which = int_arg(1) who = int_arg(2) argstr = sprintf("%d, %d", which, who) } probe nd_syscall.ioprio_get.return = kprobe.function("sys_ioprio_get").return ? { name = "ioprio_get" retstr = returnstr(1) } # ioprio_set _________________________________________________ # long sys_ioprio_set(int which, int who, int ioprio) # probe nd_syscall.ioprio_set = kprobe.function("sys_ioprio_set") ? { name = "ioprio_set" // which = $which // who = $who // ioprio = $ioprio // argstr = sprintf("%d, %d, %d", $which, $who, $ioprio) asmlinkage() which = int_arg(1) who = int_arg(2) ioprio = int_arg(3) argstr = sprintf("%d, %d, %d", which, who, ioprio) } probe nd_syscall.ioprio_set.return = kprobe.function("sys_ioprio_set").return ? { name = "ioprio_set" retstr = returnstr(1) } # kexec_load _________________________________________________ # long sys_kexec_load(unsigned long entry, # unsigned long nr_segments, # struct kexec_segment __user *segments, # unsigned long flags) # long compat_sys_kexec_load(unsigned long entry, # unsigned long nr_segments, # struct compat_kexec_segment __user *segments, # unsigned long flags) # probe nd_syscall.kexec_load = kprobe.function("compat_sys_kexec_load") ?, kprobe.function("sys_kexec_load") ? { name = "kexec_load" // entry = $entry // nr_segments = $nr_segments // segments_uaddr = $segments // flags = $flags // argstr = sprintf("%p, %d, %p, %d", $entry, $nr_segments, $segments, $flags) asmlinkage() entry = ulong_arg(1) nr_segments = ulong_arg(2) segments_uaddr = pointer_arg(3) flags = ulong_arg(4) argstr = sprintf("%p, %d, %p, %d", entry, nr_segments, segments_uaddr, flags) } probe nd_syscall.kexec_load.return = kprobe.function("compat_sys_kexec_load").return ?, kprobe.function("sys_kexec_load").return ? { name = "kexec_load" retstr = returnstr(1) } # keyctl _____________________________________________________ # long sys_keyctl(int option, # unsigned long arg2, # unsigned long arg3, # unsigned long arg4, # unsigned long arg5) # long compat_sys_keyctl(u32 option, u32 arg2, u32 arg3, u32 arg4, u32 arg5) # probe nd_syscall.keyctl = kprobe.function("compat_sys_keyctl") ?, kprobe.function("sys_keyctl") ? { name = "keyctl" // argstr = sprintf("%d, ...", $option) asmlinkage() argstr = sprintf("%d, ...", uint_arg(1)) } probe nd_syscall.keyctl.return = kprobe.function("compat_sys_keyctl").return ?, kprobe.function("sys_keyctl").return ? { name = "keyctl" retstr = returnstr(1) } # kill _______________________________________________________ # long sys_kill(int pid, int sig) probe nd_syscall.kill = kprobe.function("sys_kill") ? { name = "kill" // pid = $pid // sig = $sig // argstr = sprintf("%d, %s", $pid, _signal_name($sig)) asmlinkage() pid = int_arg(1) sig = int_arg(2) argstr = sprintf("%d, %s", pid, _signal_name(sig)) } probe nd_syscall.kill.return = kprobe.function("sys_kill").return ? { name = "kill" retstr = returnstr(1) } # lchown _____________________________________________________ # long sys_lchown(const char __user * filename, uid_t user, gid_t group) # probe nd_syscall.lchown = kprobe.function("sys_lchown") ? { name = "lchown" // path = user_string($filename) // owner = __int32($user) // group = __int32($group) // argstr = sprintf("%s, %d, %d", user_string_quoted($filename), owner, group) asmlinkage() path = user_string_quoted(pointer_arg(1)) owner = __int32(uint_arg(2)) group = __int32(uint_arg(3)) argstr = sprintf("%s, %d, %d", user_string_quoted(pointer_arg(1)), owner, group) } probe nd_syscall.lchown.return = kprobe.function("sys_lchown").return ? { name = "lchown" retstr = returnstr(1) } # lchown16 ___________________________________________________ # long sys_lchown16(const char __user * filename, old_uid_t user, # old_gid_t group) # probe nd_syscall.lchown16 = kprobe.function("sys_lchown16") ? { name = "lchown16" // path = user_string($filename) // owner = __short($user) // group = __short($group) // argstr = sprintf("%s, %d, %d", user_string_quoted($filename), owner, group) asmlinkage() path = user_string_quoted(pointer_arg(1)) owner = __short(uint_arg(2)) group = __short(uint_arg(3)) argstr = sprintf("%s, %d, %d", user_string_quoted(pointer_arg(1)), owner, group) } probe nd_syscall.lchown16.return = kprobe.function("sys_lchown16").return ? { name = "lchown16" retstr = returnstr(1) } # lgetxattr __________________________________________________ # ssize_t sys_lgetxattr(char __user *path, # char __user *name, # void __user *value, # size_t size) # probe nd_syscall.lgetxattr = kprobe.function("sys_lgetxattr") ? { name = "lgetxattr" // path = user_string(@defined($pathname) ? $pathname : $path) // # FIXME // name2 = user_string($name) // value_uaddr = $value // size = $size // argstr = sprintf("%s, %s, %p, %d", // user_string_quoted(@defined($pathname) ? $pathname : $path), // user_string_quoted($name), // value_uaddr, size) asmlinkage() path = user_string_quoted(pointer_arg(1)) # 'name2' should have been 'name_str'. Deprecate the old name. %(systemtap_v <= "1.4" %? name2 = user_string_quoted(pointer_arg(2)) %) name_str = user_string_quoted(pointer_arg(2)) value_uaddr = pointer_arg(3) size = ulong_arg(4) argstr = sprintf("%s, %s, %p, %d", user_string_quoted(pointer_arg(1)), user_string_quoted(pointer_arg(2)), value_uaddr, size) } probe nd_syscall.lgetxattr.return = kprobe.function("sys_lgetxattr").return ? { name = "lgetxattr" retstr = returnstr(1) } # link _______________________________________________________ # long sys_link(const char __user * oldname, # const char __user * newname) probe nd_syscall.link = kprobe.function("sys_link") ? { name = "link" // oldpath = user_string($oldname) // newpath = user_string($newname) // argstr = sprintf("%s, %s", // user_string_quoted($oldname), // user_string_quoted($newname)) asmlinkage() oldpath = user_string_quoted(pointer_arg(1)) newpath = user_string_quoted(pointer_arg(2)) argstr = sprintf("%s, %s", user_string_quoted(pointer_arg(1)), user_string_quoted(pointer_arg(2))) } probe nd_syscall.link.return = kprobe.function("sys_link").return ? { name = "link" retstr = returnstr(1) } # linkat _____________________________________________________ # new function with 2.6.16 # long sys_linkat(int olddfd, const char __user *oldname, # int newdfd, const char __user *newname, int flags) probe nd_syscall.linkat = kprobe.function("sys_linkat") ? { name = "linkat" // olddirfd = $olddfd // olddirfd_str = _dfd_str($olddfd) // oldpath = user_string($oldname) // newdirfd = $newdfd // newdirfd_str = _dfd_str($newdfd) // newpath = user_string($newname) // flags = $flags // flags_str = _at_flag_str($flags) // argstr = sprintf("%s, %s, %s, %s, %s", // olddirfd_str, user_string_quoted($oldname), // newdirfd_str, user_string_quoted($newname), // flags_str) asmlinkage() olddirfd = int_arg(1) olddirfd_str = _dfd_str(olddirfd) oldpath = user_string_quoted(pointer_arg(2)) newdirfd = int_arg(3) newdirfd_str = _dfd_str(newdirfd) newpath = user_string_quoted(pointer_arg(4)) flags = int_arg(5) flags_str = _at_flag_str(flags) argstr = sprintf("%s, %s, %s, %s, %s", olddirfd_str, user_string_quoted(pointer_arg(2)), newdirfd_str, user_string_quoted(pointer_arg(4)), flags_str) } probe nd_syscall.linkat.return = kprobe.function("sys_linkat").return ? { name = "linkat" retstr = returnstr(1) } # listen _____________________________________________________ # long sys_listen(int fd, int backlog) probe nd_syscall.listen = kprobe.function("sys_listen") ? { name = "listen" // sockfd = $fd // backlog = $backlog // argstr = sprintf("%d, %d", $fd, $backlog) asmlinkage() sockfd = int_arg(1) backlog = int_arg(2) argstr = sprintf("%d, %d", sockfd, backlog) } probe nd_syscall.listen.return = kprobe.function("sys_listen").return ? { name = "listen" retstr = returnstr(1) } # listxattr __________________________________________________ # ssize_t sys_listxattr(char __user *path, char __user *list, size_t size) # probe nd_syscall.listxattr = kprobe.function("sys_listxattr") ? { name = "listxattr" // list_uaddr = $list // size = $size // path_uaddr = (@defined($pathname) ? $pathname : $path) // path = user_string(@defined($pathname) ? $pathname : $path) // argstr = sprintf("%s, %p, %d", // user_string_quoted(@defined($pathname) ? $pathname : $path), // $list, $size) asmlinkage() path_uaddr = pointer_arg(1) path = user_string_quoted(path_uaddr) list_uaddr = pointer_arg(2) size = ulong_arg(3) argstr = sprintf("%s, %p, %d", user_string_quoted(path_uaddr), list_uaddr, size) } probe nd_syscall.listxattr.return = kprobe.function("sys_listxattr").return ? { name = "listxattr" retstr = returnstr(1) } # llistxattr _________________________________________________ # ssize_t sys_llistxattr(char __user *path, char __user *list, size_t size) # probe nd_syscall.llistxattr = kprobe.function("sys_llistxattr") ? { name = "llistxattr" // list_uaddr = $list // size = $size // path_uaddr = (@defined($pathname) ? $pathname : $path) // path = user_string(@defined($pathname) ? $pathname : $path) // argstr = sprintf("%s, %p, %d", // user_string_quoted(@defined($pathname) ? $pathname : $path), // $list, $size) asmlinkage() path_uaddr = pointer_arg(1) path = user_string_quoted(path_uaddr) list_uaddr = pointer_arg(2) size = ulong_arg(3) argstr = sprintf("%s, %p, %d", user_string_quoted(path_uaddr), list_uaddr, size) } probe nd_syscall.llistxattr.return = kprobe.function("sys_llistxattr").return ? { name = "llistxattr" retstr = returnstr(1) } # llseek _____________________________________________________ # long sys_llseek(unsigned int fd, # unsigned long offset_high, # unsigned long offset_low, # loff_t __user * result, # unsigned int whence) probe nd_syscall.llseek = kprobe.function("sys_llseek") ? { name = "llseek" // fd = $fd // offset_high = $offset_high // offset_low = $offset_low // result_uaddr = $result // whence = $origin // whence_str = _seek_whence_str($origin) // argstr = sprintf("%d, 0x%x, 0x%x, %p, %s", $fd, $offset_high, // $offset_low, $result, whence_str) asmlinkage() fd = int_arg(1) offset_high = ulong_arg(2) offset_low = ulong_arg(3) result_uaddr = pointer_arg(4) whence = uint_arg(5) whence_str = _seek_whence_str(whence) argstr = sprintf("%d, 0x%x, 0x%x, %p, %s", fd, offset_high, offset_low, result_uaddr, whence_str) } probe nd_syscall.llseek.return = kprobe.function("sys_llseek").return ? { name = "llseek" retstr = returnstr(1) } # lookup_dcookie _____________________________________________ # long sys_lookup_dcookie(u64 cookie64, char __user * buf, size_t len) # probe nd_syscall.lookup_dcookie = kprobe.function("sys_lookup_dcookie") ? { name = "lookup_dcookie" // cookie = $cookie64 // buffer_uaddr = $buf // len = $len // argstr = sprintf("%d, %p, %d", $cookie64, $buf, $len) asmlinkage() cookie = ulonglong_arg(1) buffer_uaddr = pointer_arg(2) len = ulong_arg(3) argstr = sprintf("%d, %p, %d", cookie, buffer_uaddr, len) } probe nd_syscall.lookup_dcookie.return = kprobe.function("sys_lookup_dcookie").return ? { name = "lookup_dcookie" retstr = returnstr(1) } # lremovexattr _______________________________________________ # long sys_lremovexattr(char __user *path, char __user *name) # probe nd_syscall.lremovexattr = kprobe.function("sys_lremovexattr") ? { name = "lremovexattr" // name_uaddr = $name // name2 = user_string($name) // path_uaddr = (@defined($pathname) ? $pathname : $path) // path = user_string(@defined($pathname) ? $pathname : $path) // argstr = sprintf("%s, %s", // user_string_quoted(@defined($pathname) ? $pathname : $path), // user_string_quoted($name)) asmlinkage() path_uaddr = pointer_arg(1) path = user_string_quoted(path_uaddr) name_uaddr = pointer_arg(2) # 'name2' should have been 'name_str'. Deprecate the old name. %(systemtap_v <= "1.4" %? name2 = user_string_quoted(name_uaddr) %) name_str = user_string_quoted(name_uaddr) argstr = sprintf("%s, %s", user_string_quoted(path_uaddr), user_string_quoted(name_uaddr)) } probe nd_syscall.lremovexattr.return = kprobe.function("sys_lremovexattr").return ? { name = "lremovexattr" retstr = returnstr(1) } # lseek ______________________________________________________ # off_t sys_lseek(unsigned int fd, off_t offset, unsigned int whence) probe nd_syscall.lseek = kprobe.function("sys_lseek") ? { name = "lseek" // fildes = $fd // # offset = __int32($offset) // offset = $offset // whence = $origin // whence_str = _seek_whence_str($origin) // argstr = sprintf("%d, %d, %s", $fd, offset, whence_str) asmlinkage() fildes = int_arg(1) offset = long_arg(2) whence = uint_arg(3) whence_str = _seek_whence_str(whence) argstr = sprintf("%d, %d, %s", fildes, offset, whence_str) } probe nd_syscall.lseek.return = kprobe.function("sys_lseek").return ? { name = "lseek" retstr = returnstr(1) } # lsetxattr __________________________________________________ # long sys_lsetxattr(char __user *path, # char __user *name, # void __user *value, # size_t size, # int flags) # probe nd_syscall.lsetxattr = kprobe.function("sys_lsetxattr") ? { name = "lsetxattr" // path_uaddr = (@defined($pathname) ? $pathname : $path) // path = user_string(@defined($pathname) ? $pathname : $path) // name_uaddr = $name // name_str = user_string($name) // value_uaddr = $value // size = $size // flags = $flags // argstr = sprintf("%s, %s, %p, %d, %d", // user_string_quoted(@defined($pathname) ? $pathname : $path), // user_string_quoted($name), // value_uaddr, $size, $flags) asmlinkage() path_uaddr = pointer_arg(1) path = user_string_quoted(path_uaddr) name_uaddr = pointer_arg(2) name_str = user_string_quoted(name_uaddr) value_uaddr = pointer_arg(3) size = ulong_arg(4) flags = int_arg(5) argstr = sprintf("%s, %s, %p, %d, %d", user_string_quoted(path_uaddr), user_string_quoted(name_uaddr), value_uaddr, size, flags) } probe nd_syscall.lsetxattr.return = kprobe.function("sys_lsetxattr").return ? { name = "lsetxattr" retstr = returnstr(1) } # lstat ______________________________________________________ # long sys_lstat(char __user * filename, struct __old_kernel_stat __user * statbuf) # long sys_newlstat(char __user * filename, struct stat __user * statbuf) # long compat_sys_newlstat(char __user * filename, struct compat_stat __user *statbuf) # long sys32_lstat64(char * filename, struct stat64 __user *statbuf) # long sys_lstat64(char __user * filename, struct stat64 __user * statbuf) # long sys_oabi_lstat64(char __user * filename, # struct oldabi_stat64 __user * statbuf) # probe nd_syscall.lstat = kprobe.function("sys_lstat") ?, kprobe.function("sys_newlstat") ?, kprobe.function("compat_sys_newlstat") ?, kprobe.function("sys32_lstat64") ?, kprobe.function("sys_lstat64") ?, kprobe.function("sys_oabi_lstat64") ? { name = "lstat" // path = user_string($filename) // buf_uaddr = $statbuf // argstr = sprintf("%s, %p", user_string_quoted($filename), $statbuf) asmlinkage() path = user_string_quoted(pointer_arg(1)) buf_uaddr = pointer_arg(2) argstr = sprintf("%s, %p", user_string_quoted(pointer_arg(1)), buf_uaddr) } probe nd_syscall.lstat.return = kprobe.function("sys_lstat").return ?, kprobe.function("sys_newlstat").return ?, kprobe.function("compat_sys_newlstat").return ?, kprobe.function("sys32_lstat64").return ?, kprobe.function("sys_lstat64").return ?, kprobe.function("sys_oabi_lstat64").return ? { name = "lstat" retstr = returnstr(1) } # madvise ____________________________________________________ # long sys_madvise(unsigned long start, size_t len_in, int behavior) # probe nd_syscall.madvise = kprobe.function("sys_madvise") ? { name = "madvise" // start = $start // length = $len_in // advice = $behavior // advice_str = _madvice_advice_str($behavior) // argstr = sprintf("%p, %d, %s", $start, $len_in, _madvice_advice_str($behavior)) asmlinkage() start = ulong_arg(1) length = ulong_arg(2) advice = int_arg(3) advice_str = _madvice_advice_str(advice) argstr = sprintf("%p, %d, %s", start, length, _madvice_advice_str(advice)) } probe nd_syscall.madvise.return = kprobe.function("sys_madvise").return ? { name = "madvise" retstr = returnstr(1) } # mbind ______________________________________________________ # long sys_mbind(unsigned long start, # unsigned long len, # unsigned long mode, # unsigned long __user *nmask, # unsigned long maxnode, # unsigned flags) # # long compat_sys_mbind(compat_ulong_t start, # compat_ulong_t len, # compat_ulong_t mode, # compat_ulong_t __user *nmask, # compat_ulong_t maxnode, # compat_ulong_t flags) # probe nd_syscall.mbind = kprobe.function("compat_sys_mbind") ?, kprobe.function("sys_mbind") ? { name = "mbind" // start = $start // len = $len // mode = $mode // nmask_uaddr = $nmask // maxnode = $maxnode // flags = $flags // argstr = sprintf("%d, %d, %d, %p, %d, 0x%x", $start, $len, $mode, // $nmask, $maxnode, $flags) asmlinkage() start = ulong_arg(1) len = long_arg(2) mode = ulong_arg(3) nmask_uaddr = pointer_arg(4) maxnode = ulong_arg(5) flags = uint_arg(6) argstr = sprintf("%d, %d, %d, %p, %d, 0x%x", start, len, mode, nmask_uaddr, maxnode, flags) } probe nd_syscall.mbind.return = kprobe.function("compat_sys_mbind").return ?, kprobe.function("sys_mbind").return ? { name = "mbind" retstr = returnstr(1) } # migrate_pages ____________________________________________________ # long sys_migrate_pages(pid_t pid, unsigned long maxnode, # const unsigned long __user *old_nodes, # const unsigned long __user *new_nodes) probe nd_syscall.migrate_pages = kprobe.function("sys_migrate_pages") ? { name = "migrate_pages" // argstr = sprintf("%d, %d, %p, %p", $pid, $maxnode, $old_nodes, $new_nodes) asmlinkage() argstr = sprintf("%d, %d, %p, %p", int_arg(1), ulong_arg(2), pointer_arg(3), pointer_arg(4)) } probe nd_syscall.migrate_pages.return = kprobe.function("sys_migrate_pages").return ? { name = "migrate_pages" retstr = returnstr(1) } # mincore ____________________________________________________ # long sys_mincore(unsigned long start, size_t len, unsigned char __user * vec) # probe nd_syscall.mincore = kprobe.function("sys_mincore") ? { name = "mincore" // start = $start // length = $len // vec_uaddr = $vec // argstr = sprintf("%p, %d, %p", $start, $len, $vec) asmlinkage() start = ulong_arg(1) length = ulong_arg(2) vec_uaddr = pointer_arg(3) argstr = sprintf("%p, %d, %p", start, length, vec_uaddr) } probe nd_syscall.mincore.return = kprobe.function("sys_mincore").return ? { name = "mincore" retstr = returnstr(1) } # mkdir ______________________________________________________ # long sys_mkdir(const char __user * pathname, int mode) probe nd_syscall.mkdir = kprobe.function("sys_mkdir") ? { name = "mkdir" // pathname_uaddr = $pathname // pathname = user_string($pathname) // mode = $mode // argstr = sprintf("%s, %#o", user_string_quoted($pathname), $mode) asmlinkage() pathname_uaddr = pointer_arg(1) pathname = user_string_quoted(pathname_uaddr) mode = int_arg(2) argstr = sprintf("%s, %#o", user_string_quoted(pathname_uaddr), mode) } probe nd_syscall.mkdir.return = kprobe.function("sys_mkdir").return ? { name = "mkdir" retstr = returnstr(1) } # mkdirat ____________________________________________________ # new function with 2.6.16 # long sys_mkdirat(int dfd, const char __user *pathname, int mode) probe nd_syscall.mkdirat = kprobe.function("sys_mkdirat") ? { name = "mkdirat" // dirfd = $dfd // pathname = user_string($pathname) // mode = $mode // argstr = sprintf("%d, %s, %#o", $dfd, user_string_quoted($pathname), $mode) asmlinkage() dirfd = int_arg(1) pathname = user_string_quoted(pointer_arg(2)) mode = int_arg(3) argstr = sprintf("%d, %s, %#o", dirfd, user_string_quoted(pointer_arg(2)), mode) } probe nd_syscall.mkdirat.return = kprobe.function("sys_mkdirat").return ? { name = "mkdirat" retstr = returnstr(1) } # mknod # long sys_mknod(const char __user * filename, int mode, unsigned dev) probe nd_syscall.mknod = kprobe.function("sys_mknod") ? { name = "mknod" // pathname = user_string($filename) // mode = $mode // dev = $dev // argstr = sprintf("%s, %s, %p", user_string_quoted($filename), _mknod_mode_str($mode), dev) asmlinkage() pathname = user_string_quoted(pointer_arg(1)) mode = int_arg(2) dev = uint_arg(3) argstr = sprintf("%s, %s, %p", user_string_quoted(pointer_arg(1)), _mknod_mode_str(mode), dev) } probe nd_syscall.mknod.return = kprobe.function("sys_mknod").return ? { name = "mknod" retstr = returnstr(1) } # mknodat ____________________________________________________ # new function with 2.6.16 # long sys_mknodat(int dfd, const char __user *filename, # int mode, unsigned dev) probe nd_syscall.mknodat = kprobe.function("sys_mknodat") ? { name = "mknodat" // dirfd = $dfd // dirfd_str = _dfd_str($dfd) // pathname = user_string($filename) // mode = $mode // mode_str = _mknod_mode_str($mode) // dev = $dev // argstr = sprintf("%s, %s, %s, %p", // dirfd_str, user_string_quoted($filename), mode_str, $dev) asmlinkage() dirfd = int_arg(1) dirfd_str = _dfd_str(dirfd) pathname = user_string_quoted(pointer_arg(2)) mode = int_arg(3) mode_str = _mknod_mode_str(mode) dev = uint_arg(4) argstr = sprintf("%s, %s, %s, %p", dirfd_str, user_string_quoted(pointer_arg(2)), mode_str, dev) } probe nd_syscall.mknodat.return = kprobe.function("sys_mknodat").return ? { name = "mknodat" retstr = returnstr(1) } # mlock ______________________________________________________ # # long sys_mlock(unsigned long start, size_t len) # probe nd_syscall.mlock = kprobe.function("sys_mlock") ? { name = "mlock" // addr = $start // len = $len // argstr = sprintf("%p, %d", $start, $len) asmlinkage() addr = ulong_arg(1) len = ulong_arg(2) argstr = sprintf("%p, %d", addr, len) } probe nd_syscall.mlock.return = kprobe.function("sys_mlock").return ? { name = "mlock" retstr = returnstr(1) } # mlockall ___________________________________________________ # # long sys_mlockall(int flags) # probe nd_syscall.mlockall = kprobe.function("sys_mlockall") ? { name = "mlockall" // flags = $flags // argstr = _mlockall_flags_str($flags) asmlinkage() flags = int_arg(1) argstr = _mlockall_flags_str(flags) } probe nd_syscall.mlockall.return = kprobe.function("sys_mlockall").return ? { name = "mlockall" retstr = returnstr(1) } # modify_ldt _________________________________________________ # int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) # probe nd_syscall.modify_ldt = kprobe.function("sys_modify_ldt") ? { name = "modify_ldt" // func = $func // ptr_uaddr = $ptr // bytecount = $bytecount // argstr = sprintf("%d, %p, %d", $func, $ptr, $bytecount) asmlinkage() func = int_arg(1) ptr_uaddr = pointer_arg(2) bytecount = ulong_arg(3) argstr = sprintf("%d, %p, %d", func, ptr_uaddr, bytecount) } probe nd_syscall.modify_ldt.return = kprobe.function("sys_modify_ldt").return ? { name = "modify_ldt" retstr = returnstr(1) } # move_pages ____________________________________________________ # long sys_move_pages(pid_t pid, unsigned long nr_pages, # const void __user * __user *pages, # const int __user *nodes, # int __user *status, # int flags) # # long compat_sys_move_pages(pid_t pid, unsigned long nr_pages, # compat_uptr_t __user *pages32, # const int __user *nodes, # int __user *status, # int flags) # probe nd_syscall.move_pages = kprobe.function("compat_sys_move_pages") ?, kprobe.function("sys_move_pages") ? { name = "move_pages" // argstr = sprintf("%d, %d, %p, %p, 0x%x", $pid, $nr_pages, $nodes, $status, $flags) asmlinkage() argstr = sprintf("%d, %d, %p, %p, 0x%x", int_arg(1), ulong_arg(2), pointer_arg(4), pointer_arg(5), int_arg(6)) } probe nd_syscall.move_pages.return = kprobe.function("compat_sys_move_pages").return ?, kprobe.function("sys_move_pages").return ? { name = "move_pages" retstr = returnstr(1) } # mount ______________________________________________________ # long sys_mount(char __user * dev_name, # char __user * dir_name, # char __user * type, # unsigned long flags, # void __user * data) # long compat_sys_mount(char __user * dev_name, # char __user * dir_name, # char __user * type, # unsigned long flags, # void __user * data) probe nd_syscall.mount = kprobe.function("compat_sys_mount") ?, kprobe.function("sys_mount") ? { name = "mount" // source = user_string($dev_name) // target = user_string($dir_name) // filesystemtype = user_string($type) // mountflags = $flags // mountflags_str = _mountflags_str($flags) // data = text_strn(user_string($data), syscall_string_trunc, 1) // argstr = sprintf("%s, %s, %s, %s, %s", // user_string_quoted($dev_name), // user_string_quoted($dir_name), // user_string_quoted($type), // mountflags_str, data) asmlinkage() source = user_string_quoted(pointer_arg(1)) target = user_string_quoted(pointer_arg(2)) filesystemtype = user_string_quoted(pointer_arg(3)) mountflags = ulong_arg(4) mountflags_str = _mountflags_str(mountflags) data = user_string_n_quoted(pointer_arg(5), syscall_string_trunc) argstr = sprintf("%s, %s, %s, %s, %s", user_string_quoted(pointer_arg(1)), user_string_quoted(pointer_arg(2)), user_string_quoted(pointer_arg(3)), mountflags_str, data) } probe nd_syscall.mount.return = kprobe.function("compat_sys_mount").return ?, kprobe.function("sys_mount").return ? { name = "mount" retstr = returnstr(1) } %( kernel_v >= "2.6.33" %? # In newer kernels (2.6.33+), all the sys_mmap() variants are just # wrappers around sys_mmap_pgoff(), which is in arch-generic code. # # long sys_mmap_pgoff(unsigned long addr, unsigned long len, # unsigned long prot, unsigned long flags, # unsigned long fd, unsigned long pgoff) probe nd_syscall.mmap2 = kprobe.function("sys_mmap_pgoff") ? { name = "mmap2" // start = $addr // length = $len // prot = $prot // flags = $flags // # Although the kernel gets an unsigned long fd, on the // # user-side it is a signed int. Fix this. // fd = __int32($fd) // pgoffset = $pgoff // argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len, // _mprotect_prot_str($prot), _mmap_flags($flags), // __int32($fd), $pgoff) asmlinkage() start = ulong_arg(1) length = ulong_arg(2) prot = ulong_arg(3) flags = ulong_arg(4) # Although the kernel gets an unsigned long fd, on the # user-side it is a signed int. Fix this. fd = int_arg(5) pgoffset = ulong_arg(6) argstr = sprintf("%p, %d, %s, %s, %d, %d", start, length, _mprotect_prot_str(prot), _mmap_flags(flags), fd, pgoffset) } probe nd_syscall.mmap2.return = kprobe.function("sys_mmap_pgoff").return ? { name = "mmap2" retstr = returnstr(2) } %) # mprotect ___________________________________________________ # long sys_mprotect(unsigned long start, size_t len, unsigned long prot) # probe nd_syscall.mprotect = kprobe.function("sys_mprotect") ? { name = "mprotect" // addr = $start // len = $len // prot = $prot // prot_str = _mprotect_prot_str($prot) // argstr = sprintf("%p, %d, %s", $start, $len, _mprotect_prot_str($prot)) asmlinkage() addr = ulong_arg(1) len = ulong_arg(2) prot = ulong_arg(3) prot_str = _mprotect_prot_str(prot) argstr = sprintf("%p, %d, %s", addr, len, _mprotect_prot_str(prot)) } probe nd_syscall.mprotect.return = kprobe.function("sys_mprotect").return ? { name = "mprotect" retstr = returnstr(1) } # mq_getsetattr ______________________________________________ # long sys_mq_getsetattr(mqd_t mqdes, # const struct mq_attr __user *u_mqstat, # struct mq_attr __user *u_omqstat) # long compat_sys_mq_getsetattr(mqd_t mqdes, # const struct compat_mq_attr __user *u_mqstat, # struct compat_mq_attr __user *u_omqstat) # probe nd_syscall.mq_getsetattr = kprobe.function("compat_sys_mq_getsetattr") ?, kprobe.function("sys_mq_getsetattr") ? { name = "mq_getsetattr" // mqdes = $mqdes // u_mqstat_uaddr = $u_mqstat // u_omqstat_uaddr = $u_omqstat // argstr = sprintf("%d, %p, %p", $mqdes, $u_mqstat, $u_omqstat) asmlinkage() mqdes = int_arg(1) u_mqstat_uaddr = pointer_arg(2) u_omqstat_uaddr = pointer_arg(3) argstr = sprintf("%d, %p, %p", mqdes, u_mqstat_uaddr, u_omqstat_uaddr) } probe nd_syscall.mq_getsetattr.return = kprobe.function("compat_sys_mq_getsetattr").return ?, kprobe.function("sys_mq_getsetattr").return ? { name = "mq_getsetattr" retstr = returnstr(1) } # mq_notify __________________________________________________ # long sys_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification) # long compat_sys_mq_notify(mqd_t mqdes, const struct compat_sigevent __user *u_notification) # probe nd_syscall.mq_notify = kprobe.function("compat_sys_mq_notify") ?, kprobe.function("sys_mq_notify") ? { name = "mq_notify" // mqdes = $mqdes // notification_uaddr = $u_notification // argstr = sprintf("%d, %p", $mqdes, $u_notification) asmlinkage() mqdes = int_arg(1) notification_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", mqdes, notification_uaddr) } probe nd_syscall.mq_notify.return = kprobe.function("compat_sys_mq_notify").return ?, kprobe.function("sys_mq_notify").return ? { name = "mq_notify" retstr = returnstr(1) } # mq_open ____________________________________________________ # long sys_mq_open(const char __user *u_name, # int oflag, # mode_t mode, # struct mq_attr __user *u_attr) # long compat_sys_mq_open(const char __user *u_name, # int oflag, compat_mode_t mode, # struct compat_mq_attr __user *u_attr) # probe nd_syscall.mq_open = kprobe.function("compat_sys_mq_open") ?, kprobe.function("sys_mq_open") ? { name = "mq_open" // name_uaddr = $u_name // filename = user_string($u_name) // mode = $mode // u_attr_uaddr = $u_attr // oflag = $oflag // if (oflag & 64) // argstr = sprintf("%s, %s, %#o, %p", user_string_quoted($u_name), // _sys_open_flag_str($oflag), $mode, $u_attr) // else // argstr = sprintf("%s, %s", user_string_quoted($u_name), _sys_open_flag_str($oflag)) asmlinkage() name_uaddr = pointer_arg(1) filename = user_string_quoted(name_uaddr) mode = uint_arg(3) u_attr_uaddr = pointer_arg(4) oflag = int_arg(2) if (oflag & 64) argstr = sprintf("%s, %s, %#o, %p", user_string_quoted(name_uaddr), _sys_open_flag_str(oflag), mode, u_attr_uaddr) else argstr = sprintf("%s, %s", user_string_quoted(name_uaddr), _sys_open_flag_str(oflag)) } probe nd_syscall.mq_open.return = kprobe.function("compat_sys_mq_open").return ?, kprobe.function("sys_mq_open").return ? { name = "mq_open" retstr = returnstr(1) } # mq_timedreceive ____________________________________________ # ssize_t sys_mq_timedreceive(mqd_t mqdes, # char __user *u_msg_ptr, # size_t msg_len, # unsigned int __user *u_msg_prio, # const struct timespec __user *u_abs_timeout) # ssize_t compat_sys_mq_timedreceive(mqd_t mqdes, # char __user *u_msg_ptr, # size_t msg_len, unsigned int __user *u_msg_prio, # const struct compat_timespec __user *u_abs_timeout) # probe nd_syscall.mq_timedreceive = kprobe.function("compat_sys_mq_timedreceive") ?, kprobe.function("sys_mq_timedreceive") ? { name = "mq_timedreceive" // mqdes = $mqdes // msg_ptr_uaddr = $u_msg_ptr // msg_len = $msg_len // msg_prio_uaddr = $u_msg_prio // abs_timout_uaddr = $u_abs_timeout // argstr = sprintf("%d, %p, %d, %p, %p", $mqdes, $u_msg_ptr, $msg_len, // $u_msg_prio, $u_abs_timeout) asmlinkage() mqdes = int_arg(1) msg_ptr_uaddr = pointer_arg(2) msg_len = ulong_arg(3) msg_prio_uaddr = pointer_arg(4) abs_timeout_uaddr = pointer_arg(5) argstr = sprintf("%d, %p, %d, %p, %p", mqdes, msg_ptr_uaddr, msg_len, msg_prio_uaddr, abs_timeout_uaddr) } probe nd_syscall.mq_timedreceive.return = kprobe.function("compat_sys_mq_timedreceive").return ?, kprobe.function("sys_mq_timedreceive").return ? { name = "mq_timedreceive" retstr = returnstr(1) } # mq_timedsend _______________________________________________ # long sys_mq_timedsend(mqd_t mqdes, # const char __user *u_msg_ptr, # size_t msg_len, # unsigned int msg_prio, # const struct timespec __user *u_abs_timeout) # long compat_sys_mq_timedsend(mqd_t mqdes, # const char __user *u_msg_ptr, # size_t msg_len, unsigned int msg_prio, # const struct compat_timespec __user *u_abs_timeout) # probe nd_syscall.mq_timedsend = kprobe.function("compat_sys_mq_timedsend") ?, kprobe.function("sys_mq_timedsend") ? { name = "mq_timedsend" // mqdes = $mqdes // msg_ptr_uaddr = $u_msg_ptr // msg_len = $msg_len // msg_prio = $msg_prio // abs_timeout_uaddr = $u_abs_timeout // argstr = sprintf("%d, %p, %d, %d, %p", $mqdes, $u_msg_ptr, $msg_len, // $msg_prio, $u_abs_timeout) asmlinkage() mqdes = int_arg(1) msg_ptr_uaddr = pointer_arg(2) msg_len = ulong_arg(3) msg_prio = uint_arg(4) abs_timeout_uaddr = pointer_arg(5) argstr = sprintf("%d, %p, %d, %d, %p", mqdes, msg_ptr_uaddr, msg_len, msg_prio, abs_timeout_uaddr) } probe nd_syscall.mq_timedsend.return = kprobe.function("compat_sys_mq_timedsend").return ?, kprobe.function("sys_mq_timedsend").return ? { name = "mq_timedsend" retstr = returnstr(1) } # mq_unlink __________________________________________________ # long sys_mq_unlink(const char __user *u_name) # probe nd_syscall.mq_unlink = kprobe.function("sys_mq_unlink") ? { name = "mq_unlink" // u_name_uaddr = $u_name // u_name = user_string($u_name) // argstr = user_string_quoted($u_name) asmlinkage() u_name_uaddr = pointer_arg(1) u_name = user_string_quoted(u_name_uaddr) argstr = user_string_quoted(u_name_uaddr) } probe nd_syscall.mq_unlink.return = kprobe.function("sys_mq_unlink").return ? { name = "mq_unlink" retstr = returnstr(1) } # mremap _____________________________________________________ # unsigned long sys_mremap(unsigned long addr, # unsigned long old_len, # unsigned long new_len, # unsigned long flags, # unsigned long new_addr) # probe nd_syscall.mremap = kprobe.function("ia64_mremap") ?, kprobe.function("sys_mremap") ? { name = "mremap" // old_address = $addr // old_size = $old_len // new_size = $new_len // flags = $flags // new_address = $new_addr // argstr = sprintf("%p, %d, %d, %s, %p", $addr, $old_len, $new_len, // _mremap_flags($flags), $new_addr) asmlinkage() old_address = ulong_arg(1) old_size = ulong_arg(2) new_size = ulong_arg(3) flags = ulong_arg(4) new_address = ulong_arg(5) argstr = sprintf("%p, %d, %d, %s, %p", old_address, old_size, new_size, _mremap_flags(flags), new_address) } probe nd_syscall.mremap.return = kprobe.function("ia64_mremap").return ?, kprobe.function("sys_mremap").return ? { name = "mremap" retstr = returnstr(2) } # msgctl _____________________________________________________ # long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf) # probe nd_syscall.msgctl = kprobe.function("sys_msgctl") ? { name = "msgctl" // msqid = $msqid // cmd = $cmd // buf_uaddr = $buf // argstr = sprintf("%d, %d, %p", $msqid, $cmd, $buf) asmlinkage() msqid = int_arg(1) cmd = int_arg(2) buf_uaddr = pointer_arg(3) argstr = sprintf("%d, %d, %p", msqid, cmd, buf_uaddr) } probe nd_syscall.msgctl.return = kprobe.function("sys_msgctl").return ? { name = "msgctl" retstr = returnstr(1) } # compat_sys_msgctl ________________________________________ # # long compat_sys_msgctl(int first, int second, void __user *uptr) # probe nd_syscall.compat_sys_msgctl = kprobe.function("compat_sys_msgctl") ? { name = "compat_sys_msgctl" // msqid = $first // cmd = $second // buf_uaddr = $uptr // argstr = sprintf("%d, %d, %p", $first, $second, $uptr) asmlinkage() msqid = int_arg(1) cmd = int_arg(2) buf_uaddr = pointer_arg(3) argstr = sprintf("%d, %d, %p", int_arg(1), int_arg(2), pointer_arg(3)) } probe nd_syscall.compat_sys_msgctl.return = kprobe.function("compat_sys_msgctl").return ? { name = "compat_sys_msgctl" retstr = returnstr(1) } # msgget _____________________________________________________ # long sys_msgget (key_t key, int msgflg) # probe nd_syscall.msgget = kprobe.function("sys_msgget") ? { name = "msgget" // key = $key // msgflg = $msgflg // msgflg_str = _sys_open_flag_str($msgflg) // argstr = sprintf("%d, %s", $key, _sys_open_flag_str($msgflg)) asmlinkage() key = int_arg(1) msgflg = int_arg(2) msgflg_str = _sys_open_flag_str(msgflg) argstr = sprintf("%d, %s", key, _sys_open_flag_str(msgflg)) } probe nd_syscall.msgget.return = kprobe.function("sys_msgget").return ? { name = "msgget" retstr = returnstr(1) } # msgrcv _____________________________________________________ # long sys_msgrcv (int msqid, # struct msgbuf __user *msgp, # size_t msgsz, # long msgtyp, # int msgflg) # probe nd_syscall.msgrcv = kprobe.function("sys_msgrcv") ? { name = "msgrcv" // msqid = $msqid // msgp_uaddr = $msgp // msgsz = $msgsz // msgtyp = $msgtyp // msgflg = $msgflg // argstr = sprintf("%d, %p, %d, %d, %d", $msqid, $msgp, $msgsz, $msgtyp, $msgflg) asmlinkage() msqid = int_arg(1) msgp_uaddr = pointer_arg(2) msgsz = ulong_arg(3) msgtyp = long_arg(4) msgflg = int_arg(5) argstr = sprintf("%d, %p, %d, %d, %d", msqid, msgp_uaddr, msgsz, msgtyp, msgflg) } probe nd_syscall.msgrcv.return = kprobe.function("sys_msgrcv").return ? { name = "msgrcv" retstr = returnstr(1) } # compat_sys_msgrcv ________________________________________ # # long compat_sys_msgrcv(int first, int second, int msgtyp, int third, # int version, void __user *uptr) # probe nd_syscall.compat_sys_msgrcv = kprobe.function("compat_sys_msgrcv") ? { name = "compat_sys_msgrcv" // msqid = $first // msgp_uaddr = $uptr // msgsz = $second // msgtyp = $msgtyp // msgflg = $third // argstr = sprintf("%d, %p, %d, %d", $first, $uptr, $second, $third) asmlinkage() msqid = int_arg(1) msgp_uaddr = pointer_arg(5) msgsz = int_arg(2) msgtyp = int_arg(3) msgflg = int_arg(4) argstr = sprintf("%d, %p, %d, %d", msqid, msgp_uaddr, msgsz, msgflg) } probe nd_syscall.compat_sys_msgrcv.return = kprobe.function("compat_sys_msgrcv").return ? { name = "compat_sys_msgrcv" retstr = returnstr(1) } # msgsnd _____________________________________________________ # long sys_msgsnd (int msqid, # struct msgbuf __user *msgp, # size_t msgsz, # int msgflg) # probe nd_syscall.msgsnd = kprobe.function("sys_msgsnd") ? { name = "msgsnd" // msqid = $msqid // msgp_uaddr = $msgp // msgsz = $msgsz // msgflg = $msgflg // argstr = sprintf("%d, %p, %d, %d", $msqid, $msgp, $msgsz, $msgflg) asmlinkage() msqid = int_arg(1) msgp_uaddr = pointer_arg(2) msgsz = ulong_arg(3) msgflg = int_arg(4) argstr = sprintf("%d, %p, %d, %d", msqid, msgp_uaddr, msgsz, msgflg) } probe nd_syscall.msgsnd.return = kprobe.function("sys_msgsnd").return ? { name = "msgsnd" retstr = returnstr(1) } # compat_sys_msgsnd ________________________________________ # # long compat_sys_msgsnd(int first, int second, int third, void __user *uptr) # probe nd_syscall.compat_sys_msgsnd = kprobe.function("compat_sys_msgsnd") ? { name = "compat_sys_msgsnd" // msqid = $first // msgp_uaddr = $uptr // msgsz = $second // msgflg = $third // argstr = sprintf("%d, %p, %d, %d", $first, $uptr, $second, $third) asmlinkage() msqid = int_arg(1) msgp_uaddr = pointer_arg(4) msgsz = int_arg(2) msgflg = int_arg(3) argstr = sprintf("%d, %p, %d, %d", msqid, msgp_uaddr, msgsz, msgflg) } probe nd_syscall.compat_sys_msgsnd.return = kprobe.function("compat_sys_msgsnd").return ? { name = "compat_sys_msgsnd" retstr = returnstr(1) } # msync ______________________________________________________ # long sys_msync(unsigned long start, size_t len, int flags) probe nd_syscall.msync = kprobe.function("sys_msync") ? { name = "msync" // start = $start // length = $len // flags = $flags asmlinkage() start = ulong_arg(1) length = ulong_arg(2) flags = int_arg(3) argstr = sprintf("%p, %d, %s", start, length, _msync_flag_str(flags)) } probe nd_syscall.msync.return = kprobe.function("sys_msync").return ? { name = "msync" retstr = returnstr(1) } # munlock ____________________________________________________ # long sys_munlock(unsigned long start, size_t len) probe nd_syscall.munlock = kprobe.function("sys_munlock") ? { name = "munlock" // addr = $start // len = $len asmlinkage() addr = ulong_arg(1) len = ulong_arg(2) argstr = sprintf("%p, %d", addr, len) } probe nd_syscall.munlock.return = kprobe.function("sys_munlock").return ? { name = "munlock" retstr = returnstr(1) } # munlockall _________________________________________________ # long sys_munlockall(void) probe nd_syscall.munlockall = kprobe.function("sys_munlockall") ? { name = "munlockall" argstr = "" } probe nd_syscall.munlockall.return = kprobe.function("sys_munlockall").return ? { name = "munlockall" retstr = returnstr(1) } # munmap _____________________________________________________ # long sys_munmap(unsigned long addr, size_t len) probe nd_syscall.munmap = kprobe.function("sys_munmap") ? { name = "munmap" // start = $addr // length = $len asmlinkage() start = ulong_arg(1) length = ulong_arg(2) argstr = sprintf("%p, %d", start, length) } probe nd_syscall.munmap.return = kprobe.function("sys_munmap").return ? { name = "munmap" retstr = returnstr(1) } systemtap-2.3/tapset/linux/nd_syscalls2.stp000066400000000000000000003753371217430427200212220ustar00rootroot00000000000000// syscalls tapset part 2 [N-Z] // Copyright (C) 2005 IBM Corp. // Copyright (C) 2005, 2006, 2007, 2010, 2013 Red Hat Inc. // Copyright (C) 2007 Quentin Barnes. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /* Each syscall returns the calls parameters. In addition, the following * variables are set: * * name - generally the syscall name minus the "sys_". * * argstr - a string containing the decoded args in an easy-to-read format. * It doesn't need to contain everything, but should have all the * important args. Set in entry probes only. * * retstr - a string containing the return value in an easy-to-read format. * Set in return probes only. */ # nanosleep __________________________________________________ # # long sys_nanosleep(struct timespec __user *rqtp, # struct timespec __user *rmtp) # long compat_sys_nanosleep(struct compat_timespec __user *rqtp, # struct compat_timespec __user *rmtp) # probe nd_syscall.nanosleep = kprobe.function("sys_nanosleep") ? { name = "nanosleep" // req_uaddr = $rqtp // rem_uaddr = $rmtp // argstr = sprintf("%s, %p", _struct_timespec_u($rqtp, 1), $rmtp) asmlinkage() req_uaddr = pointer_arg(1) rem_uaddr = pointer_arg(2) argstr = sprintf("%s, %p", _struct_timespec_u(req_uaddr, 1), rem_uaddr) } probe nd_syscall.nanosleep.return = kprobe.function("sys_nanosleep").return ? { name = "nanosleep" retstr = returnstr(1) } probe nd_syscall.compat_nanosleep = kprobe.function("compat_sys_nanosleep") ? { name = "nanosleep" // req_uaddr = $rqtp // rem_uaddr = $rmtp // argstr = sprintf("%s, %p", _struct_compat_timespec_u($rqtp, 1), $rmtp) asmlinkage() req_uaddr = pointer_arg(1) rem_uaddr = pointer_arg(2) argstr = sprintf("%s, %p", _struct_compat_timespec_u(req_uaddr, 1), rem_uaddr) } probe nd_syscall.compat_nanosleep.return = kprobe.function("compat_sys_nanosleep").return ? { name = "nanosleep" retstr = returnstr(1) } # nfsservctl _________________________________________________ # # long sys_nfsservctl(int cmd, struct nfsctl_arg __user *arg, void __user *res) # long compat_sys_nfsservctl(int cmd, struct compat_nfsctl_arg __user *arg, # union compat_nfsctl_res __user *res) # # nfsservctl was removed in kernel 3.0/2.6.40. %( kernel_v < "2.6.40" && CONFIG_NFSD == "[ym]" %? probe nd_syscall.nfsservctl = kprobe.function("sys_nfsservctl") ?, kprobe.function("compat_sys_nfsservctl") ? { name = "nfsservctl" // cmd = $cmd // argp_uaddr = $arg // resp_uaddr = $res // argstr = sprintf("%s, %p, %p", _nfsctl_cmd_str($cmd), $arg, $res) asmlinkage() cmd = int_arg(1) argp_uaddr = pointer_arg(2) resp_uaddr = pointer_arg(3) argstr = sprintf("%s, %p, %p", _nfsctl_cmd_str(cmd), argp_uaddr, resp_uaddr) } probe nd_syscall.nfsservctl.return = kprobe.function("sys_nfsservctl").return ?, kprobe.function("compat_sys_nfsservctl").return ? { name = "nfsservctl" retstr = returnstr(1) } %) # nice _______________________________________________________ # long sys_nice(int increment) # probe nd_syscall.nice = kprobe.function("sys_nice") ? { name = "nice" // inc = $increment // argstr = sprintf("%d", $increment) asmlinkage() inc = int_arg(1) argstr = sprintf("%d", inc) } probe nd_syscall.nice.return = kprobe.function("sys_nice").return ? { name = "nice" retstr = returnstr(1) } # ni_syscall _________________________________________________ # # long sys_ni_syscall(void) # probe nd_syscall.ni_syscall = kprobe.function("sys_ni_syscall") { name = "ni_syscall" argstr = "" } probe nd_syscall.ni_syscall.return = kprobe.function("sys_ni_syscall").return { name = "ni_syscall" retstr = returnstr(1) } # open _______________________________________________________ # long sys_open(const char __user * filename, int flags, int mode) # (obsolete) long sys32_open(const char * filename, int flags, int mode) # probe nd_syscall.open = kprobe.function("compat_sys_open") ?, kprobe.function("sys32_open") ?, kprobe.function("sys_open") ? { name = "open" // filename = user_string($filename) // flags = $flags // mode = $mode // if (flags & 64) // argstr = sprintf("%s, %s, %#o", user_string_quoted($filename), // _sys_open_flag_str($flags), $mode) // else // argstr = sprintf("%s, %s", user_string_quoted($filename), // _sys_open_flag_str($flags)) asmlinkage() filename = user_string_quoted(pointer_arg(1)) flags = int_arg(2) mode = int_arg(3) if (flags & 64) argstr = sprintf("%s, %s, %#o", user_string_quoted(pointer_arg(1)), _sys_open_flag_str(flags), mode) else argstr = sprintf("%s, %s", user_string_quoted(pointer_arg(1)), _sys_open_flag_str(flags)) } probe nd_syscall.open.return = kprobe.function("compat_sys_open").return ?, kprobe.function("sys32_open").return ?, kprobe.function("sys_open").return ? { name = "open" retstr = returnstr(1) } # openat _______________________________________________________ # long sys_openat(int dfd, const char __user *filename, int flags, int mode) # long compat_sys_openat(unsigned int dfd, const char __user *filename, int flags, int mode) # probe nd_syscall.openat = kprobe.function("compat_sys_openat") ?, kprobe.function("sys_openat") ? { name = "openat" // filename = user_string($filename) // flags = $flags // mode = $mode // if ($flags & 64) // argstr = sprintf("%s, %s, %s, %#o", _dfd_str($dfd), // user_string_quoted($filename), // _sys_open_flag_str($flags), $mode) // else // argstr = sprintf("%s, %s, %s", _dfd_str($dfd), // user_string_quoted($filename), // _sys_open_flag_str($flags)) asmlinkage() filename = user_string_quoted(pointer_arg(2)) flags = int_arg(3) mode = int_arg(4) if (flags & 64) argstr = sprintf("%s, %s, %s, %#o", _dfd_str(int_arg(1)), user_string_quoted(pointer_arg(2)), _sys_open_flag_str(flags), mode) else argstr = sprintf("%s, %s, %s", _dfd_str(int_arg(1)), user_string_quoted(pointer_arg(2)), _sys_open_flag_str(flags)) } probe nd_syscall.openat.return = kprobe.function("compat_sys_openat").return ?, kprobe.function("sys_openat").return ? { name = "openat" retstr = returnstr(1) } # pause ______________________________________________________ # # sys_pause(void) # probe nd_syscall.pause = kprobe.function("sys_pause") ?, kprobe.function("sys32_pause") ?, kprobe.function("compat_sys_pause") ? { name = "pause" argstr = "" } probe nd_syscall.pause.return = kprobe.function("sys_pause").return ?, kprobe.function("sys32_pause").return ?, kprobe.function("compat_sys_pause").return ? { name = "pause" retstr = returnstr(1) } # pciconfig_iobase ___________________________________________ # # asmlinkage long # sys_pciconfig_iobase(long which, # unsigned long bus, # unsigned long dfn) # # #probe nd_syscall.pciconfig_iobase = kprobe.function("sys_pciconfig_iobase") #{ # name = "pciconfig_iobase" # which = $which # bus = $bus # dfn = $dfn # argstr = sprintf("%p, %p, %p", which, bus, dfn) #} #probe nd_syscall.pciconfig_iobase.return = kprobe.function("sys_pciconfig_iobase").return #{ # name = "pciconfig_iobase" # retstr = returnstr(1) #} # pciconfig_read _____________________________________________ # # asmlinkage int # sys_pciconfig_read(unsigned long bus, # unsigned long dfn, # unsigned long off, # unsigned long len, # unsigned char *buf) # { return 0; } # # #probe nd_syscall.pciconfig_read = kprobe.function("sys_pciconfig_read") #{ # name = "pciconfig_read" # bus = $bus # dfn = $dfn # off = $off # len = $len # buf_uaddr = $buf # argstr = sprintf("%p, %p, %p, %d, %p", bus, dfn, off, # len, buf_uaddr) #} #probe nd_syscall.pciconfig_read.return = kprobe.function("sys_pciconfig_read").return #{ # name = "pciconfig_read" # retstr = returnstr(1) #} # pciconfig_write ____________________________________________ # # asmlinkage int # sys_pciconfig_write(unsigned long bus, # unsigned long dfn, # unsigned long off, # unsigned long len, # unsigned char *buf) # # #probe nd_syscall.pciconfig_write = kprobe.function("sys_pciconfig_write") #{ # name = "pciconfig_write" # bus = $bus # dfn = $dfn # off = $off # len = $len # buf_uaddr = $buf # argstr = sprintf("%p, %p, %p, %d, %p", bus, dfn, off, # len, buf_uaddr) #} #probe nd_syscall.pciconfig_write.return = kprobe.function("sys_pciconfig_write").return #{ # name = "pciconfig_write" # retstr = returnstr(1) #} # personality ________________________________________________ # # asmlinkage long # sys_personality(u_long personality) # probe nd_syscall.personality = kprobe.function("sys_personality") ? { name = "personality" // persona = $personality asmlinkage() persona = ulong_arg(1) argstr = sprintf("%p", persona); } probe nd_syscall.personality.return = kprobe.function("sys_personality").return ? { name = "personality" retstr = returnstr(1) } # pipe _______________________________________________________ # # asmlinkage int # sys_pipe(unsigned long __user * fildes) # # SYSCALL_DEFINE2(pipe2, int __user *, fildes, int, flags) # # FIXME: When ia64 kprobe support is added (PR6971 - nd_syscalls.stp # tapset broken on ia64), sys_ia64_pipe probing will need to be done # here. probe nd_syscall.pipe = __nd_syscall.pipe2 !, __nd_syscall.pipe { } probe __nd_syscall.pipe2 = kprobe.function("sys_pipe2") { %( arch != "powerpc" %? asmlinkage() %) flags = int_arg(2) flag_str = _sys_pipe2_flag_str(flags); name = flags == 0 ? "pipe" : "pipe2"; fildes_uaddr = pointer_arg(1) if (fildes_uaddr == 0) { pipe0 = 0; pipe1 = 0; argstr = "NULL" } else { pipe0 = _fildes_index_u(fildes_uaddr, 0) pipe1 = _fildes_index_u(fildes_uaddr, 1) if (flags == 0) argstr = sprintf("[%d, %d]", pipe0, pipe1); else argstr = sprintf("[%d, %d], %s", pipe0, pipe1, flag_str); } } probe __nd_syscall.pipe = kprobe.function("sys_pipe") { name = "pipe" flags = 0 flag_str = "" %( arch != "powerpc" %? asmlinkage() %) fildes_uaddr = pointer_arg(1) if (fildes_uaddr == 0) { pipe0 = 0; pipe1 = 0; argstr = "NULL" } else { pipe0 = _fildes_index_u(fildes_uaddr, 0) pipe1 = _fildes_index_u(fildes_uaddr, 1) argstr = sprintf("[%d, %d]", pipe0, pipe1); } } probe nd_syscall.pipe.return = __nd_syscall.pipe2.return !, __nd_syscall.pipe.return { } probe __nd_syscall.pipe2.return = kprobe.function("sys_pipe2").return { flags = @entry(%( arch != "powerpc" %? __asmlinkage_int_arg(2) %: int_arg(2) %)) name = (flags == 0) ? "pipe" : "pipe2"; fildes_uaddr = @entry(pointer_arg(1)) if (fildes_uaddr == 0) { pipe0 = 0; pipe1 = 0; } else { pipe0 = _fildes_index_u(fildes_uaddr, 0) pipe1 = _fildes_index_u(fildes_uaddr, 1) } retstr = returnstr(1) } probe __nd_syscall.pipe.return = kprobe.function("sys_pipe").return { flags = 0 name = "pipe" fildes_uaddr = @entry(%( arch != "powerpc" %? __asmlinkage_int_arg(1) %: int_arg(1) %)) if (fildes_uaddr == 0) { pipe0 = 0; pipe1 = 0; } else { pipe0 = _fildes_index_u(fildes_uaddr, 0) pipe1 = _fildes_index_u(fildes_uaddr, 1) } retstr = returnstr(1) } # pivot_root _________________________________________________ # # long sys_pivot_root(const char __user *new_root, const char __user *put_old) # probe nd_syscall.pivot_root = kprobe.function("sys_pivot_root") ? { name = "pivot_root" // new_root_str = user_string($new_root) // old_root_str = user_string($put_old) // argstr = sprintf("%s, %s", user_string_quoted($new_root), // user_string_quoted($put_old)) asmlinkage() new_root_str = user_string_quoted(pointer_arg(1)) old_root_str = user_string_quoted(pointer_arg(2)) argstr = sprintf("%s, %s", user_string_quoted(pointer_arg(1)), user_string_quoted(pointer_arg(2))) } probe nd_syscall.pivot_root.return = kprobe.function("sys_pivot_root").return ? { name = "pivot_root" retstr = returnstr(1) } # poll _______________________________________________________ # # long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long timeout) # probe nd_syscall.poll = kprobe.function("sys_poll") ? { name = "poll" // ufds_uaddr = $ufds // nfds = $nfds // timeout = $timeout // argstr = sprintf("%p, %d, %d", $ufds, $nfds, timeout) asmlinkage() ufds_uaddr = pointer_arg(1) nfds = uint_arg(2) timeout = long_arg(3) argstr = sprintf("%p, %d, %d", ufds_uaddr, nfds, timeout) } probe nd_syscall.poll.return = kprobe.function("sys_poll").return ? { name = "poll" retstr = returnstr(1) } # ppoll _______________________________________________________ # # long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds, # struct timespec __user *tsp, const sigset_t __user *sigmask, # size_t sigsetsize) # probe nd_syscall.ppoll = kprobe.function("sys_ppoll") ? { name = "ppoll" // argstr = sprintf("%p, %d, %s, %p, %d", // $ufds, // $nfds, // _struct_timespec_u($tsp, 1), // $sigmask, // $sigsetsize) asmlinkage() argstr = sprintf("%p, %d, %s, %p, %d", pointer_arg(1), uint_arg(2), _struct_timespec_u(pointer_arg(3), 1), pointer_arg(4), ulong_arg(5)) } probe nd_syscall.ppoll.return = kprobe.function("sys_ppoll").return ? { name = "ppoll" retstr = returnstr(1) } # long compat_sys_ppoll(struct pollfd __user *ufds, # unsigned int nfds, struct compat_timespec __user *tsp, # const compat_sigset_t __user *sigmask, compat_size_t sigsetsize) # probe nd_syscall.compat_ppoll = kprobe.function("compat_sys_ppoll") ? { name = "ppoll" // argstr = sprintf("%p, %d, %s, %p, %d", // $ufds, // $nfds, // _struct_compat_timespec_u($tsp, 1), // $sigmask, // $sigsetsize) asmlinkage() argstr = sprintf("%p, %d, %s, %p, %d", pointer_arg(1), uint_arg(2), _struct_compat_timespec_u(pointer_arg(3), 1), pointer_arg(4), u32_arg(5)) } probe nd_syscall.compat_ppoll.return = kprobe.function("compat_sys_ppoll").return ? { name = "ppoll" retstr = returnstr(1) } # prctl ______________________________________________________ # # asmlinkage long # sys_prctl(int option, # unsigned long arg2, # unsigned long arg3, # unsigned long arg4, # unsigned long arg5) # probe nd_syscall.prctl = kprobe.function("sys_prctl") ? { name = "prctl" // option = $option // arg2 = $arg2 // arg3 = $arg3 // arg4 = $arg4 // arg5 = $arg5 asmlinkage() option = int_arg(1) arg2 = ulong_arg(2) arg3 = ulong_arg(3) arg4 = ulong_arg(4) arg5 = ulong_arg(5) argstr = sprintf("%p, %p, %p, %p, %p", option, arg2, arg3, arg4, arg5) } probe nd_syscall.prctl.return = kprobe.function("sys_prctl").return ? { name = "prctl" retstr = returnstr(1) } # pread64 ____________________________________________________ # # ssize_t sys_pread64(unsigned int fd, # char __user *buf, # size_t count, # loff_t pos) # probe nd_syscall.pread = kprobe.function("sys_pread64") ? { name = "pread" // fd = $fd // buf_uaddr = $buf // count = $count // offset = $pos // argstr = sprintf("%d, %p, %d, %d", $fd, $buf, $count, $pos) asmlinkage() fd = uint_arg(1) buf_uaddr = pointer_arg(2) count = ulong_arg(3) offset = longlong_arg(4) argstr = sprintf("%d, %p, %d, %d", fd, buf_uaddr, count, offset) } probe nd_syscall.pread.return = kprobe.function("sys_pread64").return ? { name = "pread" retstr = returnstr(1) } # pselect6 _____________________________________________________ # # long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp, # fd_set __user *exp, struct timespec __user *tsp, void __user *sig) # probe nd_syscall.pselect6 = kprobe.function("sys_pselect6") ? { name = "pselect6" // argstr = sprintf("%d, %p, %p, %p, %s, %p", $n, $inp, $outp, $exp, // _struct_timespec_u($tsp, 1), $sig) asmlinkage() argstr = sprintf("%d, %p, %p, %p, %s, %p", int_arg(1) , pointer_arg(2), pointer_arg(3), pointer_arg(4), _struct_timespec_u(pointer_arg(5), 1), pointer_arg(6)) } probe nd_syscall.pselect6.return = kprobe.function("sys_pselect6").return ? { name = "pselect6" retstr = returnstr(1) } probe nd_syscall.compat_pselect6 = kprobe.function("compat_sys_pselect6") ? { name = "pselect6" // argstr = sprintf("%d, %p, %p, %p, %s, %p", $n, $inp, $outp, $exp, // _struct_compat_timespec_u($tsp, 1), $sig) asmlinkage() argstr = sprintf("%d, %p, %p, %p, %s, %p", int_arg(1), pointer_arg(2), pointer_arg(3), pointer_arg(4), _struct_compat_timespec_u(pointer_arg(5), 1), pointer_arg(6)) } probe nd_syscall.compat_pselect6.return = kprobe.function("compat_sys_pselect6").return ? { name = "pselect6" retstr = returnstr(1) } # pselect7 _____________________________________________________ # # long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp, # fd_set __user *exp, struct timespec __user *tsp, # const sigset_t __user *sigmask, size_t sigsetsize) # probe nd_syscall.pselect7 = kprobe.function("sys_pselect7") ? { name = "pselect7" // argstr = sprintf("%d, %p, %p, %p, %s, %p, %d", $n, $inp, $outp, $exp, // _struct_timespec_u($tsp, 1), $sigmask, $sigsetsize) asmlinkage() argstr = sprintf("%d, %p, %p, %p, %s, %p, %d", int_arg(1), pointer_arg(2), pointer_arg(3), pointer_arg(4), _struct_timespec_u(pointer_arg(5), 1), pointer_arg(6), %( arch != "s390" %? ulong_arg(7)) %: -1) %) } probe nd_syscall.pselect7.return = kprobe.function("sys_pselect7").return ? { name = "pselect7" retstr = returnstr(1) } # Through a typo, 'compat_pselect7' was misnamed as # 'compat_pselect7a' (notice the trailing 'a'). The old name is # deprecated. To use the old name without changing your script, use # the '--compatible 1.4' stap option. probe %( systemtap_v <= "1.4" %? nd_syscall.compat_pselect7a %: nd_syscall.compat_pselect7 %) = kprobe.function("compat_sys_pselect7") ? { name = "pselect7" //argstr = sprintf("%d, %p, %p, %p, %s, %p, %d", $n, $inp, $outp, $exp, // _struct_compat_timespec_u($tsp, 1), $sigmask, $sigsetsize) asmlinkage() argstr = sprintf("%d, %p, %p, %p, %s, %p, %d", int_arg(1), pointer_arg(2), pointer_arg(3), pointer_arg(4), _struct_timespec_u(pointer_arg(5), 1), pointer_arg(6), %( arch != "s390" %? ulong_arg(7)) %: -1) %) } probe nd_syscall.compat_pselect7.return = kprobe.function("compat_sys_pselect7").return ? { name = "pselect7" retstr = returnstr(1) } # ptrace _____________________________________________________ # # int sys_ptrace(long request, # long pid, # long addr, # long data) # probe nd_syscall.ptrace = kprobe.function("sys_ptrace") ? { name = "ptrace" // request = $request // pid = $pid // addr = $addr // data = $data asmlinkage() request = long_arg(1) pid = long_arg(2) addr = long_arg(3) data = long_arg(4) argstr = _ptrace_argstr(request, pid, addr, data) } probe nd_syscall.ptrace.return = kprobe.function("sys_ptrace").return ? { name = "ptrace" retstr = returnstr(1) // long_arg values are not available here. geteventmsg_data = 0 arch_prctl_addr = 0 } # pwrite64 ___________________________________________________ # # ssize_t sys_pwrite64(unsigned int fd, # const char __user *buf, # size_t count, # loff_t pos) # probe nd_syscall.pwrite = kprobe.function("sys_pwrite64") ? { name = "pwrite" // fd = $fd // buf_uaddr = $buf // count = $count // offset = $pos // argstr = sprintf("%d, %s, %d, %d", $fd, // text_strn(user_string($buf), syscall_string_trunc, 1), // $count, $pos) asmlinkage() fd = uint_arg(1) buf_uaddr = pointer_arg(2) count = ulong_arg(3) offset = longlong_arg(4) argstr = sprintf("%d, %s, %d, %d", fd, user_string_n_quoted(buf_uaddr, syscall_string_trunc), count, offset) } probe nd_syscall.pwrite.return = kprobe.function("sys_pwrite64").return ? { name = "pwrite" retstr = returnstr(1) } # long sys32_pwrite64(unsigned int fd, const char __user *ubuf, # size_t count, u32 poshi, u32 poslo) probe nd_syscall.pwrite32 = kprobe.function("sys32_pwrite64") ? { name = "pwrite" // fd = $fd // buf_uaddr = $buf // count = $count // offset = ($poshi << 32) + $poslo // %( arch == "s390" %? // buf_uaddr = $ubuf // argstr = sprintf("%d, %s, %d, %d", $fd, // text_strn(user_string($ubuf), syscall_string_trunc, 1), // $count, ($poshi << 32) + $poslo) // %: // buf_uaddr = $buf // argstr = sprintf("%d, %s, %d, %d", $fd, // text_strn(user_string($buf), syscall_string_trunc, 1), // $count, ($poshi << 32) + $poslo) // %) asmlinkage() fd = uint_arg(1) buf_uaddr = pointer_arg(2) count = ulong_arg(3) offset = (u32_arg(4) << 32) + u32_arg(5) argstr = sprintf("%d, %s, %d, %d", fd, user_string_n_quoted(buf_uaddr, syscall_string_trunc), count, offset) } probe nd_syscall.pwrite32.return = kprobe.function("sys32_pwrite64").return ? { name = "pwrite" retstr = returnstr(1) } # quotactl ___________________________________________________ # # long sys_quotactl(unsigned int cmd, # const char __user *special, # qid_t id, # void __user *addr) # probe nd_syscall.quotactl = kprobe.function("sys_quotactl") ? { name = "quotactl" // cmd = $cmd // cmd_str = _quotactl_cmd_str($cmd) // special = $special // special_str = user_string($special) // id = $id // addr_uaddr = $addr // argstr = sprintf("%s, %s, %d, %p", cmd_str, special_str, $id, $addr) asmlinkage() cmd = uint_arg(1) cmd_str = _quotactl_cmd_str(cmd) special = pointer_arg(2) special_str = user_string_quoted(special) id = uint_arg(3) addr_uaddr = pointer_arg(4) argstr = sprintf("%s, %s, %d, %p", cmd_str, special_str, id, addr_uaddr) } probe nd_syscall.quotactl.return = kprobe.function("sys_quotactl").return ? { name = "quotactl" retstr = returnstr(1) } # read _______________________________________________________ # ssize_t sys_read(unsigned int fd, char __user * buf, size_t count) probe nd_syscall.read = kprobe.function("sys_read") ? { name = "read" // fd = $fd // buf_uaddr = $buf // count = $count // argstr = sprintf("%d, %p, %d", $fd, $buf, $count) asmlinkage() fd = uint_arg(1) buf_uaddr = pointer_arg(2) count = ulong_arg(3) argstr = sprintf("%d, %p, %d", fd, buf_uaddr, count) } probe nd_syscall.read.return = kprobe.function("sys_read").return ? { name = "read" retstr = returnstr(1) } # readahead __________________________________________________ # # asmlinkage ssize_t # sys_readahead(int fd, # loff_t offset, # size_t count) # probe nd_syscall.readahead = kprobe.function("sys_readahead") ? { name = "readahead" // fd = $fd // offset = $offset // count = $count asmlinkage() fd = int_arg(1) offset = longlong_arg(2) count = ulong_arg(3) argstr = sprintf("%d, %p, %p", fd, offset, count) } probe nd_syscall.readahead.return = kprobe.function("sys_readahead").return ? { name = "readahead" retstr = returnstr(1) } # readdir ___________________________________________________ # # long compat_sys_old_readdir(unsigned int fd, struct compat_old_linux_dirent __user *dirent, unsigned int count) # int old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent, unsigned int count) # probe nd_syscall.readdir = kprobe.function("compat_sys_old_readdir") ?, kprobe.function("old32_readdir") ? { name = "readdir" // argstr = sprintf("%d, %p, %d", $fd, $dirent, $count) asmlinkage() argstr = sprintf("%d, %p, %d", uint_arg(1), pointer_arg(2), uint_arg(3)) } probe nd_syscall.readdir.return = kprobe.function("compat_sys_old_readdir").return ?, kprobe.function("old32_readdir").return ? { name = "readdir" retstr = returnstr(1) } # readlink ___________________________________________________ # # long sys_readlink(const char __user * path, # char __user * buf, # int bufsiz) # probe nd_syscall.readlink = kprobe.function("sys_readlink") ? { name = "readlink" // path = user_string($path) // buf_uaddr = $buf // bufsiz = $bufsiz // argstr = sprintf("%s, %p, %d", user_string_quoted($path), // $buf, $bufsiz) asmlinkage() path = user_string_quoted(pointer_arg(1)) buf_uaddr = pointer_arg(2) bufsiz = int_arg(3) argstr = sprintf("%s, %p, %d", user_string_quoted(pointer_arg(1)), buf_uaddr, bufsiz) } probe nd_syscall.readlink.return = kprobe.function("sys_readlink").return ? { name = "readlink" retstr = returnstr(1) } # readlinkat ___________________________________________________ # # long sys_readlinkat(int dfd, const char __user * path, # char __user * buf, # int bufsiz) # probe nd_syscall.readlinkat = kprobe.function("sys_readlinkat") ? { name = "readlinkat" //dfd = $dfd // path = user_string($path) // buf_uaddr = $buf // bufsiz = $bufsiz // argstr = sprintf("%s, %s, %p, %d", _dfd_str($dfd), user_string_quoted($path), // $buf, $bufsiz) asmlinkage() dfd = int_arg(1) path = user_string_quoted(pointer_arg(2)) buf_uaddr = pointer_arg(3) bufsiz = int_arg(4) argstr = sprintf("%s, %s, %p, %d", _dfd_str(dfd), user_string_quoted(pointer_arg(2)), buf_uaddr, bufsiz) } probe nd_syscall.readlinkat.return = kprobe.function("sys_readlinkat").return ? { name = "readlinkat" retstr = returnstr(1) } # readv ______________________________________________________ # # ssize_t sys_readv(unsigned long fd, # const struct iovec __user *vec, # unsigned long vlen) # ssize_t compat_sys_readv(unsigned long fd, # const struct compat_iovec __user *vec, # unsigned long vlen) # probe nd_syscall.readv = kprobe.function("compat_sys_readv") ?, kprobe.function("sys_readv") ? { name = "readv" // vector_uaddr = $vec // count = $vlen // fd = $fd // argstr = sprintf("%d, %p, %d", $fd, $vec, $vlen) asmlinkage() vector_uaddr = pointer_arg(2) count = ulong_arg(3) fd = ulong_arg(1) argstr = sprintf("%d, %p, %d", fd, vector_uaddr, count) } probe nd_syscall.readv.return = kprobe.function("compat_sys_readv").return ?, kprobe.function("sys_readv").return ? { name = "readv" retstr = returnstr(1) } # reboot _____________________________________________________ # # long sys_reboot(int magic1, # int magic2, # unsigned int cmd, # void __user * arg) # probe nd_syscall.reboot = kprobe.function("sys_reboot") ? { name = "reboot" // magic = $magic1 // magic_str = _reboot_magic_str($magic1) // magic2 = $magic2 // magic2_str =_reboot_magic_str($magic2) // flag = $cmd // flag_str = _reboot_flag_str($cmd) // arg_uaddr = $arg // argstr = sprintf("%s, %s, %s, %p", magic_str, magic2_str, // flag_str, $arg) asmlinkage() magic = int_arg(1) magic_str = _reboot_magic_str(magic) magic2 = int_arg(2) magic2_str =_reboot_magic_str(magic2) flag = uint_arg(3) flag_str = _reboot_flag_str(flag) arg_uaddr = pointer_arg(4) argstr = sprintf("%s, %s, %s, %p", magic_str, magic2_str, flag_str, arg_uaddr) } probe nd_syscall.reboot.return = kprobe.function("sys_reboot").return ? { name = "reboot" retstr = returnstr(1) } # recv _______________________________________________________ # # long sys_recv(int fd, void __user *ubuf, size_t size, unsigned flags) # probe nd_syscall.recv = kprobe.function("sys_recv") ? { name = "recv" // s = $fd // buf_uaddr = $ubuf // len = $size // flags = $flags // flags_str = _recvflags_str($flags) // argstr = sprintf("%d, %p, %d, %s", $fd, $ubuf, $size, _recvflags_str($flags)) asmlinkage() s = int_arg(1) buf_uaddr = pointer_arg(2) len = ulong_arg(3) flags = uint_arg(4) flags_str = _recvflags_str(flags) argstr = sprintf("%d, %p, %d, %s", s, buf_uaddr, len, flags_str) } probe nd_syscall.recv.return = kprobe.function("sys_recv").return ? { name = "recv" retstr = returnstr(1) } # recvfrom ___________________________________________________ # # long sys_recvfrom(int fd, # void __user * ubuf, # size_t size, # unsigned flags, # struct sockaddr __user *addr, # int __user *addr_len) # probe nd_syscall.recvfrom = kprobe.function("sys_recvfrom") ? { name = "recvfrom" // s = $fd // buf_uaddr = $ubuf // len = $size // flags = $flags // flags_str = _recvflags_str($flags) // addr_uaddr = $addr // addrlen_uaddr = $addr_len // argstr = sprintf("%d, %p, %d, %s, %p, %p", // $fd, $ubuf, $size, _recvflags_str($flags), $addr, $addr_len) asmlinkage() s = int_arg(1) buf_uaddr = pointer_arg(2) len = ulong_arg(3) flags = uint_arg(4) flags_str = _recvflags_str(flags) addr_uaddr = pointer_arg(5) addrlen_uaddr = pointer_arg(6) argstr = sprintf("%d, %p, %d, %s, %p, %p", s, buf_uaddr, len, flags_str, addr_uaddr, addrlen_uaddr) } probe nd_syscall.recvfrom.return = kprobe.function("sys_recvfrom").return ? { name = "recvfrom" retstr = returnstr(1) } # recvmsg ____________________________________________________ # # long sys_recvmsg(int fd, # struct msghdr __user *msg, # unsigned int flags) # probe nd_syscall.recvmsg = kprobe.function("sys_recvmsg") ? { name = "recvmsg" // s = $fd // msg_uaddr = $msg // flags = $flags // flags_str = _recvflags_str($flags) // argstr = sprintf("%d, %p, %s", $fd, $msg, _recvflags_str($flags)) asmlinkage() s = int_arg(1) msg_uaddr = pointer_arg(2) flags = uint_arg(3) flags_str = _recvflags_str(flags) argstr = sprintf("%d, %p, %s", s, msg_uaddr, flags_str) } probe nd_syscall.recvmsg.return = kprobe.function("sys_recvmsg").return ? { name = "recvmsg" retstr = returnstr(1) } # compat_sys_recvmsg ________________________________________ # # long compat_sys_recvmsg(int fd, # struct compat_msghdr __user *msg, # unsigned int flags) # probe nd_syscall.compat_sys_recvmsg = kprobe.function("compat_sys_recvmsg") ? { name = "compat_sys_recvmsg" // s = $fd // msg_uaddr = $msg // flags = $flags // argstr = sprintf("%d, %p, %s", $fd, $msg, _recvflags_str($flags)) asmlinkage() s = int_arg(1) msg_uaddr = pointer_arg(2) flags = uint_arg(3) flags_str = _recvflags_str(flags) argstr = sprintf("%d, %p, %s", s, msg_uaddr, _recvflags_str(flags)) } probe nd_syscall.compat_sys_recvmsg.return = kprobe.function("compat_sys_recvmsg").return ? { name = "compat_sys_recvmsg" retstr = returnstr(1) } # remap_file_pages ___________________________________________ # # long sys_remap_file_pages(unsigned long start, # unsigned long size, # unsigned long __prot, # unsigned long pgoff, # unsigned long flags) # probe nd_syscall.remap_file_pages = kprobe.function("sys_remap_file_pages") ? { name = "remap_file_pages" // start = $start // size = $size // prot = (@defined($prot) ? $prot : $__prot) // pgoff = $pgoff // flags = $flags asmlinkage() start = ulong_arg(1) size = ulong_arg(2) prot = ulong_arg(3) pgoff = ulong_arg(4) flags = ulong_arg(5) argstr = sprintf("%p, %p, %p, %p, %p", start, size, prot, pgoff, flags) } probe nd_syscall.remap_file_pages.return = kprobe.function("sys_remap_file_pages").return ? { name = "remap_file_pages" retstr = returnstr(1) } # removexattr ________________________________________________ # # asmlinkage long # sys_removexattr(char __user *path, # char __user *name) # probe nd_syscall.removexattr = kprobe.function("sys_removexattr") ? { name = "removexattr" // path = user_string($path) // name_str = user_string($name) // argstr = sprintf("%s, %s", user_string_quoted($path), // user_string_quoted($name)) asmlinkage() path = user_string_quoted(pointer_arg(1)) name_str = user_string_quoted(pointer_arg(2)) argstr = sprintf("%s, %s", user_string_quoted(pointer_arg(1)), user_string_quoted(pointer_arg(2))) } probe nd_syscall.removexattr.return = kprobe.function("sys_removexattr").return ? { name = "removexattr" retstr = returnstr(1) } # rename _____________________________________________________ # # asmlinkage long # sys_rename(const char __user * oldname, # const char __user * newname) # probe nd_syscall.rename = kprobe.function("sys_rename") ? { name = "rename" // oldpath = user_string($oldname) // newpath = user_string($newname) // argstr = sprintf("%s, %s", user_string_quoted($oldname), // user_string_quoted($newname)) asmlinkage() oldpath = user_string_quoted(pointer_arg(1)) newpath = user_string_quoted(pointer_arg(2)) argstr = sprintf("%s, %s", user_string_quoted(pointer_arg(1)), user_string_quoted(pointer_arg(2))) } probe nd_syscall.rename.return = kprobe.function("sys_rename").return ? { name = "rename" retstr = returnstr(1) } # renameat ___________________________________________________ # new function with 2.6.16 # long sys_renameat(int olddfd, const char __user *oldname, # int newdfd, const char __user *newname) probe nd_syscall.renameat = kprobe.function("sys_renameat") ? { name = "renameat" // olddfd = $olddfd // olddfd_str = _dfd_str($olddfd) // oldname = $oldname // oldname_str = user_string($oldname) // newdfd = $newdfd // newdfd_str = _dfd_str($newdfd) // newname = $newname // newname_str = user_string($newname) // argstr = sprintf("%s, %s, %s, %s", // olddfd_str, user_string_quoted($oldname), // newdfd_str, user_string_quoted($newname)) asmlinkage() olddfd = int_arg(1) olddfd_str = _dfd_str(olddfd) oldname = pointer_arg(2) oldname_str = user_string_quoted(oldname) newdfd = int_arg(3) newdfd_str = _dfd_str(newdfd) newname = pointer_arg(4) newname_str = user_string_quoted(newname) argstr = sprintf("%s, %s, %s, %s", olddfd_str, user_string_quoted(oldname), newdfd_str, user_string_quoted(newname)) } probe nd_syscall.renameat.return = kprobe.function("sys_renameat").return ? { name = "renameat" retstr = returnstr(1) } # request_key ________________________________________________ # # long sys_request_key(const char __user *_type, # const char __user *_description, # const char __user *_callout_info, # key_serial_t destringid) # compat_sys_request_key() calls sys_request_key, so don't need probe there. # probe nd_syscall.request_key = kprobe.function("sys_request_key") ? { name = "request_key" // type_uaddr = $_type // description_uaddr = $_description // callout_info_uaddr = $_callout_info // destringid = $destringid // argstr = sprintf("%p, %p, %p, %p", $_type, $_description, $_callout_info, $destringid) asmlinkage() type_uaddr = pointer_arg(1) description_uaddr = pointer_arg(2) callout_info_uaddr = pointer_arg(3) destringid = u32_arg(4) argstr = sprintf("%p, %p, %p, %p", type_uaddr, description_uaddr, callout_info_uaddr, destringid) } probe nd_syscall.request_key.return = kprobe.function("sys_request_key").return ? { name = "request_key" retstr = returnstr(1) } # restart_syscall ____________________________________________ # # asmlinkage long # sys_restart_syscall(void) # probe nd_syscall.restart_syscall = kprobe.function("sys_restart_syscall") { name = "restart_syscall" argstr = "" } probe nd_syscall.restart_syscall.return = kprobe.function("sys_restart_syscall").return { name = "restart_syscall" retstr = returnstr(1) } # rmdir ______________________________________________________ # # asmlinkage long # sys_rmdir(const char __user * pathname) # probe nd_syscall.rmdir = kprobe.function("sys_rmdir") ? { name = "rmdir" // pathname = user_string($pathname) // argstr = user_string_quoted($pathname) asmlinkage() pathname = user_string_quoted(pointer_arg(1)) argstr = user_string_quoted(pointer_arg(1)) } probe nd_syscall.rmdir.return = kprobe.function("sys_rmdir").return ? { name = "rmdir" retstr = returnstr(1) } # rt_sigaction _______________________________________________ # # sys_rt_sigaction(int sig, # const struct sigaction __user *act, # struct sigaction __user *oact, # size_t sigsetsize) # probe nd_syscall.rt_sigaction = kprobe.function("sys_rt_sigaction") ? { name = "rt_sigaction" // sig = $sig // act_uaddr = $act // oact_uaddr = $oact // sigsetsize = $sigsetsize // argstr = sprintf("%s, {%s}, %p, %d", _signal_name($sig), // _struct_sigaction_u($act), $oact, $sigsetsize) asmlinkage() sig = int_arg(1) act_uaddr = pointer_arg(2) oact_uaddr = pointer_arg(3) sigsetsize = ulong_arg(4) argstr = sprintf("%s, {%s}, %p, %d", _signal_name(sig), _struct_sigaction_u(act_uaddr), oact_uaddr, sigsetsize) } probe nd_syscall.rt_sigaction.return = kprobe.function("sys_rt_sigaction").return ? { name = "rt_sigaction" retstr = returnstr(1) } # # long sys32_rt_sigaction(int sig, # struct sigaction32 __user *act, # struct sigaction32 __user *oact, # unsigned int sigsetsize) # ppc only # compat_sys_rt_sigaction(int sig, # const struct sigaction32 __user *act, # struct sigaction32 __user *oact, # size_t sigsetsize) probe nd_syscall.rt_sigaction32 = kprobe.function("sys32_rt_sigaction") ?, kprobe.function("compat_sys_rt_sigaction") ? { name = "rt_sigaction" // sig = $sig // act_uaddr = $act // oact_uaddr = $oact // sigsetsize = $sigsetsize // argstr = sprintf("%s, {%s}, %p, %d", _signal_name($sig), // _struct_sigaction32_u($act), $oact, $sigsetsize) asmlinkage() sig = int_arg(1) act_uaddr = pointer_arg(2) oact_uaddr = pointer_arg(3) sigsetsize = uint_arg(4) argstr = sprintf("%s, {%s}, %p, %d", _signal_name(sig), _struct_sigaction32_u(act_uaddr), oact_uaddr, sigsetsize) } probe nd_syscall.rt_sigaction32.return = kprobe.function("sys32_rt_sigaction").return ?, kprobe.function("compat_sys_rt_sigaction").return ? { name = "rt_sigaction" retstr = returnstr(1) } # rt_sigpending ______________________________________________ # # long sys_rt_sigpending(sigset_t __user *set, size_t sigsetsize) # probe nd_syscall.rt_sigpending = kprobe.function("sys_rt_sigpending") ? { name = "rt_sigpending" // set_uaddr = $set // sigsetsize = $sigsetsize // argstr = sprintf("%p, %d", $set, $sigsetsize) asmlinkage() set_uaddr = pointer_arg(1) sigsetsize = ulong_arg(2) argstr = sprintf("%p, %d", set_uaddr, sigsetsize) } probe nd_syscall.rt_sigpending.return = kprobe.function("sys_rt_sigpending").return ? { name = "rt_sigpending" retstr = returnstr(1) } # rt_sigprocmask _____________________________________________ # long sys_rt_sigprocmask(int how, sigset_t __user *set, sigset_t __user *oset, # size_t sigsetsize) # long sys32_rt_sigprocmask(u32 how, compat_sigset_t __user *set, # compat_sigset_t __user *oset, size_t sigsetsize) # long compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set, # compat_sigset_t __user *oset, # compat_size_t sigsetsize) # probe nd_syscall.rt_sigprocmask = kprobe.function("sys_rt_sigprocmask") ? { name = "rt_sigprocmask" // how = $how // how_str = _sigprocmask_how_str($how) // set_uaddr = $set // oldset_uaddr = $oset // argstr = sprintf("%s, [%s], %p, %d", how_str, _stp_sigset_u($set), // $oset, $sigsetsize) asmlinkage() how = int_arg(1) how_str = _sigprocmask_how_str(how) set_uaddr = pointer_arg(2) oldset_uaddr = pointer_arg(3) argstr = sprintf("%s, [%s], %p, %d", how_str, _stp_sigset_u(set_uaddr), oldset_uaddr, uint_arg(4)) } probe nd_syscall.rt_sigprocmask.return = kprobe.function("sys_rt_sigprocmask").return ? { name = "rt_sigprocmask" retstr = returnstr(1) } probe nd_syscall.compat_rt_sigprocmask = kprobe.function("compat_sys_rt_sigprocmask") ?, kprobe.function("sys32_rt_sigprocmask") ? { name = "rt_sigprocmask" // how = $how // how_str = _sigprocmask_how_str($how) // set_uaddr = @choose_defined($set, $nset) // oldset_uaddr = $oset // argstr = sprintf("%s, [%s], %p, %d", how_str, // _stp_compat_sigset_u(set_uaddr), $oset, $sigsetsize) if (symname(addr()) != "compat_sys_rt_sigprocmask") asmlinkage() how = int_arg(1) how_str = _sigprocmask_how_str(how) set_uaddr = pointer_arg(2) oldset_uaddr = pointer_arg(3) argstr = sprintf("%s, [%s], %p, %d", how_str, _stp_compat_sigset_u(set_uaddr), oldset_uaddr, uint_arg(4)) } probe nd_syscall.compat_rt_sigprocmask.return = kprobe.function("compat_sys_rt_sigprocmask").return ?, kprobe.function("sys32_rt_sigprocmask").return ? { name = "rt_sigprocmask" retstr = returnstr(1) } # rt_sigqueueinfo ____________________________________________ # # long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t __user *uinfo) # probe nd_syscall.rt_sigqueueinfo = kprobe.function("sys_rt_sigqueueinfo") ? { name = "rt_sigqueueinfo" // pid = $pid // sig = $sig // uinfo_uaddr = $uinfo // argstr = sprintf("%d, %s, %p", $pid, _signal_name($sig), $uinfo) asmlinkage() pid = int_arg(1) sig = int_arg(2) uinfo_uaddr = pointer_arg(3) argstr = sprintf("%d, %s, %p", pid, _signal_name(sig), uinfo_uaddr) } probe nd_syscall.rt_sigqueueinfo.return = kprobe.function("sys_rt_sigqueueinfo").return ? { name = "rt_sigqueueinfo" retstr = returnstr(1) } # rt_sigreturn _______________________________________________ # int sys_rt_sigreturn(unsigned long __unused) # probe nd_syscall.rt_sigreturn = kprobe.function("sys_rt_sigreturn") ?, kprobe.function("sys32_rt_sigreturn") ? { name = "rt_sigreturn" argstr = "" } probe nd_syscall.rt_sigreturn.return = kprobe.function("sys_rt_sigreturn").return ?, kprobe.function("sys32_rt_sigreturn").return ? { name = "rt_sigreturn" retstr = returnstr(1) } # rt_sigsuspend ______________________________________________ # # sys_rt_sigsuspend(struct pt_regs regs) # probe nd_syscall.rt_sigsuspend = kprobe.function("compat_sys_rt_sigsuspend") ?, kprobe.function("ia64_rt_sigsuspend") ?, kprobe.function("sys_rt_sigsuspend") ? { name = "rt_sigsuspend" argstr = "" } probe nd_syscall.rt_sigsuspend.return = kprobe.function("compat_sys_rt_sigsuspend").return ?, kprobe.function("ia64_rt_sigsuspend").return ?, kprobe.function("sys_rt_sigsuspend").return ? { name = "rt_sigsuspend" retstr = returnstr(1) } # rt_sigtimedwait ____________________________________________ # # long sys_rt_sigtimedwait(const sigset_t __user *uthese, # siginfo_t __user *uinfo, # const struct timespec __user *uts, # size_t sigsetsize) # long compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, # struct compat_siginfo __user *uinfo, # struct compat_timespec __user *uts, compat_size_t sigsetsize) # probe nd_syscall.rt_sigtimedwait = kprobe.function("compat_sys_rt_sigtimedwait") ?, kprobe.function("sys_rt_sigtimedwait") ? { name = "rt_sigtimedwait" // uthese_uaddr = $uthese // uinfo_uaddr = $uinfo // uts_uaddr = $uts // sigsetsize = $sigsetsize // argstr = sprintf("%p, %p, %p, %d", $uthese, $uinfo, $uts, $sigsetsize) asmlinkage() uthese_uaddr = pointer_arg(1) uinfo_uaddr = pointer_arg(2) uts_uaddr = pointer_arg(3) if (symname(addr()) == "sys_rt_sigtimedwait") sigsetsize = ulong_arg(4) else sigsetsize = u32_arg(4) argstr = sprintf("%p, %p, %p, %d", uthese_uaddr, uinfo_uaddr, uts_uaddr, sigsetsize) } probe nd_syscall.rt_sigtimedwait.return = kprobe.function("compat_sys_rt_sigtimedwait").return ?, kprobe.function("sys_rt_sigtimedwait").return ? { name = "rt_sigtimedwait" retstr = returnstr(1) } # sched_getaffinity __________________________________________ # # asmlinkage long # sys_sched_getaffinity(pid_t pid, # unsigned int len, # unsigned long __user *user_mask_ptr) # probe nd_syscall.sched_getaffinity = kprobe.function("sys_sched_getaffinity") ? { name = "sched_getaffinity" // pid = $pid // len = $len // mask_uaddr = $user_mask_ptr asmlinkage() pid = int_arg(1) len = uint_arg(2) mask_uaddr = pointer_arg(3) argstr = sprintf("%d, %p, %p", pid, len, mask_uaddr) } probe nd_syscall.sched_getaffinity.return = kprobe.function("sys_sched_getaffinity").return ? { name = "sched_getaffinity" retstr = returnstr(1) } # sched_getparam _____________________________________________ # # asmlinkage long # sys_sched_getparam(pid_t pid, # struct sched_param __user *param) # probe nd_syscall.sched_getparam = kprobe.function("sys_sched_getparam") ? { name = "sched_getparam" // pid = $pid // p_uaddr = $param asmlinkage() pid = int_arg(1) p_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", pid, p_uaddr) } probe nd_syscall.sched_getparam.return = kprobe.function("sys_sched_getparam").return ? { name = "sched_getparam" retstr = returnstr(1) } # sched_get_priority_max _____________________________________ # # asmlinkage long # sys_sched_get_priority_max(int policy) # probe nd_syscall.sched_get_priority_max = kprobe.function("sys_sched_get_priority_max") ? { name = "sched_get_priority_max" // policy = $policy asmlinkage() policy = int_arg(1) argstr = sprint(policy) } probe nd_syscall.sched_get_priority_max.return = kprobe.function("sys_sched_get_priority_max").return ? { name = "sched_get_priority_max" retstr = returnstr(1) } # sched_get_priority_min _____________________________________ # # asmlinkage long # sys_sched_get_priority_min(int policy) # probe nd_syscall.sched_get_priority_min = kprobe.function("sys_sched_get_priority_min") ? { name = "sched_get_priority_min" // policy = $policy asmlinkage() policy = int_arg(1) argstr = sprint(policy) } probe nd_syscall.sched_get_priority_min.return = kprobe.function("sys_sched_get_priority_min").return ? { name = "sched_get_priority_min" retstr = returnstr(1) } # sched_getscheduler _________________________________________ # # long sys_sched_getscheduler(pid_t pid) # probe nd_syscall.sched_getscheduler = kprobe.function("sys_sched_getscheduler") ? { name = "sched_getscheduler" // pid = $pid // argstr = sprint($pid) asmlinkage() pid = int_arg(1) argstr = sprint(pid) } probe nd_syscall.sched_getscheduler.return = kprobe.function("sys_sched_getscheduler").return ? { name = "sched_getscheduler" retstr = returnstr(1) } # sched_rr_get_interval ______________________________________ # # long sys_sched_rr_get_interval(pid_t pid, struct timespec __user *interval) # probe nd_syscall.sched_rr_get_interval = kprobe.function("sys_sched_rr_get_interval") ? { name = "sched_rr_get_interval" // pid = $pid // tp_uaddr = $interval // argstr = sprintf("%d, %s", $pid, _struct_timespec_u($interval, 1)) asmlinkage() pid = int_arg(1) tp_uaddr = pointer_arg(2) argstr = sprintf("%d, %s", pid, _struct_timespec_u(tp_uaddr, 1)) } probe nd_syscall.sched_rr_get_interval.return = kprobe.function("sys_sched_rr_get_interval").return ? { name = "sched_rr_get_interval" retstr = returnstr(1) } # sched_setaffinity __________________________________________ # long sys_sched_setaffinity(pid_t pid, # unsigned int len, # unsigned long __user *user_mask_ptr) # probe nd_syscall.sched_setaffinity = kprobe.function("sys_sched_setaffinity") ? { name = "sched_setaffinity" // pid = $pid // len = $len // mask_uaddr = $user_mask_ptr // argstr = sprintf("%d, %d, %p", $pid, $len, $user_mask_ptr) asmlinkage() pid = int_arg(1) len = uint_arg(2) mask_uaddr = pointer_arg(3) argstr = sprintf("%d, %d, %p", pid, len, mask_uaddr) } probe nd_syscall.sched_setaffinity.return = kprobe.function("sys_sched_setaffinity").return ? { name = "sched_setaffinity" retstr = returnstr(1) } # sched_setparam _____________________________________________ # # long sys_sched_setparam(pid_t pid, struct sched_param __user *param) # probe nd_syscall.sched_setparam = kprobe.function("sys_sched_setparam") ? { name = "sched_setparam" // pid = $pid // p_uaddr = $param // argstr = sprintf("%d, %p", $pid, $param) asmlinkage() pid = int_arg(1) p_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", pid, p_uaddr) } probe nd_syscall.sched_setparam.return = kprobe.function("sys_sched_setparam").return ? { name = "sched_setparam" retstr = returnstr(1) } # sched_setscheduler _________________________________________ # # long sys_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) # probe nd_syscall.sched_setscheduler = kprobe.function("sys_sched_setscheduler") ? { name = "sched_setscheduler" // pid = $pid // policy = $policy // policy_str = _sched_policy_str($policy) // p_uaddr = $param // argstr = sprintf("%d, %s, %p", $pid, policy_str, $param) asmlinkage() pid = int_arg(1) policy = int_arg(2) policy_str = _sched_policy_str(policy) p_uaddr = pointer_arg(3) argstr = sprintf("%d, %s, %p", pid, policy_str, p_uaddr) } probe nd_syscall.sched_setscheduler.return = kprobe.function("sys_sched_setscheduler").return ? { name = "sched_setscheduler" retstr = returnstr(1) } # sched_yield ________________________________________________ # long sys_sched_yield(void) # probe nd_syscall.sched_yield = kprobe.function("sys_sched_yield") { name = "sched_yield" argstr = "" } probe nd_syscall.sched_yield.return = kprobe.function("sys_sched_yield").return { name = "sched_yield" retstr = returnstr(1) } # select _____________________________________________________ # long sys_select(int n, # fd_set __user *inp, # fd_set __user *outp, # fd_set __user *exp, # struct timeval __user *tvp) # probe nd_syscall.select = kprobe.function("sys_select") ? { name = "select" // n = $n // readfds_uaddr = $inp // writefds_uaddr = $outp // exceptfds_uaddr = $exp // timeout_uaddr = $tvp // argstr = sprintf("%d, %p, %p, %p, %s", $n, $inp, $outp, $exp, // _struct_timeval_u($tvp, 1)) asmlinkage() n = int_arg(1) readfds_uaddr = pointer_arg(2) writefds_uaddr = pointer_arg(3) exceptfds_uaddr = pointer_arg(4) timeout_uaddr = pointer_arg(5) argstr = sprintf("%d, %p, %p, %p, %s", n, readfds_uaddr, writefds_uaddr, exceptfds_uaddr, _struct_timeval_u(timeout_uaddr, 1)) } probe nd_syscall.select.return = kprobe.function("sys_select").return ? { name = "select" retstr = returnstr(1) } # long compat_sys_select(int n, # compat_ulong_t __user *inp, # compat_ulong_t __user *outp, # compat_ulong_t __user *exp, # struct compat_timeval __user *tvp) # probe nd_syscall.compat_select = kprobe.function("compat_sys_select") ? { name = "select" // n = $n // readfds_uaddr = $inp // writefds_uaddr = $outp // exceptfds_uaddr = $exp // timeout_uaddr = $tvp // argstr = sprintf("%d, %p, %p, %p, %s", $n, $inp, $outp, $exp, // _struct_compat_timeval_u($tvp, 1)) asmlinkage() n = int_arg(1) readfds_uaddr = pointer_arg(2) writefds_uaddr = pointer_arg(3) exceptfds_uaddr = pointer_arg(4) timeout_uaddr = pointer_arg(5) argstr = sprintf("%d, %p, %p, %p, %s", n, readfds_uaddr, writefds_uaddr, exceptfds_uaddr, _struct_compat_timeval_u(timeout_uaddr, 1)) } probe nd_syscall.compat_select.return = kprobe.function("compat_sys_select").return ? { name = "select" retstr = returnstr(1) } # semctl _____________________________________________________ # long sys_semctl (int semid, # int semnum, # int cmd, # union semun arg) # probe nd_syscall.semctl = kprobe.function("sys_semctl") ? { name = "semctl" // semid = $semid // semnum = $semnum // cmd = $cmd /* * unsupported type tag identifier '$arg' * arg = $arg */ // argstr = sprintf("%d, %d, %s", $semid, $semnum, _semctl_cmd($cmd)) asmlinkage() semid = int_arg(1) semnum = int_arg(2) cmd = int_arg(3) argstr = sprintf("%d, %d, %s", semid, semnum, _semctl_cmd(cmd)) } probe nd_syscall.semctl.return = kprobe.function("sys_semctl").return ? { name = "semctl" retstr = returnstr(1) } # compat_sys_semctl ________________________________________ # # long compat_sys_semctl(int first, int second, int third, void __user *uptr) # probe nd_syscall.compat_sys_semctl = kprobe.function("compat_sys_semctl") ? { name = "compat_sys_semctl" // semid = @choose_defined($semid, $first) // semnum = @choose_defined($semnum, $second) // cmd = @choose_defined($cmd, $third) // argstr = sprintf("%d, %d, %s", semid, semnum, _semctl_cmd(cmd)) // NB: no asmlinkage() semid = int_arg(1) semnum = int_arg(2) cmd = int_arg(3) argstr = sprintf("%d, %d, %s", semid, semnum, _semctl_cmd(cmd)) } probe nd_syscall.compat_sys_semctl.return = kprobe.function("compat_sys_semctl").return ? { name = "compat_sys_semctl" retstr = returnstr(1) } # semget _____________________________________________________ # long sys_semget (key_t key, int nsems, int semflg) # probe nd_syscall.semget = kprobe.function("sys_semget") ? { name = "semget" // key = $key // nsems = $nsems // semflg = $semflg // argstr = sprintf("%d, %d, %s", $key, $nsems, __sem_flags($semflg)) asmlinkage() key = int_arg(1) nsems = int_arg(2) semflg = int_arg(3) argstr = sprintf("%d, %d, %s", key, nsems, __sem_flags(semflg)) } probe nd_syscall.semget.return = kprobe.function("sys_semget").return ? { name = "semget" retstr = returnstr(1) } # semop ______________________________________________________ # # long sys_semop (int semid, # struct sembuf __user *tsops, # unsigned nsops) # probe nd_syscall.semop = kprobe.function("sys_semtimedop") ? { name = "semop" // semid = $semid // [t]sops_uaddr = $tsops // nsops = $nsops // argstr = sprintf("%d, %p, %d", $semid, $tsops, $nsops) asmlinkage() semid = int_arg(1) %( systemtap_v < "2.3" %? tsops_uaddr = pointer_arg(2) %: sops_uaddr = pointer_arg(2) %) nsops = uint_arg(3) argstr = sprintf("%d, %p, %d", semid, pointer_arg(2), nsops) } probe nd_syscall.semop.return = kprobe.function("sys_semtimedop").return ? { name = "semop" retstr = returnstr(1) } # semtimedop _________________________________________________ # # long sys_semtimedop(int semid, # struct sembuf __user *tsops, # unsigned nsops, # const struct timespec __user *timeout) # probe nd_syscall.semtimedop = kprobe.function("sys_semtimedop") ? { name = "semtimedop" // semid = $semid // sops_uaddr = $tsops // nsops = $nsops // timeout_uaddr = $timeout // argstr = sprintf("%d, %p, %d, %s", $semid, $tsops, $nsops, // _struct_timespec_u($timeout, 1)) asmlinkage() semid = int_arg(1) sops_uaddr = pointer_arg(2) nsops = uint_arg(3) timeout_uaddr = pointer_arg(4) argstr = sprintf("%d, %p, %d, %s", semid, sops_uaddr, nsops, _struct_timespec_u(timeout_uaddr, 1)) } probe nd_syscall.semtimedop.return = kprobe.function("sys_semtimedop").return ? { name = "semtimedop" retstr = returnstr(1) } # compat_sys_semtimedop ________________________________________ # # long compat_sys_semtimedop(int semid, struct sembuf __user *tsems, # unsigned nsops, const struct compat_timespec __user *timeout) # probe nd_syscall.compat_sys_semtimedop = kprobe.function("compat_sys_semtimedop") ? { name = "compat_sys_semtimedop" // semid = $semid // sops_uaddr = $tsems // nsops = $nsops // timeout_uaddr = $timeout // argstr = sprintf("%d, %p, %d, %s", $semid, $tsems, $nsops, // _struct_compat_timespec_u($timeout, 1)) // no asmlinkage semid = int_arg(1) sops_uaddr = pointer_arg(2) nsops = uint_arg(3) timeout_uaddr = pointer_arg(4) argstr = sprintf("%d, %p, %d, %s", semid, sops_uaddr, nsops, _struct_compat_timespec_u(timeout_uaddr, 1)) } probe nd_syscall.compat_sys_semtimedop.return = kprobe.function("compat_sys_semtimedop").return ? { name = "compat_sys_semtimedop" retstr = returnstr(1) } # send _______________________________________________________ # # long sys_send(int fd, # void __user * buff, # size_t len, # unsigned flags) # probe nd_syscall.send = kprobe.function("sys_send") ? { name = "send" // s = $fd // buf_uaddr = $buff // len = $len // flags = $flags // flags_str = _sendflags_str($flags) // argstr = sprintf("%d, %p, %d, %s", $fd, $buff, $len, flags_str) asmlinkage() s = int_arg(1) buf_uaddr = pointer_arg(2) len = ulong_arg(3) flags = uint_arg(4) flags_str = _sendflags_str(flags) argstr = sprintf("%d, %p, %d, %s", s, buf_uaddr, len, flags_str) } probe nd_syscall.send.return = kprobe.function("sys_send").return ? { name = "send" retstr = returnstr(1) } # sendfile ___________________________________________________ # # ssize_t sys_sendfile[64](int out_fd, # int in_fd, # off_t __user *offset, # size_t count) # probe nd_syscall.sendfile = kprobe.function("sys_sendfile") ?, kprobe.function("sys_sendfile64") ? { name = "sendfile" // out_fd = $out_fd // in_fd = $in_fd // offset_uaddr = $offset // count = $count // argstr = sprintf("%d, %d, %p, %d", $out_fd, $in_fd, $offset, // $count) asmlinkage() out_fd = int_arg(1) in_fd = int_arg(2) offset_uaddr = pointer_arg(3) count = ulong_arg(4) argstr = sprintf("%d, %d, %p, %d", out_fd, in_fd, offset_uaddr, count) } probe nd_syscall.sendfile.return = kprobe.function("sys_sendfile").return ?, kprobe.function("sys_sendfile64").return ? { name = "sendfile" retstr = returnstr(1) } # sendmsg ____________________________________________________ # # long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) # probe nd_syscall.sendmsg = kprobe.function("sys_sendmsg") ? { name = "sendmsg" // s = $fd // msg_uaddr = $msg // flags = $flags // flags_str = _sendflags_str($flags) // argstr = sprintf("%d, %p, %s", $fd, $msg, _sendflags_str($flags)) asmlinkage() s = int_arg(1) msg_uaddr = pointer_arg(2) flags = uint_arg(3) flags_str = _sendflags_str(flags) argstr = sprintf("%d, %p, %s", s, msg_uaddr, _sendflags_str(flags)) } probe nd_syscall.sendmsg.return = kprobe.function("sys_sendmsg").return ? { name = "sendmsg" retstr = returnstr(1) } # compat_sys_sendmsg ________________________________________ # # long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags) # probe nd_syscall.compat_sys_sendmsg = kprobe.function("compat_sys_sendmsg") ? { name = "compat_sys_sendmsg" // s = $fd // msg_uaddr = $msg // flags = $flags // flags_str = _sendflags_str($flags) // argstr = sprintf("%d, %p, %s", $fd, $msg, _sendflags_str($flags)) asmlinkage() s = int_arg(1) msg_uaddr = pointer_arg(2) flags = uint_arg(3) flags_str = _sendflags_str(flags) argstr = sprintf("%d, %p, %s", s, msg_uaddr, _sendflags_str(flags)) } probe nd_syscall.compat_sys_sendmsg.return = kprobe.function("compat_sys_sendmsg").return ? { name = "compat_sys_sendmsg" retstr = returnstr(1) } # sendmmsg ____________________________________________________ # # int sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, # unsigned int flags) # probe nd_syscall.sendmmsg = kprobe.function("sys_sendmmsg").call ? { name = "sendmmsg" // s = $fd // mmsg_uaddr = $mmsg // vlen = $vlen // flags = $flags // flags_str = _sendflags_str($flags) // argstr = sprintf("%d, %p, %d, %s", $fd, $mmsg, $vlen, // _sendflags_str($flags)) asmlinkage() s = int_arg(1) mmsg_uaddr = pointer_arg(2) vlen = uint_arg(3) flags = uint_arg(4) flags_str = _sendflags_str(flags) argstr = sprintf("%d, %p, %d, %s", s, mmsg_uaddr, vlen, _sendflags_str(flags)) } probe nd_syscall.sendmmsg.return = kprobe.function("sys_sendmmsg").return ? { name = "sendmmsg" retstr = returnstr(1) } # sendto _____________________________________________________ # # long sys_sendto(int fd, # void __user * buff, # size_t len, # unsigned flags, # struct sockaddr __user *addr, # int addr_len) # probe nd_syscall.sendto = kprobe.function("sys_sendto") ? { name = "sendto" // s = $fd // buf_uaddr = $buff // len = $len // flags = $flags // flags_str = _sendflags_str($flags) // to_uaddr = $addr // tolen = $addr_len // argstr = sprintf("%d, %p, %d, %s, %s, %d", $fd, $buff, // $len, flags_str, _struct_sockaddr_u($addr, $addr_len), $addr_len) asmlinkage() s = int_arg(1) buf_uaddr = pointer_arg(2) len = ulong_arg(3) flags = uint_arg(4) flags_str = _sendflags_str(flags) to_uaddr = pointer_arg(5) tolen = int_arg(6) argstr = sprintf("%d, %p, %d, %s, %s, %d", s, buf_uaddr, len, flags_str, _struct_sockaddr_u(to_uaddr, tolen), tolen) } probe nd_syscall.sendto.return = kprobe.function("sys_sendto").return ? { name = "sendto" retstr = returnstr(1) } # setdomainname ______________________________________________ # # asmlinkage long # sys_setdomainname(char __user *name, # int len) # probe nd_syscall.setdomainname = kprobe.function("sys_setdomainname") ? { name = "setdomainname" // hostname_uaddr = $name // len = $len // argstr = sprintf("%p, %d", $name, $len) asmlinkage() hostname_uaddr = pointer_arg(1) len = int_arg(2) argstr = sprintf("%p, %d", hostname_uaddr, len) } probe nd_syscall.setdomainname.return = kprobe.function("sys_setdomainname").return ? { name = "setdomainname" retstr = returnstr(1) } # setfsgid ___________________________________________________ # long sys_setfsgid(gid_t gid) # long sys_setfsgid16(old_gid_t gid) # probe nd_syscall.setfsgid = kprobe.function("sys_setfsgid16") ?, kprobe.function("sys_setfsgid") ? { name = "setfsgid" // fsgid = $gid // argstr = sprint($gid) asmlinkage() fsgid = uint_arg(1) argstr = sprint(fsgid) } probe nd_syscall.setfsgid.return = kprobe.function("sys_setfsgid16").return ?, kprobe.function("sys_setfsgid").return ? { name = "setfsgid" retstr = returnstr(1) } # setfsuid ___________________________________________________ # long sys_setfsuid(uid_t uid) # long sys_setfsuid16(old_uid_t uid) # probe nd_syscall.setfsuid = kprobe.function("sys_setfsuid16") ?, kprobe.function("sys_setfsuid") ? { name = "setfsuid" // fsuid = $uid // argstr = sprint($uid) asmlinkage() fsuid = uint_arg(1) argstr = sprint(fsuid) } probe nd_syscall.setfsuid.return = kprobe.function("sys_setfsuid16").return ?, kprobe.function("sys_setfsuid").return ? { name = "setfsuid" retstr = returnstr(1) } # setgid _____________________________________________________ # # long sys_setgid(gid_t gid) # long sys_setgid16(old_gid_t gid) # probe nd_syscall.setgid = kprobe.function("sys_setgid16") ?, kprobe.function("sys_setgid") ? { name = "setgid" // gid = $gid // argstr = sprint($gid) asmlinkage() gid = uint_arg(1) argstr = sprint(gid) } probe nd_syscall.setgid.return = kprobe.function("sys_setgid16").return ?, kprobe.function("sys_setgid").return ? { name = "setgid" retstr = returnstr(1) } # setgroups __________________________________________________ # # long sys_setgroups(int gidsetsize, gid_t __user *grouplist) # long sys_setgroups16(int gidsetsize, old_gid_t __user *grouplist) # long sys32_setgroups16(int gidsetsize, u16 __user *grouplist) # probe nd_syscall.setgroups = kprobe.function("sys_setgroups16") ?, kprobe.function("sys32_setgroups16") ?, kprobe.function("sys_setgroups") ? { name = "setgroups" // size = $gidsetsize // list_uaddr = $grouplist // argstr = sprintf("%d, %p", $gidsetsize, $grouplist) asmlinkage() size = int_arg(1) list_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", size, list_uaddr) } probe nd_syscall.setgroups.return = kprobe.function("sys_setgroups16").return ?, kprobe.function("sys32_setgroups16").return ?, kprobe.function("sys_setgroups").return ? { name = "setgroups" retstr = returnstr(1) } # sethostname ________________________________________________ # # asmlinkage long # sys_sethostname(char __user *name, # int len) # probe nd_syscall.sethostname = kprobe.function("sys_sethostname") ? { name = "sethostname" // hostname_uaddr = $name // name_str = user_string($name) // len = $len // argstr = sprintf("%s, %d", user_string_quoted($name), $len) asmlinkage() hostname_uaddr = pointer_arg(1) name_str = user_string_quoted(hostname_uaddr) len = int_arg(2) argstr = sprintf("%s, %d", user_string_quoted(hostname_uaddr), len) } probe nd_syscall.sethostname.return = kprobe.function("sys_sethostname").return ? { name = "sethostname" retstr = returnstr(1) } # setitimer __________________________________________________ # # long sys_setitimer(int which, # struct itimerval __user *value, # struct itimerval __user *ovalue) # probe nd_syscall.setitimer = kprobe.function("sys_setitimer") ? { name = "setitimer" // which = $which // value_uaddr = $value // ovalue_uaddr = $ovalue // argstr = sprintf("%s, %s, %p", _itimer_which_str($which), // _struct_itimerval_u($value), $ovalue) asmlinkage() which = int_arg(1) value_uaddr = pointer_arg(2) ovalue_uaddr = pointer_arg(3) argstr = sprintf("%s, %s, %p", _itimer_which_str(which), _struct_itimerval_u(value_uaddr), ovalue_uaddr) } probe nd_syscall.setitimer.return = kprobe.function("sys_setitimer").return ? { name = "setitimer" retstr = returnstr(1) } # # long compat_sys_setitimer(int which, # struct compat_itimerval __user *in, # struct compat_itimerval __user *out) # probe nd_syscall.compat_setitimer = kprobe.function("compat_sys_setitimer") ? { name = "setitimer" // which = $which // value_uaddr = $in // ovalue_uaddr = $out // argstr = sprintf("%s, %s, %p", _itimer_which_str($which), // _struct_compat_itimerval_u($in), $out) asmlinkage() which = int_arg(1) value_uaddr = pointer_arg(2) ovalue_uaddr = pointer_arg(3) argstr = sprintf("%s, %s, %p", _itimer_which_str(which), _struct_compat_itimerval_u(value_uaddr), ovalue_uaddr) } probe nd_syscall.compat_setitimer.return = kprobe.function("compat_sys_setitimer").return ? { name = "setitimer" retstr = returnstr(1) } # set_mempolicy ______________________________________________ # long sys_set_mempolicy(int mode, # unsigned long __user *nmask, # unsigned long maxnode) # probe nd_syscall.set_mempolicy = kprobe.function("compat_sys_set_mempolicy") ?, kprobe.function("sys_set_mempolicy") ? { name = "set_mempolicy" // mode = $mode // nmask_uaddr = $nmask // maxnode = $maxnode // argstr = sprintf("%d, %p, %d", $mode, $nmask, $maxnode) asmlinkage() mode = int_arg(1) nmask_uaddr = pointer_arg(2) maxnode = ulong_arg(3) argstr = sprintf("%d, %p, %d", mode, nmask_uaddr, maxnode) } probe nd_syscall.set_mempolicy.return = kprobe.function("compat_sys_set_mempolicy").return ?, kprobe.function("sys_set_mempolicy").return ? { name = "set_mempolicy" retstr = returnstr(1) } # setpgid ____________________________________________________ # # asmlinkage long # sys_setpgid(pid_t pid, # pid_t pgid) # probe nd_syscall.setpgid = kprobe.function("sys_setpgid") ? { name = "setpgid" // pid = $pid // pgid = $pgid // argstr = sprintf("%d, %d", $pid, $pgid) asmlinkage() pid = int_arg(1) pgid = int_arg(2) argstr = sprintf("%d, %d", pid, pgid) } probe nd_syscall.setpgid.return = kprobe.function("sys_setpgid").return ? { name = "setpgid" retstr = returnstr(1) } # setpriority ________________________________________________ # # asmlinkage long # sys_setpriority(int which, # int who, # int niceval) # probe nd_syscall.setpriority = kprobe.function("sys_setpriority") ? { name = "setpriority" // which = $which // which_str = _priority_which_str($which) // who = $who // prio = $niceval // argstr = sprintf("%s, %d, %d", which_str, $who, $niceval) asmlinkage() which = int_arg(1) which_str = _priority_which_str(which) who = int_arg(2) prio = int_arg(3) argstr = sprintf("%s, %d, %d", which_str, who, prio) } probe nd_syscall.setpriority.return = kprobe.function("sys_setpriority").return ? { name = "setpriority" retstr = returnstr(1) } # setregid ___________________________________________________ # long sys_setregid(gid_t rgid, gid_t egid) # probe nd_syscall.setregid = kprobe.function("sys_setregid") ? { name = "setregid" // rgid = __int32($rgid) // egid = __int32($egid) asmlinkage() rgid = __int32(uint_arg(1)) egid = __int32(uint_arg(2)) argstr = sprintf("%d, %d", rgid, egid) } probe nd_syscall.setregid.return = kprobe.function("sys_setregid").return ? { name = "setregid" retstr = returnstr(1) } # setregid16 _________________________________________________ # long sys_setregid16(old_gid_t rgid, old_gid_t egid) # probe nd_syscall.setregid16 = kprobe.function("sys_setregid16") ? { name = "setregid" // rgid = __short($rgid) // egid = __short($egid) asmlinkage() rgid = __short(uint_arg(1)) egid = __short(uint_arg(2)) argstr = sprintf("%d, %d", rgid, egid) } probe nd_syscall.setregid16.return = kprobe.function("sys_setregid16").return ? { name = "setregid" retstr = returnstr(1) } # setresgid __________________________________________________ # long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) # probe nd_syscall.setresgid = kprobe.function("sys_setresgid") ? { name = "setresgid" // rgid = __int32($rgid) // egid = __int32($egid) // sgid = __int32($sgid) asmlinkage() rgid = __int32(uint_arg(1)) egid = __int32(uint_arg(2)) sgid = __int32(uint_arg(3)) argstr = sprintf("%d, %d, %d", rgid, egid, sgid) } probe nd_syscall.setresgid.return = kprobe.function("sys_setresgid").return ? { name = "setresgid" retstr = returnstr(1) } # setresgid16 ________________________________________________ # # long sys_setresgid16(old_gid_t rgid, # old_gid_t egid, # old_gid_t sgid) # probe nd_syscall.setresgid16 = kprobe.function("sys_setresgid16") ? { name = "setresgid" // rgid = __short($rgid) // egid = __short($egid) // sgid = __short($sgid) asmlinkage() rgid = __short(uint_arg(1)) egid = __short(uint_arg(2)) sgid = __short(uint_arg(3)) argstr = sprintf("%d, %d, %d", rgid, egid, sgid) } probe nd_syscall.setresgid16.return = kprobe.function("sys_setresgid16").return ? { name = "setresgid16" retstr = returnstr(1) } # setresuid __________________________________________________ # # long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) # probe nd_syscall.setresuid = kprobe.function("sys_setresuid") ? { name = "setresuid" // ruid = __int32($ruid) // euid = __int32($euid) // suid = __int32($suid) asmlinkage() ruid = __int32(uint_arg(1)) euid = __int32(uint_arg(2)) suid = __int32(uint_arg(3)) argstr = sprintf("%d, %d, %d", ruid, euid, suid) } probe nd_syscall.setresuid.return = kprobe.function("sys_setresuid").return ? { name = "setresuid" retstr = returnstr(1) } # setresuid16 ________________________________________________ # # long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid) # probe nd_syscall.setresuid16 = kprobe.function("sys_setresuid16") ? { name = "setresuid" // ruid = __short($ruid) // reuid = __short($euid) // rsuid = __short($suid) asmlinkage() ruid = __short(uint_arg(1)) euid = __short(uint_arg(2)) suid = __short(uint_arg(3)) argstr = sprintf("%d, %d, %d", ruid, euid, suid) } probe nd_syscall.setresuid16.return = kprobe.function("sys_setresuid16").return ? { name = "setresuid" retstr = returnstr(1) } # setreuid ___________________________________________________ # long sys_setreuid(uid_t ruid, uid_t euid) # probe nd_syscall.setreuid = kprobe.function("sys_setreuid") ? { name = "setreuid" // ruid = __int32($ruid) // euid = __int32($euid) asmlinkage() ruid = __int32(uint_arg(1)) euid = __int32(uint_arg(2)) argstr = sprintf("%d, %d", ruid, euid) } probe nd_syscall.setreuid.return = kprobe.function("sys_setreuid").return ? { name = "setreuid" retstr = returnstr(1) } # setreuid16 _________________________________________________ # long sys_setreuid16(old_uid_t ruid, old_uid_t euid) # probe nd_syscall.setreuid16 = kprobe.function("sys_setreuid16") ? { name = "setreuid" // ruid = __short($ruid) // euid = __short($euid) asmlinkage() ruid = __short(uint_arg(1)) euid = __short(uint_arg(2)) argstr = sprintf("%d, %d", ruid, euid) } probe nd_syscall.setreuid16.return = kprobe.function("sys_setreuid16").return ? { name = "setreuid" retstr = returnstr(1) } # setrlimit __________________________________________________ # # asmlinkage long # sys_setrlimit(unsigned int resource, # struct rlimit __user *rlim) # probe nd_syscall.setrlimit = kprobe.function("sys_setrlimit") ? { name = "setrlimit" // resource = $resource // rlim_uaddr = $rlim // argstr = sprintf("%s, %s", _rlimit_resource_str($resource), // _struct_rlimit_u($rlim)) asmlinkage() resource = uint_arg(1) rlim_uaddr = pointer_arg(2) argstr = sprintf("%s, %s", _rlimit_resource_str(resource), _struct_rlimit_u(rlim_uaddr)) } probe nd_syscall.setrlimit.return = kprobe.function("sys_setrlimit").return ? { name = "setrlimit" retstr = returnstr(1) } # setsid _____________________________________________________ # # long sys_setsid(void) # probe nd_syscall.setsid = kprobe.function("sys_setsid") { name = "setsid" argstr = "" } probe nd_syscall.setsid.return = kprobe.function("sys_setsid").return { name = "setsid" retstr = returnstr(1) } # setsockopt _________________________________________________ # # long sys_setsockopt(int fd, # int level, # int optname, # char __user *optval, # int optlen) # probe nd_syscall.setsockopt = kprobe.function("compat_sys_setsockopt") ?, kprobe.function("sys_setsockopt") ? { name = "setsockopt" // fd = $fd // level = $level // level_str = _sockopt_level_str($level) // optname = $optname // optname_str = _sockopt_optname_str($optname) // optval_uaddr = $optval // optlen = $optlen // argstr = sprintf("%d, %s, %s, %p, %d", $fd, level_str, // optname_str, $optval, $optlen) asmlinkage() fd = int_arg(1) level = int_arg(2) level_str = _sockopt_level_str(level) optname = int_arg(3) optname_str = _sockopt_optname_str(optname) optval_uaddr = pointer_arg(4) optlen = int_arg(5) argstr = sprintf("%d, %s, %s, %p, %d", fd, level_str, optname_str, optval_uaddr, optlen) } probe nd_syscall.setsockopt.return = kprobe.function("compat_sys_setsockopt").return ?, kprobe.function("sys_setsockopt").return ? { name = "setsockopt" retstr = returnstr(1) } # set_tid_address ____________________________________________ # # asmlinkage long # sys_set_tid_address(int __user *tidptr) # probe nd_syscall.set_tid_address = kprobe.function("sys_set_tid_address") ? { name = "set_tid_address" // tidptr_uaddr = $tidptr asmlinkage() tidptr_uaddr = pointer_arg(1) argstr = sprintf("%p", tidptr_uaddr) } probe nd_syscall.set_tid_address.return = kprobe.function("sys_set_tid_address").return ? { name = "set_tid_address" retstr = returnstr(1) } # settimeofday _______________________________________________ # # long sys_settimeofday(struct timeval __user *tv, # struct timezone __user *tz) # probe nd_syscall.settimeofday = kprobe.function("sys_settimeofday") ? { name = "settimeofday" // ttv_uaddr = $tv // ttz_uaddr = $tz // targstr = sprintf("%s, %s", _struct_timeval_u($tv, 1), _struct_timezone_u($tz)) asmlinkage() tv_uaddr = pointer_arg(1) tz_uaddr = pointer_arg(2) argstr = sprintf("%s, %s", _struct_timeval_u(tv_uaddr, 1), _struct_timezone_u(tz_uaddr)) } probe nd_syscall.settimeofday.return = kprobe.function("sys_settimeofday").return ? { name = "settimeofday" retstr = returnstr(1) } # # long sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) # long compat_sys_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) # probe nd_syscall.settimeofday32 = kprobe.function("sys32_settimeofday") ?, kprobe.function("compat_sys_settimeofday") ? { name = "settimeofday" // tv_uaddr = $tv // tz_uaddr = $tz // argstr = sprintf("%s, %s", _struct_compat_timeval_u($tv, 1), _struct_timezone_u($tz)) asmlinkage() tv_uaddr = pointer_arg(1) tz_uaddr = pointer_arg(2) argstr = sprintf("%s, %s", _struct_compat_timeval_u(tv_uaddr, 1), _struct_timezone_u(tz_uaddr)) } probe nd_syscall.settimeofday32.return = kprobe.function("sys32_settimeofday").return ?, kprobe.function("compat_sys_settimeofday").return ? { name = "settimeofday" retstr = returnstr(1) } # setuid _____________________________________________________ # # long sys_setuid(uid_t uid) # long sys_setuid16(old_uid_t uid) # probe nd_syscall.setuid = kprobe.function("sys_setuid16") ?, kprobe.function("sys_setuid") ? { name = "setuid" // uid = $uid // argstr = sprint($uid) asmlinkage() uid = uint_arg(1) argstr = sprint(uid) } probe nd_syscall.setuid.return = kprobe.function("sys_setuid16").return ?, kprobe.function("sys_setuid").return ? { name = "setuid" retstr = returnstr(1) } # setxattr ___________________________________________________ # long sys_setxattr(char __user *path, # char __user *name, # void __user *value, # size_t size, # int flags) # probe nd_syscall.setxattr = kprobe.function("sys_setxattr") ? { name = "setxattr" // path_uaddr = $path // path = user_string($path) // name_uaddr = $name // name_str = user_string($name) // value_uaddr = $value // size = $size // flags = $flags // argstr = sprintf("%s, %s, %p, %d, %d", // user_string_quoted($path), // user_string_quoted($name), // value_uaddr, $size, $flags) asmlinkage() path_uaddr = pointer_arg(1) path = user_string_quoted(path_uaddr) name_uaddr = pointer_arg(2) name_str = user_string_quoted(name_uaddr) value_uaddr = pointer_arg(3) size = ulong_arg(4) flags = int_arg(5) argstr = sprintf("%s, %s, %p, %d, %d", user_string_quoted(path_uaddr), user_string_quoted(name_uaddr), value_uaddr, size, flags) } probe nd_syscall.setxattr.return = kprobe.function("sys_setxattr").return ? { name = "setxattr" retstr = returnstr(1) } # sgetmask ___________________________________________________ # # sys_sgetmask(void) # probe nd_syscall.sgetmask = kprobe.function("sys_sgetmask") ? { name = "sgetmask" argstr = "" } probe nd_syscall.sgetmask.return = kprobe.function("sys_sgetmask").return ? { name = "sgetmask" retstr = returnstr(1) } # shmat ______________________________________________________ # # long sys_shmat(int shmid, char __user *shmaddr, int shmflg) # probe nd_syscall.shmat = kprobe.function("sys_shmat") ? { name = "shmat" // shmid = $shmid // shmaddr_uaddr = $shmaddr // shmflg = $shmflg // argstr = sprintf("%d, %p, %s", $shmid, $shmaddr, _shmat_flags_str($shmflg)) asmlinkage() shmid = int_arg(1) shmaddr_uaddr = pointer_arg(2) shmflg = int_arg(3) argstr = sprintf("%d, %p, %s", shmid, shmaddr_uaddr, _shmat_flags_str(shmflg)) } probe nd_syscall.shmat.return = kprobe.function("sys_shmat").return ? { name = "shmat" retstr = returnstr(1) } # compat_sys_shmat ________________________________________ # # long compat_sys_shmat(int first, int second, compat_uptr_t third, # int version, void __user *uptr) # COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, # int, shmflg) # probe nd_syscall.compat_sys_shmat = kprobe.function("compat_sys_shmat") ? { name = "compat_sys_shmat" // %( systemtap_v <= "2.3" %? // first = @choose_defined($shmid, $first) // second = @choose_defined($shmflg, $second) // third = @choose_defined($third, 0) // uptr_uaddr = @choose_defined($shmaddr, $uptr) // %) // shmid = @choose_defined($shmid, $first) // shmaddr_uaddr = @choose_defined($shmaddr, $uptr) // shmflg = @choose_defined($shmflg, $second) // argstr = sprintf("%d, %p, %s", shmid, shmaddr_uaddr, // _shmat_flags_str(shmflg)) // no asmlinkage %( systemtap_v < "2.3" %? first = int_arg(1) second = int_arg(2) third = u32_arg(3) uptr_uaddr = pointer_arg(5) %) shmid = int_arg(1) %( kernel_v > "3.9" || CONFIG_ARCH_WANT_OLD_COMPAT_IPC == "y" %? shmflg = int_arg(3) shmaddr_uaddr = pointer_arg(2) %: shmflg = int_arg(2) shmaddr_uaddr = pointer_arg(5) %) argstr = sprintf("%d, %p, %s", shmid, shmaddr_uaddr, _shmat_flags_str(shmflg)) } probe nd_syscall.compat_sys_shmat.return = kprobe.function("compat_sys_shmat").return ? { name = "compat_sys_shmat" retstr = returnstr(1) } # shmctl _____________________________________________________ # # long sys_shmctl (int shmid, # int cmd, # struct shmid_ds __user *buf) # probe nd_syscall.shmctl = kprobe.function("sys_shmctl") ? { name = "shmctl" // shmid = $shmid // cmd = $cmd // buf_uaddr = $buf // argstr = sprintf("%d, %s, %p", $shmid, _semctl_cmd($cmd), $buf) asmlinkage() shmid = int_arg(1) cmd = int_arg(2) buf_uaddr = pointer_arg(3) argstr = sprintf("%d, %s, %p", shmid, _semctl_cmd(cmd), buf_uaddr) } probe nd_syscall.shmctl.return = kprobe.function("sys_shmctl").return ? { name = "shmctl" retstr = returnstr(1) } # compat_sys_shmctl ________________________________________ # # long compat_sys_shmctl(int first, int second, void __user *uptr) # probe nd_syscall.compat_sys_shmctl = kprobe.function("compat_sys_shmctl") ? { name = "compat_sys_shmctl" // first = $first // second = $second // uptr_uaddr = $uptr // argstr = sprintf("%d, %d, %p", $first, $second, $uptr) // no asmlinkages first = int_arg(1) second = int_arg(2) uptr_uaddr = pointer_arg(3) argstr = sprintf("%d, %d, %p", first, second, uptr_uaddr) } probe nd_syscall.compat_sys_shmctl.return = kprobe.function("compat_sys_shmctl").return ? { name = "compat_sys_shmctl" retstr = returnstr(1) } # shmdt ______________________________________________________ # # long sys_shmdt(char __user *shmaddr) # probe nd_syscall.shmdt = kprobe.function("sys_shmdt") ? { name = "shmdt" // shmaddr_uaddr = $shmaddr // argstr = sprintf("%p", $shmaddr) asmlinkage() shmaddr_uaddr = pointer_arg(1) argstr = sprintf("%p", shmaddr_uaddr) } probe nd_syscall.shmdt.return = kprobe.function("sys_shmdt").return ? { name = "shmdt" retstr = returnstr(1) } # shmget _____________________________________________________ # # long sys_shmget (key_t key, # size_t size, # int shmflg) # probe nd_syscall.shmget = kprobe.function("sys_shmget") ? { name = "shmget" // key = $key // size = $size // shmflg = $shmflg // argstr = sprintf("%d, %d, %d", $key, $size, $shmflg) asmlinkage() key = int_arg(1) size = ulong_arg(2) shmflg = int_arg(3) argstr = sprintf("%d, %d, %d", key, size, shmflg) } probe nd_syscall.shmget.return = kprobe.function("sys_shmget").return ? { name = "shmget" retstr = returnstr(1) } # shutdown ___________________________________________________ # # long sys_shutdown(int fd, int how) # probe nd_syscall.shutdown = kprobe.function("sys_shutdown") ? { name = "shutdown" // s = $fd // how = $how // how_str = _shutdown_how_str($how) // argstr = sprintf("%d, %s", $fd, how_str) asmlinkage() s = int_arg(1) how = int_arg(2) how_str = _shutdown_how_str(how) argstr = sprintf("%d, %s", s, how_str) } probe nd_syscall.shutdown.return = kprobe.function("sys_shutdown").return ? { name = "shutdown" retstr = returnstr(1) } # sigaction __________________________________________________ # sys_sigaction(int sig, const struct old_sigaction __user *act, struct old_sigaction __user *oact) # sys32_sigaction(int sig, struct old_sigaction32 __user *act, struct old_sigaction32 __user *oact) # probe nd_syscall.sigaction = kprobe.function("sys_sigaction") ? { name = "sigaction" // sig = $sig // act_uaddr = $act // oact_uaddr = $oact // argstr = sprintf("%s, {%s}, %p", _signal_name($sig), _struct_sigaction_u($act), $oact) %( arch != "powerpc" %? asmlinkage() %) sig = int_arg(1) act_uaddr = pointer_arg(2) oact_uaddr = pointer_arg(3) argstr = sprintf("%s, {%s}, %p", _signal_name(sig), _struct_sigaction_u(act_uaddr), oact_uaddr) } probe nd_syscall.sigaction.return = kprobe.function("sys_sigaction").return ? { name = "sigaction" retstr = returnstr(1) } probe nd_syscall.sigaction32 = kprobe.function("sys32_sigaction") ?, kprobe.function("compat_sys_sigaction") ? { name = "sigaction" // sig = $sig // sact_uaddr = $act // soact_uaddr = $oact // argstr = sprintf("%s, {%s}, %p", _signal_name($sig), _struct_old_sigaction32_u($act), $oact) asmlinkage() sig = int_arg(1) act_uaddr = pointer_arg(2) oact_uaddr = pointer_arg(3) argstr = sprintf("%s, {%s}, %p", _signal_name(sig), _struct_old_sigaction32_u(act_uaddr), oact_uaddr) } probe nd_syscall.sigaction32.return = kprobe.function("sys32_sigaction").return ?, kprobe.function("compat_sys_sigaction").return ? { name = "sigaction" retstr = returnstr(1) } # In kernel 3.8, CONFIG_GENERIC_SIGALTSTACK was added by # kernel commit 6bf9adfc90370b695cb111116e15fdc0e1906270. # # Then, in kernel 3.9, all architectures were switched to using the # generic sigaltstack by kernel commit # d64008a8f30e0b381b292788ec6f3ee509b3bb40, which also removed the # CONFIG_GENERIC_SIGALTSTACK config variable. # # Thus the following preprocessor test. %( CONFIG_GENERIC_SIGALTSTACK == "y" || kernel_v >= "3.9" %? # sigaltstack ________________________________________________ # SYSCALL_DEFINE2(sigaltstack,const stack_t __user *,uss, stack_t __user *,uoss) # probe nd_syscall.sigaltstack = kprobe.function("sys_sigaltstack") { name = "sigaltstack" // uss_uaddr = $uss // uoss_uaddr = $uoss // argstr = sprintf("%p, %p", $uss, $uoss) asmlinkage() uss_uaddr = pointer_arg(1) uoss_uaddr = pointer_arg(2) argstr = sprintf("%p, %p", uss_uaddr, uoss_uaddr) } probe nd_syscall.sigaltstack.return = kprobe.function("sys_sigaltstack").return { name = "sigaltstack" retstr = returnstr(1) } %) # signal _____________________________________________________ # unsigned long sys_signal(int sig, __sighandler_t handler) # probe nd_syscall.signal = kprobe.function("sys_signal") ? { name = "signal" // sig = $sig // handler = $handler // argstr = sprintf("%s, %s", _signal_name($sig), _sighandler_str($handler)) asmlinkage() sig = int_arg(1) handler = pointer_arg(2) argstr = sprintf("%s, %s", _signal_name(sig), _sighandler_str(handler)) } probe nd_syscall.signal.return = kprobe.function("sys_signal").return ? { name = "signal" retstr = returnstr(1) } # signalfd _____________________________________________________ # # long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask) # long sys_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, # int flags) # long compat_sys_signalfd(int ufd, const compat_sigset_t __user *sigmask, # compat_size_t sigsetsize) # long compat_sys_signalfd4(int ufd, const compat_sigset_t __user *sigmask, # compat_size_t sigsetsize, int flags) # probe nd_syscall.signalfd = __nd_syscall.signalfd4 !, __nd_syscall.signalfd ? { } probe __nd_syscall.signalfd4 = kprobe.function("sys_signalfd4") { asmlinkage() flags = int_arg(4) if (flags == 0) { name = "signalfd" // argstr = sprintf("%d, %p, %d", $ufd, $user_mask, $sizemask) argstr = sprintf("%d, %p, %d", int_arg(1), pointer_arg(2), ulong_arg(3)) } else { name = "signalfd4" // argstr = sprintf("%d, %p, %d, %s", $ufd, $user_mask, // $sizemask, _signalfd4_flags_str($flags)) argstr = sprintf("%d, %p, %d, %s", int_arg(1), pointer_arg(2), ulong_arg(3), _signalfd4_flags_str(flags)) } } probe __nd_syscall.signalfd = kprobe.function("sys_signalfd") { name = "signalfd" asmlinkage() flags = 0 // argstr = sprintf("%d, %p, %d", $ufd, $user_mask, $sizemask) argstr = sprintf("%d, %p, %d", int_arg(1), pointer_arg(2), ulong_arg(3)) } probe nd_syscall.signalfd.return = __nd_syscall.signalfd4.return !, __nd_syscall.signalfd.return ? { } probe __nd_syscall.signalfd4.return = kprobe.function("sys_signalfd4").return { flags = @entry(__asmlinkage_int_arg(4)) name = (flags == 0) ? "signalfd" : "signalfd4" retstr = returnstr(1) } probe __nd_syscall.signalfd.return = kprobe.function("sys_signalfd").return { flags = 0 name = "signalfd" retstr = returnstr(1) } probe nd_syscall.compat_signalfd = __nd_syscall.compat_signalfd4 !, __nd_syscall.compat_signalfd ? { } probe __nd_syscall.compat_signalfd4 = kprobe.function("compat_sys_signalfd4") { asmlinkage() flags = int_arg(4) if (flags == 0) { name = "compat_signalfd" // argstr = sprintf("%d, %p, %d", $ufd, $sigmask, $sigsetsize) argstr = sprintf("%d, %p, %d", int_arg(1), pointer_arg(2), u32_arg(3)) } else { name = "compat_signalfd4" // argstr = sprintf("%d, %p, %d, %s", $ufd, $sigmask, // $sigsetsize, _signalfd4_flags_str($flags)) argstr = sprintf("%d, %p, %d, %s", int_arg(1), pointer_arg(2), u32_arg(3), _signalfd4_flags_str(flags)) } } probe __nd_syscall.compat_signalfd = kprobe.function("compat_sys_signalfd") { asmlinkage() flags = 0 name = "compat_signalfd" // argstr = sprintf("%d, %p, %d", $ufd, $sigmask, $sigsetsize) argstr = sprintf("%d, %p, %d", int_arg(1), pointer_arg(2), u32_arg(3)) } probe nd_syscall.compat_signalfd.return = __nd_syscall.compat_signalfd4.return !, __nd_syscall.compat_signalfd.return ? { } probe __nd_syscall.compat_signalfd4.return = kprobe.function("compat_sys_signalfd4").return { flags = @entry(__asmlinkage_int_arg(4)) name = (flags == 0) ? "compat_signalfd" : "compat_signalfd4" retstr = returnstr(1) } probe __nd_syscall.compat_signalfd.return = kprobe.function("compat_sys_signalfd").return { flags = 0 name = "compat_signalfd" retstr = returnstr(1) } # sigpending _________________________________________________ # long sys_sigpending(old_sigset_t __user *set) # probe nd_syscall.sigpending = kprobe.function("sys_sigpending") ? { name = "sigpending" // argstr = sprintf("%p", $set) asmlinkage() argstr = sprintf("%p", pointer_arg(1)) } probe nd_syscall.sigpending.return = kprobe.function("sys_sigpending").return ? { name = "sigpending" retstr = returnstr(1) } # sigprocmask ________________________________________________ # long sys_sigprocmask(int how, old_sigset_t __user *set, old_sigset_t __user *oset) # asmlinkage long compat_sys_sigprocmask(int how, # compat_old_sigset_t __user *nset, # compat_old_sigset_t __user *oset) # # probe nd_syscall.sigprocmask = kprobe.function("sys_sigprocmask") ?, kprobe.function("compat_sys_sigprocmask") ? { name = "sigprocmask" // how = $how // how_str = _sigprocmask_how_str($how) // set_uaddr = $set // oldset_uaddr = $oset // argstr = sprintf("%s, %p, %p", how_str, $set, $oset) asmlinkage() how = int_arg(1) how_str = _sigprocmask_how_str(how) set_uaddr = pointer_arg(2) oldset_uaddr = pointer_arg(3) argstr = sprintf("%s, %p, %p", how_str, set_uaddr, oldset_uaddr) } probe nd_syscall.sigprocmask.return = kprobe.function("sys_sigprocmask").return ?, kprobe.function("compat_sys_sigprocmask").return ? { name = "sigprocmask" retstr = returnstr(1) } # sigreturn __________________________________________________ # int sys_sigreturn(unsigned long __unused) # probe nd_syscall.sigreturn = kprobe.function("sys_sigreturn") ?, kprobe.function("sys32_sigreturn") ? { name = "sigreturn" argstr = "" } probe nd_syscall.sigreturn.return = kprobe.function("sys_sigreturn").return ?, kprobe.function("sys32_sigreturn").return ? { name = "sigreturn" retstr = returnstr(1) } # sigsuspend _________________________________________________ # probe nd_syscall.sigsuspend = kprobe.function("sys_sigsuspend") ?, kprobe.function("sys32_sigsuspend") ? { name = "sigsuspend" argstr = "" } probe nd_syscall.sigsuspend.return = kprobe.function("sys_sigsuspend").return ?, kprobe.function("sys32_sigsuspend").return ? { name = "sigsuspend" retstr = returnstr(1) } # socket _____________________________________________________ # long sys_socket(int family, int type, int protocol) # probe nd_syscall.socket = kprobe.function("sys_socket") ? { name = "socket" // family = $family // type = $type // protocol = $protocol // argstr = sprintf("%s, %s, %d", _sock_family_str($family), // _sock_type_str($type), // $protocol) asmlinkage() family = int_arg(1) type = int_arg(2) protocol = int_arg(3) argstr = sprintf("%s, %s, %d", _sock_family_str(family), _sock_type_str(type), protocol) } probe nd_syscall.socket.return = kprobe.function("sys_socket").return ? { name = "socket" retstr = returnstr(1) } # commented out because this seems redundant # socketcall _________________________________________________ # # long sys_socketcall(int call, unsigned long __user *args) # #probe nd_syscall.socketcall = kprobe.function("sys_socketcall") ? #{ # name = "socketcall" # call = $call # args_uaddr = $args # argstr = sprintf("%d, %p", $call, args_uaddr) #} #probe nd_syscall.socketcall.return = kprobe.function("sys_socketcall").return ? #{ # name = "socketcall" # retstr = returnstr(1) #} # socketpair _________________________________________________ # long sys_socketpair(int family, # int type, # int protocol, # int __user *usockvec) # probe nd_syscall.socketpair = kprobe.function("sys_socketpair") ? { name = "socketpair" // family = $family // type = $type // protocol = $protocol // sv_uaddr = $usockvec // argstr = sprintf("%s, %s, %d, %p", // _sock_family_str($family), // _sock_type_str($type), // $protocol, sv_uaddr) asmlinkage() family = int_arg(1) type = int_arg(2) protocol = int_arg(3) sv_uaddr = pointer_arg(4) argstr = sprintf("%s, %s, %d, %p", _sock_family_str(family), _sock_type_str(type), protocol, sv_uaddr) } probe nd_syscall.socketpair.return = kprobe.function("sys_socketpair").return ? { name = "socketpair" retstr = returnstr(1) } # splice ___________________________________________________ # # long sys_splice(int fd_in, loff_t __user *off_in, # int fd_out, loff_t __user *off_out, # size_t len, unsigned int flags) # probe nd_syscall.splice = kprobe.function("sys_splice") ? { name = "splice" // argstr = sprintf("%d, %p, %d, %p, %d, 0x%x", // $fd_in, $off_in, $fd_out, $off_out, $len, $flags) asmlinkage() argstr = sprintf("%d, %p, %d, %p, %d, 0x%x", int_arg(1), pointer_arg(2), int_arg(3), pointer_arg(4), ulong_arg(5), uint_arg(6)) } probe nd_syscall.splice.return = kprobe.function("sys_splice").return ? { name = "splice" retstr = returnstr(1) } # ssetmask ___________________________________________________ # # long sys_ssetmask(int newmask) # probe nd_syscall.ssetmask = kprobe.function("sys_ssetmask") ? { name = "ssetmask" // newmask = $newmask // argstr = sprint($newmask) asmlinkage() newmask = int_arg(1) argstr = sprint(newmask) } probe nd_syscall.ssetmask.return = kprobe.function("sys_ssetmask").return ? { name = "ssetmask" retstr = returnstr(1) } # stat _______________________________________________________ # long sys_stat(char __user * filename, struct __old_stat __user * statbuf) # long sys32_stat64(char __user * filename, struct stat64 __user *statbuf) # long sys_stat64(char __user * filename, struct stat64 __user * statbuf) # long sys_oabi_stat64(char __user * filename, struct oldabi_stat64 __user * statbuf) # long compat_sys_newstat(char __user * filename, struct compat_stat __user *statbuf) probe nd_syscall.stat = kprobe.function("sys_stat") ?, kprobe.function("sys_newstat") ?, kprobe.function("sys32_stat64") ?, kprobe.function("sys_stat64") ?, kprobe.function("sys_oabi_stat64") ?, kprobe.function("compat_sys_newstat") ? { name = "stat" // filename_uaddr = $filename // filename = user_string($filename) // buf_uaddr = $statbuf // argstr = sprintf("%s, %p", user_string_quoted($filename), buf_uaddr) asmlinkage() filename_uaddr = pointer_arg(1) filename = user_string_quoted(filename_uaddr) buf_uaddr = pointer_arg(2) argstr = sprintf("%s, %p", user_string_quoted(filename_uaddr), buf_uaddr) } probe nd_syscall.stat.return = kprobe.function("sys_stat").return ?, kprobe.function("sys_newstat").return ?, kprobe.function("sys32_stat64").return ?, kprobe.function("sys_stat64").return ?, kprobe.function("sys_oabi_stat64").return ?, kprobe.function("compat_sys_newstat").return ? { name = "stat" retstr = returnstr(1) } # statfs _____________________________________________________ # long sys_statfs(const char __user * path, struct statfs __user * buf) # long compat_sys_statfs(const char __user *path, struct compat_statfs __user *buf) # probe nd_syscall.statfs = kprobe.function("compat_sys_statfs") ?, kprobe.function("sys_statfs") ? { name = "statfs" // path = user_string($path) // buf_uaddr = $buf // argstr = sprintf("%s, %p", user_string_quoted($path), $buf) asmlinkage() path = user_string_quoted(pointer_arg(1)) buf_uaddr = pointer_arg(2) argstr = sprintf("%s, %p", user_string_quoted(pointer_arg(1)), buf_uaddr) } probe nd_syscall.statfs.return = kprobe.function("compat_sys_statfs").return ?, kprobe.function("sys_statfs").return ? { name = "statfs" retstr = returnstr(1) } # statfs64 ___________________________________________________ # # long sys_statfs64(const char __user *path, size_t sz, struct statfs64 __user *buf) # long compat_sys_statfs64(const char __user *path, compat_size_t sz, struct compat_statfs64 __user *buf) # probe nd_syscall.statfs64 = kprobe.function("compat_sys_statfs64") ?, kprobe.function("sys_statfs64") ? { name = "statfs" // path = user_string($path) // sz = $sz // buf_uaddr = $buf // argstr = sprintf("%s, %d, %p", user_string_quoted($path), $sz, $buf) asmlinkage() path = user_string_quoted(pointer_arg(1)) sz = ulong_arg(2) buf_uaddr = pointer_arg(3) argstr = sprintf("%s, %d, %p", user_string_quoted(pointer_arg(1)), sz, buf_uaddr) } probe nd_syscall.statfs64.return = kprobe.function("compat_sys_statfs64").return ?, kprobe.function("sys_statfs64").return ? { name = "statfs" retstr = returnstr(1) } # stime ______________________________________________________ # # long sys_stime(time_t __user *tptr) # long compat_sys_stime(compat_time_t __user *tptr) # probe nd_syscall.stime = kprobe.function("compat_sys_stime") ?, kprobe.function("sys_stime") ? { name = "stime" // t_uaddr = $tptr /* FIXME. Decode time */ // argstr = sprintf("%p", $tptr) asmlinkage() t_uaddr = pointer_arg(1) argstr = sprintf("%p", t_uaddr) } probe nd_syscall.stime.return = kprobe.function("compat_sys_stime").return ?, kprobe.function("sys_stime").return ? { name = "stime" retstr = returnstr(1) } # swapoff ____________________________________________________ # # asmlinkage long # sys_swapoff(const char __user * specialfile) # probe nd_syscall.swapoff = kprobe.function("sys_swapoff") ? { name = "swapoff" // path = user_string($specialfile) // argstr = user_string_quoted($specialfile) asmlinkage() path = user_string_quoted(pointer_arg(1)) argstr = user_string_quoted(pointer_arg(1)) } probe nd_syscall.swapoff.return = kprobe.function("sys_swapoff").return ? { name = "swapoff" retstr = returnstr(1) } # swapon _____________________________________________________ # # asmlinkage long # sys_swapon(const char __user * specialfile, # int swap_flags) # probe nd_syscall.swapon = kprobe.function("sys_swapon") ? { name = "swapon" // path = user_string($specialfile) // swapflags = $swap_flags // argstr = sprintf("%s, %d", user_string_quoted($specialfile), swapflags) asmlinkage() path = user_string_quoted(pointer_arg(1)) swapflags = int_arg(2) argstr = sprintf("%s, %d", user_string_quoted(pointer_arg(1)), swapflags) } probe nd_syscall.swapon.return = kprobe.function("sys_swapon").return ? { name = "swapon" retstr = returnstr(1) } # symlink ____________________________________________________ # long sys_symlink(const char __user * oldname, # const char __user * newname) probe nd_syscall.symlink = kprobe.function("sys_symlink") ? { name = "symlink" // oldpath = user_string($oldname) // newpath = user_string($newname) // argstr = sprintf("%s, %s", user_string_quoted($oldname), // user_string_quoted($newname)) asmlinkage() oldpath = user_string_quoted(pointer_arg(1)) newpath = user_string_quoted(pointer_arg(2)) argstr = sprintf("%s, %s", user_string_quoted(pointer_arg(1)), user_string_quoted(pointer_arg(2))) } probe nd_syscall.symlink.return = kprobe.function("sys_symlink").return ? { name = "symlink" retstr = returnstr(1) } # symlinkat __________________________________________________ # new function with 2.6.16 # long sys_symlinkat(const char __user *oldname, int newdfd, # const char __user *newname) probe nd_syscall.symlinkat = kprobe.function("sys_symlinkat") ? { name = "symlinkat" // oldname = $oldname // oldname_str = user_string($oldname) // newdfd = $newdfd // newdfd_str = _dfd_str($newdfd) // newname = $newname // newname_str = user_string($newname) // argstr = sprintf("%s, %s, %s", user_string_quoted($oldname), // newdfd_str, user_string_quoted($newname)) asmlinkage() oldname = pointer_arg(1) oldname_str = user_string_quoted(oldname) newdfd = int_arg(2) newdfd_str = _dfd_str(newdfd) newname = pointer_arg(3) newname_str = user_string_quoted(newname) argstr = sprintf("%s, %s, %s", user_string_quoted(oldname), newdfd_str, user_string_quoted(newname)) } probe nd_syscall.symlinkat.return = kprobe.function("sys_symlinkat").return ? { name = "symlinkat" retstr = returnstr(1) } # sync _______________________________________________________ # # sys_sync(void) # probe nd_syscall.sync = kprobe.function("sys_sync") { name = "sync" argstr = "" } probe nd_syscall.sync.return = kprobe.function("sys_sync").return { name = "sync" retstr = returnstr(1) } # sysctl _____________________________________________________ # # long sys_sysctl(struct __sysctl_args __user *args) # probe nd_syscall.sysctl = kprobe.function("compat_sys_sysctl") ?, kprobe.function("sys_sysctl") ? { name = "sysctl" // argstr = sprintf("%p", $args) asmlinkage() argstr = sprintf("%p", pointer_arg(1)) } probe nd_syscall.sysctl.return = kprobe.function("compat_sys_sysctl").return ?, kprobe.function("sys_sysctl").return ? { name = "sysctl" retstr = returnstr(1) } # sysfs ______________________________________________________ # # asmlinkage long # sys_sysfs(int option, # unsigned long arg1, # unsigned long arg2) # probe nd_syscall.sysfs = kprobe.function("sys_sysfs") ? { name = "sysfs" // option = $option // arg1 = $arg1 // arg2 = $arg2 // if (option == 1) // argstr = sprintf("%d, %s, %d", $option, user_string_quoted($arg1), $arg2) // else if (option == 2) // argstr = sprintf("%d, %d, %p", $option, $arg1, $arg2) // else if (option == 3) // argstr = sprintf("%d, %d, %d", $option, $arg1, $arg2) // else // argstr = sprintf("%d, %d, %d", $option, $arg1, $arg2) asmlinkage() option = int_arg(1) arg1 = ulong_arg(2) arg2 = ulong_arg(3) if (option == 1) argstr = sprintf("%d, %s, %d", option, user_string_quoted(arg1), arg2) else if (option == 2) argstr = sprintf("%d, %d, %p", option, arg1, arg2) else argstr = sprintf("%d, %d, %d", option, arg1, arg2) } probe nd_syscall.sysfs.return = kprobe.function("sys_sysfs").return ? { name = "sysfs" retstr = returnstr(1) } # sysinfo ____________________________________________________ # # long sys_sysinfo(struct sysinfo __user *info) # long compat_sys_sysinfo(struct compat_sysinfo __user *info) probe nd_syscall.sysinfo = kprobe.function("compat_sys_sysinfo") ?, kprobe.function("sys_sysinfo") ? { name = "sysinfo" // info_uaddr = $info // argstr = sprintf("%p", $info) asmlinkage() info_uaddr = pointer_arg(1) argstr = sprintf("%p", info_uaddr) } probe nd_syscall.sysinfo.return = kprobe.function("compat_sys_sysinfo").return ?, kprobe.function("sys_sysinfo").return ? { name = "sysinfo" retstr = returnstr(1) } # syslog _____________________________________________________ # # long sys_syslog(int type, char __user * buf, int len) # probe nd_syscall.syslog = kprobe.function("sys_syslog") ? { name = "syslog" // type = $type // bufp_uaddr = $buf // len = $len // argstr = sprintf("%d, %p, %d", $type, $buf, $len) asmlinkage() type = int_arg(1) bufp_uaddr = pointer_arg(2) len = int_arg(3) argstr = sprintf("%d, %p, %d", type, bufp_uaddr, len) } probe nd_syscall.syslog.return = kprobe.function("sys_syslog").return ? { name = "syslog" retstr = returnstr(1) } # tee _____________________________________________________ # # long sys_tee(int fdin, int fdout, size_t len, unsigned int flags) # probe nd_syscall.tee = kprobe.function("sys_tee") ? { name = "tee" // argstr = sprintf("%d, %d, %d, 0x%x", $fdin, $fdout, $len, $flags) asmlinkage() argstr = sprintf("%d, %d, %d, 0x%x", int_arg(1), int_arg(2), ulong_arg(3), uint_arg(4)) } probe nd_syscall.tee.return = kprobe.function("sys_tee").return ? { name = "tee" retstr = returnstr(1) } # tgkill _____________________________________________________ # # asmlinkage long # sys_tgkill(int tgid, # int pid, # int sig) # probe nd_syscall.tgkill = kprobe.function("sys_tgkill") ? { name = "tgkill" // tgid = $tgid // pid = $pid // sig = $sig // argstr = sprintf("%d, %d, %s", $tgid, $pid, _signal_name($sig)) asmlinkage() tgid = int_arg(1) pid = int_arg(2) sig = int_arg(3) argstr = sprintf("%d, %d, %s", tgid, pid, _signal_name(sig)) } probe nd_syscall.tgkill.return = kprobe.function("sys_tgkill").return ? { name = "tgkill" retstr = returnstr(1) } # time _______________________________________________________ # # long sys_time(time_t __user * tloc) # long sys_time64(long __user * tloc) # long sys32_time(compat_time_t __user * tloc) # long compat_sys_time(compat_time_t __user * tloc) # probe nd_syscall.time = kprobe.function("sys32_time") ?, kprobe.function("sys_time64") ?, kprobe.function("compat_sys_time") ?, kprobe.function("sys_time") ? { name = "time" // t_uaddr = $tloc // argstr = sprintf("%p", $tloc) asmlinkage() t_uaddr = pointer_arg(1) argstr = sprintf("%p", t_uaddr) } probe nd_syscall.time.return = kprobe.function("sys32_time").return ?, kprobe.function("sys_time64").return ?, kprobe.function("compat_sys_time").return ?, kprobe.function("sys_time").return ? { name = "time" retstr = returnstr(1) } # timer_create _______________________________________________ # # long sys_timer_create(clockid_t which_clock, # struct sigevent __user *timer_event_spec, # timer_t __user * created_timer_id) # probe nd_syscall.timer_create = kprobe.function("sys_timer_create") ? { name = "timer_create" // clockid = $which_clock // clockid_str = _get_wc_str($which_clock) // evp_uaddr = $timer_event_spec // timerid_uaddr = $created_timer_id // argstr = sprintf("%s, %p, %p", clockid_str, $timer_event_spec, $created_timer_id) asmlinkage() clockid = int_arg(1) clockid_str = _get_wc_str(clockid) evp_uaddr = pointer_arg(2) timerid_uaddr = pointer_arg(3) argstr = sprintf("%s, %p, %p", clockid_str, evp_uaddr, timerid_uaddr) } probe nd_syscall.timer_create.return = kprobe.function("sys_timer_create").return ? { name = "timer_create" retstr = returnstr(1) } # timer_delete _______________________________________________ # # long sys_timer_delete(timer_t timer_id) # probe nd_syscall.timer_delete = kprobe.function("sys_timer_delete") ? { name = "timer_delete" // timerid = $timer_id // argstr = sprint($timer_id) asmlinkage() timerid = int_arg(1) argstr = sprint(timerid) } probe nd_syscall.timer_delete.return = kprobe.function("sys_timer_delete").return ? { name = "timer_delete" retstr = returnstr(1) } # timer_getoverrun ___________________________________________ # # long sys_timer_getoverrun(timer_t timer_id) # probe nd_syscall.timer_getoverrun = kprobe.function("sys_timer_getoverrun") ? { name = "timer_getoverrun" // timerid = $timer_id // argstr = sprint($timer_id) asmlinkage() timerid = int_arg(1) argstr = sprint(timerid) } probe nd_syscall.timer_getoverrun.return = kprobe.function("sys_timer_getoverrun").return ? { name = "timer_getoverrun" retstr = returnstr(1) } # timer_gettime ______________________________________________ # # long sys_timer_gettime(timer_t timer_id, # struct itimerspec __user *setting) # probe nd_syscall.timer_gettime = kprobe.function("sys_timer_gettime") ? { name = "timer_gettime" // timerid = $timer_id // value_uaddr = $setting // argstr = sprintf("%d, %p", $timer_id, $setting) asmlinkage() timerid = int_arg(1) value_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", timerid, value_uaddr) } probe nd_syscall.timer_gettime.return = kprobe.function("sys_timer_gettime").return ? { name = "timer_gettime" retstr = returnstr(1) } # timer_settime ______________________________________________ # # long sys_timer_settime(timer_t timer_id, # int flags, # const struct itimerspec __user *new_setting, # struct itimerspec __user *old_setting) # probe nd_syscall.timer_settime = kprobe.function("sys_timer_settime") ? { name = "timer_settime" // timerid = $timer_id // flags = $flags // value_uaddr = $new_setting // ovalue_uaddr = $old_setting // argstr = sprintf("%d, %d, %s, %p", $timer_id, $flags, // _struct_itimerspec_u($new_setting), // $old_setting) asmlinkage() timerid = int_arg(1) flags = int_arg(2) value_uaddr = pointer_arg(3) ovalue_uaddr = pointer_arg(4) argstr = sprintf("%d, %d, %s, %p", timerid, flags, _struct_itimerspec_u(value_uaddr), ovalue_uaddr) } probe nd_syscall.timer_settime.return = kprobe.function("sys_timer_settime").return ? { name = "timer_settime" retstr = returnstr(1) } # timerfd ______________________________________________ # # long sys_timerfd(int ufd, int clockid, int flags, # const struct itimerspec __user *utmr) # long compat_sys_timerfd(int ufd, int clockid, int flags, # const struct compat_itimerspec __user *utmr) # probe nd_syscall.timerfd = kprobe.function("sys_timerfd") ?, kprobe.function("compat_sys_timerfd") ? { name = "timerfd" // argstr = sprintf("%d, %d, 0x%x", $ufd, $clockid, $flags) asmlinkage() argstr = sprintf("%d, %d, 0x%x", int_arg(1), int_arg(2), int_arg(3)) } probe nd_syscall.timerfd.return = kprobe.function("sys_timerfd").return ?, kprobe.function("compat_sys_timerfd").return ? { name = "timerfd" retstr = returnstr(1) } # times ______________________________________________________ # # long sys_times(struct tms __user * tbuf) # long compat_sys_times(struct compat_tms __user *tbuf) probe nd_syscall.times = kprobe.function("compat_sys_times") ?, kprobe.function("sys_times") ? { name = "times" // argstr = sprintf("%p", $tbuf) asmlinkage() argstr = sprintf("%p", pointer_arg(1)) } probe nd_syscall.times.return = kprobe.function("compat_sys_times").return ?, kprobe.function("sys_times").return ? { name = "times" retstr = returnstr(1) } # tkill ______________________________________________________ # # asmlinkage long # sys_tkill(int pid, # int sig) # probe nd_syscall.tkill = kprobe.function("sys_tkill") ? { name = "tkill" // pid = $pid // sig = $sig // argstr = sprintf("%d, %s", $pid, _signal_name($sig)) asmlinkage() pid = int_arg(1) sig = int_arg(2) argstr = sprintf("%d, %s", pid, _signal_name(sig)) } probe nd_syscall.tkill.return = kprobe.function("sys_tkill").return ? { name = "tkill" retstr = returnstr(1) } # truncate ___________________________________________________ # # sys_truncate(const char __user * path, unsigned long length) # sys_truncate64(const char __user * path, loff_t length) # probe nd_syscall.truncate = kprobe.function("sys_truncate") ?, kprobe.function("sys_truncate64") ? { name = "truncate" // path_uaddr = $path // path = user_string($path) // length = $length // argstr = sprintf("%s, %d", user_string_quoted($path), $length) asmlinkage() path_uaddr = pointer_arg(1) path = user_string_quoted(path_uaddr) if (symname(addr()) == "sys_truncate") length = ulong_arg(2) else length = longlong_arg(2) argstr = sprintf("%s, %d", user_string_quoted(path_uaddr), length) } probe nd_syscall.truncate.return = kprobe.function("sys_truncate").return ?, kprobe.function("sys_truncate64").return ? { name = "truncate" retstr = returnstr(1) } # tux ________________________________________________________ # long sys_tux (unsigned int action, user_req_t *u_info) # probe nd_syscall.tux = kprobe.function("sys_tux") ? { name = "tux" // action = $action // u_info_uaddr = $u_info // argstr = sprintf("%d, %p", $action, $u_info) // no sys_tux in recent kernels; guessing asmlinkage asmlinkage() action = uint_arg(1) u_info_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", action, u_info_uaddr) } probe nd_syscall.tux.return = kprobe.function("sys_tux").return ? { name = "tux" retstr = returnstr(1) } # umask ______________________________________________________ # long sys_umask(int mask) # probe nd_syscall.umask = kprobe.function("sys_umask") ? { name = "umask" // mask = $mask // argstr = sprintf("%#o", $mask) asmlinkage() mask = int_arg(1) argstr = sprintf("%#o", mask) } probe nd_syscall.umask.return = kprobe.function("sys_umask").return ? { name = "umask" retstr = returnstr(3) } # umount _____________________________________________________ # long sys_umount(char __user * name, int flags) # probe nd_syscall.umount = kprobe.function("sys_umount") ? { name = "umount" // target = user_string($name) // flags = $flags // flags_str = _umountflags_str($flags) // argstr = sprintf("%s, %s", user_string_quoted($name), flags_str) asmlinkage() target = user_string_quoted(pointer_arg(1)) flags = int_arg(2) flags_str = _umountflags_str(flags) argstr = sprintf("%s, %s", user_string_quoted(pointer_arg(1)), flags_str) } probe nd_syscall.umount.return = kprobe.function("sys_umount").return ? { name = "umount" retstr = returnstr(1) } # uname ______________________________________________________ # # int sys_uname(struct old_utsname __user *name) # long sys_newuname(struct new_utsname __user * name) # int sys_olduname(struct oldold_utsname __user * name) # int sys32_olduname(struct oldold_utsname __user * name) # long sys32_uname(struct old_utsname __user * name) # probe nd_syscall.uname = kprobe.function("sys_uname") ?, kprobe.function("sys_olduname") ?, kprobe.function("sys32_olduname") ?, kprobe.function("sys32_uname") ?, kprobe.function("sys_newuname") ? { name = "uname" // argstr = sprintf("%p", $name) _func_name = symname(addr()) if (_func_name != "sys32_uname") { if (_func_name == "sys_uname" || _func_name == "sys_olduname") { %( arch != "powerpc" %? asmlinkage() %) } else asmlinkage() } argstr = sprintf("%p", pointer_arg(1)) } probe nd_syscall.uname.return = kprobe.function("sys_uname").return ?, kprobe.function("sys_olduname").return ?, kprobe.function("sys32_olduname").return ?, kprobe.function("sys32_uname").return ?, kprobe.function("sys_newuname").return ? { name = "uname" retstr = returnstr(1) } # unlink _____________________________________________________ # long sys_unlink(const char __user * pathname) # probe nd_syscall.unlink = kprobe.function("sys_unlink") ? { name = "unlink" // pathname_uaddr = $pathname // pathname = user_string($pathname) // argstr = user_string_quoted($pathname) asmlinkage() pathname_uaddr = pointer_arg(1) pathname = user_string_quoted(pathname_uaddr) argstr = user_string_quoted(pathname_uaddr) } probe nd_syscall.unlink.return = kprobe.function("sys_unlink").return ? { name = "unlink" retstr = returnstr(1) } # unlinkat ___________________________________________________ # new function with 2.6.16 # long sys_unlinkat(int dfd, const char __user *pathname, # int flag) probe nd_syscall.unlinkat = kprobe.function("sys_unlinkat") ? { name = "unlinkat" // dfd = $dfd // dfd_str = _dfd_str($dfd) // pathname = $pathname // pathname_str = user_string($pathname) // flag = $flag // flag_str = _at_flag_str($flag) // argstr = sprintf("%s, %s, %s", dfd_str, user_string_quoted($pathname), flag_str) asmlinkage() dfd = int_arg(1) dfd_str = _dfd_str(dfd) pathname = pointer_arg(2) pathname_str = user_string_quoted(pathname) flag = int_arg(3) flag_str = _at_flag_str(flag) argstr = sprintf("%s, %s, %s", dfd_str, user_string_quoted(pathname), flag_str) } probe nd_syscall.unlinkat.return = kprobe.function("sys_unlinkat").return ? { name = "unlinkat" retstr = returnstr(1) } # unshare ____________________________________________________ # new function with 2.6.16 # long sys_unshare(unsigned long unshare_flags) probe nd_syscall.unshare = kprobe.function("sys_unshare") ? { name = "unshare" // unshare_flags = $unshare_flags asmlinkage() unshare_flags = ulong_arg(1) argstr = __fork_flags(unshare_flags) } probe nd_syscall.unshare.return = kprobe.function("sys_unshare").return ? { name = "unshare" retstr = returnstr(1) } # uselib _____________________________________________________ # # asmlinkage long # sys_uselib(const char __user * library) # probe nd_syscall.uselib = kprobe.function("sys_uselib") ? { name = "uselib" // library_uaddr = $library // library = user_string($library) // argstr = user_string_quoted($library) asmlinkage() library_uaddr = pointer_arg(1) library = user_string_quoted(library_uaddr) argstr = user_string_quoted(library_uaddr) } probe nd_syscall.uselib.return = kprobe.function("sys_uselib").return ? { name = "uselib" retstr = returnstr(1) } # ustat ______________________________________________________ # long sys_ustat(unsigned dev, struct ustat __user * ubuf) # probe nd_syscall.ustat = kprobe.function("sys_ustat") ? { name = "ustat" // dev = $dev // ubuf_uaddr = $ubuf // argstr = sprintf("%d, %p", $dev, $ubuf) asmlinkage() dev = uint_arg(1) ubuf_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", dev, ubuf_uaddr) } #long sys32_ustat(unsigned dev, struct ustat32 __user *u32p) probe nd_syscall.ustat32 = kprobe.function("sys32_ustat") ? { name = "ustat" // dev = $dev // ubuf_uaddr = (@defined($u) ? $u : $u32p) // argstr = sprintf("%d, %p", $dev, (@defined($u) ? $u : $u32p)) // no asmlinkage dev = uint_arg(1) ubuf_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", dev, ubuf_uaddr) } # Since 2.6.30 sys32_ustat is called compat_sys_ustat and is now asmlinkage. #asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u) probe nd_syscall.ustat32 = kprobe.function("compat_sys_ustat") ? { name = "ustat" // dev = $dev // ubuf_uaddr = (@defined($u) ? $u : $u32p) // argstr = sprintf("%d, %p", $dev, (@defined($u) ? $u : $u32p)) // asmlinkage asmlinkage() dev = uint_arg(1) ubuf_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", dev, ubuf_uaddr) } probe nd_syscall.ustat.return = kprobe.function("sys_ustat").return ? { name = "ustat" retstr = returnstr(1) } probe nd_syscall.ustat32.return = kprobe.function("sys32_ustat").return ?, kprobe.function("compat_sys_ustat").return ? { name = "ustat" retstr = returnstr(1) } # utime ______________________________________________________ # long sys_utime(char __user * filename, struct utimbuf __user * times) probe nd_syscall.utime = kprobe.function("sys_utime") ? { name = "utime" asmlinkage() filename_uaddr = pointer_arg(1) filename = user_string_quoted(filename_uaddr) buf_uaddr = pointer_arg(2) actime = _struct_utimbuf_actime(buf_uaddr) modtime = _struct_utimbuf_modtime(buf_uaddr) argstr = sprintf("%s, [%s, %s]", filename, ctime(actime), ctime(modtime)) } probe nd_syscall.utime.return = kprobe.function("sys_utime").return ? { name = "utime" retstr = returnstr(1) } # long compat_sys_utime(char __user *filename, struct compat_utimbuf __user *t) probe nd_syscall.compat_utime = kprobe.function("compat_sys_utime") ? { name = "utime" asmlinkage() filename_uaddr = pointer_arg(1) filename = user_string_quoted(filename_uaddr) buf_uaddr = pointer_arg(2) actime = _struct_compat_utimbuf_actime(buf_uaddr) modtime = _struct_compat_utimbuf_modtime(buf_uaddr) argstr = sprintf("%s, [%s, %s]", filename, ctime(actime), ctime(modtime)) } probe nd_syscall.compat_utime.return = kprobe.function("compat_sys_utime").return ? { name = "utime" retstr = returnstr(1) } # utimes _____________________________________________________ # # long sys_utimes(char __user * filename, struct timeval __user * utimes) # probe nd_syscall.utimes = kprobe.function("sys_utimes") ? { name = "utimes" // filename_uaddr = $filename // filename = user_string($filename) // tvp_uaddr = $utimes // argstr = sprintf("%s, %s", user_string_quoted($filename), // _struct_timeval_u($utimes, 2)) asmlinkage() filename_uaddr = pointer_arg(1) filename = user_string_quoted(filename_uaddr) tvp_uaddr = pointer_arg(2) argstr = sprintf("%s, %s", user_string_quoted(filename_uaddr), _struct_timeval_u(tvp_uaddr, 2)) } probe nd_syscall.utimes.return = kprobe.function("sys_utimes").return ? { name = "utimes" retstr = returnstr(1) } # compat_sys_utimes ________________________________________ # # long compat_sys_utimes(char __user *filename, struct compat_timeval __user *t) # probe nd_syscall.compat_sys_utimes = kprobe.function("compat_sys_utimes") ? { name = "utimes" // filename = user_string($filename) // argstr = sprintf("%s, %s", user_string_quoted($filename), // _struct_compat_timeval_u($t, 2)) asmlinkage() filename = user_string_quoted(pointer_arg(1)) argstr = sprintf("%s, %s", user_string_quoted(pointer_arg(1)), _struct_compat_timeval_u(pointer_arg(2), 2)) } probe nd_syscall.compat_sys_utimes.return = kprobe.function("compat_sys_utimes").return ? { name = "utimes" retstr = returnstr(1) } # utimensat ____________________________________________________ # long sys_utimensat(int dfd, char __user *filename, struct timespec __user *utimes, int flags) # long compat_sys_utimensat(unsigned int dfd, char __user *filename, struct compat_timespec __user *t, int flags) # probe nd_syscall.utimensat = kprobe.function("sys_utimensat") ? { name = "utimensat" // argstr = sprintf("%s, %s, %s, %s", _dfd_str($dfd), user_string_quoted($filename), _struct_timespec_u($utimes, 2), // _at_flag_str($flags)) asmlinkage() argstr = sprintf("%s, %s, %s, %s", _dfd_str(int_arg(1)), user_string_quoted(pointer_arg(2)), _struct_timespec_u(pointer_arg(3), 2), _at_flag_str(int_arg(4))) } probe nd_syscall.compat_utimensat = kprobe.function("compat_sys_utimensat") ? { name = "utimensat" // argstr = sprintf("%s, %s, %s, %s", _dfd_str($dfd), user_string_quoted($filename), _struct_compat_timespec_u($t, 2), // _at_flag_str($flags)) asmlinkage() argstr = sprintf("%s, %s, %s, %s", _dfd_str(uint_arg(1)), user_string_quoted(pointer_arg(2)), _struct_compat_timespec_u(pointer_arg(3), 2), _at_flag_str(int_arg(4))) } probe nd_syscall.utimensat.return = kprobe.function("sys_utimensat").return ? { name = "utimensat" retstr = returnstr(1) } probe nd_syscall.compat_utimensat.return = kprobe.function("compat_sys_utimensat").return ? { name = "utimensat" retstr = returnstr(1) } # vhangup ____________________________________________________ # # asmlinkage long # sys_vhangup(void) # probe nd_syscall.vhangup = kprobe.function("sys_vhangup") { name = "vhangup" argstr = "" } probe nd_syscall.vhangup.return = kprobe.function("sys_vhangup").return { name = "vhangup" retstr = returnstr(1) } # vmsplice ___________________________________________________ # # long sys_vmsplice(int fd, const struct iovec __user *iov, # unsigned long nr_segs, unsigned int flags) # long compat_sys_vmsplice(int fd, const struct compat_iovec __user *iov32, # unsigned int nr_segs, unsigned int flags) # probe nd_syscall.vmsplice = kprobe.function("sys_vmsplice") ? { name = "vmsplice" // argstr = sprintf("%d, %p, %d, 0x%x", $fd, $iov, $nr_segs, $flags) asmlinkage() argstr = sprintf("%d, %p, %d, 0x%x", int_arg(1), pointer_arg(2), ulong_arg(3), uint_arg(4)) } probe nd_syscall.compat_vmsplice = kprobe.function("compat_sys_vmsplice") ? { name = "vmsplice" // argstr = sprintf("%d, %p, %d, 0x%x", $fd, $iov32, $nr_segs, $flags) asmlinkage() argstr = sprintf("%d, %p, %d, 0x%x", int_arg(1), pointer_arg(2), uint_arg(3), uint_arg(4)) } probe nd_syscall.vmsplice.return = kprobe.function("sys_vmsplice").return ? { name = "vmsplice" retstr = returnstr(1) } probe nd_syscall.compat_vmsplice.return = kprobe.function("compat_sys_vmsplice").return ? { name = "vmsplice" retstr = returnstr(1) } # wait4 ______________________________________________________ # # long sys_wait4(pid_t pid, # int __user *stat_addr, # int options, # struct rusage __user *ru) # probe nd_syscall.wait4 = kprobe.function("sys_wait4") ? { name = "wait4" // pid = (@defined($upid) ? $upid : $pid) // status_uaddr = $stat_addr // options = $options & 0xffffffff // options_str = _wait4_opt_str(options) // rusage_uaddr = $ru // argstr = sprintf("%d, %p, %s, %p", // (@defined($upid) ? $upid : $pid), // $stat_addr, _wait4_opt_str($options), $ru) asmlinkage() pid = int_arg(1) status_uaddr = pointer_arg(2) options = int_arg(3) & 0xffffffff options_str = _wait4_opt_str(options) rusage_uaddr = pointer_arg(4) argstr = sprintf("%d, %p, %s, %p", pid, status_uaddr, _wait4_opt_str(options), rusage_uaddr) } probe nd_syscall.wait4.return = kprobe.function("sys_wait4").return ? { name = "wait4" status_uaddr = pointer_arg(2) if (returnval () <= 0) status_str = "N/A" else if (status_uaddr == 0) status_str = "NULL" else status_str = _wait_status_str(user_int(status_uaddr)) retstr = returnstr(1) } # waitid _____________________________________________________ # # long sys_waitid(int which, # pid_t pid, # struct siginfo __user *infop, # int options, # struct rusage __user *ru) # probe nd_syscall.waitid = kprobe.function("sys_waitid") ? { name = "waitid" // pid = (@defined($upid) ? $upid : $pid) // which = $which // which_str = _waitid_which_str($which) // infop_uaddr = $infop // options = $options // options_str = _waitid_opt_str($options) // rusage_uaddr = $ru // argstr = sprintf("%d, %d, %p, %s, %p", $which, // (@defined($upid) ? $upid : $pid), $infop, // _waitid_opt_str($options), $ru) asmlinkage() pid = int_arg(1) which = int_arg(2) which_str = _waitid_which_str(which) infop_uaddr = pointer_arg(3) options = int_arg(4) options_str = _waitid_opt_str(options) rusage_uaddr = pointer_arg(5) argstr = sprintf("%d, %d, %p, %s, %p", which, pid, infop_uaddr, _waitid_opt_str(options), rusage_uaddr) } probe nd_syscall.waitid.return = kprobe.function("sys_waitid").return ? { name = "waitid" retstr = returnstr(1) } /* FIXME: # waitpid ____________________________________________________ # # long sys_wait4(pid_t pid, # int __user *stat_addr, # int options, # struct rusage __user *ru) # probe nd_syscall.waitpid = kprobe.function("sys_wait4") ? { name = "waitpid" pid = $pid status_uaddr = $stat_addr options = $options & 0xffffffff options_str = _wait4_opt_str(options) rusage_uaddr = $ru argstr = sprintf("%d, %p, %s, %p", $pid, $stat_addr, options_str, $ru) } probe nd_syscall.waitpid.return = kprobe.function("sys_wait4").return ? { name = "waitpid" retstr = returnstr(1) } */ # write ______________________________________________________ # # ssize_t sys_write(unsigned int fd, # const char __user * buf, # size_t count) # probe nd_syscall.write = kprobe.function("sys_write") ? { name = "write" // fd = $fd // buf_uaddr = $buf // count = $count // argstr = sprintf("%d, %s, %d", $fd, text_strn(user_string($buf), syscall_string_trunc, 1), $count) asmlinkage() fd = uint_arg(1) buf_uaddr = pointer_arg(2) count = ulong_arg(3) argstr = sprintf("%d, %s, %d", fd, user_string_n_quoted(buf_uaddr, syscall_string_trunc), count) } probe nd_syscall.write.return = kprobe.function("sys_write").return ? { name = "write" retstr = returnstr(1) } # writev _____________________________________________________ # # ssize_t sys_writev(unsigned long fd, # const struct iovec __user *vec, # unsigned long vlen) # ssize_t compat_sys_writev(unsigned long fd, # const struct compat_iovec __user *vec, # unsigned long vlen) # probe nd_syscall.writev = kprobe.function("compat_sys_writev") ?, kprobe.function("sys_writev") ? { name = "writev" // vector_uaddr = $vec // count = $vlen // fd = $fd // argstr = sprintf("%d, %p, %d", $fd, $vec, $vlen) asmlinkage() vector_uaddr = pointer_arg(2) count = ulong_arg(3) fd = ulong_arg(1) argstr = sprintf("%d, %p, %d", fd, vector_uaddr, count) } probe nd_syscall.writev.return = kprobe.function("compat_sys_writev").return ?, kprobe.function("sys_writev").return ? { name = "writev" retstr = returnstr(1) } systemtap-2.3/tapset/linux/netfilter.stp000066400000000000000000000644521217430427200206070ustar00rootroot00000000000000/* netfilter.stp - netfilter hook tapset * * Copyright (C) 2012 Red Hat Inc. * * This family of probe points provides a simple way to examine network traffic using the netfilter hooks mechanism. * */ /* The below functionality is mostly inspired by tcp.stp and networking.stp. */ %{ #include #include #include #include #include %} # XXX: IPPROTO_* and NF_* constants should be secure globals -- needs PR10607 # ... currently we use a hideous copypasta hack which defines them as # locals in each probe alias. Blegh function __read_char:long(addr:long) %{ /* pure */ STAP_RETVALUE = kderef(sizeof(char), STAP_ARG_addr); CATCH_DEREF_FAULT (); %} function __mac_addr_to_string:string(addr:long) { return sprintf("%02x:%02x:%02x:%02x:%02x:%02x", __read_char(addr), __read_char(addr+1), __read_char(addr+2), __read_char(addr+3), __read_char(addr+4), __read_char(addr+5)) } function __get_mac_addr:string(addr:long) { return __mac_addr_to_string(@cast(addr, "struct net_device")->dev_addr) } function __get_skb_arphdr:long(addr:long) { // The method is exactly the same as for an IP header: return __get_skb_iphdr(addr) } function __ip6_skb_proto:long(addr:long) %{ /* pure */ struct sk_buff *skb = (struct sk_buff *)(uintptr_t)STAP_ARG_addr; struct ipv6hdr *hdr; u8 nexthdr; /* We call deref() here to ensure the memory at the skb location * is valid to read, to avoid potential kernel panic calling ipv6_hdr(). */ (void)kderef_buffer(NULL, skb, sizeof(struct sk_buff)); hdr = ipv6_hdr(skb); nexthdr = kread(&(hdr->nexthdr)); if (ipv6_ext_hdr(nexthdr)) { #if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) long result = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr); #else __be16 frag_offp; int extoff = (u8 *)(hdr + 1) - kread(&(skb->data)); long result = ipv6_skip_exthdr(skb, extoff, &nexthdr, &frag_offp); #endif STAP_RETVALUE = result < 0 ? 0 : result; } else { STAP_RETVALUE = 0; } CATCH_DEREF_FAULT(); %} @define netfilter_common_setup(pf_name) %( pf = @pf_name /* XXX not relevant for netfilter.arp & netfilter.bridge probes */ ipproto_tcp = %{ /* pure */ IPPROTO_TCP %} ipproto_udp = %{ /* pure */ IPPROTO_UDP %} /* from include/linux/netfilter.h: */ nf_drop = 0 nf_accept = 1 nf_stolen = 2 nf_queue = 3 nf_repeat = 4 nf_stop = 5 indev = $in; outdev = $out indev_name = kernel_string2(@cast(indev,"struct net_device")->name, "") outdev_name = kernel_string2(@cast(outdev,"struct net_device")->name, "") if (indev) { indev_mac_len = @cast(indev,"struct net_device")->addr_len in_mac = __get_mac_addr(indev) } if (outdev) { outdev_mac_len = @cast(outdev,"struct net_device")->addr_len out_mac = __get_mac_addr(outdev) } %) @define netfilter_ip4_setup %( iphdr = __get_skb_iphdr($skb) family = %{ /* pure */ AF_INET %} saddr = format_ipaddr(__ip_skb_saddr(iphdr), %{ /* pure */ AF_INET %}) daddr = format_ipaddr(__ip_skb_daddr(iphdr), %{ /* pure */ AF_INET %}) protocol = __ip_skb_proto(iphdr) length = @cast($skb, "struct sk_buff")->len tcphdr = __get_skb_tcphdr($skb) if (protocol == ipproto_tcp) { dport = __tcp_skb_dport(tcphdr) sport = __tcp_skb_sport(tcphdr) urg = __tcp_skb_urg(tcphdr) ack = __tcp_skb_ack(tcphdr) psh = __tcp_skb_psh(tcphdr) rst = __tcp_skb_rst(tcphdr) syn = __tcp_skb_syn(tcphdr) fin = __tcp_skb_fin(tcphdr) } udphdr = tcphdr /* the same place where tcphdr would have been */ if (protocol == ipproto_udp) { dport = ntohs(@cast(udphdr,"udphdr")->dest) sport = ntohs(@cast(udphdr,"udphdr")->source) } %) @define netfilter_ip6_setup %( iphdr = __get_skb_iphdr($skb) family = %{ /* pure */ AF_INET6 %} saddr = format_ipaddr(&@cast(iphdr, "ipv6hdr")->saddr, %{ /* pure */ AF_INET6 %}) daddr = format_ipaddr(&@cast(iphdr, "ipv6hdr")->daddr, %{ /* pure */ AF_INET6 %}) protocol = __ip6_skb_proto($skb) length = @cast($skb, "struct sk_buff")->len tcphdr = __get_skb_tcphdr($skb) if (protocol == ipproto_tcp) { dport = __tcp_skb_dport(tcphdr) sport = __tcp_skb_sport(tcphdr) urg = __tcp_skb_urg(tcphdr) ack = __tcp_skb_ack(tcphdr) psh = __tcp_skb_psh(tcphdr) rst = __tcp_skb_rst(tcphdr) syn = __tcp_skb_syn(tcphdr) fin = __tcp_skb_fin(tcphdr) } udphdr = tcphdr /* the same place where tcphdr would have been */ if (protocol == ipproto_udp) { dport = ntohs(@cast(udphdr,"udphdr")->dest) sport = ntohs(@cast(udphdr,"udphdr")->source) } %) /** * probe netfilter.ip.pre_routing - Called before an IP packet is routed * @pf: Protocol family - either 'ipv4' or 'ipv6' * @indev: Address of net_device representing input device, 0 if unknown * @outdev: Address of net_device representing output device, 0 if unknown * @indev_name: Name of network device packet was received on (if known) * @outdev_name: Name of network device packet will be routed to (if known) * @length: The length of the packet buffer contents, in bytes * @iphdr: Address of IP header * @protocol: Packet protocol from driver (ipv4 only) * @ipproto_tcp: Constant used to signify that the packet protocol is TCP * @ipproto_udp: Constant used to signify that the packet protocol is UDP * @nf_drop: Constant used to signify a 'drop' verdict * @nf_accept: Constant used to signify an 'accept' verdict * @nf_stolen: Constant used to signify a 'stolen' verdict * @nf_queue: Constant used to signify a 'queue' verdict * @nf_repeat: Constant used to signify a 'repeat' verdict * @nf_stop: Constant used to signify a 'stop' verdict * @family: IP address family * @saddr: A string representing the source IP address * @daddr: A string representing the destination IP address * @sport: TCP or UDP source port (ipv4 only) * @dport: TCP or UDP destination port (ipv4 only) * @urg: TCP URG flag (if protocol is TCP; ipv4 only) * @ack: TCP ACK flag (if protocol is TCP; ipv4 only) * @psh: TCP PSH flag (if protocol is TCP; ipv4 only) * @rst: TCP RST flag (if protocol is TCP; ipv4 only) * @syn: TCP SYN flag (if protocol is TCP; ipv4 only) * @fin: TCP FIN flag (if protocol is TCP; ipv4 only) */ probe netfilter.ip.pre_routing = netfilter.ipv4.pre_routing, netfilter.ipv6.pre_routing { } probe netfilter.ipv4.pre_routing = netfilter.hook("NF_INET_PRE_ROUTING").pf("NFPROTO_IPV4") { @netfilter_common_setup("ipv4") @netfilter_ip4_setup } probe netfilter.ipv6.pre_routing = netfilter.hook("NF_IP6_PRE_ROUTING").pf("NFPROTO_IPV6") { @netfilter_common_setup("ipv6") @netfilter_ip6_setup } /** * probe netfilter.ip.local_in - Called on an incoming IP packet addressed to the local computer * @pf: Protocol family -- either "ipv4" or "ipv6" * @indev: Address of net_device representing input device, 0 if unknown * @outdev: Address of net_device representing output device, 0 if unknown * @indev_name: Name of network device packet was received on (if known) * @outdev_name: Name of network device packet will be routed to (if known) * @length: The length of the packet buffer contents, in bytes * @iphdr: Address of IP header * @protocol: Packet protocol from driver (ipv4 only) * @ipproto_tcp: Constant used to signify that the packet protocol is TCP * @ipproto_udp: Constant used to signify that the packet protocol is UDP * @nf_drop: Constant used to signify a 'drop' verdict * @nf_accept: Constant used to signify an 'accept' verdict * @nf_stolen: Constant used to signify a 'stolen' verdict * @nf_queue: Constant used to signify a 'queue' verdict * @nf_repeat: Constant used to signify a 'repeat' verdict * @nf_stop: Constant used to signify a 'stop' verdict * @family: IP address family * @saddr: A string representing the source IP address * @daddr: A string representing the destination IP address * @sport: TCP or UDP source port (ipv4 only) * @dport: TCP or UDP destination port (ipv4 only) * @urg: TCP URG flag (if protocol is TCP; ipv4 only) * @ack: TCP ACK flag (if protocol is TCP; ipv4 only) * @psh: TCP PSH flag (if protocol is TCP; ipv4 only) * @rst: TCP RST flag (if protocol is TCP; ipv4 only) * @syn: TCP SYN flag (if protocol is TCP; ipv4 only) * @fin: TCP FIN flag (if protocol is TCP; ipv4 only) */ probe netfilter.ip.local_in = netfilter.ipv4.local_in, netfilter.ipv6.local_in { } probe netfilter.ipv4.local_in = netfilter.hook("NF_INET_LOCAL_IN").pf("NFPROTO_IPV4") { @netfilter_common_setup("ipv4") @netfilter_ip4_setup } probe netfilter.ipv6.local_in = netfilter.hook("NF_IP6_LOCAL_IN").pf("NFPROTO_IPV6") { @netfilter_common_setup("ipv6") @netfilter_ip6_setup } /** * probe netfilter.ip.forward - Called on an incoming IP packet addressed to some other computer * @pf: Protocol family -- either "ipv4" or "ipv6" * @indev: Address of net_device representing input device, 0 if unknown * @outdev: Address of net_device representing output device, 0 if unknown * @indev_name: Name of network device packet was received on (if known) * @outdev_name: Name of network device packet will be routed to (if known) * @length: The length of the packet buffer contents, in bytes * @iphdr: Address of IP header * @protocol: Packet protocol from driver (ipv4 only) * @ipproto_tcp: Constant used to signify that the packet protocol is TCP * @ipproto_udp: Constant used to signify that the packet protocol is UDP * @nf_drop: Constant used to signify a 'drop' verdict * @nf_accept: Constant used to signify an 'accept' verdict * @nf_stolen: Constant used to signify a 'stolen' verdict * @nf_queue: Constant used to signify a 'queue' verdict * @nf_repeat: Constant used to signify a 'repeat' verdict * @nf_stop: Constant used to signify a 'stop' verdict * @family: IP address family * @saddr: A string representing the source IP address * @daddr: A string representing the destination IP address * @sport: TCP or UDP source port (ipv4 only) * @dport: TCP or UDP destination port (ipv4 only) * @urg: TCP URG flag (if protocol is TCP; ipv4 only) * @ack: TCP ACK flag (if protocol is TCP; ipv4 only) * @psh: TCP PSH flag (if protocol is TCP; ipv4 only) * @rst: TCP RST flag (if protocol is TCP; ipv4 only) * @syn: TCP SYN flag (if protocol is TCP; ipv4 only) * @fin: TCP FIN flag (if protocol is TCP; ipv4 only) */ probe netfilter.ip.forward = netfilter.ipv4.forward, netfilter.ipv6.forward { } probe netfilter.ipv4.forward = netfilter.hook("NF_INET_FORWARD").pf("NFPROTO_IPV4") { @netfilter_common_setup("ipv4") @netfilter_ip4_setup } probe netfilter.ipv6.forward = netfilter.hook("NF_IP6_FORWARD").pf("NFPROTO_IPV6") { @netfilter_common_setup("ipv6") @netfilter_ip6_setup } /** * probe netfilter.ip.local_out - Called on an outgoing IP packet * @pf: Protocol family -- either "ipv4" or "ipv6" * @indev: Address of net_device representing input device, 0 if unknown * @outdev: Address of net_device representing output device, 0 if unknown * @indev_name: Name of network device packet was received on (if known) * @outdev_name: Name of network device packet will be routed to (if known) * @length: The length of the packet buffer contents, in bytes * @iphdr: Address of IP header * @protocol: Packet protocol from driver (ipv4 only) * @ipproto_tcp: Constant used to signify that the packet protocol is TCP * @ipproto_udp: Constant used to signify that the packet protocol is UDP * @nf_drop: Constant used to signify a 'drop' verdict * @nf_accept: Constant used to signify an 'accept' verdict * @nf_stolen: Constant used to signify a 'stolen' verdict * @nf_queue: Constant used to signify a 'queue' verdict * @nf_repeat: Constant used to signify a 'repeat' verdict * @nf_stop: Constant used to signify a 'stop' verdict * @family: IP address family * @saddr: A string representing the source IP address * @daddr: A string representing the destination IP address * @sport: TCP or UDP source port (ipv4 only) * @dport: TCP or UDP destination port (ipv4 only) * @urg: TCP URG flag (if protocol is TCP; ipv4 only) * @ack: TCP ACK flag (if protocol is TCP; ipv4 only) * @psh: TCP PSH flag (if protocol is TCP; ipv4 only) * @rst: TCP RST flag (if protocol is TCP; ipv4 only) * @syn: TCP SYN flag (if protocol is TCP; ipv4 only) * @fin: TCP FIN flag (if protocol is TCP; ipv4 only) */ probe netfilter.ip.local_out = netfilter.ipv4.local_out, netfilter.ipv6.local_out { } probe netfilter.ipv4.local_out = netfilter.hook("NF_INET_LOCAL_OUT").pf("NFPROTO_IPV4") { @netfilter_common_setup("ipv4") @netfilter_ip4_setup } probe netfilter.ipv6.local_out = netfilter.hook("NF_IP6_LOCAL_OUT").pf("NFPROTO_IPV6") { @netfilter_common_setup("ipv6") @netfilter_ip6_setup } /** * probe netfilter.ip.post_routing - Called immediately before an outgoing IP packet leaves the computer * @pf: Protocol family -- either "ipv4" or "ipv6" * @indev: Address of net_device representing input device, 0 if unknown * @outdev: Address of net_device representing output device, 0 if unknown * @indev_name: Name of network device packet was received on (if known) * @outdev_name: Name of network device packet will be routed to (if known) * @length: The length of the packet buffer contents, in bytes * @iphdr: Address of IP header * @protocol: Packet protocol from driver (ipv4 only) * @ipproto_tcp: Constant used to signify that the packet protocol is TCP * @ipproto_udp: Constant used to signify that the packet protocol is UDP * @nf_drop: Constant used to signify a 'drop' verdict * @nf_accept: Constant used to signify an 'accept' verdict * @nf_stolen: Constant used to signify a 'stolen' verdict * @nf_queue: Constant used to signify a 'queue' verdict * @nf_repeat: Constant used to signify a 'repeat' verdict * @nf_stop: Constant used to signify a 'stop' verdict * @family: IP address family * @saddr: A string representing the source IP address * @daddr: A string representing the destination IP address * @sport: TCP or UDP source port (ipv4 only) * @dport: TCP or UDP destination port (ipv4 only) * @urg: TCP URG flag (if protocol is TCP; ipv4 only) * @ack: TCP ACK flag (if protocol is TCP; ipv4 only) * @psh: TCP PSH flag (if protocol is TCP; ipv4 only) * @rst: TCP RST flag (if protocol is TCP; ipv4 only) * @syn: TCP SYN flag (if protocol is TCP; ipv4 only) * @fin: TCP FIN flag (if protocol is TCP; ipv4 only) */ probe netfilter.ip.post_routing = netfilter.ipv4.post_routing, netfilter.ipv6.local_out { } probe netfilter.ipv4.post_routing = netfilter.hook("NF_INET_POST_ROUTING").pf("NFPROTO_IPV4") { @netfilter_common_setup("ipv4") @netfilter_ip4_setup } probe netfilter.ipv6.post_routing = netfilter.hook("NF_IP6_POST_ROUTING").pf("NFPROTO_IPV6") { @netfilter_common_setup("ipv6") @netfilter_ip6_setup } function __read4:long (x:long) %{ /* pure */ long a = kderef(sizeof(u32),STAP_ARG_x); STAP_RETVALUE = a; CATCH_DEREF_FAULT(); %} @define netfilter_arp_setup %( # XXX: include functionality to parse ARP packet contents arphdr = __get_skb_arphdr($skb) family = %{ /* pure */ NF_ARP %} // from linux/netfilter_arp.h ar_hrd = ntohs(@cast(arphdr, "struct arphdr")->ar_hrd) ar_pro = ntohs(@cast(arphdr, "struct arphdr")->ar_pro) ar_hln = @cast(arphdr, "struct arphdr")->ar_hln ar_pln = @cast(arphdr, "struct arphdr")->ar_pln ar_op = ntohs(@cast(arphdr, "struct arphdr")->ar_op) ar_data = arphdr + 8 if (ar_hrd == 0x001 && ar_pro == 0x800) { /* additional info available for most common (Ethernet+IP) case: */ ar_sha = __mac_addr_to_string(ar_data) ar_sip = format_ipaddr(__read4(ar_data + 6), %{ /* pure */ AF_INET %}) ar_tha = __mac_addr_to_string(ar_data + 10) ar_tip = format_ipaddr(__read4(ar_data + 16), %{ /* pure */ AF_INET %}) } /* XXX support for additional cases? */ length = @cast($skb, "struct sk_buff")->len %) /** * probe netfilter.arp.in -- Called for each incoming ARP packet * @pf: Protocol family -- always "arp" * @indev: Address of net_device representing input device, 0 if unknown * @outdev: Address of net_device representing output device, 0 if unknown * @indev_name: Name of network device packet was received on (if known) * @outdev_name: Name of network device packet will be routed to (if known) * @length: The length of the packet buffer contents, in bytes * @arphdr: Address of ARP header * @ar_hrd: Format of hardware address * @ar_pro: Format of protocol address * @ar_hln: Length of hardware address * @ar_pln: Length of protocol address * @ar_op: ARP opcode (command) * @ar_data: Address of ARP packet data region (after the header) * @ar_sha: Ethernet+IP only (ar_pro==0x800): source hardware (MAC) address * @ar_sip: Ethernet+IP only (ar_pro==0x800): source IP address * @ar_tha: Ethernet+IP only (ar_pro==0x800): target hardware (MAC) address * @ar_tip: Ethernet+IP only (ar_pro==0x800): target IP address * @nf_drop: Constant used to signify a 'drop' verdict * @nf_accept: Constant used to signify an 'accept' verdict * @nf_stolen: Constant used to signify a 'stolen' verdict * @nf_queue: Constant used to signify a 'queue' verdict * @nf_repeat: Constant used to signify a 'repeat' verdict * @nf_stop: Constant used to signify a 'stop' verdict */ probe netfilter.arp.in = netfilter.hook("NF_ARP_IN").pf("NFPROTO_ARP") { @netfilter_common_setup("arp") @netfilter_arp_setup } /** * probe netfilter.arp.out -- Called for each outgoing ARP packet * @pf: Protocol family -- always "arp" * @indev: Address of net_device representing input device, 0 if unknown * @outdev: Address of net_device representing output device, 0 if unknown * @indev_name: Name of network device packet was received on (if known) * @outdev_name: Name of network device packet will be routed to (if known) * @length: The length of the packet buffer contents, in bytes * @arphdr: Address of ARP header * @ar_hrd: Format of hardware address * @ar_pro: Format of protocol address * @ar_hln: Length of hardware address * @ar_pln: Length of protocol address * @ar_op: ARP opcode (command) * @ar_data: Address of ARP packet data region (after the header) * @ar_sha: Ethernet+IP only (ar_pro==0x800): source hardware (MAC) address * @ar_sip: Ethernet+IP only (ar_pro==0x800): source IP address * @ar_tha: Ethernet+IP only (ar_pro==0x800): target hardware (MAC) address * @ar_tip: Ethernet+IP only (ar_pro==0x800): target IP address * @nf_drop: Constant used to signify a 'drop' verdict * @nf_accept: Constant used to signify an 'accept' verdict * @nf_stolen: Constant used to signify a 'stolen' verdict * @nf_queue: Constant used to signify a 'queue' verdict * @nf_repeat: Constant used to signify a 'repeat' verdict * @nf_stop: Constant used to signify a 'stop' verdict */ probe netfilter.arp.out = netfilter.hook("NF_ARP_OUT").pf("NFPROTO_ARP") { @netfilter_common_setup("arp") @netfilter_arp_setup } /** * probe netfilter.arp.forward -- Called for each ARP packet to be forwarded * @pf: Protocol family -- always "arp" * @indev: Address of net_device representing input device, 0 if unknown * @outdev: Address of net_device representing output device, 0 if unknown * @indev_name: Name of network device packet was received on (if known) * @outdev_name: Name of network device packet will be routed to (if known) * @length: The length of the packet buffer contents, in bytes * @arphdr: Address of ARP header * @ar_hrd: Format of hardware address * @ar_pro: Format of protocol address * @ar_hln: Length of hardware address * @ar_pln: Length of protocol address * @ar_op: ARP opcode (command) * @ar_data: Address of ARP packet data region (after the header) * @ar_sha: Ethernet+IP only (ar_pro==0x800): source hardware (MAC) address * @ar_sip: Ethernet+IP only (ar_pro==0x800): source IP address * @ar_tha: Ethernet+IP only (ar_pro==0x800): target hardware (MAC) address * @ar_tip: Ethernet+IP only (ar_pro==0x800): target IP address * @nf_drop: Constant used to signify a 'drop' verdict * @nf_accept: Constant used to signify an 'accept' verdict * @nf_stolen: Constant used to signify a 'stolen' verdict * @nf_queue: Constant used to signify a 'queue' verdict * @nf_repeat: Constant used to signify a 'repeat' verdict * @nf_stop: Constant used to signify a 'stop' verdict */ probe netfilter.arp.forward = netfilter.hook("NF_ARP_FORWARD").pf("NFPROTO_ARP") { @netfilter_common_setup("arp") @netfilter_arp_setup } # XXX: think of some way to comprehensively study bridged packets? /** * probe netfilter.bridge.pre_routing -- Called before a bridging packet is routed * @pf: Protocol family -- always "bridge" * @indev: Address of net_device representing input device, 0 if unknown * @outdev: Address of net_device representing output device, 0 if unknown * @indev_name: Name of network device packet was received on (if known) * @outdev_name: Name of network device packet will be routed to (if known) * @length: The length of the packet buffer contents, in bytes * @nf_drop: Constant used to signify a 'drop' verdict * @nf_accept: Constant used to signify an 'accept' verdict * @nf_stolen: Constant used to signify a 'stolen' verdict * @nf_queue: Constant used to signify a 'queue' verdict * @nf_repeat: Constant used to signify a 'repeat' verdict * @nf_stop: Constant used to signify a 'stop' verdict */ probe netfilter.bridge.pre_routing = netfilter.hook("NF_BR_PRE_ROUTING").pf("NFPROTO_BRIDGE") { @netfilter_common_setup("bridge") length = @cast($skb, "struct sk_buff")->len } /** * probe netfilter.bridge.local_in - Called on a bridging packet destined for the local computer * @pf: Protocol family -- always "bridge" * @indev: Address of net_device representing input device, 0 if unknown * @outdev: Address of net_device representing output device, 0 if unknown * @indev_name: Name of network device packet was received on (if known) * @outdev_name: Name of network device packet will be routed to (if known) * @length: The length of the packet buffer contents, in bytes * @nf_drop: Constant used to signify a 'drop' verdict * @nf_accept: Constant used to signify an 'accept' verdict * @nf_stolen: Constant used to signify a 'stolen' verdict * @nf_queue: Constant used to signify a 'queue' verdict * @nf_repeat: Constant used to signify a 'repeat' verdict * @nf_stop: Constant used to signify a 'stop' verdict */ probe netfilter.bridge.local_in = netfilter.hook("NF_BR_LOCAL_IN").pf("NFPROTO_BRIDGE") { @netfilter_common_setup("bridge") length = @cast($skb, "struct sk_buff")->len } /** * probe netfilter.bridge.forward - Called on an incoming bridging packet destined for some other computer * @pf: Protocol family -- always "bridge" * @indev: Address of net_device representing input device, 0 if unknown * @outdev: Address of net_device representing output device, 0 if unknown * @indev_name: Name of network device packet was received on (if known) * @outdev_name: Name of network device packet will be routed to (if known) * @length: The length of the packet buffer contents, in bytes * @nf_drop: Constant used to signify a 'drop' verdict * @nf_accept: Constant used to signify an 'accept' verdict * @nf_stolen: Constant used to signify a 'stolen' verdict * @nf_queue: Constant used to signify a 'queue' verdict * @nf_repeat: Constant used to signify a 'repeat' verdict * @nf_stop: Constant used to signify a 'stop' verdict */ probe netfilter.bridge.forward = netfilter.hook("NF_BR_FORWARD").pf("NFPROTO_BRIDGE") { @netfilter_common_setup("bridge") length = @cast($skb, "struct sk_buff")->len } /** * probe netfilter.bridge.local_out - Called on a bridging packet coming from a local process * @pf: Protocol family -- always "bridge" * @indev: Address of net_device representing input device, 0 if unknown * @outdev: Address of net_device representing output device, 0 if unknown * @indev_name: Name of network device packet was received on (if known) * @outdev_name: Name of network device packet will be routed to (if known) * @length: The length of the packet buffer contents, in bytes * @nf_drop: Constant used to signify a 'drop' verdict * @nf_accept: Constant used to signify an 'accept' verdict * @nf_stolen: Constant used to signify a 'stolen' verdict * @nf_queue: Constant used to signify a 'queue' verdict * @nf_repeat: Constant used to signify a 'repeat' verdict * @nf_stop: Constant used to signify a 'stop' verdict */ probe netfilter.bridge.local_out = netfilter.hook("NF_BR_LOCAL_OUT").pf("NFPROTO_BRIDGE") { @netfilter_common_setup("bridge") length = @cast($skb, "struct sk_buff")->len } /** * probe netfilter.bridge.post_routing -- Called before a bridging packet hits the wire * @pf: Protocol family -- always "bridge" * @indev: Address of net_device representing input device, 0 if unknown * @outdev: Address of net_device representing output device, 0 if unknown * @indev_name: Name of network device packet was received on (if known) * @outdev_name: Name of network device packet will be routed to (if known) * @length: The length of the packet buffer contents, in bytes * @nf_drop: Constant used to signify a 'drop' verdict * @nf_accept: Constant used to signify an 'accept' verdict * @nf_stolen: Constant used to signify a 'stolen' verdict * @nf_queue: Constant used to signify a 'queue' verdict * @nf_repeat: Constant used to signify a 'repeat' verdict * @nf_stop: Constant used to signify a 'stop' verdict */ probe netfilter.bridge.post_routing = netfilter.hook("NF_BR_POST_ROUTING").pf("NFPROTO_BRIDGE") { @netfilter_common_setup("bridge") length = @cast($skb, "struct sk_buff")->len } systemtap-2.3/tapset/linux/networking.stp000066400000000000000000000160721217430427200207750ustar00rootroot00000000000000// networking tapset // Copyright (C) 2005, 2006 IBM Corp. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // This family of probe points is used to probe the activities of the network device. // /* A function that returns the device name given the net_device struct */ function get_netdev_name:string (addr:long) { return kernel_string(@cast(addr, "net_device")->name) } /** * probe netdev.receive - Data received from network device. * @dev_name: The name of the device. e.g: eth0, ath1. * @length: The length of the receiving buffer. * @protocol: Protocol of received packet. * */ /// protocol /// The possible values of protocol could be: ///
Sample output of when piped through gnuplot
Protocol Values /// /// /// /// /// Value(Hex)Protocol /// /// /// 0001802.3 /// 0002AX.25 /// 0004802.2 /// 0005SNAP /// 0009Localtalk /// 0800IP /// 0805X.25 /// 0806ARP /// 8035RARP /// 8100802.1Q VLAN /// 8137IPX /// 86DDIPv6 /// /// ///
///
/// /// /// truesize /// /// The size of the received data. /// /// /// /// /// // Main device receive routine, be called when packet arrives on network device probe netdev.receive = kernel.function("netif_receive_skb") { dev_name = kernel_string($skb->dev->name) length = $skb->len protocol = $skb->protocol truesize = $skb->truesize } /** * probe netdev.transmit - Network device transmitting buffer * @dev_name: The name of the device. e.g: eth0, ath1. * @length: The length of the transmit buffer. * @protocol: The protocol of this packet(defined in include/linux/if_ether.h). * @truesize: The size of the data to be transmitted. * */ // Queue a buffer for transmission to a network device probe netdev.transmit = kernel.function("dev_queue_xmit") { dev_name = kernel_string($skb->dev->name) length = $skb->len protocol = $skb->protocol truesize = $skb->truesize } /** * probe netdev.change_mtu - Called when the netdev MTU is changed * @dev_name: The device that will have the MTU changed * @old_mtu: The current MTU * @new_mtu: The new MTU */ probe netdev.change_mtu = kernel.function("dev_set_mtu") { old_mtu = $dev->mtu new_mtu = $new_mtu dev_name = get_netdev_name($dev) } /** * probe netdev.open - Called when the device is opened * @dev_name: The device that is going to be opened */ probe netdev.open = kernel.function("dev_open") { dev_name = get_netdev_name($dev) } /** * probe netdev.close - Called when the device is closed * @dev_name: The device that is going to be closed */ probe netdev.close = kernel.function("dev_close") { dev_name = get_netdev_name($dev) } /** * probe netdev.hard_transmit - Called when the devices is going to TX (hard) * @dev_name: The device scheduled to transmit * @protocol: The protocol used in the transmission * @length: The length of the transmit buffer. * @truesize: The size of the data to be transmitted. */ probe netdev.hard_transmit = kernel.function("dev_hard_start_xmit") ? { dev_name = get_netdev_name($dev) protocol = $skb->protocol length = $skb->len truesize = $skb->truesize } /** * probe netdev.rx - Called when the device is going to receive a packet * @dev_name: The device received the packet * @protocol: The packet protocol */ probe netdev.rx = kernel.function("netif_rx") { netdev = $skb->dev dev_name = get_netdev_name(netdev) protocol = $skb->protocol } /** * probe netdev.change_rx_flag - Called when the device RX flag will be changed * @dev_name: The device that will be changed * @flags: The new flags */ probe netdev.change_rx_flag = kernel.function("dev_change_rx_flags") ? { dev_name = (@defined($dev) ? get_netdev_name($dev) : "unknown") flags = @choose_defined($flags, 0) } /** * probe netdev.set_promiscuity - Called when the device enters/leaves promiscuity * @dev_name: The device that is entering/leaving promiscuity mode * @enable: If the device is entering promiscuity mode * @disable: If the device is leaving promiscuity mode * @inc: Count the number of promiscuity openers */ probe netdev.set_promiscuity = kernel.function("dev_set_promiscuity") { dev_name = get_netdev_name($dev) if ($inc){ enable = 1 } else { disable = 1 } inc = $inc } /** * probe netdev.ioctl - Called when the device suffers an IOCTL * @cmd: The IOCTL request * @arg: The IOCTL argument (usually the netdev interface) */ probe netdev.ioctl = kernel.function("dev_ioctl") { cmd = $cmd arg = user_string_quoted($arg) } /** * probe netdev.register - Called when the device is registered * @dev_name: The device that is going to be registered */ probe netdev.register = kernel.function("register_netdevice"), kernel.function("register_netdev") { dev_name = get_netdev_name($dev) } /** * probe netdev.unregister - Called when the device is being unregistered * @dev_name: The device that is going to be unregistered */ probe netdev.unregister = kernel.function("unregister_netdev") { dev_name = get_netdev_name($dev) } /** * probe netdev.get_stats - Called when someone asks the device statistics * @dev_name: The device that is going to provide the statistics */ probe netdev.get_stats = kernel.function("dev_get_stats") ? { dev_name = get_netdev_name($dev) } /** * probe netdev.change_mac - Called when the netdev_name has the MAC changed * @dev_name: The device that will have the MAC changed * @mac_len: The MAC length * @old_mac: The current MAC address * @new_mac: The new MAC address */ probe netdev.change_mac = kernel.function("dev_set_mac_address") ? { dev_name = get_netdev_name($dev) mac_len = $dev->addr_len // Old MAC Address old_mac = sprintf("%02x:%02x:%02x:%02x:%02x:%02x", $dev->dev_addr[0], $dev->dev_addr[1], $dev->dev_addr[2], $dev->dev_addr[3], $dev->dev_addr[4], $dev->dev_addr[5]) // New MAC Address new_mac = sprintf("%02x:%02x:%02x:%02x:%02x:%02x", $sa->sa_data[0], $sa->sa_data[1], $sa->sa_data[2], $sa->sa_data[3], $sa->sa_data[4], $sa->sa_data[5]) } systemtap-2.3/tapset/linux/nfs.stp000066400000000000000000001034231217430427200173710ustar00rootroot00000000000000// nfs tapset // Copyright (C) 2006-2007 IBM Corp. // Copyright (C) 2007 Intel Corporation. // Copyright (C) 2007 Bull S.A.S // Copyright (c) 2009,2010,2011 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. %{ #include #include %} /* Get cache_validity flag from struct inode */ function __nfsi_cache_valid:long (inode:long) { if (inode == 0) return -1 return @cast(NFS_I(inode), "nfs_inode", "kernel:nfs")->cache_validity } /* Get read_cache_jiffies from struct inode */ function __nfsi_rcache_time:long (inode:long) { if (inode == 0) return -1 return @cast(NFS_I(inode), "nfs_inode", "kernel:nfs")->read_cache_jiffies } /* Get attrtimeo from struct inode */ function __nfsi_attr_time :long (inode:long) { if (inode == 0) return -1 return @cast(NFS_I(inode), "nfs_inode", "kernel:nfs")->attrtimeo } /* Get ndirty from struct inode */ function __nfsi_ndirty:long (inode:long) { if (inode == 0) return -1 return @choose_defined(@cast(NFS_I(inode), "nfs_inode", "kernel:nfs")->ndirty, -1) } /* Get rsize from struct inode */ function __nfs_server_rsize:long (inode:long) { if (inode == 0) return -1 return @cast(NFS_SERVER(inode), "nfs_server", "kernel:nfs")->rsize } /* Get version from struct inode */ function __nfs_version:long (inode:long) { if (inode == 0) return -1 return @cast(NFS_PROTO(inode), "nfs_rpc_ops", "kernel:nfs")->version } /* Get wsize from struct inode */ function __nfs_server_wsize:long (inode:long) { if (inode == 0) return -1 return @cast(NFS_SERVER(inode), "nfs_server", "kernel:nfs")->wsize } /* Get rpages from struct inode */ function __nfs_rpages:long (inode:long) { if (inode == 0) return -1 return @cast(NFS_SERVER(inode), "nfs_server", "kernel:nfs")->rpages } /* Get wpages from struct inode */ function __nfs_wpages:long (inode:long) { if (inode == 0) return -1 return @cast(NFS_SERVER(inode), "nfs_server", "kernel:nfs")->wpages } /* Get struct inode from struct page */ function __p2i :long (page:long) { mapping = page? @cast(page, "page", "kernel:nfs")->mapping : 0 if (mapping == 0) return 0 return @cast(mapping, "address_space", "kernel:nfs")->host } /* Get i_flags from struct page */ function __p2i_flag : long (page:long) { host = __p2i(page) if (host == 0) return -1 return @cast(host, "inode", "kernel:nfs")->i_flags } /* Get i_state from struct page */ function __p2i_state :long (page:long) { host = __p2i(page) if (host == 0) return -1 return @cast(host, "inode", "kernel:nfs")->i_state } /* Get i_size from struct page */ function __p2i_size :long (page:long) { host = __p2i(page) if (host == 0) return -1 return @cast(host, "inode", "kernel:nfs")->i_size } /* Get s_flags from struct page */ function __p2sb_flag:long (page:long) { host = __p2i(page) i_sb = host? @cast(host, "inode", "kernel:nfs")->i_sb : 0 if (i_sb == 0) return -1 return @cast(i_sb, "super_block", "kernel:nfs")->s_flags } function __file_inode:long (file:long) { dentry = file ? @choose_defined(@cast(file, "file", "kernel:nfs")->f_path->dentry, @cast(file, "file", "kernel:nfs")->f_dentry) : 0 if (dentry == 0) return 0 return @cast(dentry, "dentry", "kernel:nfs")->d_inode } function __file_id:long (file:long) { d_inode = __file_inode(file) if (d_inode == 0) return 0 return @cast(d_inode, "inode", "kernel:nfs")->i_sb->s_id } function __file_mode:long (file:long) { d_inode = __file_inode(file) if (d_inode == 0) return 0 return @cast(d_inode, "inode", "kernel:nfs")->i_mode } function __file_parentname:string (file:long) { dentry = file ? @choose_defined(@cast(file, "file", "kernel:nfs")->f_path->dentry, @cast(file, "file", "kernel:nfs")->f_dentry) : 0 d_parent = dentry? @cast(dentry, "dentry", "kernel:nfs")->d_parent : 0 if (d_parent == 0) return "NULL" name = @cast(d_parent, "dentry", "kernel:nfs")->d_name->name return kernel_string(name) } /* * Combination of generic_segment_checks and iov_length functions * @iov: io vector request * @nr_segs: number of segments in the iovec * @check_flag: whether to check (0 as iov_length, 1 as * generic_segment_checks) * @access_flags: valid when check_flag >0, type of access: * VERIFY_READ - 0 or VERIFY_WRITE - 1 * * @return: number of bytes to write/read */ function __iov_length:long (iov:long, nr_segs:long, check_flag:long, access_flags:long) %{ /* pure */ unsigned long seg; size_t ret = 0; const struct iovec *iov = (const struct iovec *)(long)STAP_ARG_iov; unsigned long nr_segs = (unsigned long)STAP_ARG_nr_segs; for (seg = 0; seg < nr_segs; seg++) { __kernel_size_t iov_len = kread(&(iov[seg].iov_len)); ret += iov_len; if (STAP_ARG_check_flag) { if (unlikely((ssize_t)(ret|iov_len) < 0)) { STAP_RETVALUE = -EINVAL; return; } if (access_ok((int)STAP_ARG_access_flags, kread(&(iov[seg].iov_base)), iov_len)) continue; if (seg == 0) { STAP_RETVALUE = -EFAULT; return; } ret -= iov_len; /* This segment is no good */ break; } } STAP_RETVALUE = (long)ret; CATCH_DEREF_FAULT(); %} probe nfs.fop.entries = nfs.fop.llseek, nfs.fop.read, nfs.fop.write, nfs.fop.aio_read, nfs.fop.aio_write, nfs.fop.mmap, nfs.fop.open, nfs.fop.flush, nfs.fop.release, nfs.fop.sendfile ?, nfs.fop.fsync, nfs.fop.lock { } probe nfs.fop.return = nfs.fop.llseek.return, nfs.fop.read.return, nfs.fop.write.return, nfs.fop.aio_read.return, nfs.fop.aio_write.return, nfs.fop.mmap.return, nfs.fop.open.return, nfs.fop.flush.return, nfs.fop.release.return, nfs.fop.sendfile.return ?, nfs.fop.fsync.return, nfs.fop.lock.return { } /** * probe nfs.fop.llseek - NFS client llseek operation * * @dev: device identifier * @ino: inode number * @offset: the offset of the file will be repositioned * @whence: the position to seek from * @whence_str: symbolic string representation of the position to seek from */ probe nfs.fop.llseek = kernel.function ("nfs_file_llseek") !, module("nfs").function("nfs_file_llseek") { dev = __file_dev($filp) ino = __file_ino($filp) s_id = __file_id($filp) devname = kernel_string(s_id) maxbyte = __file_maxbytes($filp) offset = $offset %(systemtap_v < "2.3" %? origin = @choose_defined($whence, $origin) %) whence = @choose_defined($whence, $origin) whence_str = _seek_whence_str(@choose_defined($whence, $origin)) name = "nfs.fop.llseek" argstr = sprintf("%d, %d", offset, @choose_defined($whence, $origin)) } probe nfs.fop.llseek.return = kernel.function ("nfs_file_llseek").return !, module("nfs").function("nfs_file_llseek").return { name = "nfs.fop.llseek.return" retstr = sprintf("%d", $return) } /** * probe nfs.fop.read - NFS client read operation * * @devname: block device name * * SystemTap uses the vfs.do_sync_read probe to implement this probe * and as a result will get operations other than the NFS client read * operations. */ probe nfs.fop.read = vfs.do_sync_read { s_id = __file_id($filp) devname = kernel_string(s_id) name = "nfs.fop.read" } probe nfs.fop.read.return = vfs.do_sync_read.return { name = "nfs.fop.read.return" } /** * probe nfs.fop.write - NFS client write operation * * @devname: block device name * * SystemTap uses the vfs.do_sync_write probe to implement this probe * and as a result will get operations other than the NFS client write * operations. */ probe nfs.fop.write = vfs.do_sync_write { s_id = __file_id($filp) devname = kernel_string(s_id) name = "nfs.fop.write" } probe nfs.fop.write.return = vfs.do_sync_write.return { name = "nfs.fop.write.return" } /** * probe nfs.fop.aio_read - NFS client aio_read file operation * * @dev: device identifier * @ino: inode number * @count: read bytes * @pos: current position of file * @buf: the address of buf in user space * @parent_name: parent dir name * @file_name: file name * @cache_valid: cache related bit mask flag * @cache_time: when we started read-caching this inode * @attrtimeo: how long the cached information is assumed to be valid. * We need to revalidate the cached attrs for this inode * if jiffies - read_cache_jiffies > attrtimeo. */ probe nfs.fop.aio_read = kernel.function ("nfs_file_read") !, module("nfs").function("nfs_file_read") { dev = __file_dev($iocb->ki_filp) ino = __file_ino($iocb->ki_filp) s_id = __file_id($iocb->ki_filp) devname = kernel_string(s_id) pos = $pos if (@defined($iov)) { buf = $iov->iov_base count = __iov_length($iov, $nr_segs, 0, -1) } else { buf = $buf count = $count } parent_name = __file_parentname($iocb->ki_filp) file_name = __file_filename($iocb->ki_filp) cache_valid = __nfsi_cache_valid(__file_inode($iocb->ki_filp)) cache_time = __nfsi_rcache_time(__file_inode($iocb->ki_filp)) attr_time = __nfsi_attr_time(__file_inode($iocb->ki_filp)) name = "nfs.fop.aio_read" argstr = sprintf("%p, %d, %d", buf, count, pos) size = count units = "bytes" } probe nfs.fop.aio_read.return = kernel.function ("nfs_file_read").return !, module("nfs").function("nfs_file_read").return { name = "nfs.fop.aio_read.return" retstr = sprintf("%d", $return) if ($return > 0) { size = $return } units = "bytes" } /** * probe nfs.fop.aio_write - NFS client aio_write file operation * * @dev: device identifier * @ino: inode number * @count: read bytes * @pos: offset of the file * @buf: the address of buf in user space * @parent_name: parent dir name * @file_name: file name */ probe nfs.fop.aio_write = kernel.function("nfs_file_write") !, module("nfs").function("nfs_file_write") { dev = __file_dev($iocb->ki_filp) ino = __file_ino($iocb->ki_filp) s_id = __file_id($iocb->ki_filp) devname = kernel_string(s_id) pos = $pos if (@defined($iov)) { buf = $iov->iov_base count = __iov_length($iov, $nr_segs, 0, -1) } else { buf = $buf count = $count } parent_name = __file_parentname($iocb->ki_filp) file_name = __file_filename($iocb->ki_filp) name = "nfs.fop.aio_write" argstr = sprintf("%p, %d, %d", buf, count, pos) size = count units = "bytes" } probe nfs.fop.aio_write.return = kernel.function("nfs_file_write").return !, module("nfs").function("nfs_file_write").return { name = "nfs.fop.aio_write.return" retstr = sprintf("%d", $return) if ($return > 0) { size = $return } units = "bytes" } /** * probe nfs.fop.mmap - NFS client mmap operation * * @dev: device identifier * @ino: inode number * @vm_start: start address within vm_mm * @vm_end: the first byte after end address within vm_mm * @vm_flag: vm flags * @buf: the address of buf in user space * @parent_name: parent dir name * @file_name: file name * @cache_valid: cache related bit mask flag * @cache_time: when we started read-caching this inode * @attrtimeo: how long the cached information is assumed to be valid. * We need to revalidate the cached attrs for this inode * if jiffies - read_cache_jiffies > attrtimeo. */ probe nfs.fop.mmap = kernel.function("nfs_file_mmap") !, module("nfs").function("nfs_file_mmap") { dev = __file_dev($file) ino = __file_ino($file) s_id = __file_id($file) devname = kernel_string(s_id) vm_start = $vma->vm_start vm_end = $vma->vm_end vm_flags = $vma->vm_flags parent_name = __file_parentname($file) file_name = __file_filename($file) cache_valid = __nfsi_cache_valid(__file_inode($file)) cache_time = __nfsi_rcache_time(__file_inode($file)) attr_time = __nfsi_attr_time(__file_inode($file)) name = "nfs.fop.mmap" argstr = sprintf("0x%x, 0x%x, 0x%x", vm_start, vm_end, vm_flags) } probe nfs.fop.mmap.return = kernel.function("nfs_file_mmap").return !, module("nfs").function("nfs_file_mmap").return { name = "nfs.fop.mmap.return" retstr = sprintf("%d", $return) } /** * probe nfs.fop.open - NFS client file open operation * * @dev: device identifier * @ino: inode number * @file_name: file name * @flag: file flag * @i_size: file length in bytes */ probe nfs.fop.open = kernel.function("nfs_file_open") !, module("nfs").function("nfs_file_open") { dev = __file_dev($filp) ino = $inode->i_ino s_id = $inode->i_sb->s_id devname = kernel_string(s_id) filename = __file_filename($filp) flag = $filp->f_flags i_size = $inode->i_size name = "nfs.fop.open" argstr = sprintf("%d, %d, %s", flag, ino, filename) } probe nfs.fop.open.return = kernel.function("nfs_file_open").return !, module("nfs").function("nfs_file_open").return { name = "nfs.fop.open.return" retstr = sprintf("%d", $return) } /** * probe nfs.fop.flush - NFS client flush file operation * * @dev: device identifier * @ino: inode number * @mode: file mode * @ndirty: number of dirty page */ probe nfs.fop.flush = kernel.function("nfs_file_flush") !, module("nfs").function("nfs_file_flush") { dev = __file_dev($file) ino = __file_ino($file) s_id = __file_id($file) devname = kernel_string(s_id) mode = $file->f_mode ndirty = __nfsi_ndirty(__file_inode($file)) name = "nfs.fop.flush" argstr = sprintf("%d", ino) } probe nfs.fop.flush.return = kernel.function("nfs_file_flush").return !, module("nfs").function("nfs_file_flush").return { name = "nfs.fop.flush.return" retstr = sprintf("%d", $return) } /** * probe nfs.fop.release - NFS client release page operation * * @dev: device identifier * @ino: inode number * @mode: file mode */ probe nfs.fop.release = kernel.function("nfs_file_release") !, module("nfs").function("nfs_file_release") { dev = __file_dev($filp) ino = $inode->i_ino s_id = $inode->i_sb->s_id devname = kernel_string(s_id) mode = $filp->f_mode name = "nfs.fop.release" argstr = sprintf("%d", ino) } probe nfs.fop.release.return = kernel.function("nfs_file_release").return !, module("nfs").function("nfs_file_release").return { name = "nfs.fop.release.return" retstr = sprintf("%d", $return) } /** * probe nfs.fop.fsync - NFS client fsync operation * * @dev: device identifier * @ino: inode number * @ndirty: number of dirty pages */ probe nfs.fop.fsync = kernel.function("nfs_file_fsync") !, module("nfs").function("nfs_file_fsync") !, kernel.function("nfs_fsync") !, module("nfs").function("nfs_fsync") { dev = __file_dev($file) ino = __file_ino($file) s_id = __file_id($file) devname = kernel_string(s_id) ndirty = __nfsi_ndirty(__file_inode($file)) name = "nfs.fop.fsync" argstr = sprintf("%d", ino) } probe nfs.fop.fsync.return = kernel.function("nfs_file_fsync").return !, module("nfs").function("nfs_file_fsync").return !, kernel.function("nfs_fsync").return !, module("nfs").function("nfs_fsync").return { name = "nfs.fop.fsync.return" retstr = sprintf("%d", $return) } /** * probe nfs.fop.lock - NFS client file lock operation * * @dev: device identifier * @ino: inode number * @i_mode: file type and access rights * @cmd: cmd arguments * @fl_type:lock type * @fl_flag: lock flags * @fl_start: starting offset of locked region * @fl_end: ending offset of locked region */ probe nfs.fop.lock = kernel.function("nfs_lock") !, module("nfs").function("nfs_lock") { dev = __file_dev($filp) ino = __file_ino($filp) s_id = __file_id($filp) devname = kernel_string(s_id) i_mode = __file_mode($filp) cmd = $cmd fl_type = $fl->fl_type fl_flag = $fl->fl_flags fl_start = $fl->fl_start fl_end = $fl->fl_end name = "nfs.fop.lock" argstr = sprintf("%d, %d", cmd, i_mode) } probe nfs.fop.lock.return = kernel.function("nfs_lock").return !, module("nfs").function("nfs_lock").return { name = "nfs.fop.lock.return" retstr = sprintf("%d", $return) } /** * probe nfs.fop.sendfile - NFS client send file operation * * @dev: device identifier * @ino: inode number * @count: read bytes * @ppos: current position of file * @cache_valid: cache related bit mask flag * @cache_time: when we started read-caching this inode * @attrtimeo: how long the cached information is assumed to be valid. * We need to revalidate the cached attrs for this inode * if jiffies - read_cache_jiffies > attrtimeo. */ probe nfs.fop.sendfile = kernel.function("nfs_file_sendfile") !, module("nfs").function("nfs_file_sendfile") ? { dev = __file_dev($filp) ino = __file_ino($filp) s_id = __file_id($filp) devname = kernel_string(s_id) count = $count ppos = $ppos ? kernel_pointer($ppos) : -1 cache_valid = __nfsi_cache_valid(__file_inode($filp)) cache_time = __nfsi_rcache_time(__file_inode($filp)) attr_time = __nfsi_attr_time(__file_inode($filp)) name = "nfs.fop.sendfile" argstr = sprintf("%d, %d", count, ppos) size = count units = "bytes" } probe nfs.fop.sendfile.return = kernel.function("nfs_file_sendfile").return !, module("nfs").function("nfs_file_sendfile").return ? { name = "nfs.fop.sendfile.return" retstr = sprintf("%d", $return) if ($return > 0) { size = $return } units = "bytes" } /** * probe nfs.fop.check_flags - NFS client checking flag operation * * @flag: file flag */ probe nfs.fop.check_flags = kernel.function("nfs_check_flags") !, module("nfs").function("nfs_check_flags") { flag = $flags name = "nfs.fop.check_flags" argstr = sprintf("%d", flag) } probe nfs.fop.check_flags.return = kernel.function("nfs_check_flags").return !, module("nfs").function("nfs_check_flags").return { name = "nfs.fop.check_flags.return" retstr = sprintf("%d", $return) } probe nfs.aop.entries = nfs.aop.readpage, nfs.aop.readpages, nfs.aop.writepage, nfs.aop.writepages, nfs.aop.release_page ?, nfs.aop.write_begin, nfs.aop.write_end { } probe nfs.aop.return = nfs.aop.readpage.return, nfs.aop.readpages.return, nfs.aop.writepage.return, nfs.aop.writepages.return, nfs.aop.release_page.return ?, nfs.aop.write_begin.return, nfs.aop.write_end.return { } /** * probe nfs.aop.readpage - NFS client synchronously reading a page * @__page: the address of page * @dev: device identifier * @ino: inode number * @i_flag: file flags * @i_size: file length in bytes * @sb_flag: super block flags * @file: file argument * @page_index : offset within mapping, can used a page identifier * and position identifier in the page frame * @rsize: read size (in bytes) * @size: number of pages to be read in this execution * * Read the page over, only fires when a previous async * read operation failed */ probe nfs.aop.readpage = kernel.function ("nfs_readpage") !, module("nfs").function ("nfs_readpage") { __page = $page dev = __page_dev(__page) ino = __page_ino(__page) i_flag = __p2i_flag($page) i_size = __p2i_size($page) sb_flag = __p2sb_flag($page) file = $file page_index = $page->index __inode = __p2i($page) rsize = __nfs_server_rsize(__inode) name = "nfs.aop.readpage" argstr = sprintf("%d, %d", page_index, rsize) size = 1 units = "pages" } probe nfs.aop.readpage.return = kernel.function ("nfs_readpage").return !, module("nfs").function ("nfs_readpage").return { name = "nfs.aop.readpage.return" retstr = sprintf("%d", $return) size = 1 units = "pages" } /** * probe nfs.aop.readpages - NFS client reading multiple pages * @dev: device identifier * @ino: inode number * @nr_pages: number of pages attempted to read in this execution * @file: filp argument * @rpages: read size (in pages) * @rsize: read size (in bytes) * @size: number of pages attempted to read in this execution * * Fires when in readahead way, read several pages once */ probe nfs.aop.readpages = kernel.function ("nfs_readpages") !, module("nfs").function ("nfs_readpages") { dev = $mapping->host->i_sb->s_dev ino = $mapping->host->i_ino nr_pages = $nr_pages file = $filp rpages = __nfs_rpages($mapping->host) rsize = __nfs_server_rsize($mapping->host) name = "nfs.aop.readpages" argstr = sprintf("%d", nr_pages) size = nr_pages units = "pages" } probe nfs.aop.readpages.return = kernel.function ("nfs_readpages").return !, module("nfs").function ("nfs_readpages").return { name = "nfs.aop.readpages.return" retstr = sprintf("%d", $return) if ($return > 0 ) { size = $return } units = "pages" } /** * probe nfs.aop.set_page_dirty - NFS client marking page as dirty * @__page: the address of page * @page_flag: page flags * * This probe attaches to the generic __set_page_dirty_nobuffers function. * Thus, this probe is going to fire on many other file systems in * addition to the NFS client. */ probe nfs.aop.set_page_dirty = kernel.function ("__set_page_dirty_nobuffers") !, module("nfs").function ("__set_page_dirty_nobuffers") { __page = $page page_flag = $page->flags name = "nfs.aop.set_page_dirty" argstr = sprintf("%d", page_flag) } probe nfs.aop.set_page_dirty.return = kernel.function ("__set_page_dirty_nobuffers") .return !, module("nfs").function ("__set_page_dirty_nobuffers").return { name = "nfs.aop.set_page_dirty.return" retstr = sprintf("%d", $return) } /** * probe nfs.aop.writepage - NFS client writing a mapped page to the NFS server * @__page: the address of page * @dev: device identifier * @ino: inode number * @for_reclaim: a flag of writeback_control, * indicates if it's invoked from the page allocator * @for_kupdate: a flag of writeback_control, * indicates if it's a kupdate writeback * @i_flag: file flags * @i_size: file length in bytes * @i_state: inode state flags * @sb_flag: super block flags * @page_index: offset within mapping, * can used a page identifier and position identifier in the page frame * @wsize: write size * @size: number of pages to be written in this execution * * The priority of wb is decided by the flags * @for_reclaim and @for_kupdate. */ probe nfs.aop.writepage = kernel.function ("nfs_writepage") !, module("nfs").function ("nfs_writepage") { __page = $page dev = __page_dev(__page) ino = __page_ino(__page) for_reclaim = $wbc->for_reclaim for_kupdate = $wbc->for_kupdate i_flag = __p2i_flag($page) i_state = __p2i_state($page) i_size = __p2i_size($page) sb_flag = __p2sb_flag($page) page_index = $page->index __inode = __p2i($page) wsize = __nfs_server_wsize(__inode) name = "nfs.aop.writepage" argstr = sprintf("%d", page_index) size = 1 units = "pages" } probe nfs.aop.writepage.return = kernel.function ("nfs_writepage").return !, module("nfs").function ("nfs_writepage").return { name = "nfs.aop.writepage.return" retstr = sprintf("%d", $return) } /** * probe nfs.aop.writepages - NFS client writing several dirty pages to the NFS server * @dev: device identifier * @ino: inode number * @for_reclaim: a flag of writeback_control, * indicates if it's invoked from the page allocator * @for_kupdate: a flag of writeback_control, * indicates if it's a kupdate writeback * @wsize: write size * @wpages: write size (in pages) * @nr_to_write: number of pages attempted to be written in this execution * @size: number of pages attempted to be written in this execution * * The priority of wb is decided by the flags * @for_reclaim and @for_kupdate. */ probe nfs.aop.writepages = kernel.function ("nfs_writepages") !, module("nfs").function ("nfs_writepages") { dev = $mapping->host->i_sb->s_dev ino = $mapping->host->i_ino for_reclaim = $wbc->for_reclaim for_kupdate = $wbc->for_kupdate nr_to_write = $wbc->nr_to_write wsize = __nfs_server_wsize($mapping->host) wpages = __nfs_wpages($mapping->host) name = "nfs.aop.writepages" argstr = sprintf("%d", nr_to_write) size = nr_to_write units = "pages" } probe nfs.aop.writepages.return = kernel.function ("nfs_writepages").return !, module("nfs").function ("nfs_writepages").return { name = "nfs.aop.writepages.return" retstr = sprintf("%d", $return) } # kernel commit 4899f9c852564ce7b6d0ca932ac6674bf471fd28 removed # nfs_prepare_write()/nfs_commit_write() and created # nfs_write_begin()/nfs_write_end(). So, we try to find whatever the # current kernel has. /** * probe nfs.aop.write_begin - NFS client begin to write data * @__page: the address of page * @dev: device identifier * @ino: inode number * @offset: start address of this write operation * @to: end address of this write operation * @page_index: offset within mapping, can used a page identifier * and position identifier in the page frame * @size: write bytes * * Occurs when write operation occurs on nfs. It prepare a page for writing, * look for a request corresponding to the page. If there * is one, and it belongs to another file, it flush it out * before it tries to copy anything into the page. * Also do the same if it finds a request from an existing * dropped page * */ probe nfs.aop.write_begin = __nfs.aop.write_begin !, __nfs.aop.prepare_write { } probe nfs.aop.write_begin.return = __nfs.aop.write_begin.return !, __nfs.aop.prepare_write.return { } /** * probe nfs.aop.write_end - NFS client complete writing data * @__page: the address of page * @dev: device identifier * @ino: inode number * @offset: start address of this write operation * @to: end address of this write operation * @i_flag: file flags * @i_size: file length in bytes * @sb_flag: super block flags * @page_index: offset within mapping, can used a page identifier and position identifier in the page frame * @size: write bytes * * Fires when do a write operation on nfs, * often after prepare_write * * Update and possibly write a cached page of an NFS file. */ probe nfs.aop.write_end = __nfs.aop.write_end !, __nfs.aop.commit_write { } probe nfs.aop.write_end.return = __nfs.aop.write_end.return !, __nfs.aop.commit_write.return { } probe __nfs.aop.write_begin = kernel.function ("nfs_write_begin") !, module("nfs").function("nfs_write_begin") { # Since __nfs.aop.write_begin and __nfs.aop.prepare_write # share a "parent" probe (nfs.aop.write_begin), they need to # have the same convenience variables. So, define a few fake # ones here. The optimizer will remove any that aren't # actually used. __page = -1 offset = $pos to = $pos + $len page_index = -1 size = $len dev = __file_dev($file) ino = __file_ino($file) s_id = __file_id($file) devname = kernel_string(s_id) pos = $pos count = $len name = "nfs.aop.write_begin" argstr = sprintf("%d", ino) units = "bytes" } probe __nfs.aop.write_begin.return = kernel.function ("nfs_write_begin").return !, module("nfs").function ("nfs_write_begin").return { name = "nfs.aop.write_begin.return" retstr = sprintf("%d", $return) } probe __nfs.aop.write_end = kernel.function ("nfs_write_end") !, module("nfs").function("nfs_write_end") { # Since __nfs.aop.write_end and __nfs.aop.commit_write # share a "parent" probe (nfs.aop.write_end), they need to # have the same convenience variables. So, define a few fake # ones here. The optimizer will remove any that aren't # actually used. __page = -1 offset = $pos to = $pos + $len i_flag = 0 i_size = 0 sb_flag = 0 page_index = -1 size = $len dev = __file_dev($file) ino = __file_ino($file) s_id = __file_id($file) devname = kernel_string(s_id) pos = $pos count = $len name = "nfs.aop.write_end" argstr = sprintf("%d", ino) units = "bytes" } probe __nfs.aop.write_end.return = kernel.function ("nfs_write_end").return !, module("nfs").function("nfs_write_end").return { name = "nfs.aop.write_end.return" retstr = sprintf("%d", $return) } probe __nfs.aop.prepare_write = kernel.function ("nfs_prepare_write") !, module("nfs").function ("nfs_prepare_write") { # Since __nfs.aop.write_begin and __nfs.aop.prepare_write # share a "parent" probe (nfs.aop.write_begin), they need to # have the same convenience variables. So, define a few fake # ones here. The optimizer will remove any that aren't # actually used. s_id = -1 pos = $offset count = $to - $offset __page = $page dev = __page_dev(__page) devname = __find_bdevname(dev, __page_bdev(__page)) ino = __page_ino(__page) offset = $offset to = $to page_index = $page->index name = "nfs.aop.prepare_write" argstr = sprintf("%d", page_index) size = $to - $offset units = "bytes" } probe __nfs.aop.prepare_write.return = kernel.function ("nfs_prepare_write").return !, module("nfs").function ("nfs_prepare_write").return { name = "nfs.aop.prepare_write.return" retstr = sprintf("%d", $return) } probe __nfs.aop.commit_write = kernel.function ("nfs_commit_write") !, module("nfs").function ("nfs_commit_write") { # Since __nfs.aop.write_end and __nfs.aop.commit_write # share a "parent" probe (nfs.aop.write_end), they need to # have the same convenience variables. So, define a few fake # ones here. The optimizer will remove any that aren't # actually used. s_id = -1 pos = $offset count = $to - $offset __page = $page dev = __page_dev(__page) devname = __find_bdevname(dev, __page_bdev(__page)) ino = __page_ino(__page) offset = $offset to = $to i_flag = __p2i_flag($page) i_size = __p2i_size($page) sb_flag = __p2sb_flag($page) page_index = $page->index name = "nfs.aop.commit_write" argstr = sprintf("%d, %d", offset, to) size = $to - $offset units = "bytes" } probe __nfs.aop.commit_write.return = kernel.function ("nfs_commit_write").return !, module("nfs").function ("nfs_commit_write").return { name = "nfs.aop.commit_write.return" retstr = sprintf("%d", $return) } /** * probe nfs.aop.release_page - NFS client releasing page * @__page: the address of page * @dev: device identifier * @ino: inode number * @page_index: offset within mapping, can used a page identifier * and position identifier in the page frame * @size: release pages * * Fires when do a release operation on NFS. */ probe nfs.aop.release_page = kernel.function ("nfs_release_page") !, module("nfs").function ("nfs_release_page") ? { __page = $page dev = __page_dev(__page) ino = __page_ino(__page) // gfp = $gfp page_index = $page->index name = "nfs.aop.release_page" argstr = sprintf("%d", page_index) size = 1 units = "pages" } probe nfs.aop.release_page.return = kernel.function ("nfs_release_page").return !, module("nfs").function ("nfs_release_page").return ? { name = "nfs.aop.release_page.return" retstr = sprintf("%d", $return) } systemtap-2.3/tapset/linux/nfs_proc.stp000066400000000000000000001336651217430427200204270ustar00rootroot00000000000000// NFS procedure tapset // Copyright (C) 2006 IBM Corp. // Copyright (C) 2007-2013 Red Hat // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. %{ /* For AF_INET */ #include %} function AF_INET:long() { return %{ /* pure */ /* unprivileged */ AF_INET %} } function AF_INET6:long() { return %{ /* pure */ /* unprivileged */ AF_INET6 %} } function NFS_I:long(inode:long) { /* * Notice we're casting 0 here on purpose. We need the offset * of the 'vfs_inode' member of 'struct nfs_inode'. This is * the script language equivalent of: * offset = offsetof(struct nfs_inode, vfs_inode); */ offset = &@cast(0, "nfs_inode", "kernel:nfs")->vfs_inode return (inode - offset) } function NFS_FH:long(inode:long) { return &@cast(NFS_I(inode), "nfs_inode", "kernel:nfs")->fh } function NFS_SERVER:long(inode:long) { return @cast(inode, "inode")->i_sb->s_fs_info } function NFS_CLIENT:long(inode:long) { return @cast(NFS_SERVER(inode), "nfs_server", "kernel:nfs")->client } %( systemtap_v < "2.3" %? /* deprecated */ function stap_NFS_CLIENT:long(inode:long) { return NFS_CLIENT(inode) } %) function NFS_PROTO:long(inode:long) { nfsserver = NFS_SERVER(inode) return @choose_defined(@cast(nfsserver, "nfs_server", "kernel:nfs")->nfs_client->rpc_ops, @cast(nfsserver, "nfs_server", "kernel:nfs")->rpc_ops) } /* Get ip address from a rpc_clnt */ function get_ip_from_client:long(clnt:long) { cl_xprt = @cast(clnt, "rpc_clnt", "kernel:sunrpc")->cl_xprt addr = &@cast(cl_xprt, "rpc_xprt", "kernel:sunrpc")->addr /* In reality, 'cl_xprt->addr' is of 'sockaddr_storage' type * (since 2.6.19). But when used, you cast it to what is * inside that buffer. */ if (@cast(addr, "sockaddr_in")->sin_family != %{ /* pure */ /* unprivileged */ AF_INET %}) { /* Now consider ipv4 only */ return 0 } return @cast(addr, "sockaddr_in")->sin_addr->s_addr } /* Get protocol types from a rpc_clnt */ function get_prot_from_client:long(clnt:long) { cl_xprt = @cast(clnt, "rpc_clnt", "kernel:sunrpc")->cl_xprt return @cast(cl_xprt, "rpc_xprt", "kernel:sunrpc")->prot } /* Get ip address from a rpc_task */ function get_ip:long(task:long) { clnt = @cast(task, "rpc_task", "kernel:sunrpc")->tk_client return get_ip_from_client(clnt) } /* Get protocol types from a rpc_task */ function get_prot:long(task:long) { clnt = @cast(task, "rpc_task", "kernel:sunrpc")->tk_client return get_prot_from_client(clnt) } function __nfsv4_bitmask:long(dir:long, i:long) { %( CONFIG_NFS_V4 == "[ym]" %? return @cast(NFS_SERVER(dir), "nfs_server", "kernel:nfs")->attr_bitmask[i] %) return 0 } %( systemtap_v < "2.3" %? /* deprecated */ function __getfh_inode:long(dir:long) { return NFS_FH(dir) } %) probe nfs.proc.entries = nfs.proc.lookup, nfs.proc.read ?, nfs.proc.write ?, nfs.proc.commit ?, nfs.proc.read_setup, nfs.proc.write_setup, nfs.proc.commit_setup, nfs.proc.read_done, nfs.proc.write_done, nfs.proc.commit_done, nfs.proc.open, nfs.proc.create, nfs.proc.rename, nfs.proc.remove, nfs.proc.release { } probe nfs.proc.return = nfs.proc.lookup.return, nfs.proc.read.return ?, nfs.proc.write.return ?, nfs.proc.commit.return ?, nfs.proc.read_setup.return, nfs.proc.write_setup.return, nfs.proc.commit_setup.return, nfs.proc.read_done.return, nfs.proc.write_done.return, nfs.proc.commit_done.return, nfs.proc.open.return, nfs.proc.create.return, nfs.proc.rename.return, nfs.proc.remove.return, nfs.proc.release.return { } /** * probe nfs.proc.lookup - NFS client opens/searches a file on server * * @server_ip: IP address of server * @prot: transfer protocol * @version: NFS version * @filename: the name of file which client opens/searches on server * @name_len: the length of file name * @bitmask0: V4 bitmask representing the set of attributes supported * on this filesystem * @bitmask1: V4 bitmask representing the set of attributes supported * on this filesystem */ probe nfs.proc.lookup = nfs.proc2.lookup, nfs.proc3.lookup, nfs.proc4.lookup { } probe nfs.proc.lookup.return = nfs.proc2.lookup.return, nfs.proc3.lookup.return, nfs.proc4.lookup.return {} probe nfs.proc2.lookup = kernel.function("nfs_proc_lookup") !, module("nfs").function("nfs_proc_lookup") ?, module("nfsv2").function("nfs_proc_lookup") ? { client = NFS_CLIENT($dir) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 2 name_len = $name->len filename = kernel_string_n($name->name, name_len) bitmask0 = 0 bitmask1 = 0 name = "nfs.proc2.lookup" argstr = sprintf("%s", filename) } probe nfs.proc2.lookup.return = kernel.function("nfs_proc_lookup").return !, module("nfs").function("nfs_proc_lookup").return ?, module("nfsv2").function("nfs_proc_lookup").return ? { version = 2 name = "nfs.proc2.lookup.return" retstr = sprintf("%d", $return) } probe nfs.proc3.lookup = kernel.function("nfs3_proc_lookup") !, module("nfs").function("nfs3_proc_lookup") ?, module("nfsv3").function("nfs3_proc_lookup") ? { client = NFS_CLIENT($dir) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 3 name_len = $name->len filename = kernel_string_n($name->name, name_len) bitmask0 = 0 bitmask1 = 0 name = "nfs.proc3.lookup" argstr = sprintf("%s", filename) } probe nfs.proc3.lookup.return = kernel.function("nfs3_proc_lookup").return !, module("nfs").function("nfs3_proc_lookup").return ?, module("nfsv3").function("nfs3_proc_lookup").return ? { version = 3 name = "nfs.proc3.lookup.return" retstr = sprintf("%d", $return) } probe nfs.proc4.lookup = kernel.function("nfs4_proc_lookup") !, module("nfs").function("nfs4_proc_lookup") ?, module("nfsv4").function("nfs4_proc_lookup") ? { client = NFS_CLIENT($dir) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 4 name_len = $name->len filename = kernel_string_n($name->name, name_len) bitmask0 = __nfsv4_bitmask($dir, 0) bitmask1 = __nfsv4_bitmask($dir, 1) name = "nfs.proc4.lookup" argstr = sprintf("%s", filename) } probe nfs.proc4.lookup.return = kernel.function("nfs4_proc_lookup").return !, module("nfs").function("nfs4_proc_lookup").return ?, module("nfsv4").function("nfs4_proc_lookup").return ? { version = 4 name = "nfs.proc4.lookup.return" retstr = sprintf("%d", $return) } /** * probe nfs.proc.read - NFS client synchronously reads file from server * * @server_ip: IP address of server * @prot: transfer protocol * @version: NFS version * @flags: used to set task->tk_flags in rpc_init_task function * @size: * @count: read bytes in this execution * @offset: the file offset * * All the nfs.proc.read kernel functions were removed in kernel commit * 8e0969 in December 2006, so these probes do not exist on Linux * 2.6.21 and newer kernels. */ probe nfs.proc.read = nfs.proc2.read ?, nfs.proc3.read ?, nfs.proc4.read ? {} probe nfs.proc.read.return = nfs.proc2.read.return ?, nfs.proc3.read.return ?, nfs.proc4.read.return ? { } probe nfs.proc2.read = kernel.function("nfs_proc_read") !, module("nfs").function("nfs_proc_read") ?, module("nfsv2").function("nfs_proc_read") ? { server_ip = @_nfs_data_server_ip($rdata) prot = @_nfs_data_prot($rdata) version = 2 flags = $rdata->flags count = @_nfs_data_args_count($rdata) offset = $rdata->args->offset name = "nfs.proc2.read" argstr = sprintf("%d,%d", count, offset) size = count units = "bytes" } probe nfs.proc2.read.return = kernel.function("nfs_proc_read").return !, module("nfs").function("nfs_proc_read").return ?, module("nfsv2").function("nfs_proc_read").return ? { version = 2 name = "nfs.proc2.read.return" retstr = sprintf("%d", $return) } probe nfs.proc3.read = kernel.function("nfs3_proc_read") !, module("nfs").function("nfs3_proc_read") ?, module("nfsv3").function("nfs3_proc_read") ? { server_ip = @_nfs_data_server_ip($rdata) prot = @_nfs_data_prot($rdata) version = 3 flags = $rdata->flags count = @_nfs_data_args_count($rdata) offset = $rdata->args->offset name = "nfs.proc3.read" argstr = sprintf("%d,%d", count, offset) size = count units = "bytes" } probe nfs.proc3.read.return = kernel.function("nfs3_proc_read").return !, module("nfs").function("nfs3_proc_read").return ?, module("nfsv3").function("nfs3_proc_read").return ? { version = 3 name = "nfs.proc3.read.return" retstr = sprintf("%d", $return) } probe nfs.proc4.read = kernel.function("nfs4_proc_read") !, module("nfs").function("nfs4_proc_read") ?, module("nfsv3").function("nfs4_proc_read") ? { server_ip = @_nfs_data_server_ip($rdata) prot = @_nfs_data_prot($rdata) version = 4 flags = $rdata->flags count = @_nfs_data_args_count($rdata) offset = $rdata->args->offset name = "nfs.proc4.read" argstr = sprintf("%d,%d", count, offset) size = count units = "bytes" } probe nfs.proc4.read.return = kernel.function("nfs4_proc_read").return !, module("nfs").function("nfs4_proc_read").return ?, module("nfsv4").function("nfs4_proc_read").return ? { version = 4 name = "nfs.proc4.read.return" retstr = sprintf("%d", $return) } /** * probe nfs.proc.write - NFS client synchronously writes file to server * * @server_ip: IP address of server * @prot: transfer protocol * @version: NFS version * @flags: used to set task->tk_flags in rpc_init_task function * @count: * @size: read bytes in this execution * @offset: the file offset * @bitmask0: V4 bitmask representing the set of attributes supported * on this filesystem * @bitmask1: V4 bitmask representing the set of attributes supported * on this filesystem * * All the nfs.proc.write kernel functions were removed in kernel commit * 200baa in December 2006, so these probes do not exist on Linux * 2.6.21 and newer kernels. */ probe nfs.proc.write = nfs.proc2.write ?, nfs.proc3.write ?, nfs.proc4.write ? {} probe nfs.proc.write.return = nfs.proc2.write.return ?, nfs.proc3.write.return ?, nfs.proc4.write.return ? {} probe nfs.proc2.write = kernel.function("nfs_proc_write") !, module("nfs").function("nfs_proc_write") ?, module("nfsv2").function("nfs_proc_write") ? { server_ip = @_nfs_data_server_ip($wdata) prot = @_nfs_data_prot($wdata) version = 2 flags = $wdata->flags count = @_nfs_data_args_count($wdata) offset = $wdata->args->offset bitmask0 = 0 bitmask1 = 0 name = "nfs.proc2.write" argstr = sprintf("%d,%d", count, offset) size = count units = "bytes" } probe nfs.proc2.write.return = kernel.function("nfs_proc_write").return !, module("nfs").function("nfs_proc_write").return ?, module("nfsv2").function("nfs_proc_write").return ? { version = 2 name = "nfs.proc2.write.return" retstr = sprintf("%d", $return) if ($return >= 0) { size = $return units = "bytes" } } probe nfs.proc3.write = kernel.function("nfs3_proc_write") !, module("nfs").function("nfs3_proc_write") ?, module("nfsv3").function("nfs3_proc_write") ? { server_ip = @_nfs_data_server_ip($wdata) prot = @_nfs_data_prot($wdata) version = 3 flags = $wdata->flags count = @_nfs_data_args_count($wdata) offset = $wdata->args->offset bitmask0 = 0 bitmask1 = 0 name = "nfs.proc3.write" argstr = sprintf("%d,%d", count, offset) size = count units = "bytes" } probe nfs.proc3.write.return = kernel.function("nfs3_proc_write").return !, module("nfs").function("nfs3_proc_write").return ?, module("nfsv3").function("nfs3_proc_write").return ? { version = 3 name = "nfs.proc3.write.return" retstr = sprintf("%d", $return) if ($return >= 0) { size = $return units = "bytes" } } probe nfs.proc4.write = kernel.function("nfs4_proc_write") !, module("nfs").function("nfs4_proc_write") ?, module("nfsv4").function("nfs4_proc_write") ? { server_ip = @_nfs_data_server_ip($wdata) prot = @_nfs_data_prot($wdata) version = 4 flags = $wdata->flags count = @_nfs_data_args_count($wdata) offset = $wdata->args->offset bitmask0 = __nfsv4_bitmask($wdata->inode, 0) bitmask1 = __nfsv4_bitmask($wdata->inode, 1) name = "nfs.proc4.write" argstr = sprintf("%d,%d", count, offset) size = count units = "bytes" } probe nfs.proc4.write.return = kernel.function("nfs4_proc_write").return !, module("nfs").function("nfs4_proc_write").return ?, module("nfsv4").function("nfs4_proc_write").return ? { version = 4 name = "nfs.proc4.write.return" retstr = sprintf("%d", $return) if ($return >= 0) { size = $return units = "bytes" } } /** * probe nfs.proc.commit - NFS client committing data on server * * @server_ip: IP address of server * @prot: transfer protocol * @version: NFS version * @count: * @size: read bytes in this execution * @offset: the file offset * @bitmask0: V4 bitmask representing the set of attributes supported * on this filesystem * @bitmask1: V4 bitmask representing the set of attributes supported * on this filesystem * * All the nfs.proc.commit kernel functions were removed in kernel * commit 200baa in December 2006, so these probes do not exist on Linux * 2.6.21 and newer kernels. * * Fires when client writes the buffered data to disk. * The buffered data is asynchronously written by client earlier. * The commit function works in sync way. * This probe point does not exist in NFSv2. */ probe nfs.proc.commit = nfs.proc3.commit ?, nfs.proc4.commit ? {} probe nfs.proc.commit.return = nfs.proc3.commit.return ?, nfs.proc4.commit.return ? {} // XXX: on kernels > 2.6.18 (?), module("nfs") -> module("nfsd") and // function("nfsN...") becomes function("nfsdN..."). PR3833. probe nfs.proc3.commit = kernel.function ("nfs3_proc_commit") !, module("nfs").function("nfs3_proc_commit") ?, module("nfsv3").function("nfs3_proc_commit") ? { server_ip = @_nfs_data_server_ip($cdata) prot = @_nfs_data_prot($cdata) version = 3 count = @_nfs_data_args_count($cdata) offset = $cdata->args->offset bitmask0 = 0 bitmask1 = 0 name = "nfs.proc3.commit" argstr = sprintf("%d,%d", count, offset) size = count units = "bytes" } probe nfs.proc3.commit.return = kernel.function ("nfs3_proc_commit").return !, module("nfs").function("nfs3_proc_commit").return ?, module("nfsv3").function("nfs3_proc_commit").return ? { version = 3 name = "nfs.proc3.commit.return" retstr = sprintf("%d", $return) if ($return >= 0) { size = $return units = "bytes" } } probe nfs.proc4.commit = kernel.function ("nfs4_proc_commit") !, module("nfs").function("nfs4_proc_commit") ?, module("nfsv4").function("nfs4_proc_commit") ? { server_ip = @_nfs_data_server_ip($cdata) prot = @_nfs_data_prot($cdata) version = 4 count = @_nfs_data_args_count($cdata) offset = $cdata->args->offset bitmask0 = __nfsv4_bitmask($cdata->inode, 0) bitmask1 = __nfsv4_bitmask($cdata->inode, 1) name = "nfs.proc4.commit" argstr = sprintf("%d,%d", count, offset) size = count units = "bytes" } probe nfs.proc4.commit.return = kernel.function ("nfs4_proc_commit").return !, module("nfs").function("nfs4_proc_commit").return ?, module("nfsv4").function("nfs4_proc_commit").return ? { version = 4 name = "nfs.proc4.commit.return" retstr = sprintf("%d", $return) if ($return >= 0) { size = $return units = "bytes" } } /** * probe nfs.proc.read_setup - NFS client setting up a read RPC task * * @server_ip: IP address of server * @prot: transfer protocol * @version: NFS version * @count: read bytes in this execution * @size: read bytes in this execution * @offset: the file offset * * The read_setup function is used to setup a read RPC task. * It is not doing the actual read operation. */ probe nfs.proc.read_setup = nfs.proc2.read_setup, nfs.proc3.read_setup, nfs.proc4.read_setup {} probe nfs.proc.read_setup.return = nfs.proc2.read_setup.return, nfs.proc3.read_setup.return, nfs.proc4.read_setup.return {} probe nfs.proc2.read_setup = kernel.function("nfs_proc_read_setup") !, module("nfs").function("nfs_proc_read_setup") ?, module("nfsv2").function("nfs_proc_read_setup") ? { inode = @defined($data->header) ? $data->header->inode : $data->inode client = NFS_CLIENT(inode) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 2 count = @_nfs_data_args_count($data) offset = $data->args->offset name = "nfs.proc2.read_setup" argstr = sprintf("%d,%d", count, offset) size = count units = "bytes" } probe nfs.proc2.read_setup.return = kernel.function("nfs_proc_read_setup").return !, module("nfs").function("nfs_proc_read_setup").return ?, module("nfsv2").function("nfs_proc_read_setup").return ? { version = 2 name = "nfs.proc2.read_setup.return" retvalue = 0; } probe nfs.proc3.read_setup = kernel.function("nfs3_proc_read_setup") !, module("nfs").function("nfs3_proc_read_setup") ?, module("nfsv3").function("nfs3_proc_read_setup") ? { inode = @defined($data->header) ? $data->header->inode : $data->inode client = NFS_CLIENT(inode) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 3 fh = count = @_nfs_data_args_count($data) offset = $data->args->offset name = "nfs.proc3.read_setup" argstr = sprintf("%d,%d", count, offset) size = count units = "bytes" } probe nfs.proc3.read_setup.return = kernel.function("nfs3_proc_read_setup").return !, module("nfs").function("nfs3_proc_read_setup").return ?, module("nfsv3").function("nfs3_proc_read_setup").return ? { version = 3 name = "nfs.proc3.read_setup.return" retvalue = 0; } probe nfs.proc4.read_setup = kernel.function("nfs4_proc_read_setup") !, module("nfs").function("nfs4_proc_read_setup") ?, module("nfsv4").function("nfs4_proc_read_setup") ? { inode = @defined($data->header) ? $data->header->inode : $data->inode client = NFS_CLIENT(inode) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 4 count = @_nfs_data_args_count($data) offset = $data->args->offset //timestamp = $jiffies name = "nfs.proc4.read_setup" argstr = sprintf("%d,%d", count, offset) size = count units = "bytes" } probe nfs.proc4.read_setup.return = kernel.function("nfs4_proc_read_setup").return !, module("nfs").function("nfs4_proc_read_setup").return ?, module("nfsv4").function("nfs4_proc_read_setup").return ? { version = 4 name = "nfs.proc4.read_setup.return" retvalue = 0; } /** * probe nfs.proc.read_done - NFS client response to a read RPC task * * @server_ip: IP address of server * @prot: transfer protocol * @version: NFS version * @status: result of last operation * @count: number of bytes read * @timestamp : V4 timestamp, which is used for lease renewal * * Fires when a reply to a read RPC task is received or some read error occurs * (timeout or socket shutdown). */ probe nfs.proc.read_done = nfs.proc2.read_done, nfs.proc3.read_done, nfs.proc4.read_done {} probe nfs.proc.read_done.return = nfs.proc2.read_done.return, nfs.proc3.read_done.return, nfs.proc4.read_done.return {} probe nfs.proc2.read_done = kernel.function("nfs_read_done") !, module("nfs").function("nfs_read_done") ?, module("nfsv2").function("nfs_read_done") ? { if (@defined($data)) { # kernels >= 2.6.10 server_ip = @_nfs_data_server_ip($data) prot = @_nfs_data_prot($data) count = @_nfs_data_res_count($data) } else { server_ip = @_nfs_data_server_ip($task->tk_calldata) prot = @_nfs_data_prot($task->tk_calldata) count = @_nfs_data_res_count($task->tk_calldata) } timestamp = 0 version = 2 status = $task->tk_status name = "nfs.proc2.read_done" argstr = sprintf("%d", status) } probe nfs.proc2.read_done.return = kernel.function("nfs_read_done").return !, module("nfs").function("nfs_read_done").return ?, module("nfsv2").function("nfs_read_done").return ? { version = 2 name = "nfs.proc2.read_done.return" retstr = (@defined($return) ? sprintf("%d", $return) : "N/A") } probe nfs.proc3.read_done = kernel.function("nfs3_read_done") !, module("nfs").function("nfs3_read_done") ?, module("nfsv3").function("nfs3_read_done") ? { if (@defined($data)) { # kernels >= 2.6.10 server_ip = @_nfs_data_server_ip($data) prot = @_nfs_data_prot($data) count = @_nfs_data_res_count($data) } else { server_ip = @_nfs_data_server_ip($task->tk_calldata) prot = @_nfs_data_prot($task->tk_calldata) count = @_nfs_data_res_count($task->tk_calldata) } timestamp = 0 version = 3 status = $task->tk_status name = "nfs.proc3.read_done" argstr = sprintf("%d", status) } probe nfs.proc3.read_done.return = kernel.function("nfs3_read_done").return !, module("nfs").function("nfs3_read_done").return ?, module("nfsv3").function("nfs3_read_done").return ? { version = 3 name = "nfs.proc3.read_done.return" retstr = (@defined($return) ? sprintf("%d", $return) : "N/A") } probe nfs.proc4.read_done = kernel.function("nfs4_read_done") !, module("nfs").function("nfs4_read_done") ?, module("nfsv4").function("nfs4_read_done") ? { if (@defined($data)) { # kernels >= 2.6.10 server_ip = @_nfs_data_server_ip($data) prot = @_nfs_data_prot($data) count = @_nfs_data_res_count($data) timestamp = @_nfs_data_timestamp($data) } else { server_ip = @_nfs_data_server_ip($task->tk_calldata) prot = @_nfs_data_prot($task->tk_calldata) count = @_nfs_data_res_count($task->tk_calldata) timestamp = @_nfs_data_timestamp($task->tk_calldata) } version = 4 status = $task->tk_status name = "nfs.proc4.read_done" argstr = sprintf("%d", status) } probe nfs.proc4.read_done.return = kernel.function("nfs4_read_done").return !, module("nfs").function("nfs4_read_done").return ?, module("nfsv4").function("nfs4_read_done").return ? { version = 4 name = "nfs.proc4.read_done.return" retstr = (@defined($return) ? sprintf("%d", $return) : "N/A") } /** * probe nfs.proc.write_setup - NFS client setting up a write RPC task * * @server_ip: IP address of server * @prot: transfer protocol * @version: NFS version * @size: bytes written in this execution * @count: bytes written in this execution * @offset: the file offset * @how: used to set args.stable. The stable value could be: * NFS_UNSTABLE,NFS_DATA_SYNC,NFS_FILE_SYNC * (in nfs.proc3.write_setup and nfs.proc4.write_setup) * @bitmask0: V4 bitmask representing the set of attributes supported * on this filesystem * @bitmask1: V4 bitmask representing the set of attributes supported * on this filesystem * * The write_setup function is used to setup a write RPC task. * It is not doing the actual write operation. */ probe nfs.proc.write_setup = nfs.proc2.write_setup, nfs.proc3.write_setup, nfs.proc4.write_setup {} probe nfs.proc.write_setup.return = nfs.proc2.write_setup.return, nfs.proc3.write_setup.return, nfs.proc4.write_setup.return {} probe nfs.proc2.write_setup = kernel.function("nfs_proc_write_setup") !, module("nfs").function("nfs_proc_write_setup") ?, module("nfsv2").function("nfs_proc_write_setup") ? { inode = @defined($data->header) ? $data->header->inode : $data->inode client = NFS_CLIENT(inode) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 2 count = @_nfs_data_args_count($data) offset = $data->args->offset how = @choose_defined($how, $data->args->stable) bitmask0 = 0 bitmask1 = 0 name = "nfs.proc2.write_setup" argstr = sprintf("%d,%d", count, offset) size = count units = "bytes" } probe nfs.proc2.write_setup.return = kernel.function("nfs_proc_write_setup").return !, module("nfs").function("nfs_proc_write_setup").return ?, module("nfsv2").function("nfs_proc_write_setup").return ? { version = 2 name = "nfs.proc2.write_setup.return" retvalue = 0 } probe nfs.proc3.write_setup = kernel.function("nfs3_proc_write_setup") !, module("nfs").function("nfs3_proc_write_setup") ?, module("nfsv3").function("nfs3_proc_write_setup") ? { inode = @defined($data->header) ? $data->header->inode : $data->inode client = NFS_CLIENT(inode) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 3 count = @_nfs_data_args_count($data) offset = $data->args->offset how = @choose_defined($how, $data->args->stable) bitmask0 = 0 bitmask1 = 0 name = "nfs.proc3.write_setup" argstr = sprintf("%d,%d,%d", count, offset, how) size = count units = "bytes" } probe nfs.proc3.write_setup.return = kernel.function("nfs3_proc_write_setup").return !, module("nfs").function("nfs3_proc_write_setup").return ?, module("nfsv3").function("nfs3_proc_write_setup").return ? { version = 3 name = "nfs.proc3.write_setup.return" retvalue = 0 } probe nfs.proc4.write_setup = kernel.function("nfs4_proc_write_setup") !, module("nfs").function("nfs4_proc_write_setup") ?, module("nfsv4").function("nfs4_proc_write_setup") ? { inode = @defined($data->header) ? $data->header->inode : $data->inode client = NFS_CLIENT(inode) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 4 count = @_nfs_data_args_count($data) offset = $data->args->offset how = @choose_defined($how, $data->args->stable) bitmask0 = __nfsv4_bitmask(inode, 0) bitmask1 = __nfsv4_bitmask(inode, 1) //timestamp = $jiffies name = "nfs.proc4.write_setup" argstr = sprintf("%d,%d,%d", count, offset, how) size = count units = "bytes" } probe nfs.proc4.write_setup.return = kernel.function("nfs4_proc_write_setup").return !, module("nfs").function("nfs4_proc_write_setup").return ?, module("nfsv4").function("nfs4_proc_write_setup").return ? { version = 4 name = "nfs.proc4.write_setup.return" retvalue = 0 } /** * probe nfs.proc.write_done - NFS client response to a write RPC task * * @server_ip: IP address of server * @prot: transfer protocol * @version: NFS version * @status: result of last operation * @valid: fattr->valid, indicates which fields are valid * @count: number of bytes written * @timestamp: V4 timestamp, which is used for lease renewal * * Fires when a reply to a write RPC task is received or some write error occurs * (timeout or socket shutdown). */ probe nfs.proc.write_done = nfs.proc2.write_done, nfs.proc3.write_done, nfs.proc4.write_done {} probe nfs.proc.write_done.return = nfs.proc2.write_done.return, nfs.proc3.write_done.return, nfs.proc4.write_done.return {} probe nfs.proc2.write_done = kernel.function("nfs_write_done") !, module("nfs").function("nfs_write_done") ?, module("nfsv2").function("nfs_write_done") ? { if (@defined($data)) { # kernels >= 2.6.10 server_ip = @_nfs_data_server_ip($data) prot = @_nfs_data_prot($data) count = @_nfs_data_res_count($data) valid = @_nfs_data_valid($data) } else { server_ip = @_nfs_data_server_ip($task->tk_calldata) prot = @_nfs_data_prot($task->tk_calldata) count = @_nfs_data_res_count($task->tk_calldata) valid = @_nfs_data_valid($task->tk_calldata) } timestamp = 0 version = 2 status = $task->tk_status name = "nfs.proc2.write_done" argstr = sprintf("%d", status) } probe nfs.proc2.write_done.return = kernel.function("nfs_write_done").return !, module("nfs").function("nfs_write_done").return ?, module("nfsv2").function("nfs_write_done").return ? { version = 2 name = "nfs.proc2.write_done.return" retstr = (@defined($return) ? sprintf("%d", $return) : "N/A") } probe nfs.proc3.write_done = kernel.function("nfs3_write_done") !, module("nfs").function("nfs3_write_done") ?, module("nfsv3").function("nfs3_write_done") ? { if (@defined($data)) { # kernels >= 2.6.10 server_ip = @_nfs_data_server_ip($data) prot = @_nfs_data_prot($data) count = @_nfs_data_res_count($data) valid = @_nfs_data_valid($data) } else { server_ip = @_nfs_data_server_ip($task->tk_calldata) prot = @_nfs_data_prot($task->tk_calldata) count = @_nfs_data_res_count($task->tk_calldata) valid = @_nfs_data_valid($task->tk_calldata) } timestamp = 0 version = 3 status = $task->tk_status name = "nfs.proc3.write_done" argstr = sprintf("%d", status) } probe nfs.proc3.write_done.return = kernel.function("nfs3_write_done").return !, module("nfs").function("nfs3_write_done").return ?, module("nfsv3").function("nfs3_write_done").return ? { version = 3 name = "nfs.proc3.write_done.return" retstr = (@defined($return) ? sprintf("%d", $return) : "N/A") } probe nfs.proc4.write_done = kernel.function("nfs4_write_done") !, module("nfs").function("nfs4_write_done") ?, module("nfsv4").function("nfs4_write_done") ? { if (@defined($data)) { # kernels >= 2.6.10 server_ip = @_nfs_data_server_ip($data) prot = @_nfs_data_prot($data) count = @_nfs_data_res_count($data) valid = @_nfs_data_valid($data) timestamp = @_nfs_data_timestamp($data) } else { server_ip = @_nfs_data_server_ip($task->tk_calldata) prot = @_nfs_data_prot($task->tk_calldata) count = @_nfs_data_res_count($task->tk_calldata) valid = @_nfs_data_valid($task->tk_calldata) timestamp = @_nfs_data_timestamp($task->tk_calldata) } version = 4 status = $task->tk_status name = "nfs.proc4.write_done" argstr = sprintf("%d", status) } probe nfs.proc4.write_done.return = kernel.function("nfs4_write_done").return !, module("nfs").function("nfs4_write_done").return ?, module("nfsv4").function("nfs4_write_done").return ? { version = 4 name = "nfs.proc4.write_done.return" retstr = (@defined($return) ? sprintf("%d", $return) : "N/A") } /** * probe nfs.proc.commit_setup - NFS client setting up a commit RPC task * * @server_ip: IP address of server * @prot: transfer protocol * @version: NFS version * @size: bytes in this commit * @count: bytes in this commit * @offset: the file offset * @bitmask0: V4 bitmask representing the set of attributes supported * on this filesystem * @bitmask1: V4 bitmask representing the set of attributes supported * on this filesystem * * The commit_setup function is used to setup a commit RPC task. * Is is not doing the actual commit operation. * It is does not exist in NFSv2. */ probe nfs.proc.commit_setup = nfs.proc3.commit_setup, nfs.proc4.commit_setup {} probe nfs.proc.commit_setup.return = nfs.proc3.commit_setup.return, nfs.proc4.commit_setup.return {} probe nfs.proc3.commit_setup = kernel.function("nfs3_proc_commit_setup") !, module("nfs").function("nfs3_proc_commit_setup") ?, module("nfsv3").function("nfs3_proc_commit_setup") ? { inode = @defined($data->header) ? $data->header->inode : $data->inode client = NFS_CLIENT(inode) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 3 count = @_nfs_data_args_count($data) offset = $data->args->offset bitmask0 = 0 bitmask1 = 0 name = "nfs.proc3.commit_setup" argstr = sprintf("%d,%d", count, offset) size = count units = "bytes" } probe nfs.proc3.commit_setup.return = kernel.function("nfs3_proc_commit_setup") .return !, module("nfs").function("nfs3_proc_commit_setup").return ?, module("nfsv3").function("nfs3_proc_commit_setup").return ? { version = 3 name = "nfs.proc3.commit_setup.return" retvalue = 0 } probe nfs.proc4.commit_setup = kernel.function("nfs4_proc_commit_setup") !, module("nfs").function("nfs4_proc_commit_setup") ?, module("nfsv4").function("nfs4_proc_commit_setup") ? { inode = @defined($data->header) ? $data->header->inode : $data->inode client = NFS_CLIENT(inode) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 4 count = @_nfs_data_args_count($data) offset = $data->args->offset bitmask0 = __nfsv4_bitmask(inode, 0) bitmask1 = __nfsv4_bitmask(inode, 1) //timestamp = $jiffies name = "nfs.proc4.commit_setup" argstr = sprintf("%d,%d", count, offset) size = count units = "bytes" } probe nfs.proc4.commit_setup.return = kernel.function("nfs4_proc_commit_setup") .return !, module("nfs").function("nfs4_proc_commit_setup").return ?, module("nfsv4").function("nfs4_proc_commit_setup").return ? { version = 4 name = "nfs.proc4.commit_setup.return" retvalue = 0 } /** * probe nfs.proc.commit_done - NFS client response to a commit RPC task * * @server_ip: IP address of server * @prot: transfer protocol * @version: NFS version * @status: result of last operation * @valid: fattr->valid, indicates which fields are valid * @count: number of bytes committed * @timestamp: V4 timestamp, which is used for lease renewal * * Fires when a reply to a commit RPC task is received * or some commit operation error occur (timeout or socket shutdown). */ probe nfs.proc.commit_done = nfs.proc3.commit_done, nfs.proc4.commit_done {} probe nfs.proc.commit_done.return = nfs.proc3.commit_done.return, nfs.proc4.commit_done.return {} probe nfs.proc3.commit_done = kernel.function("nfs3_commit_done") !, module("nfs").function("nfs3_commit_done") ?, module("nfsv3").function("nfs3_commit_done") ? { if (@defined($data)) { # kernels >= 2.6.10 server_ip = @_nfs_data_server_ip($data) prot = @_nfs_data_prot($data) count = @_nfs_data_res_count($data) valid = @_nfs_data_valid($data) } else { server_ip = @_nfs_data_server_ip($task->tk_calldata) prot = @_nfs_data_prot($task->tk_calldata) count = @_nfs_data_res_count($task->tk_calldata) valid = @_nfs_data_valid($task->tk_calldata) } timestamp = 0 version = 3 status = $task->tk_status name = "nfs.proc3.commit_done" argstr = sprintf("%d", status) } probe nfs.proc3.commit_done.return = kernel.function("nfs3_commit_done").return !, module("nfs").function("nfs3_commit_done").return ?, module("nfsv3").function("nfs3_commit_done").return ? { version = 3 name = "nfs.proc3.commit_done.return" retstr = (@defined($return) ? sprintf("%d", $return) : "N/A") } probe nfs.proc4.commit_done = kernel.function("nfs4_commit_done") !, module("nfs").function("nfs4_commit_done") ?, module("nfsv4").function("nfs4_commit_done") ? { if (@defined($data)) { # kernels >= 2.6.10 server_ip = @_nfs_data_server_ip($data) prot = @_nfs_data_prot($data) count = @_nfs_data_res_count($data) valid = @_nfs_data_valid($data) timestamp = @_nfs_data_timestamp($data) } else { server_ip = @_nfs_data_server_ip($task->tk_calldata) prot = @_nfs_data_prot($task->tk_calldata) count = @_nfs_data_res_count($task->tk_calldata) valid = @_nfs_data_valid($task->tk_calldata) timestamp = @_nfs_data_timestamp($task->tk_calldata) } version = 4 status = $task->tk_status name = "nfs.proc4.commit_done" argstr = sprintf("%d", status) } probe nfs.proc4.commit_done.return = kernel.function("nfs4_commit_done").return !, module("nfs").function("nfs4_commit_done").return ?, module("nfsv4").function("nfs4_commit_done").return ? { version = 4 name = "nfs.proc4.commit_done.return" retstr = (@defined($return) ? sprintf("%d", $return) : "N/A") } /** * probe nfs.proc.open - NFS client allocates file read/write context information * * @server_ip: IP address of server * @prot: transfer protocol * @version: NFS version (the function is used for all NFS version) * @filename: file name * @flag: file flag * @mode: file mode * * Allocate file read/write context information */ probe nfs.proc.open = kernel.function("nfs_open") !, module("nfs").function("nfs_open") ? { client = NFS_CLIENT($inode) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = __nfs_version($inode) filename = __file_filename($filp) flag = $filp->f_flags mode = $filp->f_mode name = "nfs.proc.open" argstr = sprintf("%s,%d,%d", filename, flag, mode) } probe nfs.proc.open.return = kernel.function("nfs_open").return !, module("nfs").function("nfs_open").return ? { name = "nfs.proc.open.return" retstr = sprintf("%d", $return) } /** * probe nfs.proc.release - NFS client releases file read/write context information * * @server_ip: IP address of server * @prot: transfer protocol * @version: NFS version (the function is used for all NFS version) * @filename: file name * @flag: file flag * @mode: file mode * * Release file read/write context information */ probe nfs.proc.release = kernel.function("nfs_release") !, module("nfs").function("nfs_release") ? { client = NFS_CLIENT($inode) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = __nfs_version($inode) filename = __file_filename($filp) flag = $filp->f_flags mode = $filp->f_mode name = "nfs.proc.release" argstr = sprintf("%s,%d,%d", filename, flag, mode) } probe nfs.proc.release.return = kernel.function("nfs_release").return !, module("nfs").function("nfs_release").return ? { name = "nfs.proc.release.return" retstr = sprintf("%d", $return) } /** * probe nfs.proc.handle_exception - NFS client handling an NFSv4 exception * * @errorcode: indicates the type of error * * This is the error handling routine for processes for NFSv4. */ probe nfs.proc.handle_exception = nfs.proc4.handle_exception {} probe nfs.proc.handle_exception.return = nfs.proc4.handle_exception.return {} probe nfs.proc4.handle_exception = kernel.function("nfs4_handle_exception") !, module("nfs").function("nfs4_handle_exception") ?, module("nfsv4").function("nfs4_handle_exception") ? { version = 4 errorcode = $errorcode name = "nfs.proc4.handle_exception" argstr = sprintf("%d", errorcode) } probe nfs.proc4.handle_exception.return = kernel.function("nfs4_handle_exception").return !, module("nfs").function("nfs4_handle_exception").return ?, module("nfsv4").function("nfs4_handle_exception").return ? { name = "nfs.proc4.handle_exception.return" retstr = sprintf("%d", $return) } /** * probe nfs.proc.create - NFS client creating file on server * * @server_ip: IP address of server * @prot: transfer protocol * @version: NFS version (the function is used for all NFS version) * @fh: file handler of parent dir * @filename: file name * @filelen: length of file name * @flag: indicates create mode (only for NFSv3 and NFSv4) */ probe nfs.proc.create = nfs.proc2.create, nfs.proc3.create, nfs.proc4.create {} probe nfs.proc.create.return = nfs.proc2.create.return, nfs.proc3.create.return, nfs.proc4.create.return {} probe nfs.proc2.create = kernel.function("nfs_proc_create") !, module("nfs").function("nfs_proc_create") ?, module("nfsv2").function("nfs_proc_create") ? { client = NFS_CLIENT($dir) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 2 fh = NFS_FH($dir) filelen = $dentry->d_name->len filename = kernel_string_n($dentry->d_name->name, filelen) mode = $sattr->ia_mode name = "nfs.proc2.create" argstr = sprintf("%s", filename) } probe nfs.proc2.create.return = kernel.function("nfs_proc_create").return !, module("nfs").function("nfs_proc_create").return ?, module("nfsv2").function("nfs_proc_create").return ? { name = "nfs.proc2.create.return" version = 2 retstr = sprintf("%d", $return) } probe nfs.proc3.create = kernel.function("nfs3_proc_create") !, module("nfs").function("nfs3_proc_create") ?, module("nfsv3").function("nfs3_proc_create") ? { client = NFS_CLIENT($dir) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 3 fh = NFS_FH($dir) filelen = $dentry->d_name->len filename = kernel_string_n($dentry->d_name->name, filelen) flag = $flags mode = $sattr->ia_mode name = "nfs.proc3.create" argstr = sprintf("%s", filename) } probe nfs.proc3.create.return = kernel.function("nfs3_proc_create").return !, module("nfs").function("nfs3_proc_create").return ?, module("nfsv3").function("nfs3_proc_create").return ? { name = "nfs.proc3.create.return" version = 3 retstr = sprintf("%d", $return) } probe nfs.proc4.create = kernel.function("nfs4_proc_create") !, module("nfs").function("nfs4_proc_create") ?, module("nfsv4").function("nfs4_proc_create") ? { client = NFS_CLIENT($dir) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 4 fh = NFS_FH($dir) filelen = $dentry->d_name->len filename = kernel_string_n($dentry->d_name->name, filelen) flag = $flags mode = $sattr->ia_mode name = "nfs.proc4.create" argstr = sprintf("%s", filename) } probe nfs.proc4.create.return = kernel.function("nfs4_proc_create").return !, module("nfs").function("nfs4_proc_create").return ?, module("nfsv4").function("nfs4_proc_create").return ? { name = "nfs.proc4.create.return" version = 4 retstr = sprintf("%d", $return) } /** * probe nfs.proc.remove - NFS client removes a file on server * * @server_ip: IP address of server * @prot: transfer protocol * @version: NFS version (the function is used for all NFS version) * @fh: file handler of parent dir * @filename: file name * @filelen: length of file name */ probe nfs.proc.remove = nfs.proc2.remove, nfs.proc3.remove, nfs.proc4.remove {} probe nfs.proc.remove.return = nfs.proc2.remove.return, nfs.proc3.remove.return, nfs.proc4.remove.return {} probe nfs.proc2.remove = kernel.function("nfs_proc_remove") !, module("nfs").function("nfs_proc_remove") ?, module("nfsv2").function("nfs_proc_remove") ? { client = NFS_CLIENT($dir) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 2 fh = NFS_FH($dir) filelen = $name->len filename = kernel_string_n($name->name, filelen) name = "nfs.proc2.remove" argstr = sprintf("%s", filename) } probe nfs.proc2.remove.return = kernel.function("nfs_proc_remove").return !, module("nfs").function("nfs_proc_remove").return ?, module("nfsv2").function("nfs_proc_remove").return ? { name = "nfs.proc2.remove.return" version = 2 retstr = sprintf("%d", $return) } probe nfs.proc3.remove = kernel.function("nfs3_proc_remove") !, module("nfs").function("nfs3_proc_remove") ?, module("nfsv3").function("nfs3_proc_remove") ? { client = NFS_CLIENT($dir) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 3 fh = NFS_FH($dir) filelen = $name->len filename = kernel_string_n($name->name, filelen) name = "nfs.proc3.remove" argstr = sprintf("%s", filename) } probe nfs.proc3.remove.return = kernel.function("nfs3_proc_remove").return !, module("nfs").function("nfs3_proc_remove").return ?, module("nfsv3").function("nfs3_proc_remove").return ? { name = "nfs.proc3.remove.return" version = 3 retstr = sprintf("%d", $return) } probe nfs.proc4.remove = kernel.function("nfs4_proc_remove") !, module("nfs").function("nfs4_proc_remove") ?, module("nfsv4").function("nfs4_proc_remove") ? { client = NFS_CLIENT($dir) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 4 fh = NFS_FH($dir) filelen = $name->len filename = kernel_string_n($name->name, filelen) name = "nfs.proc4.remove" argstr = sprintf("%s", filename) } probe nfs.proc4.remove.return = kernel.function("nfs4_proc_remove").return !, module("nfs").function("nfs4_proc_remove").return ?, module("nfsv4").function("nfs4_proc_remove").return ? { name = "nfs.proc4.remove.return" version = 4 retstr = sprintf("%d", $return) } /** * probe nfs.proc.rename - NFS client renames a file on server * * @server_ip: IP address of server * @prot: transfer protocol * @version: NFS version (the function is used for all NFS version) * @old_fh: file handler of old parent dir * @new_fh: file handler of new parent dir * @old_name: old file name * @old_filelen: length of old file name * @new_name: new file name * @new_filelen: length of new file name */ probe nfs.proc.rename = nfs.proc2.rename, nfs.proc3.rename, nfs.proc4.rename {} probe nfs.proc.rename.return = nfs.proc2.rename.return, nfs.proc3.rename.return, nfs.proc4.rename.return {} probe nfs.proc2.rename = kernel.function("nfs_proc_rename") !, module("nfs").function("nfs_proc_rename") ?, module("nfsv2").function("nfs_proc_rename") ? { client = NFS_CLIENT($old_dir) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 2 old_fh = NFS_FH($old_dir) old_filelen = $old_name->len old_name = kernel_string_n($old_name->name, old_filelen) new_fh = NFS_FH($new_dir) new_filelen = $new_name->len new_name = kernel_string_n($new_name->name, new_filelen) name = "nfs.proc2.rename" argstr = sprintf("%s,%s", old_name, new_name) } probe nfs.proc2.rename.return = kernel.function("nfs_proc_rename").return !, module("nfs").function("nfs_proc_rename").return ?, module("nfsv2").function("nfs_proc_rename").return ? { name = "nfs.proc2.rename.return" version = 2 retstr = sprintf("%d", $return) } probe nfs.proc3.rename = kernel.function("nfs3_proc_rename") !, module("nfs").function("nfs3_proc_rename") ?, module("nfsv3").function("nfs3_proc_rename") ? { client = NFS_CLIENT($old_dir) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 3 old_fh = NFS_FH($old_dir) old_filelen = $old_name->len old_name = kernel_string_n($old_name->name, old_filelen) new_fh = NFS_FH($new_dir) new_filelen = $new_name->len new_name = kernel_string_n($new_name->name, new_filelen) name = "nfs.proc3.rename" argstr = sprintf("%s,%s", old_name, new_name) } probe nfs.proc3.rename.return = kernel.function("nfs3_proc_rename").return !, module("nfs").function("nfs3_proc_rename").return ?, module("nfsv3").function("nfs3_proc_rename").return ? { name = "nfs.proc3.rename.return" version = 3 retstr = sprintf("%d", $return) } probe nfs.proc4.rename = kernel.function("nfs4_proc_rename") !, module("nfs").function("nfs4_proc_rename") ?, module("nfsv4").function("nfs4_proc_rename") ? { client = NFS_CLIENT($old_dir) server_ip = get_ip_from_client(client) prot = get_prot_from_client(client) version = 4 old_fh = NFS_FH($old_dir) old_filelen = $old_name->len old_name = kernel_string_n($old_name->name, old_filelen) new_fh = NFS_FH($new_dir) new_filelen = $new_name->len new_name = kernel_string_n($new_name->name, new_filelen) name = "nfs.proc4.rename" argstr = sprintf("%s,%s", old_name, new_name) } probe nfs.proc4.rename.return = kernel.function("nfs4_proc_rename").return !, module("nfs").function("nfs4_proc_rename").return ?, module("nfsv4").function("nfs4_proc_rename").return ? { name = "nfs.proc4.rename.return" version = 4 retstr = sprintf("%d", $return) } systemtap-2.3/tapset/linux/nfs_proc.stpm000066400000000000000000000022751217430427200205740ustar00rootroot00000000000000// macros for nfs_proc.stp (the NFS procedure tapset) // Copyright (C) 2013 Red Hat // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // Macros to return data from a 'struct nfs_read_data', 'struct // nfs_write_data', or 'struct nfs_commit_data'. Even though the // structures are laid out differently, since the names of the fields // are the same, one set of macros can work for all types. @define _nfs_data_server_ip(nfs_data) %( ( get_ip(&@nfs_data->task) ) %) @define _nfs_data_prot(nfs_data) %( ( get_prot(&@nfs_data->task) ) %) @define _nfs_data_args_count(nfs_data) %( ( @nfs_data->args->count ) %) // The 'nfs_commitres' structure has no 'count' field. @define _nfs_data_res_count(nfs_data) %( ( @choose_defined(@nfs_data->res->count, 0) ) %) @define _nfs_data_valid(nfs_data) %( ( @nfs_data->res->fattr->valid ) %) // The 'nfs_commit_data' structure has no 'timestamp' field. @define _nfs_data_timestamp(nfs_data) %( ( %( CONFIG_NFS_V4 == "[ym]" %? @choose_defined(@nfs_data->timestamp, 0) %: 0 %) ) %) systemtap-2.3/tapset/linux/nfsd.stp000066400000000000000000001140601217430427200175340ustar00rootroot00000000000000// nfs tapset // Copyright (C) 2006-2007 IBM Corp. // Copyright (C) 2007 Intel Corporation. // Copyright (C) 2007 Bull S.A.S // Copyright (C) 2010,2011 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. %{ #include #include #include #include #include %} /* *1 : nfsd.proc2.lookup *2 : nfsd.proc3.lookup *3 : nfsd.proc2.read *4 : nfsd.proc3.read *5 : nfsd.proc2.write *6 : nfsd.proc3.write *7 : nfsd.proc3.commit *8 : nfsd.proc2.create *9 : nfsd.proc3.create *10: nfsd.proc2.remove *11: nfsd.proc3.remove *12 :nfsd.proc2.rename.ffh *13 :nfsd.proc2.rename.tfh *14 :nfsd.proc3.rename.ffh *15 :nfsd.proc3.rename.tfh */ /*Get file handler from struct svc_fh */ function __svc_fh:string(fh :long) %{ /* pure */ struct svc_fh * fhp = (struct svc_fh *) (long)(STAP_ARG_fh); struct knfsd_fh *fh = &fhp->fh_handle; snprintf(STAP_RETVALUE, MAXSTRINGLEN, "%d: %08x %08x %08x %08x %08x %08x", kread(&(fh->fh_size)), kread(&(fh->fh_base.fh_pad[0])), kread(&(fh->fh_base.fh_pad[1])), kread(&(fh->fh_base.fh_pad[2])), kread(&(fh->fh_base.fh_pad[3])), kread(&(fh->fh_base.fh_pad[4])), kread(&(fh->fh_base.fh_pad[5]))); CATCH_DEREF_FAULT(); %} function nfs3_cmode:string(cmode:long) %{ /* pure */ int cmode = (int)(long)STAP_ARG_cmode; switch (cmode) { case NFS3_CREATE_UNCHECKED: snprintf(STAP_RETVALUE, MAXSTRINGLEN, "UNCHECKED"); break; case NFS3_CREATE_GUARDED: snprintf(STAP_RETVALUE, MAXSTRINGLEN, "GUARDED"); break; case NFS3_CREATE_EXCLUSIVE: snprintf(STAP_RETVALUE, MAXSTRINGLEN, "EXCLUSIVE"); break; default: snprintf(STAP_RETVALUE, MAXSTRINGLEN, "Bad Value(%d)", cmode); } CATCH_DEREF_FAULT(); %} function nfs4_ctype:string(cmode:long) %{ /* pure */ int cmode = (int)(long)STAP_ARG_cmode; switch (cmode) { case NF4BAD: snprintf(STAP_RETVALUE, MAXSTRINGLEN, "NF4BAD"); break; case NF4REG: snprintf(STAP_RETVALUE, MAXSTRINGLEN, "NF4REG"); break; case NF4DIR: snprintf(STAP_RETVALUE, MAXSTRINGLEN, "NF4DIR"); break; case NF4BLK: snprintf(STAP_RETVALUE, MAXSTRINGLEN, "NF4BLK"); break; case NF4CHR: snprintf(STAP_RETVALUE, MAXSTRINGLEN, "NF4CHR"); break; case NF4LNK: snprintf(STAP_RETVALUE, MAXSTRINGLEN, "NF4LNK"); break; case NF4SOCK: snprintf(STAP_RETVALUE, MAXSTRINGLEN, "NF4SOCK"); break; case NF4FIFO: snprintf(STAP_RETVALUE, MAXSTRINGLEN, "NF4FIFO"); break; case NF4ATTRDIR: snprintf(STAP_RETVALUE, MAXSTRINGLEN, "NF4ATTRDIR"); break; case NF4NAMEDATTR: snprintf(STAP_RETVALUE, MAXSTRINGLEN, "NF4NAMEDATTR"); break; default: snprintf(STAP_RETVALUE, MAXSTRINGLEN, "Bad Value(%d)", cmode); } CATCH_DEREF_FAULT(); %} function ftype:string(type:long) %{ /* pure */ int type = (int)(long)STAP_ARG_type; if (S_ISLNK(type)) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0%o (ISLNK)", type); } else if (S_ISREG(type)) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0%o (ISREG)", type); } else if (S_ISDIR(type)) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0%o (ISDIR)", type); } else if (S_ISCHR(type)) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0%o (ISCHR)", type); } else if (S_ISBLK(type)) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0%o (ISBLK)", type); } else if (S_ISFIFO(type)) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0%o (ISFIFO)", type); } else if (S_ISSOCK(type)) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0%o (ISSOCK)", type); } else { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0%o (Unknown)", type); } %} /** * probe nfsd.dispatch - NFS server receives an operation from client * * @client_ip: the ip address of client * @proto: transfer protocol * @version: nfs version * @xid: transmission id * @prog: program number * @proc: procedure number */ probe nfsd.dispatch = kernel.function("nfsd_dispatch") !, module("nfsd").function("nfsd_dispatch") ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = $rqstp->rq_vers xid = $rqstp->rq_xid prog = $rqstp->rq_prog proc = $rqstp->rq_proc name = "nfsd.dispatch" argstr = sprintf("%d,%d",version,proto) } probe nfsd.dispatch.return = kernel.function("nfsd_dispatch").return !, module("nfsd").function("nfsd_dispatch").return ? { name = "nfsd.dispatch.return" retstr = sprintf("%d",$return) } probe nfsd.proc.entries = nfsd.proc.lookup, nfsd.proc.read, nfsd.proc.write, nfsd.proc.commit, nfsd.proc.remove, nfsd.proc.rename, nfsd.proc.create {} probe nfsd.proc.return = nfsd.proc.lookup.return, nfsd.proc.read.return, nfsd.proc.write.return, nfsd.proc.remove.return, nfsd.proc.rename.return, nfsd.proc.create.return {} /** * probe nfsd.proc.lookup - NFS server opening or searching for a file for client * * @client_ip: the ip address of client * @proto: transfer protocol * @version: nfs version * @fh: file handle of parent dir (the first part is the length of the file handle) * @filename: file name * @filelen: the length of file name * @uid: requester's user id * @gid: requester's group id */ probe nfsd.proc.lookup = nfsd.proc4.lookup ?, nfsd.proc3.lookup, nfsd.proc2.lookup {} probe nfsd.proc.lookup.return = nfsd.proc4.lookup.return ?, nfsd.proc3.lookup.return, nfsd.proc2.lookup.return {} probe nfsd.proc2.lookup = kernel.function("nfsd_proc_lookup") !, module("nfsd").function("nfsd_proc_lookup") ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 2 fh = & @cast($argp, "nfsd_diropargs", "kernel:nfsd")->fh filelen = $argp->len filename = kernel_string_n($argp->name, $argp->len) uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc2.lookup" argstr = sprintf("%s", kernel_string_n($argp->name, $argp->len)) } probe nfsd.proc2.lookup.return = kernel.function("nfsd_proc_lookup").return !, module("nfsd").function("nfsd_proc_lookup").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc2.lookup.return" version = 2 retstr = sprintf("%s", nfsderror($return)) } probe nfsd.proc3.lookup = kernel.function("nfsd3_proc_lookup") !, module("nfsd").function("nfsd3_proc_lookup") ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 3 fh = & @cast($argp, "nfsd_diropargs", "kernel:nfsd")->fh filelen = $argp->len filename = kernel_string_n($argp->name, $argp->len) uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc3.lookup" argstr = sprintf("%s", kernel_string_n($argp->name, $argp->len)) } probe nfsd.proc3.lookup.return = kernel.function("nfsd3_proc_lookup").return !, module("nfsd").function("nfsd3_proc_lookup").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc3.lookup.return" version = 3 retstr = sprintf("%s", nfsderror($return)) } /* * Several of the nfsd.proc4.* entry probes use '.call'. Why? On * kernels <= 2.6.18 (i.e. RHEL4 and RHEL5), those are inline * functions. Besides having different arguments, because those * functions are inline systemtap has trouble finding their arguments * (PR 1155). Finally, those functions are just simple wrappers * around their nfsd_* counterparts (for example, nfsd4_lookup() is a * wrapper for nfsd_lookup). As a comment in fs/nfsd/nfs4proc.c says: * * Note: some routines in this file are just trivial wrappers * (e.g. nfsd4_lookup()) defined solely for the sake of consistent * naming. * * So, we'll just ignore those inline wrappers by specifying * '.call'. which means the function must be a "real" (non-inline) * function. */ probe nfsd.proc4.lookup = kernel.function("nfsd4_lookup").call !, module("nfsd").function("nfsd4_lookup").call ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 4 fh = & @cast($cstate, "nfsd4_compound_state", "kernel:nfsd")->current_fh filelen = $lookup->lo_len filename = kernel_string_n($lookup->lo_name, $lookup->lo_len) uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc4.lookup" argstr = sprintf("%s", kernel_string_n($lookup->lo_name, $lookup->lo_len)) } probe nfsd.proc4.lookup.return = kernel.function("nfsd4_lookup").return !, module("nfsd").function("nfsd4_lookup").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc4.lookup.return" version = 4 retstr = sprintf("%s", nfsderror($return)) } /** * probe nfsd.proc.read - NFS server reading file for client * * @client_ip: the ip address of client * @proto: transfer protocol * @version: nfs version * @fh: file handle (the first part is the length of the file handle) * @size: read bytes * @count: read bytes * @offset: the offset of file * @vec: struct kvec, includes buf address in kernel address and length of each buffer * @vlen: read blocks * @uid: requester's user id * @gid: requester's group id */ probe nfsd.proc.read = nfsd.proc4.read ?, nfsd.proc3.read, nfsd.proc2.read {} probe nfsd.proc.read.return = nfsd.proc4.read.return ?, nfsd.proc3.read.return, nfsd.proc2.read.return {} probe nfsd.proc2.read = kernel.function("nfsd_proc_read") !, module("nfsd").function("nfsd_proc_read") ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 2 fh = & @cast($argp, "nfsd_readargs", "kernel:nfsd")->fh count = $argp->count offset = $argp->offset vec = @choose_defined($rqstp->rq_vec, $argp->vec) vlen = $argp->vlen uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc2.read" argstr = sprintf("%d,%d",count,offset) size = count units = "bytes" } probe nfsd.proc2.read.return = kernel.function("nfsd_proc_read").return !, module("nfsd").function("nfsd_proc_read").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc2.read.return" version = 2 retstr = sprintf("%s", nfsderror($return)) } probe nfsd.proc3.read = kernel.function("nfsd3_proc_read") !, module("nfsd").function("nfsd3_proc_read") ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 3 fh = & @cast($argp, "nfsd3_readargs", "kernel:nfsd")->fh count = $argp->count offset = $argp->offset vec = @choose_defined($rqstp->rq_vec, $argp->vec) vlen = $argp->vlen uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc3.read" argstr = sprintf("%d,%d",count,offset) size = count units = "bytes" } probe nfsd.proc3.read.return = kernel.function("nfsd3_proc_read").return !, module("nfsd").function("nfsd3_proc_read").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc3.read.return" version = 3 retstr = sprintf("%s", nfsderror($return)) } probe nfsd.proc4.read = kernel.function("nfsd4_read").call !, module("nfsd").function("nfsd4_read").call ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 4 fh = & @cast($cstate, "nfsd4_compound_state", "kernel:nfsd")->current_fh count = $read->rd_length offset = $read->rd_offset vec = $rqstp->rq_vec vlen = $read->rd_vlen uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc4.read" argstr = sprintf("%d,%d",count,offset) size = count units = "bytes" } probe nfsd.proc4.read.return = kernel.function("nfsd4_read").return !, module("nfsd").function("nfsd4_read").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc4.read.return" version = 4 retstr = sprintf("%s", nfsderror($return)) } /** * probe nfsd.proc.write - NFS server writing data to file for client * * @client_ip: the ip address of client * @proto: transfer protocol * @version: nfs version * @fh: file handle (the first part is the length of the file handle) * @size: read bytes * @count: read bytes * @offset: the offset of file * @vec: struct kvec, includes buf address in kernel address and length of each buffer * @vlen: read blocks * @stable: argp->stable * @uid: requester's user id * @gid: requester's group id */ probe nfsd.proc.write = nfsd.proc4.write ?, nfsd.proc3.write, nfsd.proc2.write {} probe nfsd.proc.write.return = nfsd.proc4.write.return ?, nfsd.proc3.write.return, nfsd.proc2.write.return {} probe nfsd.proc2.write = kernel.function("nfsd_proc_write") !, module("nfsd").function("nfsd_proc_write") ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 2 fh = & @cast($argp, "nfsd_writeargs", "kernel:nfsd")->fh count = $argp->len offset = $argp->offset vec = @choose_defined($rqstp->rq_vec, $argp->vec) vlen = $argp->vlen stable = 1 # hardcoded in nfsd_proc_write() uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc2.write" argstr = sprintf("%d,%d",count,offset) size = count units = "bytes" } probe nfsd.proc2.write.return = kernel.function("nfsd_proc_write").return !, module("nfsd").function("nfsd_proc_write").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc2.write.return" version = 2 retstr = sprintf("%s", nfsderror($return)) count = ($return == 0 ? $argp->len : $return) stable = 1 } probe nfsd.proc3.write = kernel.function("nfsd3_proc_write") !, module("nfsd").function("nfsd3_proc_write") ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 3 fh = & @cast($argp, "nfsd3_writeargs", "kernel:nfsd")->fh count = $argp->count offset = $argp->offset vec = @choose_defined($rqstp->rq_vec, $argp->vec) vlen = $argp->vlen stable = $argp->stable uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc3.write" argstr = sprintf("%d,%d",count,offset) size = count units = "bytes" } probe nfsd.proc3.write.return = kernel.function("nfsd3_proc_write").return !, module("nfsd").function("nfsd3_proc_write").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc3.write.return" version = 3 retstr = sprintf("%s", nfsderror($return)) count = $resp->count stable = $resp->committed } probe nfsd.proc4.write = kernel.function("nfsd4_write").call !, module("nfsd").function("nfsd4_write").call ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 4 fh = & @cast($cstate, "nfsd4_compound_state", "kernel:nfsd")->current_fh count = $write->wr_buflen offset = $write->wr_offset vec = $rqstp->rq_vec vlen = @choose_defined($write->wr_vlen, 0) stable = $write->wr_stable_how uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc4.write" argstr = sprintf("%d,%d",count,offset) size = count units = "bytes" } probe nfsd.proc4.write.return = kernel.function("nfsd4_write").return !, module("nfsd").function("nfsd4_write").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc4.write.return" version = 4 count = $write->wr_bytes_written stable = $write->wr_how_written retstr = sprintf("%s", nfsderror($return)) } /** * probe nfsd.proc.commit - NFS server performing a commit operation for client * * @client_ip: the ip address of client * @proto: transfer protocol * @version: nfs version * @fh: file handle (the first part is the length of the file handle) * @size: read bytes * @count: read bytes * @offset: the offset of file * @uid: requester's user id * @gid: requester's group id */ probe nfsd.proc.commit = nfsd.proc4.commit ?, nfsd.proc3.commit {} probe nfsd.proc.commit.return = nfsd.proc4.commit.return ?, nfsd.proc3.commit.return {} probe nfsd.proc3.commit = kernel.function("nfsd3_proc_commit") !, module("nfsd").function("nfsd3_proc_commit") ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 3 fh = & @cast($argp, "struct nfsd3_commitargs", "kernel:nfsd")->fh count = $argp->count offset = $argp->offset uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc3.commit" argstr = sprintf("%d,%d",count,offset) size = count units = "bytes" } probe nfsd.proc3.commit.return = kernel.function("nfsd3_proc_commit").return !, module("nfsd").function("nfsd3_proc_commit").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc3.commit.return" version = 3 retstr = sprintf("%s", nfsderror($return)) } probe nfsd.proc4.commit = kernel.function("nfsd4_commit").call !, module("nfsd").function("nfsd4_commit").call ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 4 fh = & @cast($cstate, "nfsd4_compound_state", "kernel:nfsd")->current_fh count = $commit->co_count offset = $commit->co_offset uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc4.commit" argstr = sprintf("%d,%d",count,offset) size = count units = "bytes" } probe nfsd.proc4.commit.return = kernel.function("nfsd4_commit").return !, module("nfsd").function("nfsd4_commit").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc4.commit.return" version = 4 retstr = sprintf("%s", nfsderror($return)) } /** * probe nfsd.proc.create - NFS server creating a file for client * * @client_ip: the ip address of client * @proto: transfer protocol * @version: nfs version * @fh: file handle (the first part is the length of the file handle) * @filename: file name * @filelen: length of file name * @uid: requester's user id * @gid: requester's group id */ probe nfsd.proc.create = nfsd.proc4.create ?, nfsd.proc3.create, nfsd.proc2.create {} probe nfsd.proc.create.return = nfsd.proc4.create.return ?, nfsd.proc3.create.return, nfsd.proc2.create.return {} probe nfsd.proc2.create = kernel.function("nfsd_proc_create") !, module("nfsd").function("nfsd_proc_create") ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 2 fh = & @cast($argp, "struct nfsd_createargs", "kernel:nfsd")->fh filelen = $argp->len filename = kernel_string_n($argp->name, $argp->len) createmode = 0 # gets computed by nfsd_proc_create uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc2.create" argstr = sprintf("%s", kernel_string_n($argp->name, $argp->len)) } probe nfsd.proc2.create.return = kernel.function("nfsd_proc_create").return !, module("nfsd").function("nfsd_proc_create").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc2.create.return" version = 2 retstr = sprintf("%s", nfsderror($return)) } probe nfsd.proc3.create = kernel.function("nfsd3_proc_create") !, module("nfsd").function("nfsd3_proc_create") ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 3 fh = & @cast($argp, "struct nfsd_createargs", "kernel:nfsd")->fh filelen = $argp->len filename = kernel_string_n($argp->name, $argp->len) createmode = $argp->createmode uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc3.create" argstr = sprintf("%s (mode=%s)", kernel_string_n($argp->name, $argp->len), nfs3_cmode(createmode)) } probe nfsd.proc3.create.return = kernel.function("nfsd3_proc_create").return !, module("nfsd").function("nfsd3_proc_create").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc3.create.return" version = 3 retstr = sprintf("%s", nfsderror($return)) } probe nfsd.proc4.create = kernel.function("nfsd4_create").call !, module("nfsd").function("nfsd4_create").call ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 4 fh = (@defined($cstate) ? &@cast($cstate, "nfsd4_compound_state", "kernel:nfsd")->current_fh : $current_fh) filelen = $create->cr_namelen filename = kernel_string_n($create->cr_name, $create->cr_namelen) createmode = $create->cr_type uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc4.create" argstr = sprintf("%s (type=%s)", kernel_string_n($create->cr_name, $create->cr_namelen), nfs4_ctype(createmode)) } probe nfsd.proc4.create.return = kernel.function("nfsd4_create").return !, module("nfsd").function("nfsd4_create").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc4.create.return" version = 4 retstr = sprintf("%s", nfsderror($return)) } /** * probe nfsd.proc.remove - NFS server removing a file for client * * @client_ip: the ip address of client * @proto: transfer protocol * @version: nfs version * @fh: file handle (the first part is the length of the file handle) * @filename: file name * @filelen: length of file name * @uid: requester's user id * @gid: requester's group id */ probe nfsd.proc.remove = nfsd.proc4.remove ?, nfsd.proc3.remove, nfsd.proc2.remove {} probe nfsd.proc.remove.return = nfsd.proc4.remove.return ?, nfsd.proc3.remove.return, nfsd.proc2.remove.return {} probe nfsd.proc2.remove = kernel.function("nfsd_proc_remove") !, module("nfsd").function("nfsd_proc_remove") ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 2 fh = & @cast($argp, "struct nfsd_diropargs", "kernel:nfsd")->fh filelen = $argp->len filename = kernel_string_n($argp->name, $argp->len) uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc2.remove" argstr = sprintf("%s", kernel_string_n($argp->name, $argp->len)) } probe nfsd.proc2.remove.return = kernel.function("nfsd_proc_remove").return !, module("nfsd").function("nfsd_proc_remove").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc2.remove.return" version = 2 retstr = sprintf("%s", nfsderror($return)) } probe nfsd.proc3.remove = kernel.function("nfsd3_proc_remove") !, module("nfsd").function("nfsd3_proc_remove") ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 3 fh = & @cast($argp, "struct nfsd3_diropargs", "kernel:nfsd")->fh filelen = $argp->len filename = kernel_string_n($argp->name, $argp->len) uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc3.remove" argstr = sprintf("%s", kernel_string_n($argp->name, $argp->len)) } probe nfsd.proc3.remove.return = kernel.function("nfsd3_proc_remove").return !, module("nfsd").function("nfsd3_proc_remove").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc3.remove.return" version = 3 retstr = sprintf("%s", nfsderror($return)) } probe nfsd.proc4.remove = kernel.function("nfsd4_remove").call !, module("nfsd").function("nfsd4_remove").call ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 4 fh = & @cast($cstate, "nfsd4_compound_state", "kernel:nfsd")->current_fh filelen = $remove->rm_namelen filename = kernel_string_n($remove->rm_name, $remove->rm_namelen) uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc4.remove" argstr = sprintf("%s", kernel_string_n($remove->rm_name, $remove->rm_namelen)) } probe nfsd.proc4.remove.return = kernel.function("nfsd4_remove").return !, module("nfsd").function("nfsd4_remove").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc4.remove.return" version = 4 retstr = sprintf("%s", nfsderror($return)) } /** * probe nfsd.proc.rename - NFS Server renaming a file for client * * @client_ip: the ip address of client * @fh: file handler of old path * @tfh: file handler of new path * @filename: old file name * @tname: new file name * @flen: length of old file name * @tlen: length of new file name * @uid: requester's user id * @gid: requester's group id */ probe nfsd.proc.rename = nfsd.proc4.rename ?, nfsd.proc3.rename, nfsd.proc2.rename {} probe nfsd.proc.rename.return = nfsd.proc4.rename.return ?, nfsd.proc3.rename.return, nfsd.proc2.rename.return {} probe nfsd.proc2.rename = kernel.function("nfsd_proc_rename") !, module("nfsd").function("nfsd_proc_rename") ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 2 fh = & @cast($argp, "struct nfsd_renameargs", "kernel:nfsd")->ffh tfh = & @cast($argp, "struct nfsd_renameargs", "kernel:nfsd")->tfh filelen = $argp->flen filename = kernel_string_n($argp->fname, $argp->flen) tlen = $argp->tlen tname = kernel_string_n($argp->tname, $argp->tlen) uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc2.rename" argstr = sprintf("%s to %s", kernel_string_n($argp->fname, $argp->flen), kernel_string_n($argp->tname, $argp->tlen)) } probe nfsd.proc2.rename.return = kernel.function("nfsd_proc_rename").return !, module("nfsd").function("nfsd_proc_rename").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc2.rename.return" version = 2 retstr = sprintf("%s", nfsderror($return)) } probe nfsd.proc3.rename = kernel.function("nfsd3_proc_rename") !, module("nfsd").function("nfsd3_proc_rename") ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 3 fh = & @cast($argp, "struct nfsd3_renameargs", "kernel:nfsd")->ffh tfh = & @cast($argp, "struct nfsd3_renameargs", "kernel:nfsd")->tfh filelen = $argp->flen filename = kernel_string_n($argp->fname, $argp->flen) tlen = $argp->tlen tname = kernel_string_n($argp->tname, $argp->tlen) uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc3.rename" argstr = sprintf("%s to %s", kernel_string_n($argp->fname, $argp->flen), kernel_string_n($argp->tname, $argp->tlen)) } probe nfsd.proc3.rename.return = kernel.function("nfsd3_proc_rename").return !, module("nfsd").function("nfsd3_proc_rename").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc3.rename.return" version = 3 retstr = sprintf("%s", nfsderror($return)) } probe nfsd.proc4.rename = kernel.function("nfsd4_rename").call !, module("nfsd").function("nfsd4_rename").call ? { client_ip = addr_from_rqst_str($rqstp) proto = $rqstp->rq_prot version = 4 fh = & @cast($cstate, "nfsd4_compound_state", "kernel:nfsd")->save_fh tfh = & @cast($cstate, "nfsd4_compound_state", "kernel:nfsd")->current_fh filelen = $rename->rn_snamelen filename = kernel_string_n($rename->rn_sname, $rename->rn_snamelen) tlen = $rename->rn_tnamelen tname = kernel_string_n($rename->rn_tname, $rename->rn_tnamelen) uid = $rqstp->rq_cred->cr_uid gid = $rqstp->rq_cred->cr_gid name = "nfsd.proc4.rename" argstr = sprintf("%s to %s", kernel_string_n($rename->rn_sname, $rename->rn_snamelen), kernel_string_n($rename->rn_tname, $rename->rn_tnamelen)) } probe nfsd.proc4.rename.return = kernel.function("nfsd4_rename").return !, module("nfsd").function("nfsd4_rename").return ? { client_ip = addr_from_rqst_str($rqstp) name = "nfsd.proc4.rename.return" version = 4 retstr = sprintf("%s", nfsderror($return)) } probe nfsd.entries = nfsd.open, nfsd.read, nfsd.write, nfsd.lookup, nfsd.commit, nfsd.create, nfsd.createv3, nfsd.unlink, nfsd.rename, nfsd.close {} probe nfsd.return = nfsd.open.return, nfsd.read.return, nfsd.write.return, nfsd.lookup.return, nfsd.commit.return, nfsd.create.return, nfsd.createv3.return, nfsd.unlink.return, nfsd.rename.return {} /** * probe nfsd.open - NFS server opening a file for client * * @client_ip: the ip address of client * @fh: file handle (the first part is the length of the file handle) * @access: indicates the type of open (read/write/commit/readdir...) * @type: type of file (regular file or dir) */ probe nfsd.open = kernel.function("nfsd_open") !, module("nfsd").function("nfsd_open") ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($fhp) access = @choose_defined($access, $may_flags) type = $type name = "nfsd.open" argstr = sprintf("access: %d type: %s", access, ftype(type)) } probe nfsd.open.return = kernel.function("nfsd_open").return !, module("nfsd").function("nfsd_open").return ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($fhp) name = "nfsd.open.return" retstr = sprintf("%s", nfsderror($return)) } /** * probe nfsd.close - NFS server closing a file for client * * @filename: file name */ probe nfsd.close = kernel.function("nfsd_close") !, module("nfsd").function("nfsd_close") ? { client_ip ="N/A" filename = __file_filename($filp) name = "nfsd.close" argstr = sprintf("%s",filename) } probe nfsd.close.return = kernel.function("nfsd_close").return !, module("nfsd").function("nfsd_close").return ? { name = "nfsd.close.return" retstr = "N/A" } /** * probe nfsd.read - NFS server reading data from a file for client * * @client_ip: the ip address of client * @fh: file handle (the first part is the length of the file handle) * @file: argument file, indicates if the file has been opened. * @size: read bytes * @count: read bytes * @offset: the offset of file * @vec: struct kvec, includes buf address in kernel address and length of each buffer * @vlen: read blocks */ probe nfsd.read = kernel.function("nfsd_read") !, module("nfsd").function("nfsd_read") ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($fhp) file = @choose_defined($file, 0) count = kernel_long($count) offset = $offset vec = $vec vlen = $vlen name = "nfsd.read" argstr = sprintf("count: %d offset: %d",count,offset) size = count units = "bytes" } probe nfsd.read.return = kernel.function("nfsd_read").return !, module("nfsd").function("nfsd_read").return ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($fhp) name = "nfsd.read.return" retstr = sprintf("%s", nfsderror($return)) } /** * probe nfsd.write - NFS server writing data to a file for client * * @client_ip: the ip address of client * @fh: file handle (the first part is the length of the file handle) * @file: argument file, indicates if the file has been opened. * @size: read bytes * @count: read bytes * @offset: the offset of file * @vec: struct kvec, includes buf address in kernel address and length of each buffer * @vlen: read blocks */ probe nfsd.write = kernel.function("nfsd_write") !, module("nfsd").function("nfsd_write") ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($fhp) file = @choose_defined($file, 0) %( kernel_v >= "2.6.30" %? count = kernel_long($cnt) %: count = $cnt %) offset = $offset vec = $vec vlen = $vlen name = "nfsd.write" argstr = sprintf("count: %d offset: %d",count,offset) size = count units = "bytes" } probe nfsd.write.return = kernel.function("nfsd_write").return !, module("nfsd").function("nfsd_write").return ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($fhp) name = "nfsd.write.return" retstr = sprintf("%s", nfsderror($return)) } /** * probe nfsd.commit - NFS server committing all pending writes to stable storage * * @client_ip: the ip address of client * @fh: file handle (the first part is the length of the file handle) * @flag: indicates whether this execution is a sync operation * @size: read bytes * @count: read bytes * @offset: the offset of file */ probe nfsd.commit = kernel.function("nfsd_commit") !, module("nfsd").function("nfsd_commit") ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($fhp) count = $count offset = $offset flag = $fhp->fh_export->ex_flags name = "nfsd.commit" argstr = sprintf("count: %d offset: %d",count,offset) size = count units = "bytes" } probe nfsd.commit.return = kernel.function("nfsd_commit").return !, module("nfsd").function("nfsd_commit").return ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($fhp) name = "nfsd.commit.return" retstr = sprintf("%s", nfsderror($return)) } /** * probe nfsd.lookup - NFS server opening or searching file for a file for client * * @client_ip: the ip address of client * @fh: file handle of parent dir(the first part is the length of the file handle) * @filename: file name * @filelen: the length of file name */ probe nfsd.lookup = kernel.function("nfsd_lookup") !, module("nfsd").function("nfsd_lookup") ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($fhp) filelen = $len filename = kernel_string_n($name, $len) name = "nfsd.lookup" argstr = sprintf("name: %s", kernel_string_n($name, $len)) } probe nfsd.lookup.return = kernel.function("nfsd_lookup").return !, module("nfsd").function("nfsd_lookup").return ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($fhp) name = "nfsd.lookup.return" retstr = sprintf("%s", nfsderror($return)) } /** * probe nfsd.create - NFS server creating a file(regular,dir,device,fifo) for client * * @client_ip: the ip address of client * @fh: file handle (the first part is the length of the file handle) * @filename: file name * @filelen: the length of file name * @type: file type(regular,dir,device,fifo ...) * @iap_valid: Attribute flags * @iap_mode: file access mode * * Sometimes nfsd will call nfsd_create_v3 instead of this this probe point. */ probe nfsd.create = kernel.function("nfsd_create") !, module("nfsd").function("nfsd_create") ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($fhp) filelen = $flen filename = kernel_string_n($fname, $flen) type = $type iap_valid = $iap->ia_valid iap_mode = $iap->ia_mode name = "nfsd.create" argstr = sprintf("name: %s type: %s", kernel_string_n($fname, $flen), ftype(type)) } probe nfsd.create.return = kernel.function("nfsd_create").return !, module("nfsd").function("nfsd_create").return ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($fhp) name = "nfsd.create.return" retstr = sprintf("%s", nfsderror($return)) } /** * probe nfsd.createv3 - NFS server creating a regular file or set file attributes for client * * @client_ip: the ip address of client * @fh: file handle (the first part is the length of the file handle) * @filename: file name * @filelen: the length of file name * @iap_valid: Attribute flags * @iap_mode: file access mode * @createmode: create mode .The possible values could be: NFS3_CREATE_EXCLUSIVE, NFS3_CREATE_UNCHECKED, or NFS3_CREATE_GUARDED * @truncp: trunp arguments, indicates if the file shouldbe truncate * @verifier: file attributes (atime,mtime,mode). It's used to reset file attributes for CREATE_EXCLUSIVE * * This probepoints is only called by nfsd3_proc_create and * nfsd4_open when op_claim_type is NFS4_OPEN_CLAIM_NULL. */ probe nfsd.createv3 = kernel.function("do_nfsd_create") !, module("nfsd").function("do_nfsd_create") !, kernel.function("nfsd_create_v3") !, module("nfsd").function("nfsd_create_v3") ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($fhp) filelen = $flen filename = kernel_string_n($fname, $flen) iap_valid = $iap->ia_valid iap_mode = $iap->ia_mode truncp = $truncp verifier = $verifier createmode = $createmode name = "nfsd.createv3" argstr = sprintf("name: %s mode: %s", kernel_string_n($fname, $flen), nfs3_cmode(createmode)) } probe nfsd.createv3.return = kernel.function("do_nfsd_create").return !, module("nfsd").function("do_nfsd_create").return !, kernel.function("nfsd_create_v3").return !, module("nfsd").function("nfsd_create_v3").return ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($fhp) name = "nfsd.createv3.return" retstr = sprintf("%s", nfsderror($return)) } /** * probe nfsd.unlink - NFS server removing a file or a directory for client * * @client_ip: the ip address of client * @fh: file handle (the first part is the length of the file handle) * @filename: file name * @filelen: the length of file name * @type: file type (file or dir) */ probe nfsd.unlink = kernel.function("nfsd_unlink") !, module("nfsd").function("nfsd_unlink") ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($fhp) filelen = $flen filename = kernel_string_n($fname, $flen) type = $type name = "nfsd.unlink" argstr = sprintf("name: %s", kernel_string_n($fname, $flen)) } probe nfsd.unlink.return = kernel.function("nfsd_unlink").return !, module("nfsd").function("nfsd_unlink").return ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($fhp) name = "nfsd.unlink.return" retstr = sprintf("%s", nfsderror($return)) } /** * probe nfsd.rename -NFS server renaming a file for client * * @client_ip: the ip address of client * @fh: file handler of old path * @tfh: file handler of new path * @filename: old file name * @tname: new file name * @flen: length of old file name * @tlen: length of new file name */ probe nfsd.rename = kernel.function("nfsd_rename") !, module("nfsd").function("nfsd_rename") ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($ffhp) tfh = __svc_fh($tfhp) filelen = $flen filename = kernel_string_n($fname, $flen) tlen = $tlen tname = kernel_string_n($tname, $tlen) name = "nfsd.rename" argstr = sprintf("%s to %s", kernel_string_n($fname, $flen), kernel_string_n($tname, $tlen)) } probe nfsd.rename.return = kernel.function("nfsd_rename").return !, module("nfsd").function("nfsd_rename").return ? { client_ip = addr_from_rqst_str($rqstp) fh = __svc_fh($ffhp) name = "nfsd.rename.return" retstr = sprintf("%s", nfsderror($return)) } systemtap-2.3/tapset/linux/nfsderrno.stp000066400000000000000000000273131217430427200206060ustar00rootroot00000000000000// nfsd errnos tapset // Copyright (C) 2010 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. %{ #include #include #define nfs_ok __constant_htonl(NFS_OK) #define nfserr_perm __constant_htonl(NFSERR_PERM) #define nfserr_noent __constant_htonl(NFSERR_NOENT) #define nfserr_io __constant_htonl(NFSERR_IO) #define nfserr_nxio __constant_htonl(NFSERR_NXIO) #define nfserr_eagain __constant_htonl(NFSERR_EAGAIN) #define nfserr_acces __constant_htonl(NFSERR_ACCES) #define nfserr_exist __constant_htonl(NFSERR_EXIST) #define nfserr_xdev __constant_htonl(NFSERR_XDEV) #define nfserr_nodev __constant_htonl(NFSERR_NODEV) #define nfserr_notdir __constant_htonl(NFSERR_NOTDIR) #define nfserr_isdir __constant_htonl(NFSERR_ISDIR) #define nfserr_inval __constant_htonl(NFSERR_INVAL) #define nfserr_fbig __constant_htonl(NFSERR_FBIG) #define nfserr_nospc __constant_htonl(NFSERR_NOSPC) #define nfserr_rofs __constant_htonl(NFSERR_ROFS) #define nfserr_mlink __constant_htonl(NFSERR_MLINK) #define nfserr_opnotsupp __constant_htonl(NFSERR_OPNOTSUPP) #define nfserr_nametoolong __constant_htonl(NFSERR_NAMETOOLONG) #define nfserr_notempty __constant_htonl(NFSERR_NOTEMPTY) #define nfserr_dquot __constant_htonl(NFSERR_DQUOT) #define nfserr_stale __constant_htonl(NFSERR_STALE) #define nfserr_remote __constant_htonl(NFSERR_REMOTE) #define nfserr_wflush __constant_htonl(NFSERR_WFLUSH) #define nfserr_badhandle __constant_htonl(NFSERR_BADHANDLE) #define nfserr_notsync __constant_htonl(NFSERR_NOT_SYNC) #define nfserr_badcookie __constant_htonl(NFSERR_BAD_COOKIE) #define nfserr_notsupp __constant_htonl(NFSERR_NOTSUPP) #define nfserr_toosmall __constant_htonl(NFSERR_TOOSMALL) #define nfserr_serverfault __constant_htonl(NFSERR_SERVERFAULT) #define nfserr_badtype __constant_htonl(NFSERR_BADTYPE) #define nfserr_jukebox __constant_htonl(NFSERR_JUKEBOX) #define nfserr_denied __constant_htonl(NFSERR_DENIED) #define nfserr_deadlock __constant_htonl(NFSERR_DEADLOCK) #define nfserr_expired __constant_htonl(NFSERR_EXPIRED) #define nfserr_bad_cookie __constant_htonl(NFSERR_BAD_COOKIE) #define nfserr_same __constant_htonl(NFSERR_SAME) #define nfserr_clid_inuse __constant_htonl(NFSERR_CLID_INUSE) #define nfserr_stale_clientid __constant_htonl(NFSERR_STALE_CLIENTID) #define nfserr_resource __constant_htonl(NFSERR_RESOURCE) #define nfserr_moved __constant_htonl(NFSERR_MOVED) #define nfserr_nofilehandle __constant_htonl(NFSERR_NOFILEHANDLE) #define nfserr_minor_vers_mismatch __constant_htonl(NFSERR_MINOR_VERS_MISMATCH) #define nfserr_share_denied __constant_htonl(NFSERR_SHARE_DENIED) #define nfserr_stale_stateid __constant_htonl(NFSERR_STALE_STATEID) #define nfserr_old_stateid __constant_htonl(NFSERR_OLD_STATEID) #define nfserr_bad_stateid __constant_htonl(NFSERR_BAD_STATEID) #define nfserr_bad_seqid __constant_htonl(NFSERR_BAD_SEQID) #define nfserr_symlink __constant_htonl(NFSERR_SYMLINK) #define nfserr_not_same __constant_htonl(NFSERR_NOT_SAME) #define nfserr_restorefh __constant_htonl(NFSERR_RESTOREFH) #define nfserr_attrnotsupp __constant_htonl(NFSERR_ATTRNOTSUPP) #define nfserr_bad_xdr __constant_htonl(NFSERR_BAD_XDR) #define nfserr_openmode __constant_htonl(NFSERR_OPENMODE) #define nfserr_locks_held __constant_htonl(NFSERR_LOCKS_HELD) #define nfserr_op_illegal __constant_htonl(NFSERR_OP_ILLEGAL) #define nfserr_grace __constant_htonl(NFSERR_GRACE) #define nfserr_no_grace __constant_htonl(NFSERR_NO_GRACE) #define nfserr_reclaim_bad __constant_htonl(NFSERR_RECLAIM_BAD) #define nfserr_badname __constant_htonl(NFSERR_BADNAME) #define nfserr_cb_path_down __constant_htonl(NFSERR_CB_PATH_DOWN) #define nfserr_locked __constant_htonl(NFSERR_LOCKED) #define nfserr_wrongsec __constant_htonl(NFSERR_WRONGSEC) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) #define nfserr_badiomode __constant_htonl(NFS4ERR_BADIOMODE) #define nfserr_badlayout __constant_htonl(NFS4ERR_BADLAYOUT) #define nfserr_bad_session_digest __constant_htonl(NFS4ERR_BAD_SESSION_DIGEST) #define nfserr_badsession __constant_htonl(NFS4ERR_BADSESSION) #define nfserr_badslot __constant_htonl(NFS4ERR_BADSLOT) #define nfserr_complete_already __constant_htonl(NFS4ERR_COMPLETE_ALREADY) #define nfserr_conn_not_bound_to_session __constant_htonl(NFS4ERR_CONN_NOT_BOUND_TO_SESSION) #define nfserr_deleg_already_wanted __constant_htonl(NFS4ERR_DELEG_ALREADY_WANTED) #define nfserr_back_chan_busy __constant_htonl(NFS4ERR_BACK_CHAN_BUSY) #define nfserr_layouttrylater __constant_htonl(NFS4ERR_LAYOUTTRYLATER) #define nfserr_layoutunavailable __constant_htonl(NFS4ERR_LAYOUTUNAVAILABLE) #define nfserr_nomatching_layout __constant_htonl(NFS4ERR_NOMATCHING_LAYOUT) #define nfserr_recallconflict __constant_htonl(NFS4ERR_RECALLCONFLICT) #define nfserr_unknown_layouttype __constant_htonl(NFS4ERR_UNKNOWN_LAYOUTTYPE) #define nfserr_seq_misordered __constant_htonl(NFS4ERR_SEQ_MISORDERED) #define nfserr_sequence_pos __constant_htonl(NFS4ERR_SEQUENCE_POS) #define nfserr_req_too_big __constant_htonl(NFS4ERR_REQ_TOO_BIG) #define nfserr_rep_too_big __constant_htonl(NFS4ERR_REP_TOO_BIG) #define nfserr_rep_too_big_to_cache __constant_htonl(NFS4ERR_REP_TOO_BIG_TO_CACHE) #define nfserr_retry_uncached_rep __constant_htonl(NFS4ERR_RETRY_UNCACHED_REP) #define nfserr_unsafe_compound __constant_htonl(NFS4ERR_UNSAFE_COMPOUND) #define nfserr_too_many_ops __constant_htonl(NFS4ERR_TOO_MANY_OPS) #define nfserr_op_not_in_session __constant_htonl(NFS4ERR_OP_NOT_IN_SESSION) #define nfserr_hash_alg_unsupp __constant_htonl(NFS4ERR_HASH_ALG_UNSUPP) #define nfserr_clientid_busy __constant_htonl(NFS4ERR_CLIENTID_BUSY) #define nfserr_pnfs_io_hole __constant_htonl(NFS4ERR_PNFS_IO_HOLE) #define nfserr_seq_false_retry __constant_htonl(NFS4ERR_SEQ_FALSE_RETRY) #define nfserr_bad_high_slot __constant_htonl(NFS4ERR_BAD_HIGH_SLOT) #define nfserr_deadsession __constant_htonl(NFS4ERR_DEADSESSION) #define nfserr_encr_alg_unsupp __constant_htonl(NFS4ERR_ENCR_ALG_UNSUPP) #define nfserr_pnfs_no_layout __constant_htonl(NFS4ERR_PNFS_NO_LAYOUT) #define nfserr_not_only_op __constant_htonl(NFS4ERR_NOT_ONLY_OP) #define nfserr_wrong_cred __constant_htonl(NFS4ERR_WRONG_CRED) #define nfserr_wrong_type __constant_htonl(NFS4ERR_WRONG_TYPE) #define nfserr_dirdeleg_unavail __constant_htonl(NFS4ERR_DIRDELEG_UNAVAIL) #define nfserr_reject_deleg __constant_htonl(NFS4ERR_REJECT_DELEG) #define nfserr_returnconflict __constant_htonl(NFS4ERR_RETURNCONFLICT) #define nfserr_deleg_revoked __constant_htonl(NFS4ERR_DELEG_REVOKED) #endif %} /** * sfunction nfsderror - Convert nfsd error number into string * @err: errnum * * Description: This function returns a string for the error number * passed into the function. */ function nfsderror:string(err:long) %{ static struct { int nfserr; char *string; } nfs_errtbl[] = { {nfs_ok, "NFS_OK"}, {nfserr_perm, "NFSERR_PERM"}, {nfserr_noent, "NFSERR_NOENT"}, {nfserr_io, "NFSERR_IO"}, {nfserr_nxio, "NFSERR_NXIO"}, {nfserr_eagain, "NFSERR_EAGAIN"}, {nfserr_acces, "NFSERR_ACCES"}, {nfserr_exist, "NFSERR_EXIST"}, {nfserr_xdev, "NFSERR_XDEV"}, {nfserr_nodev, "NFSERR_NODEV"}, {nfserr_notdir, "NFSERR_NOTDIR"}, {nfserr_isdir, "NFSERR_ISDIR"}, {nfserr_inval, "NFSERR_INVAL"}, {nfserr_fbig, "NFSERR_FBIG"}, {nfserr_nospc, "NFSERR_NOSPC"}, {nfserr_rofs, "NFSERR_ROFS"}, {nfserr_mlink, "NFSERR_MLINK"}, {nfserr_opnotsupp, "NFSERR_OPNOTSUPP"}, {nfserr_nametoolong, "NFSERR_NAMETOOLONG"}, {nfserr_notempty, "NFSERR_NOTEMPTY"}, {nfserr_dquot, "NFSERR_DQUOT"}, {nfserr_stale, "NFSERR_STALE"}, {nfserr_remote, "NFSERR_REMOTE"}, {nfserr_wflush, "NFSERR_WFLUSH"}, {nfserr_badhandle, "NFSERR_BADHANDLE"}, {nfserr_notsync, "NFSERR_NOT_SYNC"}, {nfserr_badcookie, "NFSERR_BAD_COOKIE"}, {nfserr_notsupp, "NFSERR_NOTSUPP"}, {nfserr_toosmall, "NFSERR_TOOSMALL"}, {nfserr_serverfault, "NFSERR_SERVERFAULT"}, {nfserr_badtype, "NFSERR_BADTYPE"}, {nfserr_jukebox, "NFSERR_JUKEBOX"}, {nfserr_denied, "NFSERR_DENIED"}, {nfserr_deadlock, "NFSERR_DEADLOCK"}, {nfserr_expired, "NFSERR_EXPIRED"}, {nfserr_bad_cookie, "NFSERR_BAD_COOKIE"}, {nfserr_same, "NFSERR_SAME"}, {nfserr_clid_inuse, "NFSERR_CLID_INUSE"}, {nfserr_stale_clientid, "NFSERR_STALE_CLIENTID"}, {nfserr_resource, "NFSERR_RESOURCE"}, {nfserr_moved, "NFSERR_MOVED"}, {nfserr_nofilehandle, "NFSERR_NOFILEHANDLE"}, {nfserr_minor_vers_mismatch, "NFSERR_MINOR_VERS_MISMATCH"}, {nfserr_share_denied, "NFSERR_SHARE_DENIED"}, {nfserr_stale_stateid, "NFSERR_STALE_STATEID"}, {nfserr_old_stateid, "NFSERR_OLD_STATEID"}, {nfserr_bad_stateid, "NFSERR_BAD_STATEID"}, {nfserr_bad_seqid, "NFSERR_BAD_SEQID"}, {nfserr_symlink , "NFSERR_SYMLINK"}, {nfserr_not_same , "NFSERR_NOT_SAME"}, {nfserr_restorefh , "NFSERR_RESTOREFH"}, {nfserr_attrnotsupp, "NFSERR_ATTRNOTSUPP"}, {nfserr_bad_xdr, "NFSERR_BAD_XDR"}, {nfserr_openmode, "NFSERR_OPENMODE"}, {nfserr_locks_held, "NFSERR_LOCKS_HELD"}, {nfserr_op_illegal, "NFSERR_OP_ILLEGAL"}, {nfserr_grace, "NFSERR_GRACE"}, {nfserr_no_grace, "NFSERR_NO_GRACE"}, {nfserr_reclaim_bad, "NFSERR_RECLAIM_BAD"}, {nfserr_badname, "NFSERR_BADNAME"}, {nfserr_cb_path_down, "NFSERR_CB_PATH_DOWN"}, {nfserr_locked, "NFSERR_LOCKED"}, {nfserr_wrongsec, "NFSERR_WRONGSEC"}, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) {nfserr_badiomode, "NFS4ERR_BADIOMODE"}, {nfserr_badlayout, "NFS4ERR_BADLAYOUT"}, {nfserr_bad_session_digest, "NFS4ERR_BAD_SESSION_DIGEST"}, {nfserr_badsession, "NFS4ERR_BADSESSION"}, {nfserr_badslot, "NFS4ERR_BADSLOT"}, {nfserr_complete_already, "NFS4ERR_COMPLETE_ALREADY"}, {nfserr_conn_not_bound_to_session, "NFS4ERR_CONN_NOT_BOUND_TO_SESSION"}, {nfserr_deleg_already_wanted, "NFS4ERR_DELEG_ALREADY_WANTED"}, {nfserr_back_chan_busy, "NFS4ERR_BACK_CHAN_BUSY"}, {nfserr_layouttrylater, "NFS4ERR_LAYOUTTRYLATER"}, {nfserr_layoutunavailable, "NFS4ERR_LAYOUTUNAVAILABLE"}, {nfserr_nomatching_layout, "NFS4ERR_NOMATCHING_LAYOUT"}, {nfserr_recallconflict, "NFS4ERR_RECALLCONFLICT"}, {nfserr_unknown_layouttype, "NFS4ERR_UNKNOWN_LAYOUTTYPE"}, {nfserr_seq_misordered, "NFS4ERR_SEQ_MISORDERED"}, {nfserr_sequence_pos, "NFS4ERR_SEQUENCE_POS"}, {nfserr_req_too_big, "NFS4ERR_REQ_TOO_BIG"}, {nfserr_rep_too_big, "NFS4ERR_REP_TOO_BIG"}, {nfserr_rep_too_big_to_cache, "NFS4ERR_REP_TOO_BIG_TO_CACHE"}, {nfserr_retry_uncached_rep, "NFS4ERR_RETRY_UNCACHED_REP"}, {nfserr_unsafe_compound, "NFS4ERR_UNSAFE_COMPOUND"}, {nfserr_too_many_ops, "NFS4ERR_TOO_MANY_OPS"}, {nfserr_op_not_in_session, "NFS4ERR_OP_NOT_IN_SESSION"}, {nfserr_hash_alg_unsupp, "NFS4ERR_HASH_ALG_UNSUPP"}, {nfserr_clientid_busy, "NFS4ERR_CLIENTID_BUSY"}, {nfserr_pnfs_io_hole, "NFS4ERR_PNFS_IO_HOLE"}, {nfserr_seq_false_retry, "NFS4ERR_SEQ_FALSE_RETRY"}, {nfserr_bad_high_slot, "NFS4ERR_BAD_HIGH_SLOT"}, {nfserr_deadsession, "NFS4ERR_DEADSESSION"}, {nfserr_encr_alg_unsupp, "NFS4ERR_ENCR_ALG_UNSUPP"}, {nfserr_pnfs_no_layout, "NFS4ERR_PNFS_NO_LAYOUT"}, {nfserr_not_only_op, "NFS4ERR_NOT_ONLY_OP"}, {nfserr_wrong_cred, "NFS4ERR_WRONG_CRED"}, {nfserr_wrong_type, "NFS4ERR_WRONG_TYPE"}, {nfserr_dirdeleg_unavail, "NFS4ERR_DIRDELEG_UNAVAIL"}, {nfserr_reject_deleg, "NFS4ERR_REJECT_DELEG"}, {nfserr_returnconflict, "NFS4ERR_RETURNCONFLICT"}, {nfserr_deleg_revoked, "NFS4ERR_DELEG_REVOKED"}, #endif }; int i; int tabsz = (sizeof(nfs_errtbl)/sizeof(nfs_errtbl[0])); for (i = 0; i < tabsz; i++) { if (nfs_errtbl[i].nfserr == STAP_ARG_err) { break; } } if (i == tabsz) snprintf(STAP_RETVALUE, MAXSTRINGLEN, "nfsderr %d", ntohl(STAP_ARG_err)); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "nfsderr %d(%s)", ntohl(nfs_errtbl[i].nfserr), nfs_errtbl[i].string); %} systemtap-2.3/tapset/linux/panic.stp000066400000000000000000000020541217430427200176730ustar00rootroot00000000000000// Copyright (C) 2012 Red Hat Inc., Bryn M. Reeves // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // // Functions in the panic tapset allow a probe handler to invoke // the system panic routine with a user-specified message. // // This may be used with a crash dump collection facility such as // kexec/kdump in order to capture data for post-mortem debugging. // // Due to the fact that this will bring the system to an immediate // halt the functions in this tapset require guru mode. // /** * sfunction panic - trigger a panic * @msg: message to pass to kernel's panic() function * * Description: This function triggers an immediate panic of the running * kernel with a user-specified panic message. * It requires guru mode. */ function panic(msg:string) %{ /* guru */ panic("%s", STAP_ARG_msg); %} systemtap-2.3/tapset/linux/perf.stp000066400000000000000000000110011217430427200175250ustar00rootroot00000000000000// pcl aka perf aka perf-events tapset // Copyright (C) 2010 Red Hat Inc. // // This file is free software. You can redistribute it and/or modify it under // the terms of the GNU General Public License (GPL), version 2. // The type and config values are part of the sys_perf_event_open() ABI, // 'perf_event_attr' struct. See . // PERF_TYPE_HW probe perf.hw.cpu_cycles = perf.type(0).config(0) { } probe perf.hw.instructions = perf.type(0).config(1) { } probe perf.hw.cache_references = perf.type(0).config(2) { } probe perf.hw.cache_misses = perf.type(0).config(3) { } probe perf.hw.branch_instructions = perf.type(0).config(4) { } probe perf.hw.branch_misses = perf.type(0).config(5) { } probe perf.hw.bus_cycles = perf.type(0).config(6) { } // PERF_TYPE_SOFTWARE probe perf.sw.cpu_clock = perf.type(1).config(0) { } probe perf.sw.task_clock = perf.type(1).config(1) { } probe perf.sw.page_faults = perf.type(1).config(2) { } probe perf.sw.context_switches = perf.type(1).config(3) { } probe perf.sw.cpu_migrations = perf.type(1).config(4) { } probe perf.sw.page_faults_min = perf.type(1).config(5) { } probe perf.sw.page_faults_maj = perf.type(1).config(6) { } probe perf.sw.alignment_faults = perf.type(1).config(7) { } probe perf.sw.emulation_faults = perf.type(1).config(8) { } // PERF_TYPE_TRACEPOINT: PR10745 // probe perf.tracepoint.FOO = perf.type(2).config(NNN) { } // PERF_TYPE_HW_CACHE, encoded into config (cache_op_result_id<<16 | cache_op_id<<8 | cache_id) probe perf.hw_cache.l1d.read.access = perf.type(3).config(0x000000) {} probe perf.hw_cache.l1d.read.miss = perf.type(3).config(0x010000) {} probe perf.hw_cache.l1d.write.access = perf.type(3).config(0x000100) {} probe perf.hw_cache.l1d.write.miss = perf.type(3).config(0x010100) {} probe perf.hw_cache.l1d.prefetch.access = perf.type(3).config(0x000200) {} probe perf.hw_cache.l1d.prefetch.miss = perf.type(3).config(0x010200) {} // according to kernel tools/perf/util/parse-events.c, WRITE not available probe perf.hw_cache.l1i.read.access = perf.type(3).config(0x000001) {} probe perf.hw_cache.l1i.read.miss = perf.type(3).config(0x010001) {} //probe perf.hw_cache.l1i.write.access = perf.type(3).config(0x000101) {} //probe perf.hw_cache.l1i.write.miss = perf.type(3).config(0x010101) {} probe perf.hw_cache.l1i.prefetch.access = perf.type(3).config(0x000201) {} probe perf.hw_cache.l1i.prefetch.miss = perf.type(3).config(0x010201) {} probe perf.hw_cache.ll.read.access = perf.type(3).config(0x000002) {} probe perf.hw_cache.ll.read.miss = perf.type(3).config(0x010002) {} probe perf.hw_cache.ll.write.access = perf.type(3).config(0x000102) {} probe perf.hw_cache.ll.write.miss = perf.type(3).config(0x010102) {} probe perf.hw_cache.ll.prefetch.access = perf.type(3).config(0x000202) {} probe perf.hw_cache.ll.prefetch.miss = perf.type(3).config(0x010202) {} probe perf.hw_cache.dtlb.read.access = perf.type(3).config(0x000003) {} probe perf.hw_cache.dtlb.read.miss = perf.type(3).config(0x010003) {} probe perf.hw_cache.dtlb.write.access = perf.type(3).config(0x000103) {} probe perf.hw_cache.dtlb.write.miss = perf.type(3).config(0x010103) {} probe perf.hw_cache.dtlb.prefetch.access = perf.type(3).config(0x000203) {} probe perf.hw_cache.dtlb.prefetch.miss = perf.type(3).config(0x010203) {} // according to kernel tools/perf/util/parse-events.c, WRITE, PREFETCH not available probe perf.hw_cache.itlb.read.access = perf.type(3).config(0x000004) {} probe perf.hw_cache.itlb.read.miss = perf.type(3).config(0x010004) {} //probe perf.hw_cache.itlb.write.access = perf.type(3).config(0x000104) {} //probe perf.hw_cache.itlb.write.miss = perf.type(3).config(0x010104) {} //probe perf.hw_cache.itlb.prefetch.access = perf.type(3).config(0x000204) {} //probe perf.hw_cache.itlb.prefetch.miss = perf.type(3).config(0x010204) {} // according to kernel tools/perf/util/parse-events.c, WRITE, PREFETCH not available probe perf.hw_cache.bpu.read.access = perf.type(3).config(0x000005) {} probe perf.hw_cache.bpu.read.miss = perf.type(3).config(0x010005) {} //probe perf.hw_cache.bpu.write.access = perf.type(3).config(0x000105) {} //probe perf.hw_cache.bpu.write.miss = perf.type(3).config(0x010105) {} //probe perf.hw_cache.bpu.prefetch.access = perf.type(3).config(0x000205) {} //probe perf.hw_cache.bpu.prefetch.miss = perf.type(3).config(0x010205) {} systemtap-2.3/tapset/linux/powerpc/000077500000000000000000000000001217430427200175275ustar00rootroot00000000000000systemtap-2.3/tapset/linux/powerpc/aux_syscalls.stp000066400000000000000000000126761217430427200230050ustar00rootroot00000000000000# arch-specific requests of ptrace ___________________________ # %{ #ifndef PPC_PTRACE_GETHWDBGINFO # define PPC_PTRACE_GETHWDBGINFO 0x89 #endif #ifndef PPC_PTRACE_SETHWDEBUG # define PPC_PTRACE_SETHWDEBUG 0x88 #endif #ifndef PPC_PTRACE_DELHWDEBUG # define PPC_PTRACE_DELHWDEBUG 0x87 #endif #ifndef PTRACE_GETVSRREGS # define PTRACE_GETVSRREGS 27 #endif #ifndef PTRACE_SETVSRREGS # define PTRACE_SETVSRREGS 28 #endif #ifndef PTRACE_GETREGS # define PTRACE_GETREGS 12 #endif #ifndef PTRACE_SETREGS # define PTRACE_SETREGS 13 #endif #ifndef PTRACE_GETFPREGS # define PTRACE_GETFPREGS 14 #endif #ifndef PTRACE_SETFPREGS # define PTRACE_SETFPREGS 15 #endif #ifndef PTRACE_GETEVRREGS # define PTRACE_GETEVRREGS 20 #endif #ifndef PTRACE_SETEVRREGS # define PTRACE_SETEVRREGS 21 #endif #ifndef PTRACE_GETREGS64 # define PTRACE_GETREGS64 22 #endif #ifndef PTRACE_SETREGS64 # define PTRACE_SETREGS64 23 #endif #ifndef PTRACE_GET_DEBUGREG # define PTRACE_GET_DEBUGREG 25 #endif #ifndef PTRACE_SET_DEBUGREG # define PTRACE_SET_DEBUGREG 26 #endif #ifndef PTRACE_SINGLEBLOCK # define PTRACE_SINGLEBLOCK 0x100 #endif /* (old) PTRACE requests with inverted arguments */ #ifndef PPC_PTRACE_GETREGS #define PPC_PTRACE_GETREGS 0x99 #endif #ifndef PPC_PTRACE_SETREGS #define PPC_PTRACE_SETREGS 0x98 #endif #ifndef PPC_PTRACE_GETFPREGS #define PPC_PTRACE_GETFPREGS 0x97 #endif #ifndef PPC_PTRACE_SETFPREGS #define PPC_PTRACE_SETFPREGS 0x96 #endif %} function _arch_ptrace_argstr(request, pid, addr, data) { if (request == %{ PTRACE_GETVRREGS %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GETVRREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_SETVRREGS %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SETVRREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_GETEVRREGS %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GETEVRREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_SETEVRREGS %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SETEVRREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_GETVSRREGS %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GETVSRREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_SETVSRREGS %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SETVSRREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_GET_DEBUGREG %}) // ADDR is now required by kernel to be 0. return sprintf ("PTRACE_GET_DEBUGREG, %d, (addr=%p), data=%p", pid, addr, data) if (request == %{ PTRACE_SET_DEBUGREG %}) // ADDR is now required by kernel to be 0. return sprintf ("PTRACE_SET_DEBUGREG, %d, (addr=%p), data=%p", pid, addr, data) if (request == %{ PTRACE_GETREGS %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GETREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_SETREGS %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SETREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_GETFPREGS %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GETFPREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_SETFPREGS %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SETFPREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_GETREGS64 %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GETREGS64, %d, data=%p", pid, data) if (request == %{ PTRACE_SETREGS64 %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SETREGS64, %d, data=%p", pid, data) if (request == %{ PPC_PTRACE_GETREGS %}) // TODO: Retrieve *data in .return return sprintf ("PPC_PTRACE_GETREGS, %d, data=%p", pid, data) if (request == %{ PPC_PTRACE_SETREGS %}) // TODO: Retrieve *data here return sprintf ("PPC_PTRACE_SETREGS, %d, data=%p", pid, data) if (request == %{ PPC_PTRACE_GETFPREGS %}) // TODO: Retrieve *data in .return return sprintf ("PPC_PTRACE_GETFPREGS, %d, data=%p", pid, data) if (request == %{ PPC_PTRACE_SETFPREGS %}) // TODO: Retrieve *data here return sprintf ("PPC_PTRACE_SETFPREGS, %d, data=%p", pid, data) if (request == %{ PPC_PTRACE_PEEKTEXT_3264 %}) // TODO: Retrieve *data in .return return sprintf ("PPC_PTRACE_PEEKTEXT_3264, %d, *addr=%p, data=%p", pid, user_long(addr), data) if (request == %{ PPC_PTRACE_PEEKDATA_3264 %}) // TODO: Retrieve *data in .return return sprintf ("PPC_PTRACE_PEEKDATA_3264, %d, *addr=%p, data=%p", pid, user_long(addr), data) if (request == %{ PPC_PTRACE_POKETEXT_3264 %}) return sprintf ("PPC_PTRACE_POKETEXT_3264, %d, *addr=%p, data=%p", pid, user_long(addr), data) if (request == %{ PPC_PTRACE_POKEDATA_3264 %}) return sprintf ("PPC_PTRACE_POKEDATA_3264, %d, *addr=%p, data=%p", pid, user_long(addr), data) if (request == %{ PPC_PTRACE_PEEKUSR_3264 %}) return sprintf ("PPC_PTRACE_PEEKUSR_3264, %d, addr=%p, data=%p", pid, addr, data) if (request == %{ PPC_PTRACE_POKEUSR_3264 %}) return sprintf ("PPC_PTRACE_POKEUSR_3264, %d, addr=%p, data=%p", pid, addr, data) if (request == %{ PTRACE_SINGLEBLOCK %}) return sprintf ("PTRACE_SINGLEBLOCK, %d, %s", pid, _signal_name (data)) if (request == %{ PPC_PTRACE_GETHWDBGINFO %}) // TODO: Retrieve *data in .return return sprintf ("PPC_PTRACE_GETHWDBGINFO, %d, data=%p", pid, data) if (request == %{ PPC_PTRACE_SETHWDEBUG %}) // TODO: Retrieve *data here return sprintf ("PPC_PTRACE_SETHWDEBUG, %d, data=%p", pid, data) if (request == %{ PPC_PTRACE_DELHWDEBUG %}) return sprintf ("PPC_PTRACE_DELHWDEBUG, %d, data=%d", pid, data) } function _ptrace_return_arch_prctl_addr:long(request:long, addr:long, data:long) { return 0 } systemtap-2.3/tapset/linux/powerpc/nd_syscalls.stp000066400000000000000000000514501217430427200226020ustar00rootroot00000000000000# PPC64-specific system calls # sys64_time ________________________________________ # # time_t sys64_time(time_t __user * tloc) # probe nd_syscall.sys64_time = kprobe.function("sys64_time") ? { name = "sys64_time" // argstr = sprintf("%p", $tloc) asmlinkage() argstr = sprintf("%p", pointer_arg(1)) } probe nd_syscall.sys64_time.return = kprobe.function("sys64_time").return ? { name = "sys64_time" retstr = returnstr(1) } # ppc64_personality ________________________________________ # # long ppc64_personality(unsigned long personality) # probe nd_syscall.ppc64_personality = kprobe.function("ppc64_personality") { name = "ppc64_personality" // persona = $personality // argstr = sprint($personality) asmlinkage() persona = ulong_arg(1) argstr = sprint(persona) } probe nd_syscall.ppc64_personality.return = kprobe.function("ppc64_personality").return { name = "ppc64_personality" retstr = returnstr(1) } # ppc_rtas ________________________________________ # # int ppc_rtas(struct rtas_args __user *uargs) # probe nd_syscall.ppc_rtas = kprobe.function("ppc_rtas") ? { name = "ppc_rtas" // uargs_uaddr = $uargs // argstr = sprintf("%p", $uargs) asmlinkage() uargs_uaddr = pointer_arg(1) argstr = sprintf("%p", uargs_uaddr) } probe nd_syscall.ppc_rtas.return = kprobe.function("ppc_rtas").return ? { name = "ppc_rtas" retstr = returnstr(1) } # ppc64_sys32_stime ________________________________________ # # long ppc64_sys32_stime(int __user * tptr) # probe nd_syscall.ppc64_sys32_stime = kprobe.function("ppc64_sys32_stime") ? { name = "ppc64_sys32_stime" // t_uaddr = $tptr // argstr = sprintf("%p", $tptr) asmlinkage() t_uaddr = pointer_arg(1) argstr = sprintf("%p", t_uaddr) } probe nd_syscall.ppc64_sys32_stime.return = kprobe.function("ppc64_sys32_stime").return ? { name = "ppc64_sys32_stime" retstr = returnstr(1) } # sys32_ptrace ________________________________________ # (obsolete) # int sys32_ptrace(long request, long pid, unsigned long addr, # unsigned long data) # probe nd_syscall.sys32_ptrace = kprobe.function("sys32_ptrace") ? { name = "sys32_ptrace" // request = $request // pid = $pid // addr = $addr // data = $data // argstr = sprintf("%p, %p, %p, %p", $request, $pid, $addr, $data) asmlinkage() request = long_arg(1) pid = long_arg(2) addr = ulong_arg(3) data = ulong_arg(4) argstr = sprintf("%p, %p, %p, %p", request, pid, addr, data) } probe nd_syscall.sys32_ptrace.return = kprobe.function("sys32_ptrace").return ? { name = "sys32_ptrace" retstr = returnstr(1) } # sys32_sysinfo ________________________________________ # # (obsolete) long sys32_sysinfo(struct sysinfo32 __user *info) # probe nd_syscall.sys32_sysinfo = kprobe.function("sys32_sysinfo") ? { name = "sys32_sysinfo" // info_uaddr = $info asmlinkage() info_uaddr = pointer_arg(1) argstr = sprintf("%p", info_uaddr) } probe nd_syscall.sys32_sysinfo.return = kprobe.function("sys32_sysinfo").return ? { name = "sys32_sysinfo" retstr = returnstr(1) } # ipc ________________________________________ # # long sys32_ipc(u32 call, u32 first, u32 second, u32 third, # compat_uptr_t ptr, u32 fifth) # probe nd_syscall.ipc = kprobe.function("sys32_ipc") ? { name = "ipc" // argstr = sprintf("%d, %d, %d, %d, %p, %d", $call, $first, $second, // $third, $ptr, $fifth) asmlinkage() argstr = sprintf("%d, %d, %d, %d, %p, %d", uint_arg(1), uint_arg(2), uint_arg(3), uint_arg(4), uint_arg(5), uint_arg(6)) } probe nd_syscall.ipc.return = kprobe.function("sys32_ipc").return ? { name = "sys_ipc" retstr = returnstr(1) } # sys32_sigreturn ________________________________________ # # long sys32_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, # struct pt_regs *regs) # probe nd_syscall.sys32_sigreturn = kprobe.function("sys32_sigreturn") ? { name = "sys32_sigreturn" // r3 = $r3 // r4 = $r4 // // r5 = $r5 // r6 = $r6 // r7 = $r7 // r8 = $r8 // argstr = sprintf("%p, %p, %p, %p, %p, %p", // $r3, $r4, $r5, $r6, $r7, $r8) asmlinkage() r3 = int_arg(1) r4 = int_arg(2) r5 = int_arg(3) r6 = int_arg(4) r7 = int_arg(5) r8 = int_arg(6) argstr = sprintf("%p, %p, %p, %p, %p, %p", r3, r4, r5, r6, r7, r8) } probe nd_syscall.sys32_sigreturn.return = kprobe.function("sys32_sigreturn").return ? { name = "sys32_sigreturn" retstr = returnstr(1) } # sys32_adjtimex ________________________________________ # # long sys32_adjtimex(struct timex32 __user *utp) # probe nd_syscall.sys32_adjtimex = kprobe.function("sys32_adjtimex") ? { name = "sys32_adjtimex" // argstr = sprintf("%p", $utp) asmlinkage() argstr = sprintf("%p", pointer_arg(1)) } probe nd_syscall.sys32_adjtimex.return = kprobe.function("sys32_adjtimex").return ? { name = "sys32_adjtimex" retstr = returnstr(1) } # sys32_getdents ________________________________________ # # asmlinkage long sys32_getdents(unsigned int fd, # struct linux_dirent32 __user *dirent, # unsigned int count) # probe nd_syscall.sys32_getdents = kprobe.function("sys32_getdents") ? { name = "sys32_getdents" // fd = $fd // dirp_uaddr = $dirent // count = $count asmlinkage() fd = uint_arg(1) dirp_uaddr = pointer_arg(2) count = uint_arg(3) argstr = sprintf("%d, %p, %d", fd, dirp_uaddr, count) } probe nd_syscall.sys32_getdents.return = kprobe.function("sys32_getdents").return ? { name = "sys32_getdents" retstr = returnstr(1) } # compat_sys_sysctl ________________________________________ # # long compat_sys_sysctl(struct __sysctl_args32 __user *args) # probe nd_syscall.compat_sysctl = kprobe.function("compat_sys_sysctl") ? { name = "sysctl" // argstr = sprintf("%p", $args) asmlinkage() argstr = sprintf("%p", pointer_arg(1)) } probe nd_syscall.compat_sysctl.return = kprobe.function("compat_sys_sysctl").return ? { name = "sysctl" retstr = returnstr(1) } # sys32_sched_setparam ________________________________________ # # asmlinkage long sys32_sched_setparam(u32 pid, # struct sched_param __user *param) # probe nd_syscall.sys32_sched_setparam = kprobe.function("sys32_sched_setparam") ? { name = "sys32_sched_setparam" // pid = $pid // param_uaddr = $param asmlinkage() pid = uint_arg(1) param_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", pid, param_uaddr) } probe nd_syscall.sys32_sched_setparam.return = kprobe.function("sys32_sched_setparam").return ? { name = "sys32_sched_setparam" retstr = returnstr(1) } # sys32_sched_rr_get_interval ________________________________________ # # asmlinkage long sys32_sched_rr_get_interval(u32 pid, # struct compat_timespec __user *interval) # probe nd_syscall.sys32_sched_rr_get_interval = kprobe.function("sys32_sched_rr_get_interval") ? { name = "sys32_sched_rr_get_interval" // pid = $pid // interval_uaddr = $interval asmlinkage() pid = uint_arg(1) interval_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", pid, interval_uaddr) } probe nd_syscall.sys32_sched_rr_get_interval.return = kprobe.function("sys32_sched_rr_get_interval").return ? { name = "sys32_sched_rr_get_interval" retstr = returnstr(1) } # sys32_rt_sigpending ________________________________________ # # long sys32_rt_sigpending(compat_sigset_t __user *set, # compat_size_t sigsetsize) # probe nd_syscall.sys32_rt_sigpending = kprobe.function("sys32_rt_sigpending") ? { name = "sys32_rt_sigpending" // set_uaddr = $set // sigsetsize = $sigsetsize // argstr = sprintf("%p, %d", set_uaddr, $sigsetsize) asmlinkage() set_uaddr = pointer_arg(1) sigsetsize = uint_arg(2) argstr = sprintf("%p, %d", set_uaddr, sigsetsize) } probe nd_syscall.sys32_rt_sigpending.return = kprobe.function("sys32_rt_sigpending").return ? { name = "sys32_rt_sigpending" retstr = returnstr(1) } # sys32_rt_sigtimedwait ________________________________________ # # long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese, # compat_siginfo_t __user *uinfo, # struct compat_timespec __user *uts, # compat_size_t sigsetsize) # probe nd_syscall.sys32_rt_sigtimedwait = kprobe.function("sys32_rt_sigtimedwait") ? { name = "sys32_rt_sigtimedwait" // uthese_uaddr = $uthese // uinfo_uaddr = $uinfo // uts_uaddr = $uts // sigsetsize = $sigsetsize asmlinkage() uthese_uaddr = pointer_arg(1) uinfo_uaddr = pointer_arg(2) uts_uaddr = pointer_arg(3) sigsetsize = uint_arg(4) argstr = sprintf("%p, %p, %p, %p", uthese_uaddr, uinfo_uaddr, uts_uaddr, sigsetsize) } probe nd_syscall.sys32_rt_sigtimedwait.return = kprobe.function("sys32_rt_sigtimedwait").return ? { name = "sys32_rt_sigtimedwait" retstr = returnstr(1) } # sys32_rt_sigqueueinfo ________________________________________ # # long sys32_rt_sigqueueinfo(u32 pid, u32 sig, compat_siginfo_t __user *uinfo) # probe nd_syscall.sys32_rt_sigqueueinfo = kprobe.function("sys32_rt_sigqueueinfo") ? { name = "sys32_rt_sigqueueinfo" // pid = $pid // sig = $sig // uinfo_uaddr = $uinfo // argstr = sprintf("%p, %s, %p", pid, _signal_name($sig), // uinfo_uaddr) asmlinkage() pid = uint_arg(1) sig = uint_arg(2) uinfo_uaddr = pointer_arg(3) argstr = sprintf("%p, %s, %p", pid, _signal_name(sig), uinfo_uaddr) } probe nd_syscall.sys32_rt_sigqueueinfo.return = kprobe.function("sys32_rt_sigqueueinfo").return ? { name = "sys32_rt_sigqueueinfo" retstr = returnstr(1) } %( CONFIG_GENERIC_SIGALTSTACK == "n" || kernel_v < "3.8" %? # sigaltstack ________________________________________________ # long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, # unsigned long r5, unsigned long r6, # unsigned long r7, unsigned long r8, # struct pt_regs *regs) # # NOTE: args vary between archs. # probe nd_syscall.sigaltstack = kprobe.function("sys_sigaltstack") { name = "sigaltstack" // uss_uaddr = $uss // uoss_uaddr = $uoss // regs = $regs // argstr = sprintf("%p, %p", $uss, $uoss) asmlinkage() uss_uaddr = pointer_arg(1) uoss_uaddr = pointer_arg(2) %(systemtap_v < "2.3" %? regs = pointer_arg(7) %) argstr = sprintf("%p, %p", uss_uaddr, uoss_uaddr) } probe nd_syscall.sigaltstack.return = kprobe.function("sys_sigaltstack").return { name = "sigaltstack" retstr = returnstr(1) } %) # sys32_sigaltstack ________________________________________ # # int sys32_sigaltstack(u32 __new, u32 __old, int r5, # int r6, int r7, int r8, struct pt_regs *regs) # probe nd_syscall.sys32_sigaltstack = kprobe.function("sys32_sigaltstack") ? { name = "sys32_sigaltstack" argstr = "" } probe nd_syscall.sys32_sigaltstack.return = kprobe.function("sys32_sigaltstack").return ? { name = "sys32_sigaltstack" retstr = returnstr(1) } # sys32_sendfile64 ________________________________________ # # asmlinkage int sys32_sendfile64(int out_fd, int in_fd, # compat_loff_t __user *offset, s32 count) # probe nd_syscall.sys32_sendfile64 = kprobe.function("sys32_sendfile64") ? { name = "sys32_sendfile64" // out_fd = $out_fd // in_fd = $in_fd // offset_uaddr = $offset // count = $count // argstr = sprintf("%d, %d, %p, %d", $out_fd, $in_fd, offset_uaddr, // $count) asmlinkage() out_fd = int_arg(1) in_fd = int_arg(2) offset_uaddr = long_arg(3) count = int_arg(4) argstr = sprintf("%d, %d, %p, %d", out_fd, in_fd, offset_uaddr, count) } probe nd_syscall.sys32_sendfile64.return = kprobe.function("sys32_sendfile64").return ? { name = "sys32_sendfile64" retstr = returnstr(1) } # ppc32_timer_create ________________________________________ # # long ppc32_timer_create(clockid_t clock, # struct compat_sigevent __user *ev32, # timer_t __user *timer_id) # probe nd_syscall.ppc32_timer_create = kprobe.function("ppc32_timer_create") ? { name = "ppc32_timer_create" // which_clock = $clock // timer_event_spec = $ev32 // created_timer_id = $timer_id asmlinkage() which_clock = int_arg(1) timer_event_spec = pointer_arg(2) created_timer_id = pointer_arg(3) argstr = sprintf("%d, %p, %p", which_clock, timer_event_spec, created_timer_id) } probe nd_syscall.ppc32_timer_create.return = kprobe.function("ppc32_timer_create").return ? { name = "ppc32_timer_create" retstr = returnstr(1) } # compat_timer_settime ________________________________________ # # long compat_timer_settime(timer_t timer_id, int flags, # struct compat_itimerspec __user *new, # struct compat_itimerspec __user *old) # probe nd_syscall.compat_timer_settime = kprobe.function("compat_timer_settime") ? { name = "compat_timer_settime" // timer_id = $timer_id // flags = $flags // new_setting_uaddr = $new // old_setting_uaddr = $old asmlinkage() timer_id = int_arg(1) flags = int_arg(2) new_setting_uaddr = pointer_arg(3) old_setting_uaddr = pointer_arg(4) argstr = sprintf("%d, %d, %p, %p", timer_id, flags, new_setting_uaddr, old_setting_uaddr) } probe nd_syscall.compat_timer_settime.return = kprobe.function("compat_timer_settime").return ? { name = "compat_timer_settime" retstr = returnstr(1) } # compat_timer_gettime ________________________________________ # # long compat_timer_gettime(timer_t timer_id, # struct compat_itimerspec __user *setting) # probe nd_syscall.compat_timer_gettime = kprobe.function("compat_timer_gettime") ? { name = "compat_timer_gettime" // timer_id = $timer_id // setting_uaddr = $setting asmlinkage() timer_id = int_arg(1) setting_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", timer_id, setting_uaddr) } probe nd_syscall.compat_timer_gettime.return = kprobe.function("compat_timer_gettime").return ? { name = "compat_timer_gettime" retstr = returnstr(1) } # compat_clock_settime ________________________________________ # # long compat_clock_settime(clockid_t which_clock, # struct compat_timespec __user *tp) # probe nd_syscall.compat_clock_settime = kprobe.function("compat_clock_settime") ? { name = "compat_clock_settime" // which_clock = $which_clock // tp_uaddr = $tp asmlinkage() which_clock = int_arg(1) tp_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", which_clock, tp_uaddr) } probe nd_syscall.compat_clock_settime.return = kprobe.function("compat_clock_settime").return ? { name = "compat_clock_settime" retstr = returnstr(1) } # sys32_swapcontext ________________________________________ # # long sys32_swapcontext(struct ucontext32 __user *old_ctx, # struct ucontext32 __user *new_ctx, # int ctx_size, int r6, int r7, int r8, # struct pt_regs *regs) # probe nd_syscall.sys32_swapcontext = kprobe.function("sys32_swapcontext") ? { name = "sys32_swapcontext" // old_ctx_uaddr = $old_ctx // new_ctx_uaddr = $new_ctx // r5 = $ctx_size // r6 = $r6 // r7 = $r7 // r8 = $r8 // regs = $regs asmlinkage() old_ctx_uaddr = pointer_arg(1) new_ctx_uaddr = pointer_arg(2) r5 = int_arg(3) r6 = int_arg(4) r7 = int_arg(5) r8 = int_arg(6) regs = pointer_arg(7) argstr = sprintf("%p, %p, %d, %d, %d, %d, %p", old_ctx_uaddr, new_ctx_uaddr, r5, r6, r7, r8, regs) } probe nd_syscall.sys32_swapcontext.return = kprobe.function("sys32_swapcontext").return ? { name = "sys32_swapcontext" retstr = returnstr(1) } # sys32_utimes ________________________________________ # # asmlinkage long sys32_utimes(char __user *filename, # struct compat_timeval __user *tvs) # probe nd_syscall.sys32_utimes = kprobe.function("sys32_utimes") ? { name = "sys32_utimes" // filename_uaddr = $filename // path = user_string($filename) // tvp_uaddr = $tvs // argstr = sprintf("%s, %p", user_string_quoted($filename), tvp_uaddr) asmlinkage() filename_uaddr = pointer_arg(1) path = user_string_quoted(filename_uaddr) tvp_uaddr = pointer_arg(2) argstr = sprintf("%s, %p", user_string_quoted(filename_uaddr), tvp_uaddr) } probe nd_syscall.sys32_utimes.return = kprobe.function("sys32_utimes").return ? { name = "sys32_utimes" retstr = returnstr(1) } # compat_mbind ________________________________________ # # asmlinkage long compat_mbind(compat_ulong_t start, compat_ulong_t len, # compat_ulong_t mode, compat_ulong_t __user *nmask, # compat_ulong_t maxnode, compat_ulong_t flags) # probe nd_syscall.compat_mbind = kprobe.function("compat_mbind") ? { name = "compat_mbind" // start_uaddr = $start // len = $len // policy = $mode // nodemask_uaddr = $nmask // maxnode = $maxnode // flags = $flags asmlinkage() start_uaddr = uint_arg(1) len = uint_arg(2) policy = uint_arg(3) nodemask_uaddr = uint_arg(4) maxnode = uint_arg(5) flags = uint_arg(6) argstr = sprintf("%p, %d, %d, %p, %d, %d", start_uaddr, len, policy, nodemask_uaddr, maxnode, flags) } probe nd_syscall.compat_mbind.return = kprobe.function("compat_mbind").return ? { name = "compat_mbind" retstr = returnstr(1) } # compat_get_mempolicy ________________________________________ # # asmlinkage long compat_get_mempolicy(int __user *policy, # compat_ulong_t __user *nmask, # compat_ulong_t maxnode, # compat_ulong_t addr, compat_ulong_t flags) # probe nd_syscall.compat_get_mempolicy = kprobe.function("compat_get_mempolicy") ? { name = "compat_get_mempolicy" // policy_uaddr = $policy // nmask_uaddr = $nmask // maxnode = $maxnode // addr = $addr // flags = $flags asmlinkage() policy_uaddr = int_arg(1) nmask_uaddr = uint_arg(2) maxnode = uint_arg(3) addr = uint_arg(4) flags = uint_arg(5) argstr = sprintf("%p, %p, %d, %d", policy_uaddr, nmask_uaddr, maxnode, addr) } probe nd_syscall.compat_get_mempolicy.return = kprobe.function("compat_get_mempolicy").return ? { name = "compat_get_mempolicy" retstr = returnstr(1) } # compat_set_mempolicy ________________________________________ # # asmlinkage long compat_set_mempolicy(int mode, compat_ulong_t __user *nmask, # compat_ulong_t maxnode) # probe nd_syscall.compat_set_mempolicy = kprobe.function("compat_set_mempolicy") ? { name = "compat_set_mempolicy" // policy = $mode // nodemask_uaddr = $nmask // maxnode = $maxnode asmlinkage() policy = int_arg(1) nodemask_uaddr = uint_arg(2) maxnode = uint_arg(3) argstr = sprintf("%d, %p, %d", policy, nodemask_uaddr, maxnode) } probe nd_syscall.compat_set_mempolicy.return = kprobe.function("compat_set_mempolicy").return ? { name = "compat_set_mempolicy" retstr = returnstr(1) } # In kernels < 2.6.33, mmap()/mmap2() was handled by arch-specific # code. In kernels >= 2.6.33, the arch-specific code just calls # generic sys_mmap_pgoff(). %( kernel_v < "2.6.33" %? # mmap # long sys_mmap(unsigned long addr, size_t len, # unsigned long prot, unsigned long flags, # unsigned long fd, off_t offset) # probe nd_syscall.mmap = kprobe.function("sys_mmap") ? { name = "mmap" // start = $addr // len = $len // prot = $prot // flags = $flags // fd = __int32($fd) // offset = $offset // argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len, // _mprotect_prot_str($prot), _mmap_flags($flags), // __int32($fd), $offset) asmlinkage() start = ulong_arg(1) len = ulong_arg(2) prot = ulong_arg(3) flags = ulong_arg(4) # Although the kernel gets an unsigned long fd, on the # user-side it is a signed int. Fix this. fd = int_arg(5) offset = ulong_arg(6) argstr = sprintf("%p, %d, %s, %s, %d, %d", start, len, _mprotect_prot_str(prot), _mmap_flags(flags), fd, offset) } probe nd_syscall.mmap.return = kprobe.function("sys_mmap").return ? { name = "mmap" retstr = returnstr(2) } # mmap2 # long sys_mmap2(unsigned long addr, size_t len, # unsigned long prot, unsigned long flags, # unsigned long fd, unsigned long pgoff) # long compat_sys_mmap2(unsigned long addr, size_t len, # unsigned long prot, unsigned long flags, # unsigned long fd, unsigned long pgoff) # probe nd_syscall.mmap2 = kprobe.function("sys_mmap2") ?, kprobe.function("compat_sys_mmap2") ? { name = "mmap2" // start = $addr // length = $len // prot = $prot // flags = $flags // fd = __int32($fd) // pgoffset = $pgoff // argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, // $len, _mprotect_prot_str($prot), _mmap_flags($flags), // $fd, $pgoff) asmlinkage() start = ulong_arg(1) length = ulong_arg(2) prot = ulong_arg(3) flags = ulong_arg(4) # Although the kernel gets an unsigned long fd, on the # user-side it is a signed int. Fix this. fd = int_arg(5) pgoffset = ulong_arg(6) argstr = sprintf("%p, %d, %s, %s, %d, %d", start, length, _mprotect_prot_str(prot), _mmap_flags(flags), fd, pgoffset) } probe nd_syscall.mmap2.return = kprobe.function("sys_mmap2").return ?, kprobe.function("compat_sys_mmap2").return ? { name = "mmap2" retstr = returnstr(2) } %) # ppc64_sys_stime ________________________________________ # # long ppc64_sys_stime(long __user * tptr) # probe nd_syscall.ppc64_sys_stime = kprobe.function("ppc64_sys_stime") ? { name = "ppc64_sys_stime" /* FIXME */ // t_uaddr = $tptr asmlinkage() t_uaddr = pointer_arg(1) argstr = sprintf("%p", t_uaddr) } probe nd_syscall.ppc64_sys_stime.return = kprobe.function("ppc64_sys_stime").return ? { name = "ppc64_sys_stime" retstr = returnstr(1) } # ppc64_newuname ________________________________________ # # asmlinkage int ppc64_newuname(struct new_utsname __user * name) # probe nd_syscall.ppc64_newuname = kprobe.function("ppc64_newuname") ? { name = "ppc64_newuname" // name_uaddr = $name asmlinkage() name_uaddr = pointer_arg(1) argstr = sprintf("%p", name_uaddr) } probe nd_syscall.ppc64_newuname.return = kprobe.function("ppc64_newuname").return ? { name = "ppc64_newuname" retstr = returnstr(1) } # # systemtap-2.3/tapset/linux/powerpc/syscalls.stp000066400000000000000000000434031217430427200221200ustar00rootroot00000000000000# PPC64-specific system calls # sys64_time ________________________________________ # # time_t sys64_time(time_t __user * tloc) # probe syscall.sys64_time = kernel.function("sys64_time") ? { name = "sys64_time" argstr = sprintf("%p", $tloc) } probe syscall.sys64_time.return = kernel.function("sys64_time").return ? { name = "sys64_time" retstr = return_str(1, $return) } # ppc64_personality ________________________________________ # # long ppc64_personality(unsigned long personality) # probe syscall.ppc64_personality = kernel.function("ppc64_personality") { name = "ppc64_personality" persona = $personality argstr = sprint($personality) } probe syscall.ppc64_personality.return = kernel.function("ppc64_personality").return { name = "ppc64_personality" retstr = return_str(1, $return) } # ppc_rtas ________________________________________ # # int ppc_rtas(struct rtas_args __user *uargs) # probe syscall.ppc_rtas = kernel.function("ppc_rtas") ? { name = "ppc_rtas" uargs_uaddr = $uargs argstr = sprintf("%p", $uargs) } probe syscall.ppc_rtas.return = kernel.function("ppc_rtas").return ? { name = "ppc_rtas" retstr = return_str(1, $return) } # ppc64_sys32_stime ________________________________________ # # long ppc64_sys32_stime(int __user * tptr) # probe syscall.ppc64_sys32_stime = kernel.function("ppc64_sys32_stime") ? { name = "ppc64_sys32_stime" t_uaddr = $tptr argstr = sprintf("%p", $tptr) } probe syscall.ppc64_sys32_stime.return = kernel.function("ppc64_sys32_stime").return ? { name = "ppc64_sys32_stime" retstr = return_str(1, $return) } # sys32_ptrace ________________________________________ # (obsolete) # int sys32_ptrace(long request, long pid, unsigned long addr, # unsigned long data) # probe syscall.sys32_ptrace = kernel.function("sys32_ptrace") ? { name = "sys32_ptrace" request = $request pid = $pid addr = $addr data = $data argstr = sprintf("%p, %p, %p, %p", $request, $pid, $addr, $data) } probe syscall.sys32_ptrace.return = kernel.function("sys32_ptrace").return ? { name = "sys32_ptrace" retstr = return_str(1, $return) } # sys32_sysinfo ________________________________________ # # (obsolete) long sys32_sysinfo(struct sysinfo32 __user *info) # probe syscall.sys32_sysinfo = kernel.function("sys32_sysinfo") ? { name = "sys32_sysinfo" info_uaddr = $info argstr = sprintf("%p", info_uaddr) } probe syscall.sys32_sysinfo.return = kernel.function("sys32_sysinfo").return ? { name = "sys32_sysinfo" retstr = return_str(1, $return) } # ipc ________________________________________ # # long sys32_ipc(u32 call, u32 first, u32 second, u32 third, # compat_uptr_t ptr, u32 fifth) # probe syscall.ipc = kernel.function("sys32_ipc") ? { name = "ipc" argstr = sprintf("%d, %d, %d, %d, %p, %d", $call, $first, $second, $third, $ptr, $fifth) } probe syscall.ipc.return = kernel.function("sys32_ipc").return ? { name = "sys_ipc" retstr = return_str(1, $return) } # sys32_sigreturn ________________________________________ # # long sys32_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, # struct pt_regs *regs) # probe syscall.sys32_sigreturn = kernel.function("sys32_sigreturn") ? { name = "sys32_sigreturn" r3 = $r3 r4 = $r4 r5 = $r5 r6 = $r6 r7 = $r7 r8 = $r8 argstr = sprintf("%p, %p, %p, %p, %p, %p", $r3, $r4, $r5, $r6, $r7, $r8) } probe syscall.sys32_sigreturn.return = kernel.function("sys32_sigreturn").return ? { name = "sys32_sigreturn" retstr = return_str(1, $return) } # sys32_adjtimex ________________________________________ # # long sys32_adjtimex(struct timex32 __user *utp) # probe syscall.sys32_adjtimex = kernel.function("sys32_adjtimex") ? { name = "sys32_adjtimex" argstr = sprintf("%p", $utp) } probe syscall.sys32_adjtimex.return = kernel.function("sys32_adjtimex").return ? { name = "sys32_adjtimex" retstr = return_str(1, $return) } # sys32_getdents ________________________________________ # # asmlinkage long sys32_getdents(unsigned int fd, # struct linux_dirent32 __user *dirent, # unsigned int count) # probe syscall.sys32_getdents = kernel.function("sys32_getdents") ? { name = "sys32_getdents" fd = $fd dirp_uaddr = $dirent count = $count argstr = sprintf("%d, %p, %d", fd, dirp_uaddr, count) } probe syscall.sys32_getdents.return = kernel.function("sys32_getdents").return ? { name = "sys32_getdents" retstr = return_str(1, $return) } # compat_sys_sysctl ________________________________________ # # long compat_sys_sysctl(struct __sysctl_args32 __user *args) # # To match the ia64/s390/x86_64 versions, the 'syscall.compat_sysctl' # probe name is deprecated and 'syscall.sysctl32' should be used # instead. To use the old name without changing your script, use # the '--compatible 1.4' stap option. probe %( systemtap_v <= "1.4" %? syscall.compat_sysctl %: syscall.sysctl32 %) = kernel.function("compat_sys_sysctl") ? { name = "sysctl" argstr = sprintf("%p", $args) } probe %( systemtap_v <= "1.4" %? syscall.compat_sysctl.return %: syscall.sysctl32.return %) = kernel.function("compat_sys_sysctl").return ? { name = "sysctl" retstr = return_str(1, $return) } # sys32_sched_setparam ________________________________________ # # asmlinkage long sys32_sched_setparam(u32 pid, # struct sched_param __user *param) # probe syscall.sys32_sched_setparam = kernel.function("sys32_sched_setparam") ? { name = "sys32_sched_setparam" pid = $pid param_uaddr = $param argstr = sprintf("%d, %p", pid, param_uaddr) } probe syscall.sys32_sched_setparam.return = kernel.function("sys32_sched_setparam").return ? { name = "sys32_sched_setparam" retstr = return_str(1, $return) } # sys32_sched_rr_get_interval ________________________________________ # # asmlinkage long sys32_sched_rr_get_interval(u32 pid, # struct compat_timespec __user *interval) # probe syscall.sys32_sched_rr_get_interval = kernel.function("sys32_sched_rr_get_interval") ? { name = "sys32_sched_rr_get_interval" pid = $pid interval_uaddr = $interval argstr = sprintf("%d, %p", pid, interval_uaddr) } probe syscall.sys32_sched_rr_get_interval.return = kernel.function("sys32_sched_rr_get_interval").return ? { name = "sys32_sched_rr_get_interval" retstr = return_str(1, $return) } # sys32_rt_sigpending ________________________________________ # # long sys32_rt_sigpending(compat_sigset_t __user *set, # compat_size_t sigsetsize) # probe syscall.sys32_rt_sigpending = kernel.function("sys32_rt_sigpending") ? { name = "sys32_rt_sigpending" set_uaddr = $set sigsetsize = $sigsetsize argstr = sprintf("%p, %d", set_uaddr, $sigsetsize) } probe syscall.sys32_rt_sigpending.return = kernel.function("sys32_rt_sigpending").return ? { name = "sys32_rt_sigpending" retstr = return_str(1, $return) } # sys32_rt_sigtimedwait ________________________________________ # # long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese, # compat_siginfo_t __user *uinfo, # struct compat_timespec __user *uts, # compat_size_t sigsetsize) # probe syscall.sys32_rt_sigtimedwait = kernel.function("sys32_rt_sigtimedwait") ? { name = "sys32_rt_sigtimedwait" uthese_uaddr = $uthese uinfo_uaddr = $uinfo uts_uaddr = $uts sigsetsize = $sigsetsize argstr = sprintf("%p, %p, %p, %p", uthese_uaddr, uinfo_uaddr, uts_uaddr, sigsetsize) } probe syscall.sys32_rt_sigtimedwait.return = kernel.function("sys32_rt_sigtimedwait").return ? { name = "sys32_rt_sigtimedwait" retstr = return_str(1, $return) } # sys32_rt_sigqueueinfo ________________________________________ # # long sys32_rt_sigqueueinfo(u32 pid, u32 sig, compat_siginfo_t __user *uinfo) # probe syscall.sys32_rt_sigqueueinfo = kernel.function("sys32_rt_sigqueueinfo") ? { name = "sys32_rt_sigqueueinfo" pid = $pid sig = $sig uinfo_uaddr = $uinfo argstr = sprintf("%p, %s, %p", pid, _signal_name($sig), uinfo_uaddr) } probe syscall.sys32_rt_sigqueueinfo.return = kernel.function("sys32_rt_sigqueueinfo").return ? { name = "sys32_rt_sigqueueinfo" retstr = return_str(1, $return) } %( CONFIG_GENERIC_SIGALTSTACK == "n" || kernel_v < "3.8" %? # sigaltstack ________________________________________________ # long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, # unsigned long r5, unsigned long r6, # unsigned long r7, unsigned long r8, # struct pt_regs *regs) # # NOTE: args vary between archs. # probe syscall.sigaltstack = kernel.function("sys_sigaltstack") { name = "sigaltstack" uss_uaddr = $uss uoss_uaddr = $uoss %(systemtap_v < "2.3" %? regs = $regs %) argstr = sprintf("%p, %p", $uss, $uoss) } probe syscall.sigaltstack.return = kernel.function("sys_sigaltstack").return { name = "sigaltstack" retstr = return_str(1, $return) } %) # sys32_sigaltstack ________________________________________ # # int compat_sys_sigaltstack(u32 __new, u32 __old, int r5, # int r6, int r7, int r8, struct pt_regs *regs) # int sys32_sigaltstack(u32 __new, u32 __old, int r5, # int r6, int r7, int r8, struct pt_regs *regs) # # Args are too different to match 'syscall.sigaltstack'. probe syscall.sys32_sigaltstack = kernel.function("compat_sys_sigaltstack") !, kernel.function("sys32_sigaltstack") ? { name = "sys32_sigaltstack" argstr = "" } probe syscall.sys32_sigaltstack.return = kernel.function("sys32_sigaltstack").return ? { name = "sys32_sigaltstack" retstr = return_str(1, $return) } # sys32_sendfile64 ________________________________________ # # asmlinkage int sys32_sendfile64(int out_fd, int in_fd, # compat_loff_t __user *offset, s32 count) # probe syscall.sys32_sendfile64 = kernel.function("sys32_sendfile64") ? { name = "sys32_sendfile64" out_fd = $out_fd in_fd = $in_fd offset_uaddr = $offset count = $count argstr = sprintf("%d, %d, %p, %d", $out_fd, $in_fd, offset_uaddr, $count) } probe syscall.sys32_sendfile64.return = kernel.function("sys32_sendfile64").return ? { name = "sys32_sendfile64" retstr = return_str(1, $return) } # ppc32_timer_create ________________________________________ # # long ppc32_timer_create(clockid_t clock, # struct compat_sigevent __user *ev32, # timer_t __user *timer_id) # probe syscall.ppc32_timer_create = kernel.function("ppc32_timer_create") ? { name = "ppc32_timer_create" which_clock = $clock timer_event_spec = $ev32 created_timer_id = $timer_id argstr = sprintf("%d, %p, %p", which_clock, timer_event_spec, created_timer_id) } probe syscall.ppc32_timer_create.return = kernel.function("ppc32_timer_create").return ? { name = "ppc32_timer_create" retstr = return_str(1, $return) } # compat_timer_settime ________________________________________ # # long compat_timer_settime(timer_t timer_id, int flags, # struct compat_itimerspec __user *new, # struct compat_itimerspec __user *old) # probe syscall.compat_timer_settime = kernel.function("compat_timer_settime") ? { name = "compat_timer_settime" timer_id = $timer_id flags = $flags new_setting_uaddr = $new old_setting_uaddr = $old argstr = sprintf("%d, %d, %p, %p", timer_id, flags, new_setting_uaddr, old_setting_uaddr) } probe syscall.compat_timer_settime.return = kernel.function("compat_timer_settime").return ? { name = "compat_timer_settime" retstr = return_str(1, $return) } # compat_timer_gettime ________________________________________ # # long compat_timer_gettime(timer_t timer_id, # struct compat_itimerspec __user *setting) # probe syscall.compat_timer_gettime = kernel.function("compat_timer_gettime") ? { name = "compat_timer_gettime" timer_id = $timer_id setting_uaddr = $setting argstr = sprintf("%d, %p", timer_id, setting_uaddr) } probe syscall.compat_timer_gettime.return = kernel.function("compat_timer_gettime").return ? { name = "compat_timer_gettime" retstr = return_str(1, $return) } # compat_clock_settime ________________________________________ # # long compat_clock_settime(clockid_t which_clock, # struct compat_timespec __user *tp) # probe syscall.compat_clock_settime = kernel.function("compat_clock_settime") ? { name = "compat_clock_settime" which_clock = $which_clock tp_uaddr = $tp argstr = sprintf("%d, %p", which_clock, tp_uaddr) } probe syscall.compat_clock_settime.return = kernel.function("compat_clock_settime").return ? { name = "compat_clock_settime" retstr = return_str(1, $return) } # sys32_swapcontext ________________________________________ # # long sys32_swapcontext(struct ucontext32 __user *old_ctx, # struct ucontext32 __user *new_ctx, # int ctx_size, int r6, int r7, int r8, # struct pt_regs *regs) # probe syscall.sys32_swapcontext = kernel.function("sys32_swapcontext") ? { name = "sys32_swapcontext" old_ctx_uaddr = $old_ctx new_ctx_uaddr = $new_ctx r5 = $ctx_size r6 = $r6 r7 = $r7 r8 = $r8 regs = $regs argstr = sprintf("%p, %p, %d, %d, %d, %d, %p", old_ctx_uaddr, new_ctx_uaddr, r5, r6, r7, r8, regs) } probe syscall.sys32_swapcontext.return = kernel.function("sys32_swapcontext").return ? { name = "sys32_swapcontext" retstr = return_str(1, $return) } # sys32_utimes ________________________________________ # # asmlinkage long sys32_utimes(char __user *filename, # struct compat_timeval __user *tvs) # probe syscall.sys32_utimes = kernel.function("sys32_utimes") ? { name = "sys32_utimes" filename_uaddr = $filename path = user_string_quoted($filename) tvp_uaddr = $tvs argstr = sprintf("%s, %p", user_string_quoted($filename), tvp_uaddr) } probe syscall.sys32_utimes.return = kernel.function("sys32_utimes").return ? { name = "sys32_utimes" retstr = return_str(1, $return) } # compat_mbind ________________________________________ # # asmlinkage long compat_mbind(compat_ulong_t start, compat_ulong_t len, # compat_ulong_t mode, compat_ulong_t __user *nmask, # compat_ulong_t maxnode, compat_ulong_t flags) # probe syscall.compat_mbind = kernel.function("compat_mbind") ? { name = "compat_mbind" start_uaddr = $start len = $len policy = $mode nodemask_uaddr = $nmask maxnode = $maxnode flags = $flags argstr = sprintf("%p, %d, %d, %p, %d, %d", start_uaddr, len, policy, nodemask_uaddr, maxnode, flags) } probe syscall.compat_mbind.return = kernel.function("compat_mbind").return ? { name = "compat_mbind" retstr = return_str(1, $return) } # compat_get_mempolicy ________________________________________ # # asmlinkage long compat_get_mempolicy(int __user *policy, # compat_ulong_t __user *nmask, # compat_ulong_t maxnode, # compat_ulong_t addr, compat_ulong_t flags) # probe syscall.compat_get_mempolicy = kernel.function("compat_get_mempolicy") ? { name = "compat_get_mempolicy" policy_uaddr = $policy nmask_uaddr = $nmask maxnode = $maxnode addr = $addr flags = $flags argstr = sprintf("%p, %p, %d, %d", policy_uaddr, nmask_uaddr, maxnode, addr) } probe syscall.compat_get_mempolicy.return = kernel.function("compat_get_mempolicy").return ? { name = "compat_get_mempolicy" retstr = return_str(1, $return) } # compat_set_mempolicy ________________________________________ # # asmlinkage long compat_set_mempolicy(int mode, compat_ulong_t __user *nmask, # compat_ulong_t maxnode) # probe syscall.compat_set_mempolicy = kernel.function("compat_set_mempolicy") ? { name = "compat_set_mempolicy" policy = $mode nodemask_uaddr = $nmask maxnode = $maxnode argstr = sprintf("%d, %p, %d", policy, nodemask_uaddr, maxnode) } probe syscall.compat_set_mempolicy.return = kernel.function("compat_set_mempolicy").return ? { name = "compat_set_mempolicy" retstr = return_str(1, $return) } # In kernels < 2.6.33, mmap()/mmap2() was handled by arch-specific # code. In kernels >= 2.6.33, the arch-specific code just calls # generic sys_mmap_pgoff(). %( kernel_v < "2.6.33" %? # mmap # long sys_mmap(unsigned long addr, size_t len, # unsigned long prot, unsigned long flags, # unsigned long fd, off_t offset) # probe syscall.mmap = kernel.function("sys_mmap") ? { name = "mmap" start = $addr len = $len prot = $prot flags = $flags # Although the kernel gets an unsigned long fd, on the # user-side it is a signed int. Fix this. fd = __int32($fd) offset = $offset argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len, _mprotect_prot_str($prot), _mmap_flags($flags), __int32($fd), $offset) } probe syscall.mmap.return = kernel.function("sys_mmap").return ? { name = "mmap" retstr = return_str(2, $return) } # mmap2 # long sys_mmap2(unsigned long addr, size_t len, # unsigned long prot, unsigned long flags, # unsigned long fd, unsigned long pgoff) # long compat_sys_mmap2(unsigned long addr, size_t len, # unsigned long prot, unsigned long flags, # unsigned long fd, unsigned long pgoff) # probe syscall.mmap2 = kernel.function("sys_mmap2") ?, kernel.function("compat_sys_mmap2") ? { name = "mmap2" start = $addr length = $len prot = $prot flags = $flags # Although the kernel gets an unsigned long fd, on the # user-side it is a signed int. Fix this. fd = __int32($fd) pgoffset = $pgoff argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len, _mprotect_prot_str($prot), _mmap_flags($flags), __int32($fd), $pgoff) } probe syscall.mmap2.return = kernel.function("sys_mmap2").return ?, kernel.function("compat_sys_mmap2").return ? { name = "mmap2" retstr = return_str(2, $return) } %) # ppc64_sys_stime ________________________________________ # # long ppc64_sys_stime(long __user * tptr) # probe syscall.ppc64_sys_stime = kernel.function("ppc64_sys_stime") ? { name = "ppc64_sys_stime" /* FIXME */ t_uaddr = $tptr argstr = sprintf("%p", t_uaddr) } probe syscall.ppc64_sys_stime.return = kernel.function("ppc64_sys_stime").return ? { name = "ppc64_sys_stime" retstr = return_str(1, $return) } # ppc64_newuname ________________________________________ # # asmlinkage int ppc64_newuname(struct new_utsname __user * name) # probe syscall.ppc64_newuname = kernel.function("ppc64_newuname") ? { name = "ppc64_newuname" name_uaddr = $name argstr = sprintf("%p", name_uaddr) } probe syscall.ppc64_newuname.return = kernel.function("ppc64_newuname").return ? { name = "ppc64_newuname" retstr = return_str(1, $return) } # # systemtap-2.3/tapset/linux/proc_mem.stp000066400000000000000000000314451217430427200204100ustar00rootroot00000000000000// Process memory query and utility functions. // Copyright (C) 2009, 2010 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // Process memory query and utility functions provide information about // the memory usage of the current application. These functions provide // information about the full size, resident, shared, code and data used // by the current process. And provide utility functions to query the // page size of the current architecture and create human readable string // representations of bytes and pages used. // %{ /* PF_BORROWED_MM got renamed to PF_KTHREAD with same semantics somewhere. */ #ifdef PF_BORROWED_MM #define _STP_PF_KTHREAD PF_BORROWED_MM #elif defined(PF_KTHREAD) #define _STP_PF_KTHREAD PF_KTHREAD #else /* 2.6.9 doesn't have either PF_BORROWED_MM or PF_KTHREAD */ #define _STP_PF_KTHREAD 0 #endif /* PF_STARTING was removed in later kernels */ #ifdef PF_STARTING #define _STP_BAD_TASK_FLAGS (_STP_PF_KTHREAD | PF_EXITING | PF_STARTING) #else #define _STP_BAD_TASK_FLAGS (_STP_PF_KTHREAD | PF_EXITING) #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) #include #else /* Define our own mm types */ enum { MM_FILEPAGES, MM_ANONPAGES }; #endif %} /* Try to be slightly paranoid. Only returns 1 if the task isn't starting, exiting or (coopted by) a kernel thread. */ function _stp_valid_task:long(tsk:long) %{ struct task_struct *tsk = (struct task_struct *)(long)STAP_ARG_tsk; STAP_RETVALUE = 0; if (tsk) { unsigned int flags = kread(&(tsk->flags)); if (flags & ~_STP_BAD_TASK_FLAGS) STAP_RETVALUE = 1; } CATCH_DEREF_FAULT(); %} function _MM_FILEPAGES:long() %{ /* pure */ /* unprivileged */ STAP_RETVALUE = MM_FILEPAGES; %} function _MM_ANONPAGES:long() %{ /* pure */ /* unprivileged */ STAP_RETVALUE = MM_ANONPAGES; %} function _stp_get_mm_counter:long(mm:long, member:long) { /* kernels >= 2.6.34, 3.0 (2.6.40 fedora) and later always use atomics */ if (@defined(&@cast(mm, "mm_struct", "kernel")->rss_stat)) { %( kernel_v >= "2.6.40" || CONFIG_NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS %? val = atomic_long_read(&@cast(mm, "mm_struct", "kernel")->rss_stat->count[member]) %: val = @cast(mm, "mm_struct", "kernel")->rss_stat->count[member] %) if (val < 0) return 0 } /* kernels < 2.6.34 && kernels >= 2.6.12 */ else if (@defined(&@cast(mm, "mm_struct", "kernel")->_file_rss)) { if (member == _MM_FILEPAGES()) { %( CONFIG_NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS %? val = atomic_long_read(&@cast(mm, "mm_struct", "kernel")->_file_rss) %: val = @cast(mm, "mm_struct", "kernel")->_file_rss %) } else if (member == _MM_ANONPAGES()) { %( CONFIG_NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS %? val = atomic_long_read(&@cast(mm, "mm_struct", "kernel")->_anon_rss) %: val = @cast(mm, "mm_struct", "kernel")->_anon_rss %) } } /* kernels < 2.6.12 */ else { if (member == _MM_FILEPAGES()) val = @cast(mm, "mm_struct", "kernel")->rss else if (member == _MM_ANONPAGES()) val = @cast(mm, "mm_struct", "kernel")->anon_rss } return val } /** * sfunction proc_mem_size - Total program virtual memory size in pages * * Description: Returns the total virtual memory size in pages of the * current process, or zero when there is no current process or the * number of pages couldn't be retrieved. */ function proc_mem_size:long () { task = task_current() if (_stp_valid_task(task)) { mm = @cast(task, "task_struct", "kernel")->mm if (mm != 0) return @cast(mm, "mm_struct", "kernel")->total_vm } return 0 } /** * sfunction proc_mem_size_pid - Total program virtual memory size in pages * * @pid: The pid of process to examine * * Description: Returns the total virtual memory size in pages of the * given process, or zero when that process doesn't exist or the * number of pages couldn't be retrieved. */ function proc_mem_size_pid:long (pid:long) { task = pid2task(pid) if (_stp_valid_task(task)) { mm = @cast(task, "task_struct", "kernel")->mm if (mm != 0) return @cast(mm, "mm_struct", "kernel")->total_vm } return 0 } /** * sfunction proc_mem_rss - Program resident set size in pages * * Description: Returns the resident set size in pages of the current * process, or zero when there is no current process or the number of * pages couldn't be retrieved. */ function proc_mem_rss:long () { task = task_current() if (_stp_valid_task(task)) { mm = @cast(task, "task_struct", "kernel")->mm if (mm != 0) return (_stp_get_mm_counter(mm, _MM_FILEPAGES()) + _stp_get_mm_counter(mm, _MM_ANONPAGES())) } return 0 } /** * sfunction proc_mem_rss_pid - Program resident set size in pages * * @pid: The pid of process to examine * * Description: Returns the resident set size in pages of the given * process, or zero when the process doesn't exist or the number of * pages couldn't be retrieved. */ function proc_mem_rss_pid:long (pid:long) { task = pid2task(pid) if (_stp_valid_task(task)) { mm = @cast(task, "task_struct", "kernel")->mm if (mm != 0) return (_stp_get_mm_counter(mm, _MM_FILEPAGES()) + _stp_get_mm_counter(mm, _MM_ANONPAGES())) } return 0 } /** * sfunction proc_mem_shr - Program shared pages (from shared mappings) * * Description: Returns the shared pages (from shared mappings) of the * current process, or zero when there is no current process or the * number of pages couldn't be retrieved. */ function proc_mem_shr:long () { task = task_current() if (_stp_valid_task(task)) { mm = @cast(task, "task_struct", "kernel")->mm if (mm != 0) return _stp_get_mm_counter(mm, _MM_FILEPAGES()) } return 0 } /** * sfunction proc_mem_shr_pid - Program shared pages (from shared mappings) * * @pid: The pid of process to examine * * Description: Returns the shared pages (from shared mappings) of the * given process, or zero when the process doesn't exist or the * number of pages couldn't be retrieved. */ function proc_mem_shr_pid:long (pid:long) { task = pid2task(pid) if (_stp_valid_task(task)) { mm = @cast(task, "task_struct", "kernel")->mm if (mm != 0) return _stp_get_mm_counter(mm, _MM_FILEPAGES()) } return 0 } function _stp_mem_txt_adjust:long (start_code:long, end_code:long) %{ /* pure */ unsigned long start_code = (unsigned long) STAP_ARG_start_code; unsigned long end_code = (unsigned long) STAP_ARG_end_code; STAP_RETVALUE = (PAGE_ALIGN(end_code) - (start_code & PAGE_MASK)) >> PAGE_SHIFT; %} /** * sfunction proc_mem_txt - Program text (code) size in pages * * Description: Returns the current process text (code) size in pages, * or zero when there is no current process or the number of pages * couldn't be retrieved. */ function proc_mem_txt:long () { task = task_current() if (_stp_valid_task(task)) { mm = @cast(task, "task_struct", "kernel")->mm if (mm != 0) { s = @cast(mm, "mm_struct", "kernel")->start_code e = @cast(mm, "mm_struct", "kernel")->end_code return _stp_mem_txt_adjust(s, e) } } return 0 } /** * sfunction proc_mem_txt_pid - Program text (code) size in pages * * @pid: The pid of process to examine * * Description: Returns the given process text (code) size in pages, * or zero when the process doesn't exist or the number of pages * couldn't be retrieved. */ function proc_mem_txt_pid:long (pid:long) { task = pid2task(pid) if (_stp_valid_task(task)) { mm = @cast(task, "task_struct", "kernel")->mm if (mm != 0) { s = @cast(mm, "mm_struct", "kernel")->start_code e = @cast(mm, "mm_struct", "kernel")->end_code return _stp_mem_txt_adjust (s, e) } } return 0 } /** * sfunction proc_mem_data - Program data size (data + stack) in pages * * Description: Returns the current process data size (data + stack) * in pages, or zero when there is no current process or the number of * pages couldn't be retrieved. */ function proc_mem_data:long () { task = task_current() if (_stp_valid_task(task)) { mm = @cast(task, "task_struct", "kernel")->mm if (mm != 0) { t = @cast(mm, "mm_struct", "kernel")->total_vm s = @cast(mm, "mm_struct", "kernel")->shared_vm return (t - s) } } return 0 } /** * sfunction proc_mem_data_pid - Program data size (data + stack) in pages * * @pid: The pid of process to examine * * Description: Returns the given process data size (data + stack) * in pages, or zero when the process doesn't exist or the number of * pages couldn't be retrieved. */ function proc_mem_data_pid:long (pid:long) { task = pid2task(pid) if (_stp_valid_task(task)) { mm = @cast(task, "task_struct", "kernel")->mm if (mm != 0) { t = @cast(mm, "mm_struct", "kernel")->total_vm s = @cast(mm, "mm_struct", "kernel")->shared_vm return t - s } } return 0 } /** * sfunction mem_page_size - Number of bytes in a page for this architecture */ function mem_page_size:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = PAGE_SIZE; %} // Return a 5 character wide string " x.yyp", " xx.yp", " xxxp", "xxxxp". function _stp_number_to_string_postfix:string (x:long, y:long, p:string) { if (x < 10) return sprintf("%d.%.2d%s", x, y * 100 / 1024, p); if (x < 100) return sprintf("%2d.%d%s", x, y * 10 / 1024, p); return sprintf("%4d%s", x, p); } /** * sfunction bytes_to_string - Human readable string for given bytes * * @bytes: Number of bytes to translate. * * Description: Returns a string representing the number of bytes (up * to 1024 bytes), the number of kilobytes (when less than 1024K) * postfixed by 'K', the number of megabytes (when less than 1024M) * postfixed by 'M' or the number of gigabytes postfixed by 'G'. If * representing K, M or G, and the number is amount is less than 100, * it includes a '.' plus the remainer. The returned string will be 5 * characters wide (padding with whitespace at the front) unless * negative or representing more than 9999G bytes. */ function bytes_to_string:string (bytes:long) { if (bytes < 1024) return sprintf("%5d", bytes); remain = bytes % 1024; bytes = bytes / 1024; if (bytes < 1024) return _stp_number_to_string_postfix(bytes, remain, "K"); remain = bytes % 1024; bytes = bytes / 1024; if (bytes < 1024) return _stp_number_to_string_postfix(bytes, remain, "M"); remain = bytes % 1024; bytes = bytes / 1024; return _stp_number_to_string_postfix(bytes, remain, "G"); } /** * sfunction pages_to_string - Turns pages into a human readable string * * @pages: Number of pages to translate. * * Description: Multiplies pages by page_size() to get the number of * bytes and returns the result of bytes_to_string(). */ function pages_to_string:string (pages:long) { bytes = pages * mem_page_size(); return bytes_to_string (bytes); } /** * sfunction proc_mem_string - Human readable string of current proc memory usage * * Description: Returns a human readable string showing the size, rss, * shr, txt and data of the memory used by the current process. * For example "size: 301m, rss: 11m, shr: 8m, txt: 52k, data: 2248k". */ function proc_mem_string:string () { return sprintf ("size: %s, rss: %s, shr: %s, txt: %s, data: %s", pages_to_string(proc_mem_size()), pages_to_string(proc_mem_rss()), pages_to_string(proc_mem_shr()), pages_to_string(proc_mem_txt()), pages_to_string(proc_mem_data())); } /** * sfunction proc_mem_string_pid - Human readable string of process memory usage * * @pid: The pid of process to examine * * Description: Returns a human readable string showing the size, rss, * shr, txt and data of the memory used by the given process. * For example "size: 301m, rss: 11m, shr: 8m, txt: 52k, data: 2248k". */ function proc_mem_string_pid:string (pid:long) { return sprintf ("size: %s, rss: %s, shr: %s, txt: %s, data: %s", pages_to_string(proc_mem_size_pid(pid)), pages_to_string(proc_mem_rss_pid(pid)), pages_to_string(proc_mem_shr_pid(pid)), pages_to_string(proc_mem_txt_pid(pid)), pages_to_string(proc_mem_data_pid(pid))); } systemtap-2.3/tapset/linux/pstrace.stp000066400000000000000000000014061217430427200202420ustar00rootroot00000000000000/* * kernel pstrace tapset * Copyright (C) 2012 Red Hat Corporation. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. */ /** * sfunction pstrace - Chain of processes and pids back to init(1) * @task: Pointer to task struct of process * * This function returns a string listing execname and pid for each * process starting from @task back to the process ancestor * that init(1) spawned. */ function pstrace:string(task:long) { while (task_pid(task) != 1) { trace = sprintf("%s %s(%d)", trace, task_execname(task), task_pid(task)); task = task_parent(task); } return trace; } systemtap-2.3/tapset/linux/rcu.stp000066400000000000000000000016251217430427200173750ustar00rootroot00000000000000// rcu tapset // Copyright (C) 2013 Red Hat // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. %{ #include %} function rcu_dereference:long (protected_pointer:long) %{ /* pure */ void *protected_pointer = (void *)(long)STAP_ARG_protected_pointer; long fetched_value; /* We call kderef() here to ensure the memory is valid to read. * Note the result is thrown away, then we use the "real" * rcu_dereference function now that we know the address is * safe. */ (void)kderef(sizeof(*protected_pointer), protected_pointer); rcu_read_lock(); fetched_value = (long)rcu_dereference(protected_pointer); rcu_read_unlock(); STAP_RETVALUE = fetched_value; CATCH_DEREF_FAULT(); %} systemtap-2.3/tapset/linux/rpc.stp000066400000000000000000001067121217430427200173730ustar00rootroot00000000000000// rpc tapset // Copyright (C) 2006 IBM Corp. // Copyright (C) 2007 Bull S.A.S // Copyright (C) 2008, 2010-2013 Red Hat // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. %{ // Includes everything needed for __rpc_prot_from_protocol(). #include %} probe sunrpc.entry = sunrpc.clnt.entry, sunrpc.svc.entry, sunrpc.sched.entry {} probe sunrpc.return = sunrpc.clnt.return, sunrpc.svc.return, sunrpc.sched.return {} /****************************************************************** * Probe points on RPC client functions * ******************************************************************/ probe sunrpc.clnt.entry = sunrpc.clnt.create_client, sunrpc.clnt.clone_client, sunrpc.clnt.bind_new_program, sunrpc.clnt.shutdown_client, sunrpc.clnt.call_sync, sunrpc.clnt.call_async, sunrpc.clnt.restart_call {} probe sunrpc.clnt.return = sunrpc.clnt.create_client.return, sunrpc.clnt.clone_client.return, sunrpc.clnt.bind_new_program.return, sunrpc.clnt.shutdown_client.return, sunrpc.clnt.call_sync.return, sunrpc.clnt.call_async.return, sunrpc.clnt.restart_call.return {} /* * Fires when an RPC client is to be created * * kernels > 2.6.18 * * struct rpc_clnt * * rpc_create(struct rpc_create_args *args) * The rpc_create() function is used to create an RPC client. It * calculates some arguments (such as args->servername), then * calls rpc_new_client(). We need the calculated arguments, so * we'll probe rpc_new_client(). But, see discussion of * sunrpc.clnt.create_client.return below. * * static struct rpc_clnt * * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) * * kernels <= 2.6.18 * * static struct rpc_clnt * * rpc_new_client(struct rpc_xprt *xprt, char *servname, * struct rpc_program *program, u32 vers, * rpc_authflavor_t flavor) * * struct rpc_clnt * * rpc_create_client(struct rpc_xprt *xprt, char *servname, * struct rpc_program *info, u32 version, * rpc_authflavor_t authflavor) */ /** * probe sunrpc.clnt.create_client - Create an RPC client * * @servername: the server machine name * @progname: the RPC program name * @prog: the RPC program number * @vers: the RPC program version number * @prot: the IP protocol number * @port: the port number * @authflavor: the authentication flavor */ probe sunrpc.clnt.create_client = _sunrpc.clnt.create_client.rpc_new_client_inline !, _sunrpc.clnt.create_client.rpc_new_client ?, _sunrpc.clnt.create_client.rpc_create_client ? { name = "sunrpc.clnt.create_client" argstr = sprintf("%s %s %d %d %d %d %d", servername, progname, prog, vers, prot, port, authflavor) } /* * Newer kernels (> 2.6.18) compiled with gcc less than version * 4.4.3-16, tend to have debuginfo that doesn't include location * information for inline function arguments. This is a problem, since * we need the arguments to rpc_new_client(), which is inline. Since * we can't get them for those kernels, we stash (and delete) the value * of the 'args' parameter of rpc_create(). We then use this value * when probing the inline version of rpc_new_client() (if we don't * have the real arguments to that inline function). */ global __rpc_create_args probe kernel.function("rpc_create").call !, module("sunrpc").function("rpc_create").call ? { __rpc_create_args[tid()] = $args } probe kernel.function("rpc_create").return !, module("sunrpc").function("rpc_create").return ? { delete __rpc_create_args[tid()] } /* * This function could be written in script language, but we'd need * embedded-C functions for XPRT_TRANSPORT_{UDP,TCP,BC_TCP} and * IPPROTO_{UDP,TCP}. So, do it all in embedded-C. */ function __rpc_prot_from_protocol:long(protocol:long) %{ switch (STAP_ARG_protocol) { #ifdef XPRT_TRANSPORT_BC case XPRT_TRANSPORT_UDP: STAP_RETVALUE = IPPROTO_UDP; break; case XPRT_TRANSPORT_TCP: case XPRT_TRANSPORT_BC_TCP: STAP_RETVALUE = IPPROTO_TCP; break; #endif default: STAP_RETVALUE = -1; break; } %} /* * The probe for the inline version of "rpc_new_client" (kernels > * 2.6.18) and the non-inline version of "rpc_new_client" (kernels <= * 2.6.18) could be combined. However, the optimizer isn't smart * enough to optimize away the '__rpc_create_args' global then. */ probe _sunrpc.clnt.create_client.rpc_new_client_inline = kernel.function("rpc_new_client").inline !, module("sunrpc").function("rpc_new_client").inline { if (@defined($args)) { # kernel > 2.6.18 (with good debuginfo) %(systemtap_v <= "1.7" %? args = $args %) __args = $args servername = kernel_string($args->servername) progname = kernel_string($args->program->name) prog = $args->prognumber vers = vers_from_prog($args->program, $args->version) authflavor = $args->authflavor prot = $xprt->prot port = @choose_defined($xprt->port, port_from_xprt($xprt)) } else { # kernel > 2.6.18 (with bad debuginfo) %(systemtap_v <= "1.7" %? args = __rpc_create_args[tid()] %) __args = __rpc_create_args[tid()] servername = kernel_string(@cast(__args, "rpc_create_args", "kernel:sunrpc")->servername) progname = kernel_string(@cast(__args, "rpc_create_args", "kernel:sunrpc")->program->name) prog = @cast(__args, "rpc_create_args", "kernel:sunrpc")->prognumber vers = vers_from_prog(@cast(__args, "rpc_create_args", "kernel:sunrpc")->program, @cast(__args, "rpc_create_args", "kernel:sunrpc")->version) authflavor = @cast(__args, "rpc_create_args", "kernel:sunrpc")->authflavor prot = __rpc_prot_from_protocol(@cast(__args, "rpc_create_args", "kernel:sunrpc")->protocol) # Since we can't find $xprt, we can't know the port port = -1 } } probe _sunrpc.clnt.create_client.rpc_new_client = kernel.function("rpc_new_client").call !, module("sunrpc").function("rpc_new_client").call { if (@defined($args)) { # kernel > 2.6.18 servername = kernel_string($args->servername) progname = kernel_string($args->program->name) prog = $args->prognumber vers = vers_from_prog($args->program, $args->version) authflavor = $args->authflavor } else { # kernel <= 2.6.18 servername = kernel_string($servname) progname = kernel_string($program->name) prog = $program->number vers = vers_from_prog($program, $vers) authflavor = $flavor } prot = $xprt->prot port = @choose_defined($xprt->port, port_from_xprt($xprt)) } probe _sunrpc.clnt.create_client.rpc_create_client = kernel.function("rpc_create_client") !, module("sunrpc").function("rpc_create_client") { servername = kernel_string($servname) if (@defined($info)) { progname = kernel_string($info->name) prog = $info->number vers = vers_from_prog($info, $version) authflavor = $authflavor } else { progname = kernel_string($program->name) prog = $program->number vers = vers_from_prog($program, $vers) authflavor = $flavor } prot = $xprt->prot port = @choose_defined($xprt->port, port_from_xprt($xprt)) } /* * On newer kernels, we want to probe the return of rpc_new_client() * here. But because of problems with return probes on inline * functions (PR 4413), we have to probe the return of rpc_create() * instead. So, if we find the return of rpc_create() (the only * caller of rpc_new_client()), we're done. */ probe sunrpc.clnt.create_client.return = _sunrpc.clnt.create_client.return.rpc_create !, _sunrpc.clnt.create_client.return.rpc_new_client ?, _sunrpc.clnt.create_client.return.rpc_create_client ? { name = "sunrpc.clnt.create_client.return" retstr = return_str(2, $return) } probe _sunrpc.clnt.create_client.return.rpc_create = kernel.function("rpc_create").return !, module("sunrpc").function("rpc_create").return { } probe _sunrpc.clnt.create_client.return.rpc_new_client = kernel.function("rpc_new_client").return !, module("sunrpc").function("rpc_new_client").return { } probe _sunrpc.clnt.create_client.return.rpc_create_client = kernel.function("rpc_create_client").return !, module("sunrpc").function("rpc_create_client").return { } /** * probe sunrpc.clnt.clone_client - Clone an RPC client structure * * @servername: the server machine name * @progname: the RPC program name * @prog: the RPC program number * @vers: the RPC program version number * @prot: the IP protocol number * @port: the port number * @authflavor: the authentication flavor */ probe sunrpc.clnt.clone_client = kernel.function("rpc_clone_client") !, module("sunrpc").function("rpc_clone_client") { servername = kernel_string(@choose_defined($clnt->cl_server, @cast(rcu_dereference($clnt->cl_xprt), "struct rpc_xprt")->servername)) progname = kernel_string($clnt->cl_protname) prog = prog_from_clnt($clnt) vers = vers_from_clnt($clnt) prot = prot_from_clnt($clnt) port = port_from_clnt($clnt) authflavor = $clnt->cl_auth->au_flavor name = "sunrpc.clnt.clone_client" argstr = sprintf("%s %s %d %d %d %d %d", servername, progname, prog, vers, prot, port, authflavor) } probe sunrpc.clnt.clone_client.return = kernel.function("rpc_clone_client").return !, module("sunrpc").function("rpc_clone_client").return { name = "sunrpc.clnt.clone_client.return" retstr = return_str(2, $return) } /** * probe sunrpc.clnt.shutdown_client - Shutdown an RPC client * * @servername: the server machine name * @progname: the RPC program name * @prog: the RPC program number * @vers: the RPC program version number * @prot: the IP protocol number * @port: the port number * @authflavor: the authentication flavor * @clones: the number of clones * @tasks: the number of references * @netreconn: the count of reconnections * @rpccnt: the count of RPC calls * @om_ops: the count of operations * @om_ntrans: the count of RPC transmissions * @om_bytes_sent: the count of bytes out * @om_bytes_recv: the count of bytes in * @om_queue: the jiffies queued for xmit * @om_rtt: the RPC RTT jiffies * @om_execute: the RPC execution jiffies */ probe sunrpc.clnt.shutdown_client = kernel.function("rpc_shutdown_client") !, module("sunrpc").function("rpc_shutdown_client") { servername = kernel_string(@choose_defined($clnt->cl_server, @cast(rcu_dereference($clnt->cl_xprt), "struct rpc_xprt")->servername)) progname = kernel_string($clnt->cl_protname) prog = prog_from_clnt($clnt) vers = vers_from_clnt($clnt) prot = prot_from_clnt($clnt) port = port_from_clnt($clnt) authflavor = $clnt->cl_auth->au_flavor clones = clones_from_clnt($clnt) tasks = tasks_from_clnt($clnt) /* per-program statistics */ netreconn = $clnt->cl_stats->netreconn rpccnt = $clnt->cl_stats->rpccnt /* per-client statistics */ if (@defined($clnt->cl_metrics)) { om_ops = $clnt->cl_metrics->om_ops om_ntrans = $clnt->cl_metrics->om_ntrans om_bytes_sent = $clnt->cl_metrics->om_bytes_sent om_bytes_recv = $clnt->cl_metrics->om_bytes_recv if (@defined($clnt->cl_metrics->om_queue->tv64)) { om_queue = $clnt->cl_metrics->om_queue->tv64 om_rtt = $clnt->cl_metrics->om_rtt->tv64 om_execute = $clnt->cl_metrics->om_execute->tv64 } else { om_queue = $clnt->cl_metrics->om_queue om_rtt = $clnt->cl_metrics->om_rtt om_execute = $clnt->cl_metrics->om_execute } } else { om_ops = -1 om_ntrans = -1 om_bytes_sent = -1 om_bytes_recv = -1 om_queue = -1 om_rtt = -1 om_execute = -1 } name = "sunrpc.clnt.shutdown_client" argstr = sprintf("%s %s %d %d %d %d %d %d %d", servername, progname, prog, vers, prot, port, authflavor, clones, tasks) } probe sunrpc.clnt.shutdown_client.return = kernel.function("rpc_shutdown_client").return !, module("sunrpc").function("rpc_shutdown_client").return { name = "sunrpc.clnt.shutdown_client.return" retstr = (@defined($return) ? return_str(1, $return) : "N/A") } /** * probe sunrpc.clnt.bind_new_program - Bind a new RPC program to an existing client * * @servername: the server machine name * @old_progname: the name of old RPC program * @old_prog: the number of old RPC program * @old_vers: the version of old RPC program * @progname: the name of new RPC program * @prog: the number of new RPC program * @vers: the version of new RPC program */ probe sunrpc.clnt.bind_new_program = kernel.function("rpc_bind_new_program") !, module("sunrpc").function("rpc_bind_new_program") { servername = kernel_string(@choose_defined($old->cl_server, @cast(rcu_dereference($old->cl_xprt), "struct rpc_xprt")->servername)) old_progname = kernel_string($old->cl_protname) old_prog = prog_from_clnt($old) old_vers = vers_from_clnt($old) progname = kernel_string($program->name) prog = $program->number vers = vers_from_prog($program, $vers) name = "sunrpc.clnt.bind_new_program" argstr = sprintf("%s %s %d %s %d", servername, old_progname, old_vers, progname, vers) } probe sunrpc.clnt.bind_new_program.return = kernel.function("rpc_bind_new_program").return !, module("sunrpc").function("rpc_bind_new_program").return { name = "sunrpc.clnt.bind_new_program.return" retstr = return_str(2, $return) } /** * probe sunrpc.clnt.call_sync - Make a synchronous RPC call * * @servername: the server machine name * @progname: the RPC program name * @prog: the RPC program number * @vers: the RPC program version number * @prot: the IP protocol number * @port: the port number * @xid: current transmission id * @dead: whether this client is abandoned * @procname: the procedure name in this RPC call * @proc: the procedure number in this RPC call * @flags: flags */ probe sunrpc.clnt.call_sync = kernel.function("rpc_call_sync") !, module("sunrpc").function("rpc_call_sync") { servername = kernel_string(@choose_defined($clnt->cl_server, @cast(rcu_dereference($clnt->cl_xprt), "struct rpc_xprt")->servername)) progname = kernel_string($clnt->cl_protname) prog = prog_from_clnt($clnt) vers = vers_from_clnt($clnt) prot = prot_from_clnt($clnt) port = port_from_clnt($clnt) xid = xid_from_clnt($clnt) dead = @choose_defined($clnt->cl_dead, atomic_read(@choose_defined(&$clnt->cl_kref->refcount, &$clnt->cl_count)) == 0) proc = proc_from_msg($msg) procname = kernel_string2(@choose_defined($msg->rpc_proc->p_name, 0), "NULL") flags = $flags name = "sunrpc.clnt.call_sync" argstr = sprintf("%s %d %s %d %s %d", servername, xid, progname, vers, procname, flags) } probe sunrpc.clnt.call_sync.return = kernel.function("rpc_call_sync").return !, module("sunrpc").function("rpc_call_sync").return { name = "sunrpc.clnt.call_sync.return" retstr = return_str(1, $return) } /** * probe sunrpc.clnt.call_async - Make an asynchronous RPC call * * @servername: the server machine name * @progname: the RPC program name * @prog: the RPC program number * @vers: the RPC program version number * @prot: the IP protocol number * @port: the port number * @xid: current transmission id * @dead: whether this client is abandoned * @procname: the procedure name in this RPC call * @proc: the procedure number in this RPC call * @flags: flags */ probe sunrpc.clnt.call_async = kernel.function("rpc_call_async") !, module("sunrpc").function("rpc_call_async") { servername = kernel_string(@choose_defined($clnt->cl_server, @cast(rcu_dereference($clnt->cl_xprt), "struct rpc_xprt")->servername)) progname = kernel_string($clnt->cl_protname) prog = prog_from_clnt($clnt) vers = vers_from_clnt($clnt) prot = prot_from_clnt($clnt) port = port_from_clnt($clnt) xid = xid_from_clnt($clnt) dead = @choose_defined($clnt->cl_dead, atomic_read(@choose_defined(&$clnt->cl_kref->refcount, &$clnt->cl_count)) == 0) proc = proc_from_msg($msg) procname = kernel_string2(@choose_defined($msg->rpc_proc->p_name, 0), "NULL") flags = $flags name = "sunrpc.clnt.call_async" argstr = sprintf("%s %d %s %d %s %d", servername, xid, progname, vers, procname, flags) } probe sunrpc.clnt.call_async.return = kernel.function("rpc_call_async").return !, module("sunrpc").function("rpc_call_async").return { name = "sunrpc.clnt.call_async.return" retstr = return_str(1, $return) } /** * probe sunrpc.clnt.restart_call - Restart an asynchronous RPC call * * @servername: the server machine name * @prog: the RPC program number * @xid: the transmission id * @tk_pid: the debugging aid of task * @tk_flags: the task flags * @tk_priority: the task priority * @tk_runstate: the task run status */ probe sunrpc.clnt.restart_call = kernel.function("rpc_restart_call") !, module("sunrpc").function("rpc_restart_call") { servername = kernel_string(@choose_defined($task->tk_client->cl_server, @cast(rcu_dereference($task->tk_client->cl_xprt), "struct rpc_xprt")->servername)) prog = prog_from_clnt($task->tk_client) xid = $task->tk_rqstp->rq_xid tk_pid = $task->tk_pid tk_flags = $task->tk_flags tk_priority = $task->tk_priority tk_runstate = $task->tk_runstate name = "sunrpc.clnt.restart_call" argstr = sprintf("%s %d %d %d %d %d %d", servername, prog, xid, tk_pid, tk_flags, tk_priority, tk_runstate) } probe sunrpc.clnt.restart_call.return = kernel.function("rpc_restart_call").return !, module("sunrpc").function("rpc_restart_call").return { name = "sunrpc.clnt.restart_call.return" retstr = "N/A" } /********************************************* * Probe points on RPC server interface * ********************************************/ probe sunrpc.svc.entry = sunrpc.svc.register, sunrpc.svc.create, sunrpc.svc.destroy, sunrpc.svc.process, sunrpc.svc.authorise, sunrpc.svc.recv, sunrpc.svc.send, sunrpc.svc.drop {} probe sunrpc.svc.return = sunrpc.svc.register.return, sunrpc.svc.create.return, sunrpc.svc.destroy.return, sunrpc.svc.process.return, sunrpc.svc.authorise.return, sunrpc.svc.recv.return, sunrpc.svc.send.return, sunrpc.svc.drop.return {} /** * probe sunrpc.svc.register - Register an RPC service with the local portmapper * * @sv_name: the service name * @progname: the name of the program * @prog: the number of the program * @prot: the IP protocol number * @port: the port number * * If @proto and @port are both 0, then unregister a service. */ probe sunrpc.svc.register = kernel.function("svc_register") !, module("sunrpc").function("svc_register") { sv_name = kernel_string($serv->sv_name) progname = kernel_string($serv->sv_program->pg_name) prog = $serv->sv_program->pg_prog prot = $proto port = $port name = "sunrpc.svc.register" argstr = sprintf("%s %s %d %d", sv_name, progname, prot, port) } probe sunrpc.svc.register.return = kernel.function("svc_register").return !, module("sunrpc").function("svc_register").return { name = "sunrpc.svc.register.return" retstr = return_str(1, $return) } /** * probe sunrpc.svc.create - Create an RPC service * * @progname: the name of the program * @prog: the number of the program * @pg_nvers: the number of supported versions * @bufsize: the buffer size */ probe sunrpc.svc.create = kernel.function("svc_create") !, module("sunrpc").function("svc_create") { progname = kernel_string($prog->pg_name) prog = $prog->pg_prog pg_nvers = $prog->pg_nvers bufsize = $bufsize name = "sunrpc.svc.create" argstr = sprintf("%s %d %d %d", progname, prog, pg_nvers, bufsize) } probe sunrpc.svc.create.return = kernel.function("svc_create").return !, module("sunrpc").function("svc_create").return { name = "sunrpc.svc.create.return" retstr = return_str(2, $return) } /** * probe sunrpc.svc.destroy - Destroy an RPC service * * @sv_name: the service name * @sv_progname: the name of the program * @sv_prog: the number of the program * @sv_nrthreads:the number of concurrent threads * @netcnt: the count of received RPC requests * @nettcpconn: the count of accepted TCP connections * @rpccnt: the count of valid RPC requests * @rpcbadfmt: the count of requests dropped for bad formats * @rpcbadauth: the count of requests drooped for authentication failure */ probe sunrpc.svc.destroy = kernel.function("svc_destroy") !, module("sunrpc").function("svc_destroy") { sv_name = kernel_string($serv->sv_name) /* service name */ sv_progname = kernel_string($serv->sv_program->pg_name) sv_prog = $serv->sv_program->pg_prog sv_nrthreads = $serv->sv_nrthreads /* RPC statistics */ netcnt = $serv->sv_stats->netcnt netcpconn = $serv->sv_stats->nettcpconn rpccnt = $serv->sv_stats->rpccnt rpcbadfmt = $serv->sv_stats->rpcbadfmt rpcbadauth = $serv->sv_stats->rpcbadauth name = "sunrpc.svc.destroy" argstr = sprintf("%s %d %d", sv_name, sv_prog, sv_nrthreads) } probe sunrpc.svc.destroy.return = kernel.function("svc_destroy").return !, module("sunrpc").function("svc_destroy").return { name = "sunrpc.svc.destroy.return" retstr = "N/A" } /** * probe sunrpc.svc.process - Process an RPC request * * @sv_name: the service name * @sv_prog: the number of the program * @sv_nrthreads:the number of concurrent threads * @peer_ip: the peer address where the request is from * @rq_xid: the transmission id in the request * @rq_prog: the program number in the request * @rq_vers: the program version in the request * @rq_proc: the procedure number in the request * @rq_prot: the IP protocol of the reqeust */ probe sunrpc.svc.process = kernel.function("svc_process") !, module("sunrpc").function("svc_process") { if (! @defined($serv)) { sv_name = kernel_string($rqstp->rq_server->sv_name) sv_prog = $rqstp->rq_server->sv_program->pg_prog sv_nrthreads = $rqstp->rq_server->sv_nrthreads } else { sv_name = kernel_string($serv->sv_name) /* service name */ sv_prog = $serv->sv_program->pg_prog sv_nrthreads = $serv->sv_nrthreads } peer_ip = addr_from_rqst($rqstp) rq_xid = $rqstp->rq_xid rq_prog = $rqstp->rq_prog rq_vers = $rqstp->rq_vers rq_proc = $rqstp->rq_proc rq_prot = $rqstp->rq_prot name = "sunrpc.svc.process" argstr = sprintf("%s %d %d %d %d %d %d", sv_name, sv_prog, peer_ip, rq_xid, rq_prog, rq_vers, rq_proc) } probe sunrpc.svc.process.return = kernel.function("svc_process").return !, module("sunrpc").function("svc_process").return { name = "sunrpc.svc.process.return" retstr = return_str(1, $return) } /* * probe sunrpc.svc.authorise - An RPC request is to be authorised * * @sv_name: the service name * @peer_ip: the peer address where the request is from * @rq_xid: the transmission id in the request * @rq_prog: the program number in the request * @rq_vers: the program version in the request * @rq_proc: the procedure number in the request * @rq_prot: the IP protocol of the reqeust */ probe sunrpc.svc.authorise = kernel.function("svc_authorise") !, module("sunrpc").function("svc_authorise") { sv_name = kernel_string($rqstp->rq_server->sv_name) peer_ip = addr_from_rqst($rqstp) rq_xid = $rqstp->rq_xid rq_prog = $rqstp->rq_prog rq_vers = $rqstp->rq_vers rq_proc = $rqstp->rq_proc rq_prot = $rqstp->rq_prot name = "sunrpc.svc.authorise" argstr = sprintf("%d %d %d %d %d %d", peer_ip, rq_xid, rq_prog, rq_vers, rq_proc, rq_prot) } probe sunrpc.svc.authorise.return = kernel.function("svc_authorise").return !, module("sunrpc").function("svc_authorise").return { name = "sunrpc.svc.authorise.return" retstr = return_str(1, $return) } /** * probe sunrpc.svc.recv - Listen for the next RPC request on any socket * * @sv_name: the service name * @sv_prog: the number of the program * @sv_nrthreads:the number of concurrent threads * @timeout: the timeout of waiting for data */ probe sunrpc.svc.recv = kernel.function("svc_recv") !, module("sunrpc").function("svc_recv") { if (! @defined($serv)) { sv_name = kernel_string($rqstp->rq_server->sv_name) sv_prog = $rqstp->rq_server->sv_program->pg_prog sv_nrthreads = $rqstp->rq_server->sv_nrthreads } else { sv_name = kernel_string($serv->sv_name) sv_prog = $serv->sv_program->pg_prog sv_nrthreads = $serv->sv_nrthreads } timeout = $timeout name = "sunrpc.svc.recv" argstr = sprintf("%s %d", sv_name, timeout) } probe sunrpc.svc.recv.return = kernel.function("svc_recv").return !, module("sunrpc").function("svc_recv").return { name = "sunrpc.svc.recv.return" retstr = return_str(1, $return) } /** * probe sunrpc.svc.send - Return reply to RPC client * * @sv_name: the service name * @peer_ip: the peer address where the request is from * @rq_xid: the transmission id in the request * @rq_prog: the program number in the request * @rq_vers: the program version in the request * @rq_proc: the procedure number in the request * @rq_prot: the IP protocol of the reqeust */ probe sunrpc.svc.send = kernel.function("svc_send") !, module("sunrpc").function("svc_send") { sv_name = kernel_string($rqstp->rq_server->sv_name) peer_ip = addr_from_rqst($rqstp) rq_xid = $rqstp->rq_xid rq_prog = $rqstp->rq_prog rq_vers = $rqstp->rq_vers rq_proc = $rqstp->rq_proc rq_prot = $rqstp->rq_prot name = "sunrpc.svc.send" argstr = sprintf("%s %d %d %d %d %d %d", sv_name, peer_ip, rq_xid, rq_prog, rq_vers, rq_proc, rq_prot) } probe sunrpc.svc.send.return = kernel.function("svc_send").return !, module("sunrpc").function("svc_send").return { name = "sunrpc.svc.send.return" retstr = return_str(1, $return) } /** * probe sunrpc.svc.drop - Drop RPC request * * @sv_name: the service name * @peer_ip: the peer address where the request is from * @rq_xid: the transmission id in the request * @rq_prog: the program number in the request * @rq_vers: the program version in the request * @rq_proc: the procedure number in the request * @rq_prot: the IP protocol of the reqeust */ probe sunrpc.svc.drop = kernel.function("svc_drop") !, module("sunrpc").function("svc_drop") { sv_name = kernel_string($rqstp->rq_server->sv_name) peer_ip = addr_from_rqst($rqstp) rq_xid = $rqstp->rq_xid rq_prog = $rqstp->rq_prog rq_vers = $rqstp->rq_vers rq_proc = $rqstp->rq_proc rq_prot = $rqstp->rq_prot name = "sunrpc.svc.drop" argstr = sprintf("%s %d %d %d %d %d %d", sv_name, peer_ip, rq_xid, rq_prog, rq_vers, rq_proc, rq_prot) } probe sunrpc.svc.drop.return = kernel.function("svc_drop").return !, module("sunrpc").function("svc_drop").return { name = "sunrpc.svc.drop.return" retstr = "N/A" } /******************************************************************* * Probe points on RPC scheduler * ******************************************************************/ probe sunrpc.sched.entry = sunrpc.sched.new_task, sunrpc.sched.release_task ?, sunrpc.sched.execute, sunrpc.sched.delay {} probe sunrpc.sched.return = sunrpc.sched.new_task.return, sunrpc.sched.release_task.return ?, sunrpc.sched.execute.return, sunrpc.sched.delay.return {} /** * probe sunrpc.sched.new_task - Create new task for the specified client * * @xid: the transmission id in the RPC call * @prog: the program number in the RPC call * @vers: the program version in the RPC call * @prot: the IP protocol in the RPC call * @tk_flags: the flags of the task */ probe sunrpc.sched.new_task = kernel.function("rpc_new_task") !, module("sunrpc").function("rpc_new_task") { if (@defined($setup_data)) { xid = xid_from_clnt($setup_data->rpc_client) prog = prog_from_clnt($setup_data->rpc_client) vers = vers_from_clnt($setup_data->rpc_client) prot = prot_from_clnt($setup_data->rpc_client) flags = $setup_data->flags } else { xid = xid_from_clnt($clnt) prog = prog_from_clnt($clnt) vers = vers_from_clnt($clnt) prot = prot_from_clnt($clnt) flags = $flags } name = "sunrpc.sched.new_task" argstr = sprintf("%d %d %d %d %d", xid, prog, vers, prot, flags) } probe sunrpc.sched.new_task.return = kernel.function("rpc_new_task").return !, module("sunrpc").function("rpc_new_task").return { name = "sunrpc.sched.new_task.return" retstr = return_str(2, $return) } /** * probe sunrpc.sched.release_task - Release all resources associated with a task * * @xid: the transmission id in the RPC call * @prog: the program number in the RPC call * @vers: the program version in the RPC call * @prot: the IP protocol in the RPC call * @tk_flags: the flags of the task * * rpc_release_task() function might not be found for a particular kernel. * So, if we can't find it, just return '-1' for everything. */ /* * The '.call' here is so that we're sure to grab the non-inline * version of rpc_release_task() (assuming it exists). We can't find * the return of rpc_release_task() if it is inline (PR 4413). */ probe sunrpc.sched.release_task = kernel.function("rpc_release_task").call !, module("sunrpc").function("rpc_release_task").call !, never { if (@defined($task)) { xid = xid_from_clnt($task->tk_client) prog = prog_from_clnt($task->tk_client) vers = vers_from_clnt($task->tk_client) prot = prot_from_clnt($task->tk_client) tk_flags = $task->tk_flags } else { xid = -1 prog = -1 vers = -1 prot = -1 tk_flags = -1 } name = "sunrpc.sched.release_task" argstr = sprintf("%d %d %d %d %d", xid, prog, vers, prot, tk_flags) } probe sunrpc.sched.release_task.return = kernel.function("rpc_release_task").return !, module("sunrpc").function("rpc_release_task").return ? { name = "sunrpc.sched.release_task.return" retstr = "N/A" } /** * probe sunrpc.sched.execute - Execute the RPC `scheduler' * * @xid: the transmission id in the RPC call * @prog: the program number in the RPC call * @vers: the program version in the RPC call * @prot: the IP protocol in the RPC call * @tk_pid: the debugging id of the task * @tk_flags: the flags of the task */ probe sunrpc.sched.execute = kernel.function("__rpc_execute") !, module("sunrpc").function("__rpc_execute") { xid = xid_from_clnt($task->tk_client) prog = prog_from_clnt($task->tk_client) vers = vers_from_clnt($task->tk_client) prot = prot_from_clnt($task->tk_client) tk_pid = $task->tk_pid tk_flags = $task->tk_flags name = "sunrpc.sched.execute" argstr = sprintf("%d %d %d %d %d %d", xid, prog, vers, prot, tk_pid, tk_flags) } probe sunrpc.sched.execute.return = kernel.function("__rpc_execute").return !, module("sunrpc").function("__rpc_execute").return { name = "sunrpc.sched.execute.return" # On kernels > 2.6.20, __rpc_execute() is a void function. if (@defined($return)) { retstr = return_str(1, $return) } else { retstr = "N/A" } } /** * probe sunrpc.sched.delay - Delay an RPC task * * @xid: the transmission id in the RPC call * @prog: the program number in the RPC call * @vers: the program version in the RPC call * @prot: the IP protocol in the RPC call * @tk_pid: the debugging id of the task * @tk_flags: the flags of the task * @delay: the time delayed */ probe sunrpc.sched.delay = kernel.function("rpc_delay") !, module("sunrpc").function("rpc_delay") { xid = xid_from_clnt($task->tk_client) prog = prog_from_clnt($task->tk_client) vers = vers_from_clnt($task->tk_client) prot = prot_from_clnt($task->tk_client) tk_pid = $task->tk_pid tk_flags = $task->tk_flags delay = $delay name = "sunrpc.sched.delay" argstr = sprintf("%d %d %d %d %d %d %d", xid, prog, vers, prot, tk_pid, tk_flags, delay) } probe sunrpc.sched.delay.return = kernel.function("rpc_delay").return !, module("sunrpc").function("rpc_delay").return { name = "sunrpc.sched.delay.return" retstr = "N/A" } /****************************************************************** * Helper functions * *****************************************************************/ function xid_from_clnt:long(clnt:long) { if (clnt == 0) return 0 return @cast(clnt, "rpc_clnt", "kernel:sunrpc")->cl_xprt->xid } function prog_from_clnt:long(clnt:long) { if (clnt == 0) return 0 return @choose_defined(@cast(clnt, "rpc_clnt", "kernel:sunrpc")->cl_prog, @cast(clnt, "rpc_clnt", "kernel:sunrpc")->cl_pmap->pm_prog) } function vers_from_clnt:long(clnt:long) { if (clnt == 0) return 0 return @choose_defined(@cast(clnt, "rpc_clnt", "kernel:sunrpc")->cl_vers, @cast(clnt, "rpc_clnt", "kernel:sunrpc")->cl_pmap->pm_vers) } function prot_from_clnt:long(clnt:long) { if (clnt == 0) return 0 return @cast(clnt, "rpc_clnt", "kernel:sunrpc")->cl_xprt->prot } function port_from_xprt:long(cl_xprt:long) { if (cl_xprt == 0) return 0 addr = &@cast(cl_xprt, "rpc_xprt", "kernel:sunrpc")->addr if (addr == 0) return 0 /* In reality, 'cl_xprt->addr' is of 'sockaddr_storage' type * (since 2.6.19). But when used, you cast it to what is * inside that buffer. The 'struct sockaddr', 'struct * sockaddr_in', and 'sockaddr_in6' structures all have a * family type as their 1st member. */ if (@cast(addr, "sockaddr")->sa_family == %{ /* pure */ /* unprivileged */ AF_INET %}) { return ntohs(@cast(addr, "sockaddr_in")->sin_port) } else if (@cast(addr, "sockaddr")->sa_family == %{ /* pure */ /* unprivileged */ AF_INET6 %}) { return ntohs(@cast(addr, "sockaddr_in6")->sin6_port) } return 0 } function port_from_clnt:long(clnt:long) { if (clnt == 0) return 0 cl_xprt = @cast(clnt, "rpc_clnt", "kernel:sunrpc")->cl_xprt return port_from_xprt(cl_xprt) } function clones_from_clnt:long(clnt:long) { return (@defined(@cast(clnt, "rpc_clnt", "kernel:sunrpc")->cl_count) ? atomic_read(&@cast(clnt, "rpc_clnt", "kernel:sunrpc")->cl_count) : -1) } function tasks_from_clnt:long(clnt:long) { return (@defined(@cast(clnt, "rpc_clnt", "kernel:sunrpc")->cl_users) ? atomic_read(&@cast(clnt, "rpc_clnt", "kernel:sunrpc")->cl_users) : -1) } function proc_from_msg:long(msg:long) { if (msg == 0) return 0 return @cast(msg, "rpc_message", "kernel:sunrpc")->rpc_proc->p_proc } function vers_from_prog:long(program:long, vers:long) { if (program && vers < @cast(program, "rpc_program", "kernel:sunrpc")->nrvers) return @cast(program, "rpc_program", "kernel:sunrpc")->version[vers]->number return 0 } function addr_from_rqst:long(rqstp:long) { if (rqstp) { addr = &@cast(rqstp, "svc_rqst", "kernel:nfs")->rq_addr if (addr == 0) return 0 /* In reality, 'rq_addr' is of 'sockaddr_storage' type * (since 2.6.19). But when used, you cast it to what is * inside that buffer. The 'struct sockaddr', 'struct * sockaddr_in', and 'sockaddr_in6' structures all have a * family type as their 1st member. */ if (@cast(addr, "sockaddr")->sa_family == %{ /* pure */ /* unprivileged */ AF_INET %}) { return @cast(addr, "sockaddr_in")->sin_addr->s_addr } else if (@cast(addr, "sockaddr")->sa_family == %{ /* pure */ /* unprivileged */ AF_INET6 %}) { return &@cast(addr, "sockaddr_in6")->sin6_addr } } return 0 } function addr_from_rqst_str:string(rqstp:long) { if (rqstp == 0) return "Null" addr = &@cast(rqstp, "svc_rqst", "kernel:nfs")->rq_addr if (addr == 0) return "Null" s_addr = addr_from_rqst(rqstp) if (s_addr == 0) return "Unsupported Address Family" if (@cast(addr, "sockaddr_in")->sin_family == %{ /* pure */ /* unprivileged */ AF_INET %}) { return sprintf("%s:%d", format_ipaddr(s_addr, %{ /* pure */ /* unprivileged */ AF_INET %}), @cast(addr, "sockaddr_in")->sin_port) } return sprintf("[%s]:%d", format_ipaddr(s_addr, %{ /* pure */ /* unprivileged */ AF_INET6 %}), @cast(addr, "sockaddr_in6")->sin6_port) } systemtap-2.3/tapset/linux/s390/000077500000000000000000000000001217430427200165465ustar00rootroot00000000000000systemtap-2.3/tapset/linux/s390/aux_syscalls.stp000066400000000000000000000026601217430427200220140ustar00rootroot00000000000000# arch-specific requests of ptrace ___________________________ # %{ #ifndef PTRACE_GET_LAST_BREAK #define PTRACE_GET_LAST_BREAK 0x5006 #endif %} function _arch_ptrace_argstr(request, pid, addr, data) { if (request == %{ PTRACE_OLDSETOPTIONS %}) return sprintf ("PTRACE_OLDSETOPTIONS, %d, %s", pid, _ptrace_options_str (data)) if (request == %{ PTRACE_PEEKUSR_AREA %}) area="PTRACE_PEEKUSR_AREA" if (request == %{ PTRACE_POKEUSR_AREA %}) area="PTRACE_POKEUSR_AREA" if (request == %{ PTRACE_PEEKTEXT_AREA %}) area="PTRACE_PEEKTEXT_AREA" if (request == %{ PTRACE_PEEKDATA_AREA %}) area="PTRACE_PEEKDATA_AREA" if (request == %{ PTRACE_POKETEXT_AREA %}) area="PTRACE_POKETEXT_AREA" if (request == %{ PTRACE_POKEDATA_AREA %}) area="PTRACE_POKEDATA_AREA" if (area!="") // FIXME: ptrace of 32-bit debuggers is not caught by SystemTap, // use +4 and +8 offsets for them return sprintf ("%s, %d, {len=%d, kernel_addr=%p, process_addr=%p}", area, pid, user_int(addr), user_long(addr+8), user_long(addr+16)) if (request == %{ PTRACE_GET_LAST_BREAK %}) // TODO: Retrieve *data in return return sprintf ("PTRACE_GET_LAST_BREAK, %d, data=%p", pid, data) if (request == %{ PTRACE_PROT %}) // Not implemented in kernel return sprintf ("PTRACE_PROT, %d, addr=%p, data=%p", pid, addr, data) } function _ptrace_return_arch_prctl_addr:long(request:long, addr:long, data:long) { return 0 } systemtap-2.3/tapset/linux/s390/nd_syscalls.stp000066400000000000000000000166371217430427200216310ustar00rootroot00000000000000# S390-specific system calls %(arch == "s390" %? # getresgid __________________________________________________ # long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid) # probe nd_syscall.getresgid16 = kprobe.function("sys32_getresgid16") ? { name = "getresgid" // argstr = sprintf("%p, %p, %p", $rgid, $egid, $sgid) asmlinkage() argstr = sprintf("%p, %p, %p", pointer_arg(1), pointer_arg(2), pointer_arg(3)) } probe nd_syscall.getresgid16.return = kprobe.function("sys32_getresgid16").return ? { name = "getresgid" retstr = returnstr(1) } # getresuid __________________________________________________ # long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid) # probe nd_syscall.getresuid16 = kprobe.function("sys32_getresuid16") ? { name = "getresuid" // argstr = sprintf("%p, %p, %p", $ruid, $euid, $suid) asmlinkage() argstr = sprintf("%p, %p, %p", pointer_arg(1), pointer_arg(2), pointer_arg(3)) } probe nd_syscall.getresuid16.return = kprobe.function("sys32_getresuid16").return ? { name = "getresuid" retstr = returnstr(1) } # ipc _________________________________________________ # long sys32_ipc(u32 call, int first, int second, int third, u32 ptr) # probe nd_syscall.ipc = kprobe.function("sys32_ipc") ? { name = "ipc" // argstr = sprintf("%d, %d, %d, %d, %p", $call, $first, $second, $third, $ptr) asmlinkage() argstr = sprintf("%d, %d, %d, %d, %p", uint_arg(1), int_arg(2), int_arg(3), int_arg(4), uint_arg(5)) } probe nd_syscall.ipc.return = kprobe.function("sys_ipc").return ? { name = "ipc" retstr = returnstr(1) } # In kernels < 2.6.33, mmap()/mmap2() was handled by arch-specific # code. In kernels >= 2.6.33, the arch-specific code just calls # generic sys_mmap_pgoff(). %( kernel_v < "2.6.33" %? # mmap _________________________________________________ # long old_mmap(struct mmap_arg_struct __user *arg) # long old32_mmap(struct mmap_arg_struct_emu31 __user *arg) # probe nd_syscall.mmap = kprobe.function("old_mmap") ?, kprobe.function("old32_mmap") ?, kprobe.function("SyS_s390_old_mmap") ? { name = "mmap" // if ((symname(addr()) == "old_mmap") || (symname(addr()) == "SyS_s390_old_mmap")) // argstr = get_mmap_args($arg) // else // argstr = get_32mmap_args($arg) asmlinkage() if ((symname(addr()) == "old_mmap") || (symname(addr()) == "SyS_s390_old_mmap")) argstr = get_mmap_args(pointer_arg(1)) else argstr = get_32mmap_args(pointer_arg(1)) } probe nd_syscall.mmap.return = kprobe.function("old_mmap").return ?, kprobe.function("old32_mmap").return ?, kprobe.function("SyS_s390_old_mmap").return ? { name = "mmap" retstr = returnstr(2) } # mmap2 _________________________________________________ # # long sys_mmap2(struct mmap_arg_struct __user *arg) # long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg) # probe nd_syscall.mmap2 = kprobe.function("sys_mmap2") ?, kprobe.function("sys32_mmap2") ? { name = "mmap2" // if ((symname(addr()) == "sys_mmap2") || (symname(addr()) == "SyS_mmap2")) // argstr = get_mmap_args($arg) // else // argstr = get_32mmap_args($arg) asmlinkage() if ((symname(addr()) == "sys_mmap2") || (symname(addr()) == "SyS_mmap2")) argstr = get_mmap_args(pointer_arg(1)) else argstr = get_32mmap_args(pointer_arg(1)) } probe nd_syscall.mmap2.return = kprobe.function("sys_mmap2").return ?, kprobe.function("sys32_mmap2").return ? { name = "mmap2" retstr = returnstr(2) } %) %( CONFIG_GENERIC_SIGALTSTACK == "n" || kernel_v < "3.8" %? # sigaltstack ________________________________________________ # asmlinkage long # sys_sigaltstack(const stack_t __user * uss, stack_t __user *uoss) # # NOTE: args vary between archs. probe nd_syscall.sigaltstack = kprobe.function("sys_sigaltstack") { name = "sigaltstack" //uss_uaddr = $uss //uoss_uaddr = $uoss asmlinkage() uss_uaddr = pointer_arg(1) uoss_uaddr = pointer_arg(2) %(systemtap_v < "2.3" %? regs = %{ _stp_current_pt_regs() %} %) argstr = sprintf("%p, %p", uss_uaddr, uoss_uaddr) } probe nd_syscall.sigaltstack.return = kprobe.function("sys_sigaltstack").return { name = "sigaltstack" retstr = returnstr(1) } %) # sys32_sigaltstack ________________________________________________ # asmlinkage long # sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss) # # NOTE: args vary between archs. probe nd_syscall.sys32_sigaltstack = kprobe.function("sys32_sigaltstack") ? { name = "sys32_sigaltstack" argstr = "" } probe nd_syscall.sys32_sigaltstack.return = kprobe.function("sys32_sigaltstack").return ? { name = "sys32_sigaltstack" retstr = returnstr(1) } # sysctl _____________________________________________________ # # long sys32_sysctl(struct __sysctl_args32 __user *args) # probe nd_syscall.sysctl32 = kprobe.function("sys32_sysctl") ? { name = "sysctl" // argstr = sprintf("%p", $args) asmlinkage() argstr = sprintf("%p", pointer_arg(1)) } probe nd_syscall.sysctl32.return = kprobe.function("sys32_sysctl").return ? { name = "sysctl" retstr = returnstr(1) } /* compat */ function get_32mmap_args:string (args:long) %{ /* pure */ struct mmap_arg_struct_emu31 { u32 addr; u32 len; u32 prot; u32 flags; u32 fd; u32 offset; }a; char proto[60]; char flags[160]; if(_stp_copy_from_user((char *)&a, (char *)STAP_ARG_args, sizeof(a))== 0){ /* _mprotect_prot_str */ proto[0] = '\0'; if(a.prot){ if(a.prot & 1) strlcat (proto, "PROT_READ|", sizeof(proto)); if(a.prot & 2) strlcat (proto, "PROT_WRITE|", sizeof(proto)); if(a.prot & 4) strlcat (proto, "PROT_EXEC|", sizeof(proto)); } else { strlcat (proto, "PROT_NONE", sizeof(proto)); } if (proto[0] != '\0') proto[strlen(proto)-1] = '\0'; /* _mmap_flags */ flags[0]='\0'; if (a.flags & 1) strlcat (flags, "MAP_SHARED|", sizeof(flags)); if (a.flags & 2) strlcat (flags, "MAP_PRIVATE|", sizeof(flags)); if (a.flags & 0x10) strlcat (flags, "MAP_FIXED|", sizeof(flags)); if (a.flags & 0x20) strlcat (flags, "MAP_ANONYMOUS|", sizeof(flags)); if (a.flags & 0x100) strlcat (flags, "MAP_GROWSDOWN|", sizeof(flags)); if (a.flags & 0x800) strlcat (flags, "MAP_DENYWRITE|", sizeof(flags)); if (a.flags & 0x1000) strlcat (flags, "MAP_EXECUTABLE|", sizeof(flags)); if (a.flags & 0x2000) strlcat (flags, "MAP_LOCKED|", sizeof(flags)); if (a.flags & 0x4000) strlcat (flags, "MAP_NORESERVE|", sizeof(flags)); if (a.flags & 0x8000) strlcat (flags, "MAP_POPULATE|", sizeof(flags)); if (a.flags & 0x10000) strlcat (flags, "MAP_NONBLOCK|", sizeof(flags)); if (flags[0] != '\0') flags[strlen(flags)-1] = '\0'; snprintf (STAP_RETVALUE, MAXSTRINGLEN, "0x%x, %d, %s, %s, %d, %d", a.addr, a.len, proto, flags, a.fd, a.offset); }else{ strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); } %} %) systemtap-2.3/tapset/linux/s390/syscalls.stp000066400000000000000000000141571217430427200211430ustar00rootroot00000000000000# S390-specific system calls %(arch == "s390" %? # FIXME: the getresgid16/getresuid16 probes could be combined with # their "generic" versions in tapset/syscalls.stp. # getresgid __________________________________________________ # long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid) # probe syscall.getresgid16 = kernel.function("sys32_getresgid16") ? { name = "getresgid" rgid_uaddr = $rgid egid_uaddr = $egid sgid_uaddr = $sgid argstr = sprintf("%p, %p, %p", $rgid, $egid, $sgid) } probe syscall.getresgid16.return = kernel.function("sys32_getresgid16").return ? { name = "getresgid" retstr = return_str(1, $return) } # getresuid __________________________________________________ # long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid) # probe syscall.getresuid16 = kernel.function("sys32_getresuid16") ? { name = "getresuid" ruid_uaddr = $ruid euid_uaddr = $euid suid_uaddr = $suid argstr = sprintf("%p, %p, %p", $ruid, $euid, $suid) } probe syscall.getresuid16.return = kernel.function("sys32_getresuid16").return ? { name = "getresuid" retstr = return_str(1, $return) } # ipc _________________________________________________ # long sys32_ipc(u32 call, int first, int second, int third, u32 ptr) # probe syscall.ipc = kernel.function("sys32_ipc") ? { name = "ipc" argstr = sprintf("%d, %d, %d, %d, %p", $call, $first, $second, $third, $ptr) } probe syscall.ipc.return = kernel.function("sys_ipc").return ? { name = "ipc" retstr = return_str(1, $return) } # In kernels < 2.6.33, mmap()/mmap2() was handled by arch-specific # code. In kernels >= 2.6.33, the arch-specific code just calls # generic sys_mmap_pgoff(). %( kernel_v < "2.6.33" %? # mmap _________________________________________________ # long old_mmap(struct mmap_arg_struct __user *arg) # long old32_mmap(struct mmap_arg_struct_emu31 __user *arg) # probe syscall.mmap = kernel.function("old_mmap") ?, kernel.function("old32_mmap") ?, kernel.function("SyS_s390_old_mmap") ? { name = "mmap" if ((symname(addr()) == "old_mmap") || (symname(addr()) == "SyS_s390_old_mmap")) { start = user_long(&@cast($arg, "mmap_arg_struct")->addr) len = user_long(&@cast($arg, "mmap_arg_struct")->len) prot = user_long(&@cast($arg, "mmap_arg_struct")->prot) flags = user_long(&@cast($arg, "mmap_arg_struct")->flags) fd = user_long(&@cast($arg, "mmap_arg_struct")->fd) offset = user_long(&@cast($arg, "mmap_arg_struct")->offset) } else { start = user_int(&@cast($arg, "mmap_arg_struct_emu31")->addr) len = user_int(&@cast($arg, "mmap_arg_struct_emu31")->len) prot = user_int(&@cast($arg, "mmap_arg_struct_emu31")->prot) flags = user_int(&@cast($arg, "mmap_arg_struct_emu31")->flags) fd = user_int(&@cast($arg, "mmap_arg_struct_emu31")->fd) offset = user_int(&@cast($arg, "mmap_arg_struct_emu31")->offset) } argstr = sprintf("%p, %d, %s, %s, %d, %d", start, len, _mprotect_prot_str(prot), _mmap_flags(flags), fd, offset) } probe syscall.mmap.return = kernel.function("old_mmap").return ?, kernel.function("old32_mmap").return ?, kernel.function("SyS_s390_old_mmap").return ? { name = "mmap" retstr = return_str(2, $return) } # mmap2 _________________________________________________ # # long sys_mmap2(struct mmap_arg_struct __user *arg) # long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg) # probe syscall.mmap2 = kernel.function("sys_mmap2") ?, kernel.function("sys32_mmap2") ? { name = "mmap2" if ((symname(addr()) == "sys_mmap2") || (symname(addr()) == "SyS_mmap2")) { start = user_long(&@cast($arg, "mmap_arg_struct")->addr) length = user_long(&@cast($arg, "mmap_arg_struct")->len) prot = user_long(&@cast($arg, "mmap_arg_struct")->prot) flags = user_long(&@cast($arg, "mmap_arg_struct")->flags) fd = user_long(&@cast($arg, "mmap_arg_struct")->fd) pgoffset = user_long(&@cast($arg, "mmap_arg_struct")->offset) } else { start = user_int(&@cast($arg, "mmap_arg_struct_emu31")->addr) length = user_int(&@cast($arg, "mmap_arg_struct_emu31")->len) prot = user_int(&@cast($arg, "mmap_arg_struct_emu31")->prot) flags = user_int(&@cast($arg, "mmap_arg_struct_emu31")->flags) fd = user_int(&@cast($arg, "mmap_arg_struct_emu31")->fd) pgoffset = user_int(&@cast($arg, "mmap_arg_struct_emu31")->offset) } argstr = sprintf("%p, %d, %s, %s, %d, %d", start, length, _mprotect_prot_str(prot), _mmap_flags(flags), fd, pgoffset) } probe syscall.mmap2.return = kernel.function("sys_mmap2").return ?, kernel.function("sys32_mmap2").return ? { name = "mmap2" retstr = return_str(2, $return) } %) %( CONFIG_GENERIC_SIGALTSTACK == "n" || kernel_v < "3.8" %? # sigaltstack ________________________________________________ # asmlinkage long # sys_sigaltstack(const stack_t __user * uss, stack_t __user *uoss) # # NOTE: args vary between archs. probe syscall.sigaltstack = kernel.function("sys_sigaltstack") { name = "sigaltstack" uss_uaddr = $uss uoss_uaddr = $uoss %(systemtap_v < "2.3" %? regs = %{ _stp_current_pt_regs() %} %) argstr = sprintf("%p, %p", $uss, $uoss) } probe syscall.sigaltstack.return = kernel.function("sys_sigaltstack").return { name = "sigaltstack" retstr = return_str(1, $return) } %) # sys32_sigaltstack ________________________________________________ # asmlinkage long # sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss) # # NOTE: args vary between archs. probe syscall.sys32_sigaltstack = kernel.function("sys32_sigaltstack") ? { name = "sys32_sigaltstack" argstr = "" } probe syscall.sys32_sigaltstack.return = kernel.function("sys32_sigaltstack").return ? { name = "sys32_sigaltstack" retstr = return_str(1, $return) } # sysctl _____________________________________________________ # # long sys32_sysctl(struct __sysctl_args32 __user *args) # probe syscall.sysctl32 = kernel.function("sys32_sysctl") ? { name = "sysctl" argstr = sprintf("%p", $args) } probe syscall.sysctl32.return = kernel.function("sys32_sysctl").return ? { name = "sysctl" retstr = return_str(1, $return) } %) systemtap-2.3/tapset/linux/scheduler.stp000066400000000000000000000276521217430427200205720ustar00rootroot00000000000000// scheduler tapset // Copyright (C) 2006 Intel Corporation. // Copyright (C) 2005, 2006 IBM Corp. // Copyright (C) 2010 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. function __is_idle:long() %{ /* pure */ /* Ways to detect idle-ness: * - pid() or tid() == 0 * - current == current->parent * - current == this_rq()->idle * - others? */ STAP_RETVALUE = (current->pid == 0); %} /** * probe scheduler.cpu_off - Process is about to stop running on a cpu * * @name: name of the probe point * @task_prev: the process leaving the cpu (same as current) * @task_next: the process replacing current * @idle: boolean indicating whether current is the idle process * * Context: The process leaving the cpu. * */ probe scheduler.cpu_off = kernel.trace("sched_switch") !, kernel.function("context_switch") { name = "cpu_off" task_prev = $prev task_next = $next idle = __is_idle() } /** * probe scheduler.cpu_on - Process is beginning execution on a cpu * * @name: name of the probe point * @task_prev: the process that was previously running on this cpu * @idle:- boolean indicating whether current is the idle process * * Context: The resuming process. */ probe scheduler.cpu_on = kernel.function("finish_task_switch") ? { name = "cpu_on" task_prev = $prev idle = __is_idle() } /** * probe scheduler.tick - Schedulers internal tick, a processes timeslice accounting is updated * * @name: name of the probe point * @idle: boolean indicating whether current is the idle process * * Context: The process whose accounting will be updated. */ probe scheduler.tick = kernel.function("scheduler_tick") { name = "tick" idle = __is_idle() } /** * probe scheduler.balance - A cpu attempting to find more work. * * @name: name of the probe point * * Context: The cpu looking for more work. */ probe scheduler.balance = kernel.function("idle_balance") ? { name = "balance" } /** * probe scheduler.ctxswitch - A context switch is occuring. * * @name: name of the probe point * @prev_pid: The PID of the process to be switched out * @next_pid: The PID of the process to be switched in * @prev_tid: The TID of the process to be switched out * @next_tid: The TID of the process to be switched in * @prev_task_name: The name of the process to be switched out * @next_task_name: The name of the process to be switched in * @prev_priority: The priority of the process to be switched out * @next_priority: The priority of the process to be switched in * @prevtsk_state: the state of the process to be switched out * @nexttsk_state: the state of the process to be switched in */ /* * We prefer the "sched_switch" tracepoint here, since we can reliably * access the tracepoint's arguments. If we don't have the * tracepoint, we try function probing. But these are typically * inlined, and SystemTap can't access arguments of inline functions * consistently. So we choose to probe __switch_to() instead of * context_switch() on some platforms. * * Since the argument names for the tracepoint ("$prev" and "$next") * match up with the function argument names, handling either the * tracepoint or function here was made easier. */ probe scheduler.ctxswitch = kernel.trace("sched_switch") !, %( arch != "x86_64" && arch != "ia64" && arch != "arm" %? kernel.function("__switch_to") %: kernel.function("context_switch") %) { name = "ctxswitch" /* * Note that we prefer '$prev_p' here because on RHEL5 * (2.6.18-238.1.1.el5) the '__switch_to()' function has both * a '$prev_p' and a '$prev' argument. Since '$prev_p' is of * the correct type (struct task_struct *), we need to look * for it first. */ if (@defined($prev_p)) { prev_priority = $prev_p->prio prev_pid = $prev_p->tgid prev_tid = $prev_p->pid prev_task = $prev_p prev_task_name = task_execname($prev_p) prevtsk_state = $prev_p->state } else { prev_priority = $prev->prio prev_pid = $prev->tgid prev_tid = $prev->pid prev_task = $prev prev_task_name = task_execname($prev) prevtsk_state = $prev->state } if (@defined($next)) { next_priority = $next->prio next_pid = $next->tgid next_tid = $next->pid next_task = $next next_task_name = task_execname($next) nexttsk_state = $next->state } else if (@defined($next_p)) { next_priority = $next_p->prio next_pid = $next_p->tgid next_tid = $next_p->pid next_task = $next_p next_task_name = task_execname($next_p) nexttsk_state = $next_p->state } else { next_priority = $new->prio next_pid = $new->tgid next_tid = $new->pid next_task = $new next_task_name = task_execname($new) nexttsk_state = $new->state } } /** * probe scheduler.kthread_stop - A thread created by kthread_create is being stopped * @thread_pid: PID of the thread being stopped * @thread_priority: priority of the thread */ probe __scheduler.kthread_stop.kp = kernel.function("kthread_stop") { thread_pid = $k->tgid thread_priority = $k->prio } probe __scheduler.kthread_stop.tp = kernel.trace("sched_kthread_stop") { thread_pid = $t->tgid thread_priority = $t->prio } probe scheduler.kthread_stop = __scheduler.kthread_stop.tp !, __scheduler.kthread_stop.kp { name = "kthread_stop" } /** * probe scheduler.kthread_stop.return - A kthread is stopped and gets the return value * @name: name of the probe point * @return_value: return value after stopping the thread */ probe __scheduler.kthread_stop.return.kp = kernel.function("kthread_stop").return { return_value = $k->exit_code } probe __scheduler.kthread_stop.return.tp = kernel.trace("sched_kthread_stop_ret") { return_value = $ret } probe scheduler.kthread_stop.return = __scheduler.kthread_stop.return.tp !, __scheduler.kthread_stop.return.kp { name = "kthread_stop" } /** * probe scheduler.wait_task - Waiting on a task to unschedule (become inactive) * @name: name of the probe point * @task_pid: PID of the task the scheduler is waiting on * @task_priority: priority of the task */ probe scheduler.wait_task = kernel.trace("sched_wait_task") !, kernel.function("wait_task_inactive") ? { name = "wait_task" task_pid = $p->tgid task_priority = $p->prio } /** * probe scheduler.wakeup - Task is woken up * @name: name of the probe point * @task_pid: PID of the task being woken up * @task_priority: priority of the task being woken up * @task_cpu: cpu of the task being woken up * @task_state: state of the task being woken up * @task_tid: tid of the task being woken up */ probe scheduler.wakeup = kernel.trace("sched_wakeup") !, kernel.function("try_to_wake_up") { name = "wakeup" task = $p task_pid = $p->tgid task_tid = $p->pid task_priority = $p->prio task_cpu = task_cpu($p) task_state = task_state($p) } /** * probe scheduler.wakeup_new - Newly created task is woken up for the first time * @name: name of the probe point * @task_pid: PID of the new task woken up * @task_priority: priority of the new task * @task_tid: TID of the new task woken up * @task_state: state of the task woken up * @task_cpu: cpu of the task woken up */ probe scheduler.wakeup_new = kernel.trace("sched_wakeup_new") !, kernel.function("wake_up_new_task") { name = "wakeup_new" task_pid = $p->tgid task_priority = $p->prio task_cpu = task_cpu($p) task_state = task_state($p) task = $p task_tid = $p->pid } /** * probe scheduler.migrate - Task migrating across cpus * @name: name of the probe point * @task: the process that is being migrated * @pid: PID of the task being migrated * @priority: priority of the task being migrated * @cpu_from: the original cpu * @cpu_to: the destination cpu */ probe __scheduler.migrate.kp = kernel.function("set_task_cpu") !, kernel.function("pull_task") ? { cpu_to = @choose_defined($new_cpu, @choose_defined($cpu, $this_cpu)) } probe __scheduler.migrate.tp = kernel.trace("sched_migrate_task") { cpu_to = $dest_cpu } probe scheduler.migrate = __scheduler.migrate.tp !, __scheduler.migrate.kp ? { name = "migrate" task = $p pid = $p->tgid priority = $p->prio cpu_from = task_cpu($p) } function container_of_task_rcu:long(rcu_ptr:long) { if (@defined(&@cast(0, "task_struct", "kernel")->rcu)) { /* * The following is the script language equivalent of: * * return container_of(rcu_ptr, struct task_struct, rcu); * * More spelled out, that would look like: * * return (rcu_ptr - offsetof(struct task_struct, rcu)); * * Notice we're casting 0 here on purpose to find the * offset of the 'rcu' member of 'struct task_struct'. */ offset = &@cast(0, "task_struct", "kernel")->rcu if (rcu_ptr > offset) return (rcu_ptr - offset) } return 0 } /** * probe scheduler.process_free - Scheduler freeing a data structure for a process * @name: name of the probe point * @pid: PID of the process getting freed * @priority: priority of the process getting freed */ probe __scheduler.process_free.kp = kernel.function("delayed_put_task_struct") !, kernel.function("__put_task_struct") { if (@defined($rhp)) { __tsk = container_of_task_rcu($rhp) pid = @cast(__tsk, "task_struct", "kernel")->tgid priority = @cast(__tsk, "task_struct", "kernel")->prio } else { pid = $tsk->tgid priority = $tsk->prio } } probe __scheduler.process_free.tp = kernel.trace("sched_process_free") { pid = $p->tgid priority = $p->prio } probe scheduler.process_free = __scheduler.process_free.tp !, __scheduler.process_free.kp { name = "process_free" } /** * probe scheduler.process_exit - Process exiting * @name: name of the probe point * @pid: PID of the process exiting * @priority: priority of the process exiting */ probe __scheduler.process_exit.kp = kernel.function("do_exit") { if (@defined($tsk)) { __tsk = $tsk pid = $tsk->tgid priority = $tsk->prio } else { __tsk = task_current() pid = @cast(__tsk, "task_struct", "kernel")->tgid priority = @cast(__tsk, "task_struct", "kernel")->prio } } probe __scheduler.process_exit.tp = kernel.trace("sched_process_exit") { pid = $p->tgid priority = $p->prio } probe scheduler.process_exit = __scheduler.process_exit.tp !, __scheduler.process_exit.kp { name = "process_exit" } /** * probe scheduler.process_wait - Scheduler starting to wait on a process * @name: name of the probe point * @pid: PID of the process scheduler is waiting on */ probe __scheduler.process_wait.kp = kernel.function("do_wait") { if (@defined($wo)) { pid = $wo->wo_pid } else { pid = $pid } } probe __scheduler.process_wait.tp = kernel.trace("sched_process_wait") { pid = $pid } probe scheduler.process_wait = __scheduler.process_wait.tp !, __scheduler.process_wait.kp { name = "process_wait" } /** * probe scheduler.process_fork - Process forked * @name: name of the probe point * @parent_pid: PID of the parent process * @child_pid: PID of the child process */ probe __scheduler.process_fork.kp = kernel.function("do_fork").return { parent_pid = @cast(task_current(), "task_struct", "kernel")->tgid child_pid = $return } probe __scheduler.process_fork.tp = kernel.trace("sched_process_fork") { parent_pid = $parent->tgid child_pid = $child->tgid } probe scheduler.process_fork = __scheduler.process_fork.tp !, __scheduler.process_fork.kp { name = "process_fork" } /** * probe scheduler.signal_send - Sending a signal * @name: name of the probe point * @pid: pid of the process sending signal * @signal_number: signal number */ probe __scheduler.signal_send.kp = kernel.function("__send_signal") !, kernel.function("send_signal") { pid = $t->tgid } probe __scheduler.signal_send.tp = kernel.trace("sched_signal_send") { pid = $p->tgid } probe scheduler.signal_send = __scheduler.signal_send.tp !, __scheduler.signal_send.kp { name = "signal_send" signal_number = $sig } systemtap-2.3/tapset/linux/scsi.stp000066400000000000000000000224601217430427200175450ustar00rootroot00000000000000// scsi tapset // Copyright (C) 2005, 2006, 2009 IBM Corp. // Copyright (C) 2010 Red Hat // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // This family of probe points is used to probe SCSI activities. // %{ #include #include #include #include #include #include %} function describe_data_direction:string(state:long) %{ /* pure */ switch ((long)STAP_ARG_state) { case DMA_BIDIRECTIONAL: strlcpy(STAP_RETVALUE, "BIDIRECTIONAL", MAXSTRINGLEN); break; case DMA_TO_DEVICE: strlcpy(STAP_RETVALUE, "TO_DEVICE", MAXSTRINGLEN); break; case DMA_FROM_DEVICE: strlcpy(STAP_RETVALUE, "FROM_DEVICE", MAXSTRINGLEN); break; case DMA_NONE: strlcpy(STAP_RETVALUE, "NONE", MAXSTRINGLEN); break; default: strlcpy(STAP_RETVALUE, "[INVALID]", MAXSTRINGLEN); } %} function describe_device_state:string(state:long) %{ /* pure */ switch ((long)STAP_ARG_state) { case SDEV_CREATED: strlcpy(STAP_RETVALUE, "CREATED", MAXSTRINGLEN); break; case SDEV_RUNNING: strlcpy(STAP_RETVALUE, "RUNNING", MAXSTRINGLEN); break; case SDEV_CANCEL: strlcpy(STAP_RETVALUE, "CANCEL", MAXSTRINGLEN); break; case SDEV_DEL: strlcpy(STAP_RETVALUE, "DEL", MAXSTRINGLEN); break; case SDEV_QUIESCE: strlcpy(STAP_RETVALUE, "QUIESCE", MAXSTRINGLEN); break; case SDEV_OFFLINE: strlcpy(STAP_RETVALUE, "OFFLINE", MAXSTRINGLEN); break; #ifdef SDEV_BLOCK case SDEV_BLOCK: strlcpy(STAP_RETVALUE, "BLOCK", MAXSTRINGLEN); break; #endif #ifdef SDEV_CREATED_BLOCK case SDEV_CREATED_BLOCK: strlcpy(STAP_RETVALUE, "CREATED_BLOCK", MAXSTRINGLEN); break; #endif default: strlcpy(STAP_RETVALUE, "[INVALID]", MAXSTRINGLEN); } %} /** * probe scsi.ioentry - Prepares a SCSI mid-layer request * @disk_major: The major number of the disk (-1 if no information) * @disk_minor: The minor number of the disk (-1 if no information) * @device_state: The current state of the device * @device_state_str: The current state of the device, as a string * @req_addr: The current struct request pointer, as a number */ probe scsi.ioentry.scsilib = module("scsi_mod").function("scsi_prep_fn")!, kernel.function("scsi_prep_fn") { } probe scsi.ioentry.sd = module("sd_mod").function("sd_prep_fn")!, kernel.function("sd_prep_fn") { } probe scsi.ioentry.sr = module("sr_mod").function("sr_prep_fn")!, kernel.function("sr_prep_fn") { } probe scsi.ioentry = scsi.ioentry.* ? { req_addr = @choose_defined($req, $rq); if(@cast(req_addr,"request")->rq_disk == 0) { disk_major = -1 disk_minor = -1 } else { disk_major = @cast(req_addr,"request")->rq_disk->major disk_minor = @cast(req_addr,"request")->rq_disk->first_minor } device_state = get_devstate_from_req($q) device_state_str = describe_device_state(device_state) } /** * probe scsi.iodispatching - SCSI mid-layer dispatched low-level SCSI command * @host_no: The host number * @channel: The channel number * @lun: The lun number * @dev_id: The scsi device id * @device_state: The current state of the device * @device_state_str: The current state of the device, as a string * @data_direction: The data_direction specifies whether this command is from/to the device * 0 (DMA_BIDIRECTIONAL), 1 (DMA_TO_DEVICE), * 2 (DMA_FROM_DEVICE), 3 (DMA_NONE) * @data_direction_str: Data direction, as a string * @request_buffer: The request buffer address * @request_bufflen: The request buffer length * @req_addr: The current struct request pointer, as a number */ probe scsi.iodispatching = module("scsi_mod").function("scsi_dispatch_cmd@drivers/scsi/scsi.c")!, kernel.function("scsi_dispatch_cmd@drivers/scsi/scsi.c")? { host_no = $cmd->device->host->host_no channel = $cmd->device->channel lun = $cmd->device->lun dev_id = $cmd->device->id device_state = $cmd->device->sdev_state device_state_str = describe_device_state(device_state) data_direction = $cmd->sc_data_direction data_direction_str = describe_data_direction(data_direction) request_buffer = @choose_defined($cmd->sdb->table->sgl, $cmd->request_buffer) request_bufflen = @choose_defined($cmd->sdb->length, $cmd->request_bufflen) req_addr = $cmd->request } /** * probe scsi.iodone - SCSI command completed by low level driver and enqueued into the done queue. * @host_no: The host number * @channel: The channel number * @lun: The lun number * @dev_id: The scsi device id * @device_state: The current state of the device * @device_state_str: The current state of the device, as a string * @data_direction: The data_direction specifies whether this command is * from/to the device. * @data_direction_str: Data direction, as a string * @req_addr: The current struct request pointer, as a number * @scsi_timer_pending: 1 if a timer is pending on this request */ probe scsi.iodone = module("scsi_mod").function("scsi_done@drivers/scsi/scsi.c")!, kernel.function("scsi_done@drivers/scsi/scsi.c")? { host_no = $cmd->device->host->host_no channel = $cmd->device->channel lun = $cmd->device->lun dev_id = $cmd->device->id device_state = $cmd->device->sdev_state device_state_str = describe_device_state(device_state) data_direction = $cmd->sc_data_direction data_direction_str = describe_data_direction(data_direction) req_addr = $cmd->request scsi_timer_pending = scsi_timer_pending($cmd); } /** * probe scsi.iocompleted - SCSI mid-layer running the completion processing for block device I/O requests * @host_no: The host number * @channel: The channel number * @lun: The lun number * @dev_id: The scsi device id * @device_state: The current state of the device * @device_state_str: The current state of the device, as a string * @data_direction: The data_direction specifies whether this command is from/to * the device * @data_direction_str: Data direction, as a string * @goodbytes: The bytes completed * @req_addr: The current struct request pointer, as a number */ // mid-layer processes the completed IO probe scsi.iocompleted = module("scsi_mod").function("scsi_io_completion@drivers/scsi/scsi_lib.c")!, kernel.function("scsi_io_completion@drivers/scsi/scsi_lib.c")? { host_no = $cmd->device->host->host_no channel = $cmd->device->channel lun = $cmd->device->lun dev_id = $cmd->device->id device_state = $cmd->device->sdev_state device_state_str = describe_device_state(device_state) data_direction = $cmd->sc_data_direction data_direction_str = describe_data_direction(data_direction) req_addr = $cmd->request goodbytes = $good_bytes } function timer_pending:long(timer:long) { return (@choose_defined(@cast(timer, "timer_list")->entry->next, @cast(timer, "timer_list")->base) != 0) } function scsi_timer_pending:long(cmd:long) { %( kernel_v >= "2.6.28" %? return timer_pending(&@cast(cmd, "scsi_cmnd", "kernel:scsi_mod")->request->q->timeout) %: return timer_pending(&@cast(cmd, "scsi_cmnd", "kernel:scsi_mod")->eh_timeout) %) } function get_devstate_from_req:long(var:long) { sdev = @cast(var, "request_queue", "kernel:scsi_mod")->queuedata return @cast(sdev, "scsi_device", "kernel:scsi_mod")->sdev_state } /** * probe scsi.ioexecute - Create mid-layer SCSI request and wait for the result * @host_no: The host number * @channel: The channel number * @lun: The lun number * @dev_id: The scsi device id * @device_state: The current state of the device * @device_state_str: The current state of the device, as a string * @data_direction: The data_direction specifies whether this command is * from/to the device. * @data_direction_str: Data direction, as a string * @request_buffer: The data buffer address * @request_bufflen: The data buffer buffer length * @timeout: Request timeout in seconds * @retries: Number of times to retry request */ probe scsi.ioexecute = module("scsi_mod").function("scsi_execute@drivers/scsi/scsi_lib.c")!, kernel.function("scsi_execute@drivers/scsi/scsi_lib.c")? { host_no = $sdev->host->host_no channel = $sdev->channel lun = $sdev->lun dev_id = $sdev->id device_state = $sdev->sdev_state device_state_str = describe_device_state(device_state) data_direction = $data_direction data_direction_str = describe_data_direction(data_direction) request_buffer = $buffer request_bufflen = $bufflen timeout = $timeout retries = $retries } /** * probe scsi.set_state - Order SCSI device state change * @host_no: The host number * @channel: The channel number * @lun: The lun number * @dev_id: The scsi device id * @old_state: The current state of the device * @old_state_str: The current state of the device, as a string * @state: The new state of the device * @state_str: The new state of the device, as a string */ probe scsi.set_state = module("scsi_mod").function("scsi_device_set_state@drivers/scsi/scsi_lib.c")!, kernel.function("scsi_device_set_state@drivers/scsi/scsi_lib.c")? { state = $state state_str = describe_device_state(state) host_no = $sdev->host->host_no channel = $sdev->channel lun = $sdev->lun dev_id = $sdev->id old_state = $sdev->sdev_state old_state_str = describe_device_state(old_state) } systemtap-2.3/tapset/linux/signal.stp000066400000000000000000000675011217430427200200660ustar00rootroot00000000000000// Signal tapset // Copyright (C) 2006 IBM Corp. // Copyright (C) 2006 Intel Corporation. // Copyright (C) 2008-2010 Red Hat, Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // // // This family of probe points is used to probe signal activities. // Since there are so many signals sent to processes at any given // point, it is advisable to filter the information according to the // requirements. For example, filter only for a particular signal // (if sig==2) or for a particular process (if pid_name==stap). // /** * probe signal.send - Signal being sent to a process * Arguments: * @sig: The number of the signal * @sig_name: A string representation of the signal * @sig_pid: The PID of the process receiving the signal * @pid_name: The name of the signal recipient * @si_code: Indicates the signal type * @task: A task handle to the signal recipient * @sinfo: The address of siginfo struct * @shared: Indicates whether the signal is shared by the thread group * @send2queue: Indicates whether the signal is sent to an existing * sigqueue (deprecated in SystemTap 2.1) * @name: The name of the function used to send out the signal * * Context: * The signal's sender. * */ probe signal.send = __signal.send.signal_generate !, __signal.send.send_sigqueue, %( kernel_v > "2.6.25" %? __signal.send.send_signal ? %: __signal.send.group_send_sig_info ?, __signal.send.send_group_sigqueue ?, __signal.send.specific_send_sig_info ? %) { sig_name = _signal_name(sig) sig_pid = task_pid(task) pid_name = task_execname(task) if (sinfo == 2) # 2 == SEND_SIG_FORCED si_code ="SIGSTOP or SIGKILL" else if (sinfo > 0) si_code="SI_KERNEL (SIGFPE, SIGSEGV, SIGTRAP, SIGCHLD, SIGPOLL)" else if (sinfo <= 0) si_code="SI_USER or SI_TIMER or SI_ASYNCIO" } probe __signal.send.signal_generate = kernel.trace("signal_generate") ? { name = "signal_generate" sig = $sig task = $task sinfo = $info shared = (@choose_defined($group, 0) == 0) ? 0 : 1 %( systemtap_v <= "2.1" %? send2queue = 0 %) } probe __signal.send.send_sigqueue = kernel.function("send_sigqueue") { name = "send_sigqueue" task = @choose_defined($t, $p) sig = @choose_defined($q->info->si_signo, $sig) sinfo = @choose_defined($q->info, 0) shared = 0 %( systemtap_v <= "2.1" %? send2queue = 1 %) } probe __signal.send.send_signal = kernel.function("__send_signal") !, kernel.function("send_signal") ? { if (@defined($group)) { name = "__send_signal" shared = ($group == 0) ? 0 : 1 } else { name = "send_signal" shared = 0 } sig = $sig task = $t sinfo = $info %( systemtap_v <= "2.1" %? send2queue = 0 %) } probe __signal.send.group_send_sig_info = kernel.function("__group_send_sig_info") { name = "__group_send_sig_info" sig = $sig task = $p sinfo = $info shared = 1 %( systemtap_v <= "2.1" %? send2queue = 0 %) } probe __signal.send.send_group_sigqueue = kernel.function("send_group_sigqueue") { name = "send_group_sigqueue" sig = $sig task = $p sinfo = 0 # $q->info shared = 1 %( systemtap_v <= "2.1" %? send2queue = 1 %) } probe __signal.send.specific_send_sig_info = kernel.function("specific_send_sig_info").call { name = "specific_send_sig_info" sig = $sig task = $t sinfo = $info shared = 0 %( systemtap_v <= "2.1" %? send2queue = 0 %) } %( systemtap_v <= "2.1" %? /** * probe signal.send.return - Signal being sent to a process completed (deprecated in SystemTap 2.1) * @retstr: The return value to either __group_send_sig_info, specific_send_sig_info, or send_sigqueue * @shared: Indicates whether the sent signal is shared by the thread group. * @send2queue: Indicates whether the sent signal was sent to an existing sigqueue * @name: The name of the function used to send out the signal * * Context: * The signal's sender. (correct?) * * Possible __group_send_sig_info and * specific_send_sig_info return values are as follows; * * 0 -- The signal is successfully sent to a process, * which means that, (1) the signal was ignored by the receiving process, * (2) this is a non-RT signal and the system already has one queued, and * (3) the signal was successfully added to the sigqueue of the receiving process. * * -EAGAIN -- The sigqueue of the receiving process is * overflowing, the signal was RT, and the signal was sent by a user using something other * than kill(). * * Possible send_group_sigqueue and * send_sigqueue return values are as follows; * * 0 -- The signal was either successfully added into the * sigqueue of the receiving process, or a SI_TIMER entry is already * queued (in which case, the overrun count will be simply incremented). * * 1 -- The signal was ignored by the receiving process. * * -1 -- (send_sigqueue only) The task was marked * exiting, allowing * posix_timer_event to redirect it to the group * leader. * */ probe signal.send.return = __signal.send.send_sigqueue.return, %( kernel_v > "2.6.25" %? __signal.send.send_signal.return ? %: __signal.send.group_send_sig_info.return ?, __signal.send.send_group_sigqueue.return ?, __signal.send.specific_send_sig_info.return ? %) { retstr = return_str(1, $return) } // - return 0 if the signal is either sucessfully added into the // sigqueue of receiving process or a SI_TIMER entry is already // queued so just increment the overrun count // // - return 1 if this signal is ignored by receiving process // // - return -1 if the task is marked exiting, so posix_timer_event // can redirect it to the group leader probe __signal.send.send_sigqueue.return = kernel.function("send_sigqueue").return ? { name = "send_sigqueue" shared = 0 send2queue = 1 } probe __signal.send.send_signal.return = kernel.function("__send_signal").return !, kernel.function("send_signal").return ? { if (@defined($group)) { name = "__send_signal" shared = ($group == 0) ? 0 : 1 } else { name = "send_signal" shared = 0 } send2queue = 0 } // Return values for "__group_send_sig_info" and "specific_send_sig_info" // // - return 0 if the signal is successfully sent to a process, // which means the following: // <1> the signal is ignored by receiving process // <2> this is a non-RT signal and we already have one queued // <3> the signal is successfully added into the sigqueue of // receiving process // // - return -EAGAIN if the sigqueue is overflow the signal was RT // and sent by user using something other than kill() probe __signal.send.group_send_sig_info.return = kernel.function("__group_send_sig_info").return { name = "__group_send_sig_info" shared = 1 send2queue = 0 } probe __signal.send.specific_send_sig_info.return = kernel.function("specific_send_sig_info").return { name = "specific_send_sig_info" shared = 0 send2queue = 0 } // - return 0 if the signal is either successfully added into the // sigqueue of receiving process or a SI_TIMER entry is already // queued so just increment the overrun count // // - return 1 if this signal is ignored by receiving process probe __signal.send.send_group_siggueue.return = kernel.function("send_group_sigqueue").return { name = "send_group_sigqueue" shared = 1 send2queue = 1 } %) /** * probe signal.checkperm - Check being performed on a sent signal * @sig: The number of the signal * @sig_name: A string representation of the signal * @sig_pid: The PID of the process receiving the signal * @pid_name: Name of the process receiving the signal * @si_code: Indicates the signal type * @task: A task handle to the signal recipient * @sinfo: The address of the siginfo structure * @name: Name of the probe point */ probe signal.checkperm = kernel.function("check_kill_permission") { sig = $sig task = $t sinfo = $info name = "checkperm" sig_name = _signal_name($sig) sig_pid = task_pid(task) pid_name = task_execname(task) if (sinfo == 2) si_code ="SIGSTOP or SIGKILL" else if (sinfo > 0) si_code="SI_KERNEL (SIGFPE, SIGSEGV, SIGTRAP, SIGCHLD, SIGPOLL)" else if (sinfo <= 0) si_code="SI_USER or SI_TIMER or SI_ASYNCIO" } /** * probe signal.checkperm.return - Check performed on a sent signal completed * @name: Name of the probe point * @retstr: Return value as a string */ probe signal.checkperm.return = kernel.function("check_kill_permission").return { name = "checkperm" retstr = return_str(1, $return) } /** * probe signal.wakeup - Sleeping process being wakened for signal * @sig_pid: The PID of the process to wake * @pid_name: Name of the process to wake * @resume: Indicates whether to wake up a task in a * STOPPED or TRACED state * @state_mask: A string representation indicating the mask * of task states to wake. Possible values are * TASK_INTERRUPTIBLE, TASK_STOPPED, * TASK_TRACED, TASK_WAKEKILL, and TASK_INTERRUPTIBLE. */ probe __signal.wakeup.signal_wake_up_state = kernel.function("signal_wake_up_state") { resume = ($state == 0) ? 0 : 1; if ($state & %{ __TASK_STOPPED %} != 0) { state_mask .= " | TASK_STOPPED" } if ($state & %{ __TASK_TRACED %} != 0) { state_mask .= " | TASK_TRACED" } if ($state & %{ TASK_WAKEKILL %} != 0) { state_mask .= " | TASK_WAKEKILL" } state_mask = "TASK_INTERRUPTIBLE" . state_mask } probe __signal.wakeup.signal_wake_up = kernel.function("signal_wake_up") { resume = $resume if (resume == 0) { state_mask = "TASK_INTERRUPTIBLE" } else { state_mask = "TASK_INTERRUPTIBLE | TASK_STOPPED | TASK_TRACED" } } probe signal.wakeup = __signal.wakeup.signal_wake_up_state !, __signal.wakeup.signal_wake_up { name = "wakeup" sig_pid = $t->pid pid_name = kernel_string($t->comm) } /** * probe signal.check_ignored - Checking to see signal is ignored * @sig_pid: The PID of the process receiving the signal * @pid_name: Name of the process receiving the signal * @sig: The number of the signal * @sig_name: A string representation of the signal */ probe signal.check_ignored = kernel.function("sig_ignored") { name = "check_ignored" sig_pid = $t->pid pid_name = kernel_string($t->comm) sig = $sig sig_name = _signal_name($sig) } /** * probe signal.check_ignored.return - Check to see signal is ignored completed * @name: Name of the probe point * @retstr: Return value as a string */ /* On newer kernels, sig_ignored() is inline, so we can't do a return * probe. So, instead we'll probe prepare_signal(), which is the only * caller of sig_ignored(). */ probe __signal.check_ignored.sig_ignored.return = kernel.function("sig_ignored").return { retstr = return_str(1, $return) } probe __signal.check_ignored.prepare_signal.return = kernel.function("prepare_signal").return { /* The prepare_signal() function inverts the return value of * sig_ignored(). */ retstr = return_str(1, !$return) } probe signal.check_ignored.return = __signal.check_ignored.sig_ignored.return !, __signal.check_ignored.prepare_signal.return { name = "check_ignored" } // probe signal.handle_stop // For now, just comment it out since at the time handle_stop_signal() // is called, it doesn't know whether current signal is STOP/COUNT. // So the calling of handle_stop_signal() doesn't mean that the Kernel // is now processing the STOP/COUNT signal // /* probe signal.handle_stop = kernel.function("handle_stop_signal") { sig_pid = $p->pid pid_name = kernel_string($p->comm) sig_info = $sig sig_name = _signal_name($sig) } */ /** * probe signal.force_segv - Forcing send of SIGSEGV * @sig_pid: The PID of the process receiving the signal * @pid_name: Name of the process receiving the signal * @sig: The number of the signal * @sig_name: A string representation of the signal * @name: Name of the probe point */ probe signal.force_segv = _signal.force_segv.* { name = "force_segv" } probe _signal.force_segv.part1 = kernel.function("force_sigsegv") { sig_pid = $p->pid pid_name = kernel_string($p->comm) sig = $sig sig_name = _signal_name($sig) } probe _signal.force_segv.part2 = kernel.function("force_sigsegv_info") ? { sig_pid = pid() pid_name = execname() sig = $sig sig_name = _signal_name($sig) } /** * probe signal.force_segv.return - Forcing send of SIGSEGV complete * @name: Name of the probe point * @retstr: Return value as a string */ probe signal.force_segv.return = kernel.function("force_sigsegv").return, kernel.function("force_sigsegv_info").return ? { name = "force_segv" retstr = return_str(1, $return) } /** * probe signal.syskill - Sending kill signal to a process * @name: Name of the probe point * @sig: The specific signal sent to the process * @sig_name: A string representation of the signal * @sig_pid: The PID of the process receiving the signal * @pid_name: The name of the signal recipient */ probe signal.syskill = syscall.kill { name = "syskill" sig_name = _signal_name($sig) sig_pid = $pid pid_name = task_execname($pid) } /** * probe signal.syskill.return - Sending kill signal completed */ probe signal.syskill.return = syscall.kill.return { name = "syskill" } /** * probe signal.sys_tkill - Sending a kill signal to a thread * @name: Name of the probe point * @sig_pid: The PID of the process receiving the kill signal * @pid_name: The name of the signal recipient * @sig: The specific signal sent to the process * @sig_name: A string representation of the signal * * The tkill call is analogous to kill(2), * except that it also allows a process within a specific thread group to * be targeted. Such processes are targeted through their unique * thread IDs (TID). */ probe signal.systkill = syscall.tkill { name = "systkill" sig_name = _signal_name($sig) sig_pid = $pid pid_name = task_execname($pid) } /** * probe signal.systkill.return - Sending kill signal to a thread completed * @name: Name of the probe point * @retstr: The return value to either __group_send_sig_info, */ probe signal.systkill.return = syscall.tkill.return { name = "systkill" } /** * probe signal.sys_tgkill - Sending kill signal to a thread group * @name: Name of the probe point * @sig_pid: The PID of the thread receiving the kill signal * @pid_name: The name of the signal recipient * @tgid: The thread group ID of the thread receiving the kill signal * @sig: The specific kill signal sent to the process * @sig_name: A string representation of the signal * * The tgkill call is similar to tkill, * except that it also allows the caller to specify the thread group ID of * the thread to be signalled. This protects against TID reuse. */ probe signal.systgkill = syscall.tgkill { name = "systgkill" sig_name = _signal_name($sig) sig_pid = $pid pid_name = task_execname($pid) } /** * probe signal.sys_tgkill.return - Sending kill signal to a thread group completed * @name: Name of the probe point * @retstr: The return value to either __group_send_sig_info, */ probe signal.systgkill.return = syscall.tgkill.return { name = "systgkill" } /** * probe signal.send_sig_queue - Queuing a signal to a process * @name: Name of the probe point * @sig: The queued signal * @sig_name: A string representation of the signal * @sig_pid: The PID of the process to which the signal is queued * @pid_name: Name of the process to which the signal is queued * @sigqueue_addr: The address of the signal queue */ probe signal.send_sig_queue = kernel.function("send_sigqueue"), kernel.function("send_group_sigqueue") ? { name = "send_sig_queue" if (! @defined($sig)) { sig = $q->info->si_signo sig_name = _signal_name($q->info->si_signo) } else { sig = $sig sig_name = _signal_name($sig) } if (@defined($t)) { sig_pid = $t->pid pid_name = kernel_string($t->comm) } else { sig_pid = $p->pid pid_name = kernel_string($p->comm) } sigqueue_addr = $q } /** * probe signal.send_sig_queue.return - Queuing a signal to a process completed * @name: Name of the probe point * @retstr: Return value as a string */ probe signal.send_sig_queue.return = kernel.function("send_sigqueue").return, kernel.function("send_group_sigqueue").return ? { name = "send_sig_queue" retstr = return_str(1, $return) } /** * probe signal.pending - Examining pending signal * @name: Name of the probe point * @sigset_add: The address of the user-space signal set * (sigset_t) * @sigset_size: The size of the user-space signal set * * This probe is used to examine a set of signals pending for delivery * to a specific thread. This normally occurs when the * do_sigpending kernel function is executed. */ probe signal.pending = kernel.function("do_sigpending") { name = "pending" sigset_add=$set sigset_size=$sigsetsize } /** * probe signal.pending.return - Examination of pending signal completed * @name: Name of the probe point * @retstr: Return value as a string */ probe signal.pending.return = kernel.function("do_sigpending").return { name = "pending" retstr = return_str(1, $return) } /** * probe signal.handle - Signal handler being invoked * @name: Name of the probe point * @sig: The signal number that invoked the signal handler * @sig_name: A string representation of the signal * @sinfo: The address of the siginfo table * @sig_code: The si_code value of the siginfo signal * @ka_addr: The address of the k_sigaction table * associated with the signal * @oldset_addr: The address of the bitmask array of blocked signals * (deprecated in SystemTap 2.1) * @regs: The address of the kernel-mode stack area (deprecated in * SystemTap 2.1) * @sig_mode: Indicates whether the signal was a user-mode or kernel-mode signal */ probe signal.handle = __signal.handle.tp !, __signal.handle.kp { name = "handle" // Check whether the signal is a User Mode or Kernel mode Signal. if (sinfo == 0 && sig_code <= 0) sig_mode = "User Mode Signal" else if (sinfo >= 1) sig_mode = "Kernel Mode Signal" } probe __signal.handle.tp = kernel.trace("signal_deliver") ? { sig = $sig sig_name = _signal_name($sig) sinfo = $info sig_code = $info->si_code ka_addr = $ka %( systemtap_v <= "2.1" %? oldset_addr = 0 regs = 0 %) } probe __signal.handle.kp = kernel.function("handle_rt_signal64") ?, kernel.function("handle_rt_signal32") ?, kernel.function("handle_signal32") !, kernel.function("handle_signal") { if (@defined($sig)) { sig = $sig sig_name = _signal_name($sig) } else { sig = $signr sig_name = _signal_name($signr) } sinfo = $info sig_code = $info->si_code ka_addr = $ka %( systemtap_v <= "2.1" %? oldset_addr = @choose_defined($oldset, @choose_defined($set, 0)) regs = $regs %) } %( systemtap_v <= "2.1" %? /** * probe signal.handle.return - Signal handler invocation completed * (deprecated in SystemTap 2.1) * @name: Name of the probe point * @retstr: Return value as a string */ probe signal.handle.return = kernel.function("handle_rt_signal64").return ?, kernel.function("handle_rt_signal32").return ?, kernel.function("handle_signal32").return !, kernel.function("handle_signal").return ? { name = "handle" retstr = return_str(1, $return) } %) /** * probe signal.do_action - Examining or changing a signal action * @name: Name of the probe point * @sig: The signal to be examined/changed * @sig_name: A string representation of the signal * @sigact_addr: The address of the new sigaction * struct associated with the signal * @oldsigact_addr: The address of the old sigaction * struct associated with the signal * @sa_handler: The new handler of the signal * @sa_mask: The new mask of the signal */ probe signal.do_action = kernel.function("do_sigaction") { name = "do_action" sig = $sig sig_name = _signal_name($sig) sigact_addr = $act oldsigact_addr = $oact if(sigact_addr != 0) { sa_handler = $act->sa->sa_handler sa_mask = __get_action_mask($act) } } /** * probe signal.do_action.return - Examining or changing a signal action completed * @name: Name of the probe point * @retstr: Return value as a string */ probe signal.do_action.return = kernel.function("do_sigaction").return { name = "do_action" retstr = return_str(1, $return) } function __get_action_mask:long(act:long) %{ /* pure */ int i; struct k_sigaction *act = (struct k_sigaction *)((long)STAP_ARG_act); sigset_t *sigset = &act->sa.sa_mask; STAP_RETVALUE = kread(&(sigset->sig[0])); for (i=1; i<_NSIG_WORDS; ++i) { uint64_t part = kread(&(sigset->sig[i])); STAP_RETVALUE |= part << (_NSIG_BPW*i); } CATCH_DEREF_FAULT(); %} /** * probe signal.procmask - Examining or changing blocked signals * @name: Name of the probe point * @how: Indicates how to change the blocked signals; possible values are * SIG_BLOCK=0 (for blocking signals), * SIG_UNBLOCK=1 (for unblocking signals), and * SIG_SETMASK=2 for setting the signal mask. * @sigset_addr: The address of the signal set (sigset_t) * to be implemented * @oldsigset_addr: The old address of the signal set * (sigset_t) * @sigset: The actual value to be set for sigset_t * (correct?) */ probe signal.procmask = kernel.function("sigprocmask") { name = "procmask" how=$how sigset_addr = $set oldsigset_addr = $oldset sigset = get_sigset($set) } function get_sigset:long(sigset:long) %{ /* pure */ int i; sigset_t *sigset = (sigset_t *)((long)STAP_ARG_sigset); STAP_RETVALUE = kread(&(sigset->sig[0])); for (i=1; i<_NSIG_WORDS; ++i) { uint64_t part = kread(&(sigset->sig[i])); STAP_RETVALUE |= part << (_NSIG_BPW*i); } CATCH_DEREF_FAULT(); %} /** * probe signal.procmask.return - Examining or changing blocked signals completed * @name: Name of the probe point * @retstr: Return value as a string */ probe signal.procmask.return = kernel.function("sigprocmask").return { name = "procmask" retstr = return_str(1, $return) } /** * probe signal.flush - Flushing all pending signals for a task * @name: Name of the probe point * @task: The task handler of the process performing the flush * @sig_pid: The PID of the process associated with the task * performing the flush * @pid_name: The name of the process associated with the task * performing the flush */ probe signal.flush = kernel.function("flush_signals") { name = "flush" task = $t sig_pid = $t->pid pid_name = kernel_string($t->comm) } /** * sfunction get_sa_flags - Returns the numeric value of sa_flags * * @act: address of the sigaction to query. */ function get_sa_flags:long (act:long) { return @cast(act, "k_sigaction", "kernel")->sa->sa_flags } /** * sfunction get_sa_flags - Returns the numeric value of sa_handler * * @act: address of the sigaction to query. */ function get_sa_handler:long (act:long) { return @cast(act, "k_sigaction", "kernel")->sa->sa_handler } // sa_mask contains the set of signals to be blocked when executing the // signal handler. This function returns a string, delimited by ",". // // struct task_struct { // [...] // struct signal_struct//signal; // struct sighand_struct//sighand; // [...] // struct sighand_struct { // atomic_t count; // struct k_sigaction action[_NSIG]; // [...] // struct k_sigaction { // struct sigaction sa; // }; // // struct sigaction { // [...] // sigset_t sa_mask; // }; /** * sfunction get_sa_flags - Returns the string representation of a sigset * * @mask: the sigset to convert to string. */ function sigset_mask_str:string (mask:long) %{ /* pure */ int i, len; char *str = STAP_RETVALUE, tmp[5]; str[0] = '\0'; for (i = 1; i < _NSIG; ++i, STAP_ARG_mask >>=1) if (STAP_ARG_mask & 1) { snprintf(tmp, sizeof(tmp), "%u,", i); strlcat(str, tmp, MAXSTRINGLEN); } len = strlen(str); if (len) str[len - 1] = '\0'; %} // task_struct->blocked signal mask contains the set of signals that are // currently blocked. // // struct task_struct { // [...] // sigset_t blocked, real_blocked; /** * sfunction is_sig_blocked - Returns 1 if the signal is currently blocked, or 0 if it is not * * @task: address of the task_struct to query. * @sig: the signal number to test. */ function is_sig_blocked:long (task:long, sig:long) %{ /* pure */ int i; sigset_t blocked; struct task_struct *p = (struct task_struct *)((long)STAP_ARG_task); for (i = 0; i < _NSIG_WORDS; ++i) blocked.sig[i] = kread(&p->blocked.sig[i]); STAP_RETVALUE = sigismember(&blocked, STAP_ARG_sig); CATCH_DEREF_FAULT(); %} /** * sfunction sa_flags_str - Returns the string representation of sa_flags * * @sa_flags: the set of flags to convert to string. */ function sa_flags_str:string (sa_flags:long) %{ /* pure */ int len; char *str = STAP_RETVALUE; str[0] = '\0'; if (STAP_ARG_sa_flags & 0x00000001u) strlcat(str, "NOCLDSTOP|", MAXSTRINGLEN); if (STAP_ARG_sa_flags & 0x00000002u) strlcat(str, "NOCLDWAIT|", MAXSTRINGLEN); if (STAP_ARG_sa_flags & 0x00000004u) strlcat(str, "SIGINFO|", MAXSTRINGLEN); if (STAP_ARG_sa_flags & 0x08000000u) strlcat(str, "ONSTACK|", MAXSTRINGLEN); if (STAP_ARG_sa_flags & 0x10000000u) strlcat(str, "RESTART|", MAXSTRINGLEN); if (STAP_ARG_sa_flags & 0x40000000u) strlcat(str, "NODEFER|", MAXSTRINGLEN); if (STAP_ARG_sa_flags & 0x80000000u) strlcat(str, "RESETHAND|", MAXSTRINGLEN); if (STAP_ARG_sa_flags & 0x04000000) strlcat(str, "RESTORER|", MAXSTRINGLEN); len = strlen(str); if (len) str[len - 1] = '\0'; %} /** * sfunction sa_handler - Returns the string representation of an sa_handler * * @handler: the sa_handler to convert to string. * * Description: Returns the string representation of an sa_handler. * If it is not SIG_DFL, SIG_IGN or SIG_ERR, it will return the address * of the handler. */ function sa_handler_str(handler) { if (handler == 0) return "default"; /* SIG_DFL */ if (handler == 1) return "ignored"; /* SIG_IGN */ if (handler == -1) return "error"; /* SIG_ERR */ return sprintf("%p", handler); /* userspace address */ } // Signals start from 1 not 0. global __sig[64] /** * sfunction signal_str - Returns the string representation of a signal number * * @num: the signal number to convert to string. */ function signal_str(num) { if (!(64 in __sig)) { __sig[1] = "HUP" __sig[2] = "INT" __sig[3] = "QUIT" __sig[4] = "ILL" __sig[5] = "TRAP" __sig[6] = "ABRT" /* or IOT */ __sig[7] = "BUS" __sig[8] = "FPE" __sig[9] = "KILL" __sig[10] = "USR1" __sig[11] = "SEGV" __sig[12] = "USR2" __sig[13] = "PIPE" __sig[14] = "ALRM" __sig[15] = "TERM" __sig[16] = "STKFLT" __sig[17] = "CHLD" /* or CLD */ __sig[18] = "CONT" __sig[19] = "STOP" __sig[20] = "TSTP" __sig[21] = "TTIN" __sig[22] = "TTOU" __sig[23] = "URG" __sig[24] = "XCPU" __sig[25] = "XFSZ" __sig[26] = "VTALRM" __sig[27] = "PROF" __sig[28] = "WINCH" __sig[29] = "IO/POLL" __sig[30] = "PWR" __sig[31] = "SYS" /* or UNUSED */ __sig[32] = "RTMIN" __sig[33] = "RTMIN+1" __sig[34] = "RTMIN+2" __sig[35] = "RTMIN+3" __sig[36] = "RTMIN+4" __sig[37] = "RTMIN+5" __sig[38] = "RTMIN+6" __sig[39] = "RTMIN+7" __sig[40] = "RTMIN+8" __sig[41] = "RTMIN+9" __sig[42] = "RTMIN+10" __sig[43] = "RTMIN+11" __sig[44] = "RTMIN+12" __sig[45] = "RTMIN+13" __sig[46] = "RTMIN+14" __sig[47] = "RTMIN+15" __sig[48] = "RTMIN+16" __sig[49] = "RTMIN+17" __sig[50] = "RTMIN+18" __sig[51] = "RTMIN+19" __sig[52] = "RTMIN+20" __sig[53] = "RTMIN+21" __sig[54] = "RTMIN+22" __sig[55] = "RTMIN+23" __sig[56] = "RTMIN+24" __sig[57] = "RTMIN+25" __sig[58] = "RTMIN+26" __sig[59] = "RTMIN+27" __sig[60] = "RTMIN+28" __sig[61] = "RTMIN+29" __sig[62] = "RTMIN+30" __sig[63] = "RTMIN+31" __sig[64] = "RTMIN+32" } return __sig[num] } systemtap-2.3/tapset/linux/socket.stp000066400000000000000000000710001217430427200200660ustar00rootroot00000000000000// Socket tapset // Copyright (C) 2006 IBM Corp. // Copyright (C) 2010-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // This family of probe points is used to probe socket activities. // %{ #include #include %} ################### # INTERNAL MACROS # ################### // Note that since these macros are defined in this file, they are // local to this file. They are internal only. // // Note the '&@sock[0]' usage below. This allows calling the macros // with either a dwarf variable (like '$sock') or casts (like // '@cast(_sock, "socket", "kernel") without needing additional casts // inside the macros (which would then lose type information when // called with a dwarf variable). // Return whether the operation was successful. @define _sock_success_check(ret) %( ( @ret >= 0 ? 1 : 0 ) %) // Return the socket protocol number. @define _sock_prot_num(sock) %( ( &@sock[0] ? ( @sock->sk ? @sock->sk->sk_protocol : -1 ) : -1 ) %) // Return the socket family number. @define _sock_fam_num(sock) %( ( &@sock[0] ? ( @sock->ops ? @sock->ops->family : -1 ) : -1 ) %) // Return the socket state number. @define _sock_state_num(sock) %( ( &@sock[0] ? @sock->state : -1 ) %) // Return the socket type number. @define _sock_type_num(sock) %( ( &@sock[0] ? @sock->type : -1 ) %) // Return the socket flags number. @define _sock_flags_num(sock) %( ( &@sock[0] ? @sock->flags : -1 ) %) ################# # PROBE ALIASES # ################# ### GENERAL SEND/RECEIVE PROBES ### /** * probe socket.send - Message sent on a socket. * @name: Name of this probe * @size: Size of message sent (in bytes) or error code if success = 0 * @protocol: Protocol value * @family: Protocol family value * @state: Socket state value * @flags: Socket flags value * @type: Socket type value * @success: Was send successful? (1 = yes, 0 = no) * * Context: * The message sender */ probe socket.send = socket.sendmsg.return, socket.writev.return ?, socket.aio_write.return { name = "socket.send" } /** * probe socket.receive - Message received on a socket. * @name: Name of this probe * @size: Size of message received (in bytes) or error code if success = 0 * @protocol: Protocol value * @family: Protocol family value * @state: Socket state value * @flags: Socket flags value * @type: Socket type value * @success: Was send successful? (1 = yes, 0 = no) * * Context: * The message receiver */ probe socket.receive = socket.recvmsg.return, socket.readv.return ?, socket.aio_read.return { name = "socket.receive" } ### FUNCTION SPECIFIC SEND/RECEIVE PROBES ### /** * probe socket.sendmsg - Message is currently being sent on a socket. * @name: Name of this probe * @size: Message size in bytes * @protocol: Protocol value * @family: Protocol family value * @state: Socket state value * @flags: Socket flags value * @type: Socket type value * * Context: * The message sender * * Fires at the beginning of sending a message on a socket * via the sock_sendmsg() function */ probe socket.sendmsg = kernel.function ("sock_sendmsg") { name = "socket.sendmsg" size = $size protocol = @_sock_prot_num($sock) family = @_sock_fam_num($sock) state = @_sock_state_num($sock) flags = @_sock_flags_num($sock) type = @_sock_type_num($sock) } /** * probe socket.sendmsg.return - Return from socket.sendmsg. * @name: Name of this probe * @size: Size of message sent (in bytes) or error code if success = 0 * @protocol: Protocol value * @family: Protocol family value * @state: Socket state value * @flags: Socket flags value * @type: Socket type value * @success: Was send successful? (1 = yes, 0 = no) * * Context: * The message sender. * * Fires at the conclusion of sending a message on a socket * via the sock_sendmsg() function */ probe socket.sendmsg.return = kernel.function("sock_sendmsg").return { name = "socket.sendmsg.return" size = $return protocol = @_sock_prot_num($sock) family = @_sock_fam_num($sock) state = @_sock_state_num($sock) flags = @_sock_flags_num($sock) type = @_sock_type_num($sock) success = @_sock_success_check($return) } /** * probe socket.recvmsg - Message being received on socket * @name: Name of this probe * @size: Message size in bytes * @protocol: Protocol value * @family: Protocol family value * @state: Socket state value * @flags: Socket flags value * @type: Socket type value * * Context: * The message receiver. * * Fires at the beginning of receiving a message on a socket * via the sock_recvmsg() function * */ probe socket.recvmsg = kernel.function("sock_recvmsg") { name = "socket.recvmsg" size = $size protocol = @_sock_prot_num($sock) family = @_sock_fam_num($sock) state = @_sock_state_num($sock) flags = @_sock_flags_num($sock) type = @_sock_type_num($sock) } /** * probe socket.recvmsg.return - Return from Message being received on socket * @name: Name of this probe * @size: Size of message received (in bytes) or error code if success = 0 * @protocol: Protocol value * @family: Protocol family value * @state: Socket state value * @flags: Socket flags value * @type: Socket type value * @success: Was receive successful? (1 = yes, 0 = no) * * Context: * The message receiver. * * Fires at the conclusion of receiving a message on a socket * via the sock_recvmsg() function. * * */ probe socket.recvmsg.return = kernel.function("sock_recvmsg").return { name = "socket.recvmsg.return" size = $return protocol = @_sock_prot_num($sock) family = @_sock_fam_num($sock) state = @_sock_state_num($sock) flags = @_sock_flags_num($sock) type = @_sock_type_num($sock) success = @_sock_success_check($return) } /** * probe socket.aio_write - Message send via sock_aio_write() * @name: Name of this probe * @size: Message size in bytes * @protocol: Protocol value * @family: Protocol family value * @state: Socket state value * @flags: Socket flags value * @type: Socket type value * * Context: * The message sender * * Fires at the beginning of sending a message on a socket * via the sock_aio_write() function */ // // 2.6.9~2.6.15: // static ssize_t sock_aio_write(struct kiocb *iocb, // const char __user *ubuf, size_t size, loff_t pos); // 2.6.16~2.6.18: // static ssize_t sock_aio_write(struct kiocb *iocb, // const char __user *ubuf, size_t count, loff_t pos); // 2.6.19~2.6.26: // static ssize_t sock_aio_write(struct kiocb *iocb, // const struct iovec *iov, unsigned long nr_segs, loff_t pos); probe socket.aio_write = kernel.function("sock_aio_write") { name = "socket.aio_write" _sock = _get_sock_addr($iocb->ki_filp) size = (@defined($iov) ? _get_sock_size($iov, $nr_segs) : @choose_defined($count, $size)) protocol = @_sock_prot_num(@cast(_sock, "socket", "kernel")) family = @_sock_fam_num(@cast(_sock, "socket", "kernel")) state = @_sock_state_num(@cast(_sock, "socket", "kernel")) flags = @_sock_flags_num(@cast(_sock, "socket", "kernel")) type = @_sock_type_num(@cast(_sock, "socket", "kernel")) } /** * probe socket.aio_write.return - Conclusion of message send via sock_aio_write() * @name: Name of this probe * @size: Size of message received (in bytes) or error code if success = 0 * @protocol: Protocol value * @family: Protocol family value * @state: Socket state value * @flags: Socket flags value * @type: Socket type value * @success: Was receive successful? (1 = yes, 0 = no) * * Context: * The message receiver. * * Fires at the conclusion of sending a message on a socket * via the sock_aio_write() function */ probe socket.aio_write.return = kernel.function("sock_aio_write").return { name = "socket.aio_write.return" size = $return _sock = _get_sock_addr($iocb->ki_filp) protocol = @_sock_prot_num(@cast(_sock, "socket", "kernel")) family = @_sock_fam_num(@cast(_sock, "socket", "kernel")) state = @_sock_state_num(@cast(_sock, "socket", "kernel")) flags = @_sock_flags_num(@cast(_sock, "socket", "kernel")) type = @_sock_type_num(@cast(_sock, "socket", "kernel")) success = @_sock_success_check($return) } /** * probe socket.aio_read - Receiving message via sock_aio_read() * @name: Name of this probe * @size: Message size in bytes * @protocol: Protocol value * @family: Protocol family value * @state: Socket state value * @flags: Socket flags value * @type: Socket type value * * Context: * The message sender * * Fires at the beginning of receiving a message on a socket * via the sock_aio_read() function */ // // 2.6.9~2.6.15: // static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf, // size_t size, loff_t pos); // 2.6.16~2.6.18: // static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf, // size_t count, loff_t pos); // 2.6.19~2.6.26: // static ssize_t sock_aio_read(struct kiocb *iocb, // const struct iovec *iov, unsigned long nr_segs, loff_t pos); probe socket.aio_read = kernel.function("sock_aio_read") { name = "socket.aio_read" _sock = _get_sock_addr($iocb->ki_filp) size = (@defined($iov) ? _get_sock_size($iov, $nr_segs) : @choose_defined($count, $size)) protocol = @_sock_prot_num(@cast(_sock, "socket", "kernel")) family = @_sock_fam_num(@cast(_sock, "socket", "kernel")) state = @_sock_state_num(@cast(_sock, "socket", "kernel")) flags = @_sock_flags_num(@cast(_sock, "socket", "kernel")) type = @_sock_type_num(@cast(_sock, "socket", "kernel")) } /** * probe socket.aio_read.return - Conclusion of message received via sock_aio_read() * @name: Name of this probe * @size: Size of message received (in bytes) or error code if success = 0 * @protocol: Protocol value * @family: Protocol family value * @state: Socket state value * @flags: Socket flags value * @type: Socket type value * @success: Was receive successful? (1 = yes, 0 = no) * * Context: * The message receiver. * * Fires at the conclusion of receiving a message on a socket * via the sock_aio_read() function */ probe socket.aio_read.return = kernel.function("sock_aio_read").return { name = "socket.aio_read.return" size = $return _sock = _get_sock_addr($iocb->ki_filp) protocol = @_sock_prot_num(@cast(_sock, "socket", "kernel")) family = @_sock_fam_num(@cast(_sock, "socket", "kernel")) state = @_sock_state_num(@cast(_sock, "socket", "kernel")) flags = @_sock_flags_num(@cast(_sock, "socket", "kernel")) type = @_sock_type_num(@cast(_sock, "socket", "kernel")) success = @_sock_success_check($return) } /** * probe socket.writev - Message sent via socket_writev() * @name: Name of this probe * @size: Message size in bytes * @protocol: Protocol value * @family: Protocol family value * @state: Socket state value * @flags: Socket flags value * @type: Socket type value * * Context: * The message sender * * Fires at the beginning of sending a message on a socket * via the sock_writev() function */ probe socket.writev = kernel.function("sock_writev") ? { name = "socket.writev" _sock = _get_sock_addr($file) size = (@defined($iov) ? _get_sock_size($iov, $nr_segs) : _get_sock_size($vector, $count)) protocol = @_sock_prot_num(@cast(_sock, "socket", "kernel")) family = @_sock_fam_num(@cast(_sock, "socket", "kernel")) state = @_sock_state_num(@cast(_sock, "socket", "kernel")) flags = @_sock_flags_num(@cast(_sock, "socket", "kernel")) type = @_sock_type_num(@cast(_sock, "socket", "kernel")) } /** * probe socket.writev.return - Conclusion of message sent via socket_writev() * @name: Name of this probe * @size: Size of message sent (in bytes) or error code if success = 0 * @protocol: Protocol value * @family: Protocol family value * @state: Socket state value * @flags: Socket flags value * @type: Socket type value * @success: Was send successful? (1 = yes, 0 = no) * * Context: * The message receiver. * * Fires at the conclusion of sending a message on a socket * via the sock_writev() function */ probe socket.writev.return = kernel.function("sock_writev").return ? { name = "socket.writev.return" size = $return _sock = _get_sock_addr($file) protocol = @_sock_prot_num(@cast(_sock, "socket", "kernel")) family = @_sock_fam_num(@cast(_sock, "socket", "kernel")) state = @_sock_state_num(@cast(_sock, "socket", "kernel")) flags = @_sock_flags_num(@cast(_sock, "socket", "kernel")) type = @_sock_type_num(@cast(_sock, "socket", "kernel")) success = @_sock_success_check($return) } /** * probe socket.readv - Receiving a message via sock_readv() * @name: Name of this probe * @size: Message size in bytes * @protocol: Protocol value * @family: Protocol family value * @state: Socket state value * @flags: Socket flags value * @type: Socket type value * * Context: * The message sender * * Fires at the beginning of receiving a message on a socket * via the sock_readv() function */ probe socket.readv = kernel.function("sock_readv") ? { name = "socket.readv" _sock = _get_sock_addr($file) size = (@defined($iov) ? _get_sock_size($iov, $nr_segs) : _get_sock_size($vector, $count)) protocol = @_sock_prot_num(@cast(_sock, "socket", "kernel")) family = @_sock_fam_num(@cast(_sock, "socket", "kernel")) state = @_sock_state_num(@cast(_sock, "socket", "kernel")) flags = @_sock_flags_num(@cast(_sock, "socket", "kernel")) type = @_sock_type_num(@cast(_sock, "socket", "kernel")) } /** * probe socket.readv.return - Conclusion of receiving a message via sock_readv() * @name: Name of this probe * @size: Size of message received (in bytes) or error code if success = 0 * @protocol: Protocol value * @family: Protocol family value * @state: Socket state value * @flags: Socket flags value * @type: Socket type value * @success: Was receive successful? (1 = yes, 0 = no) * * Context: * The message receiver. * * Fires at the conclusion of receiving a message on a socket * via the sock_readv() function */ probe socket.readv.return = kernel.function("sock_readv").return ? { name = "socket.readv.return" size = $return _sock = _get_sock_addr($file) protocol = @_sock_prot_num(@cast(_sock, "socket", "kernel")) family = @_sock_fam_num(@cast(_sock, "socket", "kernel")) state = @_sock_state_num(@cast(_sock, "socket", "kernel")) flags = @_sock_flags_num(@cast(_sock, "socket", "kernel")) type = @_sock_type_num(@cast(_sock, "socket", "kernel")) success = @_sock_success_check($return) } /** * probe socket.create - Creation of a socket * @name: Name of this probe * @protocol: Protocol value * @family: Protocol family value * @type: Socket type value * @requester: Requested by user process or the kernel (1 = kernel, 0 = user) * * Context: * The requester (see requester variable) * * Fires at the beginning of creating a socket. */ probe socket.create = kernel.function("__sock_create") { name = "socket.create" protocol = $protocol family = $family type = $type requester = $kern } /** * probe socket.create.return - Return from Creation of a socket * @name: Name of this probe * @protocol: Protocol value * @family: Protocol family value * @type: Socket type value * @requester: Requested by user process or the kernel (1 = kernel, 0 = user) * @err: Error code if success == 0 * @success: Was socket creation successful? (1 = yes, 0 = no) * * Context: * The requester (user process or kernel) * * Fires at the conclusion of creating a socket. */ probe socket.create.return = kernel.function("__sock_create").return { name = "socket.create.return" protocol = $protocol family = $family type = $type requester = $kern err = $return success = @_sock_success_check($return) } /** * probe socket.close - Close a socket * @name: Name of this probe * @protocol: Protocol value * @family: Protocol family value * @state: Socket state value * @flags: Socket flags value * @type: Socket type value * * Context: * The requester (user process or kernel) * * Fires at the beginning of closing a socket. */ probe socket.close = kernel.function("sock_release") { name = "socket.close" protocol = @_sock_prot_num($sock) family = @_sock_fam_num($sock) state = @_sock_state_num($sock) flags = @_sock_flags_num($sock) type = @_sock_type_num($sock) } /** * probe socket.close.return - Return from closing a socket * @name: Name of this probe * * Context: * The requester (user process or kernel) * * Fires at the conclusion of closing a socket. */ probe socket.close.return = kernel.function("sock_release").return { name = "socket.close.return" /* void return */ } ################## # USER FUNCTIONS # ################## ####### PROTOCOL HELPER FUNCTIONS ######## /** * sfunction sock_prot_num2str - Given a protocol number, return a string representation * @proto: The protocol number */ function sock_prot_num2str:string(proto:long) { return (proto in _prot_num2str ? _prot_num2str[proto] : "UNDEF") } /** * sfunction sock_prot_str2num - Given a protocol name (string), return the corresponding protocol number * @proto: The protocol name */ function sock_prot_str2num:long(proto:string) { return (proto in _prot_str2num ? _prot_str2num[proto] : -1) } ######### PROTOCOL FAMILY HELPER FUNCTIONS ########### /** * sfunction sock_fam_num2str - Given a protocol family number, return a string representation * @family: The family number */ function sock_fam_num2str:string(family:long) { return (family in _fam_num2str ? _fam_num2str[family] : "UNDEF") } /** * sfunction sock_fam_str2num - Given a protocol family name (string), return the corresponding protocol family number * @family: The family name */ function sock_fam_str2num:long(family:string) { return (family in _fam_str2num ? _fam_str2num[family] : -1) } ######### SOCKET STATE HELPER FUNCTIONS ########## /** * sfunction sock_state_num2str - Given a socket state number, return a string representation * @state: The state number */ function sock_state_num2str:string(state:long) { return (state in _state_num2str ? _state_num2str[state] : "UNDEF") } /** * sfunction sock_state_str2num - Given a socket state string, return the corresponding state number * @state: The state name */ function sock_state_str2num:long(state:string) { return (state in _state_str2num ? _state_str2num[state] : -1) } ######## SOCKET TYPE HELPER FUNCTIONS ######## function sock_type_num2str:string(type:long) { return (type in _type_num2str ? _type_num2str[type] : "UNDEF") } function sock_type_str2num:long(type:string) { return (type in _type_str2num ? _type_str2num[type] : -1) } ######### SOCKET FLAGS HELPER FUNCTIONS ######### function sock_flags_num2str:string(flags:long) %{ /* pure */ #ifndef SOCK_PASSCRED #define SOCK_PASSCRED 3 /* introduced in 2.6.12? */ #endif #ifndef SOCK_PASSSEC #define SOCK_PASSSEC 4 /* introduced in 2.6.18 */ #endif unsigned long flags = STAP_ARG_flags; STAP_RETVALUE[0] = '\0'; if (test_bit(SOCK_ASYNC_NOSPACE, &flags)) strlcat(STAP_RETVALUE, "ASYNC_NOSPACE|", MAXSTRINGLEN); if (test_bit(SOCK_ASYNC_WAITDATA, &flags)) strlcat(STAP_RETVALUE, "ASYNC_WAITDATA|", MAXSTRINGLEN); if (test_bit(SOCK_NOSPACE, &flags)) strlcat(STAP_RETVALUE, "NOSPACE|", MAXSTRINGLEN); if (test_bit(SOCK_PASSCRED, &flags)) strlcat(STAP_RETVALUE, "PASSCRED|", MAXSTRINGLEN); if (test_bit(SOCK_PASSSEC, &flags)) strlcat(STAP_RETVALUE, "PASSSEC|", MAXSTRINGLEN); if (STAP_RETVALUE[0] != '\0') STAP_RETVALUE[strlen(STAP_RETVALUE)-1] = '\0'; %} ######### MESSAGE FLAGS HELPER FUNCTIONS ######### function msg_flags_num2str:string(flags:long) %{ /* pure */ STAP_RETVALUE[0] = '\0'; if (STAP_ARG_flags & MSG_OOB) strlcat(STAP_RETVALUE, "OOB|", MAXSTRINGLEN); if (STAP_ARG_flags & MSG_PEEK) strlcat(STAP_RETVALUE, "PEEK|", MAXSTRINGLEN); if (STAP_ARG_flags & MSG_DONTROUTE) strlcat(STAP_RETVALUE, "DONTROUTE|", MAXSTRINGLEN); if (STAP_ARG_flags & MSG_TRYHARD) strlcat(STAP_RETVALUE, "TRYHARD|", MAXSTRINGLEN); if (STAP_ARG_flags & MSG_CTRUNC) strlcat(STAP_RETVALUE, "CTRUNC|", MAXSTRINGLEN); if (STAP_ARG_flags & MSG_PROBE) strlcat(STAP_RETVALUE, "PROBE|", MAXSTRINGLEN); if (STAP_ARG_flags & MSG_TRUNC) strlcat(STAP_RETVALUE, "TRUNC|", MAXSTRINGLEN); if (STAP_ARG_flags & MSG_DONTWAIT) strlcat(STAP_RETVALUE, "DONTWAIT|", MAXSTRINGLEN); if (STAP_ARG_flags & MSG_EOR) strlcat(STAP_RETVALUE, "EOR|", MAXSTRINGLEN); if (STAP_ARG_flags & MSG_WAITALL) strlcat(STAP_RETVALUE, "WAITALL|", MAXSTRINGLEN); if (STAP_ARG_flags & MSG_FIN) strlcat(STAP_RETVALUE, "FIN|", MAXSTRINGLEN); if (STAP_ARG_flags & MSG_SYN) strlcat(STAP_RETVALUE, "SYN|", MAXSTRINGLEN); if (STAP_ARG_flags & MSG_CONFIRM) strlcat(STAP_RETVALUE, "CONFIRM|", MAXSTRINGLEN); if (STAP_ARG_flags & MSG_RST) strlcat(STAP_RETVALUE, "RST|", MAXSTRINGLEN); if (STAP_ARG_flags & MSG_ERRQUEUE) strlcat(STAP_RETVALUE, "ERRQUEUE|", MAXSTRINGLEN); if (STAP_ARG_flags & MSG_NOSIGNAL) strlcat(STAP_RETVALUE, "NOSIGNAL|", MAXSTRINGLEN); if (STAP_ARG_flags & MSG_MORE) strlcat(STAP_RETVALUE, "MORE|", MAXSTRINGLEN); if (STAP_RETVALUE[0] != '\0') STAP_RETVALUE[strlen(STAP_RETVALUE)-1] = '\0'; %} ########################### # INTERNAL MAPPING ARRAYS # ########################### global _prot_num2str[138], _prot_str2num[138] global _fam_num2str[34], _fam_str2num[34] global _state_num2str[5], _state_str2num[5] global _type_num2str[11], _type_str2num[11] probe begin(-1001) { /* From /etc/protocols. * Many of these protocols aren't currently used over * sockets, but are included for completeness */ _prot_num2str[0] = "IP" _prot_num2str[1] = "ICMP" _prot_num2str[2] = "IGMP" _prot_num2str[3] = "GGP" _prot_num2str[4] = "IPENCAP" _prot_num2str[5] = "ST" _prot_num2str[6] = "TCP" _prot_num2str[7] = "CBT" _prot_num2str[8] = "EGP" _prot_num2str[9] = "IGP" _prot_num2str[10] = "BBN-RCC" _prot_num2str[11] = "NVP" _prot_num2str[12] = "PUP" _prot_num2str[13] = "ARGUS" _prot_num2str[14] = "EMCON" _prot_num2str[15] = "XNET" _prot_num2str[16] = "CHAOS" _prot_num2str[17] = "UDP" _prot_num2str[18] = "MUX" _prot_num2str[19] = "DCN" _prot_num2str[20] = "HMP" _prot_num2str[21] = "PRM" _prot_num2str[22] = "XNS-IDP" _prot_num2str[23] = "TRUNK-1" _prot_num2str[24] = "TRUNK-2" _prot_num2str[25] = "LEAF-1" _prot_num2str[26] = "LEAF-2" _prot_num2str[27] = "RDP" _prot_num2str[28] = "IRTP" _prot_num2str[29] = "ISO-TP4" _prot_num2str[30] = "NETBLT" _prot_num2str[31] = "MFE-NSP" _prot_num2str[32] = "MERIT-INP" _prot_num2str[33] = "SEP" _prot_num2str[34] = "3PC" _prot_num2str[35] = "IDPR" _prot_num2str[36] = "XTP" _prot_num2str[37] = "DDP" _prot_num2str[38] = "IDPR-CMTP" _prot_num2str[39] = "TP++" _prot_num2str[40] = "IL" _prot_num2str[41] = "IPV6" _prot_num2str[42] = "SDRP" _prot_num2str[43] = "IPV6-ROUTE" _prot_num2str[44] = "IPV6-FRAG" _prot_num2str[45] = "IDRP" _prot_num2str[46] = "RSVP" _prot_num2str[47] = "GRE" _prot_num2str[48] = "MHRP" _prot_num2str[49] = "BNA" _prot_num2str[50] = "IPV6-CRYPT" _prot_num2str[51] = "IPV6-AUTH" _prot_num2str[52] = "I-NLSP" _prot_num2str[53] = "SWIPE" _prot_num2str[54] = "NARP" _prot_num2str[55] = "MOBILE" _prot_num2str[56] = "TLSP" _prot_num2str[57] = "SKIP" _prot_num2str[58] = "IPV6-ICMP" _prot_num2str[59] = "IPV6-NONXT" _prot_num2str[60] = "IPV6-OPTS" _prot_num2str[62] = "CFTP" _prot_num2str[64] = "SAT-EXPAK" _prot_num2str[65] = "KRYPTOLAN" _prot_num2str[66] = "RVD" _prot_num2str[67] = "IPPC" _prot_num2str[69] = "SAT-MON" _prot_num2str[70] = "VISA" _prot_num2str[71] = "IPCV" _prot_num2str[72] = "CPNX" _prot_num2str[73] = "CPHB" _prot_num2str[74] = "WSN" _prot_num2str[75] = "PVP" _prot_num2str[76] = "BR-SAT-MON" _prot_num2str[77] = "SUN-ND" _prot_num2str[78] = "WB-MON" _prot_num2str[79] = "WB-EXPAK" _prot_num2str[80] = "ISO-IP" _prot_num2str[81] = "VMTP" _prot_num2str[82] = "SECURE-VMTP" _prot_num2str[83] = "VINES" _prot_num2str[84] = "TTP" _prot_num2str[85] = "NSFNET-IGP" _prot_num2str[86] = "DGP" _prot_num2str[87] = "TCF" _prot_num2str[88] = "EIGRP" _prot_num2str[89] = "OSPF" _prot_num2str[90] = "SPRITE-RPC" _prot_num2str[91] = "LARP" _prot_num2str[92] = "MTP" _prot_num2str[93] = "AX.25" _prot_num2str[94] = "IPIP" _prot_num2str[95] = "MICP" _prot_num2str[96] = "SCC-SP" _prot_num2str[97] = "ETHERIP" _prot_num2str[98] = "ENCAP" _prot_num2str[100] = "GMTP" _prot_num2str[101] = "IFMP" _prot_num2str[102] = "PNNI" _prot_num2str[103] = "PIM" _prot_num2str[104] = "ARIS" _prot_num2str[105] = "SCPS" _prot_num2str[106] = "QNX" _prot_num2str[107] = "A/N" _prot_num2str[108] = "IPCOMP" _prot_num2str[109] = "SNP" _prot_num2str[110] = "COMPAQ-PEER" _prot_num2str[111] = "IPX-IN-IP" _prot_num2str[112] = "VRRP" _prot_num2str[113] = "PGM" _prot_num2str[115] = "L2TP" _prot_num2str[116] = "DDX" _prot_num2str[117] = "IATP" _prot_num2str[118] = "STP" _prot_num2str[119] = "SRP" _prot_num2str[120] = "UTI" _prot_num2str[121] = "SMP" _prot_num2str[122] = "SM" _prot_num2str[123] = "PTP" _prot_num2str[124] = "ISIS" _prot_num2str[125] = "FIRE" _prot_num2str[126] = "CRTP" _prot_num2str[127] = "CRDUP" _prot_num2str[128] = "SSCOPMCE" _prot_num2str[129] = "IPLT" _prot_num2str[130] = "SPS" _prot_num2str[131] = "PIPE" _prot_num2str[132] = "SCTP" _prot_num2str[133] = "FC" _prot_num2str[134] = "RSVP-E2E-IGNORE" _prot_num2str[135] = "Mobility-Header" _prot_num2str[136] = "UDPLite" _prot_num2str[137] = "MPLS-IN-IP" foreach (num in _prot_num2str) _prot_str2num[_prot_num2str[num]] = num /* from include/linux/socket.h */ _fam_num2str[0] = "UNSPEC" _fam_num2str[1] = "LOCAL" _fam_num2str[2] = "INET" _fam_num2str[3] = "AX25" _fam_num2str[4] = "IPX" _fam_num2str[5] = "APPLETALK" _fam_num2str[6] = "NETROM" _fam_num2str[7] = "BRIDGE" _fam_num2str[8] = "ATMPVC" _fam_num2str[9] = "X25" _fam_num2str[10] = "INET6" _fam_num2str[11] = "ROSE" _fam_num2str[12] = "DECNET" _fam_num2str[13] = "NETBEUI" _fam_num2str[14] = "SECURITY" _fam_num2str[15] = "KEY" _fam_num2str[16] = "NETLINK" _fam_num2str[17] = "PACKET" _fam_num2str[18] = "ASH" _fam_num2str[19] = "ECONET" _fam_num2str[20] = "ATMSVC" _fam_num2str[22] = "SNA" _fam_num2str[23] = "IRDA" _fam_num2str[24] = "PPPOX" _fam_num2str[25] = "WANPIPE" _fam_num2str[26] = "LLC" _fam_num2str[30] = "TIPC" _fam_num2str[31] = "BLUETOOTH" _fam_num2str[32] = "IUCV" _fam_num2str[33] = "RXRPC" foreach (num in _fam_num2str) _fam_str2num[_fam_num2str[num]] = num /* from include/linux/net.h */ _state_num2str[0] = "FREE" _state_num2str[1] = "UNCONNECTED" _state_num2str[2] = "CONNECTING" _state_num2str[3] = "CONNECTED" _state_num2str[4] = "DISCONNECTING" foreach (num in _state_num2str) _state_str2num[_state_num2str[num]] = num /* from include/linux/net.h */ _type_num2str[1] = "STREAM" _type_num2str[2] = "DGRAM" _type_num2str[3] = "RAW" _type_num2str[4] = "RDM" _type_num2str[5] = "SEQPACKET" _type_num2str[6] = "DCCP" _type_num2str[10] = "PACKET" foreach (num in _type_num2str) _type_str2num[_type_num2str[num]] = num } ###################### # INTERNAL FUNCTIONS # ###################### function _get_sock_addr:long(file:long) %{ /* pure */ struct file *filep = (struct file *)(long)(STAP_ARG_file); struct socket *sockp; if (filep) { struct dentry *dentry = kread(&(filep->f_dentry)); struct inode *inode = kread(&(dentry->d_inode)); sockp = &container_of(inode, struct socket_alloc, vfs_inode)->socket; } else { sockp = NULL; } if (sockp == NULL) STAP_RETVALUE = -1; else STAP_RETVALUE = (long) sockp; CATCH_DEREF_FAULT(); %} function _get_sock_size:long(iov:long, nr_segs:long) %{ /* pure */ struct iovec *iovp = (struct iovec *)(long)(STAP_ARG_iov); if (iovp == NULL) STAP_RETVALUE = -1; else { int i; STAP_RETVALUE = 0; for (i = 0 ; i < STAP_ARG_nr_segs ; i++) STAP_RETVALUE += kread(&(iovp[i].iov_len)); } CATCH_DEREF_FAULT(); %} %( systemtap_v < "2.3" %? function _success_check:long(ret:long) { return @_sock_success_check(ret) } function _sock_prot_num:long(sock:long) { return @_sock_prot_num(@cast(sock, "socket", "kernel")) } function _sock_fam_num:long(sock:long) { return @_sock_fam_num(@cast(sock, "socket", "kernel")) } function _sock_state_num:long(sock:long) { return @_sock_state_num(@cast(sock, "socket", "kernel")) } function _sock_type_num:long(sock:long) { return @_sock_type_num(@cast(sock, "socket", "kernel")) } function _sock_flags_num:long(sock:long) { return @_sock_flags_num(@cast(sock, "socket", "kernel")) } %) systemtap-2.3/tapset/linux/syscalls.stp000066400000000000000000003032401217430427200204370ustar00rootroot00000000000000// syscalls tapset part 1 [A-M] // Copyright (C) 2005 IBM Corp. // Copyright (C) 2005, 2006, 2007, 2010, 2013 Red Hat Inc. // Copyright (C) 2007 Quentin Barnes. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /* Each syscall returns the calls parameters. In addition, the following * variables are set: * * name - generally the syscall name minus the "sys_". * * argstr - a string containing the decoded args in an easy-to-read format. * It doesn't need to contain everything, but should have all the * important args. Set in entry probes only. Values enclosed in * square brackets are user-space pointers. Values in curly * braces are decoded structs. * * retstr - a string containing the return value in an easy-to-read format. * Set in return probes only. */ # accept _____________________________________________________ # long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, # int __user *upeer_addrlen, int flags) probe syscall.accept = _syscall.accept4 !, _syscall.accept { name = "accept" sockfd = $fd addr_uaddr = $upeer_sockaddr addrlen_uaddr = $upeer_addrlen argstr = sprintf("%d, %p, %p, %s", $fd, $upeer_sockaddr, $upeer_addrlen, flags_str) } probe _syscall.accept4 = kernel.function("sys_accept4").call { flags = $flags flags_str = _sock_flags_str($flags) } probe _syscall.accept = kernel.function("sys_accept").call ? { flags = 0 flags_str = "0" } probe syscall.accept.return = kernel.function("sys_accept4").return !, kernel.function("sys_accept").return ? { name = "accept" retstr = return_str(1, $return) } # access _____________________________________________________ # long sys_access(const char __user * filename, int mode) probe syscall.access = kernel.function("sys_access").call { name = "access" pathname = user_string_quoted($filename) mode = $mode mode_str = _access_mode_str($mode) argstr = sprintf("%s, %s", user_string_quoted($filename), mode_str) } probe syscall.access.return = kernel.function("sys_access").return { name = "access" retstr = return_str(1, $return) } # acct _______________________________________________________ # long sys_acct(const char __user *name) probe syscall.acct = kernel.function("sys_acct").call ? { name = "acct" filename = user_string_quoted($name) argstr = user_string_quoted($name) } probe syscall.acct.return = kernel.function("sys_acct").return ? { name = "acct" retstr = return_str(1, $return) } # add_key ____________________________________________________ # long sys_add_key(const char __user *_type, # const char __user *_description, # const void __user *_payload, # size_t plen, # key_serial_t ringid) # probe syscall.add_key = kernel.function("sys_add_key").call ? { name = "add_key" type_uaddr = $_type # 'description_auddr' should have been 'description_uaddr'. Deprecate # the old name. %(systemtap_v <= "1.4" %? description_auddr = $_description %) description_uaddr = $_description payload_uaddr = $_payload plen = $plen ringid = $ringid argstr = sprintf("%s, %s, %s, %d, %d", user_string_quoted($_type), user_string_quoted($_description), user_string_n_quoted($_payload, syscall_string_trunc), $plen, $ringid) } probe syscall.add_key.return = kernel.function("sys_add_key").return ? { name = "add_key" retstr = return_str(1, $return) } # adjtimex ___________________________________________________ # long sys_adjtimex(struct timex __user *txc_p) probe syscall.adjtimex = kernel.function("sys_adjtimex").call { name = "adjtimex" /* * buf_offset = __uget_timex_m($txc_p, 1) * buf_freq = __uget_timex_m($txc_p, 2) * buf_maxerror = __uget_timex_m($txc_p, 3) * buf_esterror = __uget_timex_m($txc_p, 4) * buf_status = __uget_timex_m($txc_p, 5) * buf_constant = __uget_timex_m($txc_p, 6) * buf_precision = __uget_timex_m($txc_p, 7) * buf_tolerance = __uget_timex_m($txc_p, 8) * buf_time_tv_sec = __uget_timex_m($txc_p, 9) * buf_time_tv_usec = __uget_timex_m($txc_p, 10) * buf_tick = __uget_timex_m($txc_p, 11) */ argstr = sprintf("%p", $txc_p) } probe syscall.adjtimex.return = kernel.function("sys_adjtimex").return { name = "adjtimex" retstr = _adjtimex_return_str($return) } # long compat_sys_adjtimex(struct compat_timex __user *utp) probe syscall.compat_adjtimex = kernel.function("compat_sys_adjtimex").call ? { name = "compat_adjtimex" argstr = sprintf("%p", $utp) } probe syscall.compat_adjtimex.return = kernel.function("compat_sys_adjtimex").return ? { name = "compat_adjtimex" retstr = return_str(1, $return) } # alarm ______________________________________________________ # unsigned long sys_alarm (unsigned int seconds) # long sys32_alarm(unsigned int seconds) # probe syscall.alarm = kernel.function("sys32_alarm").call ?, kernel.function("sys_alarm").call ? { name = "alarm" seconds = $seconds argstr = sprint($seconds) } probe syscall.alarm.return = kernel.function("sys32_alarm").return ?, kernel.function("sys_alarm").return ? { name = "alarm" retstr = return_str(1, $return) } # bdflush ____________________________________________________ # long sys_bdflush(int func, long data) probe syscall.bdflush = kernel.function("sys_bdflush").call ? { name = "bdflush" func = $func data = $data if (($func >= 2) && ($func % 2 == 0)) data_str = sprintf("%p", $data) else data_str = sprintf("%d", $data) argstr = sprintf("%d, %s", func, data_str) } probe syscall.bdflush.return = kernel.function("sys_bdflush").return ? { name = "bdflush" retstr = return_str(1, $return) } # bind _______________________________________________________ # long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) probe syscall.bind = kernel.function("sys_bind").call ? { name = "bind" sockfd = $fd my_addr_uaddr = $umyaddr addrlen = $addrlen argstr = sprintf("%d, %s, %d", $fd, _struct_sockaddr_u($umyaddr, $addrlen), $addrlen) } probe syscall.bind.return = kernel.function("sys_bind").return ? { name = "bind" retstr = return_str(1, $return) } # brk ________________________________________________________ # unsigned long sys_brk(unsigned long brk) probe syscall.brk = kernel.function("ia64_brk").call ?, kernel.function("sys_brk").call { name = "brk" brk = $brk argstr = sprintf("%p", brk) } probe syscall.brk.return = kernel.function("ia64_brk").return ?, kernel.function("sys_brk").return { name = "brk" retstr = return_str(1, $return) } # capget _____________________________________________________ /* * NOTE * this is probably not a good function * to probe. The structures are always * changing. It also seems like it is * not really used. Cscope produced no * reference of this function in the * kernel (returned no callers). Perhaps * cap_get_proc / cap_set_proc are better * functions to export. */ # long sys_capget(cap_user_header_t header, cap_user_data_t dataptr) probe syscall.capget = kernel.function("sys_capget").call { name = "capget" header_uaddr = $header data_uaddr = $dataptr argstr = sprintf("%p, %p", $header, $dataptr) } probe syscall.capget.return = kernel.function("sys_capget").return { name = "capget" retstr = return_str(1, $return) } # capset _____________________________________________________ /* * NOTE * this is probably not a good function * to probe. The structures are always * changing. It also seems like it is * not really used. Cscope produced no * reference of this function in the * kernel (returned no callers). Perhaps * cap_get_proc / cap_set_proc are better * functions to export. */ # long sys_capset(cap_user_header_t header, const cap_user_data_t data) probe syscall.capset = kernel.function("sys_capset").call { name = "capset" header_uaddr = $header data_uaddr = $data argstr = sprintf("%p, %p", $header, $data) } probe syscall.capset.return = kernel.function("sys_capset").return { name = "capset" retstr = return_str(1, $return) } # chdir ______________________________________________________ # long sys_chdir(const char __user * filename) probe syscall.chdir = kernel.function("sys_chdir").call { name = "chdir" path = user_string_quoted($filename) argstr = user_string_quoted($filename) } probe syscall.chdir.return = kernel.function("sys_chdir").return { name = "chdir" retstr = return_str(1, $return) } # chmod ______________________________________________________ # long sys_chmod(const char __user * filename, mode_t mode) probe syscall.chmod = kernel.function("sys_chmod").call { name = "chmod" path = user_string_quoted($filename) mode = $mode argstr = sprintf("%s, %#o", user_string_quoted($filename), mode) } probe syscall.chmod.return = kernel.function("sys_chmod").return { name = "chmod" retstr = return_str(1, $return) } # chown ______________________________________________________ # long sys_chown(const char __user * filename, uid_t user, gid_t group) probe syscall.chown = kernel.function("sys_chown").call { name = "chown" path = user_string_quoted($filename) owner = __int32($user) group = __int32($group) argstr = sprintf("%s, %d, %d", user_string_quoted($filename), owner, group) } probe syscall.chown.return = kernel.function("sys_chown").return { name = "chown" retstr = return_str(1, $return) } # chown16 ___________________________________________________ # long sys_chown16(const char __user * filename, old_uid_t user, # old_gid_t group) # probe syscall.chown16 = kernel.function("sys_chown16").call ? { name = "chown16" path = user_string_quoted($filename) owner = __short($user) group = __short($group) argstr = sprintf("%s, %d, %d", user_string_quoted($filename), owner, group) } probe syscall.chown16.return = kernel.function("sys_chown16").return ? { name = "chown16" retstr = return_str(1, $return) } # chroot _____________________________________________________ # long sys_chroot(const char __user * filename) probe syscall.chroot = kernel.function("sys_chroot").call { name = "chroot" path = user_string_quoted($filename) argstr = user_string_quoted($filename) } probe syscall.chroot.return = kernel.function("sys_chroot").return { name = "chroot" retstr = return_str(1, $return) } # clock_getres _______________________________________________ # long sys_clock_getres(clockid_t which_clock, struct timespec __user *tp) # long compat_clock_getres(clockid_t which_clock, struct compat_timespec __user *tp) # probe syscall.clock_getres = kernel.function("compat_clock_getres").call ?, kernel.function("sys_clock_getres").call { name = "clock_getres" clk_id = $which_clock clk_id_str = _get_wc_str($which_clock) res_uaddr = $tp argstr = sprintf("%s, %p", _get_wc_str($which_clock), $tp) } probe syscall.clock_getres.return = kernel.function("compat_clock_getres").return ?, kernel.function("sys_clock_getres").return { name = "clock_getres" retstr = return_str(1, $return) } # clock_gettime ______________________________________________ # long sys_clock_gettime(clockid_t which_clock, struct timespec __user *tp) # probe syscall.clock_gettime = kernel.function("sys_clock_gettime").call { name = "clock_gettime" clk_id = $which_clock clk_id_str = _get_wc_str($which_clock) argstr = sprintf("%s, %p", _get_wc_str($which_clock), $tp) } probe syscall.clock_gettime.return = kernel.function("sys_clock_gettime").return { name = "clock_gettime" retstr = return_str(1, $return) } # clock_nanosleep ____________________________________________ # long sys_clock_nanosleep(clockid_t which_clock, # int flags, # const struct timespec __user *rqtp, # struct timespec __user *rmtp) # probe syscall.clock_nanosleep = kernel.function("sys_clock_nanosleep").call { name = "clock_nanosleep" flags = $flags if ($flags == 1) flag_str = "TIMER_ABSTIME" else flag_str = sprintf("0x%x", $flags) argstr = sprintf("%s, %s, %s, %p", _get_wc_str($which_clock), flag_str, _struct_timespec_u($rqtp, 1), $rmtp) } probe syscall.clock_nanosleep.return = kernel.function("sys_clock_nanosleep").return { name = "clock_nanosleep" retstr = return_str(1, $return) } # compat_clock_nanosleep ________________________________________ # # long compat_clock_nanosleep(clockid_t which_clock, int flags, # struct compat_timespec __user *rqtp, # struct compat_timespec __user *rmtp) # probe syscall.compat_clock_nanosleep = kernel.function("compat_clock_nanosleep").call ?, kernel.function("compat_sys_clock_nanosleep").call ? { name = "compat_clock_nanosleep" flags = $flags if ($flags == 1) flag_str = "TIMER_ABSTIME" else flag_str = sprintf("0x%x", $flags) argstr = sprintf("%s, %s, %s, %p", _get_wc_str($which_clock), flag_str, _struct_compat_timespec_u($rqtp, 1), $rmtp) } probe syscall.compat_clock_nanosleep.return = kernel.function("compat_clock_nanosleep").return ?, kernel.function("compat_sys_clock_nanosleep").return ? { name = "compat_clock_nanosleep" retstr = return_str(1, $return) } # clock_settime ______________________________________________ # long sys_clock_settime(clockid_t which_clock, # const struct timespec __user *tp) # probe syscall.clock_settime = kernel.function("sys_clock_settime").call { name = "clock_settime" clk_id = $which_clock clk_id_str = _get_wc_str($which_clock) tp_uaddr = $tp argstr = sprintf("%s, %s", clk_id_str, _struct_timespec_u($tp, 1)) } probe syscall.clock_settime.return = kernel.function("sys_clock_settime").return { name = "clock_settime" retstr = return_str(1, $return) } # close ______________________________________________________ # long sys_close(unsigned int fd) probe syscall.close = kernel.function("sys_close").call { name = "close" fd = $fd argstr = sprint(fd) } probe syscall.close.return = kernel.function("sys_close").return { name = "close" retstr = return_str(1, $return) } # connect ____________________________________________________ # long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen) probe syscall.connect = kernel.function("sys_connect").call ? { name = "connect" sockfd = $fd serv_addr_uaddr = $uservaddr addrlen = $addrlen argstr = sprintf("%d, %s, %d", $fd, _struct_sockaddr_u($uservaddr, $addrlen), $addrlen) } probe syscall.connect.return = kernel.function("sys_connect").return ? { name = "connect" retstr = return_str(1, $return) } # creat # long sys_creat(const char __user * pathname, int mode) probe syscall.creat = kernel.function("sys_creat").call ? { name = "creat" mode = $mode pathname = user_string_quoted($pathname) argstr = sprintf("%s, %#o", user_string_quoted($pathname), $mode) } probe syscall.creat.return = kernel.function("sys_creat").return ? { name = "creat" retstr = return_str(1, $return) } # delete_module ______________________________________________ # long sys_delete_module(const char __user *name_user, unsigned int flags) probe syscall.delete_module = kernel.function("sys_delete_module").call ? { name = "delete_module" name_user = user_string_quoted($name_user) flags = $flags argstr = sprintf("%s, %s", user_string_quoted($name_user), _module_flags_str($flags)) } probe syscall.delete_module.return = kernel.function("sys_delete_module").return ? { name = "delete_module" retstr = return_str(1, $return) } # dup ________________________________________________________ # long sys_dup(unsigned int fildes) probe syscall.dup = kernel.function("sys_dup").call { name = "dup" oldfd = $fildes argstr = sprint($fildes) } probe syscall.dup.return = kernel.function("sys_dup").return { name = "dup" retstr = return_str(1, $return) } # Notice there are two syscall.dup2 probe aliases. This is # intentional, to handle dup2/dup3 properly (and all their corner # cases). See commit 816395 for details (and a testcase). # # dup2 _______________________________________________________ # long sys_dup2(unsigned int oldfd, unsigned int newfd) # Only handles corner case, others handled by dup3. probe syscall.dup2 = kernel.function("sys_dup2").call { if ($oldfd != $newfd) next; name = "dup2" oldfd = $oldfd newfd = $newfd flags = 0 argstr = sprintf("%d, %d", $oldfd, $newfd) } probe syscall.dup2.return = kernel.function("sys_dup2").return { if ($oldfd != $newfd) next; name = "dup2" retstr = return_str(1, $return) } # dup3 (handles both dup2 and dup3 except for corner case)___________ # long sys_dup2(unsigned int oldfd, unsigned int newfd) # SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags) probe syscall.dup2 = kernel.function("sys_dup3").call !, kernel.function("sys_dup2").call { oldfd = $oldfd newfd = $newfd flags = @choose_defined($flags, 0); # Corner case handled by dup2 if ($oldfd == $newfd && flags == 0) next if (flags == 0) { name = "dup2"; argstr = sprintf("%d, %d", $oldfd, $newfd); } else { name = "dup3"; argstr = sprintf("%d, %d, %s", $oldfd, $newfd, _dup3_flag_str(flags)); } } probe syscall.dup2.return = kernel.function("sys_dup3").return !, kernel.function("sys_dup2").return { flags = @choose_defined($flags, 0); # Corner case handled by dup2 if ($oldfd == $newfd && flags == 0) next name = flags == 0 ? "dup2" : "dup3"; retstr = return_str(1, $return) } # epoll_create _______________________________________________ # long sys_epoll_create(int size) # SYSCALL_DEFINE1(epoll_create1, int, flags) probe syscall.epoll_create = kernel.function("sys_epoll_create1").call !, kernel.function("sys_epoll_create").call ? { size = @choose_defined($size, 0); flags = @choose_defined($flags, 0); if (flags == 0) { name = "epoll_create"; argstr = sprint(size); } else { name = "epoll_create1"; argstr = _epoll_create1_flag_str(flags); } } probe syscall.epoll_create.return = kernel.function("sys_epoll_create1").return !, kernel.function("sys_epoll_create").return ? { flags = @choose_defined($flags, 0); name = (flags == 0) ? "epoll_create" : "epoll_create1"; retstr = return_str(1, $return) } # epoll_ctl __________________________________________________ # # long sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event) # long compat_sys_epoll_ctl(int epfd, int op, int fd, # struct compat_epoll_event __user *event) # probe syscall.epoll_ctl = kernel.function("compat_sys_epoll_ctl").call ?, kernel.function("sys_epoll_ctl").call ? { name = "epoll_ctl" epfd = $epfd op = $op op_str = _opoll_op_str($op) fd = $fd event_uaddr = $event argstr = sprintf("%d, %s, %d, %p", $epfd, _opoll_op_str($op), $fd, $event) } probe syscall.epoll_ctl.return = kernel.function("compat_sys_epoll_ctl").return ?, kernel.function("sys_epoll_ctl").return ? { name = "epoll_ctl" retstr = return_str(1, $return) } # epoll_pwait _________________________________________________ # # long sys_epoll_pwait(int epfd, struct epoll_event __user *events, # int maxevents, int timeout, const sigset_t __user *sigmask, # size_t sigsetsize) # long compat_sys_epoll_pwait(int epfd, # struct compat_epoll_event __user *events, # int maxevents, int timeout, # const compat_sigset_t __user *sigmask, # compat_size_t sigsetsize) # probe syscall.epoll_pwait = kernel.function("compat_sys_epoll_pwait").call ?, kernel.function("sys_epoll_pwait").call ? { name = "epoll_pwait" argstr = sprintf("%d, %p, %d, %d, %p, %d", $epfd, $events, $maxevents, $timeout, $sigmask, $sigsetsize) } probe syscall.epoll_pwait.return = kernel.function("compat_sys_epoll_pwait").return ?, kernel.function("sys_epoll_pwait").return ? { name = "epoll_pwait" retstr = return_str(1, $return) } # epoll_wait _________________________________________________ # # long sys_epoll_wait(int epfd, struct epoll_event __user *events, # int maxevents, int timeout) # long compat_sys_epoll_wait(int epfd, # struct compat_epoll_event __user *events, # int maxevents, int timeout) # probe syscall.epoll_wait = kernel.function("compat_sys_epoll_wait").call ?, kernel.function("sys_epoll_wait").call ? { name = "epoll_wait" epfd = $epfd events_uaddr = $events maxevents = $maxevents timeout = $timeout argstr = sprintf("%d, %p, %d, %d", $epfd, $events, $maxevents, $timeout) } probe syscall.epoll_wait.return = kernel.function("compat_sys_epoll_wait").return ?, kernel.function("sys_epoll_wait").return ? { name = "epoll_wait" retstr = return_str(1, $return) } # eventfd _____________________________________________________ # long sys_eventfd(unsigned int count) # SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags) probe syscall.eventfd = kernel.function("sys_eventfd2").call !, kernel.function("sys_eventfd").call ? { flags = @choose_defined($flags, 0) if (flags == 0) { name = "eventfd" argstr = sprint($count) } else { name = "eventfd2" argstr = sprintf("%d, %s", $count, _eventfd2_flag_str(flags)) } } probe syscall.eventfd.return = kernel.function("sys_eventfd2").return !, kernel.function("sys_eventfd").return ? { flags = @choose_defined($flags, 0) name = flags == 0 ? "eventfd" : "eventfd2" retstr = return_str(1, $return) } # execve _____________________________________________________ # SYSCALL_DEFINE3(execve, # const char __user *, filename, # const char __user *const __user *, argv, # const char __user *const __user *, envp) probe syscall.execve = kernel.function("sys_execve").call { name = "execve" filename = user_string(@choose_defined($filename, $name)) # kernel 3.0 changed the pointer's name to __argv __argv = @choose_defined($__argv, $argv) args = __get_argv(__argv, 0) argstr = sprintf("%s %s", filename, __get_argv(__argv, 1)) } probe syscall.execve.return = kernel.function("sys_execve").return { name = "execve" retstr = return_str(1, $return) } # asmlinkage long compat_sys_execve(const char __user * filename, # const compat_uptr_t __user * argv, # const compat_uptr_t __user * envp) # static int compat_do_execve(const char *filename, # const compat_uptr_t __user *__argv, # const compat_uptr_t __user *__envp) probe syscall.compat_execve = _syscall.compat_sys_execve !, _syscall.compat_do_execve ? { name = "compat_execve" # kernel 3.0 changed the pointer's name to __argv __argv = @choose_defined($__argv, $argv) args = __get_compat_argv(__argv, 0) argstr = sprintf("%s %s", filename, __get_compat_argv(__argv, 1)) } probe _syscall.compat_sys_execve = kernel.function("compat_sys_execve").call { filename = user_string($filename) } probe _syscall.compat_do_execve = kernel.function("compat_do_execve").call { filename = kernel_string($filename) } probe syscall.compat_execve.return = kernel.function("compat_sys_execve").return !, kernel.function("compat_do_execve").return ? { name = "compat_execve" retstr = return_str(1, $return) } # exit _______________________________________________________ # long sys_exit(int error_code) probe syscall.exit = kernel.function("do_exit").call { name = "exit" status = $code argstr = sprint($code) } # sys_exit() never returns, and is blacklisted for return probes, # so no alias here. See bz6588. # exit_group _________________________________________________ # void sys_exit_group(int error_code) # probe syscall.exit_group = kernel.function("sys_exit_group").call { name = "exit_group" status = $error_code argstr = sprint($error_code) } # sys_exit_group() never returns, and is blacklisted for return probes, # so no alias here. See bz6588. # faccessat __________________________________________________ # new function with 2.6.16 # long sys_faccessat(int dfd, const char __user *filename, int mode) probe syscall.faccessat = kernel.function("sys_faccessat").call ? { name = "faccessat" dirfd = $dfd dirfd_str = _dfd_str($dfd) pathname = user_string_quoted($filename) mode = $mode mode_str = _access_mode_str($mode) argstr = sprintf("%s, %s, %s", dirfd_str, user_string_quoted($filename), mode_str) } probe syscall.faccessat.return = kernel.function("sys_faccessat").return ? { name = "faccessat" retstr = return_str(1, $return) } # fadvise64 __________________________________________________ # long sys_fadvise64(int fd, loff_t offset, size_t len, int advice) # probe syscall.fadvise64 = kernel.function("sys_fadvise64").call ? { name = "fadvise64" fd = @choose_defined($fd, 0) offset = @choose_defined($offset, 0) len = @choose_defined($len, 0) advice = @choose_defined($advice, 0) argstr = sprintf("%d, %d, %d, %s", $fd, $offset, $len, _fadvice_advice_str($advice)) } probe syscall.fadvise64.return = kernel.function("sys_fadvise64").return ? { name = "fadvise64" retstr = return_str(1, $return) } # fadvise64_64 _______________________________________________ # long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) # probe syscall.fadvise64_64 = kernel.function("sys_fadvise64_64").call ? { name = "fadvise64_64" fd = @choose_defined($fd, 0) offset = @choose_defined($offset, 0) len = @choose_defined($len, 0) advice = @choose_defined($advice, 0) argstr = sprintf("%d, %d, %d, %s", $fd, $offset, $len, _fadvice_advice_str($advice)) } probe syscall.fadvise64_64.return = kernel.function("sys_fadvise64_64").return ? { name = "fadvise64_64" retstr = return_str(1, $return) } # fchdir _____________________________________________________ # long sys_fchdir(unsigned int fd) probe syscall.fchdir = kernel.function("sys_fchdir").call { name = "fchdir" fd = $fd argstr = sprint($fd) } probe syscall.fchdir.return = kernel.function("sys_fchdir").return { name = "fchdir" retstr = return_str(1, $return) } # fchmod _____________________________________________________ # long sys_fchmod(unsigned int fd, mode_t mode) probe syscall.fchmod = kernel.function("sys_fchmod").call { name = "fchmod" fildes = $fd mode = $mode argstr = sprintf("%d, %#o", $fd, $mode) } probe syscall.fchmod.return = kernel.function("sys_fchmod").return { name = "fchmod" retstr = return_str(1, $return) } # fchmodat ___________________________________________________ # new function with 2.6.16 # long sys_fchmodat(int dfd, const char __user *filename, # mode_t mode) probe syscall.fchmodat = kernel.function("sys_fchmodat").call ? { name = "fchmodat" dirfd = $dfd dirfd_str = _dfd_str($dfd) pathname = user_string_quoted($filename) mode = $mode argstr = sprintf("%s, %s, %#o", dirfd_str, user_string_quoted($filename), $mode) } probe syscall.fchmodat.return = kernel.function("sys_fchmodat").return ? { name = "fchmodat" retstr = return_str(1, $return) } # fchown _____________________________________________________ # long sys_fchown(unsigned int fd, uid_t user, gid_t group) probe syscall.fchown = kernel.function("sys_fchown").call { name = "fchown" fd = $fd owner = __int32($user) group = __int32($group) argstr = sprintf("%d, %d, %d", $fd, owner, group) } probe syscall.fchown.return = kernel.function("sys_fchown").return { name = "fchown" retstr = return_str(1, $return) } # fchown16 ___________________________________________________ # long sys_fchown16(unsigned int fd, old_uid_t user, old_gid_t group) probe syscall.fchown16 = kernel.function("sys_fchown16").call ? { name = "fchown16" fd = $fd owner = __short($user) group = __short($group) argstr = sprintf("%d, %d, %d", $fd, owner, group) } probe syscall.fchown16.return = kernel.function("sys_fchown16").return ? { name = "fchown16" retstr = return_str(1, $return) } # fchownat ___________________________________________________ # new function with 2.6.16 # long sys_fchownat(int dfd, const char __user *filename, # uid_t user, gid_t group, int flag) probe syscall.fchownat = kernel.function("sys_fchownat").call ? { name = "fchownat" dirfd = $dfd dirfd_str = _dfd_str($dfd) pathname = user_string_quoted($filename) owner = __int32($user) group = __int32($group) flags = $flag flags_str = _at_flag_str($flag) argstr = sprintf("%s, %s, %d, %d, %s", dirfd_str, user_string_quoted($filename), owner, group, flags_str) } probe syscall.fchownat.return = kernel.function("sys_fchownat").return ? { name = "fchownat" retstr = return_str(1, $return) } # fcntl ______________________________________________________ # long sys_fcntl(int fd, unsigned int cmd, unsigned long arg) # long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) # long compat_sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) # long compat_sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) # probe syscall.fcntl = kernel.function("compat_sys_fcntl").call ?, kernel.function("compat_sys_fcntl64").call ?, kernel.function("sys_fcntl64").call ?, kernel.function("sys_fcntl").call ? { name = "fcntl" fd = $fd cmd = $cmd cmd_str = _fcntl_cmd_str($cmd) arg = $arg argstr = sprintf("%d, %s, %p", $fd, _fcntl_cmd_str($cmd), $arg) } probe syscall.fcntl.return = kernel.function("compat_sys_fcntl").return ?, kernel.function("compat_sys_fcntl64").return ?, kernel.function("sys_fcntl64").return ?, kernel.function("sys_fcntl").return ? { name = "fcntl" retstr = return_str(1, $return) } # fdatasync __________________________________________________ # long sys_fdatasync(unsigned int fd) probe syscall.fdatasync = kernel.function("sys_fdatasync").call { name = "fdatasync" fd = $fd argstr = sprint(fd) } probe syscall.fdatasync.return = kernel.function("sys_fdatasync").return { name = "fdatasync" retstr = return_str(1, $return) } # fgetxattr __________________________________________________ # ssize_t sys_fgetxattr(int fd, char __user *name, # void __user *value, size_t size) probe syscall.fgetxattr = kernel.function("sys_fgetxattr").call { name = "fgetxattr" filedes = $fd # 'name2' should have been 'name_str'. Deprecate the old name. %(systemtap_v <= "1.4" %? name2 = user_string_quoted($name) %) name_str = user_string_quoted($name) value_uaddr = $value size = $size argstr = sprintf("%d, %s, %p, %d", filedes, user_string_quoted($name), value_uaddr, size) } probe syscall.fgetxattr.return = kernel.function("sys_fgetxattr").return { name = "fgetxattr" retstr = return_str(1, $return) } # flistxattr _________________________________________________ # ssize_t sys_flistxattr(int fd, char __user *list, size_t size) probe syscall.flistxattr = kernel.function("sys_flistxattr").call { name = "flistxattr" filedes = $fd list_uaddr = $list size = $size argstr = sprintf("%d, %p, %d", filedes, list_uaddr, size) } probe syscall.flistxattr.return = kernel.function("sys_flistxattr").return { name = "flistxattr" retstr = return_str(1, $return) } # flock ______________________________________________________ # long sys_flock(unsigned int fd, unsigned int cmd) probe syscall.flock = kernel.function("sys_flock").call { name = "flock" fd = $fd operation = $cmd argstr = sprintf("%d, %s", fd, _flock_cmd_str(operation)) } probe syscall.flock.return = kernel.function("sys_flock").return { name = "flock" retstr = return_str(1, $return) } # fork _______________________________________________________ # long do_fork(unsigned long clone_flags, # unsigned long stack_start, # unsigned long stack_size, # int __user *parent_tidptr, # int __user *child_tidptr) probe syscall.fork = kernel.function("do_fork").call { clone_flags = $clone_flags stack_start = $stack_start stack_size = $stack_size parent_tid_uaddr = $parent_tidptr child_tid_uaddr = $child_tidptr if (@defined($regs)) { %(systemtap_v < "2.3" %? regs = $regs %) if (!__is_user_regs($regs)) { name = "fork_kernel_thread" argstr = __fork_flags($clone_flags) } else if ($clone_flags & %{ CLONE_VFORK %}) { name = "vfork" } else if (($clone_flags & %{ CSIGNAL %}) != %{ SIGCHLD %}) { name = "clone" argstr = __fork_flags($clone_flags) } else { name = "fork" } } else { %(systemtap_v < "2.3" %? regs = 0 %) if ($clone_flags & %{ CLONE_VM | CLONE_UNTRACED %}) { name = "fork_kernel_thread" argstr = __fork_flags($clone_flags) } else if ($clone_flags & %{ CLONE_VFORK %}) { name = "vfork" } else if (($clone_flags & %{ CSIGNAL %}) != %{ SIGCHLD %}) { name = "clone" argstr = __fork_flags($clone_flags) } else { name = "fork" } } } probe syscall.fork.return = kernel.function("do_fork").return { name = "fork" retstr = return_str(1, $return) } # fremovexattr _______________________________________________ # long sys_fremovexattr(int fd, char __user *name) probe syscall.fremovexattr = kernel.function("sys_fremovexattr").call { name = "fremovexattr" filedes = $fd name_uaddr = $name name_str = user_string_quoted($name) argstr = sprintf("%d, %s", $fd, user_string_quoted($name)) } probe syscall.fremovexattr.return = kernel.function("sys_fremovexattr").return { name = "fremovexattr" retstr = return_str(1, $return) } # fsetxattr __________________________________________________ /* * asmlinkage long * sys_fsetxattr(int fd, * char __user *name, * void __user *value, * size_t size, * int flags) */ probe syscall.fsetxattr = kernel.function("sys_fsetxattr").call { name = "fsetxattr" filedes = $fd # 'name2' should have been 'name_str'. Deprecate the old name. %(systemtap_v <= "1.4" %? name2 = user_string_quoted($name) %) name_uaddr = $name name_str = user_string_quoted($name) value_uaddr = $value size = $size flags = $flags argstr = sprintf("%d, %s, %p, %d, %p", $fd, user_string_quoted($name), $value, $size, $flags) } probe syscall.fsetxattr.return = kernel.function("sys_fsetxattr").return { name = "fsetxattr" retstr = return_str(1, $return) } # fstat ______________________________________________________ # long sys_fstat(unsigned int fd, struct __old_kernel_stat __user * statbuf) # long sys_fstat64(unsigned long fd, struct stat64 __user * statbuf) # long sys32_fstat64(unsigned int fd, struct stat64 __user *statbuf) # long sys_newfstat(unsigned int fd, struct stat __user * statbuf) # long sys_oabi_fstat64(char __user * filename, # struct oldabi_stat64 __user * statbuf) # long compat_sys_newfstat(unsigned int fd, struct compat_stat __user * statbuf) # probe syscall.fstat = kernel.function("sys_fstat").call ?, kernel.function("sys_fstat64").call ?, kernel.function("sys32_fstat64").call ?, kernel.function("sys_newfstat").call ?, kernel.function("sys_oabi_fstat64").call ?, kernel.function("compat_sys_newfstat").call ? { name = "fstat" filedes = $fd buf_uaddr = $statbuf argstr = sprintf("%d, %p", $fd, $statbuf) } probe syscall.fstat.return = kernel.function("sys_fstat").return ?, kernel.function("sys_fstat64").return ?, kernel.function("sys32_fstat64").return ?, kernel.function("sys_newfstat").return ?, kernel.function("sys_oabi_fstat64").return ?, kernel.function("compat_sys_newfstat").return ? { name = "fstat" retstr = return_str(1, $return) } # fstatat ____________________________________________________ # sys32_fstatat64(unsigned int dfd, char __user *filename, struct stat64_emu31 __user* statbuf, int flag) # long sys_newfstatat(int dfd, char __user *filename, struct stat __user *statbuf, int flag) # long sys_fstatat64(int dfd, char __user *filename, struct stat64 __user *statbuf, int flag) # long compat_sys_newfstatat(unsigned int dfd, char __user *filename, struct compat_stat __user *statbuf, int flag) probe syscall.fstatat = kernel.function("sys_fstatat64").call ?, kernel.function("sys_newfstatat").call ?, kernel.function("compat_sys_newfstatat").call ?, kernel.function("sys32_fstatat64").call ? { name = "fstatat" dirfd = $dfd path = user_string_quoted($filename) buf_uaddr = $statbuf argstr = sprintf("%s, %s, %p, %s", _dfd_str($dfd), user_string_quoted($filename), $statbuf, _at_flag_str($flag)) } probe syscall.fstatat.return = kernel.function("sys_fstatat64").return ?, kernel.function("sys_newfstatat").return ?, kernel.function("compat_sys_newfstatat").return ?, kernel.function("sys32_fstatat64").return ? { name = "fstatat" retstr = return_str(1, $return) } # fstatfs ____________________________________________________ # long sys_fstatfs(unsigned int fd, struct statfs __user * buf) # long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user *buf) # probe syscall.fstatfs = kernel.function("compat_sys_fstatfs").call ?, kernel.function("sys_fstatfs").call { name = "fstatfs" fd = $fd buf_uaddr = $buf argstr = sprintf("%d, %p", $fd, $buf) } probe syscall.fstatfs.return = kernel.function("compat_sys_fstatfs").return ?, kernel.function("sys_fstatfs").return { name = "fstatfs" retstr = return_str(1, $return) } # fstatfs64 __________________________________________________ # long sys_fstatfs64(unsigned int fd, size_t sz, struct statfs64 __user *buf) # long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf) # probe syscall.fstatfs64 = kernel.function("compat_sys_fstatfs64").call ?, kernel.function("sys_fstatfs64").call ? { name = "fstatfs" fd = $fd sz = $sz buf_uaddr = $buf argstr = sprintf("%d, %d, %p", $fd, $sz, $buf) } probe syscall.fstatfs64.return = kernel.function("compat_sys_fstatfs64").return ?, kernel.function("sys_fstatfs64").return ? { name = "fstatfs" retstr = return_str(1, $return) } # fsync ______________________________________________________ # long sys_fsync(unsigned int fd) probe syscall.fsync = kernel.function("sys_fsync").call { name = "fsync" fd = $fd argstr = sprint(fd) } probe syscall.fsync.return = kernel.function("sys_fsync").return { name = "fsync" retstr = return_str(1, $return) } # ftruncate __________________________________________________ # long sys_ftruncate(unsigned int fd, unsigned long length) probe syscall.ftruncate = kernel.function("sys_ftruncate").call { name = "ftruncate" fd = $fd length = $length argstr = sprintf("%d, %d", fd, length) } probe syscall.ftruncate.return = kernel.function("sys_ftruncate").return { name = "ftruncate" retstr = return_str(1, $return) } # ftruncate64 ________________________________________________ # long sys_ftruncate64(unsigned int fd, loff_t length) probe syscall.ftruncate64 = kernel.function("sys_ftruncate64").call ? { name = "ftruncate" fd = $fd length = $length argstr = sprintf("%d, %d", fd, length) } probe syscall.ftruncate64.return = kernel.function("sys_ftruncate64").return ? { name = "ftruncate" retstr = return_str(1, $return) } # futex ______________________________________________________ # long sys_futex(u32 __user *uaddr, # int op, # int val, # struct timespec __user *utime, # u32 __user *uaddr2, # int val3) # long compat_sys_futex(u32 __user *uaddr, int op, u32 val, # struct compat_timespec __user *utime, u32 __user *uaddr2, # u32 val3) # probe syscall.futex = kernel.function("sys_futex").call ? { name = "futex" futex_uaddr = $uaddr op = $op val = $val utime_uaddr = $utime uaddr2_uaddr = $uaddr2 val3 = $val3 if ($op == 0) argstr = sprintf("%p, %s, %d, %s", $uaddr, _futex_op_str($op), $val, _struct_timespec_u($utime, 1)) else argstr = sprintf("%p, %s, %d", $uaddr, _futex_op_str($op), $val) } probe syscall.futex.return = kernel.function("sys_futex").return ? { name = "futex" retstr = return_str(1, $return) } probe syscall.compat_futex = kernel.function("compat_sys_futex").call ? { name = "futex" futex_uaddr = $uaddr op = $op val = $val utime_uaddr = $utime uaddr2_uaddr = $uaddr2 val3 = $val3 if ($op == 0) argstr = sprintf("%p, %s, %d, %s", $uaddr, _futex_op_str($op), $val, _struct_compat_timespec_u($utime, 1)) else argstr = sprintf("%p, %s, %d", $uaddr, _futex_op_str($op), $val) } probe syscall.compat_futex.return = kernel.function("compat_sys_futex").return ? { name = "futex" retstr = return_str(1, $return) } # futimesat _____________________________________________________ # # long sys_futimesat(int dfd, char __user *filename, struct timeval __user *utimes) # long compat_sys_futimesat(unsigned int dfd, char __user *filename, struct compat_timeval __user *t) # probe syscall.futimesat = kernel.function("sys_futimesat").call ? { name = "futimesat" dirfd = $dfd filename_uaddr = $filename filename = user_string_quoted($filename) tvp_uaddr = $utimes argstr = sprintf("%s, %s, %s", _dfd_str($dfd), user_string_quoted($filename), _struct_timeval_u($utimes, 2)) } probe syscall.compat_futimesat = kernel.function("compat_sys_futimesat").call ? { name = "futimesat" dirfd = $dfd filename_uaddr = $filename filename = user_string_quoted($filename) tvp_uaddr = $t argstr = sprintf("%s, %s, %s", _dfd_str($dfd), user_string_quoted($filename), _struct_compat_timeval_u($t, 2)) } probe syscall.futimesat.return = kernel.function("sys_futimesat").return ? { name = "futimesat" retstr = return_str(1, $return) } probe syscall.compat_futimesat.return = kernel.function("compat_sys_futimesat").return ? { name = "futimesat" retstr = return_str(1, $return) } # getcwd _____________________________________________________ # long sys_getcwd(char __user *buf, unsigned long size) probe syscall.getcwd = kernel.function("sys_getcwd").call { name = "getcwd" buf_uaddr = $buf size = $size argstr = sprintf("%p, %d", buf_uaddr, size) } probe syscall.getcwd.return = kernel.function("sys_getcwd").return { name = "getcwd" retstr = return_str(1, $return) } # getdents ___________________________________________________ # long sys_getdents(unsigned int fd, struct linux_dirent __user * dirent, unsigned int count) # long compat_sys_getdents(unsigned int fd, struct compat_linux_dirent __user *dirent, unsigned int count) # long sys_getdents64(unsigned int fd, struct linux_dirent64 __user * dirent, unsigned int count) # long compat_sys_getdents64(unsigned int fd, struct linux_dirent64 __user * dirent, unsigned int count) # probe syscall.getdents = kernel.function("sys_getdents").call ?, kernel.function("sys_getdents64").call ?, kernel.function("compat_sys_getdents").call ?, kernel.function("compat_sys_getdents64").call ? { name = "getdents" fd = $fd dirp_uaddr = $dirent count = $count argstr = sprintf("%d, %p, %d", $fd, $dirent, $count) } probe syscall.getdents.return = kernel.function("sys_getdents").return ?, kernel.function("sys_getdents64").return ?, kernel.function("compat_sys_getdents").return ?, kernel.function("compat_sys_getdents64").return ? { name = "getdents" retstr = return_str(1, $return) } # getegid ____________________________________________________ # long sys_getegid(void) # long sys_getegid16(void) # long sys32_getegid16(void) # probe syscall.getegid = kernel.function("sys_getegid16").call ?, kernel.function("sys32_getegid16").call ?, kernel.function("sys_getegid").call { name = "getegid" argstr = "" } probe syscall.getegid.return = kernel.function("sys_getegid16").return ?, kernel.function("sys32_getegid16").return ?, kernel.function("sys_getegid").return { name = "getegid" retstr = return_str(1, $return) } # geteuid ____________________________________________________ # long sys_geteuid(void) # long sys32_geteuid16(void) # probe syscall.geteuid = kernel.function("sys_geteuid16").call ?, kernel.function("sys32_geteuid16").call ?, kernel.function("sys_geteuid").call { name = "geteuid" argstr = "" } probe syscall.geteuid.return = kernel.function("sys_geteuid16").return ?, kernel.function("sys32_geteuid16").return ?, kernel.function("sys_geteuid").return { name = "geteuid" retstr = return_str(1, $return) } # getgid _____________________________________________________ # long sys_getgid(void) # long sys32_getgid16(void) # probe syscall.getgid = kernel.function("sys_getgid16").call ?, kernel.function("sys32_getgid16").call ?, kernel.function("sys_getgid").call { name = "getgid" argstr = "" } probe syscall.getgid.return = kernel.function("sys_getgid16").return ?, kernel.function("sys32_getgid16").return ?, kernel.function("sys_getgid").return { name = "getgid" retstr = return_str(1, $return) } # getgroups __________________________________________________ # long sys_getgroups(int gidsetsize, gid_t __user *grouplist) # long sys_getgroups16(int gidsetsize, old_gid_t __user *grouplist) # long sys32_getgroups16(int gidsetsize, u16 __user *grouplist) # probe syscall.getgroups = kernel.function("sys_getgroups16").call ?, kernel.function("sys32_getgroups16").call ?, kernel.function("sys_getgroups").call ? { name = "getgroups" size = $gidsetsize list_uaddr = $grouplist argstr = sprintf("%d, %p", $gidsetsize, $grouplist) } probe syscall.getgroups.return = kernel.function("sys_getgroups16").return ?, kernel.function("sys32_getgroups16").return ?, kernel.function("sys_getgroups").return ? { name = "getgroups" retstr = return_str(1, $return) } # gethostname ________________________________________________ # long sys_gethostname(char __user *name, int len) probe syscall.gethostname = kernel.function("sys_gethostname").call ? { name = "gethostname" name_uaddr = $name len = $len argstr = sprintf ("%p, %d", name_uaddr, len) } probe syscall.gethostname.return = kernel.function("sys_gethostname").return ? { name = "gethostname" retstr = return_str(1, $return) } # getitimer __________________________________________________ # sys_getitimer(int which, struct itimerval __user *value) # probe syscall.getitimer = kernel.function("sys_getitimer").call { name = "getitimer" which = $which value_uaddr = $value argstr = sprintf("%s, %p", _itimer_which_str($which), $value) } probe syscall.getitimer.return = kernel.function("sys_getitimer").return { name = "getitimer" retstr = return_str(1, $return) } # long compat_sys_getitimer(int which, struct compat_itimerval __user *it probe syscall.compat_getitimer = kernel.function("compat_sys_getitimer").call ? { name = "getitimer" which = $which value_uaddr = $it argstr = sprintf("%s, %p", _itimer_which_str($which), $it) } probe syscall.compat_getitimer.return = kernel.function("compat_sys_getitimer").return ? { name = "getitimer" retstr = return_str(1, $return) } # get_mempolicy ______________________________________________ # long sys_get_mempolicy(int __user *policy, # unsigned long __user *nmask, # unsigned long maxnode, # unsigned long addr, # unsigned long flags) # long compat_sys_get_mempolicy(int __user *policy, # compat_ulong_t __user *nmask, # compat_ulong_t maxnode, # compat_ulong_t addr, compat_ulong_t flags) # probe syscall.get_mempolicy = kernel.function("compat_sys_get_mempolicy").call ?, kernel.function("sys_get_mempolicy").call ? { name = "get_mempolicy" policy_uaddr = $policy nmask_uaddr = $nmask maxnode = $maxnode addr = $addr flags = $flags argstr = sprintf("%p, %p, %d, %p, 0x%x", $policy, $nmask, $maxnode, $addr, $flags) } probe syscall.get_mempolicy.return = kernel.function("compat_sys_get_mempolicy").return ?, kernel.function("sys_get_mempolicy").return ? { name = "get_mempolicy" retstr = return_str(1, $return) } # getpeername ________________________________________________ # long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len) # probe syscall.getpeername = kernel.function("sys_getpeername").call ? { name = "getpeername" s = $fd name_uaddr = $usockaddr namelen_uaddr = $usockaddr_len argstr = sprintf("%d, %p, %p", $fd, $usockaddr, $usockaddr_len) } probe syscall.getpeername.return = kernel.function("sys_getpeername").return ? { name = "getpeername" retstr = return_str(1, $return) } # getpgid ____________________________________________________ # long sys_getpgid(pid_t pid) probe syscall.getpgid = kernel.function("sys_getpgid").call { name = "getpgid" pid = $pid argstr = sprintf("%d", $pid) } probe syscall.getpgid.return = kernel.function("sys_getpgid").return { name = "getpgid" retstr = return_str(1, $return) } # getpgrp ____________________________________________________ # long sys_getpgrp(void) probe syscall.getpgrp = kernel.function("sys_getpgrp").call ? { name = "getpgrp" argstr = "" } probe syscall.getpgrp.return = kernel.function("sys_getpgrp").return ? { name = "getpgrp" retstr = return_str(1, $return) } # getpid _____________________________________________________ # long sys_getpid(void) probe syscall.getpid = kernel.function("sys_getpid").call { name = "getpid" argstr = "" } probe syscall.getpid.return = kernel.function("sys_getpid").return { name = "getpid" retstr = return_str(1, $return) } # getppid ____________________________________________________ # long sys_getppid(void) probe syscall.getppid = kernel.function("sys_getppid").call { name = "getppid" argstr = "" } probe syscall.getppid.return = kernel.function("sys_getppid").return { name = "getppid" retstr = return_str(1, $return) } # getpriority ________________________________________________ # long sys_getpriority(int which, int who) probe syscall.getpriority = kernel.function("sys_getpriority").call { name = "getpriority" which = $which who = $who argstr = sprintf("%s, %d", _priority_which_str(which), who) } probe syscall.getpriority.return = kernel.function("sys_getpriority").return { name = "getpriority" retstr = return_str(1, $return) } # getresgid __________________________________________________ # long sys_getresgid(gid_t __user *rgid, # gid_t __user *egid, # gid_t __user *sgid) # long sys_getresgid16(old_uid_t __user *rgid, # old_uid_t __user *egid, # old_uid_t __user *sgid) probe syscall.getresgid = kernel.function("sys_getresgid16").call ?, kernel.function("sys_getresgid").call { name = "getresgid" rgid_uaddr = @choose_defined($rgidp, $rgid) egid_uaddr = @choose_defined($egidp, $egid) sgid_uaddr = @choose_defined($sgidp, $sgid) argstr = sprintf("%p, %p, %p", @choose_defined($rgidp, $rgid), @choose_defined($egidp, $egid), @choose_defined($sgidp, $sgid)) } probe syscall.getresgid.return = kernel.function("sys_getresgid16").return ?, kernel.function("sys_getresgid").return { name = "getresgid" retstr = return_str(1, $return) } # getresuid __________________________________________________ # long sys_getresuid(uid_t __user *ruid, # uid_t __user *euid, # uid_t __user *suid) probe syscall.getresuid = kernel.function("sys_getresuid16").call ?, kernel.function("sys_getresuid").call { name = "getresuid" ruid_uaddr = @choose_defined($ruidp, $ruid) euid_uaddr = @choose_defined($euidp, $euid) suid_uaddr = @choose_defined($suidp, $suid) argstr = sprintf("%p, %p, %p", @choose_defined($ruidp, $ruid), @choose_defined($euidp, $euid), @choose_defined($suidp, $suid)) } probe syscall.getresuid.return = kernel.function("sys_getresuid16").return ?, kernel.function("sys_getresuid").return { name = "getresuid" retstr = return_str(1, $return) } # getrlimit __________________________________________________ # long sys_getrlimit(unsigned int resource, struct rlimit __user *rlim) # long sys_old_getrlimit(unsigned int resource, struct rlimit __user *rlim) # long compat_sys_getrlimit (unsigned int resource, struct compat_rlimit __user *rlim) probe syscall.getrlimit = kernel.function("sys_getrlimit").call ?, kernel.function("sys_old_getrlimit").call ?, kernel.function("compat_sys_getrlimit").call ? { name = "getrlimit" resource = $resource rlim_uaddr = $rlim argstr = sprintf("%s, %p", _rlimit_resource_str($resource), $rlim) } probe syscall.getrlimit.return = kernel.function("sys_getrlimit").return ?, kernel.function("sys_old_getrlimit").return ?, kernel.function("compat_sys_getrlimit").return ? { name = "getrlimit" retstr = return_str(1, $return) } # getrusage __________________________________________________ # long sys_getrusage(int who, struct rusage __user *ru) probe syscall.getrusage = kernel.function("sys_getrusage").call { name = "getrusage" who = $who if ($who == -2) { # RUSAGE_BOTH is not valid argument for sys_getrusage who_str = sprintf("UNKNOWN VALUE: %d", $who) } else who_str = _rusage_who_str($who) usage_uaddr = $ru argstr = sprintf("%s, %p", who_str, usage_uaddr) } probe syscall.getrusage.return = kernel.function("sys_getrusage").return { name = "getrusage" retstr = return_str(1, $return) } # getsid _____________________________________________________ # long sys_getsid(pid_t pid) probe syscall.getsid = kernel.function("sys_getsid").call { name = "getsid" pid = $pid argstr = sprint(pid) } probe syscall.getsid.return = kernel.function("sys_getsid").return { name = "getsid" retstr = return_str(1, $return) } # getsockname ________________________________________________ # long sys_getsockname(int fd, # struct sockaddr __user *usockaddr, # int __user *usockaddr_len) probe syscall.getsockname = kernel.function("sys_getsockname").call ? { name = "getsockname" s = $fd name_uaddr = $usockaddr namelen_uaddr = $usockaddr_len argstr = sprintf("%d, %p, %p", $fd, $usockaddr, $usockaddr_len) } probe syscall.getsockname.return = kernel.function("sys_getsockname").return ? { name = "getsockname" retstr = return_str(1, $return) } # getsockopt _________________________________________________ # long sys_getsockopt(int fd, # int level, # int optname, # char __user *optval, # int __user *optlen) # probe syscall.getsockopt = kernel.function("compat_sys_getsockopt").call ?, kernel.function("sys_getsockopt").call ? { name = "getsockopt" fd = $fd level = $level level_str = _sockopt_level_str($level) optname = $optname optname_str = _sockopt_optname_str($optname) optval_uaddr = $optval optlen_uaddr = $optlen argstr = sprintf("%d, %s, %s, %p, %p", $fd, _sockopt_level_str($level), _sockopt_optname_str($optname), $optval, $optlen) } probe syscall.getsockopt.return = kernel.function("compat_sys_getsockopt").return ?, kernel.function("sys_getsockopt").return ? { name = "getsockopt" retstr = return_str(1, $return) } # gettid _____________________________________________________ # long sys_gettid(void) probe syscall.gettid = kernel.function("sys_gettid").call { name = "gettid" argstr = "" } probe syscall.gettid.return = kernel.function("sys_gettid").return { name = "gettid" retstr = return_str(1, $return) } # gettimeofday _______________________________________________ # long sys_gettimeofday(struct timeval __user *tv, # struct timezone __user *tz) # long sys32_gettimeofday(struct compat_timeval __user *tv, # struct timezone __user *tz) # long compat_sys_gettimeofday(struct compat_timeval __user *tv, # struct timezone __user *tz) probe syscall.gettimeofday = kernel.function("compat_sys_gettimeofday").call ?, kernel.function("sys32_gettimeofday").call ?, kernel.function("sys_gettimeofday").call { name = "gettimeofday" tv_uaddr = $tv tz_uaddr = $tz argstr = sprintf("%p, %p", $tv, $tz) } probe syscall.gettimeofday.return = kernel.function("compat_sys_gettimeofday").return ?, kernel.function("sys32_gettimeofday").return ?, kernel.function("sys_gettimeofday").return { name = "gettimeofday" retstr = return_str(1, $return) } # getuid _____________________________________________________ # long sys_getuid(void # long sys_getuid16(void) # long sys32_getuid16(void) # probe syscall.getuid = kernel.function("sys_getuid16").call ?, kernel.function("sys32_getuid16").call ?, kernel.function("sys_getuid").call { name = "getuid" argstr = "" } probe syscall.getuid.return = kernel.function("sys_getuid16").return ?, kernel.function("sys32_getuid16").return ?, kernel.function("sys_getuid").return { name = "getuid" retstr = return_str(1, $return) } # getxattr ___________________________________________________ # ssize_t sys_getxattr(char __user *path, char __user *name, # void __user *value, size_t size) probe syscall.getxattr = kernel.function("sys_getxattr").call { name = "getxattr" path = user_string_quoted(@choose_defined($pathname, $path)) # 'name2' should have been 'name_str'. Deprecate the old name. %(systemtap_v <= "1.4" %? name2 = user_string_quoted($name) %) name_str = user_string_quoted($name) value_uaddr = $value size = $size argstr = sprintf("%s, %s, %p, %d", user_string_quoted(@choose_defined($pathname, $path)), user_string_quoted($name), $value, $size) } probe syscall.getxattr.return = kernel.function("sys_getxattr").return { name = "getxattr" retstr = return_str(1, $return) } # init_module ________________________________________________ # long sys_init_module(void __user *umod, # unsigned long len, # const char __user *uargs) # probe syscall.init_module = kernel.function("sys_init_module").call ? { name = "init_module" umod_uaddr = $umod len = $len uargs = user_string_quoted($uargs) argstr = sprintf("%p, %d, %s", $umod, $len, user_string_quoted($uargs)) } probe syscall.init_module.return = kernel.function("sys_init_module").return ? { name = "init_module" retstr = return_str(1, $return) } # inotify_add_watch __________________________________________ # # long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) # probe syscall.inotify_add_watch = kernel.function("sys_inotify_add_watch").call ? { name = "inotify_add_watch" fd = $fd mask = $mask path_uaddr = @choose_defined($pathname, $path) path = user_string_quoted(@choose_defined($pathname, $path)) argstr = sprintf("%d, %s, %s", $fd, user_string_quoted(@choose_defined($pathname, $path)), _inotify_watch_mask_str($mask)) } probe syscall.inotify_add_watch.return = kernel.function("sys_inotify_add_watch").return ? { name = "inotify_add_watch" retstr = return_str(1, $return) } # inotify_init _______________________________________________ # # long sys_inotify_init(void) # probe syscall.inotify_init = kernel.function("sys_inotify_init1").call !, kernel.function("sys_inotify_init").call ? { flags = @choose_defined($flags, 0); if (flags == 0) { name = "inotify_init" argstr = "" } else { name = "inotify_init1" argstr = _inotify_init1_flag_str(flags) } } probe syscall.inotify_init.return = kernel.function("sys_inotify_init1").return !, kernel.function("sys_inotify_init").return ? { flags = @choose_defined($flags, 0); name = (flags == 0) ? "inotify_init" : "inotify_init1" retstr = return_str(1, $return) } # inotify_rm_watch ___________________________________________ # # long sys_inotify_rm_watch(int fd, u32 wd) # probe syscall.inotify_rm_watch = kernel.function("sys_inotify_rm_watch").call ? { name = "inotify_rm_watch" fd = $fd wd = $wd argstr = sprintf("%d, %d", $fd, $wd) } probe syscall.inotify_rm_watch.return = kernel.function("sys_inotify_rm_watch").return ? { name = "inotify_rm_watch" retstr = return_str(1, $return) } # io_cancel __________________________________________________ # long sys_io_cancel(aio_context_t ctx_id, # struct iocb __user *iocb, # struct io_event __user *result) probe syscall.io_cancel = kernel.function("sys_io_cancel").call { name = "io_cancel" ctx_id = $ctx_id iocb_uaddr = $iocb result_uaddr = $result argstr = sprintf("%d, %p, %p", ctx_id, iocb_uaddr, result_uaddr) } probe syscall.io_cancel.return = kernel.function("sys_io_cancel").return { name = "io_cancel" retstr = return_str(1, $return) } # ioctl ______________________________________________________ # long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) # long compat_sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) # probe syscall.ioctl = kernel.function("compat_sys_ioctl").call ?, kernel.function("sys_ioctl").call ? { name = "ioctl" fd = $fd request = $cmd argp = $arg argstr = sprintf("%d, %d, %p", $fd, $cmd, $arg) } probe syscall.ioctl.return = kernel.function("compat_sys_ioctl").return ?, kernel.function("sys_ioctl").return ? { name = "ioctl" retstr = return_str(1, $return) } # io_destroy _________________________________________________ # long sys_io_destroy(aio_context_t ctx) probe syscall.io_destroy = kernel.function("sys_io_destroy").call { name = "io_destroy" ctx = $ctx argstr = sprintf("%d", ctx) } probe syscall.io_destroy.return = kernel.function("sys_io_destroy").return { name = "io_destroy" retstr = return_str(1, $return) } # io_getevents _______________________________________________ # long sys_io_getevents(aio_context_t ctx_id, # long min_nr, # long nr, # struct io_event __user *events, # struct timespec __user *timeout) # long compat_sys_io_getevents(aio_context_t ctx_id, # unsigned long min_nr, # unsigned long nr, # struct io_event __user *events, # struct compat_timespec __user *timeout) # probe syscall.io_getevents = kernel.function("sys_io_getevents").call ? { name = "io_getevents" ctx_id = $ctx_id min_nr = $min_nr nr = $nr events_uaddr = $events timeout_uaddr = $timeout timestr = _struct_timespec_u($timeout, 1) argstr = sprintf("%d, %d, %d, %p, %p, %s", $ctx_id, $min_nr, $nr, $events, $timeout, timestr) } probe syscall.io_getevents.return = kernel.function("sys_io_getevents").return ? { name = "io_getevents" retstr = return_str(1, $return) } probe syscall.compat_io_getevents = kernel.function("compat_sys_io_getevents").call ? { name = "io_getevents" ctx_id = $ctx_id min_nr = $min_nr nr = $nr events_uaddr = $events timeout_uaddr = $timeout timestr = _struct_compat_timespec_u($timeout, 1) argstr = sprintf("%d, %d, %d, %p, %p, %s", $ctx_id, $min_nr, $nr, $events, $timeout, timestr) } probe syscall.compat_io_getevents.return = kernel.function("compat_sys_io_getevents").return ? { name = "io_getevents" retstr = return_str(1, $return) } # ioperm _____________________________________________________ # long sys_ioperm(unsigned long from, unsigned long num, int turn_on) # probe syscall.ioperm = kernel.function("sys_ioperm").call ? { name = "ioperm" from = $from num = $num turn_on = $turn_on argstr = sprintf("%d, %d, %d", $from, $num, $turn_on) } probe syscall.ioperm.return = kernel.function("sys_ioperm").return ? { name = "ioperm" retstr = return_str(1, $return) } # io_setup ___________________________________________________ # long sys_io_setup(unsigned nr_events, aio_context_t __user *ctxp) # probe syscall.io_setup = kernel.function("sys_io_setup").call { name = "io_setup" maxevents = $nr_events ctxp_uaddr = $ctxp argstr = sprintf("%d, %p", $nr_events, $ctxp) } probe syscall.io_setup.return = kernel.function("sys_io_setup").return { name = "io_setup" retstr = return_str(1, $return) } # long compat_sys_io_setup(unsigned nr_reqs, u32 __user *ctx32p) # probe syscall.compat_io_setup = kernel.function("compat_sys_io_setup").call ? { name = "io_setup" maxevents = $nr_reqs ctxp_uaddr = $ctx32p argstr = sprintf("%d, %p", $nr_reqs, $ctx32p) } probe syscall.compat_io_setup.return = kernel.function("compat_sys_io_setup").return ? { name = "io_setup" retstr = return_str(1, $return) } # io_submit __________________________________________________ # long sys_io_submit(aio_context_t ctx_id, long nr, struct iocb __user * __user *iocbpp) # probe syscall.io_submit = kernel.function("sys_io_submit").call { name = "io_submit" ctx_id = $ctx_id nr = $nr iocbpp_uaddr = $iocbpp argstr = sprintf("%d, %d, %p", $ctx_id, $nr, $iocbpp) } probe syscall.io_submit.return = kernel.function("sys_io_submit").return { name = "io_submit" retstr = return_str(1, $return) } # long compat_sys_io_submit(aio_context_t ctx_id, int nr, u32 __user *iocb) # probe syscall.compat_io_submit = kernel.function("compat_sys_io_submit").call ? { name = "io_submit" ctx_id = $ctx_id nr = $nr iocbpp_uaddr = $iocb argstr = sprintf("%d, %d, %p", $ctx_id, $nr, $iocb) } probe syscall.compat_io_submit.return = kernel.function("compat_sys_io_submit").return ? { name = "io_submit" retstr = return_str(1, $return) } # ioprio_get _________________________________________________ # long sys_ioprio_get(int which, int who) # probe syscall.ioprio_get = kernel.function("sys_ioprio_get").call ? { name = "ioprio_get" which = $which who = $who argstr = sprintf("%d, %d", $which, $who) } probe syscall.ioprio_get.return = kernel.function("sys_ioprio_get").return ? { name = "ioprio_get" retstr = return_str(1, $return) } # ioprio_set _________________________________________________ # long sys_ioprio_set(int which, int who, int ioprio) # probe syscall.ioprio_set = kernel.function("sys_ioprio_set").call ? { name = "ioprio_set" which = $which who = $who ioprio = $ioprio argstr = sprintf("%d, %d, %d", $which, $who, $ioprio) } probe syscall.ioprio_set.return = kernel.function("sys_ioprio_set").return ? { name = "ioprio_set" retstr = return_str(1, $return) } # kexec_load _________________________________________________ # long sys_kexec_load(unsigned long entry, # unsigned long nr_segments, # struct kexec_segment __user *segments, # unsigned long flags) # long compat_sys_kexec_load(unsigned long entry, # unsigned long nr_segments, # struct compat_kexec_segment __user *segments, # unsigned long flags) # probe syscall.kexec_load = kernel.function("compat_sys_kexec_load").call ?, kernel.function("sys_kexec_load").call ? { name = "kexec_load" entry = $entry nr_segments = $nr_segments segments_uaddr = $segments flags = $flags argstr = sprintf("%p, %d, %p, %d", $entry, $nr_segments, $segments, $flags) } probe syscall.kexec_load.return = kernel.function("compat_sys_kexec_load").return ?, kernel.function("sys_kexec_load").return ? { name = "kexec_load" retstr = return_str(1, $return) } # keyctl _____________________________________________________ # long sys_keyctl(int option, # unsigned long arg2, # unsigned long arg3, # unsigned long arg4, # unsigned long arg5) # long compat_sys_keyctl(u32 option, u32 arg2, u32 arg3, u32 arg4, u32 arg5) # probe syscall.keyctl = kernel.function("compat_sys_keyctl").call ?, kernel.function("sys_keyctl").call ? { name = "keyctl" argstr = sprintf("%d, ...", $option) } probe syscall.keyctl.return = kernel.function("compat_sys_keyctl").return ?, kernel.function("sys_keyctl").return ? { name = "keyctl" retstr = return_str(1, $return) } # kill _______________________________________________________ # long sys_kill(int pid, int sig) probe syscall.kill = kernel.function("sys_kill").call { name = "kill" pid = $pid sig = $sig argstr = sprintf("%d, %s", $pid, _signal_name($sig)) } probe syscall.kill.return = kernel.function("sys_kill").return { name = "kill" retstr = return_str(1, $return) } # lchown _____________________________________________________ # long sys_lchown(const char __user * filename, uid_t user, gid_t group) # probe syscall.lchown = kernel.function("sys_lchown").call { name = "lchown" path = user_string_quoted($filename) owner = __int32($user) group = __int32($group) argstr = sprintf("%s, %d, %d", user_string_quoted($filename), owner, group) } probe syscall.lchown.return = kernel.function("sys_lchown").return { name = "lchown" retstr = return_str(1, $return) } # lchown16 ___________________________________________________ # long sys_lchown16(const char __user * filename, old_uid_t user, # old_gid_t group) # probe syscall.lchown16 = kernel.function("sys_lchown16").call ? { name = "lchown16" path = user_string_quoted($filename) owner = __short($user) group = __short($group) argstr = sprintf("%s, %d, %d", user_string_quoted($filename), owner, group) } probe syscall.lchown16.return = kernel.function("sys_lchown16").return ? { name = "lchown16" retstr = return_str(1, $return) } # lgetxattr __________________________________________________ # ssize_t sys_lgetxattr(char __user *path, # char __user *name, # void __user *value, # size_t size) # probe syscall.lgetxattr = kernel.function("sys_lgetxattr").call { name = "lgetxattr" path = user_string_quoted(@choose_defined($pathname, $path)) # 'name2' should have been 'name_str'. Deprecate the old name. %(systemtap_v <= "1.4" %? name2 = user_string_quoted($name) %) name_str = user_string_quoted($name) value_uaddr = $value size = $size argstr = sprintf("%s, %s, %p, %d", user_string_quoted(@choose_defined($pathname, $path)), user_string_quoted($name), value_uaddr, size) } probe syscall.lgetxattr.return = kernel.function("sys_lgetxattr").return { name = "lgetxattr" retstr = return_str(1, $return) } # link _______________________________________________________ # long sys_link(const char __user * oldname, # const char __user * newname) probe syscall.link = kernel.function("sys_link").call { name = "link" oldpath = user_string_quoted($oldname) newpath = user_string_quoted($newname) argstr = sprintf("%s, %s", user_string_quoted($oldname), user_string_quoted($newname)) } probe syscall.link.return = kernel.function("sys_link").return { name = "link" retstr = return_str(1, $return) } # linkat _____________________________________________________ # new function with 2.6.16 # long sys_linkat(int olddfd, const char __user *oldname, # int newdfd, const char __user *newname, int flags) probe syscall.linkat = kernel.function("sys_linkat").call ? { name = "linkat" olddirfd = $olddfd olddirfd_str = _dfd_str($olddfd) oldpath = user_string_quoted($oldname) newdirfd = $newdfd newdirfd_str = _dfd_str($newdfd) newpath = user_string_quoted($newname) flags = $flags flags_str = _at_flag_str($flags) argstr = sprintf("%s, %s, %s, %s, %s", olddirfd_str, user_string_quoted($oldname), newdirfd_str, user_string_quoted($newname), flags_str) } probe syscall.linkat.return = kernel.function("sys_linkat").return ? { name = "linkat" retstr = return_str(1, $return) } # listen _____________________________________________________ # long sys_listen(int fd, int backlog) probe syscall.listen = kernel.function("sys_listen").call ? { name = "listen" sockfd = $fd backlog = $backlog argstr = sprintf("%d, %d", $fd, $backlog) } probe syscall.listen.return = kernel.function("sys_listen").return ? { name = "listen" retstr = return_str(1, $return) } # listxattr __________________________________________________ # ssize_t sys_listxattr(char __user *path, char __user *list, size_t size) # probe syscall.listxattr = kernel.function("sys_listxattr").call { name = "listxattr" list_uaddr = $list size = $size path_uaddr = @choose_defined($pathname, $path) path = user_string_quoted(@choose_defined($pathname, $path)) argstr = sprintf("%s, %p, %d", user_string_quoted(@choose_defined($pathname, $path)), $list, $size) } probe syscall.listxattr.return = kernel.function("sys_listxattr").return { name = "listxattr" retstr = return_str(1, $return) } # llistxattr _________________________________________________ # ssize_t sys_llistxattr(char __user *path, char __user *list, size_t size) # probe syscall.llistxattr = kernel.function("sys_llistxattr").call { name = "llistxattr" list_uaddr = $list size = $size path_uaddr = @choose_defined($pathname, $path) path = user_string_quoted(@choose_defined($pathname, $path)) argstr = sprintf("%s, %p, %d", user_string_quoted(@choose_defined($pathname, $path)), $list, $size) } probe syscall.llistxattr.return = kernel.function("sys_llistxattr").return { name = "llistxattr" retstr = return_str(1, $return) } # llseek _____________________________________________________ # long sys_llseek(unsigned int fd, # unsigned long offset_high, # unsigned long offset_low, # loff_t __user * result, # unsigned int whence) probe syscall.llseek = kernel.function("sys_llseek").call ? { name = "llseek" fd = $fd offset_high = $offset_high offset_low = $offset_low result_uaddr = $result whence = @choose_defined($whence, $origin) whence_str = _seek_whence_str(@choose_defined($whence, $origin)) argstr = sprintf("%d, 0x%x, 0x%x, %p, %s", $fd, $offset_high, $offset_low, $result, whence_str) } probe syscall.llseek.return = kernel.function("sys_llseek").return ? { name = "llseek" retstr = return_str(1, $return) } # lookup_dcookie _____________________________________________ # long sys_lookup_dcookie(u64 cookie64, char __user * buf, size_t len) # probe syscall.lookup_dcookie = kernel.function("sys_lookup_dcookie").call ? { name = "lookup_dcookie" cookie = $cookie64 buffer_uaddr = $buf len = $len argstr = sprintf("%d, %p, %d", $cookie64, $buf, $len) } probe syscall.lookup_dcookie.return = kernel.function("sys_lookup_dcookie").return ? { name = "lookup_dcookie" retstr = return_str(1, $return) } # lremovexattr _______________________________________________ # long sys_lremovexattr(char __user *path, char __user *name) # probe syscall.lremovexattr = kernel.function("sys_lremovexattr").call { name = "lremovexattr" name_uaddr = $name # 'name2' should have been 'name_str'. Deprecate the old name. %(systemtap_v <= "1.4" %? name2 = user_string_quoted($name) %) name_str = user_string_quoted($name) path_uaddr = @choose_defined($pathname, $path) path = user_string_quoted(@choose_defined($pathname, $path)) argstr = sprintf("%s, %s", user_string_quoted(@choose_defined($pathname, $path)), user_string_quoted($name)) } probe syscall.lremovexattr.return = kernel.function("sys_lremovexattr").return { name = "lremovexattr" retstr = return_str(1, $return) } # lseek ______________________________________________________ # off_t sys_lseek(unsigned int fd, off_t offset, unsigned int whence) probe syscall.lseek = kernel.function("sys_lseek").call { name = "lseek" fildes = $fd # offset = __int32($offset) offset = $offset whence = @choose_defined($whence, $origin) whence_str = _seek_whence_str(@choose_defined($whence, $origin)) argstr = sprintf("%d, %d, %s", $fd, offset, whence_str) } probe syscall.lseek.return = kernel.function("sys_lseek").return { name = "lseek" retstr = return_str(1, $return) } # lsetxattr __________________________________________________ # long sys_lsetxattr(char __user *path, # char __user *name, # void __user *value, # size_t size, # int flags) # probe syscall.lsetxattr = kernel.function("sys_lsetxattr").call { name = "lsetxattr" path_uaddr = @choose_defined($pathname, $path) path = user_string_quoted(@choose_defined($pathname, $path)) name_uaddr = $name name_str = user_string_quoted($name) value_uaddr = $value size = $size flags = $flags argstr = sprintf("%s, %s, %p, %d, %d", user_string_quoted(@choose_defined($pathname, $path)), user_string_quoted($name), value_uaddr, $size, $flags) } probe syscall.lsetxattr.return = kernel.function("sys_lsetxattr").return { name = "lsetxattr" retstr = return_str(1, $return) } # lstat ______________________________________________________ # long sys_lstat(char __user * filename, struct __old_kernel_stat __user * statbuf) # long sys_newlstat(char __user * filename, struct stat __user * statbuf) # long compat_sys_newlstat(char __user * filename, struct compat_stat __user *statbuf) # long sys32_lstat64(char * filename, struct stat64 __user *statbuf) # long sys_lstat64(char __user * filename, struct stat64 __user * statbuf) # long sys_oabi_lstat64(char __user * filename, # struct oldabi_stat64 __user * statbuf) # probe syscall.lstat = kernel.function("sys_lstat").call ?, kernel.function("sys_newlstat").call ?, kernel.function("compat_sys_newlstat").call ?, kernel.function("sys32_lstat64").call ?, kernel.function("sys_lstat64").call ?, kernel.function("sys_oabi_lstat64").call ? { name = "lstat" path = user_string_quoted($filename) buf_uaddr = $statbuf argstr = sprintf("%s, %p", user_string_quoted($filename), $statbuf) } probe syscall.lstat.return = kernel.function("sys_lstat").return ?, kernel.function("sys_newlstat").return ?, kernel.function("compat_sys_newlstat").return ?, kernel.function("sys32_lstat64").return ?, kernel.function("sys_lstat64").return ?, kernel.function("sys_oabi_lstat64").return ? { name = "lstat" retstr = return_str(1, $return) } # madvise ____________________________________________________ # long sys_madvise(unsigned long start, size_t len_in, int behavior) # probe syscall.madvise = kernel.function("sys_madvise").call ? { name = "madvise" start = $start length = $len_in advice = $behavior advice_str = _madvice_advice_str($behavior) argstr = sprintf("%p, %d, %s", $start, $len_in, _madvice_advice_str($behavior)) } probe syscall.madvise.return = kernel.function("sys_madvise").return ? { name = "madvise" retstr = return_str(1, $return) } # mbind ______________________________________________________ # long sys_mbind(unsigned long start, # unsigned long len, # unsigned long mode, # unsigned long __user *nmask, # unsigned long maxnode, # unsigned flags) # # long compat_sys_mbind(compat_ulong_t start, # compat_ulong_t len, # compat_ulong_t mode, # compat_ulong_t __user *nmask, # compat_ulong_t maxnode, # compat_ulong_t flags) # probe syscall.mbind = kernel.function("compat_sys_mbind").call ?, kernel.function("sys_mbind").call ? { name = "mbind" start = $start len = $len mode = $mode nmask_uaddr = $nmask maxnode = $maxnode flags = $flags argstr = sprintf("%d, %d, %d, %p, %d, 0x%x", $start, $len, $mode, $nmask, $maxnode, $flags) } probe syscall.mbind.return = kernel.function("compat_sys_mbind").return ?, kernel.function("sys_mbind").return ? { name = "mbind" retstr = return_str(1, $return) } # migrate_pages ____________________________________________________ # long sys_migrate_pages(pid_t pid, unsigned long maxnode, # const unsigned long __user *old_nodes, # const unsigned long __user *new_nodes) probe syscall.migrate_pages = kernel.function("sys_migrate_pages").call ? { name = "migrate_pages" argstr = sprintf("%d, %d, %p, %p", $pid, $maxnode, $old_nodes, $new_nodes) } probe syscall.migrate_pages.return = kernel.function("sys_migrate_pages").return ? { name = "migrate_pages" retstr = return_str(1, $return) } # mincore ____________________________________________________ # long sys_mincore(unsigned long start, size_t len, unsigned char __user * vec) # probe syscall.mincore = kernel.function("sys_mincore").call ? { name = "mincore" start = $start length = $len vec_uaddr = $vec argstr = sprintf("%p, %d, %p", $start, $len, $vec) } probe syscall.mincore.return = kernel.function("sys_mincore").return ? { name = "mincore" retstr = return_str(1, $return) } # mkdir ______________________________________________________ # long sys_mkdir(const char __user * pathname, int mode) probe syscall.mkdir = kernel.function("sys_mkdir").call { name = "mkdir" pathname_uaddr = $pathname pathname = user_string_quoted($pathname) mode = $mode argstr = sprintf("%s, %#o", user_string_quoted($pathname), $mode) } probe syscall.mkdir.return = kernel.function("sys_mkdir").return { name = "mkdir" retstr = return_str(1, $return) } # mkdirat ____________________________________________________ # new function with 2.6.16 # long sys_mkdirat(int dfd, const char __user *pathname, int mode) probe syscall.mkdirat = kernel.function("sys_mkdirat").call ? { name = "mkdirat" dirfd = $dfd pathname = user_string_quoted($pathname) mode = $mode argstr = sprintf("%s, %s, %#o", _dfd_str($dfd), user_string_quoted($pathname), $mode) } probe syscall.mkdirat.return = kernel.function("sys_mkdirat").return ? { name = "mkdirat" retstr = return_str(1, $return) } # mknod # long sys_mknod(const char __user * filename, int mode, unsigned dev) probe syscall.mknod = kernel.function("sys_mknod").call { name = "mknod" pathname = user_string_quoted($filename) mode = $mode dev = $dev argstr = sprintf("%s, %s, %p", user_string_quoted($filename), _mknod_mode_str($mode), dev) } probe syscall.mknod.return = kernel.function("sys_mknod").return { name = "mknod" retstr = return_str(1, $return) } # mknodat ____________________________________________________ # new function with 2.6.16 # long sys_mknodat(int dfd, const char __user *filename, # int mode, unsigned dev) probe syscall.mknodat = kernel.function("sys_mknodat").call ? { name = "mknodat" dirfd = $dfd dirfd_str = _dfd_str($dfd) pathname = user_string_quoted($filename) mode = $mode mode_str = _mknod_mode_str($mode) dev = $dev argstr = sprintf("%s, %s, %s, %p", dirfd_str, user_string_quoted($filename), mode_str, $dev) } probe syscall.mknodat.return = kernel.function("sys_mknodat").return ? { name = "mknodat" retstr = return_str(1, $return) } # mlock ______________________________________________________ # # long sys_mlock(unsigned long start, size_t len) # probe syscall.mlock = kernel.function("sys_mlock").call ? { name = "mlock" addr = $start len = $len argstr = sprintf("%p, %d", $start, $len) } probe syscall.mlock.return = kernel.function("sys_mlock").return ? { name = "mlock" retstr = return_str(1, $return) } # mlockall ___________________________________________________ # # long sys_mlockall(int flags) # probe syscall.mlockall = kernel.function("sys_mlockall").call ? { name = "mlockall" flags = $flags argstr = _mlockall_flags_str($flags) } probe syscall.mlockall.return = kernel.function("sys_mlockall").return ? { name = "mlockall" retstr = return_str(1, $return) } # modify_ldt _________________________________________________ # int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) # probe syscall.modify_ldt = kernel.function("sys_modify_ldt").call ? { name = "modify_ldt" func = $func ptr_uaddr = $ptr bytecount = $bytecount argstr = sprintf("%d, %p, %d", $func, $ptr, $bytecount) } probe syscall.modify_ldt.return = kernel.function("sys_modify_ldt").return ? { name = "modify_ldt" retstr = return_str(1, $return) } # move_pages ____________________________________________________ # long sys_move_pages(pid_t pid, unsigned long nr_pages, # const void __user * __user *pages, # const int __user *nodes, # int __user *status, # int flags) # # long compat_sys_move_pages(pid_t pid, unsigned long nr_pages, # compat_uptr_t __user *pages32, # const int __user *nodes, # int __user *status, # int flags) # probe syscall.move_pages = kernel.function("compat_sys_move_pages").call ?, kernel.function("sys_move_pages").call ? { name = "move_pages" argstr = sprintf("%d, %d, %p, %p, 0x%x", $pid, $nr_pages, $nodes, $status, $flags) } probe syscall.move_pages.return = kernel.function("compat_sys_move_pages").return ?, kernel.function("sys_move_pages").return ? { name = "move_pages" retstr = return_str(1, $return) } # mount ______________________________________________________ # long sys_mount(char __user * dev_name, # char __user * dir_name, # char __user * type, # unsigned long flags, # void __user * data) # long compat_sys_mount(char __user * dev_name, # char __user * dir_name, # char __user * type, # unsigned long flags, # void __user * data) probe syscall.mount = kernel.function("compat_sys_mount").call ?, kernel.function("sys_mount").call { name = "mount" source = user_string_quoted($dev_name) target = user_string_quoted($dir_name) filesystemtype = user_string_quoted($type) mountflags = $flags mountflags_str = _mountflags_str($flags) data = user_string_n_quoted($data, syscall_string_trunc) argstr = sprintf("%s, %s, %s, %s, %s", user_string_quoted($dev_name), user_string_quoted($dir_name), user_string_quoted($type), mountflags_str, data) } probe syscall.mount.return = kernel.function("compat_sys_mount").return ?, kernel.function("sys_mount").return { name = "mount" retstr = return_str(1, $return) } %( kernel_v >= "2.6.33" %? # In newer kernels (2.6.33+), all the sys_mmap() variants are just # wrappers around sys_mmap_pgoff(), which is in arch-generic code. # # long sys_mmap_pgoff(unsigned long addr, unsigned long len, # unsigned long prot, unsigned long flags, # unsigned long fd, unsigned long pgoff) probe syscall.mmap2 = kernel.function("sys_mmap_pgoff") ? { name = "mmap2" start = $addr length = $len prot = $prot flags = $flags # Although the kernel gets an unsigned long fd, on the # user-side it is a signed int. Fix this. fd = __int32($fd) pgoffset = $pgoff argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len, _mprotect_prot_str($prot), _mmap_flags($flags), __int32($fd), $pgoff) } probe syscall.mmap2.return = kernel.function("sys_mmap_pgoff").return ? { name = "mmap2" retstr = return_str(2, $return) } %) # mprotect ___________________________________________________ # long sys_mprotect(unsigned long start, size_t len, unsigned long prot) # probe syscall.mprotect = kernel.function("sys_mprotect").call ? { name = "mprotect" addr = $start len = $len prot = $prot prot_str = _mprotect_prot_str($prot) argstr = sprintf("%p, %d, %s", $start, $len, _mprotect_prot_str($prot)) } probe syscall.mprotect.return = kernel.function("sys_mprotect").return ? { name = "mprotect" retstr = return_str(1, $return) } # mq_getsetattr ______________________________________________ # long sys_mq_getsetattr(mqd_t mqdes, # const struct mq_attr __user *u_mqstat, # struct mq_attr __user *u_omqstat) # long compat_sys_mq_getsetattr(mqd_t mqdes, # const struct compat_mq_attr __user *u_mqstat, # struct compat_mq_attr __user *u_omqstat) # probe syscall.mq_getsetattr = kernel.function("compat_sys_mq_getsetattr").call ?, kernel.function("sys_mq_getsetattr").call ? { name = "mq_getsetattr" mqdes = $mqdes u_mqstat_uaddr = $u_mqstat u_omqstat_uaddr = $u_omqstat argstr = sprintf("%d, %p, %p", $mqdes, $u_mqstat, $u_omqstat) } probe syscall.mq_getsetattr.return = kernel.function("compat_sys_mq_getsetattr").return ?, kernel.function("sys_mq_getsetattr").return ? { name = "mq_getsetattr" retstr = return_str(1, $return) } # mq_notify __________________________________________________ # long sys_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification) # long compat_sys_mq_notify(mqd_t mqdes, const struct compat_sigevent __user *u_notification) # probe syscall.mq_notify = kernel.function("compat_sys_mq_notify").call ?, kernel.function("sys_mq_notify").call ? { name = "mq_notify" mqdes = $mqdes notification_uaddr = $u_notification argstr = sprintf("%d, %p", $mqdes, $u_notification) } probe syscall.mq_notify.return = kernel.function("compat_sys_mq_notify").return ?, kernel.function("sys_mq_notify").return ? { name = "mq_notify" retstr = return_str(1, $return) } # mq_open ____________________________________________________ # long sys_mq_open(const char __user *u_name, # int oflag, # mode_t mode, # struct mq_attr __user *u_attr) # long compat_sys_mq_open(const char __user *u_name, # int oflag, compat_mode_t mode, # struct compat_mq_attr __user *u_attr) # probe syscall.mq_open = kernel.function("compat_sys_mq_open").call ?, kernel.function("sys_mq_open").call ? { name = "mq_open" name_uaddr = $u_name filename = user_string_quoted($u_name) mode = $mode u_attr_uaddr = $u_attr oflag = $oflag if (oflag & 64) argstr = sprintf("%s, %s, %#o, %p", user_string_quoted($u_name), _sys_open_flag_str($oflag), $mode, $u_attr) else argstr = sprintf("%s, %s", user_string_quoted($u_name), _sys_open_flag_str($oflag)) } probe syscall.mq_open.return = kernel.function("compat_sys_mq_open").return ?, kernel.function("sys_mq_open").return ? { name = "mq_open" retstr = return_str(1, $return) } # mq_timedreceive ____________________________________________ # ssize_t sys_mq_timedreceive(mqd_t mqdes, # char __user *u_msg_ptr, # size_t msg_len, # unsigned int __user *u_msg_prio, # const struct timespec __user *u_abs_timeout) # ssize_t compat_sys_mq_timedreceive(mqd_t mqdes, # char __user *u_msg_ptr, # size_t msg_len, unsigned int __user *u_msg_prio, # const struct compat_timespec __user *u_abs_timeout) # probe syscall.mq_timedreceive = kernel.function("compat_sys_mq_timedreceive").call ?, kernel.function("sys_mq_timedreceive").call ? { name = "mq_timedreceive" mqdes = $mqdes msg_ptr_uaddr = $u_msg_ptr msg_len = $msg_len msg_prio_uaddr = $u_msg_prio abs_timeout_uaddr = $u_abs_timeout argstr = sprintf("%d, %p, %d, %p, %p", $mqdes, $u_msg_ptr, $msg_len, $u_msg_prio, $u_abs_timeout) } probe syscall.mq_timedreceive.return = kernel.function("compat_sys_mq_timedreceive").return ?, kernel.function("sys_mq_timedreceive").return ? { name = "mq_timedreceive" retstr = return_str(1, $return) } # mq_timedsend _______________________________________________ # long sys_mq_timedsend(mqd_t mqdes, # const char __user *u_msg_ptr, # size_t msg_len, # unsigned int msg_prio, # const struct timespec __user *u_abs_timeout) # long compat_sys_mq_timedsend(mqd_t mqdes, # const char __user *u_msg_ptr, # size_t msg_len, unsigned int msg_prio, # const struct compat_timespec __user *u_abs_timeout) # probe syscall.mq_timedsend = kernel.function("compat_sys_mq_timedsend").call ?, kernel.function("sys_mq_timedsend").call ? { name = "mq_timedsend" mqdes = $mqdes msg_ptr_uaddr = $u_msg_ptr msg_len = $msg_len msg_prio = $msg_prio abs_timeout_uaddr = $u_abs_timeout argstr = sprintf("%d, %p, %d, %d, %p", $mqdes, $u_msg_ptr, $msg_len, $msg_prio, $u_abs_timeout) } probe syscall.mq_timedsend.return = kernel.function("compat_sys_mq_timedsend").return ?, kernel.function("sys_mq_timedsend").return ? { name = "mq_timedsend" retstr = return_str(1, $return) } # mq_unlink __________________________________________________ # long sys_mq_unlink(const char __user *u_name) # probe syscall.mq_unlink = kernel.function("sys_mq_unlink").call ? { name = "mq_unlink" u_name_uaddr = $u_name u_name = user_string_quoted($u_name) argstr = user_string_quoted($u_name) } probe syscall.mq_unlink.return = kernel.function("sys_mq_unlink").return ? { name = "mq_unlink" retstr = return_str(1, $return) } # mremap _____________________________________________________ # unsigned long sys_mremap(unsigned long addr, # unsigned long old_len, # unsigned long new_len, # unsigned long flags, # unsigned long new_addr) # probe syscall.mremap = kernel.function("ia64_mremap").call ?, kernel.function("sys_mremap").call ? { name = "mremap" old_address = $addr old_size = $old_len new_size = $new_len flags = $flags new_address = $new_addr argstr = sprintf("%p, %d, %d, %s, %p", $addr, $old_len, $new_len, _mremap_flags($flags), $new_addr) } probe syscall.mremap.return = kernel.function("ia64_mremap").return ?, kernel.function("sys_mremap").return ? { name = "mremap" retstr = return_str(2, $return) } # msgctl _____________________________________________________ # long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf) # probe syscall.msgctl = kernel.function("sys_msgctl").call ? { name = "msgctl" msqid = $msqid cmd = $cmd buf_uaddr = $buf argstr = sprintf("%d, %d, %p", $msqid, $cmd, $buf) } probe syscall.msgctl.return = kernel.function("sys_msgctl").return ? { name = "msgctl" retstr = return_str(1, $return) } # compat_sys_msgctl ________________________________________ # # long compat_sys_msgctl(int first, int second, void __user *uptr) # probe syscall.compat_sys_msgctl = kernel.function("compat_sys_msgctl").call ? { name = "compat_sys_msgctl" msqid = $first cmd = $second buf_uaddr = $uptr argstr = sprintf("%d, %d, %p", $first, $second, $uptr) } probe syscall.compat_sys_msgctl.return = kernel.function("compat_sys_msgctl").return ? { name = "compat_sys_msgctl" retstr = return_str(1, $return) } # msgget _____________________________________________________ # long sys_msgget (key_t key, int msgflg) # probe syscall.msgget = kernel.function("sys_msgget").call ? { name = "msgget" key = $key msgflg = $msgflg msgflg_str = _sys_open_flag_str($msgflg) argstr = sprintf("%d, %s", $key, _sys_open_flag_str($msgflg)) } probe syscall.msgget.return = kernel.function("sys_msgget").return ? { name = "msgget" retstr = return_str(1, $return) } # msgrcv _____________________________________________________ # long sys_msgrcv (int msqid, # struct msgbuf __user *msgp, # size_t msgsz, # long msgtyp, # int msgflg) # probe syscall.msgrcv = kernel.function("sys_msgrcv").call ? { name = "msgrcv" msqid = $msqid msgp_uaddr = $msgp msgsz = $msgsz msgtyp = $msgtyp msgflg = $msgflg argstr = sprintf("%d, %p, %d, %d, %d", $msqid, $msgp, $msgsz, $msgtyp, $msgflg) } probe syscall.msgrcv.return = kernel.function("sys_msgrcv").return ? { name = "msgrcv" retstr = return_str(1, $return) } # compat_sys_msgrcv ________________________________________ # # long compat_sys_msgrcv(int first, int second, int msgtyp, int third, # int version, void __user *uptr) # COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp, # compat_ssize_t, msgsz, long, msgtyp, int, msgflg) # probe syscall.compat_sys_msgrcv = kernel.function("compat_sys_msgrcv").call ? { name = "compat_sys_msgrcv" msqid = @choose_defined($msqid, $first) msgp_uaddr = @choose_defined($msgp, $uptr) msgsz = @choose_defined($msgsz, $second) msgtyp = $msgtyp msgflg = @choose_defined($msgflg, $third) argstr = sprintf("%d, %p, %d, %d", msqid, msgp_uaddr, msgsz, msgflg) } probe syscall.compat_sys_msgrcv.return = kernel.function("compat_sys_msgrcv").return ? { name = "compat_sys_msgrcv" retstr = return_str(1, $return) } # msgsnd _____________________________________________________ # long sys_msgsnd (int msqid, # struct msgbuf __user *msgp, # size_t msgsz, # int msgflg) # probe syscall.msgsnd = kernel.function("sys_msgsnd").call ? { name = "msgsnd" msqid = $msqid msgp_uaddr = $msgp msgsz = $msgsz msgflg = $msgflg argstr = sprintf("%d, %p, %d, %d", $msqid, $msgp, $msgsz, $msgflg) } probe syscall.msgsnd.return = kernel.function("sys_msgsnd").return ? { name = "msgsnd" retstr = return_str(1, $return) } # compat_sys_msgsnd ________________________________________ # # long compat_sys_msgsnd(int first, int second, int third, void __user *uptr) # COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp, # compat_ssize_t, msgsz, int, msgflg) # probe syscall.compat_sys_msgsnd = kernel.function("compat_sys_msgsnd").call ? { name = "compat_sys_msgsnd" msqid = @choose_defined($msqid, $first) msgp_uaddr = @choose_defined($msgp, $uptr) msgsz = @choose_defined($msgsz, $second) msgflg = @choose_defined($msgflg, $third) argstr = sprintf("%d, %p, %d, %d", msqid, msgp_uaddr, msgsz, msgflg) } probe syscall.compat_sys_msgsnd.return = kernel.function("compat_sys_msgsnd").return ? { name = "compat_sys_msgsnd" retstr = return_str(1, $return) } # msync ______________________________________________________ # long sys_msync(unsigned long start, size_t len, int flags) probe syscall.msync = kernel.function("sys_msync").call ? { name = "msync" start = $start length = $len flags = $flags argstr = sprintf("%p, %d, %s", start, length, _msync_flag_str(flags)) } probe syscall.msync.return = kernel.function("sys_msync").return ? { name = "msync" retstr = return_str(1, $return) } # munlock ____________________________________________________ # long sys_munlock(unsigned long start, size_t len) probe syscall.munlock = kernel.function("sys_munlock").call ? { name = "munlock" addr = $start len = $len argstr = sprintf("%p, %d", addr, len) } probe syscall.munlock.return = kernel.function("sys_munlock").return ? { name = "munlock" retstr = return_str(1, $return) } # munlockall _________________________________________________ # long sys_munlockall(void) probe syscall.munlockall = kernel.function("sys_munlockall").call ? { name = "munlockall" argstr = "" } probe syscall.munlockall.return = kernel.function("sys_munlockall").return ? { name = "munlockall" retstr = return_str(1, $return) } # munmap _____________________________________________________ # long sys_munmap(unsigned long addr, size_t len) probe syscall.munmap = kernel.function("sys_munmap").call { name = "munmap" start = $addr length = $len argstr = sprintf("%p, %d", start, length) } probe syscall.munmap.return = kernel.function("sys_munmap").return { name = "munmap" retstr = return_str(1, $return) } systemtap-2.3/tapset/linux/syscalls2.stp000066400000000000000000003140201217430427200205170ustar00rootroot00000000000000// syscalls tapset part 2 [N-Z] // Copyright (C) 2005 IBM Corp. // Copyright (C) 2005, 2006, 2007, 2010, 2013 Red Hat Inc. // Copyright (C) 2007 Quentin Barnes. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /* Each syscall returns the calls parameters. In addition, the following * variables are set: * * name - generally the syscall name minus the "sys_". * * argstr - a string containing the decoded args in an easy-to-read format. * It doesn't need to contain everything, but should have all the * important args. Set in entry probes only. * * retstr - a string containing the return value in an easy-to-read format. * Set in return probes only. */ # nanosleep __________________________________________________ # # long sys_nanosleep(struct timespec __user *rqtp, # struct timespec __user *rmtp) # long compat_sys_nanosleep(struct compat_timespec __user *rqtp, # struct compat_timespec __user *rmtp) # probe syscall.nanosleep = kernel.function("sys_nanosleep").call { name = "nanosleep" req_uaddr = $rqtp rem_uaddr = $rmtp argstr = sprintf("%s, %p", _struct_timespec_u($rqtp, 1), $rmtp) } probe syscall.nanosleep.return = kernel.function("sys_nanosleep").return { name = "nanosleep" retstr = return_str(1, $return) } probe syscall.compat_nanosleep = kernel.function("compat_sys_nanosleep").call ? { name = "nanosleep" req_uaddr = $rqtp rem_uaddr = $rmtp argstr = sprintf("%s, %p", _struct_compat_timespec_u($rqtp, 1), $rmtp) } probe syscall.compat_nanosleep.return = kernel.function("compat_sys_nanosleep").return ? { name = "nanosleep" retstr = return_str(1, $return) } # nfsservctl _________________________________________________ # # long sys_nfsservctl(int cmd, struct nfsctl_arg __user *arg, void __user *res) # long compat_sys_nfsservctl(int cmd, struct compat_nfsctl_arg __user *arg, # union compat_nfsctl_res __user *res) # # nfsservctl was removed in kernel 3.0/2.6.40. %( kernel_v < "2.6.40" && CONFIG_NFSD == "[ym]" %? probe syscall.nfsservctl = kernel.function("sys_nfsservctl").call ?, kernel.function("compat_sys_nfsservctl").call ? { name = "nfsservctl" cmd = $cmd if (@defined($arg) && @defined($res)) { argp_uaddr = $arg resp_uaddr = $res argstr = sprintf("%s, %p, %p", _nfsctl_cmd_str($cmd), $arg, $res) } else { argp_uaddr = $notused resp_uaddr = $notused2 argstr = sprintf("/* NI_SYSCALL */ %s, %p, %p", _nfsctl_cmd_str($cmd), $notused, $notused2) } } probe syscall.nfsservctl.return = kernel.function("sys_nfsservctl").return ?, kernel.function("compat_sys_nfsservctl").return ? { name = "nfsservctl" retstr = return_str(1, $return) } %) # nice _______________________________________________________ # long sys_nice(int increment) # probe syscall.nice = kernel.function("sys_nice").call ? { name = "nice" inc = $increment argstr = sprintf("%d", $increment) } probe syscall.nice.return = kernel.function("sys_nice").return ? { name = "nice" retstr = return_str(1, $return) } # ni_syscall _________________________________________________ # # long sys_ni_syscall(void) # probe syscall.ni_syscall = kernel.function("sys_ni_syscall").call { name = "ni_syscall" argstr = "" } probe syscall.ni_syscall.return = kernel.function("sys_ni_syscall").return { name = "ni_syscall" retstr = return_str(1, $return) } # open _______________________________________________________ # long sys_open(const char __user * filename, int flags, int mode) # (obsolete) long sys32_open(const char * filename, int flags, int mode) # probe syscall.open = kernel.function("compat_sys_open").call ?, kernel.function("sys32_open").call ?, kernel.function("sys_open").call ? { name = "open" filename = user_string_quoted($filename) flags = $flags mode = $mode if (flags & 64) argstr = sprintf("%s, %s, %#o", user_string_quoted($filename), _sys_open_flag_str($flags), $mode) else argstr = sprintf("%s, %s", user_string_quoted($filename), _sys_open_flag_str($flags)) } probe syscall.open.return = kernel.function("compat_sys_open").return ?, kernel.function("sys32_open").return ?, kernel.function("sys_open").return ? { name = "open" retstr = return_str(1, $return) } # openat _______________________________________________________ # long sys_openat(int dfd, const char __user *filename, int flags, int mode) # long compat_sys_openat(unsigned int dfd, const char __user *filename, int flags, int mode) # probe syscall.openat = kernel.function("compat_sys_openat").call ?, kernel.function("sys_openat").call ? { name = "openat" filename = user_string_quoted($filename) flags = $flags mode = $mode if ($flags & 64) argstr = sprintf("%s, %s, %s, %#o", _dfd_str($dfd), user_string_quoted($filename), _sys_open_flag_str($flags), $mode) else argstr = sprintf("%s, %s, %s", _dfd_str($dfd), user_string_quoted($filename), _sys_open_flag_str($flags)) } probe syscall.openat.return = kernel.function("compat_sys_openat").return ?, kernel.function("sys_openat").return ? { name = "openat" retstr = return_str(1, $return) } # pause ______________________________________________________ # # sys_pause(void) # probe syscall.pause = kernel.function("sys_pause").call ?, kernel.function("sys32_pause").call ?, kernel.function("compat_sys_pause").call ? { name = "pause" argstr = "" } probe syscall.pause.return = kernel.function("sys_pause").return ?, kernel.function("sys32_pause").return ?, kernel.function("compat_sys_pause").return ? { name = "pause" retstr = return_str(1, $return) } # pciconfig_iobase ___________________________________________ # # asmlinkage long # sys_pciconfig_iobase(long which, # unsigned long bus, # unsigned long dfn) # # #probe syscall.pciconfig_iobase = kernel.function("sys_pciconfig_iobase").call #{ # name = "pciconfig_iobase" # which = $which # bus = $bus # dfn = $dfn # argstr = sprintf("%p, %p, %p", which, bus, dfn) #} #probe syscall.pciconfig_iobase.return = kernel.function("sys_pciconfig_iobase").return #{ # name = "pciconfig_iobase" # retstr = return_str(1, $return) #} # pciconfig_read _____________________________________________ # # asmlinkage int # sys_pciconfig_read(unsigned long bus, # unsigned long dfn, # unsigned long off, # unsigned long len, # unsigned char *buf) # { return 0; } # # #probe syscall.pciconfig_read = kernel.function("sys_pciconfig_read").call #{ # name = "pciconfig_read" # bus = $bus # dfn = $dfn # off = $off # len = $len # buf_uaddr = $buf # argstr = sprintf("%p, %p, %p, %d, %p", bus, dfn, off, # len, buf_uaddr) #} #probe syscall.pciconfig_read.return = kernel.function("sys_pciconfig_read").return #{ # name = "pciconfig_read" # retstr = return_str(1, $return) #} # pciconfig_write ____________________________________________ # # asmlinkage int # sys_pciconfig_write(unsigned long bus, # unsigned long dfn, # unsigned long off, # unsigned long len, # unsigned char *buf) # # #probe syscall.pciconfig_write = kernel.function("sys_pciconfig_write").call #{ # name = "pciconfig_write" # bus = $bus # dfn = $dfn # off = $off # len = $len # buf_uaddr = $buf # argstr = sprintf("%p, %p, %p, %d, %p", bus, dfn, off, # len, buf_uaddr) #} #probe syscall.pciconfig_write.return = kernel.function("sys_pciconfig_write").return #{ # name = "pciconfig_write" # retstr = return_str(1, $return) #} # personality ________________________________________________ # # asmlinkage long # sys_personality(u_long personality) # probe syscall.personality = kernel.function("sys_personality").call { name = "personality" persona = $personality argstr = sprintf("%p", persona); } probe syscall.personality.return = kernel.function("sys_personality").return { name = "personality" retstr = return_str(1, $return) } # ia64 returns the results from the pipe call through (user) registers. %( arch == "ia64" %? function _ia64_pipe0:long() %{ STAP_RETVALUE = CONTEXT->kregs ? CONTEXT->kregs->r8 : 0; %} function _ia64_pipe1:long() %{ STAP_RETVALUE = _stp_current_pt_regs()->r9; %} %) # pipe _______________________________________________________ # # asmlinkage int # sys_pipe(unsigned long __user * fildes) # # SYSCALL_DEFINE2(pipe2, int __user *, fildes, int, flags) # pipe2() was added to Linux in version 2.6.27. probe syscall.pipe = kernel.function("sys_pipe2").call !, kernel.function("sys_ia64_pipe").call ?, kernel.function("sys_pipe").call { if (@defined($flags)) { flags = $flags flag_str = _sys_pipe2_flag_str(flags); } name = flags == 0 ? "pipe" : "pipe2"; if (@defined($fildes)) { fildes_uaddr = $fildes if (fildes_uaddr == 0) { pipe0 = 0; pipe1 = 0; argstr = "NULL" } else { /* * Why use @cast here? Why not just: * * pipe0 = user_int(&$fildes[0]); * pipe1 = user_int(&$fildes[1]); * * The answer is syscall wrappers * (CONFIG_SYSCALL_WRAPPERS). On ppc (for * example), SyS_foo has all "long" arguments, * and then the inline SYSC_foo has the real * argument types. The @cast makes sure we're * dealing with the "final" type. */ pipe0 = user_int(&@cast($fildes, "int")[0]) pipe1 = user_int(&@cast($fildes, "int")[1]) if (flags == 0) argstr = sprintf("[%d, %d]", pipe0, pipe1); else argstr = sprintf("[%d, %d], %s", pipe0, pipe1, flag_str); } } else { fildes_uaddr = 0; pipe0 = 0; pipe1 = 0; argstr = "[0, 0]"; } } probe syscall.pipe.return = kernel.function("sys_pipe2").return !, kernel.function("sys_ia64_pipe").return ?, kernel.function("sys_pipe").return { if (@defined($flags)) name = ($flags == 0) ? "pipe" : "pipe2"; else name = "pipe" if (@defined($fildes)) { fildes_uaddr = $fildes if (fildes_uaddr == 0) { pipe0 = 0; pipe1 = 0; } else { /* * See comment in syscall.pipe about why @cast * is used here. */ pipe0 = user_int(&@cast($fildes, "int")[0]) pipe1 = user_int(&@cast($fildes, "int")[1]) } } else { fildes_uaddr = 0; %( arch == "ia64" %? pipe0 = _ia64_pipe0(); pipe1 = _ia64_pipe1(); %: pipe0 = 0; pipe1 = 0; %) } %( arch == "ia64" %? retstr = (pipe0 < 0) ? return_str(1, $return) : "0"; %: retstr = return_str(1, $return) %) } # pivot_root _________________________________________________ # # long sys_pivot_root(const char __user *new_root, const char __user *put_old) # probe syscall.pivot_root = kernel.function("sys_pivot_root").call { name = "pivot_root" new_root_str = user_string_quoted($new_root) old_root_str = user_string_quoted($put_old) argstr = sprintf("%s, %s", user_string_quoted($new_root), user_string_quoted($put_old)) } probe syscall.pivot_root.return = kernel.function("sys_pivot_root").return { name = "pivot_root" retstr = return_str(1, $return) } # poll _______________________________________________________ # # long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long timeout) # probe syscall.poll = kernel.function("sys_poll").call { name = "poll" ufds_uaddr = $ufds nfds = $nfds timeout = @choose_defined($timeout_msecs, $timeout) argstr = sprintf("%p, %d, %d", $ufds, $nfds, @choose_defined($timeout_msecs, $timeout)) } probe syscall.poll.return = kernel.function("sys_poll").return { name = "poll" retstr = return_str(1, $return) } # ppoll _______________________________________________________ # # long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds, # struct timespec __user *tsp, const sigset_t __user *sigmask, # size_t sigsetsize) # probe syscall.ppoll = kernel.function("sys_ppoll").call ? { name = "ppoll" argstr = sprintf("%p, %d, %s, %p, %d", $ufds, $nfds, _struct_timespec_u($tsp, 1), $sigmask, $sigsetsize) } probe syscall.ppoll.return = kernel.function("sys_ppoll").return ? { name = "ppoll" retstr = return_str(1, $return) } # long compat_sys_ppoll(struct pollfd __user *ufds, # unsigned int nfds, struct compat_timespec __user *tsp, # const compat_sigset_t __user *sigmask, compat_size_t sigsetsize) # probe syscall.compat_ppoll = kernel.function("compat_sys_ppoll").call ? { name = "ppoll" argstr = sprintf("%p, %d, %s, %p, %d", $ufds, $nfds, _struct_compat_timespec_u($tsp, 1), $sigmask, $sigsetsize) } probe syscall.compat_ppoll.return = kernel.function("compat_sys_ppoll").return ? { name = "ppoll" retstr = return_str(1, $return) } # prctl ______________________________________________________ # # asmlinkage long # sys_prctl(int option, # unsigned long arg2, # unsigned long arg3, # unsigned long arg4, # unsigned long arg5) # probe syscall.prctl = kernel.function("sys_prctl").call { name = "prctl" option = $option arg2 = $arg2 arg3 = $arg3 arg4 = $arg4 arg5 = $arg5 argstr = sprintf("%p, %p, %p, %p, %p", option, arg2, arg3, arg4, arg5) } probe syscall.prctl.return = kernel.function("sys_prctl").return { name = "prctl" retstr = return_str(1, $return) } # pread64 ____________________________________________________ # # ssize_t sys_pread64(unsigned int fd, # char __user *buf, # size_t count, # loff_t pos) # probe syscall.pread = kernel.function("sys_pread64").call { name = "pread" fd = $fd buf_uaddr = $buf count = $count offset = $pos argstr = sprintf("%d, %p, %d, %d", $fd, $buf, $count, $pos) } probe syscall.pread.return = kernel.function("sys_pread64").return { name = "pread" retstr = return_str(1, $return) } # pselect6 _____________________________________________________ # # long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp, # fd_set __user *exp, struct timespec __user *tsp, void __user *sig) # probe syscall.pselect6 = kernel.function("sys_pselect6").call ? { name = "pselect6" argstr = sprintf("%d, %p, %p, %p, %s, %p", $n, $inp, $outp, $exp, _struct_timespec_u($tsp, 1), $sig) } probe syscall.pselect6.return = kernel.function("sys_pselect6").return ? { name = "pselect6" retstr = return_str(1, $return) } probe syscall.compat_pselect6 = kernel.function("compat_sys_pselect6").call ? { name = "pselect6" argstr = sprintf("%d, %p, %p, %p, %s, %p", $n, $inp, $outp, $exp, _struct_compat_timespec_u($tsp, 1), $sig) } probe syscall.compat_pselect6.return = kernel.function("compat_sys_pselect6").return ? { name = "pselect6" retstr = return_str(1, $return) } # pselect7 _____________________________________________________ # # long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp, # fd_set __user *exp, struct timespec __user *tsp, # const sigset_t __user *sigmask, size_t sigsetsize) # probe syscall.pselect7 = kernel.function("sys_pselect7").call ? { name = "pselect7" argstr = sprintf("%d, %p, %p, %p, %s, %p, %d", $n, $inp, $outp, $exp, _struct_timespec_u($tsp, 1), $sigmask, $sigsetsize) } probe syscall.pselect7.return = kernel.function("sys_pselect7").return ? { name = "pselect7" retstr = return_str(1, $return) } # Through a typo, 'compat_pselect7' was misnamed as # 'compat_pselect7a' (notice the trailing 'a'). The old name is # deprecated. To use the old name without changing your script, use # the '--compatible 1.3' stap option. probe %( systemtap_v <= "1.3" %? syscall.compat_pselect7a %: syscall.compat_pselect7 %) = kernel.function("compat_sys_pselect7").call ? { name = "pselect7" argstr = sprintf("%d, %p, %p, %p, %s, %p, %d", $n, $inp, $outp, $exp, _struct_compat_timespec_u($tsp, 1), $sigmask, $sigsetsize) } probe syscall.compat_pselect7.return = kernel.function("compat_sys_pselect7").return ? { name = "pselect7" retstr = return_str(1, $return) } # ptrace _____________________________________________________ # # int sys_ptrace(long request, # long pid, # long addr, # long data) # probe syscall.ptrace = kernel.function("sys_ptrace").call ? { name = "ptrace" request = $request pid = $pid addr = $addr data = $data argstr = _ptrace_argstr($request, $pid, $addr, $data) } probe syscall.ptrace.return = kernel.function("sys_ptrace").return ? { name = "ptrace" retstr = return_str(1, $return) geteventmsg_data = _ptrace_return_geteventmsg_data($request, $data) arch_prctl_addr = _ptrace_return_arch_prctl_addr($request, $addr, $data) } # pwrite64 ___________________________________________________ # # ssize_t sys_pwrite64(unsigned int fd, # const char __user *buf, # size_t count, # loff_t pos) # probe syscall.pwrite = kernel.function("sys_pwrite64").call { name = "pwrite" fd = $fd buf_uaddr = $buf count = $count offset = $pos argstr = sprintf("%d, %s, %d, %d", $fd, user_string_n_quoted($buf, syscall_string_trunc), $count, $pos) } probe syscall.pwrite.return = kernel.function("sys_pwrite64").return { name = "pwrite" retstr = return_str(1, $return) } # long sys32_pwrite64(unsigned int fd, const char __user *ubuf, # size_t count, u32 poshi, u32 poslo) probe syscall.pwrite32 = kernel.function("sys32_pwrite64").call ? { name = "pwrite" fd = $fd count = $count offset = ($poshi << 32) + $poslo %( arch == "s390" %? buf_uaddr = $ubuf argstr = sprintf("%d, %s, %d, %d", $fd, user_string_n_quoted($ubuf, syscall_string_trunc), $count, ($poshi << 32) + $poslo) %: buf_uaddr = $buf argstr = sprintf("%d, %s, %d, %d", $fd, user_string_n_quoted($buf, syscall_string_trunc), $count, ($poshi << 32) + $poslo) %) } probe syscall.pwrite32.return = kernel.function("sys32_pwrite64").return ? { name = "pwrite" retstr = return_str(1, $return) } # quotactl ___________________________________________________ # # long sys_quotactl(unsigned int cmd, # const char __user *special, # qid_t id, # void __user *addr) # probe syscall.quotactl = kernel.function("sys_quotactl").call ? { name = "quotactl" cmd = $cmd cmd_str = _quotactl_cmd_str($cmd) special = $special special_str = user_string_quoted($special) id = $id addr_uaddr = $addr argstr = sprintf("%s, %s, %d, %p", cmd_str, special_str, $id, $addr) } probe syscall.quotactl.return = kernel.function("sys_quotactl").return ? { name = "quotactl" retstr = return_str(1, $return) } # read _______________________________________________________ # ssize_t sys_read(unsigned int fd, char __user * buf, size_t count) probe syscall.read = kernel.function("sys_read").call { name = "read" fd = $fd buf_uaddr = $buf count = $count argstr = sprintf("%d, %p, %d", $fd, $buf, $count) } probe syscall.read.return = kernel.function("sys_read").return { name = "read" retstr = return_str(1, $return) } # readahead __________________________________________________ # # asmlinkage ssize_t # sys_readahead(int fd, # loff_t offset, # size_t count) # probe syscall.readahead = kernel.function("sys_readahead").call { name = "readahead" fd = $fd offset = $offset count = $count argstr = sprintf("%d, %p, %p", fd, offset, count) } probe syscall.readahead.return = kernel.function("sys_readahead").return { name = "readahead" retstr = return_str(1, $return) } # readdir ___________________________________________________ # # long compat_sys_old_readdir(unsigned int fd, struct compat_old_linux_dirent __user *dirent, unsigned int count) # int old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent, unsigned int count) # probe syscall.readdir = kernel.function("compat_sys_old_readdir").call ?, kernel.function("old32_readdir").call ? { name = "readdir" argstr = sprintf("%d, %p, %d", $fd, $dirent, $count) } probe syscall.readdir.return = kernel.function("compat_sys_old_readdir").return ?, kernel.function("old32_readdir").return ? { name = "readdir" retstr = return_str(1, $return) } # readlink ___________________________________________________ # # long sys_readlink(const char __user * path, # char __user * buf, # int bufsiz) # probe syscall.readlink = kernel.function("sys_readlink").call { name = "readlink" path = user_string_quoted($path) buf_uaddr = $buf bufsiz = $bufsiz argstr = sprintf("%s, %p, %d", user_string_quoted($path), $buf, $bufsiz) } probe syscall.readlink.return = kernel.function("sys_readlink").return { name = "readlink" retstr = return_str(1, $return) } # readlinkat ___________________________________________________ # # long sys_readlinkat(int dfd, const char __user * path, # char __user * buf, # int bufsiz) # probe syscall.readlinkat = kernel.function("sys_readlinkat").call ? { name = "readlinkat" dfd = $dfd buf_uaddr = $buf bufsiz = $bufsiz path = user_string_quoted(@choose_defined($pathname, $path)) argstr = sprintf("%s, %s, %p, %d", _dfd_str($dfd), user_string_quoted(@choose_defined($pathname, $path)), $buf, $bufsiz) } probe syscall.readlinkat.return = kernel.function("sys_readlinkat").return ? { name = "readlinkat" retstr = return_str(1, $return) } # readv ______________________________________________________ # # ssize_t sys_readv(unsigned long fd, # const struct iovec __user *vec, # unsigned long vlen) # ssize_t compat_sys_readv(unsigned long fd, # const struct compat_iovec __user *vec, # unsigned long vlen) # probe syscall.readv = kernel.function("compat_sys_readv").call ?, kernel.function("sys_readv").call { name = "readv" vector_uaddr = $vec count = $vlen fd = $fd argstr = sprintf("%d, %p, %d", $fd, $vec, $vlen) } probe syscall.readv.return = kernel.function("compat_sys_readv").return ?, kernel.function("sys_readv").return { name = "readv" retstr = return_str(1, $return) } # reboot _____________________________________________________ # # long sys_reboot(int magic1, # int magic2, # unsigned int cmd, # void __user * arg) # probe syscall.reboot = kernel.function("sys_reboot").call { name = "reboot" magic = $magic1 magic_str = _reboot_magic_str($magic1) magic2 = $magic2 magic2_str =_reboot_magic_str($magic2) flag = $cmd flag_str = _reboot_flag_str($cmd) arg_uaddr = $arg argstr = sprintf("%s, %s, %s, %p", magic_str, magic2_str, flag_str, $arg) } probe syscall.reboot.return = kernel.function("sys_reboot").return { name = "reboot" retstr = return_str(1, $return) } # recv _______________________________________________________ # # long sys_recv(int fd, void __user *ubuf, size_t size, unsigned flags) # probe syscall.recv = kernel.function("sys_recv").call ? { name = "recv" s = $fd buf_uaddr = $ubuf len = $size flags = $flags flags_str = _recvflags_str($flags) argstr = sprintf("%d, %p, %d, %s", $fd, $ubuf, $size, _recvflags_str($flags)) } probe syscall.recv.return = kernel.function("sys_recv").return ? { name = "recv" retstr = return_str(1, $return) } # recvfrom ___________________________________________________ # # long sys_recvfrom(int fd, # void __user * ubuf, # size_t size, # unsigned flags, # struct sockaddr __user *addr, # int __user *addr_len) # probe syscall.recvfrom = kernel.function("sys_recvfrom").call ? { name = "recvfrom" s = $fd buf_uaddr = $ubuf len = $size flags = $flags flags_str = _recvflags_str($flags) addr_uaddr = $addr addrlen_uaddr = $addr_len argstr = sprintf("%d, %p, %d, %s, %p, %p", $fd, $ubuf, $size, _recvflags_str($flags), $addr, $addr_len) } probe syscall.recvfrom.return = kernel.function("sys_recvfrom").return ? { name = "recvfrom" retstr = return_str(1, $return) } # recvmmsg ___________________________________________________ # # long sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, # unsigned int vlen, unsigned int flags, # struct timespec __user *timeout) # probe syscall.recvmmsg = kernel.function("sys_recvmmsg").call ? { name = "recvmmsg" s = $fd mmsg_uaddr = $mmsg vlen = $vlen flags = $flags flags_str = _recvflags_str($flags) timeout_uaddr = $timeout argstr = sprintf("%d, %p, %d, %s, %s", $fd, $mmsg, $vlen, _recvflags_str($flags), _struct_timespec_u($timeout, 1)) } probe syscall.recvmmsg.return = kernel.function("sys_recvmmsg").return ? { name = "recvmmsg" retstr = return_str(1, $return) } # compat_recvmmsg ___________________________________________________ # # long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, # unsigned vlen, unsigned int flags, # struct compat_timespec __user *timeout) probe syscall.compat_recvmmsg = kernel.function("compat_sys_recvmmsg").call ? { name = "compat_recvmmsg" s = $fd mmsg_uaddr = $mmsg vlen = $vlen flags = $flags flags_str = _recvflags_str($flags) timeout_uaddr = $timeout argstr = sprintf("%d, %p, %d, %s, %s", $fd, $mmsg, $vlen, _recvflags_str($flags), _struct_compat_timespec_u($timeout, 1)) } probe syscall.compat_recvmmsg.return = kernel.function("compat_sys_recvmmsg").return ? { name = "compat_recvmmsg" retstr = return_str(1, $return) } # recvmsg ____________________________________________________ # # long sys_recvmsg(int fd, # struct msghdr __user *msg, # unsigned int flags) # probe syscall.recvmsg = kernel.function("sys_recvmsg").call ? { name = "recvmsg" s = $fd msg_uaddr = $msg flags = $flags flags_str = _recvflags_str($flags) argstr = sprintf("%d, %p, %s", $fd, $msg, _recvflags_str($flags)) } probe syscall.recvmsg.return = kernel.function("sys_recvmsg").return ? { name = "recvmsg" retstr = return_str(1, $return) } # compat_sys_recvmsg ________________________________________ # # long compat_sys_recvmsg(int fd, # struct compat_msghdr __user *msg, # unsigned int flags) # probe syscall.compat_sys_recvmsg = kernel.function("compat_sys_recvmsg").call ? { name = "compat_sys_recvmsg" s = $fd msg_uaddr = $msg flags = $flags flags_str = _recvflags_str($flags) argstr = sprintf("%d, %p, %s", $fd, $msg, _recvflags_str($flags)) } probe syscall.compat_sys_recvmsg.return = kernel.function("compat_sys_recvmsg").return ? { name = "compat_sys_recvmsg" retstr = return_str(1, $return) } # remap_file_pages ___________________________________________ # # long sys_remap_file_pages(unsigned long start, # unsigned long size, # unsigned long __prot, # unsigned long pgoff, # unsigned long flags) # probe syscall.remap_file_pages = kernel.function("sys_remap_file_pages").call ? { name = "remap_file_pages" start = $start size = $size prot = @choose_defined($prot, $__prot) pgoff = $pgoff flags = $flags argstr = sprintf("%p, %p, %p, %p, %p", start, size, prot, pgoff, flags) } probe syscall.remap_file_pages.return = kernel.function("sys_remap_file_pages").return ? { name = "remap_file_pages" retstr = return_str(1, $return) } # removexattr ________________________________________________ # # asmlinkage long # sys_removexattr(char __user *path, # char __user *name) # probe syscall.removexattr = kernel.function("sys_removexattr").call { name = "removexattr" name_str = user_string_quoted($name) path = user_string_quoted(@choose_defined($pathname, $path)) argstr = sprintf("%s, %s", user_string_quoted(@choose_defined($pathname, $path)), user_string_quoted($name)) } probe syscall.removexattr.return = kernel.function("sys_removexattr").return { name = "removexattr" retstr = return_str(1, $return) } # rename _____________________________________________________ # # asmlinkage long # sys_rename(const char __user * oldname, # const char __user * newname) # probe syscall.rename = kernel.function("sys_rename").call { name = "rename" oldpath = user_string_quoted($oldname) newpath = user_string_quoted($newname) argstr = sprintf("%s, %s", user_string_quoted($oldname), user_string_quoted($newname)) } probe syscall.rename.return = kernel.function("sys_rename").return { name = "rename" retstr = return_str(1, $return) } # renameat ___________________________________________________ # new function with 2.6.16 # long sys_renameat(int olddfd, const char __user *oldname, # int newdfd, const char __user *newname) probe syscall.renameat = kernel.function("sys_renameat").call ? { name = "renameat" olddfd = $olddfd olddfd_str = _dfd_str($olddfd) oldname = $oldname oldname_str = user_string_quoted($oldname) newdfd = $newdfd newdfd_str = _dfd_str($newdfd) newname = $newname newname_str = user_string_quoted($newname) argstr = sprintf("%s, %s, %s, %s", olddfd_str, user_string_quoted($oldname), newdfd_str, user_string_quoted($newname)) } probe syscall.renameat.return = kernel.function("sys_renameat").return ? { name = "renameat" retstr = return_str(1, $return) } # request_key ________________________________________________ # # long sys_request_key(const char __user *_type, # const char __user *_description, # const char __user *_callout_info, # key_serial_t destringid) # compat_sys_request_key() calls sys_request_key, so don't need probe there. # probe syscall.request_key = kernel.function("sys_request_key").call ? { name = "request_key" type_uaddr = $_type description_uaddr = $_description callout_info_uaddr = $_callout_info destringid = $destringid argstr = sprintf("%p, %p, %p, %p", $_type, $_description, $_callout_info, $destringid) } probe syscall.request_key.return = kernel.function("sys_request_key").return ? { name = "request_key" retstr = return_str(1, $return) } # restart_syscall ____________________________________________ # # asmlinkage long # sys_restart_syscall(void) # probe syscall.restart_syscall = kernel.function("sys_restart_syscall").call { name = "restart_syscall" argstr = "" } probe syscall.restart_syscall.return = kernel.function("sys_restart_syscall").return { name = "restart_syscall" retstr = return_str(1, $return) } # rmdir ______________________________________________________ # # asmlinkage long # sys_rmdir(const char __user * pathname) # probe syscall.rmdir = kernel.function("sys_rmdir").call { name = "rmdir" pathname = user_string_quoted($pathname) argstr = user_string_quoted($pathname) } probe syscall.rmdir.return = kernel.function("sys_rmdir").return { name = "rmdir" retstr = return_str(1, $return) } # rt_sigaction _______________________________________________ # # sys_rt_sigaction(int sig, # const struct sigaction __user *act, # struct sigaction __user *oact, # size_t sigsetsize) # probe syscall.rt_sigaction = kernel.function("sys_rt_sigaction").call ? { name = "rt_sigaction" sig = $sig act_uaddr = $act oact_uaddr = $oact sigsetsize = $sigsetsize argstr = sprintf("%s, {%s}, %p, %d", _signal_name($sig), _struct_sigaction_u($act), $oact, $sigsetsize) } probe syscall.rt_sigaction.return = kernel.function("sys_rt_sigaction").return ? { name = "rt_sigaction" retstr = return_str(1, $return) } # # long sys32_rt_sigaction(int sig, # struct sigaction32 __user *act, # struct sigaction32 __user *oact, # unsigned int sigsetsize) # ppc only # compat_sys_rt_sigaction(int sig, # const struct sigaction32 __user *act, # struct sigaction32 __user *oact, # size_t sigsetsize) probe syscall.rt_sigaction32 = kernel.function("sys32_rt_sigaction").call ?, kernel.function("compat_sys_rt_sigaction").call ? { name = "rt_sigaction" sig = $sig act_uaddr = $act oact_uaddr = $oact sigsetsize = $sigsetsize argstr = sprintf("%s, {%s}, %p, %d", _signal_name($sig), _struct_sigaction32_u($act), $oact, $sigsetsize) } probe syscall.rt_sigaction32.return = kernel.function("sys32_rt_sigaction").return ?, kernel.function("compat_sys_rt_sigaction").return ? { name = "rt_sigaction" retstr = return_str(1, $return) } # rt_sigpending ______________________________________________ # # long sys_rt_sigpending(sigset_t __user *set, size_t sigsetsize) # probe syscall.rt_sigpending = kernel.function("sys_rt_sigpending").call ? { name = "rt_sigpending" set_uaddr = @choose_defined($uset, $set) sigsetsize = $sigsetsize argstr = sprintf("%p, %d", set_uaddr, $sigsetsize) } probe syscall.rt_sigpending.return = kernel.function("sys_rt_sigpending").return ? { name = "rt_sigpending" retstr = return_str(1, $return) } # rt_sigprocmask _____________________________________________ # long sys_rt_sigprocmask(int how, sigset_t __user *set, sigset_t __user *oset, # size_t sigsetsize) # long sys32_rt_sigprocmask(u32 how, compat_sigset_t __user *set, # compat_sigset_t __user *oset, size_t sigsetsize) # long compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set, # compat_sigset_t __user *oset, # compat_size_t sigsetsize) # probe syscall.rt_sigprocmask = kernel.function("sys_rt_sigprocmask").call ? { name = "rt_sigprocmask" how = $how how_str = _sigprocmask_how_str($how) set_uaddr = @choose_defined($set, $nset) oldset_uaddr = $oset argstr = sprintf("%s, [%s], %p, %d", how_str, _stp_sigset_u(set_uaddr), $oset, $sigsetsize) } probe syscall.rt_sigprocmask.return = kernel.function("sys_rt_sigprocmask").return ? { name = "rt_sigprocmask" retstr = return_str(1, $return) } probe syscall.compat_rt_sigprocmask = kernel.function("compat_sys_rt_sigprocmask").call ?, kernel.function("sys32_rt_sigprocmask").call ? { name = "rt_sigprocmask" how = $how how_str = _sigprocmask_how_str($how) set_uaddr = @choose_defined($set, $nset) oldset_uaddr = $oset argstr = sprintf("%s, [%s], %p, %d", how_str, _stp_compat_sigset_u(set_uaddr), $oset, $sigsetsize) } probe syscall.compat_rt_sigprocmask.return = kernel.function("compat_sys_rt_sigprocmask").return ?, kernel.function("sys32_rt_sigprocmask").return ? { name = "rt_sigprocmask" retstr = return_str(1, $return) } # rt_sigqueueinfo ____________________________________________ # # long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t __user *uinfo) # probe syscall.rt_sigqueueinfo = kernel.function("sys_rt_sigqueueinfo").call { name = "rt_sigqueueinfo" pid = $pid sig = $sig uinfo_uaddr = $uinfo argstr = sprintf("%d, %s, %p", $pid, _signal_name($sig), $uinfo) } probe syscall.rt_sigqueueinfo.return = kernel.function("sys_rt_sigqueueinfo").return { name = "rt_sigqueueinfo" retstr = return_str(1, $return) } # rt_sigreturn _______________________________________________ # int sys_rt_sigreturn(unsigned long __unused) # probe syscall.rt_sigreturn = kernel.function("sys_rt_sigreturn").call ?, kernel.function("sys32_rt_sigreturn").call ? { name = "rt_sigreturn" argstr = "" } probe syscall.rt_sigreturn.return = kernel.function("sys_rt_sigreturn").return ?, kernel.function("sys32_rt_sigreturn").return ? { name = "rt_sigreturn" retstr = return_str(1, $return) } # rt_sigsuspend ______________________________________________ # # sys_rt_sigsuspend(struct pt_regs regs) # probe syscall.rt_sigsuspend = kernel.function("compat_sys_rt_sigsuspend").call ?, kernel.function("ia64_rt_sigsuspend").call ?, kernel.function("sys_rt_sigsuspend").call ? { name = "rt_sigsuspend" argstr = "" } probe syscall.rt_sigsuspend.return = kernel.function("compat_sys_rt_sigsuspend").return ?, kernel.function("ia64_rt_sigsuspend").return ?, kernel.function("sys_rt_sigsuspend").return ? { name = "rt_sigsuspend" retstr = return_str(1, $return) } # rt_sigtimedwait ____________________________________________ # # long sys_rt_sigtimedwait(const sigset_t __user *uthese, # siginfo_t __user *uinfo, # const struct timespec __user *uts, # size_t sigsetsize) # long compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, # struct compat_siginfo __user *uinfo, # struct compat_timespec __user *uts, compat_size_t sigsetsize) # probe syscall.rt_sigtimedwait = kernel.function("compat_sys_rt_sigtimedwait").call ?, kernel.function("sys_rt_sigtimedwait").call { name = "rt_sigtimedwait" uthese_uaddr = $uthese uinfo_uaddr = $uinfo uts_uaddr = $uts sigsetsize = $sigsetsize argstr = sprintf("%p, %p, %p, %d", $uthese, $uinfo, $uts, $sigsetsize) } probe syscall.rt_sigtimedwait.return = kernel.function("compat_sys_rt_sigtimedwait").return ?, kernel.function("sys_rt_sigtimedwait").return { name = "rt_sigtimedwait" retstr = return_str(1, $return) } # sched_getaffinity __________________________________________ # # asmlinkage long # sys_sched_getaffinity(pid_t pid, # unsigned int len, # unsigned long __user *user_mask_ptr) # probe syscall.sched_getaffinity = kernel.function("sys_sched_getaffinity").call { name = "sched_getaffinity" pid = $pid len = $len mask_uaddr = $user_mask_ptr argstr = sprintf("%d, %p, %p", pid, len, mask_uaddr) } probe syscall.sched_getaffinity.return = kernel.function("sys_sched_getaffinity").return { name = "sched_getaffinity" retstr = return_str(1, $return) } # sched_getparam _____________________________________________ # # asmlinkage long # sys_sched_getparam(pid_t pid, # struct sched_param __user *param) # probe syscall.sched_getparam = kernel.function("sys_sched_getparam").call { name = "sched_getparam" pid = $pid p_uaddr = $param argstr = sprintf("%d, %p", pid, p_uaddr) } probe syscall.sched_getparam.return = kernel.function("sys_sched_getparam").return { name = "sched_getparam" retstr = return_str(1, $return) } # sched_get_priority_max _____________________________________ # # asmlinkage long # sys_sched_get_priority_max(int policy) # probe syscall.sched_get_priority_max = kernel.function("sys_sched_get_priority_max").call { name = "sched_get_priority_max" policy = $policy argstr = sprint(policy) } probe syscall.sched_get_priority_max.return = kernel.function("sys_sched_get_priority_max").return { name = "sched_get_priority_max" retstr = return_str(1, $return) } # sched_get_priority_min _____________________________________ # # asmlinkage long # sys_sched_get_priority_min(int policy) # probe syscall.sched_get_priority_min = kernel.function("sys_sched_get_priority_min").call { name = "sched_get_priority_min" policy = $policy argstr = sprint(policy) } probe syscall.sched_get_priority_min.return = kernel.function("sys_sched_get_priority_min").return { name = "sched_get_priority_min" retstr = return_str(1, $return) } # sched_getscheduler _________________________________________ # # long sys_sched_getscheduler(pid_t pid) # probe syscall.sched_getscheduler = kernel.function("sys_sched_getscheduler").call { name = "sched_getscheduler" pid = $pid argstr = sprint($pid) } probe syscall.sched_getscheduler.return = kernel.function("sys_sched_getscheduler").return { name = "sched_getscheduler" retstr = return_str(1, $return) } # sched_rr_get_interval ______________________________________ # # long sys_sched_rr_get_interval(pid_t pid, struct timespec __user *interval) # probe syscall.sched_rr_get_interval = kernel.function("sys_sched_rr_get_interval").call { name = "sched_rr_get_interval" pid = $pid tp_uaddr = $interval argstr = sprintf("%d, %s", $pid, _struct_timespec_u($interval, 1)) } probe syscall.sched_rr_get_interval.return = kernel.function("sys_sched_rr_get_interval").return { name = "sched_rr_get_interval" retstr = return_str(1, $return) } # sched_setaffinity __________________________________________ # long sys_sched_setaffinity(pid_t pid, # unsigned int len, # unsigned long __user *user_mask_ptr) # probe syscall.sched_setaffinity = kernel.function("sys_sched_setaffinity").call { name = "sched_setaffinity" pid = $pid len = @choose_defined($len, 0) mask_uaddr = $user_mask_ptr argstr = sprintf("%d, %d, %p", $pid, $len, $user_mask_ptr) } probe syscall.sched_setaffinity.return = kernel.function("sys_sched_setaffinity").return { name = "sched_setaffinity" retstr = return_str(1, $return) } # sched_setparam _____________________________________________ # # long sys_sched_setparam(pid_t pid, struct sched_param __user *param) # probe syscall.sched_setparam = kernel.function("sys_sched_setparam").call ? { name = "sched_setparam" pid = $pid p_uaddr = $param argstr = sprintf("%d, %p", $pid, $param) } probe syscall.sched_setparam.return = kernel.function("sys_sched_setparam").return ? { name = "sched_setparam" retstr = return_str(1, $return) } # sched_setscheduler _________________________________________ # # long sys_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) # probe syscall.sched_setscheduler = kernel.function("sys_sched_setscheduler").call ? { name = "sched_setscheduler" pid = $pid policy = $policy policy_str = _sched_policy_str($policy) p_uaddr = $param argstr = sprintf("%d, %s, %p", $pid, policy_str, $param) } probe syscall.sched_setscheduler.return = kernel.function("sys_sched_setscheduler").return ? { name = "sched_setscheduler" retstr = return_str(1, $return) } # sched_yield ________________________________________________ # long sys_sched_yield(void) # probe syscall.sched_yield = kernel.function("sys_sched_yield").call { name = "sched_yield" argstr = "" } probe syscall.sched_yield.return = kernel.function("sys_sched_yield").return { name = "sched_yield" retstr = return_str(1, $return) } # select _____________________________________________________ # long sys_select(int n, # fd_set __user *inp, # fd_set __user *outp, # fd_set __user *exp, # struct timeval __user *tvp) # probe syscall.select = kernel.function("sys_select").call { name = "select" n = $n readfds_uaddr = $inp writefds_uaddr = $outp exceptfds_uaddr = $exp timeout_uaddr = $tvp argstr = sprintf("%d, %p, %p, %p, %s", $n, $inp, $outp, $exp, _struct_timeval_u($tvp, 1)) } probe syscall.select.return = kernel.function("sys_select").return { name = "select" retstr = return_str(1, $return) } # long compat_sys_select(int n, # compat_ulong_t __user *inp, # compat_ulong_t __user *outp, # compat_ulong_t __user *exp, # struct compat_timeval __user *tvp) # probe syscall.compat_select = kernel.function("compat_sys_select").call ? { name = "select" n = $n readfds_uaddr = $inp writefds_uaddr = $outp exceptfds_uaddr = $exp timeout_uaddr = $tvp argstr = sprintf("%d, %p, %p, %p, %s", $n, $inp, $outp, $exp, _struct_compat_timeval_u($tvp, 1)) } probe syscall.compat_select.return = kernel.function("compat_sys_select").return ? { name = "select" retstr = return_str(1, $return) } # semctl _____________________________________________________ # long sys_semctl (int semid, # int semnum, # int cmd, # union semun arg) # probe syscall.semctl = kernel.function("sys_semctl").call ? { name = "semctl" semid = $semid semnum = $semnum cmd = $cmd /* * unsupported type tag identifier '$arg' * arg = $arg */ argstr = sprintf("%d, %d, %s", $semid, $semnum, _semctl_cmd($cmd)) } probe syscall.semctl.return = kernel.function("sys_semctl").return ? { name = "semctl" retstr = return_str(1, $return) } # compat_sys_semctl ________________________________________ # # long compat_sys_semctl(int first, int second, int third, void __user *uptr) # COMPAT_SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, int, arg) # probe syscall.compat_sys_semctl = kernel.function("compat_sys_semctl").call ? { name = "compat_sys_semctl" semid = @choose_defined($semid, $first) semnum = @choose_defined($semnum, $second) cmd = @choose_defined($cmd, $third) argstr = sprintf("%d, %d, %s", semid, semnum, _semctl_cmd(cmd)) } probe syscall.compat_sys_semctl.return = kernel.function("compat_sys_semctl").return ? { name = "compat_sys_semctl" retstr = return_str(1, $return) } # semget _____________________________________________________ # long sys_semget (key_t key, int nsems, int semflg) # probe syscall.semget = kernel.function("sys_semget").call ? { name = "semget" key = $key nsems = $nsems semflg = $semflg argstr = sprintf("%d, %d, %s", $key, $nsems, __sem_flags($semflg)) } probe syscall.semget.return = kernel.function("sys_semget").return ? { name = "semget" retstr = return_str(1, $return) } # semop ______________________________________________________ # # long sys_semop (int semid, # struct sembuf __user *tsops, # unsigned nsops) # probe syscall.semop = kernel.function("sys_semtimedop").call ? { name = "semop" semid = $semid %( systemtap_v < "2.3" %? tsops_uaddr = $tsops %: sops_uaddr = $tsops %) nsops = $nsops argstr = sprintf("%d, %p, %d", $semid, $tsops, $nsops) } probe syscall.semop.return = kernel.function("sys_semtimedop").return ? { name = "semop" retstr = return_str(1, $return) } # semtimedop _________________________________________________ # # long sys_semtimedop(int semid, # struct sembuf __user *tsops, # unsigned nsops, # const struct timespec __user *timeout) # probe syscall.semtimedop = kernel.function("sys_semtimedop").call ? { name = "semtimedop" semid = $semid sops_uaddr = $tsops nsops = $nsops timeout_uaddr = $timeout argstr = sprintf("%d, %p, %d, %s", $semid, $tsops, $nsops, _struct_timespec_u($timeout, 1)) } probe syscall.semtimedop.return = kernel.function("sys_semtimedop").return ? { name = "semtimedop" retstr = return_str(1, $return) } # compat_sys_semtimedop ________________________________________ # # long compat_sys_semtimedop(int semid, struct sembuf __user *tsems, # unsigned nsops, const struct compat_timespec __user *timeout) # probe syscall.compat_sys_semtimedop = kernel.function("compat_sys_semtimedop").call ? { name = "compat_sys_semtimedop" semid = $semid sops_uaddr = $tsems nsops = $nsops timeout_uaddr = $timeout argstr = sprintf("%d, %p, %d, %s", $semid, $tsems, $nsops, _struct_compat_timespec_u($timeout, 1)) } probe syscall.compat_sys_semtimedop.return = kernel.function("compat_sys_semtimedop").return ? { name = "compat_sys_semtimedop" retstr = return_str(1, $return) } # send _______________________________________________________ # # long sys_send(int fd, # void __user * buff, # size_t len, # unsigned flags) # probe syscall.send = kernel.function("sys_send").call ? { name = "send" s = $fd buf_uaddr = $buff len = $len flags = $flags flags_str = _sendflags_str($flags) argstr = sprintf("%d, %p, %d, %s", $fd, $buff, $len, flags_str) } probe syscall.send.return = kernel.function("sys_send").return ? { name = "send" retstr = return_str(1, $return) } # sendfile ___________________________________________________ # # ssize_t sys_sendfile[64](int out_fd, # int in_fd, # off_t __user *offset, # size_t count) # probe syscall.sendfile = kernel.function("sys_sendfile").call ?, kernel.function("sys_sendfile64").call ? { name = "sendfile" out_fd = $out_fd in_fd = $in_fd offset_uaddr = $offset count = $count argstr = sprintf("%d, %d, %p, %d", $out_fd, $in_fd, $offset, $count) } probe syscall.sendfile.return = kernel.function("sys_sendfile").return ?, kernel.function("sys_sendfile64").return ? { name = "sendfile" retstr = return_str(1, $return) } # sendmsg ____________________________________________________ # # long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) # probe syscall.sendmsg = kernel.function("sys_sendmsg").call ? { name = "sendmsg" s = $fd msg_uaddr = $msg flags = $flags flags_str = _sendflags_str($flags) argstr = sprintf("%d, %p, %s", $fd, $msg, _sendflags_str($flags)) } probe syscall.sendmsg.return = kernel.function("sys_sendmsg").return ? { name = "sendmsg" retstr = return_str(1, $return) } # compat_sys_sendmsg ________________________________________ # # long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags) # probe syscall.compat_sys_sendmsg = kernel.function("compat_sys_sendmsg").call ? { name = "compat_sys_sendmsg" s = $fd msg_uaddr = $msg flags = $flags flags_str = _sendflags_str($flags) argstr = sprintf("%d, %p, %s", $fd, $msg, _sendflags_str($flags)) } probe syscall.compat_sys_sendmsg.return = kernel.function("compat_sys_sendmsg").return ? { name = "compat_sys_sendmsg" retstr = return_str(1, $return) } # sendmmsg ____________________________________________________ # # int sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, # unsigned int flags) # probe syscall.sendmmsg = kernel.function("sys_sendmmsg").call ? { name = "sendmmsg" s = $fd mmsg_uaddr = $mmsg vlen = $vlen flags = $flags flags_str = _sendflags_str($flags) argstr = sprintf("%d, %p, %d, %s", $fd, $mmsg, $vlen, _sendflags_str($flags)) } probe syscall.sendmmsg.return = kernel.function("sys_sendmmsg").return ? { name = "sendmmsg" retstr = return_str(1, $return) } # sendto _____________________________________________________ # # long sys_sendto(int fd, # void __user * buff, # size_t len, # unsigned flags, # struct sockaddr __user *addr, # int addr_len) # probe syscall.sendto = kernel.function("sys_sendto").call ? { name = "sendto" s = $fd buf_uaddr = $buff len = $len flags = $flags flags_str = _sendflags_str($flags) to_uaddr = $addr tolen = $addr_len argstr = sprintf("%d, %p, %d, %s, %s, %d", $fd, $buff, $len, flags_str, _struct_sockaddr_u($addr, $addr_len), $addr_len) } probe syscall.sendto.return = kernel.function("sys_sendto").return ? { name = "sendto" retstr = return_str(1, $return) } # setdomainname ______________________________________________ # # asmlinkage long # sys_setdomainname(char __user *name, # int len) # probe syscall.setdomainname = kernel.function("sys_setdomainname").call { name = "setdomainname" hostname_uaddr = $name len = $len argstr = sprintf("%p, %d", $name, $len) } probe syscall.setdomainname.return = kernel.function("sys_setdomainname").return { name = "setdomainname" retstr = return_str(1, $return) } # setfsgid ___________________________________________________ # long sys_setfsgid(gid_t gid) # long sys_setfsgid16(old_gid_t gid) # probe syscall.setfsgid = kernel.function("sys_setfsgid16").call ?, kernel.function("sys_setfsgid").call ? { name = "setfsgid" fsgid = $gid argstr = sprint($gid) } probe syscall.setfsgid.return = kernel.function("sys_setfsgid16").return ?, kernel.function("sys_setfsgid").return ? { name = "setfsgid" retstr = return_str(1, $return) } # setfsuid ___________________________________________________ # long sys_setfsuid(uid_t uid) # long sys_setfsuid16(old_uid_t uid) # probe syscall.setfsuid = kernel.function("sys_setfsuid16").call ?, kernel.function("sys_setfsuid").call ? { name = "setfsuid" fsuid = $uid argstr = sprint($uid) } probe syscall.setfsuid.return = kernel.function("sys_setfsuid16").return ?, kernel.function("sys_setfsuid").return ? { name = "setfsuid" retstr = return_str(1, $return) } # setgid _____________________________________________________ # # long sys_setgid(gid_t gid) # long sys_setgid16(old_gid_t gid) # probe syscall.setgid = kernel.function("sys_setgid16").call ?, kernel.function("sys_setgid").call ? { name = "setgid" gid = $gid argstr = sprint($gid) } probe syscall.setgid.return = kernel.function("sys_setgid16").return ?, kernel.function("sys_setgid").return ? { name = "setgid" retstr = return_str(1, $return) } # setgroups __________________________________________________ # # long sys_setgroups(int gidsetsize, gid_t __user *grouplist) # long sys_setgroups16(int gidsetsize, old_gid_t __user *grouplist) # long sys32_setgroups16(int gidsetsize, u16 __user *grouplist) # probe syscall.setgroups = kernel.function("sys_setgroups16").call ?, kernel.function("sys32_setgroups16").call ?, kernel.function("sys_setgroups").call ? { name = "setgroups" size = $gidsetsize list_uaddr = $grouplist argstr = sprintf("%d, %p", $gidsetsize, $grouplist) } probe syscall.setgroups.return = kernel.function("sys_setgroups16").return ?, kernel.function("sys32_setgroups16").return ?, kernel.function("sys_setgroups").return ? { name = "setgroups" retstr = return_str(1, $return) } # sethostname ________________________________________________ # # asmlinkage long # sys_sethostname(char __user *name, # int len) # probe syscall.sethostname = kernel.function("sys_sethostname").call { name = "sethostname" hostname_uaddr = $name name_str = user_string_quoted($name) len = $len argstr = sprintf("%s, %d", user_string_quoted($name), $len) } probe syscall.sethostname.return = kernel.function("sys_sethostname").return { name = "sethostname" retstr = return_str(1, $return) } # setitimer __________________________________________________ # # long sys_setitimer(int which, # struct itimerval __user *value, # struct itimerval __user *ovalue) # probe syscall.setitimer = kernel.function("sys_setitimer").call { name = "setitimer" which = $which value_uaddr = $value ovalue_uaddr = $ovalue argstr = sprintf("%s, %s, %p", _itimer_which_str($which), _struct_itimerval_u($value), $ovalue) } probe syscall.setitimer.return = kernel.function("sys_setitimer").return { name = "setitimer" retstr = return_str(1, $return) } # # long compat_sys_setitimer(int which, # struct compat_itimerval __user *in, # struct compat_itimerval __user *out) # probe syscall.compat_setitimer = kernel.function("compat_sys_setitimer").call ? { name = "setitimer" which = $which value_uaddr = $in ovalue_uaddr = $out argstr = sprintf("%s, %s, %p", _itimer_which_str($which), _struct_compat_itimerval_u($in), $out) } probe syscall.compat_setitimer.return = kernel.function("compat_sys_setitimer").return ? { name = "setitimer" retstr = return_str(1, $return) } # set_mempolicy ______________________________________________ # long sys_set_mempolicy(int mode, # unsigned long __user *nmask, # unsigned long maxnode) # probe syscall.set_mempolicy = kernel.function("compat_sys_set_mempolicy").call ?, kernel.function("sys_set_mempolicy").call ? { name = "set_mempolicy" mode = $mode nmask_uaddr = $nmask maxnode = $maxnode argstr = sprintf("%d, %p, %d", $mode, $nmask, $maxnode) } probe syscall.set_mempolicy.return = kernel.function("compat_sys_set_mempolicy").return ?, kernel.function("sys_set_mempolicy").return ? { name = "set_mempolicy" retstr = return_str(1, $return) } # setpgid ____________________________________________________ # # asmlinkage long # sys_setpgid(pid_t pid, # pid_t pgid) # probe syscall.setpgid = kernel.function("sys_setpgid").call { name = "setpgid" pid = $pid pgid = $pgid argstr = sprintf("%d, %d", $pid, $pgid) } probe syscall.setpgid.return = kernel.function("sys_setpgid").return { name = "setpgid" retstr = return_str(1, $return) } # setpriority ________________________________________________ # # asmlinkage long # sys_setpriority(int which, # int who, # int niceval) # probe syscall.setpriority = kernel.function("sys_setpriority").call { name = "setpriority" which = $which which_str = _priority_which_str($which) who = $who prio = $niceval argstr = sprintf("%s, %d, %d", which_str, $who, $niceval) } probe syscall.setpriority.return = kernel.function("sys_setpriority").return { name = "setpriority" retstr = return_str(1, $return) } # setregid ___________________________________________________ # long sys_setregid(gid_t rgid, gid_t egid) # probe syscall.setregid = kernel.function("sys_setregid").call { name = "setregid" rgid = __int32($rgid) egid = __int32($egid) argstr = sprintf("%d, %d", rgid, egid) } probe syscall.setregid.return = kernel.function("sys_setregid").return { name = "setregid" retstr = return_str(1, $return) } # setregid16 _________________________________________________ # long sys_setregid16(old_gid_t rgid, old_gid_t egid) # probe syscall.setregid16 = kernel.function("sys_setregid16").call ? { name = "setregid" rgid = __short($rgid) egid = __short($egid) argstr = sprintf("%d, %d", rgid, egid) } probe syscall.setregid16.return = kernel.function("sys_setregid16").return ? { name = "setregid" retstr = return_str(1, $return) } # setresgid __________________________________________________ # long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) # probe syscall.setresgid = kernel.function("sys_setresgid").call { name = "setresgid" rgid = __int32($rgid) egid = __int32($egid) sgid = __int32($sgid) argstr = sprintf("%d, %d, %d", rgid, egid, sgid) } probe syscall.setresgid.return = kernel.function("sys_setresgid").return { name = "setresgid" retstr = return_str(1, $return) } # setresgid16 ________________________________________________ # # long sys_setresgid16(old_gid_t rgid, # old_gid_t egid, # old_gid_t sgid) # probe syscall.setresgid16 = kernel.function("sys_setresgid16").call ? { name = "setresgid" rgid = __short($rgid) egid = __short($egid) sgid = __short($sgid) argstr = sprintf("%d, %d, %d", rgid, egid, sgid) } probe syscall.setresgid16.return = kernel.function("sys_setresgid16").return ? { name = "setresgid16" retstr = return_str(1, $return) } # setresuid __________________________________________________ # # long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) # probe syscall.setresuid = kernel.function("sys_setresuid").call { name = "setresuid" ruid = __int32($ruid) euid = __int32($euid) suid = __int32($suid) argstr = sprintf("%d, %d, %d", ruid, euid, suid) } probe syscall.setresuid.return = kernel.function("sys_setresuid").return { name = "setresuid" retstr = return_str(1, $return) } # setresuid16 ________________________________________________ # # long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid) # probe syscall.setresuid16 = kernel.function("sys_setresuid16").call ? { name = "setresuid" ruid = __short($ruid) euid = __short($euid) suid = __short($suid) argstr = sprintf("%d, %d, %d", ruid, euid, suid) } probe syscall.setresuid16.return = kernel.function("sys_setresuid16").return ? { name = "setresuid" retstr = return_str(1, $return) } # setreuid ___________________________________________________ # long sys_setreuid(uid_t ruid, uid_t euid) # probe syscall.setreuid = kernel.function("sys_setreuid").call { name = "setreuid" ruid = __int32($ruid) euid = __int32($euid) argstr = sprintf("%d, %d", ruid, euid) } probe syscall.setreuid.return = kernel.function("sys_setreuid").return { name = "setreuid" retstr = return_str(1, $return) } # setreuid16 _________________________________________________ # long sys_setreuid16(old_uid_t ruid, old_uid_t euid) # probe syscall.setreuid16 = kernel.function("sys_setreuid16").call ? { name = "setreuid" ruid = __short($ruid) euid = __short($euid) argstr = sprintf("%d, %d", ruid, euid) } probe syscall.setreuid16.return = kernel.function("sys_setreuid16").return ? { name = "setreuid" retstr = return_str(1, $return) } # setrlimit __________________________________________________ # # asmlinkage long # sys_setrlimit(unsigned int resource, # struct rlimit __user *rlim) # probe syscall.setrlimit = kernel.function("sys_setrlimit").call { name = "setrlimit" resource = $resource rlim_uaddr = $rlim argstr = sprintf("%s, %s", _rlimit_resource_str($resource), _struct_rlimit_u($rlim)) } probe syscall.setrlimit.return = kernel.function("sys_setrlimit").return { name = "setrlimit" retstr = return_str(1, $return) } # setsid _____________________________________________________ # # long sys_setsid(void) # probe syscall.setsid = kernel.function("sys_setsid").call { name = "setsid" argstr = "" } probe syscall.setsid.return = kernel.function("sys_setsid").return { name = "setsid" retstr = return_str(1, $return) } # setsockopt _________________________________________________ # # long sys_setsockopt(int fd, # int level, # int optname, # char __user *optval, # int optlen) # probe syscall.setsockopt = kernel.function("compat_sys_setsockopt").call ?, kernel.function("sys_setsockopt").call ? { name = "setsockopt" fd = $fd level = $level level_str = _sockopt_level_str($level) optname = $optname optname_str = _sockopt_optname_str($optname) optval_uaddr = $optval optlen = $optlen argstr = sprintf("%d, %s, %s, %p, %d", $fd, level_str, optname_str, $optval, $optlen) } probe syscall.setsockopt.return = kernel.function("compat_sys_setsockopt").return ?, kernel.function("sys_setsockopt").return ? { name = "setsockopt" retstr = return_str(1, $return) } # set_tid_address ____________________________________________ # # asmlinkage long # sys_set_tid_address(int __user *tidptr) # probe syscall.set_tid_address = kernel.function("sys_set_tid_address").call { name = "set_tid_address" tidptr_uaddr = $tidptr argstr = sprintf("%p", tidptr_uaddr) } probe syscall.set_tid_address.return = kernel.function("sys_set_tid_address").return { name = "set_tid_address" retstr = return_str(1, $return) } # settimeofday _______________________________________________ # # long sys_settimeofday(struct timeval __user *tv, # struct timezone __user *tz) # probe syscall.settimeofday = kernel.function("sys_settimeofday").call { name = "settimeofday" tv_uaddr = $tv tz_uaddr = $tz argstr = sprintf("%s, %s", _struct_timeval_u($tv, 1), _struct_timezone_u($tz)) } probe syscall.settimeofday.return = kernel.function("sys_settimeofday").return { name = "settimeofday" retstr = return_str(1, $return) } # # long sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) # long compat_sys_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) # probe syscall.settimeofday32 = kernel.function("sys32_settimeofday").call ?, kernel.function("compat_sys_settimeofday").call ? { name = "settimeofday" tv_uaddr = $tv tz_uaddr = $tz argstr = sprintf("%s, %s", _struct_compat_timeval_u($tv, 1), _struct_timezone_u($tz)) } probe syscall.settimeofday32.return = kernel.function("sys32_settimeofday").return ?, kernel.function("compat_sys_settimeofday").return ? { name = "settimeofday" retstr = return_str(1, $return) } # setuid _____________________________________________________ # # long sys_setuid(uid_t uid) # long sys_setuid16(old_uid_t uid) # probe syscall.setuid = kernel.function("sys_setuid16").call ?, kernel.function("sys_setuid").call { name = "setuid" uid = $uid argstr = sprint($uid) } probe syscall.setuid.return = kernel.function("sys_setuid16").return ?, kernel.function("sys_setuid").return { name = "setuid" retstr = return_str(1, $return) } # setxattr ___________________________________________________ # long sys_setxattr(char __user *path, # char __user *name, # void __user *value, # size_t size, # int flags) # probe syscall.setxattr = kernel.function("sys_setxattr").call { name = "setxattr" path_uaddr = @choose_defined($pathname, $path) path = user_string_quoted(@choose_defined($pathname, $path)) name_uaddr = $name name_str = user_string_quoted($name) value_uaddr = $value size = $size flags = $flags argstr = sprintf("%s, %s, %p, %d, %d", user_string_quoted(@choose_defined($pathname, $path)), user_string_quoted($name), value_uaddr, $size, $flags) } probe syscall.setxattr.return = kernel.function("sys_setxattr").return { name = "setxattr" retstr = return_str(1, $return) } # sgetmask ___________________________________________________ # # sys_sgetmask(void) # probe syscall.sgetmask = kernel.function("sys_sgetmask").call ? { name = "sgetmask" argstr = "" } probe syscall.sgetmask.return = kernel.function("sys_sgetmask").return ? { name = "sgetmask" retstr = return_str(1, $return) } # shmat ______________________________________________________ # # long sys_shmat(int shmid, char __user *shmaddr, int shmflg) # probe syscall.shmat = kernel.function("sys_shmat").call ? { name = "shmat" shmid = $shmid shmaddr_uaddr = $shmaddr shmflg = $shmflg argstr = sprintf("%d, %p, %s", $shmid, $shmaddr, _shmat_flags_str($shmflg)) } probe syscall.shmat.return = kernel.function("sys_shmat").return ? { name = "shmat" retstr = return_str(1, $return) } # compat_sys_shmat ________________________________________ # # long compat_sys_shmat(int first, int second, compat_uptr_t third, # int version, void __user *uptr) # COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, # int, shmflg) # probe syscall.compat_sys_shmat = kernel.function("compat_sys_shmat").call ? { name = "compat_sys_shmat" %( systemtap_v < "2.3" %? first = @choose_defined($shmid, $first) second = @choose_defined($shmflg, $second) third = @choose_defined($third, 0) uptr_uaddr = @choose_defined($shmaddr, $uptr) %) shmid = @choose_defined($shmid, $first) shmaddr_uaddr = @choose_defined($shmaddr, $uptr) shmflg = @choose_defined($shmflg, $second) argstr = sprintf("%d, %p, %s", shmid, shmaddr_uaddr, _shmat_flags_str(shmflg)) } probe syscall.compat_sys_shmat.return = kernel.function("compat_sys_shmat").return ? { name = "compat_sys_shmat" retstr = return_str(1, $return) } # shmctl _____________________________________________________ # # long sys_shmctl (int shmid, # int cmd, # struct shmid_ds __user *buf) # probe syscall.shmctl = kernel.function("sys_shmctl").call ? { name = "shmctl" shmid = $shmid cmd = $cmd buf_uaddr = $buf argstr = sprintf("%d, %s, %p", $shmid, _semctl_cmd($cmd), $buf) } probe syscall.shmctl.return = kernel.function("sys_shmctl").return ? { name = "shmctl" retstr = return_str(1, $return) } # compat_sys_shmctl ________________________________________ # # long compat_sys_shmctl(int first, int second, void __user *uptr) # probe syscall.compat_sys_shmctl = kernel.function("compat_sys_shmctl").call ? { name = "compat_sys_shmctl" first = $first second = $second uptr_uaddr = $uptr argstr = sprintf("%d, %d, %p", $first, $second, $uptr) } probe syscall.compat_sys_shmctl.return = kernel.function("compat_sys_shmctl").return ? { name = "compat_sys_shmctl" retstr = return_str(1, $return) } # shmdt ______________________________________________________ # # long sys_shmdt(char __user *shmaddr) # probe syscall.shmdt = kernel.function("sys_shmdt").call ? { name = "shmdt" shmaddr_uaddr = $shmaddr argstr = sprintf("%p", $shmaddr) } probe syscall.shmdt.return = kernel.function("sys_shmdt").return ? { name = "shmdt" retstr = return_str(1, $return) } # shmget _____________________________________________________ # # long sys_shmget (key_t key, # size_t size, # int shmflg) # probe syscall.shmget = kernel.function("sys_shmget").call ? { name = "shmget" key = $key size = $size shmflg = $shmflg argstr = sprintf("%d, %d, %d", $key, $size, $shmflg) } probe syscall.shmget.return = kernel.function("sys_shmget").return ? { name = "shmget" retstr = return_str(1, $return) } # shutdown ___________________________________________________ # # long sys_shutdown(int fd, int how) # probe syscall.shutdown = kernel.function("sys_shutdown").call ? { name = "shutdown" s = $fd how = $how how_str = _shutdown_how_str($how) argstr = sprintf("%d, %s", $fd, how_str) } probe syscall.shutdown.return = kernel.function("sys_shutdown").return ? { name = "shutdown" retstr = return_str(1, $return) } # sigaction __________________________________________________ # sys_sigaction(int sig, const struct old_sigaction __user *act, struct old_sigaction __user *oact) # sys32_sigaction(int sig, struct old_sigaction32 __user *act, struct old_sigaction32 __user *oact) # probe syscall.sigaction = kernel.function("sys_sigaction").call ? { name = "sigaction" sig = $sig act_uaddr = $act oact_uaddr = $oact argstr = sprintf("%s, {%s}, %p", _signal_name($sig), _struct_sigaction_u($act), $oact) } probe syscall.sigaction.return = kernel.function("sys_sigaction").return ? { name = "sigaction" retstr = return_str(1, $return) } probe syscall.sigaction32 = kernel.function("sys32_sigaction").call ?, kernel.function("compat_sys_sigaction").call ? { name = "sigaction" sig = $sig act_uaddr = $act oact_uaddr = $oact argstr = sprintf("%s, {%s}, %p", _signal_name($sig), _struct_old_sigaction32_u($act), $oact) } probe syscall.sigaction32.return = kernel.function("sys32_sigaction").return ?, kernel.function("compat_sys_sigaction").return ? { name = "sigaction" retstr = return_str(1, $return) } # In kernel 3.8, CONFIG_GENERIC_SIGALTSTACK was added by # kernel commit 6bf9adfc90370b695cb111116e15fdc0e1906270. # # Then, in kernel 3.9, all architectures were switched to using the # generic sigaltstack by kernel commit # d64008a8f30e0b381b292788ec6f3ee509b3bb40, which also removed the # CONFIG_GENERIC_SIGALTSTACK config variable. # # Thus the following preprocessor test. %( CONFIG_GENERIC_SIGALTSTACK == "y" || kernel_v >= "3.9" %? # sigaltstack ________________________________________________ # SYSCALL_DEFINE2(sigaltstack,const stack_t __user *,uss, stack_t __user *,uoss) # probe syscall.sigaltstack = kernel.function("sys_sigaltstack").call { name = "sigaltstack" uss_uaddr = $uss uoss_uaddr = $uoss argstr = sprintf("%p, %p", $uss, $uoss) } probe syscall.sigaltstack.return = kernel.function("sys_sigaltstack").return { name = "sigaltstack" retstr = return_str(1, $return) } %) # signal _____________________________________________________ # unsigned long sys_signal(int sig, __sighandler_t handler) # probe syscall.signal = kernel.function("sys_signal").call ? { name = "signal" sig = $sig handler = $handler argstr = sprintf("%s, %s", _signal_name($sig), _sighandler_str($handler)) } probe syscall.signal.return = kernel.function("sys_signal").return ? { name = "signal" retstr = return_str(1, $return) } # signalfd _____________________________________________________ # # long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask) # long sys_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, # int flags) # long compat_sys_signalfd(int ufd, const compat_sigset_t __user *sigmask, # compat_size_t sigsetsize) # long compat_sys_signalfd4(int ufd, const compat_sigset_t __user *sigmask, # compat_size_t sigsetsize, int flags) # probe syscall.signalfd = kernel.function("sys_signalfd4").call !, kernel.function("sys_signalfd").call ? { flags = @choose_defined($flags, 0); if (flags == 0) { name = "signalfd" argstr = sprintf("%d, %p, %d", $ufd, $user_mask, $sizemask) } else { name = "signalfd4" argstr = sprintf("%d, %p, %d, %s", $ufd, $user_mask, $sizemask, _signalfd4_flags_str($flags)) } } probe syscall.signalfd.return = kernel.function("sys_signalfd4").return !, kernel.function("sys_signalfd").return ? { flags = @choose_defined($flags, 0); name = (flags == 0) ? "signalfd" : "signalfd4" retstr = return_str(1, $return) } probe syscall.compat_signalfd = kernel.function("compat_sys_signalfd4").call !, kernel.function("compat_sys_signalfd").call ? { flags = @choose_defined($flags, 0); if (flags == 0) { name = "compat_signalfd" argstr = sprintf("%d, %p, %d", $ufd, $sigmask, $sigsetsize) } else { name = "compat_signalfd4" argstr = sprintf("%d, %p, %d, %s", $ufd, $sigmask, $sigsetsize, _signalfd4_flags_str($flags)) } } probe syscall.compat_signalfd.return = kernel.function("compat_sys_signalfd4").return !, kernel.function("compat_sys_signalfd").return ? { flags = @choose_defined($flags, 0); name = (flags == 0) ? "compat_signalfd" : "compat_signalfd4" retstr = return_str(1, $return) } # sigpending _________________________________________________ # long sys_sigpending(old_sigset_t __user *set) # probe syscall.sigpending = kernel.function("sys_sigpending").call ? { name = "sigpending" argstr = sprintf("%p", $set) } probe syscall.sigpending.return = kernel.function("sys_sigpending").return ? { name = "sigpending" retstr = return_str(1, $return) } # sigprocmask ________________________________________________ # long sys_sigprocmask(int how, old_sigset_t __user *set, old_sigset_t __user *oset) # asmlinkage long compat_sys_sigprocmask(int how, # compat_old_sigset_t __user *nset, # compat_old_sigset_t __user *oset) # probe syscall.sigprocmask = kernel.function("sys_sigprocmask").call ?, kernel.function("compat_sys_sigprocmask").call ? { name = "sigprocmask" how = $how how_str = _sigprocmask_how_str($how) set_uaddr = @choose_defined($set, $nset) oldset_uaddr = $oset argstr = sprintf("%s, %p, %p", how_str, set_uaddr, $oset) } probe syscall.sigprocmask.return = kernel.function("sys_sigprocmask").return ?, kernel.function("compat_sys_sigprocmask").return ? { name = "sigprocmask" retstr = return_str(1, $return) } # sigreturn __________________________________________________ # int sys_sigreturn(unsigned long __unused) # probe syscall.sigreturn = kernel.function("sys_sigreturn").call ?, kernel.function("sys32_sigreturn").call ? { name = "sigreturn" argstr = "" } probe syscall.sigreturn.return = kernel.function("sys_sigreturn").return ?, kernel.function("sys32_sigreturn").return ? { name = "sigreturn" retstr = return_str(1, $return) } # sigsuspend _________________________________________________ # probe syscall.sigsuspend = kernel.function("sys_sigsuspend").call ?, kernel.function("sys32_sigsuspend").call ? { name = "sigsuspend" argstr = "" } probe syscall.sigsuspend.return = kernel.function("sys_sigsuspend").return ?, kernel.function("sys32_sigsuspend").return ? { name = "sigsuspend" retstr = return_str(1, $return) } # socket _____________________________________________________ # long sys_socket(int family, int type, int protocol) # probe syscall.socket = kernel.function("sys_socket").call ? { name = "socket" family = $family type = $type protocol = $protocol argstr = sprintf("%s, %s, %d", _sock_family_str($family), _sock_type_str($type), $protocol) } probe syscall.socket.return = kernel.function("sys_socket").return ? { name = "socket" retstr = return_str(1, $return) } # commented out because this seems redundant # socketcall _________________________________________________ # # long sys_socketcall(int call, unsigned long __user *args) # #probe syscall.socketcall = kernel.function("sys_socketcall").call ? #{ # name = "socketcall" # call = $call # args_uaddr = $args # argstr = sprintf("%d, %p", $call, args_uaddr) #} #probe syscall.socketcall.return = kernel.function("sys_socketcall").return ? #{ # name = "socketcall" # retstr = return_str(1, $return) #} # socketpair _________________________________________________ # long sys_socketpair(int family, # int type, # int protocol, # int __user *usockvec) # probe syscall.socketpair = kernel.function("sys_socketpair").call ? { name = "socketpair" family = $family type = $type protocol = $protocol sv_uaddr = $usockvec argstr = sprintf("%s, %s, %d, %p", _sock_family_str($family), _sock_type_str($type), $protocol, sv_uaddr) } probe syscall.socketpair.return = kernel.function("sys_socketpair").return ? { name = "socketpair" retstr = return_str(1, $return) } # splice ___________________________________________________ # # long sys_splice(int fd_in, loff_t __user *off_in, # int fd_out, loff_t __user *off_out, # size_t len, unsigned int flags) # probe syscall.splice = kernel.function("sys_splice").call ? { name = "splice" argstr = sprintf("%d, %p, %d, %p, %d, 0x%x", $fd_in, $off_in, $fd_out, $off_out, $len, $flags) } probe syscall.splice.return = kernel.function("sys_splice").return ? { name = "splice" retstr = return_str(1, $return) } # ssetmask ___________________________________________________ # # long sys_ssetmask(int newmask) # probe syscall.ssetmask = kernel.function("sys_ssetmask").call ? { name = "ssetmask" newmask = $newmask argstr = sprint($newmask) } probe syscall.ssetmask.return = kernel.function("sys_ssetmask").return ? { name = "ssetmask" retstr = return_str(1, $return) } # stat _______________________________________________________ # long sys_stat(char __user * filename, struct __old_stat __user * statbuf) # long sys32_stat64(char __user * filename, struct stat64 __user *statbuf) # long sys_stat64(char __user * filename, struct stat64 __user * statbuf) # long sys_oabi_stat64(char __user * filename, struct oldabi_stat64 __user * statbuf) # long compat_sys_newstat(char __user * filename, struct compat_stat __user *statbuf) probe syscall.stat = kernel.function("sys_stat").call ?, kernel.function("sys_newstat").call ?, kernel.function("sys32_stat64").call ?, kernel.function("sys_stat64").call ?, kernel.function("sys_oabi_stat64").call ?, kernel.function("compat_sys_newstat").call ? { name = "stat" filename_uaddr = $filename filename = user_string_quoted($filename) buf_uaddr = $statbuf argstr = sprintf("%s, %p", user_string_quoted($filename), buf_uaddr) } probe syscall.stat.return = kernel.function("sys_stat").return ?, kernel.function("sys_newstat").return ?, kernel.function("sys32_stat64").return ?, kernel.function("sys_stat64").return ?, kernel.function("sys_oabi_stat64").return ?, kernel.function("compat_sys_newstat").return ? { name = "stat" retstr = return_str(1, $return) } # statfs _____________________________________________________ # long sys_statfs(const char __user * path, struct statfs __user * buf) # long compat_sys_statfs(const char __user *path, struct compat_statfs __user *buf) # probe syscall.statfs = kernel.function("compat_sys_statfs").call ?, kernel.function("sys_statfs").call ? { name = "statfs" buf_uaddr = $buf path = user_string_quoted(@choose_defined($pathname, $path)) argstr = sprintf("%s, %p", user_string_quoted(@choose_defined($pathname, $path)), $buf) } probe syscall.statfs.return = kernel.function("compat_sys_statfs").return ?, kernel.function("sys_statfs").return ? { name = "statfs" retstr = return_str(1, $return) } # statfs64 ___________________________________________________ # # long sys_statfs64(const char __user *path, size_t sz, struct statfs64 __user *buf) # long compat_sys_statfs64(const char __user *path, compat_size_t sz, struct compat_statfs64 __user *buf) # probe syscall.statfs64 = kernel.function("compat_sys_statfs64").call ?, kernel.function("sys_statfs64").call ? { name = "statfs" sz = $sz buf_uaddr = $buf path = user_string_quoted(@choose_defined($pathname, $path)) argstr = sprintf("%s, %d, %p", user_string_quoted(@choose_defined($pathname, $path)), $sz, $buf) } probe syscall.statfs64.return = kernel.function("compat_sys_statfs64").return ?, kernel.function("sys_statfs64").return ? { name = "statfs" retstr = return_str(1, $return) } # stime ______________________________________________________ # # long sys_stime(time_t __user *tptr) # long compat_sys_stime(compat_time_t __user *tptr) # probe syscall.stime = kernel.function("compat_sys_stime").call ?, kernel.function("sys_stime").call ? { name = "stime" t_uaddr = $tptr /* FIXME. Decode time */ argstr = sprintf("%p", $tptr) } probe syscall.stime.return = kernel.function("compat_sys_stime").return ?, kernel.function("sys_stime").return ? { name = "stime" retstr = return_str(1, $return) } # swapoff ____________________________________________________ # # asmlinkage long # sys_swapoff(const char __user * specialfile) # probe syscall.swapoff = kernel.function("sys_swapoff").call ? { name = "swapoff" path = user_string_quoted($specialfile) argstr = user_string_quoted($specialfile) } probe syscall.swapoff.return = kernel.function("sys_swapoff").return ? { name = "swapoff" retstr = return_str(1, $return) } # swapon _____________________________________________________ # # asmlinkage long # sys_swapon(const char __user * specialfile, # int swap_flags) # probe syscall.swapon = kernel.function("sys_swapon").call ? { name = "swapon" path = user_string_quoted($specialfile) swapflags = $swap_flags argstr = sprintf("%s, %d", user_string_quoted($specialfile), swapflags) } probe syscall.swapon.return = kernel.function("sys_swapon").return ? { name = "swapon" retstr = return_str(1, $return) } # symlink ____________________________________________________ # long sys_symlink(const char __user * oldname, # const char __user * newname) probe syscall.symlink = kernel.function("sys_symlink").call { name = "symlink" oldpath = user_string_quoted($oldname) newpath = user_string_quoted($newname) argstr = sprintf("%s, %s", user_string_quoted($oldname), user_string_quoted($newname)) } probe syscall.symlink.return = kernel.function("sys_symlink").return { name = "symlink" retstr = return_str(1, $return) } # symlinkat __________________________________________________ # new function with 2.6.16 # long sys_symlinkat(const char __user *oldname, int newdfd, # const char __user *newname) probe syscall.symlinkat = kernel.function("sys_symlinkat").call ? { name = "symlinkat" oldname = $oldname oldname_str = user_string_quoted($oldname) newdfd = $newdfd newdfd_str = _dfd_str($newdfd) newname = $newname newname_str = user_string_quoted($newname) argstr = sprintf("%s, %s, %s", user_string_quoted($oldname), newdfd_str, user_string_quoted($newname)) } probe syscall.symlinkat.return = kernel.function("sys_symlinkat").return ? { name = "symlinkat" retstr = return_str(1, $return) } # sync _______________________________________________________ # # sys_sync(void) # probe syscall.sync = kernel.function("sys_sync").call { name = "sync" argstr = "" } probe syscall.sync.return = kernel.function("sys_sync").return { name = "sync" retstr = return_str(1, $return) } # sysctl _____________________________________________________ # # long sys_sysctl(struct __sysctl_args __user *args) # probe syscall.sysctl = kernel.function("compat_sys_sysctl").call ?, kernel.function("sys_sysctl").call ? { name = "sysctl" argstr = sprintf("%p", $args) } probe syscall.sysctl.return = kernel.function("compat_sys_sysctl").return ?, kernel.function("sys_sysctl").return ? { name = "sysctl" retstr = return_str(1, $return) } # sysfs ______________________________________________________ # # asmlinkage long # sys_sysfs(int option, # unsigned long arg1, # unsigned long arg2) # probe syscall.sysfs = kernel.function("sys_sysfs").call { name = "sysfs" option = $option arg1 = $arg1 arg2 = $arg2 if (option == 1) argstr = sprintf("%d, %s, %d", $option, user_string_quoted($arg1), $arg2) else if (option == 2) argstr = sprintf("%d, %d, %p", $option, $arg1, $arg2) else if (option == 3) argstr = sprintf("%d, %d, %d", $option, $arg1, $arg2) else argstr = sprintf("%d, %d, %d", $option, $arg1, $arg2) } probe syscall.sysfs.return = kernel.function("sys_sysfs").return { name = "sysfs" retstr = return_str(1, $return) } # sysinfo ____________________________________________________ # # long sys_sysinfo(struct sysinfo __user *info) # long compat_sys_sysinfo(struct compat_sysinfo __user *info) probe syscall.sysinfo = kernel.function("compat_sys_sysinfo").call ?, kernel.function("sys_sysinfo").call { name = "sysinfo" info_uaddr = $info argstr = sprintf("%p", $info) } probe syscall.sysinfo.return = kernel.function("compat_sys_sysinfo").return ?, kernel.function("sys_sysinfo").return { name = "sysinfo" retstr = return_str(1, $return) } # syslog _____________________________________________________ # # long sys_syslog(int type, char __user * buf, int len) # probe syscall.syslog = kernel.function("sys_syslog").call { name = "syslog" type = $type bufp_uaddr = $buf len = $len argstr = sprintf("%d, %p, %d", $type, $buf, $len) } probe syscall.syslog.return = kernel.function("sys_syslog").return { name = "syslog" retstr = return_str(1, $return) } # tee _____________________________________________________ # # long sys_tee(int fdin, int fdout, size_t len, unsigned int flags) # probe syscall.tee = kernel.function("sys_tee").call ? { name = "tee" argstr = sprintf("%d, %d, %d, 0x%x", $fdin, $fdout, $len, $flags) } probe syscall.tee.return = kernel.function("sys_tee").return ? { name = "tee" retstr = return_str(1, $return) } # tgkill _____________________________________________________ # # asmlinkage long # sys_tgkill(int tgid, # int pid, # int sig) # probe syscall.tgkill = kernel.function("sys_tgkill").call { name = "tgkill" tgid = $tgid pid = $pid sig = $sig argstr = sprintf("%d, %d, %s", $tgid, $pid, _signal_name($sig)) } probe syscall.tgkill.return = kernel.function("sys_tgkill").return { name = "tgkill" retstr = return_str(1, $return) } # time _______________________________________________________ # # long sys_time(time_t __user * tloc) # long sys_time64(long __user * tloc) # long sys32_time(compat_time_t __user * tloc) # long compat_sys_time(compat_time_t __user * tloc) # probe syscall.time = kernel.function("sys32_time").call ?, kernel.function("sys_time64").call ?, kernel.function("compat_sys_time").call ?, kernel.function("sys_time").call ? { name = "time" t_uaddr = $tloc argstr = sprintf("%p", $tloc) } probe syscall.time.return = kernel.function("sys32_time").return ?, kernel.function("sys_time64").return ?, kernel.function("compat_sys_time").return ?, kernel.function("sys_time").return ? { name = "time" retstr = return_str(1, $return) } # timer_create _______________________________________________ # # long sys_timer_create(clockid_t which_clock, # struct sigevent __user *timer_event_spec, # timer_t __user * created_timer_id) # probe syscall.timer_create = kernel.function("sys_timer_create").call { name = "timer_create" clockid = $which_clock clockid_str = _get_wc_str($which_clock) evp_uaddr = $timer_event_spec timerid_uaddr = $created_timer_id argstr = sprintf("%s, %p, %p", clockid_str, $timer_event_spec, $created_timer_id) } probe syscall.timer_create.return = kernel.function("sys_timer_create").return { name = "timer_create" retstr = return_str(1, $return) } # timer_delete _______________________________________________ # # long sys_timer_delete(timer_t timer_id) # probe syscall.timer_delete = kernel.function("sys_timer_delete").call { name = "timer_delete" timerid = $timer_id argstr = sprint($timer_id) } probe syscall.timer_delete.return = kernel.function("sys_timer_delete").return { name = "timer_delete" retstr = return_str(1, $return) } # timer_getoverrun ___________________________________________ # # long sys_timer_getoverrun(timer_t timer_id) # probe syscall.timer_getoverrun = kernel.function("sys_timer_getoverrun").call { name = "timer_getoverrun" timerid = $timer_id argstr = sprint($timer_id) } probe syscall.timer_getoverrun.return = kernel.function("sys_timer_getoverrun").return { name = "timer_getoverrun" retstr = return_str(1, $return) } # timer_gettime ______________________________________________ # # long sys_timer_gettime(timer_t timer_id, # struct itimerspec __user *setting) # probe syscall.timer_gettime = kernel.function("sys_timer_gettime").call { name = "timer_gettime" timerid = $timer_id value_uaddr = $setting argstr = sprintf("%d, %p", $timer_id, $setting) } probe syscall.timer_gettime.return = kernel.function("sys_timer_gettime").return { name = "timer_gettime" retstr = return_str(1, $return) } # timer_settime ______________________________________________ # # long sys_timer_settime(timer_t timer_id, # int flags, # const struct itimerspec __user *new_setting, # struct itimerspec __user *old_setting) # probe syscall.timer_settime = kernel.function("sys_timer_settime").call { name = "timer_settime" timerid = $timer_id flags = $flags value_uaddr = $new_setting ovalue_uaddr = $old_setting argstr = sprintf("%d, %d, %s, %p", $timer_id, $flags, _struct_itimerspec_u($new_setting), $old_setting) } probe syscall.timer_settime.return = kernel.function("sys_timer_settime").return { name = "timer_settime" retstr = return_str(1, $return) } # timerfd ______________________________________________ # # long sys_timerfd(int ufd, int clockid, int flags, # const struct itimerspec __user *utmr) # long compat_sys_timerfd(int ufd, int clockid, int flags, # const struct compat_itimerspec __user *utmr) # probe syscall.timerfd = kernel.function("sys_timerfd").call ?, kernel.function("compat_sys_timerfd").call ? { name = "timerfd" argstr = sprintf("%d, %d, 0x%x", $ufd, $clockid, $flags) } probe syscall.timerfd.return = kernel.function("sys_timerfd").return ?, kernel.function("compat_sys_timerfd").return ? { name = "timerfd" retstr = return_str(1, $return) } # times ______________________________________________________ # # long sys_times(struct tms __user * tbuf) # long compat_sys_times(struct compat_tms __user *tbuf) probe syscall.times = kernel.function("compat_sys_times").call ?, kernel.function("sys_times").call ? { name = "times" argstr = sprintf("%p", $tbuf) } probe syscall.times.return = kernel.function("compat_sys_times").return ?, kernel.function("sys_times").return ? { name = "times" retstr = return_str(1, $return) } # tkill ______________________________________________________ # # asmlinkage long # sys_tkill(int pid, # int sig) # probe syscall.tkill = kernel.function("sys_tkill").call { name = "tkill" pid = $pid sig = $sig argstr = sprintf("%d, %s", $pid, _signal_name($sig)) } probe syscall.tkill.return = kernel.function("sys_tkill").return { name = "tkill" retstr = return_str(1, $return) } # truncate ___________________________________________________ # # sys_truncate(const char __user * path, unsigned long length) # sys_truncate64(const char __user * path, loff_t length) # probe syscall.truncate = kernel.function("sys_truncate").call ?, kernel.function("sys_truncate64").call ? { name = "truncate" path_uaddr = $path path = user_string_quoted($path) length = $length argstr = sprintf("%s, %d", user_string_quoted($path), $length) } probe syscall.truncate.return = kernel.function("sys_truncate").return ?, kernel.function("sys_truncate64").return ? { name = "truncate" retstr = return_str(1, $return) } # tux ________________________________________________________ # long sys_tux (unsigned int action, user_req_t *u_info) # probe syscall.tux = kernel.function("sys_tux").call ? { name = "tux" action = $action u_info_uaddr = $u_info argstr = sprintf("%d, %p", $action, $u_info) } probe syscall.tux.return = kernel.function("sys_tux").return ? { name = "tux" retstr = return_str(1, $return) } # umask ______________________________________________________ # long sys_umask(int mask) # probe syscall.umask = kernel.function("sys_umask").call { name = "umask" mask = $mask argstr = sprintf("%#o", $mask) } probe syscall.umask.return = kernel.function("sys_umask").return { name = "umask" retstr = return_str(3, $return) } # umount _____________________________________________________ # long sys_umount(char __user * name, int flags) # probe syscall.umount = kernel.function("sys_umount").call { name = "umount" target = user_string_quoted($name) flags = $flags flags_str = _umountflags_str($flags) argstr = sprintf("%s, %s", user_string_quoted($name), flags_str) } probe syscall.umount.return = kernel.function("sys_umount").return { name = "umount" retstr = return_str(1, $return) } # uname ______________________________________________________ # # int sys_uname(struct old_utsname __user *name) # long sys_newuname(struct new_utsname __user * name) # int sys_olduname(struct oldold_utsname __user * name) # int sys32_olduname(struct oldold_utsname __user * name) # long sys32_uname(struct old_utsname __user * name) # probe syscall.uname = kernel.function("sys_uname").call ?, kernel.function("sys_olduname").call ?, kernel.function("sys32_olduname").call ?, kernel.function("sys32_uname").call ?, kernel.function("sys_newuname").call ? { name = "uname" argstr = sprintf("%p", $name) } probe syscall.uname.return = kernel.function("sys_uname").return ?, kernel.function("sys_olduname").return ?, kernel.function("sys32_olduname").return ?, kernel.function("sys32_uname").return ?, kernel.function("sys_newuname").return ? { name = "uname" retstr = return_str(1, $return) } # unlink _____________________________________________________ # long sys_unlink(const char __user * pathname) # probe syscall.unlink = kernel.function("sys_unlink").call { name = "unlink" pathname_uaddr = $pathname pathname = user_string_quoted($pathname) argstr = user_string_quoted($pathname) } probe syscall.unlink.return = kernel.function("sys_unlink").return { name = "unlink" retstr = return_str(1, $return) } # unlinkat ___________________________________________________ # new function with 2.6.16 # long sys_unlinkat(int dfd, const char __user *pathname, # int flag) probe syscall.unlinkat = kernel.function("sys_unlinkat").call ? { name = "unlinkat" dfd = $dfd dfd_str = _dfd_str($dfd) pathname = $pathname pathname_str = user_string_quoted($pathname) flag = $flag flag_str = _at_flag_str($flag) argstr = sprintf("%s, %s, %s", dfd_str, user_string_quoted($pathname), flag_str) } probe syscall.unlinkat.return = kernel.function("sys_unlinkat").return ? { name = "unlinkat" retstr = return_str(1, $return) } # unshare ____________________________________________________ # new function with 2.6.16 # long sys_unshare(unsigned long unshare_flags) probe syscall.unshare = kernel.function("sys_unshare").call ? { name = "unshare" unshare_flags = $unshare_flags argstr = __fork_flags(unshare_flags) } probe syscall.unshare.return = kernel.function("sys_unshare").return ? { name = "unshare" retstr = return_str(1, $return) } # uselib _____________________________________________________ # # asmlinkage long # sys_uselib(const char __user * library) # probe syscall.uselib = kernel.function("sys_uselib").call { name = "uselib" library_uaddr = $library library = user_string_quoted($library) argstr = user_string_quoted($library) } probe syscall.uselib.return = kernel.function("sys_uselib").return { name = "uselib" retstr = return_str(1, $return) } # ustat ______________________________________________________ # long sys_ustat(unsigned dev, struct ustat __user * ubuf) # probe syscall.ustat = kernel.function("sys_ustat").call { name = "ustat" dev = $dev ubuf_uaddr = $ubuf argstr = sprintf("%d, %p", $dev, $ubuf) } # long sys32_ustat(unsigned dev, struct ustat32 __user *u32p) # long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u) # probe syscall.ustat32 = kernel.function("compat_sys_ustat").call ?, kernel.function("sys32_ustat").call ? { name = "ustat" dev = $dev ubuf_uaddr = @choose_defined($u, $u32p) argstr = sprintf("%d, %p", $dev, @choose_defined($u, $u32p)) } probe syscall.ustat.return = kernel.function("sys_ustat").return ? { name = "ustat" retstr = return_str(1, $return) } probe syscall.ustat32.return = kernel.function("sys32_ustat").return ?, kernel.function("compat_sys_ustat").return ? { name = "ustat" retstr = return_str(1, $return) } # utime ______________________________________________________ # long sys_utime(char __user * filename, struct utimbuf __user * times) probe syscall.utime = kernel.function("sys_utime").call ? { name = "utime" filename_uaddr = $filename filename = user_string_quoted($filename) buf_uaddr = $times # On s390, '$times' is a long, so the @cast() is needed. actime = user_long(&@cast($times, "utimbuf")->actime) modtime = user_long(&@cast($times, "utimbuf")->modtime) argstr = sprintf("%s, [%s, %s]", user_string_quoted($filename), ctime(actime), ctime(modtime)) } probe syscall.utime.return = kernel.function("sys_utime").return ? { name = "utime" retstr = return_str(1, $return) } # long compat_sys_utime(char __user *filename, struct compat_utimbuf __user *t) probe syscall.compat_utime = kernel.function("compat_sys_utime").call ? { name = "utime" filename_uaddr = $filename filename = user_string_quoted($filename) buf_uaddr = $t actime = user_long(&$t->actime) modtime = user_long(&$t->modtime) argstr = sprintf("%s, [%s, %s]", user_string_quoted($filename), ctime(actime), ctime(modtime)) } probe syscall.compat_utime.return = kernel.function("compat_sys_utime").return ? { name = "utime" retstr = return_str(1, $return) } # utimes _____________________________________________________ # # long sys_utimes(char __user * filename, struct timeval __user * utimes) # probe syscall.utimes = kernel.function("sys_utimes").call { name = "utimes" filename_uaddr = $filename filename = user_string_quoted($filename) tvp_uaddr = $utimes argstr = sprintf("%s, %s", user_string_quoted($filename), _struct_timeval_u($utimes, 2)) } probe syscall.utimes.return = kernel.function("sys_utimes").return { name = "utimes" retstr = return_str(1, $return) } # compat_sys_utimes ________________________________________ # # long compat_sys_utimes(char __user *filename, struct compat_timeval __user *t) # probe syscall.compat_sys_utimes = kernel.function("compat_sys_utimes").call ? { name = "utimes" filename = user_string_quoted($filename) argstr = sprintf("%s, %s", user_string_quoted($filename), _struct_compat_timeval_u($t, 2)) } probe syscall.compat_sys_utimes.return = kernel.function("compat_sys_utimes").return ? { name = "utimes" retstr = return_str(1, $return) } # utimensat ____________________________________________________ # long sys_utimensat(int dfd, char __user *filename, struct timespec __user *utimes, int flags) # long compat_sys_utimensat(unsigned int dfd, char __user *filename, struct compat_timespec __user *t, int flags) # probe syscall.utimensat = kernel.function("sys_utimensat").call ? { name = "utimensat" argstr = sprintf("%s, %s, %s, %s", _dfd_str($dfd), user_string_quoted($filename), _struct_timespec_u($utimes, 2), _at_flag_str($flags)) } probe syscall.compat_utimensat = kernel.function("compat_sys_utimensat").call ? { name = "utimensat" argstr = sprintf("%s, %s, %s, %s", _dfd_str($dfd), user_string_quoted($filename), _struct_compat_timespec_u($t, 2), _at_flag_str($flags)) } probe syscall.utimensat.return = kernel.function("sys_utimensat").return ? { name = "utimensat" retstr = return_str(1, $return) } probe syscall.compat_utimensat.return = kernel.function("compat_sys_utimensat").return ? { name = "utimensat" retstr = return_str(1, $return) } # vhangup ____________________________________________________ # # asmlinkage long # sys_vhangup(void) # probe syscall.vhangup = kernel.function("sys_vhangup").call { name = "vhangup" argstr = "" } probe syscall.vhangup.return = kernel.function("sys_vhangup").return { name = "vhangup" retstr = return_str(1, $return) } # vmsplice ___________________________________________________ # # long sys_vmsplice(int fd, const struct iovec __user *iov, # unsigned long nr_segs, unsigned int flags) # long compat_sys_vmsplice(int fd, const struct compat_iovec __user *iov32, # unsigned int nr_segs, unsigned int flags) # probe syscall.vmsplice = kernel.function("sys_vmsplice").call ? { name = "vmsplice" argstr = sprintf("%d, %p, %d, 0x%x", $fd, $iov, $nr_segs, $flags) } probe syscall.compat_vmsplice = kernel.function("compat_sys_vmsplice").call ? { name = "vmsplice" argstr = sprintf("%d, %p, %d, 0x%x", $fd, $iov32, $nr_segs, $flags) } probe syscall.vmsplice.return = kernel.function("sys_vmsplice").return ? { name = "vmsplice" retstr = return_str(1, $return) } probe syscall.compat_vmsplice.return = kernel.function("compat_sys_vmsplice").return ? { name = "vmsplice" retstr = return_str(1, $return) } # wait4 ______________________________________________________ # # long sys_wait4(pid_t pid, # int __user *stat_addr, # int options, # struct rusage __user *ru) # probe syscall.wait4 = kernel.function("sys_wait4").call { name = "wait4" pid = @choose_defined($upid, $pid) status_uaddr = $stat_addr options = $options & 0xffffffff options_str = _wait4_opt_str(options) rusage_uaddr = $ru argstr = sprintf("%d, %p, %s, %p", @choose_defined($upid, $pid), $stat_addr, options_str, $ru) } probe syscall.wait4.return = kernel.function("sys_wait4").return { name = "wait4" if (returnval () <= 0) status_str = "N/A" else if ($stat_addr == 0) status_str = "NULL" else status_str = _wait_status_str(user_int($stat_addr)) retstr = return_str(1, $return) } # waitid _____________________________________________________ # # long sys_waitid(int which, # pid_t pid, # struct siginfo __user *infop, # int options, # struct rusage __user *ru) # probe syscall.waitid = kernel.function("sys_waitid").call { name = "waitid" pid = @choose_defined($upid, $pid) which = $which which_str = _waitid_which_str($which) infop_uaddr = $infop options = $options options_str = _waitid_opt_str($options) rusage_uaddr = $ru argstr = sprintf("%d, %d, %p, %s, %p", $which, @choose_defined($upid, $pid), $infop, _waitid_opt_str($options), $ru) } probe syscall.waitid.return = kernel.function("sys_waitid").return { name = "waitid" retstr = return_str(1, $return) } /* FIXME: # waitpid ____________________________________________________ # # long sys_wait4(pid_t pid, # int __user *stat_addr, # int options, # struct rusage __user *ru) # probe syscall.waitpid = kernel.function("sys_wait4").call { name = "waitpid" pid = $pid status_uaddr = $stat_addr options = $options & 0xffffffff options_str = _wait4_opt_str(options) rusage_uaddr = $ru argstr = sprintf("%d, %p, %s, %p", $pid, $stat_addr, options_str, $ru) } probe syscall.waitpid.return = kernel.function("sys_wait4").return { name = "waitpid" retstr = return_str(1, $return) } */ # write ______________________________________________________ # # ssize_t sys_write(unsigned int fd, # const char __user * buf, # size_t count) # probe syscall.write = kernel.function("sys_write").call { name = "write" fd = $fd buf_uaddr = $buf count = $count argstr = sprintf("%d, %s, %d", $fd, user_string_n_quoted($buf, syscall_string_trunc), $count) } probe syscall.write.return = kernel.function("sys_write").return { name = "write" retstr = return_str(1, $return) } # writev _____________________________________________________ # # ssize_t sys_writev(unsigned long fd, # const struct iovec __user *vec, # unsigned long vlen) # ssize_t compat_sys_writev(unsigned long fd, # const struct compat_iovec __user *vec, # unsigned long vlen) # probe syscall.writev = kernel.function("compat_sys_writev").call ?, kernel.function("sys_writev").call { name = "writev" vector_uaddr = $vec count = $vlen fd = $fd argstr = sprintf("%d, %p, %d", $fd, $vec, $vlen) } probe syscall.writev.return = kernel.function("compat_sys_writev").return ?, kernel.function("sys_writev").return { name = "writev" retstr = return_str(1, $return) } systemtap-2.3/tapset/linux/syscalls_cfg_trunc.stp000066400000000000000000000001571217430427200224720ustar00rootroot00000000000000 # Default length for string truncation in e.g. read/write syscall arguments. global syscall_string_trunc = 50 systemtap-2.3/tapset/linux/target_set.stp000066400000000000000000000032461217430427200207460ustar00rootroot00000000000000 global _target_set # map: target-set-pid -> ancestor-pid /** * sfunction target_set_pid - Does pid descend from target process? * * @pid: The pid of the process to query * * Description: This function returns whether the given process-id is * within the "target set", that is whether it is a descendant of the * top-level target() process. */ function target_set_pid (pid) { return ([pid] in _target_set) } probe begin { if (target()) _target_set[target()] = stp_pid() } # ia64 systems and pre-2.6.18 systems don't support dwarfless probes, # so we'll use 'syscall' probes instead of 'nd_syscall' probes. probe process.begin!, %( arch != "ia64" && kernel_v >= "2.6.18" %? nd_syscall.fork.return!, %) syscall.fork.return { if (is_return()) { # fork.return runs in parent context pid = @choose_defined($return, returnval()) ppid = pid() } else { # process.begin runs in child context pid = pid() ppid = ppid() } # NB: when using process.*, if target() execs we'll see a process.end # (removing it) then a new process.begin. The target's ppid (stp_pid) # is not part of the target set, so check for this case. if (pid == target() || ppid in _target_set) _target_set[pid] = ppid } probe process.end!, %( arch != "ia64" && kernel_v >= "2.6.18" %? nd_syscall.exit!, %) syscall.exit { delete _target_set[pid()] } /** * sfunction target_set_report - Print a report about the target set * * Description: This function prints a report about the processes in the * target set, and their ancestry. */ function target_set_report () { printf("target set:\n") foreach (pid in _target_set+) printf("%d begat %d\n", _target_set[pid], pid) } systemtap-2.3/tapset/linux/task.stp000066400000000000000000000226101217430427200175430ustar00rootroot00000000000000// task information tapset // Copyright (C) 2006 Intel Corporation. // Copyright (C) 2010 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. %{ #include #include #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) #include #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) #include #endif #ifndef STAPCONF_TASK_UID #include #endif %} /** * sfunction task_current - The current task_struct of the current task * * Description: This function returns the task_struct representing the current process. * This address can be passed to the various task_*() functions to extract * more task-specific data. */ function task_current:long () %{ /* pure */ STAP_RETVALUE = (long)current; %} /** * sfunction task_parent - The task_struct of the parent task * * @task: task_struct pointer * * Description: This function returns the parent task_struct of * the given task. This address can be passed to the various * task_*() functions to extract more task-specific data. */ function task_parent:long(task:long) { return @choose_defined( @cast(task, "task_struct", "kernel")->real_parent, @cast(task, "task_struct", "kernel")->parent) } /** * sfunction task_state - The state of the task * * @task: task_struct pointer * * Description: Return the state of the given task, one of: * TASK_RUNNING (0), TASK_INTERRUPTIBLE (1), TASK_UNINTERRUPTIBLE (2), * TASK_STOPPED (4), TASK_TRACED (8), EXIT_ZOMBIE (16), or EXIT_DEAD (32). */ function task_state:long (task:long) { return @cast(task, "task_struct", "kernel")->state } /** * sfunction task_execname - The name of the task * * @task: task_struct pointer * * Description: Return the name of the given task. */ function task_execname:string (task:long) { return kernel_string(@cast(task, "task_struct", "kernel")->comm) } /** * sfunction task_pid - The process identifier of the task * * @task: task_struct pointer * * Description: This fucntion returns the process id of the given task. */ function task_pid:long (task:long) { return @cast(task, "task_struct", "kernel")->tgid } /** * sfunction pid2task - The task_struct of the given process identifier * * @pid: process identifier * * Description: Return the task struct of the given process id. */ function pid2task:long (pid:long) %{ /* pure */ struct task_struct *t = NULL; pid_t t_pid = (pid_t)(long)STAP_ARG_pid; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) struct pid *p_pid = find_get_pid(t_pid); rcu_read_lock(); t = pid_task(p_pid, PIDTYPE_PID); put_pid(p_pid); #else rcu_read_lock(); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) t = find_task_by_vpid (t_pid); #else t = find_task_by_pid (t_pid); #endif /* 2.6.24 */ #endif /* 2.6.31 */ rcu_read_unlock(); STAP_RETVALUE = (long)t; %} /** * sfunction pid2execname - The name of the given process identifier * * @pid: process identifier * * Description: Return the name of the given process id. */ function pid2execname:string (pid:long) { tsk = pid2task(pid) if (tsk) return task_execname(tsk) return "" } /** * sfunction task_tid - The thread identifier of the task * * @task: task_struct pointer * * Description: This function returns the thread id of the given task. */ function task_tid:long (task:long) { return @cast(task, "task_struct", "kernel")->pid } /** * sfunction task_gid - The group identifier of the task * * @task: task_struct pointer * * Description: This function returns the group id of the given task. */ function task_gid:long (task:long) %{ /* pure */ struct task_struct *t = (struct task_struct *)(long)STAP_ARG_task; #ifdef STAPCONF_TASK_UID STAP_RETVALUE = kread(&(t->gid)); CATCH_DEREF_FAULT(); #else /* If task_gid() isn't defined, make our own. */ #if !defined(task_gid) && defined(task_cred_xxx) #define task_gid(task) (task_cred_xxx((task), gid)) #endif /* XXX: We can't easily kread this rcu-protected field. */ STAP_RETVALUE = task_gid (t); #endif %} /** * sfunction task_egid - The effective group identifier of the task * * @task: task_struct pointer * * Description: This function returns the effective group id of the given task. */ function task_egid:long (task:long) %{ /* pure */ struct task_struct *t = (struct task_struct *)(long)STAP_ARG_task; #ifdef STAPCONF_TASK_UID STAP_RETVALUE = kread(&(t->egid)); CATCH_DEREF_FAULT(); #else /* If task_egid() isn't defined, make our own. */ #if !defined(task_egid) && defined(task_cred_xxx) #define task_egid(task) (task_cred_xxx((task), egid)) #endif /* XXX: We can't easily kread this rcu-protected field. */ STAP_RETVALUE = task_egid (t); #endif %} /** * sfunction task_uid - The user identifier of the task * * @task: task_struct pointer * * Description: This function returns the user id of the given task. */ function task_uid:long (task:long) %{ /* pure */ struct task_struct *t = (struct task_struct *)(long)STAP_ARG_task; #ifdef STAPCONF_TASK_UID STAP_RETVALUE = kread(&(t->uid)); CATCH_DEREF_FAULT(); #else /* XXX: We can't easily kread this rcu-protected field. */ STAP_RETVALUE = task_uid (t); #endif %} /** * sfunction task_euid - The effective user identifier of the task * * @task: task_struct pointer * * Description: This function returns the effective user id of the given task. */ function task_euid:long (task:long) %{ /* pure */ struct task_struct *t = (struct task_struct *)(long)STAP_ARG_task; #ifdef STAPCONF_TASK_UID STAP_RETVALUE = kread(&(t->euid)); CATCH_DEREF_FAULT(); #else /* XXX: We can't easily kread this rcu-protected field. */ STAP_RETVALUE = task_euid (t); #endif %} /** * sfunction task_prio - The priority value of the task * * @task: task_struct pointer * * Description: This function returns the priority value of the given task. */ function task_prio:long (task:long) %{ /* pure */ struct task_struct *t = (struct task_struct *)(long)STAP_ARG_task; STAP_RETVALUE = kread(&(t->prio)) - MAX_RT_PRIO; CATCH_DEREF_FAULT(); %} /** * sfunction task_nice - The nice value of the task * * @task: task_struct pointer * * Description: This function returns the nice value of the given task. */ function task_nice:long (task:long) %{ /* pure */ struct task_struct *t = (struct task_struct *)(long)STAP_ARG_task; STAP_RETVALUE = kread(&(t->static_prio)) - MAX_RT_PRIO - 20; CATCH_DEREF_FAULT(); %} /** * sfunction task_cpu - The scheduled cpu of the task * * @task: task_struct pointer * * Description: This function returns the scheduled cpu for the given task. */ function task_cpu:long (task:long) { ti = @choose_defined(@cast(task, "task_struct", "kernel")->stack, @cast(task, "task_struct", "kernel")->thread_info); return @cast(ti, "thread_info", "kernel")->cpu } /** * sfunction task_open_file_handles - The number of open files of the task * * @task: task_struct pointer * * Description: This function returns the number of open file handlers for the given task. */ function task_open_file_handles:long (task:long) %( kernel_v >= "2.6.15" %? %{ /* pure */ int locked = 0; unsigned int count=0, fd, max; struct task_struct *t; struct files_struct *fs; struct fdtable *f; t = (struct task_struct *)(long)STAP_ARG_task; fs = kread(&(t->files)); f = kread(&(fs->fdt)); rcu_read_lock(); locked = 1; max = kread(&(f->max_fds)); for (fd = 0; fd < max; fd++) { if ( kread(&(f->fd[fd])) != NULL) count ++; } STAP_RETVALUE = count; CATCH_DEREF_FAULT(); if (locked) rcu_read_unlock(); %} %: %{ /* pure */ int locked = 0; unsigned int count=0, fd, max; struct task_struct *t; struct files_struct *f; t = (struct task_struct *)(long)STAP_ARG_task; f = kread(&(t->files)); rcu_read_lock(); locked = 1; max = kread(&(f->max_fds)); for (fd = 0; fd < max; fd++) { if ( kread(&(f->fd[fd])) != NULL) count ++; } STAP_RETVALUE = count; CATCH_DEREF_FAULT(); if (locked) rcu_read_unlock(); %} %) /** * sfunction task_max_file_handles - The max number of open files for the task * * @task: task_struct pointer * * Description: This function returns the maximum number of file handlers for the given task. */ function task_max_file_handles:long (task:long) %( kernel_v >= "2.6.15" %? %{ /* pure */ int locked = 0; struct task_struct *t; struct files_struct *fs; struct fdtable *f; t = (struct task_struct *)(long)STAP_ARG_task; fs = kread (&(t->files)); f = kread(&(fs->fdt)); rcu_read_lock(); locked = 1; STAP_RETVALUE = kread(&(f->max_fds)); CATCH_DEREF_FAULT(); if (locked) rcu_read_unlock(); %} %: %{ /* pure */ int locked = 0; struct task_struct *t; struct files_struct *f; t = (struct task_struct *)(long)STAP_ARG_task; f = kread(&(t->files)); rcu_read_lock(); locked = 1; STAP_RETVALUE = kread(&(f->max_fds)); CATCH_DEREF_FAULT(); if (locked) rcu_read_unlock(); %} %) systemtap-2.3/tapset/linux/task_time.stp000066400000000000000000000145071217430427200205670ustar00rootroot00000000000000// Task time query and utility functions. // Copyright (C) 2009, 2010 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // Task time query and utility functions provide information about // the time resource usage of the current task. These functions provide // information about the user time and system time of the current // task. And provide utility functions to turn the reported times // into miliseconds and create human readable string representations // of task time used. The reported times are approximates and should // be used for "coarse grained" measurements only. The reported user // and system time are only for the current task, not for the process // as a whole nor of any time spend by children of the current task. // %{ #include /* includes asm/cputime.h */ #include /* Kernels since 2.6.37 generally have cputime_to_usecs, but not msecs. * (ref: kernel commit d57af9b2142f31a39dcfdeb30776baadfc802827) * Yet note some kernels (RHEL6) may already have both... */ #if defined(cputime_to_usecs) #if !defined(cputime_to_msecs) #define cputime_to_msecs(__ct) _stp_div64(NULL, cputime_to_usecs(__ct), 1000ULL) #endif /* Kernels before 2.6.37 have cputime_to_msecs, but not usecs. */ #elif defined(cputime_to_msecs) #define cputime_to_usecs(__ct) (cputime_to_msecs(__ct) * 1000ULL) /* RHEL4 (2.6.9) kernels have neither, but it's just jiffies anyway. */ #else #define cputime_to_msecs(__ct) jiffies_to_msecs(__ct) #define cputime_to_usecs(__ct) jiffies_to_usecs(__ct) #endif %} /** * sfunction task_utime - User time of the current task * * Description: Returns the user time of the current task in cputime. * Does not include any time used by other tasks in this process, nor * does it include any time of the children of this task. */ function task_utime:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = current->utime; %} /** * sfunction task_utime_tid - User time of the given task * * @tid: Thread id of the given task * * Description: Returns the user time of the given task in cputime, * or zero if the task doesn't exist. * Does not include any time used by other tasks in this process, nor * does it include any time of the children of this task. */ function task_utime_tid:long(tid:long) { task = pid2task(tid); if (task != 0) return @cast(task, "task_struct", "kernel")->utime; else return 0; } /** * sfunction task_stime - System time of the current task * * Description: Returns the system time of the current task in cputime. * Does not include any time used by other tasks in this process, nor * does it include any time of the children of this task. */ function task_stime:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = current->stime; %} /** * sfunction task_stime_tid - System time of the given task * * @tid: Thread id of the given task * * Description: Returns the system time of the given task in cputime, * or zero if the task doesn't exist. * Does not include any time used by other tasks in this process, nor * does it include any time of the children of this task. */ function task_stime_tid:long(tid:long) { task = pid2task(tid); if (task != 0) return @cast(task, "task_struct", "kernel")->stime; else return 0; } /** * sfunction cputime_to_msecs - Translates the given cputime into milliseconds * @cputime: Time to convert to milliseconds. */ function cputime_to_msecs:long (cputime:long) %{ /* pure */ /* unprivileged */ STAP_RETVALUE = cputime_to_msecs (STAP_ARG_cputime); %} /** * sfunction cputime_to_usecs - Translates the given cputime into microseconds * @cputime: Time to convert to microseconds. */ function cputime_to_usecs:long (cputime:long) %{ /* pure */ /* unprivileged */ STAP_RETVALUE = cputime_to_usecs (STAP_ARG_cputime); %} /** * sfunction msecs_to_string - Human readable string for given milliseconds * * @msecs: Number of milliseconds to translate. * * Description: Returns a string representing the number of * milliseconds as a human readable string consisting of "XmY.ZZZs", * where X is the number of minutes, Y is the number of seconds and * ZZZ is the number of milliseconds. */ function msecs_to_string:string (msecs:long) { ms = msecs % 1000; secs = msecs / 1000; mins = secs / 60; secs = secs % 60; return sprintf("%dm%d.%.3ds", mins, secs, ms); } /** * sfunction usecs_to_string - Human readable string for given microseconds * * @usecs: Number of microseconds to translate. * * Description: Returns a string representing the number of * milliseconds as a human readable string consisting of "XmY.ZZZZZZs", * where X is the number of minutes, Y is the number of seconds and * ZZZZZZ is the number of microseconds. */ function usecs_to_string:string (usecs:long) { us = usecs % 1000000; secs = usecs / 1000000; mins = secs / 60; secs = secs % 60; return sprintf("%dm%d.%.6ds", mins, secs, us); } /** * sfunction cputime_to_string - Human readable string for given cputime * * @cputime: Time to translate. * * Description: Equivalent to calling: * msec_to_string (cputime_to_msecs (cputime). */ function cputime_to_string:string (cputime:long) { return msecs_to_string (cputime_to_msecs (cputime)); } /** * sfunction task_time_string - Human readable string of task time usage * * Description: Returns a human readable string showing the user and * system time the current task has used up to now. For example * "usr: 0m12.908s, sys: 1m6.851s". */ function task_time_string:string () { return sprintf ("usr: %s, sys: %s", cputime_to_string (task_utime()), cputime_to_string (task_stime())); } /** * sfunction task_time_string_tid - Human readable string of task time usage * * @tid: Thread id of the given task * * Description: Returns a human readable string showing the user and * system time the given task has used up to now. For example * "usr: 0m12.908s, sys: 1m6.851s". */ function task_time_string_tid:string (tid:long) { return sprintf ("usr: %s, sys: %s", cputime_to_string (task_utime_tid(tid)), cputime_to_string (task_stime_tid(tid))); } systemtap-2.3/tapset/linux/tcp.stp000066400000000000000000000544621217430427200174010ustar00rootroot00000000000000// TCP tapset // Copyright (C) 2006 IBM Corp. // Copyright (C) 2006 Intel Corporation. // Copyright (C) 2007, 2010, 2012 Red Hat, Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // This family of probe points is used to probe events that occur in the TCP layer, // %{ #include #include #include #include #include %} // Get retransmission timeout in usecs. RTO is initialized from default // retransmission time, but can be adjusted (increased) each time we // retransmit. It should always be less than the max value of TCP retransmission // timeout (TCP_RTO_MAX) function tcp_get_info_rto:long(sock:long) %{ /* pure */ struct sock *sk = (struct sock *)(long) STAP_ARG_sock; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) struct tcp_opt *tp = tcp_sk(sk); STAP_RETVALUE = (int64_t) jiffies_to_usecs(kread(&(tp->rto))); #else const struct inet_connection_sock *icsk = inet_csk(sk); STAP_RETVALUE = (int64_t) jiffies_to_usecs(kread(&(icsk->icsk_rto))); #endif CATCH_DEREF_FAULT(); %} //Get congestion window segment size. Initial value of congestion window size //typically set to one segment (i.e., slow start algorithm, each segment can be 512 bytes). //This congestion window size can be dynamically increased based on whether TCP //is performing slow start or congestion avoidance. function tcp_get_info_snd_cwnd:long(sock:long) %{ /* pure */ struct sock *sk = (struct sock *)(long) STAP_ARG_sock; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) struct tcp_opt *tp = tcp_sk(sk); #else struct tcp_sock *tp = tcp_sk(sk); #endif STAP_RETVALUE = (int64_t) kread(&(tp->snd_cwnd)); CATCH_DEREF_FAULT(); %} // //Definitions of the TCP protocol sk_state field listed below. // // TCP_ESTABLISHED = 1, Normal data transfer // TCP_SYN_SENT = 2, App. has started to open a connection // TCP_SYN_RECV = 3, A connection request has arrived; wait for ACK // TCP_FIN_WAIT1 = 4, App. has said it is finished // TCP_FIN_WAIT2 = 5, The other side has agreed to close // TCP_TIME_WAIT = 6, Wait for all packets to die off // TCP_CLOSE = 7, No connection is active or pending // TCP_CLOSE_WAIT = 8, The other side has initiated a release // TCP_LAST_ACK = 9, Last ACK, wait for all packets to die off // TCP_LISTEN = 10, Waiting for incoming call // TCP_CLOSING = 11, Both sides have tried to close simultaneously // TCP_MAX_STATES = 12 Max states number // function tcp_ts_get_info_state:long(sock:long) %{ /* pure */ struct sock *sk = (struct sock *)(long) STAP_ARG_sock; STAP_RETVALUE = (int64_t) kread(&(sk->sk_state)); CATCH_DEREF_FAULT(); %} /* return the TCP destination port for a given sock */ function __tcp_sock_dport:long (sock:long) { port = @choose_defined(@cast(sock, "inet_sock", "kernel")->sk->__sk_common->skc_dport, # kernel >= 3.8 @choose_defined(@cast(sock, "inet_sock")->inet_dport, # kernel >= 2.6.33 @choose_defined(@cast(sock, "inet_sock", "kernel")->dport, # kernel >= 2.6.11 @cast(sock, "inet_sock", "kernel")->inet->dport))) return ntohs(port) } /* returns the TCP header for recent (<2.6.21) kernel */ function __get_skb_tcphdr_new:long(skb:long) %{ /* pure */ struct sk_buff *skb; skb = (struct sk_buff *)(long)STAP_ARG_skb; /* as done by skb_transport_header() */ #ifdef NET_SKBUFF_DATA_USES_OFFSET STAP_RETVALUE = (long)(kread(&(skb->head)) + kread(&(skb->transport_header))); #else STAP_RETVALUE = (long)kread(&(skb->transport_header)); #endif CATCH_DEREF_FAULT(); %} /* returns the TCP header for a given sk_buff structure */ function __get_skb_tcphdr:long(skb:long) { %( kernel_v < "2.6.21" %? tcphdr = @cast(skb, "sk_buff")->h->raw return tcphdr %: return __get_skb_tcphdr_new(skb) %) } /* returns TCP URG flag for a given sk_buff structure */ function __tcp_skb_urg:long (tcphdr:long) { return @cast(tcphdr, "tcphdr")->urg } /* returns TCP ACK flag for a given sk_buff structure */ function __tcp_skb_ack:long (tcphdr:long) { return @cast(tcphdr, "tcphdr")->ack } /* returns TCP PSH flag for a given sk_buff structure */ function __tcp_skb_psh:long (tcphdr:long) { return @cast(tcphdr, "tcphdr")->psh } /* returns TCP RST flag for a given sk_buff structure */ function __tcp_skb_rst:long (tcphdr:long) { return @cast(tcphdr, "tcphdr")->rst } /* returns TCP SYN flag for a given sk_buff structure */ function __tcp_skb_syn:long (tcphdr:long) { return @cast(tcphdr, "tcphdr")->syn } /* returns TCP FIN flag for a given sk_buff structure */ function __tcp_skb_fin:long (tcphdr:long) { return @cast(tcphdr, "tcphdr")->fin } /* returns TCP source port for a given sk_buff structure */ function __tcp_skb_sport:long (tcphdr:long) { return ntohs(@cast(tcphdr, "tcphdr")->source) } /* returns TCP destination port for a given sk_buff structure */ function __tcp_skb_dport:long (tcphdr:long){ return ntohs(@cast(tcphdr, "tcphdr")->dest) } /* return the TCP source port for a given sock */ function __tcp_sock_sport:long (sock:long) { port = @choose_defined(@cast(sock, "inet_sock")->inet_sport, # kernel >= 2.6.33 @choose_defined(@cast(sock, "inet_sock", "kernel")->sport, # kernel >= 2.6.11 @cast(sock, "inet_sock", "kernel")->inet->sport)) return ntohs(port) } global sockstate[13], sockstate_init_p function tcp_sockstate_str:string (state:long) { if (! sockstate_init_p) { sockstate_init_p = 1 sockstate[1] = "TCP_ESTABLISHED" sockstate[2] = "TCP_SYN_SENT" sockstate[3] = "TCP_SYN_RECV" sockstate[4] = "TCP_FIN_WAIT1" sockstate[5] = "TCP_FIN_WAIT2" sockstate[6] = "TCP_TIME_WAIT" sockstate[7] = "TCP_CLOSE" sockstate[8] = "TCP_CLOSE_WAIT" sockstate[9] = "TCP_LAST_ACK" sockstate[10] = "TCP_LISTEN" sockstate[11] = "TCP_CLOSING" sockstate[12] = "TCP_MAX_STATES" } return (state in sockstate ? sockstate[state] : "UNDEF") } // Get slow start threshold size. If cwnd size is less than or equal to // threshold size, then TCP is in slow start; otherwise TCP is in congestion // avoidance. function tcp_ts_get_info_snd_ssthresh:long(sock:long) %{ /* pure */ struct sock *sk = (struct sock *)(long) STAP_ARG_sock; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) struct tcp_opt *tp = tcp_sk(sk); #else struct tcp_sock *tp = tcp_sk(sk); #endif STAP_RETVALUE = (int64_t) kread(&(tp->snd_ssthresh)); CATCH_DEREF_FAULT(); %} // Get receiver's advertised segment size. TCP typically never sends more // than what receiver can accept. function tcp_ts_get_info_rcv_mss:long(sock:long) %{ /* pure */ struct sock *sk = (struct sock *)(long) STAP_ARG_sock; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) struct tcp_opt *tp = tcp_sk(sk); STAP_RETVALUE = (int64_t) kread(&(tp->ack.rcv_mss)); #else const struct inet_connection_sock *icsk = inet_csk(sk); STAP_RETVALUE = (int64_t) kread(&(icsk->icsk_ack.rcv_mss)); #endif CATCH_DEREF_FAULT(); %} %{ // Define newer IPv4 sockopt constants for older kernels. #ifndef TCP_CONGESTION #define TCP_CONGESTION 0 #endif #ifndef TCP_MD5SIG #define TCP_MD5SIG 0 #endif #ifndef TCP_COOKIE_TRANSACTIONS #define TCP_COOKIE_TRANSACTIONS 0 #endif #ifndef TCP_THIN_LINEAR_TIMEOUTS #define TCP_THIN_LINEAR_TIMEOUTS 0 #endif #ifndef TCP_THIN_DUPACK #define TCP_THIN_DUPACK 0 #endif #ifndef TCP_USER_TIMEOUT #define TCP_USER_TIMEOUT 0 #endif %} global __sockopt, __sockopt_init_p function tcp_sockopt_str:string (optname:long) { if (!__sockopt_init_p) { __sockopt_init_p = 1 __sockopt[%{/* pure */TCP_NODELAY%}] = "TCP_NODELAY" __sockopt[%{/* pure */TCP_MAXSEG%}] = "TCP_MAXSEG" __sockopt[%{/* pure */TCP_CORK%}] = "TCP_CORK" __sockopt[%{/* pure */TCP_KEEPIDLE%}] = "TCP_KEEPIDLE" __sockopt[%{/* pure */TCP_KEEPINTVL%}] = "TCP_KEEPINTVL" __sockopt[%{/* pure */TCP_KEEPCNT%}] = "TCP_KEEPCNT" __sockopt[%{/* pure */TCP_SYNCNT%}] = "TCP_SYNCNT" __sockopt[%{/* pure */TCP_LINGER2%}] = "TCP_LINGER2" __sockopt[%{/* pure */TCP_DEFER_ACCEPT%}] = "TCP_DEFER_ACCEPT" __sockopt[%{/* pure */TCP_WINDOW_CLAMP%}] = "TCP_WINDOW_CLAMP" __sockopt[%{/* pure */TCP_INFO%}] = "TCP_INFO" __sockopt[%{/* pure */TCP_QUICKACK%}] = "TCP_QUICKACK" if (%{/* pure */TCP_CONGESTION%} > 0) __sockopt[%{/* pure */TCP_CONGESTION%}] = "TCP_CONGESTION" if (%{/* pure */TCP_MD5SIG%} > 0) __sockopt[%{/* pure */TCP_MD5SIG%}] = "TCP_MD5SIG" if (%{/* pure */TCP_COOKIE_TRANSACTIONS%} > 0) __sockopt[%{/* pure */TCP_COOKIE_TRANSACTIONS%}] = "TCP_COOKIE_TRANSACTIONS" if (%{/* pure */TCP_THIN_LINEAR_TIMEOUTS%} > 0) __sockopt[%{/* pure */TCP_THIN_LINEAR_TIMEOUTS%}] = "TCP_THIN_LINEAR_TIMEOUTS" if (%{/* pure */TCP_THIN_DUPACK%} > 0) __sockopt[%{/* pure */TCP_THIN_DUPACK%}] = "TCP_THIN_DUPACK" if (%{/* pure */TCP_USER_TIMEOUT%} > 0) __sockopt[%{/* pure */TCP_USER_TIMEOUT%}] = "TCP_USER_TIMEOUT" } return (optname in __sockopt ? __sockopt[optname] : sprintf("UNDEF_SOCKOPT(%d)", optname)) } %{ // Define newer IPv6 sockopt constants for older kernels. #include #ifndef IPV6_2292PKTINFO #define IPV6_2292PKTINFO 0 #endif #ifndef IPV6_2292HOPOPTS #define IPV6_2292HOPOPTS 0 #endif #ifndef IPV6_2292DSTOPTS #define IPV6_2292DSTOPTS 0 #endif #ifndef IPV6_2292RTHDR #define IPV6_2292RTHDR 0 #endif #ifndef IPV6_2292PKTOPTIONS #define IPV6_2292PKTOPTIONS 0 #endif #ifndef IPV6_2292HOPLIMIT #define IPV6_2292HOPLIMIT 0 #endif #ifndef IPV6_RECVPKTINFO #define IPV6_RECVPKTINFO 0 #endif #ifndef IPV6_RECVHOPLIMIT #define IPV6_RECVHOPLIMIT 0 #endif #ifndef IPV6_RECVHOPOPTS #define IPV6_RECVHOPOPTS 0 #endif #ifndef IPV6_RTHDRDSTOPTS #define IPV6_RTHDRDSTOPTS 0 #endif #ifndef IPV6_RECVRTHDR #define IPV6_RECVRTHDR 0 #endif #ifndef IPV6_RECVDSTOPTS #define IPV6_RECVDSTOPTS 0 #endif #ifndef IPV6_RECVPATHMTU #define IPV6_RECVPATHMTU 0 #endif #ifndef IPV6_PATHMTU #define IPV6_PATHMTU 0 #endif #ifndef IPV6_DONTFRAG #define IPV6_DONTFRAG 0 #endif #ifndef IPV6_ADDR_PREFERENCES #define IPV6_ADDR_PREFERENCES 0 #endif #ifndef IPV6_MINHOPCOUNT #define IPV6_MINHOPCOUNT 0 #endif #ifndef IPV6_RECVORIGDSTADDR #define IPV6_RECVORIGDSTADDR 0 #endif #ifndef IPV6_TRANSPARENT #define IPV6_TRANSPARENT 0 #endif %} global __ipv6_sockopt, __ipv6_sockopt_init_p function tcp_ipv6_sockopt_str:string (optname:long) { if (!__ipv6_sockopt_init_p) { __ipv6_sockopt_init_p = 1 __ipv6_sockopt[%{/* pure */IPV6_ADDRFORM%}] = "IPV6_ADDRFORM" if (%{/* pure */IPV6_2292PKTINFO%} > 0) __ipv6_sockopt[%{/* pure */IPV6_2292PKTINFO%}] = "IPV6_2292PKTINFO" if (%{/* pure */IPV6_2292HOPOPTS%} > 0) __ipv6_sockopt[%{/* pure */IPV6_2292HOPOPTS%}] = "IPV6_2292HOPOPTS" if (%{/* pure */IPV6_2292DSTOPTS%} > 0) __ipv6_sockopt[%{/* pure */IPV6_2292DSTOPTS%}] = "IPV6_2292DSTOPTS" if (%{/* pure */IPV6_2292RTHDR%} > 0) __ipv6_sockopt[%{/* pure */IPV6_2292RTHDR%}] = "IPV6_2292RTHDR" if (%{/* pure */IPV6_2292PKTOPTIONS%} > 0) __ipv6_sockopt[%{/* pure */IPV6_2292PKTOPTIONS%}] = "IPV6_2292PKTOPTIONS" __ipv6_sockopt[%{/* pure */IPV6_CHECKSUM%}] = "IPV6_CHECKSUM" if (%{/* pure */IPV6_2292HOPLIMIT%} > 0) __ipv6_sockopt[%{/* pure */IPV6_2292HOPLIMIT%}] = "IPV6_2292HOPLIMIT" __ipv6_sockopt[%{/* pure */IPV6_NEXTHOP%}] = "IPV6_NEXTHOP" __ipv6_sockopt[%{/* pure */IPV6_AUTHHDR%}] = "IPV6_AUTHHDR" __ipv6_sockopt[%{/* pure */IPV6_FLOWINFO%}] = "IPV6_FLOWINFO" __ipv6_sockopt[%{/* pure */IPV6_UNICAST_HOPS%}] = "IPV6_UNICAST_HOPS" __ipv6_sockopt[%{/* pure */IPV6_MULTICAST_IF%}] = "IPV6_MULTICAST_IF" __ipv6_sockopt[%{/* pure */IPV6_MULTICAST_HOPS%}] = "IPV6_MULTICAST_HOPS" __ipv6_sockopt[%{/* pure */IPV6_MULTICAST_LOOP%}] = "IPV6_MULTICAST_LOOP" __ipv6_sockopt[%{/* pure */IPV6_ADD_MEMBERSHIP%}] = "IPV6_ADD_MEMBERSHIP" __ipv6_sockopt[%{/* pure */IPV6_DROP_MEMBERSHIP%}] = "IPV6_DROP_MEMBERSHIP" __ipv6_sockopt[%{/* pure */IPV6_ROUTER_ALERT%}] = "IPV6_ROUTER_ALERT" __ipv6_sockopt[%{/* pure */IPV6_MTU_DISCOVER%}] = "IPV6_MTU_DISCOVER" __ipv6_sockopt[%{/* pure */IPV6_MTU%}] = "IPV6_MTU" __ipv6_sockopt[%{/* pure */IPV6_RECVERR%}] = "IPV6_RECVERR" __ipv6_sockopt[%{/* pure */IPV6_V6ONLY%}] = "IPV6_V6ONLY" __ipv6_sockopt[%{/* pure */IPV6_JOIN_ANYCAST%}] = "IPV6_JOIN_ANYCAST" __ipv6_sockopt[%{/* pure */IPV6_LEAVE_ANYCAST%}] = "IPV6_LEAVE_ANYCAST" __ipv6_sockopt[%{/* pure */IPV6_FLOWLABEL_MGR%}] = "IPV6_FLOWLABEL_MGR" __ipv6_sockopt[%{/* pure */IPV6_FLOWINFO_SEND%}] = "IPV6_FLOWINFO_SEND" __ipv6_sockopt[%{/* pure */IPV6_IPSEC_POLICY%}] = "IPV6_IPSEC_POLICY" __ipv6_sockopt[%{/* pure */IPV6_XFRM_POLICY%}] = "IPV6_XFRM_POLICY" __ipv6_sockopt[%{/* pure */MCAST_JOIN_GROUP%}] = "MCAST_JOIN_GROUP" __ipv6_sockopt[%{/* pure */MCAST_BLOCK_SOURCE%}] = "MCAST_BLOCK_SOURCE" __ipv6_sockopt[%{/* pure */MCAST_UNBLOCK_SOURCE%}] = "MCAST_UNBLOCK_SOURCE" __ipv6_sockopt[%{/* pure */MCAST_LEAVE_GROUP%}] = "MCAST_LEAVE_GROUP" __ipv6_sockopt[%{/* pure */MCAST_JOIN_SOURCE_GROUP%}] = "MCAST_JOIN_SOURCE_GROUP" __ipv6_sockopt[%{/* pure */MCAST_LEAVE_SOURCE_GROUP%}] = "MCAST_LEAVE_SOURCE_GROUP" __ipv6_sockopt[%{/* pure */MCAST_MSFILTER%}] = "MCAST_MSFILTER" if (%{/* pure */IPV6_RECVPKTINFO%} > 0) __ipv6_sockopt[%{/* pure */IPV6_RECVPKTINFO%}] = "IPV6_RECVPKTINFO" __ipv6_sockopt[%{/* pure */IPV6_PKTINFO%}] = "IPV6_PKTINFO" if (%{/* pure */IPV6_RECVHOPLIMIT%} > 0) __ipv6_sockopt[%{/* pure */IPV6_RECVHOPLIMIT%}] = "IPV6_RECVHOPLIMIT" __ipv6_sockopt[%{/* pure */IPV6_HOPLIMIT%}] = "IPV6_HOPLIMIT" if (%{/* pure */IPV6_RECVHOPOPTS%} > 0) __ipv6_sockopt[%{/* pure */IPV6_RECVHOPOPTS%}] = "IPV6_RECVHOPOPTS" __ipv6_sockopt[%{/* pure */IPV6_HOPOPTS%}] = "IPV6_HOPOPTS" if (%{/* pure */IPV6_RTHDRDSTOPTS%} > 0) __ipv6_sockopt[%{/* pure */IPV6_RTHDRDSTOPTS%}] = "IPV6_RTHDRDSTOPTS" if (%{/* pure */IPV6_RECVRTHDR%} > 0) __ipv6_sockopt[%{/* pure */IPV6_RECVRTHDR%}] = "IPV6_RECVRTHDR" __ipv6_sockopt[%{/* pure */IPV6_RTHDR%}] = "IPV6_RTHDR" if (%{/* pure */IPV6_RECVDSTOPTS%} > 0) __ipv6_sockopt[%{/* pure */IPV6_RECVDSTOPTS%}] = "IPV6_RECVDSTOPTS" __ipv6_sockopt[%{/* pure */IPV6_DSTOPTS%}] = "IPV6_DSTOPTS" if (%{/* pure */IPV6_RECVPATHMTU%} > 0) __ipv6_sockopt[%{/* pure */IPV6_RECVPATHMTU%}] = "IPV6_RECVPATHMTU" if (%{/* pure */IPV6_PATHMTU%} > 0) __ipv6_sockopt[%{/* pure */IPV6_PATHMTU%}] = "IPV6_PATHMTU" if (%{/* pure */IPV6_DONTFRAG%} > 0) __ipv6_sockopt[%{/* pure */IPV6_DONTFRAG%}] = "IPV6_DONTFRAG" __ipv6_sockopt[%{/* pure */IPV6_RECVTCLASS%}] = "IPV6_RECVTCLASS" __ipv6_sockopt[%{/* pure */IPV6_TCLASS%}] = "IPV6_TCLASS" if (%{/* pure */IPV6_ADDR_PREFERENCES%} > 0) __ipv6_sockopt[%{/* pure */IPV6_ADDR_PREFERENCES%}] = "IPV6_ADDR_PREFERENCES" if (%{/* pure */IPV6_MINHOPCOUNT%} > 0) __ipv6_sockopt[%{/* pure */IPV6_MINHOPCOUNT%}] = "IPV6_MINHOPCOUNT" if (%{/* pure */IPV6_RECVORIGDSTADDR%} > 0) __ipv6_sockopt[%{/* pure */IPV6_RECVORIGDSTADDR%}] = "IPV6_RECVORIGDSTADDR" if (%{/* pure */IPV6_TRANSPARENT%} > 0) __ipv6_sockopt[%{/* pure */IPV6_TRANSPARENT%}] = "IPV6_TRANSPARENT" } return (optname in __ipv6_sockopt ? __ipv6_sockopt[optname] : sprintf("UNDEF_SOCKOPT(%d)", optname)) } /** * probe tcp.sendmsg - Sending a tcp message * @name: Name of this probe * @sock: Network socket * @family: IP address family * @size: Number of bytes to send * * Context: * The process which sends a tcp message */ probe tcp.sendmsg = kernel.function("tcp_sendmsg") { name = "tcp.sendmsg" sock = (@defined($sock) ? $sock->sk : $sk) family = __ip_sock_family(@defined($sock) ? $sock->sk : $sk) size = $size } /** * probe tcp.sendmsg.return - Sending TCP message is done * @name: Name of this probe * @size: Number of bytes sent or error code if an error occurred. * * Context: * The process which sends a tcp message */ probe tcp.sendmsg.return = kernel.function("tcp_sendmsg").return { name = "tcp.sendmsg" size = $return } /** * probe tcp.recvmsg - Receiving TCP message * @name: Name of this probe * @sock: Network socket * @size: Number of bytes to be received * @family: IP address family * @saddr: A string representing the source IP address * @daddr: A string representing the destination IP address * @sport: TCP source port * @dport: TCP destination port * Context: * The process which receives a tcp message */ probe tcp.recvmsg = kernel.function("tcp_recvmsg") { name = "tcp.recvmsg" sock = $sk size = $len family = __ip_sock_family($sk) saddr = format_ipaddr(__ip_sock_saddr($sk), __ip_sock_family($sk)) daddr = format_ipaddr(__ip_sock_daddr($sk), __ip_sock_family($sk)) sport = __tcp_sock_sport($sk) dport = __tcp_sock_dport($sk) } /** * probe tcp.recvmsg.return - Receiving TCP message complete * @name: Name of this probe * @size: Number of bytes received or error code if an error occurred. * @family: IP address family * @saddr: A string representing the source IP address * @daddr: A string representing the destination IP address * @sport: TCP source port * @dport: TCP destination port * * Context: * The process which receives a tcp message */ probe tcp.recvmsg.return = kernel.function("tcp_recvmsg").return { name = "tcp.recvmsg" size = $return family = __ip_sock_family($sk) saddr = format_ipaddr(__ip_sock_saddr($sk), __ip_sock_family($sk)) daddr = format_ipaddr(__ip_sock_daddr($sk), __ip_sock_family($sk)) sport = __tcp_sock_sport($sk) dport = __tcp_sock_dport($sk) } /** * probe tcp.disconnect - TCP socket disconnection * @name: Name of this probe * @sock: Network socket * @family: IP address family * @flags: TCP flags (e.g. FIN, etc) * @saddr: A string representing the source IP address * @daddr: A string representing the destination IP address * @sport: TCP source port * @dport: TCP destination port * * Context: * The process which disconnects tcp */ probe tcp.disconnect = kernel.function("tcp_disconnect") { name = "tcp.disconnect" sock = $sk family = __ip_sock_family($sk) flags = $flags saddr = format_ipaddr(__ip_sock_saddr($sk), __ip_sock_family($sk)) daddr = format_ipaddr(__ip_sock_daddr($sk), __ip_sock_family($sk)) sport = __tcp_sock_sport($sk) dport = __tcp_sock_dport($sk) } /** * probe tcp.disconnect.return - TCP socket disconnection complete * @name: Name of this probe * @ret: Error code (0: no error) * * Context: * The process which disconnects tcp */ probe tcp.disconnect.return = kernel.function("tcp_disconnect").return { name = "tcp.disconnect" ret = $return } /** * probe tcp.setsockopt - Call to setsockopt() * @name: Name of this probe * @sock: Network socket * @family: IP address family * @level: The level at which the socket options will be manipulated * @optname: TCP socket options (e.g. TCP_NODELAY, TCP_MAXSEG, etc) * @optstr: Resolves optname to a human-readable format * @optlen: Used to access values for setsockopt() * * Context: * The process which calls setsockopt */ probe tcp.setsockopt = tcp.ipv4.setsockopt, tcp.ipv6.setsockopt { } probe tcp.ipv4.setsockopt = kernel.function("tcp_setsockopt") { name = "tcp.ipv4.setsockopt" sock = $sk family = __ip_sock_family($sk) level = $level optname = $optname optstr = tcp_sockopt_str($optname) optlen = $optlen } probe tcp.ipv6.setsockopt = kernel.function("ipv6_setsockopt")!, module("ipv6").function("ipv6_setsockopt") { name = "tcp.ipv6.setsockopt" sock = $sk family = __ip_sock_family($sk) level = $level optname = $optname optstr = tcp_ipv6_sockopt_str($optname) optlen = $optlen } /** * probe tcp.setsockopt.return - Return from setsockopt() * @name: Name of this probe * @ret: Error code (0: no error) * * Context: * The process which calls setsockopt */ probe tcp.setsockopt.return = tcp.ipv4.setsockopt.return, tcp.ipv6.setsockopt.return { } probe tcp.ipv4.setsockopt.return = kernel.function("tcp_setsockopt").return { name = "tcp.ipv4.setsockopt" ret = $return } probe tcp.ipv6.setsockopt.return = kernel.function("ipv6_setsockopt").return!, module("ipv6").function("ipv6_setsockopt").return { name = "tcp.ipv6.setsockopt" ret = $return } /** * probe tcp.receive - Called when a TCP packet is received * @name: Name of the probe point * @iphdr: IP header address * @protocol: Packet protocol from driver * @family: IP address family * @saddr: A string representing the source IP address * @daddr: A string representing the destination IP address * @sport: TCP source port * @dport: TCP destination port * @urg: TCP URG flag * @ack: TCP ACK flag * @psh: TCP PSH flag * @rst: TCP RST flag * @syn: TCP SYN flag * @fin: TCP FIN flag */ probe tcp.receive = tcp.ipv4.receive, tcp.ipv6.receive { } probe tcp.ipv4.receive = kernel.function("tcp_v4_rcv") { name = "tcp.ipv4.receive" iphdr = __get_skb_iphdr($skb) # If we're here, by definition we're doing AF_INET, not AF_INET6. family = %{ /* pure */ AF_INET %} saddr = format_ipaddr(__ip_skb_saddr(iphdr), %{ /* pure */ AF_INET %}) daddr = format_ipaddr(__ip_skb_daddr(iphdr), %{ /* pure */ AF_INET %}) protocol = __ip_skb_proto(iphdr) tcphdr = __get_skb_tcphdr($skb) dport = __tcp_skb_dport(tcphdr) sport = __tcp_skb_sport(tcphdr) urg = __tcp_skb_urg(tcphdr) ack = __tcp_skb_ack(tcphdr) psh = __tcp_skb_psh(tcphdr) rst = __tcp_skb_rst(tcphdr) syn = __tcp_skb_syn(tcphdr) fin = __tcp_skb_fin(tcphdr) } probe tcp.ipv6.receive = kernel.function("tcp_v6_rcv")!, module("ipv6").function("tcp_v6_rcv") { name = "tcp.ipv6.receive" iphdr = __get_skb_iphdr(@choose_defined($skb, kernel_pointer($pskb))) # If we're here, by definition we're doing AF_INET6, not AF_INET. family = %{ /* pure */ AF_INET6 %} saddr = format_ipaddr(&@cast(iphdr, "ipv6hdr")->saddr, %{ /* pure */ AF_INET6 %}) daddr = format_ipaddr(&@cast(iphdr, "ipv6hdr")->daddr, %{ /* pure */ AF_INET6 %}) # If we're here, by definition we're doing IPPROTO_TCP. There # isn't a protocol field in 'struct ipv6hdr'. There is one in # 'struct sk_buff', but that protocol field is an Ethernet # Procol ID (ETH_P_*), not an IP protocol ID (IPPROTO_*). protocol = %{ /* pure */ IPPROTO_TCP %} tcphdr = __get_skb_tcphdr(@choose_defined($skb, kernel_pointer($pskb))) dport = __tcp_skb_dport(tcphdr) sport = __tcp_skb_sport(tcphdr) urg = __tcp_skb_urg(tcphdr) ack = __tcp_skb_ack(tcphdr) psh = __tcp_skb_psh(tcphdr) rst = __tcp_skb_rst(tcphdr) syn = __tcp_skb_syn(tcphdr) fin = __tcp_skb_fin(tcphdr) } systemtap-2.3/tapset/linux/tcpmib-filter-default.stp000066400000000000000000000015651217430427200227720ustar00rootroot00000000000000/* * Copyright (C) 2009 IBM Corp. * Copyright (C) 2010 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. */ /** * sfunction tcpmib_filter_key - Default filter function for tcpmib.* probes * * @sk: pointer to the struct sock being acted on * @op: value to be counted if @sk passes the filter * * This function is a default filter function. * The user can replace this function with their own. * The user-supplied filter function returns an index key based on the values * in @sk. * A return value of 0 means this particular @sk should be not be counted. */ function tcpmib_filter_key:long (sk:long, op:long) { if (!sk) return 0 return 1 } systemtap-2.3/tapset/linux/tcpmib.stp000066400000000000000000000236341217430427200200660ustar00rootroot00000000000000/* * Copyright (C) 2009 IBM Corp. * Copyright (C) 2010 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. * * Version 1.0 wilder@us.ibm.com 2009-07-06 */ /* Global counter definitions for mib TCP_MIB. */ %{ #include #include #include #include %} global ActiveOpens global AttemptFails global CurrEstab global EstabResets // global InErrs, this mib is not yet supported global InSegs global OutRsts global OutSegs global PassiveOpens global RetransSegs /** * sfunction tcpmib_get_state - Get a socket's state * @sk: pointer to a struct sock * * Returns the sk_state from a struct sock. */ function tcpmib_get_state:long (sk:long) { return @cast(sk, "sock", "kernel")->__sk_common->skc_state; } /** * sfunction tcpmib_local_addr - Get the source address * @sk: pointer to a struct inet_sock * * Returns the saddr from a struct inet_sock in host order. */ function tcpmib_local_addr:long(sk:long) { return ntohl(__ip_sock_saddr(sk)) } /** * sfunction tcpmib_remote_addr - Get the remote address * @sk: pointer to a struct inet_sock * * Returns the daddr from a struct inet_sock in host order. */ function tcpmib_remote_addr:long(sk:long) { return ntohl(__ip_sock_daddr(sk)) } /** * sfunction tcpmib_local_port - Get the local port * @sk: pointer to a struct inet_sock * * Returns the sport from a struct inet_sock in host order. */ function tcpmib_local_port:long(sk:long) { return __tcp_sock_sport(sk) } /** * sfunction tcpmib_remote_port - Get the remote port * @sk: pointer to a struct inet_sock * * Returns the dport from a struct inet_sock in host order. */ function tcpmib_remote_port:long(sk:long) { return __tcp_sock_dport(sk) } /** * probe tcpmib.ActiveOpens - Count an active opening of a socket * @sk: pointer to the struct sock being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * tcpmib_filter_key(). If the packet passes the filter is is * counted in the global @ActiveOpens (equivalent to SNMP's MIB * TCP_MIB_ACTIVEOPENS) */ probe tcpmib.ActiveOpens = kernel.function("tcp_connect").return { sk = $sk; op = 1; if ( $return ) next; // definition in tcpipstat.stp key = tcpmib_filter_key($sk,op); if ( key ) ActiveOpens[key] += op; } /** * probe tcpmib.AttemptFails - Count a failed attempt to open a socket * @sk: pointer to the struct sock being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * tcpmib_filter_key(). If the packet passes the filter is is * counted in the global @AttemptFails (equivalent to SNMP's MIB * TCP_MIB_ATTEMPTFAILS) */ probe tcpmib.AttemptFails = kernel.function("tcp_done").call ? { sk = $sk; state = tcpmib_get_state($sk); op = 1; TCP_SYN_SENT = 2; TCP_SYN_RECV = 3; if( state == TCP_SYN_SENT || state == TCP_SYN_RECV){ key = tcpmib_filter_key($sk,op); if ( key ) AttemptFails[key] += op; } } /** * probe tcpmib.CurrEstab - Update the count of open sockets * @sk: pointer to the struct sock being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * tcpmib_filter_key(). If the packet passes the filter is is * counted in the global @CurrEstab (equivalent to SNMP's MIB * TCP_MIB_CURRESTAB) */ probe tcpmib.CurrEstab = kernel.function("tcp_set_state").call ? { sk = $sk; state = $state; oldstate = tcpmib_get_state($sk); TCP_ESTABLISHED = 1; if ( oldstate == TCP_ESTABLISHED ) { op = -1; key = tcpmib_filter_key($sk,op); if ( key ) CurrEstab[key] += op; } else { if ( state == TCP_ESTABLISHED ) { op = 1; key = tcpmib_filter_key($sk,op); if ( key ) CurrEstab[key] += op; } } } /** * probe tcpmib.EstabResets - Count the reset of a socket * @sk: pointer to the struct sock being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * tcpmib_filter_key(). If the packet passes the filter is is * counted in the global @EstabResets (equivalent to SNMP's MIB * TCP_MIB_ESTABRESETS) */ probe tcpmib.EstabResets = kernel.function("tcp_set_state").call ? { sk = $sk; state = $state; oldstate = tcpmib_get_state($sk); op = 1; TCP_CLOSE = 7; TCP_CLOSE_WAIT = 8; TCP_ESTABLISHED = 1; if ( ( state == TCP_CLOSE ) && (oldstate == TCP_CLOSE_WAIT || oldstate == TCP_ESTABLISHED) ){ key = tcpmib_filter_key($sk,op); if ( key ) EstabResets[key] += op; } } /** * probe tcpmib.InSegs - Count an incoming tcp segment * @sk: pointer to the struct sock being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * tcpmib_filter_key() (or ipmib_filter_key() for tcp v4). * If the packet passes the filter is is * counted in the global @InSegs (equivalent to SNMP's MIB * TCP_MIB_INSEGS) */ probe tcpmib.InSegs = kernel.function("__inet_lookup_established").return !, kernel.function("tcp_v4_rcv") { if (@defined($return)) { sk=$return key = tcpmib_filter_key($return,op) } else { # We don't know the sk in tcp_v4_rcv() sk=0 key = ipmib_filter_key($skb,op,0); } op=1 if ( key ) InSegs[key] += op; } /** * probe tcpmib.OutRsts - Count the sending of a reset packet * @sk: pointer to the struct sock being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * tcpmib_filter_key(). If the packet passes the filter is is * counted in the global @OutRsts (equivalent to SNMP's MIB * TCP_MIB_OUTRSTS) */ probe tcpmib.OutRsts = __tcpmib.OutRsts.* { } function _rtn_local:long () %{ STAP_RETVALUE = RTN_LOCAL; %} function _is_reset:long (skb:long) %{ /* pure */ struct tcphdr *th; struct sk_buff *skb = (struct sk_buff *)(long)STAP_ARG_skb; #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21) th = (struct tcphdr *)kread(&(skb->h.th)); #else #ifdef NET_SKBUFF_DATA_USES_OFFSET th = (struct tcphdr *)(kread(&(skb->network_header)) + kread(&(skb->head))); #else th = (struct tcphdr *)kread(&(skb->network_header)); #endif #endif STAP_RETVALUE = th->rst; CATCH_DEREF_FAULT(); %} function _tcpmib_input_route_type:long (skb:long) %{ /* pure */ struct rtable *rt; struct sk_buff *skb = (struct sk_buff *)(long)STAP_ARG_skb; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) rt = (struct rtable *)kread(&(skb->_skb_refdst)); #else #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) rt = (struct rtable *)kread(&(skb->_skb_dst)); #else #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) rt = (struct rtable *)kread(&(skb->dst)); #else rt = (struct rtable *)kread(&(skb->rtable)); #endif #endif #endif if ( rt ) STAP_RETVALUE = kread(&(rt->rt_type)); else STAP_RETVALUE = RTN_UNSPEC; CATCH_DEREF_FAULT(); %} /* * note: * tcp_v4_send_reset may be called with a NULL sk. * This happens when sending a reset in response to a syn * when no socket exists (for example the service is not running). * Without a socket we can't count the reset. */ probe __tcpmib.OutRsts.tcp_v4_send_reset = kernel.function("tcp_v4_send_reset") { sk = @choose_defined($sk, 0) op = 1; if ( _is_reset($skb) ) next if (_tcpmib_input_route_type($skb) != _rtn_local() ) next; key = (@defined($sk) ? tcpmib_filter_key(sk,op) : ipmib_filter_key($skb,op,1)) if ( key ) OutRsts[key] += op; } probe __tcpmib.OutRsts.tcp_send_active_reset = kernel.function("tcp_send_active_reset") { /* Almost correct, * If alloc_skb() fails it incorrectly bumps TCP_MIB_OUTRSTS, */ sk = $sk; op = 1; key = tcpmib_filter_key($sk,op); if ( key ) OutRsts[key] += op; } /** * probe tcpmib.OutSegs - Count the sending of a TCP segment * @sk: pointer to the struct sock being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * tcpmib_filter_key(). If the packet passes the filter is is * counted in the global @OutSegs (equivalent to SNMP's MIB * TCP_MIB_OUTSEGS) */ probe tcpmib.OutSegs=kernel.function("ip_queue_xmit").return { if ( $return < 0 ) next; sk = $skb->sk; op = 1; // Only count the events with protocol IPPROTO_TCP,6. iphdr = __get_skb_iphdr($skb); if( !(__ip_skb_proto(iphdr) == 6) ) next ; key = tcpmib_filter_key(sk,op); if ( key ) OutSegs[key] += op; } /** * probe tcpmib.PassiveOpens - Count the passive creation of a socket * @sk: pointer to the struct sock being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * tcpmib_filter_key(). If the packet passes the filter is is * counted in the global @PassiveOpens (equivalent to SNMP's MIB * TCP_MIB_PASSIVEOPENS) */ probe tcpmib.PassiveOpens=kernel.function("tcp_v4_syn_recv_sock").return { sk = $return; op = 1; if ( !sk ) next; key = tcpmib_filter_key(sk,op); if ( key ) PassiveOpens[key] += op; } /** * probe tcpmib.RetransSegs - Count the retransmission of a TCP segment * @sk: pointer to the struct sock being acted on * @op: value to be added to the counter (default value of 1) * * The packet pointed to by @skb is filtered by the function * tcpmib_filter_key(). If the packet passes the filter is is * counted in the global @RetransSegs (equivalent to SNMP's MIB * TCP_MIB_RETRANSSEGS) */ probe tcpmib.RetransSegs=kernel.function("tcp_retransmit_skb").return { sk = $sk; op = 1; if ( $return ) next; key = tcpmib_filter_key($sk,op); if ( key ) RetransSegs[key] += op; } systemtap-2.3/tapset/linux/timestamp.stp000066400000000000000000000033411217430427200206040ustar00rootroot00000000000000// timestamp tapset // Copyright (C) 2005-2006 Red Hat Inc. // Copyright (C) 2006 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // Each timestamp function returns a value to indicate when a function is executed. These //returned values can then be used to indicate when an event occurred, provide an ordering for events, //or compute the amount of time elapsed between two time stamps. // /** * sfunction get_cycles - Processor cycle count * * Description: This function returns the processor cycle counter value * if available, else it returns zero. The cycle counter is free running * and unsynchronized on each processor. Thus, the order of events cannot * determined by comparing the results of the get_cycles function on * different processors. */ function get_cycles:long () %{ /* pure */ /* unprivileged */ cycles_t c = get_cycles(); STAP_RETVALUE = (int64_t) c; %} /** * sfunction jiffies - Kernel jiffies count * * Description: This function returns the value of the kernel jiffies * variable. This value is incremented periodically by timer interrupts, * and may wrap around a 32-bit or 64-bit boundary. See HZ(). */ function jiffies:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = (int64_t) jiffies; %} /** * sfunction HZ - Kernel HZ * * Description: This function returns the value of the kernel HZ macro, * which corresponds to the rate of increase of the jiffies value. */ function HZ:long () %{ /* pure */ /* unprivileged */ STAP_RETVALUE = (int64_t) HZ; %} systemtap-2.3/tapset/linux/timestamp_gtod.stp000066400000000000000000000031351217430427200216220ustar00rootroot00000000000000// timestamp tapset -- gettimeofday variants // Copyright (C) 2005-2009 Red Hat Inc. // Copyright (C) 2006 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. %{ #define STAP_NEED_GETTIMEOFDAY 1 %} /** * sfunction gettimeofday_ns - Number of nanoseconds since UNIX epoch * * Description: This function returns the number of nanoseconds * since the UNIX epoch. */ function gettimeofday_ns:long () %{ /* pure */ /* unprivileged */ /* NOTE: we can't use do_gettimeofday because we could be called from a * context where xtime_lock is already held. See bug #2525. */ STAP_RETVALUE = _stp_gettimeofday_ns(); if (STAP_RETVALUE < 0) CONTEXT->last_error = "gettimeofday not initialized"; %} /** * sfunction gettimeofday_us - Number of microseconds since UNIX epoch * * Description: This function returns the number of microseconds * since the UNIX epoch. */ function gettimeofday_us:long () { return gettimeofday_ns() / 1000; } /** * sfunction gettimeofday_ms - Number of milliseconds since UNIX epoch * * Description: This function returns the number of milliseconds * since the UNIX epoch. */ function gettimeofday_ms:long () { return gettimeofday_ns() / 1000000; } /** * sfunction gettimeofday_s - Number of seconds since UNIX epoch * * Description: This function returns the number of seconds since * the UNIX epoch. */ function gettimeofday_s:long () { return gettimeofday_ns() / 1000000000; } systemtap-2.3/tapset/linux/timestamp_monotonic.stp000066400000000000000000000121731217430427200226740ustar00rootroot00000000000000// timestamp tapset -- monotonic clock variants // Copyright (C) 2011 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. %{ // Since scripts can run from quite arbitrary contexts, we can only use // cpu_clock once it was made NMI safe. This was in commit def0a9b2 for // HAVE_UNSTABLE_SCHED_CLOCK archs (included in 2.6.32), and commit b9f8fcd5 // for the rest (included in 2.6.33). So before that, we'll just pretend that // cpu_clock and local_clock don't exist. #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)) \ || (!defined (CONFIG_HAVE_UNSTABLE_SCHED_CLOCK) \ && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))) #undef STAPCONF_CPU_CLOCK #undef STAPCONF_LOCAL_CLOCK #endif // If we're falling back on gettimeofday, that machinery needs to be started. #if !defined (STAPCONF_CPU_CLOCK) #define STAP_NEED_GETTIMEOFDAY 1 #endif %} /** * sfunction cpu_clock_ns - Number of nanoseconds on the given cpu's clock * @cpu: Which processor's clock to read * * Description: This function returns the number of nanoseconds on the given * cpu's clock. This is always monotonic comparing on the same cpu, but may * have some drift between cpus (within about a jiffy). */ function cpu_clock_ns:long (cpu:long) %{ /* pure */ /* unprivileged */ #if defined (STAPCONF_CPU_CLOCK) if (likely(STAP_ARG_cpu >= 0 && STAP_ARG_cpu < NR_CPUS && cpu_online(STAP_ARG_cpu))) STAP_RETVALUE = cpu_clock(STAP_ARG_cpu); else { snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "cpu %lld is not online", STAP_ARG_cpu); CONTEXT->last_error = CONTEXT->error_buffer; } #else /* NOTE: we can't use do_gettimeofday because we could be called from a * context where xtime_lock is already held. See bug #2525. */ STAP_RETVALUE = _stp_gettimeofday_ns(); if (STAP_RETVALUE < 0) CONTEXT->last_error = "gettimeofday not initialized"; #endif %} /** * sfunction cpu_clock_us - Number of microseconds on the given cpu's clock * @cpu: Which processor's clock to read * * Description: This function returns the number of microseconds on the given * cpu's clock. This is always monotonic comparing on the same cpu, but may * have some drift between cpus (within about a jiffy). */ function cpu_clock_us:long (cpu:long) { return cpu_clock_ns(cpu) / 1000; } /** * sfunction cpu_clock_ms - Number of milliseconds on the given cpu's clock * @cpu: Which processor's clock to read * * Description: This function returns the number of milliseconds on the given * cpu's clock. This is always monotonic comparing on the same cpu, but may * have some drift between cpus (within about a jiffy). */ function cpu_clock_ms:long (cpu:long) { return cpu_clock_ns(cpu) / 1000000; } /** * sfunction cpu_clock_s - Number of seconds on the given cpu's clock * @cpu: Which processor's clock to read * * Description: This function returns the number of seconds on the given cpu's * clock. This is always monotonic comparing on the same cpu, but may have * some drift between cpus (within about a jiffy). */ function cpu_clock_s:long (cpu:long) { return cpu_clock_ns(cpu) / 1000000000; } /** * sfunction local_clock_ns - Number of nanoseconds on the local cpu's clock * * Description: This function returns the number of nanoseconds on the local * cpu's clock. This is always monotonic comparing on the same cpu, but may * have some drift between cpus (within about a jiffy). */ function local_clock_ns:long () %{ /* pure */ /* unprivileged */ #if defined (STAPCONF_LOCAL_CLOCK) STAP_RETVALUE = local_clock(); #elif defined (STAPCONF_CPU_CLOCK) STAP_RETVALUE = cpu_clock(smp_processor_id()); #else /* NOTE: we can't use do_gettimeofday because we could be called from a * context where xtime_lock is already held. See bug #2525. */ STAP_RETVALUE = _stp_gettimeofday_ns(); if (STAP_RETVALUE < 0) CONTEXT->last_error = "gettimeofday not initialized"; #endif %} /** * sfunction local_clock_us - Number of microseconds on the local cpu's clock * * Description: This function returns the number of microseconds on the local * cpu's clock. This is always monotonic comparing on the same cpu, but may * have some drift between cpus (within about a jiffy). */ function local_clock_us:long () { return local_clock_ns() / 1000; } /** * sfunction local_clock_ms - Number of milliseconds on the local cpu's clock * * Description: This function returns the number of milliseconds on the local * cpu's clock. This is always monotonic comparing on the same cpu, but may * have some drift between cpus (within about a jiffy). */ function local_clock_ms:long () { return local_clock_ns() / 1000000; } /** * sfunction local_clock_s - Number of seconds on the local cpu's clock * * Description: This function returns the number of seconds on the local cpu's * clock. This is always monotonic comparing on the same cpu, but may have * some drift between cpus (within about a jiffy). */ function local_clock_s:long () { return local_clock_ns() / 1000000000; } systemtap-2.3/tapset/linux/tty.stp000066400000000000000000000135421217430427200174250ustar00rootroot00000000000000// tty tapset // Copyright (C) 2009 IBM Corp. // Copyright (C) 2010 Red Hat Inc. // // Author: Breno Leitao // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /** * probe tty.open - Called when a tty is opened * @inode_number: the inode number * @inode_state: the inode state * @inode_flags: the inode flags * @file_name: the file name * @file_mode: the file mode * @file_flags: the file flags */ probe tty.open = kernel.function("tty_open") { inode_number = $inode->i_ino inode_state = $inode->i_state inode_flags = $inode->i_flags file_name = d_name(@choose_defined($filp->f_path->dentry, $filp->f_dentry)) file_mode = $filp->f_mode file_flags = $filp->f_flags } /** * probe tty.release - Called when the tty is closed * @inode_number: the inode number * @inode_state: the inode state * @inode_flags: the inode flags * @file_name: the file name * @file_mode: the file mode * @file_flags: the file flags */ probe tty.release = kernel.function("tty_release") { // RHEL4 (2.6.9) kernel's debuginfo doesn't seem to have // $inode, even though the function isn't inline. So, make // sure $inode is defined. if (@defined($inode)) { inode_number = $inode->i_ino inode_state = $inode->i_state inode_flags = $inode->i_flags } else { inode_number = -1 inode_state = -1 inode_flags = -1 } file_name = d_name(@choose_defined($filp->f_path->dentry, $filp->f_dentry)) file_mode = $filp->f_mode file_flags = $filp->f_flags } /** * probe tty.resize - Called when a terminal resize happens * @name: the tty name * @old_row: the old row value * @old_col: the old col value * @old_ypixel: the old ypixel * @old_xpixel: the old xpixel * @new_row: the new row value * @new_col: the new col value * @new_ypixel: the new ypixel value * @new_xpixel: the new xpixel value */ probe tty.resize = kernel.function("tiocswinsz") { name = kernel_string($tty->name) old_row = $tty->winsize->ws_row old_col = $tty->winsize->ws_col old_ypixel = $tty->winsize->ws_ypixel old_xpixel = $tty->winsize->ws_xpixel if (@defined($arg)) { new_row = user_ushort($arg->ws_row) new_col = user_ushort($arg->ws_col) new_ypixel = user_ushort($arg->ws_ypixel) new_xpixel = user_ushort($arg->ws_xpixel) } else { new_row = -1 new_col = -1 new_ypixel = -1 new_xpixel = -1 } } /** * probe tty.ioctl - called when a ioctl is request to the tty * @name: the file name * @cmd: the ioctl command * @arg: the ioctl argument */ probe tty.ioctl = kernel.function("tty_ioctl") { name = kernel_string(@choose_defined($file->f_path->dentry->d_iname, $file->f_dentry->d_iname)) cmd = $cmd arg = $arg } /** * probe tty.init - Called when a tty is being initalized * @driver_name: the driver name * @name: the driver .dev_name name * @module: the module name */ probe tty.init = kernel.function("tty_init_dev") !, kernel.function("init_dev") { driver_name = kernel_string($driver->driver_name) name = kernel_string($driver->name) module = kernel_string($driver->owner->name) } /** * probe tty.register - Called when a tty device is registred * @driver_name: the driver name * @name: the driver .dev_name name * @module: the module name * @index: the tty index requested */ probe tty.register = kernel.function("tty_register_device") { driver_name = kernel_string($driver->driver_name) name = kernel_string($driver->name) module = kernel_string($driver->owner->name) index = $index } /** * probe tty.unregister - Called when a tty device is being unregistered * @driver_name: the driver name * @name: the driver .dev_name name * @module: the module name * @index: the tty index requested */ probe tty.unregister = kernel.function("tty_unregister_device") { driver_name = kernel_string($driver->driver_name) name = kernel_string($driver->name) module = kernel_string($driver->owner->name) index = $index } /** * probe tty.poll - Called when a tty device is being polled * @file_name: the tty file name * @wait_key: the wait queue key */ probe tty.poll = kernel.function("tty_poll") { file_name = d_name(@choose_defined($filp->f_path->dentry, $filp->f_dentry)) wait_key = (@defined($wait->key) ? ($wait ? $wait->key : 0) : 0) } /** * probe tty.receive - called when a tty receives a message * @cp: the buffer that was received * @fp: The flag buffer * @count: The amount of characters received * @driver_name: the driver name * @name: the name of the module file * @index: The tty Index * @id: the tty id */ probe tty.receive = kernel.function("n_tty_receive_buf") { cp = kernel_string($cp) fp = kernel_string($fp) count = $count driver_name = kernel_string($tty->driver->driver_name) name = kernel_string($tty->driver->name) index = $tty->index id = $tty->magic } /** * probe tty.write - write to the tty line * @buffer: the buffer that will be written * @nr: The amount of characters * @driver_name: the driver name * @file_name: the file name lreated to the tty */ probe tty.write = kernel.function("n_tty_write") !, kernel.function("write_chan") { buffer = kernel_string($buf) nr = $nr file_name = d_name(@choose_defined($file->f_path->dentry, $file->f_dentry)) driver_name = kernel_string($tty->driver->driver_name) } /** * probe tty.read - called when a tty line will be read * @buffer: the buffer that will receive the characters * @nr: The amount of characters to be read * @driver_name: the driver name * @file_name: the file name lreated to the tty */ probe tty.read = kernel.function("n_tty_read") !, kernel.function("read_chan") { buffer = kernel_string($buf) nr = $nr file_name = d_name(@choose_defined($file->f_path->dentry, $file->f_dentry)) driver_name = kernel_string($tty->driver->driver_name) } systemtap-2.3/tapset/linux/tzinfo.stp000066400000000000000000000014431217430427200201130ustar00rootroot00000000000000// timezone tapset // Copyright (C) 2010 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /** * sfunction tz_gmtoff - Return local time zone offset * * Description: Returns the local time zone offset (seconds west of UTC), as * passed by staprun at script startup only. */ function tz_gmtoff() { return %{ /* pure */ /* unprivileged */ tz_gmtoff %} } /** * sfunction tz_name - Return local time zone name * * Description: Returns the local time zone name, as passed by staprun at * script startup only. */ function tz_name() { return %{ /* pure */ /* unprivileged */ /* string */ tz_name %} } systemtap-2.3/tapset/linux/ucontext-symbols.stp000066400000000000000000000156441217430427200221510ustar00rootroot00000000000000// User context symbols tapset // Copyright (C) 2009-2012 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // User context symbol functions provide additional information about // addresses from an application. These functions can provide // information about the user space map (library) that the event occurred or // the function symbol of an address. // function __ustack_raw (n:long) %{ /* pragma:unwind */ /* pure */ /* myproc-unprivileged */ /* basic sanity check for bounds: */ if (unlikely(STAP_ARG_n < 0 || STAP_ARG_n >= MAXBACKTRACE)) STAP_RETVALUE = 0; else STAP_RETVALUE = _stp_stack_user_get (CONTEXT, (unsigned)STAP_ARG_n); %} /** * sfunction ustack - Return address at given depth of user stack backtrace * @n: number of levels to descend in the stack. * * Description: Performs a simple (user space) backtrace, and returns the * element at the specified position. The results of the backtrace itself * are cached, so that the backtrace computation is performed at most once * no matter how many times ustack() is called, or in what order. */ function ustack:long (n:long) { __r = __ustack_raw(n); if (__r != 0) return __r /* fallback: parse backtrace() to go deeper in the stack */ __b = ubacktrace (); __orig_n = n; __sym = tokenize (__b, " "); if (__sym == "") @__context_unwind_error(__orig_n); while (__n > 0) { __sym = tokenize ("", " "); if (__sym == "") @__context_unwind_error(__orig_n); __n--; } return strtol(__sym, 16) } /** * sfunction usymname - Return the symbol of an address in the current task. * @addr: The address to translate. * * Description: Returns the (function) symbol name associated with the * given address if known. If not known it will return the hex string * representation of addr. */ function usymname:string (addr: long) %{ /* pure */ /* myproc-unprivileged */ /* pragma:vma */ /* pragma:symbols */ _stp_snprint_addr(STAP_RETVALUE, MAXSTRINGLEN, STAP_ARG_addr, _STP_SYM_SYMBOL, current); %} /** * sfunction usymdata - Return the symbol and module offset of an address. * @addr: The address to translate. * * Description: Returns the (function) symbol name associated with the * given address in the current task if known, the offset from the * start and the size of the symbol, plus the module name (between * brackets). If symbol is unknown, but module is known, the offset * inside the module, plus the size of the module is added. If any * element is not known it will be omitted and if the symbol name is * unknown it will return the hex string for the given address. */ function usymdata:string (addr: long) %{ /* pure */ /* myproc-unprivileged */ /* pragma:vma */ /* pragma:symbols */ _stp_snprint_addr(STAP_RETVALUE, MAXSTRINGLEN, STAP_ARG_addr, _STP_SYM_DATA, current); %} /** * sfunction print_ustack - Print out stack for the current task from string. * @stk: String with list of hexadecimal addresses for the current task. * * Perform a symbolic lookup of the addresses in the given string, * which is assumed to be the result of a prior call to * ubacktrace() for the current task. * * Print one line per address, including the address, the * name of the function containing the address, and an estimate of * its position within that function. Return nothing. * * NOTE: it is recommended to use print_usyms() instead of this function. */ function print_ustack(stk:string) { print_usyms(stk) } /** * sfunction print_usyms - Print out user stack from string * @callers: String with list of hexadecimal (user) addresses * * Description: This function performs a symbolic lookup of the addresses * in the given string, * which are assumed to be the result of prior calls to ustack(), * ucallers(), and similar functions. * * Prints one line per address, including the address, the * name of the function containing the address, and an estimate of * its position within that function, as obtained by usymdata(). * Returns nothing. */ function print_usyms (callers:string) { __sym = tokenize (callers, " "); while (__sym != "") { printf (" %s : %s\n", __sym, usymdata (strtol(__sym,16))); __sym = tokenize ("", " "); } } /** * sfunction sprint_ustack - Return stack for the current task from string. * @stk: String with list of hexadecimal addresses for the current task. * * Perform a symbolic lookup of the addresses in the given string, * which is assumed to be the result of a prior call to * ubacktrace() for the current task. * * Returns a simple backtrace from the given hex string. One line per * address. Includes the symbol name (or hex address if symbol * couldn't be resolved) and module name (if found). Includes the * offset from the start of the function if found, otherwise the * offset will be added to the module (if found, between * brackets). Returns the backtrace as string (each line terminated by * a newline character). Note that the returned stack will be * truncated to MAXSTRINGLEN, to print fuller and richer stacks use * print_ustack. * * NOTE: it is recommended to use sprint_usyms() instead of this function. */ function sprint_ustack:string(stk:string) { sprint_usyms(stk) } /** * sfunction sprint_usyms - Return stack for user addresses from string * * @callers: String with list of hexadecimal (user) addresses * * Perform a symbolic lookup of the addresses in the given string, * which are assumed to be the result of a prior calls to ustack(), * ucallers(), and similar functions. * * Returns a simple backtrace from the given hex string. One line per * address. Includes the symbol name (or hex address if symbol * couldn't be resolved) and module name (if found), as obtained from * usymdata(). Includes the offset from the start of the function if * found, otherwise the offset will be added to the module (if found, between * brackets). Returns the backtrace as string (each line terminated by * a newline character). Note that the returned stack will be * truncated to MAXSTRINGLEN, to print fuller and richer stacks use * print_usyms(). */ function sprint_usyms (callers:string) { __sym = tokenize (callers, " "); __foo = ""; __l = 0 while (__sym != "") { // cleanly handle overflow instead of printing partial line: __line = sprintf (" %s : %s\n", __sym, usymdata (strtol(__sym,16))); __l += strlen(__line) if (__l > %{ MAXSTRINGLEN %}) break __foo .= __line __sym = tokenize ("", " ") } return __foo } systemtap-2.3/tapset/linux/ucontext-unwind.stp000066400000000000000000000071661217430427200217650ustar00rootroot00000000000000// User context unwind tapset // Copyright (C) 2009-2013 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /** * sfunction print_ubacktrace - Print stack back trace for current user-space task. * * Equivalent to print_ustack(ubacktrace()), except that deeper stack * nesting may be supported. Returns nothing. See print_backtrace() * for kernel backtrace. * * Note: To get (full) backtraces for user space applications and shared * shared libraries not mentioned in the current script run stap with * -d /path/to/exe-or-so and/or add --ldd to load all needed unwind data. */ function print_ubacktrace () %{ /* pragma:unwind */ /* pragma:symbols */ /* myproc-unprivileged */ /* pragma:uprobes */ /* pragma:vma */ _stp_stack_user_print(CONTEXT, _STP_SYM_FULL); %} /** * sfunction sprint_ubacktrace - Return stack back trace for current user-space task as string. * * Returns a simple backtrace for the current task. One line per * address. Includes the symbol name (or hex address if symbol * couldn't be resolved) and module name (if found). Includes the * offset from the start of the function if found, otherwise the * offset will be added to the module (if found, between * brackets). Returns the backtrace as string (each line terminated by * a newline character). Note that the returned stack will be * truncated to MAXSTRINGLEN, to print fuller and richer stacks use * print_ubacktrace(). Equivalent to sprint_ustack(ubacktrace()), * but more efficient (no need to translate between hex strings and * final backtrace string). * * Note: To get (full) backtraces for user space applications and shared * shared libraries not mentioned in the current script run stap with * -d /path/to/exe-or-so and/or add --ldd to load all needed unwind data. */ function sprint_ubacktrace:string () %{ /* pragma:unwind */ /* pragma:symbols */ /* pure */ /* myproc-unprivileged */ /* pragma:uprobes */ /* pragma:vma */ _stp_stack_user_sprint (STAP_RETVALUE, MAXSTRINGLEN, CONTEXT, _STP_SYM_SIMPLE); %} /** * sfunction print_ubacktrace_brief- Print stack back trace for current user-space task. * * Equivalent to print_ubacktrace(), but output for each symbol is * shorter (just name and offset, or just the hex address of no symbol * could be found). * * Note: To get (full) backtraces for user space applications and shared * shared libraries not mentioned in the current script run stap with * -d /path/to/exe-or-so and/or add --ldd to load all needed unwind data. */ function print_ubacktrace_brief () %{ /* pragma:unwind */ /* pragma:symbols */ /* myproc-unprivileged */ /* pragma:uprobes */ /* pragma:vma */ _stp_stack_user_print(CONTEXT, _STP_SYM_BRIEF); %} /** * sfunction ubacktrace - Hex backtrace of current user-space task stack. * * Return a string of hex addresses that are a backtrace of the * stack of the current task. Output may be truncated as per maximum * string length. Returns empty string when current probe point cannot * determine user backtrace. See backtrace() for kernel traceback. * * Note: To get (full) backtraces for user space applications and shared * shared libraries not mentioned in the current script run stap with * -d /path/to/exe-or-so and/or add --ldd to load all needed unwind data. */ function ubacktrace:string () %{ /* pragma:unwind */ /* pure */ /* myproc-unprivileged */ /* pragma:uprobes */ /* pragma:vma */ _stp_stack_user_sprint (STAP_RETVALUE, MAXSTRINGLEN, CONTEXT, _STP_SYM_NONE); %} systemtap-2.3/tapset/linux/ucontext.stp000066400000000000000000000042741217430427200204600ustar00rootroot00000000000000// User context tapset // Copyright (C) 2010-2011 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /** * sfunction umodname - Returns the (short) name of the user module. * @addr: User-space address * * Returns the short name of the user space module for the current task that * that the given address is part of. Reports an error when the address * isn't in a (mapped in) module, or the module cannot be found for some reason. */ function umodname:string (addr:long) %{ /* pure */ /* myproc-unprivileged */ /* pragma:vma */ const char *name = NULL; _stp_umod_lookup(STAP_ARG_addr, current, &name, NULL, NULL); if (!name) { name = ""; #if STAP_COMPAT_VERSION >= STAP_VERSION(2,3) // PR15044 CONTEXT->last_error = "module cannot be found"; #endif } strlcpy (STAP_RETVALUE, name, MAXSTRINGLEN); %} /** * sfunction ucallers - Return first n elements of user stack backtrace * * @n: number of levels to descend in the stack (not counting the top * level). If n is -1, print the entire stack. * * Description: This function returns a string of the first n hex * addresses from the backtrace of the user stack. Output may be * truncated as per maximum string length (MAXSTRINGLEN). * * Note: To get (full) backtraces for user space applications and shared * shared libraries not mentioned in the current script run stap with * -d /path/to/exe-or-so and/or add --ldd to load all needed unwind data. */ function ucallers:string (n:long) { __str = ""; __l = 0 for (__i = 0; __i <= n || n == -1; __i++) { __foo = __i > 0 ? " " : "" try { __foo .= sprintf("0x%x", ustack(__i)) } catch { /* assume we've hit the end of the stack */ if (n == -1) break @__context_unwind_error(n) } // ensure string cuts off cleanly at MAXSTRINGLEN: __l += strlen(__foo); if (__l > %{ MAXSTRINGLEN %}) break __str .= __foo } return __str } systemtap-2.3/tapset/linux/udp.stp000066400000000000000000000133501217430427200173720ustar00rootroot00000000000000// UDP tapset // Copyright (C) 2006 Intel Corporation. // Copyright (C) 2013 Red Hat, Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // This family of probe points is used to probe events that occur in the UDP layer. // /* Helper functions analogous (or even identical) those in tcp.stp */ function __get_skb_udphdr:long (skb:long) { return __get_skb_tcphdr(skb) } function __udp_sock_sport (sock) { return __tcp_sock_sport (sock) } function __udp_sock_dport (sock) { return __tcp_sock_dport (sock) } function __udp_skb_dport(udphdr) { return ntohs(@cast(udphdr, "udphdr")->dest) } function __udp_skb_sport(udphdr) { return ntohs(@cast(udphdr, "udphdr")->source) } /** * probe udp.sendmsg - Fires whenever a process sends a UDP message * @name: The name of this probe * @sock: Network socket used by the process * @size: Number of bytes sent by the process * @family: IP address family * @saddr: A string representing the source IP address * @daddr: A string representing the destination IP address * @sport: UDP source port * @dport: UDP destination port * * Context: * The process which sent a UDP message */ probe udp.sendmsg = kernel.function("udp_sendmsg") { name = "udp.sendmsg" sock = $sk size = $len %( systemtap_v >= "2.3" %? family = __ip_sock_family($sk) saddr = format_ipaddr(__ip_sock_saddr($sk), __ip_sock_family($sk)) daddr = format_ipaddr(__ip_sock_daddr($sk), __ip_sock_family($sk)) sport = __udp_sock_sport($sk) dport = __udp_sock_dport($sk) %) } /** * probe udp.sendmsg.return - Fires whenever an attempt to send a UDP message is completed * @name: The name of this probe * @size: Number of bytes sent by the process * * Context: * The process which sent a UDP message */ probe udp.sendmsg.return = kernel.function("udp_sendmsg").return { name = "udp.sendmsg" size = $return %( systemtap_v >= "2.3" %? family = __ip_sock_family($sk) saddr = format_ipaddr(__ip_sock_saddr($sk), __ip_sock_family($sk)) daddr = format_ipaddr(__ip_sock_daddr($sk), __ip_sock_family($sk)) sport = __udp_sock_sport($sk) dport = __udp_sock_dport($sk) %) } /** * probe udp.recvmsg - Fires whenever a UDP message is received * @name: The name of this probe * @sock: Network socket used by the process * @size: Number of bytes received by the process * @family: IP address family * @saddr: A string representing the source IP address * @daddr: A string representing the destination IP address * @sport: UDP source port * @dport: UDP destination port * * Context: * The process which received a UDP message */ probe udp.recvmsg = kernel.function("udp_recvmsg") { name = "udp.recvmsg" sock = $sk size = $len %( systemtap_v >= "2.3" %? family = __ip_sock_family($sk) saddr = format_ipaddr(__ip_sock_saddr($sk), __ip_sock_family($sk)) daddr = format_ipaddr(__ip_sock_daddr($sk), __ip_sock_family($sk)) sport = __udp_sock_sport($sk) dport = __udp_sock_dport($sk) %) } /** * probe udp.recvmsg.return - Fires whenever an attempt to receive a UDP message received is completed * @name: The name of this probe * @size: Number of bytes received by the process * @family: IP address family * @saddr: A string representing the source IP address * @daddr: A string representing the destination IP address * @sport: UDP source port * @dport: UDP destination port * * Context: * The process which received a UDP message */ probe udp.recvmsg.return = kernel.function("udp_recvmsg").return { name = "udp.recvmsg" size = $return %( systemtap_v >= "2.3" %? family = __ip_sock_family($sk) saddr = format_ipaddr(__ip_sock_saddr($sk), __ip_sock_family($sk)) daddr = format_ipaddr(__ip_sock_daddr($sk), __ip_sock_family($sk)) sport = __udp_sock_sport($sk) dport = __udp_sock_dport($sk) %) } /** * probe udp.disconnect - Fires when a process requests for a UDP disconnection * @name: The name of this probe * @sock: Network socket used by the process * @flags: Flags (e.g. FIN, etc) * @family: IP address family * @saddr: A string representing the source IP address * @daddr: A string representing the destination IP address * @sport: UDP source port * @dport: UDP destination port * * Context: * The process which requests a UDP disconnection */ probe udp.disconnect = kernel.function("udp_disconnect") { name = "udp.disconnect" sock = $sk flags = $flags %( systemtap_v >= "2.3" %? family = __ip_sock_family($sk) saddr = format_ipaddr(__ip_sock_saddr($sk), __ip_sock_family($sk)) daddr = format_ipaddr(__ip_sock_daddr($sk), __ip_sock_family($sk)) sport = __udp_sock_sport($sk) dport = __udp_sock_dport($sk) %) } /** * probe udp.disconnect.return - UDP has been disconnected successfully * @name: The name of this probe * @ret: Error code (0: no error) * @family: IP address family * @saddr: A string representing the source IP address * @daddr: A string representing the destination IP address * @sport: UDP source port * @dport: UDP destination port * * Context: * The process which requested a UDP disconnection */ probe udp.disconnect.return = kernel.function("udp_disconnect").return { name = "udp.disconnect" ret = $return %( systemtap_v >= "2.3" %? family = __ip_sock_family($sk) saddr = format_ipaddr(__ip_sock_saddr($sk), __ip_sock_family($sk)) daddr = format_ipaddr(__ip_sock_daddr($sk), __ip_sock_family($sk)) sport = __udp_sock_sport($sk) dport = __udp_sock_dport($sk) %) } systemtap-2.3/tapset/linux/utrace.stp000066400000000000000000000024641217430427200200710ustar00rootroot00000000000000/* utrace-only subset of register accessors */ %{ #include "syscall.h" %} function _utrace_syscall_nr:long () %{ /* pure */ /* myproc-unprivileged */ if (! CONTEXT->uregs || ! CONTEXT->user_mode_p) { CONTEXT->last_error = "invalid call without context registers"; } else { STAP_RETVALUE = syscall_get_nr(current, CONTEXT->uregs); } %} function _utrace_syscall_arg:long (n:long) %{ /* pure */ /* myproc-unprivileged */ unsigned long arg = 0; if (! CONTEXT->uregs || ! CONTEXT->user_mode_p) { CONTEXT->last_error = "invalid call without context registers"; } else { syscall_get_arguments(current, CONTEXT->uregs, (int)STAP_ARG_n, 1, &arg); } STAP_RETVALUE = arg; %} function _utrace_syscall_return:long () %{ /* pure */ /* myproc-unprivileged */ /* * Here's the reason for the "unsigned long" cast. Since all * values inside systemtap are 64-bit numbers, return values were * getting sign extended. This caused return values to not match * up with the same values passes as arguments. */ if (! CONTEXT->uregs || ! CONTEXT->user_mode_p) { CONTEXT->last_error = "invalid call without context registers"; } else { STAP_RETVALUE = (unsigned long)syscall_get_return_value(current, CONTEXT->uregs); } %} systemtap-2.3/tapset/linux/vfs.stp000066400000000000000000000555071217430427200174120ustar00rootroot00000000000000// vfs tapset // Copyright (C) 2006-2007 IBM Corp. // Copyright (C) 2007 Intel Corporation. // Copyright (C) 2007 Bull S.A.S // Copyright (c) 2008, 2010 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /* generic vfs probes */ /* We don't want to have to do a bdevname() call every time we want a devname, so we'll hash them here. */ function __find_bdevname:string(dev:long, bdev:long) { /* bdevname() can't do anything without an actual bdev, so let's just * return the same result early without wasting space in __devnames. */ if (bdev == 0) return "N/A" return bdevname(bdev) } %(systemtap_v < "2.3" %? /* deprecated */ function ppos_pos:long (ppos:long) { return kernel_pointer(ppos) } %) function __address_inode:long (page:long) { mapping = page? @cast(page, "page", "kernel")->mapping : 0 if (mapping == 0) return -1 else return @cast(mapping, "address_space", "kernel")->host } function __page_ino:long (page:long) { host = __address_inode(page) if (host == -1) return -1 else return @cast(host, "inode", "kernel")->i_ino } function __page_dev:long (page:long) { host = __address_inode(page) if (host == -1) return -1 return @cast(host, "inode", "kernel")->i_sb->s_dev } function __page_bdev:long (page:long) { host = __address_inode(page) if (host == -1) return 0 return @cast(host, "inode", "kernel")->i_sb->s_bdev } function __page_index:long (page:long) { return @cast(page, "page", "kernel")->index } function __file_dev:long (file:long) { d_inode = __file_inode(file) if (d_inode == 0) return 0 return @cast(d_inode, "inode", "kernel")->i_sb->s_dev } function __file_bdev:long (file:long) { d_inode = __file_inode(file) if (d_inode == 0) return 0 return @cast(d_inode, "inode", "kernel")->i_sb->s_bdev } function __file_ino:long (file:long) { d_inode = __file_inode(file) if (d_inode == 0) return 0 return @cast(d_inode, "inode", "kernel")->i_ino } function __file_maxbytes:long (file:long) { d_inode = __file_inode(file) if (d_inode == 0) return 0 return @cast(d_inode, "inode", "kernel")->i_sb->s_maxbytes } function __file_filename:string (file:long) { dentry = file ? @choose_defined(@cast(file, "file", "kernel")->f_path->dentry, @cast(file, "file", "kernel")->f_dentry) : 0 name = dentry? @cast(dentry, "dentry", "kernel")->d_name->name : 0 if (name == 0) return "NULL" else return kernel_string(name) } function _get_fopv_size:long (iovp:long, nr_segs:long) { if (iovp) { val = 0 for (i = 0; i < nr_segs; i++) val += @cast(iovp, "iovec")[i]->iov_len return val } return -1 } %(systemtap_v < "2.3" %? /* deprecated */ function _dev_minor:long (dev:long) { return MINOR(dev) } /* deprecated */ function _dev_major:long (dev:long) { return MAJOR(dev) } %) probe generic.fop.llseek = kernel.function("generic_file_llseek") { dev = __file_dev($file) devname = __find_bdevname(dev, __file_bdev($file)) ino = __file_ino($file) file = $file offset = $offset %(systemtap_v < "2.3" %? origin = @choose_defined($whence, $origin) %) whence = @choose_defined($whence, $origin) whence_str = _seek_whence_str(@choose_defined($whence, $origin)) maxbyte = __file_maxbytes($file) name = "generic_file_llseek" argstr = sprintf("%d, %d", $offset, @choose_defined($whence, $origin)) } probe generic.fop.llseek.return = kernel.function("generic_file_llseek").return { name = "generic_file_llseek" retstr = sprintf("%d", $return) file = $file offset = $offset %(systemtap_v < "2.3" %? origin = @choose_defined($whence, $origin) %) whence = @choose_defined($whence, $origin) whence_str = _seek_whence_str(@choose_defined($whence, $origin)) error = $return < 0 ? $return : 0 error_str = error ? errno_str(error) : "" } probe generic.fop.aio_read = kernel.function("__generic_file_aio_read") !, kernel.function("generic_file_aio_read") { file = $iocb->ki_filp dev = __file_dev($iocb->ki_filp) devname = __find_bdevname(dev, __file_bdev($iocb->ki_filp)) ino = __file_ino($iocb->ki_filp) pos = @choose_defined($pos, kernel_pointer($ppos)) buf = $iov->iov_base count = __iov_length($iov,$nr_segs,1,1) /*FIX ME: should be VERIFY_WRITE instead of 1*/ name = "generic_file_aio_read" argstr = sprintf("%d, %d, %p", count, pos, buf) size = count units = "bytes" } probe generic.fop.aio_read.return = kernel.function("__generic_file_aio_read").return !, kernel.function("generic_file_aio_read").return { file = $iocb->ki_filp nr_segs = $nr_segs name = "generic_file_aio_read" retstr = sprintf("%d", $return) bytes_read = $return > 0 ? $return : 0 error = $return < 0 ? $return : 0 error_str = error ? errno_str(error) : "" if ($return > 0) { size = $return units = "bytes" } } probe generic.fop.aio_write = kernel.function("generic_file_aio_write") { file = $iocb->ki_filp dev = __file_dev($iocb->ki_filp) devname = __find_bdevname(dev, __file_bdev($iocb->ki_filp)) ino = __file_ino($iocb->ki_filp) pos = $pos count = (@defined($iov) ? __iov_length($iov,$nr_segs,1,0) /*FIX ME: should be VERIFY_READ instead of 0*/ : $count) buf = @choose_defined($iov->iov_base, $buf) name = "generic_file_aio_write" argstr = sprintf("%d, %d, %p", count, pos, buf) size = count units = "bytes" } probe generic.fop.aio_write.return = kernel.function("generic_file_aio_write").return { file = $iocb->ki_filp name = "generic_file_aio_write" retstr = sprintf("%d", $return) if ($return > 0) { size = $return units = "bytes" } } probe generic.fop.readv = kernel.function("generic_file_readv") ? { dev = __file_dev($filp) devname = __find_bdevname(dev, __file_bdev($filp)) ino = __file_ino($filp) file = $filp nr_segs = $nr_segs pos = kernel_pointer($ppos) name = "generic_file_readv" argstr = sprintf("%d, %d", $nr_segs, pos) size = nr_segs units = "segs" } probe generic.fop.readv.return = kernel.function("generic_file_readv").return ? { file = $filp name = "generic_file_readv" retstr = sprintf("%d", $return) bytes_read = $return > 0 ? $return : 0 error = $return < 0 ? $return : 0 error_str = error ? errno_str(error) : "" if ($return > 0) { size = $return units = "bytes" } } /* calls __generic_file_write_nolock */ probe generic.fop.writev = kernel.function("generic_file_writev") ? { dev = __file_dev($file) devname = __find_bdevname(dev, __file_bdev($file)) ino = __file_ino($file) file = $file nr_segs = $nr_segs pos = kernel_pointer($ppos) name = "generic_file_writev" argstr = sprintf("%d, %d", $nr_segs, pos) size = nr_segs units = "segs" } probe generic.fop.writev.return = kernel.function("generic_file_writev").return ? { file = $file name = "generic_file_writev" retstr = sprintf("%d", $return) bytes_written = $return > 0 ? $return : 0 error = $return < 0 ? $return : 0 error_str = error ? errno_str(error) : "" if ($return > 0) { size = $return units = "bytes" } } /* checks for aops->readpage, if not defined, return -ENOEXEC else assigns generic_file_vm_ops to vma add filemap_nopage, filemap_populate */ probe generic.fop.mmap = kernel.function("generic_file_mmap") { file = $file dev = __file_dev($file) devname = __find_bdevname(dev, __file_bdev($file)) ino = __file_ino($file) vm_start = $vma->vm_start vm_end = $vma->vm_end vm_flags = $vma->vm_flags name = "generic_file_mmap" argstr = sprintf("0x%x, 0x%x, 0x%x", $vma->vm_start, $vma->vm_end, $vma->vm_flags) } probe generic.fop.mmap.return = kernel.function("generic_file_mmap").return { file = $file name = "generic_file_mmap" retstr = sprintf("%d", $return) error = $return < 0 ? $return : 0 error_str = error ? errno_str(error) : "" } probe generic.fop.open = kernel.function("generic_file_open") { dev = __file_dev($filp) devname = __find_bdevname(dev, __file_bdev($filp)) ino = $inode->i_ino file = $filp filename = __file_filename($filp) flag = $filp->f_flags size = $inode->i_size name = "generic_file_open" argstr = sprintf("%d, %d, %s", $inode->i_ino, $filp->f_flags, filename) } probe generic.fop.open.return = kernel.function("generic_file_open").return { name = "generic_file_open" retstr = sprintf("%d", $return) } probe generic.fop.sendfile = kernel.function("generic_file_sendfile") ? { dev = __file_dev($in_file) devname = __find_bdevname($in_file, __file_bdev($in_file)) ino = __file_ino($in_file) file = $in_file count = $count ppos = $ppos name = "generic_file_sendfile" argstr = sprintf("%d", $count) size = $count units = "bytes" } probe generic.fop.sendfile.return = kernel.function("generic_file_sendfile").return ? { name = "generic_file_sendfile" retstr = sprintf("%d", $return) if ($return > 0) { size = $return units = "bytes" } } probe generic.fop.splice_read = kernel.function("generic_file_splice_read") ? { dev = __file_dev($in) devname = __find_bdevname(dev, __file_bdev($in)) ino = __file_ino($in) file = $in dev_major = MAJOR(dev) dev_minor = MINOR(dev) len = $len flags = $flags name = "generic_file_splice_read" argstr = sprintf("%d, %x", $len, $flags) size = $len units = "bytes" } probe generic.fop.splice_read.return = kernel.function("generic_file_splice_read").return ? { name = "generic_file_splice_read" retstr = sprintf("%d", $return) file = $in ino = __file_ino($in) dev = __file_dev($in) dev_major = MAJOR(dev) dev_minor = MINOR(dev) ret = $return error = $return < 0 ? $return : 0 error_str = error ? errno_str(error) : "" if ($return > 0) { size = $return units = "bytes" } } probe generic.fop.splice_write = kernel.function("generic_file_splice_write") ? { dev = __file_dev($out) devname = __find_bdevname(dev, __file_bdev($out)) ino = __file_ino($out) file = $out len = $len flags = $flags name = "generic_file_splice_write" argstr = sprintf("%d, %x", $len, $flags) size = $len units = "bytes" } probe generic.fop.splice_write.return = kernel.function("generic_file_splice_write").return ? { name = "generic_file_splice_write" retstr = sprintf("%d", $return) file = $out error = $return < 0 ? $return : 0 error_str = error ? errno_str(error) : "" if (error) { size = $return units = "bytes" } } probe generic.fop.read = kernel.function("generic_file_read") ? { dev = __file_dev($filp) devname = __find_bdevname(dev, __file_bdev($filp)) ino = __file_ino($filp) file = $filp count = $count name = "generic_file_read" argstr = sprintf("%d", $count) size = $count units = "bytes" } probe generic.fop.read.return = kernel.function("generic_file_read").return ? { name = "generic_file_read" retstr = sprintf("%d", $return) if ($return > 0) { size = $return units = "bytes" } } probe generic.fop.write = kernel.function("generic_file_write") ? { dev = __file_dev($file) devname = __find_bdevname(dev, __file_bdev($file)) ino = __file_ino($file) file = $file count = $count name = "generic_file_write" argstr = sprintf("%d", $count) size = $count units = "bytes" } probe generic.fop.write.return = kernel.function("generic_file_write").return ? { name = "generic_file_write" retstr = sprintf("%d", $return) if ($return > 0) { size = $return units = "bytes" } } /* generic_writepages calls mpage_writepages(mapping, wbc, NULL) */ probe generic.aop.writepages = kernel.function("mpage_writepages") { dev = $mapping->host->i_sb->s_dev devname = __find_bdevname(dev, $mapping->host->i_sb->s_bdev) ino = $mapping->host->i_ino nr_to_write = $wbc->nr_to_write name = "generic_writepages" argstr = sprintf("%d", $wbc->nr_to_write) size = $wbc->nr_to_write units = "pages" } probe generic.aop.writepages.return = kernel.function("mpage_writepages").return { name = "generic_writepages" retstr = sprintf("%d", $return) } probe vfs.do_sync_read = kernel.function("do_sync_read") { dev = __file_dev($filp) devname = __find_bdevname(dev, __file_bdev($filp)) ino = __file_ino($filp) file = $filp len = $len pos = kernel_pointer($ppos) buf = $buf name = "do_sync_read" argstr = sprintf("%d, %d, %p", $len, pos, $buf) size = $len units = "bytes" bytes_to_read = $len } probe vfs.do_sync_read.return = kernel.function("do_sync_read").return { name = "do_sync_read" retstr = sprintf("%d", $return) bytes_to_read = $len ret = $return bytes_read = $return > 0 ? $return : 0 error = $return < 0 ? $return : 0 error_str = error ? errno_str(error) : "" if ($return > 0) { size = $return units = "bytes" } } probe vfs.do_sync_write = kernel.function("do_sync_write") { dev = __file_dev($filp) devname = __find_bdevname(dev, __file_bdev($filp)) ino = __file_ino($filp) file = $filp len = $len pos = kernel_pointer($ppos) buf = $buf bytes_to_write = $len name = "do_sync_write" argstr = sprintf("%d, %d , %p", $len, pos, $buf) size = $len units = "bytes" } probe vfs.do_sync_write.return = kernel.function("do_sync_write").return { name = "do_sync_write" retstr = sprintf("%d", $return) bytes_to_write = $len pos = kernel_pointer($ppos) ret = $return bytes_written = $return > 0 ? $return : 0 error = $return < 0 ? $return : 0 error_str = error ? errno_str(error) : "" if (error) { size = $return units = "bytes" } } probe vfs.block_sync_page = kernel.function("block_sync_page") ? { dev = __page_dev($page) devname = __find_bdevname(dev, __page_bdev($page)) ino = __page_ino($page) %(systemtap_v < "2.3" %? # 'page_index' is deprecated page_index = __page_index($page) %) index = __page_index($page) name = "block_sync_page" argstr = sprintf("%d", index) size = 1 units = "pages" } probe vfs.block_sync_page.return = kernel.function("block_sync_page").return ? { name = "block_sync_page" retstr = sprintf("N/A") } probe vfs.buffer_migrate_page = kernel.function("buffer_migrate_page") ? { dev = __page_dev($page) ino = __page_ino($page) devname = __find_bdevname(dev,__page_bdev($page)) %(systemtap_v < "2.3" %? # 'page_index' is deprecated page_index = __page_index($page) %) index = __page_index($page) name = "buffer_migrate_page" argstr = sprintf("%d", index) size = 1 units = "pages" } probe vfs.buffer_migrate_page.return = kernel.function("buffer_migrate_page").return ? { name = "buffer_migrate_page" retstr = sprintf("%d", $return) if ($return == 0) { size = 1 units = "pages" } } /* default if aop not set, __set_page_dirty_nobuffers usually used if set */ probe vfs.__set_page_dirty_buffers = kernel.function("__set_page_dirty_buffers") { dev = __page_dev($page) devname = __find_bdevname(dev, __page_bdev($page)) ino = __page_ino($page) index = __page_index($page) name = "__set_page_dirty_buffers" argstr = sprintf("%d", index) size = 1 units = "pages" } probe vfs.__set_page_dirty_buffers.return = kernel.function("__set_page_dirty_buffers").return { name = "__set_page_dirty_buffers" retstr = sprintf("%d", $return) %( kernel_v >= "2.6.17" %? if ($return == 1) %: if ($return == 0) %) { size = 1 units = "pages" } } probe vfs.do_mpage_readpage = kernel.function("do_mpage_readpage") { dev = __page_dev($page) devname = __find_bdevname(dev, __page_bdev($page)) ino = __page_ino($page) index = __page_index($page) name = "do_mpage_readpage" argstr = sprintf("%d", index) size = 1 units = "pages" } probe vfs.do_mpage_readpage.return = kernel.function("do_mpage_readpage").return { name = "do_mpage_readpage" retstr = sprintf("0x%x", $return) size = 1 units = "pages" } probe vfs.add_to_page_cache = kernel.function("add_to_page_cache_locked") !, kernel.function("add_to_page_cache") { dev = $mapping->host->i_sb->s_dev devname = __find_bdevname(dev, $mapping->host->i_sb->s_bdev) ino = $mapping->host->i_ino index = $offset nrpages = $mapping->nrpages size = $mapping->nrpages units = "pages" name = "vfs.add_to_page_cache" argstr = sprintf("%d, %d", ino, $offset) } probe vfs.add_to_page_cache.return = kernel.function("add_to_page_cache_locked").return !, kernel.function("add_to_page_cache").return { name = "vfs.add_to_page_cache" retstr = sprintf("%d", $return) if ($return == 0) { size = 1 units = "pages" } } probe vfs.remove_from_page_cache = kernel.function("__delete_from_page_cache") !, kernel.function("__remove_from_page_cache") { dev = __page_dev($page) devname = __find_bdevname(dev, __page_bdev($page)) ino = __page_ino($page) index = __page_index($page) name = "vfs.remove_from_page_cache" argstr = sprintf("%d", ino) } probe vfs.remove_from_page_cache.return = kernel.function("__delete_from_page_cache").return !, kernel.function("__remove_from_page_cache").return { name = "vfs.remove_from_page_cache" retstr = sprintf("N/A") } probe vfs.read = kernel.function("vfs_read") { file = $file pos = $pos buf = $buf bytes_to_read = $count dev = __file_dev($file) devname = __find_bdevname(dev, __file_bdev($file)) ino = __file_ino($file) name = "vfs.read" argstr = sprintf("%d, %d, %p", $count, $pos, $buf) } probe vfs.read.return = kernel.function("vfs_read").return { name = "vfs.read" retstr = sprintf("%d", $return) file = $file pos = $pos buf = $buf bytes_to_read = $count dev = __file_dev($file) devname = __find_bdevname(dev, __file_bdev($file)) ino = __file_ino($file) ret = $return bytes_read = $return > 0 ? $return : 0 error = $return < 0 ? $return : 0 error_str = error ? errno_str(error) : "" } probe vfs.readv = kernel.function("vfs_readv") { file = $file dev = __file_dev($file) devname = __find_bdevname(dev, __file_bdev($file)) ino = __file_ino($file) pos = $pos vec = $vec vlen = $vlen bytes_to_read = _get_fopv_size($vec, $vlen) name = "vfs.readv" argstr = sprintf("%d, %d, %p", bytes_to_read, $pos, $vec) } probe vfs.readv.return = kernel.function("vfs_readv").return { name = "vfs.readv" retstr = sprintf("%d", $return) file = $file dev = __file_dev($file) devname = __find_bdevname(dev, __file_bdev($file)) ino = __file_ino($file) pos = $pos vec = $vec vlen = $vlen bytes_to_read = _get_fopv_size($vec, $vlen) ret = $return bytes_read = $return > 0 ? $return : 0 error = $return < 0 ? $return : 0 error_str = error ? errno_str(error) : "" } probe vfs.write = kernel.function("vfs_write") { file = $file pos = $pos buf = $buf bytes_to_write = $count dev = __file_dev($file) devname = __find_bdevname(dev, __file_bdev($file)) ino = __file_ino($file) name = "vfs.write" argstr = sprintf("%d, %d, %p", $count, $pos, $buf) } probe vfs.write.return = kernel.function("vfs_write").return { name = "vfs.write" retstr = sprintf("%d", $return) file = $file pos = $pos buf = $buf bytes_to_write = $count dev = __file_dev($file) devname = __find_bdevname(dev, __file_bdev($file)) ino = __file_ino($file) ret = $return bytes_written = $return > 0 ? $return : 0 error = $return < 0 ? $return : 0 error_str = error ? errno_str(error) : "" } probe vfs.writev = kernel.function("vfs_writev") { file = $file dev = __file_dev($file) devname = __find_bdevname(dev, __file_bdev($file)) ino = __file_ino($file) pos = $pos vlen = $vlen vec = $vec bytes_to_write = _get_fopv_size($vec, $vlen) name = "vfs.writev" argstr = sprintf("%d, %d, %p", bytes_to_write, $pos, $vec) } probe vfs.writev.return = kernel.function("vfs_writev").return { name = "vfs.writev" retstr = sprintf("%d", $return) file = $file dev = __file_dev($file) devname = __find_bdevname(dev, __file_bdev($file)) ino = __file_ino($file) pos = $pos vlen = $vlen vec = $vec bytes_to_write = _get_fopv_size($vec, $vlen) ret = $return bytes_written = $return > 0 ? $return : 0 error = $return < 0 ? $return : 0 error_str = error ? errno_str(error) : "" } probe _vfs.generic_file_readonly_mmap = kernel.function("generic_file_readonly_mmap") { file = $file vma = $vma name = "_vfs.generic_file_readonly_mmap" argstr = sprintf("%p, %p", $file, $vma) } probe _vfs.generic_file_readonly_mmap.return = kernel.function("generic_file_readonly_mmap").return { name = "_vfs.generic_file_readonly_mmap" retstr = sprintf("%d", $return) file = $file vma = $vma ret = $return error = $return < 0 ? $return : 0 error_str = error ? errno_str(error) : "" } probe _vfs.generic_block_bmap = kernel.function("generic_block_bmap") { mapping = $mapping block = $block get_block = $get_block name = "_vfs.generic_block_bmap" argstr = sprintf("%p, %p, %p", $mapping, $block, $get_block) } probe _vfs.generic_commit_write = kernel.function("generic_commit_write") ? { file = $file page = $page from = $from to = $to name = "_vfs.generic_commit_write" argstr = sprintf("%p, %p, %d, %d", $file, $page, $from, $to) } probe _vfs.block_prepare_write = kernel.function("__block_write_begin") !, kernel.function("__block_prepare_write") { page = $page if (@defined($pos)) { _inode = __page_ino($page) from = $pos & (%{ PAGE_CACHE_SIZE %} - 1) to = from + $len %(systemtap_v < "2.3" %? # write_from and write_upto are deprecated write_from = from write_upto = to %) } else { _inode = $inode %(systemtap_v < "2.3" %? # write_from and write_upto are deprecated write_from = $from write_upto = $to %) from = $from to = $to } name = "_vfs.generic_commit_write" argstr = sprintf("%p, %d, %d", $page, from, to) } probe _vfs.block_prepare_write.return = kernel.function("__block_write_begin").return !, kernel.function("__block_prepare_write").return { name = "_vfs.block_prepare_write" retstr = sprintf("%d", $return) page = $page if (@defined($pos)) { _inode = __page_ino($page) from = $pos & (%{ PAGE_CACHE_SIZE %} - 1) to = from + $len %(systemtap_v < "2.3" %? # write_from and write_upto are deprecated write_from = from write_upto = to %) } else { _inode = $inode %(systemtap_v < "2.3" %? # write_from and write_upto are deprecated write_from = $from write_upto = $to %) from = $from to = $to } page = $page ret = $return error = ret < 0 ? ret : 0 error_str = error ? errno_str(error) : "" } probe _vfs.block_write_begin = kernel.function("block_write_begin") ? { file = @choose_defined($file, 0) pos = $pos len = $len flags = $flags _inode = __address_inode($mapping) name = "_vfs.block_write_begin" argstr = sprintf("%p, %d, %d, %x", file, $pos, $len, $flags) } probe _vfs.block_write_begin.return = kernel.function("block_write_begin").return ? { name = "_vfs.block_write_begin" retstr = sprintf("%d", $return) file = @choose_defined($file, 0) pos = $pos len = $len flags = $flags _inode = __address_inode($mapping) ret = $return error = $return < 0 ? $return : 0 error_str = error ? errno_str(error) : "" } probe _vfs.block_write_end = kernel.function("block_write_end") ? { file = $file pos = $pos len = $len page = $page _inode = __address_inode($mapping) name = "_vfs.block_write_end" argstr = sprintf("%p, %d, %d, %p", $file, $pos, $len, $page) } probe _vfs.block_write_end.return = kernel.function("block_write_end").return ? { name = "_vfs.block_write_end" retstr = sprintf("%d", $return) file = $file pos = $pos len = $len page = $page _inode = __address_inode($mapping) ret = $return } systemtap-2.3/tapset/linux/x86_64/000077500000000000000000000000001217430427200170065ustar00rootroot00000000000000systemtap-2.3/tapset/linux/x86_64/aux_syscalls.stp000066400000000000000000000052231217430427200222520ustar00rootroot00000000000000# Helper for _arch_ptrace_argstr below. %{ #include %} function _arch_ptrace_prctl_str(f) { if (f == %{ ARCH_SET_GS %}) return "ARCH_SET_GS" else if (f == %{ ARCH_SET_FS %}) return "ARCH_SET_FS" else if (f == %{ ARCH_GET_FS %}) return "ARCH_GET_FS" else if (f == %{ ARCH_GET_GS %}) return "ARCH_GET_GS" else return sprintf("?=%d",f) } # arch-specific requests of ptrace ___________________________ # = like tapset/x86_64/syscalls.stp but with PTRACE_ARCH_PRCTL # %{ #ifndef PTRACE_SYSEMU # define PTRACE_SYSEMU 31 #endif #ifndef PTRACE_SYSEMU_SINGLESTEP # define PTRACE_SYSEMU_SINGLESTEP 32 #endif #ifndef PTRACE_SINGLEBLOCK # define PTRACE_SINGLEBLOCK 33 #endif %} function _arch_ptrace_argstr(request, pid, addr, data) { if (request == %{ PTRACE_GETREGS %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GETREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_SETREGS %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SETREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_GETFPREGS %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GETFPREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_SETFPREGS %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SETFPREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_GETFPXREGS %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GETFPXREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_SETFPXREGS %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SETFPXREGS, %d, data=%p", pid, data) if (request == %{ PTRACE_OLDSETOPTIONS %}) return sprintf ("PTRACE_OLDSETOPTIONS, %d, %s", pid, _ptrace_options_str (data)) if (request == %{ PTRACE_GET_THREAD_AREA %}) // TODO: Retrieve *data in .return return sprintf ("PTRACE_GET_THREAD_AREA, %d, index=%d, data=%p", pid, addr, data) if (request == %{ PTRACE_SET_THREAD_AREA %}) // TODO: Retrieve *data here return sprintf ("PTRACE_SET_THREAD_AREA, %d, index=%p, data=%p", pid, addr, data) if (request == %{ PTRACE_ARCH_PRCTL %}) return sprintf ("PTRACE_ARCH_PRCTL, %d, addr=%p, %s", pid, addr, _arch_ptrace_prctl_str(data)) if (request == %{ PTRACE_SYSEMU %}) return sprintf ("PTRACE_SYSEMU, %d, %s", pid, _signal_name (data)) if (request == %{ PTRACE_SYSEMU_SINGLESTEP %}) return sprintf ("PTRACE_SYSEMU_SINGLESTEP, %d, %s", pid, _signal_name (data)) if (request == %{ PTRACE_SINGLEBLOCK %}) return sprintf ("PTRACE_SINGLEBLOCK, %d, %s", pid, _signal_name (data)) } function _ptrace_return_arch_prctl_addr(request, addr, data) { if (request == %{ PTRACE_ARCH_PRCTL %} && (data == %{ ARCH_GET_FS %} || data == %{ ARCH_GET_GS %})) return user_long(addr) } systemtap-2.3/tapset/linux/x86_64/nd_syscalls.stp000066400000000000000000000121251217430427200220550ustar00rootroot00000000000000# x86_64-specific system calls # arch_prctl _________________________________________________ # long sys_arch_prctl(int code, unsigned long addr) # # NOTE: x86_64 only. # probe nd_syscall.arch_prctl = kprobe.function("sys_arch_prctl") { name = "arch_prctl" // code = $code // addr = $addr // argstr = sprintf("%d, %p", $code, $addr) // NB: no asmlinkage() code = int_arg(1) addr = ulong_arg(2) argstr = sprintf("%d, %p", code, addr) } probe nd_syscall.arch_prctl.return = kprobe.function("sys_arch_prctl").return { name = "arch_prctl" retstr = returnstr(1) } # iopl _______________________________________________________ # long sys_iopl(unsigned int level, struct pt_regs *regs); # NOTE. This function is only in i386 and x86_64 and its args vary # between those two archs. # probe nd_syscall.iopl = kprobe.function("sys_iopl") { name = "iopl" // level = (@defined($level) ? $level : $new_iopl) asmlinkage() level = int_arg(1) argstr = sprint(level) } probe nd_syscall.iopl.return = kprobe.function("sys_iopl").return { name = "iopl" retstr = returnstr(1) } %( CONFIG_GENERIC_SIGALTSTACK == "n" || kernel_v < "3.8" %? # sigaltstack ________________________________________________ # long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, # struct pt_regs *regs) # # NOTE: args vary between archs. # probe nd_syscall.sigaltstack = kprobe.function("sys_sigaltstack") { name = "sigaltstack" // uss_uaddr = $uss // uoss_uaddr = $uoss // regs = $regs // argstr = sprintf("%p, %p", $uss, $uoss) asmlinkage() uss_uaddr = pointer_arg(1) uoss_uaddr = pointer_arg(2) %(systemtap_v < "2.3" %? regs_uaddr = pointer_arg(3) regs = pointer_arg(3) %) argstr = sprintf("%p, %p", uss_uaddr, uoss_uaddr) } probe nd_syscall.sigaltstack.return = kprobe.function("sys_sigaltstack").return { name = "sigaltstack" retstr = returnstr(1) } %) # sysctl _____________________________________________________ # # long sys32_sysctl(struct sysctl_ia32 __user *args32) # probe nd_syscall.sysctl32 = kprobe.function("sys32_sysctl") ? { name = "sysctl" // argstr = sprintf("%p", $args32) asmlinkage() argstr = sprintf("%p", pointer_arg(1)) } probe nd_syscall.sysctl32.return = kprobe.function("sys32_sysctl").return ? { name = "sysctl" retstr = returnstr(1) } # In kernels < 2.6.33, mmap()/mmap2() was handled by arch-specific # code. In kernels >= 2.6.33, the arch-specific code just calls # generic sys_mmap_pgoff(). %( kernel_v < "2.6.33" %? # mmap # long sys_mmap(unsigned long addr, unsigned long len, # unsigned long prot, unsigned long flags, # unsigned long fd, unsigned long off) probe nd_syscall.mmap = kprobe.function("sys_mmap") ? { name = "mmap" // start = $addr // len = $len // prot = $prot // flags = $flags // fd = __int32($fd) // offset = $off // argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len, // _mprotect_prot_str($prot), _mmap_flags($flags), // __int32($fd), $off) asmlinkage() start = ulong_arg(1) len = ulong_arg(2) prot = ulong_arg(3) flags = ulong_arg(4) # Although the kernel gets an unsigned long fd, on the # user-side it is a signed int. Fix this. fd = int_arg(5) offset = ulong_arg(6) argstr = sprintf("%p, %d, %s, %s, %d, %d", start, len, _mprotect_prot_str(prot), _mmap_flags(flags), fd, offset) } probe nd_syscall.mmap.return = kprobe.function("sys_mmap").return ? { name = "mmap" retstr = returnstr(2) } # # sys32_mmap(struct mmap_arg_struct __user *arg) # probe nd_syscall.mmap32 = kprobe.function("sys32_mmap") { name = "mmap" // argstr = get_mmap_args($arg) asmlinkage() argstr = get_mmap_args(pointer_arg(1)) } probe nd_syscall.mmap32.return = kprobe.function("sys32_mmap").return { name = "mmap" retstr = returnstr(2) } # sys32_mmap2(unsigned long addr, unsigned long len, # unsigned long prot, unsigned long flags, # unsigned long fd, unsigned long pgoff) # probe nd_syscall.mmap2 = kprobe.function("sys_mmap_pgoff") ?, kprobe.function("sys32_mmap2") ? { name = "mmap2" // argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len, // _mprotect_prot_str($prot), _mmap_flags($flags), // __int32($fd), $pgoff) asmlinkage() argstr = sprintf("%p, %d, %s, %s, %d, %d", ulong_arg(1), ulong_arg(2), _mprotect_prot_str(ulong_arg(3)), _mmap_flags(ulong_arg(4)), int_arg(5), ulong_arg(6)) } probe nd_syscall.mmap2.return = kprobe.function("sys_mmap_pgoff").return ?, kprobe.function("sys32_mmap2").return ? { name = "mmap2" retstr = returnstr(2) } %) # vm86_warning _____________________________________________________ # # long sys32_vm86_warning(void) # probe nd_syscall.vm86_warning = kprobe.function("sys32_vm86_warning") { name = "vm86_warning" argstr = "" } probe nd_syscall.vm86_warning.return = kprobe.function("sys32_vm86_warning").return { name = "wm86_warning" retstr = returnstr(1) } # pipe _______________________________________________________ # # long sys32_pipe(int __user *fd) # probe nd_syscall.pipe32 = kprobe.function("sys32_pipe")? { name = "pipe" // argstr = sprintf("%p", $fd) asmlinkage() argstr = sprintf("%p", pointer_arg(1)) } probe nd_syscall.pipe32.return = kprobe.function("sys32_pipe").return? { name = "pipe" retstr = returnstr(1) } systemtap-2.3/tapset/linux/x86_64/syscalls.stp000066400000000000000000000140531217430427200213760ustar00rootroot00000000000000# x86_64-specific system calls # arch_prctl _________________________________________________ # long sys_arch_prctl(int code, unsigned long addr) # # NOTE: x86_64 only. # probe syscall.arch_prctl = kernel.function("sys_arch_prctl") { name = "arch_prctl" code = $code addr = $addr argstr = sprintf("%d, %p", $code, $addr) } probe syscall.arch_prctl.return = kernel.function("sys_arch_prctl").return { name = "arch_prctl" retstr = return_str(1, $return) } # iopl _______________________________________________________ # long sys_iopl(unsigned int level, struct pt_regs *regs); # NOTE. This function is only in i386 and x86_64 and its args vary # between those two archs. # probe syscall.iopl = kernel.function("sys_iopl") { name = "iopl" level = @choose_defined($level, $new_iopl) argstr = sprint(level) } probe syscall.iopl.return = kernel.function("sys_iopl").return { name = "iopl" retstr = return_str(1, $return) } %( CONFIG_GENERIC_SIGALTSTACK == "n" || kernel_v < "3.8" %? # sigaltstack ________________________________________________ # long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, # struct pt_regs *regs) # # NOTE: args vary between archs. # probe syscall.sigaltstack = kernel.function("sys_sigaltstack") { name = "sigaltstack" uss_uaddr = $uss uoss_uaddr = $uoss # 'regs_uaddr' should have been 'regs'. Deprecate the old name. %(systemtap_v <= "1.4" %? regs_uaddr = $regs %) %(systemtap_v < "2.3" %? regs = $regs %) argstr = sprintf("%p, %p", $uss, $uoss) } probe syscall.sigaltstack.return = kernel.function("sys_sigaltstack").return { name = "sigaltstack" retstr = return_str(1, $return) } %) # sysctl _____________________________________________________ # # long sys32_sysctl(struct sysctl_ia32 __user *args32) # probe syscall.sysctl32 = kernel.function("sys32_sysctl") ? { name = "sysctl" argstr = sprintf("%p", $args32) } probe syscall.sysctl32.return = kernel.function("sys32_sysctl").return ? { name = "sysctl" retstr = return_str(1, $return) } # In kernels < 2.6.33, mmap()/mmap2() was handled by arch-specific # code. In kernels >= 2.6.33, the arch-specific code just calls # generic sys_mmap_pgoff(). %( kernel_v < "2.6.33" %? # mmap # long sys_mmap(unsigned long addr, unsigned long len, # unsigned long prot, unsigned long flags, # unsigned long fd, unsigned long off) probe syscall.mmap = kernel.function("sys_mmap") ? { name = "mmap" start = $addr len = $len prot = $prot flags = $flags # Although the kernel gets an unsigned long fd, on the # user-side it is a signed int. Fix this. fd = __int32($fd) offset = $off argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len, _mprotect_prot_str($prot), _mmap_flags($flags), __int32($fd), $off) } probe syscall.mmap.return = kernel.function("sys_mmap").return ? { name = "mmap" retstr = return_str(2, $return) } # # sys32_mmap(struct mmap_arg_struct32 __user *arg) # sys32_mmap(struct mmap_arg_struct __user *arg) # probe syscall.mmap32 = kernel.function("sys32_mmap") { name = "mmap" if (@defined(@cast($arg, "mmap_arg_struct32")->addr)) { start = user_long(&@cast($arg, "mmap_arg_struct32")->addr) len = user_long(&@cast($arg, "mmap_arg_struct32")->len) prot = user_long(&@cast($arg, "mmap_arg_struct32")->prot) flags = user_long(&@cast($arg, "mmap_arg_struct32")->flags) fd = user_long(&@cast($arg, "mmap_arg_struct32")->fd) offset = user_long(&@cast($arg, "mmap_arg_struct32")->offset) } else { start = user_long(&@cast($arg, "mmap_arg_struct")->addr) len = user_long(&@cast($arg, "mmap_arg_struct")->len) prot = user_long(&@cast($arg, "mmap_arg_struct")->prot) flags = user_long(&@cast($arg, "mmap_arg_struct")->flags) fd = user_long(&@cast($arg, "mmap_arg_struct")->fd) offset = user_long(&@cast($arg, "mmap_arg_struct")->offset) } argstr = sprintf("%p, %d, %s, %s, %d, %d", start, len, _mprotect_prot_str(prot), _mmap_flags(flags), fd, offset) } probe syscall.mmap32.return = kernel.function("sys32_mmap").return { name = "mmap" retstr = return_str(2, $return) } # sys32_mmap2(unsigned long addr, unsigned long len, # unsigned long prot, unsigned long flags, # unsigned long fd, unsigned long pgoff) # The function is removed since 2.6.33 probe syscall.mmap2 = kernel.function("sys_mmap_pgoff") ?, kernel.function("sys32_mmap2") ? { name = "mmap2" start = $addr length = $len prot = $prot flags = $flags # Although the kernel gets an unsigned long fd, on the # user-side it is a signed int. Fix this. fd = __int32($fd) pgoffset = $pgoff argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len, _mprotect_prot_str($prot), _mmap_flags($flags), __int32($fd), $pgoff) } probe syscall.mmap2.return = kernel.function("sys_mmap_pgoff").return ?, kernel.function("sys32_mmap2").return ? { name = "mmap2" retstr = return_str(2, $return) } %) # vm86_warning _____________________________________________________ # # long sys32_vm86_warning(void) # probe syscall.vm86_warning = kernel.function("sys32_vm86_warning") { name = "vm86_warning" argstr = "" } probe syscall.vm86_warning.return = kernel.function("sys32_vm86_warning").return { name = "wm86_warning" retstr = return_str(1, $return) } # pipe _______________________________________________________ # # long sys32_pipe(int __user *fd) # Not available in newer kernels. probe syscall.pipe32 = kernel.function("sys32_pipe")? { name = "pipe" flags = 0; flag_str = "" if (@defined($fd)) { fildes_uaddr = $fd if (fildes_uaddr == 0) { pipe0 = 0; pipe1 = 0; argstr = "NULL" } else { pipe0 = user_int(&$fd[0]); pipe1 = user_int(&$fd[1]); argstr = sprintf("[%d, %d]", pipe0, pipe1); } } else { fildes_uaddr = 0; pipe0 = 0; pipe1 = 0; argstr = "[0, 0]"; } } probe syscall.pipe32.return = kernel.function("sys32_pipe").return? { name = "pipe" flags = 0; if (@defined($fd)) { fildes_uaddr = $fd if (fildes_uaddr == 0) { pipe0 = 0; pipe1 = 0; } else { pipe0 = user_int(&$fd[0]); pipe1 = user_int(&$fd[1]); } } else { fildes_uaddr = 0; pipe0 = 0; pipe1 = 0; } retstr = return_str(1, $return) } systemtap-2.3/tapset/logging.stp000066400000000000000000000050361217430427200170730ustar00rootroot00000000000000// logging tapset // Copyright (C) 2005-2011 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /** * sfunction log - Send a line to the common trace buffer * * @msg: The formatted message string * * Description: This function logs data. log sends the * message immediately to staprun and to the bulk transport * (relayfs) if it is being used. If the last character given * is not a newline, then one is added. This function is not * as efficient as printf and should be used only for urgent * messages. */ function log (msg:string) %{ /* unprivileged */ _stp_printf ("%s\n", STAP_ARG_msg); %} /** * sfunction warn - Send a line to the warning stream * * @msg: The formatted message string * * Description: This function sends a warning message immediately to * staprun. It is also sent over the bulk transport (relayfs) if it is * being used. If the last characater is not a newline, the one is added. */ function warn (msg:string) %{ /* unprivileged */ _stp_warn ("%s", STAP_ARG_msg); %} /** * sfunction exit - Start shutting down probing script. * * Description: This only enqueues a request to start * shutting down the script. New probes will not fire * (except "end" probes), but all currently * running ones may complete their work. */ function exit () %{ /* unprivileged */ atomic_set (session_state(), STAP_SESSION_STOPPING); _stp_exit (); %} /** * sfunction error - Send an error message * * @msg: The formatted message string * * Description: An implicit end-of-line is added. staprun prepends * the string "ERROR:". Sending an error message aborts the currently * running probe. Depending on the MAXERRORS parameter, it may * trigger an exit(). */ function error (msg:string) %{ /* unprivileged */ /* This is an assignment of a local char[] to a global char*. It would normally be just as unsafe as returning a pointer to a local variable from a function. However, the translated code ensures that upon an error (last_error != NULL), the context stack is only ever unwound, and not reused, before the probe-level stp-error call. */ CONTEXT->last_error = STAP_ARG_msg; CONTEXT->last_stmt = NULL; %} function stp_print_binary(n:long, arg1:long, arg2:long, arg3:long, arg4:long) %{ _stp_print_binary (STAP_ARG_n, STAP_ARG_arg1, STAP_ARG_arg2, STAP_ARG_arg3, STAP_ARG_arg4); %} systemtap-2.3/tapset/null.stp000066400000000000000000000000211217430427200164040ustar00rootroot00000000000000 global NULL = 0 systemtap-2.3/tapset/pn.stp000066400000000000000000000014201217430427200160530ustar00rootroot00000000000000// probe-name tapset // Copyright (C) 2010, 2011 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. %{ #ifndef STP_NEED_PROBE_NAME #define STP_NEED_PROBE_NAME 1 #endif %} /** * sfunction pn - Returns the active probe name * * Description: This function returns the script-level probe point * associated with a currently running probe handler, including * wild-card expansion effects. Context: The current probe point. */ function pn:string () %{ /* pure */ /* unprivileged */ const char* name = CONTEXT->probe_name ?: CONTEXT->probe_point; strlcpy (STAP_RETVALUE, name, MAXSTRINGLEN); %} systemtap-2.3/tapset/powerpc/000077500000000000000000000000001217430427200163705ustar00rootroot00000000000000systemtap-2.3/tapset/powerpc/registers.stp000066400000000000000000000127051217430427200211340ustar00rootroot00000000000000/* Dwarfless register access for powerpc */ global _reg_offsets, _stp_regs_registered function _stp_register_regs() { /* Same order as pt_regs */ _reg_offsets["r0"] = 0 _reg_offsets["r1"] = 8 _reg_offsets["r2"] = 16 _reg_offsets["r3"] = 24 _reg_offsets["r4"] = 32 _reg_offsets["r5"] = 40 _reg_offsets["r6"] = 48 _reg_offsets["r7"] = 56 _reg_offsets["r8"] = 64 _reg_offsets["r9"] = 72 _reg_offsets["r10"] = 80 _reg_offsets["r11"] = 88 _reg_offsets["r12"] = 96 _reg_offsets["r13"] = 104 _reg_offsets["r14"] = 112 _reg_offsets["r15"] = 120 _reg_offsets["r16"] = 128 _reg_offsets["r17"] = 136 _reg_offsets["r18"] = 144 _reg_offsets["r19"] = 152 _reg_offsets["r20"] = 160 _reg_offsets["r21"] = 168 _reg_offsets["r22"] = 176 _reg_offsets["r23"] = 184 _reg_offsets["r24"] = 192 _reg_offsets["r25"] = 200 _reg_offsets["r26"] = 208 _reg_offsets["r27"] = 216 _reg_offsets["r28"] = 224 _reg_offsets["r29"] = 232 _reg_offsets["r30"] = 240 _reg_offsets["r31"] = 248 _reg_offsets["nip"] = 256 _reg_offsets["msr"] = 264 _reg_offsets["orig_gpr3"] = 272 _reg_offsets["ctr"] = 280 _reg_offsets["link"] = 288 _reg_offsets["xer"] = 296 _reg_offsets["ccr"] = 304 _reg_offsets["softe"] = 312 _reg_offsets["trap"] = 320 _reg_offsets["dar"] = 328 _reg_offsets["dsisr"] = 336 _reg_offsets["result"] = 344 /* * If we ever need to support 32bit powerpc, we can * get to the register offsets by using just a * reg32_offset = _reg_offsets["reg"]/2 * or somesuch */ _stp_regs_registered = 1 } function probing_32bit_app() %{ /* pure */ STAP_RETVALUE = (CONTEXT->user_mode_p && _stp_is_compat_task()); %} function _stp_get_register_by_offset:long (offset:long) %{ /* pure */ long value; struct pt_regs *regs; regs = (CONTEXT->user_mode_p ? CONTEXT->uregs : CONTEXT->kregs); if (!regs) { CONTEXT->last_error = "No registers available in this context"; return; } if (STAP_ARG_offset < 0 || STAP_ARG_offset > sizeof(struct pt_regs) - sizeof(long)) { snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "Bad register offset: %lld", (long long)STAP_ARG_offset); CONTEXT->last_error = CONTEXT->error_buffer; return; } memcpy(&value, ((char *)regs) + STAP_ARG_offset, sizeof(value)); STAP_RETVALUE = value; %} function _stp_sign_extend32:long (value:long) { if (value & 0x80000000) value |= (0xffffffff << 32) return value } function _stp_register:long (name:string, sign_extend:long) { if (!registers_valid()) { error("cannot access CPU registers in this context") return 0 } if (!_stp_regs_registered) _stp_register_regs() offset = _reg_offsets[name] if (offset == 0 && !(name in _reg_offsets)) { error("Unknown register: " . name) return 0 } value = _stp_get_register_by_offset(offset) if (probing_32bit_app()) { if (sign_extend) value = _stp_sign_extend32(value) else value &= 0xffffffff } return value } /* Return the named register value as a signed value. */ function register:long (name:string) { return _stp_register(name, 1) } /* * Return the named register value as an unsigned value. Specifically, * don't sign-extend the register value when promoting it to 64 bits. */ function u_register:long (name:string) { return _stp_register(name, 0) } /* * Return the value of function arg #argnum (1=first arg). * If truncate=1, mask off the top 32 bits. * If sign_extend=1 and (truncate=1 or the probepoint we've hit is in a * 32-bit app), sign-extend the 32-bit value. */ function _stp_arg:long (argnum:long, sign_extend:long, truncate:long) { val = 0 if (argnum < 1 || argnum > 8) { error(sprintf("Cannot access arg(%d)", argnum)) return 0 } if (argnum == 1) val = u_register("r3") else if (argnum == 2) val = u_register("r4") else if (argnum == 3) val = u_register("r5") else if (argnum == 4) val = u_register("r6") else if (argnum == 5) val = u_register("r7") else if (argnum == 6) val = u_register("r8") else if (argnum == 7) val = u_register("r9") else if (argnum == 8) val = u_register("r10") if (truncate) { if (sign_extend) val = _stp_sign_extend32(val) else /* High bits may be garbage. */ val = (val & 0xffffffff); } return val; } /* Return the value of function arg #argnum (1=first arg) as a signed int. */ function int_arg:long (argnum:long) { return _stp_arg(argnum, 1, 1) } /* Return the value of function arg #argnum (1=first arg) as an unsigned int. */ function uint_arg:long (argnum:long) { return _stp_arg(argnum, 0, 1) } function long_arg:long (argnum:long) { return _stp_arg(argnum, 1, 0) } function ulong_arg:long (argnum:long) { return _stp_arg(argnum, 0, 0) } function longlong_arg:long (argnum:long) { if (probing_32bit_app()) { lowbits = _stp_arg(argnum, 0, 1) highbits = _stp_arg(argnum+1, 0, 1) return ((highbits << 32) | lowbits) } else return _stp_arg(argnum, 0, 0) } function ulonglong_arg:long (argnum:long) { return longlong_arg(argnum) } function pointer_arg:long (argnum:long) { return _stp_arg(argnum, 0, 0) } function s32_arg:long (argnum:long) { return int_arg(argnum) } function u32_arg:long (argnum:long) { return uint_arg(argnum) } function s64_arg:long (argnum:long) { return longlong_arg(argnum) } function u64_arg:long (argnum:long) { return ulonglong_arg(argnum) } function asmlinkage() %{ /* pure */ %} function fastcall() %{ /* pure */ %} function regparm(n:long) %{ snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "regparm is invalid on powerpc."); CONTEXT->last_error = CONTEXT->error_buffer; %} systemtap-2.3/tapset/queue_stats.stp000066400000000000000000000223331217430427200200060ustar00rootroot00000000000000# qstats.stp: Queue statistics gathering tapset /* * The queue_stats tapset provides functions that, * given notifications of elementary queuing events (wait, run, done), * tracks averages such as queue length, service and wait times, * utilization. * * The functions qs_wait(), qs_run(), and qs_done() should be called * from appropriate probes, in sequence. * * Functions with the prefix qsq_ are for querying the statistics averaged * since the first queue operation (or when qsq_start() was called). * Since statistics are often fractional, a scale parameter is used to * multiply the result to a more useful scale. For some fractions, a scale * of 100 will usefully return percentage numbers. * */ # ------------------------------------------------------------------------ # The default timing function: microseconds. This function could # go into a separate file (say, qstats_qs_time.stp), so that a user # script can override it with another definition. /* XXX: docstring */ function qs_time () { return gettimeofday_us () } # ------------------------------------------------------------------------ global qs_wtime, qs_wlentime, qs_wcount global qs_rtime, qs_rlentime, qs_rcount global qs_stime, qs_utime, qs_dcount # ------------------------------------------------------------------------ function _qs_update (qname) { now = qs_time () then = qs_utime[qname]; if (! then) { then = now } delta = now-then qs_wtime[qname] += qs_wcount[qname] ? delta : 0 qs_wlentime[qname] += qs_wcount[qname] * delta qs_rtime[qname] += qs_rcount[qname] ? delta : 0 qs_rlentime[qname] += qs_rcount[qname] * delta qs_utime[qname] = now } /** * sfunction qs_wait - Function to record enqueue requests * @qname: the name of the queue requesting enqueue * * Description: This function records that a new request * was enqueued for the given queue name. */ function qs_wait (qname:string) { # enqueueing request _qs_update (qname) qs_wcount[qname] ++ } /** * sfunction qs_run - Function to record being moved from wait queue to being serviced * @qname: the name of the service being moved and started * * Description: This function records that the previous enqueued * request was removed from the given wait queue and is now * being serviced. */ function qs_run (qname:string) { # starting to service request _qs_update (qname) if (qs_wcount[qname] > 0) { qs_wcount[qname] -- qs_rcount[qname] ++ } } /** * sfunction qs_done - Function to record finishing request * @qname: the name of the service that finished * * Description: This function records that a request * originally from the given queue has completed being * serviced. */ function qs_done (qname:string) { # done servicing request _qs_update (qname) if (qs_rcount[qname] > 0) { qs_rcount[qname] -- qs_dcount[qname] ++ } } # ------------------------------------------------------------------------ /** * sfunction qsq_start - Function to reset the stats for a queue * @qname: the name of the service that finished * * Description: This function resets the statistics counters for the given * queue, and restarts tracking from the moment the function was called. * This function is also used to create intialize a queue. */ function qsq_start (qname:string) { # reset statistics for new baseline qs_rcount[qname] = 0 delete qs_rtime[qname] delete qs_rlentime[qname] qs_wcount[qname] = 0 delete qs_wtime[qname] delete qs_wlentime[qname] delete qs_dcount[qname] delete qs_utime[qname] qs_stime[qname] = qs_time () } # ------------------------------------------------------------------------ # Various query functions. Each returns the average, taken over the time # interval from the last qsq_start(). Most deal with fractions, and so # also take a scale parameter (use 100 for percent). /** * sfunction qsq_utilization - Fraction of time that any request was being serviced * @qname: queue name * @scale: scale variable to take account for interval fraction * * Description: This function returns the average time in microseconds * that at least one request was being serviced. */ function qsq_utilization:long (qname:string, scale:long) { _qs_update (qname) elapsed = qs_time() - qs_stime[qname] return (scale * qs_rtime[qname]) / elapsed } # fraction of time that any request was blocked in the wait queue /** * sfunction qsq_blocked - Returns the time reqest was on the wait queue * @qname: queue name * @scale: scale variable to take account for interval fraction * * Description: This function returns the fraction of elapsed time during * which one or more requests were on the wait queue. */ function qsq_blocked:long (qname:string, scale:long) { _qs_update (qname) elapsed = qs_time() - qs_stime[qname] return (scale * qs_wtime[qname]) / elapsed } # length of wait queue /** * sfunction qsq_wait_queue_length - length of wait queue * @qname: queue name * @scale: scale variable to take account for interval fraction * * Description: This function returns the average length of the wait queue */ function qsq_wait_queue_length:long (qname:string, scale:long) { _qs_update (qname) elapsed = qs_time() - qs_stime[qname] return (scale * qs_wlentime[qname]) / elapsed } /** * sfunction qsq_service_time - Amount of time per request service * @qname: queue name * @scale: scale variable to take account for interval fraction * * Description: This function returns the average time in microseconds * required to service a request once it is removed from the wait queue. */ function qsq_service_time:long (qname:string, scale:long) { _qs_update (qname) return (scale * qs_rlentime[qname]) / qs_dcount[qname] } /** * sfunction qsq_wait_time - Amount of time in queue + service per request * @qname: queue name * @scale: scale variable to take account for interval fraction * * Description: This function returns the average time in microseconds * that it took for a request to be serviced (qs_wait() to qa_done()). */ function qsq_wait_time:long (qname:string, scale:long) { _qs_update (qname) return (scale * (qs_rlentime[qname] + qs_wlentime[qname])) / qs_dcount[qname] } /** * sfunction qsq_throughput - Number of requests served per unit time * @qname: queue name * @scale: scale variable to take account for interval fraction * * Description: This function returns the average number or requests * served per microsecond. */ function qsq_throughput:long (qname:string, scale:long) { _qs_update (qname) elapsed = qs_time() - qs_stime[qname] return (scale * qs_dcount[qname]) / elapsed } # ------------------------------------------------------------------------ /** * sfunction qsq_print - Prints a line of statistics for the given queue * @qname: queue name * * Description: This function prints a line containing the following * statistics for the given queue: * the queue name, * the average rate of requests per second, * the average wait queue length, * the average time on the wait queue, * the average time to service a request, * the percentage of time the wait queue was used, * and the percentage of time request was being serviced. */ function qsq_print (qname:string) { qt = qsq_throughput (qname, 1000000000) # 1000 * (number of requests served per second) qwl = qsq_wait_queue_length (qname, 1000) printf("%s: %d.%03d ops/s, %d.%03d qlen, %d await, %d svctm, %d%% wait, %d%% util\n", qname, qt/1000, qt%1000, qwl/1000, qwl%1000, qsq_wait_time (qname, 1), qsq_service_time (qname, 1), qsq_blocked (qname, 100), qsq_utilization (qname, 100)) } /* What follows in an example form src/testsuite/systemtap.samples/queue_demo.stp * It uses the randomize feature of the timer probe to simulate queuing activity. * * probe begin { * qsq_start ("block-read") * qsq_start ("block-write") * } * * probe timer.ms(3500), end { * qsq_print ("block-read") * qsq_start ("block-read") * qsq_print ("block-write") * qsq_start ("block-write") * } * * probe timer.ms(10000) { * exit() * } * * // synthesize queue work/service using three randomized "threads" for each queue. * global tc * * function qs_doit (thread, name) { * n = tc[thread] = (tc[thread]+1) % 3 //per-thread state counter * if (n==1) qs_wait (name) * else if (n==2) qs_run (name) * else if (n==0) qs_done (name) * } * * probe timer.ms(100).randomize(100) { qs_doit (0, "block-read") } * probe timer.ms(100).randomize(100) { qs_doit (1, "block-read") } * probe timer.ms(100).randomize(100) { qs_doit (2, "block-read") } * probe timer.ms(100).randomize(100) { qs_doit (3, "block-write") } * probe timer.ms(100).randomize(100) { qs_doit (4, "block-write") } * probe timer.ms(100).randomize(100) { qs_doit (5, "block-write") } * * //This prints: * block-read: 9 ops/s, 1.090 qlen, 215749 await, 96382 svctm, 69% wait, 64% util * block-write: 9 ops/s, 0.992 qlen, 208485 await, 103150 svctm, 69% wait, 61% util * block-read: 9 ops/s, 0.968 qlen, 197411 await, 97762 svctm, 63% wait, 63% util * block-write: 8 ops/s, 0.930 qlen, 202414 await, 93870 svctm, 60% wait, 56% util * block-read: 8 ops/s, 0.744 qlen, 192957 await, 99995 svctm, 58% wait, 62% util * block-write: 9 ops/s, 0.861 qlen, 193857 await, 101573 svctm, 56% wait, 64% util */ systemtap-2.3/tapset/random.stp000066400000000000000000000006411217430427200167220ustar00rootroot00000000000000/** * sfunction randint - Return a random number between [0,n) * @n: Number past upper limit of range, not larger than 2**20. */ function randint:long(n:long) %{ /* unprivileged */ #define RANDMAX (1024*1024) if (STAP_ARG_n > RANDMAX) CONTEXT->last_error = "range too wide"; else { STAP_RETVALUE = (uint64_t) _stp_random_u((unsigned long) STAP_ARG_n); } #undef RANDMAX %} systemtap-2.3/tapset/registers.stp000066400000000000000000000164621217430427200174610ustar00rootroot00000000000000/* This is a stub tapset documenting a number of * architecture-dependent functions. For actual implementation of the * functions, see tapset/ARCH/registers.stp. */ /* * The functions in this tapset can be used to access information * from the context at the time a probe point was hit. This includes * functions to access named CPU registers, and functions that provide * the values of a probed function's arguments. (The latter can be * called when you have hit a probe point at the entry to a function, * and are useful when the code you are probing was built without debugging * information.) * * Function arguments are referred to by number, starting at 1. * On 32-bit architectures * (and when probing 32-bit applications on 64-bit architectures) * a 64-bit argument occupies two "arg slots." * For example, if you are probing the following function * * void f(int a, long long b, char *c) * * you would refer to a, b, and c as int_arg(1), longlong_arg(2), and * pointer_arg(3), respectively, on a 64-bit architecture; * but on a 32-bit architecture, you would refer to c as pointer_arg(4) * (since b occupies slots 2 and 3). * * If the function you are probing doesn't follow the default rules * for argument passing, you need to call one of the following functions * in your handler before calling any *_arg function: * asmlinkage(), fastcall(), or regparm(). * (This isn't necessary when referring to arguments only by name.) * * For some architectures, the *_arg functions may reject unusually * high values of n. * */ %( kernel_vr == "invalidkernel" %? /** * sfunction register - Return the signed value of the named CPU register * * @name: Name of the register to return * * Description: Return the value of the named CPU register, * as it was saved when the current probe point was hit. * If the register is 32 bits, it is sign-extended to 64 bits. * * For the i386 architecture, the following names are recognized. * (name1/name2 indicates that name1 and name2 are alternative names * for the same register.) * eax/ax, ebp/bp, ebx/bx, ecx/cx, edi/di, edx/dx, eflags/flags, * eip/ip, esi/si, esp/sp, orig_eax/orig_ax, * xcs/cs, xds/ds, xes/es, xfs/fs, xss/ss. * * For the x86_64 architecture, the following names are recognized: * 64-bit registers: * r8, r9, r10, r11, r12, r13, r14, r15, * rax/ax, rbp/bp, rbx/bx, rcx/cx, rdi/di, rdx/dx, * rip/ip, rsi/si, rsp/sp; * 32-bit registers: * eax, ebp, ebx, ecx, edx, edi, edx, eip, esi, esp, flags/eflags, * orig_eax; segment registers: xcs/cs, xss/ss. * * For powerpc, the following names are recognized: * r0, r1, ... r31, nip, msr, orig_gpr3, ctr, link, xer, ccr, softe, trap, * dar, dsisr, result. * * For s390x, the following names are recognized: * r0, r1, ... r15, args, psw.mask, psw.addr, orig_gpr2, ilc, trap. */ function register:long (name:string) { } /** * sfunction u_register - Return the unsigned value of the named CPU register * * @name: Name of the register to return * * Description: Same as register(name), except that if the register * is 32 bits wide, it is zero-extended to 64 bits. */ function u_register:long (name:string) { } /** * sfunction int_arg - Return function argument as signed int * * @n: index of argument to return * * Description: Return the value of argument n as a signed int * (i.e., a 32-bit integer sign-extended to 64 bits). */ function int_arg:long (n:long) { } /** * sfunction uint_arg - Return function argument as unsigned int * * @n: index of argument to return * * Description: Return the value of argument n as an unsigned int * (i.e., a 32-bit integer zero-extended to 64 bits). */ function uint_arg:long (n:long) { } /** * sfunction long_arg - Return function argument as signed long * * @n: index of argument to return * * Description: Return the value of argument n as a signed long. * On architectures where a long is 32 bits, the value is sign-extended * to 64 bits. */ function long_arg:long (n:long) { } /** * sfunction ulong_arg - Return function argument as unsigned long * * @n: index of argument to return * * Description: Return the value of argument n as an unsigned long. * On architectures where a long is 32 bits, the value is zero-extended * to 64 bits. */ function ulong_arg:long (n:long) { } /** * sfunction longlong_arg - Return function argument as 64-bit value * * @n: index of argument to return * * Description: Return the value of argument n as a 64-bit value. */ function longlong_arg:long (n:long) { } /** * sfunction ulonglong_arg - Return function argument as 64-bit value * * @n: index of argument to return * * Description: Return the value of argument n as a 64-bit value. * (Same as longlong_arg.) */ function ulonglong_arg:long (n:long) { } /** * sfunction pointer_arg - Return function argument as pointer value * * @n: index of argument to return * * Description: Return the unsigned value of argument n, same as ulong_arg. * Can be used with any type of pointer. */ function pointer_arg:long (n:long) { } /** * sfunction s32_arg - Return function argument as signed 32-bit value * * @n: index of argument to return * * Description: Return the signed 32-bit value of argument n, * same as int_arg. */ function s32_arg:long (n:long) { } /** * sfunction u32_arg - Return function argument as unsigned 32-bit value * * @n: index of argument to return * * Description: Return the unsigned 32-bit value of argument n, * same as uint_arg. */ function u32_arg:long (n:long) { } /** * sfunction s64_arg - Return function argument as signed 64-bit value * * @n: index of argument to return * * Description: Return the signed 64-bit value of argument n, * same as longlong_arg. */ function s64_arg:long (n:long) { } /** * sfunction u64_arg - Return function argument as unsigned 64-bit value * * @n: index of argument to return * * Description: Return the unsigned 64-bit value of argument n, * same as ulonglong_arg. */ function u64_arg:long (n:long) { } /** * sfunction asmlinkage - Mark function as declared asmlinkage * * Description: Call this function before accessing arguments * using the *_arg functions * if the probed kernel function was declared asmlinkage in the source. */ function asmlinkage() { } /** * sfunction fastcall - Mark function as declared fastcall * * Description: Call this function before accessing arguments * using the *_arg functions * if the probed kernel function was declared fastcall in the source. */ function fastcall() { } /** * sfunction regparm - Specify regparm value used to compile function * * @n: original regparm value * * Description: Call this function with argument n before accessing function * arguments using the *_arg function is the function was build with the * gcc -mregparm=n option. * * (The i386 kernel is built with \-mregparm=3, so systemtap considers * regparm(3) the default for kernel functions on that architecture.) * Only valid on i386 and x86_64 (when probing 32bit applications). * Produces an error on other architectures. */ function regparm(n:long) { } %) /* * In nd_syscall.return probes, we sometimes need @entry() values. To * ensure we get the argument in the correct mode, we need a function * that calls asmlinkage() first. */ function __asmlinkage_int_arg:long(n:long) { asmlinkage() return int_arg(n) } systemtap-2.3/tapset/s390/000077500000000000000000000000001217430427200154075ustar00rootroot00000000000000systemtap-2.3/tapset/s390/registers.stp000066400000000000000000000132311217430427200201460ustar00rootroot00000000000000/* Dwarfless register access for s390x */ global _reg_offsets, _stp_regs_registered function _stp_register_regs() { /* Same order as pt_regs */ _reg_offsets["args"] = 0 _reg_offsets["psw.mask"] = 8 _reg_offsets["psw.addr"] = 16 _reg_offsets["r0"] = 24 _reg_offsets["r1"] = 32 _reg_offsets["r2"] = 40 _reg_offsets["r3"] = 48 _reg_offsets["r4"] = 56 _reg_offsets["r5"] = 64 _reg_offsets["r6"] = 72 _reg_offsets["r7"] = 80 _reg_offsets["r8"] = 88 _reg_offsets["r9"] = 96 _reg_offsets["r10"] = 104 _reg_offsets["r11"] = 112 _reg_offsets["r12"] = 120 _reg_offsets["r13"] = 128 _reg_offsets["r14"] = 136 _reg_offsets["r15"] = 144 _reg_offsets["orig_gpr2"] = 152 _reg_offsets["ilc"] = 160 _reg_offsets["trap"] = 162 /* * If we ever need to support s390 (31-bit arch), we can * get to the register offsets by using just a * reg32_offset = _reg_offsets["reg"]/2 * or somesuch */ _stp_regs_registered = 1 } /* * Though the flag says 31bit, asm-s390/thread_info.h comment * says "32bit process" */ function probing_32bit_app() %{ /* pure */ if (CONTEXT->user_mode_p && _stp_is_compat_task()) STAP_RETVALUE = 1; else STAP_RETVALUE = 0; %} function _stp_probing_kernel: long () { return !user_mode(); } function _stp_get_register_by_offset:long (offset:long) %{ /* pure */ long value; struct pt_regs *regs; regs = (CONTEXT->user_mode_p ? CONTEXT->uregs : CONTEXT->kregs); if (!regs) { CONTEXT->last_error = "No registers available in this context"; return; } if (STAP_ARG_offset < 0 || STAP_ARG_offset > sizeof(struct pt_regs) - sizeof(unsigned short)) { snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "Bad register offset: %lld", (long long)STAP_ARG_offset); CONTEXT->last_error = CONTEXT->error_buffer; return; } if (STAP_ARG_offset < sizeof(struct pt_regs) - 2 * sizeof(unsigned short)) memcpy(&value, ((char *)regs) + STAP_ARG_offset, sizeof(value)); else { /* ilc or trap */ unsigned short us_value; memcpy(&us_value, ((char *)regs) + STAP_ARG_offset, sizeof(us_value)); value = us_value; // not sign-extended } STAP_RETVALUE = value; %} function _stp_sign_extend32:long (value:long) { if (value & 0x80000000) value |= (0xffffffff << 32) return value } function _stp_register:long (name:string, sign_extend:long) { if (!registers_valid()) { error("cannot access CPU registers in this context") return 0 } if (!_stp_regs_registered) _stp_register_regs() offset = _reg_offsets[name] if (offset == 0 && !(name in _reg_offsets)) { error("Unknown register: " . name) return 0 } value = _stp_get_register_by_offset(offset) if (probing_32bit_app()) { if (sign_extend) value = _stp_sign_extend32(value) else value &= 0xffffffff } return value } /* Return the named register value as a signed value. */ function register:long (name:string) { return _stp_register(name, 1) } /* * Return the named register value as an unsigned value. Specifically, * don't sign-extend the register value when promoting it to 64 bits. */ function u_register:long (name:string) { return _stp_register(name, 0) } /* * Return the value of function arg #argnum (1=first arg). * If truncate=1, mask off the top 32 bits. * If sign_extend=1 and (truncate=1 or the probepoint we've hit is in a * 32-bit app), sign-extend the 32-bit value. */ function _stp_arg:long (argnum:long, sign_extend:long, truncate:long) %{ /* pure */ unsigned long val = 0; struct pt_regs *regs; STAP_RETVALUE = 0; if (STAP_ARG_argnum < 1 || STAP_ARG_argnum > 6) { snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "Cannot access arg %d", (int)STAP_ARG_argnum); CONTEXT->last_error = CONTEXT->error_buffer; return; } if (CONTEXT->user_mode_p) { CONTEXT->last_error = ("Cannot access function args in" " user context"); return; } regs = CONTEXT->kregs; if (!regs) { CONTEXT->last_error = ("Cannot access function args" " (no registers available)"); return; } syscall_get_arguments(current, regs, (((int)STAP_ARG_argnum) - 1), 1, &val); if (STAP_ARG_truncate || _stp_is_compat_task()) { if (STAP_ARG_sign_extend) STAP_RETVALUE = (int64_t) (int32_t) val; else /* High bits may be garbage. */ STAP_RETVALUE = (int64_t) (val & 0xffffffff); } else STAP_RETVALUE = (int64_t) val; return; %} /* Return the value of function arg #argnum (1=first arg) as a signed int. */ function int_arg:long (argnum:long) { return _stp_arg(argnum, 1, 1) } /* Return the value of function arg #argnum (1=first arg) as an unsigned int. */ function uint_arg:long (argnum:long) { return _stp_arg(argnum, 0, 1) } function long_arg:long (argnum:long) { return _stp_arg(argnum, 1, 0) } function ulong_arg:long (argnum:long) { return _stp_arg(argnum, 0, 0) } function longlong_arg:long (argnum:long) { if (probing_32bit_app()) { /* TODO verify if this is correct for 31bit apps */ highbits = _stp_arg(argnum, 0, 1) lowbits = _stp_arg(argnum+1, 0, 1) return ((highbits << 32) | lowbits) } else return _stp_arg(argnum, 0, 0) } function ulonglong_arg:long (argnum:long) { return longlong_arg(argnum) } function pointer_arg:long (argnum:long) { return _stp_arg(argnum, 0, 0) } function s32_arg:long (argnum:long) { return int_arg(argnum) } function u32_arg:long (argnum:long) { return uint_arg(argnum) } function s64_arg:long (argnum:long) { return longlong_arg(argnum) } function u64_arg:long (argnum:long) { return ulonglong_arg(argnum) } function asmlinkage() %{ /* pure */ %} function fastcall() %{ /* pure */ %} function regparm(n:long) %{ snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "regparm is invalid on s390."); CONTEXT->last_error = CONTEXT->error_buffer; %} systemtap-2.3/tapset/speculative.stp000066400000000000000000000036451217430427200177750ustar00rootroot00000000000000// Speculative tapset // Copyright (C) 2011 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. global _spec_id global _spec_counter global _spec_buff global _spec_discard /** * sfunction speculation - Allocate a new id for speculative output * * The speculation() function is called when a new speculation buffer is needed. * It returns an id for the speculative output. * There can be multiple threads being speculated on concurrently. * This id is used by other speculation functions to keep the threads * separate. */ function speculation:long () { _spec_id += 1 return _spec_id } /** * sfunction speculate - Store a string for possible output later * @id: buffer id to store the information in * @output: string to write out when commit occurs * * Add a string to the speculaive buffer for id. */ function speculate (id:long, output:string) { _spec_counter[id] += 1 _spec_buff[id, _spec_counter[id]] = output } function _spec_erase (id:long) { foreach([i, counter] in _spec_discard) delete _spec_buff[i, counter] delete _spec_discard } /** * sfunction discard - Discard all output related to a speculation buffer * @id: of the buffer to store the information in * */ function discard (id:long) { foreach([i, counter] in _spec_buff) if (i==id) _spec_discard[i, counter] = 1 _spec_erase (id) } /** * sfunction commit - Write out all output related to a speculation buffer * @id: of the buffer to store the information in * * Output all the output for @id in the order that it was entered into * the speculative buffer by speculative(). */ function commit (id:long) { foreach([i, counter+] in _spec_buff) { if (i==id) { printf("%s", _spec_buff[i, counter]) _spec_discard[i, counter] = 1 } } _spec_erase (id) } systemtap-2.3/tapset/stap_staticmarkers.stp000066400000000000000000000227061217430427200213530ustar00rootroot00000000000000// stap/staprun/stapio static probes tapset // // Copyright (C) 2009 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /** * probe stap.pass0 - Starting stap pass0 (parsing command line arguments) * * @session: the systemtap_session variable s * * pass0 fires after command line arguments have been parsed. */ probe stap.pass0 = process("stap").mark("pass0__start") { session = $arg1 } /** * probe stap.pass0.end - Finished stap pass0 (parsing command line arguments) * @session: the systemtap_session variable s * * pass0.end fires just before the gettimeofday() call for pass1. */ probe stap.pass0.end = process("stap").mark("pass0__end") { session = $arg1 } /** * probe stap.pass1a - Starting stap pass1 (parsing user script) * @session: the systemtap_session variable s * * pass1a fires just after the call to gettimeofday(), before the * user script is parsed. */ probe stap.pass1a = process("stap").mark("pass1a__start") { session = $arg1 } /** * probe stap.pass1b - Starting stap pass1 (parsing library scripts) * @session: the systemtap_session variable s * * pass1b fires just before the library scripts are parsed. */ probe stap.pass1b = process("stap").mark("pass1b__start") { session = $arg1 } /** * probe stap.pass1.end - Finished stap pass1 (parsing scripts) * @session: the systemtap_session variable s * * pass1.end fires just before the jump to cleanup if s.last_pass = 1. */ probe stap.pass1.end = process("stap").mark("pass1__end") { session = $arg1 } /** * probe stap.pass2 - Starting stap pass2 (elaboration) * @session: the systemtap_session variable s * * pass2 fires just after the call to gettimeofday(), just before the * call to semantic_pass. */ probe stap.pass2 = process("stap").mark("pass2__start") { session = $arg1 } /** * probe stap.pass2.end - Finished stap pass2 (elaboration) * @session: the systemtap_session variable s * * pass2.end fires just before the jump to cleanup if s.last_pass = 2 */ probe stap.pass2.end = process("stap").mark("pass2__end") { session = $arg1 } /** * probe stap.pass3 - Starting stap pass3 (translation to C) * @session: the systemtap_session variable s * * pass3 fires just after the call to gettimeofday(), just before the * call to translate_pass. */ probe stap.pass3 = process("stap").mark("pass3__start") { session = $arg1 } /** * probe stap.pass3.end - Finished stap pass3 (translation to C) * @session: the systemtap_session variable s * * pass3.end fires just before the jump to cleanup if s.last_pass = 3 */ probe stap.pass3.end = process("stap").mark("pass3__end") { session = $arg1 } /** * probe stap.pass4 - Starting stap pass4 (compile C code into kernel module) * @session: the systemtap_session variable s * * pass4 fires just after the call to gettimeofday(), just before the * call to compile_pass. */ probe stap.pass4 = process("stap").mark("pass4__start") { session = $arg1 } /** * probe stap.pass4.end - Finished stap pass4 (compile C code into kernel module) * @session: the systemtap_session variable s * * pass4.end fires just before the jump to cleanup if s.last_pass = 4 */ probe stap.pass4.end = process("stap").mark("pass4__end") { session = $arg1 } /** * probe stap.pass5 - Starting stap pass5 (running the instrumentation) * @session: the systemtap_session variable s * * pass5 fires just after the call to gettimeofday(), just before the * call to run_pass. */ probe stap.pass5 = process("stap").mark("pass5__start") { session = $arg1 } /** * probe stap.pass5.end - Finished stap pass5 (running the instrumentation) * @session: the systemtap_session variable s * * pass5.end fires just before the cleanup label */ probe stap.pass5.end = process("stap").mark("pass5__end") { session = $arg1 } /** * probe stap.pass6 - Starting stap pass6 (cleanup) * @session: the systemtap_session variable s * * pass6 fires just after the cleanup label, essentially the same spot * as pass5.end */ probe stap.pass6 = process("stap").mark("pass6__start") { session = $arg1 } /** * probe stap.pass6.end - Finished stap pass6 (cleanup) * @session: the systemtap_session variable s * * pass6.end fires just before main's return. */ probe stap.pass6.end = process("stap").mark("pass6__end") { session = $arg1 } /** * probe stap.cache_clean - Removing file from stap cache * @path: the path to the .ko/.c file being removed * * Fires just before the call to unlink the module/source file. */ probe stap.cache_clean = process("stap").mark("cache__clean") { path = user_string_quoted($arg1) } /** * probe stap.cache_add_mod - Adding kernel instrumentation module to cache * @source_path: the path the .ko file is coming from (incl filename) * @dest_path: the path the .ko file is going to (incl filename) * * Fires just before the file is actually moved. Note: if moving fails, * cache_add_src and cache_add_nss will not fire. */ probe stap.cache_add_mod = process("stap").mark("cache__add__module") { source_path = user_string_quoted($arg1) dest_path = user_string_quoted($arg2) } /** * probe stap.cache_add_src - Adding C code translation to cache * @source_path: the path the .c file is coming from (incl filename) * @dest_path: the path the .c file is going to (incl filename) * * Fires just before the file is actually moved. Note: if moving the * kernel module fails, this probe will not fire. */ probe stap.cache_add_src = process("stap").mark("cache__add__source") { source_path = user_string_quoted($arg1) dest_path = user_string_quoted($arg2) } /** * probe stap.cache_add_nss - Add NSS (Network Security Services) information to cache * @source_path: the path the .sgn file is coming from (incl filename) * @dest_path: the path the .sgn file is coming from (incl filename) * * Fires just before the file is actually moved. Note: stap must compiled * with NSS support; if moving the kernel module fails, this probe will * not fire. */ probe stap.cache_add_nss = process("stap").mark("cache__add__nss") ? { source_path = user_string_quoted($arg1) dest_path = user_string_quoted($arg2) } /** * probe stap.cache_get - Found item in stap cache * @source_path: the path of the .c source file * @module_path: the path of the .ko kernel module file * * Fires just before the return of get_from_cache, when the cache grab * is successful. */ probe stap.cache_get = process("stap").mark("cache__get") { source_path = user_string_quoted($arg1) module_path = user_string_quoted($arg2) } /** * probe stap.system - Starting a command from stap * @command: the command string to be run by posix_spawn (as sh -c ) * * Fires at the entry of the stap_system command. */ probe stap.system = process("stap").mark("stap_system__start") { command = user_string_quoted($arg1) } /** * probe stap.system.spawn - stap spawned new process * @ret: the return value from posix_spawn * @pid: the pid of the spawned process * * Fires just after the call to posix_spawn. */ probe stap.system.spawn = process("stap").mark("stap_system__spawn") { /* posix_spawn(3p) for meaning of ret */ ret = $arg1 pid = $arg2 } /** * probe stap.system.return - Finished a command from stap * @ret: a return code associated with running waitpid on the spawned process; * a non-zero value indicates error * * Fires just before the return of the stap_system function, after waitpid. */ probe stap.system.return = process("stap").mark("stap_system__complete") { ret = $arg1 } /** * probe staprun.insert_module - Inserting SystemTap instrumentation module * @path: the full path to the .ko kernel module about to be inserted * * Fires just before the call to insert the module. */ probe staprun.insert_module = process("staprun").mark("insert__module") { path = user_string_quoted($arg1) } /** * probe staprun.remove_module - Removing SystemTap instrumentation module * @name: the stap module name to be removed (without the .ko extension) * * Fires just before the call to remove the module. */ probe staprun.remove_module = process("staprun").mark("remove__module") { name = user_string_quoted($arg1) } /** * probe staprun.send_control_message - Sending a control message * @type: type of message being send; defined in runtime/transport/transport_msgs.h * @data: a ptr to a binary blob of data sent as the control message * @len: the length (in bytes) of the data blob * * Fires at the beginning of the send_request function. */ probe staprun.send_control_message = process("staprun").mark("send__ctlmsg") { type = $arg1 data = $arg2 len = $arg3 } /** * probe stapio.receive_control_message - Received a control message * @type: type of message being send; defined in runtime/transport/transport_msgs.h * @data: a ptr to a binary blob of data sent as the control message * @len: the length (in bytes) of the data blob * * Fires just after a message was receieved and before it's processed. */ /* *** Due to stapio not being in a user's PATH and the build environment of *** *** stap, there is no immediate 'good' way to insert the correct path here *** *** so comment out this probe. Note however, the static marker is still *** *** present in source. *** probe stapio.receive_control_message = process("@libexecdir@/systemtap/stapio").mark("recv__ctlmsg") { type = $arg1 data = $arg2 len = $arg3 } */ systemtap-2.3/tapset/stopwatch.stp000066400000000000000000000057531217430427200174670ustar00rootroot00000000000000// stopwatch tapset // Copyright (C) 2012 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. global _stopwatch_starttime, _stopwatch_acc /* * Description of the stopwatch states: * if (! name in _stopwatch_acc) {stopwatch doesn't exist} * if (_stopwatch_starttime[name] == 0 ) {stopwatch not running} * if (_stopwatch_starttime[name] != 0 ) {stopwatch running} */ /** * sfunction delete_stopwatch - Remove an existing stopwatch * @name: the stopwatch name * * Remove stopwatch @name. */ function delete_stopwatch (name:string) { delete _stopwatch_starttime[name]; delete _stopwatch_acc[name]; } /** * sfunction start_stopwatch - Start a stopwatch * @name: the stopwatch name * * Start stopwatch @name. * Creates stopwatch @name if it does not currently exist. */ function start_stopwatch (name:string) { stime = _stopwatch_starttime[name] if (stime == 0) _stopwatch_starttime[name] = gettimeofday_ns() /* make sure there is an entry in _stopwatch_acc */ _stopwatch_acc[name] = _stopwatch_acc[name] } /** * sfunction stop_stopwatch - Stop a stopwatch * @name: the stopwatch name * * Stop stopwatch @name. * Creates stopwatch @name if it does not currently exist. */ function stop_stopwatch (name:string) { stime = _stopwatch_starttime[name] if (stime != 0) delta = gettimeofday_ns() - stime else delta = 0 _stopwatch_starttime[name] = 0 _stopwatch_acc[name] = _stopwatch_acc[name] + delta } /** * sfunction read_stopwatch_ns - Reads the time in nanoseconds for a stopwatch * @name: stopwatch name * * Returns time in nanoseconds for stopwatch @name. * Creates stopwatch @name if it does not currently exist. */ function read_stopwatch_ns:long (name:string) { stime = _stopwatch_starttime[name] if (stime != 0) delta = gettimeofday_ns() - stime else delta = 0 _stopwatch_acc[name] = _stopwatch_acc[name] return (_stopwatch_acc[name] + delta) } /** * sfunction read_stopwatch_us - Reads the time in microseconds for a stopwatch * @name: stopwatch name * * Returns time in microseconds for stopwatch @name. * Creates stopwatch @name if it does not currently exist. */ function read_stopwatch_us:long (name:string) { return read_stopwatch_ns(name)/1000; } /** * sfunction read_stopwatch_ms - Reads the time in milliseconds for a stopwatch * @name: stopwatch name * * Returns time in milliseconds for stopwatch @name. * Creates stopwatch @name if it does not currently exist. */ function read_stopwatch_ms:long (name:string) { return read_stopwatch_ns(name)/1000000; } /** * sfunction read_stopwatch_ms - Reads the time in seconds for a stopwatch * @name: stopwatch name * * Returns time in seconds for stopwatch @name. * Creates stopwatch @name if it does not currently exist. */ function read_stopwatch_s:long (name:string) { return read_stopwatch_ns(name)/1000000000; } systemtap-2.3/tapset/string.stp000066400000000000000000000127161217430427200167560ustar00rootroot00000000000000// Standard string functions tapset. // Copyright (C) 2009 Red Hat, Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /** * sfunction strlen - Returns the length of a string * * @s: the string * * Description: This function returns the length of the string, which * can be zero up to MAXSTRINGLEN. */ function strlen:long(s:string) %{ /* pure */ /* unprivileged */ STAP_RETVALUE = strlen(STAP_ARG_s); %} /** * sfunction substr - Returns a substring * * @str: the string to take a substring from * @start: starting position of the extracted string (first character is 0) * @length: length of string to return * * Description: Returns the substring of the given string at the given * start position with the given length (or smaller if the length of the * original string is less than start + length, or length is bigger than * MAXSTRINGLEN). */ function substr:string(str:string,start:long, length:long) %{ /* pure */ /* unprivileged */ int64_t length = clamp_t(int64_t, STAP_ARG_length + 1, 0, MAXSTRINGLEN); if (STAP_ARG_start >= 0 && STAP_ARG_start < strlen(STAP_ARG_str)) strlcpy(STAP_RETVALUE, STAP_ARG_str + STAP_ARG_start, length); %} /** * sfunction stringat - Returns the char at a given position in the string * * @str: the string to fetch the character from * @pos: the position to get the character from (first character is 0) * * Description: This function returns the character at a given position in * the string or zero if the string doesn't have as many characters. Reports * an error if pos is out of bounds. */ function stringat:long(str:string, pos:long) %{ /* pure */ /* unprivileged */ if (STAP_ARG_pos >= 0 && STAP_ARG_pos < strlen(STAP_ARG_str)) STAP_RETVALUE = STAP_ARG_str[STAP_ARG_pos]; else { STAP_RETVALUE = 0; #if STAP_COMPAT_VERSION >= STAP_VERSION(2,3) // PR15044 CONTEXT->last_error = "Position out of bounds"; #endif } %} /** * sfunction isinstr - Returns whether a string is a substring of another string * * @s1: string to search in * @s2: substring to find * * Description: This function returns 1 if string @s1 contains @s2, * otherwise zero. */ function isinstr:long(s1:string,s2:string) %{ /* pure */ /* unprivileged */ if (strstr(STAP_ARG_s1,STAP_ARG_s2) != NULL) STAP_RETVALUE = 1; else STAP_RETVALUE = 0; %} /** * sfunction text_str - Escape any non-printable chars in a string * * @input: the string to escape * * Description: This function accepts a string argument, * and any ASCII characters that are not * printable are replaced by the corresponding escape sequence in the * returned string. */ function text_str:string(input:string) %{ /* pure */ /* unprivileged */ if (_stp_text_str(STAP_RETVALUE, STAP_ARG_input, 0, 0, 0) < 0) { STAP_RETVALUE[0] = '\0'; } %} /** * sfunction text_strn - Escape any non-printable chars in a string * * @input: the string to escape * @len: maximum length of string to return (0 implies MAXSTRINGLEN) * @quoted: put double quotes around the string. If input string is * truncated it will have "..." after the second quote * * Description: This function accepts a string of designated length, * and any ASCII characters that are not * printable are replaced by the corresponding escape sequence in the * returned string. */ function text_strn:string(input:string, len:long, quoted:long) %{ /* pure */ /* unprivileged */ int64_t len = clamp_t(int64_t, STAP_ARG_len, 0, MAXSTRINGLEN); if (_stp_text_str( STAP_RETVALUE, STAP_ARG_input, len, STAP_ARG_quoted, 0) < 0) { STAP_RETVALUE[0] = '\0'; } %} /** * sfunction - str_replace Replaces all instances of a substring with another * * @prnt_str: the string to search and replace in * @srch_str: the substring which is used to search in @prnt_str string * @rplc_str: the substring which is used to replace @srch_str * * Description: This function returns the given string with * substrings replaced. */ function str_replace:string (prnt_str:string, srch_str:string, rplc_str:string) %{ /* pure */ /* unprivileged */ char *ptr = STAP_ARG_prnt_str; char *ptr_base = STAP_ARG_prnt_str; int strlen_srch_str = strlen(STAP_ARG_srch_str); STAP_RETVALUE[0] = '\0'; if(strlen_srch_str == 0) { strlcat(STAP_RETVALUE, ptr_base, MAXSTRINGLEN); return; } while((ptr = strstr(ptr, STAP_ARG_srch_str)) != NULL) { *ptr = '\0'; strlcat(STAP_RETVALUE, ptr_base, MAXSTRINGLEN); strlcat(STAP_RETVALUE, STAP_ARG_rplc_str, MAXSTRINGLEN); ptr = ptr + strlen_srch_str; ptr_base = ptr; } strlcat(STAP_RETVALUE, ptr_base, MAXSTRINGLEN); return; %} /** * sfunction - strtol - Convert a string to a long * * @str: string to convert * @base: the base to use * * Description: This function converts the string representation of a number to an integer. * The @base parameter indicates the number base to assume for the string (eg. 16 for hex, 8 for octal, 2 for binary). */ function strtol:long(str:string, base:long) %{ /* pure */ /* unprivileged */ STAP_RETVALUE = simple_strtol(STAP_ARG_str, NULL, STAP_ARG_base); %} /** * sfunction isdigit - Checks for a digit * * @str: string to check * * Description: Checks for a digit (0 through 9) as the first * character of a string. Returns non-zero if true, and a zero if * false. */ function isdigit:long(str:string) %{ /* pure */ /* unprivileged */ STAP_RETVALUE = isdigit(STAP_ARG_str[0]); %} systemtap-2.3/tapset/system.stp000066400000000000000000000007311217430427200167660ustar00rootroot00000000000000/** * sfunction system - Issue a command to the system * * @cmd: the command to issue to the system * * Description: This function runs a command on the system. The * command is started in the background some time after the current * probe completes. The command is run with the same UID as the user * running the stap or staprun command. */ function system (cmd:string) %{ /* unprivileged */ _stp_ctl_send(STP_SYSTEM, STAP_ARG_cmd, strlen(STAP_ARG_cmd)+1); %} systemtap-2.3/tapset/timers.stp000066400000000000000000000014661217430427200167530ustar00rootroot00000000000000// timers tapset // // Copyright (C) 2009 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // Most of the timer probes are defined in tapset-timers.cxx; // however, timer.profile needs to fall back to perf in certain // circumstances. /** * probe timer.profile - timer.profile.tick with a perf fallback on recent kernels * * This probe behaves identically to timer.profile.tick, except on * some recent kernels which lack the underlying profile timer * functionality. In those cases, timer.profile falls back to using * perf.sw.cpu_clock. */ probe timer.profile = timer.profile.tick ! , perf.sw.cpu_clock.sample(1000000) {} systemtap-2.3/tapset/tokenize.stp000066400000000000000000000031531217430427200172730ustar00rootroot00000000000000// Tokenize tapset // Copyright (C) 2010 Red Hat, Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. %{ #define STAP_NEED_CONTEXT_TOKENIZE 1 %} /** * sfunction tokenize - Return the next non-empty token in a string * * @input: string to tokenize. If empty, returns the next non-empty token * in the string passed in the previous call to tokenize(). * @delim: set of characters that delimit the tokens * * Description: This function returns the next non-empty token in the * given input string, where the tokens are delimited by characters in * the delim string. If the input string is non-empty, it returns the * first token. If the input string is empty, it returns the next * token in the string passed in the previous call to tokenize. * If no delimiter is found, the entire remaining input string is * returned. It returns empty when no more tokens are available. */ function tokenize:string(input:string, delim:string) %{ /* unprivileged */ char *token = NULL; char *token_end = NULL; if (STAP_ARG_input[0]) { strncpy(CONTEXT->tok_str, STAP_ARG_input, MAXSTRINGLEN); CONTEXT->tok_start = &CONTEXT->tok_str[0]; CONTEXT->tok_end = &CONTEXT->tok_str[0] + strlen(CONTEXT->tok_str); } do { token = strsep(& CONTEXT->tok_start, STAP_ARG_delim); } while (token && !token[0]); if (token) { token_end = (CONTEXT->tok_start ? CONTEXT->tok_start - 1 : CONTEXT->tok_end); memcpy(STAP_RETVALUE, token, token_end - token + 1); } %} systemtap-2.3/tapset/tzinfo.stp000066400000000000000000000016421217430427200167550ustar00rootroot00000000000000// timezone tapset // Copyright (C) 2010 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. /** * sfunction tz_ctime - Convert seconds since epoch into human readable date/time string, with local time zone * * @epochsecs: number of seconds since epoch (as returned by gettimeofday_s()) * * Description: Takes an argument of seconds since the epoch as returned by * gettimeofday_s(). Returns a string of the same form as ctime(), but * offsets the epoch time for the local time zone, and appends the name of the * local time zone. The string length may vary. The time zone information is * passed by staprun at script startup only. */ function tz_ctime(epochsecs) { return (ctime(epochsecs - tz_gmtoff()) . " " . tz_name()) } systemtap-2.3/tapset/uconversions.stp000066400000000000000000000513561217430427200202100ustar00rootroot00000000000000// userspace conversions tapset // Copyright (C) 2005-2012 Red Hat Inc. // Copyright (C) 2007 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // implement in terms of runtime/loc2c-runtime.h macro uread() %{ #define __STP_GET_USER(t, warn) \ do { \ __label__ deref_fault; \ t *_ptr = (t*) (intptr_t) STAP_ARG_addr; \ STAP_RETVALUE = uread (_ptr); \ if (0) { \ deref_fault: \ STAP_RETVALUE = 0; \ CONTEXT->last_error = NULL; \ if (warn) { \ snprintf(CONTEXT->error_buffer, \ sizeof(CONTEXT->error_buffer), \ "user %s copy fault %p", #t, _ptr); \ _stp_warn(CONTEXT->error_buffer); \ } \ } \ } while (0) #define STP_GET_USER(t) __STP_GET_USER(t, 0) #define STP_GET_USER_WARN(t) __STP_GET_USER(t, 1) %} /** * sfunction user_string - Retrieves string from user space * * @addr: the user space address to retrieve the string from * * Description: Returns the null terminated C string from a given user space * memory address. Reports an error on the rare cases when userspace * data is not accessible. */ function user_string:string (addr:long) { return user_string_n(addr, %{ MAXSTRINGLEN %} ) } /** * sfunction user_string2 - Retrieves string from user space with alternative error string * * @addr: the user space address to retrieve the string from * @err_msg: the error message to return when data isn't available * * Description: Returns the null terminated C string from a given user space * memory address. Reports the given error message on the rare cases when * userspace data is not accessible. */ function user_string2:string (addr:long, err_msg:string) { return user_string_n2(addr, %{ MAXSTRINGLEN %}, err_msg) } /** * sfunction user_string_warn - Retrieves string from user space * * @addr: the user space address to retrieve the string from * * Description: Returns the null terminated C string from a given user space * memory address. Reports "" on the rare cases when userspace data is * not accessible and warns (but does not abort) about the failure. */ function user_string_warn:string (addr:long) { %(systemtap_v < "2.3" %? // PR15044 return user_string2_warn(addr, "") %: return user_string2_warn(addr, "") %) } /** * sfunction user_string2_warn - Retrieves string from user space with alternative warning string * * @addr: the user space address to retrieve the string from * @warn_msg: the warning message to return when data isn't available * * Description: Returns the null terminated C string from a given user space * memory address. Reports the given warning message on the rare cases * when userspace data is not accessible and warns (but does not abort) * about the failure. */ function user_string2_warn:string (addr:long, warn_msg:string) { return user_string2_n_warn(addr, %{ MAXSTRINGLEN %}, warn_msg) } /** * sfunction user_string_quoted - Retrieves and quotes string from user space * * @addr: the user space address to retrieve the string from * * Description: Returns the null terminated C string from a given user space * memory address where any ASCII characters that are not printable are * replaced by the corresponding escape sequence in the returned string. Note * that the string will be surrounded by double quotes. On the rare cases when * userspace data is not accessible at the given address, the address itself is * returned as a string, without double quotes. */ function user_string_quoted:string (addr:long) { return user_string_n_quoted(addr, %{ MAXSTRINGLEN %}) } /** * sfunction user_string_n - Retrieves string of given length from user space * * @addr: the user space address to retrieve the string from * @n: the maximum length of the string (if not null terminated) * * Description: Returns the C string of a maximum given length from a * given user space address. Reports an error on the rare cases * when userspace data is not accessible at the given address. */ function user_string_n:string (addr:long, n:long) %( systemtap_v < "2.3" %? // PR15044 { return user_string_n2(addr, n, "") } %: %{ /* pure */ /* myproc-unprivileged */ long rc; int64_t len = clamp_t(int64_t, STAP_ARG_n + 1, 1, MAXSTRINGLEN); rc = _stp_strncpy_from_user(STAP_RETVALUE, (char __user *) (uintptr_t) STAP_ARG_addr, len); if (rc < 0) { strlcpy(STAP_RETVALUE, "", MAXSTRINGLEN); snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "user string copy fault %ld at %p", rc, (void *) (uintptr_t) STAP_ARG_addr); CONTEXT->last_error = CONTEXT->error_buffer; } else STAP_RETVALUE[len - 1] = '\0'; %} %) /** * sfunction user_string_n2 - Retrieves string of given length from user space * * @addr: the user space address to retrieve the string from * @n: the maximum length of the string (if not null terminated) * @err_msg: the error message to return when data isn't available * * Description: Returns the C string of a maximum given length from a * given user space address. Returns the given error message string on * the rare cases when userspace data is not accessible at the given * address. */ function user_string_n2:string (addr:long, n:long, err_msg:string) %{ /* pure */ /* myproc-unprivileged */ int64_t len = clamp_t(int64_t, STAP_ARG_n + 1, 1, MAXSTRINGLEN); if (_stp_strncpy_from_user(STAP_RETVALUE, (char __user *) (uintptr_t) STAP_ARG_addr, len) < 0) strlcpy(STAP_RETVALUE, STAP_ARG_err_msg, MAXSTRINGLEN); else STAP_RETVALUE[len - 1] = '\0'; %} /** * sfunction user_string_n_warn - Retrieves string from user space * * @addr: the user space address to retrieve the string from * @n: the maximum length of the string (if not null terminated) * * Description: Returns up to n characters of a C string from a given * user space memory address. Reports "" on the rare cases * when userspace data is not accessible and warns (but does not abort) * about the failure. */ function user_string_n_warn:string (addr:long, n:long) { %(systemtap_v < "2.3" %? // PR15044 return user_string2_n_warn(addr, n, "") %: return user_string2_n_warn(addr, n, "") %) } /** * sfunction user_string2_n_warn - Retrieves string from user space with alternative warning string * * @addr: the user space address to retrieve the string from * @n: the maximum length of the string (if not null terminated) * @warn_msg: the warning message to return when data isn't available * * Description: Returns up to n characters of a C string from a given * user space memory address. Reports the given warning message on the * rare cases when userspace data is not accessible and warns (but does * not abort) about the failure. */ function user_string2_n_warn:string (addr:long, n:long, warn_msg:string) %{ /* pure */ /* myproc-unprivileged */ int64_t len = clamp_t(int64_t, STAP_ARG_n + 1, 1, MAXSTRINGLEN); long rc; rc = _stp_strncpy_from_user(STAP_RETVALUE, (char __user *) (uintptr_t) STAP_ARG_addr, len); if (rc < 0) { // NB: using error_buffer to get local space for the warning, but we're // not aborting, so leave last_error alone. snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "user string copy fault %ld at %p", rc, (void *) (uintptr_t) STAP_ARG_addr); _stp_warn(CONTEXT->error_buffer); strlcpy (STAP_RETVALUE, STAP_ARG_warn_msg, MAXSTRINGLEN); } else STAP_RETVALUE[len - 1] = '\0'; %} /** * sfunction user_string_n_quoted - Retrieves and quotes string from user space * * @addr: the user space address to retrieve the string from * @n: the maximum length of the string (if not null terminated) * * Description: Returns up to n characters of a C string from the given * user space memory address where any ASCII characters that are not * printable are replaced by the corresponding escape sequence in the * returned string. Note that the string will be surrounded by double quotes. * On the rare cases when userspace data is not accessible at the given address, * the address itself is returned as a string, without double quotes. */ function user_string_n_quoted:string (addr:long, n:long) %{ /* pure */ /* myproc-unprivileged */ // Note the lack of STAP_ARG_n+1 as in other funcs() -- PR15617 int64_t len = clamp_t(int64_t, STAP_ARG_n, 0, MAXSTRINGLEN); if (STAP_ARG_addr == 0) #if STAP_COMPAT_VERSION < STAP_VERSION(2,3) // PR15044 strlcpy(STAP_RETVALUE, "NULL", MAXSTRINGLEN); #else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "%p", (void *)(long)STAP_ARG_addr); #endif else { int rc = _stp_text_str(STAP_RETVALUE, (char *)(uintptr_t)STAP_ARG_addr, len, 1, 1); if (rc < 0) #if STAP_COMPAT_VERSION < STAP_VERSION(2,3) // PR15044 strlcpy(STAP_RETVALUE, "", MAXSTRINGLEN); #else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "%p", (void *)(long)STAP_ARG_addr); #endif } %} /** * sfunction user_string_utf32 - Retrieves UTF-32 string from user memory * @addr: The user address to retrieve the string from * * Description: This function returns a null terminated UTF-8 string converted * from the UTF-32 string at a given user memory address. Reports an error on * string copy fault or conversion error. */ function user_string_utf32:string (addr:long) %{ /* pure */ /* myproc-unprivileged */ int rc = 0, len = MAXSTRINGLEN; uint32_t c32, *source = (uint32_t*)(intptr_t)STAP_ARG_addr; char *destination = STAP_RETVALUE; *destination = '\0'; while (len > 1 && (c32 = uread(source))) { if ((rc = _stp_convert_utf32(destination, len, c32)) <= 0) { if (rc < 0) { snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "invalid UTF-32 character U+%X at 0x%p", c32, source); CONTEXT->last_error = CONTEXT->error_buffer; } break; } ++source; destination += rc; len -= rc; } if (0) { deref_fault: /* branched to from deref_string() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "user string copy fault at 0x%p", source); CONTEXT->last_error = CONTEXT->error_buffer; } %} /** * sfunction user_string2_utf32 - Retrieves UTF-32 string from user memory with alternative error string * @addr: The user address to retrieve the string from * @err_msg: The error message to return when data isn't available * * Description: This function returns a null terminated UTF-8 string converted * from the UTF-32 string at a given user memory address. Reports the given * error message on string copy fault or conversion error. */ function user_string2_utf32:string (addr:long, err_msg:string) { try { return user_string_utf32(addr) } catch { return err_msg } } /** * sfunction user_string_utf16 - Retrieves UTF-16 string from user memory * @addr: The user address to retrieve the string from * * Description: This function returns a null terminated UTF-8 string converted * from the UTF-16 string at a given user memory address. Reports an error on * string copy fault or conversion error. */ function user_string_utf16:string (addr:long) %{ /* pure */ /* myproc-unprivileged */ int rc = 0, len = MAXSTRINGLEN; uint32_t c32; uint16_t c16low, *source = (uint16_t*)(intptr_t)STAP_ARG_addr; char *destination = STAP_RETVALUE; *destination = '\0'; while (len > 1 && (c32 = uread(source))) { /* Check for a UTF-16 high surrogate, then its low pair, and combine them. * Broken surrogates will just fall through to _stp_convert_utf32 and get * flagged as an error there. (Or even allowed, if we decide to be lax.) */ if (c32 >= 0xD800 && c32 <= 0xDBFF) { ++source; c16low = uread(source); if (c16low >= 0xDC00 && c16low <= 0xDFFF) c32 = 0x10000 + ((c32 & 0x3FF) << 10) + (c16low & 0x3FF); else --source; } if ((rc = _stp_convert_utf32(destination, len, c32)) <= 0) { if (rc < 0) { snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "invalid UTF-16 character U+%X at 0x%p", c32, source); CONTEXT->last_error = CONTEXT->error_buffer; } break; } ++source; destination += rc; len -= rc; } if (0) { deref_fault: /* branched to from deref_string() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "user string copy fault at 0x%p", source); CONTEXT->last_error = CONTEXT->error_buffer; } %} /** * sfunction user_string2_utf16 - Retrieves UTF-16 string from user memory with alternative error string * @addr: The user address to retrieve the string from * @err_msg: The error message to return when data isn't available * * Description: This function returns a null terminated UTF-8 string converted * from the UTF-16 string at a given user memory address. Reports the given * error message on string copy fault or conversion error. */ function user_string2_utf16:string (addr:long, err_msg:string) { try { return user_string_utf16(addr) } catch { return err_msg } } /** * sfunction user_char - Retrieves a char value stored in user space * * @addr: the user space address to retrieve the char from * * Description: Returns the char value from a given user space address. * Returns zero when user space data is not accessible. */ function user_char:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ STP_GET_USER(char); %} /** * sfunction user_char_warn - Retrieves a char value stored in user space * * @addr: the user space address to retrieve the char from * * Description: Returns the char value from a given user space address. * Returns zero when user space and warns (but does not abort) about the * failure. */ function user_char_warn:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ STP_GET_USER_WARN(char); %} /** * sfunction user_short - Retrieves a short value stored in user space * * @addr: the user space address to retrieve the short from * * Description: Returns the short value from a given user space address. * Returns zero when user space data is not accessible. */ function user_short:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ STP_GET_USER(short); %} /** * sfunction user_short_warn - Retrieves a short value stored in user space * * @addr: the user space address to retrieve the short from * * Description: Returns the short value from a given user space address. * Returns zero when user space and warns (but does not abort) about the * failure. */ function user_short_warn:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ STP_GET_USER_WARN(short); %} /** * sfunction user_ushort - Retrieves an unsigned short value stored in user space * * @addr: the user space address to retrieve the unsigned short from * * Description: Returns the unsigned short value from a given user * space address. Returns zero when user space data is not accessible. */ function user_ushort:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ STP_GET_USER(unsigned short); %} /** * sfunction user_ushort_warn - Retrieves an unsigned short value stored in user space * * @addr: the user space address to retrieve the unsigned short from * * Description: Returns the unsigned short value from a given user * space address. Returns zero when user space and warns (but does * not abort) about the failure. */ function user_ushort_warn:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ STP_GET_USER_WARN(unsigned short); %} /** * sfunction user_int - Retrieves an int value stored in user space * * @addr: the user space address to retrieve the int from * * Description: Returns the int value from a given user space address. * Returns zero when user space data is not accessible. */ function user_int:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ STP_GET_USER(int); %} /** * sfunction user_int_warn - Retrieves an int value stored in user space * * @addr: the user space address to retrieve the int from * * Description: Returns the int value from a given user space address. * Returns zero when user space and warns (but does not abort) about the * failure. */ function user_int_warn:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ STP_GET_USER_WARN(int); %} /** * sfunction user_long - Retrieves a long value stored in user space * * @addr: the user space address to retrieve the long from * * Description: Returns the long value from a given user space address. * Returns zero when user space data is not accessible. Note that the * size of the long depends on the architecture of the current user space * task (for those architectures that support both 64/32 bit compat tasks). */ function user_long:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ #ifdef CONFIG_COMPAT if (_stp_is_compat_task()) STP_GET_USER(compat_long_t); else #endif STP_GET_USER(long); %} /** * sfunction user_long_warn - Retrieves a long value stored in user space * * @addr: the user space address to retrieve the long from * * Description: Returns the long value from a given user space address. * Returns zero when user space and warns (but does not abort) about the * failure. Note that the size of the long depends on the architecture * of the current user space task (for those architectures that support * both 64/32 bit compat tasks). */ function user_long_warn:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ #ifdef CONFIG_COMPAT if (_stp_is_compat_task()) STP_GET_USER_WARN(compat_long_t); else #endif STP_GET_USER_WARN(long); %} /** * sfunction user_int8 - Retrieves a 8-bit integer value stored in user space * * @addr: the user space address to retrieve the 8-bit integer from * * Description: Returns the 8-bit integer value from a given user space * address. Returns zero when user space data is not accessible. */ function user_int8:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ STP_GET_USER(int8_t); %} /** * sfunction user_uint8 - Retrieves an unsigned 8-bit integer value stored in user space * * @addr: the user space address to retrieve the unsigned 8-bit integer from * * Description: Returns the unsigned 8-bit integer value from a given user * space address. Returns zero when user space data is not accessible. */ function user_uint8:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ STP_GET_USER(uint8_t); %} /** * sfunction user_int16 - Retrieves a 16-bit integer value stored in user space * * @addr: the user space address to retrieve the 16-bit integer from * * Description: Returns the 16-bit integer value from a given user space * address. Returns zero when user space data is not accessible. */ function user_int16:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ STP_GET_USER(int16_t); %} /** * sfunction user_uint16 - Retrieves an unsigned 16-bit integer value stored in user space * * @addr: the user space address to retrieve the unsigned 16-bit integer from * * Description: Returns the unsigned 16-bit integer value from a given user * space address. Returns zero when user space data is not accessible. */ function user_uint16:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ STP_GET_USER(uint16_t); %} /** * sfunction user_int32 - Retrieves a 32-bit integer value stored in user space * * @addr: the user space address to retrieve the 32-bit integer from * * Description: Returns the 32-bit integer value from a given user space * address. Returns zero when user space data is not accessible. */ function user_int32:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ STP_GET_USER(int32_t); %} /** * sfunction user_uint32 - Retrieves an unsigned 32-bit integer value stored in user space * * @addr: the user space address to retrieve the unsigned 32-bit integer from * * Description: Returns the unsigned 32-bit integer value from a given user * space address. Returns zero when user space data is not accessible. */ function user_uint32:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ STP_GET_USER(uint32_t); %} /** * sfunction user_int64 - Retrieves a 64-bit integer value stored in user space * * @addr: the user space address to retrieve the 64-bit integer from * * Description: Returns the 64-bit integer value from a given user space * address. Returns zero when user space data is not accessible. */ function user_int64:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ STP_GET_USER(int64_t); %} /** * sfunction user_uint64 - Retrieves an unsigned 64-bit integer value stored in user space * * @addr: the user space address to retrieve the unsigned 64-bit integer from * * Description: Returns the unsigned 64-bit integer value from a given user * space address. Returns zero when user space data is not accessible. */ function user_uint64:long (addr:long) { /* NB: We have no script-level notion of 64-bit unsigned, * but we keep user_uint64 anyway for API completeness. */ return user_int64 (addr); } systemtap-2.3/tapset/x86_64/000077500000000000000000000000001217430427200156475ustar00rootroot00000000000000systemtap-2.3/tapset/x86_64/registers.stp000066400000000000000000000166261217430427200204210ustar00rootroot00000000000000%{ /* Set to include regparm field in probe context in translate.cxx. */ #ifndef STAP_NEED_REGPARM #define STAP_NEED_REGPARM 1 #endif %} global _reg_offsets, _r32_offsets, _stp_regs_registered function _stp_register_regs() { /* Same order as pt_regs */ _reg_offsets["r15"] = 0 _reg_offsets["r14"] = 8 _reg_offsets["r13"] = 16 _reg_offsets["r12"] = 24 _reg_offsets["rbp"] = 32 _reg_offsets["bp"] = 32 _reg_offsets["rbx"] = 40 _reg_offsets["bx"] = 40 _reg_offsets["r11"] = 48 _reg_offsets["r10"] = 56 _reg_offsets["r9"] = 64 _reg_offsets["r8"] = 72 _reg_offsets["rax"] = 80 _reg_offsets["ax"] = 80 _reg_offsets["rcx"] = 88 _reg_offsets["cx"] = 88 _reg_offsets["rdx"] = 96 _reg_offsets["dx"] = 96 _reg_offsets["rsi"] = 104 _reg_offsets["si"] = 104 _reg_offsets["rdi"] = 112 _reg_offsets["di"] = 112 _reg_offsets["orig_rax"] = 120 _reg_offsets["orig_ax"] = 120 _reg_offsets["rip"] = 128 _reg_offsets["ip"] = 128 _reg_offsets["xcs"] = 136 _reg_offsets["cs"] = 136 _reg_offsets["eflags"] = 144 _reg_offsets["flags"] = 144 _reg_offsets["rsp"] = 152 _reg_offsets["sp"] = 152 _reg_offsets["xss"] = 160 _reg_offsets["ss"] = 160 _r32_offsets["ebp"] = 32 _r32_offsets["ebx"] = 40 _r32_offsets["eax"] = 80 _r32_offsets["ecx"] = 88 _r32_offsets["edx"] = 96 _r32_offsets["esi"] = 104 _r32_offsets["edi"] = 112 _r32_offsets["orig_eax"] = 120 _r32_offsets["eip"] = 128 _r32_offsets["esp"] = 152 _stp_regs_registered = 1 } function _stp_get_register_by_offset:long (offset:long) %{ /* pure */ long value; struct pt_regs *regs; regs = (CONTEXT->user_mode_p ? CONTEXT->uregs : CONTEXT->kregs); if (!regs) { CONTEXT->last_error = "No registers available in this context"; return; } if (STAP_ARG_offset < 0 || STAP_ARG_offset > sizeof(struct pt_regs) - sizeof(long)) { snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "Bad register offset: %lld", STAP_ARG_offset); CONTEXT->last_error = CONTEXT->error_buffer; return; } memcpy(&value, ((char *)regs) + STAP_ARG_offset, sizeof(value)); STAP_RETVALUE = value; %} /* * _stp_sign_extend32() is callable from a script function. * __stp_sign_extend32() (in regs.c) is callable from a C function. */ function _stp_sign_extend32:long (value:long) %{ /* pure */ STAP_RETVALUE = __stp_sign_extend32(STAP_ARG_value); %} function _stp_register:long (name:string, sign_extend:long) { reg32 = 0 if (!registers_valid()) { error("cannot access CPU registers in this context") return 0 } if (!_stp_regs_registered) _stp_register_regs() offset = _reg_offsets[name] if (offset == 0 && !(name in _reg_offsets)) { offset = _r32_offsets[name] if (offset == 0 && !(name in _r32_offsets)) { error("Unknown register: " . name) return 0 } reg32 = 1 } value = _stp_get_register_by_offset(offset) if (reg32) { if (sign_extend) value = _stp_sign_extend32(value) else value &= 0xffffffff } return value } /* Return the named register value as a signed value. */ function register:long (name:string) { return _stp_register(name, 1) } /* * Return the named register value as an unsigned value. Specifically, * don't sign-extend the register value when promoting it to 64 bits. */ function u_register:long (name:string) { return _stp_register(name, 0) } /* * Return the value of function arg #argnum (1=first arg). * If truncate=1, mask off the top 32 bits. * If sign_extend=1 and (truncate=1 or the probepoint we've hit is in a * 32-bit app), sign-extend the 32-bit value. */ function _stp_arg:long (argnum:long, sign_extend:long, truncate:long) %{ /* pure */ long val; struct pt_regs *regs; int result, n, nr_regargs; size_t argsz = sizeof(long); regs = (CONTEXT->user_mode_p ? CONTEXT->uregs : CONTEXT->kregs); STAP_RETVALUE = 0; if (!regs) { snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "cannot access function args in this context"); CONTEXT->last_error = CONTEXT->error_buffer; return; } if (STAP_ARG_argnum < 1) goto bad_argnum; n = (int) STAP_ARG_argnum; if (CONTEXT->regparm == 0) { /* Default */ if (CONTEXT->user_mode_p && _stp_is_compat_task()) nr_regargs = 0; else nr_regargs = 6; } else nr_regargs = (CONTEXT->regparm & _STP_REGPARM_MASK); if (CONTEXT->user_mode_p && _stp_is_compat_task()) { argsz = sizeof(int); result = _stp_get_arg32_by_number(n, nr_regargs, regs, &val); } else result = _stp_get_arg64_by_number(n, nr_regargs, regs, &val); switch (result) { case 0: /* Arg is in register. */ break; case 1: /* Arg is on kernel stack. */ val = kread((long *) val); break; case 2: { /* Arg is on user stack. */ const char __user *vaddr = (const char __user*) val; if (_stp_copy_from_user((char*)&val, vaddr, argsz) != 0) { /* Stack page not resident. */ _stp_warn("cannot access arg(%d) " "at user stack address %p\n", n, vaddr); STAP_RETVALUE = 0; return; } break; } default: goto bad_argnum; } if (STAP_ARG_truncate || argsz == sizeof(int)) { if (STAP_ARG_sign_extend) STAP_RETVALUE = (int64_t) __stp_sign_extend32(val); else /* High bits may be garbage. */ STAP_RETVALUE = (int64_t) (val & 0xffffffff); } else STAP_RETVALUE = (int64_t) val; return; bad_argnum: snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "cannot access arg(%lld)", STAP_ARG_argnum); CONTEXT->last_error = CONTEXT->error_buffer; return; if (0) { deref_fault: /* branched to from kread() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel fault at %#lx accessing arg(%lld)", val, STAP_ARG_argnum); CONTEXT->last_error = CONTEXT->error_buffer; } %} function probing_32bit_app() %{ /* pure */ STAP_RETVALUE = (CONTEXT->user_mode_p && _stp_is_compat_task()); %} /* Return the value of function arg #argnum (1=first arg) as a signed int. */ function int_arg:long (argnum:long) { return _stp_arg(argnum, 1, 1) } /* Return the value of function arg #argnum (1=first arg) as an unsigned int. */ function uint_arg:long (argnum:long) { return _stp_arg(argnum, 0, 1) } function long_arg:long (argnum:long) { return _stp_arg(argnum, 1, 0) } function ulong_arg:long (argnum:long) { return _stp_arg(argnum, 0, 0) } function longlong_arg:long (argnum:long) { if (probing_32bit_app()) { lowbits = _stp_arg(argnum, 0, 1) highbits = _stp_arg(argnum+1, 0, 1) return ((highbits << 32) | lowbits) } else return _stp_arg(argnum, 0, 0) } function ulonglong_arg:long (argnum:long) { return longlong_arg(argnum) } function pointer_arg:long (argnum:long) { return _stp_arg(argnum, 0, 0) } function s32_arg:long (argnum:long) { return int_arg(argnum) } function u32_arg:long (argnum:long) { return uint_arg(argnum) } function s64_arg:long (argnum:long) { return longlong_arg(argnum) } function u64_arg:long (argnum:long) { return ulonglong_arg(argnum) } function asmlinkage() %{ /* pure */ %} function fastcall() %{ /* pure */ %} function regparm(n:long) %{ if (CONTEXT->user_mode_p && _stp_is_compat_task() && (STAP_ARG_n < 0 || STAP_ARG_n > 3)) { snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "For -m32 programs, " "regparm value must be in the range 0-3."); CONTEXT->last_error = CONTEXT->error_buffer; } else if (STAP_ARG_n < 0 || STAP_ARG_n > 6) { snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "For x86_64, regparm value must be in the range 0-6."); CONTEXT->last_error = CONTEXT->error_buffer; } else CONTEXT->regparm = _STP_REGPARM | (int) STAP_ARG_n; %} systemtap-2.3/tapsets.cxx000066400000000000000000012746341217430427200156410ustar00rootroot00000000000000// tapset resolution // Copyright (C) 2005-2013 Red Hat Inc. // Copyright (C) 2005-2007 Intel Corporation. // Copyright (C) 2008 James.Bottomley@HansenPartnership.com // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "config.h" #include "staptree.h" #include "elaborate.h" #include "tapsets.h" #include "task_finder.h" #include "tapset-dynprobe.h" #include "translate.h" #include "session.h" #include "util.h" #include "buildrun.h" #include "dwarf_wrappers.h" #include "auto_free.h" #include "hash.h" #include "dwflpp.h" #include "setupdwfl.h" #include #include "sdt_types.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern "C" { #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define __STDC_FORMAT_MACROS #include } using namespace std; using namespace __gnu_cxx; // ------------------------------------------------------------------------ string common_probe_init (derived_probe* p) { assert(p->session_index != (unsigned)-1); return "(&stap_probes[" + lex_cast(p->session_index) + "])"; } void common_probe_entryfn_prologue (systemtap_session& s, string statestr, string probe, string probe_type, bool overload_processing) { if (s.runtime_usermode_p()) { // If session_state() is NULL, then we haven't even initialized shm yet, // and there's *nothing* for the probe to do. (even alibi is in shm) // So failure skips this whole block through the end of the epilogue. s.op->newline() << "if (likely(session_state())) {"; s.op->indent(1); } s.op->newline() << "#ifdef STP_ALIBI"; s.op->newline() << "atomic_inc(probe_alibi(" << probe << "->index));"; s.op->newline() << "#else"; if (s.runtime_usermode_p()) s.op->newline() << "int _stp_saved_errno = errno;"; s.op->newline() << "struct context* __restrict__ c = NULL;"; s.op->newline() << "#if !INTERRUPTIBLE"; s.op->newline() << "unsigned long flags;"; s.op->newline() << "#endif"; s.op->newline() << "#ifdef STP_TIMING"; s.op->newline() << "Stat stat = probe_timing(" << probe << "->index);"; s.op->newline() << "#endif"; if (overload_processing && !s.runtime_usermode_p()) s.op->newline() << "#if defined(STP_TIMING) || defined(STP_OVERLOAD)"; else s.op->newline() << "#ifdef STP_TIMING"; if (! s.runtime_usermode_p()) s.op->newline() << "cycles_t cycles_atstart = get_cycles ();"; else { s.op->newline() << "struct timespec timespec_atstart;"; s.op->newline() << "(void)clock_gettime(CLOCK_MONOTONIC_RAW, ×pec_atstart);"; } s.op->newline() << "#endif"; s.op->newline() << "#if INTERRUPTIBLE"; s.op->newline() << "preempt_disable ();"; s.op->newline() << "#else"; s.op->newline() << "local_irq_save (flags);"; s.op->newline() << "#endif"; if (! s.runtime_usermode_p()) { // Check for enough free enough stack space s.op->newline() << "if (unlikely ((((unsigned long) (& c)) & (THREAD_SIZE-1))"; // free space s.op->newline(1) << "< (MINSTACKSPACE + sizeof (struct thread_info)))) {"; // needed space // XXX: may need porting to platforms where task_struct is not // at bottom of kernel stack NB: see also // CONFIG_DEBUG_STACKOVERFLOW s.op->newline() << "atomic_inc (skipped_count());"; s.op->newline() << "#ifdef STP_TIMING"; s.op->newline() << "atomic_inc (skipped_count_lowstack());"; s.op->newline() << "#endif"; s.op->newline() << "goto probe_epilogue;"; s.op->newline(-1) << "}"; } s.op->newline() << "if (atomic_read (session_state()) != " << statestr << ")"; s.op->newline(1) << "goto probe_epilogue;"; s.op->indent(-1); s.op->newline() << "c = _stp_runtime_entryfn_get_context();"; if (s.runtime_usermode_p()) { s.op->newline() << "if (!c) {"; s.op->newline(1) << "#if !INTERRUPTIBLE"; s.op->newline() << "atomic_inc (skipped_count());"; s.op->newline() << "#endif"; s.op->newline() << "#ifdef STP_TIMING"; s.op->newline() << "atomic_inc (skipped_count_reentrant());"; s.op->newline() << "#ifdef DEBUG_REENTRANCY"; s.op->newline() << "_stp_warn (\"Skipped %s\\n\", " << probe << "->pp);"; s.op->newline() << "#endif"; s.op->newline() << "#endif"; s.op->newline() << "goto probe_epilogue;"; s.op->newline(-1) << "}"; } s.op->newline() << "if (atomic_inc_return (& c->busy) != 1) {"; s.op->newline(1) << "#if !INTERRUPTIBLE"; s.op->newline() << "atomic_inc (skipped_count());"; s.op->newline() << "#endif"; s.op->newline() << "#ifdef STP_TIMING"; s.op->newline() << "atomic_inc (skipped_count_reentrant());"; s.op->newline() << "#ifdef DEBUG_REENTRANCY"; s.op->newline() << "_stp_warn (\"Skipped %s due to %s residency on cpu %u\\n\", " << probe << "->pp, c->probe_point ?: \"?\", smp_processor_id());"; // NB: There is a conceivable race condition here with reading // c->probe_point, knowing that this other probe is sort of running. // However, in reality, it's interrupted. Plus even if it were able // to somehow start again, and stop before we read c->probe_point, // at least we have that ?: "?" bit in there to avoid a NULL deref. s.op->newline() << "#endif"; s.op->newline() << "#endif"; s.op->newline() << "atomic_dec (& c->busy);"; s.op->newline() << "goto probe_epilogue;"; s.op->newline(-1) << "}"; s.op->newline(); s.op->newline() << "c->last_stmt = 0;"; s.op->newline() << "c->last_error = 0;"; s.op->newline() << "c->nesting = -1;"; // NB: PR10516 packs locals[] tighter s.op->newline() << "c->uregs = 0;"; s.op->newline() << "c->kregs = 0;"; s.op->newline() << "#if defined __ia64__"; s.op->newline() << "c->unwaddr = 0;"; s.op->newline() << "#endif"; if (s.runtime_usermode_p()) s.op->newline() << "c->probe_index = " << probe << "->index;"; s.op->newline() << "c->probe_point = " << probe << "->pp;"; s.op->newline() << "#ifdef STP_NEED_PROBE_NAME"; s.op->newline() << "c->probe_name = " << probe << "->pn;"; s.op->newline() << "#endif"; s.op->newline() << "c->probe_type = " << probe_type << ";"; // reset Individual Probe State union s.op->newline() << "memset(&c->ips, 0, sizeof(c->ips));"; s.op->newline() << "c->user_mode_p = 0; c->full_uregs_p = 0;"; s.op->newline() << "#ifdef STAP_NEED_REGPARM"; // i386 or x86_64 register.stp s.op->newline() << "c->regparm = 0;"; s.op->newline() << "#endif"; if(!s.suppress_time_limits){ s.op->newline() << "#if INTERRUPTIBLE"; s.op->newline() << "c->actionremaining = MAXACTION_INTERRUPTIBLE;"; s.op->newline() << "#else"; s.op->newline() << "c->actionremaining = MAXACTION;"; s.op->newline() << "#endif"; } // NB: The following would actually be incorrect. // That's because cycles_sum/cycles_base values are supposed to survive // between consecutive probes. Periodically (STP_OVERLOAD_INTERVAL // cycles), the values will be reset. /* s.op->newline() << "#ifdef STP_OVERLOAD"; s.op->newline() << "c->cycles_sum = 0;"; s.op->newline() << "c->cycles_base = 0;"; s.op->newline() << "#endif"; */ s.op->newline() << "#if defined(STP_NEED_UNWIND_DATA)"; s.op->newline() << "c->uwcache_user.state = uwcache_uninitialized;"; s.op->newline() << "c->uwcache_kernel.state = uwcache_uninitialized;"; s.op->newline() << "#endif"; } void common_probe_entryfn_epilogue (systemtap_session& s, bool overload_processing) { if (overload_processing && !s.runtime_usermode_p()) s.op->newline() << "#if defined(STP_TIMING) || defined(STP_OVERLOAD)"; else s.op->newline() << "#ifdef STP_TIMING"; s.op->newline() << "{"; s.op->indent(1); if (! s.runtime_usermode_p()) { s.op->newline() << "cycles_t cycles_atend = get_cycles ();"; // NB: we truncate cycles counts to 32 bits. Perhaps it should be // fewer, if the hardware counter rolls over really quickly. We // handle 32-bit wraparound here. s.op->newline() << "int32_t cycles_elapsed = ((int32_t)cycles_atend > (int32_t)cycles_atstart)"; s.op->newline(1) << "? ((int32_t)cycles_atend - (int32_t)cycles_atstart)"; s.op->newline() << ": (~(int32_t)0) - (int32_t)cycles_atstart + (int32_t)cycles_atend + 1;"; s.op->indent(-1); } else { s.op->newline() << "struct timespec timespec_atend, timespec_elapsed;"; s.op->newline() << "long cycles_elapsed;"; s.op->newline() << "(void)clock_gettime(CLOCK_MONOTONIC_RAW, ×pec_atend);"; s.op->newline() << "_stp_timespec_sub(×pec_atend, ×pec_atstart, ×pec_elapsed);"; // 'cycles_elapsed' is really elapsed nanoseconds s.op->newline() << "cycles_elapsed = (timespec_elapsed.tv_sec * NSEC_PER_SEC) + timespec_elapsed.tv_nsec;"; } s.op->newline() << "#ifdef STP_TIMING"; s.op->newline() << "if (likely (stat)) _stp_stat_add(stat, cycles_elapsed);"; s.op->newline() << "#endif"; if (overload_processing && !s.runtime_usermode_p()) { s.op->newline() << "#ifdef STP_OVERLOAD"; s.op->newline() << "{"; // If the cycle count has wrapped (cycles_atend > cycles_base), // let's go ahead and pretend the interval has been reached. // This should reset cycles_base and cycles_sum. s.op->newline(1) << "cycles_t interval = (cycles_atend > c->cycles_base)"; s.op->newline(1) << "? (cycles_atend - c->cycles_base)"; s.op->newline() << ": (STP_OVERLOAD_INTERVAL + 1);"; s.op->newline(-1) << "c->cycles_sum += cycles_elapsed;"; // If we've spent more than STP_OVERLOAD_THRESHOLD cycles in a // probe during the last STP_OVERLOAD_INTERVAL cycles, the probe // has overloaded the system and we need to quit. // NB: this is not suppressible via --suppress-runtime-errors, // because this is a system safety metric that we cannot trust // unprivileged users to override. s.op->newline() << "if (interval > STP_OVERLOAD_INTERVAL) {"; s.op->newline(1) << "if (c->cycles_sum > STP_OVERLOAD_THRESHOLD) {"; s.op->newline(1) << "_stp_error (\"probe overhead exceeded threshold\");"; s.op->newline() << "atomic_set (session_state(), STAP_SESSION_ERROR);"; s.op->newline() << "atomic_inc (error_count());"; s.op->newline(-1) << "}"; s.op->newline() << "c->cycles_base = cycles_atend;"; s.op->newline() << "c->cycles_sum = 0;"; s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; s.op->newline() << "#endif"; } s.op->newline(-1) << "}"; s.op->newline() << "#endif"; s.op->newline() << "c->probe_point = 0;"; // vacated s.op->newline() << "#ifdef STP_NEED_PROBE_NAME"; s.op->newline() << "c->probe_name = 0;"; s.op->newline() << "#endif"; s.op->newline() << "c->probe_type = 0;"; s.op->newline() << "if (unlikely (c->last_error && c->last_error[0])) {"; s.op->indent(1); if (s.suppress_handler_errors) // PR 13306 { s.op->newline() << "atomic_inc (error_count());"; } else { s.op->newline() << "if (c->last_stmt != NULL)"; s.op->newline(1) << "_stp_softerror (\"%s near %s\", c->last_error, c->last_stmt);"; s.op->newline(-1) << "else"; s.op->newline(1) << "_stp_softerror (\"%s\", c->last_error);"; s.op->indent(-1); s.op->newline() << "atomic_inc (error_count());"; s.op->newline() << "if (atomic_read (error_count()) > MAXERRORS) {"; s.op->newline(1) << "atomic_set (session_state(), STAP_SESSION_ERROR);"; s.op->newline() << "_stp_exit ();"; s.op->newline(-1) << "}"; } s.op->newline(-1) << "}"; s.op->newline() << "atomic_dec (&c->busy);"; s.op->newline(-1) << "probe_epilogue:"; // context is free s.op->indent(1); // In dyninst mode, we're not done with the context yet, since // _stp_error() still needs a context structure (since the log // buffers are stored there). if (!s.runtime_usermode_p()) { s.op->newline() << "_stp_runtime_entryfn_put_context(c);"; } if (! s.suppress_handler_errors) // PR 13306 { // Check for excessive skip counts. s.op->newline() << "if (unlikely (atomic_read (skipped_count()) > MAXSKIPPED)) {"; s.op->newline(1) << "if (unlikely (pseudo_atomic_cmpxchg(session_state(), STAP_SESSION_RUNNING, STAP_SESSION_ERROR) == STAP_SESSION_RUNNING))"; s.op->newline() << "_stp_error (\"Skipped too many probes, check MAXSKIPPED or try again with stap -t for more details.\");"; s.op->newline(-1) << "}"; } s.op->newline() << "#if INTERRUPTIBLE"; s.op->newline() << "preempt_enable_no_resched ();"; s.op->newline() << "#else"; s.op->newline() << "local_irq_restore (flags);"; s.op->newline() << "#endif"; if (s.runtime_usermode_p()) { s.op->newline() << "_stp_runtime_entryfn_put_context(c);"; s.op->newline() << "errno = _stp_saved_errno;"; } s.op->newline() << "#endif // STP_ALIBI"; if (s.runtime_usermode_p()) s.op->newline(-1) << "}"; } // ------------------------------------------------------------------------ // ------------------------------------------------------------------------ // Dwarf derived probes. "We apologize for the inconvience." // ------------------------------------------------------------------------ static const string TOK_KERNEL("kernel"); static const string TOK_MODULE("module"); static const string TOK_FUNCTION("function"); static const string TOK_INLINE("inline"); static const string TOK_CALL("call"); static const string TOK_EXPORTED("exported"); static const string TOK_RETURN("return"); static const string TOK_MAXACTIVE("maxactive"); static const string TOK_STATEMENT("statement"); static const string TOK_ABSOLUTE("absolute"); static const string TOK_PROCESS("process"); static const string TOK_PROVIDER("provider"); static const string TOK_MARK("mark"); static const string TOK_TRACE("trace"); static const string TOK_LABEL("label"); static const string TOK_LIBRARY("library"); static const string TOK_PLT("plt"); static const string TOK_METHOD("method"); static const string TOK_CLASS("class");; static int query_cu (Dwarf_Die * cudie, void * arg); static void query_addr(Dwarf_Addr addr, dwarf_query *q); // Can we handle this query with just symbol-table info? enum dbinfo_reqt { dbr_unknown, dbr_none, // kernel.statement(NUM).absolute dbr_need_symtab, // can get by with symbol table if there's no dwarf dbr_need_dwarf }; struct base_query; // forward decls struct dwarf_query; struct dwflpp; struct symbol_table; struct symbol_table { module_info *mod_info; // associated module map map_by_name; multimap map_by_addr; typedef multimap::iterator iterator_t; typedef pair range_t; #ifdef __powerpc__ GElf_Word opd_section; #endif void add_symbol(const char *name, bool weak, bool descriptor, Dwarf_Addr addr, Dwarf_Addr *high_addr); enum info_status read_symbols(FILE *f, const string& path); enum info_status read_from_elf_file(const string& path, systemtap_session &sess); enum info_status read_from_text_file(const string& path, systemtap_session &sess); enum info_status get_from_elf(); void prepare_section_rejection(Dwfl_Module *mod); bool reject_section(GElf_Word section); void purge_syscall_stubs(); func_info *lookup_symbol(const string& name); Dwarf_Addr lookup_symbol_address(const string& name); func_info *get_func_containing_address(Dwarf_Addr addr); func_info *get_first_func(); symbol_table(module_info *mi) : mod_info(mi) {} ~symbol_table(); }; static bool null_die(Dwarf_Die *die) { static Dwarf_Die null; return (!die || !memcmp(die, &null, sizeof(null))); } enum function_spec_type { function_alone, function_and_file, function_file_and_line }; struct dwarf_builder; struct dwarf_var_expanding_visitor; // XXX: This class is a candidate for subclassing to separate // the relocation vs non-relocation variants. Likewise for // kprobe vs kretprobe variants. struct dwarf_derived_probe: public derived_probe { dwarf_derived_probe (const string& function, const string& filename, int line, const string& module, const string& section, Dwarf_Addr dwfl_addr, Dwarf_Addr addr, dwarf_query & q, Dwarf_Die* scope_die); string module; string section; Dwarf_Addr addr; string path; bool has_process; bool has_return; bool has_maxactive; bool has_library; long maxactive_val; // dwarf_derived_probe_group::emit_module_decls uses this to emit sdt kprobe definition string user_path; string user_lib; bool access_vars; unsigned saved_longs, saved_strings; dwarf_derived_probe* entry_handler; void printsig (std::ostream &o) const; virtual void join_group (systemtap_session& s); void emit_probe_local_init(systemtap_session& s, translator_output * o); void getargs(std::list &arg_set) const; void emit_privilege_assertion (translator_output*); void print_dupe_stamp(ostream& o); // Pattern registration helpers. static void register_statement_variants(match_node * root, dwarf_builder * dw, privilege_t privilege); static void register_function_variants(match_node * root, dwarf_builder * dw, privilege_t privilege); static void register_function_and_statement_variants(systemtap_session& s, match_node * root, dwarf_builder * dw, privilege_t privilege); static void register_sdt_variants(systemtap_session& s, match_node * root, dwarf_builder * dw); static void register_plt_variants(systemtap_session& s, match_node * root, dwarf_builder * dw); static void register_patterns(systemtap_session& s); protected: dwarf_derived_probe(probe *base, probe_point *location, Dwarf_Addr addr, bool has_return): derived_probe(base, location), addr(addr), has_process(0), has_return(has_return), has_maxactive(0), has_library(0), maxactive_val(0), access_vars(false), saved_longs(0), saved_strings(0), entry_handler(0) {} private: list args; void saveargs(dwarf_query& q, Dwarf_Die* scope_die, Dwarf_Addr dwfl_addr); }; struct uprobe_derived_probe: public dwarf_derived_probe { int pid; // 0 => unrestricted uprobe_derived_probe (const string& function, const string& filename, int line, const string& module, const string& section, Dwarf_Addr dwfl_addr, Dwarf_Addr addr, dwarf_query & q, Dwarf_Die* scope_die): dwarf_derived_probe(function, filename, line, module, section, dwfl_addr, addr, q, scope_die), pid(0) {} // alternate constructor for process(PID).statement(ADDR).absolute uprobe_derived_probe (probe *base, probe_point *location, int pid, Dwarf_Addr addr, bool has_return): dwarf_derived_probe(base, location, addr, has_return), pid(pid) {} void join_group (systemtap_session& s); void emit_privilege_assertion (translator_output*); void print_dupe_stamp(ostream& o) { print_dupe_stamp_unprivileged_process_owner (o); } void getargs(std::list &arg_set) const; void saveargs(int nargs); private: list args; }; struct dwarf_derived_probe_group: public derived_probe_group { private: multimap probes_by_module; typedef multimap::iterator p_b_m_iterator; public: dwarf_derived_probe_group() {} void enroll (dwarf_derived_probe* probe); void emit_module_decls (systemtap_session& s); void emit_module_init (systemtap_session& s); void emit_module_refresh (systemtap_session& s); void emit_module_exit (systemtap_session& s); }; // Helper struct to thread through the dwfl callbacks. struct base_query { base_query(dwflpp & dw, literal_map_t const & params); base_query(dwflpp & dw, const string & module_val); virtual ~base_query() {} systemtap_session & sess; dwflpp & dw; // Parameter extractors. static bool has_null_param(literal_map_t const & params, string const & k); static bool get_string_param(literal_map_t const & params, string const & k, string & v); static bool get_number_param(literal_map_t const & params, string const & k, long & v); static bool get_number_param(literal_map_t const & params, string const & k, Dwarf_Addr & v); static void query_library_callback (void *object, const char *data); static void query_plt_callback (void *object, const char *link, size_t addr); virtual void query_library (const char *data) = 0; virtual void query_plt (const char *link, size_t addr) = 0; // Extracted parameters. bool has_kernel; bool has_module; bool has_process; bool has_library; bool has_plt; bool has_statement; string module_val; // has_kernel => module_val = "kernel" string path; // executable path if module is a .so string plt_val; // has_plt => plt wildcard virtual void handle_query_module() = 0; }; base_query::base_query(dwflpp & dw, literal_map_t const & params): sess(dw.sess), dw(dw), has_library(false), has_plt(false), has_statement(false) { has_kernel = has_null_param (params, TOK_KERNEL); if (has_kernel) module_val = "kernel"; has_module = get_string_param (params, TOK_MODULE, module_val); if (has_module) has_process = false; else { string library_name; long statement_num_val; has_process = get_string_param(params, TOK_PROCESS, module_val); has_library = get_string_param (params, TOK_LIBRARY, library_name); if ((has_plt = has_null_param (params, TOK_PLT))) plt_val = "*"; else has_plt = get_string_param (params, TOK_PLT, plt_val); if (has_plt) sess.consult_symtab = true; has_statement = get_number_param(params, TOK_STATEMENT, statement_num_val); if (has_process) module_val = find_executable (module_val, sess.sysroot, sess.sysenv); if (has_library) { if (! contains_glob_chars (library_name)) { path = path_remove_sysroot(sess, module_val); module_val = find_executable (library_name, sess.sysroot, sess.sysenv, "LD_LIBRARY_PATH"); if (module_val.find('/') == string::npos) { // We didn't find library_name so use iterate_over_libraries module_val = path; path = library_name; } } else path = library_name; } } assert (has_kernel || has_process || has_module); } base_query::base_query(dwflpp & dw, const string & module_val) : sess(dw.sess), dw(dw), has_library(false), has_plt(false), has_statement(false), module_val(module_val) { // NB: This uses '/' to distinguish between kernel modules and userspace, // which means that userspace modules won't get any PATH searching. if (module_val.find('/') == string::npos) { has_kernel = (module_val == TOK_KERNEL); has_module = !has_kernel; has_process = false; } else { has_kernel = has_module = false; has_process = true; } } bool base_query::has_null_param(literal_map_t const & params, string const & k) { return derived_probe_builder::has_null_param(params, k); } bool base_query::get_string_param(literal_map_t const & params, string const & k, string & v) { return derived_probe_builder::get_param (params, k, v); } bool base_query::get_number_param(literal_map_t const & params, string const & k, long & v) { int64_t value; bool present = derived_probe_builder::get_param (params, k, value); v = (long) value; return present; } bool base_query::get_number_param(literal_map_t const & params, string const & k, Dwarf_Addr & v) { int64_t value; bool present = derived_probe_builder::get_param (params, k, value); v = (Dwarf_Addr) value; return present; } struct dwarf_query : public base_query { dwarf_query(probe * base_probe, probe_point * base_loc, dwflpp & dw, literal_map_t const & params, vector & results, const string user_path, const string user_lib); vector & results; set inlined_non_returnable; // function names probe * base_probe; probe_point * base_loc; string user_path; string user_lib; // Used to keep track of which modules were visited during // iterate_over_modules() set visited_modules; virtual void handle_query_module(); void query_module_dwarf(); void query_module_symtab(); void query_library (const char *data); void query_plt (const char *entry, size_t addr); void add_probe_point(string const & funcname, char const * filename, int line, Dwarf_Die *scope_die, Dwarf_Addr addr); // Track addresses we've already seen in a given module set alias_dupes; // Track inlines we've already seen as well // NB: this can't be compared just by entrypc, as inlines can overlap set inline_dupes; // Extracted parameters. string function_val; bool has_function_str; bool has_statement_str; bool has_function_num; bool has_statement_num; string statement_str_val; string function_str_val; Dwarf_Addr statement_num_val; Dwarf_Addr function_num_val; bool has_call; bool has_exported; bool has_inline; bool has_return; bool has_maxactive; long maxactive_val; bool has_label; string label_val; bool has_relative; long relative_val; bool has_absolute; bool has_mark; enum dbinfo_reqt dbinfo_reqt; enum dbinfo_reqt assess_dbinfo_reqt(); void parse_function_spec(const string & spec); function_spec_type spec_type; vector scopes; string function; string file; line_t line_type; int line[2]; bool query_done; // Found exact match set filtered_srcfiles; // Map official entrypc -> func_info object inline_instance_map_t filtered_inlines; func_info_map_t filtered_functions; bool choose_next_line; Dwarf_Addr entrypc_for_next_line; void query_module_functions (); }; static void delete_session_module_cache (systemtap_session& s); // forward decl struct dwarf_builder: public derived_probe_builder { map kern_dw; /* NB: key string could be a wildcard */ map user_dw; string user_path; string user_lib; // Holds modules to suggest functions from. NB: aggregates over // recursive calls to build() when deriving globby probes. set modules_seen; dwarf_builder() {} dwflpp *get_kern_dw(systemtap_session& sess, const string& module) { if (kern_dw[module] == 0) kern_dw[module] = new dwflpp(sess, module, true); // might throw return kern_dw[module]; } dwflpp *get_user_dw(systemtap_session& sess, const string& module) { if (user_dw[module] == 0) user_dw[module] = new dwflpp(sess, module, false); // might throw return user_dw[module]; } string suggest_functions(systemtap_session& sess, string func); /* NB: not virtual, so can be called from dtor too: */ void dwarf_build_no_more (bool) { delete_map(kern_dw); delete_map(user_dw); } void build_no_more (systemtap_session &s) { dwarf_build_no_more (s.verbose > 3); delete_session_module_cache (s); } ~dwarf_builder() { dwarf_build_no_more (false); } virtual void build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results); }; dwarf_query::dwarf_query(probe * base_probe, probe_point * base_loc, dwflpp & dw, literal_map_t const & params, vector & results, const string user_path, const string user_lib) : base_query(dw, params), results(results), base_probe(base_probe), base_loc(base_loc), user_path(user_path), user_lib(user_lib), has_relative(false), relative_val(0), choose_next_line(false), entrypc_for_next_line(0) { // Reduce the query to more reasonable semantic values (booleans, // extracted strings, numbers, etc). has_function_str = get_string_param(params, TOK_FUNCTION, function_str_val); has_function_num = get_number_param(params, TOK_FUNCTION, function_num_val); has_statement_str = get_string_param(params, TOK_STATEMENT, statement_str_val); has_statement_num = get_number_param(params, TOK_STATEMENT, statement_num_val); has_label = get_string_param(params, TOK_LABEL, label_val); has_call = has_null_param(params, TOK_CALL); has_exported = has_null_param(params, TOK_EXPORTED); has_inline = has_null_param(params, TOK_INLINE); has_return = has_null_param(params, TOK_RETURN); has_maxactive = get_number_param(params, TOK_MAXACTIVE, maxactive_val); has_absolute = has_null_param(params, TOK_ABSOLUTE); has_mark = false; if (has_function_str) parse_function_spec(function_str_val); else if (has_statement_str) parse_function_spec(statement_str_val); dbinfo_reqt = assess_dbinfo_reqt(); query_done = false; } func_info_map_t * get_filtered_functions(dwarf_query *q) { return &q->filtered_functions; } inline_instance_map_t * get_filtered_inlines(dwarf_query *q) { return &q->filtered_inlines; } void dwarf_query::query_module_dwarf() { if (has_function_num || has_statement_num) { // If we have module("foo").function(0xbeef) or // module("foo").statement(0xbeef), the address is relative // to the start of the module, so we seek the function // number plus the module's bias. Dwarf_Addr addr = has_function_num ? function_num_val : statement_num_val; // These are raw addresses, we need to know what the elf_bias // is to feed it to libdwfl based functions. Dwarf_Addr elf_bias; Elf *elf = dwfl_module_getelf (dw.module, &elf_bias); assert(elf); addr += elf_bias; query_addr(addr, this); } else { // Otherwise if we have a function("foo") or statement("foo") // specifier, we have to scan over all the CUs looking for // the function(s) in question assert(has_function_str || has_statement_str); // For simple cases, no wildcard and no source:line, we can do a very // quick function lookup in a module-wide cache. if (spec_type == function_alone && !dw.name_has_wildcard(function) && !startswith(function, "_Z")) query_module_functions(); else dw.iterate_over_cus(&query_cu, this, false); } } static void query_func_info (Dwarf_Addr entrypc, func_info & fi, dwarf_query * q); void dwarf_query::query_module_symtab() { // Get the symbol table if it's necessary, sufficient, and not already got. if (dbinfo_reqt == dbr_need_dwarf) return; module_info *mi = dw.mod_info; if (dbinfo_reqt == dbr_need_symtab) { if (mi->symtab_status == info_unknown) mi->get_symtab(this); if (mi->symtab_status == info_absent) return; } func_info *fi = NULL; symbol_table *sym_table = mi->sym_table; if (has_function_str) { // Per dwarf_query::assess_dbinfo_reqt()... assert(spec_type == function_alone); if (dw.name_has_wildcard(function_str_val)) { // Until we augment the blacklist sufficently... if (function_str_val.find_first_not_of("*?") == string::npos) { // e.g., kernel.function("*") cerr << _F("Error: Pattern '%s' matches every single " "instruction address in the symbol table,\n" "some of which aren't even functions.\n", function_str_val.c_str()) << endl; return; } symbol_table::iterator_t iter; for (iter = sym_table->map_by_addr.begin(); iter != sym_table->map_by_addr.end(); ++iter) { fi = iter->second; if (!null_die(&fi->die)) continue; // already handled in query_module_dwarf() if (dw.function_name_matches_pattern(fi->name, function_str_val)) query_func_info(fi->addr, *fi, this); } } else { fi = sym_table->lookup_symbol(function_str_val); if (fi && !fi->descriptor && null_die(&fi->die)) query_func_info(fi->addr, *fi, this); } } else { assert(has_function_num || has_statement_num); // Find the "function" in which the indicated address resides. Dwarf_Addr addr = (has_function_num ? function_num_val : statement_num_val); if (has_plt) { // Use the raw address from the .plt fi = sym_table->get_first_func(); fi->addr = addr; } else fi = sym_table->get_func_containing_address(addr); if (!fi) { sess.print_warning(_F("address %#" PRIx64 " out of range for module %s", addr, dw.module_name.c_str())); return; } if (!null_die(&fi->die)) { // addr looks like it's in the compilation unit containing // the indicated function, but query_module_dwarf() didn't // match addr to any compilation unit, so addr must be // above that cu's address range. sess.print_warning(_F("address %#" PRIx64 " maps to no known compilation unit in module %s", addr, dw.module_name.c_str())); return; } query_func_info(fi->addr, *fi, this); } } void dwarf_query::handle_query_module() { bool report = dbinfo_reqt == dbr_need_dwarf || !sess.consult_symtab; dw.get_module_dwarf(false, report); // prebuild the symbol table to resolve aliases dw.mod_info->get_symtab(this); // reset the dupe-checking for each new module alias_dupes.clear(); inline_dupes.clear(); if (dw.mod_info->dwarf_status == info_present) query_module_dwarf(); // Consult the symbol table if we haven't found all we're looking for. // asm functions can show up in the symbol table but not in dwarf. if (sess.consult_symtab && !query_done) query_module_symtab(); // Add to list of visited modules // Use mod_info->name rather than dw.module_name since the former is // what's actually used in the sess.module_cache->cache map visited_modules.insert(dw.mod_info->name); } void dwarf_query::parse_function_spec(const string & spec) { line_type = ABSOLUTE; line[0] = line[1] = 0; size_t src_pos, line_pos, dash_pos, scope_pos; // look for named scopes scope_pos = spec.rfind("::"); if (scope_pos != string::npos) { tokenize_cxx(spec.substr(0, scope_pos), scopes); scope_pos += 2; } else scope_pos = 0; // look for a source separator src_pos = spec.find('@', scope_pos); if (src_pos == string::npos) { function = spec.substr(scope_pos); spec_type = function_alone; } else { function = spec.substr(scope_pos, src_pos - scope_pos); // look for a line-number separator line_pos = spec.find_first_of(":+", src_pos); if (line_pos == string::npos) { file = spec.substr(src_pos + 1); spec_type = function_and_file; } else { file = spec.substr(src_pos + 1, line_pos - src_pos - 1); // classify the line spec spec_type = function_file_and_line; if (spec[line_pos] == '+') line_type = RELATIVE; else if (spec[line_pos + 1] == '*' && spec.length() == line_pos + 2) line_type = WILDCARD; else line_type = ABSOLUTE; if (line_type != WILDCARD) try { // try to parse either N or N-M dash_pos = spec.find('-', line_pos + 1); if (dash_pos == string::npos) line[0] = line[1] = lex_cast(spec.substr(line_pos + 1)); else { line_type = RANGE; line[0] = lex_cast(spec.substr(line_pos + 1, dash_pos - line_pos - 1)); line[1] = lex_cast(spec.substr(dash_pos + 1)); } } catch (runtime_error & exn) { goto bad; } } } if (function.empty() || (spec_type != function_alone && file.empty())) goto bad; if (sess.verbose > 2) { //clog << "parsed '" << spec << "'"; clog << _F("parse '%s'", spec.c_str()); if (!scopes.empty()) clog << ", scope '" << scopes[0] << "'"; for (unsigned i = 1; i < scopes.size(); ++i) clog << "::'" << scopes[i] << "'"; clog << ", func '" << function << "'"; if (spec_type != function_alone) clog << ", file '" << file << "'"; if (spec_type == function_file_and_line) { clog << ", line "; switch (line_type) { case ABSOLUTE: clog << line[0]; break; case RELATIVE: clog << "+" << line[0]; break; case RANGE: clog << line[0] << " - " << line[1]; break; case WILDCARD: clog << "*"; break; } } clog << endl; } return; bad: throw semantic_error(_F("malformed specification '%s'", spec.c_str()), base_probe->tok); } string path_remove_sysroot(const systemtap_session& sess, const string& path) { size_t pos; string retval = path; if (!sess.sysroot.empty() && (pos = retval.find(sess.sysroot)) != string::npos) retval.replace(pos, sess.sysroot.length(), "/"); return retval; } void dwarf_query::add_probe_point(const string& dw_funcname, const char* filename, int line, Dwarf_Die* scope_die, Dwarf_Addr addr) { string reloc_section; // base section for relocation purposes Dwarf_Addr reloc_addr; // relocated const string& module = dw.module_name; // "kernel" or other string funcname = dw_funcname; assert (! has_absolute); // already handled in dwarf_builder::build() if (!has_plt) reloc_addr = dw.relocate_address(addr, reloc_section); else { // Set the reloc_section but use the plt entry for reloc_addr dw.relocate_address(addr, reloc_section); reloc_addr = addr; } // If we originally used the linkage name, then let's call it that way const char* linkage_name; if (scope_die && startswith (this->function, "_Z") && (linkage_name = dwarf_linkage_name (scope_die))) funcname = linkage_name; if (sess.verbose > 1) { clog << _("probe ") << funcname << "@" << filename << ":" << line; if (string(module) == TOK_KERNEL) clog << _(" kernel"); else if (has_module) clog << _(" module=") << module; else if (has_process) clog << _(" process=") << module; if (reloc_section != "") clog << " reloc=" << reloc_section; clog << " pc=0x" << hex << addr << dec; } bool bad = dw.blacklisted_p (funcname, filename, line, module, addr, has_return); if (sess.verbose > 1) clog << endl; if (module == TOK_KERNEL) { // PR 4224: adapt to relocatable kernel by subtracting the _stext address here. reloc_addr = addr - sess.sym_stext; reloc_section = "_stext"; // a message to runtime's _stp_module_relocate } if (! bad) { sess.unwindsym_modules.insert (module); if (has_process) { string module_tgt = path_remove_sysroot(sess, module); results.push_back (new uprobe_derived_probe(funcname, filename, line, module_tgt, reloc_section, addr, reloc_addr, *this, scope_die)); } else { assert (has_kernel || has_module); results.push_back (new dwarf_derived_probe(funcname, filename, line, module, reloc_section, addr, reloc_addr, *this, scope_die)); } } } enum dbinfo_reqt dwarf_query::assess_dbinfo_reqt() { if (has_absolute) { // kernel.statement(NUM).absolute return dbr_none; } if (has_inline) { // kernel.function("f").inline or module("m").function("f").inline return dbr_need_dwarf; } if (has_function_str && spec_type == function_alone) { // kernel.function("f") or module("m").function("f") return dbr_need_symtab; } if (has_statement_num) { // kernel.statement(NUM) or module("m").statement(NUM) // Technically, all we need is the module offset (or _stext, for // the kernel). But for that we need either the ELF file or (for // _stext) the symbol table. In either case, the symbol table // is available, and that allows us to map the NUM (address) // to a function, which is goodness. return dbr_need_symtab; } if (has_function_num) { // kernel.function(NUM) or module("m").function(NUM) // Need the symbol table so we can back up from NUM to the // start of the function. return dbr_need_symtab; } // Symbol table tells us nothing about source files or line numbers. return dbr_need_dwarf; } // The critical determining factor when interpreting a pattern // string is, perhaps surprisingly: "presence of a lineno". The // presence of a lineno changes the search strategy completely. // // Compare the two cases: // // 1. {statement,function}(foo@file.c:lineno) // - find the files matching file.c // - in each file, find the functions matching foo // - query the file for line records matching lineno // - iterate over the line records, // - and iterate over the functions, // - if(haspc(function.DIE, line.addr)) // - if looking for statements: probe(lineno.addr) // - if looking for functions: probe(function.{entrypc,return,etc.}) // // 2. {statement,function}(foo@file.c) // - find the files matching file.c // - in each file, find the functions matching foo // - probe(function.{entrypc,return,etc.}) // // Thus the first decision we make is based on the presence of a // lineno, and we enter entirely different sets of callbacks // depending on that decision. // // Note that the first case is a generalization fo the second, in that // we could theoretically search through line records for matching // file names (a "table scan" in rdbms lingo). Luckily, file names // are already cached elsewhere, so we can do an "index scan" as an // optimization. static void query_statement (string const & func, char const * file, int line, Dwarf_Die *scope_die, Dwarf_Addr stmt_addr, dwarf_query * q) { try { q->add_probe_point(func, file ? file : "", line, scope_die, stmt_addr); } catch (const semantic_error& e) { q->sess.print_error (e); } } static void query_addr(Dwarf_Addr addr, dwarf_query *q) { dwflpp &dw = q->dw; if (q->sess.verbose > 2) clog << "query_addr 0x" << hex << addr << dec << endl; // First pick which CU contains this address Dwarf_Die* cudie = dw.query_cu_containing_address(addr); if (!cudie) // address could be wildly out of range return; dw.focus_on_cu(cudie); // Now compensate for the dw bias addr -= dw.module_bias; // Per PR5787, we look up the scope die even for // statement_num's, for blacklist sensitivity and $var // resolution purposes. // Find the scopes containing this address vector scopes = dw.getscopes(addr); if (scopes.empty()) return; // Look for the innermost containing function Dwarf_Die *fnscope = NULL; for (size_t i = 0; i < scopes.size(); ++i) { int tag = dwarf_tag(&scopes[i]); if ((tag == DW_TAG_subprogram && !q->has_inline) || (tag == DW_TAG_inlined_subroutine && !q->has_call && !q->has_return && !q->has_exported)) { fnscope = &scopes[i]; break; } } if (!fnscope) return; dw.focus_on_function(fnscope); Dwarf_Die *scope = q->has_function_num ? fnscope : &scopes[0]; const char *file = dwarf_decl_file(fnscope); int line; dwarf_decl_line(fnscope, &line); // Function probes should reset the addr to the function entry // and possibly perform prologue searching if (q->has_function_num) { dw.die_entrypc(fnscope, &addr); if (dwarf_tag(fnscope) == DW_TAG_subprogram && (q->sess.prologue_searching || q->has_process)) // PR 6871 { func_info func; func.die = *fnscope; func.name = dw.function_name; func.decl_file = file; func.decl_line = line; func.entrypc = addr; func_info_map_t funcs(1, func); dw.resolve_prologue_endings (funcs); if (q->has_return) // PR13200 { if (q->sess.verbose > 2) clog << "ignoring prologue for .return probes" << endl; } else { if (funcs[0].prologue_end) addr = funcs[0].prologue_end; } } } else { dwarf_line_t address_line(dwarf_getsrc_die(cudie, addr)); if (address_line) { file = address_line.linesrc(); line = address_line.lineno(); } // Verify that a raw address matches the beginning of a // statement. This is a somewhat lame check that the address // is at the start of an assembly instruction. Mark probes are in the // middle of a macro and thus not strictly at a statement beginning. // Guru mode may override this check. if (!q->has_mark && (!address_line || address_line.addr() != addr)) { stringstream msg; msg << _F("address %#" PRIx64 " does not match the beginning of a statement", addr); if (address_line) msg << _F(" (try %#" PRIx64 ")", address_line.addr()); else msg << _F(" (no line info found for '%s', in module '%s')", dw.cu_name().c_str(), dw.module_name.c_str()); if (! q->sess.guru_mode) throw semantic_error(msg.str()); else q->sess.print_warning(msg.str()); } } // Build a probe at this point query_statement(dw.function_name, file, line, scope, addr, q); } static void query_label (string const & func, char const * label, char const * file, int line, Dwarf_Die *scope_die, Dwarf_Addr stmt_addr, dwarf_query * q) { assert (q->has_statement_str || q->has_function_str); size_t i = q->results.size(); // weed out functions whose decl_file isn't one of // the source files that we actually care about if (q->spec_type != function_alone && q->filtered_srcfiles.count(file) == 0) return; query_statement(func, file, line, scope_die, stmt_addr, q); // after the fact, insert the label back into the derivation chain probe_point::component* ppc = new probe_point::component(TOK_LABEL, new literal_string (label)); for (; i < q->results.size(); ++i) { derived_probe* p = q->results[i]; probe_point* pp = new probe_point(*p->locations[0]); pp->components.push_back (ppc); p->base = p->base->create_alias(p->locations[0], pp); } } static void query_inline_instance_info (inline_instance_info & ii, dwarf_query * q) { try { assert (! q->has_return); // checked by caller already if (q->sess.verbose>2) clog << _F("querying entrypc %#" PRIx64 " of instance of inline '%s'\n", ii.entrypc, ii.name.c_str()); query_statement (ii.name, ii.decl_file, ii.decl_line, &ii.die, ii.entrypc, q); } catch (semantic_error &e) { q->sess.print_error (e); } } static void query_func_info (Dwarf_Addr entrypc, func_info & fi, dwarf_query * q) { try { if (q->has_return) { // NB. dwarf_derived_probe::emit_registrations will emit a // kretprobe based on the entrypc in this case. if (fi.prologue_end != 0 && q->has_return) // PR13200 { if (q->sess.verbose > 2) clog << "ignoring prologue for .return probes" << endl; } query_statement (fi.name, fi.decl_file, fi.decl_line, &fi.die, entrypc, q); } else { if (fi.prologue_end != 0) { query_statement (fi.name, fi.decl_file, fi.decl_line, &fi.die, fi.prologue_end, q); } else { query_statement (fi.name, fi.decl_file, fi.decl_line, &fi.die, entrypc, q); } } } catch (semantic_error &e) { q->sess.print_error (e); } } static void query_srcfile_label (const dwarf_line_t& line, void * arg) { dwarf_query * q = static_cast(arg); Dwarf_Addr addr = line.addr(); for (func_info_map_t::iterator i = q->filtered_functions.begin(); i != q->filtered_functions.end(); ++i) if (q->dw.die_has_pc (i->die, addr)) q->dw.iterate_over_labels (&i->die, q->label_val, i->name, q, query_label); for (inline_instance_map_t::iterator i = q->filtered_inlines.begin(); i != q->filtered_inlines.end(); ++i) if (q->dw.die_has_pc (i->die, addr)) q->dw.iterate_over_labels (&i->die, q->label_val, i->name, q, query_label); } static void query_srcfile_line (const dwarf_line_t& line, void * arg) { dwarf_query * q = static_cast(arg); Dwarf_Addr addr = line.addr(); int lineno = line.lineno(); for (func_info_map_t::iterator i = q->filtered_functions.begin(); i != q->filtered_functions.end(); ++i) { if (q->dw.die_has_pc (i->die, addr)) { if (q->sess.verbose>3) clog << _("function DIE lands on srcfile\n"); if (q->has_statement_str) { Dwarf_Die scope; q->dw.inner_die_containing_pc(i->die, addr, scope); query_statement (i->name, i->decl_file, lineno, // NB: not q->line ! &scope, addr, q); } else query_func_info (i->entrypc, *i, q); } } for (inline_instance_map_t::iterator i = q->filtered_inlines.begin(); i != q->filtered_inlines.end(); ++i) { if (q->dw.die_has_pc (i->die, addr)) { if (q->sess.verbose>3) clog << _("inline instance DIE lands on srcfile\n"); if (q->has_statement_str) { Dwarf_Die scope; q->dw.inner_die_containing_pc(i->die, addr, scope); query_statement (i->name, i->decl_file, lineno, // NB: not q->line ! &scope, addr, q); } else query_inline_instance_info (*i, q); } } } bool inline_instance_info::operator<(const inline_instance_info& other) const { if (entrypc != other.entrypc) return entrypc < other.entrypc; if (decl_line != other.decl_line) return decl_line < other.decl_line; int cmp = name.compare(other.name); if (!cmp) cmp = strcmp(decl_file, other.decl_file); return cmp < 0; } static int query_dwarf_inline_instance (Dwarf_Die * die, void * arg) { dwarf_query * q = static_cast(arg); assert (q->has_statement_str || q->has_function_str); assert (!q->has_call && !q->has_return && !q->has_exported); try { if (q->sess.verbose>2) clog << _F("selected inline instance of %s\n", q->dw.function_name.c_str()); Dwarf_Addr entrypc; if (q->dw.die_entrypc (die, &entrypc)) { inline_instance_info inl; inl.die = *die; inl.name = q->dw.function_name; inl.entrypc = entrypc; q->dw.function_file (&inl.decl_file); q->dw.function_line (&inl.decl_line); // make sure that this inline hasn't already // been matched from a different CU if (q->inline_dupes.insert(inl).second) q->filtered_inlines.push_back(inl); } return DWARF_CB_OK; } catch (const semantic_error& e) { q->sess.print_error (e); return DWARF_CB_ABORT; } } static int query_dwarf_func (Dwarf_Die * func, base_query * bq) { dwarf_query * q = static_cast(bq); assert (q->has_statement_str || q->has_function_str); // weed out functions whose decl_file isn't one of // the source files that we actually care about if (q->spec_type != function_alone && q->filtered_srcfiles.count(dwarf_decl_file(func)?:"") == 0) return DWARF_CB_OK; try { q->dw.focus_on_function (func); if (!q->dw.function_scope_matches(q->scopes)) return DWARF_CB_OK; // make sure that this function address hasn't // already been matched under an aliased name Dwarf_Addr addr; if (!q->dw.func_is_inline() && dwarf_entrypc(func, &addr) == 0 && !q->alias_dupes.insert(addr).second) return DWARF_CB_OK; if (q->dw.func_is_inline () && (! q->has_call) && (! q->has_return) && (! q->has_exported)) { if (q->sess.verbose>3) clog << _F("checking instances of inline %s\n", q->dw.function_name.c_str()); q->dw.iterate_over_inline_instances (query_dwarf_inline_instance, q); } else if (q->dw.func_is_inline () && (q->has_return)) // PR 11553 { q->inlined_non_returnable.insert (q->dw.function_name); } else if (!q->dw.func_is_inline () && (! q->has_inline)) { if (q->has_exported && !q->dw.func_is_exported ()) return DWARF_CB_OK; if (q->sess.verbose>2) clog << _F("selected function %s\n", q->dw.function_name.c_str()); func_info func; q->dw.function_die (&func.die); func.name = q->dw.function_name; q->dw.function_file (&func.decl_file); q->dw.function_line (&func.decl_line); Dwarf_Addr entrypc; if (q->dw.function_entrypc (&entrypc)) { func.entrypc = entrypc; q->filtered_functions.push_back (func); } /* else this function is fully inlined, just ignore it */ } return DWARF_CB_OK; } catch (const semantic_error& e) { q->sess.print_error (e); return DWARF_CB_ABORT; } } static int query_cu (Dwarf_Die * cudie, void * arg) { dwarf_query * q = static_cast(arg); assert (q->has_statement_str || q->has_function_str); if (pending_interrupts) return DWARF_CB_ABORT; try { q->dw.focus_on_cu (cudie); if (false && q->sess.verbose>2) clog << _F("focused on CU '%s', in module '%s'\n", q->dw.cu_name().c_str(), q->dw.module_name.c_str()); q->filtered_srcfiles.clear(); q->filtered_functions.clear(); q->filtered_inlines.clear(); // In this path, we find "abstract functions", record // information about them, and then (depending on lineno // matching) possibly emit one or more of the function's // associated addresses. Unfortunately the control of this // cannot easily be turned inside out. if (q->spec_type != function_alone) { // If we have a pattern string with a filename, we need // to elaborate the srcfile mask in question first. q->dw.collect_srcfiles_matching (q->file, q->filtered_srcfiles); // If we have a file pattern and *no* srcfile matches, there's // no need to look further into this CU, so skip. if (q->filtered_srcfiles.empty()) return DWARF_CB_OK; } // Pick up [entrypc, name, DIE] tuples for all the functions // matching the query, and fill in the prologue endings of them // all in a single pass. int rc = q->dw.iterate_over_functions (query_dwarf_func, q, q->function); if (rc != DWARF_CB_OK) q->query_done = true; if ((q->sess.prologue_searching || q->has_process) // PR 6871 && !q->has_statement_str) // PR 2608 if (! q->filtered_functions.empty()) q->dw.resolve_prologue_endings (q->filtered_functions); // NB: we could skip the resolve_prologue_endings() call here for has_return case (PR13200), // but don't have to. We can resolve the prologue, just not actually use it in query_addr(). if (q->spec_type == function_file_and_line) { // .statement(...:NN) often gets mixed up with .function(...:NN) if (q->has_function_str) q->sess.print_warning (_("For probing a particular line, use a " ".statement() probe, not .function()"), q->base_probe->tok); // If we have a pattern string with target *line*, we // have to look at lines in all the matched srcfiles. void (* callback) (const dwarf_line_t&, void*) = q->has_label ? query_srcfile_label : query_srcfile_line; for (set::const_iterator i = q->filtered_srcfiles.begin(); i != q->filtered_srcfiles.end(); ++i) q->dw.iterate_over_srcfile_lines (i->c_str(), q->line, q->has_statement_str, q->line_type, callback, q->function, q); } else if (q->has_label) { for (func_info_map_t::iterator i = q->filtered_functions.begin(); i != q->filtered_functions.end(); ++i) q->dw.iterate_over_labels (&i->die, q->label_val, i->name, q, query_label); for (inline_instance_map_t::iterator i = q->filtered_inlines.begin(); i != q->filtered_inlines.end(); ++i) q->dw.iterate_over_labels (&i->die, q->label_val, i->name, q, query_label); } else { // Otherwise, simply probe all resolved functions. for (func_info_map_t::iterator i = q->filtered_functions.begin(); i != q->filtered_functions.end(); ++i) query_func_info (i->entrypc, *i, q); // And all inline instances (if we're not excluding inlines with ".call") if (! q->has_call) for (inline_instance_map_t::iterator i = q->filtered_inlines.begin(); i != q->filtered_inlines.end(); ++i) query_inline_instance_info (*i, q); } return DWARF_CB_OK; } catch (const semantic_error& e) { q->sess.print_error (e); return DWARF_CB_ABORT; } } void dwarf_query::query_module_functions () { try { filtered_srcfiles.clear(); filtered_functions.clear(); filtered_inlines.clear(); // Collect all module functions so we know which CUs are interesting int rc = dw.iterate_single_function(query_dwarf_func, this, function); if (rc != DWARF_CB_OK) { query_done = true; return; } set used_cus; // by cu->addr vector cus; Dwarf_Die cu_mem; for (func_info_map_t::iterator i = filtered_functions.begin(); i != filtered_functions.end(); ++i) if (dwarf_diecu(&i->die, &cu_mem, NULL, NULL) && used_cus.insert(cu_mem.addr).second) cus.push_back(cu_mem); for (inline_instance_map_t::iterator i = filtered_inlines.begin(); i != filtered_inlines.end(); ++i) if (dwarf_diecu(&i->die, &cu_mem, NULL, NULL) && used_cus.insert(cu_mem.addr).second) cus.push_back(cu_mem); // Reset the dupes since we didn't actually collect them the first time alias_dupes.clear(); inline_dupes.clear(); // Run the query again on the individual CUs for (vector::iterator i = cus.begin(); i != cus.end(); ++i) query_cu(&*i, this); } catch (const semantic_error& e) { sess.print_error (e); } } static void validate_module_elf (Dwfl_Module *mod, const char *name, base_query *q) { // Validate the machine code in this elf file against the // session machine. This is important, in case the wrong kind // of debuginfo is being automagically processed by elfutils. // While we can tell i686 apart from x86-64, unfortunately // we can't help confusing i586 vs i686 (both EM_386). Dwarf_Addr bias; // We prefer dwfl_module_getdwarf to dwfl_module_getelf here, // because dwfl_module_getelf can force costly section relocations // we don't really need, while either will do for this purpose. Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (mod, &bias)) ?: dwfl_module_getelf (mod, &bias)); GElf_Ehdr ehdr_mem; GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem); if (em == 0) { dwfl_assert ("dwfl_getehdr", dwfl_errno()); } assert(em); int elf_machine = em->e_machine; const char* debug_filename = ""; const char* main_filename = ""; (void) dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL, & main_filename, & debug_filename); const string& sess_machine = q->sess.architecture; string expect_machine; // to match sess.machine (i.e., kernel machine) string expect_machine2; // NB: See also the 'uname -m' squashing done in main.cxx. switch (elf_machine) { // x86 and ppc are bi-architecture; a 64-bit kernel // can normally run either 32-bit or 64-bit *userspace*. case EM_386: expect_machine = "i?86"; if (! q->has_process) break; // 32-bit kernel/module /* FALLSTHROUGH */ case EM_X86_64: expect_machine2 = "x86_64"; break; case EM_PPC: case EM_PPC64: expect_machine = "powerpc"; break; case EM_S390: expect_machine = "s390"; break; case EM_IA_64: expect_machine = "ia64"; break; case EM_ARM: expect_machine = "arm*"; break; // XXX: fill in some more of these default: expect_machine = "?"; break; } if (! debug_filename) debug_filename = main_filename; if (! debug_filename) debug_filename = name; if (fnmatch (expect_machine.c_str(), sess_machine.c_str(), 0) != 0 && fnmatch (expect_machine2.c_str(), sess_machine.c_str(), 0) != 0) { stringstream msg; msg << _F("ELF machine %s|%s (code %d) mismatch with target %s in '%s'", expect_machine.c_str(), expect_machine2.c_str(), elf_machine, sess_machine.c_str(), debug_filename); throw semantic_error(msg.str ()); } if (q->sess.verbose>1) clog << _F("focused on module '%s' = [%#" PRIx64 "-%#" PRIx64 ", bias %#" PRIx64 " file %s ELF machine %s|%s (code %d)\n", q->dw.module_name.c_str(), q->dw.module_start, q->dw.module_end, q->dw.module_bias, debug_filename, expect_machine.c_str(), expect_machine2.c_str(), elf_machine); } static Dwarf_Addr lookup_symbol_address (Dwfl_Module *m, const char* wanted) { int syments = dwfl_module_getsymtab(m); assert(syments); for (int i = 1; i < syments; ++i) { GElf_Sym sym; const char *name = dwfl_module_getsym(m, i, &sym, NULL); if (name != NULL && strcmp(name, wanted) == 0) return sym.st_value; } return 0; } static int query_module (Dwfl_Module *mod, void **, const char *name, Dwarf_Addr addr, void *arg) { base_query *q = static_cast(arg); try { module_info* mi = q->sess.module_cache->cache[name]; if (mi == 0) { mi = q->sess.module_cache->cache[name] = new module_info(name); mi->mod = mod; mi->addr = addr; const char* debug_filename = ""; const char* main_filename = ""; (void) dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL, & main_filename, & debug_filename); if (debug_filename || main_filename) { mi->elf_path = debug_filename ?: main_filename; } else if (name == TOK_KERNEL) { mi->dwarf_status = info_absent; } } // OK, enough of that module_info caching business. q->dw.focus_on_module(mod, mi); // If we have enough information in the pattern to skip a module and // the module does not match that information, return early. if (!q->dw.module_name_matches(q->module_val)) return pending_interrupts ? DWARF_CB_ABORT : DWARF_CB_OK; // Don't allow module("*kernel*") type expressions to match the // elfutils module "kernel", which we refer to in the probe // point syntax exclusively as "kernel.*". if (q->dw.module_name == TOK_KERNEL && ! q->has_kernel) return pending_interrupts ? DWARF_CB_ABORT : DWARF_CB_OK; if (mod) validate_module_elf(mod, name, q); else assert(q->has_kernel); // and no vmlinux to examine if (q->sess.verbose>2) cerr << _F("focused on module '%s'\n", q->dw.module_name.c_str()); // Collect a few kernel addresses. XXX: these belong better // to the sess.module_info["kernel"] struct. if (q->dw.module_name == TOK_KERNEL) { if (! q->sess.sym_kprobes_text_start) q->sess.sym_kprobes_text_start = lookup_symbol_address (mod, "__kprobes_text_start"); if (! q->sess.sym_kprobes_text_end) q->sess.sym_kprobes_text_end = lookup_symbol_address (mod, "__kprobes_text_end"); if (! q->sess.sym_stext) q->sess.sym_stext = lookup_symbol_address (mod, "_stext"); } // We either have a wildcard or an unresolved library if (q->has_library && (contains_glob_chars (q->path) || q->path.find('/') == string::npos)) // handle .library(GLOB) q->dw.iterate_over_libraries (&q->query_library_callback, q); // .plt is translated to .plt.statement(N). We only want to iterate for the // .plt case else if (q->has_plt && ! q->has_statement) q->dw.iterate_over_plt (q, &q->query_plt_callback); else // search the module for matches of the probe point. q->handle_query_module(); // If we know that there will be no more matches, abort early. if (q->dw.module_name_final_match(q->module_val) || pending_interrupts) return DWARF_CB_ABORT; else return DWARF_CB_OK; } catch (const semantic_error& e) { q->sess.print_error (e); return DWARF_CB_ABORT; } } void base_query::query_library_callback (void *q, const char *data) { base_query *me = (base_query*)q; me->query_library (data); } string query_one_library (const char *library, dwflpp & dw, const string user_lib, probe * base_probe, probe_point *base_loc, vector & results) { if (dw.function_name_matches_pattern(library, "*" + user_lib)) { string library_path = find_executable (library, "", dw.sess.sysenv, "LD_LIBRARY_PATH"); probe_point* specific_loc = new probe_point(*base_loc); specific_loc->optional = true; vector derived_comps; vector::iterator it; for (it = specific_loc->components.begin(); it != specific_loc->components.end(); ++it) if ((*it)->functor == TOK_LIBRARY) derived_comps.push_back(new probe_point::component(TOK_LIBRARY, new literal_string(library_path))); else derived_comps.push_back(*it); probe_point* derived_loc = new probe_point(*specific_loc); derived_loc->components = derived_comps; probe *new_base = new probe (new probe (base_probe, specific_loc), derived_loc); derive_probes(dw.sess, new_base, results); if (dw.sess.verbose > 2) clog << _("module=") << library_path << endl; return library_path; } return ""; } void dwarf_query::query_library (const char *library) { string library_path = query_one_library (library, dw, user_lib, base_probe, base_loc, results); if (!library_path.empty()) visited_modules.insert(library_path); } struct plt_expanding_visitor: public var_expanding_visitor { plt_expanding_visitor(const string & entry): entry (entry) { } const string & entry; void visit_target_symbol (target_symbol* e); }; void base_query::query_plt_callback (void *q, const char *entry, size_t address) { base_query *me = (base_query*)q; if (me->dw.function_name_matches_pattern (entry, me->plt_val)) me->query_plt (entry, address); } void query_one_plt (const char *entry, long addr, dwflpp & dw, probe * base_probe, probe_point *base_loc, vector & results) { probe_point* specific_loc = new probe_point(*base_loc); vector derived_comps; if (dw.sess.verbose > 2) clog << _F("plt entry=%s\n", entry); // query_module_symtab requires .plt to recognize that it can set the probe at // a plt entry so we convert process.plt to process.plt.statement vector::iterator it; for (it = specific_loc->components.begin(); it != specific_loc->components.end(); ++it) if ((*it)->functor == TOK_PLT) { *it = new probe_point::component(TOK_PLT, new literal_string(entry)); derived_comps.push_back(*it); derived_comps.push_back(new probe_point::component(TOK_STATEMENT, new literal_number(addr, true))); } else derived_comps.push_back(*it); probe_point* derived_loc = new probe_point(*specific_loc); derived_loc->components = derived_comps; probe *new_base = new probe (new probe (base_probe, specific_loc), derived_loc); string e = string(entry); plt_expanding_visitor pltv (e); pltv.replace (new_base->body); derive_probes(dw.sess, new_base, results); } void dwarf_query::query_plt (const char *entry, size_t address) { query_one_plt (entry, address, dw, base_probe, base_loc, results); } // This would more naturally fit into elaborate.cxx:semantic_pass_symbols, // but the needed declaration for module_cache is not available there. // Nor for that matter in session.cxx. Only in this CU is that field ever // set (in query_module() above), so we clean it up here too. static void delete_session_module_cache (systemtap_session& s) { if (s.module_cache) { if (s.verbose > 3) clog << _("deleting module_cache") << endl; delete s.module_cache; s.module_cache = 0; } } struct dwarf_var_expanding_visitor: public var_expanding_visitor { dwarf_query & q; Dwarf_Die *scope_die; Dwarf_Addr addr; block *add_block; block *add_call_probe; // synthesized from .return probes with saved $vars // NB: tids are not always collected in add_block & add_call_probe, because // gen_kretprobe_saved_return doesn't need them. Thus we need these extra // *_tid bools for gen_mapped_saved_return to tell what's there. bool add_block_tid, add_call_probe_tid; unsigned saved_longs, saved_strings; // data saved within kretprobes map return_ts_map; vector scopes; // probe counter name -> pointer of associated probe std::set perf_counter_refs; bool visited; dwarf_var_expanding_visitor(dwarf_query & q, Dwarf_Die *sd, Dwarf_Addr a): q(q), scope_die(sd), addr(a), add_block(NULL), add_call_probe(NULL), add_block_tid(false), add_call_probe_tid(false), saved_longs(0), saved_strings(0), visited(false) {} expression* gen_mapped_saved_return(expression* e, const string& name); expression* gen_kretprobe_saved_return(expression* e); void visit_target_symbol_saved_return (target_symbol* e); void visit_target_symbol_context (target_symbol* e); void visit_target_symbol (target_symbol* e); void visit_atvar_op (atvar_op* e); void visit_cast_op (cast_op* e); void visit_entry_op (entry_op* e); void visit_perf_op (perf_op* e); private: vector& getscopes(target_symbol *e); }; unsigned var_expanding_visitor::tick = 0; var_expanding_visitor::var_expanding_visitor (): op() { // FIXME: for the time being, by default we only support plain '$foo // = bar', not '+=' or any other op= variant. This is fixable, but a // bit ugly. // // If derived classes desire to add additional operator support, add // new operators to this list in the derived class constructor. valid_ops.insert ("="); } bool var_expanding_visitor::rewrite_lvalue(const token* tok, const std::string& eop, expression*& lvalue, expression*& rvalue) { // Our job would normally be to require() the left and right sides // into a new assignment. What we're doing is slightly trickier: // we're pushing a functioncall** onto a stack, and if our left // child sets the functioncall* for that value, we're going to // assume our left child was a target symbol -- transformed into a // set_target_foo(value) call, and it wants to take our right child // as the argument "value". // // This is why some people claim that languages with // constructor-decomposing case expressions have a leg up on // visitors. functioncall *fcall = NULL; // Let visit_target_symbol know what operator it should handle. const string* old_op = op; op = &eop; target_symbol_setter_functioncalls.push (&fcall); replace (lvalue); target_symbol_setter_functioncalls.pop (); replace (rvalue); op = old_op; if (fcall != NULL) { // Our left child is informing us that it was a target variable // and it has been replaced with a set_target_foo() function // call; we are going to provide that function call -- with the // right child spliced in as sole argument -- in place of // ourselves, in the var expansion we're in the middle of making. if (valid_ops.find (eop) == valid_ops.end ()) { // Build up a list of supported operators. string ops; std::set::iterator i; int valid_ops_size = 0; for (i = valid_ops.begin(); i != valid_ops.end(); i++) { ops += " " + *i + ","; valid_ops_size++; } ops.resize(ops.size() - 1); // chop off the last ',' // Throw the error. throw semantic_error (_NF("Only the following assign operator is implemented on target variables: %s", "Only the following assign operators are implemented on target variables: %s", valid_ops_size, ops.c_str()), tok); } assert (lvalue == fcall); if (rvalue) fcall->args.push_back (rvalue); provide (fcall); return true; } else return false; } void var_expanding_visitor::visit_assignment (assignment* e) { if (!rewrite_lvalue (e->tok, e->op, e->left, e->right)) provide (e); } void var_expanding_visitor::visit_pre_crement (pre_crement* e) { expression *dummy = NULL; if (!rewrite_lvalue (e->tok, e->op, e->operand, dummy)) provide (e); } void var_expanding_visitor::visit_post_crement (post_crement* e) { expression *dummy = NULL; if (!rewrite_lvalue (e->tok, e->op, e->operand, dummy)) provide (e); } void var_expanding_visitor::visit_delete_statement (delete_statement* s) { string fakeop = "delete"; expression *dummy = NULL; if (!rewrite_lvalue (s->tok, fakeop, s->value, dummy)) provide (s); } void var_expanding_visitor::visit_defined_op (defined_op* e) { bool resolved = true; defined_ops.push (e); try { // NB: provide<>/require<> are NOT typesafe. So even though a defined_op is // defined with a target_symbol* operand, a subsidiary call may attempt to // rewrite it to a general expression* instead, and require<> happily // casts to/from void*, causing possible memory corruption. We use // expression* here, being the general case of rewritten $variable. expression *foo1 = e->operand; foo1 = require (foo1); // NB: Formerly, we had some curious cases to consider here, depending on what // various visit_target_symbol() implementations do for successful or // erroneous resolutions. Some would signal a visit_target_symbol failure // with an exception, with a set flag within the target_symbol, or nothing // at all. // // Now, failures always have to be signalled with a // saved_conversion_error being chained to the target_symbol. // Successes have to result in an attempted rewrite of the // target_symbol (via provide()). // // Edna Mode: "no capes". fche: "no exceptions". // dwarf stuff: success: rewrites to a function; failure: retains target_symbol, sets saved_conversion_error // // sdt-kprobes sdt.h: success: string or functioncall; failure: semantic_error // // sdt-uprobes: success: string or no op; failure: no op; expect derived/synthetic // dwarf probe to take care of it. // But this is rather unhelpful. So we rig the sdt_var_expanding_visitor // to pass through @defined() to the synthetic dwarf probe. // // utrace: success: rewrites to function; failure: semantic_error // // procfs: success: rewrites to function; failure: semantic_error target_symbol* foo2 = dynamic_cast (foo1); if (foo2 && foo2->saved_conversion_error) // failing resolved = false; else if (foo2) // unresolved but not marked failing { // There are some visitors that won't touch certain target_symbols, // e.g. dwarf_var_expanding_visitor won't resolve @cast. We should // leave it for now so some other visitor can have a chance. e->operand = foo2; provide (e); return; } else // resolved, rewritten to some other expression type resolved = true; } catch (const semantic_error& e) { assert (0); // should not happen } defined_ops.pop (); literal_number* ln = new literal_number (resolved ? 1 : 0); ln->tok = e->tok; provide (ln); } struct dwarf_pretty_print { dwarf_pretty_print (dwflpp& dw, vector& scopes, Dwarf_Addr pc, const string& local, bool userspace_p, const target_symbol& e): dw(dw), local(local), scopes(scopes), pc(pc), pointer(NULL), userspace_p(userspace_p), deref_p(true) { init_ts (e); dw.type_die_for_local (scopes, pc, local, ts, &base_type); } dwarf_pretty_print (dwflpp& dw, Dwarf_Die *scope_die, Dwarf_Addr pc, bool userspace_p, const target_symbol& e): dw(dw), scopes(1, *scope_die), pc(pc), pointer(NULL), userspace_p(userspace_p), deref_p(true) { init_ts (e); dw.type_die_for_return (&scopes[0], pc, ts, &base_type); } dwarf_pretty_print (dwflpp& dw, Dwarf_Die *type_die, expression* pointer, bool deref_p, bool userspace_p, const target_symbol& e): dw(dw), pc(0), pointer(pointer), pointer_type(*type_die), userspace_p(userspace_p), deref_p(deref_p) { init_ts (e); dw.type_die_for_pointer (type_die, ts, &base_type); } functioncall* expand (); ~dwarf_pretty_print () { delete ts; } private: dwflpp& dw; target_symbol* ts; bool print_full; Dwarf_Die base_type; string local; vector scopes; Dwarf_Addr pc; expression* pointer; Dwarf_Die pointer_type; const bool userspace_p, deref_p; void recurse (Dwarf_Die* type, target_symbol* e, print_format* pf, bool top=false); void recurse_bitfield (Dwarf_Die* type, target_symbol* e, print_format* pf); void recurse_base (Dwarf_Die* type, target_symbol* e, print_format* pf); void recurse_array (Dwarf_Die* type, target_symbol* e, print_format* pf, bool top); void recurse_pointer (Dwarf_Die* type, target_symbol* e, print_format* pf, bool top); void recurse_struct (Dwarf_Die* type, target_symbol* e, print_format* pf, bool top); void recurse_struct_members (Dwarf_Die* type, target_symbol* e, print_format* pf, int& count); bool print_chars (Dwarf_Die* type, target_symbol* e, print_format* pf); void init_ts (const target_symbol& e); expression* deref (target_symbol* e); bool push_deref (print_format* pf, const string& fmt, target_symbol* e); }; void dwarf_pretty_print::init_ts (const target_symbol& e) { // Work with a new target_symbol so we can modify arguments ts = new target_symbol (e); if (ts->addressof) throw semantic_error(_("cannot take address of pretty-printed variable"), ts->tok); if (ts->components.empty() || ts->components.back().type != target_symbol::comp_pretty_print) throw semantic_error(_("invalid target_symbol for pretty-print"), ts->tok); print_full = ts->components.back().member.length() > 1; ts->components.pop_back(); } functioncall* dwarf_pretty_print::expand () { static unsigned tick = 0; // function pretty_print_X([pointer], [arg1, arg2, ...]) { // try { // return sprintf("{.foo=...}", (ts)->foo, ...) // } catch { // return "ERROR" // } // } // Create the function decl and call. functiondecl *fdecl = new functiondecl; fdecl->tok = ts->tok; fdecl->synthetic = true; fdecl->name = "_dwarf_pretty_print_" + lex_cast(tick++); fdecl->type = pe_string; functioncall* fcall = new functioncall; fcall->tok = ts->tok; fcall->function = fdecl->name; fcall->type = pe_string; // If there's a , replace it with a new var and make that // the first function argument. if (pointer) { vardecl *v = new vardecl; v->type = pe_long; v->name = "pointer"; v->tok = ts->tok; fdecl->formal_args.push_back (v); fcall->args.push_back (pointer); symbol* sym = new symbol; sym->tok = ts->tok; sym->name = v->name; pointer = sym; } // For each expression argument, replace it with a function argument. for (unsigned i = 0; i < ts->components.size(); ++i) if (ts->components[i].type == target_symbol::comp_expression_array_index) { vardecl *v = new vardecl; v->type = pe_long; v->name = "index" + lex_cast(i); v->tok = ts->tok; fdecl->formal_args.push_back (v); fcall->args.push_back (ts->components[i].expr_index); symbol* sym = new symbol; sym->tok = ts->tok; sym->name = v->name; ts->components[i].expr_index = sym; } // Create the return sprintf. token* pf_tok = new token(*ts->tok); pf_tok->content = "sprintf"; print_format* pf = print_format::create(pf_tok); return_statement* rs = new return_statement; rs->tok = ts->tok; rs->value = pf; // Recurse into the actual values. recurse (&base_type, ts, pf, true); pf->components = print_format::string_to_components(pf->raw_components); // Create the try-catch net try_block* tb = new try_block; tb->tok = ts->tok; tb->try_block = rs; tb->catch_error_var = 0; return_statement* rs2 = new return_statement; rs2->tok = ts->tok; rs2->value = new literal_string ("ERROR"); rs2->value->tok = ts->tok; tb->catch_block = rs2; fdecl->body = tb; fdecl->join (dw.sess); return fcall; } void dwarf_pretty_print::recurse (Dwarf_Die* start_type, target_symbol* e, print_format* pf, bool top) { Dwarf_Die type; dw.resolve_unqualified_inner_typedie (start_type, &type, e); switch (dwarf_tag(&type)) { default: // XXX need a warning? // throw semantic_error ("unsupported type (tag " + lex_cast(dwarf_tag(&type)) // + ") for " + dwarf_type_name(&type), e->tok); pf->raw_components.append("?"); break; case DW_TAG_enumeration_type: case DW_TAG_base_type: recurse_base (&type, e, pf); break; case DW_TAG_array_type: recurse_array (&type, e, pf, top); break; case DW_TAG_pointer_type: case DW_TAG_reference_type: case DW_TAG_rvalue_reference_type: recurse_pointer (&type, e, pf, top); break; case DW_TAG_subroutine_type: push_deref (pf, ":%p", e); break; case DW_TAG_union_type: case DW_TAG_structure_type: case DW_TAG_class_type: recurse_struct (&type, e, pf, top); break; } } // Bit fields are handled as a special-case combination of recurse() and // recurse_base(), only called from recurse_struct_members(). The main // difference is that the value is always printed numerically, even if the // underlying type is a char. void dwarf_pretty_print::recurse_bitfield (Dwarf_Die* start_type, target_symbol* e, print_format* pf) { Dwarf_Die type; dw.resolve_unqualified_inner_typedie (start_type, &type, e); int tag = dwarf_tag(&type); if (tag != DW_TAG_base_type && tag != DW_TAG_enumeration_type) { // XXX need a warning? // throw semantic_error ("unsupported bitfield type (tag " + lex_cast(tag) // + ") for " + dwarf_type_name(&type), e->tok); pf->raw_components.append("?"); return; } Dwarf_Attribute attr; Dwarf_Word encoding = (Dwarf_Word) -1; dwarf_formudata (dwarf_attr_integrate (&type, DW_AT_encoding, &attr), &encoding); switch (encoding) { case DW_ATE_float: case DW_ATE_complex_float: // XXX need a warning? // throw semantic_error ("unsupported bitfield type (encoding " + lex_cast(encoding) // + ") for " + dwarf_type_name(&type), e->tok); pf->raw_components.append("?"); break; case DW_ATE_unsigned: case DW_ATE_unsigned_char: push_deref (pf, "%u", e); break; case DW_ATE_signed: case DW_ATE_signed_char: default: push_deref (pf, "%i", e); break; } } void dwarf_pretty_print::recurse_base (Dwarf_Die* type, target_symbol* e, print_format* pf) { Dwarf_Attribute attr; Dwarf_Word encoding = (Dwarf_Word) -1; dwarf_formudata (dwarf_attr_integrate (type, DW_AT_encoding, &attr), &encoding); switch (encoding) { case DW_ATE_float: case DW_ATE_complex_float: // XXX need a warning? // throw semantic_error ("unsupported type (encoding " + lex_cast(encoding) // + ") for " + dwarf_type_name(type), e->tok); pf->raw_components.append("?"); break; case DW_ATE_UTF: // XXX need to add unicode to _stp_vsprint_char case DW_ATE_signed_char: case DW_ATE_unsigned_char: // Use escapes to make sure that non-printable characters // don't interrupt our stream (especially '\0' values). push_deref (pf, "'%#c'", e); break; case DW_ATE_unsigned: push_deref (pf, "%u", e); break; case DW_ATE_signed: default: push_deref (pf, "%i", e); break; } } void dwarf_pretty_print::recurse_array (Dwarf_Die* type, target_symbol* e, print_format* pf, bool top) { if (!top && !print_full) { pf->raw_components.append("[...]"); return; } Dwarf_Die childtype; dwarf_attr_die (type, DW_AT_type, &childtype); if (print_chars (&childtype, e, pf)) return; pf->raw_components.append("["); // We print the array up to the first 5 elements. // XXX how can we determine the array size? // ... for now, just print the first element // NB: limit to 32 args; see PR10750 and c_unparser::visit_print_format. unsigned i, size = 1; for (i=0; i < size && i < 5 && pf->args.size() < 32; ++i) { if (i > 0) pf->raw_components.append(", "); target_symbol* e2 = new target_symbol(*e); e2->components.push_back (target_symbol::component(e->tok, i)); recurse (&childtype, e2, pf); } if (i < size || 1/*XXX until real size is known */) pf->raw_components.append(", ..."); pf->raw_components.append("]"); } void dwarf_pretty_print::recurse_pointer (Dwarf_Die* type, target_symbol* e, print_format* pf, bool top) { // We chase to top-level pointers, but leave the rest alone bool void_p = true; Dwarf_Die pointee; if (dwarf_attr_die (type, DW_AT_type, &pointee)) { try { dw.resolve_unqualified_inner_typedie (&pointee, &pointee, e); void_p = false; } catch (const semantic_error&) {} } if (!void_p) { if (print_chars (&pointee, e, pf)) return; if (top) { recurse (&pointee, e, pf, top); return; } } push_deref (pf, "%p", e); } void dwarf_pretty_print::recurse_struct (Dwarf_Die* type, target_symbol* e, print_format* pf, bool top) { if (dwarf_hasattr(type, DW_AT_declaration)) { Dwarf_Die *resolved = dw.declaration_resolve(type); if (!resolved) { // could be an error, but for now just stub it // throw semantic_error ("unresolved " + dwarf_type_name(type), e->tok); pf->raw_components.append("{...}"); return; } type = resolved; } int count = 0; pf->raw_components.append("{"); if (top || print_full) recurse_struct_members (type, e, pf, count); else pf->raw_components.append("..."); pf->raw_components.append("}"); } void dwarf_pretty_print::recurse_struct_members (Dwarf_Die* type, target_symbol* e, print_format* pf, int& count) { /* With inheritance, a subclass may mask member names of parent classes, so * our search among the inheritance tree must be breadth-first rather than * depth-first (recursive). The type die is still our starting point. When * we encounter a masked name, just skip it. */ set dupes; deque inheritees(1, *type); for (; !inheritees.empty(); inheritees.pop_front()) { Dwarf_Die child, childtype, import; if (dwarf_child (&inheritees.front(), &child) == 0) do { target_symbol* e2 = e; // skip static members if (dwarf_hasattr(&child, DW_AT_declaration)) continue; int tag = dwarf_tag (&child); /* Pretend imported units contain members by recursing into struct_member printing with the same count. */ if (tag == DW_TAG_imported_unit && dwarf_attr_die (&child, DW_AT_import, &import)) recurse_struct_members (&import, e2, pf, count); if (tag != DW_TAG_member && tag != DW_TAG_inheritance) continue; dwarf_attr_die (&child, DW_AT_type, &childtype); if (tag == DW_TAG_inheritance) { inheritees.push_back(childtype); continue; } int childtag = dwarf_tag (&childtype); const char *member = dwarf_diename (&child); // "_vptr.foo" members are C++ virtual function tables, // which (generally?) aren't interesting for users. if (member && startswith(member, "_vptr.")) continue; // skip inheritance-masked duplicates if (member && !dupes.insert(member).second) continue; if (++count > 1) pf->raw_components.append(", "); // NB: limit to 32 args; see PR10750 and c_unparser::visit_print_format. if (pf->args.size() >= 32) { pf->raw_components.append("..."); break; } if (member) { pf->raw_components.append("."); pf->raw_components.append(member); e2 = new target_symbol(*e); e2->components.push_back (target_symbol::component(e->tok, member)); } else if (childtag == DW_TAG_union_type) pf->raw_components.append(""); else if (childtag == DW_TAG_structure_type) pf->raw_components.append(""); else if (childtag == DW_TAG_class_type) pf->raw_components.append(""); pf->raw_components.append("="); if (dwarf_hasattr_integrate (&child, DW_AT_bit_offset)) recurse_bitfield (&childtype, e2, pf); else recurse (&childtype, e2, pf); } while (dwarf_siblingof (&child, &child) == 0); } } bool dwarf_pretty_print::print_chars (Dwarf_Die* start_type, target_symbol* e, print_format* pf) { Dwarf_Die type; dw.resolve_unqualified_inner_typedie (start_type, &type, e); Dwarf_Attribute attr; Dwarf_Word encoding = (Dwarf_Word) -1; dwarf_formudata (dwarf_attr_integrate (&type, DW_AT_encoding, &attr), &encoding); switch (encoding) { case DW_ATE_UTF: case DW_ATE_signed_char: case DW_ATE_unsigned_char: break; default: return false; } string function = userspace_p ? "user_string2" : "kernel_string2"; Dwarf_Word size = (Dwarf_Word) -1; dwarf_formudata (dwarf_attr_integrate (&type, DW_AT_byte_size, &attr), &size); switch (size) { case 1: break; case 2: function += "_utf16"; break; case 4: function += "_utf32"; break; default: return false; } if (push_deref (pf, "\"%s\"", e)) { // steal the last arg for a string access assert (!pf->args.empty()); functioncall* fcall = new functioncall; fcall->tok = e->tok; fcall->function = function; fcall->args.push_back (pf->args.back()); expression *err_msg = new literal_string (""); err_msg->tok = e->tok; fcall->args.push_back (err_msg); pf->args.back() = fcall; } return true; } // PR10601: adapt to kernel-vs-userspace loc2c-runtime static const string EMBEDDED_FETCH_DEREF_KERNEL = string("\n") + "#define fetch_register k_fetch_register\n" + "#define store_register k_store_register\n" + "#define deref kderef\n" + "#define store_deref store_kderef\n"; static const string EMBEDDED_FETCH_DEREF_USER = string("\n") + "#define fetch_register u_fetch_register\n" + "#define store_register u_store_register\n" + "#define deref uderef\n" + "#define store_deref store_uderef\n"; #define EMBEDDED_FETCH_DEREF(U) \ (U ? EMBEDDED_FETCH_DEREF_USER : EMBEDDED_FETCH_DEREF_KERNEL) static const string EMBEDDED_FETCH_DEREF_DONE = string("\n") + "#undef fetch_register\n" + "#undef store_register\n" + "#undef deref\n" + "#undef store_deref\n"; static functioncall* synthetic_embedded_deref_call(systemtap_session& session, const string& function_name, const string& function_code, exp_type function_type, bool userspace_p, bool lvalue_p, target_symbol* e, expression* pointer=NULL) { // Synthesize a functiondecl for the given embedded code string. functiondecl *fdecl = new functiondecl; fdecl->synthetic = true; fdecl->tok = e->tok; fdecl->name = function_name; fdecl->type = function_type; embeddedcode *ec = new embeddedcode; ec->tok = e->tok; ec->code += "/* unprivileged */"; if (! lvalue_p) ec->code += "/* pure */"; ec->code += EMBEDDED_FETCH_DEREF(userspace_p); ec->code += function_code; ec->code += EMBEDDED_FETCH_DEREF_DONE; fdecl->body = ec; // Synthesize a functioncall. functioncall* fcall = new functioncall; fcall->tok = e->tok; fcall->function = fdecl->name; fcall->type = fdecl->type; // If this code snippet uses a precomputed pointer, // pass that as the first argument. if (pointer) { vardecl *v = new vardecl; v->type = pe_long; v->name = "pointer"; v->tok = e->tok; fdecl->formal_args.push_back(v); fcall->args.push_back(pointer); } // Any non-literal indexes need to be passed as arguments too. for (unsigned i = 0; i < e->components.size(); ++i) if (e->components[i].type == target_symbol::comp_expression_array_index) { vardecl *v = new vardecl; v->type = pe_long; v->name = "index" + lex_cast(i); v->tok = e->tok; fdecl->formal_args.push_back(v); fcall->args.push_back(e->components[i].expr_index); } // If this code snippet is assigning to an lvalue, // add a final argument for the rvalue. if (lvalue_p) { // Modify the fdecl so it carries a single pe_long formal // argument called "value". // FIXME: For the time being we only support setting target // variables which have base types; these are 'pe_long' in // stap's type vocabulary. Strings and pointers might be // reasonable, some day, but not today. vardecl *v = new vardecl; v->type = pe_long; v->name = "value"; v->tok = e->tok; fdecl->formal_args.push_back(v); // NB: We don't know the value for fcall argument yet. // (see target_symbol_setter_functioncalls) } // Add the synthesized decl to the session, and return the call. fdecl->join (session); return fcall; } expression* dwarf_pretty_print::deref (target_symbol* e) { static unsigned tick = 0; if (!deref_p) { assert (pointer && e->components.empty()); return pointer; } bool lvalue_p = false; string name = "_dwarf_pretty_print_deref_" + lex_cast(tick++); string code; exp_type type = pe_long; if (pointer) code = dw.literal_stmt_for_pointer (&pointer_type, e, false, type); else if (!local.empty()) code = dw.literal_stmt_for_local (scopes, pc, local, e, false, type); else code = dw.literal_stmt_for_return (&scopes[0], pc, e, false, type); return synthetic_embedded_deref_call(dw.sess, name, code, type, userspace_p, lvalue_p, e, pointer); } bool dwarf_pretty_print::push_deref (print_format* pf, const string& fmt, target_symbol* e) { expression* e2 = NULL; try { e2 = deref (e); } catch (const semantic_error&) { pf->raw_components.append ("?"); return false; } pf->raw_components.append (fmt); pf->args.push_back (e2); return true; } void dwarf_var_expanding_visitor::visit_target_symbol_saved_return (target_symbol* e) { // Get the full name of the target symbol. stringstream ts_name_stream; e->print(ts_name_stream); string ts_name = ts_name_stream.str(); // Check and make sure we haven't already seen this target // variable in this return probe. If we have, just return our // last replacement. map::iterator i = return_ts_map.find(ts_name); if (i != return_ts_map.end()) { provide (i->second); return; } // Attempt the expansion directly first, so if there's a problem with the // variable we won't have a bogus entry probe lying around. Like in // saveargs(), we pretend for a moment that we're not in a .return. bool saved_has_return = q.has_return; q.has_return = false; expression *repl = e; replace (repl); q.has_return = saved_has_return; target_symbol* n = dynamic_cast(repl); if (n && n->saved_conversion_error) { provide (repl); return; } expression *exp; if (!q.has_process && strverscmp(q.sess.kernel_base_release.c_str(), "2.6.25") >= 0) exp = gen_kretprobe_saved_return(repl); else exp = gen_mapped_saved_return(repl, e->sym_name()); // Provide the variable to our parent so it can be used as a // substitute for the target symbol. provide (exp); // Remember this replacement since we might be able to reuse // it later if the same return probe references this target // symbol again. return_ts_map[ts_name] = exp; } static expression* gen_mapped_saved_return(systemtap_session &sess, expression* e, const string& name, block *& add_block, bool& add_block_tid, block *& add_call_probe, bool& add_call_probe_tid) { static unsigned tick = 0; // We've got to do several things here to handle target // variables in return probes. // (1) Synthesize two global arrays. One is the cache of the // target variable and the other contains a thread specific // nesting level counter. The arrays will look like // this: // // _entry_tvar_{name}_{num} // _entry_tvar_{name}_{num}_ctr string aname = (string("_entry_tvar_") + name + "_" + lex_cast(tick++)); vardecl* vd = new vardecl; vd->name = aname; vd->tok = e->tok; sess.globals.push_back (vd); string ctrname = aname + "_ctr"; vd = new vardecl; vd->name = ctrname; vd->tok = e->tok; sess.globals.push_back (vd); // (2) Create a new code block we're going to insert at the // beginning of this probe to get the cached value into a // temporary variable. We'll replace the target variable // reference with the temporary variable reference. The code // will look like this: // // _entry_tvar_tid = tid() // _entry_tvar_{name}_{num}_tmp // = _entry_tvar_{name}_{num}[_entry_tvar_tid, // _entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]] // delete _entry_tvar_{name}_{num}[_entry_tvar_tid, // _entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]--] // if (! _entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]) // delete _entry_tvar_{name}_{num}_ctr[_entry_tvar_tid] // (2a) Synthesize the tid temporary expression, which will look // like this: // // _entry_tvar_tid = tid() symbol* tidsym = new symbol; tidsym->name = string("_entry_tvar_tid"); tidsym->tok = e->tok; if (add_block == NULL) { add_block = new block; add_block->tok = e->tok; } if (!add_block_tid) { // Synthesize a functioncall to grab the thread id. functioncall* fc = new functioncall; fc->tok = e->tok; fc->function = string("tid"); // Assign the tid to '_entry_tvar_tid'. assignment* a = new assignment; a->tok = e->tok; a->op = "="; a->left = tidsym; a->right = fc; expr_statement* es = new expr_statement; es->tok = e->tok; es->value = a; add_block->statements.push_back (es); add_block_tid = true; } // (2b) Synthesize an array reference and assign it to a // temporary variable (that we'll use as replacement for the // target variable reference). It will look like this: // // _entry_tvar_{name}_{num}_tmp // = _entry_tvar_{name}_{num}[_entry_tvar_tid, // _entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]] arrayindex* ai_tvar_base = new arrayindex; ai_tvar_base->tok = e->tok; symbol* sym = new symbol; sym->name = aname; sym->tok = e->tok; ai_tvar_base->base = sym; ai_tvar_base->indexes.push_back(tidsym); // We need to create a copy of the array index in its current // state so we can have 2 variants of it (the original and one // that post-decrements the second index). arrayindex* ai_tvar = new arrayindex; arrayindex* ai_tvar_postdec = new arrayindex; *ai_tvar = *ai_tvar_base; *ai_tvar_postdec = *ai_tvar_base; // Synthesize the // "_entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]" used as the // second index into the array. arrayindex* ai_ctr = new arrayindex; ai_ctr->tok = e->tok; sym = new symbol; sym->name = ctrname; sym->tok = e->tok; ai_ctr->base = sym; ai_ctr->indexes.push_back(tidsym); ai_tvar->indexes.push_back(ai_ctr); symbol* tmpsym = new symbol; tmpsym->name = aname + "_tmp"; tmpsym->tok = e->tok; assignment* a = new assignment; a->tok = e->tok; a->op = "="; a->left = tmpsym; a->right = ai_tvar; expr_statement* es = new expr_statement; es->tok = e->tok; es->value = a; add_block->statements.push_back (es); // (2c) Add a post-decrement to the second array index and // delete the array value. It will look like this: // // delete _entry_tvar_{name}_{num}[_entry_tvar_tid, // _entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]--] post_crement* pc = new post_crement; pc->tok = e->tok; pc->op = "--"; pc->operand = ai_ctr; ai_tvar_postdec->indexes.push_back(pc); delete_statement* ds = new delete_statement; ds->tok = e->tok; ds->value = ai_tvar_postdec; add_block->statements.push_back (ds); // (2d) Delete the counter value if it is 0. It will look like // this: // if (! _entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]) // delete _entry_tvar_{name}_{num}_ctr[_entry_tvar_tid] ds = new delete_statement; ds->tok = e->tok; ds->value = ai_ctr; unary_expression *ue = new unary_expression; ue->tok = e->tok; ue->op = "!"; ue->operand = ai_ctr; if_statement *ifs = new if_statement; ifs->tok = e->tok; ifs->condition = ue; ifs->thenblock = ds; ifs->elseblock = NULL; add_block->statements.push_back (ifs); // (3) We need an entry probe that saves the value for us in the // global array we created. Create the entry probe, which will // look like this: // // probe kernel.function("{function}").call { // _entry_tvar_tid = tid() // _entry_tvar_{name}_{num}[_entry_tvar_tid, // ++_entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]] // = ${param} // } if (add_call_probe == NULL) { add_call_probe = new block; add_call_probe->tok = e->tok; } if (!add_call_probe_tid) { // Synthesize a functioncall to grab the thread id. functioncall* fc = new functioncall; fc->tok = e->tok; fc->function = string("tid"); // Assign the tid to '_entry_tvar_tid'. assignment* a = new assignment; a->tok = e->tok; a->op = "="; a->left = tidsym; a->right = fc; expr_statement* es = new expr_statement; es->tok = e->tok; es->value = a; add_call_probe = new block(add_call_probe, es); add_call_probe_tid = true; } // Save the value, like this: // _entry_tvar_{name}_{num}[_entry_tvar_tid, // ++_entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]] // = ${param} arrayindex* ai_tvar_preinc = new arrayindex; *ai_tvar_preinc = *ai_tvar_base; pre_crement* preinc = new pre_crement; preinc->tok = e->tok; preinc->op = "++"; preinc->operand = ai_ctr; ai_tvar_preinc->indexes.push_back(preinc); a = new assignment; a->tok = e->tok; a->op = "="; a->left = ai_tvar_preinc; a->right = e; es = new expr_statement; es->tok = e->tok; es->value = a; add_call_probe = new block(add_call_probe, es); // (4) Provide the '_entry_tvar_{name}_{num}_tmp' variable to // our parent so it can be used as a substitute for the target // symbol. delete ai_tvar_base; return tmpsym; } expression* dwarf_var_expanding_visitor::gen_mapped_saved_return(expression* e, const string& name) { return ::gen_mapped_saved_return(q.sess, e, name, add_block, add_block_tid, add_call_probe, add_call_probe_tid); } expression* dwarf_var_expanding_visitor::gen_kretprobe_saved_return(expression* e) { // The code for this is simple. // // .call: // _set_kretprobe_long(index, $value) // // .return: // _get_kretprobe_long(index) // // (or s/long/string/ for things like $$parms) unsigned index; string setfn, getfn; // We need the caller to predetermine the type of the expression! switch (e->type) { case pe_string: index = saved_strings++; setfn = "_set_kretprobe_string"; getfn = "_get_kretprobe_string"; break; case pe_long: index = saved_longs++; setfn = "_set_kretprobe_long"; getfn = "_get_kretprobe_long"; break; default: throw semantic_error(_("unknown type to save in kretprobe"), e->tok); } // Create the entry code // _set_kretprobe_{long|string}(index, $value) if (add_call_probe == NULL) { add_call_probe = new block; add_call_probe->tok = e->tok; } functioncall* set_fc = new functioncall; set_fc->tok = e->tok; set_fc->function = setfn; set_fc->args.push_back(new literal_number(index)); set_fc->args.back()->tok = e->tok; set_fc->args.push_back(e); expr_statement* set_es = new expr_statement; set_es->tok = e->tok; set_es->value = set_fc; add_call_probe->statements.push_back(set_es); // Create the return code // _get_kretprobe_{long|string}(index) functioncall* get_fc = new functioncall; get_fc->tok = e->tok; get_fc->function = getfn; get_fc->args.push_back(new literal_number(index)); get_fc->args.back()->tok = e->tok; return get_fc; } void dwarf_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) { if (null_die(scope_die)) return; target_symbol *tsym = new target_symbol(*e); bool pretty = (!e->components.empty() && e->components[0].type == target_symbol::comp_pretty_print); string format = pretty ? "=%s" : "=%#x"; // Convert $$parms to sprintf of a list of parms and active local vars // which we recursively evaluate // NB: we synthesize a new token here rather than reusing // e->tok, because print_format::print likes to use // its tok->content. token* pf_tok = new token(*e->tok); pf_tok->type = tok_identifier; pf_tok->content = "sprintf"; print_format* pf = print_format::create(pf_tok); if (q.has_return && (e->name == "$$return")) { tsym->name = "$return"; // Ignore any variable that isn't accessible. tsym->saved_conversion_error = 0; expression *texp = tsym; replace (texp); // NB: throws nothing ... if (tsym->saved_conversion_error) // ... but this is how we know it happened. { } else { pf->raw_components += "return"; pf->raw_components += format; pf->args.push_back(texp); } } else { // non-.return probe: support $$parms, $$vars, $$locals bool first = true; Dwarf_Die result; vector scopes = q.dw.getscopes(scope_die); for (unsigned i = 0; i < scopes.size(); ++i) { if (dwarf_tag(&scopes[i]) == DW_TAG_compile_unit) break; // we don't want file-level variables if (dwarf_child (&scopes[i], &result) == 0) do { switch (dwarf_tag (&result)) { case DW_TAG_variable: if (e->name == "$$parms") continue; break; case DW_TAG_formal_parameter: if (e->name == "$$locals") continue; break; default: continue; } const char *diename = dwarf_diename (&result); if (! diename) continue; if (! first) pf->raw_components += " "; pf->raw_components += diename; first = false; // Write a placeholder for ugly aggregates Dwarf_Die type; if (!pretty && dwarf_attr_die(&result, DW_AT_type, &type)) { q.dw.resolve_unqualified_inner_typedie(&type, &type, e); switch (dwarf_tag(&type)) { case DW_TAG_union_type: case DW_TAG_structure_type: case DW_TAG_class_type: pf->raw_components += "={...}"; continue; case DW_TAG_array_type: pf->raw_components += "=[...]"; continue; } } tsym->name = "$"; tsym->name += diename; // Ignore any variable that isn't accessible. tsym->saved_conversion_error = 0; expression *texp = tsym; replace (texp); // NB: throws nothing ... if (tsym->saved_conversion_error) // ... but this is how we know it happened. { if (q.sess.verbose>2) { for (const semantic_error *c = tsym->saved_conversion_error; c != 0; c = c->chain) { clog << _("variable location problem [man error::dwarf]: ") << c->what() << endl; } } pf->raw_components += "=?"; } else { pf->raw_components += format; pf->args.push_back(texp); } } while (dwarf_siblingof (&result, &result) == 0); } } pf->components = print_format::string_to_components(pf->raw_components); pf->type = pe_string; provide (pf); } void dwarf_var_expanding_visitor::visit_atvar_op (atvar_op *e) { // Fill in our current module context if needed if (e->module.empty()) e->module = q.dw.module_name; if (e->module == q.dw.module_name && e->cu_name.empty()) { // process like any other local // e->sym_name() will do the right thing visit_target_symbol(e); return; } var_expanding_visitor::visit_atvar_op(e); } void dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) { assert(e->name.size() > 0 && (e->name[0] == '$' || e->name == "@var")); visited = true; bool defined_being_checked = (defined_ops.size() > 0 && (defined_ops.top()->operand == e)); // In this mode, we avoid hiding errors or generating extra code such as for .return saved $vars try { bool lvalue = is_active_lvalue(e); if (lvalue && !q.sess.guru_mode) throw semantic_error(_("write to target variable not permitted; need stap -g"), e->tok); // XXX: process $context vars should be writable // See if we need to generate a new probe to save/access function // parameters from a return probe. PR 1382. if (q.has_return && !defined_being_checked && e->name != "$return" // not the special return-value variable handled below && e->name != "$$return") // nor the other special variable handled below { if (lvalue) throw semantic_error(_("write to target variable not permitted in .return probes"), e->tok); visit_target_symbol_saved_return(e); return; } if (e->name == "$$vars" || e->name == "$$parms" || e->name == "$$locals" || (q.has_return && (e->name == "$$return"))) { if (lvalue) throw semantic_error(_("cannot write to context variable"), e->tok); if (e->addressof) throw semantic_error(_("cannot take address of context variable"), e->tok); e->assert_no_components("dwarf", true); visit_target_symbol_context(e); return; } if (!e->components.empty() && e->components.back().type == target_symbol::comp_pretty_print) { if (lvalue) throw semantic_error(_("cannot write to pretty-printed variable"), e->tok); if (q.has_return && (e->name == "$return")) { dwarf_pretty_print dpp (q.dw, scope_die, addr, q.has_process, *e); dpp.expand()->visit(this); } else { dwarf_pretty_print dpp (q.dw, getscopes(e), addr, e->sym_name(), q.has_process, *e); dpp.expand()->visit(this); } return; } bool userspace_p = q.has_process; string fname = (string(lvalue ? "_dwarf_tvar_set" : "_dwarf_tvar_get") + "_" + e->sym_name() + "_" + lex_cast(tick++)); exp_type type = pe_long; string code; if (q.has_return && (e->name == "$return")) code = q.dw.literal_stmt_for_return (scope_die, addr, e, lvalue, type); else code = q.dw.literal_stmt_for_local (getscopes(e), addr, e->sym_name(), e, lvalue, type); functioncall* n = synthetic_embedded_deref_call(q.sess, fname, code, type, userspace_p, lvalue, e); if (lvalue) { // Provide the functioncall to our parent, so that it can be // used to substitute for the assignment node immediately above // us. assert(!target_symbol_setter_functioncalls.empty()); *(target_symbol_setter_functioncalls.top()) = n; } // Revisit the functioncall so arguments can be expanded. n->visit (this); } catch (const semantic_error& er) { // We suppress this error message, and pass the unresolved // target_symbol to the next pass. We hope that this value ends // up not being referenced after all, so it can be optimized out // quietly. e->chain (er); provide (e); } } void dwarf_var_expanding_visitor::visit_cast_op (cast_op *e) { // Fill in our current module context if needed if (e->module.empty()) e->module = q.dw.module_name; var_expanding_visitor::visit_cast_op(e); } void dwarf_var_expanding_visitor::visit_entry_op (entry_op *e) { expression *repl = e; if (q.has_return) { // expand the operand as if it weren't a return probe q.has_return = false; replace (e->operand); q.has_return = true; // XXX it would be nice to use gen_kretprobe_saved_return when available, // but it requires knowing the types already, which is problematic for // arbitrary expressons. repl = gen_mapped_saved_return (e->operand, "entry"); } provide (repl); } void dwarf_var_expanding_visitor::visit_perf_op (perf_op *e) { token* t = new token; string e_lit_val = e->operand->value; t->location = e->tok->location; t->type = tok_identifier; t->content = e_lit_val; add_block = new block; systemtap_session &s = this->q.sess; map >::iterator it; // Find the associated perf.counter probe for (it=s.perf_counters.begin(); it != s.perf_counters.end(); it++) if ((*it).first == e_lit_val) { // if perf .function("name") omitted, then set it to this process name if ((*it).second.first.length() == 0) ((*it).second).first = this->q.user_path; if (((*it).second).first == this->q.user_path) break; } if (it != s.perf_counters.end()) { perf_counter_refs.insert((*it).second.second); // __perf_read_N is assigned in the probe prologue symbol* sym = new symbol; sym->tok = t; sym->name = "__perf_read_" + (*it).first; provide (sym); } else throw semantic_error(_F("perf counter '%s' not defined", e_lit_val.c_str())); } vector& dwarf_var_expanding_visitor::getscopes(target_symbol *e) { if (scopes.empty()) { if(scope_die != NULL) scopes = q.dw.getscopes(scope_die); if (scopes.empty()) //throw semantic_error (_F("unable to find any scopes containing %d", addr), e->tok); // ((scope_die == NULL) ? "" : (string (" in ") + (dwarf_diename(scope_die) ?: "") + "(" + (dwarf_diename(q.dw.cu) ?: "") ")" )) throw semantic_error ("unable to find any scopes containing " + lex_cast_hex(addr) + ((scope_die == NULL) ? "" : (string (" in ") + (dwarf_diename(scope_die) ?: "") + "(" + (dwarf_diename(q.dw.cu) ?: "") + ")")) + " while searching for local '" + e->sym_name() + "'", e->tok); } return scopes; } struct dwarf_cast_expanding_visitor: public var_expanding_visitor { systemtap_session& s; dwarf_builder& db; dwarf_cast_expanding_visitor(systemtap_session& s, dwarf_builder& db): s(s), db(db) {} void visit_cast_op (cast_op* e); void filter_special_modules(string& module); }; struct dwarf_cast_query : public base_query { cast_op& e; const bool lvalue; const bool userspace_p; functioncall*& result; dwarf_cast_query(dwflpp& dw, const string& module, cast_op& e, bool lvalue, const bool userspace_p, functioncall*& result): base_query(dw, module), e(e), lvalue(lvalue), userspace_p(userspace_p), result(result) {} void handle_query_module(); void query_library (const char *) {} void query_plt (const char *entry, size_t addr) {} }; void dwarf_cast_query::handle_query_module() { static unsigned tick = 0; if (result) return; // look for the type in any CU Dwarf_Die* type_die = NULL; if (startswith(e.type_name, "class ")) { // normalize to match dwflpp::global_alias_caching_callback string struct_name = "struct " + e.type_name.substr(6); type_die = dw.declaration_resolve_other_cus(struct_name); } else type_die = dw.declaration_resolve_other_cus(e.type_name); // NB: We now index the types as "struct name"/"union name"/etc. instead of // just "name". But since we didn't require users to be explicit before, and // actually sort of discouraged it, we must be flexible now. So if a lookup // fails with a bare name, try augmenting it. if (!type_die && !startswith(e.type_name, "class ") && !startswith(e.type_name, "struct ") && !startswith(e.type_name, "union ") && !startswith(e.type_name, "enum ")) { type_die = dw.declaration_resolve_other_cus("struct " + e.type_name); if (!type_die) type_die = dw.declaration_resolve_other_cus("union " + e.type_name); if (!type_die) type_die = dw.declaration_resolve_other_cus("enum " + e.type_name); } if (!type_die) return; string code; exp_type type = pe_long; try { Dwarf_Die cu_mem; dw.focus_on_cu(dwarf_diecu(type_die, &cu_mem, NULL, NULL)); if (!e.components.empty() && e.components.back().type == target_symbol::comp_pretty_print) { if (lvalue) throw semantic_error(_("cannot write to pretty-printed variable"), e.tok); dwarf_pretty_print dpp(dw, type_die, e.operand, true, userspace_p, e); result = dpp.expand(); return; } code = dw.literal_stmt_for_pointer (type_die, &e, lvalue, type); } catch (const semantic_error& er) { // NB: we can have multiple errors, since a @cast // may be attempted using several different modules: // @cast(ptr, "type", "module1:module2:...") e.chain (er); } if (code.empty()) return; string fname = (string(lvalue ? "_dwarf_cast_set" : "_dwarf_cast_get") + "_" + e.sym_name() + "_" + lex_cast(tick++)); result = synthetic_embedded_deref_call(dw.sess, fname, code, type, userspace_p, lvalue, &e, e.operand); } void dwarf_cast_expanding_visitor::filter_special_modules(string& module) { // look for "" or "kernel" // for those cases, build a module including that header if (module[module.size() - 1] == '>' && (module[0] == '<' || startswith(module, "kernel<"))) { string cached_module; if (s.use_cache) { // see if the cached module exists cached_module = find_typequery_hash(s, module); if (!cached_module.empty() && !s.poison_cache) { int fd = open(cached_module.c_str(), O_RDONLY); if (fd != -1) { if (s.verbose > 2) //TRANSLATORS: Here we're using a cached module. clog << _("Pass 2: using cached ") << cached_module << endl; module = cached_module; close(fd); return; } } } // no cached module, time to make it if (make_typequery(s, module) == 0) { // try to save typequery in the cache if (s.use_cache) copy_file(module, cached_module, s.verbose > 2); } } } void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e) { bool lvalue = is_active_lvalue(e); if (lvalue && !s.guru_mode) throw semantic_error(_("write to @cast context variable not permitted; need stap -g"), e->tok); if (e->module.empty()) e->module = "kernel"; // "*" may also be reasonable to search all kernel modules functioncall* result = NULL; // split the module string by ':' for alternatives vector modules; tokenize(e->module, modules, ":"); bool userspace_p=false; // PR10601 for (unsigned i = 0; !result && i < modules.size(); ++i) { string& module = modules[i]; filter_special_modules(module); // NB: This uses '/' to distinguish between kernel modules and userspace, // which means that userspace modules won't get any PATH searching. dwflpp* dw; try { userspace_p=is_user_module (module); if (! userspace_p) { // kernel or kernel module target dw = db.get_kern_dw(s, module); } else { module = find_executable (module, "", s.sysenv); // canonicalize it dw = db.get_user_dw(s, module); } } catch (const semantic_error& er) { /* ignore and go to the next module */ continue; } dwarf_cast_query q (*dw, module, *e, lvalue, userspace_p, result); dw->iterate_over_modules(&query_module, &q); } if (!result) { // We pass the unresolved cast_op to the next pass, and hope // that this value ends up not being referenced after all, so // it can be optimized out quietly. provide (e); return; } if (lvalue) { // Provide the functioncall to our parent, so that it can be // used to substitute for the assignment node immediately above // us. assert(!target_symbol_setter_functioncalls.empty()); *(target_symbol_setter_functioncalls.top()) = result; } result->visit (this); } struct dwarf_atvar_expanding_visitor: public var_expanding_visitor { systemtap_session& s; dwarf_builder& db; dwarf_atvar_expanding_visitor(systemtap_session& s, dwarf_builder& db): s(s), db(db) {} void visit_atvar_op (atvar_op* e); }; struct dwarf_atvar_query: public base_query { atvar_op& e; const bool userspace_p, lvalue; functioncall*& result; unsigned& tick; const string cu_name_pattern; dwarf_atvar_query(dwflpp& dw, const string& module, atvar_op& e, const bool userspace_p, const bool lvalue, functioncall*& result, unsigned& tick): base_query(dw, module), e(e), userspace_p(userspace_p), lvalue(lvalue), result(result), tick(tick), cu_name_pattern(string("*/") + e.cu_name) {} void handle_query_module (); void query_library (const char *) {} void query_plt (const char *entry, size_t addr) {} static int atvar_query_cu (Dwarf_Die *cudie, void *data); }; int dwarf_atvar_query::atvar_query_cu (Dwarf_Die * cudie, void * data) { dwarf_atvar_query * q = static_cast(data); if (! q->e.cu_name.empty()) { const char *die_name = dwarf_diename(cudie); if (strcmp(die_name, q->e.cu_name.c_str()) != 0 // Perfect match && fnmatch(q->cu_name_pattern.c_str(), die_name, 0) != 0) { return DWARF_CB_OK; } } try { vector scopes(1, *cudie); q->dw.focus_on_cu (cudie); if (! q->e.components.empty() && q->e.components.back().type == target_symbol::comp_pretty_print) { dwarf_pretty_print dpp (q->dw, scopes, 0, q->e.sym_name(), q->userspace_p, q->e); q->result = dpp.expand(); return DWARF_CB_ABORT; } exp_type type = pe_long; string code = q->dw.literal_stmt_for_local (scopes, 0, q->e.sym_name(), &q->e, q->lvalue, type); if (code.empty()) return DWARF_CB_OK; string fname = (string(q->lvalue ? "_dwarf_tvar_set" : "_dwarf_tvar_get") + "_" + q->e.sym_name() + "_" + lex_cast(q->tick++)); q->result = synthetic_embedded_deref_call (q->sess, fname, code, type, q->userspace_p, q->lvalue, &q->e); } catch (const semantic_error& er) { // Here we suppress the error because we often just have too many // when scanning all the CUs. return DWARF_CB_OK; } if (q->result) { return DWARF_CB_ABORT; } return DWARF_CB_OK; } void dwarf_atvar_query::handle_query_module () { dw.iterate_over_cus(atvar_query_cu, this, false); } void dwarf_atvar_expanding_visitor::visit_atvar_op (atvar_op* e) { const bool lvalue = is_active_lvalue(e); if (lvalue && !s.guru_mode) throw semantic_error(_("write to @var variable not permitted; " "need stap -g"), e->tok); if (e->module.empty()) e->module = "kernel"; functioncall* result = NULL; // split the module string by ':' for alternatives vector modules; tokenize(e->module, modules, ":"); bool userspace_p = false; for (unsigned i = 0; !result && i < modules.size(); ++i) { string& module = modules[i]; dwflpp* dw; try { userspace_p = is_user_module(module); if (!userspace_p) { // kernel or kernel module target dw = db.get_kern_dw(s, module); } else { module = find_executable(module, "", s.sysenv); dw = db.get_user_dw(s, module); } } catch (const semantic_error& er) { /* ignore and go to the next module */ continue; } dwarf_atvar_query q (*dw, module, *e, userspace_p, lvalue, result, tick); dw->iterate_over_modules(&query_module, &q); if (result) { s.unwindsym_modules.insert(module); if (lvalue) { // Provide the functioncall to our parent, so that it can be // used to substitute for the assignment node immediately above // us. assert(!target_symbol_setter_functioncalls.empty()); *(target_symbol_setter_functioncalls.top()) = result; } result->visit(this); return; } /* Unable to find the variable in the current module, so we chain * an error in atvar_op */ semantic_error er(_F("unable to find global '%s' in %s%s%s", e->sym_name().c_str(), module.c_str(), e->cu_name.empty() ? "" : _(", in "), e->cu_name.c_str())); e->chain (er); } provide(e); } void dwarf_derived_probe::printsig (ostream& o) const { // Instead of just printing the plain locations, we add a PC value // as a comment as a way of telling e.g. apart multiple inlined // function instances. This is distinct from the verbose/clog // output, since this part goes into the cache hash calculations. sole_location()->print (o); o << " /* pc=" << section << "+0x" << hex << addr << dec << " */"; printsig_nested (o); } void dwarf_derived_probe::join_group (systemtap_session& s) { // skip probes which are paired entry-handlers if (!has_return && (saved_longs || saved_strings)) return; if (! s.dwarf_derived_probes) s.dwarf_derived_probes = new dwarf_derived_probe_group (); s.dwarf_derived_probes->enroll (this); } static bool kernel_supports_inode_uprobes(systemtap_session& s) { // The arch-supports is new to the builtin inode-uprobes, so it makes a // reasonable indicator of the new API. Else we'll need an autoconf... // see also buildrun.cxx:kernel_built_uprobs() return (s.kernel_config["CONFIG_ARCH_SUPPORTS_UPROBES"] == "y" && s.kernel_config["CONFIG_UPROBES"] == "y"); } static bool kernel_supports_inode_uretprobes(systemtap_session& s) { // We need inode-uprobes first, then look for a sign of uretprobes. The only // non-static function at present is arch_uretprobe_hijack_return_addr. return kernel_supports_inode_uprobes(s) && (s.kernel_functions.count("arch_uretprobe_hijack_return_addr") > 0); } void check_process_probe_kernel_support(systemtap_session& s) { // If we've got utrace, we're good to go. if (s.kernel_config["CONFIG_UTRACE"] == "y") return; // We don't have utrace. For process probes that aren't // uprobes-based, we just need the task_finder. The task_finder // needs CONFIG_TRACEPOINTS and specific tracepoints. There is a // specific autoconf test for its needs. // // We'll just require CONFIG_TRACEPOINTS here as a quick-and-dirty // approximation. if (! s.need_uprobes && s.kernel_config["CONFIG_TRACEPOINTS"] == "y") return; // For uprobes-based process probes, we need the task_finder plus // the builtin inode-uprobes. if (s.need_uprobes && s.kernel_config["CONFIG_TRACEPOINTS"] == "y" && kernel_supports_inode_uprobes(s)) return; throw semantic_error (_("process probes not available without kernel CONFIG_UTRACE or CONFIG_TRACEPOINTS/CONFIG_ARCH_SUPPORTS_UPROBES/CONFIG_UPROBES")); } dwarf_derived_probe::dwarf_derived_probe(const string& funcname, const string& filename, int line, // module & section specify a relocation // base for , unless section=="" // (equivalently module=="kernel") const string& module, const string& section, // NB: dwfl_addr is the virtualized // address for this symbol. Dwarf_Addr dwfl_addr, // addr is the section-offset for // actual relocation. Dwarf_Addr addr, dwarf_query& q, Dwarf_Die* scope_die /* may be null */) : derived_probe (q.base_probe, q.base_loc, true /* .components soon rewritten */ ), module (module), section (section), addr (addr), path (q.path), has_process (q.has_process), has_return (q.has_return), has_maxactive (q.has_maxactive), has_library (q.has_library), maxactive_val (q.maxactive_val), user_path (q.user_path), user_lib (q.user_lib), access_vars(false), saved_longs(0), saved_strings(0), entry_handler(0) { if (user_lib.size() != 0) has_library = true; if (q.has_process) { // We may receive probes on two types of ELF objects: ET_EXEC or ET_DYN. // ET_EXEC ones need no further relocation on the addr(==dwfl_addr), whereas // ET_DYN ones do (addr += run-time mmap base address). We tell these apart // by the incoming section value (".absolute" vs. ".dynamic"). // XXX Assert invariants here too? // inode-uprobes needs an offset rather than an absolute VM address. // ditto for userspace runtimes (dyninst) if ((kernel_supports_inode_uprobes(q.dw.sess) || q.dw.sess.runtime_usermode_p()) && section == ".absolute" && addr == dwfl_addr && addr >= q.dw.module_start && addr < q.dw.module_end) this->addr = addr - q.dw.module_start; } else { // Assert kernel relocation invariants if (section == "" && dwfl_addr != addr) // addr should be absolute throw semantic_error (_("missing relocation basis"), tok); if (section != "" && dwfl_addr == addr) // addr should be an offset throw semantic_error (_("inconsistent relocation address"), tok); } // XXX: hack for strange g++/gcc's #ifndef USHRT_MAX #define USHRT_MAX 32767 #endif // Range limit maxactive() value if (has_maxactive && (maxactive_val < 0 || maxactive_val > USHRT_MAX)) throw semantic_error (_F("maxactive value out of range [0,%s]", lex_cast(USHRT_MAX).c_str()), q.base_loc->components.front()->tok); // Expand target variables in the probe body if (!null_die(scope_die)) { // XXX: user-space deref's for q.has_process! dwarf_var_expanding_visitor v (q, scope_die, dwfl_addr); v.replace (this->body); // Propagate perf.counters so we can emit later this->perf_counter_refs = v.perf_counter_refs; // Emit local var used to save the perf counter read value std::set::iterator pcii; for (pcii = v.perf_counter_refs.begin(); pcii != v.perf_counter_refs.end(); pcii++) { map >::iterator it; // Find the associated perf counter probe for (it=q.sess.perf_counters.begin() ; it != q.sess.perf_counters.end(); it++) if ((*it).second.second == (*pcii)) break; vardecl* vd = new vardecl; vd->name = "__perf_read_" + (*it).first; vd->tok = this->tok; vd->set_arity(0, this->tok); vd->type = pe_long; vd->synthetic = true; this->locals.push_back (vd); } if (!q.has_process) access_vars = v.visited; // If during target-variable-expanding the probe, we added a new block // of code, add it to the start of the probe. if (v.add_block) this->body = new block(v.add_block, this->body); // If when target-variable-expanding the probe, we need to synthesize a // sibling function-entry probe. We don't go through the whole probe derivation // business (PR10642) that could lead to wildcard/alias resolution, or for that // dwarf-induced duplication. if (v.add_call_probe) { assert (q.has_return && !q.has_call); // We temporarily replace q.base_probe. statement* old_body = q.base_probe->body; q.base_probe->body = v.add_call_probe; q.has_return = false; q.has_call = true; if (q.has_process) entry_handler = new uprobe_derived_probe (funcname, filename, line, module, section, dwfl_addr, addr, q, scope_die); else entry_handler = new dwarf_derived_probe (funcname, filename, line, module, section, dwfl_addr, addr, q, scope_die); saved_longs = entry_handler->saved_longs = v.saved_longs; saved_strings = entry_handler->saved_strings = v.saved_strings; q.results.push_back (entry_handler); q.has_return = true; q.has_call = false; q.base_probe->body = old_body; } // Save the local variables for listing mode if (q.sess.listing_mode_vars) saveargs(q, scope_die, dwfl_addr); } // else - null scope_die - $target variables will produce an error during translate phase // PR10820: null scope die, local variables aren't accessible, not necessary to invoke saveargs // Reset the sole element of the "locations" vector as a // "reverse-engineered" form of the incoming (q.base_loc) probe // point. This allows a user to see what function / file / line // number any particular match of the wildcards. vector comps; if (q.has_kernel) comps.push_back (new probe_point::component(TOK_KERNEL)); else if(q.has_module) comps.push_back (new probe_point::component(TOK_MODULE, new literal_string(module))); else if(q.has_process) comps.push_back (new probe_point::component(TOK_PROCESS, new literal_string(module))); else assert (0); string fn_or_stmt; if (q.has_function_str || q.has_function_num) fn_or_stmt = "function"; else fn_or_stmt = "statement"; if (q.has_function_str || q.has_statement_str) { string retro_name = funcname; if (filename != "") { retro_name += ("@" + string (filename)); if (line > 0) retro_name += (":" + lex_cast (line)); } comps.push_back (new probe_point::component (fn_or_stmt, new literal_string (retro_name))); } else if (q.has_function_num || q.has_statement_num) { Dwarf_Addr retro_addr; if (q.has_function_num) retro_addr = q.function_num_val; else retro_addr = q.statement_num_val; comps.push_back (new probe_point::component (fn_or_stmt, new literal_number(retro_addr, true))); if (q.has_absolute) comps.push_back (new probe_point::component (TOK_ABSOLUTE)); } if (q.has_call) comps.push_back (new probe_point::component(TOK_CALL)); if (q.has_exported) comps.push_back (new probe_point::component(TOK_EXPORTED)); if (q.has_inline) comps.push_back (new probe_point::component(TOK_INLINE)); if (has_return) comps.push_back (new probe_point::component(TOK_RETURN)); if (has_maxactive) comps.push_back (new probe_point::component (TOK_MAXACTIVE, new literal_number(maxactive_val))); // Overwrite it. this->sole_location()->components = comps; } void dwarf_derived_probe::saveargs(dwarf_query& q, Dwarf_Die* scope_die, Dwarf_Addr dwfl_addr) { if (null_die(scope_die)) return; bool verbose = q.sess.verbose > 2; if (verbose) clog << _F("saveargs: examining '%s' (dieoffset: %#" PRIx64 ")\n", (dwarf_diename(scope_die)?: "unknown"), dwarf_dieoffset(scope_die)); if (has_return) { /* Only save the return value if it has a type. */ string type_name; Dwarf_Die type_die; if (dwarf_attr_die (scope_die, DW_AT_type, &type_die) && dwarf_type_name(&type_die, type_name)) args.push_back("$return:"+type_name); else if (verbose) clog << _F("saveargs: failed to retrieve type name for return value (dieoffset: %s)\n", lex_cast_hex(dwarf_dieoffset(scope_die)).c_str()); } Dwarf_Die arg; vector scopes = q.dw.getscopes(scope_die); for (unsigned i = 0; i < scopes.size(); ++i) { if (dwarf_tag(&scopes[i]) == DW_TAG_compile_unit) break; // we don't want file-level variables if (dwarf_child (&scopes[i], &arg) == 0) do { switch (dwarf_tag (&arg)) { case DW_TAG_variable: case DW_TAG_formal_parameter: break; default: continue; } /* Ignore this local if it has no name. */ const char *arg_name = dwarf_diename (&arg); if (!arg_name) { if (verbose) clog << _F("saveargs: failed to retrieve name for local (dieoffset: %s)\n", lex_cast_hex(dwarf_dieoffset(&arg)).c_str()); continue; } if (verbose) clog << _F("saveargs: finding location for local '%s' (dieoffset: %s)\n", arg_name, lex_cast_hex(dwarf_dieoffset(&arg)).c_str()); /* Ignore this local if it has no location (or not at this PC). */ /* NB: It still may not be directly accessible, e.g. if it is an * aggregate type, implicit_pointer, etc., but the user can later * figure out how to access the interesting parts. */ /* XXX: Perhaps saveargs() / listings-mode should work by synthesizing * several synthetic * probe foo { $var } * probes, testing them for overall resolvability. */ Dwarf_Attribute attr_mem; if (!dwarf_attr_integrate (&arg, DW_AT_const_value, &attr_mem)) { Dwarf_Op *expr; size_t len; if (!dwarf_attr_integrate (&arg, DW_AT_location, &attr_mem)) { if (verbose) clog << _F("saveargs: failed to resolve the location for local '%s' (dieoffset: %s)\n", arg_name, lex_cast_hex(dwarf_dieoffset(&arg)).c_str()); continue; } else if (!(dwarf_getlocation_addr(&attr_mem, dwfl_addr, &expr, &len, 1) == 1 && len > 0)) { Dwarf_Addr dwfl_addr2 = q.dw.pr15123_retry_addr (dwfl_addr, & arg); if (!dwfl_addr2 || (!(dwarf_getlocation_addr(&attr_mem, dwfl_addr2, &expr, &len, 1) == 1 && len > 0))) { if (verbose) clog << _F("saveargs: local '%s' (dieoffset: %s) is not available at this address (%s)\n", arg_name, lex_cast_hex(dwarf_dieoffset(&arg)).c_str(), lex_cast_hex(dwfl_addr).c_str()); continue; } } } /* Ignore this local if it has no type. */ string type_name; Dwarf_Die type_die; if (!dwarf_attr_die (&arg, DW_AT_type, &type_die) || !dwarf_type_name(&type_die, type_name)) { if (verbose) clog << _F("saveargs: failed to retrieve type name for local '%s' (dieoffset: %s)\n", arg_name, lex_cast_hex(dwarf_dieoffset(&arg)).c_str()); continue; } /* This local looks good -- save it! */ args.push_back("$"+string(arg_name)+":"+type_name); } while (dwarf_siblingof (&arg, &arg) == 0); } } void dwarf_derived_probe::getargs(std::list &arg_set) const { arg_set.insert(arg_set.end(), args.begin(), args.end()); } void dwarf_derived_probe::emit_privilege_assertion (translator_output* o) { if (has_process) { // These probes are allowed for unprivileged users, but only in the // context of processes which they own. emit_process_owner_assertion (o); return; } // Other probes must contain the default assertion which aborts // if executed by an unprivileged user. derived_probe::emit_privilege_assertion (o); } void dwarf_derived_probe::print_dupe_stamp(ostream& o) { if (has_process) { // These probes are allowed for unprivileged users, but only in the // context of processes which they own. print_dupe_stamp_unprivileged_process_owner (o); return; } // Other probes must contain the default dupe stamp derived_probe::print_dupe_stamp (o); } void dwarf_derived_probe::register_statement_variants(match_node * root, dwarf_builder * dw, privilege_t privilege) { root ->bind_privilege(privilege) ->bind(dw); } void dwarf_derived_probe::register_function_variants(match_node * root, dwarf_builder * dw, privilege_t privilege) { root ->bind_privilege(privilege) ->bind(dw); root->bind(TOK_CALL) ->bind_privilege(privilege) ->bind(dw); root->bind(TOK_EXPORTED) ->bind_privilege(privilege) ->bind(dw); root->bind(TOK_RETURN) ->bind_privilege(privilege) ->bind(dw); // For process probes / uprobes, .maxactive() is unused. if (! pr_contains (privilege, pr_stapusr)) { root->bind(TOK_RETURN) ->bind_num(TOK_MAXACTIVE)->bind(dw); } } void dwarf_derived_probe::register_function_and_statement_variants( systemtap_session& s, match_node * root, dwarf_builder * dw, privilege_t privilege ) { // Here we match 4 forms: // // .function("foo") // .function(0xdeadbeef) // .statement("foo") // .statement(0xdeadbeef) match_node *fv_root = root->bind_str(TOK_FUNCTION); register_function_variants(fv_root, dw, privilege); // ROOT.function("STRING") always gets the .inline and .label variants. fv_root->bind(TOK_INLINE) ->bind_privilege(privilege) ->bind(dw); fv_root->bind_str(TOK_LABEL) ->bind_privilege(privilege) ->bind(dw); fv_root = root->bind_num(TOK_FUNCTION); register_function_variants(fv_root, dw, privilege); // ROOT.function(NUMBER).inline is deprecated in release 1.7 and removed thereafter. if (strverscmp(s.compatible.c_str(), "1.7") <= 0) { fv_root->bind(TOK_INLINE) ->bind_privilege(privilege) ->bind(dw); } register_statement_variants(root->bind_str(TOK_STATEMENT), dw, privilege); register_statement_variants(root->bind_num(TOK_STATEMENT), dw, privilege); } void dwarf_derived_probe::register_sdt_variants(systemtap_session& s, match_node * root, dwarf_builder * dw) { root->bind_str(TOK_MARK) ->bind_privilege(pr_all) ->bind(dw); root->bind_str(TOK_PROVIDER)->bind_str(TOK_MARK) ->bind_privilege(pr_all) ->bind(dw); } void dwarf_derived_probe::register_plt_variants(systemtap_session& s, match_node * root, dwarf_builder * dw) { root->bind(TOK_PLT) ->bind_privilege(pr_all) ->bind(dw); root->bind_str(TOK_PLT) ->bind_privilege(pr_all) ->bind(dw); root->bind(TOK_PLT)->bind_num(TOK_STATEMENT) ->bind_privilege(pr_all) ->bind(dw); root->bind_str(TOK_PLT)->bind_num(TOK_STATEMENT) ->bind_privilege(pr_all) ->bind(dw); } void dwarf_derived_probe::register_patterns(systemtap_session& s) { match_node* root = s.pattern_root; dwarf_builder *dw = new dwarf_builder(); update_visitor *filter = new dwarf_cast_expanding_visitor(s, *dw); s.code_filters.push_back(filter); filter = new dwarf_atvar_expanding_visitor(s, *dw); s.code_filters.push_back(filter); register_function_and_statement_variants(s, root->bind(TOK_KERNEL), dw, pr_privileged); register_function_and_statement_variants(s, root->bind_str(TOK_MODULE), dw, pr_privileged); root->bind(TOK_KERNEL)->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE) ->bind(dw); match_node* uprobes[] = { root->bind(TOK_PROCESS), root->bind_str(TOK_PROCESS), root->bind(TOK_PROCESS)->bind_str(TOK_LIBRARY), root->bind_str(TOK_PROCESS)->bind_str(TOK_LIBRARY), }; for (size_t i = 0; i < sizeof(uprobes) / sizeof(*uprobes); ++i) { register_function_and_statement_variants(s, uprobes[i], dw, pr_all); register_sdt_variants(s, uprobes[i], dw); register_plt_variants(s, uprobes[i], dw); } } void dwarf_derived_probe::emit_probe_local_init(systemtap_session& s, translator_output * o) { std::set::iterator pcii; for (pcii = perf_counter_refs.begin(); pcii != perf_counter_refs.end(); pcii++) { map >::iterator it; // Find the associated perf.counter probe unsigned i = 0; for (it=s.perf_counters.begin() ; it != s.perf_counters.end(); it++, i++) if ((*it).second.second == (*pcii)) break; // place the perf counter read so it precedes stp_lock_probe o->newline() << "l->l___perf_read_" + (*it).first + " = (((int64_t) (_stp_perf_read(smp_processor_id()," + lex_cast(i) + "))));"; } if (access_vars) { // if accessing $variables, emit bsp cache setup for speeding up o->newline() << "#if defined __ia64__"; o->newline() << "bspcache(c->unwaddr, c->kregs);"; o->newline() << "#endif"; } } // ------------------------------------------------------------------------ void dwarf_derived_probe_group::enroll (dwarf_derived_probe* p) { probes_by_module.insert (make_pair (p->module, p)); // XXX: probes put at the same address should all share a // single kprobe/kretprobe, and have their handlers executed // sequentially. } void dwarf_derived_probe_group::emit_module_decls (systemtap_session& s) { if (probes_by_module.empty()) return; s.op->newline() << "/* ---- dwarf probes ---- */"; // Warn of misconfigured kernels s.op->newline() << "#if ! defined(CONFIG_KPROBES)"; s.op->newline() << "#error \"Need CONFIG_KPROBES!\""; s.op->newline() << "#endif"; s.op->newline(); s.op->newline() << "#ifndef KRETACTIVE"; s.op->newline() << "#define KRETACTIVE (max(15,6*(int)num_possible_cpus()))"; s.op->newline() << "#endif"; // Forward decls s.op->newline() << "#include \"linux/kprobes-common.h\""; // Forward declare the master entry functions s.op->newline() << "static int enter_kprobe_probe (struct kprobe *inst,"; s.op->line() << " struct pt_regs *regs);"; s.op->newline() << "static int enter_kretprobe_probe (struct kretprobe_instance *inst,"; s.op->line() << " struct pt_regs *regs);"; // Emit an array of kprobe/kretprobe pointers s.op->newline() << "#if defined(STAPCONF_UNREGISTER_KPROBES)"; s.op->newline() << "static void * stap_unreg_kprobes[" << probes_by_module.size() << "];"; s.op->newline() << "#endif"; // Emit the actual probe list. // NB: we used to plop a union { struct kprobe; struct kretprobe } into // struct stap_dwarf_probe, but it being initialized data makes it add // hundreds of bytes of padding per stap_dwarf_probe. (PR5673) s.op->newline() << "static struct stap_dwarf_kprobe stap_dwarf_kprobes[" << probes_by_module.size() << "];"; // NB: bss! s.op->newline() << "static struct stap_dwarf_probe {"; s.op->newline(1) << "const unsigned return_p:1;"; s.op->newline() << "const unsigned maxactive_p:1;"; s.op->newline() << "const unsigned optional_p:1;"; s.op->newline() << "unsigned registered_p:1;"; s.op->newline() << "const unsigned short maxactive_val;"; // data saved in the kretprobe_instance packet s.op->newline() << "const unsigned short saved_longs;"; s.op->newline() << "const unsigned short saved_strings;"; // Let's find some stats for the embedded strings. Maybe they // are small and uniform enough to justify putting char[MAX]'s into // the array instead of relocated char*'s. size_t module_name_max = 0, section_name_max = 0; size_t module_name_tot = 0, section_name_tot = 0; size_t all_name_cnt = probes_by_module.size(); // for average for (p_b_m_iterator it = probes_by_module.begin(); it != probes_by_module.end(); it++) { dwarf_derived_probe* p = it->second; #define DOIT(var,expr) do { \ size_t var##_size = (expr) + 1; \ var##_max = max (var##_max, var##_size); \ var##_tot += var##_size; } while (0) DOIT(module_name, p->module.size()); DOIT(section_name, p->section.size()); #undef DOIT } // Decide whether it's worthwhile to use char[] or char* by comparing // the amount of average waste (max - avg) to the relocation data size // (3 native long words). #define CALCIT(var) \ if ((var##_name_max-(var##_name_tot/all_name_cnt)) < (3 * sizeof(void*))) \ { \ s.op->newline() << "const char " << #var << "[" << var##_name_max << "];"; \ if (s.verbose > 2) clog << "stap_dwarf_probe " << #var \ << "[" << var##_name_max << "]" << endl; \ } \ else \ { \ s.op->newline() << "const char * const " << #var << ";"; \ if (s.verbose > 2) clog << "stap_dwarf_probe *" << #var << endl; \ } CALCIT(module); CALCIT(section); #undef CALCIT s.op->newline() << "const unsigned long address;"; s.op->newline() << "const struct stap_probe * const probe;"; s.op->newline() << "const struct stap_probe * const entry_probe;"; s.op->newline(-1) << "} stap_dwarf_probes[] = {"; s.op->indent(1); for (p_b_m_iterator it = probes_by_module.begin(); it != probes_by_module.end(); it++) { dwarf_derived_probe* p = it->second; s.op->newline() << "{"; if (p->has_return) s.op->line() << " .return_p=1,"; if (p->has_maxactive) { s.op->line() << " .maxactive_p=1,"; assert (p->maxactive_val >= 0 && p->maxactive_val <= USHRT_MAX); s.op->line() << " .maxactive_val=" << p->maxactive_val << ","; } if (p->saved_longs || p->saved_strings) { if (p->saved_longs) s.op->line() << " .saved_longs=" << p->saved_longs << ","; if (p->saved_strings) s.op->line() << " .saved_strings=" << p->saved_strings << ","; if (p->entry_handler) s.op->line() << " .entry_probe=" << common_probe_init (p->entry_handler) << ","; } if (p->locations[0]->optional) s.op->line() << " .optional_p=1,"; s.op->line() << " .address=(unsigned long)0x" << hex << p->addr << dec << "ULL,"; s.op->line() << " .module=\"" << p->module << "\","; s.op->line() << " .section=\"" << p->section << "\","; s.op->line() << " .probe=" << common_probe_init (p) << ","; s.op->line() << " },"; } s.op->newline(-1) << "};"; // Emit the kprobes callback function s.op->newline(); s.op->newline() << "static int enter_kprobe_probe (struct kprobe *inst,"; s.op->line() << " struct pt_regs *regs) {"; // NB: as of PR5673, the kprobe|kretprobe union struct is in BSS s.op->newline(1) << "int kprobe_idx = ((uintptr_t)inst-(uintptr_t)stap_dwarf_kprobes)/sizeof(struct stap_dwarf_kprobe);"; // Check that the index is plausible s.op->newline() << "struct stap_dwarf_probe *sdp = &stap_dwarf_probes["; s.op->line() << "((kprobe_idx >= 0 && kprobe_idx < " << probes_by_module.size() << ")?"; s.op->line() << "kprobe_idx:0)"; // NB: at least we avoid memory corruption // XXX: it would be nice to give a more verbose error though; BUG_ON later? s.op->line() << "];"; common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sdp->probe", "stp_probe_type_kprobe"); s.op->newline() << "c->kregs = regs;"; // Make it look like the IP is set as it wouldn't have been replaced // by a breakpoint instruction when calling real probe handler. Reset // IP regs on return, so we don't confuse kprobes. PR10458 s.op->newline() << "{"; s.op->indent(1); s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->kregs);"; s.op->newline() << "SET_REG_IP(regs, (unsigned long) inst->addr);"; s.op->newline() << "(*sdp->probe->ph) (c);"; s.op->newline() << "SET_REG_IP(regs, kprobes_ip);"; s.op->newline(-1) << "}"; common_probe_entryfn_epilogue (s, true); s.op->newline() << "return 0;"; s.op->newline(-1) << "}"; // Same for kretprobes s.op->newline(); s.op->newline() << "static int enter_kretprobe_common (struct kretprobe_instance *inst,"; s.op->line() << " struct pt_regs *regs, int entry) {"; s.op->newline(1) << "struct kretprobe *krp = inst->rp;"; // NB: as of PR5673, the kprobe|kretprobe union struct is in BSS s.op->newline() << "int kprobe_idx = ((uintptr_t)krp-(uintptr_t)stap_dwarf_kprobes)/sizeof(struct stap_dwarf_kprobe);"; // Check that the index is plausible s.op->newline() << "struct stap_dwarf_probe *sdp = &stap_dwarf_probes["; s.op->line() << "((kprobe_idx >= 0 && kprobe_idx < " << probes_by_module.size() << ")?"; s.op->line() << "kprobe_idx:0)"; // NB: at least we avoid memory corruption // XXX: it would be nice to give a more verbose error though; BUG_ON later? s.op->line() << "];"; s.op->newline() << "const struct stap_probe *sp = entry ? sdp->entry_probe : sdp->probe;"; s.op->newline() << "if (sp) {"; s.op->indent(1); common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sp", "stp_probe_type_kretprobe"); s.op->newline() << "c->kregs = regs;"; // for assisting runtime's backtrace logic and accessing kretprobe data packets s.op->newline() << "c->ips.krp.pi = inst;"; s.op->newline() << "c->ips.krp.pi_longs = sdp->saved_longs;"; // Make it look like the IP is set as it wouldn't have been replaced // by a breakpoint instruction when calling real probe handler. Reset // IP regs on return, so we don't confuse kprobes. PR10458 s.op->newline() << "{"; s.op->newline(1) << "unsigned long kprobes_ip = REG_IP(c->kregs);"; s.op->newline() << "if (entry)"; s.op->newline(1) << "SET_REG_IP(regs, (unsigned long) inst->rp->kp.addr);"; s.op->newline(-1) << "else"; s.op->newline(1) << "SET_REG_IP(regs, (unsigned long)inst->ret_addr);"; s.op->newline(-1) << "(sp->ph) (c);"; s.op->newline() << "SET_REG_IP(regs, kprobes_ip);"; s.op->newline(-1) << "}"; common_probe_entryfn_epilogue (s, true); s.op->newline(-1) << "}"; s.op->newline() << "return 0;"; s.op->newline(-1) << "}"; s.op->newline(); s.op->newline() << "static int enter_kretprobe_probe (struct kretprobe_instance *inst,"; s.op->line() << " struct pt_regs *regs) {"; s.op->newline(1) << "return enter_kretprobe_common(inst, regs, 0);"; s.op->newline(-1) << "}"; s.op->newline(); s.op->newline() << "static int enter_kretprobe_entry_probe (struct kretprobe_instance *inst,"; s.op->line() << " struct pt_regs *regs) {"; s.op->newline(1) << "return enter_kretprobe_common(inst, regs, 1);"; s.op->newline(-1) << "}"; s.op->newline(); } void dwarf_derived_probe_group::emit_module_init (systemtap_session& s) { s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {"; s.op->newline(1) << "struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];"; s.op->newline() << "struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];"; s.op->newline() << "unsigned long relocated_addr = _stp_kmodule_relocate (sdp->module, sdp->section, sdp->address);"; s.op->newline() << "if (relocated_addr == 0) continue;"; // quietly; assume module is absent s.op->newline() << "probe_point = sdp->probe->pp;"; // for error messages s.op->newline() << "if (sdp->return_p) {"; s.op->newline(1) << "kp->u.krp.kp.addr = (void *) relocated_addr;"; s.op->newline() << "if (sdp->maxactive_p) {"; s.op->newline(1) << "kp->u.krp.maxactive = sdp->maxactive_val;"; s.op->newline(-1) << "} else {"; s.op->newline(1) << "kp->u.krp.maxactive = KRETACTIVE;"; s.op->newline(-1) << "}"; s.op->newline() << "kp->u.krp.handler = &enter_kretprobe_probe;"; s.op->newline() << "#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)"; s.op->newline() << "if (sdp->entry_probe) {"; s.op->newline(1) << "kp->u.krp.entry_handler = &enter_kretprobe_entry_probe;"; s.op->newline() << "kp->u.krp.data_size = sdp->saved_longs * sizeof(int64_t) + "; s.op->newline() << " sdp->saved_strings * MAXSTRINGLEN;"; s.op->newline(-1) << "}"; s.op->newline() << "#endif"; // to ensure safeness of bspcache, always use aggr_kprobe on ia64 s.op->newline() << "#ifdef __ia64__"; s.op->newline() << "kp->dummy.addr = kp->u.krp.kp.addr;"; s.op->newline() << "kp->dummy.pre_handler = NULL;"; s.op->newline() << "rc = register_kprobe (& kp->dummy);"; s.op->newline() << "if (rc == 0) {"; s.op->newline(1) << "rc = register_kretprobe (& kp->u.krp);"; s.op->newline() << "if (rc != 0)"; s.op->newline(1) << "unregister_kprobe (& kp->dummy);"; s.op->newline(-2) << "}"; s.op->newline() << "#else"; s.op->newline() << "rc = register_kretprobe (& kp->u.krp);"; s.op->newline() << "#endif"; s.op->newline(-1) << "} else {"; // to ensure safeness of bspcache, always use aggr_kprobe on ia64 s.op->newline(1) << "kp->u.kp.addr = (void *) relocated_addr;"; s.op->newline() << "kp->u.kp.pre_handler = &enter_kprobe_probe;"; s.op->newline() << "#ifdef __ia64__"; s.op->newline() << "kp->dummy.addr = kp->u.kp.addr;"; s.op->newline() << "kp->dummy.pre_handler = NULL;"; s.op->newline() << "rc = register_kprobe (& kp->dummy);"; s.op->newline() << "if (rc == 0) {"; s.op->newline(1) << "rc = register_kprobe (& kp->u.kp);"; s.op->newline() << "if (rc != 0)"; s.op->newline(1) << "unregister_kprobe (& kp->dummy);"; s.op->newline(-2) << "}"; s.op->newline() << "#else"; s.op->newline() << "rc = register_kprobe (& kp->u.kp);"; s.op->newline() << "#endif"; s.op->newline(-1) << "}"; s.op->newline() << "if (rc) {"; // PR6749: tolerate a failed register_*probe. s.op->newline(1) << "sdp->registered_p = 0;"; s.op->newline() << "if (!sdp->optional_p)"; s.op->newline(1) << "_stp_warn (\"probe %s (address 0x%lx) registration error (rc %d)\", probe_point, (unsigned long) relocated_addr, rc);"; s.op->newline(-1) << "rc = 0;"; // continue with other probes // XXX: shall we increment numskipped? s.op->newline(-1) << "}"; #if 0 /* pre PR 6749; XXX consider making an option */ s.op->newline(1) << "for (j=i-1; j>=0; j--) {"; // partial rollback s.op->newline(1) << "struct stap_dwarf_probe *sdp2 = & stap_dwarf_probes[j];"; s.op->newline() << "struct stap_dwarf_kprobe *kp2 = & stap_dwarf_kprobes[j];"; s.op->newline() << "if (sdp2->return_p) unregister_kretprobe (&kp2->u.krp);"; s.op->newline() << "else unregister_kprobe (&kp2->u.kp);"; s.op->newline() << "#ifdef __ia64__"; s.op->newline() << "unregister_kprobe (&kp2->dummy);"; s.op->newline() << "#endif"; // NB: we don't have to clear sdp2->registered_p, since the module_exit code is // not run for this early-abort case. s.op->newline(-1) << "}"; s.op->newline() << "break;"; // don't attempt to register any more probes s.op->newline(-1) << "}"; #endif s.op->newline() << "else sdp->registered_p = 1;"; s.op->newline(-1) << "}"; // for loop } void dwarf_derived_probe_group::emit_module_refresh (systemtap_session& s) { s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {"; s.op->newline(1) << "struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];"; s.op->newline() << "struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];"; s.op->newline() << "unsigned long relocated_addr = _stp_kmodule_relocate (sdp->module, sdp->section, sdp->address);"; s.op->newline() << "int rc;"; // new module arrived? s.op->newline() << "if (sdp->registered_p == 0 && relocated_addr != 0) {"; s.op->newline(1) << "if (sdp->return_p) {"; s.op->newline(1) << "kp->u.krp.kp.addr = (void *) relocated_addr;"; s.op->newline() << "if (sdp->maxactive_p) {"; s.op->newline(1) << "kp->u.krp.maxactive = sdp->maxactive_val;"; s.op->newline(-1) << "} else {"; s.op->newline(1) << "kp->u.krp.maxactive = KRETACTIVE;"; s.op->newline(-1) << "}"; s.op->newline() << "kp->u.krp.handler = &enter_kretprobe_probe;"; s.op->newline() << "#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)"; s.op->newline() << "if (sdp->entry_probe) {"; s.op->newline(1) << "kp->u.krp.entry_handler = &enter_kretprobe_entry_probe;"; s.op->newline() << "kp->u.krp.data_size = sdp->saved_longs * sizeof(int64_t) + "; s.op->newline() << " sdp->saved_strings * MAXSTRINGLEN;"; s.op->newline(-1) << "}"; s.op->newline() << "#endif"; // to ensure safeness of bspcache, always use aggr_kprobe on ia64 s.op->newline() << "#ifdef __ia64__"; s.op->newline() << "kp->dummy.addr = kp->u.krp.kp.addr;"; s.op->newline() << "kp->dummy.pre_handler = NULL;"; s.op->newline() << "rc = register_kprobe (& kp->dummy);"; s.op->newline() << "if (rc == 0) {"; s.op->newline(1) << "rc = register_kretprobe (& kp->u.krp);"; s.op->newline() << "if (rc != 0)"; s.op->newline(1) << "unregister_kprobe (& kp->dummy);"; s.op->newline(-2) << "}"; s.op->newline() << "#else"; s.op->newline() << "rc = register_kretprobe (& kp->u.krp);"; s.op->newline() << "#endif"; s.op->newline(-1) << "} else {"; // to ensure safeness of bspcache, always use aggr_kprobe on ia64 s.op->newline(1) << "kp->u.kp.addr = (void *) relocated_addr;"; s.op->newline() << "kp->u.kp.pre_handler = &enter_kprobe_probe;"; s.op->newline() << "#ifdef __ia64__"; s.op->newline() << "kp->dummy.addr = kp->u.kp.addr;"; s.op->newline() << "kp->dummy.pre_handler = NULL;"; s.op->newline() << "rc = register_kprobe (& kp->dummy);"; s.op->newline() << "if (rc == 0) {"; s.op->newline(1) << "rc = register_kprobe (& kp->u.kp);"; s.op->newline() << "if (rc != 0)"; s.op->newline(1) << "unregister_kprobe (& kp->dummy);"; s.op->newline(-2) << "}"; s.op->newline() << "#else"; s.op->newline() << "rc = register_kprobe (& kp->u.kp);"; s.op->newline() << "#endif"; s.op->newline(-1) << "}"; s.op->newline() << "if (rc == 0) sdp->registered_p = 1;"; // old module disappeared? s.op->newline(-1) << "} else if (sdp->registered_p == 1 && relocated_addr == 0) {"; s.op->newline(1) << "if (sdp->return_p) {"; s.op->newline(1) << "unregister_kretprobe (&kp->u.krp);"; s.op->newline() << "atomic_add (kp->u.krp.nmissed, skipped_count());"; s.op->newline() << "#ifdef STP_TIMING"; s.op->newline() << "if (kp->u.krp.nmissed)"; s.op->newline(1) << "_stp_warn (\"Skipped due to missed kretprobe/1 on '%s': %d\\n\", sdp->probe->pp, kp->u.krp.nmissed);"; s.op->newline(-1) << "#endif"; s.op->newline() << "atomic_add (kp->u.krp.kp.nmissed, skipped_count());"; s.op->newline() << "#ifdef STP_TIMING"; s.op->newline() << "if (kp->u.krp.kp.nmissed)"; s.op->newline(1) << "_stp_warn (\"Skipped due to missed kretprobe/2 on '%s': %lu\\n\", sdp->probe->pp, kp->u.krp.kp.nmissed);"; s.op->newline(-1) << "#endif"; s.op->newline(-1) << "} else {"; s.op->newline(1) << "unregister_kprobe (&kp->u.kp);"; s.op->newline() << "atomic_add (kp->u.kp.nmissed, skipped_count());"; s.op->newline() << "#ifdef STP_TIMING"; s.op->newline() << "if (kp->u.kp.nmissed)"; s.op->newline(1) << "_stp_warn (\"Skipped due to missed kprobe on '%s': %lu\\n\", sdp->probe->pp, kp->u.kp.nmissed);"; s.op->newline(-1) << "#endif"; s.op->newline(-1) << "}"; s.op->newline() << "#if defined(__ia64__)"; s.op->newline() << "unregister_kprobe (&kp->dummy);"; s.op->newline() << "#endif"; s.op->newline() << "sdp->registered_p = 0;"; s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; // for loop } void dwarf_derived_probe_group::emit_module_exit (systemtap_session& s) { //Unregister kprobes by batch interfaces. s.op->newline() << "#if defined(STAPCONF_UNREGISTER_KPROBES)"; s.op->newline() << "j = 0;"; s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {"; s.op->newline(1) << "struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];"; s.op->newline() << "struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];"; s.op->newline() << "if (! sdp->registered_p) continue;"; s.op->newline() << "if (!sdp->return_p)"; s.op->newline(1) << "stap_unreg_kprobes[j++] = &kp->u.kp;"; s.op->newline(-2) << "}"; s.op->newline() << "unregister_kprobes((struct kprobe **)stap_unreg_kprobes, j);"; s.op->newline() << "j = 0;"; s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {"; s.op->newline(1) << "struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];"; s.op->newline() << "struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];"; s.op->newline() << "if (! sdp->registered_p) continue;"; s.op->newline() << "if (sdp->return_p)"; s.op->newline(1) << "stap_unreg_kprobes[j++] = &kp->u.krp;"; s.op->newline(-2) << "}"; s.op->newline() << "unregister_kretprobes((struct kretprobe **)stap_unreg_kprobes, j);"; s.op->newline() << "#ifdef __ia64__"; s.op->newline() << "j = 0;"; s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {"; s.op->newline(1) << "struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];"; s.op->newline() << "struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];"; s.op->newline() << "if (! sdp->registered_p) continue;"; s.op->newline() << "stap_unreg_kprobes[j++] = &kp->dummy;"; s.op->newline(-1) << "}"; s.op->newline() << "unregister_kprobes((struct kprobe **)stap_unreg_kprobes, j);"; s.op->newline() << "#endif"; s.op->newline() << "#endif"; s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {"; s.op->newline(1) << "struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];"; s.op->newline() << "struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];"; s.op->newline() << "if (! sdp->registered_p) continue;"; s.op->newline() << "if (sdp->return_p) {"; s.op->newline() << "#if !defined(STAPCONF_UNREGISTER_KPROBES)"; s.op->newline(1) << "unregister_kretprobe (&kp->u.krp);"; s.op->newline() << "#endif"; s.op->newline() << "atomic_add (kp->u.krp.nmissed, skipped_count());"; s.op->newline() << "#ifdef STP_TIMING"; s.op->newline() << "if (kp->u.krp.nmissed)"; s.op->newline(1) << "_stp_warn (\"Skipped due to missed kretprobe/1 on '%s': %d\\n\", sdp->probe->pp, kp->u.krp.nmissed);"; s.op->newline(-1) << "#endif"; s.op->newline() << "atomic_add (kp->u.krp.kp.nmissed, skipped_count());"; s.op->newline() << "#ifdef STP_TIMING"; s.op->newline() << "if (kp->u.krp.kp.nmissed)"; s.op->newline(1) << "_stp_warn (\"Skipped due to missed kretprobe/2 on '%s': %lu\\n\", sdp->probe->pp, kp->u.krp.kp.nmissed);"; s.op->newline(-1) << "#endif"; s.op->newline(-1) << "} else {"; s.op->newline() << "#if !defined(STAPCONF_UNREGISTER_KPROBES)"; s.op->newline(1) << "unregister_kprobe (&kp->u.kp);"; s.op->newline() << "#endif"; s.op->newline() << "atomic_add (kp->u.kp.nmissed, skipped_count());"; s.op->newline() << "#ifdef STP_TIMING"; s.op->newline() << "if (kp->u.kp.nmissed)"; s.op->newline(1) << "_stp_warn (\"Skipped due to missed kprobe on '%s': %lu\\n\", sdp->probe->pp, kp->u.kp.nmissed);"; s.op->newline(-1) << "#endif"; s.op->newline(-1) << "}"; s.op->newline() << "#if !defined(STAPCONF_UNREGISTER_KPROBES) && defined(__ia64__)"; s.op->newline() << "unregister_kprobe (&kp->dummy);"; s.op->newline() << "#endif"; s.op->newline() << "sdp->registered_p = 0;"; s.op->newline(-1) << "}"; } static void sdt_v3_tokenize(const string& str, vector& tokens) { string::size_type pos; string::size_type lastPos = str.find_first_not_of(" ", 0); string::size_type nextAt = str.find("@", lastPos); if (nextAt == string::npos) { // PR13934: Assembly probes are not forced to use the N@OP form. // In this case, N is inferred to be the native word size. Since we // don't have a nice delimiter, just split it on spaces. SDT-asm authors // then must not put any spaces in arguments, to avoid ambiguity. tokenize(str, tokens, " "); return; } while (lastPos != string::npos) { pos = nextAt + 1; nextAt = str.find("@", pos); if (nextAt == string::npos) pos = string::npos; else pos = str.rfind(" ", nextAt); tokens.push_back(str.substr(lastPos, pos - lastPos)); lastPos = str.find_first_not_of(" ", pos); } } struct sdt_uprobe_var_expanding_visitor: public var_expanding_visitor { enum regwidths {QI, QIh, HI, SI, DI}; sdt_uprobe_var_expanding_visitor(systemtap_session& s, int elf_machine, const string & process_name, const string & provider_name, const string & probe_name, stap_sdt_probe_type probe_type, const string & arg_string, int ac): session (s), elf_machine (elf_machine), process_name (process_name), provider_name (provider_name), probe_name (probe_name), probe_type (probe_type), arg_count ((unsigned) ac) { /* Register name mapping table depends on the elf machine of this particular probe target process/file, not upon the host. So we can't just #ifdef _i686_ etc. */ #define DRI(name,num,width) dwarf_regs[name]=make_pair(num,width) if (elf_machine == EM_X86_64) { DRI ("%rax", 0, DI); DRI ("%eax", 0, SI); DRI ("%ax", 0, HI); DRI ("%al", 0, QI); DRI ("%ah", 0, QIh); DRI ("%rdx", 1, DI); DRI ("%edx", 1, SI); DRI ("%dx", 1, HI); DRI ("%dl", 1, QI); DRI ("%dh", 1, QIh); DRI ("%rcx", 2, DI); DRI ("%ecx", 2, SI); DRI ("%cx", 2, HI); DRI ("%cl", 2, QI); DRI ("%ch", 2, QIh); DRI ("%rbx", 3, DI); DRI ("%ebx", 3, SI); DRI ("%bx", 3, HI); DRI ("%bl", 3, QI); DRI ("%bh", 3, QIh); DRI ("%rsi", 4, DI); DRI ("%esi", 4, SI); DRI ("%si", 4, HI); DRI ("%sil", 4, QI); DRI ("%rdi", 5, DI); DRI ("%edi", 5, SI); DRI ("%di", 5, HI); DRI ("%dil", 5, QI); DRI ("%rbp", 6, DI); DRI ("%ebp", 6, SI); DRI ("%bp", 6, HI); DRI ("%bpl", 6, QI); DRI ("%rsp", 7, DI); DRI ("%esp", 7, SI); DRI ("%sp", 7, HI); DRI ("%spl", 7, QI); DRI ("%r8", 8, DI); DRI ("%r8d", 8, SI); DRI ("%r8w", 8, HI); DRI ("%r8b", 8, QI); DRI ("%r9", 9, DI); DRI ("%r9d", 9, SI); DRI ("%r9w", 9, HI); DRI ("%r9b", 9, QI); DRI ("%r10", 10, DI); DRI ("%r10d", 10, SI); DRI ("%r10w", 10, HI); DRI ("%r10b", 10, QI); DRI ("%r11", 11, DI); DRI ("%r11d", 11, SI); DRI ("%r11w", 11, HI); DRI ("%r11b", 11, QI); DRI ("%r12", 12, DI); DRI ("%r12d", 12, SI); DRI ("%r12w", 12, HI); DRI ("%r12b", 12, QI); DRI ("%r13", 13, DI); DRI ("%r13d", 13, SI); DRI ("%r13w", 13, HI); DRI ("%r13b", 13, QI); DRI ("%r14", 14, DI); DRI ("%r14d", 14, SI); DRI ("%r14w", 14, HI); DRI ("%r14b", 14, QI); DRI ("%r15", 15, DI); DRI ("%r15d", 15, SI); DRI ("%r15w", 15, HI); DRI ("%r15b", 15, QI); } else if (elf_machine == EM_386) { DRI ("%eax", 0, SI); DRI ("%ax", 0, HI); DRI ("%al", 0, QI); DRI ("%ah", 0, QIh); DRI ("%ecx", 1, SI); DRI ("%cx", 1, HI); DRI ("%cl", 1, QI); DRI ("%ch", 1, QIh); DRI ("%edx", 2, SI); DRI ("%dx", 2, HI); DRI ("%dl", 2, QI); DRI ("%dh", 2, QIh); DRI ("%ebx", 3, SI); DRI ("%bx", 3, HI); DRI ("%bl", 3, QI); DRI ("%bh", 3, QIh); DRI ("%esp", 4, SI); DRI ("%sp", 4, HI); DRI ("%ebp", 5, SI); DRI ("%bp", 5, HI); DRI ("%esi", 6, SI); DRI ("%si", 6, HI); DRI ("%sil", 6, QI); DRI ("%edi", 7, SI); DRI ("%di", 7, HI); DRI ("%dil", 7, QI); } else if (elf_machine == EM_PPC || elf_machine == EM_PPC64) { DRI ("%r0", 0, DI); DRI ("%r1", 1, DI); DRI ("%r2", 2, DI); DRI ("%r3", 3, DI); DRI ("%r4", 4, DI); DRI ("%r5", 5, DI); DRI ("%r6", 6, DI); DRI ("%r7", 7, DI); DRI ("%r8", 8, DI); DRI ("%r9", 9, DI); DRI ("%r10", 10, DI); DRI ("%r11", 11, DI); DRI ("%r12", 12, DI); DRI ("%r13", 13, DI); DRI ("%r14", 14, DI); DRI ("%r15", 15, DI); DRI ("%r16", 16, DI); DRI ("%r17", 17, DI); DRI ("%r18", 18, DI); DRI ("%r19", 19, DI); DRI ("%r20", 20, DI); DRI ("%r21", 21, DI); DRI ("%r22", 22, DI); DRI ("%r23", 23, DI); DRI ("%r24", 24, DI); DRI ("%r25", 25, DI); DRI ("%r26", 26, DI); DRI ("%r27", 27, DI); DRI ("%r28", 28, DI); DRI ("%r29", 29, DI); DRI ("%r30", 30, DI); DRI ("%r31", 31, DI); // PR11821: unadorned register "names" without -mregnames DRI ("0", 0, DI); DRI ("1", 1, DI); DRI ("2", 2, DI); DRI ("3", 3, DI); DRI ("4", 4, DI); DRI ("5", 5, DI); DRI ("6", 6, DI); DRI ("7", 7, DI); DRI ("8", 8, DI); DRI ("9", 9, DI); DRI ("10", 10, DI); DRI ("11", 11, DI); DRI ("12", 12, DI); DRI ("13", 13, DI); DRI ("14", 14, DI); DRI ("15", 15, DI); DRI ("16", 16, DI); DRI ("17", 17, DI); DRI ("18", 18, DI); DRI ("19", 19, DI); DRI ("20", 20, DI); DRI ("21", 21, DI); DRI ("22", 22, DI); DRI ("23", 23, DI); DRI ("24", 24, DI); DRI ("25", 25, DI); DRI ("26", 26, DI); DRI ("27", 27, DI); DRI ("28", 28, DI); DRI ("29", 29, DI); DRI ("30", 30, DI); DRI ("31", 31, DI); } else if (elf_machine == EM_S390) { DRI ("%r0", 0, DI); DRI ("%r1", 1, DI); DRI ("%r2", 2, DI); DRI ("%r3", 3, DI); DRI ("%r4", 4, DI); DRI ("%r5", 5, DI); DRI ("%r6", 6, DI); DRI ("%r7", 7, DI); DRI ("%r8", 8, DI); DRI ("%r9", 9, DI); DRI ("%r10", 10, DI); DRI ("%r11", 11, DI); DRI ("%r12", 12, DI); DRI ("%r13", 13, DI); DRI ("%r14", 14, DI); DRI ("%r15", 15, DI); } else if (elf_machine == EM_ARM) { DRI ("r0", 0, SI); DRI ("r1", 1, SI); DRI ("r2", 2, SI); DRI ("r3", 3, SI); DRI ("r4", 4, SI); DRI ("r5", 5, SI); DRI ("r6", 6, SI); DRI ("r7", 7, SI); DRI ("r8", 8, SI); DRI ("r9", 9, SI); DRI ("sl", 10, SI); DRI ("fp", 11, SI); DRI ("ip", 12, SI); DRI ("sp", 13, SI); DRI ("lr", 14, SI); DRI ("pc", 15, SI); } else if (arg_count) { /* permit this case; just fall back to dwarf */ } #undef DRI need_debug_info = false; if (probe_type == uprobe3_type) { sdt_v3_tokenize(arg_string, arg_tokens); assert(arg_count <= 12); } else { tokenize(arg_string, arg_tokens, " "); assert(arg_count <= 10); } } systemtap_session& session; int elf_machine; const string & process_name; const string & provider_name; const string & probe_name; stap_sdt_probe_type probe_type; unsigned arg_count; vector arg_tokens; map > dwarf_regs; bool need_debug_info; void visit_target_symbol (target_symbol* e); void visit_target_symbol_arg (target_symbol* e); void visit_target_symbol_context (target_symbol* e); void visit_atvar_op (atvar_op* e); void visit_cast_op (cast_op* e); }; void sdt_uprobe_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) { if (e->addressof) throw semantic_error(_("cannot take address of context variable"), e->tok); if (e->name == "$$name") { literal_string *myname = new literal_string (probe_name); myname->tok = e->tok; provide(myname); return; } else if (e->name == "$$provider") { literal_string *myname = new literal_string (provider_name); myname->tok = e->tok; provide(myname); return; } else if (e->name == "$$vars" || e->name == "$$parms") { e->assert_no_components("sdt", true); // Convert $$vars to sprintf of a list of vars which we recursively evaluate // NB: we synthesize a new token here rather than reusing // e->tok, because print_format::print likes to use // its tok->content. token* pf_tok = new token(*e->tok); pf_tok->content = "sprintf"; print_format* pf = print_format::create(pf_tok); for (unsigned i = 1; i <= arg_count; ++i) { if (i > 1) pf->raw_components += " "; target_symbol *tsym = new target_symbol; tsym->tok = e->tok; tsym->name = "$arg" + lex_cast(i); pf->raw_components += tsym->name; tsym->components = e->components; expression *texp = require (tsym); if (!e->components.empty() && e->components[0].type == target_symbol::comp_pretty_print) pf->raw_components += "=%s"; else pf->raw_components += "=%#x"; pf->args.push_back(texp); } pf->components = print_format::string_to_components(pf->raw_components); provide (pf); } else assert(0); // shouldn't get here } void sdt_uprobe_var_expanding_visitor::visit_target_symbol_arg (target_symbol *e) { try { unsigned argno = 0; // the N in $argN try { if (startswith(e->name, "$arg")) argno = lex_cast(e->name.substr(4)); } catch (const runtime_error& f) // non-integral $arg suffix: e.g. $argKKKSDF { argno = 0; } if (arg_count == 0 || // a sdt.h variant without .probe-stored arg_count argno < 1 || argno > arg_count) // a $argN with out-of-range N { // NB: Either // 1) uprobe1_type $argN or $FOO (we don't know the arg_count) // 2) uprobe2_type $FOO (no probe args) // both of which get resolved later. // Throw it now, and it might be resolved by DWARF later. need_debug_info = true; throw semantic_error(_("target-symbol requires debuginfo"), e->tok); } assert (arg_tokens.size() >= argno); string asmarg = arg_tokens[argno-1]; // $arg1 => arg_tokens[0] // Now we try to parse this thing, which is an assembler operand // expression. If we can't, we warn, back down to need_debug_info // and hope for the best. Here is the syntax for a few architectures. // Note that the power iN syntax is only for V3 sdt.h; gcc emits the i. // // literal reg reg reg + base+index*size+offset // indirect offset // x86 $N %rR (%rR) N(%rR) O(%bR,%iR,S) // power iN R (R) N(R) // ia64 N rR [r16] // s390 N %rR 0(rR) N(r15) // arm #N rR [rR] [rR, #N] expression* argexpr = 0; // filled in in case of successful parse string percent_regnames; string regnames; vector matches; long precision; int rc; // Parse the leading length if (asmarg.find('@') != string::npos) { precision = lex_cast(asmarg.substr(0, asmarg.find('@'))); asmarg = asmarg.substr(asmarg.find('@')+1); } else { // V1/V2 do not have precision field so default to signed long // V3 asm does not have precision field so default to unsigned long if (probe_type == uprobe3_type) precision = sizeof(long); // this is an asm probe else precision = -sizeof(long); } // test for a numeric literal. // Only accept (signed) decimals throughout. XXX // PR11821. NB: on powerpc, literals are not prefixed with $, // so this regex does not match. But that's OK, since without // -mregnames, we can't tell them apart from register numbers // anyway. With -mregnames, we could, if gcc somehow // communicated to us the presence of that option, but alas it // doesn't. http://gcc.gnu.org/PR44995. rc = regexp_match (asmarg, "^[i\\$#][-]?[0-9][0-9]*$", matches); if (! rc) { string sn = matches[0].substr(1); int64_t n; try { // We have to pay attention to the size & sign, as gcc sometimes // propagates constants that don't quite match, like a negative // value to fill an unsigned type. switch (precision) { case -1: n = lex_cast< int8_t>(sn); break; case 1: n = lex_cast< uint8_t>(sn); break; case -2: n = lex_cast< int16_t>(sn); break; case 2: n = lex_cast(sn); break; case -4: n = lex_cast< int32_t>(sn); break; case 4: n = lex_cast(sn); break; default: case -8: n = lex_cast< int64_t>(sn); break; case 8: n = lex_cast(sn); break; } } catch (std::runtime_error&) { goto not_matched; } literal_number* ln = new literal_number(n); ln->tok = e->tok; argexpr = ln; goto matched; } if (dwarf_regs.empty()) goto not_matched; // Build regex pieces out of the known dwarf_regs. We keep two separate // lists: ones with the % prefix (and thus unambigiuous even despite PR11821), // and ones with no prefix (and thus only usable in unambiguous contexts). for (map >::iterator ri = dwarf_regs.begin(); ri != dwarf_regs.end(); ri++) { string regname = ri->first; assert (regname != ""); regnames += string("|")+regname; if (regname[0]=='%') percent_regnames += string("|")+regname; } // clip off leading | regnames = regnames.substr(1); if (percent_regnames != "") percent_regnames = percent_regnames.substr(1); // test for REGISTER // NB: Because PR11821, we must use percent_regnames here. if (elf_machine == EM_PPC || elf_machine == EM_PPC64 || elf_machine == EM_ARM) rc = regexp_match (asmarg, string("^(")+regnames+string(")$"), matches); else rc = regexp_match (asmarg, string("^(")+percent_regnames+string(")$"), matches); if (! rc) { string regname = matches[1]; map >::iterator ri = dwarf_regs.find (regname); if (ri != dwarf_regs.end()) // known register { embedded_expr *get_arg1 = new embedded_expr; string width_adjust; switch (ri->second.second) { case QI: width_adjust = ") & 0xff)"; break; case QIh: width_adjust = ">>8) & 0xff)"; break; case HI: // preserve 16 bit register signness width_adjust = ") & 0xffff)"; if (precision < 0) width_adjust += " << 48 >> 48"; break; case SI: // preserve 32 bit register signness width_adjust = ") & 0xffffffff)"; if (precision < 0) width_adjust += " << 32 >> 32"; break; default: width_adjust = "))"; } string type = ""; if (probe_type == uprobe3_type) type = (precision < 0 ? "(int" : "(uint") + lex_cast(abs(precision) * 8) + "_t)"; type = type + "(("; get_arg1->tok = e->tok; get_arg1->code = string("/* unprivileged */ /* pure */") + string(" ((int64_t)") + type + (is_user_module (process_name) ? string("u_fetch_register(") : string("k_fetch_register(")) + lex_cast(dwarf_regs[regname].first) + string("))") + width_adjust; argexpr = get_arg1; goto matched; } // invalid register name, fall through } int reg, offset1; // test for OFFSET(REGISTER) where OFFSET is +-N+-N+-N // NB: Despite PR11821, we can use regnames here, since the parentheses // make things unambiguous. (Note: gdb/stap-probe.c also parses this) // On ARM test for [REGISTER, OFFSET] if (elf_machine == EM_ARM) { rc = regexp_match (asmarg, string("^\\[(")+regnames+string("), #([+-]?[0-9]+)([+-][0-9]*)?([+-][0-9]*)?\\]$"), matches); reg = 1; offset1 = 2; } else { rc = regexp_match (asmarg, string("^([+-]?[0-9]*)([+-][0-9]*)?([+-][0-9]*)?[(](")+regnames+string(")[)]$"), matches); reg = 4; offset1 = 1; } if (! rc) { string regname; int64_t disp = 0; if (matches[reg].length()) regname = matches[reg]; if (dwarf_regs.find (regname) == dwarf_regs.end()) goto not_matched; for (int i=offset1; i <= (offset1 + 2); i++) if (matches[i].length()) try { disp += lex_cast(matches[i]); // should decode positive/negative hex/decimal } catch (const runtime_error& f) // unparseable offset { goto not_matched; // can't just 'break' out of // this case or use a sentinel // value, unfortunately } // synthesize user_long(%{fetch_register(R)%} + D) embedded_expr *get_arg1 = new embedded_expr; get_arg1->tok = e->tok; get_arg1->code = string("/* unprivileged */ /* pure */") + (is_user_module (process_name) ? string("u_fetch_register(") : string("k_fetch_register(")) + lex_cast(dwarf_regs[regname].first) + string(")"); // XXX: may we ever need to cast that to a narrower type? literal_number* inc = new literal_number(disp); inc->tok = e->tok; binary_expression *be = new binary_expression; be->tok = e->tok; be->left = get_arg1; be->op = "+"; be->right = inc; functioncall *fc = new functioncall; switch (precision) { case 1: case -1: fc->function = "user_int8"; break; case 2: fc->function = "user_uint16"; break; case -2: fc->function = "user_int16"; break; case 4: fc->function = "user_uint32"; break; case -4: fc->function = "user_int32"; break; case 8: case -8: fc->function = "user_int64"; break; default: fc->function = "user_long"; } fc->tok = e->tok; fc->args.push_back(be); argexpr = fc; goto matched; } // test for OFFSET(BASE_REGISTER,INDEX_REGISTER[,SCALE]) where OFFSET is +-N+-N+-N // NB: Despite PR11821, we can use regnames here, since the parentheses // make things unambiguous. (Note: gdb/stap-probe.c also parses this) rc = regexp_match (asmarg, string("^([+-]?[0-9]*)([+-][0-9]*)?([+-][0-9]*)?[(](")+regnames+string("),(")+regnames+string(")(,[1248])?[)]$"), matches); if (! rc) { string baseregname; string indexregname; int64_t disp = 0; short scale = 1; if (matches[6].length()) try { scale = lex_cast(matches[6].substr(1)); // NB: skip the comma! // We could verify that scale is one of 1,2,4,8, // but it doesn't really matter. An erroneous // address merely results in run-time errors. } catch (const runtime_error &f) // unparseable scale { goto not_matched; } if (matches[4].length()) baseregname = matches[4]; if (dwarf_regs.find (baseregname) == dwarf_regs.end()) goto not_matched; if (matches[5].length()) indexregname = matches[5]; if (dwarf_regs.find (indexregname) == dwarf_regs.end()) goto not_matched; for (int i = 1; i <= 3; i++) // up to three OFFSET terms if (matches[i].length()) try { disp += lex_cast(matches[i]); // should decode positive/negative hex/decimal } catch (const runtime_error& f) // unparseable offset { goto not_matched; // can't just 'break' out of // this case or use a sentinel // value, unfortunately } // synthesize user_long(%{fetch_register(R1)+fetch_register(R2)*N%} + D) embedded_expr *get_arg1 = new embedded_expr; string regfn = is_user_module (process_name) ? string("u_fetch_register") : string("k_fetch_register"); // NB: in practice sdt.h probes are for userspace only get_arg1->tok = e->tok; get_arg1->code = string("/* unprivileged */ /* pure */") + regfn + string("(")+lex_cast(dwarf_regs[baseregname].first)+string(")") + string("+(") + regfn + string("(")+lex_cast(dwarf_regs[indexregname].first)+string(")") + string("*") + lex_cast(scale) + string(")"); // NB: could plop this +DISPLACEMENT bit into the embedded-c expression too literal_number* inc = new literal_number(disp); inc->tok = e->tok; binary_expression *be = new binary_expression; be->tok = e->tok; be->left = get_arg1; be->op = "+"; be->right = inc; functioncall *fc = new functioncall; switch (precision) { case 1: case -1: fc->function = "user_int8"; break; case 2: fc->function = "user_uint16"; break; case -2: fc->function = "user_int16"; break; case 4: fc->function = "user_uint32"; break; case -4: fc->function = "user_int32"; break; case 8: case -8: fc->function = "user_int64"; break; default: fc->function = "user_long"; } fc->tok = e->tok; fc->args.push_back(be); argexpr = fc; goto matched; } not_matched: // The asmarg operand was not recognized. Back down to dwarf. if (! session.suppress_warnings) { if (probe_type == UPROBE3_TYPE) session.print_warning (_F("Can't parse SDT_V3 operand '%s'", asmarg.c_str()), e->tok); else // must be *PROBE2; others don't get asm operands session.print_warning (_F("Downgrading SDT_V2 probe argument to dwarf, can't parse '%s'", asmarg.c_str()), e->tok); } assert (argexpr == 0); need_debug_info = true; throw semantic_error(_("SDT asm not understood, requires debuginfo"), e->tok); matched: assert (argexpr != 0); if (session.verbose > 2) //TRANSLATORS: We're mapping the operand to a new expression*. clog << _F("mapped asm operand %s to ", asmarg.c_str()) << *argexpr << endl; if (e->components.empty()) // We have a scalar { if (e->addressof) throw semantic_error(_("cannot take address of sdt variable"), e->tok); provide (argexpr); return; } else // $var->foo { cast_op *cast = new cast_op; cast->name = "@cast"; cast->tok = e->tok; cast->operand = argexpr; cast->components = e->components; cast->type_name = probe_name + "_arg" + lex_cast(argno); cast->module = process_name; cast->visit(this); return; } /* NOTREACHED */ } catch (const semantic_error &er) { e->chain (er); provide (e); } } void sdt_uprobe_var_expanding_visitor::visit_target_symbol (target_symbol* e) { try { assert(e->name.size() > 0 && (e->name[0] == '$' || e->name == "@var")); if (e->name == "$$name" || e->name == "$$provider" || e->name == "$$parms" || e->name == "$$vars") visit_target_symbol_context (e); else visit_target_symbol_arg (e); } catch (const semantic_error &er) { e->chain (er); provide (e); } } void sdt_uprobe_var_expanding_visitor::visit_atvar_op (atvar_op* e) { need_debug_info = true; // Fill in our current module context if needed if (e->module.empty()) e->module = process_name; var_expanding_visitor::visit_atvar_op(e); } void sdt_uprobe_var_expanding_visitor::visit_cast_op (cast_op* e) { // Fill in our current module context if needed if (e->module.empty()) e->module = process_name; var_expanding_visitor::visit_cast_op(e); } void plt_expanding_visitor::visit_target_symbol (target_symbol *e) { try { if (e->name == "$$name") { literal_string *myname = new literal_string (entry); myname->tok = e->tok; provide(myname); return; } // variable not found -> throw a semantic error // (only to be caught right away, but this may be more complex later...) string alternatives = "$$name"; throw semantic_error(_F("unable to find plt variable '%s' (alternatives: %s)", e->name.c_str(), alternatives.c_str()), e->tok); } catch (const semantic_error &er) { e->chain (er); provide (e); } } struct sdt_query : public base_query { sdt_query(probe * base_probe, probe_point * base_loc, dwflpp & dw, literal_map_t const & params, vector & results, const string user_lib); void query_library (const char *data); void query_plt (const char *entry, size_t addr) {} void handle_query_module(); private: stap_sdt_probe_type probe_type; enum { probe_section=0, note_section=1, unknown_section=-1 } probe_loc; probe * base_probe; probe_point * base_loc; literal_map_t const & params; vector & results; string pp_mark; string pp_provider; string user_lib; set probes_handled; Elf_Data *pdata; size_t probe_scn_offset; size_t probe_scn_addr; uint64_t arg_count; GElf_Addr base; GElf_Addr pc; string arg_string; string probe_name; string provider_name; GElf_Addr semaphore_load_offset; Dwarf_Addr semaphore; bool init_probe_scn(); bool get_next_probe(); void iterate_over_probe_entries(); void handle_probe_entry(); static void setup_note_probe_entry_callback (void *object, int type, const char *data, size_t len); void setup_note_probe_entry (int type, const char *data, size_t len); void convert_probe(probe *base); void record_semaphore(vector & results, unsigned start); probe* convert_location(); bool have_uprobe() {return probe_type == uprobe1_type || probe_type == uprobe2_type || probe_type == uprobe3_type;} bool have_debuginfo_uprobe(bool need_debug_info) {return probe_type == uprobe1_type || ((probe_type == uprobe2_type || probe_type == uprobe3_type) && need_debug_info);} bool have_debuginfoless_uprobe() {return probe_type == uprobe2_type || probe_type == uprobe3_type;} }; sdt_query::sdt_query(probe * base_probe, probe_point * base_loc, dwflpp & dw, literal_map_t const & params, vector & results, const string user_lib): base_query(dw, params), probe_type(unknown_probe_type), probe_loc(unknown_section), base_probe(base_probe), base_loc(base_loc), params(params), results(results), user_lib(user_lib), probe_scn_offset(0), probe_scn_addr(0), arg_count(0), base(0), pc(0), semaphore_load_offset(0), semaphore(0) { assert(get_string_param(params, TOK_MARK, pp_mark)); get_string_param(params, TOK_PROVIDER, pp_provider); // pp_provider == "" -> unspecified // PR10245: permit usage of dtrace-y "-" separator in marker name; // map it to double-underscores. size_t pos = 0; while (1) // there may be more than one { size_t i = pp_mark.find("-", pos); if (i == string::npos) break; pp_mark.replace (i, 1, "__"); pos = i+1; // resume searching after the inserted __ } // XXX: same for pp_provider? } void sdt_query::handle_probe_entry() { if (! have_uprobe() && !probes_handled.insert(probe_name).second) return; if (sess.verbose > 3) { //TRANSLATORS: Describing what probe type (kprobe or uprobe) the probe //TRANSLATORS: is matched to. clog << _F("matched probe_name %s probe type ", probe_name.c_str()); switch (probe_type) { case uprobe1_type: clog << "uprobe1 at 0x" << hex << pc << dec << endl; break; case uprobe2_type: clog << "uprobe2 at 0x" << hex << pc << dec << endl; break; case uprobe3_type: clog << "uprobe3 at 0x" << hex << pc << dec << endl; break; default: clog << "unknown!" << endl; break; } } // Extend the derivation chain probe *new_base = convert_location(); probe_point *new_location = new_base->locations[0]; bool need_debug_info = false; // We could get the Elf* from either dwarf_getelf(dwfl_module_getdwarf(...)) // or dwfl_module_getelf(...). We only need it for the machine type, which // should be the same. The bias is used for relocating debuginfoless probes, // though, so that must come from the possibly-prelinked ELF file, not DWARF. Dwarf_Addr bias; Elf* elf = dwfl_module_getelf (dw.mod_info->mod, &bias); /* Figure out the architecture of this particular ELF file. The dwarfless register-name mappings depend on it. */ GElf_Ehdr ehdr_mem; GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem); if (em == 0) { dwfl_assert ("dwfl_getehdr", dwfl_errno()); } assert(em); int elf_machine = em->e_machine; sdt_uprobe_var_expanding_visitor svv (sess, elf_machine, module_val, provider_name, probe_name, probe_type, arg_string, arg_count); svv.replace (new_base->body); need_debug_info = svv.need_debug_info; // XXX: why not derive_probes() in the uprobes case too? literal_map_t params; for (unsigned i = 0; i < new_location->components.size(); ++i) { probe_point::component *c = new_location->components[i]; params[c->functor] = c->arg; } unsigned prior_results_size = results.size(); dwarf_query q(new_base, new_location, dw, params, results, "", ""); q.has_mark = true; // enables mid-statement probing // V1 probes always need dwarf info // V2+ probes need dwarf info in case of a variable reference if (have_debuginfo_uprobe(need_debug_info)) dw.iterate_over_modules(&query_module, &q); // For V2+ probes, if variable references weren't used or failed (PR14369), // then try with the more direct approach. Unresolved $vars might still // cause their own error, but this gives them a chance to be optimized out. if (have_debuginfoless_uprobe() && results.size() == prior_results_size) { string section; Dwarf_Addr reloc_addr = q.statement_num_val + bias; if (dwfl_module_relocations (q.dw.mod_info->mod) > 0) { dwfl_module_relocate_address (q.dw.mod_info->mod, &reloc_addr); section = ".dynamic"; } else section = ".absolute"; uprobe_derived_probe* p = new uprobe_derived_probe ("", "", 0, path_remove_sysroot(sess,q.module_val), section, q.statement_num_val, reloc_addr, q, 0); p->saveargs (arg_count); results.push_back (p); } sess.unwindsym_modules.insert (dw.module_name); record_semaphore(results, prior_results_size); } void sdt_query::handle_query_module() { if (!init_probe_scn()) return; if (sess.verbose > 3) clog << "TOK_MARK: " << pp_mark << " TOK_PROVIDER: " << pp_provider << endl; if (probe_loc == note_section) { GElf_Shdr shdr_mem; GElf_Shdr *shdr = dw.get_section (".stapsdt.base", &shdr_mem); // The 'base' lets us adjust the hardcoded addresses in notes for prelink // effects. The 'semaphore_load_offset' accounts for the difference in // load addresses between text and data, so the semaphore can be // converted to a file offset if needed. if (shdr) { base = shdr->sh_addr; GElf_Addr base_offset = shdr->sh_offset; shdr = dw.get_section (".probes", &shdr_mem); if (shdr) semaphore_load_offset = (shdr->sh_addr - shdr->sh_offset) - (base - base_offset); } else base = semaphore_load_offset = 0; dw.iterate_over_notes ((void*) this, &sdt_query::setup_note_probe_entry_callback); } else if (probe_loc == probe_section) iterate_over_probe_entries (); } bool sdt_query::init_probe_scn() { Elf* elf; GElf_Shdr shdr_mem; GElf_Shdr *shdr = dw.get_section (".note.stapsdt", &shdr_mem); if (shdr) { probe_loc = note_section; return true; } shdr = dw.get_section (".probes", &shdr_mem, &elf); if (shdr) { pdata = elf_getdata_rawchunk (elf, shdr->sh_offset, shdr->sh_size, ELF_T_BYTE); probe_scn_offset = 0; probe_scn_addr = shdr->sh_addr; assert (pdata != NULL); if (sess.verbose > 4) clog << "got .probes elf scn_addr@0x" << probe_scn_addr << ", size: " << pdata->d_size << endl; probe_loc = probe_section; return true; } else return false; } void sdt_query::setup_note_probe_entry_callback (void *object, int type, const char *data, size_t len) { sdt_query *me = (sdt_query*)object; me->setup_note_probe_entry (type, data, len); } void sdt_query::setup_note_probe_entry (int type, const char *data, size_t len) { // if (nhdr.n_namesz == sizeof _SDT_NOTE_NAME // && !memcmp (data->d_buf + name_off, // _SDT_NOTE_NAME, sizeof _SDT_NOTE_NAME)) // probes are in the .note.stapsdt section #define _SDT_NOTE_TYPE 3 if (type != _SDT_NOTE_TYPE) return; union { Elf64_Addr a64[3]; Elf32_Addr a32[3]; } buf; Dwarf_Addr bias; Elf* elf = (dwfl_module_getelf (dw.mod_info->mod, &bias)); Elf_Data dst = { &buf, ELF_T_ADDR, EV_CURRENT, gelf_fsize (elf, ELF_T_ADDR, 3, EV_CURRENT), 0, 0 }; assert (dst.d_size <= sizeof buf); if (len < dst.d_size + 3) return; Elf_Data src = { (void *) data, ELF_T_ADDR, EV_CURRENT, dst.d_size, 0, 0 }; if (gelf_xlatetom (elf, &dst, &src, elf_getident (elf, NULL)[EI_DATA]) == NULL) printf ("gelf_xlatetom: %s", elf_errmsg (-1)); probe_type = uprobe3_type; const char * provider = data + dst.d_size; const char *name = (const char*)memchr (provider, '\0', data + len - provider); if(name++ == NULL) return; const char *args = (const char*)memchr (name, '\0', data + len - name); if (args++ == NULL || memchr (args, '\0', data + len - name) != data + len - 1) return; provider_name = provider; probe_name = name; arg_string = args; // Did we find a matching probe? if (! (dw.function_name_matches_pattern (probe_name, pp_mark) && ((pp_provider == "") || dw.function_name_matches_pattern (provider_name, pp_provider)))) return; // PR13934: Assembly probes are not forced to use the N@OP form. // If we have '@' then great, else count based on space-delimiters. arg_count = count(arg_string.begin(), arg_string.end(), '@'); if (!arg_count && !arg_string.empty()) arg_count = 1 + count(arg_string.begin(), arg_string.end(), ' '); GElf_Addr base_ref; if (gelf_getclass (elf) == ELFCLASS32) { pc = buf.a32[0]; base_ref = buf.a32[1]; semaphore = buf.a32[2]; } else { pc = buf.a64[0]; base_ref = buf.a64[1]; semaphore = buf.a64[2]; } semaphore += base - base_ref; pc += base - base_ref; // The semaphore also needs the ELF bias added now, so // record_semaphore can properly relocate it later. semaphore += bias; if (sess.verbose > 4) clog << _F(" saw .note.stapsdt %s%s ", probe_name.c_str(), (provider_name != "" ? _(" (provider ")+provider_name+") " : "").c_str()) << "@0x" << hex << pc << dec << endl; handle_probe_entry(); } void sdt_query::iterate_over_probe_entries() { // probes are in the .probe section while (probe_scn_offset < pdata->d_size) { stap_sdt_probe_entry_v1 *pbe_v1 = (stap_sdt_probe_entry_v1 *) ((char*)pdata->d_buf + probe_scn_offset); stap_sdt_probe_entry_v2 *pbe_v2 = (stap_sdt_probe_entry_v2 *) ((char*)pdata->d_buf + probe_scn_offset); probe_type = (stap_sdt_probe_type)(pbe_v1->type_a); if (! have_uprobe()) { // Unless this is a mangled .probes section, this happens // because the name of the probe comes first, followed by // the sentinel. if (sess.verbose > 5) clog << _F("got unknown probe_type : 0x%x", probe_type) << endl; probe_scn_offset += sizeof(__uint32_t); continue; } if ((long)pbe_v1 % sizeof(__uint64_t)) // we have stap_sdt_probe_entry_v1.type_b { pbe_v1 = (stap_sdt_probe_entry_v1*)((char*)pbe_v1 - sizeof(__uint32_t)); if (pbe_v1->type_b != uprobe1_type) continue; } if (probe_type == uprobe1_type) { if (pbe_v1->name == 0) // No name possibly means we have a .so with a relocation return; semaphore = 0; probe_name = (char*)((char*)pdata->d_buf + pbe_v1->name - (char*)probe_scn_addr); provider_name = ""; // unknown pc = pbe_v1->arg; arg_count = 0; probe_scn_offset += sizeof (stap_sdt_probe_entry_v1); } else if (probe_type == uprobe2_type) { if (pbe_v2->name == 0) // No name possibly means we have a .so with a relocation return; semaphore = pbe_v2->semaphore; probe_name = (char*)((char*)pdata->d_buf + pbe_v2->name - (char*)probe_scn_addr); provider_name = (char*)((char*)pdata->d_buf + pbe_v2->provider - (char*)probe_scn_addr); arg_count = pbe_v2->arg_count; pc = pbe_v2->pc; if (pbe_v2->arg_string) arg_string = (char*)((char*)pdata->d_buf + pbe_v2->arg_string - (char*)probe_scn_addr); // skip over pbe_v2, probe_name text and provider text probe_scn_offset = ((long)(pbe_v2->name) - (long)(probe_scn_addr)) + probe_name.length(); probe_scn_offset += sizeof (__uint32_t) - probe_scn_offset % sizeof (__uint32_t); } if (sess.verbose > 4) clog << _("saw .probes ") << probe_name << (provider_name != "" ? _(" (provider ")+provider_name+") " : "") << "@0x" << hex << pc << dec << endl; if (dw.function_name_matches_pattern (probe_name, pp_mark) && ((pp_provider == "") || dw.function_name_matches_pattern (provider_name, pp_provider))) handle_probe_entry (); } } void sdt_query::record_semaphore (vector & results, unsigned start) { for (unsigned i=0; i<2; i++) { // prefer with-provider symbol; look without provider prefix for backward compatibility only string semaphore = (i==0 ? (provider_name+"_") : "") + probe_name + "_semaphore"; // XXX: multiple addresses? if (sess.verbose > 2) clog << _F("looking for semaphore symbol %s ", semaphore.c_str()); Dwarf_Addr addr; if (this->semaphore) addr = this->semaphore; else addr = lookup_symbol_address(dw.module, semaphore.c_str()); if (addr) { if (dwfl_module_relocations (dw.module) > 0) dwfl_module_relocate_address (dw.module, &addr); // XXX: relocation basis? // Dyninst needs the *file*-based offset for semaphores, // so subtract the difference in load addresses between .text and .probes if (dw.sess.runtime_usermode_p()) addr -= semaphore_load_offset; for (unsigned i = start; i < results.size(); ++i) results[i]->sdt_semaphore_addr = addr; if (sess.verbose > 2) clog << _(", found at 0x") << hex << addr << dec << endl; return; } else if (sess.verbose > 2) clog << _(", not found") << endl; } } void sdt_query::convert_probe (probe *base) { block *b = new block; b->tok = base->body->tok; // Generate: if (arg1 != mark("label")) next; functioncall *fc = new functioncall; fc->function = "ulong_arg"; fc->tok = b->tok; literal_number* num = new literal_number(1); num->tok = b->tok; fc->args.push_back(num); functioncall *fcus = new functioncall; fcus->function = "user_string"; fcus->type = pe_string; fcus->tok = b->tok; fcus->args.push_back(fc); if_statement *is = new if_statement; is->thenblock = new next_statement; is->elseblock = NULL; is->tok = b->tok; is->thenblock->tok = b->tok; comparison *be = new comparison; be->op = "!="; be->tok = b->tok; be->left = fcus; be->right = new literal_string(probe_name); be->right->tok = b->tok; is->condition = be; b->statements.push_back(is); // Now replace the body b->statements.push_back(base->body); base->body = b; } probe* sdt_query::convert_location () { probe_point* specific_loc = new probe_point(*base_loc); vector derived_comps; vector::iterator it; for (it = specific_loc->components.begin(); it != specific_loc->components.end(); ++it) if ((*it)->functor == TOK_PROCESS) { // copy the process name derived_comps.push_back(*it); } else if ((*it)->functor == TOK_LIBRARY) { // copy the library name for process probes derived_comps.push_back(*it); } else if ((*it)->functor == TOK_PROVIDER) { // replace the possibly wildcarded arg with the specific provider name *it = new probe_point::component(TOK_PROVIDER, new literal_string(provider_name)); } else if ((*it)->functor == TOK_MARK) { // replace the possibly wildcarded arg with the specific marker name *it = new probe_point::component(TOK_MARK, new literal_string(probe_name)); if (sess.verbose > 3) switch (probe_type) { case uprobe1_type: clog << _("probe_type == uprobe1, use statement addr: 0x") << hex << pc << dec << endl; break; case uprobe2_type: clog << _("probe_type == uprobe2, use statement addr: 0x") << hex << pc << dec << endl; break; case uprobe3_type: clog << _("probe_type == uprobe3, use statement addr: 0x") << hex << pc << dec << endl; break; default: clog << _F("probe_type == use_uprobe_no_dwarf, use label name: _stapprobe1_%s", pp_mark.c_str()) << endl; } switch (probe_type) { case uprobe1_type: case uprobe2_type: case uprobe3_type: // process("executable").statement(probe_arg) derived_comps.push_back (new probe_point::component(TOK_STATEMENT, new literal_number(pc, true))); break; default: // deprecated // process("executable").function("*").label("_stapprobe1_MARK_NAME") derived_comps.push_back (new probe_point::component(TOK_FUNCTION, new literal_string("*"))); derived_comps.push_back (new probe_point::component(TOK_LABEL, new literal_string("_stapprobe1_" + pp_mark))); break; } } probe_point* derived_loc = new probe_point(*specific_loc); derived_loc->components = derived_comps; return new probe (new probe (base_probe, specific_loc), derived_loc); } void sdt_query::query_library (const char *library) { query_one_library (library, dw, user_lib, base_probe, base_loc, results); } string dwarf_builder::suggest_functions(systemtap_session& sess, string func) { // Trim any @ component size_t pos = func.find('@'); if (pos != string::npos) func.erase(pos); if (func.empty() || modules_seen.empty() || sess.module_cache == NULL) return ""; // We must first aggregate all the functions from the cache set funcs; const map &cache = sess.module_cache->cache; for (set::iterator itmod = modules_seen.begin(); itmod != modules_seen.end(); ++itmod) { map::const_iterator itcache; if ((itcache = cache.find(*itmod)) != cache.end()) funcs.insert(itcache->second->sym_seen.begin(), itcache->second->sym_seen.end()); } if (sess.verbose > 2) clog << "suggesting from " << funcs.size() << " functions" << endl; if (funcs.empty()) return ""; // Calculate Levenshtein distance for each symbol // Sensitivity parameters (open for tweaking) #define MAXFUNCS 5 // maximum number of funcs to suggest multimap scores; for (set::iterator it=funcs.begin(); it!=funcs.end(); ++it) { unsigned score = levenshtein(func, *it); scores.insert(make_pair(score, *it)); } // Print out the top MAXFUNCS funcs string suggestions; unsigned i = 0; for (multimap::iterator it = scores.begin(); it != scores.end() && i < MAXFUNCS; ++it, i++) suggestions += it->second + ", "; if (!suggestions.empty()) suggestions.erase(suggestions.size()-2); return suggestions; } void dwarf_builder::build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results) { // NB: the kernel/user dwlfpp objects are long-lived. // XXX: but they should be per-session, as this builder object // may be reused if we try to cross-instrument multiple targets. dwflpp* dw = 0; literal_map_t filled_parameters = parameters; string module_name; if (has_null_param (parameters, TOK_KERNEL)) { dw = get_kern_dw(sess, "kernel"); } else if (get_param (parameters, TOK_MODULE, module_name)) { size_t dash_pos = 0; while((dash_pos=module_name.find('-'))!=string::npos) module_name.replace(int(dash_pos),1,"_"); filled_parameters[TOK_MODULE] = new literal_string(module_name); // NB: glob patterns get expanded later, during the offline // elfutils module listing. dw = get_kern_dw(sess, module_name); } else if (get_param (parameters, TOK_PROCESS, module_name) || has_null_param(parameters, TOK_PROCESS)) { module_name = sess.sysroot + module_name; if(has_null_param(filled_parameters, TOK_PROCESS)) { wordexp_t words; int rc = wordexp(sess.cmd.c_str(), &words, WRDE_NOCMD|WRDE_UNDEF); if(rc || words.we_wordc <= 0) throw semantic_error(_("unspecified process probe is invalid without a -c COMMAND")); module_name = sess.sysroot + words.we_wordv[0]; filled_parameters[TOK_PROCESS] = new literal_string(module_name);// this needs to be used in place of the blank map // in the case of TOK_MARK we need to modify locations as well if(location->components[0]->functor==TOK_PROCESS && location->components[0]->arg == 0) location->components[0]->arg = new literal_string(module_name); wordfree (& words); } // PR6456 process("/bin/*") glob handling if (contains_glob_chars (module_name)) { // Expand glob via rewriting the probe-point process("....") // parameter, asserted to be the first one. assert (location->components.size() > 0); assert (location->components[0]->functor == TOK_PROCESS); assert (location->components[0]->arg); literal_string* lit = dynamic_cast(location->components[0]->arg); assert (lit); // Evaluate glob here, and call derive_probes recursively with each match. glob_t the_blob; int rc = glob (module_name.c_str(), 0, NULL, & the_blob); if (rc) throw semantic_error (_F("glob %s error (%s)", module_name.c_str(), lex_cast(rc).c_str() )); unsigned results_pre = finished_results.size(); for (unsigned i = 0; i < the_blob.gl_pathc; ++i) { assert_no_interrupts(); const char* globbed = the_blob.gl_pathv[i]; struct stat st; if (access (globbed, X_OK) == 0 && stat (globbed, &st) == 0 && S_ISREG (st.st_mode)) // see find_executable() { // Need to call canonicalize here, in order to path-expand // patterns like process("stap*"). Otherwise it may go through // to the next round of expansion as ("stap"), leading to a $PATH // search that's not consistent with the glob search already done. char *cf = canonicalize_file_name (globbed); if (cf) globbed = cf; // synthesize a new probe_point, with the glob-expanded string probe_point *pp = new probe_point (*location); // PR13338: quote results to prevent recursion string eglobbed = escape_glob_chars (globbed); if (sess.verbose > 1) clog << _F("Expanded process(\"%s\") to process(\"%s\")", module_name.c_str(), eglobbed.c_str()) << endl; string eglobbed_tgt = path_remove_sysroot(sess, eglobbed); probe_point::component* ppc = new probe_point::component (TOK_PROCESS, new literal_string (eglobbed_tgt)); ppc->tok = location->components[0]->tok; // overwrite [0] slot, pattern matched above pp->components[0] = ppc; probe* new_probe = new probe (base, pp); // We override "optional = true" here, as if the // wildcarded probe point was given a "?" suffix. // This is because wildcard probes will be expected // by users to apply only to some subset of the // matching binaries, in the sense of "any", rather // than "all", sort of similarly how // module("*").function("...") patterns work. derive_probes (sess, new_probe, finished_results, true /* NB: not location->optional */ ); } } globfree (& the_blob); unsigned results_post = finished_results.size(); // Did we fail to find a function by name? Let's suggest // something! string func; if (results_pre == results_post && get_param(filled_parameters, TOK_FUNCTION, func) && !func.empty()) { if (sess.verbose > 2) { clog << "suggesting functions from modules:" << endl; for (set::const_iterator it = modules_seen.begin(); it != modules_seen.end(); ++it) { clog << *it << endl; } } string sugs = suggest_functions(sess, func); modules_seen.clear(); if (!sugs.empty()) throw semantic_error (_NF("no match (similar function: %s)", "no match (similar functions: %s)", sugs.find(',') == string::npos, sugs.c_str())); } return; // avoid falling through } // PR13338: unquote glob results module_name = unescape_glob_chars (module_name); user_path = find_executable (module_name, "", sess.sysenv); // canonicalize it // if the executable starts with "#!", we look for the interpreter of the script { ifstream script_file (user_path.c_str () ); if (script_file.good ()) { string line; getline (script_file, line); if (line.compare (0, 2, "#!") == 0) { string path_head = line.substr(2); // remove white spaces at the beginning of the string size_t p2 = path_head.find_first_not_of(" \t"); if (p2 != string::npos) { string path = path_head.substr(p2); // remove white spaces at the end of the string p2 = path.find_last_not_of(" \t\n"); if (string::npos != p2) path.erase(p2+1); // handle "#!/usr/bin/env" redirect size_t offset = 0; if (path.compare(0, sizeof("/bin/env")-1, "/bin/env") == 0) { offset = sizeof("/bin/env")-1; } else if (path.compare(0, sizeof("/usr/bin/env")-1, "/usr/bin/env") == 0) { offset = sizeof("/usr/bin/env")-1; } if (offset != 0) { size_t p3 = path.find_first_not_of(" \t", offset); if (p3 != string::npos) { string env_path = path.substr(p3); user_path = find_executable (env_path, sess.sysroot, sess.sysenv); } } else { user_path = find_executable (path, sess.sysroot, sess.sysenv); } struct stat st; if (access (user_path.c_str(), X_OK) == 0 && stat (user_path.c_str(), &st) == 0 && S_ISREG (st.st_mode)) // see find_executable() { if (sess.verbose > 1) clog << _F("Expanded process(\"%s\") to process(\"%s\")", module_name.c_str(), user_path.c_str()) << endl; assert (location->components.size() > 0); assert (location->components[0]->functor == TOK_PROCESS); assert (location->components[0]->arg); literal_string* lit = dynamic_cast(location->components[0]->arg); assert (lit); // synthesize a new probe_point, with the expanded string probe_point *pp = new probe_point (*location); string user_path_tgt = path_remove_sysroot(sess, user_path); probe_point::component* ppc = new probe_point::component (TOK_PROCESS, new literal_string (user_path_tgt.c_str())); ppc->tok = location->components[0]->tok; // overwrite [0] slot, pattern matched above pp->components[0] = ppc; probe* new_probe = new probe (base, pp); derive_probes (sess, new_probe, finished_results); script_file.close(); return; } } } } script_file.close(); } if (get_param (parameters, TOK_LIBRARY, user_lib) && user_lib.length() && ! contains_glob_chars (user_lib)) { module_name = find_executable (user_lib, sess.sysroot, sess.sysenv, "LD_LIBRARY_PATH"); if (module_name.find('/') == string::npos) // We didn't find user_lib so use iterate_over_libraries module_name = user_path; } else module_name = user_path; // canonicalize it // uretprobes aren't available everywhere if (has_null_param(parameters, TOK_RETURN) && !sess.runtime_usermode_p()) { if (kernel_supports_inode_uprobes(sess) && !kernel_supports_inode_uretprobes(sess)) throw semantic_error (_("process return probes not available [man error::inode-uprobes]")); } // There is a similar check in pass 4 (buildrun), but it is // needed here too to make sure alternatives for optional // (? or !) process probes are disposed and/or alternatives // are selected. if (!sess.runtime_usermode_p()) check_process_probe_kernel_support(sess); // user-space target; we use one dwflpp instance per module name // (= program or shared library) dw = get_user_dw(sess, module_name); } if (sess.verbose > 3) clog << _F("dwarf_builder::build for %s", module_name.c_str()) << endl; string dummy_mark_name; // NB: PR10245: dummy value, need not substitute - => __ if (get_param(parameters, TOK_MARK, dummy_mark_name)) { assert(dw); sdt_query sdtq(base, location, *dw, filled_parameters, finished_results, user_lib); dw->iterate_over_modules(&query_module, &sdtq); return; } unsigned results_pre = finished_results.size(); dwarf_query q(base, location, *dw, filled_parameters, finished_results, user_path, user_lib); // XXX: kernel.statement.absolute is a special case that requires no // dwfl processing. This code should be in a separate builder. if (q.has_kernel && q.has_absolute) { // assert guru mode for absolute probes if (! q.base_probe->privileged) { throw semantic_error (_("absolute statement probe in unprivileged script; need stap -g"), q.base_probe->tok); } // For kernel.statement(NUM).absolute probe points, we bypass // all the debuginfo stuff: We just wire up a // dwarf_derived_probe right here and now. dwarf_derived_probe* p = new dwarf_derived_probe ("", "", 0, "kernel", "", q.statement_num_val, q.statement_num_val, q, 0); finished_results.push_back (p); sess.unwindsym_modules.insert ("kernel"); return; } dw->iterate_over_modules(&query_module, &q); // We need to update modules_seen with the modules we've visited modules_seen.insert(q.visited_modules.begin(), q.visited_modules.end()); // PR11553 special processing: .return probes requested, but // some inlined function instances matched. unsigned i_n_r = q.inlined_non_returnable.size(); unsigned results_post = finished_results.size(); if (i_n_r > 0) { if ((results_pre == results_post) && (! sess.suppress_warnings)) // no matches; issue warning { string quicklist; for (set::iterator it = q.inlined_non_returnable.begin(); it != q.inlined_non_returnable.end(); it++) { quicklist += " " + (*it); if (quicklist.size() > 80) // heuristic, don't make an overlong report line { quicklist += " ..."; break; } } sess.print_warning (_NF("cannot probe .return of %u inlined function %s", "cannot probe .return of %u inlined functions %s", quicklist.size(), i_n_r, quicklist.c_str())); // There will be also a "no matches" semantic error generated. } if (sess.verbose > 1) clog << _NF("skipped .return probe of %u inlined function", "skipped .return probe of %u inlined functions", i_n_r, i_n_r) << endl; if ((sess.verbose > 3) || (sess.verbose > 2 && results_pre == results_post)) // issue details with high verbosity { for (set::iterator it = q.inlined_non_returnable.begin(); it != q.inlined_non_returnable.end(); it++) clog << (*it) << " "; clog << endl; } } // i_n_r > 0 // Did we fail to find a function by name? Let's suggest something! We // need to check for optional because otherwise, we will be suggesting // things during intermediate results without including all the // possible functions. For example, process("/usr/bin/*").function // will go through here for each executable found (all labelled as // optionals). Similarly for library(glob) probes. TODO: find a // mechanism to have suggestions for optional probes as well when no // probes could be derived, e.g. probepoint1?, probepoint2 should // suggest for both 1 and 2 if both fail to resolve (maybe print as a // warning?). This may entails detecting the difference between script // optional probes and probes that are optional in recursive calls. string func; if (results_pre == results_post && !location->optional && get_param(filled_parameters, TOK_FUNCTION, func) && !func.empty()) { if (sess.verbose > 2) { clog << "suggesting functions from modules:" << endl; for (set::const_iterator it = modules_seen.begin(); it != modules_seen.end(); ++it) clog << *it << endl; } string sugs = suggest_functions(sess, func); modules_seen.clear(); if (!sugs.empty()) // Note that this error will not even be printed out if it is // exactly the same suggestion as a previous throw (since // print_error() filters out identical errors). Which makes // sense since it's possible that the user misspelled the same // function in different probes, in which case the first // suggestion is sufficient. throw semantic_error (_NF("no match (similar function: %s)", "no match (similar functions: %s)", sugs.find(',') == string::npos, sugs.c_str())); } else if (results_pre != results_post) // Something was derived so we won't need to suggest something modules_seen.clear(); } symbol_table::~symbol_table() { delete_map(map_by_addr); } void symbol_table::add_symbol(const char *name, bool weak, bool descriptor, Dwarf_Addr addr, Dwarf_Addr* /*high_addr*/) { #ifdef __powerpc__ // Map ".sys_foo" to "sys_foo". if (name[0] == '.') name++; #endif func_info *fi = new func_info(); fi->addr = addr; fi->name = name; fi->weak = weak; fi->descriptor = descriptor; map_by_name[fi->name] = fi; // TODO: Use a multimap in case there are multiple static // functions with the same name? map_by_addr.insert(make_pair(addr, fi)); } enum info_status symbol_table::read_symbols(FILE *f, const string& path) { // Based on do_kernel_symbols() in runtime/staprun/symbols.c int ret; char *name = 0; char *mod = 0; char type; unsigned long long addr; Dwarf_Addr high_addr = 0; int line = 0; #if __GLIBC__ >2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7) #define MS_FMT "%ms" #else #define MS_FMT "%as" #endif // %ms (newer than %as) mallocs space for the string and stores its address. while ((ret = fscanf(f, "%llx %c " MS_FMT " [" MS_FMT, &addr, &type, &name, &mod)) > 0) { auto_free free_name(name); auto_free free_mod(mod); line++; if (ret < 3) { cerr << _F("Symbol table error: Line %d of symbol list from %s is not in correct format: address type name [module]\n", line, path.c_str()); // Caller should delete symbol_table object. return info_absent; } else if (ret > 3) { // Modules are loaded above the kernel, so if we're getting // modules, we're done. break; } if (type == 'T' || type == 't' || type == 'W') add_symbol(name, (type == 'W'), false, (Dwarf_Addr) addr, &high_addr); } if (map_by_addr.size() < 1) { cerr << _F("Symbol table error: %s contains no function symbols.\n", path.c_str()) << endl; return info_absent; } return info_present; } // NB: This currently unused. We use get_from_elf() instead because // that gives us raw addresses -- which we need for modules -- whereas // nm provides the address relative to the beginning of the section. enum info_status symbol_table::read_from_elf_file(const string &path, systemtap_session &sess) { vector cmd; cmd.push_back("/usr/bin/nm"); cmd.push_back("-n"); cmd.push_back("--defined-only"); cmd.push_back("path"); FILE *f; int child_fd; pid_t child = stap_spawn_piped(sess.verbose, cmd, NULL, &child_fd); if (child <= 0 || !(f = fdopen(child_fd, "r"))) { // nm failures are detected by stap_waitpid cerr << _F("Internal error reading symbol table from %s -- %s\n", path.c_str(), strerror(errno)); return info_absent; } enum info_status status = read_symbols(f, path); if (fclose(f) || stap_waitpid(sess.verbose, child)) { if (status == info_present) sess.print_warning("nm cannot read symbol table from " + path); return info_absent; } return status; } enum info_status symbol_table::read_from_text_file(const string& path, systemtap_session &sess) { FILE *f = fopen(path.c_str(), "r"); if (!f) { sess.print_warning("cannot read symbol table from " + path + " -- " + strerror(errno)); return info_absent; } enum info_status status = read_symbols(f, path); (void) fclose(f); return status; } void symbol_table::prepare_section_rejection(Dwfl_Module *mod __attribute__ ((unused))) { #ifdef __powerpc__ /* * The .opd section contains function descriptors that can look * just like function entry points. For example, there's a function * descriptor called "do_exit" that links to the entry point ".do_exit". * Reject all symbols in .opd. */ opd_section = SHN_UNDEF; Dwarf_Addr bias; Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (mod, &bias)) ?: dwfl_module_getelf (mod, &bias)); Elf_Scn* scn = 0; size_t shstrndx; if (!elf) return; if (elf_getshdrstrndx (elf, &shstrndx) != 0) return; while ((scn = elf_nextscn(elf, scn)) != NULL) { GElf_Shdr shdr_mem; GElf_Shdr *shdr = gelf_getshdr(scn, &shdr_mem); if (!shdr) continue; const char *name = elf_strptr(elf, shstrndx, shdr->sh_name); if (!strcmp(name, ".opd")) { opd_section = elf_ndxscn(scn); return; } } #endif } bool symbol_table::reject_section(GElf_Word section) { if (section == SHN_UNDEF) return true; #ifdef __powerpc__ if (section == opd_section) return true; #endif return false; } enum info_status symbol_table::get_from_elf() { Dwarf_Addr high_addr = 0; Dwfl_Module *mod = mod_info->mod; int syments = dwfl_module_getsymtab(mod); assert(syments); prepare_section_rejection(mod); for (int i = 1; i < syments; ++i) { GElf_Sym sym; GElf_Word section; const char *name = dwfl_module_getsym(mod, i, &sym, §ion); if (name && GELF_ST_TYPE(sym.st_info) == STT_FUNC) add_symbol(name, (GELF_ST_BIND(sym.st_info) == STB_WEAK), reject_section(section), sym.st_value, &high_addr); } return info_present; } func_info * symbol_table::get_func_containing_address(Dwarf_Addr addr) { iterator_t iter = map_by_addr.upper_bound(addr); if (iter == map_by_addr.begin()) return NULL; else return (--iter)->second; } func_info * symbol_table::get_first_func() { iterator_t iter = map_by_addr.begin(); return (iter)->second; } func_info * symbol_table::lookup_symbol(const string& name) { map::iterator i = map_by_name.find(name); if (i == map_by_name.end()) return NULL; return i->second; } Dwarf_Addr symbol_table::lookup_symbol_address(const string& name) { func_info *fi = lookup_symbol(name); if (fi) return fi->addr; return 0; } // This is the kernel symbol table. The kernel macro cond_syscall creates // a weak symbol for each system call and maps it to sys_ni_syscall. // For system calls not implemented elsewhere, this weak symbol shows up // in the kernel symbol table. Following the precedent of dwarfful stap, // we refuse to consider such symbols. Here we delete them from our // symbol table. // TODO: Consider generalizing this and/or making it part of blacklist // processing. void symbol_table::purge_syscall_stubs() { Dwarf_Addr stub_addr = lookup_symbol_address("sys_ni_syscall"); if (stub_addr == 0) return; range_t purge_range = map_by_addr.equal_range(stub_addr); for (iterator_t iter = purge_range.first; iter != purge_range.second; ) { func_info *fi = iter->second; if (fi->weak && fi->name != "sys_ni_syscall") { map_by_name.erase(fi->name); map_by_addr.erase(iter++); delete fi; } else iter++; } } void module_info::get_symtab(dwarf_query *q) { if (symtab_status != info_unknown) return; sym_table = new symbol_table(this); if (!elf_path.empty()) { symtab_status = sym_table->get_from_elf(); } else { assert(name == TOK_KERNEL); symtab_status = info_absent; cerr << _("Error: Cannot find vmlinux.") << endl;; } if (symtab_status == info_absent) { delete sym_table; sym_table = NULL; return; } if (name == TOK_KERNEL) sym_table->purge_syscall_stubs(); } // update_symtab reconciles data between the elf symbol table and the dwarf // function enumeration. It updates the symbol table entries with the dwarf // die that describes the function, which also signals to query_module_symtab // that a statement probe isn't needed. In return, it also adds aliases to the // function table for names that share the same addr/die. void module_info::update_symtab(cu_function_cache_t *funcs) { if (!sym_table) return; cu_function_cache_t new_funcs; for (cu_function_cache_t::iterator func = funcs->begin(); func != funcs->end(); func++) { sym_seen.insert(func->first); // optimization: inlines will never be in the symbol table if (dwarf_func_inline(&func->second) != 0) continue; // XXX We may want to make additional efforts to match mangled elf names // to dwarf too. MIPS_linkage_name can help, but that's sometimes // missing, so we may also need to try matching by address. See also the // notes about _Z in dwflpp::iterate_over_functions(). func_info *fi = sym_table->lookup_symbol(func->first); if (!fi) continue; // iterate over all functions at the same address symbol_table::range_t er = sym_table->map_by_addr.equal_range(fi->addr); for (symbol_table::iterator_t it = er.first; it != er.second; ++it) { // update this function with the dwarf die it->second->die = func->second; // if this function is a new alias, then // save it to merge into the function cache if (it->second != fi) new_funcs.insert(make_pair(it->second->name, it->second->die)); } } // add all discovered aliases back into the function cache // NB: this won't replace any names that dwarf may have already found funcs->insert(new_funcs.begin(), new_funcs.end()); } module_info::~module_info() { if (sym_table) delete sym_table; } // ------------------------------------------------------------------------ // user-space probes // ------------------------------------------------------------------------ struct uprobe_derived_probe_group: public generic_dpg { private: string make_pbm_key (uprobe_derived_probe* p) { return p->path + "|" + p->module + "|" + p->section + "|" + lex_cast(p->pid); } void emit_module_maxuprobes (systemtap_session& s); // Using our own utrace-based uprobes void emit_module_utrace_decls (systemtap_session& s); void emit_module_utrace_init (systemtap_session& s); void emit_module_utrace_exit (systemtap_session& s); // Using the upstream inode-based uprobes void emit_module_inode_decls (systemtap_session& s); void emit_module_inode_init (systemtap_session& s); void emit_module_inode_exit (systemtap_session& s); // Using the dyninst backend (via stapdyn) void emit_module_dyninst_decls (systemtap_session& s); void emit_module_dyninst_init (systemtap_session& s); void emit_module_dyninst_exit (systemtap_session& s); public: void emit_module_decls (systemtap_session& s); void emit_module_init (systemtap_session& s); void emit_module_exit (systemtap_session& s); }; void uprobe_derived_probe::join_group (systemtap_session& s) { if (! s.uprobe_derived_probes) s.uprobe_derived_probes = new uprobe_derived_probe_group (); s.uprobe_derived_probes->enroll (this); if (s.runtime_usermode_p()) enable_dynprobes(s); else enable_task_finder(s); // Ask buildrun.cxx to build extra module if needed, and // signal staprun to load that module. If we're using the builtin // inode-uprobes, we still need to know that it is required. s.need_uprobes = true; } void uprobe_derived_probe::getargs(std::list &arg_set) const { dwarf_derived_probe::getargs(arg_set); arg_set.insert(arg_set.end(), args.begin(), args.end()); } void uprobe_derived_probe::saveargs(int nargs) { for (int i = 1; i <= nargs; i++) args.push_back("$arg" + lex_cast (i) + ":long"); } void uprobe_derived_probe::emit_privilege_assertion (translator_output* o) { // These probes are allowed for unprivileged users, but only in the // context of processes which they own. emit_process_owner_assertion (o); } struct uprobe_builder: public derived_probe_builder { uprobe_builder() {} virtual void build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results) { int64_t process, address; if (kernel_supports_inode_uprobes(sess)) throw semantic_error (_("absolute process probes not available [man error::inode-uprobes]")); bool b1 = get_param (parameters, TOK_PROCESS, process); (void) b1; bool b2 = get_param (parameters, TOK_STATEMENT, address); (void) b2; bool rr = has_null_param (parameters, TOK_RETURN); assert (b1 && b2); // by pattern_root construction finished_results.push_back(new uprobe_derived_probe(base, location, process, address, rr)); } }; void uprobe_derived_probe_group::emit_module_maxuprobes (systemtap_session& s) { // We'll probably need at least this many: unsigned minuprobes = probes.size(); // .. but we don't want so many that .bss is inflated (PR10507): unsigned uprobesize = 64; unsigned maxuprobesmem = 10*1024*1024; // 10 MB unsigned maxuprobes = maxuprobesmem / uprobesize; // Let's choose a value on the geometric middle. This should end up // between minuprobes and maxuprobes. It's OK if this number turns // out to be < minuprobes or > maxuprobes. At worst, we get a // run-time error of one kind (too few: missed uprobe registrations) // or another (too many: vmalloc errors at module load time). unsigned default_maxuprobes = (unsigned)sqrt((double)minuprobes * (double)maxuprobes); s.op->newline() << "#ifndef MAXUPROBES"; s.op->newline() << "#define MAXUPROBES " << default_maxuprobes; s.op->newline() << "#endif"; } void uprobe_derived_probe_group::emit_module_utrace_decls (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "/* ---- utrace uprobes ---- */"; // If uprobes isn't in the kernel, pull it in from the runtime. s.op->newline() << "#if defined(CONFIG_UPROBES) || defined(CONFIG_UPROBES_MODULE)"; s.op->newline() << "#include "; s.op->newline() << "#else"; s.op->newline() << "#include \"linux/uprobes/uprobes.h\""; s.op->newline() << "#endif"; s.op->newline() << "#ifndef UPROBES_API_VERSION"; s.op->newline() << "#define UPROBES_API_VERSION 1"; s.op->newline() << "#endif"; emit_module_maxuprobes (s); // Forward decls s.op->newline() << "#include \"linux/uprobes-common.h\""; // In .bss, the shared pool of uprobe/uretprobe structs. These are // too big to embed in the initialized .data stap_uprobe_spec array. // XXX: consider a slab cache or somesuch for stap_uprobes s.op->newline() << "static struct stap_uprobe stap_uprobes [MAXUPROBES];"; s.op->newline() << "static DEFINE_MUTEX(stap_uprobes_lock);"; // protects against concurrent registration/unregistration s.op->assert_0_indent(); // Assign task-finder numbers as we build up the stap_uprobe_tf table. // This means we process probes[] in two passes. map module_index; unsigned module_index_ctr = 0; // not const since embedded task_finder_target struct changes s.op->newline() << "static struct stap_uprobe_tf stap_uprobe_finders[] = {"; s.op->indent(1); for (unsigned i=0; inewline() << "{"; // NB: it's essential that make_pbm_key() use all of and // only the same fields as we're about to emit. s.op->line() << " .finder={"; s.op->line() << " .purpose=\"uprobes\","; if (p->pid != 0) s.op->line() << " .pid=" << p->pid << ","; if (p->section == "") // .statement(addr).absolute s.op->line() << " .callback=&stap_uprobe_process_found,"; else if (p->section == ".absolute") // proxy for ET_EXEC -> exec()'d program { s.op->line() << " .procname=" << lex_cast_qstring(p->module) << ","; s.op->line() << " .callback=&stap_uprobe_process_found,"; } else if (p->section != ".absolute") // ET_DYN { if (p->has_library) s.op->line() << " .procname=\"" << p->path << "\", "; s.op->line() << " .mmap_callback=&stap_uprobe_mmap_found, "; s.op->line() << " .munmap_callback=&stap_uprobe_munmap_found, "; s.op->line() << " .callback=&stap_uprobe_process_munmap,"; } s.op->line() << " },"; if (p->module != "") s.op->line() << " .pathname=" << lex_cast_qstring(p->module) << ", "; s.op->line() << " },"; } else { } // skip it in this pass, already have a suitable stap_uprobe_tf slot for it. } s.op->newline(-1) << "};"; s.op->assert_0_indent(); unsigned pci; for (pci=0; pci::iterator pcii; s.op->newline() << "long perf_counters_" + lex_cast(pci) + "[] = {"; for (pcii = p->perf_counter_refs.begin(); pcii != p->perf_counter_refs.end(); pcii++) { map >::iterator it; unsigned i = 0; // Find the associated perf.counter probe for (it=s.perf_counters.begin() ; it != s.perf_counters.end(); it++, i++) if ((*it).second.second == (*pcii)) break; s.op->line() << lex_cast(i) << ", "; } s.op->newline() << "};"; } // NB: read-only structure s.op->newline() << "static const struct stap_uprobe_spec stap_uprobe_specs [] = {"; s.op->indent(1); for (unsigned i =0; inewline() << "{"; string key = make_pbm_key (p); unsigned value = module_index[key]; if (value != 0) s.op->line() << " .tfi=" << value << ","; s.op->line() << " .address=(unsigned long)0x" << hex << p->addr << dec << "ULL,"; s.op->line() << " .probe=" << common_probe_init (p) << ","; if (p->sdt_semaphore_addr != 0) s.op->line() << " .sdt_sem_offset=(unsigned long)0x" << hex << p->sdt_semaphore_addr << dec << "ULL,"; // XXX: don't bother emit if array is empty s.op->line() << " .perf_counters_dim=ARRAY_SIZE(perf_counters_" << lex_cast(i) << "),"; // List of perf counters used by a probe from above s.op->line() << " .perf_counters=perf_counters_" + lex_cast(i) + ","; if (p->has_return) s.op->line() << " .return_p=1,"; s.op->line() << " },"; } s.op->newline(-1) << "};"; s.op->assert_0_indent(); s.op->newline() << "static void enter_uprobe_probe (struct uprobe *inst, struct pt_regs *regs) {"; s.op->newline(1) << "struct stap_uprobe *sup = container_of(inst, struct stap_uprobe, up);"; s.op->newline() << "const struct stap_uprobe_spec *sups = &stap_uprobe_specs [sup->spec_index];"; common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sups->probe", "stp_probe_type_uprobe"); s.op->newline() << "if (sup->spec_index < 0 || " << "sup->spec_index >= " << probes.size() << ") {"; s.op->newline(1) << "_stp_error (\"bad spec_index %d (max " << probes.size() << "): %s\", sup->spec_index, c->probe_point);"; s.op->newline() << "atomic_dec (&c->busy);"; s.op->newline() << "goto probe_epilogue;"; s.op->newline(-1) << "}"; s.op->newline() << "c->uregs = regs;"; s.op->newline() << "c->user_mode_p = 1;"; // Make it look like the IP is set as it would in the actual user // task when calling real probe handler. Reset IP regs on return, so // we don't confuse uprobes. PR10458 s.op->newline() << "{"; s.op->indent(1); s.op->newline() << "unsigned long uprobes_ip = REG_IP(c->uregs);"; s.op->newline() << "SET_REG_IP(regs, inst->vaddr);"; s.op->newline() << "(*sups->probe->ph) (c);"; s.op->newline() << "SET_REG_IP(regs, uprobes_ip);"; s.op->newline(-1) << "}"; common_probe_entryfn_epilogue (s, true); s.op->newline(-1) << "}"; s.op->newline() << "static void enter_uretprobe_probe (struct uretprobe_instance *inst, struct pt_regs *regs) {"; s.op->newline(1) << "struct stap_uprobe *sup = container_of(inst->rp, struct stap_uprobe, urp);"; s.op->newline() << "const struct stap_uprobe_spec *sups = &stap_uprobe_specs [sup->spec_index];"; common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sups->probe", "stp_probe_type_uretprobe"); s.op->newline() << "c->ips.ri = inst;"; s.op->newline() << "if (sup->spec_index < 0 || " << "sup->spec_index >= " << probes.size() << ") {"; s.op->newline(1) << "_stp_error (\"bad spec_index %d (max " << probes.size() << "): %s\", sup->spec_index, c->probe_point);"; s.op->newline() << "atomic_dec (&c->busy);"; s.op->newline() << "goto probe_epilogue;"; s.op->newline(-1) << "}"; s.op->newline() << "c->uregs = regs;"; s.op->newline() << "c->user_mode_p = 1;"; // Make it look like the IP is set as it would in the actual user // task when calling real probe handler. Reset IP regs on return, so // we don't confuse uprobes. PR10458 s.op->newline() << "{"; s.op->indent(1); s.op->newline() << "unsigned long uprobes_ip = REG_IP(c->uregs);"; s.op->newline() << "SET_REG_IP(regs, inst->ret_addr);"; s.op->newline() << "(*sups->probe->ph) (c);"; s.op->newline() << "SET_REG_IP(regs, uprobes_ip);"; s.op->newline(-1) << "}"; common_probe_entryfn_epilogue (s, true); s.op->newline(-1) << "}"; s.op->newline(); s.op->newline() << "#include \"linux/uprobes-common.c\""; s.op->newline(); } void uprobe_derived_probe_group::emit_module_utrace_init (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "/* ---- utrace uprobes ---- */"; s.op->newline() << "for (j=0; jnewline(1) << "struct stap_uprobe *sup = & stap_uprobes[j];"; s.op->newline() << "sup->spec_index = -1;"; // free slot // NB: we assume the rest of the struct (specificaly, sup->up) is // initialized to zero. This is so that we can use // sup->up->kdata = NULL for "really free!" PR 6829. s.op->newline(-1) << "}"; s.op->newline() << "mutex_init (& stap_uprobes_lock);"; // Set up the task_finders s.op->newline() << "for (i=0; inewline(1) << "struct stap_uprobe_tf *stf = & stap_uprobe_finders[i];"; s.op->newline() << "probe_point = stf->pathname;"; // for error messages; XXX: would prefer pp() or something better s.op->newline() << "rc = stap_register_task_finder_target (& stf->finder);"; // NB: if (rc), there is no need (XXX: nor any way) to clean up any // finders already registered, since mere registration does not // cause any utrace or memory allocation actions. That happens only // later, once the task finder engine starts running. So, for a // partial initialization requiring unwind, we need do nothing. s.op->newline() << "if (rc) break;"; s.op->newline(-1) << "}"; } void uprobe_derived_probe_group::emit_module_utrace_exit (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "/* ---- utrace uprobes ---- */"; // NB: there is no stap_unregister_task_finder_target call; // important stuff like utrace cleanups are done by // __stp_task_finder_cleanup() via stap_stop_task_finder(). // // This function blocks until all callbacks are completed, so there // is supposed to be no possibility of any registration-related code starting // to run in parallel with our shutdown here. So we don't need to protect the // stap_uprobes[] array with the mutex. s.op->newline() << "for (j=0; jnewline(1) << "struct stap_uprobe *sup = & stap_uprobes[j];"; s.op->newline() << "const struct stap_uprobe_spec *sups = &stap_uprobe_specs [sup->spec_index];"; s.op->newline() << "if (sup->spec_index < 0) continue;"; // free slot // PR10655: decrement that ENABLED semaphore s.op->newline() << "if (sup->sdt_sem_address) {"; s.op->newline(1) << "unsigned short sdt_semaphore;"; // NB: fixed size s.op->newline() << "pid_t pid = (sups->return_p ? sup->urp.u.pid : sup->up.pid);"; s.op->newline() << "struct task_struct *tsk;"; s.op->newline() << "rcu_read_lock();"; // Do a pid->task_struct* lookup. For 2.6.24+, this code assumes // that the pid is always in the global namespace, not in any // private namespace. s.op->newline() << "#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)"; // We'd like to call find_task_by_pid_ns() here, but it isn't // exported. So, we call what it calls... s.op->newline() << " tsk = pid_task(find_pid_ns(pid, &init_pid_ns), PIDTYPE_PID);"; s.op->newline() << "#else"; s.op->newline() << " tsk = find_task_by_pid (pid);"; s.op->newline() << "#endif /* 2.6.24 */"; s.op->newline() << "if (tsk) {"; // just in case the thing exited while we weren't watching s.op->newline(1) << "if (__access_process_vm_noflush(tsk, sup->sdt_sem_address, &sdt_semaphore, sizeof(sdt_semaphore), 0)) {"; s.op->newline(1) << "sdt_semaphore --;"; s.op->newline() << "#ifdef DEBUG_UPROBES"; s.op->newline() << "_stp_dbug (__FUNCTION__,__LINE__, \"-semaphore %#x @ %#lx\\n\", sdt_semaphore, sup->sdt_sem_address);"; s.op->newline() << "#endif"; s.op->newline() << "__access_process_vm_noflush(tsk, sup->sdt_sem_address, &sdt_semaphore, sizeof(sdt_semaphore), 1);"; s.op->newline(-1) << "}"; // XXX: need to analyze possibility of race condition s.op->newline(-1) << "}"; s.op->newline() << "rcu_read_unlock();"; s.op->newline(-1) << "}"; s.op->newline() << "if (sups->return_p) {"; s.op->newline(1) << "#ifdef DEBUG_UPROBES"; s.op->newline() << "_stp_dbug (__FUNCTION__,__LINE__, \"-uretprobe spec %d index %d pid %d addr %p\\n\", sup->spec_index, j, sup->up.pid, (void*) sup->up.vaddr);"; s.op->newline() << "#endif"; // NB: PR6829 does not change that we still need to unregister at // *this* time -- when the script as a whole exits. s.op->newline() << "unregister_uretprobe (& sup->urp);"; s.op->newline(-1) << "} else {"; s.op->newline(1) << "#ifdef DEBUG_UPROBES"; s.op->newline() << "_stp_dbug (__FUNCTION__,__LINE__, \"-uprobe spec %d index %d pid %d addr %p\\n\", sup->spec_index, j, sup->up.pid, (void*) sup->up.vaddr);"; s.op->newline() << "#endif"; s.op->newline() << "unregister_uprobe (& sup->up);"; s.op->newline(-1) << "}"; s.op->newline() << "sup->spec_index = -1;"; // XXX: uprobe missed counts? s.op->newline(-1) << "}"; s.op->newline() << "mutex_destroy (& stap_uprobes_lock);"; } void uprobe_derived_probe_group::emit_module_inode_decls (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "/* ---- inode uprobes ---- */"; emit_module_maxuprobes (s); s.op->newline() << "#include \"linux/uprobes-inode.c\""; // Write the probe handler. s.op->newline() << "static int stapiu_probe_handler " << "(struct stapiu_consumer *sup, struct pt_regs *regs) {"; s.op->newline(1); // Since we're sharing the entry function, we have to dynamically choose the probe_type string probe_type = "(sup->return_p ? stp_probe_type_uretprobe : stp_probe_type_uprobe)"; common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sup->probe", probe_type); s.op->newline() << "c->uregs = regs;"; s.op->newline() << "c->user_mode_p = 1;"; // NB: IP is already set by stapiu_probe_prehandler in uprobes-inode.c s.op->newline() << "(*sup->probe->ph) (c);"; common_probe_entryfn_epilogue (s, true); s.op->newline() << "return 0;"; s.op->newline(-1) << "}"; s.op->assert_0_indent(); // Index of all the modules for which we need inodes. map module_index; unsigned module_index_ctr = 0; // Discover and declare targets for each unique path. s.op->newline() << "static struct stapiu_target " << "stap_inode_uprobe_targets[] = {"; s.op->indent(1); for (unsigned i=0; inewline() << "{"; s.op->line() << " .finder={"; s.op->line() << " .purpose=\"inode-uprobes\","; if (p->pid != 0) s.op->line() << " .pid=" << p->pid << ","; if (p->section == "") // .statement(addr).absolute XXX? s.op->line() << " .callback=&stapiu_process_found,"; else if (p->section == ".absolute") // proxy for ET_EXEC -> exec()'d program { s.op->line() << " .procname=" << lex_cast_qstring(p->module) << ","; s.op->line() << " .callback=&stapiu_process_found,"; } else if (p->section != ".absolute") // ET_DYN { if (p->has_library) s.op->line() << " .procname=\"" << p->path << "\", "; s.op->line() << " .mmap_callback=&stapiu_mmap_found, "; s.op->line() << " .munmap_callback=&stapiu_munmap_found, "; s.op->line() << " .callback=&stapiu_process_munmap,"; } s.op->line() << " },"; s.op->line() << " .filename=" << lex_cast_qstring(p->module) << ","; s.op->line() << " },"; } } s.op->newline(-1) << "};"; s.op->assert_0_indent(); // Declare the actual probes. unsigned pci; for (pci=0; pci::iterator pcii; s.op->newline() << "long perf_counters_" + lex_cast(pci) + "[] = {"; for (pcii = p->perf_counter_refs.begin(); pcii != p->perf_counter_refs.end(); pcii++) { map >::iterator it; unsigned i = 0; // Find the associated perf.counter probe for (it=s.perf_counters.begin() ; it != s.perf_counters.end(); it++, i++) if ((*it).second.second == (*pcii)) break; s.op->line() << lex_cast(i) << ", "; } s.op->newline() << "};"; } s.op->newline() << "static struct stapiu_consumer " << "stap_inode_uprobe_consumers[] = {"; s.op->indent(1); for (unsigned i=0; inewline() << "{"; if (p->has_return) s.op->line() << " .return_p=1,"; s.op->line() << " .target=&stap_inode_uprobe_targets[" << index << "],"; s.op->line() << " .offset=(loff_t)0x" << hex << p->addr << dec << "ULL,"; if (p->sdt_semaphore_addr) s.op->line() << " .sdt_sem_offset=(loff_t)0x" << hex << p->sdt_semaphore_addr << dec << "ULL,"; // XXX: don't bother emit if array is empty s.op->line() << " .perf_counters_dim=ARRAY_SIZE(perf_counters_" << lex_cast(i) << "),"; // List of perf counters used by a probe from above s.op->line() << " .perf_counters=perf_counters_" + lex_cast(i) + ","; s.op->line() << " .probe=" << common_probe_init (p) << ","; s.op->line() << " },"; } s.op->newline(-1) << "};"; s.op->assert_0_indent(); } void uprobe_derived_probe_group::emit_module_inode_init (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "/* ---- inode uprobes ---- */"; // Let stapiu_init() handle reporting errors by setting probe_point // to NULL. s.op->newline() << "probe_point = NULL;"; s.op->newline() << "rc = stapiu_init (" << "stap_inode_uprobe_targets, " << "ARRAY_SIZE(stap_inode_uprobe_targets), " << "stap_inode_uprobe_consumers, " << "ARRAY_SIZE(stap_inode_uprobe_consumers));"; } void uprobe_derived_probe_group::emit_module_inode_exit (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "/* ---- inode uprobes ---- */"; s.op->newline() << "stapiu_exit (" << "stap_inode_uprobe_targets, " << "ARRAY_SIZE(stap_inode_uprobe_targets), " << "stap_inode_uprobe_consumers, " << "ARRAY_SIZE(stap_inode_uprobe_consumers));"; } void uprobe_derived_probe_group::emit_module_dyninst_decls (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "/* ---- dyninst uprobes ---- */"; emit_module_maxuprobes (s); s.op->newline() << "#include \"dyninst/uprobes.h\""; // Let the dynprobe_derived_probe_group handle outputting targets // and probes. This allows us to merge different types of probes. s.op->newline() << "static struct stapdu_probe stapdu_probes[];"; for (unsigned i = 0; i < probes.size(); i++) { uprobe_derived_probe *p = probes[i]; dynprobe_add_uprobe(s, p->module, p->addr, p->sdt_semaphore_addr, (p->has_return ? "STAPDYN_PROBE_FLAG_RETURN" : "0"), common_probe_init(p)); } // loc2c-generated code assumes pt_regs are available, so use this to make // sure we always have *something* for it to dereference... s.op->newline() << "static struct pt_regs stapdu_dummy_uregs;"; // Write the probe handler. // NB: not static, so dyninst can find it s.op->newline() << "int enter_dyninst_uprobe " << "(uint64_t index, struct pt_regs *regs) {"; s.op->newline(1) << "struct stapdu_probe *sup = &stapdu_probes[index];"; // Since we're sharing the entry function, we have to dynamically choose the probe_type string probe_type = "((sup->flags & STAPDYN_PROBE_FLAG_RETURN) ?" " stp_probe_type_uretprobe : stp_probe_type_uprobe)"; common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sup->probe", probe_type); s.op->newline() << "c->uregs = regs ?: &stapdu_dummy_uregs;"; s.op->newline() << "c->user_mode_p = 1;"; // XXX: once we have regs, check how dyninst sets the IP // XXX: the way that dyninst rewrites stuff is probably going to be // ... very confusing to our backtracer (at least if we stay in process) s.op->newline() << "(*sup->probe->ph) (c);"; common_probe_entryfn_epilogue (s, true); s.op->newline() << "return 0;"; s.op->newline(-1) << "}"; s.op->newline() << "#include \"dyninst/uprobes-regs.c\""; s.op->assert_0_indent(); } void uprobe_derived_probe_group::emit_module_dyninst_init (systemtap_session& s) { if (probes.empty()) return; /* stapdyn handles the dirty work via dyninst */ s.op->newline() << "/* ---- dyninst uprobes ---- */"; s.op->newline() << "/* this section left intentionally blank */"; } void uprobe_derived_probe_group::emit_module_dyninst_exit (systemtap_session& s) { if (probes.empty()) return; /* stapdyn handles the dirty work via dyninst */ s.op->newline() << "/* ---- dyninst uprobes ---- */"; s.op->newline() << "/* this section left intentionally blank */"; } void uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) { if (s.runtime_usermode_p()) emit_module_dyninst_decls (s); else if (kernel_supports_inode_uprobes (s)) emit_module_inode_decls (s); else emit_module_utrace_decls (s); } void uprobe_derived_probe_group::emit_module_init (systemtap_session& s) { if (s.runtime_usermode_p()) emit_module_dyninst_init (s); else if (kernel_supports_inode_uprobes (s)) emit_module_inode_init (s); else emit_module_utrace_init (s); } void uprobe_derived_probe_group::emit_module_exit (systemtap_session& s) { if (s.runtime_usermode_p()) emit_module_dyninst_exit (s); else if (kernel_supports_inode_uprobes (s)) emit_module_inode_exit (s); else emit_module_utrace_exit (s); } // ------------------------------------------------------------------------ // Kprobe derived probes // ------------------------------------------------------------------------ static const string TOK_KPROBE("kprobe"); struct kprobe_derived_probe: public derived_probe { kprobe_derived_probe (systemtap_session& sess, vector & results, probe *base, probe_point *location, const string& name, int64_t stmt_addr, bool has_return, bool has_statement, bool has_maxactive, bool has_path, bool has_library, long maxactive_val, const string& path, const string& library ); string symbol_name; Dwarf_Addr addr; bool has_return; bool has_statement; bool has_maxactive; bool has_path; bool has_library; long maxactive_val; string path; string library; bool access_var; void printsig (std::ostream &o) const; void join_group (systemtap_session& s); }; struct kprobe_derived_probe_group: public derived_probe_group { private: multimap probes_by_module; typedef multimap::iterator p_b_m_iterator; public: void enroll (kprobe_derived_probe* probe); void emit_module_decls (systemtap_session& s); void emit_module_init (systemtap_session& s); void emit_module_exit (systemtap_session& s); }; struct kprobe_var_expanding_visitor: public var_expanding_visitor { systemtap_session& sess; block *add_block; block *add_call_probe; // synthesized from .return probes with saved $vars bool add_block_tid, add_call_probe_tid; bool has_return; kprobe_var_expanding_visitor(systemtap_session& sess, bool has_return): sess(sess), add_block(NULL), add_call_probe(NULL), add_block_tid(false), add_call_probe_tid(false), has_return(has_return) {} void visit_entry_op (entry_op* e); }; kprobe_derived_probe::kprobe_derived_probe (systemtap_session& sess, vector & results, probe *base, probe_point *location, const string& name, int64_t stmt_addr, bool has_return, bool has_statement, bool has_maxactive, bool has_path, bool has_library, long maxactive_val, const string& path, const string& library ): derived_probe (base, location, true /* .components soon rewritten */ ), symbol_name (name), addr (stmt_addr), has_return (has_return), has_statement (has_statement), has_maxactive (has_maxactive), has_path (has_path), has_library (has_library), maxactive_val (maxactive_val), path (path), library (library) { this->tok = base->tok; this->access_var = false; #ifndef USHRT_MAX #define USHRT_MAX 32767 #endif // Expansion of $target variables in the probe body produces an error during // translate phase, since we're not using debuginfo vector comps; comps.push_back (new probe_point::component(TOK_KPROBE)); if (has_statement) { comps.push_back (new probe_point::component(TOK_STATEMENT, new literal_number(addr, true))); comps.push_back (new probe_point::component(TOK_ABSOLUTE)); } else { size_t pos = name.find(':'); if (pos != string::npos) { string module = name.substr(0, pos); string function = name.substr(pos + 1); comps.push_back (new probe_point::component(TOK_MODULE, new literal_string(module))); comps.push_back (new probe_point::component(TOK_FUNCTION, new literal_string(function))); } else comps.push_back (new probe_point::component(TOK_FUNCTION, new literal_string(name))); } if (has_return) comps.push_back (new probe_point::component(TOK_RETURN)); if (has_maxactive) comps.push_back (new probe_point::component(TOK_MAXACTIVE, new literal_number(maxactive_val))); kprobe_var_expanding_visitor v (sess, has_return); v.replace (this->body); // If during target-variable-expanding the probe, we added a new block // of code, add it to the start of the probe. if (v.add_block) this->body = new block(v.add_block, this->body); // If when target-variable-expanding the probe, we need to // synthesize a sibling function-entry probe. We don't go through // the whole probe derivation business (PR10642) that could lead to // wildcard/alias resolution, or for that dwarf-induced duplication. if (v.add_call_probe) { assert (has_return); // We temporarily replace base. statement* old_body = base->body; base->body = v.add_call_probe; derived_probe *entry_handler = new kprobe_derived_probe (sess, results, base, location, name, 0, false, has_statement, has_maxactive, has_path, has_library, maxactive_val, path, library); results.push_back (entry_handler); base->body = old_body; } this->sole_location()->components = comps; } void kprobe_derived_probe::printsig (ostream& o) const { sole_location()->print (o); o << " /* " << " name = " << symbol_name << "*/"; printsig_nested (o); } void kprobe_derived_probe::join_group (systemtap_session& s) { if (! s.kprobe_derived_probes) s.kprobe_derived_probes = new kprobe_derived_probe_group (); s.kprobe_derived_probes->enroll (this); } void kprobe_derived_probe_group::enroll (kprobe_derived_probe* p) { probes_by_module.insert (make_pair (p->symbol_name, p)); // probes of same symbol should share single kprobe/kretprobe } void kprobe_derived_probe_group::emit_module_decls (systemtap_session& s) { if (probes_by_module.empty()) return; s.op->newline() << "/* ---- kprobe-based probes ---- */"; // Warn of misconfigured kernels s.op->newline() << "#if ! defined(CONFIG_KPROBES)"; s.op->newline() << "#error \"Need CONFIG_KPROBES!\""; s.op->newline() << "#endif"; s.op->newline(); s.op->newline() << "#ifndef KRETACTIVE"; s.op->newline() << "#define KRETACTIVE (max(15,6*(int)num_possible_cpus()))"; s.op->newline() << "#endif"; // Forward declare the master entry functions s.op->newline() << "static int enter_kprobe2_probe (struct kprobe *inst,"; s.op->line() << " struct pt_regs *regs);"; s.op->newline() << "static int enter_kretprobe2_probe (struct kretprobe_instance *inst,"; s.op->line() << " struct pt_regs *regs);"; // Emit an array of kprobe/kretprobe pointers s.op->newline() << "#if defined(STAPCONF_UNREGISTER_KPROBES)"; s.op->newline() << "static void * stap_unreg_kprobes2[" << probes_by_module.size() << "];"; s.op->newline() << "#endif"; // Emit the actual probe list. s.op->newline() << "static struct stap_dwarfless_kprobe {"; s.op->newline(1) << "union { struct kprobe kp; struct kretprobe krp; } u;"; s.op->newline() << "#ifdef __ia64__"; s.op->newline() << "struct kprobe dummy;"; s.op->newline() << "#endif"; s.op->newline(-1) << "} stap_dwarfless_kprobes[" << probes_by_module.size() << "];"; // NB: bss! s.op->newline() << "static struct stap_dwarfless_probe {"; s.op->newline(1) << "const unsigned return_p:1;"; s.op->newline() << "const unsigned maxactive_p:1;"; s.op->newline() << "const unsigned optional_p:1;"; s.op->newline() << "unsigned registered_p:1;"; s.op->newline() << "const unsigned short maxactive_val;"; // Function Names are mostly small and uniform enough to justify putting // char[MAX]'s into the array instead of relocated char*'s. size_t symbol_string_name_max = 0; size_t symbol_string_name_tot = 0; for (p_b_m_iterator it = probes_by_module.begin(); it != probes_by_module.end(); it++) { kprobe_derived_probe* p = it->second; #define DOIT(var,expr) do { \ size_t var##_size = (expr) + 1; \ var##_max = max (var##_max, var##_size); \ var##_tot += var##_size; } while (0) DOIT(symbol_string_name, p->symbol_name.size()); #undef DOIT } #define CALCIT(var) \ s.op->newline() << "const char " << #var << "[" << var##_name_max << "] ;"; CALCIT(symbol_string); #undef CALCIT s.op->newline() << "unsigned long address;"; s.op->newline() << "const struct stap_probe * const probe;"; s.op->newline(-1) << "} stap_dwarfless_probes[] = {"; s.op->indent(1); for (p_b_m_iterator it = probes_by_module.begin(); it != probes_by_module.end(); it++) { kprobe_derived_probe* p = it->second; s.op->newline() << "{"; if (p->has_return) s.op->line() << " .return_p=1,"; if (p->has_maxactive) { s.op->line() << " .maxactive_p=1,"; assert (p->maxactive_val >= 0 && p->maxactive_val <= USHRT_MAX); s.op->line() << " .maxactive_val=" << p->maxactive_val << ","; } if (p->locations[0]->optional) s.op->line() << " .optional_p=1,"; if (p->has_statement) s.op->line() << " .address=(unsigned long)0x" << hex << p->addr << dec << "ULL,"; else s.op->line() << " .symbol_string=\"" << p->symbol_name << "\","; s.op->line() << " .probe=" << common_probe_init (p) << ","; s.op->line() << " },"; } s.op->newline(-1) << "};"; // Emit the kprobes callback function s.op->newline(); s.op->newline() << "static int enter_kprobe2_probe (struct kprobe *inst,"; s.op->line() << " struct pt_regs *regs) {"; // NB: as of PR5673, the kprobe|kretprobe union struct is in BSS s.op->newline(1) << "int kprobe_idx = ((uintptr_t)inst-(uintptr_t)stap_dwarfless_kprobes)/sizeof(struct stap_dwarfless_kprobe);"; // Check that the index is plausible s.op->newline() << "struct stap_dwarfless_probe *sdp = &stap_dwarfless_probes["; s.op->line() << "((kprobe_idx >= 0 && kprobe_idx < " << probes_by_module.size() << ")?"; s.op->line() << "kprobe_idx:0)"; // NB: at least we avoid memory corruption // XXX: it would be nice to give a more verbose error though; BUG_ON later? s.op->line() << "];"; common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sdp->probe", "stp_probe_type_kprobe"); s.op->newline() << "c->kregs = regs;"; // Make it look like the IP is set as it wouldn't have been replaced // by a breakpoint instruction when calling real probe handler. Reset // IP regs on return, so we don't confuse kprobes. PR10458 s.op->newline() << "{"; s.op->indent(1); s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->kregs);"; s.op->newline() << "SET_REG_IP(regs, (unsigned long) inst->addr);"; s.op->newline() << "(*sdp->probe->ph) (c);"; s.op->newline() << "SET_REG_IP(regs, kprobes_ip);"; s.op->newline(-1) << "}"; common_probe_entryfn_epilogue (s, true); s.op->newline() << "return 0;"; s.op->newline(-1) << "}"; // Same for kretprobes s.op->newline(); s.op->newline() << "static int enter_kretprobe2_probe (struct kretprobe_instance *inst,"; s.op->line() << " struct pt_regs *regs) {"; s.op->newline(1) << "struct kretprobe *krp = inst->rp;"; // NB: as of PR5673, the kprobe|kretprobe union struct is in BSS s.op->newline() << "int kprobe_idx = ((uintptr_t)krp-(uintptr_t)stap_dwarfless_kprobes)/sizeof(struct stap_dwarfless_kprobe);"; // Check that the index is plausible s.op->newline() << "struct stap_dwarfless_probe *sdp = &stap_dwarfless_probes["; s.op->line() << "((kprobe_idx >= 0 && kprobe_idx < " << probes_by_module.size() << ")?"; s.op->line() << "kprobe_idx:0)"; // NB: at least we avoid memory corruption // XXX: it would be nice to give a more verbose error though; BUG_ON later? s.op->line() << "];"; common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sdp->probe", "stp_probe_type_kretprobe"); s.op->newline() << "c->kregs = regs;"; s.op->newline() << "c->ips.krp.pi = inst;"; // for assisting runtime's backtrace logic // Make it look like the IP is set as it wouldn't have been replaced // by a breakpoint instruction when calling real probe handler. Reset // IP regs on return, so we don't confuse kprobes. PR10458 s.op->newline() << "{"; s.op->indent(1); s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->kregs);"; s.op->newline() << "SET_REG_IP(regs, (unsigned long) inst->rp->kp.addr);"; s.op->newline() << "(*sdp->probe->ph) (c);"; s.op->newline() << "SET_REG_IP(regs, kprobes_ip);"; s.op->newline(-1) << "}"; common_probe_entryfn_epilogue (s, true); s.op->newline() << "return 0;"; s.op->newline(-1) << "}"; s.op->newline() << "#ifdef STAPCONF_KALLSYMS_ON_EACH_SYMBOL"; s.op->newline() << "static int kprobe_resolve(void *data, const char *name,"; s.op->newline() << " struct module *owner,"; s.op->newline() << " unsigned long val) {"; s.op->newline(1) << "int i;"; s.op->newline() << "int *p = (int *) data;"; s.op->newline() << "for (i=0; i<" << probes_by_module.size() << " && *p > 0; i++) {"; s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];"; s.op->newline() << "if (! sdp->address) {"; s.op->indent(1); s.op->newline() << "const char *colon;"; s.op->newline() << "if (owner && (colon = strchr(sdp->symbol_string, ':'))) {"; s.op->indent(1); s.op->newline() << "if ((strlen(owner->name) == (colon - sdp->symbol_string))"; s.op->newline() << " && (strncmp(sdp->symbol_string, owner->name, colon - sdp->symbol_string) == 0)"; s.op->newline() << " && (strcmp(colon + 1, name) == 0)) {"; s.op->newline(1) << "sdp->address = val;"; s.op->newline() << "(*p)--;"; s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; s.op->newline() << "else {"; s.op->newline(1) << "if (strcmp(sdp->symbol_string, name) == 0) {"; s.op->newline(1) << "sdp->address = val;"; s.op->newline() << "(*p)--;"; s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; s.op->newline() << "return (p > 0) ? 0 : -1;"; s.op->newline(-1) << "}"; s.op->newline() << "#endif"; } void kprobe_derived_probe_group::emit_module_init (systemtap_session& s) { s.op->newline() << "#ifdef STAPCONF_KALLSYMS_ON_EACH_SYMBOL"; s.op->newline() << "{"; s.op->newline(1) << "int p = 0;"; s.op->newline() << "for (i = 0; i < " << probes_by_module.size() << "; i++) {"; s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];"; s.op->newline() << "if (! sdp->address)"; s.op->newline(1) << "p++;"; s.op->newline(-2) << "}"; s.op->newline() << "kallsyms_on_each_symbol(kprobe_resolve, &p);"; s.op->newline(-1) << "}"; s.op->newline() << "#endif"; s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {"; s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];"; s.op->newline() << "struct stap_dwarfless_kprobe *kp = & stap_dwarfless_kprobes[i];"; s.op->newline() << "void *addr = (void *) sdp->address;"; s.op->newline() << "const char *symbol_name = addr ? NULL : sdp->symbol_string;"; s.op->newline() << "#ifdef STAPCONF_KALLSYMS_ON_EACH_SYMBOL"; s.op->newline() << "if (! addr) {"; s.op->newline(1) << "sdp->registered_p = 0;"; s.op->newline() << "if (!sdp->optional_p)"; s.op->newline(1) << "_stp_warn (\"probe %s registration error (symbol not found)\", probe_point);"; s.op->newline(-1) << "continue;"; s.op->newline(-1) << "}"; s.op->newline() << "#endif"; s.op->newline() << "probe_point = sdp->probe->pp;"; // for error messages s.op->newline() << "if (sdp->return_p) {"; s.op->newline(1) << "kp->u.krp.kp.addr = addr;"; s.op->newline() << "#ifdef STAPCONF_KPROBE_SYMBOL_NAME"; s.op->newline() << "kp->u.krp.kp.symbol_name = (char *) symbol_name;"; s.op->newline() << "#endif"; s.op->newline() << "if (sdp->maxactive_p) {"; s.op->newline(1) << "kp->u.krp.maxactive = sdp->maxactive_val;"; s.op->newline(-1) << "} else {"; s.op->newline(1) << "kp->u.krp.maxactive = KRETACTIVE;"; s.op->newline(-1) << "}"; s.op->newline() << "kp->u.krp.handler = &enter_kretprobe2_probe;"; // to ensure safeness of bspcache, always use aggr_kprobe on ia64 s.op->newline() << "#ifdef __ia64__"; s.op->newline() << "kp->dummy.addr = kp->u.krp.kp.addr;"; s.op->newline() << "#ifdef STAPCONF_KPROBE_SYMBOL_NAME"; s.op->newline() << "kp->dummy.symbol_name = kp->u.krp.kp.symbol_name;"; s.op->newline() << "#endif"; s.op->newline() << "kp->dummy.pre_handler = NULL;"; s.op->newline() << "rc = register_kprobe (& kp->dummy);"; s.op->newline() << "if (rc == 0) {"; s.op->newline(1) << "rc = register_kretprobe (& kp->u.krp);"; s.op->newline() << "if (rc != 0)"; s.op->newline(1) << "unregister_kprobe (& kp->dummy);"; s.op->newline(-2) << "}"; s.op->newline() << "#else"; s.op->newline() << "rc = register_kretprobe (& kp->u.krp);"; s.op->newline() << "#endif"; s.op->newline(-1) << "} else {"; // to ensure safeness of bspcache, always use aggr_kprobe on ia64 s.op->newline(1) << "kp->u.kp.addr = addr;"; s.op->newline() << "#ifdef STAPCONF_KPROBE_SYMBOL_NAME"; s.op->newline() << "kp->u.kp.symbol_name = (char *) symbol_name;"; s.op->newline() << "#endif"; s.op->newline() << "kp->u.kp.pre_handler = &enter_kprobe2_probe;"; s.op->newline() << "#ifdef __ia64__"; s.op->newline() << "kp->dummy.pre_handler = NULL;"; s.op->newline() << "kp->dummy.addr = kp->u.kp.addr;"; s.op->newline() << "#ifdef STAPCONF_KPROBE_SYMBOL_NAME"; s.op->newline() << "kp->dummy.symbol_name = kp->u.kp.symbol_name;"; s.op->newline() << "#endif"; s.op->newline() << "rc = register_kprobe (& kp->dummy);"; s.op->newline() << "if (rc == 0) {"; s.op->newline(1) << "rc = register_kprobe (& kp->u.kp);"; s.op->newline() << "if (rc != 0)"; s.op->newline(1) << "unregister_kprobe (& kp->dummy);"; s.op->newline(-2) << "}"; s.op->newline() << "#else"; s.op->newline() << "rc = register_kprobe (& kp->u.kp);"; s.op->newline() << "#endif"; s.op->newline(-1) << "}"; s.op->newline() << "if (rc) {"; // PR6749: tolerate a failed register_*probe. s.op->newline(1) << "sdp->registered_p = 0;"; s.op->newline() << "if (!sdp->optional_p)"; s.op->newline(1) << "_stp_warn (\"probe %s (address 0x%lx) registration error (rc %d)\", probe_point, (unsigned long) addr, rc);"; s.op->newline(-1) << "rc = 0;"; // continue with other probes // XXX: shall we increment numskipped? s.op->newline(-1) << "}"; s.op->newline() << "else sdp->registered_p = 1;"; s.op->newline(-1) << "}"; // for loop } void kprobe_derived_probe_group::emit_module_exit (systemtap_session& s) { //Unregister kprobes by batch interfaces. s.op->newline() << "#if defined(STAPCONF_UNREGISTER_KPROBES)"; s.op->newline() << "j = 0;"; s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {"; s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];"; s.op->newline() << "struct stap_dwarfless_kprobe *kp = & stap_dwarfless_kprobes[i];"; s.op->newline() << "if (! sdp->registered_p) continue;"; s.op->newline() << "if (!sdp->return_p)"; s.op->newline(1) << "stap_unreg_kprobes2[j++] = &kp->u.kp;"; s.op->newline(-2) << "}"; s.op->newline() << "unregister_kprobes((struct kprobe **)stap_unreg_kprobes2, j);"; s.op->newline() << "j = 0;"; s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {"; s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];"; s.op->newline() << "struct stap_dwarfless_kprobe *kp = & stap_dwarfless_kprobes[i];"; s.op->newline() << "if (! sdp->registered_p) continue;"; s.op->newline() << "if (sdp->return_p)"; s.op->newline(1) << "stap_unreg_kprobes2[j++] = &kp->u.krp;"; s.op->newline(-2) << "}"; s.op->newline() << "unregister_kretprobes((struct kretprobe **)stap_unreg_kprobes2, j);"; s.op->newline() << "#ifdef __ia64__"; s.op->newline() << "j = 0;"; s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {"; s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];"; s.op->newline() << "struct stap_dwarfless_kprobe *kp = & stap_dwarfless_kprobes[i];"; s.op->newline() << "if (! sdp->registered_p) continue;"; s.op->newline() << "stap_unreg_kprobes2[j++] = &kp->dummy;"; s.op->newline(-1) << "}"; s.op->newline() << "unregister_kprobes((struct kprobe **)stap_unreg_kprobes2, j);"; s.op->newline() << "#endif"; s.op->newline() << "#endif"; s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {"; s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];"; s.op->newline() << "struct stap_dwarfless_kprobe *kp = & stap_dwarfless_kprobes[i];"; s.op->newline() << "if (! sdp->registered_p) continue;"; s.op->newline() << "if (sdp->return_p) {"; s.op->newline() << "#if !defined(STAPCONF_UNREGISTER_KPROBES)"; s.op->newline(1) << "unregister_kretprobe (&kp->u.krp);"; s.op->newline() << "#endif"; s.op->newline() << "atomic_add (kp->u.krp.nmissed, skipped_count());"; s.op->newline() << "#ifdef STP_TIMING"; s.op->newline() << "if (kp->u.krp.nmissed)"; s.op->newline(1) << "_stp_warn (\"Skipped due to missed kretprobe/1 on '%s': %d\\n\", sdp->probe->pp, kp->u.krp.nmissed);"; s.op->newline(-1) << "#endif"; s.op->newline() << "atomic_add (kp->u.krp.kp.nmissed, skipped_count());"; s.op->newline() << "#ifdef STP_TIMING"; s.op->newline() << "if (kp->u.krp.kp.nmissed)"; s.op->newline(1) << "_stp_warn (\"Skipped due to missed kretprobe/2 on '%s': %lu\\n\", sdp->probe->pp, kp->u.krp.kp.nmissed);"; s.op->newline(-1) << "#endif"; s.op->newline(-1) << "} else {"; s.op->newline() << "#if !defined(STAPCONF_UNREGISTER_KPROBES)"; s.op->newline(1) << "unregister_kprobe (&kp->u.kp);"; s.op->newline() << "#endif"; s.op->newline() << "atomic_add (kp->u.kp.nmissed, skipped_count());"; s.op->newline() << "#ifdef STP_TIMING"; s.op->newline() << "if (kp->u.kp.nmissed)"; s.op->newline(1) << "_stp_warn (\"Skipped due to missed kprobe on '%s': %lu\\n\", sdp->probe->pp, kp->u.kp.nmissed);"; s.op->newline(-1) << "#endif"; s.op->newline(-1) << "}"; s.op->newline() << "#if !defined(STAPCONF_UNREGISTER_KPROBES) && defined(__ia64__)"; s.op->newline() << "unregister_kprobe (&kp->dummy);"; s.op->newline() << "#endif"; s.op->newline() << "sdp->registered_p = 0;"; s.op->newline(-1) << "}"; } struct kprobe_builder: public derived_probe_builder { public: kprobe_builder() {} void build_no_more (systemtap_session &s) {} virtual void build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results); }; void kprobe_builder::build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results) { string function_string_val, module_string_val; string path, library, path_tgt, library_tgt; int64_t statement_num_val = 0, maxactive_val = 0; bool has_function_str, has_module_str, has_statement_num; bool has_absolute, has_return, has_maxactive; bool has_path, has_library; has_function_str = get_param(parameters, TOK_FUNCTION, function_string_val); has_module_str = get_param(parameters, TOK_MODULE, module_string_val); has_return = has_null_param (parameters, TOK_RETURN); has_maxactive = get_param(parameters, TOK_MAXACTIVE, maxactive_val); has_statement_num = get_param(parameters, TOK_STATEMENT, statement_num_val); has_absolute = has_null_param (parameters, TOK_ABSOLUTE); has_path = get_param (parameters, TOK_PROCESS, path); has_library = get_param (parameters, TOK_LIBRARY, library); if (has_path) { path = find_executable (path, sess.sysroot, sess.sysenv); path_tgt = path_remove_sysroot(sess, path); } if (has_library) { library = find_executable (library, sess.sysroot, sess.sysenv, "LD_LIBRARY_PATH"); library_tgt = path_remove_sysroot(sess, library); } if (has_function_str) { if (has_module_str) { function_string_val = module_string_val + ":" + function_string_val; derived_probe *dp = new kprobe_derived_probe (sess, finished_results, base, location, function_string_val, 0, has_return, has_statement_num, has_maxactive, has_path, has_library, maxactive_val, path_tgt, library_tgt); finished_results.push_back (dp); } else { vector matches; // Simple names can be found directly if (function_string_val.find_first_of("*?[") == string::npos) { if (sess.kernel_functions.count(function_string_val)) matches.push_back(function_string_val); } else // Search function name list for matching names { for (set::const_iterator it = sess.kernel_functions.begin(); it != sess.kernel_functions.end(); it++) // fnmatch returns zero for matching. if (fnmatch(function_string_val.c_str(), it->c_str(), 0) == 0) matches.push_back(*it); } for (vector::const_iterator it = matches.begin(); it != matches.end(); it++) { derived_probe *dp = new kprobe_derived_probe (sess, finished_results, base, location, *it, 0, has_return, has_statement_num, has_maxactive, has_path, has_library, maxactive_val, path_tgt, library_tgt); finished_results.push_back (dp); } } } else { // assert guru mode for absolute probes if ( has_statement_num && has_absolute && !base->privileged ) throw semantic_error (_("absolute statement probe in unprivileged script; need stap -g"), base->tok); finished_results.push_back (new kprobe_derived_probe (sess, finished_results, base, location, "", statement_num_val, has_return, has_statement_num, has_maxactive, has_path, has_library, maxactive_val, path_tgt, library_tgt)); } } void kprobe_var_expanding_visitor::visit_entry_op (entry_op *e) { expression *repl = e; if (has_return) { // expand the operand as if it weren't a return probe has_return = false; replace (e->operand); has_return = true; // XXX it would be nice to use gen_kretprobe_saved_return when // available, but it requires knowing the types already, which is // problematic for arbitrary expressons. repl = gen_mapped_saved_return (sess, e->operand, "entry", add_block, add_block_tid, add_call_probe, add_call_probe_tid); } provide (repl); } // ------------------------------------------------------------------------ // Hardware breakpoint based probes. // ------------------------------------------------------------------------ static const string TOK_HWBKPT("data"); static const string TOK_HWBKPT_WRITE("write"); static const string TOK_HWBKPT_RW("rw"); static const string TOK_LENGTH("length"); #define HWBKPT_READ 0 #define HWBKPT_WRITE 1 #define HWBKPT_RW 2 struct hwbkpt_derived_probe: public derived_probe { hwbkpt_derived_probe (probe *base, probe_point *location, uint64_t addr, string symname, unsigned int len, bool has_only_read_access, bool has_only_write_access, bool has_rw_access ); Dwarf_Addr hwbkpt_addr; string symbol_name; unsigned int hwbkpt_access,hwbkpt_len; void printsig (std::ostream &o) const; void join_group (systemtap_session& s); }; struct hwbkpt_derived_probe_group: public derived_probe_group { private: vector hwbkpt_probes; public: void enroll (hwbkpt_derived_probe* probe, systemtap_session& s); void emit_module_decls (systemtap_session& s); void emit_module_init (systemtap_session& s); void emit_module_exit (systemtap_session& s); }; hwbkpt_derived_probe::hwbkpt_derived_probe (probe *base, probe_point *location, uint64_t addr, string symname, unsigned int len, bool has_only_read_access, bool has_only_write_access, bool): derived_probe (base, location, true /* .components soon rewritten */ ), hwbkpt_addr (addr), symbol_name (symname), hwbkpt_len (len) { this->tok = base->tok; vector comps; comps.push_back (new probe_point::component(TOK_KERNEL)); if (hwbkpt_addr) comps.push_back (new probe_point::component (TOK_HWBKPT, new literal_number(hwbkpt_addr, true))); else if (symbol_name.size()) comps.push_back (new probe_point::component (TOK_HWBKPT, new literal_string(symbol_name))); comps.push_back (new probe_point::component (TOK_LENGTH, new literal_number(hwbkpt_len))); if (has_only_read_access) this->hwbkpt_access = HWBKPT_READ ; //TODO add code for comps.push_back for read, since this flag is not for x86 else { if (has_only_write_access) { this->hwbkpt_access = HWBKPT_WRITE ; comps.push_back (new probe_point::component(TOK_HWBKPT_WRITE)); } else { this->hwbkpt_access = HWBKPT_RW ; comps.push_back (new probe_point::component(TOK_HWBKPT_RW)); } } this->sole_location()->components = comps; } void hwbkpt_derived_probe::printsig (ostream& o) const { sole_location()->print (o); printsig_nested (o); } void hwbkpt_derived_probe::join_group (systemtap_session& s) { if (! s.hwbkpt_derived_probes) s.hwbkpt_derived_probes = new hwbkpt_derived_probe_group (); s.hwbkpt_derived_probes->enroll (this, s); } void hwbkpt_derived_probe_group::enroll (hwbkpt_derived_probe* p, systemtap_session& s) { hwbkpt_probes.push_back (p); unsigned max_hwbkpt_probes_by_arch = 0; if (s.architecture == "i386" || s.architecture == "x86_64") max_hwbkpt_probes_by_arch = 4; else if (s.architecture == "s390") max_hwbkpt_probes_by_arch = 1; if (hwbkpt_probes.size() >= max_hwbkpt_probes_by_arch) s.print_warning (_F("Too many hardware breakpoint probes requested for %s (%zu vs. %u)", s.architecture.c_str(), hwbkpt_probes.size(), max_hwbkpt_probes_by_arch)); } void hwbkpt_derived_probe_group::emit_module_decls (systemtap_session& s) { if (hwbkpt_probes.empty()) return; s.op->newline() << "/* ---- hwbkpt-based probes ---- */"; s.op->newline() << "#include "; s.op->newline() << "#include "; s.op->newline(); // Forward declare the master entry functions s.op->newline() << "#ifdef STAPCONF_PERF_HANDLER_NMI"; s.op->newline() << "static int enter_hwbkpt_probe (struct perf_event *bp,"; s.op->line() << " int nmi,"; s.op->line() << " struct perf_sample_data *data,"; s.op->line() << " struct pt_regs *regs);"; s.op->newline() << "#else"; s.op->newline() << "static int enter_hwbkpt_probe (struct perf_event *bp,"; s.op->line() << " struct perf_sample_data *data,"; s.op->line() << " struct pt_regs *regs);"; s.op->newline() << "#endif"; // Emit the actual probe list. s.op->newline() << "static struct perf_event_attr "; s.op->newline() << "stap_hwbkpt_probe_array[" << hwbkpt_probes.size() << "];"; s.op->newline() << "static struct perf_event **"; s.op->newline() << "stap_hwbkpt_ret_array[" << hwbkpt_probes.size() << "];"; s.op->newline() << "static struct stap_hwbkpt_probe {"; s.op->newline() << "int registered_p:1;"; // registered_p = 0 signifies a probe that is unregistered (or failed) // registered_p = 1 signifies a probe that got registered successfully // Symbol Names are mostly small and uniform enough // to justify putting const char*. s.op->newline() << "const char * const symbol;"; s.op->newline() << "const unsigned long address;"; s.op->newline() << "uint8_t atype;"; s.op->newline() << "unsigned int len;"; s.op->newline() << "const struct stap_probe * const probe;"; s.op->newline() << "} stap_hwbkpt_probes[] = {"; s.op->indent(1); for (unsigned int it = 0; it < hwbkpt_probes.size(); it++) { hwbkpt_derived_probe* p = hwbkpt_probes.at(it); s.op->newline() << "{"; if (p->symbol_name.size()) s.op->line() << " .address=(unsigned long)0x0" << "ULL,"; else s.op->line() << " .address=(unsigned long)0x" << hex << p->hwbkpt_addr << dec << "ULL,"; switch(p->hwbkpt_access){ case HWBKPT_READ: s.op->line() << " .atype=HW_BREAKPOINT_R ,"; break; case HWBKPT_WRITE: s.op->line() << " .atype=HW_BREAKPOINT_W ,"; break; case HWBKPT_RW: s.op->line() << " .atype=HW_BREAKPOINT_R|HW_BREAKPOINT_W ,"; break; }; s.op->line() << " .len=" << p->hwbkpt_len << ","; s.op->line() << " .probe=" << common_probe_init (p) << ","; s.op->line() << " .symbol=\"" << p->symbol_name << "\","; s.op->line() << " },"; } s.op->newline(-1) << "};"; // Emit the hwbkpt callback function s.op->newline() ; s.op->newline() << "#ifdef STAPCONF_PERF_HANDLER_NMI"; s.op->newline() << "static int enter_hwbkpt_probe (struct perf_event *bp,"; s.op->line() << " int nmi,"; s.op->line() << " struct perf_sample_data *data,"; s.op->line() << " struct pt_regs *regs) {"; s.op->newline() << "#else"; s.op->newline() << "static int enter_hwbkpt_probe (struct perf_event *bp,"; s.op->line() << " struct perf_sample_data *data,"; s.op->line() << " struct pt_regs *regs) {"; s.op->newline() << "#endif"; s.op->newline(1) << "unsigned int i;"; s.op->newline() << "if (bp->attr.type != PERF_TYPE_BREAKPOINT) return -1;"; s.op->newline() << "for (i=0; i<" << hwbkpt_probes.size() << "; i++) {"; s.op->newline(1) << "struct perf_event_attr *hp = & stap_hwbkpt_probe_array[i];"; // XXX: why not match stap_hwbkpt_ret_array[i] against bp instead? s.op->newline() << "if (bp->attr.bp_addr==hp->bp_addr && bp->attr.bp_type==hp->bp_type && bp->attr.bp_len==hp->bp_len) {"; s.op->newline(1) << "struct stap_hwbkpt_probe *sdp = &stap_hwbkpt_probes[i];"; common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sdp->probe", "stp_probe_type_hwbkpt"); s.op->newline() << "if (user_mode(regs)) {"; s.op->newline(1)<< "c->user_mode_p = 1;"; s.op->newline() << "c->uregs = regs;"; s.op->newline(-1) << "} else {"; s.op->newline(1) << "c->kregs = regs;"; s.op->newline(-1) << "}"; s.op->newline() << "(*sdp->probe->ph) (c);"; common_probe_entryfn_epilogue (s, true); s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; s.op->newline() << "return 0;"; s.op->newline(-1) << "}"; } void hwbkpt_derived_probe_group::emit_module_init (systemtap_session& s) { s.op->newline() << "for (i=0; i<" << hwbkpt_probes.size() << "; i++) {"; s.op->newline(1) << "struct stap_hwbkpt_probe *sdp = & stap_hwbkpt_probes[i];"; s.op->newline() << "struct perf_event_attr *hp = & stap_hwbkpt_probe_array[i];"; s.op->newline() << "void *addr = (void *) sdp->address;"; s.op->newline() << "const char *hwbkpt_symbol_name = addr ? NULL : sdp->symbol;"; s.op->newline() << "hw_breakpoint_init(hp);"; s.op->newline() << "if (addr)"; s.op->newline(1) << "hp->bp_addr = (unsigned long) addr;"; s.op->newline(-1) << "else { "; s.op->newline(1) << "hp->bp_addr = kallsyms_lookup_name(hwbkpt_symbol_name);"; s.op->newline() << "if (!hp->bp_addr) { "; s.op->newline(1) << "_stp_warn(\"Probe %s registration skipped: invalid symbol %s \",sdp->probe->pp,hwbkpt_symbol_name);"; s.op->newline() << "continue;"; s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; s.op->newline() << "hp->bp_type = sdp->atype;"; // On x86 & x86-64, hp->bp_len is not just a number but a macro/enum (!?!). if (s.architecture == "i386" || s.architecture == "x86_64" ) { s.op->newline() << "switch(sdp->len) {"; s.op->newline() << "case 1:"; s.op->newline(1) << "hp->bp_len = HW_BREAKPOINT_LEN_1;"; s.op->newline() << "break;"; s.op->newline(-1) << "case 2:"; s.op->newline(1) << "hp->bp_len = HW_BREAKPOINT_LEN_2;"; s.op->newline() << "break;"; s.op->newline(-1) << "case 3:"; s.op->newline() << "case 4:"; s.op->newline(1) << "hp->bp_len = HW_BREAKPOINT_LEN_4;"; s.op->newline() << "break;"; s.op->newline(-1) << "case 5:"; s.op->newline() << "case 6:"; s.op->newline() << "case 7:"; s.op->newline() << "case 8:"; s.op->newline() << "default:"; // XXX: could instead reject s.op->newline(1) << "hp->bp_len = HW_BREAKPOINT_LEN_8;"; s.op->newline() << "break;"; s.op->newline(-1) << "}"; } else // other architectures presumed straightforward s.op->newline() << "hp->bp_len = sdp->len;"; s.op->newline() << "probe_point = sdp->probe->pp;"; // for error messages s.op->newline() << "#ifdef STAPCONF_HW_BREAKPOINT_CONTEXT"; s.op->newline() << "stap_hwbkpt_ret_array[i] = register_wide_hw_breakpoint(hp, (void *)&enter_hwbkpt_probe, NULL);"; s.op->newline() << "#else"; s.op->newline() << "stap_hwbkpt_ret_array[i] = register_wide_hw_breakpoint(hp, (void *)&enter_hwbkpt_probe);"; s.op->newline() << "#endif"; s.op->newline() << "rc = 0;"; s.op->newline() << "if (IS_ERR(stap_hwbkpt_ret_array[i])) {"; s.op->newline(1) << "rc = PTR_ERR(stap_hwbkpt_ret_array[i]);"; s.op->newline() << "stap_hwbkpt_ret_array[i] = 0;"; s.op->newline(-1) << "}"; s.op->newline() << "if (rc) {"; s.op->newline(1) << "_stp_warn(\"Hwbkpt probe %s: registration error %d, addr %p, name %s\", probe_point, rc, addr, hwbkpt_symbol_name);"; s.op->newline() << "sdp->registered_p = 0;"; s.op->newline(-1) << "}"; s.op->newline() << " else sdp->registered_p = 1;"; s.op->newline(-1) << "}"; // for loop } void hwbkpt_derived_probe_group::emit_module_exit (systemtap_session& s) { //Unregister hwbkpt probes. s.op->newline() << "for (i=0; i<" << hwbkpt_probes.size() << "; i++) {"; s.op->newline(1) << "struct stap_hwbkpt_probe *sdp = & stap_hwbkpt_probes[i];"; s.op->newline() << "if (sdp->registered_p == 0) continue;"; s.op->newline() << "unregister_wide_hw_breakpoint(stap_hwbkpt_ret_array[i]);"; s.op->newline() << "sdp->registered_p = 0;"; s.op->newline(-1) << "}"; } struct hwbkpt_builder: public derived_probe_builder { hwbkpt_builder() {} virtual void build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results); }; void hwbkpt_builder::build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, vector & finished_results) { string symbol_str_val; int64_t hwbkpt_address, len; bool has_addr, has_symbol_str, has_write, has_rw, has_len; if (! (sess.kernel_config["CONFIG_PERF_EVENTS"] == string("y"))) throw semantic_error (_("CONFIG_PERF_EVENTS not available on this kernel"), location->components[0]->tok); if (! (sess.kernel_config["CONFIG_HAVE_HW_BREAKPOINT"] == string("y"))) throw semantic_error (_("CONFIG_HAVE_HW_BREAKPOINT not available on this kernel"), location->components[0]->tok); has_addr = get_param (parameters, TOK_HWBKPT, hwbkpt_address); has_symbol_str = get_param (parameters, TOK_HWBKPT, symbol_str_val); has_len = get_param (parameters, TOK_LENGTH, len); has_write = (parameters.find(TOK_HWBKPT_WRITE) != parameters.end()); has_rw = (parameters.find(TOK_HWBKPT_RW) != parameters.end()); if (!has_len) len = 1; if (has_addr) finished_results.push_back (new hwbkpt_derived_probe (base, location, hwbkpt_address, "",len,0, has_write, has_rw)); else if (has_symbol_str) finished_results.push_back (new hwbkpt_derived_probe (base, location, 0, symbol_str_val,len,0, has_write, has_rw)); else assert (0); } // ------------------------------------------------------------------------ // statically inserted kernel-tracepoint derived probes // ------------------------------------------------------------------------ struct tracepoint_arg { string name, c_type, typecast; bool usable, used, isptr; Dwarf_Die type_die; tracepoint_arg(): usable(false), used(false), isptr(false) {} }; struct tracepoint_derived_probe: public derived_probe { tracepoint_derived_probe (systemtap_session& s, dwflpp& dw, Dwarf_Die& func_die, const string& tracepoint_name, probe* base_probe, probe_point* location); systemtap_session& sess; string tracepoint_name, header; vector args; void build_args(dwflpp& dw, Dwarf_Die& func_die); void getargs (std::list &arg_set) const; void join_group (systemtap_session& s); void print_dupe_stamp(ostream& o); }; struct tracepoint_derived_probe_group: public generic_dpg { void emit_module_decls (systemtap_session& s); void emit_module_init (systemtap_session& s); void emit_module_exit (systemtap_session& s); }; struct tracepoint_var_expanding_visitor: public var_expanding_visitor { tracepoint_var_expanding_visitor(dwflpp& dw, const string& probe_name, vector & args): dw (dw), probe_name (probe_name), args (args) {} dwflpp& dw; const string& probe_name; vector & args; void visit_target_symbol (target_symbol* e); void visit_target_symbol_arg (target_symbol* e); void visit_target_symbol_context (target_symbol* e); }; void tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) { string argname = e->sym_name(); // search for a tracepoint parameter matching this name tracepoint_arg *arg = NULL; for (unsigned i = 0; i < args.size(); ++i) if (args[i].usable && args[i].name == argname) { arg = &args[i]; arg->used = true; break; } if (arg == NULL) { stringstream alternatives; for (unsigned i = 0; i < args.size(); ++i) alternatives << " $" << args[i].name; alternatives << " $$name $$parms $$vars"; // We hope that this value ends up not being referenced after all, so it // can be optimized out quietly. throw semantic_error(_F("unable to find tracepoint variable '%s' (alternatives: %s)", e->name.c_str(), alternatives.str().c_str()), e->tok); // NB: we can have multiple errors, since a target variable // may be expanded in several different contexts: // trace ("*") { $foo->bar } } // make sure we're not dereferencing base types if (!arg->isptr) e->assert_no_components("tracepoint", true); // we can only write to dereferenced fields, and only if guru mode is on bool lvalue = is_active_lvalue(e); if (lvalue && (!dw.sess.guru_mode || e->components.empty())) throw semantic_error(_F("write to tracepoint variable '%s' not permitted; need stap -g", e->name.c_str()), e->tok); // XXX: if a struct/union arg is passed by value, then writing to its fields // is also meaningless until you dereference past a pointer member. It's // harder to detect and prevent that though... if (e->components.empty()) { if (e->addressof) throw semantic_error(_("cannot take address of tracepoint variable"), e->tok); // Just grab the value from the probe locals symbol* sym = new symbol; sym->tok = e->tok; sym->name = "__tracepoint_arg_" + arg->name; provide (sym); } else { // make a copy of the original as a bare target symbol for the tracepoint // value, which will be passed into the dwarf dereferencing code target_symbol* e2 = deep_copy_visitor::deep_copy(e); e2->components.clear(); if (e->components.back().type == target_symbol::comp_pretty_print) { if (lvalue) throw semantic_error(_("cannot write to pretty-printed variable"), e->tok); dwarf_pretty_print dpp(dw, &arg->type_die, e2, arg->isptr, false, *e); dpp.expand()->visit (this); return; } bool userspace_p = false; string fname = (string(lvalue ? "_tracepoint_tvar_set" : "_tracepoint_tvar_get") + "_" + e->sym_name() + "_" + lex_cast(tick++)); exp_type type = pe_long; string code = dw.literal_stmt_for_pointer (&arg->type_die, e, lvalue, type); functioncall* n = synthetic_embedded_deref_call(dw.sess, fname, code, type, userspace_p, lvalue, e, e2); if (lvalue) { // Provide the functioncall to our parent, so that it can be // used to substitute for the assignment node immediately above // us. assert(!target_symbol_setter_functioncalls.empty()); *(target_symbol_setter_functioncalls.top()) = n; } // Revisit the functioncall so arguments can be expanded. n->visit (this); } } void tracepoint_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) { if (e->addressof) throw semantic_error(_("cannot take address of context variable"), e->tok); if (is_active_lvalue (e)) throw semantic_error(_F("write to tracepoint '%s' not permitted", e->name.c_str()), e->tok); if (e->name == "$$name") { e->assert_no_components("tracepoint"); // Synthesize an embedded expression. embedded_expr *expr = new embedded_expr; expr->tok = e->tok; expr->code = string("/* string */ /* pure */ ") + string("c->ips.tracepoint_name ? c->ips.tracepoint_name : \"\""); provide (expr); } else if (e->name == "$$vars" || e->name == "$$parms") { e->assert_no_components("tracepoint", true); token* pf_tok = new token(*e->tok); pf_tok->content = "sprintf"; print_format* pf = print_format::create(pf_tok); for (unsigned i = 0; i < args.size(); ++i) { if (!args[i].usable) continue; if (i > 0) pf->raw_components += " "; pf->raw_components += args[i].name; target_symbol *tsym = new target_symbol; tsym->tok = e->tok; tsym->name = "$" + args[i].name; tsym->components = e->components; // every variable should always be accessible! tsym->saved_conversion_error = 0; expression *texp = require (tsym); // NB: throws nothing ... if (tsym->saved_conversion_error) // ... but this is how we know it happened. { if (dw.sess.verbose>2) for (const semantic_error *c = tsym->saved_conversion_error; c != 0; c = c->chain) clog << _("variable location problem [man error::dwarf]: ") << c->what() << endl; pf->raw_components += "=?"; continue; } if (!e->components.empty() && e->components[0].type == target_symbol::comp_pretty_print) pf->raw_components += "=%s"; else pf->raw_components += args[i].isptr ? "=%p" : "=%#x"; pf->args.push_back(texp); } pf->components = print_format::string_to_components(pf->raw_components); provide (pf); } else assert(0); // shouldn't get here } void tracepoint_var_expanding_visitor::visit_target_symbol (target_symbol* e) { try { assert(e->name.size() > 0 && e->name[0] == '$'); if (e->name == "$$name" || e->name == "$$parms" || e->name == "$$vars") visit_target_symbol_context (e); else visit_target_symbol_arg (e); } catch (const semantic_error &er) { e->chain (er); provide (e); } } tracepoint_derived_probe::tracepoint_derived_probe (systemtap_session& s, dwflpp& dw, Dwarf_Die& func_die, const string& tracepoint_name, probe* base, probe_point* loc): derived_probe (base, loc, true /* .components soon rewritten */), sess (s), tracepoint_name (tracepoint_name) { // create synthetic probe point name; preserve condition vector comps; comps.push_back (new probe_point::component (TOK_KERNEL)); comps.push_back (new probe_point::component (TOK_TRACE, new literal_string (tracepoint_name))); this->sole_location()->components = comps; // fill out the available arguments in this tracepoint build_args(dw, func_die); // determine which header defined this tracepoint string decl_file = dwarf_decl_file(&func_die); header = decl_file; #if 0 /* This convention is not enforced. */ size_t header_pos = decl_file.rfind("trace/"); if (header_pos == string::npos) throw semantic_error ("cannot parse header location for tracepoint '" + tracepoint_name + "' in '" + decl_file + "'"); header = decl_file.substr(header_pos); #endif // tracepoints from FOO_event_types.h should really be included from FOO.h // XXX can dwarf tell us the include hierarchy? it would be better to // ... walk up to see which one was directly included by tracequery.c // XXX: see also PR9993. size_t header_pos = header.find("_event_types"); if (header_pos != string::npos) header.erase(header_pos, 12); // Now expand the local variables in the probe body tracepoint_var_expanding_visitor v (dw, name, args); v.replace (this->body); for (unsigned i = 0; i < args.size(); i++) if (args[i].used) { vardecl* v = new vardecl; v->name = "__tracepoint_arg_" + args[i].name; v->tok = this->tok; v->set_arity(0, this->tok); v->type = pe_long; v->synthetic = true; this->locals.push_back (v); } if (sess.verbose > 2) clog << "tracepoint-based " << name << " tracepoint='" << tracepoint_name << "'" << endl; } static bool resolve_tracepoint_arg_type(tracepoint_arg& arg) { Dwarf_Die type; switch (dwarf_tag(&arg.type_die)) { case DW_TAG_typedef: case DW_TAG_const_type: case DW_TAG_volatile_type: // iterate on the referent type return (dwarf_attr_die(&arg.type_die, DW_AT_type, &arg.type_die) && resolve_tracepoint_arg_type(arg)); case DW_TAG_base_type: case DW_TAG_enumeration_type: // base types will simply be treated as script longs arg.isptr = false; return true; case DW_TAG_pointer_type: // pointers can be treated as script longs, // and if we know their type, they can also be dereferenced type = arg.type_die; while (dwarf_attr_die(&arg.type_die, DW_AT_type, &arg.type_die)) { // It still might be a non-type, e.g. const void, // so we need to strip away all qualifiers. int tag = dwarf_tag(&arg.type_die); if (tag != DW_TAG_typedef && tag != DW_TAG_const_type && tag != DW_TAG_volatile_type) { arg.isptr = true; break; } } if (!arg.isptr) arg.type_die = type; arg.typecast = "(intptr_t)"; return true; case DW_TAG_structure_type: case DW_TAG_union_type: // for structs/unions which are passed by value, we turn it into // a pointer that can be dereferenced. arg.isptr = true; arg.typecast = "(intptr_t)&"; return true; default: // should we consider other types too? return false; } } void tracepoint_derived_probe::build_args(dwflpp&, Dwarf_Die& func_die) { Dwarf_Die arg; if (dwarf_child(&func_die, &arg) == 0) do if (dwarf_tag(&arg) == DW_TAG_formal_parameter) { // build a tracepoint_arg for this parameter tracepoint_arg tparg; tparg.name = dwarf_diename(&arg); // read the type of this parameter if (!dwarf_attr_die (&arg, DW_AT_type, &tparg.type_die) || !dwarf_type_name(&tparg.type_die, tparg.c_type)) throw semantic_error (_F("cannot get type of parameter '%s' of tracepoint '%s'", tparg.name.c_str(), tracepoint_name.c_str())); tparg.usable = resolve_tracepoint_arg_type(tparg); args.push_back(tparg); if (sess.verbose > 4) clog << _F("found parameter for tracepoint '%s': type:'%s' name:'%s' %s", tracepoint_name.c_str(), tparg.c_type.c_str(), tparg.name.c_str(), tparg.usable ? "ok" : "unavailable") << endl; } while (dwarf_siblingof(&arg, &arg) == 0); } void tracepoint_derived_probe::getargs(std::list &arg_set) const { for (unsigned i = 0; i < args.size(); ++i) if (args[i].usable) arg_set.push_back("$"+args[i].name+":"+args[i].c_type); } void tracepoint_derived_probe::join_group (systemtap_session& s) { if (! s.tracepoint_derived_probes) s.tracepoint_derived_probes = new tracepoint_derived_probe_group (); s.tracepoint_derived_probes->enroll (this); } void tracepoint_derived_probe::print_dupe_stamp(ostream& o) { for (unsigned i = 0; i < args.size(); i++) if (args[i].used) o << "__tracepoint_arg_" << args[i].name << endl; } static vector tracepoint_extra_decls (systemtap_session& s, const string& header) { vector they_live; // PR 9993 // XXX: may need this to be configurable they_live.push_back ("#include "); // PR11649: conditional extra header // for kvm tracepoints in 2.6.33ish if (s.kernel_config["CONFIG_KVM"] != string("")) { they_live.push_back ("#include "); } if (header.find("xfs") != string::npos && s.kernel_config["CONFIG_XFS_FS"] != string("")) { they_live.push_back ("#define XFS_BIG_BLKNOS 1"); if (s.kernel_source_tree != "") they_live.push_back ("#include \"fs/xfs/xfs_types.h\""); // in kernel-source tree they_live.push_back ("struct xfs_mount;"); they_live.push_back ("struct xfs_inode;"); they_live.push_back ("struct xfs_buf;"); they_live.push_back ("struct xfs_bmbt_irec;"); they_live.push_back ("struct xfs_trans;"); } if (header.find("nfs") != string::npos && s.kernel_config["CONFIG_NFSD"] != string("")) { they_live.push_back ("struct rpc_task;"); } // RHEL6.3 if (header.find("rpc") != string::npos && s.kernel_config["CONFIG_NFSD"] != string("")) { they_live.push_back ("struct rpc_clnt;"); they_live.push_back ("struct rpc_wait_queue;"); } they_live.push_back ("#include "); // linux 3.0 they_live.push_back ("struct cpu_workqueue_struct;"); if (header.find("ext4") != string::npos && s.kernel_config["CONFIG_EXT4_FS"] != string("")) if (s.kernel_source_tree != "") they_live.push_back ("#include \"fs/ext4/ext4.h\""); // in kernel-source tree if (header.find("ext3") != string::npos && s.kernel_config["CONFIG_EXT3_FS"] != string("")) they_live.push_back ("struct ext3_reserve_window_node;"); return they_live; } void tracepoint_derived_probe_group::emit_module_decls (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "/* ---- tracepoint probes ---- */"; s.op->newline(); // We create a MODULE_aux_N.c file for each tracepoint header, to allow them // to be separately compiled. That's because kernel tracepoint headers sometimes // conflict. PR13155. map per_header_aux; // GC NB: the translator_output* structs are owned/retained by the systemtap_session. for (unsigned i = 0; i < probes.size(); ++i) { tracepoint_derived_probe *p = probes[i]; string header = p->header; // We cache the auxiliary output files on a per-header basis. We don't // need one aux file per tracepoint, only one per tracepoint-header. translator_output *tpop = per_header_aux[header]; if (tpop == 0) { tpop = s.op_create_auxiliary(); per_header_aux[header] = tpop; // PR9993: Add extra headers to work around undeclared types in individual // include/trace/foo.h files const vector& extra_decls = tracepoint_extra_decls (s, header); for (unsigned z=0; znewline() << extra_decls[z] << "\n"; // strip include/ substring, the same way as done in get_tracequery_module() size_t root_pos = header.rfind("include/"); header = ((root_pos != string::npos) ? header.substr(root_pos + 8) : header); tpop->newline() << "#include " << endl; tpop->newline() << "#include <" << header << ">"; // Starting in 2.6.35, at the same time NOARGS was added, the callback // always has a void* as the first parameter. PR11599 tpop->newline() << "#ifdef DECLARE_TRACE_NOARGS"; tpop->newline() << "#define STAP_TP_DATA , NULL"; tpop->newline() << "#define STAP_TP_PROTO void *cb_data" << " __attribute__ ((unused))"; if (!p->args.empty()) tpop->line() << ","; tpop->newline() << "#else"; tpop->newline() << "#define STAP_TP_DATA"; tpop->newline() << "#define STAP_TP_PROTO"; if (p->args.empty()) tpop->line() << " void"; tpop->newline() << "#endif"; tpop->newline() << "#define intptr_t long"; } // collect the args that are actually in use vector used_args; for (unsigned j = 0; j < p->args.size(); ++j) if (p->args[j].used) used_args.push_back(&p->args[j]); // forward-declare the generated-side tracepoint callback tpop->newline() << "void enter_real_tracepoint_probe_" << i << "("; tpop->indent(2); if (used_args.empty()) tpop->line() << "void"; for (unsigned j = 0; j < used_args.size(); ++j) { if (j > 0) tpop->line() << ", "; tpop->line() << "int64_t"; } tpop->line() << ");"; tpop->indent(-2); // define the generated-side tracepoint callback - in the main translator-output s.op->newline() << "void enter_real_tracepoint_probe_" << i << "("; s.op->indent(2); if (used_args.empty()) s.op->newline() << "void"; for (unsigned j = 0; j < used_args.size(); ++j) { if (j > 0) s.op->line() << ", "; s.op->newline() << "int64_t __tracepoint_arg_" << used_args[j]->name; } s.op->newline() << ")"; s.op->newline(-2) << "{"; s.op->newline(1) << "const struct stap_probe * const probe = " << common_probe_init (p) << ";"; common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "probe", "stp_probe_type_tracepoint"); s.op->newline() << "c->ips.tracepoint_name = " << lex_cast_qstring (p->tracepoint_name) << ";"; for (unsigned j = 0; j < used_args.size(); ++j) { s.op->newline() << "c->probe_locals." << p->name << "." + s.up->c_localname("__tracepoint_arg_" + used_args[j]->name) << " = __tracepoint_arg_" << used_args[j]->name << ";"; } s.op->newline() << "(*probe->ph) (c);"; common_probe_entryfn_epilogue (s, true); s.op->newline(-1) << "}"; // define the real tracepoint callback function tpop->newline() << "static void enter_tracepoint_probe_" << i << "("; tpop->newline(2) << "STAP_TP_PROTO"; for (unsigned j = 0; j < p->args.size(); ++j) { if (j > 0) tpop->line() << ", "; tpop->newline() << p->args[j].c_type << " __tracepoint_arg_" << p->args[j].name; } tpop->newline() << ")"; tpop->newline(-2) << "{"; tpop->newline(1) << "enter_real_tracepoint_probe_" << i << "("; tpop->indent(2); for (unsigned j = 0; j < used_args.size(); ++j) { if (j > 0) tpop->line() << ", "; tpop->newline() << "(int64_t)" << used_args[j]->typecast << "__tracepoint_arg_" << used_args[j]->name; } tpop->newline() << ");"; tpop->newline(-3) << "}"; // emit normalized registration functions tpop->newline() << "int register_tracepoint_probe_" << i << "(void) {"; tpop->newline(1) << "return register_trace_" << p->tracepoint_name << "(enter_tracepoint_probe_" << i << " STAP_TP_DATA);"; tpop->newline(-1) << "}"; // NB: we're not prepared to deal with unreg failures. However, failures // can only occur if the tracepoint doesn't exist (yet?), or if we // weren't even registered. The former should be OKed by the initial // registration call, and the latter is safe to ignore. tpop->newline() << "void unregister_tracepoint_probe_" << i << "(void) {"; tpop->newline(1) << "(void) unregister_trace_" << p->tracepoint_name << "(enter_tracepoint_probe_" << i << " STAP_TP_DATA);"; tpop->newline(-1) << "}"; tpop->newline(); // declare normalized registration functions s.op->newline() << "int register_tracepoint_probe_" << i << "(void);"; s.op->newline() << "void unregister_tracepoint_probe_" << i << "(void);"; tpop->assert_0_indent(); } // emit an array of registration functions for easy init/shutdown s.op->newline() << "static struct stap_tracepoint_probe {"; s.op->newline(1) << "int (*reg)(void);"; s.op->newline(0) << "void (*unreg)(void);"; s.op->newline(-1) << "} stap_tracepoint_probes[] = {"; s.op->indent(1); for (unsigned i = 0; i < probes.size(); ++i) { s.op->newline () << "{"; s.op->line() << " .reg=®ister_tracepoint_probe_" << i << ","; s.op->line() << " .unreg=&unregister_tracepoint_probe_" << i; s.op->line() << " },"; } s.op->newline(-1) << "};"; s.op->newline(); } void tracepoint_derived_probe_group::emit_module_init (systemtap_session &s) { if (probes.size () == 0) return; s.op->newline() << "/* init tracepoint probes */"; s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {"; s.op->newline(1) << "rc = stap_tracepoint_probes[i].reg();"; s.op->newline() << "if (rc) {"; s.op->newline(1) << "for (j=i-1; j>=0; j--)"; // partial rollback s.op->newline(1) << "stap_tracepoint_probes[j].unreg();"; s.op->newline(-1) << "break;"; // don't attempt to register any more probes s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; // This would be technically proper (on those autoconf-detectable // kernels that include this function in tracepoint.h), however we // already make several calls to synchronze_sched() during our // shutdown processes. // s.op->newline() << "if (rc)"; // s.op->newline(1) << "tracepoint_synchronize_unregister();"; // s.op->indent(-1); } void tracepoint_derived_probe_group::emit_module_exit (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "/* deregister tracepoint probes */"; s.op->newline() << "for (i=0; i<" << probes.size() << "; i++)"; s.op->newline(1) << "stap_tracepoint_probes[i].unreg();"; s.op->indent(-1); // Not necessary: see above. // s.op->newline() << "tracepoint_synchronize_unregister();"; } struct tracepoint_query : public base_query { tracepoint_query(dwflpp & dw, const string & tracepoint, probe * base_probe, probe_point * base_loc, vector & results): base_query(dw, "*"), tracepoint(tracepoint), base_probe(base_probe), base_loc(base_loc), results(results) {} const string& tracepoint; probe * base_probe; probe_point * base_loc; vector & results; set probed_names; void handle_query_module(); int handle_query_cu(Dwarf_Die * cudie); int handle_query_func(Dwarf_Die * func); void query_library (const char *) {} void query_plt (const char *entry, size_t addr) {} static int tracepoint_query_cu (Dwarf_Die * cudie, void * arg); static int tracepoint_query_func (Dwarf_Die * func, base_query * query); }; void tracepoint_query::handle_query_module() { // look for the tracepoints in each CU dw.iterate_over_cus(tracepoint_query_cu, this, false); } int tracepoint_query::handle_query_cu(Dwarf_Die * cudie) { dw.focus_on_cu (cudie); // look at each function to see if it's a tracepoint string function = "stapprobe_" + tracepoint; return dw.iterate_over_functions (tracepoint_query_func, this, function); } int tracepoint_query::handle_query_func(Dwarf_Die * func) { dw.focus_on_function (func); assert(startswith(dw.function_name, "stapprobe_")); string tracepoint_instance = dw.function_name.substr(10); // check for duplicates -- sometimes tracepoint headers may be indirectly // included in more than one of our tracequery modules. if (!probed_names.insert(tracepoint_instance).second) return DWARF_CB_OK; derived_probe *dp = new tracepoint_derived_probe (dw.sess, dw, *func, tracepoint_instance, base_probe, base_loc); results.push_back (dp); return DWARF_CB_OK; } int tracepoint_query::tracepoint_query_cu (Dwarf_Die * cudie, void * arg) { tracepoint_query * q = static_cast(arg); if (pending_interrupts) return DWARF_CB_ABORT; return q->handle_query_cu(cudie); } int tracepoint_query::tracepoint_query_func (Dwarf_Die * func, base_query * query) { tracepoint_query * q = static_cast(query); if (pending_interrupts) return DWARF_CB_ABORT; return q->handle_query_func(func); } struct tracepoint_builder: public derived_probe_builder { private: dwflpp *dw; bool init_dw(systemtap_session& s); void get_tracequery_modules(systemtap_session& s, const vector& headers, vector& modules); public: tracepoint_builder(): dw(0) {} ~tracepoint_builder() { delete dw; } void build_no_more (systemtap_session& s) { if (dw && s.verbose > 3) clog << _("tracepoint_builder releasing dwflpp") << endl; delete dw; dw = NULL; delete_session_module_cache (s); } void build(systemtap_session& s, probe *base, probe_point *location, literal_map_t const& parameters, vector& finished_results); }; // Create (or cache) one or more tracequery .o modules, based upon the // tracepoint-related header files given. Return the generated or cached // modules[]. void tracepoint_builder::get_tracequery_modules(systemtap_session& s, const vector& headers, vector& modules) { if (s.verbose > 2) { clog << _F("Pass 2: getting a tracepoint query for %zu headers: ", headers.size()) << endl; for (size_t i = 0; i < headers.size(); ++i) clog << " " << headers[i] << endl; } map headers_cache_obj; // header name -> cache/.../tracequery_hash.o file name // Map the headers to cache .o names. Note that this has side-effects of // creating the $SYSTEMTAP_DIR/.cache/XX/... directory and the hash-log file, // so we prefer not to repeat this. vector uncached_headers; for (size_t i=0; i 2) clog << _F("Pass 2: using cached %s", tracequery_path.c_str()) << endl; // an empty file is a cached failure if (get_file_size(tracequery_path) > 0) modules.push_back (tracequery_path); } else uncached_headers.push_back(headers[i]); } else uncached_headers = headers; // If we have nothing left to search for, quit if (uncached_headers.empty()) return; map headers_tracequery_src; // header -> C-source code mapping // We could query several subsets of headers[] to make this go // faster, but let's KISS and do one at a time. for (size_t i=0; i short_decls = tracepoint_extra_decls(s, header); // add each requested tracepoint header size_t root_pos = header.rfind("include/"); short_decls.push_back(string("#include <") + ((root_pos != string::npos) ? header.substr(root_pos + 8) : header) + string(">")); osrc << "#ifdef CONFIG_TRACEPOINTS" << endl; osrc << "#include " << endl; // the kernel has changed this naming a few times, previously TPPROTO, // TP_PROTO, TPARGS, TP_ARGS, etc. so let's just dupe the latest. osrc << "#ifndef PARAMS" << endl; osrc << "#define PARAMS(args...) args" << endl; osrc << "#endif" << endl; // override DECLARE_TRACE to synthesize probe functions for us osrc << "#undef DECLARE_TRACE" << endl; osrc << "#define DECLARE_TRACE(name, proto, args) \\" << endl; osrc << " void stapprobe_##name(proto) {}" << endl; // 2.6.35 added the NOARGS variant, but it's the same for us osrc << "#undef DECLARE_TRACE_NOARGS" << endl; osrc << "#define DECLARE_TRACE_NOARGS(name) \\" << endl; osrc << " DECLARE_TRACE(name, void, )" << endl; // 2.6.38 added the CONDITION variant, which can also just redirect osrc << "#undef DECLARE_TRACE_CONDITION" << endl; osrc << "#define DECLARE_TRACE_CONDITION(name, proto, args, cond) \\" << endl; osrc << " DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))" << endl; // older tracepoints used DEFINE_TRACE, so redirect that too osrc << "#undef DEFINE_TRACE" << endl; osrc << "#define DEFINE_TRACE(name, proto, args) \\" << endl; osrc << " DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))" << endl; // add the specified decls/#includes for (unsigned z=0; z tracequery_objs = make_tracequeries(s, headers_tracequery_src); // now plop them into the cache if (s.use_cache) for (size_t i=0; i 2); modules.push_back (tracequery_path); } else // cache an empty file for failures copy_file("/dev/null", tracequery_path, s.verbose > 2); } } bool tracepoint_builder::init_dw(systemtap_session& s) { if (dw != NULL) return true; vector tracequery_modules; vector system_headers; glob_t trace_glob; // find kernel_source_tree if (s.kernel_source_tree == "") { unsigned found; DwflPtr dwfl_ptr = setup_dwfl_kernel ("kernel", &found, s); Dwfl *dwfl = dwfl_ptr.get()->dwfl; if (found) { Dwarf_Die *cudie = 0; Dwarf_Addr bias; while ((cudie = dwfl_nextcu (dwfl, cudie, &bias)) != NULL) { assert_no_interrupts(); Dwarf_Attribute attr; const char* name = dwarf_formstring (dwarf_attr (cudie, DW_AT_comp_dir, &attr)); if (name) { // check that the path actually exists locally before we try to use it if (file_exists(name)) { if (s.verbose > 2) clog << _F("Located kernel source tree (DW_AT_comp_dir) at '%s'", name) << endl; s.kernel_source_tree = name; } else { if (s.verbose > 2) clog << _F("Ignoring inaccessible kernel source tree (DW_AT_comp_dir) at '%s'", name) << endl; } break; // skip others; modern Kbuild uses same comp_dir for them all } } } } // prefixes vector glob_prefixes; glob_prefixes.push_back (s.kernel_build_tree); if (s.kernel_source_tree != "") glob_prefixes.push_back (s.kernel_source_tree); // suffixes vector glob_suffixes; glob_suffixes.push_back("include/trace/events/*.h"); glob_suffixes.push_back("include/trace/*.h"); glob_suffixes.push_back("arch/x86/kvm/*trace.h"); glob_suffixes.push_back("fs/xfs/linux-*/xfs_tr*.h"); glob_suffixes.push_back("fs/xfs/xfs_trace*.h"); // compute cartesian product vector globs; for (unsigned i=0; i duped_headers; for (unsigned z = 0; z < globs.size(); z++) { string glob_str = globs[z]; if (s.verbose > 3) clog << _("Checking tracepoint glob ") << glob_str << endl; int r = glob(glob_str.c_str(), 0, NULL, &trace_glob); if (r == GLOB_NOSPACE || r == GLOB_ABORTED) throw runtime_error("Error globbing tracepoint"); for (unsigned i = 0; i < trace_glob.gl_pathc; ++i) { string header(trace_glob.gl_pathv[i]); // filter out a few known "internal-only" headers if (endswith(header, "/define_trace.h") || endswith(header, "/ftrace.h") || endswith(header, "/trace_events.h") || endswith(header, "_event_types.h")) continue; // skip identical headers from the build and source trees. size_t root_pos = header.rfind("include/"); if (root_pos != string::npos && !duped_headers.insert(header.substr(root_pos + 8)).second) continue; system_headers.push_back(header); } globfree(&trace_glob); } // Build tracequery modules get_tracequery_modules(s, system_headers, tracequery_modules); // TODO: consider other sources of tracepoint headers too, like from // a command-line parameter or some environment or .systemtaprc dw = new dwflpp(s, tracequery_modules, true); return true; } void tracepoint_builder::build(systemtap_session& s, probe *base, probe_point *location, literal_map_t const& parameters, vector& finished_results) { if (!init_dw(s)) return; string tracepoint; assert(get_param (parameters, TOK_TRACE, tracepoint)); tracepoint_query q(*dw, tracepoint, base, location, finished_results); dw->iterate_over_modules(&query_module, &q); } // ------------------------------------------------------------------------ // Standard tapset registry. // ------------------------------------------------------------------------ void register_standard_tapsets(systemtap_session & s) { register_tapset_been(s); register_tapset_itrace(s); register_tapset_mark(s); register_tapset_procfs(s); register_tapset_timers(s); register_tapset_netfilter(s); register_tapset_utrace(s); // dwarf-based kprobe/uprobe parts dwarf_derived_probe::register_patterns(s); // XXX: user-space starter set s.pattern_root->bind_num(TOK_PROCESS) ->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE) ->bind_privilege(pr_all) ->bind(new uprobe_builder ()); s.pattern_root->bind_num(TOK_PROCESS) ->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE)->bind(TOK_RETURN) ->bind_privilege(pr_all) ->bind(new uprobe_builder ()); // kernel tracepoint probes s.pattern_root->bind(TOK_KERNEL)->bind_str(TOK_TRACE) ->bind(new tracepoint_builder()); // Kprobe based probe s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_FUNCTION) ->bind(new kprobe_builder()); s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_FUNCTION)->bind(TOK_CALL) ->bind(new kprobe_builder()); s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_MODULE) ->bind_str(TOK_FUNCTION)->bind(new kprobe_builder()); s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_MODULE) ->bind_str(TOK_FUNCTION)->bind(TOK_CALL)->bind(new kprobe_builder()); s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_FUNCTION)->bind(TOK_RETURN) ->bind(new kprobe_builder()); s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_FUNCTION)->bind(TOK_RETURN) ->bind_num(TOK_MAXACTIVE)->bind(new kprobe_builder()); s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_MODULE) ->bind_str(TOK_FUNCTION)->bind(TOK_RETURN)->bind(new kprobe_builder()); s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_MODULE) ->bind_str(TOK_FUNCTION)->bind(TOK_RETURN) ->bind_num(TOK_MAXACTIVE)->bind(new kprobe_builder()); s.pattern_root->bind(TOK_KPROBE)->bind_num(TOK_STATEMENT) ->bind(TOK_ABSOLUTE)->bind(new kprobe_builder()); //Hwbkpt based probe // NB: we formerly registered the probe point types only if the kernel configuration // allowed it. However, we get better error messages if we allow probes to resolve. s.pattern_root->bind(TOK_KERNEL)->bind_num(TOK_HWBKPT) ->bind(TOK_HWBKPT_WRITE)->bind(new hwbkpt_builder()); s.pattern_root->bind(TOK_KERNEL)->bind_str(TOK_HWBKPT) ->bind(TOK_HWBKPT_WRITE)->bind(new hwbkpt_builder()); s.pattern_root->bind(TOK_KERNEL)->bind_num(TOK_HWBKPT) ->bind(TOK_HWBKPT_RW)->bind(new hwbkpt_builder()); s.pattern_root->bind(TOK_KERNEL)->bind_str(TOK_HWBKPT) ->bind(TOK_HWBKPT_RW)->bind(new hwbkpt_builder()); s.pattern_root->bind(TOK_KERNEL)->bind_num(TOK_HWBKPT) ->bind_num(TOK_LENGTH)->bind(TOK_HWBKPT_WRITE)->bind(new hwbkpt_builder()); s.pattern_root->bind(TOK_KERNEL)->bind_num(TOK_HWBKPT) ->bind_num(TOK_LENGTH)->bind(TOK_HWBKPT_RW)->bind(new hwbkpt_builder()); // length supported with address only, not symbol names //perf event based probe register_tapset_perf(s); register_tapset_java(s); } vector all_session_groups(systemtap_session& s) { vector g; #define DOONE(x) \ if (s. x##_derived_probes) \ g.push_back ((derived_probe_group*)(s. x##_derived_probes)) // Note that order *is* important here. We want to make sure we // register (actually run) begin probes before any other probe type // is run. Similarly, when unregistering probes, we want to // unregister (actually run) end probes after every other probe type // has be unregistered. To do the latter, // c_unparser::emit_module_exit() will run this list backwards. DOONE(be); DOONE(dwarf); DOONE(uprobe); DOONE(timer); DOONE(profile); DOONE(mark); DOONE(tracepoint); DOONE(kprobe); DOONE(hwbkpt); DOONE(perf); DOONE(hrtimer); DOONE(procfs); DOONE(netfilter); // Another "order is important" item. We want to make sure we // "register" the dummy task_finder probe group after all probe // groups that use the task_finder. DOONE(utrace); DOONE(itrace); DOONE(dynprobe); DOONE(java); DOONE(task_finder); #undef DOONE return g; } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/tapsets.h000066400000000000000000000052711217430427200152520ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2005-2010 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef TAPSETS_H #define TAPSETS_H #include "config.h" #include "staptree.h" #include "elaborate.h" void check_process_probe_kernel_support(systemtap_session& s); void register_standard_tapsets(systemtap_session& sess); std::vector all_session_groups(systemtap_session& s); std::string common_probe_init (derived_probe* p); void common_probe_entryfn_prologue (systemtap_session& s, std::string statestr, std::string probe, std::string probe_type, bool overload_processing = true); void common_probe_entryfn_epilogue (systemtap_session& s, bool overload_processing); void register_tapset_been(systemtap_session& sess); void register_tapset_itrace(systemtap_session& sess); void register_tapset_mark(systemtap_session& sess); void register_tapset_procfs(systemtap_session& sess); void register_tapset_timers(systemtap_session& sess); void register_tapset_netfilter(systemtap_session& sess); void register_tapset_perf(systemtap_session& sess); void register_tapset_utrace(systemtap_session& sess); void register_tapset_java(systemtap_session& sess); std::string path_remove_sysroot(const systemtap_session& sess, const std::string& path); // ------------------------------------------------------------------------ // Generic derived_probe_group: contains an ordinary vector of the // given type. It provides only the enrollment function. template struct generic_dpg: public derived_probe_group { protected: std::vector probes; public: generic_dpg () {} void enroll (DP* probe) { probes.push_back (probe); } }; // ------------------------------------------------------------------------ // An update visitor that allows replacing assignments with a function call struct var_expanding_visitor: public update_visitor { static unsigned tick; std::stack target_symbol_setter_functioncalls; std::stack defined_ops; std::set valid_ops; const std::string *op; var_expanding_visitor (); void visit_assignment (assignment* e); void visit_pre_crement (pre_crement* e); void visit_post_crement (post_crement* e); void visit_delete_statement (delete_statement* s); void visit_defined_op (defined_op* e); private: bool rewrite_lvalue(const token *tok, const std::string& eop, expression*& lvalue, expression*& rvalue); }; #endif // TAPSETS_H /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/task_finder.cxx000066400000000000000000000065031217430427200164320ustar00rootroot00000000000000// task finder for user tapsets // Copyright (C) 2005-2009 Red Hat Inc. // Copyright (C) 2005-2007 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "session.h" #include "tapsets.h" #include "task_finder.h" #include "translate.h" #include "util.h" #include #include using namespace std; using namespace __gnu_cxx; // ------------------------------------------------------------------------ // task_finder derived 'probes': These don't really exist. The whole // purpose of the task_finder_derived_probe_group is to make sure that // stap_start_task_finder()/stap_stop_task_finder() get called only // once and in the right place. // ------------------------------------------------------------------------ struct task_finder_derived_probe: public derived_probe { // Dummy constructor for gcc 3.4 compatibility task_finder_derived_probe (): derived_probe (0, 0) { assert(0); } }; struct task_finder_derived_probe_group: public generic_dpg { public: void emit_module_decls (systemtap_session& ) { } void emit_module_init (systemtap_session& s); void emit_module_post_init (systemtap_session& s); void emit_module_exit (systemtap_session& s); // Whether or not to initialize the vma tracker bool need_vma_tracker; }; void task_finder_derived_probe_group::emit_module_init (systemtap_session& s) { s.op->newline(); if (need_vma_tracker) { s.op->newline() << "/* ---- vma tracker ---- */"; s.op->newline() << "rc = _stp_vma_init();"; s.op->newline(); } s.op->newline() << "/* ---- task finder ---- */"; s.op->newline() << "if (rc == 0) {"; s.op->newline(1) << "rc = stap_start_task_finder();"; s.op->newline() << "if (rc) {"; s.op->newline(1) << "stap_stop_task_finder();"; s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; } void task_finder_derived_probe_group::emit_module_post_init (systemtap_session& s) { s.op->newline() << "/* ---- task finder ---- */"; s.op->newline() << "stap_task_finder_post_init();"; } void task_finder_derived_probe_group::emit_module_exit (systemtap_session& s) { s.op->newline(); s.op->newline() << "/* ---- task finder ---- */"; s.op->newline() << "stap_stop_task_finder();"; if (need_vma_tracker) { s.op->newline(); s.op->newline() << "/* ---- vma tracker ---- */"; s.op->newline() << "_stp_vma_done();"; } } // Declare that task_finder is needed in this session void enable_task_finder(systemtap_session& s) { if (! s.task_finder_derived_probes) { s.task_finder_derived_probes = new task_finder_derived_probe_group(); s.task_finder_derived_probes->need_vma_tracker = false; } } // Declare that vma tracker is needed in this session, // implies that the task_finder is needed. void enable_vma_tracker(systemtap_session& s) { enable_task_finder(s); s.task_finder_derived_probes->need_vma_tracker = true; } // Whether the vma tracker is needed in this session. bool vma_tracker_enabled(systemtap_session& s) { return (s.task_finder_derived_probes && s.task_finder_derived_probes->need_vma_tracker); } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/task_finder.h000066400000000000000000000013661217430427200160610ustar00rootroot00000000000000// -*- C++ -*- // Copyright (C) 2009 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef TASK_FINDER_H #define TASK_FINDER_H // Declare that task_finder is needed in this session void enable_task_finder(systemtap_session& s); // Declare that vma tracker is needed in this session, // implies that the task_finder is needed. void enable_vma_tracker(systemtap_session& s); // Whether the vma tracker is needed in this session. bool vma_tracker_enabled(systemtap_session& s); #endif // TASK_FINDER_H /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ systemtap-2.3/testsuite/000077500000000000000000000000001217430427200154425ustar00rootroot00000000000000systemtap-2.3/testsuite/.gitignore000066400000000000000000000001341217430427200174300ustar00rootroot00000000000000.systemtap-* site.exp systemtap.log systemtap.sum dbg.log server.log *.so *_exe *.exe.[0-9] systemtap-2.3/testsuite/Makefile.am000066400000000000000000000040241217430427200174760ustar00rootroot00000000000000# Makefile.am --- automake input file for systemtap testsuite ## process this file with automake to produce Makefile.in AUTOMAKE_OPTIONS = dejagnu no-dist all-local: @echo Run \"make check\" or \"make installcheck\". @if test -n "$(DEJAZILLA)"; then echo Test results will be emailed to $(DEJAZILLA); fi clean-local: -rm -f ./stap site.exp systemtap.sum systemtap.log -rm -rf .systemtap* .cache_test* 2>/dev/null -rm -f ./stap_*.ko -rm -f flightrec* -rm -f *.so -rm -f uprobe_* DEJAZILLA=@dejazilla@ TESTAPPS=@enable_testapps@ TOOL_OPTS= # automake's dejagnu library already runs check-DEJAGNU before check-local # That's why we need to add "execrc" to $(RUNTEST) - to ensure that this # subtarget gets run even if runtest per se exits with a failure. check-local: if test -n "$(DEJAZILLA)"; then mail $(DEJAZILLA) < systemtap.sum; fi # but installcheck does not follow an implicit check-DEJAGNU, go figure installcheck: site.exp -rmmod uprobes 2>/dev/null -$(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU RUNTESTFLAGS="$(RUNTESTFLAGS) --tool_opts \'install $(TOOL_OPTS)\'" if test -n "$(DEJAZILLA)"; then mail $(DEJAZILLA) < systemtap.sum; fi # $(srcdir)/These values point the test suite to the install tree, and # are overridden by "make check" from full source/build tree SYSTEMTAP_RUNTIME=$(DESTDIR)$(pkgdatadir)/runtime SYSTEMTAP_TAPSET=$(DESTDIR)$(pkgdatadir)/tapset LD_LIBRARY_PATH=$(DESTDIR)$(libdir)/systemtap CRASH_LIBDIR=$(DESTDIR)$(libdir)/systemtap SYSTEMTAP_PATH=$(DESTDIR)$(bindir) SYSTEMTAP_INCLUDES=$(DESTDIR)$(includedir) RUNTESTDEFAULTFLAGS = --tool $$tool --tool_opts \'$(TOOL_OPTS)\' --srcdir $$srcdir EXPECT = expect RUNTEST="env XDG_DATA_DIRS= SYSTEMTAP_SYNC=1 LANG=C SYSTEMTAP_TESTREMOTES=$(TESTREMOTES) SYSTEMTAP_TESTAPPS=$(TESTAPPS) SYSTEMTAP_RUNTIME=$(SYSTEMTAP_RUNTIME) SYSTEMTAP_TAPSET=$(SYSTEMTAP_TAPSET) LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) CRASH_LIBDIR=$(CRASH_LIBDIR) PATH=$(SYSTEMTAP_PATH):$$PATH SYSTEMTAP_PATH=$(SYSTEMTAP_PATH) SYSTEMTAP_INCLUDES=$(SYSTEMTAP_INCLUDES) PKGLIBDIR=$(pkglibexecdir) $(srcdir)/execrc runtest" systemtap-2.3/testsuite/Makefile.in000066400000000000000000000267431217430427200175230ustar00rootroot00000000000000# Makefile.in generated by automake 1.12.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Makefile.am --- automake input file for systemtap testsuite VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = . DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/configure $(am__configure_deps) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DEJATOOL = $(PACKAGE) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ am__leading_dot = @am__leading_dot@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ dejazilla = @dejazilla@ docdir = @docdir@ dvidir = @dvidir@ enable_testapps = @enable_testapps@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = dejagnu no-dist DEJAZILLA = @dejazilla@ TESTAPPS = @enable_testapps@ TOOL_OPTS = # $(srcdir)/These values point the test suite to the install tree, and # are overridden by "make check" from full source/build tree SYSTEMTAP_RUNTIME = $(DESTDIR)$(pkgdatadir)/runtime SYSTEMTAP_TAPSET = $(DESTDIR)$(pkgdatadir)/tapset LD_LIBRARY_PATH = $(DESTDIR)$(libdir)/systemtap CRASH_LIBDIR = $(DESTDIR)$(libdir)/systemtap SYSTEMTAP_PATH = $(DESTDIR)$(bindir) SYSTEMTAP_INCLUDES = $(DESTDIR)$(includedir) RUNTESTDEFAULTFLAGS = --tool $$tool --tool_opts \'$(TOOL_OPTS)\' --srcdir $$srcdir EXPECT = expect RUNTEST = "env XDG_DATA_DIRS= SYSTEMTAP_SYNC=1 LANG=C SYSTEMTAP_TESTREMOTES=$(TESTREMOTES) SYSTEMTAP_TESTAPPS=$(TESTAPPS) SYSTEMTAP_RUNTIME=$(SYSTEMTAP_RUNTIME) SYSTEMTAP_TAPSET=$(SYSTEMTAP_TAPSET) LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) CRASH_LIBDIR=$(CRASH_LIBDIR) PATH=$(SYSTEMTAP_PATH):$$PATH SYSTEMTAP_PATH=$(SYSTEMTAP_PATH) SYSTEMTAP_INCLUDES=$(SYSTEMTAP_INCLUDES) PKGLIBDIR=$(pkglibexecdir) $(srcdir)/execrc runtest" all: all-am .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): tags: TAGS TAGS: ctags: CTAGS CTAGS: cscope cscopelist: check-DEJAGNU: site.exp srcdir='$(srcdir)'; export srcdir; \ EXPECT=$(EXPECT); export EXPECT; \ runtest=$(RUNTEST); \ if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \ exit_status=0; l='$(DEJATOOL)'; for tool in $$l; do \ if $$runtest $(AM_RUNTESTFLAGS) $(RUNTESTDEFAULTFLAGS) $(RUNTESTFLAGS); \ then :; else exit_status=1; fi; \ done; \ else echo "WARNING: could not find 'runtest'" 1>&2; :;\ fi; \ exit $$exit_status site.exp: Makefile $(EXTRA_DEJAGNU_SITE_CONFIG) @echo 'Making a new site.exp file ...' @echo '## these variables are automatically generated by make ##' >site.tmp @echo '# Do not edit here. If you wish to override these values' >>site.tmp @echo '# edit the last section' >>site.tmp @echo 'set srcdir "$(srcdir)"' >>site.tmp @echo "set objdir `pwd`" >>site.tmp @list='$(EXTRA_DEJAGNU_SITE_CONFIG)'; for f in $$list; do \ echo "## Begin content included from file $$f. Do not modify. ##" \ && cat `test -f "$$f" || echo '$(srcdir)/'`$$f \ && echo "## End content included from file $$f. ##" \ || exit 1; \ done >> site.tmp @echo "## End of auto-generated content; you can edit from here. ##" >> site.tmp @if test -f site.exp; then \ sed -e '1,/^## End of auto-generated content.*##/d' site.exp >> site.tmp; \ fi @-rm -f site.bak @test ! -f site.exp || mv site.exp site.bak @mv site.tmp site.exp distclean-DEJAGNU: -rm -f site.exp site.bak -l='$(DEJATOOL)'; for tool in $$l; do \ rm -f $$tool.sum $$tool.log; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU check-local check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-local mostlyclean-am distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-DEJAGNU distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: check-am install-am install-strip .PHONY: all all-am all-local am--refresh check check-DEJAGNU check-am \ check-local clean clean-generic clean-local distclean \ distclean-DEJAGNU distclean-generic dvi dvi-am html html-am \ info info-am install install-am install-data install-data-am \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-info install-info-am \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ uninstall-am all-local: @echo Run \"make check\" or \"make installcheck\". @if test -n "$(DEJAZILLA)"; then echo Test results will be emailed to $(DEJAZILLA); fi clean-local: -rm -f ./stap site.exp systemtap.sum systemtap.log -rm -rf .systemtap* .cache_test* 2>/dev/null -rm -f ./stap_*.ko -rm -f flightrec* -rm -f *.so -rm -f uprobe_* # automake's dejagnu library already runs check-DEJAGNU before check-local # That's why we need to add "execrc" to $(RUNTEST) - to ensure that this # subtarget gets run even if runtest per se exits with a failure. check-local: if test -n "$(DEJAZILLA)"; then mail $(DEJAZILLA) < systemtap.sum; fi # but installcheck does not follow an implicit check-DEJAGNU, go figure installcheck: site.exp -rmmod uprobes 2>/dev/null -$(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU RUNTESTFLAGS="$(RUNTESTFLAGS) --tool_opts \'install $(TOOL_OPTS)\'" if test -n "$(DEJAZILLA)"; then mail $(DEJAZILLA) < systemtap.sum; fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: systemtap-2.3/testsuite/aclocal.m4000066400000000000000000000610771217430427200173150ustar00rootroot00000000000000# generated automatically by aclocal 1.12.2 -*- Autoconf -*- # Copyright (C) 1996-2012 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # Copyright (C) 2002-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.12' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.12.2], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.12.2])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 10 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 19 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.62])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated. For more info, see: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl dnl Support for Objective C++ was only introduced in Autoconf 2.65, dnl but we still cater to Autoconf 2.62. m4_ifdef([AC_PROG_OBJCXX], [AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])])dnl ]) _AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl dnl The 'parallel-tests' driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering # Copyright (C) 1996-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 7 # AM_MAINTAINER_MODE([DEFAULT-MODE]) # ---------------------------------- # Control maintainer-specific portions of Makefiles. # Default is to disable them, unless 'enable' is passed literally. # For symmetry, 'disable' may be passed as well. Anyway, the user # can override the default with the --enable/--disable switch. AC_DEFUN([AM_MAINTAINER_MODE], [m4_case(m4_default([$1], [disable]), [enable], [m4_define([am_maintainer_other], [disable])], [disable], [m4_define([am_maintainer_other], [enable])], [m4_define([am_maintainer_other], [enable]) m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) dnl maintainer-mode's default is 'disable' unless 'enable' is passed AC_ARG_ENABLE([maintainer-mode], [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], am_maintainer_other[ make rules and dependencies not useful (and sometimes confusing) to the casual installer])], [USE_MAINTAINER_MODE=$enableval], [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE AC_SUBST([MAINT])dnl ] ) AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 7 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 6 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 9 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of '-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR systemtap-2.3/testsuite/buildko/000077500000000000000000000000001217430427200170735ustar00rootroot00000000000000systemtap-2.3/testsuite/buildko/one.stp000077500000000000000000000003711217430427200204100ustar00rootroot00000000000000#! /bin/sh stap -p4 -g - $@ <<'END' %{ #include %} function get_release () %{ /* this is a type error, detected by gcc */ STAP_RETVALUE = 5; %} probe begin { log("hello from systemtap, kernel version " . get_release()) } END systemtap-2.3/testsuite/buildko/three.stp000077500000000000000000000001031217430427200207270ustar00rootroot00000000000000#! stap -gp4 probe begin { %{ /* not pure */ SYNTAX ERROR %} } systemtap-2.3/testsuite/buildko/two.stp000077500000000000000000000004301217430427200204340ustar00rootroot00000000000000#! stap -p4 # tests overwide arrays global a10 global b10 global c10 global d10 probe begin { a10[0,"a",0,"a",0,"a",0,"a",0,"a"]="a"; b10["b",0,"b",0,"b",0,"b",0,"b",0]=0; c10[0,"a",0,"a",0,"a",0,"a",0,"a"]<<<0; d10["b",0,"b",0,"b",0,"b",0,"b",0]<<<0; } systemtap-2.3/testsuite/buildok/000077500000000000000000000000001217430427200170735ustar00rootroot00000000000000systemtap-2.3/testsuite/buildok/alias_suffixes01.stp000077500000000000000000000001431217430427200227720ustar00rootroot00000000000000#! stap -p4 probe a.d = begin { } probe b = a { } probe b.d { print("Hello, World!\n") exit() } systemtap-2.3/testsuite/buildok/alias_suffixes02.stp000077500000000000000000000001161217430427200227730ustar00rootroot00000000000000#! stap -p4 probe syscall.open.return.maxactive(10) { printf("%s\n", pp()) } systemtap-2.3/testsuite/buildok/alias_suffixes03.stp000077500000000000000000000002371217430427200230000ustar00rootroot00000000000000#! stap -p4 # additional layer of indirection for alias suffixes probe a = syscall.open.return { } probe a.maxactive(10) { printf ("%s %s\n", pn(), pp()) } systemtap-2.3/testsuite/buildok/alias_suffixes04.stp000077500000000000000000000004221217430427200227750ustar00rootroot00000000000000#! stap -p4 # this defines three distinct derived probes from one suffixed probe probe a = syscall.open.return { print ("1 ") } probe a += syscall.open.return { print ("2 ") } probe a = syscall.close.return { print ("3 ") } probe a.maxactive(10) { printf ("%s\n", pp()) } systemtap-2.3/testsuite/buildok/alias_suffixes05.stp000077500000000000000000000002421217430427200227760ustar00rootroot00000000000000#! stap -p4 # the begin probe alias should be ignored probe a = syscall.open.return { print ("a") } probe a = begin ? { print ("b") } probe a.maxactive(10) { } systemtap-2.3/testsuite/buildok/alias_suffixes06.stp000077500000000000000000000003461217430427200230040ustar00rootroot00000000000000#! stap -p4 # probes will all expand to syscall.open.return.maxactive(10) probe syscall.open.return.maxact*(10) { print("a") } probe syscall.open.return.maxact**(10) { print("b") } probe syscall.open.return.*(10) { print("c") } systemtap-2.3/testsuite/buildok/array_size.stp000077500000000000000000000005151217430427200217770ustar00rootroot00000000000000#! stap -p4 # test reading & writing for little, big, and default arrays, with various # index types mixed in. global a[1], b[100000], c probe begin { a[42, "foobar"] = "Hello World!" b["foo", "bar", "baz", 42] = 314159265 c[42] = 161803399 printf("%s %d %d\n", a[42, "foobar"], b["foo", "bar", "baz", 42], c[42]) } systemtap-2.3/testsuite/buildok/atomic.stp000077500000000000000000000001551217430427200211030ustar00rootroot00000000000000#! stap -p4 probe begin { printf("%d\n", atomic_read(0)) printf("%d\n", atomic_long_read(0)) exit() } systemtap-2.3/testsuite/buildok/aux_syscalls-embedded.stp000077500000000000000000000055511217430427200240750ustar00rootroot00000000000000#! stap -p4 probe begin { print (_struct_timeval_u(0,0)) print (_struct_compat_timeval_u(0,0)) print (_struct_timezone_u (0)) print (_struct_utimbuf_actime(0)) print (_struct_utimbuf_modtime(0)) print (_struct_compat_utimbuf_actime(0)) print (_struct_compat_utimbuf_modtime(0)) print (_struct_timespec_u(0,0)) print (_struct_compat_timespec_u(0,0)) print (_struct_itimerspec_u(0)) print (_struct_itimerval_u(0)) print (_struct_compat_itimerval_u(0)) print (_struct_sockaddr_u(0,0)) print (_struct_rlimit_u(0)) print (_fildes_index_u(0, 0)) print (__sem_flags(0)) print (__get_argv(0,0)) print (__get_compat_argv(0,0)) print (_adjtx_mode_str(0)) print (_inotify_watch_mask_str(0)) print (_sigprocmask_how_str(0)) print (_itimer_which_str(0)) # nfsservctl was removed in kernel 3.0/2.6.40. %( kernel_v < "2.6.40" && CONFIG_NFSD == "[ym]" %? print (_nfsctl_cmd_str(0)) %) print (_get_wc_str(0)) print (_flock_cmd_str(0)) print (_sys_pipe2_flag_str(0)) print (_sys_open_flag_str(0)) print (_access_mode_str(0)) print (_sys_open_mode_str(0)) print (_mknod_mode_str(0)) print (_msync_flag_str(0)) print (_wait4_opt_str(0)) print (_waitid_opt_str(0)) print (_sendflags_str(0)) print (_recvflags_str(0)) print (_mlockall_flags_str(0)) print (_module_flags_str(0)) print (_sched_policy_str(0)) print (_priority_which_str(0)) print (_shutdown_how_str(0)) print (_reboot_magic_str(0)) print (_reboot_flag_str(0)) print (_waitid_which_str(0)) print (_futex_op_str(0)) print (_mountflags_str(0)) print (_umountflags_str(0)) print (_statfs_f_type_str(0)) print (_mremap_flags(0)) print (_madvice_advice_str(0)) print (_fadvice_advice_str(0)) print (_fcntl_cmd_str(0)) print (_seek_whence_str(0)) print (_quotactl_cmd_str(0)) print (_sockopt_optname_str(0)) print (_sockopt_level_str(0)) print (_sock_family_str(0)) print (_sock_type_str(0)) print (_sock_flags_str(0)) print (_opoll_op_str(0)) print (_epoll_events_str(0)) print (_rlimit_resource_str(0)) print (_rusage_who_str(0)) print (__short(0)) print (__int32(0)) print (__ulong(0)) print (_dfd_str(0)) print (_adjtimex_return_str(0)) print (_signal_name(0)) print (_semctl_cmd(0)) print (_stp_sigset_u(0)) print (__fork_flags(0)) print (_at_flag_str(0)) print (_epoll_create1_flag_str(0)) print (_eventfd2_flag_str(0)) print (_signalfd4_flags_str(0)) print (_inotify_init1_flag_str(0)) print (_dup3_flag_str(0)) print (_shmat_flags_str(0)) print (_mprotect_prot_str(0)) print (_mmap_flags(0)) print (get_mmap_args(0)) print (_sighandler_str(0)) print (_struct_sigaction_u(0)) print (_struct_sigaction32_u(0)) print (_struct_old_sigaction32_u(0)) print (irqflags_str(0)) print (_ptrace_argstr(0,0,0,0)) print (_ptrace_return_geteventmsg_data(0,0)) # Implementation is in arch specific files but with compatible API. print (_ptrace_return_arch_prctl_addr(0,0,0)) } systemtap-2.3/testsuite/buildok/cmdline01.stp000077500000000000000000000010361217430427200214020ustar00rootroot00000000000000#!/bin/sh # -g Guru mode. Enable parsing of unsafe expert-level constructs # like embedded C. # # -D NAME=VALUE # Add the given C preprocessor directive to the module Makefile. # Test '-g' and '-D'. The code below will give an error at # compilation stage unless 'FOO' is defined. stap $@ -g -p4 -DFOO=1 - <&1 >/dev/null ||true ` if echo "$errors" | grep -q unable.to.find.local then echo "Unexpected error $errors"; exit 1 fi echo 'probe kernel.statement("'$fn':'$ilineno'") {$'$var'}' '#' OK done systemtap-2.3/testsuite/buildok/four.stp000077500000000000000000000001761217430427200206050ustar00rootroot00000000000000#! stap -p4 probe module("ext3").function("*") ? { log ("ext3 fn") } /*to avoid empty file*/ probe begin { log("begin") } systemtap-2.3/testsuite/buildok/fourteen-plus.stp000077500000000000000000000016511217430427200224410ustar00rootroot00000000000000#! stap -tp4 # NB: beyond just checking for timer compilability, this test also plays # with duplicate probe elimination logic. See also fourteen+.stp global i, j probe timer.jiffies(100) { i++ } probe timer.jiffies(100).randomize(100) { j++ } probe timer.s(100) { i++ } probe timer.s(100).randomize(100) { j++ } probe timer.sec(100) { i++ } probe timer.sec(100).randomize(100) { j++ } probe timer.ms(100) { i++ } probe timer.ms(100).randomize(100) { j++ } probe timer.msec(100) { i++ } probe timer.msec(100).randomize(100) { j++ } probe timer.us(100) { i++ } probe timer.us(100).randomize(100) { j++ } probe timer.usec(100) { i++ } probe timer.usec(100).randomize(100) { j++ } probe timer.ns(100000) { i++ } probe timer.ns(100000).randomize(100) { j++ } probe timer.nsec(100000) { i++ } probe timer.nsec(100000).randomize(100) { j++ } probe timer.hz(100) { i++ } probe timer.profile { i++ } probe end { printf("i=%d j=%d\n", i, j) } systemtap-2.3/testsuite/buildok/fourteen.stp000077500000000000000000000016501217430427200214570ustar00rootroot00000000000000#! stap -p4 # NB: beyond just checking for timer compilability, this test also plays # with duplicate probe elimination logic. See also fourteen+.stp global i, j probe timer.jiffies(100) { i++ } probe timer.jiffies(100).randomize(100) { j++ } probe timer.s(100) { i++ } probe timer.s(100).randomize(100) { j++ } probe timer.sec(100) { i++ } probe timer.sec(100).randomize(100) { j++ } probe timer.ms(100) { i++ } probe timer.ms(100).randomize(100) { j++ } probe timer.msec(100) { i++ } probe timer.msec(100).randomize(100) { j++ } probe timer.us(100) { i++ } probe timer.us(100).randomize(100) { j++ } probe timer.usec(100) { i++ } probe timer.usec(100).randomize(100) { j++ } probe timer.ns(100000) { i++ } probe timer.ns(100000).randomize(100) { j++ } probe timer.nsec(100000) { i++ } probe timer.nsec(100000).randomize(100) { j++ } probe timer.hz(100) { i++ } probe timer.profile { i++ } probe end { printf("i=%d j=%d\n", i, j) } systemtap-2.3/testsuite/buildok/globals.stp000077500000000000000000000007001217430427200212460ustar00rootroot00000000000000#! stap -p4 # test that all known global types work at once global scalar_int global scalar_string global scalar_stat global map_int global map_string global pmap_stat probe begin { scalar_int = 42 scalar_string = "42" scalar_stat <<< 42 map_int[0] = 42 map_string[0] = "42" pmap_stat[0] <<< 42 } probe end { printdln("\t", scalar_int, scalar_string, @sum(scalar_stat), map_int[0], map_string[0], @sum(pmap_stat[0])) } systemtap-2.3/testsuite/buildok/gtod_init.stp000077500000000000000000000005011217430427200216020ustar00rootroot00000000000000#! stap -gp4 %( runtime == "kernel" %? # check that STAP_NEED_GETTIMEOFDAY is defined with a gettimeofday function check() %{ #ifndef STAP_NEED_GETTIMEOFDAY #error "gettimeofday should define STAP_NEED_GETTIMEOFDAY!" #endif %} %) probe begin { %( runtime == "kernel" %? check() %) println(gettimeofday_s()) } systemtap-2.3/testsuite/buildok/gtod_noinit.stp000077500000000000000000000004761217430427200221520ustar00rootroot00000000000000#! stap -gp4 %( runtime == "kernel" %? # check that STAP_NEED_GETTIMEOFDAY is NOT defined without a gettimeofday function check() %{ #ifdef STAP_NEED_GETTIMEOFDAY #error "STAP_NEED_GETTIMEOFDAY should not be defined!" #endif %} %) probe begin { %( runtime == "kernel" %? check() %) println(get_cycles()) } systemtap-2.3/testsuite/buildok/guru.stp000077500000000000000000000001441217430427200206070ustar00rootroot00000000000000#! stap -gp4 probe begin { mdelay(100); udelay(-1); panic("yo"); raise(%{ SIGINT %}); } systemtap-2.3/testsuite/buildok/histogram_operator_in.stp000077500000000000000000000005631217430427200242300ustar00rootroot00000000000000#! stap -p4 global foo global i probe begin { print("starting up\n") i = 0 } probe timer.jiffies(100) { printf("ping %d\n", i) foo <<< i if (i++ > 15) exit() } probe end { print("shutting down\n") printf("count %d, avg %d\n", @count(foo), @avg(foo)) for (i = 0; i < 7; ++i) { if (i in @hist_log(foo)) { printf("entry in bucket %d\n", i); } } } systemtap-2.3/testsuite/buildok/hwbkpt.stp000077500000000000000000000003661217430427200211320ustar00rootroot00000000000000#! stap -wp4 probe %(CONFIG_PERF_EVENTS=="y" && CONFIG_HAVE_HW_BREAKPOINT=="y" %? kernel.data("pid_max").write %: never %) {} probe %(CONFIG_PERF_EVENTS=="y" && CONFIG_HAVE_HW_BREAKPOINT=="y" %? kernel.data("pid_max").rw %: never %) {} systemtap-2.3/testsuite/buildok/indent.stp000077500000000000000000000001771217430427200211140ustar00rootroot00000000000000#! stap -p4 probe begin { print (thread_indent (1)) print ("yo\n") print (thread_indent (-1)) print ("ta\n") exit () } systemtap-2.3/testsuite/buildok/inet-embedded.stp000077500000000000000000000002571217430427200223200ustar00rootroot00000000000000#! stap -p4 # probe begin { print (ntohll(0xfedcba9876543210) + ntohl(0xdeadbeef) + ntohs(0xd00d) + htonll(0x0123456789abcdef) + htonl(0xff0000ff) + htons(0xabcd)) } systemtap-2.3/testsuite/buildok/inet_sock-embedded.stp000077500000000000000000000002271217430427200233340ustar00rootroot00000000000000#! stap -p4 probe begin { print (inet_get_local_port (0)) print (inet_get_ip_source (0)) %(systemtap_v < "2.0" %? print (daddr_to_string(0)) %) } systemtap-2.3/testsuite/buildok/ioblock-all-probes.stp000077500000000000000000000001611217430427200233040ustar00rootroot00000000000000#! stap -wp4 // Tests if all probes in ioblock.stp are resolvable. probe ioblock.*, ioblock_trace.* ? {} systemtap-2.3/testsuite/buildok/ioblock-detailed.stp000077500000000000000000000015021217430427200230170ustar00rootroot00000000000000#! stap -p4 probe ioblock.request { printf("%s\n", name) add_part = 0 if (bdev != bdev_contains) add_part = p_start_sect printf("%s\t%d\t%d\t%d\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", devname, sector, flags, rw, bio_rw_str(rw), vcnt, idx, phys_segments, hw_segments, size, add_part, ino) printf("%p %p\n", bdev, bdev_contains) } probe ioblock.end { printf("%s\n", name) printf("%s\t%d\t%d\t%d\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", devname, sector, flags, rw, bio_rw_str(rw), vcnt, idx, phys_segments, hw_segments, size, bytes_done, error, ino) } probe ioblock_trace.* ? { printf("%s\n", name) printf("%s\t%d\t%d\t%d\t%d\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%p\t%p\t%d\n", devname, q, sector, flags, rw, bio_rw_str(rw), vcnt, idx, phys_segments, size, bytes_done, ino, p_start_sect, bdev_contains, bdev) } systemtap-2.3/testsuite/buildok/ioblock-embedded.stp000077500000000000000000000002251217430427200227760ustar00rootroot00000000000000#! stap -p4 probe begin { print (__bio_ino (0) + bio_rw_num (0) + __bio_start_sect (0)) print (__bio_devname (0)) print (bio_rw_str(0)) } systemtap-2.3/testsuite/buildok/ioscheduler-all-probes.stp000077500000000000000000000002351217430427200241720ustar00rootroot00000000000000#! stap -wp4 // Tests if all probes in the ioscheduler tapset are resolvable. probe ioscheduler.*, ioscheduler.*.return {} probe ioscheduler_trace.* ? {} systemtap-2.3/testsuite/buildok/ioscheduler-detailed.stp000077500000000000000000000026621217430427200237130ustar00rootroot00000000000000#! stap -p4 # Normally we'd just test the ioscheduler.* probes, not the # ioscheduler.*.kp/ioscheduler.*.tp underlying probe aliases. On # systems where the tracepoint aliases are used (*.tp), we'd never # test the kprobes aliases (*.kp). This could cause them to get out # of sync with the kprobed functions. So, we test them explicitly. probe ioscheduler.elv_next_request { printf("%s: %s\n", name, elevator_name) } probe ioscheduler.elv_next_request.return { printf("name: %s, %d, %d, %p, %d", name, disk_major, disk_minor, rq, rq_flags) } probe ioscheduler.elv_completed_request { printf("name: %s, elv_name: %s, %d, %d, %p, %d", name, elevator_name, disk_major, disk_minor, rq, rq_flags) } probe ioscheduler.elv_add_request, ioscheduler.elv_add_request.kp, ioscheduler.elv_add_request.tp ? { printf("name: %s, elv_name: %s, %d, %d, %p, %d", name, elevator_name, disk_major, disk_minor, rq, rq_flags) printf("%p\n", q) } probe ioscheduler_trace.elv_completed_request ?, ioscheduler_trace.elv_issue_request ?, ioscheduler_trace.elv_requeue_request ?, ioscheduler_trace.elv_abort_request ? { printf("name: %s, request %p, elv_name: %s, %d, %d, %d\n", name, rq, elevator_name, disk_major, disk_minor, rq_flags) } probe ioscheduler_trace.plug ?, ioscheduler_trace.unplug_io ?, ioscheduler_trace.unplug_timer ? { printf("name: %s, request %p", name, rq_queue) } systemtap-2.3/testsuite/buildok/ioscheduler-embedded.stp000077500000000000000000000001401217430427200236560ustar00rootroot00000000000000#! stap -p4 probe begin { print (disk_major_from_request (0) + disk_minor_from_request (0)) } systemtap-2.3/testsuite/buildok/ip-embedded.stp000077500000000000000000000005301217430427200217630ustar00rootroot00000000000000#! stap -p4 probe begin { printf("%s\n", format_ipaddr(0, 0)) printf("%s\n", ip_ntop(0)) printf("%d\n", __ip_sock_saddr(0)) printf("%d\n", __ip_sock_daddr(0)) printf("%d\n", __ip_sock_family(0)) printf("%d\n", __get_skb_iphdr(0)) printf("%d\n", __ip_skb_proto(0)) printf("%d\n", __ip_skb_saddr(0)) printf("%d\n", __ip_skb_daddr(0)) } systemtap-2.3/testsuite/buildok/ipmib-all-probes.stp000077500000000000000000000007431217430427200227700ustar00rootroot00000000000000#! stap -p4 // Tests if all probes in the ipmib tapset are resolvable. probe ipmib.* {} function ipmib_filter_key:long (skb:long, op:long, SourceIsLocal:long) { // Insure all these functions will build if ( ipmib_remote_addr(skb, SourceIsLocal) ) return 0 if ( ipmib_local_addr(skb, SourceIsLocal) ) return 0 if ( ipmib_tcp_remote_port(skb, SourceIsLocal) ) return 0 if ( ipmib_tcp_local_port(skb, SourceIsLocal) ) return 0 if ( ipmib_get_proto(skb) ) return 0 return op } systemtap-2.3/testsuite/buildok/ipmib-detailed.stp000077500000000000000000000013001217430427200224710ustar00rootroot00000000000000#! stap -p4 function ipmib_filter_key:long (skb:long, op:long, SourceIsLocal:long) { // Insure all these functions will build if ( ipmib_remote_addr(skb, SourceIsLocal) ) return 0 if ( ipmib_local_addr(skb, SourceIsLocal) ) return 0 if ( ipmib_tcp_remote_port(skb, SourceIsLocal) ) return 0 if ( ipmib_tcp_local_port(skb, SourceIsLocal) ) return 0 if ( ipmib_get_proto(skb) ) return 0 return op } probe ipmib.InReceives, ipmib.InNoRoutes, ipmib.InAddrErrors, ipmib.InUnknownProtos, ipmib.InDiscards, %( kernel_v >= "2.6.24" %? ipmib.ForwDatagrams, %) ipmib.OutRequests, ipmib.ReasmTimeout, ipmib.ReasmReqds, ipmib.FragOKs, ipmib.FragFails { printf("%p %d\n", skb, op) } systemtap-2.3/testsuite/buildok/ipmib-embedded.stp000077500000000000000000000012751217430427200224620ustar00rootroot00000000000000#! stap -p4 probe begin { printf("%d\n", ipmib_remote_addr(0, 0)) printf("%d\n", ipmib_local_addr(0, 0)) printf("%d\n", ipmib_tcp_remote_port(0, 0)) printf("%d\n", ipmib_tcp_local_port(0, 0)) printf("%d\n", ipmib_get_proto(0)) printf("%d\n", _plunge_into_tcphdr(0)) printf("%d\n", _ehostunreach()) printf("%d\n", _enetunreach()) printf("%d\n", _icmp_dest_unreach()) printf("%d\n", _icmp_prot_unreach()) printf("%d\n", _net_rx_drop()) printf("%d\n", _icmp_time_exceeded()) printf("%d\n", _icmp_exc_fragtime()) printf("%d\n", _rtn_multicast()) printf("%d\n", _rtn_broadcast()) printf("%d\n", _rtn_unspec()) printf("%d\n", _input_route_type(0)) printf("%d\n", _output_route_type(0)) } systemtap-2.3/testsuite/buildok/irq-all-probes.stp000077500000000000000000000002351217430427200224570ustar00rootroot00000000000000#! stap -wp4 // Tests if all probes in irq tapset are resolvable probe workqueue.* !, never {} probe irq_handler.* !, never {} probe softirq.* !, never {} systemtap-2.3/testsuite/buildok/irq-detailed.stp000077500000000000000000000013151217430427200221720ustar00rootroot00000000000000#! stap -p4 # # workqueue probes # probe workqueue.create ? { printf("%p %d\n", wq_thread, cpu) } probe workqueue.insert ?, workqueue.execute ? { printf("%p %p %p\n", wq_thread, work, work_func) } probe workqueue.destroy ? { printf("%p\n", wq_thread) } # # irq_handler probes # probe irq_handler.entry ?, irq_handler.exit ? { printf("%d %p %p %d(%s)\n", irq, action, handler, flags, flags_str) printf("%d %d %p %p\n", dev_name, dev_id, next_irqaction, dir) printf("%p %p %d\n", thread_fn, thread, thread_flags) } # # softirq probes # probe softirq.entry ?, softirq.exit ? { printf("%p %p %p %d\n", h, vec, action, vec_nr) } # Make sure we've got at least one probe. probe never { printf("never\n") } systemtap-2.3/testsuite/buildok/iterate_histogram_buckets.stp000077500000000000000000000006471217430427200250670ustar00rootroot00000000000000#! stap -p4 global foo global i probe begin { print("starting up\n") i = 0 } probe timer.jiffies(100) { printf("ping %d\n", i) foo <<< i if (i++ > 15) exit() } probe end { print("shutting down\n") printf("count %d, avg %d\n", @count(foo), @avg(foo)) foreach (bucket in @hist_log(foo)) { if (@hist_log(foo)[bucket] > 0) printf("bucket %d: %d\n", bucket, @hist_log(foo)[bucket]) continue break } } systemtap-2.3/testsuite/buildok/kprocess-all-probes.stp000077500000000000000000000001411217430427200235110ustar00rootroot00000000000000#! stap -wp4 // Tests if all probes in the process tapset are resolvable. probe kprocess.* { } systemtap-2.3/testsuite/buildok/kprocess-detailed.stp000077500000000000000000000006461217430427200232360ustar00rootroot00000000000000#! stap -p4 probe kprocess.create { printf("%p %d\n", task, new_pid) } probe kprocess.start { printf("%s\n", pp()) } probe kprocess.exec { printf("%s\n", filename) } probe kprocess.exec_complete { printf("%d %d\n", errno, success) } probe kprocess.exit { printf("%d\n", code) } probe kprocess.release { printf("%p %d %d\n", task, released_pid, released_tid) %(systemtap_v <= "1.7" %? printf("%d\n", pid) %) } systemtap-2.3/testsuite/buildok/kprocess-embedded.stp000077500000000000000000000000711217430427200232040ustar00rootroot00000000000000#! stap -p4 probe begin { printf("%d\n", _IS_ERR(0)) } systemtap-2.3/testsuite/buildok/linuxmib-all-probes.stp000077500000000000000000000001401217430427200235060ustar00rootroot00000000000000#! stap -p4 // Tests if all probes in the linuxmib tapset are resolvable. probe linuxmib.* {} systemtap-2.3/testsuite/buildok/linuxmib-detailed.stp000077500000000000000000000002321217430427200232230ustar00rootroot00000000000000#! stap -p4 probe linuxmib.DelayedACKs, linuxmib.ListenOverflows, linuxmib.ListenDrops, linuxmib.TCPMemoryPressures { printf("%p %d\n", sk, op) } systemtap-2.3/testsuite/buildok/logging-embedded.stp000077500000000000000000000004161217430427200230040ustar00rootroot00000000000000#! stap -gp4 // build-test the logging tapset functions probe begin { log("log") warn("warn") exit() error("error") stp_print_binary(1, 0, 0, 0, 0) ftrace("ftrace") printk(0,"Zoink! The paper tape punch is burning chads!") } systemtap-2.3/testsuite/buildok/maxactive01.stp000077500000000000000000000001251217430427200217460ustar00rootroot00000000000000#! stap -p4 probe kernel.function("vfs_read").return.maxactive(3) { printf("."); } systemtap-2.3/testsuite/buildok/memory-all-probes.stp000077500000000000000000000001401217430427200231670ustar00rootroot00000000000000#! stap -wp4 // Tests if all probes in memory.stp are resolvable. probe vm.*, vm.*.* {} systemtap-2.3/testsuite/buildok/memory-detailed.stp000077500000000000000000000056401217430427200227140ustar00rootroot00000000000000#! stap -p4 probe vm.pagefault { printf("%s: %p %d\n", name, address, write_access) } probe vm.pagefault.return { printf("%s: %d\n", name, fault_type) } probe vm.write_shared { printf("%s: %p\n", name, address) } # vm.write_shared_copy test moved to memory-write_shared_copy.stp # vm.mmap test moved to memory-mmap.stp probe vm.munmap, vm.brk { printf("%s: %p %d\n", name, address, length) } probe vm.oom_kill { printf("%s: %p\n", name, task) } probe vm.kmalloc { printf("%s\n", name) printf("%-15s %-15p %-15s %-15p %-15d %-15d %-15d %-15s\n", execname(), call_site, caller_function, ptr, bytes_req, bytes_alloc, gfp_flags, gfp_flag_name) } # Normally we don't test "internal" probes, but let's make sure the # kprobes-based fallback probes actually work. probe __vm.kmalloc.kp { printf("%-15s %-15p %-15s %-15p %-15d %-15d %-15d %-15s\n", execname(), call_site, caller_function, ptr, bytes_req, bytes_alloc, gfp_flags, gfp_flag_name) } probe vm.kmem_cache_alloc { println(name) printf("%-15s %-15p %-15s %-15p %-15d %-15d %-15d %-15s \n", execname(), call_site, caller_function, ptr, bytes_req, bytes_alloc, gfp_flags, gfp_flag_name) } probe __vm.kmem_cache_alloc.kp { printf("%-15s %-15p %-15s %-15p %-15d %-15d %-15d %-15s \n", execname(), call_site, caller_function, ptr, bytes_req, bytes_alloc, gfp_flags, gfp_flag_name) } probe vm.kmalloc_node ? { println(name) printf("%-15s %-15p %-15s %-15p %-15d %-15d %-15d %-15s \n", execname(), call_site, caller_function, ptr, bytes_req, bytes_alloc, gfp_flags, gfp_flag_name) } probe __vm.kmalloc_node.kp ? { printf("%-15s %-15p %-15s %-15p %-15d %-15d %-15d %-15s \n", execname(), call_site, caller_function, ptr, bytes_req, bytes_alloc, gfp_flags, gfp_flag_name) } probe vm.kmem_cache_alloc_node ? { println(name) printf("%-15s %-15p %-15s %-15p %-15d %-15d %-15d %-15s \n", execname(), call_site, caller_function, ptr, bytes_req, bytes_alloc, gfp_flags, gfp_flag_name) } probe __vm.kmem_cache_alloc_node.kp ? { printf("%-15s %-15p %-15s %-15p %-15d %-15d %-15d %-15s \n", execname(), call_site, caller_function, ptr, bytes_req, bytes_alloc, gfp_flags, gfp_flag_name) } probe vm.kfree { println(name) printf("%-15s %-15p %-15s %-15p \n", execname(), call_site, caller_function, ptr) } probe __vm.kfree.kp { printf("%-15s %-15p %-15s %-15p \n", execname(), call_site, caller_function, ptr) } probe vm.kmem_cache_free { println(name) printf("%-15s %-15p %-15s %-15p \n", execname(), call_site, caller_function, ptr) } probe __vm.kmem_cache_free.kp { printf("%-15s %-15p %-15s %-15p \n", execname(), call_site, caller_function, ptr) } systemtap-2.3/testsuite/buildok/memory-embedded.stp000077500000000000000000000002441217430427200226650ustar00rootroot00000000000000#! stap -p4 probe begin { printf("%d\n", vm_fault_contains(0, 0) + addr_to_node(0) + _IS_ZERO_PAGE(0, 0) + GFP_KERNEL()) printf("%s\n", __gfp_flag_str(0)) } systemtap-2.3/testsuite/buildok/memory-mmap.stp000077500000000000000000000002631217430427200220670ustar00rootroot00000000000000#! stap -p4 # This fails on some kernels because we can't find the arguments to # this inline function (PR 1155). probe vm.mmap { printf("%s: %p %d\n", name, address, length) } systemtap-2.3/testsuite/buildok/memory-write_shared_copy.stp000077500000000000000000000004771217430427200246560ustar00rootroot00000000000000#! stap -p4 # This test fails on some kernels because we can't find the arguments to # this inline function (PR 1155). probe vm.write_shared_copy ? { printf("%s: %p %d\n", name, address, zero) } # Make sure this file compiles on kernels where vm.write_shared_copy # doesn't exist. probe begin { printf("begin\n") } systemtap-2.3/testsuite/buildok/memory.stp000077500000000000000000000002731217430427200211400ustar00rootroot00000000000000#! stap -p4 probe vm.pagefault { printf("ppname: %s, %d, %p\n", probefunc(), write_access, address) } probe vm.pagefault.return { printf("ppname: %s, %d\n", probefunc(), fault_type) } systemtap-2.3/testsuite/buildok/nd_syscalls-all-probes.stp000077500000000000000000000001771217430427200242070ustar00rootroot00000000000000#! stap -wp4 probe nd_syscall.* { printf("%s (%s)\n", name, argstr) } probe nd_syscall.*.return { printf("%s\n", retstr) } systemtap-2.3/testsuite/buildok/nd_syscalls-arch-detailed.stp000077500000000000000000000246321217430427200246370ustar00rootroot00000000000000#! stap -p4 # # Arch-specific probes that all/most arches support. # # Newer kernel's nd_syscall.mmap2 tests are in nd_syscalls-detailed.stp. %( kernel_v < "2.6.33" %? %( arch != "i386" %? probe nd_syscall.mmap { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %d, %d, %d\n", start, len, prot, flags, fd, offset) } probe nd_syscall.mmap.return { printf("%s, %s\n", name, retstr) } %) probe nd_syscall.mmap2 ? { printf("%s, %s\n", name, argstr) printf("%p, %d, %d, %d, %d, %d", start, length, prot, flags, fd, pgoffset) } probe nd_syscall.mmap2.return ? { printf("%s, %s\n", name, retstr) } %) %( CONFIG_GENERIC_SIGALTSTACK == "n" %? probe nd_syscall.sigaltstack ? { printf("%s, %s\n", name, argstr) printf("%p, %p\n", uss_uaddr, uoss_uaddr) %(systemtap_v < "2.3" %? printf("%p\n", regs) %) } probe nd_syscall.sigaltstack.return ? { printf("%s, %s\n", name, retstr) } %) probe nd_syscall.sys32_sigaltstack ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.sys32_sigaltstack.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.sysctl ?, nd_syscall.sysctl32 ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.sysctl.return ?, nd_syscall.sysctl32.return ? { printf("%s, %s\n", name, retstr) } # # i386-specific probes # %( arch == "i386" %? probe nd_syscall.get_thread_area { printf("%s, %s\n", name, argstr) printf("%p", u_info_uaddr) } probe nd_syscall.get_thread_area.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.iopl { printf("%s, %s\n", name, argstr) } probe nd_syscall.iopl.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.ipc ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %d, %p, %d", call, first, second, third, ptr_uaddr, fifth) } probe nd_syscall.ipc.return ? { printf("%s, %s\n", name, retstr) } # nd_syscall.mmap2 is above probe nd_syscall.set_thread_area { printf("%s, %s\n", name, argstr) printf("%p", u_info_uaddr) } probe nd_syscall.set_thread_area.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.set_zone_reclaim ? { name = "set_zone_reclaim" printf("%d, %d, %d", node, zone, state) } probe nd_syscall.set_zone_reclaim.return ? { printf("%s, %s\n", name, retstr) } # nd_syscall.sigaltstack is above probe nd_syscall.vm86, nd_syscall.vm86old ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.vm86.return, nd_syscall.vm86old.return ? { printf("%s, %s\n", name, retstr) } %) # # ia64-specific probes # %( arch == "ia64" %? # nd_syscall.mmap is above # nd_syscall.mmap2 is above # nd_syscall.sigaltstack is above # nd_syscall.sysctl32 is above %) # # powerpc-specific probes # %( arch == "powerpc" %? probe nd_syscall.sys64_time ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.sys64_time.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.ppc64_personality { printf("%s, %s\n", name, argstr) printf("%d\n", persona) } probe nd_syscall.ppc64_personality.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.ppc_rtas ? { printf("%s, %s\n", name, argstr) printf("%p\n", uargs_uaddr) } probe nd_syscall.ppc_rtas.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.ppc64_sys32_stime ? { printf("%s, %s\n", name, argstr) printf("%p\n", t_uaddr) } probe nd_syscall.ppc64_sys32_stime.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.sys32_ptrace ? { printf("%s, %s\n", name, argstr) printf("%p, %p, %p, %p", request, pid, addr, data) } probe nd_syscall.sys32_ptrace.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.sys32_sysinfo ? { printf("%s, %s\n", name, argstr) printf("%p\n", info_uaddr) } probe nd_syscall.sys32_sysinfo.return ? { printf("%s, %s\n", name, retstr) } # Notice no convenience variables like i386 version. 'ptr' is of a # different type. probe nd_syscall.ipc ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.ipc.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.sys32_sigreturn ? { printf("%s, %s\n", name, argstr) printf("%p, %p, %p, %p, %p, %p\n", r3, r4, r5, r6, r7, r8) } probe nd_syscall.sys32_sigreturn.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.sys32_adjtimex ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.sys32_adjtimex.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.sys32_getdents = kernel.function("sys32_getdents") ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", fd, dirp_uaddr, count) } probe nd_syscall.sys32_getdents.return = kernel.function("sys32_getdents").return ? { printf("%s, %s\n", name, retstr) } # nd_syscall.sysctl32 is above #probe nd_syscall.compat_sysctl ? #{ # printf("%s, %s\n", name, argstr) #} #probe nd_syscall.compat_sysctl.return ? #{ # printf("%s, %s\n", name, retstr) #} probe nd_syscall.sys32_sched_setparam ? { printf("%s, %s\n", name, argstr) printf("%d, %p\n", pid, param_uaddr) } probe nd_syscall.sys32_sched_setparam.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.sys32_sched_rr_get_interval ? { printf("%s, %s\n", name, argstr) printf("%d, %p\n", pid, interval_uaddr) } probe nd_syscall.sys32_sched_rr_get_interval.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.sys32_rt_sigpending ? { printf("%s, %s\n", name, argstr) printf("%p, %d\n", set_uaddr, sigsetsize) } probe nd_syscall.sys32_rt_sigpending.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.sys32_rt_sigtimedwait ? { printf("%s, %s\n", name, argstr) printf("%p, %p, %p, %p\n", uthese_uaddr, uinfo_uaddr, uts_uaddr, sigsetsize) } probe nd_syscall.sys32_rt_sigtimedwait.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.sys32_rt_sigqueueinfo ? { printf("%s, %s\n", name, argstr) printf("%p, %d, %p\n", pid, sig, uinfo_uaddr) } probe nd_syscall.sys32_rt_sigqueueinfo.return ? { printf("%s, %s\n", name, retstr) } # nd_syscall.sigaltstack is above probe nd_syscall.sys32_sendfile64 ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %p, %d", out_fd, in_fd, offset_uaddr, count) } probe nd_syscall.sys32_sendfile64.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.ppc32_timer_create ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %p\n", which_clock, timer_event_spec, created_timer_id) } probe nd_syscall.ppc32_timer_create.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.compat_timer_settime ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %p, %p\n", timer_id, flags, new_setting_uaddr, old_setting_uaddr) } probe nd_syscall.compat_timer_settime.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.compat_timer_gettime ? { printf("%s, %s\n", name, argstr) printf("%d, %p\n", timer_id, setting_uaddr) } probe nd_syscall.compat_timer_gettime.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.compat_clock_settime ? { printf("%s, %s\n", name, argstr) printf("%d, %p\n", which_clock, tp_uaddr) } probe nd_syscall.compat_clock_settime.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.sys32_swapcontext ? { printf("%s, %s\n", name, argstr) printf("%p, %p, %d, %d, %d, %d, %p\n", old_ctx_uaddr, new_ctx_uaddr, r5, r6, r7, r8, regs) } probe nd_syscall.sys32_swapcontext.return = kernel.function("sys32_swapcontext").return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.sys32_utimes ? { printf("%s, %s\n", name, argstr) argstr = sprintf("%p(%s), %p\n", filename_uaddr, path, tvp_uaddr) } probe nd_syscall.sys32_utimes.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.compat_mbind ? { printf("%s, %s\n", name, argstr) printf("%p, %d, %d, %p, %d, %d\n", start_uaddr, len, policy, nodemask_uaddr, maxnode, flags) } probe nd_syscall.compat_mbind.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.compat_get_mempolicy ? { printf("%s, %s\n", name, argstr) printf("%p, %p, %d, %d, %d\n", policy_uaddr, nmask_uaddr, maxnode, addr, flags) } probe nd_syscall.compat_get_mempolicy.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.compat_set_mempolicy ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", policy, nodemask_uaddr, maxnode) } probe nd_syscall.compat_set_mempolicy.return ? { printf("%s, %s\n", name, retstr) } # nd_syscall.mmap is above # nd_syscall.mmap2 is above probe nd_syscall.ppc64_sys_stime ? { printf("%s, %s\n", name, argstr) printf("%p\n", t_uaddr) } probe nd_syscall.ppc64_sys_stime.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.ppc64_newuname ? { printf("%s, %s\n", name, argstr) printf("%p\n", name_uaddr) } probe nd_syscall.ppc64_newuname.return ? { printf("%s, %s\n", name, retstr) } %) # # s390-specific probes # %( arch == "s390" %? probe nd_syscall.getresgid16 { printf("%s, %s\n", name, argstr) printf("%p, %p, %p\n", rgid_uaddr, egid_uaddr, sgid_uaddr) } probe nd_syscall.getresgid16.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getresuid16 { printf("%s, %s\n", name, argstr) printf("%p, %p, %p\n", ruid_uaddr, euid_uaddr, suid_uaddr) } probe nd_syscall.getresuid16.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.ipc ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.ipc.return ? { printf("%s, %s\n", name, retstr) } # nd_syscall.mmap is above # nd_syscall.mmap2 is above # nd_syscall.sysctl32 is above %) # # x86_64-specific probes # %( arch == "x86_64" %? probe nd_syscall.arch_prctl { printf("%s, %s\n", name, argstr) printf("%d, %d\n", code, addr) } probe nd_syscall.arch_prctl.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.iopl { printf("%s, %s\n", name, argstr) printf("%d\n", level) } probe nd_syscall.iopl.return { printf("%s, %s\n", name, retstr) } # nd_syscall.sigaltstack is above # nd_syscall.sysctl32 is above # Newer kernel's nd_syscall.mmap2 tests are in nd_syscalls-detailed.stp. %( kernel_v < "2.6.33" %? # nd_syscall.mmap is above, but we want to make sure nd_syscall.mmap32 # matches nd_syscall.mmap probe nd_syscall.mmap, nd_syscall.mmap32 { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %d, %d, %d\n", start, len, prot, flags, fd, offset) } probe nd_syscall.mmap.return, nd_syscall.mmap32.return { printf("%s, %s\n", name, retstr) } %) # nd_syscall.mmap2 is above probe nd_syscall.vm86_warning { printf("%s, %s\n", name, argstr) } probe nd_syscall.vm86_warning.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.pipe32 ? { printf("%s, %s\n", name, argstr) printf("%d, %s, %p, %d, %d\n", flags, flag_str, fildes_uaddr, pipe0, pipe1) } probe nd_syscall.pipe32.return ? { printf("%s, %s\n", name, retstr) } %) systemtap-2.3/testsuite/buildok/nd_syscalls-detailed.stp000077500000000000000000000645641217430427200237340ustar00rootroot00000000000000#! stap -p4 probe nd_syscall.accept { printf("%s, %s\n", name, argstr) printf("%d(%s), %d, %p, %p\n", flags, flags_str, sockfd, addr_uaddr, addrlen_uaddr) } probe nd_syscall.accept.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.access { printf("%s, %s\n", name, argstr) printf("%s, %d(%s)\n", pathname, mode, mode_str) } probe nd_syscall.access.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.acct { printf("%s, %s\n", name, argstr) printf("%s\n", filename) } probe nd_syscall.acct.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.add_key { printf("%s, %s\n", name, argstr) printf("%p, %p, %p, %d, %d\n", type_uaddr, description_uaddr, payload_uaddr, plen, ringid) } probe nd_syscall.add_key.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.adjtimex, nd_syscall.compat_adjtimex ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.adjtimex.return, nd_syscall.compat_adjtimex.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.alarm ? { printf("%s, %s\n", name, argstr) printf("%d\n", seconds) } probe nd_syscall.alarm.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.bdflush ? { printf("%s, %s\n", name, argstr) printf("%d %d(%s)\n", func, data, data_str) } probe nd_syscall.bdflush.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.bind { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", sockfd, my_addr_uaddr, addrlen) } probe nd_syscall.bind.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.brk { printf("%s, %s\n", name, argstr) printf("%d\n", brk) } probe nd_syscall.brk.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.capget, nd_syscall.capset { printf("%s, %s\n", name, argstr) printf("%p, %p\n", header_uaddr, data_uaddr) } probe nd_syscall.capget.return, nd_syscall.capset.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.chdir { printf("%s, %s\n", name, argstr) printf("%s\n", path) } probe nd_syscall.chdir.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.chmod { printf("%s, %s\n", name, argstr) printf("%s, %d\n", path, mode) } probe nd_syscall.chmod.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.chown, nd_syscall.chown16 ? { printf("%s, %s\n", name, argstr) printf("%s, %d, %d\n", path, owner, group) } probe nd_syscall.chown.return, nd_syscall.chown16.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.chroot { printf("%s, %s\n", name, argstr) printf("%s\n", path) } probe nd_syscall.chroot.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.clock_getres { printf("%s, %s\n", name, argstr) printf("%d(%s), %p\n", clk_id, clk_id_str, res_uaddr) } probe nd_syscall.clock_getres.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.clock_gettime { printf("%s, %s\n", name, argstr) printf("%d(%s)\n", clk_id, clk_id_str) } probe nd_syscall.clock_gettime.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.clock_nanosleep, nd_syscall.compat_clock_nanosleep ? { printf("%s, %s\n", name, argstr) printf("%d(%s)\n", flags, flag_str) } probe nd_syscall.clock_nanosleep.return, nd_syscall.compat_clock_nanosleep.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.clock_settime { printf("%s, %s\n", name, argstr) printf("%d(%s), %p\n", clk_id, clk_id_str, tp_uaddr) } probe nd_syscall.clock_settime.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.close { printf("%s, %s\n", name, argstr) printf("%d\n", fd) } probe nd_syscall.close.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.connect { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", sockfd, serv_addr_uaddr, addrlen) } probe nd_syscall.connect.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.creat { printf("%s, %s\n", name, argstr) printf("%d, %s\n", mode, pathname) } probe nd_syscall.creat.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.delete_module { printf("%s, %s\n", name, argstr) printf("%s, %d\n", name_user, flags) } probe nd_syscall.delete_module.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.dup { printf("%s, %s\n", name, argstr) printf("%d\n", oldfd) } probe nd_syscall.dup.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.dup2 { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", oldfd, newfd, flags) } probe nd_syscall.dup2.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.epoll_create ? { printf("%s, %s\n", name, argstr) printf("%d, %d\n", size, flags) } probe nd_syscall.epoll_create.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.epoll_ctl ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %s, %d, %p\n", epfd, op, op_str, fd, event_uaddr) } probe nd_syscall.epoll_ctl.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.epoll_pwait ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.epoll_pwait.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.epoll_wait ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %d, %d\n", epfd, events_uaddr, maxevents, timeout) } probe nd_syscall.epoll_wait.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.eventfd ? { printf("%s, %s\n", name, argstr) printf("%d\n", flags) } probe nd_syscall.eventfd.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.execve, nd_syscall.compat_execve ? { printf("%s, %s\n", name, argstr) printf("%s, %s\n", filename, args) } probe nd_syscall.execve.return, nd_syscall.compat_execve.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.exit { printf("%s, %s\n", name, argstr) printf("%d\n", status) } # no nd_syscall.exit return probe probe nd_syscall.exit_group { printf("%s, %s\n", name, argstr) printf("%d\n", status) } # no nd_syscall.exit_group return probe probe nd_syscall.faccessat ? { printf("%s, %s\n", name, argstr) printf("%d(%s), %s, %d(%s)\n", dirfd, dirfd_str, pathname, mode, mode_str) } probe nd_syscall.faccessat.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.fadvise64 ?, nd_syscall.fadvise64_64 ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %d\n", fd, offset, len, advice) } probe nd_syscall.fadvise64.return ?, nd_syscall.fadvise64_64.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.fchdir { printf("%s, %s\n", name, argstr) printf("%d\n", fd) } probe nd_syscall.fchdir.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.fchmod { printf("%s, %s\n", name, argstr) printf("%d, %d\n", fildes, mode) } probe nd_syscall.fchmod.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.fchmodat ? { printf("%s, %s\n", name, argstr) printf("%d(%s), %s, %d\n", dirfd, dirfd_str, pathname, mode) } probe nd_syscall.fchmodat.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.fchown, nd_syscall.fchown16 ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", fd, owner, group) } probe nd_syscall.fchown.return, nd_syscall.fchown16.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.fchownat ? { printf("%s, %s\n", name, argstr) printf("%d(%s), %s, %d, %d, %d(%s)\n", dirfd, dirfd_str, pathname, owner, group, flags, flags_str) } probe nd_syscall.fchownat.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.fcntl { printf("%s, %s\n", name, argstr) printf("%d, %d(%s), %d\n", fd, cmd, cmd_str, arg) } probe nd_syscall.fcntl.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.fdatasync { printf("%s, %s\n", name, argstr) printf("%d\n", fd) } probe nd_syscall.fdatasync.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.fgetxattr { printf("%s, %s\n", name, argstr) printf("%d, %s, %p, %d\n", filedes, name_str, value_uaddr, size) } probe nd_syscall.fgetxattr.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.flistxattr { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", filedes, list_uaddr, size) } probe nd_syscall.flistxattr.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.flock { printf("%s, %s\n", name, argstr) printf("%d, %d\n", fd, operation) } probe nd_syscall.flock.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.fork { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %p, %p\n", clone_flags, stack_start, stack_size, parent_tid_uaddr, child_tid_uaddr) %(systemtap_v < "2.3" %? printf("%p\n", regs) %) } probe nd_syscall.fork.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.fremovexattr { printf("%s, %s\n", name, argstr) printf("%d, %p(%s)\n", filedes, name_uaddr, name_str) } probe nd_syscall.fremovexattr.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.fsetxattr { printf("%s, %s\n", name, argstr) printf("%d, %p(%s), %p, %d, %d\n", filedes, name_uaddr, name_str, value_uaddr, size, flags) } probe nd_syscall.fsetxattr.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.fstat { printf("%s, %s\n", name, argstr) printf("%d, %p\n", filedes, buf_uaddr) } probe nd_syscall.fstat.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.fstatat ? { printf("%s, %s\n", name, argstr) printf("%d, %s, %p\n", dirfd, path, buf_uaddr) } probe nd_syscall.fstatat.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.fstatfs { printf("%s, %s\n", name, argstr) printf("%d, %p\n", fd, buf_uaddr) } probe nd_syscall.fstatfs.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.fstatfs64 { printf("%s, %s\n", name, argstr) printf("%d, %d, %p\n", fd, sz, buf_uaddr) } probe nd_syscall.fstatfs64.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.fsync { printf("%s, %s\n", name, argstr) printf("%d\n", fd) } probe nd_syscall.fsync.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.ftruncate, nd_syscall.ftruncate64 ? { printf("%s, %s\n", name, argstr) printf("%d, %d\n", fd, length) } probe nd_syscall.ftruncate.return, nd_syscall.ftruncate64.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.futex, nd_syscall.compat_futex ? { printf("%s, %s\n", name, argstr) printf("%p, %d, %d, %p, %p, %d\n", futex_uaddr, op, val, utime_uaddr, uaddr2_uaddr, val3) } probe nd_syscall.futex.return, nd_syscall.compat_futex.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.futimesat ?, nd_syscall.compat_futimesat ? { printf("%s, %s\n", name, argstr) printf("%d, %p(%s), %p\n", dirfd, filename_uaddr, filename, tvp_uaddr) } probe nd_syscall.futimesat.return ?, nd_syscall.compat_futimesat.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.getcwd { printf("%s, %s\n", name, argstr) printf("%p, %d\n", buf_uaddr, size) } probe nd_syscall.getcwd.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getdents { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", fd, dirp_uaddr, count) } probe nd_syscall.getdents.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getegid { printf("%s, %s\n", name, argstr) } probe nd_syscall.getegid.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.geteuid { printf("%s, %s\n", name, argstr) } probe nd_syscall.geteuid.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getgid { printf("%s, %s\n", name, argstr) } probe nd_syscall.getgid.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getgroups { printf("%s, %s\n", name, argstr) printf("%d, %p\n", size, list_uaddr) } probe nd_syscall.getgroups.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.gethostname ? { printf("%s, %s\n", name, argstr) printf("%p, %d\n", name_uaddr, len) } probe nd_syscall.gethostname.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.getitimer, nd_syscall.compat_getitimer ? { printf("%s, %s\n", name, argstr) printf("%d, %p\n", which, value_uaddr) } probe nd_syscall.getitimer.return, nd_syscall.compat_getitimer.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.get_mempolicy ? { printf("%s, %s\n", name, argstr) printf("%p, %p, %d, %p, %d\n", policy_uaddr, nmask_uaddr, maxnode, addr, flags) } probe nd_syscall.get_mempolicy.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.getpeername { printf("%s, %s\n", name, argstr) printf("%d, %p, %p\n", s, name_uaddr, namelen_uaddr) } probe nd_syscall.getpeername.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getpgid { printf("%s, %s\n", name, argstr) printf("%d\n", pid) } probe nd_syscall.getpgid.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getpgrp ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.getpgrp.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.getpid { printf("%s, %s\n", name, argstr) } probe nd_syscall.getpid.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getppid { printf("%s, %s\n", name, argstr) } probe nd_syscall.getppid.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getpriority { printf("%s, %s\n", name, argstr) printf("%d, %d\n", which, who) } probe nd_syscall.getpriority.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getresgid { printf("%s, %s\n", name, argstr) printf("%p, %p, %p\n", rgid_uaddr, egid_uaddr, sgid_uaddr) } probe nd_syscall.getresgid.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getresuid { printf("%s, %s\n", name, argstr) printf("%p, %p, %p\n", ruid_uaddr, euid_uaddr, suid_uaddr) } probe nd_syscall.getresuid.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getrlimit { printf("%s, %s\n", name, argstr) printf("%d, %p\n", resource, rlim_uaddr) } probe nd_syscall.getrlimit.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getrusage { printf("%s, %s\n", name, argstr) printf("%d(%s), %p\n", who, who_str, usage_uaddr) } probe nd_syscall.getrusage.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getsid { printf("%s, %s\n", name, argstr) printf("%d\n", pid) } probe nd_syscall.getsid.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getsockname { printf("%s, %s\n", name, argstr) printf("%d, %p, %p\n", s, name_uaddr, namelen_uaddr) } probe nd_syscall.getsockname.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getsockopt { printf("%s, %s\n", name, argstr) printf("%d, %d(%s), %d(%s), %p, %p\n", fd, level, level_str, optname, optname_str, optval_uaddr, optlen_uaddr) } probe nd_syscall.getsockopt.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.gettid { printf("%s, %s\n", name, argstr) } probe nd_syscall.gettid.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.gettimeofday { printf("%s, %s\n", name, argstr) printf("%p, %p\n", tv_uaddr, tz_uaddr) } probe nd_syscall.gettimeofday.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getuid { printf("%s, %s\n", name, argstr) } probe nd_syscall.getuid.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.getxattr { printf("%s, %s\n", name, argstr) printf("%s, %s, %p, %d\n", path, name_str, value_uaddr, size) } probe nd_syscall.getxattr.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.init_module { printf("%s, %s\n", name, argstr) printf("%p, %d, %s\n", umod_uaddr, len, uargs) } probe nd_syscall.init_module.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.inotify_add_watch ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %p(%s)\n", fd, mask, path_uaddr, path) } probe nd_syscall.inotify_add_watch.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.inotify_init ? { printf("%s, %s\n", name, argstr) printf("%d\n", flags) } probe nd_syscall.inotify_init.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.inotify_rm_watch ? { printf("%s, %s\n", name, argstr) printf("%d, %d\n", fd, wd) } probe nd_syscall.inotify_rm_watch.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.io_cancel { printf("%s, %s\n", name, argstr) printf("%d, %p, %p\n", ctx_id, iocb_uaddr, result_uaddr) } probe nd_syscall.io_cancel.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.ioctl { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", fd, request, argp) } probe nd_syscall.ioctl.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.io_destroy { printf("%s, %s\n", name, argstr) printf("%d\n", ctx) } probe nd_syscall.io_destroy.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.io_getevents, nd_syscall.compat_io_getevents ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %p, %p, %s\n", ctx_id, min_nr, nr, events_uaddr, timeout_uaddr, timestr) } probe nd_syscall.io_getevents.return, nd_syscall.compat_io_getevents.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.ioperm ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", from, num, turn_on) } probe nd_syscall.ioperm.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.io_setup, nd_syscall.compat_io_setup ? { printf("%s, %s\n", name, argstr) printf("%d, %p\n", maxevents, ctxp_uaddr) } probe nd_syscall.io_setup.return, nd_syscall.compat_io_setup.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.io_submit, nd_syscall.compat_io_submit ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %p\n", ctx_id, nr, iocbpp_uaddr) } probe nd_syscall.io_submit.return, nd_syscall.compat_io_submit.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.ioprio_get ? { printf("%s, %s\n", name, argstr) printf("%d, %d\n", which, who) } probe nd_syscall.ioprio_get.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.ioprio_set ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", which, who, ioprio) } probe nd_syscall.ioprio_set.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.kexec_load ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %p, %d\n", entry, nr_segments, segments_uaddr, flags) } probe nd_syscall.kexec_load.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.keyctl { printf("%s, %s\n", name, argstr) } probe nd_syscall.keyctl.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.kill { printf("%s, %s\n", name, argstr) printf("%d, %d\n", pid, sig) } probe nd_syscall.kill.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.lchown, nd_syscall.lchown16 ? { printf("%s, %s\n", name, argstr) printf("%s, %d, %d\n", path, owner, group) } probe nd_syscall.lchown.return, nd_syscall.lchown16.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.lgetxattr { printf("%s, %s\n", name, argstr) printf("%s, %s, %p, %d\n", path, name_str, value_uaddr, size) } probe nd_syscall.lgetxattr.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.link { printf("%s, %s\n", name, argstr) printf("%s, %s\n", oldpath, newpath) } probe nd_syscall.link.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.linkat ? { printf("%s, %s\n", name, argstr) printf("%d(%s), %s, %d(%s), %s, %d(%s)\n", olddirfd, olddirfd_str, oldpath, newdirfd, newdirfd_str, newpath, flags, flags_str) } probe nd_syscall.linkat.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.listen { printf("%s, %s\n", name, argstr) printf("%d, %d\n", sockfd, backlog) } probe nd_syscall.listen.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.listxattr, nd_syscall.llistxattr { printf("%s, %s\n", name, argstr) printf("%p, %d, %p(%s)\n", list_uaddr, size, path_uaddr, path) } probe nd_syscall.listxattr.return, nd_syscall.llistxattr.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.llseek ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %p, %d(%s)\n", fd, offset_high, offset_low, result_uaddr, whence, whence_str) } probe nd_syscall.llseek.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.lookup_dcookie { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", cookie, buffer_uaddr, len) } probe nd_syscall.lookup_dcookie.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.lremovexattr { printf("%s, %s\n", name, argstr) printf("%p(%s), %p(%s)\n", name_uaddr, name_str, path_uaddr, path) } probe nd_syscall.lremovexattr.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.lseek { printf("%s, %s\n", name, argstr) printf("%d, %d, %d(%s)\n", fildes, offset, whence, whence_str) } probe nd_syscall.lseek.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.lsetxattr { printf("%s, %s\n", name, argstr) printf("%p(%s), %p(%s), %p, %d, %d\n", path_uaddr, path, name_uaddr, name_str, value_uaddr, size, flags) } probe nd_syscall.lsetxattr.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.lstat { printf("%s, %s\n", name, argstr) printf("%s, %p\n", path, buf_uaddr) } probe nd_syscall.lstat.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.madvise { printf("%s, %s\n", name, argstr) printf("%d, %d, %d(%s)\n", start, length, advice, advice_str) } probe nd_syscall.madvise.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.mbind ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %p, %d, %d\n", start, len, mode, nmask_uaddr, maxnode, flags) } probe nd_syscall.mbind.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.migrate_pages ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.migrate_pages.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.mincore { printf("%s, %s\n", name, argstr) printf("%d, %d, %p\n", start, length, vec_uaddr) } probe nd_syscall.mincore.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.mkdir { printf("%s, %s\n", name, argstr) printf("%p(%s), %d\n", pathname_uaddr, pathname, mode) } probe nd_syscall.mkdir.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.mkdirat ? { printf("%s, %s\n", name, argstr) printf("%d, %s, %d\n", dirfd, pathname, mode) } probe nd_syscall.mkdirat.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.mknod { printf("%s, %s\n", name, argstr) printf("%s, %d, %d\n", pathname, mode, dev) } probe nd_syscall.mknod.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.mknodat ? { printf("%s, %s\n", name, argstr) printf("%d(%s), %s, %d(%s), %d\n", dirfd, dirfd_str, pathname, mode, mode_str, dev) } probe nd_syscall.mknodat.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.mlock { printf("%s, %s\n", name, argstr) printf("%d, %d\n", addr, len) } probe nd_syscall.mlock.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.mlockall { printf("%s, %s\n", name, argstr) printf("%d\n", flags) } probe nd_syscall.mlockall.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.modify_ldt ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", func, ptr_uaddr, bytecount) } probe nd_syscall.modify_ldt.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.move_pages ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.move_pages.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.mount { printf("%s, %s\n", name, argstr) printf("%s, %s, %s, %d(%s), %s\n", source, target, filesystemtype, mountflags, mountflags_str, data) } probe nd_syscall.mount.return { printf("%s, %s\n", name, retstr) } # Older kernel's nd_syscall.mmap* tests are in nd_syscalls-arch-detailed.stp. %( kernel_v >= "2.6.33" %? probe nd_syscall.mmap2 { printf("%s, %s\n", name, argstr) printf("%p, %d, %d, %d, %d, %d", start, length, prot, flags, fd, pgoffset) } probe nd_syscall.mmap2.return { printf("%s, %s\n", name, retstr) } %) probe nd_syscall.mprotect { printf("%s, %s\n", name, argstr) printf("%p, %d, %d(%s)\n", addr, len, prot, prot_str) } probe nd_syscall.mprotect.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.mq_getsetattr { printf("%s, %s\n", name, argstr) printf("%d, %p, %p\n", mqdes, u_mqstat_uaddr, u_omqstat_uaddr) } probe nd_syscall.mq_getsetattr.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.mq_notify { printf("%s, %s\n", name, argstr) printf("%d, %p\n", mqdes, notification_uaddr) } probe nd_syscall.mq_notify.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.mq_open { printf("%s, %s\n", name, argstr) printf("%p, %s, %d, %p, %d\n", name_uaddr, filename, mode, u_attr_uaddr, oflag) } probe nd_syscall.mq_open.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.mq_timedreceive { printf("%s, %s\n", name, argstr) printf("%d, %p, %d, %p, %p\n", mqdes, msg_ptr_uaddr, msg_len, msg_prio_uaddr, abs_timeout_uaddr) } probe nd_syscall.mq_timedreceive.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.mq_timedsend { printf("%s, %s\n", name, argstr) printf("%d, %p, %d, %d, %p\n", mqdes, msg_ptr_uaddr, msg_len, msg_prio, abs_timeout_uaddr) } probe nd_syscall.mq_timedsend.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.mq_unlink { printf("%s, %s\n", name, argstr) printf("%p(%s)\n", u_name_uaddr, u_name) } probe nd_syscall.mq_unlink.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.mremap { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %d, %d\n", old_address, old_size, new_size, flags, new_address) } probe nd_syscall.mremap.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.msgctl, nd_syscall.compat_sys_msgctl ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %p\n", msqid, cmd, buf_uaddr) } probe nd_syscall.msgctl.return, nd_syscall.compat_sys_msgctl.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.msgget { printf("%s, %s\n", name, argstr) printf("%d, %d(%s)\n", key, msgflg, msgflg_str) } probe nd_syscall.msgget.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.msgrcv, nd_syscall.compat_sys_msgrcv ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %d, %d, %d\n", msqid, msgp_uaddr, msgsz, msgtyp, msgflg) } probe nd_syscall.msgrcv.return, nd_syscall.compat_sys_msgrcv.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.msgsnd, nd_syscall.compat_sys_msgsnd ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %d, %d\n", msqid, msgp_uaddr, msgsz, msgflg) } probe nd_syscall.msgsnd.return, nd_syscall.compat_sys_msgsnd.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.msync { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", start, length, flags) } probe nd_syscall.msync.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.munlock { printf("%s, %s\n", name, argstr) printf("%p, %d\n", addr, len) } probe nd_syscall.munlock.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.munlockall { printf("%s, %s\n", name, argstr) } probe nd_syscall.munlockall.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.munmap { printf("%s, %s\n", name, argstr) printf("%p, %d\n", start, length) } probe nd_syscall.munmap.return { printf("%s, %s\n", name, retstr) } systemtap-2.3/testsuite/buildok/nd_syscalls2-detailed.stp000077500000000000000000000672011217430427200240050ustar00rootroot00000000000000#! stap -p4 probe nd_syscall.nanosleep, nd_syscall.compat_nanosleep ? { printf("%s(%s)\n", name, argstr) printf("%p %p\n", req_uaddr, rem_uaddr) } probe nd_syscall.nanosleep.return, nd_syscall.compat_nanosleep.return ? { printf("%s %s\n", name, retstr) } # nfsservctl was removed in kernel 3.0/2.6.40. %( kernel_v < "2.6.40" && CONFIG_NFSD == "[ym]" %? probe nd_syscall.nfsservctl { printf("%s(%s)\n", name, argstr) printf("%d %p %p\n", cmd, argp_uaddr, resp_uaddr) } probe nd_syscall.nfsservctl.return { printf("%s %s\n", name, retstr) } %) probe nd_syscall.nice ? { printf("%s(%s)\n", name, argstr) printf("%d\n", inc) } probe nd_syscall.nice.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.ni_syscall { printf("%s(%s)\n", name, argstr) } probe nd_syscall.ni_syscall.return { printf("%s %s\n", name, retstr) } probe nd_syscall.open, nd_syscall.openat ? { printf("%s(%s)\n", name, argstr) printf("%s %d %d\n", filename, flags, mode) } probe nd_syscall.open.return, nd_syscall.openat.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.pause ? { printf("%s(%s)\n", name, argstr) } probe nd_syscall.pause.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.personality { printf("%s(%s)\n", name, argstr) printf("%d\n", persona) } probe nd_syscall.personality.return { printf("%s %s\n", name, retstr) } probe nd_syscall.pipe { printf("%s(%s)\n", name, argstr) # Should be: # printf("%d(%s) %p [%d %d]\n", flags, flag_str, fildes_uaddr, pipe0, # pipe1) printf("%d(%s) %p\n", flags, flag_str, fildes_uaddr) } # nd_syscall.pipe.return is special, since at that point pipe0/pipe1 are valid probe nd_syscall.pipe.return { printf("%s %s\n", name, retstr) # Should be: # printf("%p [%d %d]\n", fildes_uaddr, pipe0, pipe1) } probe nd_syscall.pivot_root { printf("%s(%s)\n", name, argstr) printf("%s %s\n", new_root_str, old_root_str) } probe nd_syscall.pivot_root.return { printf("%s %s\n", name, retstr) } probe nd_syscall.poll { printf("%s(%s)\n", name, argstr) printf("%p %d %d\n", ufds_uaddr, nfds, timeout) } probe nd_syscall.poll.return { printf("%s %s\n", name, retstr) } probe nd_syscall.ppoll ?, nd_syscall.compat_ppoll ? { printf("%s(%s)\n", name, argstr) } probe nd_syscall.ppoll.return ?, nd_syscall.compat_ppoll.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.prctl { printf("%s(%s)\n", name, argstr) printf("%p %p %p %p %p\n", option, arg2, arg3, arg4, arg5) } probe nd_syscall.prctl.return { printf("%s %s\n", name, retstr) } probe nd_syscall.pread { printf("%s(%s)\n", name, argstr) printf("%d %p %d %d\n", fd, buf_uaddr, count, offset) } probe nd_syscall.pread.return { printf("%s %s\n", name, retstr) } probe nd_syscall.pselect6 ?, nd_syscall.compat_pselect6 ?, nd_syscall.pselect7 ?, %( systemtap_v <= "1.3" %? nd_syscall.compat_pselect7a ? %: nd_syscall.compat_pselect7 ? %) { printf("%s(%s)\n", name, argstr) } probe nd_syscall.pselect6.return ?, nd_syscall.compat_pselect6.return ?, nd_syscall.pselect7.return ?, nd_syscall.compat_pselect7.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.ptrace { printf("%s(%s)\n", name, argstr) printf("%d %d %p %p\n", request, pid, addr, data) } probe nd_syscall.ptrace.return { printf("%s %s\n", name, retstr) } probe nd_syscall.pwrite, nd_syscall.pwrite32 ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d %d\n", fd, buf_uaddr, count, offset) } probe nd_syscall.pwrite.return, nd_syscall.pwrite32.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.quotactl { printf("%s(%s)\n", name, argstr) printf("%d(%s) %p(%s) %d %p\n", cmd, cmd_str, special, special_str, id, addr_uaddr) } probe nd_syscall.quotactl.return { printf("%s %s\n", name, retstr) } probe nd_syscall.read { printf("%s(%s)\n", name, argstr) printf("%d %p %d\n", fd, buf_uaddr, count) } probe nd_syscall.read.return { printf("%s %s\n", name, retstr) } probe nd_syscall.readahead { printf("%s(%s)\n", name, argstr) printf("%d %d %d\n", fd, offset, count) } probe nd_syscall.readahead.return { printf("%s %s\n", name, retstr) } probe nd_syscall.readdir ? { printf("%s(%s)\n", name, argstr) } probe nd_syscall.readdir.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.readlink { printf("%s(%s)\n", name, argstr) printf("%s %p %d\n", path, buf_uaddr, bufsiz) } probe nd_syscall.readlink.return { printf("%s %s\n", name, retstr) } probe nd_syscall.readlinkat ? { printf("%s(%s)\n", name, argstr) printf("%d %s %p %d\n", dfd, path, buf_uaddr, bufsiz) } probe nd_syscall.readlinkat.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.readv { printf("%s(%s)\n", name, argstr) printf("%d %p %d\n", fd, vector_uaddr, count) } probe nd_syscall.readv.return { printf("%s %s\n", name, retstr) } probe nd_syscall.reboot { printf("%s(%s)\n", name, argstr) printf("%d(%s) %d(%s) %d(%s) %p\n", magic, magic_str, magic2, magic2_str, flag, flag_str, arg_uaddr) } probe nd_syscall.reboot.return { printf("%s %s\n", name, retstr) } probe nd_syscall.recv { printf("%s(%s)\n", name, argstr) printf("%d %p %d %d(%s)\n", s, buf_uaddr, len, flags, flags_str) } probe nd_syscall.recv.return { printf("%s %s\n", name, retstr) } probe nd_syscall.recvfrom ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d %d(%s) %p %p\n", s, buf_uaddr, len, flags, flags_str, addr_uaddr, addrlen_uaddr) } probe nd_syscall.recvfrom.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.recvmmsg ?, nd_syscall.compat_recvmmsg ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d %d(%s), %p\n", s, mmsg_uaddr, vlen, flags, flags_str, timeout_uaddr) } probe nd_syscall.recvmmsg.return ?, nd_syscall.compat_recvmmsg.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.recvmsg ?, nd_syscall.compat_sys_recvmsg ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d(%s)\n", s, msg_uaddr, flags, flags_str) } probe nd_syscall.recvmsg.return ?, nd_syscall.compat_sys_recvmsg.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.remap_file_pages ? { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d %d\n", start, size, prot, pgoff, flags) } probe nd_syscall.remap_file_pages.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.removexattr { printf("%s(%s)\n", name, argstr) printf("%s %s\n", name_str, path) } probe nd_syscall.removexattr.return { printf("%s %s\n", name, retstr) } probe nd_syscall.rename { printf("%s(%s)\n", name, argstr) printf("%s %s\n", oldpath, newpath) } probe nd_syscall.rename.return { printf("%s %s\n", name, retstr) } probe nd_syscall.renameat ? { printf("%s(%s)\n", name, argstr) printf("%p(%s) %p(%s) %p(%s) %p(%s)\n", olddfd, olddfd_str, oldname, oldname_str, newdfd, newdfd_str, newname, newname_str) } probe nd_syscall.renameat.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.request_key ? { printf("%s(%s)\n", name, argstr) printf("%p %p %p %p\n", type_uaddr, description_uaddr, callout_info_uaddr, destringid) } probe nd_syscall.request_key.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.restart_syscall { printf("%s(%s)\n", name, argstr) } probe nd_syscall.restart_syscall.return { printf("%s %s\n", name, retstr) } probe nd_syscall.rmdir { printf("%s(%s)\n", name, argstr) printf("%s\n", pathname) } probe nd_syscall.rmdir.return { printf("%s %s\n", name, retstr) } probe nd_syscall.rt_sigaction ?, nd_syscall.rt_sigaction32 ? { printf("%s(%s)\n", name, argstr) printf("%d %p %p %d\n", sig, act_uaddr, oact_uaddr, sigsetsize) } probe nd_syscall.rt_sigaction.return ?, nd_syscall.rt_sigaction32.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.rt_sigpending ? { printf("%s(%s)\n", name, argstr) printf("%p %d\n", set_uaddr, sigsetsize) } probe nd_syscall.rt_sigpending.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.rt_sigprocmask ?, nd_syscall.compat_rt_sigprocmask ? { printf("%s(%s)\n", name, argstr) printf("%d(%s) %p %p\n", how, how_str, set_uaddr, oldset_uaddr) } probe nd_syscall.rt_sigprocmask.return ?, nd_syscall.compat_rt_sigprocmask.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.rt_sigqueueinfo { printf("%s(%s)\n", name, argstr) printf("%d %d %p\n", pid, sig, uinfo_uaddr) } probe nd_syscall.rt_sigqueueinfo.return { printf("%s %s\n", name, retstr) } probe nd_syscall.rt_sigreturn ?, nd_syscall.rt_sigsuspend ? { printf("%s(%s)\n", name, argstr) } probe nd_syscall.rt_sigreturn.return ?, nd_syscall.rt_sigsuspend.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.rt_sigtimedwait { printf("%s(%s)\n", name, argstr) printf("%p %p %p %d\n", uthese_uaddr, uinfo_uaddr, uts_uaddr, sigsetsize) } probe nd_syscall.rt_sigtimedwait.return { printf("%s %s\n", name, retstr) } probe nd_syscall.sched_getaffinity { printf("%s(%s)\n", name, argstr) printf("%d %d %p\n", pid, len, mask_uaddr) } probe nd_syscall.sched_getaffinity.return { printf("%s %s\n", name, retstr) } probe nd_syscall.sched_getparam { printf("%s(%s)\n", name, argstr) printf("%d %p\n", pid, p_uaddr) } probe nd_syscall.sched_getparam.return { printf("%s %s\n", name, retstr) } probe nd_syscall.sched_get_priority_max, nd_syscall.sched_get_priority_min { printf("%s(%s)\n", name, argstr) printf("%d\n", policy) } probe nd_syscall.sched_get_priority_max.return, nd_syscall.sched_get_priority_min.return { printf("%s %s\n", name, retstr) } probe nd_syscall.sched_getscheduler { printf("%s(%s)\n", name, argstr) printf("%d\n", pid) } probe nd_syscall.sched_getscheduler.return { printf("%s %s\n", name, retstr) } probe nd_syscall.sched_rr_get_interval { printf("%s(%s)\n", name, argstr) printf("%d %p\n", pid, tp_uaddr) } probe nd_syscall.sched_rr_get_interval.return { printf("%s %s\n", name, retstr) } probe nd_syscall.sched_setaffinity { printf("%s(%s)\n", name, argstr) printf("%d %d %p\n", pid, len, mask_uaddr) } probe nd_syscall.sched_setaffinity.return { printf("%s %s\n", name, retstr) } probe nd_syscall.sched_setparam ? { printf("%s(%s)\n", name, argstr) printf("%d %p\n", pid, p_uaddr) } probe nd_syscall.sched_setparam.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.sched_setscheduler ? { printf("%s(%s)\n", name, argstr) printf("%d %d(%s) %p\n", pid, policy, policy_str, p_uaddr) } probe nd_syscall.sched_setscheduler.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.sched_yield { printf("%s(%s)\n", name, argstr) } probe nd_syscall.sched_yield.return { printf("%s %s\n", name, retstr) } probe nd_syscall.select, nd_syscall.compat_select ? { printf("%s(%s)\n", name, argstr) printf("%d %p %p %p %p\n", n, readfds_uaddr, writefds_uaddr, exceptfds_uaddr, timeout_uaddr) } probe nd_syscall.select.return, nd_syscall.compat_select.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.semctl ?, nd_syscall.compat_sys_semctl ? { printf("%s(%s)\n", name, argstr) printf("%d %d %d\n", semid, semnum, cmd) } probe nd_syscall.semctl.return ?, nd_syscall.compat_sys_semctl.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.semget ? { printf("%s(%s)\n", name, argstr) printf("%d %d %d\n", key, nsems, semflg) } probe nd_syscall.semget.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.semop ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d\n", semid, sops_uaddr, nsops) } probe nd_syscall.semop.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.semtimedop ?, nd_syscall.compat_sys_semtimedop ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d %p\n", semid, sops_uaddr, nsops, timeout_uaddr) } probe nd_syscall.semtimedop.return ?, nd_syscall.compat_sys_semtimedop.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.send ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d %d(%s)\n", s, buf_uaddr, len, flags, flags_str) } probe nd_syscall.send.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.sendfile ? { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d\n", out_fd, in_fd, offset_uaddr, count) } probe nd_syscall.sendfile.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.sendmsg ?, nd_syscall.compat_sys_sendmsg ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d(%s)\n", s, msg_uaddr, flags, flags_str) } probe nd_syscall.sendmsg.return ?, nd_syscall.compat_sys_sendmsg.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.sendmmsg ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d %d(%s)\n", s, mmsg_uaddr, vlen, flags, flags_str) } probe nd_syscall.sendmmsg.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.sendto ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d %d(%s) %p %d\n", s, buf_uaddr, len, flags, flags_str, to_uaddr, tolen) } probe nd_syscall.sendto.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.setdomainname { printf("%s(%s)\n", name, argstr) printf("%p %d\n", hostname_uaddr, len) } probe nd_syscall.setdomainname.return { printf("%s %s\n", name, retstr) } probe nd_syscall.setfsgid ? { printf("%s(%s)\n", name, argstr) printf("%d\n", fsgid) } probe nd_syscall.setfsgid.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.setfsuid ? { printf("%s(%s)\n", name, argstr) printf("%d\n", fsuid) } probe nd_syscall.setfsuid.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.setgid ? { printf("%s(%s)\n", name, argstr) printf("%d\n", gid) } probe nd_syscall.setgid.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.setgroups ? { printf("%s(%s)\n", name, argstr) printf("%d %p\n", size, list_uaddr) } probe nd_syscall.setgroups.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.sethostname { printf("%s(%s)\n", name, argstr) printf("%p(%s) %d\n", hostname_uaddr, name_str, len) } probe nd_syscall.sethostname.return { printf("%s %s\n", name, retstr) } probe nd_syscall.setitimer, nd_syscall.compat_setitimer ? { printf("%s(%s)\n", name, argstr) printf("%d %p %p\n", which, value_uaddr, ovalue_uaddr) } probe nd_syscall.setitimer.return, nd_syscall.compat_setitimer.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.set_mempolicy ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d\n", mode, nmask_uaddr, maxnode) } probe nd_syscall.set_mempolicy.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.setpgid { printf("%s(%s)\n", name, argstr) printf("%d %d\n", pid, pgid) } probe nd_syscall.setpgid.return { printf("%s %s\n", name, retstr) } probe nd_syscall.setpriority { printf("%s(%s)\n", name, argstr) printf("%d(%s) %d %d\n", which, which_str, who, prio) } probe nd_syscall.setpriority.return { printf("%s %s\n", name, retstr) } probe nd_syscall.setregid, nd_syscall.setregid16 ? { printf("%s(%s)\n", name, argstr) printf("%d %d\n", rgid, egid) } probe nd_syscall.setregid.return, nd_syscall.setregid16.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.setresgid, nd_syscall.setresgid16 ? { printf("%s(%s)\n", name, argstr) printf("%d %d %d\n", rgid, egid, sgid) } probe nd_syscall.setresgid.return, nd_syscall.setresgid16.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.setresuid, nd_syscall.setresuid16 ? { printf("%s(%s)\n", name, argstr) printf("%d %d %d\n", ruid, euid, suid) } probe nd_syscall.setresuid.return, nd_syscall.setresuid16.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.setreuid, nd_syscall.setreuid16 ? { printf("%s(%s)\n", name, argstr) printf("%d %d\n", ruid, euid) } probe nd_syscall.setreuid.return, nd_syscall.setreuid16.return ? { printf("%s %s\n", name, retstr) } probe nd_syscall.setrlimit { printf("%s(%s)\n", name, argstr) printf("%d %p\n", resource, rlim_uaddr) } probe nd_syscall.setrlimit.return { printf("%s %s\n", name, retstr) } probe nd_syscall.setsid { printf("%s(%s)\n", name, argstr) } probe nd_syscall.setsid.return { printf("%s %s\n", name, retstr) } probe nd_syscall.setsockopt { printf("%s, %s\n", name, argstr) printf("%d, %d(%s), %d(%s), %p, %d\n", fd, level, level_str, optname, optname_str, optval_uaddr, optlen) } probe nd_syscall.setsockopt.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.set_tid_address { printf("%s, %s\n", name, argstr) printf("%p\n", tidptr_uaddr) } probe nd_syscall.set_tid_address.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.settimeofday, nd_syscall.settimeofday32 ? { printf("%s, %s\n", name, argstr) printf("%p, %p\n", tv_uaddr, tz_uaddr) } probe nd_syscall.settimeofday.return, nd_syscall.settimeofday32.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.setuid { printf("%s, %s\n", name, argstr) printf("%d\n", uid) } probe nd_syscall.setuid.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.setxattr { printf("%s, %s\n", name, argstr) printf("%p(%s), %p(%s), %p, %d, %d\n", path_uaddr, path, name_uaddr, name_str, value_uaddr, size, flags) } probe nd_syscall.setxattr.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.sgetmask ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.sgetmask.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.shmat ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", shmid, shmaddr_uaddr, shmflg) } probe nd_syscall.shmat.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.compat_sys_shmat ? { printf("%s, %s\n", name, argstr) %( systemtap_v < "2.3" %? printf("%d, %d, %d, %p\n", first, second, third, uptr_uaddr) %) printf("%d, %p, %d\n", shmid, shmaddr_uaddr, shmflg) } probe nd_syscall.compat_sys_shmat.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.shmctl ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %p\n", shmid, cmd, buf_uaddr) } probe nd_syscall.shmctl.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.compat_sys_shmctl ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %p\n", first, second, uptr_uaddr) } probe nd_syscall.compat_sys_shmctl.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.shmdt { printf("%s, %s\n", name, argstr) printf("%p\n", shmaddr_uaddr) } probe nd_syscall.shmdt.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.shmget ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", key, size, shmflg) } probe nd_syscall.shmget.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.shutdown { printf("%s, %s\n", name, argstr) printf("%d, %d(%s)\n", s, how, how_str) } probe nd_syscall.shutdown.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.sigaction ?, nd_syscall.sigaction32 ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %p\n", sig, act_uaddr, oact_uaddr) } probe nd_syscall.sigaction.return ?, nd_syscall.sigaction32.return ? { printf("%s, %s\n", name, retstr) } %( CONFIG_GENERIC_SIGALTSTACK == "y" %? probe nd_syscall.sigaltstack { printf("%s, %s\n", name, argstr) printf("%p, %p\n", uss_uaddr, uoss_uaddr) } probe nd_syscall.sigaltstack.return { printf("%s, %s\n", name, retstr) } %) probe nd_syscall.signal ? { printf("%s, %s\n", name, argstr) printf("%d, %d\n", sig, handler) } probe nd_syscall.signal.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.signalfd ?, nd_syscall.compat_signalfd ? { printf("%s, %s\n", name, argstr) printf("%d\n", flags) } probe nd_syscall.signalfd.return ?, nd_syscall.compat_signalfd.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.sigpending ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.sigpending.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.sigprocmask ? { printf("%s, %s\n", name, argstr) printf("%d(%s), %p, %p\n", how, how_str, set_uaddr, oldset_uaddr) } probe nd_syscall.sigprocmask.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.sigreturn ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.sigreturn.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.sigsuspend ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.sigsuspend.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.socket { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", family, type, protocol) } probe nd_syscall.socket.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.socketpair { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %p\n", family, type, protocol, sv_uaddr) } probe nd_syscall.socketpair.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.splice ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.splice.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.ssetmask ? { printf("%s, %s\n", name, argstr) printf("%d\n", newmask) } probe nd_syscall.ssetmask.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.stat { printf("%s, %s\n", name, argstr) printf("%p, %s, %p\n", filename_uaddr, filename, buf_uaddr) } probe nd_syscall.stat.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.statfs { printf("%s, %s\n", name, argstr) printf("%p, %s\n", buf_uaddr, path) } probe nd_syscall.statfs.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.statfs64 { printf("%s, %s\n", name, argstr) printf("%d, %p, %s\n", sz, buf_uaddr, path) } probe nd_syscall.statfs64.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.stime ? { printf("%s, %s\n", name, argstr) printf("%p\n", t_uaddr) } probe nd_syscall.stime.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.swapoff { printf("%s, %s\n", name, argstr) printf("%s\n", path) } probe nd_syscall.swapoff.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.swapon { printf("%s, %s\n", name, argstr) printf("%s, %d\n", path, swapflags) } probe nd_syscall.swapon.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.symlink { printf("%s, %s\n", name, argstr) printf("%s, %s\n", oldpath, newpath) } probe nd_syscall.symlink.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.symlinkat ? { printf("%s, %s\n", name, argstr) printf("%p(%s), %d(%s), %p(%s)\n", oldname, oldname_str, newdfd, newdfd_str, newname, newname_str) } probe nd_syscall.symlinkat.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.sync { printf("%s, %s\n", name, argstr) } probe nd_syscall.sync.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.sysctl { printf("%s, %s\n", name, argstr) } probe nd_syscall.sysctl.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.sysfs { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", option, arg1, arg2) } probe nd_syscall.sysfs.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.sysinfo { printf("%s, %s\n", name, argstr) printf("%p\n", info_uaddr) } probe nd_syscall.sysinfo.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.syslog { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", type, bufp_uaddr, len) } probe nd_syscall.syslog.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.tee ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.tee.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.tgkill { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", tgid, pid, sig) } probe nd_syscall.tgkill.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.time ? { printf("%s, %s\n", name, argstr) printf("%p\n", t_uaddr) } probe nd_syscall.time.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.timer_create { printf("%s, %s\n", name, argstr) printf("%d(%s), %p, %p\n", clockid, clockid_str, evp_uaddr, timerid_uaddr) } probe nd_syscall.timer_create.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.timer_delete, nd_syscall.timer_getoverrun { printf("%s, %s\n", name, argstr) printf("%d\n", timerid) } probe nd_syscall.timer_delete.return, nd_syscall.timer_getoverrun.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.timer_gettime { printf("%s, %s\n", name, argstr) printf("%d, %p\n", timerid, value_uaddr) } probe nd_syscall.timer_gettime.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.timer_settime { printf("%s, %s\n", name, argstr) printf("%d, %d, %p, %p\n", timerid, flags, value_uaddr, ovalue_uaddr) } probe nd_syscall.timer_settime.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.timerfd ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.timerfd.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.times { printf("%s, %s\n", name, argstr) } probe nd_syscall.times.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.tkill { printf("%s, %s\n", name, argstr) printf("%d, %d\n", pid, sig) } probe nd_syscall.tkill.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.truncate { printf("%s, %s\n", name, argstr) printf("%p(%s), %d\n", path_uaddr, path, length) } probe nd_syscall.truncate.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.tux ? { printf("%s, %s\n", name, argstr) printf("%d %p\n", action, u_info_uaddr) } probe nd_syscall.tux.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.umask { printf("%s, %s\n", name, argstr) printf("%d\n", mask) } probe nd_syscall.umask.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.umount { printf("%s, %s\n", name, argstr) printf("%s, %d(%s)\n", target, flags, flags_str) } probe nd_syscall.umount.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.uname { printf("%s, %s\n", name, argstr) } probe nd_syscall.uname.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.unlink { printf("%s, %s\n", name, argstr) printf("%p(%s)\n", pathname_uaddr, pathname) } probe nd_syscall.unlink.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.unlinkat ? { printf("%s, %s\n", name, argstr) printf("%d(%s), %p(%s), %d(%s)\n", dfd, dfd_str, pathname, pathname_str, flag, flag_str) } probe nd_syscall.unlinkat.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.unshare ? { printf("%s, %s\n", name, argstr) printf("%d\n", unshare_flags) } probe nd_syscall.unshare.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.uselib { printf("%s, %s\n", name, argstr) printf("%p(%s)\n", library_uaddr, library) } probe nd_syscall.uselib.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.ustat, nd_syscall.ustat32 ? { printf("%s, %s\n", name, argstr) printf("%d, %p\n", dev, ubuf_uaddr) } probe nd_syscall.ustat.return, nd_syscall.ustat32.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.utime ?, nd_syscall.compat_utime ? { printf("%s, %s\n", name, argstr) printf("%p(%s), %p, %d, %d\n", filename_uaddr, filename, buf_uaddr, actime, modtime) } probe nd_syscall.utime.return ?, nd_syscall.compat_utime.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.utimensat ?, nd_syscall.compat_utimensat ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.utimensat.return ?, nd_syscall.compat_utimensat.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.vhangup { printf("%s, %s\n", name, argstr) } probe nd_syscall.vhangup.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.vmsplice ?, nd_syscall.compat_vmsplice ? { printf("%s, %s\n", name, argstr) } probe nd_syscall.vmsplice.return ?, nd_syscall.compat_vmsplice.return ? { printf("%s, %s\n", name, retstr) } probe nd_syscall.wait4 { printf("%s, %s\n", name, argstr) printf("%d, %p, %d(%s), %p\n", pid, status_uaddr, options, options_str, rusage_uaddr) } probe nd_syscall.wait4.return { printf("%s, %s, %s\n", name, retstr, status_str) } probe nd_syscall.waitid { printf("%s, %s\n", name, argstr) printf("%d, %d(%s), %p, %d(%s), %p\n", pid, which, which_str, infop_uaddr, options, options_str, rusage_uaddr) } probe nd_syscall.waitid.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.write { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", fd, buf_uaddr, count) } probe nd_syscall.write.return { printf("%s, %s\n", name, retstr) } probe nd_syscall.writev { printf("%s, %s\n", name, argstr) printf("%p, %d, %d\n", vector_uaddr, count, fd) } probe nd_syscall.writev.return { printf("%s, %s\n", name, retstr) } systemtap-2.3/testsuite/buildok/netfilter01.stp000077500000000000000000000004711217430427200217650ustar00rootroot00000000000000#! stap -p4 # use string as priority value probe netfilter.hook("NF_INET_PRE_ROUTING").pf("NFPROTO_IPV4").priority("-1") { printf("a") } probe netfilter.hook("NF_INET_PRE_ROUTING").pf("NFPROTO_IPV4") { printf("b") } probe netfilter.hook("NF_INET_PRE_ROUTING").pf("NFPROTO_IPV4").priority("3") { printf("c\n") } systemtap-2.3/testsuite/buildok/netfilter02.stp000077500000000000000000000003011217430427200217560ustar00rootroot00000000000000#! stap -p4 # use string as priority value probe netfilter.hook("NF_INET_PRE_ROUTING").pf("NFPROTO_IPV4").priority("1") { } probe netfilter.hook("NF_INET_PRE_ROUTING").pf("NFPROTO_IPV4") { } systemtap-2.3/testsuite/buildok/netfilter03.stp000077500000000000000000000002321217430427200217620ustar00rootroot00000000000000#! stap -gp4 # setting verdict in guru mode should succeed probe netfilter.pf("NFPROTO_IPV4").hook("NF_INET_PRE_ROUTING") { $verdict = 0 /* NF_DROP */ } systemtap-2.3/testsuite/buildok/netfilter04.stp000077500000000000000000000001201217430427200217570ustar00rootroot00000000000000#! stap -p4 probe netfilter.pf("NFPROTO_IPV4").hook("NF_INET_PRE_ROUTING") { } systemtap-2.3/testsuite/buildok/networking-all-probes.stp000077500000000000000000000001331217430427200240500ustar00rootroot00000000000000#! stap -wp4 // Tests if all probes in networking.stp are resolvable. probe netdev.* { } systemtap-2.3/testsuite/buildok/networking-change_rx_flag.stp000077500000000000000000000004731217430427200247460ustar00rootroot00000000000000#! stap -p4 # This test fails on some kernels because we can't find the arguments to # this inline function (PR 1155). probe netdev.change_rx_flag ? { printf("%s, %d\n", dev_name, flags) } # Make sure this file compiles on kernels where netdev.change_rx_flag # doesn't exist. probe begin { printf("begin\n") } systemtap-2.3/testsuite/buildok/networking-detailed.stp000077500000000000000000000015121217430427200235650ustar00rootroot00000000000000#! stap -p4 probe netdev.receive, netdev.transmit { printf("%s, %d, %d, %d\n", dev_name, length, protocol, truesize) } probe netdev.change_mtu { printf("%s, %d, %d\n", dev_name, old_mtu, new_mtu) } probe netdev.open, netdev.close { printf("%s\n", dev_name) } probe netdev.hard_transmit ? { printf("%s, %d, %d, %d\n", dev_name, length, protocol, truesize) } probe netdev.rx { printf("%s, %d, %p\n", dev_name, protocol, netdev) } # netdev.change_rx_flag test moved to networking-change_rx_flag.stp probe netdev.set_promiscuity { printf("%s, %d/%d, %d\n", dev_name, enable, disable, inc) } probe netdev.ioctl { printf("%d, %s\n", cmd, arg) } probe netdev.register, netdev.unregister, netdev.get_stats ? { printf("%s\n", dev_name) } probe netdev.change_mac ? { printf("%s, %d, %s, %s\n", dev_name, mac_len, old_mac, new_mac) } systemtap-2.3/testsuite/buildok/networking-embedded.stp000077500000000000000000000001011217430427200235340ustar00rootroot00000000000000#! stap -p4 probe begin { printf("%s\n", get_netdev_name(0)) } systemtap-2.3/testsuite/buildok/newlocals01.stp000077500000000000000000000004501217430427200217550ustar00rootroot00000000000000#! stap -gp4 # test accessing locals using STAP_ARG_* macros function baz:long(foo:long, bar:string) %{ printk("%s\n", STAP_ARG_bar); STAP_RETVALUE = 600 + STAP_ARG_foo; %} probe begin { q = baz(9001, "I'm in your dmesg making stupid jokes") printf("%d\n", q) exit() } systemtap-2.3/testsuite/buildok/nfs-all-probes.stp000077500000000000000000000001561217430427200224540ustar00rootroot00000000000000#! stap -wp4 // Tests if all probes in nfs.stp and nfs_proc.stp are resolvable. probe nfs.*.*, nfs.*.*.* {} systemtap-2.3/testsuite/buildok/nfs-detailed.stp000077500000000000000000000123551217430427200221730ustar00rootroot00000000000000#! stap -p4 # # nfs.fop.* probes # probe nfs.fop.llseek { printf("%s(%s)\n", name, argstr) printf("%d %d %d %s %d\n", dev, ino, s_id, devname, maxbyte) %(systemtap_v < "2.3" %? printf("%d\n", origin) %) printf("%d %d %s\n", offset, whence, whence_str); } probe nfs.fop.llseek.return { printf("%s(%s)\n", name, retstr) } probe nfs.fop.read, nfs.fop.write { printf("%s(%s)\n", name, argstr) printf("%d %s\n", s_id, devname) } probe nfs.fop.read.return, nfs.fop.write.return { printf("%s(%s)\n", name, retstr) } probe nfs.fop.aio_read { printf("%s(%s)\n", name, argstr) printf("%d %d %d %s\n", dev, ino, s_id, devname) printf("%s %s %d %d %d\n", parent_name, file_name, cache_valid, cache_time, attr_time) printf("%d %s\n", size, units) } probe nfs.fop.aio_read.return { printf("%s(%s)\n", name, retstr) printf("%d %s\n", size, units) } probe nfs.fop.aio_write { printf("%s(%s)\n", name, argstr) printf("%d %d %d %s\n", dev, ino, s_id, devname) printf("%s %s\n", parent_name, file_name) printf("%d %s\n", size, units) } probe nfs.fop.aio_write.return { printf("%s(%s)\n", name, retstr) printf("%d %s\n", size, units) } probe nfs.fop.mmap { printf("%s(%s)\n", name, argstr) printf("%d %d %d %s\n", dev, ino, s_id, devname) printf("%s %s %d %d %d\n", parent_name, file_name, cache_valid, cache_time, attr_time) } probe nfs.fop.mmap.return { printf("%s(%s)\n", name, retstr) } probe nfs.fop.open { printf("%s(%s)\n", name, argstr) printf("%d %d %d %s\n", dev, ino, s_id, devname) printf("%d\n", i_size) } probe nfs.fop.open.return { printf("%s(%s)\n", name, retstr) } probe nfs.fop.flush { printf("%s(%s)\n", name, argstr) printf("%d %d %d %s\n", dev, ino, s_id, devname) printf("%d %d\n", mode, ndirty) } probe nfs.fop.flush.return { printf("%s(%s)\n", name, retstr) } probe nfs.fop.release { printf("%s(%s)\n", name, argstr) printf("%d %d %d %s\n", dev, ino, s_id, devname) printf("%d\n", mode) } probe nfs.fop.release.return { printf("%s(%s)\n", name, retstr) } probe nfs.fop.fsync { printf("%s(%s)\n", name, argstr) printf("%d %d %d %s\n", dev, ino, s_id, devname) printf("%d\n", ndirty) } probe nfs.fop.fsync.return { printf("%s(%s)\n", name, retstr) } probe nfs.fop.lock { printf("%s(%s)\n", name, argstr) printf("%d %d %d %s\n", dev, ino, s_id, devname) printf("%d %d %d %d\n", fl_type, fl_flag, fl_start, fl_end) } probe nfs.fop.lock.return { printf("%s(%s)\n", name, retstr) } probe nfs.fop.sendfile ? { printf("%s(%s)\n", name, argstr) printf("%d %d %d %s\n", dev, ino, s_id, devname) printf("%d %d %d\n", cache_valid, cache_time, attr_time) } probe nfs.fop.sendfile.return ? { printf("%s(%s)\n", name, retstr) printf("%d %s\n", size, units) } # nfs.fop.check_flags test moved to nfs-fop.check_flags.stp probe nfs.fop.check_flags.return { printf("%s(%s)\n", name, retstr) } # # nfs.fop meta tests # probe nfs.fop.entries { printf("%s(%s)\n", name, argstr) } probe nfs.fop.return { printf("%s(%s)\n", name, retstr) } # # nfs.aop.* probes # probe nfs.aop.readpage { printf("%s(%s)\n", name, argstr) printf("%d %d %d\n", __page, dev, ino) printf("%d %d\n", i_flag, i_size) printf("%d %d %d\n", sb_flag, file, __inode) printf("%d %s\n", size, units) } probe nfs.aop.readpage.return { printf("%s(%s)\n", name, retstr) printf("%d %s\n", size, units) } probe nfs.aop.readpages { printf("%s(%s)\n", name, argstr) printf("%d %d\n", dev, ino) printf("%d %d %d\n", file, rpages, rsize) printf("%d %s\n", size, units) } probe nfs.aop.readpages.return { printf("%s(%s)\n", name, retstr) printf("%d %s\n", size, units) } probe nfs.aop.set_page_dirty { printf("%s(%s)\n", name, argstr) printf("%d\n", __page) } probe nfs.aop.set_page_dirty.return { printf("%s(%s)\n", name, retstr) } probe nfs.aop.writepage { printf("%s(%s)\n", name, argstr) printf("%d %d %d\n", __page, dev, ino) printf("%d %d\n", for_reclaim, for_kupdate) printf("%d %d %d\n", i_flag, i_state, i_size) printf("%d %d %d\n", sb_flag, __inode, wsize) printf("%d %s\n", size, units) } probe nfs.aop.writepage.return { printf("%s(%s)\n", name, retstr) } probe nfs.aop.writepages { printf("%s(%s)\n", name, argstr) printf("%d %d\n", dev, ino) printf("%d %d %d %d\n", for_reclaim, for_kupdate, wpages, wsize) printf("%d %s\n", size, units) } probe nfs.aop.writepages.return { printf("%s(%s)\n", name, retstr) } probe nfs.aop.write_begin { printf("%s(%s)\n", name, argstr) printf("%d %d %d %s\n", dev, ino, s_id, devname) printf("%d %d %s\n", pos, count, units) printf("%d %d %d %d %d\n", __page, offset, to, page_index, size) } probe nfs.aop.write_begin.return { printf("%s(%s)\n", name, retstr) } probe nfs.aop.write_end { printf("%s(%s)\n", name, argstr) printf("%d %d %d %s\n", dev, ino, s_id, devname) printf("%d %d %s\n", pos, count, units) printf("%d %d %d %d %d\n", __page, offset, to, page_index, size) printf("%d %d %d\n", i_flag, i_size, sb_flag) } probe nfs.aop.write_end.return { printf("%s(%s)\n", name, retstr) } probe nfs.aop.release_page ? { printf("%s(%s)\n", name, argstr) printf("%d %d %d\n", __page, dev, ino) printf("%d %s\n", size, units) } probe nfs.aop.release_page.return ? { printf("%s(%s)\n", name, retstr) } # # nfs.aop meta tests # probe nfs.aop.entries { printf("%s(%s)\n", name, argstr) } probe nfs.aop.return { printf("%s(%s)\n", name, retstr) } systemtap-2.3/testsuite/buildok/nfs-embedded.stp000077500000000000000000000007201217430427200221420ustar00rootroot00000000000000#! stap -p4 probe begin { print (__nfsi_cache_valid (0) + __nfsi_rcache_time (0) + __nfsi_attr_time (0) + __nfsi_ndirty (0) + __nfs_server_rsize (0) + __nfs_version (0) + __nfs_server_wsize (0) + __nfs_rpages (0) + __nfs_wpages (0) + __p2i(0) + __p2i_flag (0) + __p2i_state (0) + __p2i_size (0) + __p2sb_flag (0) + __file_inode (0) + __file_id (0) + __file_mode (0) + __iov_length (0,0,0,0)) print (__file_parentname (0)) } systemtap-2.3/testsuite/buildok/nfs-fop.check_flags.stp000077500000000000000000000002701217430427200234250ustar00rootroot00000000000000#! stap -p4 # This test fails on some kernels because we can't find the arguments to # this inline function (PR 1155). probe nfs.fop.check_flags { printf("%s(%s)\n", name, argstr) } systemtap-2.3/testsuite/buildok/nfs_proc-detailed.stp000077500000000000000000000072521217430427200232160ustar00rootroot00000000000000#! stap -p4 probe nfs.proc.lookup { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d\n", server_ip, prot, version, name_len) printf("%d %d\n", bitmask0, bitmask1) } probe nfs.proc.lookup.return { printf("%d: %s(%s)\n", version, name, retstr) } probe nfs.proc.read ? { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d %d %s\n", server_ip, prot, version, flags, size, units) } probe nfs.proc.read.return ? { printf("%d: %s(%s)\n", version, name, retstr) } probe nfs.proc.write ? { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d %d %s\n", server_ip, prot, version, flags, size, units) printf("%d %d\n", bitmask0, bitmask1) } probe nfs.proc.write.return ? { printf("%d: %s(%s)\n", version, name, retstr) printf("%d %s\n", size, units) } probe nfs.proc.commit ? { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d %s\n", server_ip, prot, version, size, units) printf("%d %d\n", bitmask0, bitmask1) } probe nfs.proc.commit.return ? { printf("%d: %s(%s)\n", version, name, retstr) printf("%d %s\n", size, units) } probe nfs.proc.read_setup { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d %d %s\n", client, server_ip, prot, version, size, units) } probe nfs.proc.read_setup.return { printf("%d: %s(%d)\n", version, name, retvalue) } probe nfs.proc.read_done { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d\n", server_ip, prot, count, version) printf("%d\n", timestamp) } probe nfs.proc.read_done.return { printf("%d: %s(%s)\n", version, name, retstr) } probe nfs.proc.write_setup { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d %d %s\n", client, server_ip, prot, version, size, units) printf("%d %d %d\n", how, bitmask0, bitmask1) } probe nfs.proc.write_setup.return { printf("%d: %s(%d)\n", version, name, retvalue) } probe nfs.proc.write_done { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d %d\n", server_ip, prot, count, valid, version) printf("%d\n", timestamp) } probe nfs.proc.write_done.return { printf("%d: %s(%s)\n", version, name, retstr) } probe nfs.proc.commit_setup { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d %d %s\n", client, server_ip, prot, version, size, units) printf("%d %d\n", bitmask0, bitmask1) } probe nfs.proc.commit_setup.return { printf("%d: %s(%d)\n", version, name, retvalue) } probe nfs.proc.commit_done { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d %d\n", server_ip, prot, count, valid, version) printf("%d\n", timestamp) } probe nfs.proc.commit_done.return { printf("%d: %s(%s)\n", version, name, retstr) } probe nfs.proc.open { printf("%s(%s)\n", name, argstr) printf("%d %d %d\n", server_ip, prot, version) } probe nfs.proc.open.return { printf("%s(%s)\n", name, retstr) } probe nfs.proc.release { printf("%s(%s)\n", name, argstr) printf("%d %d %d\n", server_ip, prot, version) } probe nfs.proc.release.return { printf("%s(%s)\n", name, retstr) } probe nfs.proc.handle_exception { printf("%s(%s)\n", name, argstr) printf("%d\n", version) } probe nfs.proc.handle_exception.return { printf("%s(%s)\n", name, retstr) } probe nfs.proc.create { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d %d %d\n", server_ip, prot, version, fh, filelen, mode) } probe nfs.proc.create.return { printf("%d: %s(%s)\n", version, name, retstr) } probe nfs.proc.remove { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d %d\n", server_ip, prot, version, fh, filelen) } probe nfs.proc.remove.return { printf("%d: %s(%s)\n", version, name, retstr) } probe nfs.proc.rename { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d %d %d %d\n", server_ip, prot, version, old_fh, old_filelen, new_fh, new_filelen) } probe nfs.proc.rename.return { printf("%d: %s(%s)\n", version, name, retstr) } systemtap-2.3/testsuite/buildok/nfs_proc-embedded.stp000077500000000000000000000006061217430427200231700ustar00rootroot00000000000000#! stap -p4 probe begin { print (AF_INET() + AF_INET6() + NFS_I(0) + NFS_FH(0) + NFS_SERVER(0) + NFS_CLIENT(0) + NFS_PROTO(0) + get_ip_from_client(0) + get_prot_from_client(0) + get_ip(0) + get_prot(0) + __nfsv4_bitmask (0,0) + %( systemtap_v < "2.3" %? __getfh_inode (0) + %) 0) } systemtap-2.3/testsuite/buildok/nfsd-all-probes.stp000077500000000000000000000001501217430427200226120ustar00rootroot00000000000000#! stap -wp4 // Tests if all probes in nfsd.stp are resolvable. probe nfsd.*, nfsd.*.*, nfsd.*.*.* {} systemtap-2.3/testsuite/buildok/nfsd-detailed.stp000077500000000000000000000152021217430427200223310ustar00rootroot00000000000000#! stap -p4 # # nfsd.dispatch tests # probe nfsd.dispatch { printf("%s(%s)\n", name, argstr) printf("%s %d %d %d\n", client_ip, xid, prog, proc) } probe nfsd.dispatch.return { printf("%s(%s)\n", name, retstr) } # # nfsd.proc*.lookup tests # probe nfsd.proc2.lookup, nfsd.proc3.lookup, nfsd.proc4.lookup ? { printf("%s(%s)\n", name, argstr) printf("%s %d %d %d\n", client_ip, proto, version, fh) printf("%d %s\n", filelen, filename) printf("%d %d\n", uid, gid) } probe nfsd.proc2.lookup.return, nfsd.proc3.lookup.return, nfsd.proc4.lookup.return ? { printf("%s(%s) %d\n", name, retstr, version) } probe nfsd.proc.lookup { printf("%s(%s)\n", name, argstr) } probe nfsd.proc.lookup.return { printf("%s(%s)\n", name, retstr) } # # nfsd.proc*.read tests # probe nfsd.proc2.read, nfsd.proc3.read, nfsd.proc4.read ? { printf("%s(%s)\n", name, argstr) printf("%s %d %d %d\n", client_ip, proto, version, fh) printf("%d %d\n", vec, vlen) printf("%d %s\n", size, units) printf("%d %d\n", uid, gid) } probe nfsd.proc2.read.return, nfsd.proc3.read.return, nfsd.proc4.read.return ? { printf("%s(%s) %d\n", name, retstr, version) } probe nfsd.proc.read { printf("%s(%s)\n", name, argstr) } probe nfsd.proc.read.return { printf("%s(%s)\n", name, retstr) } # # nfsd.proc*.write tests # probe nfsd.proc2.write, nfsd.proc3.write, nfsd.proc4.write ? { printf("%s(%s)\n", name, argstr) printf("%s %d %d %d\n", client_ip, proto, version, fh) printf("%d %d %d\n", vec, vlen, stable) printf("%d %s\n", size, units) printf("%d %d\n", uid, gid) } probe nfsd.proc2.write.return, nfsd.proc3.write.return, nfsd.proc4.write.return ? { printf("%s(%s) %d\n", name, retstr, version) printf("%d\n", count) } probe nfsd.proc.write { printf("%s(%s)\n", name, argstr) } probe nfsd.proc.write.return { printf("%s(%s)\n", name, retstr) } # # nfsd.proc*.commit tests # probe nfsd.proc3.commit, nfsd.proc4.commit ? { printf("%s(%s)\n", name, argstr) printf("%s %d %d %d\n", client_ip, proto, version, fh) printf("%d %s\n", size, units) printf("%d %d\n", uid, gid) } probe nfsd.proc3.commit.return, nfsd.proc4.commit.return ? { printf("%s(%s) %d\n", name, retstr, version) } probe nfsd.proc.commit { printf("%s(%s)\n", name, argstr) } probe nfsd.proc.commit.return { printf("%s(%s)\n", name, retstr) } # # nfsd.proc*.create tests # probe nfsd.proc2.create, nfsd.proc3.create, nfsd.proc4.create ? { printf("%s(%s)\n", name, argstr) printf("%s %d %d %d\n", client_ip, proto, version, fh) printf("%d\n", createmode) printf("%d %d\n", uid, gid) } probe nfsd.proc3.create.return, nfsd.proc3.create.return, nfsd.proc4.create.return ? { printf("%s(%s) %d\n", name, retstr, version) } probe nfsd.proc.create { printf("%s(%s)\n", name, argstr) } probe nfsd.proc.create.return { printf("%s(%s)\n", name, retstr) } # # nfsd.proc*.remove tests # probe nfsd.proc2.remove, nfsd.proc3.remove, nfsd.proc4.remove ? { printf("%s(%s)\n", name, argstr) printf("%s %d %d %d\n", client_ip, proto, version, fh) printf("%d %d\n", uid, gid) } probe nfsd.proc3.remove.return, nfsd.proc3.remove.return, nfsd.proc4.remove.return ? { printf("%s(%s) %d\n", name, retstr, version) } probe nfsd.proc.remove { printf("%s(%s)\n", name, argstr) } probe nfsd.proc.remove.return { printf("%s(%s)\n", name, retstr) } # # nfsd.proc*.rename tests # probe nfsd.proc2.rename, nfsd.proc3.rename, nfsd.proc4.rename ? { printf("%s(%s)\n", name, argstr) printf("%s %d %d %d %d\n", client_ip, proto, version, fh, tfh) printf("%d %s\n", filelen, filename) printf("%d %s\n", tlen, tname) printf("%d %d\n", uid, gid) } probe nfsd.proc3.rename.return, nfsd.proc3.rename.return, nfsd.proc4.rename.return ? { printf("%s(%s) %d\n", name, retstr, version) } probe nfsd.proc.rename { printf("%s(%s)\n", name, argstr) } probe nfsd.proc.rename.return { printf("%s(%s)\n", name, retstr) } # # nfsd.proc meta tests # probe nfsd.proc.entries { printf("%s(%s)\n", name, argstr) } probe nfsd.proc.return { printf("%s(%s)\n", name, retstr) } # # nfsd.open tests # probe nfsd.open { printf("%s(%s)\n", name, argstr) printf("%s %s\n", client_ip, fh) } probe nfsd.open.return { printf("%s(%s)\n", name, retstr) } # # nfsd.close tests # probe nfsd.close { printf("%s(%s)\n", name, argstr) printf("%s\n", client_ip) } probe nfsd.close.return { printf("%s(%s)\n", name, retstr) } # # nfsd.read tests # probe nfsd.read { printf("%s(%s)\n", name, argstr) printf("%s %s\n", client_ip, fh) printf("%d %d %d\n", file, vec, vlen) printf("%d %s\n", size, units) } probe nfsd.read.return { printf("%s(%s)\n", name, retstr) printf("%s %s\n", client_ip, fh) } # # nfsd.write tests # probe nfsd.write { printf("%s(%s)\n", name, argstr) printf("%s %s\n", client_ip, fh) printf("%d %d %d\n", file, vec, vlen) printf("%d %s\n", size, units) } probe nfsd.write.return { printf("%s(%s)\n", name, retstr) printf("%s %s\n", client_ip, fh) } # # nfsd.commit tests # probe nfsd.commit { printf("%s(%s)\n", name, argstr) printf("%s %s\n", client_ip, fh) printf("%d\n", flag) printf("%d %s\n", size, units) } probe nfsd.commit.return { printf("%s(%s)\n", name, retstr) printf("%s %s\n", client_ip, fh) } # # nfsd.lookup tests # probe nfsd.lookup { printf("%s(%s)\n", name, argstr) printf("%s %s\n", client_ip, fh) printf("%d %s\n", filelen, filename) } probe nfsd.lookup.return { printf("%s(%s)\n", name, retstr) printf("%s %s\n", client_ip, fh) } # # nfsd.create tests # probe nfsd.create { printf("%s(%s)\n", name, argstr) printf("%s %s\n", client_ip, fh) printf("%d %s %d %d %d\n", filelen, filename, type, iap_valid, iap_mode) } probe nfsd.create.return { printf("%s(%s)\n", name, retstr) printf("%s %s\n", client_ip, fh) } # # nfsd.createv3 tests # probe nfsd.createv3 { printf("%s(%s)\n", name, argstr) printf("%s %s\n", client_ip, fh) printf("%d %s %d %d\n", filelen, filename, iap_valid, iap_mode) printf("%d %d %d\n", truncp, verifier, createmode) } probe nfsd.createv3.return { printf("%s(%s)\n", name, retstr) printf("%s %s\n", client_ip, fh) } # # nfsd.unlink tests # probe nfsd.unlink { printf("%s(%s)\n", name, argstr) printf("%s %s\n", client_ip, fh) printf("%d %s %d\n", filelen, filename, type) } probe nfsd.unlink.return { printf("%s(%s)\n", name, retstr) printf("%s %s\n", client_ip, fh) } # # nfsd.rename tests # probe nfsd.rename { printf("%s(%s)\n", name, argstr) printf("%s %s %s\n", client_ip, fh, tfh) printf("%d %s\n", filelen, filename) printf("%d %s\n", tlen, tname) } probe nfsd.rename.return { printf("%s(%s)\n", name, retstr) printf("%s %s\n", client_ip, fh) } # # nfsd meta tests # probe nfsd.entries { printf("%s(%s)\n", name, argstr) } probe nfsd.return { printf("%s(%s)\n", name, retstr) } systemtap-2.3/testsuite/buildok/nfsd-embedded.stp000077500000000000000000000001631217430427200223070ustar00rootroot00000000000000#! stap -p4 probe begin { print (__svc_fh (0)) print (nfs3_cmode(0)) print (nfs4_ctype(0)) print (ftype(0)) } systemtap-2.3/testsuite/buildok/nfsderrno-embedded.stp000077500000000000000000000000641217430427200233550ustar00rootroot00000000000000#! stap -p4 probe begin { print (nfsderror (0)) } systemtap-2.3/testsuite/buildok/nine.stp000077500000000000000000000001371217430427200205600ustar00rootroot00000000000000#! stap -wp2 function f () { } function g (arg) { } probe begin { (true=1) ? f() : g(1); } systemtap-2.3/testsuite/buildok/nineteen.stp000077500000000000000000000005221217430427200214320ustar00rootroot00000000000000#! stap -p4 function msg1 (x) { log(x) } function msg2 (x,y) { log(x." ".y) } probe begin { msg1("55"); msg1(sprint(55)) msg2("100", "GOOD") msg2("GOOD", sprint(100)) # the next line caused a compile failure when uncommented; PR 1335 msg2(sprint(100), "GOOD") exit() } systemtap-2.3/testsuite/buildok/null.stp000077500000000000000000000001241217430427200205750ustar00rootroot00000000000000#! stap -p4 # PR10298 global foo = 5 probe begin { if (foo == NULL) log("hello") } systemtap-2.3/testsuite/buildok/oldlocals01.stp000077500000000000000000000005311217430427200217420ustar00rootroot00000000000000#! /bin/sh stap $@ -g -p4 --compatible=1.7.9 -e ' # test accessing locals using THIS->foo in legacy mode function baz:long(foo:long, bar:string) %{ _stp_printf("%s\n", THIS->bar); THIS->__retvalue = 600 + THIS->foo; %} probe begin { q = baz(9001, "I am in your dmesg making stupid jokes") printf("%d\n", q) exit() } ' systemtap-2.3/testsuite/buildok/oldlocals02.stp000077500000000000000000000006441217430427200217500ustar00rootroot00000000000000#! stap -gp4 # test accessing locals in old fashion using /* unmangled */ function baz:long(foo:long, bar:string) %{ /* unmangled */ printk("%s\n", THIS->bar); /* Notice that we can also use the new fashion: */ THIS->__retvalue = 600 + THIS->foo + STAP_ARG_foo; %} probe begin { q = baz(9001, "O hai... I am in your dmesg, putting the Lolcats ^w^") printf("%d\n", q) exit() } systemtap-2.3/testsuite/buildok/one.stp000077500000000000000000000005451217430427200204130ustar00rootroot00000000000000#! stap -p4 global foo, bar, baz probe begin { x = 10 foo["hello"] = 25 foo["hello"]++ foo["hello"] = 0; ++foo["hello"] x = foo["hello"] foo["yo"] *= bar[x, foo["hello"], "goodbye"]++; bar[0, 0, ""] = 0 foreach ([m, o, p] in bar) baz[m] = p # empty string treatment baz[10] = "" q = baz[223] print("hello from systemtap\n") print(q) } systemtap-2.3/testsuite/buildok/per-process-syscall.stp000077500000000000000000000003511217430427200235370ustar00rootroot00000000000000#! stap -p4 # # per-process syscall trace test probe process.syscall { print($syscall) print($arg1) print($arg2) print($arg3) print($arg4) print($arg5) print($arg6) } probe process.syscall.return { print($syscall) print($return) } systemtap-2.3/testsuite/buildok/pmap_foreach.stp000077500000000000000000000017451217430427200222610ustar00rootroot00000000000000#! stap -p4 global foo probe begin { for (i=0;i<10;i+=2) { foo[1] <<< i foo[2] <<< i*i foo[3] <<< i*i*i } foo[3] <<< 4*4*4 exit() } probe end { for (i=1;i<4;i++) { printf("count of foo[%d] = %d\n", i, @count(foo[i])) printf("first bucket of hist_log of foo[%d] = %d\n", i, @hist_log(foo[i])[0]) print(@hist_log(foo[i])) } foreach (i in foo) { printf("count of foo[%d] = %d\n", i, @count(foo[i])) printf("first bucket of hist_log of foo[%d] = %d\n", i, @hist_log(foo[i])[0]) print(@hist_log(foo[i])) } foreach (i+ in foo) { printf("count of foo[%d] = %d\n", i, @count(foo[i])) printf("first bucket of hist_log of foo[%d] = %d\n", i, @hist_log(foo[i])[0]) print(@hist_log(foo[i])) } foreach (i in foo) { printf("count of foo[%d] = %d\n", i, @count(foo[i])) foreach (j in @hist_log(foo[i])) if (@hist_log(foo[i])[j]) printf("bucket %d of hist_log of foo[%d] = %d\n", j, i, @hist_log(foo[i])[j]) print(@hist_log(foo[i])) } } systemtap-2.3/testsuite/buildok/pr10678.stp000077500000000000000000000004051217430427200206540ustar00rootroot00000000000000#! stap -p4 # The ne2k_pci module dwarf refers to both kernel and 8390 module symbols %( CONFIG_NE2K_PCI == "m" %? probe module("ne2k_pci").function("ne2k_pci_open") { log($$parms); } %: probe begin { log("No ne2k-pci module, this test skipped.");exit(); } %) systemtap-2.3/testsuite/buildok/pr13284.stp000077500000000000000000000002221217430427200206450ustar00rootroot00000000000000#! stap -p4 # jiffies is a global that needs to be pulled from the symbol table. probe kernel.function("schedule_timeout") { println($jiffies) } systemtap-2.3/testsuite/buildok/pretty-uprobes.stp000077500000000000000000000006031217430427200226310ustar00rootroot00000000000000#! stap -p4 global i = 1 # pretty-printing in dwarf user context probe process("stap").function("parse_cmdline") { log($this->base_hash$) log($this->base_hash$$) log($this->perpass_verbose$) log($this->perpass_verbose$$) log($this->perpass_verbose[0]$) log($this->perpass_verbose[0]$$) log($this->perpass_verbose[i]$) log($this->perpass_verbose[i]$$) } systemtap-2.3/testsuite/buildok/pretty.stp000077500000000000000000000014621217430427200211600ustar00rootroot00000000000000#! stap -p4 global i = 1 # pretty-printing with @cast probe begin { t = task_current() log(@cast(t, "task_struct")->fs$) log(@cast(t, "task_struct")->fs$$) log(@cast(t, "task_struct")->comm$) log(@cast(t, "task_struct")->comm$$) log(@cast(t, "task_struct")->comm[0]$) log(@cast(t, "task_struct")->comm[0]$$) log(@cast(t, "task_struct")->comm[i]$) log(@cast(t, "task_struct")->comm[i]$$) } # pretty-printing in dwarf kernel context probe kernel.function("schedule_tail") %( CONFIG_TRACEPOINTS == "y" %? # pretty-printing in tracepoints , kernel.trace("sched_switch") %) { log($prev->fs$) log($prev->fs$$) log($prev->comm$) log($prev->comm$$) log($prev->comm[0]$) log($prev->comm[0]$$) log($prev->comm[i]$) log($prev->comm[i]$$) } systemtap-2.3/testsuite/buildok/print_histogram_entry.stp000077500000000000000000000011661217430427200242640ustar00rootroot00000000000000#! stap -p4 global foo global i probe begin { print("starting up\n") i = 0 } probe timer.jiffies(100) { printf("ping %d\n", i) foo <<< i if (i++ > 15) exit() } probe end { print("shutting down\n") printf("count %d, avg %d\n", @count(foo), @avg(foo)) for (i = 0; i < 7; ++i) printf("bucket %d: %d\n", i, @hist_log(foo)[i]) println("the first bucket is ", @hist_log(foo)[0]) println(@hist_log(foo)[0], " is the first bucket") println(1 + @hist_log(foo)[0], " is one plus the first bucket") // XXX the parser fails on this bucket expression: // println(@hist_log(foo)[0] + 1, " is the first bucket plus one") } systemtap-2.3/testsuite/buildok/print_histograms.stp000077500000000000000000000011541217430427200232230ustar00rootroot00000000000000#! stap -p4 global foo, bar global i probe begin { print("starting up\n") i = 0 } probe timer.jiffies(100) { printf("ping %d\n", i) foo <<< ((100 * i) + 50) bar <<< (50 * i * i) if (i++ > 15) exit() } probe end { print("shutting down\n") printf("count %d, avg %d\n", @count(foo), @avg(foo)) print(@hist_log(foo)) print(@hist_linear(bar, 1000, 10000, 1000)) println(@hist_log(foo)) println(@hist_linear(bar, 1000, 10000, 1000)) print(sprint(@hist_log(foo))) print(sprint(@hist_linear(bar, 1000, 10000, 1000))) print(sprintln(@hist_log(foo))) print(sprintln(@hist_linear(bar, 1000, 10000, 1000))) } systemtap-2.3/testsuite/buildok/printf.stp000077500000000000000000000023741217430427200211360ustar00rootroot00000000000000#! stap -p4 # test the translatability of the formatted printing operators probe begin { x = sprintf("take %d steps forward, %d steps back\n", 3, 2) printf("%s", x); printf("take %d steps forward, %d steps back\n", 3, 2) printf("take %d steps forward, %d steps back\n", 3+1, 2*2) bob = "bob" alice = "alice" print(bob) print(alice) print("hello") print(10) printf("%s phoned %s %4.4x times\n", bob, alice, 3456) printf("%s phoned %s %+4d times\n", bob . alice, alice, 3456) printf("%s phoned %s %.4x times\n", bob, alice . bob, 3456) printf("%s phoned %s %-i times\n", sprintf("%s%s", bob, bob), sprint(alice), 3456) printf("%s except after %s\n", sprintf("%s before %s", sprint(1), sprint(3)), sprint("C")) printf("\"quote\\this\"\n") printf("%s", "\"quote\\this\"\n") printf("%s\n", "\"quote\\this\"") printf("%d is %03o in octal\n", 9, 9) printf("%d is %#X in hex\n", 255, 255) printf("print unsigned %u\n", 17) printf("-% d is % d\n", 9, -9) print(1, "two", 3, "four") print(sprint(1, "two", 3, "four")) println(1, "two", 3, "four") print(sprintln(1, "two", 3, "four")) printd(", ", 1, "two", 3, "four") print(sprintd(", ", 1, "two", 3, "four")) printdln(", ", 1, "two", 3, "four") print(sprintdln(", ", 1, "two", 3, "four")) } systemtap-2.3/testsuite/buildok/proc_mem-embedded.stp000077500000000000000000000014311217430427200231550ustar00rootroot00000000000000#! stap -p4 probe begin { printf("%d\n", _stp_valid_task(0) + _MM_FILEPAGES() + _MM_ANONPAGES() + _stp_get_mm_counter(0, 0) + _stp_mem_txt_adjust(0, 0)) printf("%s\n", _stp_number_to_string_postfix(1, 0, "")) printf("%d\n", proc_mem_size()); printf("%d\n", proc_mem_rss()); printf("%d\n", proc_mem_shr()); printf("%d\n", proc_mem_txt()); printf("%d\n", proc_mem_data()); printf("%d\n", mem_page_size()) printf("%s\n", bytes_to_string(0)); printf("%s\n", pages_to_string(0)); printf("%s\n", proc_mem_string()); } probe end { printf("%d\n", proc_mem_size_pid(0)); printf("%d\n", proc_mem_rss_pid(0)); printf("%d\n", proc_mem_shr_pid(0)); printf("%d\n", proc_mem_txt_pid(0)); printf("%d\n", proc_mem_data_pid(0)); printf("%s\n", proc_mem_string_pid(0)); } systemtap-2.3/testsuite/buildok/process_test.stp000077500000000000000000000010521217430427200223410ustar00rootroot00000000000000#! stap -p4 probe kprocess.create { log(pp()) log(sprint(task)) } probe kprocess.start { log(pp()) } probe kprocess.exec { log(pp()) log(filename) } probe kprocess.exec_complete { log(pp()) log(sprint(errno)) log(sprint(success)) } probe kprocess.exit { log(pp()) log(sprint(code)) } probe kprocess.release { log(pp()) log(sprint(task)) } probe signal.send { log(pp()) log(sprint(sig)) log(sig_name) log(sprint(task)) log(sprint(shared)) } probe signal.handle { log(pp()) log(sprint(sig)) log(sig_name) } systemtap-2.3/testsuite/buildok/procfs01.stp000077500000000000000000000002761217430427200212700ustar00rootroot00000000000000#! stap -p4 global foo_value = "100\n" probe procfs("foo").read { $value = foo_value } probe procfs("foo").write { foo_value = $value printf("value is %s", foo_value) } systemtap-2.3/testsuite/buildok/queue_stats-embedded.stp000077500000000000000000000010011217430427200237070ustar00rootroot00000000000000#! stap -p4 probe begin { qsq_start("test") qs_wait("test") qs_run("test") qs_done("test") print("Time = %d", qs_time()) print("Utilization % = %d", qsq_utilization("test", 100)) print("Wait % = %d", qsq_blocked("test", 100)) print("Avg queue length = %d", qsq_wait_queue_length("test", 1)) print("Avg service time = %d", qsq_service_time("test", 1)) print("Avg wait time = %d", qsq_wait_time("test", 1)) print("Avg requests served = %d", qsq_throughput("test", 1)) qsq_print("test") } systemtap-2.3/testsuite/buildok/random-embedded.stp000077500000000000000000000000721217430427200226340ustar00rootroot00000000000000#! stap -p4 probe begin { printf("%d\n", randint(10)) } systemtap-2.3/testsuite/buildok/rcu.stp000077500000000000000000000001131217430427200204120ustar00rootroot00000000000000#! stap -p4 probe begin { printf("%d\n", rcu_dereference(0)) exit() } systemtap-2.3/testsuite/buildok/rpc-all-probes.stp000077500000000000000000000001561217430427200224520ustar00rootroot00000000000000#! stap -wp4 // Tests if all probes in rpc.stp are resolvable. probe sunrpc.*, sunrpc.*.*, sunrpc.*.*.* {} systemtap-2.3/testsuite/buildok/rpc-detailed.stp000077500000000000000000000037631217430427200221740ustar00rootroot00000000000000#! stap -p4 # # Meta sunrpc tests # probe sunrpc.entry { printf("%s(%s)\n", name, argstr) } probe sunrpc.return { printf("%s %s\n", name, retstr) } # # sunrpc.clnt.* tests # probe sunrpc.clnt.*.return { printf("%s %s\n", name, retstr) } probe sunrpc.clnt.create_client, sunrpc.clnt.clone_client { printf("%s(%s)\n", name, argstr) } probe sunrpc.clnt.shutdown_client { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d %d %d %d %d %d\n", netreconn, rpccnt, om_ops, om_ntrans, om_bytes_sent, om_bytes_recv, om_queue, om_rtt, om_execute) } probe sunrpc.clnt.bind_new_program { printf("%s(%s)\n", name, argstr) printf("%d\n", prog) } probe sunrpc.clnt.call_sync, sunrpc.clnt.call_async { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d %d\n", prog, prot, port, dead, proc) } probe sunrpc.clnt.restart_call { printf("%s(%s)\n", name, argstr) } # # sunrpc.svc.* tests # probe sunrpc.svc.*.return { printf("%s %s\n", name, retstr) } probe sunrpc.svc.register { printf("%s(%s)\n", name, argstr) printf("%d\n", prog) } probe sunrpc.svc.create { printf("%s(%s)\n", name, argstr) } probe sunrpc.svc.destroy { printf("%s(%s)\n", name, argstr) printf("%s %d %d %d %d %d\n", sv_progname, netcnt, netcpconn, rpccnt, rpcbadfmt, rpcbadauth) } probe sunrpc.svc.process { printf("%s(%s)\n", name, argstr) printf("%d %d\n", sv_nrthreads, rq_prot) } probe sunrpc.svc.authorise { printf("%s(%s)\n", name, argstr) printf("%s\n", sv_name) } probe sunrpc.svc.recv { printf("%s(%s)\n", name, argstr) printf("%d %d\n", sv_prog, sv_nrthreads) } probe sunrpc.svc.send, sunrpc.svc.drop { printf("%s(%s)\n", name, argstr) } # # sunrpc.sched.* tests # probe sunrpc.sched.*.return { printf("%s %s\n", name, retstr) } probe sunrpc.sched.new_task, sunrpc.sched.release_task, sunrpc.sched.execute, sunrpc.sched.delay { printf("%s(%s)\n", name, argstr) } systemtap-2.3/testsuite/buildok/rpc-embedded.stp000077500000000000000000000005661217430427200221500ustar00rootroot00000000000000#! stap -p4 probe begin { print (__rpc_prot_from_protocol (0) + xid_from_clnt (0) + prog_from_clnt (0) + vers_from_clnt (0) + prot_from_clnt (0) + port_from_xprt(0) + port_from_clnt (0) + clones_from_clnt (0) + tasks_from_clnt (0) + proc_from_msg (0) + vers_from_prog (0, 0) + addr_from_rqst (0)) print (addr_from_rqst_str(0)) } systemtap-2.3/testsuite/buildok/scheduler-all-probes.stp000077500000000000000000000001431217430427200236400ustar00rootroot00000000000000#! stap -wp4 // Tests if all probes in the scheduler tapset are resolvable. probe scheduler.* {} systemtap-2.3/testsuite/buildok/scheduler-cpu_off.stp000077500000000000000000000001451217430427200232230ustar00rootroot00000000000000#! stap -p4 probe scheduler.cpu_off { printf("%s: %p %p %d\n", name, task_prev, task_next, idle) } systemtap-2.3/testsuite/buildok/scheduler-ctxswitch.stp000077500000000000000000000005511217430427200236230ustar00rootroot00000000000000#! stap -p4 probe scheduler.ctxswitch { printf("%s\n", name) printf("prev: pid %d, priority %d, state %d, task_name %s, tid %d\n", prev_pid, prev_priority, prevtsk_state, prev_task_name, prev_tid) printf("next: pid %d, priority %d, state %d, task_name %s, tid %d\n", next_pid, next_priority, nexttsk_state, next_task_name, next_tid) } systemtap-2.3/testsuite/buildok/scheduler-detailed.stp000077500000000000000000000047061217430427200233640ustar00rootroot00000000000000#! stap -p4 # Normally we don't test "internal" probes (ones starting with '__'), # but let's make sure the kprobes-based fallback probes for # tracepoint-based probes actually work. So, we'll test the *.kp # probes. # scheduler.cpu_off test moved to scheduler-cpu_off.stp probe scheduler.cpu_on ? { printf("%s: %p %d\n", name, task_prev, idle) } probe scheduler.tick { printf("%s: %d\n", name, idle) } probe scheduler.balance ? { printf("%s\n", name) } # scheduler.ctxswitch/__scheduler.ctxswitch.kp tests moved to # scheduler-ctxswitch.stp probe scheduler.kthread_stop { printf("%s\n", name) printf("pid = %d, priority = %d\n", thread_pid, thread_priority) } probe __scheduler.kthread_stop.kp { printf("pid = %d, priority = %d\n", thread_pid, thread_priority) } probe scheduler.kthread_stop.return { printf("%s\n", name) printf("return value = %d\n", return_value) } probe __scheduler.kthread_stop.return.kp { printf("return value = %d\n", return_value) } probe scheduler.wait_task ? { printf("%s\n", name) printf("pid = %d, priority = %d\n", task_pid, task_priority) } probe scheduler.wakeup { printf("%s\n", name) printf("pid = %d, priority = %d\n, state = %d, cpu = %d, tid = %d\n", task_pid, task_priority, task_state, task_cpu, task_tid) printf("task = %p\n", task) } probe scheduler.wakeup_new { printf("%s\n", name) printf("pid = %d, priority = %d, state = %d, cpu = %d, tid = %d\n", task_pid, task_priority, task_state, task_cpu, task_tid) printf("task = %p\n", task) } # scheduler.migrate/__scheduler.migrate.kp tests moved to # scheduler-migrate.stp probe scheduler.process_free, scheduler.process_exit { printf("%s\n", name) printf("pid = %d, priority = %d\n", pid, priority) } probe __scheduler.process_free.kp, __scheduler.process_exit.kp { printf("pid = %d, priority = %d\n", pid, priority) } probe scheduler.process_wait { printf("%s\n", name) printf("pid = %d\n", pid) } probe __scheduler.process_wait.kp { printf("pid = %d\n", pid) } probe scheduler.process_fork { printf("%s\n", name) printf("parent_pid = %d, child_pid = %d\n", parent_pid, child_pid) } probe __scheduler.process_fork.kp { printf("parent_pid = %d, child_pid = %d\n", parent_pid, child_pid) } probe scheduler.signal_send { printf("%s\n", name) printf("pid = %d, signal_number = %d\n", pid, signal_number) } probe __scheduler.signal_send.kp { printf("pid = %d\n", pid) } systemtap-2.3/testsuite/buildok/scheduler-embedded.stp000077500000000000000000000001261217430427200233320ustar00rootroot00000000000000#! stap -p4 probe begin { printf("%d\n", __is_idle() + container_of_task_rcu(0)) } systemtap-2.3/testsuite/buildok/scheduler-migrate.stp000077500000000000000000000006411217430427200232330ustar00rootroot00000000000000#! stap -p4 probe scheduler.migrate ? { printf("%s\n", name) printf("pid = %d, priority = %d\n", pid, priority) printf("%p %d/%d\n", task, cpu_from, cpu_to) } probe __scheduler.migrate.kp ? { printf("pid = %d, priority = %d\n", pid, priority) printf("%p %d/%d\n", task, cpu_from, cpu_to) } # Make sure this file compiles on kernels where scheduler.migrate # doesn't exist. probe begin { printf("begin\n") } systemtap-2.3/testsuite/buildok/scsi-all-probes.stp000077500000000000000000000001311217430427200226200ustar00rootroot00000000000000#! stap -wp4 // Tests if all probes in the scsi tapset are resolvable. probe scsi.* {} systemtap-2.3/testsuite/buildok/scsi-detailed.stp000077500000000000000000000037251217430427200223470ustar00rootroot00000000000000#! /bin/sh # This test should only be run when the scsi module is loaded (or scsi # functionality is built into the kernel). # We test for scsi functionality by grepping in /proc/kallsyms for # 'scsi_dispatch_cmd', which is what 'scsi.iodispatching' maps to. # If that mapping changes this grep command will also need changing. if ! grep scsi_dispatch_cmd /proc/kallsyms >/dev/null 2>&1 ; then echo "scsi funtionality not present - not running test"; exit 0; fi stap $@ -p4 - << EOF probe scsi.ioentry { printf("%20s, disk_major=%d, disk_minor=%d, device_state=%s, req_addr=%p\n", probefunc(), disk_major, disk_minor, device_state_str, req_addr) } probe scsi.iodispatching { printf("%20s, host_no=%d, channel=%d, lun=%d, dev_id=%d, device_state=%s, data_direction=%s, request_buffer=%p, request_bufflen=%d, req_addr=%p\n", probefunc(), host_no, channel, lun, dev_id, device_state_str, data_direction_str, request_buffer, request_bufflen, req_addr) } probe scsi.iodone { printf("%20s, host_no=%d, channel=%d, lun=%d, dev_id=%d, device_state=%s, data_direction=%s, scsi_timer_pending=%d, req_addr=%p\n", probefunc(), host_no, channel, lun, dev_id, device_state_str, data_direction_str, scsi_timer_pending, req_addr) } probe scsi.iocompleted { printf("%20s, host_no=%d, channel=%d, lun=%d, dev_id=%d, device_state=%s, data_direction=%s, goodbytes=%d, req_addr=%p\n", probefunc(), host_no, channel, lun, dev_id, device_state_str, data_direction_str, goodbytes, req_addr) } probe scsi.ioexecute { printf("%20s, host_no=%d, channel=%d, lun=%d, dev_id=%d, device_state=%s, data_direction=%s, request_buffer=%p, request_bufflen=%d retries=%d, timeout=%d\n", probefunc(), host_no, channel, lun, dev_id, device_state_str, data_direction_str, request_buffer, request_bufflen, retries, timeout) } probe scsi.set_state { printf("%20s, host_no=%d, channel=%d, lun=%d, dev_id=%d, old_state=%s, state=%s\n", probefunc(), host_no, channel, lun, dev_id, old_state_str, state_str) } EOF systemtap-2.3/testsuite/buildok/scsi-embedded.stp000077500000000000000000000003121217430427200223120ustar00rootroot00000000000000#! stap -p4 probe begin { println(describe_data_direction(0)) println(describe_device_state(0)) println(timer_pending(0)) println(scsi_timer_pending(0)) println(get_devstate_from_req (0)) } systemtap-2.3/testsuite/buildok/semicolon.stp000077500000000000000000000004751217430427200216240ustar00rootroot00000000000000#! stap -p4 # Test that semicolons are really optional (in non-block-like context). # PR11038. global x = 0; probe begin { if (x) log("true") else log("false") if (x) { log("true") } else { log("false") } if (x) log("true"); else log("false") if (x) log("true") else log("false"); } probe end { x = 1; } systemtap-2.3/testsuite/buildok/seven.stp000077500000000000000000000010071217430427200207440ustar00rootroot00000000000000#! stap -p4 # this tests whether integers, pointers, and enums can be # logged (PR 1258) # first: enums and ints %( kernel_v < "2.6.27" %? probe kernel.function("find_pid") { %( kernel_v >= "2.6.17" %? log ("find_pid (" . sprint($nr) . ")") %: log ("find_pid (" . sprint($type) . "," . sprint($nr) . ")") %) } %) # second: opaque pointers and enums probe kernel.function("detach_pid") { log ("detach_pid (" . sprintf("0x%x", $task) . "," . sprint($type) . ")") } systemtap-2.3/testsuite/buildok/seventeen.stp000077500000000000000000000012121217430427200216160ustar00rootroot00000000000000#! stap -p4 # this tests access to members of a target global variable # (PR 1191) probe kernel.function("pipe_write") { %( kernel_v > "3.9" %? printf("0x%x\n", $pipefifo_fops->llseek) %: %( kernel_v >= "2.6.27" %? printf("0x%x\n", $write_pipefifo_fops->llseek) %: printf("0x%x\n", $write_fifo_fops->llseek) %) %) } # PR10000: We're looking for *some* module function that has a nearby global variable in scope # XXX: See PR4096 probe module("nfs").function("nfs_create_client") !, module("nfs").function("nfs_init_client") !, kernel.function("nfs_fsync_dir") { println(kernel_string($nfs_program->name)) } probe timer.s(5) { exit() } systemtap-2.3/testsuite/buildok/signal-all-probes.stp000077500000000000000000000001571217430427200231440ustar00rootroot00000000000000#! stap -wp4 // Tests if all probes in the signal tapset are resolvable. probe signal.*, signal.*.* {} systemtap-2.3/testsuite/buildok/signal-check_ignored.stp000077500000000000000000000003371217430427200236700ustar00rootroot00000000000000#! stap -p4 # This test fails on some kernels because we can't find the arguments to # this inline function (PR 1155). probe signal.check_ignored { printf("%s(%d(%s), %d(%s))\n", name, sig, sig_name, sig_pid, pid_name) } systemtap-2.3/testsuite/buildok/signal-detailed.stp000077500000000000000000000047621217430427200226650ustar00rootroot00000000000000#! stap -p4 probe signal.send { printf("%s(%d(%s), %d(%s))\n", name, sig, sig_name, sig_pid, pid_name) printf("%s %p %p %d\n", si_code, task, sinfo, shared) %( systemtap_v <= "2.1" %? printf("%d\n", send2queue) %) } %( systemtap_v <= "2.1" %? probe signal.send.return { printf("%s() = %s\n", name, retstr) printf("%d %d\n", shared, send2queue) } %) probe signal.checkperm { printf("%s(%d(%s), %d(%s))\n", name, sig, sig_name, sig_pid, pid_name) printf("%s %p %p\n", si_code, task, sinfo) } probe signal.checkperm.return { printf("%s() = %s\n", name, retstr) } probe signal.wakeup { printf("%s(%d(%s))\n", name, sig_pid, pid_name) printf("%d %s\n", resume, state_mask) } # signal.check_ignored test moved to signal-check_ignored.stp probe signal.check_ignored.return { printf("%s() = %s\n", name, retstr) } probe signal.force_segv { printf("%s(%d(%s), %d(%s))\n", name, sig, sig_name, sig_pid, pid_name) } probe signal.force_segv.return { printf("%s() = %s\n", name, retstr) } probe signal.syskill { printf("%s(%d(%s), %d(%s))\n", name, sig, sig_name, sig_pid, pid_name) } probe signal.syskill.return { printf("%s() = %s\n", name, retstr) } probe signal.systkill { printf("%s(%d(%s), %d(%s))\n", name, sig, sig_name, sig_pid, pid_name) } probe signal.systkill.return { printf("%s() = %s\n", name, retstr) } probe signal.systgkill { printf("%s(%d(%s), %d(%s))\n", name, sig, sig_name, sig_pid, pid_name) printf("%d\n", tgid) } probe signal.systgkill.return { printf("%s() = %s\n", name, retstr) } probe signal.send_sig_queue { printf("%s(%d(%s), %d(%s))\n", name, sig, sig_name, sig_pid, pid_name) printf("%d\n", sigqueue_addr) } probe signal.send_sig_queue.return { printf("%s() = %s\n", name, retstr) } probe signal.pending { printf("%s(%p %d\n", name, sigset_add, sigset_size) } probe signal.pending.return { printf("%s() = %s\n", name, retstr) } # signal.handle test moved to signal-handle.stp %( systemtap_v <= "2.1" %? probe signal.handle.return ? { printf("%s() = %s\n", name, retstr) } %) probe signal.do_action { printf("%s(%d(%s)\n", name, sig, sig_name) printf("%p %p\n", sigact_addr, oldsigact_addr) printf("%p %d\n", sa_handler, sa_mask) } probe signal.do_action.return { printf("%s() = %s\n", name, retstr) } probe signal.procmask { printf("%s %d\n", name, how) printf("%p %p %d\n", sigset_addr, oldsigset_addr, sigset) } probe signal.procmask.return { printf("%s() = %s\n", name, retstr) } probe signal.flush { printf("%s(%d(%s))\n", name, sig_pid, pid_name) printf("%p\n", task) } systemtap-2.3/testsuite/buildok/signal-embedded.stp000077500000000000000000000002741217430427200226350ustar00rootroot00000000000000#! stap -p4 probe begin { print (get_sigset(0)) print (get_sa_flags(0)) print (get_sa_handler(0)) print (sigset_mask_str(0)) print (is_sig_blocked(0, 0)) print (sa_flags_str(0)) } systemtap-2.3/testsuite/buildok/signal-handle.stp000077500000000000000000000005131217430427200223330ustar00rootroot00000000000000#! stap -p4 # This test fails on some kernels because we can't find the arguments to # this inline function (PR 1155). probe signal.handle { printf("%s(%d(%s), %p\n", name, sig, sig_name, sinfo) printf("%d %p\n", sig_code, ka_addr) %( systemtap_v <= "2.1" %? printf("%p %d\n", oldset_addr, regs) %) printf("%s\n", sig_mode) } systemtap-2.3/testsuite/buildok/six.stp000077500000000000000000000004411217430427200204300ustar00rootroot00000000000000#! stap -p4 # tests probing of an inline function: note that due to comments # listed in PR 1155 we cannot resolve the parameters of the inline # at the moment. probe kernel.function("context_switch").inline ? { log ("found an inline function") } probe never { log ("or not ...") } systemtap-2.3/testsuite/buildok/sixteen.stp000077500000000000000000000005311217430427200213040ustar00rootroot00000000000000#! stap -p4 global a function foo () { if (a[4] == "sayonara") { return 2 } else { log ("no sayonara") } } probe begin { a[1] = "hello" a[2] = "goodbye" foreach (k in a) { log (a[k]) for (i=0; i<10; i++) { printf("k=%d i=%d\n", k, i) if (k % (i+1)) break else continue } if (k % 3) { foo() ; next } } } systemtap-2.3/testsuite/buildok/socket-all-probes.stp000077500000000000000000000001601217430427200231510ustar00rootroot00000000000000#! stap -wp4 // Tests if all probes in the socket tapset are resolvable. probe socket.*, socket.*.* {} systemtap-2.3/testsuite/buildok/socket-detailed.stp000077500000000000000000000046411217430427200226740ustar00rootroot00000000000000#! stap -wp4 probe socket.send, socket.receive, socket.sendmsg, socket.sendmsg.return, socket.recvmsg, socket.recvmsg.return, socket.aio_write, socket.aio_write.return, socket.aio_read, socket.aio_read.return, socket.writev ?, socket.writev.return ?, socket.readv ?, socket.readv.return ? { log(pp()) log(name) log(sprintf("%d", size)) pstr = sock_prot_num2str(protocol) prot = sock_prot_str2num(pstr) log(sprintf("%d, %d, %s", protocol, prot, pstr)) fstr = sock_fam_num2str(family) fam = sock_fam_str2num(fstr) log(sprintf("%d, %d, %s", family, fam, fstr)) sstr = sock_state_num2str(state) stat = sock_state_str2num(sstr) log(sprintf("%d, %d, %s", state, stat, sstr)) flstr = sock_flags_num2str(flags) log(sprintf("%d, %s", flags, flstr)) tstr = sock_type_num2str(type) typ = sock_type_str2num(tstr) log(sprintf("%d, %d, %s", type, typ, tstr)) log(sprintf("%d", success)) # -w since success is not universally defined } probe socket.create { log(name) pstr = sock_prot_num2str(protocol) prot = sock_prot_str2num(pstr) log(sprintf("%d, %d, %s", protocol, prot, pstr)) fstr = sock_fam_num2str(family) fam = sock_fam_str2num(fstr) log(sprintf("%d, %d, %s", family, fam, fstr)) tstr = sock_type_num2str(type) typ = sock_type_str2num(tstr) log(sprintf("%d, %d, %s", type, typ, tstr)) log(sprintf("%d", requester)) } probe socket.create.return { log(name) pstr = sock_prot_num2str(protocol) prot = sock_prot_str2num(pstr) log(sprintf("%d, %d, %s", protocol, prot, pstr)) fstr = sock_fam_num2str(family) fam = sock_fam_str2num(fstr) log(sprintf("%d, %d, %s", family, fam, fstr)) tstr = sock_type_num2str(type) typ = sock_type_str2num(tstr) log(sprintf("%d, %d, %s", type, typ, tstr)) log(sprintf("%d", requester)) log(sprintf("%d", err)) log(sprintf("%d", success)) } probe socket.close { log(name) pstr = sock_prot_num2str(protocol) prot = sock_prot_str2num(pstr) log(sprintf("%d, %d, %s", protocol, prot, pstr)) fstr = sock_fam_num2str(family) fam = sock_fam_str2num(fstr) log(sprintf("%d, %d, %s", family, fam, fstr)) tstr = sock_type_num2str(type) typ = sock_type_str2num(tstr) log(sprintf("%d, %d, %s", type, typ, tstr)) sstr = sock_state_num2str(state) stat = sock_state_str2num(sstr) log(sprintf("%d, %d, %s", state, stat, sstr)) flstr = sock_flags_num2str(flags) log(sprintf("%d, %s", flags, flstr)) } probe socket.close.return { log(name) } systemtap-2.3/testsuite/buildok/socket-embedded.stp000077500000000000000000000010221217430427200226400ustar00rootroot00000000000000#! stap -p4 # probe begin { print (sock_prot_num2str (0) . sock_fam_num2str (0) . sock_state_num2str (0) . sock_type_num2str (0) . sock_flags_num2str (0) . msg_flags_num2str (0)) print (sock_prot_str2num ("") + sock_fam_str2num ("") + sock_state_str2num ("") + sock_type_str2num ("") + _get_sock_addr (0) + _get_sock_size (0, 0) + %( systemtap_v < "2.3" %? _success_check (0) + _sock_prot_num (0) + _sock_fam_num (0) + _sock_state_num (0) + _sock_type_num (0) + _sock_flags_num (0) + %) 0) } systemtap-2.3/testsuite/buildok/stat_extract.stp000077500000000000000000000005631217430427200223370ustar00rootroot00000000000000#! stap -p4 # test the translatability of the statistic extraction operators global foo global bar global i probe timer.ms(100) { foo <<< i++ bar[10,"hello"] <<< (12 * i) if (@count(foo) > 1000) exit() } probe begin { i = 1 } probe end { printf("foo: min %d, max %d, count %d, sum %d, avg %d\n", @min(foo), @max(foo), @count(foo), @sum(foo), @avg(foo)) } systemtap-2.3/testsuite/buildok/stat_insert.stp000077500000000000000000000015141217430427200221660ustar00rootroot00000000000000#! stap -p4 # test the translatability of the statistic insertion operator global loggy global logmap global liney global linemap global numbers global strings global x, y function wibble() { i = 0 logmap[i++, "stewed"] <<< 1 logmap[i++, "boiled"] <<< 1 + 2 logmap[i++, "baked"] <<< (x = 0) logmap[i++, "fried"] <<< (x * (y=2)) + 3 } function wobble() { foreach (i in numbers) { foreach (j in strings) { linemap[strings[j],2*numbers[i],numbers[2*i]] <<< x * (y + i) } } } probe end { numbers[1] = 2 numbers[2] = 5 numbers[3] = 98279 numbers[4] = 8739287 strings[1] = "sun" strings[2] = "moon" strings[3] = "saturn" strings[4] = "venus" p = 4 q = 5 liney <<< 1 liney <<< 1 + 2 liney <<< p liney <<< (p * q) + 3 loggy <<< 1 loggy <<< 1 + 2 loggy <<< p loggy <<< (p * q) + 3 wibble() wobble() } systemtap-2.3/testsuite/buildok/stopwatches.stp000077500000000000000000000027451217430427200222020ustar00rootroot00000000000000#! stap -p4 # Copyright (C) 2012 Red Hat, Inc. # by William Cohen # # exercise the stopwatch tapset probe begin { start_stopwatch("wall"); /* The following assumes that target starts in user space */ /* If the target is already running and in the kernel, it is wrong. */ start_stopwatch("user"); stop_stopwatch("system") } probe syscall.* { if (pid() != target()) next stop_stopwatch("user") start_stopwatch("system") } probe syscall.*.return { if (pid() != target()) next start_stopwatch("user") stop_stopwatch("system") } probe end { stop_stopwatch("wall") stop_stopwatch("user") stop_stopwatch("system") w = read_stopwatch_s("wall") u = read_stopwatch_s("user") s = read_stopwatch_s("system") printf ("real\t%6ds\n", w); printf ("user\t%6ds\n", u); printf ("sys\t%6ds\n", s); w = read_stopwatch_ms("wall") u = read_stopwatch_ms("user") s = read_stopwatch_ms("system") printf ("real\t%9dms\n", w); printf ("user\t%9dms\n", u); printf ("sys\t%9dms\n", s); w = read_stopwatch_us("wall") u = read_stopwatch_us("user") s = read_stopwatch_us("system") printf ("real\t%12dus\n", w); printf ("user\t%12dus\n", u); printf ("sys\t%12dus\n", s); w = read_stopwatch_ns("wall") u = read_stopwatch_ns("user") s = read_stopwatch_ns("system") printf ("real\t%15dns\n", w); printf ("user\t%15dns\n", u); printf ("sys\t%15dns\n", s); delete_stopwatch("wall") delete_stopwatch("user") delete_stopwatch("system") } systemtap-2.3/testsuite/buildok/string-embedded.stp000077500000000000000000000005441217430427200226660ustar00rootroot00000000000000#! stap -p4 probe begin { println(strlen("abc")) println(substr("abc", 0, 1)) println(stringat("abc", 2)) println(isinstr("abc", "def")) println(text_str("abc")) println(text_strn("abc", 0, 1)) println(tokenize("abc", "a")) println(str_replace("abc", "a", "A")) println(strtol("123", 10)) println(isdigit("123")) } systemtap-2.3/testsuite/buildok/syscall.stp000077500000000000000000000002331217430427200212760ustar00rootroot00000000000000#! stap -wp4 probe syscall.*, syscall.*.return { if (retstr != "") printf("%s\n", retstr) else printf("%s: %s (%s) = ", execname(), name, argstr) } systemtap-2.3/testsuite/buildok/syscalls-arch-detailed.stp000077500000000000000000000240451217430427200241540ustar00rootroot00000000000000#! stap -p4 # # Arch-specific probes that all/most arches support. # # Newer kernel's syscall.mmap2 tests are in syscalls-detailed.stp. %( kernel_v < "2.6.33" %? %( arch != "i386" %? probe syscall.mmap { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %d, %d, %d\n", start, len, prot, flags, fd, offset) } probe syscall.mmap.return { printf("%s, %s\n", name, retstr) } %) probe syscall.mmap2 ? { printf("%s, %s\n", name, argstr) printf("%p, %d, %d, %d, %d, %d", start, length, prot, flags, fd, pgoffset) } probe syscall.mmap2.return ? { printf("%s, %s\n", name, retstr) } %) %( CONFIG_GENERIC_SIGALTSTACK == "n" %? probe syscall.sigaltstack { printf("%s, %s\n", name, argstr) printf("%p, %p\n", uss_uaddr, uoss_uaddr) %(systemtap_v < "2.3" %? printf("%p\n", regs) %) } probe syscall.sigaltstack.return { printf("%s, %s\n", name, retstr) } %) probe syscall.sys32_sigaltstack ? { printf("%s, %s\n", name, argstr) } probe syscall.sys32_sigaltstack.return ? { printf("%s, %s\n", name, retstr) } probe syscall.sysctl ?, syscall.sysctl32 ? { printf("%s, %s\n", name, argstr) } probe syscall.sysctl.return ?, syscall.sysctl32.return ? { printf("%s, %s\n", name, retstr) } # # i386-specific probes # %( arch == "i386" %? probe syscall.get_thread_area { printf("%s, %s\n", name, argstr) printf("%p", u_info_uaddr) } probe syscall.get_thread_area.return { printf("%s, %s\n", name, retstr) } probe syscall.iopl { printf("%s, %s\n", name, argstr) } probe syscall.iopl.return { printf("%s, %s\n", name, retstr) } probe syscall.ipc ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %d, %p, %d", call, first, second, third, ptr_uaddr, fifth) } probe syscall.ipc.return ? { printf("%s, %s\n", name, retstr) } # syscall.mmap2 is above probe syscall.set_thread_area { printf("%s, %s\n", name, argstr) printf("%p", u_info_uaddr) } probe syscall.set_thread_area.return { printf("%s, %s\n", name, retstr) } probe syscall.set_zone_reclaim ? { name = "set_zone_reclaim" printf("%d, %d, %d", node, zone, state) } probe syscall.set_zone_reclaim.return ? { printf("%s, %s\n", name, retstr) } # syscall.sigaltstack is above probe syscall.vm86, syscall.vm86old ? { printf("%s, %s\n", name, argstr) } probe syscall.vm86.return, syscall.vm86old.return ? { printf("%s, %s\n", name, retstr) } %) # # ia64-specific probes # %( arch == "ia64" %? # syscall.mmap is above # syscall.mmap2 is above # syscall.sigaltstack is above # syscall.sysctl32 is above %) # # powerpc-specific probes # %( arch == "powerpc" %? probe syscall.sys64_time ? { printf("%s, %s\n", name, argstr) } probe syscall.sys64_time.return ? { printf("%s, %s\n", name, retstr) } probe syscall.ppc64_personality { printf("%s, %s\n", name, argstr) printf("%d\n", persona) } probe syscall.ppc64_personality.return { printf("%s, %s\n", name, retstr) } probe syscall.ppc_rtas ? { printf("%s, %s\n", name, argstr) printf("%p\n", uargs_uaddr) } probe syscall.ppc_rtas.return ? { printf("%s, %s\n", name, retstr) } probe syscall.ppc64_sys32_stime ? { printf("%s, %s\n", name, argstr) printf("%p\n", t_uaddr) } probe syscall.ppc64_sys32_stime.return ? { printf("%s, %s\n", name, retstr) } probe syscall.sys32_ptrace ? { printf("%s, %s\n", name, argstr) printf("%p, %p, %p, %p", request, pid, addr, data) } probe syscall.sys32_ptrace.return ? { printf("%s, %s\n", name, retstr) } probe syscall.sys32_sysinfo ? { printf("%s, %s\n", name, argstr) printf("%p\n", info_uaddr) } probe syscall.sys32_sysinfo.return ? { printf("%s, %s\n", name, retstr) } # Notice no convenience variables like i386 version. 'ptr' is of a # different type. probe syscall.ipc ? { printf("%s, %s\n", name, argstr) } probe syscall.ipc.return ? { printf("%s, %s\n", name, retstr) } probe syscall.sys32_sigreturn ? { printf("%s, %s\n", name, argstr) printf("%p, %p, %p, %p, %p, %p\n", r3, r4, r5, r6, r7, r8) } probe syscall.sys32_sigreturn.return ? { printf("%s, %s\n", name, retstr) } probe syscall.sys32_adjtimex ? { printf("%s, %s\n", name, argstr) } probe syscall.sys32_adjtimex.return ? { printf("%s, %s\n", name, retstr) } probe syscall.sys32_getdents = kernel.function("sys32_getdents") ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", fd, dirp_uaddr, count) } probe syscall.sys32_getdents.return = kernel.function("sys32_getdents").return ? { printf("%s, %s\n", name, retstr) } # syscall.sysctl32 is above #probe syscall.compat_sysctl ? #{ # printf("%s, %s\n", name, argstr) #} #probe syscall.compat_sysctl.return ? #{ # printf("%s, %s\n", name, retstr) #} probe syscall.sys32_sched_setparam ? { printf("%s, %s\n", name, argstr) printf("%d, %p\n", pid, param_uaddr) } probe syscall.sys32_sched_setparam.return ? { printf("%s, %s\n", name, retstr) } probe syscall.sys32_sched_rr_get_interval ? { printf("%s, %s\n", name, argstr) printf("%d, %p\n", pid, interval_uaddr) } probe syscall.sys32_sched_rr_get_interval.return ? { printf("%s, %s\n", name, retstr) } probe syscall.sys32_rt_sigpending ? { printf("%s, %s\n", name, argstr) printf("%p, %d\n", set_uaddr, sigsetsize) } probe syscall.sys32_rt_sigpending.return ? { printf("%s, %s\n", name, retstr) } probe syscall.sys32_rt_sigtimedwait ? { printf("%s, %s\n", name, argstr) printf("%p, %p, %p, %p\n", uthese_uaddr, uinfo_uaddr, uts_uaddr, sigsetsize) } probe syscall.sys32_rt_sigtimedwait.return ? { printf("%s, %s\n", name, retstr) } probe syscall.sys32_rt_sigqueueinfo ? { printf("%s, %s\n", name, argstr) printf("%p, %d, %p\n", pid, sig, uinfo_uaddr) } probe syscall.sys32_rt_sigqueueinfo.return ? { printf("%s, %s\n", name, retstr) } # syscall.sigaltstack is above probe syscall.sys32_sendfile64 ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %p, %d", out_fd, in_fd, offset_uaddr, count) } probe syscall.sys32_sendfile64.return ? { printf("%s, %s\n", name, retstr) } probe syscall.ppc32_timer_create ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %p\n", which_clock, timer_event_spec, created_timer_id) } probe syscall.ppc32_timer_create.return ? { printf("%s, %s\n", name, retstr) } probe syscall.compat_timer_settime ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %p, %p\n", timer_id, flags, new_setting_uaddr, old_setting_uaddr) } probe syscall.compat_timer_settime.return ? { printf("%s, %s\n", name, retstr) } probe syscall.compat_timer_gettime ? { printf("%s, %s\n", name, argstr) printf("%d, %p\n", timer_id, setting_uaddr) } probe syscall.compat_timer_gettime.return ? { printf("%s, %s\n", name, retstr) } probe syscall.compat_clock_settime ? { printf("%s, %s\n", name, argstr) printf("%d, %p\n", which_clock, tp_uaddr) } probe syscall.compat_clock_settime.return ? { printf("%s, %s\n", name, retstr) } probe syscall.sys32_swapcontext ? { printf("%s, %s\n", name, argstr) printf("%p, %p, %d, %d, %d, %d, %p\n", old_ctx_uaddr, new_ctx_uaddr, r5, r6, r7, r8, regs) } probe syscall.sys32_swapcontext.return = kernel.function("sys32_swapcontext").return ? { printf("%s, %s\n", name, retstr) } probe syscall.sys32_utimes ? { printf("%s, %s\n", name, argstr) argstr = sprintf("%p(%s), %p\n", filename_uaddr, path, tvp_uaddr) } probe syscall.sys32_utimes.return ? { printf("%s, %s\n", name, retstr) } probe syscall.compat_mbind ? { printf("%s, %s\n", name, argstr) printf("%p, %d, %d, %p, %d, %d\n", start_uaddr, len, policy, nodemask_uaddr, maxnode, flags) } probe syscall.compat_mbind.return ? { printf("%s, %s\n", name, retstr) } probe syscall.compat_get_mempolicy ? { printf("%s, %s\n", name, argstr) printf("%p, %p, %d, %d, %d\n", policy_uaddr, nmask_uaddr, maxnode, addr, flags) } probe syscall.compat_get_mempolicy.return ? { printf("%s, %s\n", name, retstr) } probe syscall.compat_set_mempolicy ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", policy, nodemask_uaddr, maxnode) } probe syscall.compat_set_mempolicy.return ? { printf("%s, %s\n", name, retstr) } # syscall.mmap is above # syscall.mmap2 is above probe syscall.ppc64_sys_stime ? { printf("%s, %s\n", name, argstr) printf("%p\n", t_uaddr) } probe syscall.ppc64_sys_stime.return ? { printf("%s, %s\n", name, retstr) } probe syscall.ppc64_newuname ? { printf("%s, %s\n", name, argstr) printf("%p\n", name_uaddr) } probe syscall.ppc64_newuname.return ? { printf("%s, %s\n", name, retstr) } %) # # s390-specific probes # %( arch == "s390" %? probe syscall.getresgid16 { printf("%s, %s\n", name, argstr) printf("%p, %p, %p\n", rgid_uaddr, egid_uaddr, sgid_uaddr) } probe syscall.getresgid16.return { printf("%s, %s\n", name, retstr) } probe syscall.getresuid16 { printf("%s, %s\n", name, argstr) printf("%p, %p, %p\n", ruid_uaddr, euid_uaddr, suid_uaddr) } probe syscall.getresuid16.return { printf("%s, %s\n", name, retstr) } probe syscall.ipc ? { printf("%s, %s\n", name, argstr) } probe syscall.ipc.return ? { printf("%s, %s\n", name, retstr) } # syscall.mmap is above # syscall.mmap2 is above # syscall.sysctl32 is above %) # # x86_64-specific probes # %( arch == "x86_64" %? probe syscall.arch_prctl { printf("%s, %s\n", name, argstr) printf("%d, %d\n", code, addr) } probe syscall.arch_prctl.return { printf("%s, %s\n", name, retstr) } probe syscall.iopl { printf("%s, %s\n", name, argstr) printf("%d\n", level) } probe syscall.iopl.return { printf("%s, %s\n", name, retstr) } # syscall.sigaltstack is above # syscall.sysctl32 is above # Newer kernel's syscall.mmap2 tests are in syscalls-detailed.stp. %( kernel_v < "2.6.33" %? # syscall.mmap is above, but we want to make sure syscall.mmap32 # matches syscall.mmap probe syscall.mmap, syscall.mmap32 { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %d, %d, %d\n", start, len, prot, flags, fd, offset) } probe syscall.mmap.return, syscall.mmap32.return { printf("%s, %s\n", name, retstr) } %) # syscall.mmap2 is above probe syscall.vm86_warning { printf("%s, %s\n", name, argstr) } probe syscall.vm86_warning.return { printf("%s, %s\n", name, retstr) } probe syscall.pipe32 ? { printf("%s, %s\n", name, argstr) printf("%d, %s, %p, %d, %d\n", flags, flag_str, fildes_uaddr, pipe0, pipe1) } probe syscall.pipe32.return ? { printf("%s, %s\n", name, retstr) } %) systemtap-2.3/testsuite/buildok/syscalls-detailed.stp000077500000000000000000000626721217430427200232510ustar00rootroot00000000000000#! stap -p4 probe syscall.accept { printf("%s, %s\n", name, argstr) printf("%d(%s), %d, %p, %p\n", flags, flags_str, sockfd, addr_uaddr, addrlen_uaddr) } probe syscall.accept.return { printf("%s, %s\n", name, retstr) } probe syscall.access { printf("%s, %s\n", name, argstr) printf("%s, %d(%s)\n", pathname, mode, mode_str) } probe syscall.access.return { printf("%s, %s\n", name, retstr) } probe syscall.acct { printf("%s, %s\n", name, argstr) printf("%s\n", filename) } probe syscall.acct.return { printf("%s, %s\n", name, retstr) } probe syscall.add_key { printf("%s, %s\n", name, argstr) printf("%p, %p, %p, %d, %d\n", type_uaddr, description_uaddr, payload_uaddr, plen, ringid) } probe syscall.add_key.return { printf("%s, %s\n", name, retstr) } probe syscall.adjtimex, syscall.compat_adjtimex ? { printf("%s, %s\n", name, argstr) } probe syscall.adjtimex.return, syscall.compat_adjtimex.return ? { printf("%s, %s\n", name, retstr) } probe syscall.alarm ? { printf("%s, %s\n", name, argstr) printf("%d\n", seconds) } probe syscall.alarm.return ? { printf("%s, %s\n", name, retstr) } probe syscall.bdflush ? { printf("%s, %s\n", name, argstr) printf("%d %d(%s)\n", func, data, data_str) } probe syscall.bdflush.return ? { printf("%s, %s\n", name, retstr) } probe syscall.bind { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", sockfd, my_addr_uaddr, addrlen) } probe syscall.bind.return { printf("%s, %s\n", name, retstr) } probe syscall.brk { printf("%s, %s\n", name, argstr) printf("%d\n", brk) } probe syscall.brk.return { printf("%s, %s\n", name, retstr) } probe syscall.capget, syscall.capset { printf("%s, %s\n", name, argstr) printf("%p, %p\n", header_uaddr, data_uaddr) } probe syscall.capget.return, syscall.capset.return { printf("%s, %s\n", name, retstr) } probe syscall.chdir { printf("%s, %s\n", name, argstr) printf("%s\n", path) } probe syscall.chdir.return { printf("%s, %s\n", name, retstr) } probe syscall.chmod { printf("%s, %s\n", name, argstr) printf("%s, %d\n", path, mode) } probe syscall.chmod.return { printf("%s, %s\n", name, retstr) } probe syscall.chown, syscall.chown16 ? { printf("%s, %s\n", name, argstr) printf("%s, %d, %d\n", path, owner, group) } probe syscall.chown.return, syscall.chown16.return ? { printf("%s, %s\n", name, retstr) } probe syscall.chroot { printf("%s, %s\n", name, argstr) printf("%s\n", path) } probe syscall.chroot.return { printf("%s, %s\n", name, retstr) } probe syscall.clock_getres { printf("%s, %s\n", name, argstr) printf("%d(%s), %p\n", clk_id, clk_id_str, res_uaddr) } probe syscall.clock_getres.return { printf("%s, %s\n", name, retstr) } probe syscall.clock_gettime { printf("%s, %s\n", name, argstr) printf("%d(%s)\n", clk_id, clk_id_str) } probe syscall.clock_gettime.return { printf("%s, %s\n", name, retstr) } probe syscall.clock_nanosleep, syscall.compat_clock_nanosleep ? { printf("%s, %s\n", name, argstr) printf("%d(%s)\n", flags, flag_str) } probe syscall.clock_nanosleep.return, syscall.compat_clock_nanosleep.return ? { printf("%s, %s\n", name, retstr) } probe syscall.clock_settime { printf("%s, %s\n", name, argstr) printf("%d(%s), %p\n", clk_id, clk_id_str, tp_uaddr) } probe syscall.clock_settime.return { printf("%s, %s\n", name, retstr) } probe syscall.close { printf("%s, %s\n", name, argstr) printf("%d\n", fd) } probe syscall.close.return { printf("%s, %s\n", name, retstr) } probe syscall.connect { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", sockfd, serv_addr_uaddr, addrlen) } probe syscall.connect.return { printf("%s, %s\n", name, retstr) } probe syscall.creat { printf("%s, %s\n", name, argstr) printf("%d, %s\n", mode, pathname) } probe syscall.creat.return { printf("%s, %s\n", name, retstr) } probe syscall.delete_module { printf("%s, %s\n", name, argstr) printf("%s, %d\n", name_user, flags) } probe syscall.delete_module.return { printf("%s, %s\n", name, retstr) } probe syscall.dup { printf("%s, %s\n", name, argstr) printf("%d\n", oldfd) } probe syscall.dup.return { printf("%s, %s\n", name, retstr) } probe syscall.dup2 { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", oldfd, newfd, flags) } probe syscall.dup2.return { printf("%s, %s\n", name, retstr) } probe syscall.epoll_create ? { printf("%s, %s\n", name, argstr) printf("%d, %d\n", size, flags) } probe syscall.epoll_create.return ? { printf("%s, %s\n", name, retstr) } probe syscall.epoll_ctl ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %s, %d, %p\n", epfd, op, op_str, fd, event_uaddr) } probe syscall.epoll_ctl.return ? { printf("%s, %s\n", name, retstr) } probe syscall.epoll_pwait ? { printf("%s, %s\n", name, argstr) } probe syscall.epoll_pwait.return ? { printf("%s, %s\n", name, retstr) } probe syscall.epoll_wait ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %d, %d\n", epfd, events_uaddr, maxevents, timeout) } probe syscall.epoll_wait.return ? { printf("%s, %s\n", name, retstr) } probe syscall.eventfd ? { printf("%s, %s\n", name, argstr) printf("%d\n", flags) } probe syscall.eventfd.return ? { printf("%s, %s\n", name, retstr) } probe syscall.execve, syscall.compat_execve ? { printf("%s, %s\n", name, argstr) printf("%s, %s\n", filename, args) } probe syscall.execve.return, syscall.compat_execve.return ? { printf("%s, %s\n", name, retstr) } probe syscall.exit { printf("%s, %s\n", name, argstr) printf("%d\n", status) } # no syscall.exit return probe probe syscall.exit_group { printf("%s, %s\n", name, argstr) printf("%d\n", status) } # no syscall.exit_group return probe probe syscall.faccessat ? { printf("%s, %s\n", name, argstr) printf("%d(%s), %s, %d(%s)\n", dirfd, dirfd_str, pathname, mode, mode_str) } probe syscall.faccessat.return ? { printf("%s, %s\n", name, retstr) } probe syscall.fadvise64 ?, syscall.fadvise64_64 ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %d\n", fd, offset, len, advice) } probe syscall.fadvise64.return ?, syscall.fadvise64_64.return ? { printf("%s, %s\n", name, retstr) } probe syscall.fchdir { printf("%s, %s\n", name, argstr) printf("%d\n", fd) } probe syscall.fchdir.return { printf("%s, %s\n", name, retstr) } probe syscall.fchmod { printf("%s, %s\n", name, argstr) printf("%d, %d\n", fildes, mode) } probe syscall.fchmod.return { printf("%s, %s\n", name, retstr) } probe syscall.fchmodat ? { printf("%s, %s\n", name, argstr) printf("%d(%s), %s, %d\n", dirfd, dirfd_str, pathname, mode) } probe syscall.fchmodat.return ? { printf("%s, %s\n", name, retstr) } probe syscall.fchown, syscall.fchown16 ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", fd, owner, group) } probe syscall.fchown.return, syscall.fchown16.return ? { printf("%s, %s\n", name, retstr) } probe syscall.fchownat ? { printf("%s, %s\n", name, argstr) printf("%d(%s), %s, %d, %d, %d(%s)\n", dirfd, dirfd_str, pathname, owner, group, flags, flags_str) } probe syscall.fchownat.return ? { printf("%s, %s\n", name, retstr) } probe syscall.fcntl { printf("%s, %s\n", name, argstr) printf("%d, %d(%s), %d\n", fd, cmd, cmd_str, arg) } probe syscall.fcntl.return { printf("%s, %s\n", name, retstr) } probe syscall.fdatasync { printf("%s, %s\n", name, argstr) printf("%d\n", fd) } probe syscall.fdatasync.return { printf("%s, %s\n", name, retstr) } probe syscall.fgetxattr { printf("%s, %s\n", name, argstr) printf("%d, %s, %p, %d\n", filedes, name_str, value_uaddr, size) } probe syscall.fgetxattr.return { printf("%s, %s\n", name, retstr) } probe syscall.flistxattr { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", filedes, list_uaddr, size) } probe syscall.flistxattr.return { printf("%s, %s\n", name, retstr) } probe syscall.flock { printf("%s, %s\n", name, argstr) printf("%d, %d\n", fd, operation) } probe syscall.flock.return { printf("%s, %s\n", name, retstr) } probe syscall.fork { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %p, %p\n", clone_flags, stack_start, stack_size, parent_tid_uaddr, child_tid_uaddr) %(systemtap_v < "2.3" %? printf("%p\n", regs) %) } probe syscall.fork.return { printf("%s, %s\n", name, retstr) } probe syscall.fremovexattr { printf("%s, %s\n", name, argstr) printf("%d, %p(%s)\n", filedes, name_uaddr, name_str) } probe syscall.fremovexattr.return { printf("%s, %s\n", name, retstr) } probe syscall.fsetxattr { printf("%s, %s\n", name, argstr) printf("%d, %p(%s), %p, %d, %d\n", filedes, name_uaddr, name_str, value_uaddr, size, flags) } probe syscall.fsetxattr.return { printf("%s, %s\n", name, retstr) } probe syscall.fstat { printf("%s, %s\n", name, argstr) printf("%d, %p\n", filedes, buf_uaddr) } probe syscall.fstat.return { printf("%s, %s\n", name, retstr) } probe syscall.fstatat ? { printf("%s, %s\n", name, argstr) printf("%d, %s, %p\n", dirfd, path, buf_uaddr) } probe syscall.fstatat.return ? { printf("%s, %s\n", name, retstr) } probe syscall.fstatfs { printf("%s, %s\n", name, argstr) printf("%d, %p\n", fd, buf_uaddr) } probe syscall.fstatfs.return { printf("%s, %s\n", name, retstr) } probe syscall.fstatfs64 { printf("%s, %s\n", name, argstr) printf("%d, %d, %p\n", fd, sz, buf_uaddr) } probe syscall.fstatfs64.return { printf("%s, %s\n", name, retstr) } probe syscall.fsync { printf("%s, %s\n", name, argstr) printf("%d\n", fd) } probe syscall.fsync.return { printf("%s, %s\n", name, retstr) } probe syscall.ftruncate, syscall.ftruncate64 ? { printf("%s, %s\n", name, argstr) printf("%d, %d\n", fd, length) } probe syscall.ftruncate.return, syscall.ftruncate64.return ? { printf("%s, %s\n", name, retstr) } probe syscall.futex, syscall.compat_futex ? { printf("%s, %s\n", name, argstr) printf("%p, %d, %d, %p, %p, %d\n", futex_uaddr, op, val, utime_uaddr, uaddr2_uaddr, val3) } probe syscall.futex.return, syscall.compat_futex.return ? { printf("%s, %s\n", name, retstr) } probe syscall.futimesat ?, syscall.compat_futimesat ? { printf("%s, %s\n", name, argstr) printf("%d, %p(%s), %p\n", dirfd, filename_uaddr, filename, tvp_uaddr) } probe syscall.futimesat.return ?, syscall.compat_futimesat.return ? { printf("%s, %s\n", name, retstr) } probe syscall.getcwd { printf("%s, %s\n", name, argstr) printf("%p, %d\n", buf_uaddr, size) } probe syscall.getcwd.return { printf("%s, %s\n", name, retstr) } probe syscall.getdents { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", fd, dirp_uaddr, count) } probe syscall.getdents.return { printf("%s, %s\n", name, retstr) } probe syscall.getegid { printf("%s, %s\n", name, argstr) } probe syscall.getegid.return { printf("%s, %s\n", name, retstr) } probe syscall.geteuid { printf("%s, %s\n", name, argstr) } probe syscall.geteuid.return { printf("%s, %s\n", name, retstr) } probe syscall.getgid { printf("%s, %s\n", name, argstr) } probe syscall.getgid.return { printf("%s, %s\n", name, retstr) } probe syscall.getgroups { printf("%s, %s\n", name, argstr) printf("%d, %p\n", size, list_uaddr) } probe syscall.getgroups.return { printf("%s, %s\n", name, retstr) } probe syscall.gethostname ? { printf("%s, %s\n", name, argstr) printf("%p, %d\n", name_uaddr, len) } probe syscall.gethostname.return ? { printf("%s, %s\n", name, retstr) } probe syscall.getitimer, syscall.compat_getitimer ? { printf("%s, %s\n", name, argstr) printf("%d, %p\n", which, value_uaddr) } probe syscall.getitimer.return, syscall.compat_getitimer.return ? { printf("%s, %s\n", name, retstr) } probe syscall.get_mempolicy ? { printf("%s, %s\n", name, argstr) printf("%p, %p, %d, %p, %d\n", policy_uaddr, nmask_uaddr, maxnode, addr, flags) } probe syscall.get_mempolicy.return ? { printf("%s, %s\n", name, retstr) } probe syscall.getpeername { printf("%s, %s\n", name, argstr) printf("%d, %p, %p\n", s, name_uaddr, namelen_uaddr) } probe syscall.getpeername.return { printf("%s, %s\n", name, retstr) } probe syscall.getpgid { printf("%s, %s\n", name, argstr) printf("%d\n", pid) } probe syscall.getpgid.return { printf("%s, %s\n", name, retstr) } probe syscall.getpgrp ? { printf("%s, %s\n", name, argstr) } probe syscall.getpgrp.return ? { printf("%s, %s\n", name, retstr) } probe syscall.getpid { printf("%s, %s\n", name, argstr) } probe syscall.getpid.return { printf("%s, %s\n", name, retstr) } probe syscall.getppid { printf("%s, %s\n", name, argstr) } probe syscall.getppid.return { printf("%s, %s\n", name, retstr) } probe syscall.getpriority { printf("%s, %s\n", name, argstr) printf("%d, %d\n", which, who) } probe syscall.getpriority.return { printf("%s, %s\n", name, retstr) } probe syscall.getresgid { printf("%s, %s\n", name, argstr) printf("%p, %p, %p\n", rgid_uaddr, egid_uaddr, sgid_uaddr) } probe syscall.getresgid.return { printf("%s, %s\n", name, retstr) } probe syscall.getresuid { printf("%s, %s\n", name, argstr) printf("%p, %p, %p\n", ruid_uaddr, euid_uaddr, suid_uaddr) } probe syscall.getresuid.return { printf("%s, %s\n", name, retstr) } probe syscall.getrlimit { printf("%s, %s\n", name, argstr) printf("%d, %p\n", resource, rlim_uaddr) } probe syscall.getrlimit.return { printf("%s, %s\n", name, retstr) } probe syscall.getrusage { printf("%s, %s\n", name, argstr) printf("%d(%s), %p\n", who, who_str, usage_uaddr) } probe syscall.getrusage.return { printf("%s, %s\n", name, retstr) } probe syscall.getsid { printf("%s, %s\n", name, argstr) printf("%d\n", pid) } probe syscall.getsid.return { printf("%s, %s\n", name, retstr) } probe syscall.getsockname { printf("%s, %s\n", name, argstr) printf("%d, %p, %p\n", s, name_uaddr, namelen_uaddr) } probe syscall.getsockname.return { printf("%s, %s\n", name, retstr) } probe syscall.getsockopt { printf("%s, %s\n", name, argstr) printf("%d, %d(%s), %d(%s), %p, %p\n", fd, level, level_str, optname, optname_str, optval_uaddr, optlen_uaddr) } probe syscall.getsockopt.return { printf("%s, %s\n", name, retstr) } probe syscall.gettid { printf("%s, %s\n", name, argstr) } probe syscall.gettid.return { printf("%s, %s\n", name, retstr) } probe syscall.gettimeofday { printf("%s, %s\n", name, argstr) printf("%p, %p\n", tv_uaddr, tz_uaddr) } probe syscall.gettimeofday.return { printf("%s, %s\n", name, retstr) } probe syscall.getuid { printf("%s, %s\n", name, argstr) } probe syscall.getuid.return { printf("%s, %s\n", name, retstr) } probe syscall.getxattr { printf("%s, %s\n", name, argstr) printf("%s, %s, %p, %d\n", path, name_str, value_uaddr, size) } probe syscall.getxattr.return { printf("%s, %s\n", name, retstr) } probe syscall.init_module { printf("%s, %s\n", name, argstr) printf("%p, %d, %s\n", umod_uaddr, len, uargs) } probe syscall.init_module.return { printf("%s, %s\n", name, retstr) } probe syscall.inotify_add_watch ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %p(%s)\n", fd, mask, path_uaddr, path) } probe syscall.inotify_add_watch.return ? { printf("%s, %s\n", name, retstr) } probe syscall.inotify_init ? { printf("%s, %s\n", name, argstr) printf("%d\n", flags) } probe syscall.inotify_init.return ? { printf("%s, %s\n", name, retstr) } probe syscall.inotify_rm_watch ? { printf("%s, %s\n", name, argstr) printf("%d, %d\n", fd, wd) } probe syscall.inotify_rm_watch.return ? { printf("%s, %s\n", name, retstr) } probe syscall.io_cancel { printf("%s, %s\n", name, argstr) printf("%d, %p, %p\n", ctx_id, iocb_uaddr, result_uaddr) } probe syscall.io_cancel.return { printf("%s, %s\n", name, retstr) } probe syscall.ioctl { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", fd, request, argp) } probe syscall.ioctl.return { printf("%s, %s\n", name, retstr) } probe syscall.io_destroy { printf("%s, %s\n", name, argstr) printf("%d\n", ctx) } probe syscall.io_destroy.return { printf("%s, %s\n", name, retstr) } probe syscall.io_getevents, syscall.compat_io_getevents ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %p, %p, %s\n", ctx_id, min_nr, nr, events_uaddr, timeout_uaddr, timestr) } probe syscall.io_getevents.return, syscall.compat_io_getevents.return ? { printf("%s, %s\n", name, retstr) } probe syscall.ioperm ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", from, num, turn_on) } probe syscall.ioperm.return ? { printf("%s, %s\n", name, retstr) } probe syscall.io_setup, syscall.compat_io_setup ? { printf("%s, %s\n", name, argstr) printf("%d, %p\n", maxevents, ctxp_uaddr) } probe syscall.io_setup.return, syscall.compat_io_setup.return ? { printf("%s, %s\n", name, retstr) } probe syscall.io_submit, syscall.compat_io_submit ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %p\n", ctx_id, nr, iocbpp_uaddr) } probe syscall.io_submit.return, syscall.compat_io_submit.return ? { printf("%s, %s\n", name, retstr) } probe syscall.ioprio_get ? { printf("%s, %s\n", name, argstr) printf("%d, %d\n", which, who) } probe syscall.ioprio_get.return ? { printf("%s, %s\n", name, retstr) } probe syscall.ioprio_set ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", which, who, ioprio) } probe syscall.ioprio_set.return ? { printf("%s, %s\n", name, retstr) } probe syscall.kexec_load ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %p, %d\n", entry, nr_segments, segments_uaddr, flags) } probe syscall.kexec_load.return ? { printf("%s, %s\n", name, retstr) } probe syscall.keyctl { printf("%s, %s\n", name, argstr) } probe syscall.keyctl.return { printf("%s, %s\n", name, retstr) } probe syscall.kill { printf("%s, %s\n", name, argstr) printf("%d, %d\n", pid, sig) } probe syscall.kill.return { printf("%s, %s\n", name, retstr) } probe syscall.lchown, syscall.lchown16 ? { printf("%s, %s\n", name, argstr) printf("%s, %d, %d\n", path, owner, group) } probe syscall.lchown.return, syscall.lchown16.return ? { printf("%s, %s\n", name, retstr) } probe syscall.lgetxattr { printf("%s, %s\n", name, argstr) printf("%s, %s, %p, %d\n", path, name_str, value_uaddr, size) } probe syscall.lgetxattr.return { printf("%s, %s\n", name, retstr) } probe syscall.link { printf("%s, %s\n", name, argstr) printf("%s, %s\n", oldpath, newpath) } probe syscall.link.return { printf("%s, %s\n", name, retstr) } probe syscall.linkat ? { printf("%s, %s\n", name, argstr) printf("%d(%s), %s, %d(%s), %s, %d(%s)\n", olddirfd, olddirfd_str, oldpath, newdirfd, newdirfd_str, newpath, flags, flags_str) } probe syscall.linkat.return ? { printf("%s, %s\n", name, retstr) } probe syscall.listen { printf("%s, %s\n", name, argstr) printf("%d, %d\n", sockfd, backlog) } probe syscall.listen.return { printf("%s, %s\n", name, retstr) } probe syscall.listxattr, syscall.llistxattr { printf("%s, %s\n", name, argstr) printf("%p, %d, %p(%s)\n", list_uaddr, size, path_uaddr, path) } probe syscall.listxattr.return, syscall.llistxattr.return { printf("%s, %s\n", name, retstr) } probe syscall.llseek ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %p, %d(%s)\n", fd, offset_high, offset_low, result_uaddr, whence, whence_str) } probe syscall.llseek.return ? { printf("%s, %s\n", name, retstr) } probe syscall.lookup_dcookie { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", cookie, buffer_uaddr, len) } probe syscall.lookup_dcookie.return { printf("%s, %s\n", name, retstr) } probe syscall.lremovexattr { printf("%s, %s\n", name, argstr) printf("%p(%s), %p(%s)\n", name_uaddr, name_str, path_uaddr, path) } probe syscall.lremovexattr.return { printf("%s, %s\n", name, retstr) } probe syscall.lseek { printf("%s, %s\n", name, argstr) printf("%d, %d, %d(%s)\n", fildes, offset, whence, whence_str) } probe syscall.lseek.return { printf("%s, %s\n", name, retstr) } probe syscall.lsetxattr { printf("%s, %s\n", name, argstr) printf("%p(%s), %p(%s), %p, %d, %d\n", path_uaddr, path, name_uaddr, name_str, value_uaddr, size, flags) } probe syscall.lsetxattr.return { printf("%s, %s\n", name, retstr) } probe syscall.lstat { printf("%s, %s\n", name, argstr) printf("%s, %p\n", path, buf_uaddr) } probe syscall.lstat.return { printf("%s, %s\n", name, retstr) } probe syscall.madvise { printf("%s, %s\n", name, argstr) printf("%d, %d, %d(%s)\n", start, length, advice, advice_str) } probe syscall.madvise.return { printf("%s, %s\n", name, retstr) } probe syscall.mbind ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %p, %d, %d\n", start, len, mode, nmask_uaddr, maxnode, flags) } probe syscall.mbind.return ? { printf("%s, %s\n", name, retstr) } probe syscall.migrate_pages ? { printf("%s, %s\n", name, argstr) } probe syscall.migrate_pages.return ? { printf("%s, %s\n", name, retstr) } probe syscall.mincore { printf("%s, %s\n", name, argstr) printf("%d, %d, %p\n", start, length, vec_uaddr) } probe syscall.mincore.return { printf("%s, %s\n", name, retstr) } probe syscall.mkdir { printf("%s, %s\n", name, argstr) printf("%p(%s), %d\n", pathname_uaddr, pathname, mode) } probe syscall.mkdir.return { printf("%s, %s\n", name, retstr) } probe syscall.mkdirat ? { printf("%s, %s\n", name, argstr) printf("%d, %s, %d\n", dirfd, pathname, mode) } probe syscall.mkdirat.return ? { printf("%s, %s\n", name, retstr) } probe syscall.mknod { printf("%s, %s\n", name, argstr) printf("%s, %d, %d\n", pathname, mode, dev) } probe syscall.mknod.return { printf("%s, %s\n", name, retstr) } probe syscall.mknodat ? { printf("%s, %s\n", name, argstr) printf("%d(%s), %s, %d(%s), %d\n", dirfd, dirfd_str, pathname, mode, mode_str, dev) } probe syscall.mknodat.return ? { printf("%s, %s\n", name, retstr) } probe syscall.mlock { printf("%s, %s\n", name, argstr) printf("%d, %d\n", addr, len) } probe syscall.mlock.return { printf("%s, %s\n", name, retstr) } probe syscall.mlockall { printf("%s, %s\n", name, argstr) printf("%d\n", flags) } probe syscall.mlockall.return { printf("%s, %s\n", name, retstr) } probe syscall.modify_ldt ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", func, ptr_uaddr, bytecount) } probe syscall.modify_ldt.return ? { printf("%s, %s\n", name, retstr) } probe syscall.move_pages ? { printf("%s, %s\n", name, argstr) } probe syscall.move_pages.return ? { printf("%s, %s\n", name, retstr) } probe syscall.mount { printf("%s, %s\n", name, argstr) printf("%s, %s, %s, %d(%s), %s\n", source, target, filesystemtype, mountflags, mountflags_str, data) } probe syscall.mount.return { printf("%s, %s\n", name, retstr) } # Older kernel's syscall.mmap* tests are in syscalls-arch-detailed.stp. %( kernel_v >= "2.6.33" %? probe syscall.mmap2 { printf("%s, %s\n", name, argstr) printf("%p, %d, %d, %d, %d, %d", start, length, prot, flags, fd, pgoffset) } probe syscall.mmap2.return { printf("%s, %s\n", name, retstr) } %) probe syscall.mprotect { printf("%s, %s\n", name, argstr) printf("%p, %d, %d(%s)\n", addr, len, prot, prot_str) } probe syscall.mprotect.return { printf("%s, %s\n", name, retstr) } probe syscall.mq_getsetattr { printf("%s, %s\n", name, argstr) printf("%d, %p, %p\n", mqdes, u_mqstat_uaddr, u_omqstat_uaddr) } probe syscall.mq_getsetattr.return { printf("%s, %s\n", name, retstr) } probe syscall.mq_notify { printf("%s, %s\n", name, argstr) printf("%d, %p\n", mqdes, notification_uaddr) } probe syscall.mq_notify.return { printf("%s, %s\n", name, retstr) } probe syscall.mq_open { printf("%s, %s\n", name, argstr) printf("%p, %s, %d, %p, %d\n", name_uaddr, filename, mode, u_attr_uaddr, oflag) } probe syscall.mq_open.return { printf("%s, %s\n", name, retstr) } probe syscall.mq_timedreceive { printf("%s, %s\n", name, argstr) printf("%d, %p, %d, %p, %p\n", mqdes, msg_ptr_uaddr, msg_len, msg_prio_uaddr, abs_timeout_uaddr) } probe syscall.mq_timedreceive.return { printf("%s, %s\n", name, retstr) } probe syscall.mq_timedsend { printf("%s, %s\n", name, argstr) printf("%d, %p, %d, %d, %p\n", mqdes, msg_ptr_uaddr, msg_len, msg_prio, abs_timeout_uaddr) } probe syscall.mq_timedsend.return { printf("%s, %s\n", name, retstr) } probe syscall.mq_unlink { printf("%s, %s\n", name, argstr) printf("%p(%s)\n", u_name_uaddr, u_name) } probe syscall.mq_unlink.return { printf("%s, %s\n", name, retstr) } probe syscall.mremap { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %d, %d\n", old_address, old_size, new_size, flags, new_address) } probe syscall.mremap.return { printf("%s, %s\n", name, retstr) } probe syscall.msgctl, syscall.compat_sys_msgctl ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %p\n", msqid, cmd, buf_uaddr) } probe syscall.msgctl.return, syscall.compat_sys_msgctl.return ? { printf("%s, %s\n", name, retstr) } probe syscall.msgget { printf("%s, %s\n", name, argstr) printf("%d, %d(%s)\n", key, msgflg, msgflg_str) } probe syscall.msgget.return { printf("%s, %s\n", name, retstr) } probe syscall.msgrcv, syscall.compat_sys_msgrcv ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %d, %d, %d\n", msqid, msgp_uaddr, msgsz, msgtyp, msgflg) } probe syscall.msgrcv.return, syscall.compat_sys_msgrcv.return ? { printf("%s, %s\n", name, retstr) } probe syscall.msgsnd, syscall.compat_sys_msgsnd ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %d, %d\n", msqid, msgp_uaddr, msgsz, msgflg) } probe syscall.msgsnd.return, syscall.compat_sys_msgsnd.return ? { printf("%s, %s\n", name, retstr) } probe syscall.msync { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", start, length, flags) } probe syscall.msync.return { printf("%s, %s\n", name, retstr) } probe syscall.munlock { printf("%s, %s\n", name, argstr) printf("%p, %d\n", addr, len) } probe syscall.munlock.return { printf("%s, %s\n", name, retstr) } probe syscall.munlockall { printf("%s, %s\n", name, argstr) } probe syscall.munlockall.return { printf("%s, %s\n", name, retstr) } probe syscall.munmap { printf("%s, %s\n", name, argstr) printf("%p, %d\n", start, length) } probe syscall.munmap.return { printf("%s, %s\n", name, retstr) } systemtap-2.3/testsuite/buildok/syscalls2-detailed.stp000077500000000000000000000650431217430427200233260ustar00rootroot00000000000000#! stap -p4 probe syscall.nanosleep, syscall.compat_nanosleep ? { printf("%s(%s)\n", name, argstr) printf("%p %p\n", req_uaddr, rem_uaddr) } probe syscall.nanosleep.return, syscall.compat_nanosleep.return ? { printf("%s %s\n", name, retstr) } # nfsservctl was removed in kernel 3.0/2.6.40. %( kernel_v < "2.6.40" && CONFIG_NFSD == "[ym]" %? probe syscall.nfsservctl ? { printf("%s(%s)\n", name, argstr) printf("%d %p %p\n", cmd, argp_uaddr, resp_uaddr) } probe syscall.nfsservctl.return ? { printf("%s %s\n", name, retstr) } %) probe syscall.nice ? { printf("%s(%s)\n", name, argstr) printf("%d\n", inc) } probe syscall.nice.return ? { printf("%s %s\n", name, retstr) } probe syscall.ni_syscall { printf("%s(%s)\n", name, argstr) } probe syscall.ni_syscall.return { printf("%s %s\n", name, retstr) } probe syscall.open, syscall.openat ? { printf("%s(%s)\n", name, argstr) printf("%s %d %d\n", filename, flags, mode) } probe syscall.open.return, syscall.openat.return ? { printf("%s %s\n", name, retstr) } probe syscall.pause ? { printf("%s(%s)\n", name, argstr) } probe syscall.pause.return ? { printf("%s %s\n", name, retstr) } probe syscall.personality { printf("%s(%s)\n", name, argstr) printf("%d\n", persona) } probe syscall.personality.return { printf("%s %s\n", name, retstr) } probe syscall.pipe { printf("%s(%s)\n", name, argstr) printf("%d(%s) %p [%d %d]\n", flags, flag_str, fildes_uaddr, pipe0, pipe1) } # syscall.pipe.return is special, since at that point pipe0/pipe1 are valid probe syscall.pipe.return { printf("%s %s\n", name, retstr) printf("%p [%d %d]\n", fildes_uaddr, pipe0, pipe1) } probe syscall.pivot_root { printf("%s(%s)\n", name, argstr) printf("%s %s\n", new_root_str, old_root_str) } probe syscall.pivot_root.return { printf("%s %s\n", name, retstr) } probe syscall.poll { printf("%s(%s)\n", name, argstr) printf("%p %d %d\n", ufds_uaddr, nfds, timeout) } probe syscall.poll.return { printf("%s %s\n", name, retstr) } probe syscall.ppoll ?, syscall.compat_ppoll ? { printf("%s(%s)\n", name, argstr) } probe syscall.ppoll.return ?, syscall.compat_ppoll.return ? { printf("%s %s\n", name, retstr) } probe syscall.prctl { printf("%s(%s)\n", name, argstr) printf("%p %p %p %p %p\n", option, arg2, arg3, arg4, arg5) } probe syscall.prctl.return { printf("%s %s\n", name, retstr) } probe syscall.pread { printf("%s(%s)\n", name, argstr) printf("%d %p %d %d\n", fd, buf_uaddr, count, offset) } probe syscall.pread.return { printf("%s %s\n", name, retstr) } probe syscall.pselect6 ?, syscall.compat_pselect6 ?, syscall.pselect7 ?, %( systemtap_v <= "1.3" %? syscall.compat_pselect7a ? %: syscall.compat_pselect7 ? %) { printf("%s(%s)\n", name, argstr) } probe syscall.pselect6.return ?, syscall.compat_pselect6.return ?, syscall.pselect7.return ?, syscall.compat_pselect7.return ? { printf("%s %s\n", name, retstr) } probe syscall.ptrace { printf("%s(%s)\n", name, argstr) printf("%d %d %p %p\n", request, pid, addr, data) } probe syscall.ptrace.return { printf("%s %s\n", name, retstr) } probe syscall.pwrite, syscall.pwrite32 ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d %d\n", fd, buf_uaddr, count, offset) } probe syscall.pwrite.return, syscall.pwrite32.return ? { printf("%s %s\n", name, retstr) } probe syscall.quotactl { printf("%s(%s)\n", name, argstr) printf("%d(%s) %p(%s) %d %p\n", cmd, cmd_str, special, special_str, id, addr_uaddr) } probe syscall.quotactl.return { printf("%s %s\n", name, retstr) } probe syscall.read { printf("%s(%s)\n", name, argstr) printf("%d %p %d\n", fd, buf_uaddr, count) } probe syscall.read.return { printf("%s %s\n", name, retstr) } probe syscall.readahead { printf("%s(%s)\n", name, argstr) printf("%d %d %d\n", fd, offset, count) } probe syscall.readahead.return { printf("%s %s\n", name, retstr) } probe syscall.readdir ? { printf("%s(%s)\n", name, argstr) } probe syscall.readdir.return ? { printf("%s %s\n", name, retstr) } probe syscall.readlink { printf("%s(%s)\n", name, argstr) printf("%s %p %d\n", path, buf_uaddr, bufsiz) } probe syscall.readlink.return { printf("%s %s\n", name, retstr) } probe syscall.readlinkat ? { printf("%s(%s)\n", name, argstr) printf("%d %s %p %d\n", dfd, path, buf_uaddr, bufsiz) } probe syscall.readlinkat.return ? { printf("%s %s\n", name, retstr) } probe syscall.readv { printf("%s(%s)\n", name, argstr) printf("%d %p %d\n", fd, vector_uaddr, count) } probe syscall.readv.return { printf("%s %s\n", name, retstr) } probe syscall.reboot { printf("%s(%s)\n", name, argstr) printf("%d(%s) %d(%s) %d(%s) %p\n", magic, magic_str, magic2, magic2_str, flag, flag_str, arg_uaddr) } probe syscall.reboot.return { printf("%s %s\n", name, retstr) } probe syscall.recv { printf("%s(%s)\n", name, argstr) printf("%d %p %d %d(%s)\n", s, buf_uaddr, len, flags, flags_str) } probe syscall.recv.return { printf("%s %s\n", name, retstr) } probe syscall.recvfrom ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d %d(%s) %p %p\n", s, buf_uaddr, len, flags, flags_str, addr_uaddr, addrlen_uaddr) } probe syscall.recvfrom.return ? { printf("%s %s\n", name, retstr) } probe syscall.recvmmsg ?, syscall.compat_recvmmsg ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d %d(%s), %p\n", s, mmsg_uaddr, vlen, flags, flags_str, timeout_uaddr) } probe syscall.recvmmsg.return ?, syscall.compat_recvmmsg.return ? { printf("%s %s\n", name, retstr) } probe syscall.recvmsg ?, syscall.compat_sys_recvmsg ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d(%s)\n", s, msg_uaddr, flags, flags_str) } probe syscall.recvmsg.return ?, syscall.compat_sys_recvmsg.return ? { printf("%s %s\n", name, retstr) } probe syscall.remap_file_pages ? { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d %d\n", start, size, prot, pgoff, flags) } probe syscall.remap_file_pages.return ? { printf("%s %s\n", name, retstr) } probe syscall.removexattr { printf("%s(%s)\n", name, argstr) printf("%s %s\n", name_str, path) } probe syscall.removexattr.return { printf("%s %s\n", name, retstr) } probe syscall.rename { printf("%s(%s)\n", name, argstr) printf("%s %s\n", oldpath, newpath) } probe syscall.rename.return { printf("%s %s\n", name, retstr) } probe syscall.renameat ? { printf("%s(%s)\n", name, argstr) printf("%p(%s) %p(%s) %p(%s) %p(%s)\n", olddfd, olddfd_str, oldname, oldname_str, newdfd, newdfd_str, newname, newname_str) } probe syscall.renameat.return ? { printf("%s %s\n", name, retstr) } probe syscall.request_key ? { printf("%s(%s)\n", name, argstr) printf("%p %p %p %p\n", type_uaddr, description_uaddr, callout_info_uaddr, destringid) } probe syscall.request_key.return ? { printf("%s %s\n", name, retstr) } probe syscall.restart_syscall { printf("%s(%s)\n", name, argstr) } probe syscall.restart_syscall.return { printf("%s %s\n", name, retstr) } probe syscall.rmdir { printf("%s(%s)\n", name, argstr) printf("%s\n", pathname) } probe syscall.rmdir.return { printf("%s %s\n", name, retstr) } probe syscall.rt_sigaction ?, syscall.rt_sigaction32 ? { printf("%s(%s)\n", name, argstr) printf("%d %p %p %d\n", sig, act_uaddr, oact_uaddr, sigsetsize) } probe syscall.rt_sigaction.return ?, syscall.rt_sigaction32.return ? { printf("%s %s\n", name, retstr) } probe syscall.rt_sigpending ? { printf("%s(%s)\n", name, argstr) printf("%p %d\n", set_uaddr, sigsetsize) } probe syscall.rt_sigpending.return ? { printf("%s %s\n", name, retstr) } probe syscall.rt_sigprocmask ?, syscall.compat_rt_sigprocmask ? { printf("%s(%s)\n", name, argstr) printf("%d(%s) %p %p\n", how, how_str, set_uaddr, oldset_uaddr) } probe syscall.rt_sigprocmask.return ?, syscall.compat_rt_sigprocmask.return ? { printf("%s %s\n", name, retstr) } probe syscall.rt_sigqueueinfo { printf("%s(%s)\n", name, argstr) printf("%d %d %p\n", pid, sig, uinfo_uaddr) } probe syscall.rt_sigqueueinfo.return { printf("%s %s\n", name, retstr) } probe syscall.rt_sigreturn ?, syscall.rt_sigsuspend ? { printf("%s(%s)\n", name, argstr) } probe syscall.rt_sigreturn.return ?, syscall.rt_sigsuspend.return ? { printf("%s %s\n", name, retstr) } probe syscall.rt_sigtimedwait { printf("%s(%s)\n", name, argstr) printf("%p %p %p %d\n", uthese_uaddr, uinfo_uaddr, uts_uaddr, sigsetsize) } probe syscall.rt_sigtimedwait.return { printf("%s %s\n", name, retstr) } probe syscall.sched_getaffinity { printf("%s(%s)\n", name, argstr) printf("%d %d %p\n", pid, len, mask_uaddr) } probe syscall.sched_getaffinity.return { printf("%s %s\n", name, retstr) } probe syscall.sched_getparam { printf("%s(%s)\n", name, argstr) printf("%d %p\n", pid, p_uaddr) } probe syscall.sched_getparam.return { printf("%s %s\n", name, retstr) } probe syscall.sched_get_priority_max, syscall.sched_get_priority_min { printf("%s(%s)\n", name, argstr) printf("%d\n", policy) } probe syscall.sched_get_priority_max.return, syscall.sched_get_priority_min.return { printf("%s %s\n", name, retstr) } probe syscall.sched_getscheduler { printf("%s(%s)\n", name, argstr) printf("%d\n", pid) } probe syscall.sched_getscheduler.return { printf("%s %s\n", name, retstr) } probe syscall.sched_rr_get_interval { printf("%s(%s)\n", name, argstr) printf("%d %p\n", pid, tp_uaddr) } probe syscall.sched_rr_get_interval.return { printf("%s %s\n", name, retstr) } probe syscall.sched_setaffinity { printf("%s(%s)\n", name, argstr) printf("%d %d %p\n", pid, len, mask_uaddr) } probe syscall.sched_setaffinity.return { printf("%s %s\n", name, retstr) } probe syscall.sched_setparam ? { printf("%s(%s)\n", name, argstr) printf("%d %p\n", pid, p_uaddr) } probe syscall.sched_setparam.return ? { printf("%s %s\n", name, retstr) } probe syscall.sched_setscheduler ? { printf("%s(%s)\n", name, argstr) printf("%d %d(%s) %p\n", pid, policy, policy_str, p_uaddr) } probe syscall.sched_setscheduler.return ? { printf("%s %s\n", name, retstr) } probe syscall.sched_yield { printf("%s(%s)\n", name, argstr) } probe syscall.sched_yield.return { printf("%s %s\n", name, retstr) } probe syscall.select, syscall.compat_select ? { printf("%s(%s)\n", name, argstr) printf("%d %p %p %p %p\n", n, readfds_uaddr, writefds_uaddr, exceptfds_uaddr, timeout_uaddr) } probe syscall.select.return, syscall.compat_select.return ? { printf("%s %s\n", name, retstr) } probe syscall.semctl ?, syscall.compat_sys_semctl ? { printf("%s(%s)\n", name, argstr) printf("%d %d %d\n", semid, semnum, cmd) } probe syscall.semctl.return ?, syscall.compat_sys_semctl.return ? { printf("%s %s\n", name, retstr) } probe syscall.semget ? { printf("%s(%s)\n", name, argstr) printf("%d %d %d\n", key, nsems, semflg) } probe syscall.semget.return ? { printf("%s %s\n", name, retstr) } probe syscall.semop ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d\n", semid, sops_uaddr, nsops) } probe syscall.semop.return ? { printf("%s %s\n", name, retstr) } probe syscall.semtimedop ?, syscall.compat_sys_semtimedop ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d %p\n", semid, sops_uaddr, nsops, timeout_uaddr) } probe syscall.semtimedop.return ?, syscall.compat_sys_semtimedop.return ? { printf("%s %s\n", name, retstr) } probe syscall.send ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d %d(%s)\n", s, buf_uaddr, len, flags, flags_str) } probe syscall.send.return ? { printf("%s %s\n", name, retstr) } probe syscall.sendfile ? { printf("%s(%s)\n", name, argstr) printf("%d %d %d %d\n", out_fd, in_fd, offset_uaddr, count) } probe syscall.sendfile.return ? { printf("%s %s\n", name, retstr) } probe syscall.sendmsg ?, syscall.compat_sys_sendmsg ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d(%s)\n", s, msg_uaddr, flags, flags_str) } probe syscall.sendmsg.return ?, syscall.compat_sys_sendmsg.return ? { printf("%s %s\n", name, retstr) } probe syscall.sendmmsg ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d %d(%s)\n", s, mmsg_uaddr, vlen, flags, flags_str) } probe syscall.sendmmsg.return ? { printf("%s %s\n", name, retstr) } probe syscall.sendto ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d %d(%s) %p %d\n", s, buf_uaddr, len, flags, flags_str, to_uaddr, tolen) } probe syscall.sendto.return ? { printf("%s %s\n", name, retstr) } probe syscall.setdomainname { printf("%s(%s)\n", name, argstr) printf("%p %d\n", hostname_uaddr, len) } probe syscall.setdomainname.return { printf("%s %s\n", name, retstr) } probe syscall.setfsgid ? { printf("%s(%s)\n", name, argstr) printf("%d\n", fsgid) } probe syscall.setfsgid.return ? { printf("%s %s\n", name, retstr) } probe syscall.setfsuid ? { printf("%s(%s)\n", name, argstr) printf("%d\n", fsuid) } probe syscall.setfsuid.return ? { printf("%s %s\n", name, retstr) } probe syscall.setgid ? { printf("%s(%s)\n", name, argstr) printf("%d\n", gid) } probe syscall.setgid.return ? { printf("%s %s\n", name, retstr) } probe syscall.setgroups ? { printf("%s(%s)\n", name, argstr) printf("%d %p\n", size, list_uaddr) } probe syscall.setgroups.return ? { printf("%s %s\n", name, retstr) } probe syscall.sethostname { printf("%s(%s)\n", name, argstr) printf("%p(%s) %d\n", hostname_uaddr, name_str, len) } probe syscall.sethostname.return { printf("%s %s\n", name, retstr) } probe syscall.setitimer, syscall.compat_setitimer ? { printf("%s(%s)\n", name, argstr) printf("%d %p %p\n", which, value_uaddr, ovalue_uaddr) } probe syscall.setitimer.return, syscall.compat_setitimer.return ? { printf("%s %s\n", name, retstr) } probe syscall.set_mempolicy ? { printf("%s(%s)\n", name, argstr) printf("%d %p %d\n", mode, nmask_uaddr, maxnode) } probe syscall.set_mempolicy.return ? { printf("%s, %s\n", name, retstr) } probe syscall.setpgid { printf("%s(%s)\n", name, argstr) printf("%d %d\n", pid, pgid) } probe syscall.setpgid.return { printf("%s %s\n", name, retstr) } probe syscall.setpriority { printf("%s(%s)\n", name, argstr) printf("%d(%s) %d %d\n", which, which_str, who, prio) } probe syscall.setpriority.return { printf("%s %s\n", name, retstr) } probe syscall.setregid, syscall.setregid16 ? { printf("%s(%s)\n", name, argstr) printf("%d %d\n", rgid, egid) } probe syscall.setregid.return, syscall.setregid16.return ? { printf("%s %s\n", name, retstr) } probe syscall.setresgid, syscall.setresgid16 ? { printf("%s(%s)\n", name, argstr) printf("%d %d %d\n", rgid, egid, sgid) } probe syscall.setresgid.return, syscall.setresgid16.return ? { printf("%s %s\n", name, retstr) } probe syscall.setresuid, syscall.setresuid16 ? { printf("%s(%s)\n", name, argstr) printf("%d %d %d\n", ruid, euid, suid) } probe syscall.setresuid.return, syscall.setresuid16.return ? { printf("%s %s\n", name, retstr) } probe syscall.setreuid, syscall.setreuid16 ? { printf("%s(%s)\n", name, argstr) printf("%d %d\n", ruid, euid) } probe syscall.setreuid.return, syscall.setreuid16.return ? { printf("%s %s\n", name, retstr) } probe syscall.setrlimit { printf("%s(%s)\n", name, argstr) printf("%d %p\n", resource, rlim_uaddr) } probe syscall.setrlimit.return { printf("%s %s\n", name, retstr) } probe syscall.setsid { printf("%s(%s)\n", name, argstr) } probe syscall.setsid.return { printf("%s %s\n", name, retstr) } probe syscall.setsockopt { printf("%s, %s\n", name, argstr) printf("%d, %d(%s), %d(%s), %p, %d\n", fd, level, level_str, optname, optname_str, optval_uaddr, optlen) } probe syscall.setsockopt.return { printf("%s, %s\n", name, retstr) } probe syscall.set_tid_address { printf("%s, %s\n", name, argstr) printf("%p\n", tidptr_uaddr) } probe syscall.set_tid_address.return { printf("%s, %s\n", name, retstr) } probe syscall.settimeofday, syscall.settimeofday32 ? { printf("%s, %s\n", name, argstr) printf("%p, %p\n", tv_uaddr, tz_uaddr) } probe syscall.settimeofday.return, syscall.settimeofday32.return ? { printf("%s, %s\n", name, retstr) } probe syscall.setuid { printf("%s, %s\n", name, argstr) printf("%d\n", uid) } probe syscall.setuid.return { printf("%s, %s\n", name, retstr) } probe syscall.setxattr { printf("%s, %s\n", name, argstr) printf("%p(%s), %p(%s), %p, %d, %d\n", path_uaddr, path, name_uaddr, name_str, value_uaddr, size, flags) } probe syscall.setxattr.return { printf("%s, %s\n", name, retstr) } probe syscall.sgetmask ? { printf("%s, %s\n", name, argstr) } probe syscall.sgetmask.return ? { printf("%s, %s\n", name, retstr) } probe syscall.shmat ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", shmid, shmaddr_uaddr, shmflg) } probe syscall.shmat.return ? { printf("%s, %s\n", name, retstr) } probe syscall.compat_sys_shmat ? { printf("%s, %s\n", name, argstr) %( systemtap_v < "2.3" %? printf("%d, %d, %d, %p\n", first, second, third, uptr_uaddr) %) printf("%d, %p, %d\n", shmid, shmaddr_uaddr, shmflg) } probe syscall.compat_sys_shmat.return ? { printf("%s, %s\n", name, retstr) } probe syscall.shmctl ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %p\n", shmid, cmd, buf_uaddr) } probe syscall.shmctl.return ? { printf("%s, %s\n", name, retstr) } probe syscall.compat_sys_shmctl ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %p\n", first, second, uptr_uaddr) } probe syscall.compat_sys_shmctl.return ? { printf("%s, %s\n", name, retstr) } probe syscall.shmdt { printf("%s, %s\n", name, argstr) printf("%p\n", shmaddr_uaddr) } probe syscall.shmdt.return { printf("%s, %s\n", name, retstr) } probe syscall.shmget ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", key, size, shmflg) } probe syscall.shmget.return ? { printf("%s, %s\n", name, retstr) } probe syscall.shutdown { printf("%s, %s\n", name, argstr) printf("%d, %d(%s)\n", s, how, how_str) } probe syscall.shutdown.return { printf("%s, %s\n", name, retstr) } probe syscall.sigaction ?, syscall.sigaction32 ? { printf("%s, %s\n", name, argstr) printf("%d, %p, %p\n", sig, act_uaddr, oact_uaddr) } probe syscall.sigaction.return ?, syscall.sigaction32.return ? { printf("%s, %s\n", name, retstr) } %( CONFIG_GENERIC_SIGALTSTACK == "y" %? probe syscall.sigaltstack { printf("%s, %s\n", name, argstr) printf("%p, %p\n", uss_uaddr, uoss_uaddr) } probe syscall.sigaltstack.return { printf("%s, %s\n", name, retstr) } %) probe syscall.signal ? { printf("%s, %s\n", name, argstr) printf("%d, %d\n", sig, handler) } probe syscall.signal.return ? { printf("%s, %s\n", name, retstr) } probe syscall.signalfd ?, syscall.compat_signalfd ? { printf("%s, %s\n", name, argstr) printf("%d\n", flags) } probe syscall.signalfd.return ?, syscall.compat_signalfd.return ? { printf("%s, %s\n", name, retstr) } probe syscall.sigpending ? { printf("%s, %s\n", name, argstr) } probe syscall.sigpending.return ? { printf("%s, %s\n", name, retstr) } probe syscall.sigprocmask ? { printf("%s, %s\n", name, argstr) printf("%d(%s), %p, %p\n", how, how_str, set_uaddr, oldset_uaddr) } probe syscall.sigprocmask.return ? { printf("%s, %s\n", name, retstr) } probe syscall.sigreturn ? { printf("%s, %s\n", name, argstr) } probe syscall.sigreturn.return ? { printf("%s, %s\n", name, retstr) } probe syscall.sigsuspend ? { printf("%s, %s\n", name, argstr) } probe syscall.sigsuspend.return ? { printf("%s, %s\n", name, retstr) } probe syscall.socket { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", family, type, protocol) } probe syscall.socket.return { printf("%s, %s\n", name, retstr) } probe syscall.socketpair { printf("%s, %s\n", name, argstr) printf("%d, %d, %d, %p\n", family, type, protocol, sv_uaddr) } probe syscall.socketpair.return { printf("%s, %s\n", name, retstr) } probe syscall.splice ? { printf("%s, %s\n", name, argstr) } probe syscall.splice.return ? { printf("%s, %s\n", name, retstr) } probe syscall.ssetmask ? { printf("%s, %s\n", name, argstr) printf("%d\n", newmask) } probe syscall.ssetmask.return ? { printf("%s, %s\n", name, retstr) } probe syscall.stat { printf("%s, %s\n", name, argstr) printf("%p, %s, %p\n", filename_uaddr, filename, buf_uaddr) } probe syscall.stat.return { printf("%s, %s\n", name, retstr) } probe syscall.statfs { printf("%s, %s\n", name, argstr) printf("%p, %s\n", buf_uaddr, path) } probe syscall.statfs.return { printf("%s, %s\n", name, retstr) } probe syscall.statfs64 { printf("%s, %s\n", name, argstr) printf("%d, %p, %s\n", sz, buf_uaddr, path) } probe syscall.statfs64.return { printf("%s, %s\n", name, retstr) } probe syscall.stime ? { printf("%s, %s\n", name, argstr) printf("%p\n", t_uaddr) } probe syscall.stime.return ? { printf("%s, %s\n", name, retstr) } probe syscall.swapoff { printf("%s, %s\n", name, argstr) printf("%s\n", path) } probe syscall.swapoff.return { printf("%s, %s\n", name, retstr) } probe syscall.swapon { printf("%s, %s\n", name, argstr) printf("%s, %d\n", path, swapflags) } probe syscall.swapon.return { printf("%s, %s\n", name, retstr) } probe syscall.symlink { printf("%s, %s\n", name, argstr) printf("%s, %s\n", oldpath, newpath) } probe syscall.symlink.return { printf("%s, %s\n", name, retstr) } probe syscall.symlinkat ? { printf("%s, %s\n", name, argstr) printf("%p(%s), %d(%s), %p(%s)\n", oldname, oldname_str, newdfd, newdfd_str, newname, newname_str) } probe syscall.symlinkat.return ? { printf("%s, %s\n", name, retstr) } probe syscall.sync { printf("%s, %s\n", name, argstr) } probe syscall.sync.return { printf("%s, %s\n", name, retstr) } probe syscall.sysctl { printf("%s, %s\n", name, argstr) } probe syscall.sysctl.return { printf("%s, %s\n", name, retstr) } probe syscall.sysfs { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", option, arg1, arg2) } probe syscall.sysfs.return { printf("%s, %s\n", name, retstr) } probe syscall.sysinfo { printf("%s, %s\n", name, argstr) printf("%p\n", info_uaddr) } probe syscall.sysinfo.return { printf("%s, %s\n", name, retstr) } probe syscall.syslog { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", type, bufp_uaddr, len) } probe syscall.syslog.return { printf("%s, %s\n", name, retstr) } probe syscall.tee ? { printf("%s, %s\n", name, argstr) } probe syscall.tee.return ? { printf("%s, %s\n", name, retstr) } probe syscall.tgkill { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", tgid, pid, sig) } probe syscall.tgkill.return { printf("%s, %s\n", name, retstr) } probe syscall.time ? { printf("%s, %s\n", name, argstr) printf("%p\n", t_uaddr) } probe syscall.time.return ? { printf("%s, %s\n", name, retstr) } probe syscall.timer_create { printf("%s, %s\n", name, argstr) printf("%d(%s), %p, %p\n", clockid, clockid_str, evp_uaddr, timerid_uaddr) } probe syscall.timer_create.return { printf("%s, %s\n", name, retstr) } probe syscall.timer_delete, syscall.timer_getoverrun { printf("%s, %s\n", name, argstr) printf("%d\n", timerid) } probe syscall.timer_delete.return, syscall.timer_getoverrun.return { printf("%s, %s\n", name, retstr) } probe syscall.timer_gettime { printf("%s, %s\n", name, argstr) printf("%d, %p\n", timerid, value_uaddr) } probe syscall.timer_gettime.return { printf("%s, %s\n", name, retstr) } probe syscall.timer_settime { printf("%s, %s\n", name, argstr) printf("%d, %d, %p, %p\n", timerid, flags, value_uaddr, ovalue_uaddr) } probe syscall.timer_settime.return { printf("%s, %s\n", name, retstr) } probe syscall.timerfd ? { printf("%s, %s\n", name, argstr) } probe syscall.timerfd.return ? { printf("%s, %s\n", name, retstr) } probe syscall.times { printf("%s, %s\n", name, argstr) } probe syscall.times.return { printf("%s, %s\n", name, retstr) } probe syscall.tkill { printf("%s, %s\n", name, argstr) printf("%d, %d\n", pid, sig) } probe syscall.tkill.return { printf("%s, %s\n", name, retstr) } probe syscall.truncate { printf("%s, %s\n", name, argstr) printf("%p(%s), %d\n", path_uaddr, path, length) } probe syscall.truncate.return { printf("%s, %s\n", name, retstr) } probe syscall.tux ? { printf("%s, %s\n", name, argstr) printf("%d %p\n", action, u_info_uaddr) } probe syscall.tux.return ? { printf("%s, %s\n", name, retstr) } probe syscall.umask { printf("%s, %s\n", name, argstr) printf("%d\n", mask) } probe syscall.umask.return { printf("%s, %s\n", name, retstr) } probe syscall.umount { printf("%s, %s\n", name, argstr) printf("%s, %d(%s)\n", target, flags, flags_str) } probe syscall.umount.return { printf("%s, %s\n", name, retstr) } probe syscall.uname { printf("%s, %s\n", name, argstr) } probe syscall.uname.return { printf("%s, %s\n", name, retstr) } probe syscall.unlink { printf("%s, %s\n", name, argstr) printf("%p(%s)\n", pathname_uaddr, pathname) } probe syscall.unlink.return { printf("%s, %s\n", name, retstr) } probe syscall.unlinkat ? { printf("%s, %s\n", name, argstr) printf("%d(%s), %p(%s), %d(%s)\n", dfd, dfd_str, pathname, pathname_str, flag, flag_str) } probe syscall.unlinkat.return ? { printf("%s, %s\n", name, retstr) } probe syscall.unshare ? { printf("%s, %s\n", name, argstr) printf("%d\n", unshare_flags) } probe syscall.unshare.return ? { printf("%s, %s\n", name, retstr) } probe syscall.uselib { printf("%s, %s\n", name, argstr) printf("%p(%s)\n", library_uaddr, library) } probe syscall.uselib.return { printf("%s, %s\n", name, retstr) } probe syscall.ustat, syscall.ustat32 ? { printf("%s, %s\n", name, argstr) printf("%d, %p\n", dev, ubuf_uaddr) } probe syscall.ustat.return, syscall.ustat32.return ? { printf("%s, %s\n", name, retstr) } probe syscall.utime ?, syscall.compat_utime ? { printf("%s, %s\n", name, argstr) printf("%p(%s), %p, %d, %d\n", filename_uaddr, filename, buf_uaddr, actime, modtime) } probe syscall.utime.return ?, syscall.compat_utime.return ? { printf("%s, %s\n", name, retstr) } probe syscall.utimensat ?, syscall.compat_utimensat ? { printf("%s, %s\n", name, argstr) } probe syscall.utimensat.return ?, syscall.compat_utimensat.return ? { printf("%s, %s\n", name, retstr) } probe syscall.vhangup { printf("%s, %s\n", name, argstr) } probe syscall.vhangup.return { printf("%s, %s\n", name, retstr) } probe syscall.vmsplice ?, syscall.compat_vmsplice ? { printf("%s, %s\n", name, argstr) } probe syscall.vmsplice.return ?, syscall.compat_vmsplice.return ? { printf("%s, %s\n", name, retstr) } probe syscall.wait4 { printf("%s, %s\n", name, argstr) printf("%d, %p, %d(%s), %p\n", pid, status_uaddr, options, options_str, rusage_uaddr) } probe syscall.wait4.return { printf("%s, %s, %s\n", name, retstr, status_str) } probe syscall.waitid { printf("%s, %s\n", name, argstr) printf("%d, %d(%s), %p, %d(%s), %p\n", pid, which, which_str, infop_uaddr, options, options_str, rusage_uaddr) } probe syscall.waitid.return { printf("%s, %s\n", name, retstr) } probe syscall.write { printf("%s, %s\n", name, argstr) printf("%d, %p, %d\n", fd, buf_uaddr, count) } probe syscall.write.return { printf("%s, %s\n", name, retstr) } probe syscall.writev { printf("%s, %s\n", name, argstr) printf("%p, %d, %d\n", vector_uaddr, count, fd) } probe syscall.writev.return { printf("%s, %s\n", name, retstr) } systemtap-2.3/testsuite/buildok/system-embedded.stp000077500000000000000000000000561217430427200227020ustar00rootroot00000000000000#! stap -p4 probe begin { system("ls") } systemtap-2.3/testsuite/buildok/systemtap_privilege.stp000077500000000000000000000002741217430427200237300ustar00rootroot00000000000000#! stap -p4 %( systemtap_privilege != "stapusr" %? probe begin { printf("begin!") } %: **ERROR** %) %( systemtap_privilege == "stapusr" %? **ERROR** %: probe end { printf("end!") } %) systemtap-2.3/testsuite/buildok/task-embedded.stp000077500000000000000000000005751217430427200223260ustar00rootroot00000000000000#! stap -p4 # probe begin { print (task_current () + task_parent (0) + task_state (0) + task_pid (0) + task_tid (0) + task_gid (0) + task_egid (0) + task_uid (0) + task_euid (0) + task_prio (0) + task_nice (0) + task_cpu (0) + task_open_file_handles (0) + task_max_file_handles (0) + pid2task(0)) print (task_execname (0)) print (pid2execname (0)) } systemtap-2.3/testsuite/buildok/task_test.stp000077500000000000000000000014721217430427200216330ustar00rootroot00000000000000#! stap -p4 probe begin { c = task_current() log(sprint(task_parent(c))) log(sprint(task_state(c))) log(task_execname(c)) log(sprint(task_pid(c))) log(sprint(task_tid(c))) log(sprint(task_gid(c))) log(sprint(task_egid(c))) log(sprint(task_uid(c))) log(sprint(task_euid(c))) log(sprint(task_prio(c))) log(sprint(task_nice(c))) log(sprint(task_cpu(c))) log(sprint(task_open_file_handles(c))) log(sprint(task_max_file_handles(c))) log(sprint(pid2task(pid()))) log(sprint(pid2execname(pid()))) // task_time.stp log(task_time_string()) log(cputime_to_string(0)) log(msecs_to_string(0)) log(sprint(cputime_to_msecs(0))) log(sprint(task_stime())) log(sprint(task_utime())) log(task_time_string_tid(0)) log(sprint(task_stime_tid(0))) log(sprint(task_utime_tid(0))) exit() } systemtap-2.3/testsuite/buildok/task_time-embedded.stp000077500000000000000000000005061217430427200233360ustar00rootroot00000000000000#! stap -p4 probe begin { print(task_utime() + task_utime_tid(0) + task_stime() + task_stime_tid(0) + cputime_to_msecs(0) + cputime_to_usecs(0)) print(msecs_to_string(0)) print(usecs_to_string(0)) print(cputime_to_string(0)) print(task_time_string()) print(task_time_string_tid(0)) } systemtap-2.3/testsuite/buildok/tcp-all-probes.stp000077500000000000000000000001671217430427200224560ustar00rootroot00000000000000#! stap -wp4 // Tests if all probes in the tcp tapset are resolvable. probe tcp.*, tcp.*.*, tcp.*.*.* {} systemtap-2.3/testsuite/buildok/tcp-detailed.stp000077500000000000000000000025251217430427200221710ustar00rootroot00000000000000#! stap -p4 probe tcp.sendmsg { printf("%s %p %d %d\n", name, sock, family, size) } probe tcp.sendmsg.return { printf("%s %d\n", name, size) } probe tcp.recvmsg { printf("%s %p %d %d\n", name, sock, size, family) printf("%s %s %d %d\n", saddr, daddr, sport, dport) } probe tcp.recvmsg.return { printf("%s %d %d\n", name, size, family) printf("%s %s %d %d\n", saddr, daddr, sport, dport) } probe tcp.disconnect { printf("%s %p %d %d\n", name, sock, family, flags) printf("%s %s %d %d\n", saddr, daddr, sport, dport) } probe tcp.disconnect.return { printf("%s %d\n", name, ret) } probe tcp.ipv4.setsockopt, tcp.ipv6.setsockopt { printf("%s %p %d %d %d(%s) %d\n", name, sock, family, level, optname, optstr, optlen) } probe tcp.setsockopt { printf("%s %p %d %d %d(%s) %d\n", name, sock, family, level, optname, optstr, optlen) } probe tcp.setsockopt.return { printf("%s %d\n", name, ret) } probe tcp.ipv4.receive, tcp.ipv6.receive { printf("%s %p %d\n", name, iphdr, family) printf("%s %s %d %d\n", saddr, daddr, sport, dport) printf("%d %p %d %d %d %d %d %d\n", protocol, tcphdr, urg, ack, psh, rst, syn, fin) } probe tcp.receive { printf("%s %p %d\n", name, iphdr, family) printf("%s %s %d %d\n", saddr, daddr, sport, dport) printf("%d %p %d %d %d %d %d %d\n", protocol, tcphdr, urg, ack, psh, rst, syn, fin) } systemtap-2.3/testsuite/buildok/tcp-embedded.stp000077500000000000000000000003751217430427200221500ustar00rootroot00000000000000#! stap -p4 # probe begin { print (tcp_get_info_rto (0) + tcp_get_info_snd_cwnd (0) + tcp_ts_get_info_state (0) + tcp_ts_get_info_snd_ssthresh (0) + tcp_ts_get_info_rcv_mss (0)) printf("%s %s\n", tcp_sockopt_str(0), tcp_ipv6_sockopt_str(0)) } systemtap-2.3/testsuite/buildok/tcp_test.stp000077500000000000000000000015051217430427200214540ustar00rootroot00000000000000#! stap -p4 global send_bytes, recv_bytes, ports, src_ips, rtos, state, mss, ssthresh, cwnd function print_report() { printf("%d\t%d\t%d\t%s\t%d\t%d\t%d\t%d\t%d\n", send_bytes,recv_bytes,ports,src_ips,rtos,mss,ssthresh,cwnd,state); } probe tcp.sendmsg { ports = inet_get_local_port(sock) src_ips = inet_get_ip_source(sock) rtos = tcp_get_info_rto(sock) } probe tcp.recvmsg { cwnd = tcp_get_info_snd_cwnd(sock) mss = tcp_ts_get_info_rcv_mss(sock) ssthresh = tcp_ts_get_info_snd_ssthresh(sock) state = tcp_ts_get_info_state(sock) } probe tcp.sendmsg.return { if (size > 0) { send_bytes += size } } probe tcp.recvmsg.return { if (size > 0) { recv_bytes += size } } probe tcp.disconnect { log("tcp disconnect") } probe timer.ms(2000) { print_report() } systemtap-2.3/testsuite/buildok/tcpmib-all-probes.stp000077500000000000000000000001341217430427200231400ustar00rootroot00000000000000#! stap -p4 // Tests if all probes in the tcpmib tapset are resolvable. probe tcpmib.* {} systemtap-2.3/testsuite/buildok/tcpmib-detailed.stp000077500000000000000000000003341217430427200226550ustar00rootroot00000000000000#! stap -wp4 probe tcpmib.ActiveOpens, tcpmib.AttemptFails ?, tcpmib.CurrEstab ?, tcpmib.EstabResets ?, tcpmib.OutRsts, tcpmib.OutSegs, tcpmib.PassiveOpens, tcpmib.RetransSegs { printf("%p %d\n", sk, op) } systemtap-2.3/testsuite/buildok/tcpmib-embedded.stp000077500000000000000000000004731217430427200226370ustar00rootroot00000000000000#! stap -p4 probe begin{ print(tcpmib_get_state(0) + tcpmib_local_addr(0) + tcpmib_remote_addr(0) + tcpmib_local_port(0) + tcpmib_remote_port(0) + _rtn_local() + _is_reset(0) + _tcpmib_input_route_type(0)) } systemtap-2.3/testsuite/buildok/ten.stp000077500000000000000000000007221217430427200204150ustar00rootroot00000000000000#! stap -up4 probe begin { a = 1+01+0x1-1-01-0x1; long_max = 2147483647; ulong_max = 4294967295; long_min = -2147483647-1; long_min2 = -2147483648; llong_max = 9223372036854775807; ullong_max = 18446744073709551615; llong_min = -9223372036854775807-1; llong_min2 = -9223372036854775808; llong_min3 = 9223372036854775808; // nearly out-of-range negative numbers underflow_1 = -9223372036854775809; underflow_2 = -18446744073709551615; } systemtap-2.3/testsuite/buildok/thirteen.stp000077500000000000000000000001221217430427200214430ustar00rootroot00000000000000#! stap -p4 probe kernel.function("vfs_read") { printf ("count=%d\n", $count) } systemtap-2.3/testsuite/buildok/thirty.stp000077500000000000000000000024031217430427200211500ustar00rootroot00000000000000#! stap -p4 # tests wide arrays global a1, a2, a3, a4, a5, a6, a7, a8, a9 global b1, b2, b3, b4, b5, b6, b7, b8, b9 global c1, c2, c3, c4, c5, c6, c7, c8, c9 global d1, d2, d3, d4, d5, d6, d7, d8, d9 probe begin { a1[0]="a"; a2[0,"a"]="a"; a3[0,"a",0]="a"; a4[0,"a",0,"a"]="a"; a5[0,"a",0,"a",0]="a"; a6[0,"a",0,"a",0,"a"]="a"; a7[0,"a",0,"a",0,"a",0]="a"; a8[0,"a",0,"a",0,"a",0,"a"]="a"; a9[0,"a",0,"a",0,"a",0,"a",0]="a"; b1["b"]=0; b2["b",0]=0; b3["b",0,"b"]=0; b4["b",0,"b",0]=0; b5["b",0,"b",0,"b"]=0; b6["b",0,"b",0,"b",0]=0; b7["b",0,"b",0,"b",0,"b"]=0; b8["b",0,"b",0,"b",0,"b",0]=0; b9["b",0,"b",0,"b",0,"b",0,"b"]=0; c1[0]<<<0; c2[0,"a"]<<<0; c3[0,"a",0]<<<0; c4[0,"a",0,"a"]<<<0; c5[0,"a",0,"a",0]<<<0; c6[0,"a",0,"a",0,"a"]<<<0; c7[0,"a",0,"a",0,"a",0]<<<0; c8[0,"a",0,"a",0,"a",0,"a"]<<<0; c9[0,"a",0,"a",0,"a",0,"a",0]<<<0; d1["b"]<<<0; d2["b",0]<<<0; d3["b",0,"b"]<<<0; d4["b",0,"b",0]<<<0; d5["b",0,"b",0,"b"]<<<0; d6["b",0,"b",0,"b",0]<<<0; d7["b",0,"b",0,"b",0,"b"]<<<0; d8["b",0,"b",0,"b",0,"b",0]<<<0; d9["b",0,"b",0,"b",0,"b",0,"b"]<<<0; } systemtap-2.3/testsuite/buildok/thirtyfour.stp000077500000000000000000000004551217430427200220510ustar00rootroot00000000000000#! stap -gp4 probe begin { println("hello") %{ /* not pure */ 0 %} /* but should still compile */ %{ /* string */ "hello" %} /* likewise */ println(0 * %{ /* pure */ SYNTAX-ERROR-ME %}) /* count on constant-propagation */ log(%{ /* string */ "yellow" %}) println("world") } systemtap-2.3/testsuite/buildok/thirtyone.stp000077500000000000000000000002021217430427200216450ustar00rootroot00000000000000#! stap -wp4 probe kprobe.function("vfs_stat") {} probe kprobe.function("do_sys_open") {} probe kernel.function("filp_close") {} systemtap-2.3/testsuite/buildok/thirtythree.stp000077500000000000000000000001071217430427200221770ustar00rootroot00000000000000#! /bin/sh stap $@ --ldd -vvv -p4 -e 'probe begin {}' -t -d /bin/ls systemtap-2.3/testsuite/buildok/thirtytwo.stp000077500000000000000000000004351217430427200217050ustar00rootroot00000000000000#! /bin/sh stap $@ -t -p4 -DKRETACTIVE=8888 -e ' probe kprobe.function("sys_open").return {} probe kprobe.function("sys_open").return.maxactive(100) {} probe kernel.function("sys_open").return {} probe kernel.function("sys_open").return.maxactive(100) {} probe syscall.*.return {} ' systemtap-2.3/testsuite/buildok/three.stp000077500000000000000000000007151217430427200207400ustar00rootroot00000000000000#! stap -p4 # define some aliases which resolve to kernel functions probe pipe_read = kernel.function("pipe_read") { fname = "pipe_read" reading_from_pipe = 1 } probe pipe_write = kernel.function("pipe_write") { fname = "pipe_write" reading_from_pipe = 0 } # use the aliases, including variables defined in them probe pipe_read, pipe_write { if (reading_from_pipe) log ("reading from pipe in " . fname) else log ("writing to pipe in " . fname) } systemtap-2.3/testsuite/buildok/timestamp-embedded.stp000077500000000000000000000002351217430427200233600ustar00rootroot00000000000000#! stap -p4 probe begin { println(get_cycles()) println(tz_gmtoff()) println(tz_name()) println(tz_ctime(0)) println(jiffies()) println(HZ()) } systemtap-2.3/testsuite/buildok/timestamp_gtod-embedded.stp000077500000000000000000000002201217430427200243670ustar00rootroot00000000000000#! stap -p4 probe begin { println(gettimeofday_ns()) println(gettimeofday_us()) println(gettimeofday_ms()) println(gettimeofday_s()) } systemtap-2.3/testsuite/buildok/timestamp_monotonic-embedded.stp000077500000000000000000000003701217430427200254450ustar00rootroot00000000000000#! stap -p4 probe begin { println(cpu_clock_ns(0)) println(cpu_clock_us(1)) println(cpu_clock_ms(2)) println(cpu_clock_s(3)) println(local_clock_ns()) println(local_clock_us()) println(local_clock_ms()) println(local_clock_s()) } systemtap-2.3/testsuite/buildok/tty-detailed.stp000077500000000000000000000027351217430427200222260ustar00rootroot00000000000000#! stap -p4 probe tty.open { printf("Opening tty file %s\n", file_name) printf("INODE: number %d\nState: %d\nFlag: %d\n", inode_number, inode_state, inode_flags) printf("File: %s mode %x flags %x\n", file_name, file_mode, file_flags) } probe tty.release { printf("Closing file %s\n", file_name) printf("INODE: number %d\nState: %d\nFlag: %d\n", inode_number, inode_state, inode_flags) printf("File: %s mode %x flags %x\n", file_name, file_mode, file_flags) } # tty.resize test moved to tty-resize.stp probe tty.ioctl { printf("Ioctling file %s with %d %d\n", name, cmd, arg) } probe tty.init { printf("new tty with name %s from driver %s and module %s\n", driver_name, name, module) } probe tty.register { printf("Device registered using index %d using driver %s(%s/%s)\n", index, driver_name, name, module) } probe tty.unregister { printf("Device unregistered using index %d using driver %s(%s/%s)\n", index, driver_name, name, module) } probe tty.poll { printf("Pooling tty %s for wait queue key %d\n", file_name, wait_key); } probe tty.receive { printf("Driver %s/%s (%d/%d) received %s (%s) with len %d\n", name, driver_name, index, id, cp, fp, count) } probe tty.write { printf("Buffer %s (len %d) wrote on file %s (driver %s)\n", buffer, nr, file_name, driver_name) } probe tty.read { printf("Reading tty file %s (driver %s) to a buffer with size %d containing %s\n", file_name, driver_name, nr, buffer) } systemtap-2.3/testsuite/buildok/tty-resize.stp000077500000000000000000000004661217430427200217530ustar00rootroot00000000000000#! stap -p4 # This test fails on some kernels because we can't find the arguments to # this inline function (PR 1155). probe tty.resize { printf("Resizing %s from %dx%d (%d/%d) to %dx%d (%d/%d)\n", name, old_row, old_col, old_xpixel, old_ypixel, new_row, new_col, new_xpixel, new_ypixel) } systemtap-2.3/testsuite/buildok/twelve.stp000077500000000000000000000006201217430427200211320ustar00rootroot00000000000000#! stap -p4 # testing the "in" operator global foo, goo, moo probe begin { foo[10] = "a" goo["a",12,"c",14,"d"] = 10 moo[1,2,3,4,5] = "hello" if (10 in foo) { foo[10] = "yes" } if (["a",12,"c",14,"d"] in goo) { goo["p",1,"q",2,"r"] += (12 in foo) } x = 1 y = 2 z = 3 if ([x,y,z,y,x] in moo) { foo[30] = moo[(x in foo), (y in foo), (z in foo), (y in foo), (x in foo)] } } systemtap-2.3/testsuite/buildok/twenty.stp000077500000000000000000000003651217430427200211640ustar00rootroot00000000000000#! stap -gp4 # Test for writing to target variables, PR 1131 probe kernel.function("iterate_dir") !, kernel.function("vfs_readdir") { %( kernel_v >= "2.6.20" %? $file->f_path->dentry->d_name->len = 1 %: $file->f_dentry->d_name->len = 1 %) } systemtap-2.3/testsuite/buildok/twentyeight.stp000077500000000000000000000001221217430427200221740ustar00rootroot00000000000000#! stap -gp4 probe kernel.statement(0).absolute { log("absolute zero reached") } systemtap-2.3/testsuite/buildok/twentyeightprime.stp000077500000000000000000000001251217430427200232340ustar00rootroot00000000000000#! stap -p4 probe process(0).statement(0).absolute { log("absolute zero reached") } systemtap-2.3/testsuite/buildok/twentyfive.stp000077500000000000000000000002531217430427200220320ustar00rootroot00000000000000#! stap -p4 # PR 3522. probe module("ext3").function("ext3_check_dir_entry")? { print ($ext3_filetype_table[1]) # static global in CU } probe timer.s(4) { exit () } systemtap-2.3/testsuite/buildok/twentyfour.stp000077500000000000000000000003221217430427200220510ustar00rootroot00000000000000#! stap -wgp4 # If the optimizer is working, this function will get elided, # and thus will compile successfully. function pure() %{ /* pure */ #error "should have been elided" %} probe begin { pure () } systemtap-2.3/testsuite/buildok/twentynine.stp000077500000000000000000000001501217430427200220260ustar00rootroot00000000000000#! stap -gp4 probe kernel.function("icmp_rcv") { printf("skb = %x\n", $skb); $skb = 0; } systemtap-2.3/testsuite/buildok/twentyone.stp000077500000000000000000000007221217430427200216630ustar00rootroot00000000000000#! stap -p4 global a probe begin { a[5] = 0 a[4] = 2 a[3] = 5 a[2] = 8 a[1] = 1 a[0] = -4 exit () } probe end { log ("x+ in a") foreach (x+ in a) log ("a[" . sprint(x) . "]=" . sprint(a[x])) log ("x- in a") foreach (x- in a) log ("a[" . sprint(x) . "]=" . sprint(a[x])) log ("x in a+") foreach (x in a+) log ("a[" . sprint(x) . "]=" . sprint(a[x])) log ("x in a-") foreach (x in a-) log ("a[" . sprint(x) . "]=" . sprint(a[x])) } systemtap-2.3/testsuite/buildok/twentyseven.stp000077500000000000000000000001471217430427200222230ustar00rootroot00000000000000#! stap -p4 probe kernel.function("do_execve") { print(@defined($__argv) ? $__argv[0] : $argv[0]) } systemtap-2.3/testsuite/buildok/twentythree.stp000077500000000000000000000002631217430427200222110ustar00rootroot00000000000000#! stap -gp4 # Test for writing 64-bit target variable, PR 1271 probe kernel.function("deactivate_super") { $s->s_maxbytes = 22; printf("set to 22 => %d\n", $s->s_maxbytes) } systemtap-2.3/testsuite/buildok/twentytwo.stp000077500000000000000000000003511217430427200217110ustar00rootroot00000000000000#! stap -p4 # Test for reading 64-bit target variable, PR 1271 probe kernel.function("deactivate_super") { printf("s_maxbytes %d\n", $s->s_maxbytes) } probe kernel.function("vfs_llseek").call { printf("offset %d\n", $offset) } systemtap-2.3/testsuite/buildok/two.stp000077500000000000000000000006341217430427200204420ustar00rootroot00000000000000#! /bin/sh stap -p4 -g $@ - <<'END' %{ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) #include #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) #include #else #include #endif %} function get_release () %{ strncpy(STAP_RETVALUE, UTS_RELEASE, MAXSTRINGLEN); %} probe begin { log("hello from systemtap, kernel version " . get_release()) } END systemtap-2.3/testsuite/buildok/ucontext-embedded.stp000077500000000000000000000000651217430427200232270ustar00rootroot00000000000000#! stap -p4 probe begin { log(umodname(uaddr())) } systemtap-2.3/testsuite/buildok/ucontext-symbols-embedded.stp000077500000000000000000000004541217430427200247170ustar00rootroot00000000000000#! stap -p4 probe begin { log(usymname(0)) log(usymdata(0)) # This is really nonsense. In real use you'd do something # like: # print_usyms(ubacktrace()) # # On platforms without uprobes, this will fail. But, # buildok.exp will kfail this test. print_usyms("") log(sprint_usyms("")) } systemtap-2.3/testsuite/buildok/ucontext-unwind-embedded.stp000077500000000000000000000003761217430427200245360ustar00rootroot00000000000000#! stap -p4 probe begin { # On platforms without uprobes, this will fail. But, # buildok.exp will figure that out and kfail this test. print_ubacktrace() print_ubacktrace_brief() printf("%s\n", ubacktrace()) printf("%s\n", sprint_ubacktrace()) } systemtap-2.3/testsuite/buildok/udp-all-probes.stp000077500000000000000000000001461217430427200224550ustar00rootroot00000000000000#! stap -wp4 // Tests if all probes in the udp tapset are resolvable. probe udp.*, udp.*.* {} systemtap-2.3/testsuite/buildok/udp-detailed.stp000077500000000000000000000004511217430427200221670ustar00rootroot00000000000000#! stap -p4 probe udp.sendmsg, udp.recvmsg { printf("%s %p %d\n", name, sock, size) } probe udp.sendmsg.return, udp.recvmsg.return { printf("%s %d\n", name, size) } probe udp.disconnect { printf("%s %p %d\n", name, sock, flags) } probe udp.disconnect.return { printf("%s %d\n", name, ret) } systemtap-2.3/testsuite/buildok/udp_test.stp000077500000000000000000000007361217430427200214630ustar00rootroot00000000000000#! stap -p4 global send_bytes,recv_bytes,ports,src_ips function print_report() { printf("%d\t%d\t%d\t%s\n",send_bytes,recv_bytes,ports,src_ips); } probe udp.sendmsg { ports = inet_get_local_port(sock) src_ips = inet_get_ip_source(sock) } probe udp.sendmsg.return { if (size > 0) { send_bytes += size } } probe udp.recvmsg.return { if (size > 0) { recv_bytes += size } } probe udp.disconnect { log("tcp disconnect") } probe timer.ms(2000) { print_report() } systemtap-2.3/testsuite/buildok/utrace.stp000077500000000000000000000000461217430427200211110ustar00rootroot00000000000000#! stap -wp4 probe process.begin { } systemtap-2.3/testsuite/buildok/vfs-all-probes.stp000077500000000000000000000002161217430427200224610ustar00rootroot00000000000000#! stap -wp4 // Tests if all probes in the vfs.stp are resolvable. probe vfs.*, vfs.*.*, generic.*.*, generic.*.*.* {} systemtap-2.3/testsuite/buildok/vfs-detailed.stp000077500000000000000000000206321217430427200222000ustar00rootroot00000000000000#! stap -p4 probe generic.fop.llseek { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%d %d\n", offset, maxbyte) %(systemtap_v < "2.3" %? printf("%d\n", origin) %) printf("%d %s\n", whence, whence_str) } probe generic.fop.llseek.return { printf("%s %s\n", name, retstr) printf("%d(%s)\n", error, error_str) } probe generic.fop.aio_read { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%d %p %d\n", pos, buf, count) printf("%d %s\n", size, units) } probe generic.fop.aio_read.return { printf("%s %s\n", name, retstr) printf("%d(%s)\n", error, error_str) printf("%d %d\n", nr_segs, bytes_read) printf("%d %s\n", size, units) } probe generic.fop.aio_write { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%d %p %d\n", pos, buf, count) printf("%d %s\n", size, units) } probe generic.fop.aio_write.return { printf("%s %s\n", name, retstr) printf("%d %s\n", size, units) } probe generic.fop.readv ? { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%d %d\n", pos, nr_segs) printf("%d %s\n", size, units) } probe generic.fop.readv.return ? { printf("%s %s\n", name, retstr) printf("%p %d\n", file, bytes_read) printf("%d(%s)\n", error, error_str) printf("%d %s\n", size, units) } probe generic.fop.writev ? { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%d %d\n", pos, nr_segs) printf("%d %s\n", size, units) } probe generic.fop.writev.return ? { printf("%s %s\n", name, retstr) printf("%p %d\n", file, bytes_written) printf("%d(%s)\n", error, error_str) printf("%d %s\n", size, units) } probe generic.fop.mmap { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%x %x %x\n", vm_start, vm_end, vm_flags) } probe generic.fop.mmap.return { printf("%s %s\n", name, retstr) printf("%p\n", file) printf("%d(%s)\n", error, error_str) } probe generic.fop.open { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%s %x %d\n", filename, flag, size) } probe generic.fop.open.return { printf("%s %s\n", name, retstr) } probe generic.fop.sendfile ? { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%p %d\n", ppos, count) printf("%d %s\n", size, units) } probe generic.fop.sendfile.return ? { printf("%s %s\n", name, retstr) printf("%d %s\n", size, units) } probe generic.fop.splice_read ? { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%d %d\n", dev_major, dev_minor) printf("%d %d\n", len, flags) printf("%d %s\n", size, units) } probe generic.fop.splice_read.return ? { printf("%s %s\n", name, retstr) printf("%d(%s)\n", error, error_str) printf("%d %s\n", size, units) printf("%p %d %p\n", dev, ino, file) printf("%d %d\n", dev_major, dev_minor) } probe generic.fop.splice_write ? { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%d %d\n", len, flags) printf("%d %s\n", size, units) } probe generic.fop.splice_write.return ? { printf("%s %s\n", name, retstr) printf("%d(%s)\n", error, error_str) printf("%d %s\n", size, units) printf("%p\n", file) } probe generic.fop.read ? { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%d\n", count) printf("%d %s\n", size, units) } probe generic.fop.read.return ? { printf("%s %s\n", name, retstr) printf("%d %s\n", size, units) } probe generic.fop.write ? { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%d\n", count) printf("%d %s\n", size, units) } probe generic.fop.write.return ? { printf("%s %s\n", name, retstr) printf("%d %s\n", size, units) } probe generic.aop.writepages { printf("%s %s\n", name, argstr) printf("%p %s %d\n", dev, devname, ino) printf("%d\n", nr_to_write) printf("%d %s\n", size, units) } probe generic.aop.writepages.return { printf("%s %s\n", name, retstr) } probe vfs.do_sync_read { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%d %d %p %d\n", len, pos, buf, bytes_to_read) printf("%d %s\n", size, units) } probe vfs.do_sync_read.return { printf("%s %s\n", name, retstr) printf("%d(%s)\n", error, error_str) printf("%d %s\n", size, units) printf("%d %d\n", bytes_to_read, bytes_read) } probe vfs.do_sync_write { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%d %d %p %d\n", len, pos, buf, bytes_to_write) printf("%d %s\n", size, units) } probe vfs.do_sync_write.return { printf("%s %s\n", name, retstr) printf("%d(%s)\n", error, error_str) printf("%d %s\n", size, units) printf("%d %d\n", bytes_to_write, bytes_written) printf("%d\n", pos) } probe vfs.block_sync_page ? { printf("%s %s\n", name, argstr) printf("%p %s %d %d\n", dev, devname, ino, index) printf("%d %s\n", size, units) } probe vfs.block_sync_page.return ? { printf("%s %s\n", name, retstr) } probe vfs.buffer_migrate_page ? { printf("%s %s\n", name, argstr) printf("%p %s %d %d\n", dev, devname, ino, index) printf("%d %s\n", size, units) } probe vfs.buffer_migrate_page.return ? { printf("%s %s\n", name, retstr) printf("%d %s\n", size, units) } probe vfs.__set_page_dirty_buffers { printf("%s %s\n", name, argstr) printf("%p %s %d %d\n", dev, devname, ino, index) printf("%d %s\n", size, units) } probe vfs.__set_page_dirty_buffers.return { printf("%s %s\n", name, retstr) printf("%d %s\n", size, units) } probe vfs.do_mpage_readpage { printf("%s %s\n", name, argstr) printf("%p %s %d %d\n", dev, devname, ino, index) printf("%d %s\n", size, units) } probe vfs.do_mpage_readpage.return { printf("%s %s\n", name, retstr) printf("%d %s\n", size, units) } probe vfs.add_to_page_cache { printf("%s %s\n", name, argstr) printf("%p %s %d %d\n", dev, devname, ino, index) printf("%d %s\n", size, units) } probe vfs.add_to_page_cache.return { printf("%s %s\n", name, retstr) printf("%d %s\n", size, units) } probe vfs.remove_from_page_cache { printf("%s %s\n", name, argstr) printf("%p %s %d %d\n", dev, devname, ino, index) } probe vfs.remove_from_page_cache.return { printf("%s %s\n", name, retstr) } probe vfs.read { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%d %p %d\n", pos, buf, bytes_to_read) } probe vfs.read.return { printf("%s %s\n", name, retstr) printf("%d(%s)\n", error, error_str) printf("%d\n", bytes_read) } probe vfs.readv { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%d %p %d %d\n", pos, vec, vlen, bytes_to_read) } probe vfs.readv.return { printf("%s %s\n", name, retstr) printf("%d(%s)\n", error, error_str) printf("%d\n", bytes_read) } probe vfs.write { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%d %p %d\n", pos, buf, bytes_to_write) } probe vfs.write.return { printf("%s %s\n", name, retstr) printf("%d(%s)\n", error, error_str) printf("%d\n", bytes_written) } probe vfs.writev { printf("%s %s\n", name, argstr) printf("%p %s %d %p\n", dev, devname, ino, file) printf("%d %p %d %d\n", pos, vec, vlen, bytes_to_write) } probe vfs.writev.return { printf("%s %s\n", name, retstr) printf("%d(%s)\n", error, error_str) printf("%d\n", bytes_written) } probe _vfs.generic_file_readonly_mmap { printf("%s %s\n", name, argstr) printf("%p %p\n", file, vma) } probe _vfs.generic_file_readonly_mmap.return { printf("%s %s\n", name, retstr) printf("%d(%s)\n", error, error_str) } probe _vfs.generic_block_bmap { printf("%s %s\n", name, argstr) printf("%p %p %p\n", mapping, block, get_block) } probe _vfs.generic_commit_write ? { printf("%s %s\n", name, argstr) printf("%p, %p, %d, %d\n", file, page, from, to) } probe _vfs.block_prepare_write { printf("%s %s\n", name, argstr) printf("%p, %d, %d\n", page, from, to) } probe _vfs.block_prepare_write.return { printf("%s %s\n", name, retstr) printf("%d(%s)\n", error, error_str) } probe _vfs.block_write_begin ? { printf("%s %s\n", name, argstr) printf("%p, %d, %d, %x\n", file, pos, len, flags) } probe _vfs.block_write_begin.return ? { printf("%s %s\n", name, retstr) printf("%d(%s)\n", error, error_str) } probe _vfs.block_write_end ? { printf("%s %s\n", name, argstr) printf("%p, %d, %d, %p\n", file, pos, len, page) } probe _vfs.block_write_end.return ? { printf("%s %s\n", name, retstr) } systemtap-2.3/testsuite/buildok/vfs-embedded.stp000077500000000000000000000004651217430427200221600ustar00rootroot00000000000000#! stap -p4 probe begin { print( %(systemtap_v < "2.3" %? ppos_pos (0) + %) __address_inode(0) + __page_ino (0) + __page_dev (0) + __page_bdev (0) + __page_index (0) + __file_dev (0) + __file_bdev (0) + __file_ino (0) + __file_maxbytes (0) + _get_fopv_size(0, 0)) print(__file_filename (0)) } systemtap-2.3/testsuite/buildok/xtime.stp000077500000000000000000000005021217430427200207510ustar00rootroot00000000000000#! stap -p4 # Test for getting at an external global variable PR10622 probe kernel.function("do_gettimeofday") { printf("xtime.tv_sec:%d\n", (@defined($timekeeper->xtime_sec) ? $timekeeper->xtime_sec : (@defined($timekeeper->xtime->tv_sec) ? $timekeeper->xtime->tv_sec : $xtime->tv_sec))) exit(); } systemtap-2.3/testsuite/config/000077500000000000000000000000001217430427200167075ustar00rootroot00000000000000systemtap-2.3/testsuite/config/unix.exp000066400000000000000000000003731217430427200204130ustar00rootroot00000000000000load_lib "systemtap.exp" load_lib "stap_run2.exp" load_lib "stap_run_exact.exp" load_lib "stap_run_binary.exp" load_lib "stap_run.exp" load_lib "stap_compile.exp" load_lib "stap_run_error.exp" load_lib "cache_compile.exp" load_lib "compile_flags.exp" systemtap-2.3/testsuite/configure000077500000000000000000003121131217430427200173520ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for systemtap 2.3. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and $0: systemtap@sourceware.org about your system, including $0: any error possibly output before this message. Then $0: install a modern shell, or manually run the script $0: under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='systemtap' PACKAGE_TARNAME='systemtap' PACKAGE_VERSION='2.3' PACKAGE_STRING='systemtap 2.3' PACKAGE_BUGREPORT='systemtap@sourceware.org' PACKAGE_URL='' ac_subst_vars='LTLIBOBJS LIBOBJS enable_testapps dejazilla MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_maintainer_mode enable_dejazilla enable_testapps ' ac_precious_vars='build_alias host_alias target_alias' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures systemtap 2.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/systemtap] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of systemtap 2.3:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer --enable-dejazilla[=EMAIL] enable dejazilla support to automatically email test results to a central public collection point (default is disabled). Optional EMAIL overrides the default email address. --enable-testapps=foo bar or all enable rebuilding of large external apps for testing markers Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF systemtap configure 2.3 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by systemtap $as_me 2.3, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in .. "$srcdir"/..; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in .. \"$srcdir\"/.." "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. am__api_version='1.12' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='systemtap' VERSION='2.3' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then : enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 $as_echo "$USE_MAINTAINER_MODE" >&6; } if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE # Check whether --enable-dejazilla was given. if test "${enable_dejazilla+set}" = set; then : enableval=$enable_dejazilla; fi case "$enable_dejazilla" in no) dejazilla= ;; yes) dejazilla=dejazilla@elastic.org ;; *) dejazilla="$enable_dejazilla" ;; esac if test -n "$dejazilla"; then { $as_echo "$as_me:${as_lineno-$LINENO}: A \"make *check\" will email results to $dejazilla" >&5 $as_echo "$as_me: A \"make *check\" will email results to $dejazilla" >&6;} fi apps= for exp in $srcdir/systemtap.apps/*.exp do app=`basename $exp .exp` apps="$app $apps" done # Check whether --enable-testapps was given. if test "${enable_testapps+set}" = set; then : enableval=$enable_testapps; fi { $as_echo "$as_me:${as_lineno-$LINENO}: Will test ${enable_testapps-no} apps from: $apps" >&5 $as_echo "$as_me: Will test ${enable_testapps-no} apps from: $apps" >&6;} ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by systemtap $as_me 2.3, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ systemtap config.status 2.3 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi systemtap-2.3/testsuite/configure.ac000066400000000000000000000023021217430427200177250ustar00rootroot00000000000000dnl configure.ac --- autoconf input file for systemtap testsuite dnl Process this file with autoconf to produce a configure script. AC_INIT([systemtap], 2.3, systemtap@sourceware.org, systemtap) AC_PREREQ(2.59) AC_CONFIG_AUX_DIR(..) AM_INIT_AUTOMAKE([dejagnu foreign]) AM_MAINTAINER_MODE AC_ARG_ENABLE([dejazilla], AS_HELP_STRING([--enable-dejazilla@<:@=EMAIL@:>@], [enable dejazilla support to automatically email test results to a central public collection point (default is disabled). Optional EMAIL overrides the default email address.])) case "$enable_dejazilla" in no) dejazilla= ;; yes) dejazilla=dejazilla@elastic.org ;; *) dejazilla="$enable_dejazilla" ;; esac if test -n "$dejazilla"; then AC_MSG_NOTICE([A "make *check" will email results to $dejazilla]) fi AC_SUBST(dejazilla) apps= for exp in $srcdir/systemtap.apps/*.exp do app=`basename $exp .exp` apps="$app $apps" done AC_ARG_ENABLE([testapps], AC_HELP_STRING([--enable-testapps=foo bar or all], [enable rebuilding of large external apps for testing markers])) AC_MSG_NOTICE([Will test ${enable_testapps-no} apps from: $apps]) AC_SUBST(enable_testapps) AC_CONFIG_FILES(Makefile) AC_OUTPUT systemtap-2.3/testsuite/execrc000077500000000000000000000001231217430427200166350ustar00rootroot00000000000000#! /bin/sh # Run given program, but return a successful rc anyway. eval $@ exit 0 systemtap-2.3/testsuite/lib/000077500000000000000000000000001217430427200162105ustar00rootroot00000000000000systemtap-2.3/testsuite/lib/cache_compile.exp000066400000000000000000000042241217430427200215030ustar00rootroot00000000000000 # # flag values proc F_UNCACHED {} {return 0x1}; # compilation should be uncached proc F_CACHED {} {return 0x2}; # compilation should be cached proc F_NO_COMPILE {} {return 0x4}; # script doesn't compile proc F_COMPILE {} {return 0x8}; # script compiles # mask values to get either the cache vale or the compile value proc F_CACHE_MASK {} {return [expr [F_UNCACHED] | [F_CACHED]]} proc F_COMPILE_MASK {} {return [expr [F_NO_COMPILE] | [F_COMPILE]]} # convenience combination of flags proc F_CACHED_COMPILE {} {return [expr [F_CACHED] | [F_COMPILE]]} proc F_UNCACHED_COMPILE {} {return [expr [F_UNCACHED] | [F_COMPILE]]} proc F_UNCACHED_NO_COMPILE {} {return [expr [F_UNCACHED] | [F_NO_COMPILE]]} # cache_compile TEST_NAME flags script args # - TEST_NAME is the name of the current test # - flags indicates the expected outcome of this test # - script is the script to compile # Additional arguments are passed to stap as-is. proc cache_compile { TEST_NAME flags script args } { set cmd [concat {stap -v -p4 -e} $script $args] eval spawn $cmd set cached 0 set compile_errors 0 expect { -timeout 180 -re {^Pass\ [1234]:[^\r]*\ in\ [^\r]*\ ms\.\r\n} {exp_continue} -re {^Pass\ [34]: using cached [^\r\n]+\r\n} {incr cached 1; exp_continue} -re "^WARNING" {exp_continue} # pass-4 output -re {^/[^\r\n]+\.ko\r\n} {exp_continue} -re "compilation failed" {incr compile_errors 1; exp_continue} -re "semantic error:" {incr compile_errors 1; exp_continue} timeout { fail "$TEST_NAME (timeout)" } } catch close wait # If we've got compile errors and the script was supposed to # compile, fail. if {$compile_errors > 0 && [expr $flags & [F_COMPILE_MASK]] == [F_COMPILE]} { fail "$TEST_NAME compilation failed" return } # If we were supposed to use a cached module... if {[expr $flags & [F_CACHE_MASK]] == [F_CACHED]} { if {$cached == 2} { pass "$TEST_NAME was cached" } else { fail "$TEST_NAME wasn't cached" } # If we weren't supposed to use a cached module... } else { if {$cached > 0} { fail "$TEST_NAME was cached" } else { pass "$TEST_NAME wasn't cached" } } } systemtap-2.3/testsuite/lib/compile_flags.exp000066400000000000000000000047551217430427200215450ustar00rootroot00000000000000# Number of different compile flags for this arch. proc arch_compile_flags {} { switch -regexp $::tcl_platform(machine) { {^(x86_64|ppc64|s390x)$} { return 2 } default { return 1} } } # Additional compile flag to use for with target_compile. # Given INDEX starts at zero and should be smaller than the number # returned by arch_compile_flags. proc arch_compile_flag { INDEX } { if { [arch_compile_flags] == 1 } { return "" } switch $INDEX { 0 { return "additional_flags=-m64" } 1 { switch -regexp $::tcl_platform(machine) { {^s390x$} { return "additional_flags=-m31" } default { return "additional_flags=-m32" } } } } } # Name of compile flag to use in generated files or user/test messages. # Given INDEX starts at zero and should be smaller than the number # returned by arch_compile_flags. proc arch_compile_flag_name { INDEX } { if { [arch_compile_flags] == 1 } { switch -regexp $::tcl_platform(machine) { {^ia64$} { return "m64" } {^s390$} { return "m31" } default { return "m32" } } } switch $INDEX { 0 { return "m64" } 1 { switch -regexp $::tcl_platform(machine) { {^s390x$} { return "m31" } default { return "m32" } } } } } # Number of different combinations of compile flags. proc all_compile_flags {} { # There are 3 sets of flags for each architecture. return [expr 3 * [arch_compile_flags]] } # Is INDEX a native (i.e. non-multiarch) configuration? proc all_compile_flag_native_p { INDEX } { set arch_index [expr $INDEX % [arch_compile_flags]] if { $arch_index == 0 } { return 1 } return 0 } # Additional compile flag to use for with target_compile. # Given INDEX starts at zero and should be smaller than the number # returned by all_compile_flags. proc all_compile_flag { INDEX } { set opt_flags [list "" "additional_flags=-O" "additional_flags=-O2" ] set arch_index [expr $INDEX % [arch_compile_flags]] set opt_flag [lindex $opt_flags [expr ($INDEX / 2) % 3]] return "[arch_compile_flag $arch_index] $opt_flag" } # Name of compile flag to use in generated files or user/test messages. # Given INDEX starts at zero and should be smaller than the number # returned by arch_compile_flags. proc all_compile_flag_name { INDEX } { set opt_names [list "" "-O" "-O2" ] set arch_index [expr $INDEX % [arch_compile_flags]] set opt_name [lindex $opt_names [expr ($INDEX / 2) % 3]] return "[arch_compile_flag_name $arch_index]$opt_name" } systemtap-2.3/testsuite/lib/stap_compile.exp000066400000000000000000000032571217430427200214140ustar00rootroot00000000000000# stap_compile TEST_NAME flags script args # - TEST_NAME is the name of the current test # - compile indicates whether the script is supposed to compile # - script is the script to compile # Additional arguments are passed to stap as-is. proc stap_compile { TEST_NAME compile script args } { set cmd [concat stap {-v -p4 -e} $script $args] verbose -log "running $cmd" eval spawn $cmd set compile_errors 0 expect { -re {^Pass\ [1234]:[^\n\r]+\ in\ [^\n\r]+\ ms.\r\n} {exp_continue} -re {^Pass\ [34]: using cached [^\r\n]+\r\n} {exp_continue} -re "^WARNING" {exp_continue} # pass-4 output -re {^/[^\r\n]+.ko\r\n} {exp_continue} -re "parse error" { incr compile_errors 1; exp_continue} -re "compilation failed" {incr compile_errors 1; exp_continue} -re "semantic error:" {incr compile_errors 1; exp_continue} } set res [wait -i $spawn_id] catch close set res [lindex $res 3] if {($res == 0 && $compile_errors == 0) || ($res != 0 && $compile_errors > 0)} { # Expected case. Ignore. Real pass/fail result will come below. } else { # stap result doesn't match errors seen. if {$res == 0} { fail "${TEST_NAME}_compile successfull, but got error messages" } else { fail "${TEST_NAME}_compile failed, but got no error messages" } } # If we've got compile errors and the script was supposed to # compile, fail. if {$compile_errors > 0} { if {$compile == 1} { fail "$TEST_NAME compilation failed" } else { pass "$TEST_NAME compilation failed correctly" } } else { if {$compile == 1} { pass "$TEST_NAME compilation succeeded" } else { fail "$TEST_NAME compilation succeeded unexpectedly" } } } systemtap-2.3/testsuite/lib/stap_run.exp000066400000000000000000000113351217430427200205640ustar00rootroot00000000000000# stap_run TEST_NAME LOAD_GEN_FUNCTION OUTPUT_CHECK_STRING # TEST_NAME is path to the current test # LOAD_GEN_FUNCTION (optional) to produce something to measure # returns 0 if successful # returns 1 if there was a problem # OUTPUT_CHECK_STRING (optional) examines the output of experiment # returns 0 if successful # returns 1 if there was a problem # Additional arguments are passed to stap as-is. # # As a side-effect, global 'probe_errors' and 'skipped_probes' are set # to the number of probe errors and skipped probes seen while # running the probe. proc stap_run { TEST_NAME {LOAD_GEN_FUNCTION ""} {OUTPUT_CHECK_STRING ""} args } { global probe_errors global skipped_probes # zap the srcdir prefix set test_file_name $TEST_NAME set TEST_NAME [regsub {.*/testsuite/} $TEST_NAME ""] if {[file readable $test_file_name] && $args != ""} { # If args contains a '--runtime=RUNTIME' option, append # RUNTIME to the test name. if {[regexp -- {--runtime=(\w+)} "$args" match runtime]} { lappend TEST_NAME "(${runtime})" } } # initialize probe_errors and skipped_probes to 0 set probe_errors 0 set skipped_probes 0 set warning_regexp {^WARNING: Number of errors: ([0-9]+), skipped probes: ([0-9]+)\r\n} if {[info procs installtest_p] != "" && ![installtest_p]} { untested $TEST_NAME; return } set cmd [concat stap -v $args] if [file readable $test_file_name] { lappend cmd $test_file_name } send_log "executing: $cmd\n" eval spawn $cmd expect { -timeout 180 -re {^WARNING: cannot find module [^\r]*DWARF[^\r]*\r\n} {exp_continue} -re {^WARNING: No unwind data for /.+\r\n} {exp_continue} -re {^Pass\ ([1234]):[^\r]*\ in\ ([0-9]+)usr/([0-9]+)sys/([0-9]+)real\ ms\.\r\n} {set pass$expect_out(1,string) "\t$expect_out(2,string)\t$expect_out(3,string)\t$expect_out(4,string)"; exp_continue} -re {^Pass\ ([34]): using cached [^\r]+\r\n} {set pass$expect_out(1,string) "\t0\t0\t0"; exp_continue} -re {^Passes: via server [^\r]* using [^\r]* in [0-9]+usr/[0-9]+sys/[0-9]+real ms\.\r\n} {exp_continue} -re {^Pass 5: starting run.\r\n} {exp_continue} -re "^systemtap starting probe\r\n" { pass "$TEST_NAME startup" if {$LOAD_GEN_FUNCTION != ""} then { #run the interesting test here if {[eval $LOAD_GEN_FUNCTION] == 0} then { pass "$TEST_NAME load generation" } else { fail "$TEST_NAME load generation" } } exec kill -INT -[exp_pid] # check the output to see if it is sane set output "^systemtap ending probe\r\n$OUTPUT_CHECK_STRING" # By default, "expect -re" will match up to 2000 chars. # Increase this to 8K worth of data. exp_match_max 8192 expect { -timeout 20 -re $warning_regexp { set probe_errors $expect_out(1,string) set skipped_probes $expect_out(2,string) exp_continue} -re $output { pass "$TEST_NAME shutdown and output" expect { -timeout -1 -re {^Pass\ ([5]):[^\r]*\ in\ ([0-9]+)usr/([0-9]+)sys/([0-9]+)real\ ms\.\r\n} {set pass$expect_out(1,string) "\t$expect_out(2,string)\t$expect_out(3,string)\t$expect_out(4,string)" verbose -log "metric:\t$TEST_NAME $pass1$pass2$pass3$pass4$pass5"} -re $warning_regexp { set probe_errors $expect_out(1,string) set skipped_probes $expect_out(2,string)} } } timeout { fail "$TEST_NAME shutdown (timeout)" exec kill -INT -[exp_pid] } eof { fail "$TEST_NAME shutdown (eof)" } } } -re "semantic error:" { fail "$TEST_NAME compilation" } timeout { fail "$TEST_NAME startup (timeout)" exec kill -INT -[exp_pid] } eof { fail "$TEST_NAME startup (eof)" } } # again for good measure exec kill -INT -[exp_pid] catch close wait } proc no_load {} { # nothing in here # load to use when nothing is needed return 0 } # Load function to use when you need to wait 5 seconds. proc wait_5_secs {} { # Tcl_Sleep appears to have a cow if the systme clock jumps, so # instead of the built-in "after", use /usr/bin/sleep. catch { exec sleep 5 } return 0; } proc print_system_info {} { global Host Snapshot Distro GCC_Version SElinux clone_output "\nHost: $Host" if {[string compare $Snapshot "unknown"]!=0} { clone_output "Snapshot: $Snapshot" } clone_output "GCC: $GCC_Version" clone_output "Distro: $Distro" clone_output "SElinux: $SElinux" clone_output "\n" } print_system_info # tests better all be true # # BZ692445 was fixed by removing the '$' at the end of # all_pass_string. Yet another expect regular expression oddity. The # '\r\n' is good enough at finding the EOL. set all_pass_string "(systemtap test success\r\n)+" systemtap-2.3/testsuite/lib/stap_run2.exp000066400000000000000000000033501217430427200206440ustar00rootroot00000000000000# stap_run2.exp # # Simple script for testing multiple lines of exact output. # stap_run2 TEST_NAME # TEST_NAME is path to the current test # Additional arguments are passed to stap as-is. # # global result_string must be set to the expected output proc stap_run2 { TEST_NAME args } { # zap the srcdir prefix set TEST_FILE $TEST_NAME set TEST_NAME [regsub {.*/testsuite/} $TEST_NAME ""] if {[llength $args] == 0} { stap_run3 $TEST_NAME $TEST_FILE } else { eval stap_run3 "{$TEST_NAME $args} $TEST_FILE $args" } } # stap_run3 TEST_NAME TEST_FILE # TEST_NAME is the name of the test as shown in PASS/FAIL/SKIPPED messages. # TEST_FILE is the path to the current test # Additional arguments are passed to stap as-is. # # global result_string must be set to the expected output proc stap_run3 { TEST_NAME TEST_FILE args } { if {[info procs installtest_p] != "" && ![installtest_p]} { untested $TEST_NAME; return } set cmd [concat stap $TEST_FILE $args] send_log "executing: $cmd\n" catch {eval exec $cmd} res set n 0 set expected [split $::result_string "\n"] foreach line [split $res "\n"] { if {![string equal $line [lindex $expected $n]]} { fail "$TEST_NAME" send_log "line [expr $n + 1]: expected \"[lindex $expected $n]\"\n" send_log "Got \"$line\"\n" set m 0 foreach line2 [split $res "\n"] { if {$m > $n} { send_log " \"$line2\"\n" } incr m } return } incr n } if {[expr $n == [llength $expected]]} { pass "$TEST_NAME" } else { fail "$TEST_NAME" send_log "too few lines of output, got $n, expected [llength $expected]\n" } } systemtap-2.3/testsuite/lib/stap_run_binary.exp000066400000000000000000000020321217430427200221220ustar00rootroot00000000000000# stap_run_binary.exp # # Simple script for testing binary output # stap_run_binary TEST_NAME # TEST_NAME is path to the current test # Additional arguments are passed to stap as-is. # # global result_string must be set to the expected output proc stap_run_binary { TEST_NAME args } { # zap the srcdir prefix set test_file_name $TEST_NAME set TEST_NAME [regsub {.*/testsuite/} $TEST_NAME ""] if {[llength $args]} { set TEST_NAME [concat $TEST_NAME $args] } if {[info procs installtest_p] != "" && ![installtest_p]} {untested $TEST_NAME; return} set hex_args {-ve {8/1 "%02x " "\n"}} set cmd [concat stap $args $test_file_name | hexdump $hex_args] send_log "executing: $cmd\n" catch { eval exec $cmd } res if {[string compare $res $::result_string] == 0} { pass "$TEST_NAME" } else { fail "$TEST_NAME" puts "EXPECTED:\n-----------------------\n<$::result_string>" puts "-----------------------\n" puts "GOT:\n-----------------------\n<$res>" puts "-----------------------\n" } } systemtap-2.3/testsuite/lib/stap_run_error.exp000066400000000000000000000040521217430427200217730ustar00rootroot00000000000000# stap_run TEST_NAME EXPECT_ERROR ERROR_STRING OUTPUT_CHECK_STRING # TEST_NAME is name of the current test # EXPECT_ERROR lets us know to expect an error or not # ERROR_STRING lets us know which error to expect # OUTPUT_CHECK_STRING examines the output of experiment # Additional arguments are passed to stap as-is. proc stap_run_error { TEST_NAME EXPECT_ERROR ERROR_STRING OUTPUT_CHECK_STRING args } { set full_error "ERROR: $ERROR_STRING\r\n" set cmd [concat {stap -v} $args] send_log "executing: $cmd\n" eval spawn $cmd expect { -timeout 150 -re {^WARNING: [^\r]+\r\n} {exp_continue} -re {^Pass\ [1234]: [^\r]+real\ ms\.\r\n} {exp_continue} -re {^Pass\ ([34]): using cached [^\r]+\r\n} {exp_continue} -re {^Pass 5: starting run.\r\n} {exp_continue} -re {^ERROR: Couldn't insert module[^\r]+\r\n} { if {$EXPECT_ERROR} { pass "$TEST_NAME expected insert module error" } else { fail "$TEST_NAME expected insert module error" } } -re $full_error { if {$EXPECT_ERROR} { pass "$TEST_NAME expected error" } else { fail "$TEST_NAME expected error" } } -re "^systemtap starting probe\r\n" { exec kill -INT -[exp_pid] # check the output to see if it is sane set output "^systemtap ending probe\r\n$OUTPUT_CHECK_STRING" expect { -timeout 20 -re $output { if {$EXPECT_ERROR} { fail "$TEST_NAME no expected error" } else { pass "$TEST_NAME no expected error" } } -re $full_error { if {$EXPECT_ERROR} { pass "$TEST_NAME expected error" } else { fail "$TEST_NAME expected error" } } timeout { fail "$TEST_NAME shutdown (timeout)" exec kill -INT -[exp_pid] } eof { fail "$TEST_NAME shutdown (eof)" } } } -re "semantic error:" { fail "$TEST_NAME compilation" } timeout { fail "$TEST_NAME startup (timeout)"; exec kill -INT -[exp_pid] } eof { fail "$TEST_NAME startup (eof)" } } # again for good measure exec kill -INT -[exp_pid] catch close wait } systemtap-2.3/testsuite/lib/stap_run_exact.exp000066400000000000000000000016131217430427200217460ustar00rootroot00000000000000# stap_run_exact.exp # # Simple script for testing multiple lines of exact output. # stap_run_exact TEST_NAME filename args # TEST_NAME is the name printed # filename is path to the current test # Additional arguments are passed to stap as-is. # # global result_string must be set to the expected output proc stap_run_exact { TEST_NAME test_file_name args } { if {[info procs installtest_p] != "" && ![installtest_p]} { untested $TEST_NAME; return } set cmd [concat stap $args $test_file_name] send_log "executing: $cmd\n" catch {eval exec $cmd} res set n 0 set expected [split $::result_string "\n"] foreach line [split $res "\n"] { if {![string equal $line [lindex $expected $n]]} { fail "$TEST_NAME" send_log "line [expr $n + 1]: expected \"[lindex $expected $n]\"\n" send_log "Got \"$line\"\n" return } incr n } pass "$TEST_NAME" } systemtap-2.3/testsuite/lib/systemtap.exp000066400000000000000000000424141217430427200207640ustar00rootroot00000000000000load_lib site.exp load_lib "compile_flags.exp" proc installtest_p {} { global TOOL_OPTIONS if {[info exists TOOL_OPTIONS] && [string match "*install*" $TOOL_OPTIONS]} { return 1 } else { return 0 } } # only original rhel5/6-era utrace need apply proc utrace_orig_p {} { set path "/proc/kallsyms" if {! [catch {exec grep -q utrace_attach $path} dummy]} { return 1 } return 0 } proc utrace_p {} { set path "/proc/kallsyms" # We've got 2 ways to provide utrace support: # # (1) Kernel built-in utrace (CONFIG_UTRACE). Look for # 'utrace_attach'. if {! [catch {exec grep -q utrace_attach $path} dummy]} { return 1 # (2) Tracepoint-based utrace. Check for the set of 5 tracepoints # we need and task_work_add() (see # runtime/autoconf-utrace-via-tracepoints.c for details). } elseif {! [catch {exec grep -q tracepoint_sched_process_fork $path} dummy] && ! [catch {exec grep -q tracepoint_sched_process_exit $path} dummy] && ! [catch {exec grep -q tracepoint_sys_enter $path} dummy] && ! [catch {exec grep -q tracepoint_sys_exit $path} dummy] && ! [catch {exec grep -q tracepoint_sched_process_exec $path} dummy] && ! [catch {exec grep -q task_work_add $path} dummy]} { return 1 } return 0 } proc uprobes_p {} { set path "/proc/kallsyms" # If this is a utrace kernel, then we can use our version of uprobes. # No need to build it now, stap will handle that itself. # # classical utrace? if {! [catch {exec grep -q utrace_attach $path} dummy]} { # Although ia64 has classical utrace, uprobes hasn't been # ported there (PR7081). if {[istarget ia64-*-*]} { return 0 } return 1 } # inode-uprobes or (unlikely compiled-in classical uprobes?) # # Note we're looking for " uprobe_register" to avoid finding # 'kallsyms_uprobe_register' from a loaded systemtap module. if {! [catch {exec grep -q register_uprobe $path} dummy] || ! [catch {exec grep -q " uprobe_register" $path} dummy]} { return 1 } return 0 } proc inode_uprobes_p {} { set path "/proc/kallsyms" # Note we're looking for " uprobe_register" to avoid finding # 'kallsyms_uprobe_register' from a loaded systemtap module. if {! [catch {exec grep -q " uprobe_register" $path} dummy]} { return 1 } return 0 } proc uretprobes_p {} { set path "/proc/kallsyms" if {! [uprobes_p]} { return 0 } if {! [catch {exec grep -q uretprobe $path} dummy]} { return 1 } if {! [catch {exec grep -q utrace_attach $path} dummy]} { return 1 } return 0 } proc dyninst_p {} { global systemtap_dyninst_p return $systemtap_dyninst_p } proc nss_p {} { global systemtap_nss_p return $systemtap_nss_p } proc java_p {} { global systemtap_java_p return $systemtap_java_p } proc get_runtime_list {} { # Always return the default runtime. set runtime_list [list ""] if {[dyninst_p]} { lappend runtime_list "dyninst" } return $runtime_list } proc print_systemtap_version {} { set version [exec /bin/uname -r] set location "/boot/vmlinux-$version" if {! [file exists $location]} { # try the debuginfo location set location "/usr/lib/debug/lib/modules/$version/vmlinux" if {! [file exists $location]} { set location "" } } print "kernel location: $location" print "kernel version: $version" set location [exec /usr/bin/which stap] regexp {version [^)]*} [exec stap -V 2>@ stdout] version print "systemtap location: $location" print "systemtap version: $version" set location [exec /usr/bin/which gcc] set version [exec gcc --version | head -1] print "gcc location: $location" print "gcc version: $version" } proc setup_systemtap_environment {} { global srcdir env server_pid logfile systemtap_dyninst_p global systemtap_nss_p systemtap_java_p # need an absolute SRCDIR for the top-level src/ tree # XXX: or, we could change nearby uses of ${SRCDIR}/testsuite to ${SRCDIR} set env(SRCDIR) [fullpath $srcdir/..] # pretend to be a dumb terminal so that coloring is always turned off # otherwise, we will have problems with expect set env(TERM) dumb # Use a local systemtap directory and cache. Add user name so # make check and sudo make check don't clobber each other. set env(SYSTEMTAP_DIR) [exec pwd]/.systemtap-[exec whoami] exec mkdir -p $env(SYSTEMTAP_DIR) # Start with fresh server certificates exec rm -fr $env(SYSTEMTAP_DIR)/ssl # Remove the rc file exec rm -f $env(SYSTEMTAP_DIR)/rc # All hail the prophet lockdep set chan [open $env(SYSTEMTAP_DIR)/rc w] puts $chan "--rlimit-cpu=300" close $chan # Erase the old server log file. set logfile "[exec pwd]/server.log" if {[file exists $logfile]} then { exec rm -f $logfile; } # Create a new one and make sure it's world writable. exec touch $logfile exec chmod 666 $logfile # Zap any previous uprobes, if any catch { exec /sbin/rmmod uprobes } # No compile-server started yet. set server_pid 0 # PATH, SYSTEMTAP_TAPSET, SYSTEMTAP_RUNTIME, LD_LIBRARY_PATH are already set. foreach var {PATH STAP SRCDIR SYSTEMTAP_TAPSET SYSTEMTAP_RUNTIME SYSTEMTAP_DIR LD_LIBRARY_PATH} { if [info exists env($var)] { verbose -log "env $var = $env($var)" } } # Remember if this very version of systemtap compiled with dyninst support if {! [catch {exec sh -c "stap -V 2>&1 | grep -q DYNINST"} dummy]} { set systemtap_dyninst_p 1 } else { set systemtap_dyninst_p 0 } # Remember if this selfsame version of systemtap compiled with nss support if {! [catch {exec sh -c "stap -V 2>&1 | grep -q NSS"} dummy]} { set systemtap_nss_p 1 } else { set systemtap_nss_p 0 } # Remember if this selfsame version of systemtap compiled with java support if {! [catch {exec sh -c "stap -V 2>&1 | grep -q JAVA"} dummy]} { set systemtap_java_p 1 } else { set systemtap_java_p 0 } return 1 } # Set up the environment so that tests will be performed using the systemtap # client and server. proc setup_server { args } { global srcdir env installed_stap logfile use_server avahi_ok_p # Start the server if {! [start_server $args]} then { return 0 } # Make sure that stap can find the server. set use_server --use-server set res [catch { exec stap --list-servers=online,trusted,compatible >& stap-list-servers.out } looksee] verbose -log "stap --list-servers returned: res==$res" verbose -log $looksee[exec cat stap-list-servers.out] set res [catch { exec grep "^ host" stap-list-servers.out } looksee] verbose -log "grep for servers returned: res==$res\n$looksee" set avahi_ok_p 1 if {$res != 0} then { verbose -log "Unable to automatically find the systemtap server -- check firewall settings for mDNS" set avahi_ok_p 0 # Try to discover the port the server is listening on from the server # log. set res [catch { exec /bin/cat $logfile | awk "/^Systemtap Compile Server on port .* ready/ {print \$6}" } server_port] if {$res != 0} then { verbose -log "Unable to discover the port used by the systemtap server" shutdown_server return 0 } set server_spec [info hostname]:$server_port verbose -log "Client/Server tests will be run by contacting the server directly as $server_spec" # Make sure stap can contact the server directly set use_server --use-server=$server_spec set res [catch {exec stap $use_server -p2 -e {probe begin {exit()}}} looksee] if {$res != 0} then { verbose -log "Unable to contact the server at $server_spec directly" shutdown_server return 0 } } return 1 } proc start_server { options } { global srcdir env server_pid installed_stap logfile if {! [nss_p]} { return 0 } # Server management scripts and data are installed if this is an # install test, otherwise there is some setup to do. # Make sure the server management scripts and tools are on the $PATH. if {! [installtest_p]} then { set env(PATH) "$srcdir/..:[exec pwd]/..:$env(PATH)" set installed_stap "[exec pwd]/../stap" set env(SYSTEMTAP_SERVER_SCRIPTS) "$srcdir/.." } else { set env(PATH) "$env(PKGLIBDIR):$env(PATH)" set installed_stap "$env(SYSTEMTAP_PATH)/stap" set env(SYSTEMTAP_SERVER_SCRIPTS) $env(PKGLIBDIR) } # Try to start the server. set status 0 if {[catch {eval {exec env STAP_PR11197_OVERRIDE=1 \ env SYSTEMTAP_STAP=[exec which stap] stap-start-server \ --log=$logfile} $options} server_pid]} { if {[lindex $::errorCode 0] eq "CHILDSTATUS"} { set status [lindex $::errorCode 2] } } verbose -log "output: $server_pid" if { "$server_pid" == "" || $status != 0 } then { verbose -log "Cannot start a systemtap server" set server_pid 0 return 0 } else { verbose -log "Started a systemtap server as PID==$server_pid" } return 1 } proc shutdown_server {} { global server_pid if { $server_pid != 0 } then { verbose -log "Stopping the systemtap server with PID==$server_pid" exec stap-stop-server $server_pid set server_pid 0 } foreach module [glob -nocomplain [exec pwd]/stap_*.ko] { exec /bin/rm -f $module } foreach sig [glob -nocomplain [exec pwd]/stap_*.ko.sgn] { exec /bin/rm -f $sig } } proc normalize_arch { arch } { if {$arch == "ppc64"} then {return "powerpc"} if {$arch == "s390x"} then {return "s390"} if {$arch == "i686"} then {return "i386"} if {$arch == "armv5tel"} then {return "arm"} if {$arch == "armv7l"} then {return "arm"} if {$arch == "armv7lh"} then {return "arm"} return $arch } proc fullpath { path } { if {[string index $path 0] != "/"} then { # relative paths are anchored to the current directory return [pwd]/$path } else { return $path } } proc get_system_info {} { global Host Snapshot Distro GCC_Version env SElinux set Host [exec /bin/uname -a] if [file exists ../SNAPSHOT] { set Snapshot [exec /bin/cat ../SNAPSHOT] } elseif [file exists $env(SRCDIR)/../SNAPSHOT] { set Snapshot [exec /bin/cat $env(SRCDIR)/../SNAPSHOT] } else { regexp {version [^)]*} [exec stap -V 2>@ stdout] version set Snapshot $version } set Distro "Linux" if [file exists /usr/bin/lsb_release] { # this produces one line of this format: # Distribution:\tSTRING set Distro [lrange [exec /usr/bin/lsb_release -d] 1 end] } else { foreach f {/etc/fedora-release /etc/enterprise-release /etc/redhat-release /etc/suse-release /etc/debian_version} { if [file exists $f] then {set Distro [exec /bin/cat $f]; break } } } # Easily parsable version first major minor patch level set n [exec echo "__GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__" | cpp -P] set n [string map {" " "."} $n] set n [string map {"\n" ""} $n] # Plus full version between square brackets. set full [exec gcc --version | head -1] set GCC_Version "$n \[$full\]" # selinux status if [file exists /usr/sbin/getenforce] { set SElinux [exec /usr/sbin/getenforce] } else { set SElinux "unknown" } } if {! [setup_systemtap_environment]} then { cleanup exit 1 } print_systemtap_version get_system_info # PR11798: die if kernel-devel is not sufficient to build any modules if {[catch {exec stap -p4 -e {probe begin {exit()}}} result]} { puts "\n\n\n**** failed systemtap kernel-devel smoke test:\n" puts $result # puts "****\n" # puts $options puts "\n**** aborting testing.\n" cleanup exit 1 } # PR11798: die also if kernel-debuginfo is not available # NB: if one introduced a [kernel_debuginfo_p] proc like the # ones for uprobes/utrace above, and sprinkled it throughout, # then this wouldn't have to be a failing condition. # Note the --skip-badvars -w, we just care there is some debuginfo, # it is allowed have bad var location descriptors (which will cause # some tests to fail of course). Just test -p2, kernel-devel smoke # test above does a full module build, we don't need another one. if {[catch {exec stap --skip-badvars -w -p2 -e {probe syscall.open {println (argstr)}}} result]} { puts "\n\n\n**** failed systemtap kernel-debuginfo smoke test:\n" puts $result # puts "****\n" # puts $options puts "\n**** aborting testing.\n" cleanup exit 1 } # Make sure all development packages for the supported ABIs (-m64 -m32/-m31) # are installed by building a quick hello.c and hello.cxx program with both. set source "hello.c" set hello_file [open $source "w"] puts $hello_file "#include " puts $hello_file "int main () { printf(\"Hello World!\"); return 0; }" close $hello_file for {set i 0} {$i < [arch_compile_flags]} {incr i} { set flags "additional_flags=-g compiler=gcc [arch_compile_flag $i]" set exe "hello-[arch_compile_flag_name $i]" set result [target_compile $source $exe executable $flags] if { $result != "" } { puts "\n\n\n**** failed gcc [arch_compile_flag_name $i] smoke test:\n" puts $result puts "Please install libgcc and glibc development packages for [arch_compile_flag_name $i]\n" puts "\n**** aborting testing.\n" cleanup exit 1 } } set source "hello.cxx" set hello_file [open $source "w"] puts $hello_file "#include " puts $hello_file "using namespace std;" puts $hello_file "int main () { cout << \"Hello World!\" << endl; return 0; }" close $hello_file for {set i 0} {$i < [arch_compile_flags]} {incr i} { set flags "additional_flags=-g compiler=g++ [arch_compile_flag $i]" set exe "hello-[arch_compile_flag_name $i]" set result [target_compile $source $exe executable $flags] if { $result != "" } { puts "\n\n\n**** failed g++ [arch_compile_flag_name $i] smoke test:\n" puts $result puts "Please install libstdc++-devel package for [arch_compile_flag_name $i]\n" puts "\n**** aborting testing.\n" cleanup exit 1 } } catch { eval [list exec rm -f] [glob "hello.c*" "hello-*"] } proc systemtap_init {args} {} proc systemtap_version {} {} proc cleanup {} { # Stop the stap server, if we started it. shutdown_server } proc stap_run_batch {filename args} { verbose -log "starting $filename $args" # Many of our test cases use "#! stap ...". Since these lack # /full/paths, they are not really executable. (We can't have # /full/paths because the choice of systemtap interpreter is set # at "make check" time.) # So we cheat. If the file begins with "#! stap", we will spawn # stap manually here (relying on $PATH). Otherwise, we presume # the file properly executable. set file [open $filename r] set firstbits [gets $file] close $file if [regexp -line {\#! stap (.*)} $firstbits -> stap_args] { verbose -log "spawn1 stap $stap_args $filename $args" # Make sure we don't accidentially add an extra empty argument. if {$args == ""} { spawn stap $stap_args $filename } else { spawn stap $stap_args $filename $args } } else { verbose -log "spawn2 $filename $args" # Make sure we don't accidentially add an extra empty argument. if {$args == ""} { spawn $filename } else { spawn $filename $args } } expect { -timeout -1 -re {[^\r]*\r} { verbose -log $expect_out(0,string); exp_continue } eof { } } set results [wait] verbose -log "wait results: $results" if {[llength $results] >= 5} { # Unexpected output. stap must have crashed return -1 } else { return [lindex $results 3] } } proc as_root { command } { set effective_uid [exec /usr/bin/id -u] if {$effective_uid != 0} { set command "sudo $command" } verbose -log "as_root $command" set res [catch {eval exec $command} value] verbose -log "OUT $value" verbose -log "RC $res" return $res } proc as_non_root { command } { set effective_uid [exec /usr/bin/id -u] if {$effective_uid == 0} { # If logname fails (which it can if we're not in a login # shell) or if we're root, use user 'nobody'. # # Note that user 'nobody' can't use systemtap to load kernel # modules, since he isn't a member of the stapusr/stapdev # groups. But, 'nobody' can use systemtap to compile a kernel # module. set logname "root" if {[catch {exec /usr/bin/logname} logname] || $logname == "root"} { set logname "nobody" } set command "su -s /bin/sh $logname -c \"$command\"" } verbose -log "as_non_root $command" set res [catch {eval exec $command} value] verbose -log "OUT $value" verbose -log "RC $res" return $res } proc sdt_includes {} { global srcdir env # The wrapper sys/sdt.h for testing STAP_SDT_V[12] is here. set dirs [list $srcdir] if {[installtest_p]} { # Use the installed . lappend dirs $env(SYSTEMTAP_INCLUDES) } else { # Find in the source tree. lappend dirs $srcdir/../includes # The uninstalled, configured sdt-config.h has to be found here. lappend dirs ../includes/sys } set flags "" foreach dir $dirs { set flags "$flags additional_flags=-isystem${dir}" } return $flags } proc stripped_p { EXE } { if { [catch {eval exec "file $EXE | grep -q \"not stripped\""} dummy] } { return 1 } return 0 } systemtap-2.3/testsuite/parseko/000077500000000000000000000000001217430427200171065ustar00rootroot00000000000000systemtap-2.3/testsuite/parseko/array01.stp000077500000000000000000000000611217430427200211150ustar00rootroot00000000000000#! stap -p1 # array size must be >0 global a[0] systemtap-2.3/testsuite/parseko/array02.stp000077500000000000000000000001221217430427200211140ustar00rootroot00000000000000#! stap -p1 # array size must have a reasonable upper limit global a[1000000000] systemtap-2.3/testsuite/parseko/array03.stp000077500000000000000000000001221217430427200211150ustar00rootroot00000000000000#! stap -p1 # arrays can't be initialized with a scalar number global a[10] = 42 systemtap-2.3/testsuite/parseko/array04.stp000077500000000000000000000001301217430427200211150ustar00rootroot00000000000000#! stap -p1 # arrays can't be initialized with a scalar string global a[10] = "foobar" systemtap-2.3/testsuite/parseko/at_operators.stp000077500000000000000000000002301217430427200223360ustar00rootroot00000000000000#! stap -p2 # this used to be allowed, but really shouldn't have been: probe @hellosailor = begin { } probe @hellosailor { print("Hello, Sailor!\n") } systemtap-2.3/testsuite/parseko/bad_tapset.stp000077500000000000000000000002231217430427200217440ustar00rootroot00000000000000#!/bin/sh # PR11405: with -W, bad tapsets should still be an error TAPSET=`dirname $0`/bad_tapset/ stap $@ -p1 -e 'probe begin {}' -I $TAPSET -W systemtap-2.3/testsuite/parseko/bad_tapset/000077500000000000000000000000001217430427200212145ustar00rootroot00000000000000systemtap-2.3/testsuite/parseko/bad_tapset/foo.stp000066400000000000000000000001161217430427200225250ustar00rootroot00000000000000# this is an intentional syntax error for testing PR11405 probe foo = .bar {} systemtap-2.3/testsuite/parseko/cmdline02.stp000077500000000000000000000003531217430427200214170ustar00rootroot00000000000000#!/bin/sh # -sNUM Use NUM megabyte buffers for kernel-to-user data transfer. On a # multiprocessor in bulk mode, this is a per-processor amount. # # NUM must be between 1 and 64 stap $@ -p1 -s 0 -e 'probe begin { exit() }' systemtap-2.3/testsuite/parseko/cmdline03.stp000077500000000000000000000003101217430427200214110ustar00rootroot00000000000000#!/bin/sh # -p NUM Stop after pass NUM. The passes are numbered 1-5: parse, elabo- # rate, translate, compile, run. # # NUM must be between 1 and 5 stap $@ -p0 -e 'probe begin { exit() }' systemtap-2.3/testsuite/parseko/cmdline04.stp000077500000000000000000000002031217430427200214130ustar00rootroot00000000000000#!/bin/sh # multiple '-e' (script) options cannot be specified stap $@ -p1 -e 'probe begin { exit() }' -e 'probe end { exit() }' systemtap-2.3/testsuite/parseko/cmdline06.stp000077500000000000000000000002031217430427200214150ustar00rootroot00000000000000#!/bin/sh # Bad TMPDIR environment variable should cause exit TMPDIR=/dev/null/BADTMPDIR stap $@ -p1 -e 'probe begin { exit() }' systemtap-2.3/testsuite/parseko/cmdline07.stp000077500000000000000000000002171217430427200214230ustar00rootroot00000000000000#!/bin/sh # A module name must be specified when using '-m' - the module name # can't be empty stap $@ -p1 -m "" -e 'probe begin { exit() }' systemtap-2.3/testsuite/parseko/cmdline08.stp000077500000000000000000000001651217430427200214260ustar00rootroot00000000000000#!/bin/sh # A module name can only be composed of chars [_a-zA-Z0-9] stap $@ -p1 -m x^y -e 'probe begin { exit() }' systemtap-2.3/testsuite/parseko/cmdline09.stp000077500000000000000000000003761217430427200214330ustar00rootroot00000000000000#!/bin/sh # A module name can't have more than 60 chars (stap truncates the # module name before creating the kernel module but staprun can't # truncate an existing module name). staprun stap_123456789012345678901234567890123456789012345678901234567890 systemtap-2.3/testsuite/parseko/cmdline10.stp000077500000000000000000000005431217430427200214170ustar00rootroot00000000000000#!/bin/sh # # -b buffer size The systemtap module specifies a buffer size. # Setting one here will override that value. The # value should be an integer between 1 and 64 # which be assumed to be the buffer size in MB. # That value will be per-cpu in bulk mode. staprun -b 0 fake_module systemtap-2.3/testsuite/parseko/cmdline11.stp000077500000000000000000000003111217430427200214110ustar00rootroot00000000000000#!/bin/sh # options '-L' and '-A' are mutually exclusive # # -L Load module and start probes, then detach. # -A Attach to loaded systemtap module. staprun -L -A fake_module systemtap-2.3/testsuite/parseko/cmdline12.stp000077500000000000000000000010351217430427200214160ustar00rootroot00000000000000#!/bin/sh # options '-A' and '-b size' are mutually exclusive (since the buffer # size option only has an effect when the module is inserted) # # -A Attach to loaded systemtap module. # -b buffer size The systemtap module specifies a buffer size. # Setting one here will override that value. The # value should be an integer between 1 and 64 # which be assumed to be the buffer size in MB. # That value will be per-cpu in bulk mode. staprun -A -b 2 fake_module systemtap-2.3/testsuite/parseko/cmdline13.stp000077500000000000000000000005121217430427200214160ustar00rootroot00000000000000#!/bin/sh # options '-A' and '-c cmd' are mutually exclusive # # -A Attach to loaded systemtap module. # -c cmd Command 'cmd' will be run and staprun will # exit when it does. The '_stp_target' variable # will contain the pid for the command. staprun -A -c bash fake_module systemtap-2.3/testsuite/parseko/cmdline14.stp000077500000000000000000000003151217430427200214200ustar00rootroot00000000000000#!/bin/sh # options '-A' and '-x pid' are mutually exclusive # # -A Attach to loaded systemtap module. # -x pid Sets the '_stp_target' variable to pid. staprun -A -x 100 fake_module systemtap-2.3/testsuite/parseko/cmdline15.stp000077500000000000000000000003421217430427200214210ustar00rootroot00000000000000#!/bin/sh # options '-c cmd' and '-x pid' are mutually exclusive # # -c CMD start the probes, run CMD, and exit when it finishes # -x PID sets target() to PID stap $@ -p1 -c /bin/ls -x 100 -e 'probe begin { exit() }' systemtap-2.3/testsuite/parseko/cmdline16.stp000077500000000000000000000005321217430427200214230ustar00rootroot00000000000000#!/bin/sh # options '-c cmd' and '-x pid' are mutually exclusive # # -c cmd Command 'cmd' will be run and staprun will # exit when it does. The '_stp_target' variable # will contain the pid for the command. # -x pid Sets the '_stp_target' variable to pid. staprun -c /bin/ls -x 100 fake_module systemtap-2.3/testsuite/parseko/cmdline17.stp000077500000000000000000000003221217430427200214210ustar00rootroot00000000000000#!/bin/sh # options '-D' and '-L' are mutually exclusive # #-D Run in background. This requires '-o' option. #-L Load module and start probes, then detach. staprun -L -D fake_module systemtap-2.3/testsuite/parseko/cmdline18.stp000077500000000000000000000005351217430427200214300ustar00rootroot00000000000000#!/bin/sh # options '-D' and '-d' are mutually exclusive # #-D Run in background. This requires '-o' option. #-d Delete a module. Only detached or unused modules # the user has permission to access will be deleted. Use "*" # (quoted) to delete all unused modules. staprun -d -D fake_module systemtap-2.3/testsuite/parseko/cmdline19.stp000077500000000000000000000005251217430427200214300ustar00rootroot00000000000000#!/bin/sh # options '-D' and '-c cmd' are mutually exclusive # #-D Run in background. This requires '-o' option. #-c cmd Command 'cmd' will be run and staprun will # exit when it does. The '_stp_target' variable # will contain the pid for the command. staprun -c /bin/ls -D fake_module systemtap-2.3/testsuite/parseko/cmdline20.stp000077500000000000000000000003711217430427200214170ustar00rootroot00000000000000#!/bin/sh # You have to specify ouput FILE with '-D' option # #-D Run in background. This requires '-o' option. #-o FILE Send output to FILE. This supports strftime(3) # formats for FILE. staprun -D fake_module systemtap-2.3/testsuite/parseko/cmdline21.stp000077500000000000000000000011361217430427200214200ustar00rootroot00000000000000#!/bin/sh # You have to specify ouput FILE with '-S' option # #-S size[,N] Switches output file to next file when the size # of file reaches the specified size. The value # should be an integer greater than 1 which is # assumed to be the maximum file size in MB. # When the number of output files reaches N, it # switches to the first output file. You can omit # the second argument. #-o FILE Send output to FILE. This supports strftime(3) # formats for FILE. staprun -S 1,1 fake_module systemtap-2.3/testsuite/parseko/cmdline22.stp000077500000000000000000000005431217430427200214220ustar00rootroot00000000000000#!/bin/sh # Test a TMPDIR that is technically legal, but has "weird" characters. # Anything that would trip up a shell or makefile is bad, including spaces. TMPDIR="/tmp/stap tmp here" export TMPDIR mkdir "$TMPDIR" || exit 0 # "success" signals a problem for parseko stap $@ -p1 -e 'probe begin { exit() }' RC=$? rmdir "$TMPDIR" || exit 0 exit $RC systemtap-2.3/testsuite/parseko/cmdlinearg01.stp000077500000000000000000000001351217430427200221060ustar00rootroot00000000000000#! stap -p1 # bad command line argument number - must start at 1 probe begin { arg = $0 } systemtap-2.3/testsuite/parseko/cmdlinearg02.stp000077500000000000000000000001331217430427200221050ustar00rootroot00000000000000#! stap -p1 # bad command line argument number - bad number probe begin { arg = $12A3 } systemtap-2.3/testsuite/parseko/conditional.stp000077500000000000000000000001031217430427200221360ustar00rootroot00000000000000#! stap -p2 probe begin { %( 1 == 0 %? print(1) %? print(2) %) } systemtap-2.3/testsuite/parseko/deprecated01.stp000077500000000000000000000002471217430427200221050ustar00rootroot00000000000000#!/bin/sh # We shouldn't be able to parse a deprecated function stap $@ --check-version --compatible=1.4 -W -p2 -e 'probe nd_syscall.accept { println(flag_str++) }' systemtap-2.3/testsuite/parseko/eight.stp000077500000000000000000000000651217430427200207420ustar00rootroot00000000000000#! stap -p1 probe foo { foreach ([a, b, c] in) ; } systemtap-2.3/testsuite/parseko/eighteen.stp000077500000000000000000000000451217430427200214300ustar00rootroot00000000000000#! stap -p1 # bad global global 123 systemtap-2.3/testsuite/parseko/eleven.stp000077500000000000000000000000631217430427200211160ustar00rootroot00000000000000#! stap -p1 function foo () {} function foo () {} systemtap-2.3/testsuite/parseko/fifteen.stp000077500000000000000000000000711217430427200212570ustar00rootroot00000000000000#! stap -p1 probe begin { foreach ([x+,y-] in a) {} } systemtap-2.3/testsuite/parseko/fiftyone.stp000077500000000000000000000003701217430427200214640ustar00rootroot00000000000000#! stap -p2 // invalid regex operator usage probe begin { a = "this is regex" b = "but this is not match" =~ a // rhs must be literal regex c = 2 b = "but this is totally bonkers!" =~ c printf ("%s %d %d", a, b, c) } systemtap-2.3/testsuite/parseko/five.stp000077500000000000000000000001471217430427200205740ustar00rootroot00000000000000#! stap -p1 probe foo( { } probe bar() { } probe baz.(1) { } probe faz(2), { } probe kaz,goo. { } systemtap-2.3/testsuite/parseko/foreachstmt01.stp000077500000000000000000000002731217430427200223230ustar00rootroot00000000000000#! stap -p1 # missing parens after foreach keyword global array function decl() { array[0] = 1 foreach key in array printf("key %d, value %d\n", key, array[key]) } systemtap-2.3/testsuite/parseko/foreachstmt02.stp000077500000000000000000000003161217430427200223220ustar00rootroot00000000000000#! stap -p1 # no identifier after opening paren after foreach keyword global array function decl() { array[0] = 1 foreach (* in array) printf("key %d, value %d\n", key, array[key]) } systemtap-2.3/testsuite/parseko/foreachstmt03.stp000077500000000000000000000003331217430427200223220ustar00rootroot00000000000000#! stap -p1 # missing closing bracket after opening paren after foreach keyword global array function decl() { array[0] = 1 foreach ([key in array) printf("key %d, value %d\n", key, array[key]) } systemtap-2.3/testsuite/parseko/foreachstmt04.stp000077500000000000000000000003101217430427200223160ustar00rootroot00000000000000#! stap -p1 # multiple sort directives in foreach statement global array function decl() { array[0] = 1 foreach (key- in array-) printf("key %d, value %d\n", key, array[key]) } systemtap-2.3/testsuite/parseko/foreachstmt05.stp000077500000000000000000000003031217430427200223210ustar00rootroot00000000000000#! stap -p1 # missing closing paren after foreach keyword global array function decl() { array[0] = 1 foreach (key in array printf("key %d, value %d\n", key, array[key]) } systemtap-2.3/testsuite/parseko/foreachstmt06.stp000077500000000000000000000002751217430427200223320ustar00rootroot00000000000000#! stap -p1 # missing expression after limit global array function decl() { array[0] = 1 foreach (key in array limit) printf("key %d, value %d\n", key, array[key]) } systemtap-2.3/testsuite/parseko/foreachstmt07.stp000077500000000000000000000003071217430427200223270ustar00rootroot00000000000000#! stap -p1 # missing limit keyword but with an expression global array function decl() { array[0] = 1 foreach (key in array 5) printf("key %d, value %d\n", key, array[key]) } systemtap-2.3/testsuite/parseko/foreachstmt08.stp000077500000000000000000000001101217430427200223200ustar00rootroot00000000000000#! stap -p1 function decl() { foreach (key in array @foobar +) ; } systemtap-2.3/testsuite/parseko/foreachstmt09.stp000077500000000000000000000001031217430427200223230ustar00rootroot00000000000000#! stap -p1 function decl() { foreach (key in array @sum) ; } systemtap-2.3/testsuite/parseko/forstmt01.stp000077500000000000000000000001441217430427200214770ustar00rootroot00000000000000#! stap -p1 # no '(' following 'for' function decl() { for i = 0; i < 10; i++ j = i } systemtap-2.3/testsuite/parseko/forstmt02.stp000077500000000000000000000001461217430427200215020ustar00rootroot00000000000000#! stap -p1 # no ';' following for initialization function decl() { for (i = 0) j = i } systemtap-2.3/testsuite/parseko/forstmt03.stp000077500000000000000000000001501217430427200214760ustar00rootroot00000000000000#! stap -p1 # no ';' following for condition function decl() { for (i = 0; i < 5) j = i } systemtap-2.3/testsuite/parseko/forstmt04.stp000077500000000000000000000001471217430427200215050ustar00rootroot00000000000000#! stap -p1 # 'for' missing closing ')' function decl() { for (i = 0; i < 5; i++ j = i } systemtap-2.3/testsuite/parseko/four.stp000077500000000000000000000000661217430427200206160ustar00rootroot00000000000000#! stap -p1 probe foo { somethingawful->foo = 1; } systemtap-2.3/testsuite/parseko/fourteen.stp000077500000000000000000000001201217430427200214610ustar00rootroot00000000000000#! stap -p1 function zoo () %{ /* invalid embedded code */ %} probe begin { } systemtap-2.3/testsuite/parseko/functiondecl01.stp000077500000000000000000000001321217430427200224530ustar00rootroot00000000000000#! stap -p1 # bad function declaration function 123 (arg1, arg2) { return arg1 + arg2 } systemtap-2.3/testsuite/parseko/functiondecl02.stp000077500000000000000000000001371217430427200224610ustar00rootroot00000000000000#! stap -p1 # bad function declaration function function (arg1, arg2) { return arg1 + arg2 } systemtap-2.3/testsuite/parseko/functiondecl03.stp000077500000000000000000000002331217430427200224570ustar00rootroot00000000000000#! stap -p1 # bad function declaration - only "string" or "long" are valid # function return types function decl:foo (arg1, arg2) { return arg1 + arg2 } systemtap-2.3/testsuite/parseko/functiondecl04.stp000077500000000000000000000001311217430427200224550ustar00rootroot00000000000000#! stap -p1 # bad function declaration - no "()" after name function decl { return 0 } systemtap-2.3/testsuite/parseko/functiondecl05.stp000077500000000000000000000001341217430427200224610ustar00rootroot00000000000000#! stap -p1 # bad function declaration - bad parameter list function decl(*) { return 0 } systemtap-2.3/testsuite/parseko/functiondecl06.stp000077500000000000000000000001371217430427200224650ustar00rootroot00000000000000#! stap -p1 # bad function declaration - bad argument type function decl(a:foo) { return 0 } systemtap-2.3/testsuite/parseko/functiondecl07.stp000077500000000000000000000001511217430427200224620ustar00rootroot00000000000000#! stap -p1 # bad function declaration - needs a ',' between arguments function decl(a b) { return 0 } systemtap-2.3/testsuite/parseko/ifstmt01.stp000077500000000000000000000001231217430427200213040ustar00rootroot00000000000000#! stap -p1 # missing parens after if statment function decl() { if a == b } systemtap-2.3/testsuite/parseko/ifstmt02.stp000077500000000000000000000001641217430427200213120ustar00rootroot00000000000000#! stap -p1 # missing closing paren in if statment function decl() { if (a == b printf("in decl\n") } systemtap-2.3/testsuite/parseko/macros01.stp000077500000000000000000000000251217430427200212630ustar00rootroot00000000000000#! stap -p2 @define systemtap-2.3/testsuite/parseko/macros02.stp000077500000000000000000000000311217430427200212610ustar00rootroot00000000000000#! stap -p2 @define foo systemtap-2.3/testsuite/parseko/macros03.stp000077500000000000000000000000341217430427200212650ustar00rootroot00000000000000#! stap -p2 @define foo %( systemtap-2.3/testsuite/parseko/macros04.stp000077500000000000000000000000431217430427200212660ustar00rootroot00000000000000#! stap -p2 @define foo %( cheese systemtap-2.3/testsuite/parseko/macros05.stp000077500000000000000000000001441217430427200212710ustar00rootroot00000000000000#! stap -p2 # parsing fails due to no code being left after preprocessing @define foo %( cheese %) systemtap-2.3/testsuite/parseko/macros06.stp000077500000000000000000000001541217430427200212730ustar00rootroot00000000000000#! stap -p2 # incorrect number of parameters @define foo(a) %( probe @a %) @foo { print ("Hello World!") } systemtap-2.3/testsuite/parseko/macros07.stp000077500000000000000000000001671217430427200213000ustar00rootroot00000000000000#! stap -p2 # incorrect number of parameters @define foo(a) %( probe @a %) @foo(begin,end) { print ("Hello World!") } systemtap-2.3/testsuite/parseko/macros08.stp000077500000000000000000000001611217430427200212730ustar00rootroot00000000000000#! stap -p2 # attempt to redefine '@define' @define define %( cheese %) probe begin { print ("Hello, World!") } systemtap-2.3/testsuite/parseko/macros09.stp000077500000000000000000000001421217430427200212730ustar00rootroot00000000000000#! stap -p2 @define bar(b) %( @b %) @define foo(a) %( @bar(@a %) probe @foo(begin) { print(42) } systemtap-2.3/testsuite/parseko/macros10.stp000077500000000000000000000001421217430427200212630ustar00rootroot00000000000000#! stap -p2 @define bar(b) %( @b %) @define foo(a) %( @bar(@a) %) probe @foo(begin { print(42) } systemtap-2.3/testsuite/parseko/macros11.stp000077500000000000000000000002361217430427200212700ustar00rootroot00000000000000#! stap -p2 # error message should neatly trace through the calls: @define bar(b) %( @bluff %) @define foo(a) %( @bar(@a) %) probe @foo(begin) { print(42) } systemtap-2.3/testsuite/parseko/maxactive01.stp000077500000000000000000000001121217430427200217550ustar00rootroot00000000000000#! stap -p2 # maxactive with "begin" probe probe begin.maxactive(3) { } systemtap-2.3/testsuite/parseko/maxactive02.stp000077500000000000000000000001661217430427200217670ustar00rootroot00000000000000#! stap -p1 # maxactive with a non-number argument global N = 2 probe kernel.function("*").return.maxactive(N) { } systemtap-2.3/testsuite/parseko/maxactive03.stp000077500000000000000000000002131217430427200217610ustar00rootroot00000000000000#! stap -p1 # maxactive with a non-number argument function four() { return 4 } probe kernel.function("*").return.maxactive(four()) { } systemtap-2.3/testsuite/parseko/maxactive04.stp000077500000000000000000000001641217430427200217670ustar00rootroot00000000000000#! stap -p1 # maxactive with a numeric expression argument probe kernel.function("*").return.maxactive(3 + 2) { } systemtap-2.3/testsuite/parseko/nine.stp000077500000000000000000000000421217430427200205660ustar00rootroot00000000000000#! stap -p1 probe foo { /*/ 0 } systemtap-2.3/testsuite/parseko/nineteen.stp000077500000000000000000000001101217430427200214360ustar00rootroot00000000000000#! stap -p1 # 'next' in function context function decl() { next } systemtap-2.3/testsuite/parseko/one.stp000077500000000000000000000000321217430427200204150ustar00rootroot00000000000000#! stap -p1 "not a probe" systemtap-2.3/testsuite/parseko/perf01.stp000077500000000000000000000002351217430427200207360ustar00rootroot00000000000000#! stap -p2 # @perf not supported global x probe perf.hw.cpu_cycles.process("/bin/ed").counter("a") {} probe process("/bin/ed").begin { x = @perf("a") } systemtap-2.3/testsuite/parseko/perf02.stp000077500000000000000000000002371217430427200207410ustar00rootroot00000000000000#! stap -p2 # no counter id global x probe perf.hw.cpu_cycles.process("/bin/ls").counter("b") {} probe process("/bin/ed").function("main") { y = @perf("") } systemtap-2.3/testsuite/parseko/perf03.stp000077500000000000000000000001751217430427200207430ustar00rootroot00000000000000#! stap -p2 # missing perf probe counter component name global x probe perf.hw.cpu_cycles.process("/bin/ls").counter("") {} systemtap-2.3/testsuite/parseko/perf04.stp000077500000000000000000000002371217430427200207430ustar00rootroot00000000000000#! stap -p2 # bad counter id global x probe perf.hw.cpu_cycles.process("/bin/ls").counter("b") {} probe process("/bin/ed").function("main") { y = @perf(1) } systemtap-2.3/testsuite/parseko/preprocess01.stp000077500000000000000000000001351217430427200221660ustar00rootroot00000000000000#! stap -p1 # bad kernel version - not a string %( kernel_v <= 2.6 %? probe begin { } %) systemtap-2.3/testsuite/parseko/preprocess02.stp000077500000000000000000000001241217430427200221650ustar00rootroot00000000000000#! stap -p1 # bad comparison operator %( kernel_v * "2.6" %? probe begin { } %) systemtap-2.3/testsuite/parseko/preprocess03.stp000077500000000000000000000001171217430427200221700ustar00rootroot00000000000000#! stap -p1 # bad arch - not a string %( arch == foo %? probe begin { } %) systemtap-2.3/testsuite/parseko/preprocess04.stp000077500000000000000000000001511217430427200221670ustar00rootroot00000000000000#! stap -p1 # bad arch comparison operator - not '==' or '!=' %( arch >= "foo" %? probe begin { } %) systemtap-2.3/testsuite/parseko/preprocess05.stp000077500000000000000000000002001217430427200221630ustar00rootroot00000000000000#! stap -p1 # bad preprocess condition start - not "arch", "kernel_v", or "kernel_vr" %( foo == "2.6" %? probe begin { } %) systemtap-2.3/testsuite/parseko/preprocess06.stp000077500000000000000000000000531217430427200221720ustar00rootroot00000000000000#! stap -p1 # no "%?" %( arch == "2.6" %) systemtap-2.3/testsuite/parseko/preprocess07.stp000077500000000000000000000000601217430427200221710ustar00rootroot00000000000000#! stap -p1 # incomplete condition %( arch == systemtap-2.3/testsuite/parseko/preprocess08.stp000077500000000000000000000000751217430427200222000ustar00rootroot00000000000000#! stap -p1 # premature EOF during THEN tokens %( 0 == 0 %? systemtap-2.3/testsuite/parseko/preprocess08b.stp000077500000000000000000000001001217430427200223270ustar00rootroot00000000000000#! stap -p1 # premature EOF during ELSE tokens %( 0 == 1 %? %: systemtap-2.3/testsuite/parseko/preprocess09.stp000077500000000000000000000001131217430427200221720ustar00rootroot00000000000000#! stap -p1 # missing "else" token %( arch == "2.6" %? probe begin { } %: systemtap-2.3/testsuite/parseko/preprocess10.stp000077500000000000000000000001371217430427200221700ustar00rootroot00000000000000#! stap -p1 # expected number as right value in comparison %( $# != "2" %? probe begin { } %) systemtap-2.3/testsuite/parseko/preprocess11.stp000077500000000000000000000001351217430427200221670ustar00rootroot00000000000000#! stap -p1 # expected string as right value in comparison %( @# != 2 %? probe begin { } %) systemtap-2.3/testsuite/parseko/preprocess12.stp000077500000000000000000000002311217430427200221650ustar00rootroot00000000000000#! stap -p1 # command line argument index invalid or out of range # (try to access to an unavailable argument) %( $# < 2 %? probe begin { print @1 } %) systemtap-2.3/testsuite/parseko/preprocess13.stp000077500000000000000000000000621217430427200221700ustar00rootroot00000000000000#! /bin/sh # recursive stap $@ -p1 -e '$1' '$1' systemtap-2.3/testsuite/parseko/preprocess14.stp000077500000000000000000000001311217430427200221660ustar00rootroot00000000000000#! stap -p1 # incomplete compound condition %( arch == "2.6" && %? probe begin() { } %) systemtap-2.3/testsuite/parseko/preprocess15.stp000077500000000000000000000001441217430427200221730ustar00rootroot00000000000000#! stap -p1 # bad compound condition %( arch == "2.6" && || arch == "2.66" %? probe begin() { } %) systemtap-2.3/testsuite/parseko/preprocess16.stp000077500000000000000000000001411217430427200221710ustar00rootroot00000000000000#! /bin/sh # recursive after the first token (PR11195) stap $@ -p1 -e 'probe begin {$1}' 'x $1' systemtap-2.3/testsuite/parseko/preprocess17.stp000077500000000000000000000001421217430427200221730ustar00rootroot00000000000000#! /bin/sh stap $@ --compatible=1.0 -p1 -e 'global %( systemtap_v >= "1.2" %? PASS %: "FAIL" %)' systemtap-2.3/testsuite/parseko/preprocess18.stp000077500000000000000000000001251217430427200221750ustar00rootroot00000000000000#! stap -p1 # bad runtime - not a string %( runtime == foo %? probe begin { } %) systemtap-2.3/testsuite/parseko/preprocess19.stp000077500000000000000000000001571217430427200222030ustar00rootroot00000000000000#! stap -p1 # bad runtime comparison operator - not '==' or '!=' %( runtime >= "foo" %? probe begin { } %) systemtap-2.3/testsuite/parseko/printd01.stp000077500000000000000000000001241217430427200212770ustar00rootroot00000000000000#! stap -p1 probe begin { // missing the delimiter printd(1, 2, 3, 4, 5) } systemtap-2.3/testsuite/parseko/printd02.stp000077500000000000000000000001261217430427200213020ustar00rootroot00000000000000#! stap -p1 probe begin { // missing the delimiter printdln(1, 2, 3, 4, 5) } systemtap-2.3/testsuite/parseko/printd03.stp000077500000000000000000000001311217430427200212770ustar00rootroot00000000000000#! stap -p1 probe begin { // need more than one value to join printd(", ", 1) } systemtap-2.3/testsuite/parseko/printd04.stp000077500000000000000000000001331217430427200213020ustar00rootroot00000000000000#! stap -p1 probe begin { // need more than one value to join printdln(", ", 1) } systemtap-2.3/testsuite/parseko/probepoint01.stp000077500000000000000000000000551217430427200221630ustar00rootroot00000000000000#! stap -p1 # bad probe point probe foo bar systemtap-2.3/testsuite/parseko/probepoint02.stp000077500000000000000000000000541217430427200221630ustar00rootroot00000000000000#! stap -p1 # bad probe point probe foo(5( systemtap-2.3/testsuite/parseko/probepoint03.stp000077500000000000000000000000571217430427200221670ustar00rootroot00000000000000#! stap -p1 # bad probe point probe foo(5)(6) systemtap-2.3/testsuite/parseko/probepoint04.stp000077500000000000000000000000641217430427200221660ustar00rootroot00000000000000#! stap -p1 # bad probe point probe foo(5) if (1)? systemtap-2.3/testsuite/parseko/probepoint05.stp000077500000000000000000000000671217430427200221720ustar00rootroot00000000000000#! stap -p1 # bad probe point probe foo(5) if (1)(10) systemtap-2.3/testsuite/parseko/probepoint06.stp000077500000000000000000000000631217430427200221670ustar00rootroot00000000000000#! stap -p1 # bad probe point probe if (1) foo(5) systemtap-2.3/testsuite/parseko/probepoint07.stp000077500000000000000000000000631217430427200221700ustar00rootroot00000000000000#! stap -p1 # bad probe point probe foo(5) if (1( systemtap-2.3/testsuite/parseko/probepoint08.stp000077500000000000000000000000571217430427200221740ustar00rootroot00000000000000#! stap -p1 # bad probe point probe foo(5) if systemtap-2.3/testsuite/parseko/probepoint09.stp000077500000000000000000000000711217430427200221710ustar00rootroot00000000000000#! stap -p1 # bad probe point probe foo(5) if(1) bar(2) systemtap-2.3/testsuite/parseko/procfs01.stp000077500000000000000000000000611217430427200212730ustar00rootroot00000000000000#! stap -p2 probe procfs.umask(0880).write {} systemtap-2.3/testsuite/parseko/procfs02.stp000077500000000000000000000000601217430427200212730ustar00rootroot00000000000000#! stap -p2 probe procfs.umask(0880).read {} systemtap-2.3/testsuite/parseko/procfs03.stp000077500000000000000000000002121217430427200212730ustar00rootroot00000000000000#! stap -p2 probe procfs("bar2").umask(0002).write { printf("The user wrote: %s", $value) } probe procfs("bar2").umask(0888).read {} systemtap-2.3/testsuite/parseko/regex_notlit.stp000077500000000000000000000004401217430427200223420ustar00rootroot00000000000000#! stap -p1 // invalid regex operator usage, currently should be rejected by parser probe begin { a = "this is regex" b = "but this is not match" =~ a // rhs must be literal regex c = 2 b = "but this is totally bonkers!" =~ c printf ("%s %d %d", a, b, c) } systemtap-2.3/testsuite/parseko/seven.stp000077500000000000000000000001151217430427200207560ustar00rootroot00000000000000#! stap -p1 probe foo { [a,] in b; [,c] in d; [] in e; a in e[2]; } systemtap-2.3/testsuite/parseko/seventeen.stp000077500000000000000000000000321217430427200216300ustar00rootroot00000000000000#! stap -p1 # empty file systemtap-2.3/testsuite/parseko/six.stp000077500000000000000000000002741217430427200204470ustar00rootroot00000000000000#! stap -p1 probe foo { a = -9999999999999999999999999; b = 0xzoopoo; c = 00011122233344455566677788; d = 07777777777777777777777777; e = 18446744073709551616; # ULLONG_MAX+1 } systemtap-2.3/testsuite/parseko/sixteen.stp000077500000000000000000000000211217430427200213110ustar00rootroot00000000000000#! stap -gp1 %{ systemtap-2.3/testsuite/parseko/ternarystmt01.stp000077500000000000000000000001321217430427200223720ustar00rootroot00000000000000#! stap -p1 # missing ':' in ternary statement function decl() { a = (a == 1) ? 0 } systemtap-2.3/testsuite/parseko/thirteen.stp000077500000000000000000000001341217430427200214610ustar00rootroot00000000000000#! stap -p2 %{ /* embedded code not permitted since -g not supplied */ %} probe begin { } systemtap-2.3/testsuite/parseko/three.stp000077500000000000000000000000521217430427200207450ustar00rootroot00000000000000#! stap -p1 probe foo { foreach (a) ; } systemtap-2.3/testsuite/parseko/twelve.stp000077500000000000000000000000431217430427200211440ustar00rootroot00000000000000#! stap -p1 global foo global foo systemtap-2.3/testsuite/parseko/twenty.stp000077500000000000000000000001051217430427200211670ustar00rootroot00000000000000#! stap -p1 # 'return' in probe context probe begin { return } systemtap-2.3/testsuite/parseko/twentyeight.stp000077500000000000000000000002631217430427200222150ustar00rootroot00000000000000#! stap -p1 probe begin { foo =~ /this is not the regex syntax fyi at least atm bbq/ // note that we would have a whole *bunch* of parseko tests to check if it was } systemtap-2.3/testsuite/parseko/twentyfive.stp000077500000000000000000000000311217430427200220370ustar00rootroot00000000000000#! stap -p1 global a,;b systemtap-2.3/testsuite/parseko/twentyfour.stp000077500000000000000000000000311217430427200220610ustar00rootroot00000000000000#! stap -p1 global a;,b systemtap-2.3/testsuite/parseko/twentyone.stp000077500000000000000000000001361217430427200216750ustar00rootroot00000000000000#! stap -p1 # bad stat operator probe begin { v <<< 1 printf("foo %d\n", @foo(v)) } systemtap-2.3/testsuite/parseko/twentyseven.stp000077500000000000000000000003121217430427200222300ustar00rootroot00000000000000#! /bin/sh # PR 14360 supersedes PR 11208, except with --compatible < 2.0 stap $@ -p2 --compatible=1.8 -e 'probe kernel.function ("sys_" /* this comment no longer prevents string gluing */ "open") {}' systemtap-2.3/testsuite/parseko/twentysix.stp000077500000000000000000000000661217430427200217210ustar00rootroot00000000000000#! stap -p1 # PR 5376 case 3 probe foo ? = begin { } systemtap-2.3/testsuite/parseko/twentythree.stp000077500000000000000000000000651217430427200222240ustar00rootroot00000000000000#! /bin/sh stap $@ -p1 $SYSTEMTAP_TAPSET/indent.stp systemtap-2.3/testsuite/parseko/twentytwo.stp000077500000000000000000000000641217430427200217250ustar00rootroot00000000000000#! stap -p1 # wildcard with space probe a * b { } systemtap-2.3/testsuite/parseko/two.stp000077500000000000000000000000411217430427200204450ustar00rootroot00000000000000#! stap -p1 probe foo { a + } systemtap-2.3/testsuite/parseko/utrace01.stp000077500000000000000000000001151217430427200212620ustar00rootroot00000000000000#! stap -p2 # process NAME must be a string probe process(/bin/cat).end { } systemtap-2.3/testsuite/parseko/whilestmt01.stp000077500000000000000000000001621217430427200220210ustar00rootroot00000000000000#! stap -p1 # missing parens after while statment function decl() { while 0 == 1 printf("here\n") } systemtap-2.3/testsuite/parseko/whilestmt02.stp000077500000000000000000000001721217430427200220230ustar00rootroot00000000000000#! stap -p1 # missing closing paren after while statment function decl() { while (0 == 1 printf("here\n") } systemtap-2.3/testsuite/parseok/000077500000000000000000000000001217430427200171065ustar00rootroot00000000000000systemtap-2.3/testsuite/parseok/all_tapsets.stp000077500000000000000000000001561217430427200221560ustar00rootroot00000000000000#!/bin/sh # PR11405: all the default tapsets should succeed even with -W stap $@ -p1 -e 'probe begin {}' -W systemtap-2.3/testsuite/parseok/bad_tapset.stp000077500000000000000000000002561217430427200217520ustar00rootroot00000000000000#!/bin/sh # PR11405: without -W, bad tapsets will be warned but shouldn't be an error TAPSET=`dirname $0`/../parseko/bad_tapset/ stap $@ -p1 -e 'probe begin {}' -I $TAPSET systemtap-2.3/testsuite/parseok/cmdline01.stp000077500000000000000000000001731217430427200214160ustar00rootroot00000000000000#! /bin/sh echo "output version" stap $@ -V if [ $? != 0 ]; then exit $? fi echo "output version and help" stap $@ -h systemtap-2.3/testsuite/parseok/cmdline02.stp000077500000000000000000000001471217430427200214200ustar00rootroot00000000000000#! /bin/sh # Make sure verbose ('-v') option is accepted. stap $@ -v -p1 -e 'probe begin { exit() }' systemtap-2.3/testsuite/parseok/deprecated01.stp000077500000000000000000000002311217430427200220760ustar00rootroot00000000000000#!/bin/sh # We should be able to parse this function stap $@ --check-version --compatible=1.5 -p2 -e 'probe nd_syscall.accept { println(flag_str++) }' systemtap-2.3/testsuite/parseok/eight.stp000077500000000000000000000003111217430427200207340ustar00rootroot00000000000000#! stap -p1 probe all { "1" in a1; ["1", 2] in a2; [a] in a3; [("1").("2"), "1"."2"] in a4; a = [akbar(("foo").("bar"))] in it_s_a_trap foreach ([a, b] in a4) { foreach ([c, d] in a2) ; } } systemtap-2.3/testsuite/parseok/eighteen.stp000077500000000000000000000001041217430427200214240ustar00rootroot00000000000000#! stap -p1 global c, a = 1 global b = "hello", d probe begin { } systemtap-2.3/testsuite/parseok/eleven.stp000077500000000000000000000013371217430427200211230ustar00rootroot00000000000000#! stap -p1 probe two { # all assignment operators a = b a <<< b a += b a -= b a *= b a /= b a %= b a <<= b a >>= b a &= b a ^= b a |= b # all ternary operators a ? b : c # all binary operators a || b a && b a | b a & b a ^ b a < b a > b a == b a != b a <= b a >= b a << b a >> b a . b a + b a - b a * b a / b a % b # all unary operators a ++ a -- -- a ++ a ~ a ! a ; # grammar glitch + a ; # grammar glitch - a # grammar glitch a % b ; -- a ; ++ a ; a ++ ; a -- ; # chained unary operators + + a ; + - a ; + ! a ; + ~ a ; - + a ; - - a ; - ! a ; - ~ a ; ! + a ; ! - a ; ! ! a ; ! ~ a ; ~ + a ; ~ - a ; ~ ! a ; ~ ~ a ; } systemtap-2.3/testsuite/parseok/end_string.stp000077500000000000000000000002561217430427200220000ustar00rootroot00000000000000#! stap -p1 probe begin { log(last_var_is_last_string); exit(); } // Parser used to barf when last token in a file was a string global last_var_is_last_string="HelloWorld" systemtap-2.3/testsuite/parseok/fifteen.stp000077500000000000000000000001741217430427200212630ustar00rootroot00000000000000#! stap -p1 /* the epilogue style alias definitions */ probe syscall.read += kernel.function("sys_read") { fildes = $fd } systemtap-2.3/testsuite/parseok/five.stp000077500000000000000000000015511217430427200205740ustar00rootroot00000000000000#! stap -p1 probe lkst("process_contextswitch") {} probe syscall("name").return {} probe syscall("*") {} probe kernel.function("wait_for_godot") {} probe kernel.function("name").line(10) {} probe kernel.source("mempool.c").line(5004) {} probe kernel.address(0xdeadbeef) {} probe kernel.module("driver.ko").function("name").return {} probe kernel.module("cpqarray.ko").jumptable("ida_fops") {} probe kernel.watch("datasymbol").write {} probe user("fche").inode("/bin/vi").function("refresh") {} probe user.inode("/lib/libc.so.6").function("malloc").return {} probe time.real.hz(500) {} probe time.virtual.jiffies(100) {} probe perfcounter("tlbmiss").count(4000) {} probe resource.freemembelow(50) {} # pages? probe begin {} probe something?, or?, nothing? {} probe something!, or, nothing!, and?, zoo {} probe something? if (ture), or, nothing! if (false), then* if (0) {} systemtap-2.3/testsuite/parseok/foreachstmt01.stp000077500000000000000000000002631217430427200223220ustar00rootroot00000000000000#! stap -p1 probe one { foreach ([x+,y] in a limit 5) ; n = 5 ; foreach ([x,y-] in a limit n) ; foreach ([x,y] in a+ limit n + 2) ; foreach ([x,y] in a+ limit ++n) ; } systemtap-2.3/testsuite/parseok/four.stp000077500000000000000000000003021217430427200206070ustar00rootroot00000000000000#! stap -p1 probe syscall ("foo").foo.bar , syscall ("bar"), syscall ("*").return { # no comment $a = /* comment */ a$a = /**/ a$a$ = 0; // more comment } /* empty comment lines */ /**/ # // systemtap-2.3/testsuite/parseok/fourteen.stp000077500000000000000000000014641217430427200214750ustar00rootroot00000000000000#! stap -p1 global %( kernel_v > "2.6" %? /* and */ %( kernel_vr != "2.9.77-2873NOTHING" %? /* and */ %( kernel_v <= "3.5" %? /* and */ %( kernel_vr == "2.3.5-2.43.54.2" %? "FAIL1" %: PASS %) %: %( kernel_vr == "3.6-1NOTHING" %? "FAIL2" %: PASS %) %) %: "FAIL3" %) %: "FAIL4" %) global %( arch == "i386" %? i386 %: %( arch == "powerpc" %? powerpc %: %( arch != "x86_64" %? other %: x86_64 %) %) %) global %( $# != 2 %? /* and */ %( @# < "1" %? /* and */ %( @# == "0" %? /* and */ %( $# >= 3 %? /* and */ %( $2 >= "12" %? $3 FAIL5 %: $2 FAIL6 %) #This line must not be evaluated %: PASS2 %) %: "FAIL7" %) %: "FAIL8" %) %: "FAIL9" %) global %( runtime == "kernel" %? kernel %: %( runtime == "dyninst" %? dyninst %: "FAIL10" %) %) systemtap-2.3/testsuite/parseok/kconfig.stp000077500000000000000000000001041217430427200212540ustar00rootroot00000000000000#! stap -p2 %( CONFIG_NO_SUCH_CONFIG == "" %? probe never {} %: %) systemtap-2.3/testsuite/parseok/macros01.stp000077500000000000000000000001161217430427200212640ustar00rootroot00000000000000#! stap -p2 @define foo %( cheese %) probe begin { print ("Hello, World!") } systemtap-2.3/testsuite/parseok/macros02.stp000077500000000000000000000001141217430427200212630ustar00rootroot00000000000000#! stap -p2 @define foo %( begin %) probe @foo { print ("Hello, World!") } systemtap-2.3/testsuite/parseok/macros03.stp000077500000000000000000000001141217430427200212640ustar00rootroot00000000000000#! stap -p2 @define foo %( probe %) @foo begin { print ("Hello, World!") } systemtap-2.3/testsuite/parseok/macros04.stp000077500000000000000000000001231217430427200212650ustar00rootroot00000000000000#! stap -p2 @define foo(a) %( probe @a %) @foo(begin) { print ("Hello, World!") } systemtap-2.3/testsuite/parseok/macros05.stp000077500000000000000000000003151217430427200212710ustar00rootroot00000000000000#! /bin/sh # test interaction between conditionals and macro expansion stap $@ -p2 - 1 2 3 4 5 <<'END' @define foo %( %( $# >= 5 %? @5 %: "" %) %) probe begin { printf("Hello, World %s!", @foo) } END systemtap-2.3/testsuite/parseok/macros06.stp000077500000000000000000000001431217430427200212710ustar00rootroot00000000000000#! stap -p2 @define bar(b) %( @b %) @define foo(a) %( @bar(@a) %) probe @foo(begin) { print(42) } systemtap-2.3/testsuite/parseok/macros07.stp000077500000000000000000000002111217430427200212660ustar00rootroot00000000000000#! stap -p2 # this should work, although the user gets a warning @define min(a) %( @a %) probe begin { print(@min("Hello, World!\n")) } systemtap-2.3/testsuite/parseok/macros08.stp000077500000000000000000000003131217430427200212720ustar00rootroot00000000000000#! /bin/sh # test interaction between conditionals and macro expansion stap $@ -p2 - 1 2 3 4 <<'END' @define foo %( %( $# >= 5 %? @5 %: "" %) %) probe begin { printf("Hello, World %s!", @foo) } END systemtap-2.3/testsuite/parseok/nine.stp000077500000000000000000000001551217430427200205730ustar00rootroot00000000000000#! stap -p1 probe one { if (a) if (b) d else e } probe two { a = b c = d _e = $f; _g = h_; ; } systemtap-2.3/testsuite/parseok/nineteen.stp000077500000000000000000000001221217430427200214410ustar00rootroot00000000000000#! /bin/sh stap $@ -p1 -e '$1 {log (@1.@2)}' 'probe foo' ' ' # <- control codes systemtap-2.3/testsuite/parseok/one.stp000077500000000000000000000000451217430427200204210ustar00rootroot00000000000000#! stap -p1 # test function k () { } systemtap-2.3/testsuite/parseok/preprocess-wildcard.stp000077500000000000000000000016351217430427200236220ustar00rootroot00000000000000#! stap -p1 # PR10025: make sure that probepoint wildcards work in # various levels of proprocessor expansion # ANATOMY: # probe ==> first token is read in non-wildcard context # ab, *b, a*b, a*, * ==> check valid wildcard placement # f(x* x*y *y) ==> must be operator '*', not wildcards # TRUE %( 1==1 %? probe ab, *b, a*b, a*, * { f(x* x*y *y) } %: --ERROR-- %) # TRUE, TRUE %( 1==1 %? %( 2==2 %? probe ab, *b, a*b, a*, * { f(x* x*y *y) } %: --ERROR-- %) %: --ERROR-- %) # TRUE, FALSE %( 1==1 %? %( 2!=2 %? --ERROR-- %: probe ab, *b, a*b, a*, * { f(x* x*y *y) } %) %: --ERROR-- %) # FALSE %( 1!=1 %? --ERROR-- %: probe ab, *b, a*b, a*, * { f(x* x*y *y) } %) # FALSE, TRUE %( 1!=1 %? --ERROR-- %: %( 2==2 %? probe ab, *b, a*b, a*, * { f(x* x*y *y) } %: --ERROR-- %) %) # FALSE, FALSE %( 1!=1 %? --ERROR-- %: %( 2!=2 %? --ERROR-- %: probe ab, *b, a*b, a*, * { f(x* x*y *y) } %) %) systemtap-2.3/testsuite/parseok/semko.stp000077500000000000000000000004721217430427200207620ustar00rootroot00000000000000#! /bin/sh # make sure that we can *parse* all semko test files, to ensure # that it is semantic (elaboration) checks that fail, not parse errors set -e for file in ${SRCDIR}/testsuite/semko/*.stp do if grep -q /bin/sh $file; then true # can't override stap options else stap $@ -p1 $file fi done systemtap-2.3/testsuite/parseok/seven.stp000077500000000000000000000010351217430427200207600ustar00rootroot00000000000000#! stap -p1 probe one { if (1) {} } probe two { if (2) {;} } probe three { if (3) ; } probe four { if (4) {} else ; } probe five { if (5) ; else {} } probe six { if (6) {} else {;} } probe seven { ; } probe eight { {} } probe nine { {;} } probe ten { a=1; } probe all { if (1) {} ; if (2) {;} ; if (3) ; ; if (4) {} else ; ; if (5) ; else {} ; if (6) {} else {;} ; ; ; {} ; {;} ; a=1 } systemtap-2.3/testsuite/parseok/seventeen.stp000077500000000000000000000002671217430427200216420ustar00rootroot00000000000000#! stap -p1 # Make sure you can use keywords in target symbol structure # references (Bugzilla 2193). probe kernel.function("add_timer_on") { printf("%x\n", $timer->function) } systemtap-2.3/testsuite/parseok/six.stp000077500000000000000000000003671217430427200204520ustar00rootroot00000000000000#! stap -p1 probe nothing { a = 1+01+0x1-1-01-0x1; long_max = 2147483647; ulong_max = 4294967295; long_min = -2147483647-1; llong_max = 9223372036854775807; ullong_max = 18446744073709551615; llong_min = -9223372036854775807-1; } systemtap-2.3/testsuite/parseok/sixteen.stp000077500000000000000000000001211217430427200213120ustar00rootroot00000000000000#! stap -p1 # complicated probe point wildcard probe abcX { } probe *abc* { } systemtap-2.3/testsuite/parseok/ten.stp000077500000000000000000000005301217430427200204250ustar00rootroot00000000000000#! stap -p1 probe two { for (;;) ; for (a=0;;) { a + 4; break } for (;a>0;) { a ^ 5; continue } for (;;a++) { a | 5 } for (a=0;a>0;) { a << 4 } for (;a>0;++a) { a >> 5 } for (a=0;;a--) { a & 5 * b } for (a=0; a<=4 && b>=5; --a) ; for (a=0; a==4 || b!=5; a++) { b = a } next while (99) ; while (99) { break continue } } systemtap-2.3/testsuite/parseok/thirteen.stp000077500000000000000000000001511217430427200214600ustar00rootroot00000000000000#! stap -p1 probe one { foreach ([x+,y] in a) ; foreach ([x,y-] in a) ; foreach ([x,y] in a+) ; } systemtap-2.3/testsuite/parseok/three.stp000077500000000000000000000001271217430427200207500ustar00rootroot00000000000000#! stap -p1 probe syscall ("foo") { $a = a$a = a$a$ = 0; str = "a" . $a . "b"; } systemtap-2.3/testsuite/parseok/twelve.stp000077500000000000000000000002131217430427200211430ustar00rootroot00000000000000#! /bin/sh stap -p1 -g $@ - <<'END' %{ /* hello world */ %} function foo:long (p1:string, p2:long, p3) %{ /* goodbye world */ %} END systemtap-2.3/testsuite/parseok/twenty.stp000077500000000000000000000006661217430427200212030ustar00rootroot00000000000000#! stap -p1 global %( kernel_v > "2.6" && kernel_vr != "2.9.77-2873NOTHING" && kernel_v <= "3.5" && kernel_vr == "2.3.5-2.43.54.2" %? "FAIL1" %: PASS %) global %( arch == "i386" || arch == "i686" || arch == "x86_64" %? x86 %: other %) global %( $# != 2 && @# < "1" && @# == "0" && $# >= 3 %? %( $2 >= "12" %? $3 FAIL2 %: $2 FAIL3 %) #This line must not be evaluated %: PASS2 %) global %( systemtap_v >= "1.2" %? PASS3 %: "FAIL" %) systemtap-2.3/testsuite/parseok/twentyone.stp000077500000000000000000000000571217430427200216770ustar00rootroot00000000000000#! stap -gp1 probe one { println(%{ 1 %}) } systemtap-2.3/testsuite/parseok/twentytwo.stp000077500000000000000000000002111217430427200217170ustar00rootroot00000000000000#! stap -p1 # PR 14360 supersedes PR 11208 probe kernel.function ("sys_" /* this comment no longer prevents string gluing */ "open") {} systemtap-2.3/testsuite/parseok/two.stp000077500000000000000000000002671217430427200204570ustar00rootroot00000000000000#! stap -p1 probe syscall (231) { array[idx] <<< value; if (gbl > 5) { gbl -- } else ; } function foo () { delete array[4]; return 0; } probe end { foo ("value", 4+8); } systemtap-2.3/testsuite/parseok/umask01.stp000077500000000000000000000001111217430427200211130ustar00rootroot00000000000000#! stap -p2 probe procfs("foo1").umask(0000).read { $value = "100\n" } systemtap-2.3/testsuite/parseok/umask02.stp000077500000000000000000000001111217430427200211140ustar00rootroot00000000000000#! stap -p2 probe procfs("foo2").umask(0004).read { $value = "100\n" } systemtap-2.3/testsuite/parseok/umask03.stp000077500000000000000000000001111217430427200211150ustar00rootroot00000000000000#! stap -p2 probe procfs("foo3").umask(0404).read { $value = "100\n" } systemtap-2.3/testsuite/parseok/umask04.stp000077500000000000000000000001371217430427200211260ustar00rootroot00000000000000#! stap -p2 probe procfs("foo4").umask(0002).write { printf("The user wrote: %s", $value) } systemtap-2.3/testsuite/parseok/umask05.stp000077500000000000000000000001361217430427200211260ustar00rootroot00000000000000#! stap -p2 probe procfs("foo5").umask(0222).write { printf("The user wrote, %s", $value) } systemtap-2.3/testsuite/parseok/umask06.stp000077500000000000000000000002311217430427200211230ustar00rootroot00000000000000#! stap -p2 probe procfs("foo").umask(0002).read { $value = "100\n" } probe procfs("foo").umask(0040).write { printf("The user wrote, %s", $value) } systemtap-2.3/testsuite/parseok/umask07.stp000077500000000000000000000002171217430427200211300ustar00rootroot00000000000000#! stap -p2 probe procfs("foo7").read { $value = "100\n" } probe procfs("foo7").umask(0040).write { printf("The user wrote, %s", $value) } systemtap-2.3/testsuite/parseok/unparser.stp000077500000000000000000000007771217430427200215130ustar00rootroot00000000000000#! /bin/sh set -e for dir in ${SRCDIR}/testsuite/parseok \ ${SRCDIR}/testsuite/semok \ ${SRCDIR}/testsuite/semko \ ${SRCDIR}/testsuite/transok \ ${SRCDIR}/testsuite/transko \ ${SRCDIR}/testsuite/buildok \ ${SRCDIR}/testsuite/buildko do for file in $dir/*.stp do if head -1 $file | grep -q stap then if head -1 $file | fgrep -q -- g # guru mode then guru=-g else guru= fi echo $file $guru stap $guru -p1 $file | stap $@ $guru -p1 - > /dev/null fi done done systemtap-2.3/testsuite/semko/000077500000000000000000000000001217430427200165605ustar00rootroot00000000000000systemtap-2.3/testsuite/semko/alias_suffixes01.stp000077500000000000000000000002521217430427200224600ustar00rootroot00000000000000#! stap -p2 # fails with a "probe point mismatch" error probe a.q.b = begin { } probe a.q.e = end { } probe b = a.q { } probe b.d { print("Hello, World!\n") end() } systemtap-2.3/testsuite/semko/alias_suffixes02.stp000077500000000000000000000002601217430427200224600ustar00rootroot00000000000000#! stap -p2 # fails with an "invalid suffix for probe" error probe a = kernel.function("open").return { } probe a = begin { } probe a.maxactive(10) { printf("%s\n", pn()) } systemtap-2.3/testsuite/semko/alias_suffixes03.stp000077500000000000000000000003211217430427200224570ustar00rootroot00000000000000#! stap -p2 # fails with an "invalid suffix for probe" error probe a = kernel.function("open").return { } probe a = begin { } probe b = a { } probe c = b { } probe c.maxactive(10) { printf("%s\n", pn()) } systemtap-2.3/testsuite/semko/alias_suffixes04.stp000077500000000000000000000001611217430427200224620ustar00rootroot00000000000000#! stap -p2 # fails with the usual mismatch error and list of alternatives probe kernel.nonexistentbananas { } systemtap-2.3/testsuite/semko/alias_suffixes05.stp000077500000000000000000000001421217430427200224620ustar00rootroot00000000000000#! stap -p2 # fails with a wildcard mismatch error probe syscall.open.return.maxactive(1).* { } systemtap-2.3/testsuite/semko/alias_suffixes06.stp000077500000000000000000000003561217430427200224720ustar00rootroot00000000000000#! stap -p2 # Test detection of indefinite recursion when suffixes are involved. # a.b.c --> q.c --> r.c.c -> a.b.c.c -> ... -> a.b.c.c.c.c.c.... probe r = a.b { } probe q.c = r.c.c { } probe a.b = q { } probe a.b.c { print("what?") } systemtap-2.3/testsuite/semko/alias_suffixes07.stp000077500000000000000000000002431217430427200224660ustar00rootroot00000000000000#! stap -p2 # fails with an "invalid suffix for probe" error probe a = kernel.function("open").return, begin { } probe a.maxactive(10) { printf("%s\n", pn()) } systemtap-2.3/testsuite/semko/alias_suffixes08.stp000077500000000000000000000005231217430427200224700ustar00rootroot00000000000000#! stap -p2 # Test detection of indefinite recursion when suffixes are involved. # a.b.c -> ... -> q.c -> r.c.c -> x.b.c.c -> ... -> x.b.c.c.c.c.c.... probe r = x.b { } probe q.c = r.c.c { } probe x.b = q { } probe ants = x.b { } probe sandwich = ants { } probe bronx = sandwich { } probe a.b = bronx { } probe a.b.c { print("what?") } systemtap-2.3/testsuite/semko/alias_suffixes09.stp000077500000000000000000000005361217430427200224750ustar00rootroot00000000000000#! stap -p2 # Test detection of indefinite recursion when suffixes are involved. # More involved example which has multiple expansion paths. probe q.whoosh = nonesistent { } probe cheese = makery { } probe bar = makery.whoosh { } probe foo = q?, cheese, bar { } probe makery = foo.whoosh { } probe a.b.c = makery { } probe a.b.c { print("what?") } systemtap-2.3/testsuite/semko/array01.stp000077500000000000000000000002151217430427200205700ustar00rootroot00000000000000#! stap -p2 # arrays can't be inferred as anything else global a[10] probe begin { printf("%d\n", @count(a)) # try to make 'a' a stat } systemtap-2.3/testsuite/semko/array02.stp000077500000000000000000000001341217430427200205710ustar00rootroot00000000000000#! stap -p2 # no local arrays allowed probe end { array[1,2] = 5 print (array[4,6]) } systemtap-2.3/testsuite/semko/badregex01.stp000077500000000000000000000007601217430427200212400ustar00rootroot00000000000000#! stap -p2 // invalid actual regexes probe begin { // TODOXXX write a series of tests where the script syntax is // valid, but the syntax of the regexen is invalid // this somewhat duplicates the 'compile fail' tests in the // raw-regex testsuite, so there's no need to be comprehensive here; // just test the ability of the regex infrastructure to pass // error messages to the systemtap reporter cleanly warn ("not yet implemented") exit() } systemtap-2.3/testsuite/semko/doubleglob.stp000077500000000000000000000000371217430427200214310ustar00rootroot00000000000000#! stap -p2 probe foo**bar {} systemtap-2.3/testsuite/semko/eight.stp000077500000000000000000000001351217430427200204120ustar00rootroot00000000000000#! stap -p2 global stats probe begin { stats <<< "string" # stats only collect numbers } systemtap-2.3/testsuite/semko/eighteen.stp000077500000000000000000000001261217430427200211020ustar00rootroot00000000000000#! stap -p2 probe kernel.function("schedule") { log ($no_such_variable_anywhere) } systemtap-2.3/testsuite/semko/eleven.stp000077500000000000000000000005241217430427200205720ustar00rootroot00000000000000#! stap -up2 global arr,rra global s,n probe begin { arr[0]="value" rra["key"]=0 } probe end { # confirm that typechecking works the same way for all array indexing if (k in arr) { s=k.""; i=arr[k]+0 } foreach (l in arr) { s=l.""; i=arr[l]+0 } if (m in rra) { i=m+1; s=rra[m]."" } foreach (n in rra) { i=n+0; s=rra[n]."" } } systemtap-2.3/testsuite/semko/entry01.stp000077500000000000000000000002501217430427200206120ustar00rootroot00000000000000#! stap -p2 global stat # dwarf probes can only use @entry in .return probe kernel.function("do_filp_open").call { stat <<< get_cycles() - @entry(get_cycles()) } systemtap-2.3/testsuite/semko/entry02.stp000077500000000000000000000002121217430427200206110ustar00rootroot00000000000000#! stap -p2 global stat # @entry is only valid in dwarf .return probes probe begin { stat <<< get_cycles() - @entry(get_cycles()) } systemtap-2.3/testsuite/semko/entry03.stp000077500000000000000000000002711217430427200206170ustar00rootroot00000000000000#! stap -p2 global stat # the type must agree between what was saved and how it's used probe kernel.function("do_filp_open").return { stat <<< get_cycles() - @entry(execname()) } systemtap-2.3/testsuite/semko/entry04.stp000077500000000000000000000002471217430427200206230ustar00rootroot00000000000000#! stap -p2 global stat # dwarfless probes can only use @entry in .return probe kprobe.function("do_filp_open") { stat <<< get_cycles() - @entry(get_cycles()) } systemtap-2.3/testsuite/semko/fifteen.stp000077500000000000000000000002071217430427200207320ustar00rootroot00000000000000#! stap -p2 global tangle probe begin { foreach (state in tangle) { state = tangle[state]++ } log("hello from systemtap") } systemtap-2.3/testsuite/semko/fifty.stp000077500000000000000000000010251217430427200204320ustar00rootroot00000000000000#! /bin/sh stap $@ -g -p2 -e ' # PR 13876 %{ #include #include #include #include #include %} function tcp_ts_get_info_state:long(sock:long) %{ struct sock *sk = (struct sock *)(long) STAP_ARG_sock; STAP_RETVALUE = (int64_t) kread(&(sk->sk_state)); CATCH_DEREF_FAULT(); %} probe tcp.sendmsg { printf("%s: TCP: Sending message. state is : %d , Flags %d. Size%d\n", execname(),tcp_ts_get_info_state($sk), $sk->sk_flags, size) } ' systemtap-2.3/testsuite/semko/five.stp000077500000000000000000000001401217430427200202370ustar00rootroot00000000000000#! stap -p2 function bar () { return 0 } probe begin { bar (1, 2) # arg count mismatch } systemtap-2.3/testsuite/semko/foreachstmt01.stp000077500000000000000000000003041217430427200217700ustar00rootroot00000000000000#! stap -p2 # limit keyword with string expression global array probe begin { array[0] = 1 foreach (key in array limit "hi") printf("key %d, value %d\n", key, array[key]) } systemtap-2.3/testsuite/semko/foreachstmt02.stp000077500000000000000000000004201217430427200217700ustar00rootroot00000000000000#! stap -p2 # limit keyword with function returning a string expression global array function str_ret_type() { return "hi" } probe begin { array[0] = 1 foreach (key in array limit str_ret_type()) printf("key %d, value %d\n", key, array[key]) } systemtap-2.3/testsuite/semko/foreachstmt03.stp000077500000000000000000000003251217430427200217750ustar00rootroot00000000000000#! stap -p2 # no value which is a statistic (b/c we don't have stat locals) global array probe begin { array[0] <<< 1 foreach (val = key in array) printf("key %d, value %d\n", key, @sum(val)) } systemtap-2.3/testsuite/semko/foreachstmt04.stp000077500000000000000000000001601217430427200217730ustar00rootroot00000000000000#! stap -p2 global array probe begin { array[0] = 1 foreach (key in array @sum +) printf("%d",key); } systemtap-2.3/testsuite/semko/forty.stp000077500000000000000000000001351217430427200204550ustar00rootroot00000000000000#! stap -p2 global x probe kernel.function("do_sys_open") if (x = 1) { } # bad side-effect systemtap-2.3/testsuite/semko/fortyeight.stp000077500000000000000000000001161217430427200214750ustar00rootroot00000000000000#! stap -Wp2 # PR 11075 global foo # evokes warning probe begin { exit() } systemtap-2.3/testsuite/semko/fortyfive.stp000077500000000000000000000001201217430427200213210ustar00rootroot00000000000000#! stap -p2 probe kernel.function("*@kernel/kprobes.c").call {} // blacklisted systemtap-2.3/testsuite/semko/fortyfour.stp000077500000000000000000000001001217430427200213410ustar00rootroot00000000000000#! stap -p2 probe foo = bar {} probe bar = foo {} probe foo {} systemtap-2.3/testsuite/semko/fortynine.stp000077500000000000000000000001001217430427200213170ustar00rootroot00000000000000#! stap -up2 probe begin { try {} catch (er) {println(er+2)} } systemtap-2.3/testsuite/semko/fortyone.stp000077500000000000000000000001161217430427200211560ustar00rootroot00000000000000#! stap -p2 probe kernel.function("vfs_read") if (x > 1) { } # not a global systemtap-2.3/testsuite/semko/fortyseven.stp000077500000000000000000000001331217430427200215140ustar00rootroot00000000000000#! stap -p2 # PR5049 probe kernel.function("*@ket.c") {} # must not match "....packet.c" systemtap-2.3/testsuite/semko/fortysix.stp000077500000000000000000000001341217430427200212000ustar00rootroot00000000000000#! stap -p2 probe begin { if ("foo" == NULL) log ("boo") } # check NULL as integral global systemtap-2.3/testsuite/semko/fortythree.stp000077500000000000000000000000671217430427200215110ustar00rootroot00000000000000#! stap -p2 probe foo.bar = foo.* { } probe foo.* { } systemtap-2.3/testsuite/semko/fortytwo.stp000077500000000000000000000005521217430427200212120ustar00rootroot00000000000000#! stap -p2 probe kernel.function("vfs_read") if (foo(2)) { } # must not call functions function foo(x) { return x } # NB: If this condition is relaxed, then this will have to be blocked: # global y function foo () { return y++ } # since global y is written-to # but this one would be fine: # function foo () { return y++ } # since y is written-to systemtap-2.3/testsuite/semko/four.stp000077500000000000000000000001601217430427200202630ustar00rootroot00000000000000#! stap -p2 global a, b # types unknown function bar () { # no return statement } probe begin { a = b; } systemtap-2.3/testsuite/semko/fourteen.stp000077500000000000000000000002361217430427200211430ustar00rootroot00000000000000#! stap -p2 global foo function bar() { a = foo["hello"]++ return 10 } probe begin { foreach (a in foo) { bar() } log("hello from systemtap") } systemtap-2.3/testsuite/semko/gurufunc.stp000077500000000000000000000001451217430427200211510ustar00rootroot00000000000000#! stap -up2 # set_kernel_long should only be allowed with -g probe begin { set_kernel_long(0, 0) } systemtap-2.3/testsuite/semko/inb_blacklisted.stp000077500000000000000000000002461217430427200224260ustar00rootroot00000000000000#! stap -p2 /* PR13112 (and PR13108) probing functions from blacklisted files shouldn't be possible. */ probe kernel.function("inb@*.h") { log("blacklisted") } systemtap-2.3/testsuite/semko/local_array.stp000077500000000000000000000001311217430427200215760ustar00rootroot00000000000000#! stap -p2 # missing global declaration probe begin { a[1] = 1 println(a[1]) } systemtap-2.3/testsuite/semko/local_stat.stp000077500000000000000000000001351217430427200214370ustar00rootroot00000000000000#! stap -p2 # missing global declaration probe begin { a <<< 1 println(@count(a)) } systemtap-2.3/testsuite/semko/logging-embedded.stp000077500000000000000000000002341217430427200224670ustar00rootroot00000000000000#! stap -p2 // build-test the guru-only function (note lack of -g above) probe begin { printk(0,"Zoink! The paper tape punch is burning chads!") } systemtap-2.3/testsuite/semko/map_wrap_bad.stp000077500000000000000000000000651217430427200217300ustar00rootroot00000000000000#! stap -p2 global foo% probe begin { foo = 2; } systemtap-2.3/testsuite/semko/maxactive01.stp000077500000000000000000000001341217430427200214330ustar00rootroot00000000000000#! stap -p2 # maxactive not on a return probe probe kernel.function("*").maxactive(3) { } systemtap-2.3/testsuite/semko/maxactive02.stp000077500000000000000000000001471217430427200214400ustar00rootroot00000000000000#! stap -p2 # maxactive with a string argument probe kernel.function("*").return.maxactive("hi") { } systemtap-2.3/testsuite/semko/maxactive03.stp000077500000000000000000000001211217430427200214310ustar00rootroot00000000000000#! stap -p2 # maxactive on a timer probe probe timer.sec(100).maxactive(3) { } systemtap-2.3/testsuite/semko/maxactive04.stp000077500000000000000000000001101217430427200214300ustar00rootroot00000000000000#! stap -p2 probe kernel.function("vfs_read").return.maxactive(-4) { } systemtap-2.3/testsuite/semko/maxactive05.stp000077500000000000000000000001161217430427200214370ustar00rootroot00000000000000#! stap -p2 probe kernel.function("vfs_read").return.maxactive(99999999) { } systemtap-2.3/testsuite/semko/netfilter01.stp000077500000000000000000000000411217430427200214430ustar00rootroot00000000000000#! stap -p2 probe netfilter { } systemtap-2.3/testsuite/semko/netfilter02.stp000077500000000000000000000000461217430427200214510ustar00rootroot00000000000000#! stap -p2 probe netfilter.hook { } systemtap-2.3/testsuite/semko/netfilter03.stp000077500000000000000000000001021217430427200214430ustar00rootroot00000000000000#! stap -p2 probe netfilter.hook("NF_INET_NONEXISTENT_HOOK") { } systemtap-2.3/testsuite/semko/netfilter04.stp000077500000000000000000000001261217430427200214520ustar00rootroot00000000000000#! stap -p2 probe netfilter.hook("NF_INET_PRE_ROUTING") { printf("%d\n", $verdict) } systemtap-2.3/testsuite/semko/netfilter05.stp000077500000000000000000000001541217430427200214540ustar00rootroot00000000000000#! stap -p2 # use non-string as priority value probe netfilter.hook("NF_INET_PRE_ROUTING").priority(2) { } systemtap-2.3/testsuite/semko/netfilter06.stp000077500000000000000000000001541217430427200214550ustar00rootroot00000000000000#! stap -p2 # no priority value probe netfilter.hook("NF_INET_PRE_ROUTING").priority { $verdict = "DROP" } systemtap-2.3/testsuite/semko/netfilter07.stp000077500000000000000000000001771217430427200214630ustar00rootroot00000000000000#! stap -p2 # setting verdict in non-guru mode should fail probe netfilter.hook("NF_INET_PRE_ROUTING") { $verdict = NF_DROP } systemtap-2.3/testsuite/semko/netfilter08.stp000077500000000000000000000002111217430427200214510ustar00rootroot00000000000000#! stap -p2 # using nonexistent protocol family should fail probe netfilter.hook("NF_INET_PRE_ROUTING").pf("INTERGALACTIC_IPV3000") { } systemtap-2.3/testsuite/semko/netfilter09.stp000077500000000000000000000004001217430427200214520ustar00rootroot00000000000000#! stap -p4 # use string as priority value probe netfilter.hook("NF_INET_PRE_ROUTING").priority("-1") { printf("a") } probe netfilter.hook("NF_INET_PRE_ROUTING") { printf("b") } probe netfilter.hook("NF_INET_PRE_ROUTING").priority("3") { printf("c\n") } systemtap-2.3/testsuite/semko/netfilter10.stp000077500000000000000000000002331217430427200214460ustar00rootroot00000000000000#! stap -p4 # use string as priority value probe netfilter.hook("NF_INET_PRE_ROUTING").priority("1") { } probe netfilter.hook("NF_INET_PRE_ROUTING") { } systemtap-2.3/testsuite/semko/netfilter11.stp000077500000000000000000000001211217430427200214430ustar00rootroot00000000000000#! stap -gp4 probe netfilter.hook("NF_INET_PRE_ROUTING") { $verdict = NF_DROP } systemtap-2.3/testsuite/semko/nine.stp000077500000000000000000000000741217430427200202450ustar00rootroot00000000000000#! stap -p2 global a probe begin { a[4] = 1; a = 2; } systemtap-2.3/testsuite/semko/nofunc.stp000077500000000000000000000000711217430427200206010ustar00rootroot00000000000000#! stap -p2 probe begin { foo () # function is MIA } systemtap-2.3/testsuite/semko/one.stp000077500000000000000000000002021217430427200200660ustar00rootroot00000000000000#! stap -up2 function stamp (syscall) { # no return expression => unknown function type } probe begin { a = stamp ("read"); } systemtap-2.3/testsuite/semko/plt1.stp000077500000000000000000000001061217430427200201700ustar00rootroot00000000000000#! stap -p2 probe process("stap").plt { println($no_such_var) } systemtap-2.3/testsuite/semko/plt2.stp000077500000000000000000000001361217430427200201740ustar00rootroot00000000000000#! /bin/sh # this is an error without a -c cmd stap $@ -p2 -e 'probe process.plt { exit() }' systemtap-2.3/testsuite/semko/procfs01.stp000077500000000000000000000000361217430427200207470ustar00rootroot00000000000000#! stap -p2 probe procfs { } systemtap-2.3/testsuite/semko/procfs02.stp000077500000000000000000000000531217430427200207470ustar00rootroot00000000000000#! stap -p2 probe procfs("foo").rread { } systemtap-2.3/testsuite/semko/procfs03.stp000077500000000000000000000000511217430427200207460ustar00rootroot00000000000000#! stap -p2 probe procfs.read.write { } systemtap-2.3/testsuite/semko/procfs04.stp000077500000000000000000000001421217430427200207500ustar00rootroot00000000000000#! stap -p2 # write to $value in a procfs write probe probe procfs.write { $value = "hi" } systemtap-2.3/testsuite/semko/procfs05.stp000077500000000000000000000001661217430427200207570ustar00rootroot00000000000000#! stap -p2 # read from $value in a procfs read probe probe procfs.read { x = $value printf("%s\n", x) } systemtap-2.3/testsuite/semko/procfs06.stp000077500000000000000000000001101217430427200207450ustar00rootroot00000000000000#! stap -p2 # path can't start with '/' probe procfs("/foo").read { } systemtap-2.3/testsuite/semko/procfs07.stp000077500000000000000000000001061217430427200207530ustar00rootroot00000000000000#! stap -p2 # path can't end with '/' probe procfs("foo/").read { } systemtap-2.3/testsuite/semko/procfs08.stp000077500000000000000000000001221217430427200207520ustar00rootroot00000000000000#! stap -p2 # path can't be a relative path probe procfs("foo/../bar").read { } systemtap-2.3/testsuite/semko/procfs09.stp000077500000000000000000000001151217430427200207550ustar00rootroot00000000000000#! stap -p2 # path can't be a relative path probe procfs("foo/.").read { } systemtap-2.3/testsuite/semko/procfs10.stp000077500000000000000000000001241217430427200207450ustar00rootroot00000000000000#! stap -p2 # path can't contain an empty component probe procfs("a//c").read { } systemtap-2.3/testsuite/semko/procfs11.stp000077500000000000000000000001551217430427200207520ustar00rootroot00000000000000#! stap -p2 # use $value as a structure pointer in a procfs probe probe procfs.write { print($value->foo) } systemtap-2.3/testsuite/semko/procfs12.stp000077500000000000000000000001401217430427200207450ustar00rootroot00000000000000#! stap -p2 # use $value as an array in a procfs probe probe procfs.write { print($value[0]) } systemtap-2.3/testsuite/semko/procfs13.stp000077500000000000000000000001151217430427200207500ustar00rootroot00000000000000#! stap -p2 # no maxsize value probe procfs.read.maxsize { $value = "foo" } systemtap-2.3/testsuite/semko/procfs14.stp000077500000000000000000000001321217430427200207500ustar00rootroot00000000000000#! stap -p2 # use -1 as a maxsize value probe procfs.read.maxsize(-1) { $value = "foo" } systemtap-2.3/testsuite/semko/procfs15.stp000077500000000000000000000001411217430427200207510ustar00rootroot00000000000000#! stap -p2 # use -1 as a maxsize value probe procfs("foo").read.maxsize(-1) { $value = "foo" } systemtap-2.3/testsuite/semko/return01.stp000077500000000000000000000002501217430427200207700ustar00rootroot00000000000000#! stap -p2 probe kernel.function("get_page_state").return { # this should fail, since get_page_state() is a void function printf("return is %d\n", $return) } systemtap-2.3/testsuite/semko/return02.stp000077500000000000000000000002461217430427200207760ustar00rootroot00000000000000#! stap -p2 probe kernel.function("vfs_read") { # this should fail - using $return not in a '.return' probe printf("in sys_read - return = %d\n", $return) } systemtap-2.3/testsuite/semko/seven.stp000077500000000000000000000001431217430427200204310ustar00rootroot00000000000000#! stap -p2 global baz probe begin { baz[1] = 4; baz["1"] = 5; # inconsistent index types } systemtap-2.3/testsuite/semko/seventeen.stp000077500000000000000000000000761217430427200213120ustar00rootroot00000000000000#! stap -p2 probe module("no_such_module").function("*") { } systemtap-2.3/testsuite/semko/six.stp000077500000000000000000000001501217430427200201120ustar00rootroot00000000000000#! stap -p2 global bar probe begin { bar[1] = 2; bar[1, 2] = 3; # inconsistent array dimensions } systemtap-2.3/testsuite/semko/sixteen.stp000077500000000000000000000001171217430427200207710ustar00rootroot00000000000000#! stap -p2 probe kernel.function("no_such_function_anywhere_guaranteed") { } systemtap-2.3/testsuite/semko/source_context.stp000077500000000000000000000001231217430427200223530ustar00rootroot00000000000000#! stap -p2 probe timer.ms(123) { printf("Probe successful\n") eeexit () } systemtap-2.3/testsuite/semko/target_addr1.stp000077500000000000000000000002111217430427200216460ustar00rootroot00000000000000#! stap -p2 // can't take the address of bitfields probe kernel.function("release_task") { println(& $p->did_exec) // unsigned:1 } systemtap-2.3/testsuite/semko/target_addr2.stp000077500000000000000000000001731217430427200216560ustar00rootroot00000000000000#! stap -p2 // can't take the address of register parameters probe kernel.function("do_sys_open") { println(& $dfd) } systemtap-2.3/testsuite/semko/target_addr3.stp000077500000000000000000000002101217430427200216470ustar00rootroot00000000000000#! stap -p2 // can't take the address of register return values probe kernel.function("do_sys_open").return { println(& $return) } systemtap-2.3/testsuite/semko/target_lvalue.stp000077500000000000000000000011121217430427200221440ustar00rootroot00000000000000#!/bin/sh # Make sure that each of these fail with status 1 # - status 0 means that they succeeded, which they shouldn't # - a high status code means it crashed (PR11266) # # Since this is a semko, we exit 1 if they all fail correctly, # else we exit 0 for success or crash. stap $@ -e 'probe syscall.read { ++$fd }' -p2 -g [ $? -eq 1 ] || exit 0 stap $@ -e 'probe syscall.read { $fd++ }' -p2 -g [ $? -eq 1 ] || exit 0 stap $@ -e 'probe syscall.read { delete $fd }' -p2 -g [ $? -eq 1 ] || exit 0 stap $@ -e 'probe syscall.read { ++$fd = 42 }' -p2 -g [ $? -eq 1 ] || exit 0 exit 1 systemtap-2.3/testsuite/semko/ten.stp000077500000000000000000000001201217430427200200720ustar00rootroot00000000000000#! stap -p2 global foo probe begin { foo = 1 } probe end { if (4 in foo) { } } systemtap-2.3/testsuite/semko/thirteen.stp000077500000000000000000000002351217430427200211350ustar00rootroot00000000000000#! stap -p2 global foo function bar() { foo["hello"] = 10 return 10 } probe begin { foreach (a in foo) { bar() } log("hello from systemtap") } systemtap-2.3/testsuite/semko/thirty.stp000077500000000000000000000001651217430427200206400ustar00rootroot00000000000000#! stap -up2 # need one of these for each prohibited statistic operation global x probe end { x <<< 1 x = 10 } systemtap-2.3/testsuite/semko/thirtyeight.stp000077500000000000000000000001111217430427200216500ustar00rootroot00000000000000#! stap -p2 probe kernel.statement(0).absolute {} /* needs guru mode */ systemtap-2.3/testsuite/semko/thirtyfive.stp000077500000000000000000000001361217430427200215100ustar00rootroot00000000000000#! stap -p2 probe foo.a = kernel.function("no_such_function")? { "alias a" } probe foo.* { } systemtap-2.3/testsuite/semko/thirtyfour.stp000077500000000000000000000003251217430427200215320ustar00rootroot00000000000000#! stap -p2 # can't write to target variables in .return probes probe kernel.function("fget_light").return { $fd = 0 printf("fd is %d\n", $fd) } probe kernel.function("do_sys_open").return { $filename } systemtap-2.3/testsuite/semko/thirtynine.stp000077500000000000000000000001331217430427200215050ustar00rootroot00000000000000#! stap -p2 probe kernel.function("sys_open").if(1) {} /* if statement doesn't need '.'*/ systemtap-2.3/testsuite/semko/thirtyone.stp000077500000000000000000000001751217430427200213430ustar00rootroot00000000000000#! stap -up2 # need one of these for each prohibited statistic operation global x probe end { x[10] <<< 1 x[10] = 10 } systemtap-2.3/testsuite/semko/thirtyseven.stp000077500000000000000000000001131217430427200216720ustar00rootroot00000000000000#! stap -gp2 probe kernel.statement(0).absolute { print ($any_variable) } systemtap-2.3/testsuite/semko/thirtysix.stp000077500000000000000000000002451217430427200213630ustar00rootroot00000000000000#! stap -p2 probe kernel.function("kmem_cache_alloc") { print ($cachep->no_such_field) print ($cachep->array->should_have_indexed_it) print ($cachep->next) } systemtap-2.3/testsuite/semko/thirtythree.stp000077500000000000000000000002251217430427200216650ustar00rootroot00000000000000#! stap -p2 // should fail since all these functions are blacklisted probe kernel.function("do_IRQ") {} probe kernel.function("*@*/kprobes.c") {} systemtap-2.3/testsuite/semko/thirtytwo.stp000077500000000000000000000002031217430427200213630ustar00rootroot00000000000000#! stap -p2 // should fail since init_setup should be skipped because it is in .init.text probe kernel.function("init_setup") { } systemtap-2.3/testsuite/semko/three.stp000077500000000000000000000001421217430427200204170ustar00rootroot00000000000000#! stap -p2 global b probe begin { a <<< 2; b[a] = 4; # must not index with stats variable } systemtap-2.3/testsuite/semko/twelve.stp000077500000000000000000000001531217430427200206200ustar00rootroot00000000000000#! stap -p2 probe end { for (a=0; "hello";) {println("hello")} while ("goodbye") {println("world")} } systemtap-2.3/testsuite/semko/twenty.stp000077500000000000000000000001111217430427200206360ustar00rootroot00000000000000#! stap -p2 function a:string () { } probe begin { print (a() + 1) } systemtap-2.3/testsuite/semko/twentyeight.stp000077500000000000000000000001621217430427200216650ustar00rootroot00000000000000#! stap -p2 # need one of these for each prohibited statistic operation global x probe end { x <<< 10 x++ } systemtap-2.3/testsuite/semko/twentyfive.stp000077500000000000000000000001631217430427200215170ustar00rootroot00000000000000#! stap -up2 # need one of these for each prohibited statistic operation global x, y probe end { x = y[10] } systemtap-2.3/testsuite/semko/twentyfour.stp000077500000000000000000000001571217430427200215440ustar00rootroot00000000000000#! stap -up2 # need one of these for each prohibited statistic operation global x, y probe end { y = x } systemtap-2.3/testsuite/semko/twentynine.stp000077500000000000000000000002101217430427200215100ustar00rootroot00000000000000#! stap -up2 # need one of these for each prohibited statistic operation global x probe end { x <<< 10 <<< 11 # but see PR 1922 } systemtap-2.3/testsuite/semko/twentyone.stp000077500000000000000000000003021217430427200213420ustar00rootroot00000000000000#! stap -p2 # tests that an inline function is *not* matched using # the function().call pattern probe kernel.function("context_switch").call { log ("found an inline via function().call") } systemtap-2.3/testsuite/semko/twentyseven.stp000077500000000000000000000002301217430427200217010ustar00rootroot00000000000000#! stap -up2 # need one of these for each prohibited statistic operation global x function foo(bar) { bar <<< x } probe end { x <<< 10 foo(x) } systemtap-2.3/testsuite/semko/twentysix.stp000077500000000000000000000001761217430427200213750ustar00rootroot00000000000000#! stap -up2 # need one of these for each prohibited statistic operation global x probe end { x[10] <<< 1 x[10] = 10 } systemtap-2.3/testsuite/semko/twentythree.stp000077500000000000000000000000521217430427200216720ustar00rootroot00000000000000#! stap -p2 probe badalias.* = begin { } systemtap-2.3/testsuite/semko/twentytwo.stp000077500000000000000000000002661217430427200214030ustar00rootroot00000000000000#! stap -p2 # tests that a non-inline function is *not* matched using # the inline() pattern probe kernel.function("vfs_read").inline { log ("found a non-inline via inline()") } systemtap-2.3/testsuite/semko/two.stp000077500000000000000000000001301217430427200201160ustar00rootroot00000000000000#! stap -up2 probe begin { bar = 2 + "string"; # mixing integer+string arithmetic } systemtap-2.3/testsuite/semko/twotwo.stp000077500000000000000000000001761217430427200206620ustar00rootroot00000000000000#! stap -up2 function zoo (p) { p <<< 5; return 0 } # passing stats as function arg global car probe begin { zoo (car) } systemtap-2.3/testsuite/semko/typemismatch.stp000077500000000000000000000002001217430427200220120ustar00rootroot00000000000000#! stap -p2 global noo probe begin { foo = 1 ; foo = "bar" ; noo = 4 } probe end { foo = "zoo" ; foo <<< 2 ; noo = "zoo" }systemtap-2.3/testsuite/semko/utrace.stp000077500000000000000000000000451217430427200205750ustar00rootroot00000000000000#! stap -p2 probe process.begin { } systemtap-2.3/testsuite/semko/utrace03.stp000077500000000000000000000001131217430427200207340ustar00rootroot00000000000000#! stap -p2 # invalid probe type probe process("/bin/cat").end.return { } systemtap-2.3/testsuite/semko/utrace04.stp000077500000000000000000000001511217430427200207370ustar00rootroot00000000000000#! stap -p2 # end probes don't support target symbols probe process("/bin/cat").end { print($syscall) } systemtap-2.3/testsuite/semko/utrace05.stp000077500000000000000000000001321217430427200207370ustar00rootroot00000000000000#! stap -p2 # can't write to $syscall probe process("/bin/cat").syscall { $syscall = 1 } systemtap-2.3/testsuite/semko/utrace06.stp000077500000000000000000000001461217430427200207450ustar00rootroot00000000000000#! stap -p2 # treat $syscall as a pointer probe process("/bin/cat").syscall { print($syscall->foo) } systemtap-2.3/testsuite/semko/utrace07.stp000077500000000000000000000001431217430427200207430ustar00rootroot00000000000000#! stap -p2 # treat $syscall as an array probe process("/bin/cat").syscall { print($syscall[0]) } systemtap-2.3/testsuite/semko/utrace14.stp000077500000000000000000000001031217430427200207350ustar00rootroot00000000000000#! stap -p2 # pid can't be less than 2 probe process(1).begin { } systemtap-2.3/testsuite/semko/utrace15.stp000077500000000000000000000001161217430427200207420ustar00rootroot00000000000000#! stap -p2 # write to $argN probe process("/bin/cat").syscall { $arg1 = 1 } systemtap-2.3/testsuite/semko/utrace16.stp000077500000000000000000000001401217430427200207400ustar00rootroot00000000000000#! stap -p2 # treat $argN as a pointer probe process("/bin/cat").syscall { print($arg1->foo) } systemtap-2.3/testsuite/semko/utrace17.stp000077500000000000000000000001351217430427200207450ustar00rootroot00000000000000#! stap -p2 # treat $argN as an array probe process("/bin/cat").syscall { print($arg1[0]) } systemtap-2.3/testsuite/semko/utrace18.stp000077500000000000000000000001311217430427200207420ustar00rootroot00000000000000#! stap -p2 # write to $return probe process("/bin/cat").syscall.return { $return = 1 } systemtap-2.3/testsuite/semko/utrace19.stp000077500000000000000000000001511217430427200207450ustar00rootroot00000000000000#! stap -p2 # access to $return from syscall entry probe process("/bin/cat").syscall { print($return) } systemtap-2.3/testsuite/semko/utrace20.stp000077500000000000000000000001411217430427200207340ustar00rootroot00000000000000#! stap -p2 # treat $return as an array probe process("/bin/cat").syscall { print($return[0]) } systemtap-2.3/testsuite/semko/utrace21.stp000077500000000000000000000001651217430427200207430ustar00rootroot00000000000000#! stap -p2 # treat $return as a pointer/structure probe process("/bin/cat").syscall.return { print($return->foo) } systemtap-2.3/testsuite/semko/utrace22.stp000077500000000000000000000001551217430427200207430ustar00rootroot00000000000000#! stap -p2 # access to $argN from syscall return probe process("/bin/cat").syscall.return { print($arg1) } systemtap-2.3/testsuite/semko/zero.stp000077500000000000000000000000771217430427200202760ustar00rootroot00000000000000#! stap -p2 probe begin { print (1 = a) print (a+1 = 4) } systemtap-2.3/testsuite/semlib/000077500000000000000000000000001217430427200167155ustar00rootroot00000000000000systemtap-2.3/testsuite/semlib/f1.stp000066400000000000000000000000341217430427200177500ustar00rootroot00000000000000function f1 () { return 0 } systemtap-2.3/testsuite/semlib/g1.stp000066400000000000000000000000541217430427200177530ustar00rootroot00000000000000global g1 function g1set (a) { g1 = a + 0 } systemtap-2.3/testsuite/semlib/g2.stp000066400000000000000000000000471217430427200177560ustar00rootroot00000000000000global g2 probe begin { g2[0] = f1() } systemtap-2.3/testsuite/semok/000077500000000000000000000000001217430427200165605ustar00rootroot00000000000000systemtap-2.3/testsuite/semok/args.stp000077500000000000000000000001241217430427200202440ustar00rootroot00000000000000#! /bin/sh stap $@ -p2 -e 'probe begin { log (@1 . sprint($2)) }' hello 0xdeadbeef systemtap-2.3/testsuite/semok/badvar.stp000077500000000000000000000002031217430427200205450ustar00rootroot00000000000000#! /bin/sh stap $@ -p2 --skip-badvars -e ' probe syscall.read { if ($foo == 0) printf ("Voila! It works..\n") exit () } ' systemtap-2.3/testsuite/semok/badvar_undefined.stp000077500000000000000000000004271217430427200225760ustar00rootroot00000000000000#!/bin/sh # PR11346: We shouldn't even see a warning when a would-be skip-badvars # replacement is masked by a @defined condition. stap $@ -W -p2 --skip-badvars -e 'probe kernel.function("sys_getxattr") { printf("%s\n", user_string(@defined($pathname) ? $pathname : $path)) }' systemtap-2.3/testsuite/semok/beginend.stp000077500000000000000000000003321217430427200210640ustar00rootroot00000000000000#! stap -p2 probe begin {} probe begin(0) {} probe begin(9223372036854775807) {} probe begin(-9223372036854775808) {} probe end {} probe end(0) {} probe end(9223372036854775807) {} probe end(-9223372036854775808) {} systemtap-2.3/testsuite/semok/bz10475.stp000077500000000000000000000004161217430427200203300ustar00rootroot00000000000000#! stap -p2 // bz10475: pointer-array confused about array element size // struct file *filp_open(int dfd, const char *filename, int flags, int mode) probe kernel.function("filp_open") { // check array access on a "complex" pointer type println($filename[0]) } systemtap-2.3/testsuite/semok/bz11911.stp000077500000000000000000000006041217430427200203230ustar00rootroot00000000000000#!/bin/sh TESTBIN=`mktemp` || exit $? function clean_exit { rm $TESTBIN; exit $1; } echo ' struct point { int x, y; }; int foo (struct point p, int i) { return p.x + p.y; } int main (void) { struct point p = { 2, 3 }; return foo (p, 17); } ' | gcc -g -o $TESTBIN -xc - || clean_exit $? stap $@ -L 'process("'$TESTBIN'").function("foo")' | grep '\$p:struct point' clean_exit $? systemtap-2.3/testsuite/semok/cast.stp000077500000000000000000000020551217430427200202470ustar00rootroot00000000000000#! stap -p2 probe begin { // basic @cast test, with and without specifying kernel println(@cast(0, "task_struct")->tgid) println(@cast(0, "task_struct", "kernel")->tgid) // check module-search paths println(@cast(0, "task_struct", "foo:kernel:bar")->tgid) // would be nice to test usermode @cast too, // but who knows what debuginfo is installed... // check modules generated from headers println(@cast(0, "task_struct", "kernel")->tgid) println(@cast(0, "timeval", "")->tv_sec) // sometimes multiple headers are needed in tandem println(@cast(0, "task_struct", "kernel")->fs->umask) // make sure that bogus @casts can get optimized away @cast(0, "task_struct")->no_such_field @cast(0, "task_struct")->parent->no_such_field @cast(0, "no_such_type")->tgid @cast(0, "task_struct", "no_such_module")->tgid // PR11556: we should be able to treat the initial pointer like an array too println(@cast(0, "task_struct")[42]->tgid) } systemtap-2.3/testsuite/semok/config_config.stp000077500000000000000000000005021217430427200221020ustar00rootroot00000000000000#! stap -p2 # check that CONFIGs can match other CONFIGS. probe %( CONFIG_HZ == CONFIG_NR_CPUS || CONFIG_NR_CPUS > CONFIG_HZ || CONFIG_NR_CPUS < CONFIG_HZ %? %( CONFIG_NFSD == CONFIG_NFS_COMMON || CONFIG_NFS_COMMON != CONFIG_NFSD %? begin %: noprobe %) %: nonoprobe %) { exit() } systemtap-2.3/testsuite/semok/config_number.stp000077500000000000000000000006501217430427200221310ustar00rootroot00000000000000#! stap -p2 # check that number comparisons work in CONFIG checks # Note that unset CONFIG options compare equal the empty string and/or zero probe %( CONFIG_NR_CPUS == 13 %? noprobe %: %( CONFIG_NR_CPUS != "" && CONFIG_NR_CPUS < 1 %? nonoprobe %: %( CONFIG_NR_CPUS >= 0 && CONFIG_NO_SUCH_FOOBAR_CONFIG_OPTION == 0 %? begin %: nononoprobe %) %) %) { exit() } systemtap-2.3/testsuite/semok/config_wildcard.stp000077500000000000000000000007321217430427200224330ustar00rootroot00000000000000#! stap -p2 # check that wildcards work in CONFIG checks probe %( CONFIG_NFSD == "m" || CONFIG_NFSD == "y" %? %( CONFIG_NFSD == "[my]" && CONFIG_NFSD == "[a-z]" && CONFIG_NFSD == "?" && CONFIG_NFSD == "*" %? begin %: noprobe %) %: %( CONFIG_NFSD != "[my]" && CONFIG_NFSD != "[a-z]" && CONFIG_NFSD != "?" && CONFIG_NFSD == "*" && CONFIG_NFSD == "" %? begin %: noprobe %) %) { exit() } systemtap-2.3/testsuite/semok/context-globals.stp000077500000000000000000000014541217430427200224240ustar00rootroot00000000000000#! stap -Wp2 /* Assert no conflicts between locals used in tapset to user's script namespace. */ global n[1], r[1], b[1], orig_n[1], sym[1], foo[1], l[1], line[1], i[1], str[1] global args[1], mm[1], arg_start[1], arg_end[1], nr[1], len[1], arg[1] probe begin { n[0] = r[0] = b[0] = orig_n[0] = sym[0] = 1; foo[0] = l[0] = line[0] = i[0] = str[0] = 1; args[0] = mm[0] = arg_start[0] = arg_end[0] = 1; nr[0] = len[0] = arg[0] = 1; } probe end { /* context.stp */ println(cmdline_args(0, 0, "")) /* ucontext.stp */ println(ucallers(0)) /* ucontext-symbols.stp */ println(ustack(0)) print_usyms("") println(sprint_usyms("")) /* context-symbols.stp */ println(stack(0)) print_syms("") println(sprint_syms("")) } systemtap-2.3/testsuite/semok/defined_list_vars.stp000077500000000000000000000007761217430427200230110ustar00rootroot00000000000000#! /bin/sh # PR11360 - Make sure that @defined and -L play well together. # # The test shouldn't be dependent on the implementation of syscall.poll, in # case that evolves, so I'm recreating the problematic condition here. # # NB: This is abusing the fact that -l/-L work by wrapping the input string # with "probe " and "{}" stap $@ -L ' my_syscall.poll = kernel.function("sys_poll").call { timeout = (@defined($timeout_msecs) ? $timeout_msecs : $timeout) } probe my_syscall.poll ' | grep " timeout:long" systemtap-2.3/testsuite/semok/doubleglob.stp000077500000000000000000000002741217430427200214340ustar00rootroot00000000000000#! stap -p2 probe *sys**pen {} // [nd_]syscall.[mq_]open probe t**ile {} // timer.profile probe t**es(1) {} // timer.jiffies(1) probe ke**on("vfs_read") {} // kernel.function("vfs_open") systemtap-2.3/testsuite/semok/eight.stp000077500000000000000000000001251217430427200204110ustar00rootroot00000000000000#! /bin/sh stap $@ -p2 -I${SRCDIR}/testsuite/semlib -e 'probe begin { a = f1 (); }' systemtap-2.3/testsuite/semok/eighteen.stp000077500000000000000000000001211217430427200210750ustar00rootroot00000000000000#! stap -p2 function f () { } function g (arg) { } probe begin { f(); g(1) } systemtap-2.3/testsuite/semok/eleven.stp000077500000000000000000000017711217430427200205770ustar00rootroot00000000000000#! stap -p2 global entry_time, my_count, my_fd, read_times # future built-ins function trace (s) { return 0 } global tid probe begin /* kernel.function("read") */ { count=0 timestamp=0 fd=0 tid=1 entry_time[tid] = timestamp # "macro" variable my_count[tid] = count # function argument my_fd[tid] = fd # function argument trace ("my_count = " . sprint(my_count[tid]) . "my_fd = " . sprint(my_fd[tid])) } probe end /* kernel.function("read").return */ { syscall_name="" retvalue=0 tid=1 if (entry_time[tid]) { read_times[syscall_name] # variable from provider alias += timestamp - entry_time[tid] } trace ("syscall " . (syscall_name) . " return value = " . sprintf ("0x%x", retvalue)) # function pseudo-argument } probe end { foreach (syscall in read_times) { trace ("syscall " . syscall . " total-time=" . sprint (read_times[syscall])) } } systemtap-2.3/testsuite/semok/entry01.stp000077500000000000000000000004061217430427200206150ustar00rootroot00000000000000#! stap -Wp2 global stat # dwarf .return probes can use @entry probe kernel.function("do_filp_open").return?, kernel.function("filp_open").return?, process("stap").function("main").return? { stat[pp()] <<< get_cycles() - @entry(get_cycles()) } systemtap-2.3/testsuite/semok/entry02.stp000077500000000000000000000002701217430427200206150ustar00rootroot00000000000000#! stap -p2 global stat # @entry can be optimized away from bad locations if the result is not used. probe begin { stat <<< get_cycles(); - @entry(get_cycles()) exit() } systemtap-2.3/testsuite/semok/entry03.stp000077500000000000000000000014401217430427200206160ustar00rootroot00000000000000#! stap -Wp2 # This causes a mix of kretprobe-data-pouch and global-map # approaches for saving entry values. # # During development I found that kretprobe would add a call block without # setting up _dwarf_tvar_tid, and then global-map would neglect to create the # tid as it appended. # # We try it in both orders here to make sure they don't interfere either way. probe kernel.function("do_filp_open").return !, kernel.function("filp_open").return { println(kernel_string(@defined($pathname) ? $pathname : $filename)) println(get_cycles() - @entry(get_cycles())) } probe kernel.function("do_filp_open").return !, kernel.function("filp_open").return { println(get_cycles() - @entry(get_cycles())) println(kernel_string(@defined($pathname) ? $pathname : $filename)) } systemtap-2.3/testsuite/semok/entry04.stp000077500000000000000000000003321217430427200206160ustar00rootroot00000000000000#! stap -Wp2 global stat # dwarfless .return probes can use @entry probe kprobe.function("do_filp_open").return?, kprobe.function("filp_open").return? { stat[pp()] <<< get_cycles() - @entry(get_cycles()) } systemtap-2.3/testsuite/semok/fifteen.stp000077500000000000000000000003431217430427200207330ustar00rootroot00000000000000#! stap -p2 function trace (n) { return 0 } # multiple independent derived probes using the "same" variable # (this used to crash before we deep-copied the body) probe begin, begin, begin { base_num = 10 trace(base_num) } systemtap-2.3/testsuite/semok/five.stp000077500000000000000000000001401217430427200202370ustar00rootroot00000000000000#! stap -p2 global array probe begin { array[1] = array[2] = 3; statvar <<< value <<< 4; } systemtap-2.3/testsuite/semok/four.stp000077500000000000000000000007321217430427200202700ustar00rootroot00000000000000#! stap -p2 # these will ultimately be somehow associated with "providers" # and have a syntax of their own global kernel_jiffies, kernel_current_comm function kernel_netlink(a, b) { # this should be a builtin function return 0 } function stamp (syscall) { return kernel_netlink (4, kernel_jiffies . " " . kernel_current_comm . " " . syscall) } # probe kernel:syscall:read = kernel:function("sys_read"); probe begin /* syscall ("read") */ { stamp ("read"); } systemtap-2.3/testsuite/semok/fourteen.stp000077500000000000000000000003561217430427200211460ustar00rootroot00000000000000#! stap -p2 function trace (s) { return 0 } # recursive alias expansion probe foo = begin { trace("hello") } probe bar = foo { x=1 } probe baz = bar { y=2 } probe quux = baz { z = x + y } probe quux, end { trace("goodbye") } systemtap-2.3/testsuite/semok/gurufunc.stp000077500000000000000000000001461217430427200211520ustar00rootroot00000000000000#! stap -gup2 # set_kernel_long should only be allowed with -g probe begin { set_kernel_long(0, 0) } systemtap-2.3/testsuite/semok/kretprobe-data.stp000077500000000000000000000006711217430427200222230ustar00rootroot00000000000000#! stap -p2 # On kernels with kretprobe data-pouch, we have a tricky situation # with data types. Make sure a few different cases will work... probe kernel.function("kern_path_create").return !, kernel.function("do_path_lookup").return !, kernel.function("path_lookup").return { if (@defined($path)) { println($path) println($path) } else { println($nd) println($nd$) } println($$parms) } systemtap-2.3/testsuite/semok/mangled.stp000077500000000000000000000023721217430427200207260ustar00rootroot00000000000000#! stap -p2 # # PR11880, allow probing by mangled name, especially useful for advanced users # to distinguish overloaded function names in C++. # # For example, stap itself has: # std::vector dwflpp::getscopes(Dwarf_Die* die) # std::vector dwflpp::getscopes(Dwarf_Addr pc) # # We can probe both as process("stap").function("dwflpp::getscopes"), but we # didn't have a way to select just one, except by matching line numbers. If # you want both but with different handlers, then @defined would work, but # that's still all-or-nothing. # # Now we can use the mangled name instead, and probe them individually as we # please. The test here checks that the right $vars are available in the # separate probes. probe process("stap").function("_ZN6dwflpp9getscopesE[my]") { if (@defined($pc) && !@defined($die)) println("pc=", $pc$) else println($assert_nosuchvar) } probe process("stap").function("_ZN6dwflpp9getscopesEP9Dwarf_Die") { if (@defined($die) && !@defined($pc)) println("die=", $die$) else println($assert_nosuchvar) } probe process("stap").function("_ZN6dwflpp9getscopesE*") { if (@defined($pc) ^ @defined($die)) println("XOR ok") else println($assert_nosuchvar) } systemtap-2.3/testsuite/semok/map_wrap_good.stp000077500000000000000000000001721217430427200221310ustar00rootroot00000000000000#! stap -p2 global foo%[5] global bar%[5] probe begin { for(i=0; i<10; i++) { foo[i]=i; bar[i] <<< i; } } systemtap-2.3/testsuite/semok/netfilter01.stp000077500000000000000000000002411217430427200214450ustar00rootroot00000000000000#! stap -gp2 # guru mode should enable use of weird hook/pf options without complaining probe netfilter.hook("NF_INET_WARP_10").pf("INTERGALACTIC_IPV3000") { } systemtap-2.3/testsuite/semok/nine.stp000077500000000000000000000001241217430427200202410ustar00rootroot00000000000000#! /bin/sh stap $@ -p2 -I${SRCDIR}/testsuite/semlib -e 'probe begin { g2[1] = 0 }' systemtap-2.3/testsuite/semok/nineteen.stp000077500000000000000000000005201217430427200211150ustar00rootroot00000000000000#! stap -p2 probe foo.a = bar.a { "alias a" } probe foo.b = bar.b { "alias b" } probe bar.a = begin { "begin" } probe bar.b = end { "end" } probe baz = bar.* { "wild aliases" } # baz expands to multiple aliases probe foo.* { "foo" } # refers to multiple aliases probe bar.* { "bar" } # refers to multiple probes probe baz { "baz" } systemtap-2.3/testsuite/semok/one.stp000077500000000000000000000007461217430427200201030ustar00rootroot00000000000000#! stap -p2 # these will ultimately be somehow associated with "providers" # and have a syntax of their own global kernel_jiffies, kernel_current_comm function kernel_netlink(a, b) { # this should be a builtin function return 0 } function stamp (syscall) { kernel_netlink (4, kernel_jiffies . " " . kernel_current_comm . " " . syscall); return 0 } # probe kernel:syscall:read = kernel:function("sys_read"); probe begin /* syscall ("read") */ { stamp ("read"); } systemtap-2.3/testsuite/semok/optimize.stp000077500000000000000000000014031217430427200211510ustar00rootroot00000000000000#! stap -wp2 # We count on the optimizer to blow away these ridiculous # expressions, since they have no effect on the output. global b function zoo (x) { return "tada" + x } probe begin { a = b + 2 zoo (zoo (5)) b = "goodbye" no . $such . $target + $variable } # bug #2599 probe begin{for(i=1;i-=2;i++);} probe begin{while(i+=2);} probe begin{if(i=j);} global ii probe begin{for(ii=1;ii-=2;ii++);} probe begin{while(ii+=2);} probe begin{if(ii=j);} # bug #6466 global goo probe begin { while (24) ; } probe begin { for (2<$i; zoo(333); poo) ; } probe begin { foreach (x in goo) goo[x]+1; } probe begin { foo = $bar; if (foo) {} } probe begin { { { { } } } } function useful () { return 1 } probe begin { println (useful()) } /* don't elide this one! */ systemtap-2.3/testsuite/semok/plt1.stp000077500000000000000000000001661217430427200201760ustar00rootroot00000000000000#! stap -p2 probe process("stap").plt { println($$name) println(@defined($no_such_var) ? $no_such_var : 0) } systemtap-2.3/testsuite/semok/plt2.stp000077500000000000000000000001521217430427200201720ustar00rootroot00000000000000#! /bin/sh # this should read the plt from -c stap stap $@ -p2 -e 'probe process.plt { exit() }' -c stap systemtap-2.3/testsuite/semok/pr11808.stp000077500000000000000000000003541217430427200203400ustar00rootroot00000000000000#!/bin/sh # PR11808 # This stap command may or may not fail, depending on function/var # availability. It should not abort() though. stap $@ -e 'probe kernel.function("next_tgid").return { println($return->tgid) }' -p2 [ "$?" -le 1 ] systemtap-2.3/testsuite/semok/pr11809.stp000077500000000000000000000004371217430427200203430ustar00rootroot00000000000000#!/bin/sh # PR11809 # This stap command may or may not fail, depending on function/var # availability. When it does fail, it should not be with "stack underflow". stap $@ -e 'probe kernel.function("next_tgid") { println($iter->tgid) }' -p2 2>&1 | grep "stack underflow" [ "$?" -eq 1 ] systemtap-2.3/testsuite/semok/pretty-uprobes.stp000077500000000000000000000013071217430427200223200ustar00rootroot00000000000000#! stap -p2 # NB: Most of these can't go beyond pass-2, because systemtap_session and # task_struct are huge. It's still useful to test that the entire beast can # be expanded though... global i = 1 # pretty-printing in dwarf user context probe process("stap").function("parse_cmdline") { log($$vars$) log($$vars$$) log($$parms$) log($$parms$$) log($$locals$) log($$locals$$) log($this$) log($this$$) log($this->base_hash$) log($this->base_hash$$) log($this->perpass_verbose$) log($this->perpass_verbose$$) log($this->perpass_verbose[0]$) log($this->perpass_verbose[0]$$) log($this->perpass_verbose[i]$) log($this->perpass_verbose[i]$$) } systemtap-2.3/testsuite/semok/pretty.stp000077500000000000000000000022221217430427200206400ustar00rootroot00000000000000#! stap -p2 # NB: Most of these can't go beyond pass-2, because systemtap_session and # task_struct are huge. It's still useful to test that the entire beast can # be expanded though... global i = 1 # pretty-printing with @cast probe begin { t = task_current() log(@cast(t, "task_struct")$) log(@cast(t, "task_struct")$$) log(@cast(t, "task_struct")->fs$) log(@cast(t, "task_struct")->fs$$) log(@cast(t, "task_struct")->comm$) log(@cast(t, "task_struct")->comm$$) log(@cast(t, "task_struct")->comm[0]$) log(@cast(t, "task_struct")->comm[0]$$) log(@cast(t, "task_struct")->comm[i]$) log(@cast(t, "task_struct")->comm[i]$$) } # pretty-printing in dwarf kernel context probe kernel.function("schedule_tail") %( CONFIG_TRACEPOINTS == "y" %? # pretty-printing in tracepoints , kernel.trace("sched_switch") %) { log($$vars$) log($$vars$$) log($$parms$) log($$parms$$) log($prev$) log($prev$$) log($prev->fs$) log($prev->fs$$) log($prev->comm$) log($prev->comm$$) log($prev->comm[0]$) log($prev->comm[0]$$) log($prev->comm[i]$) log($prev->comm[i]$$) } systemtap-2.3/testsuite/semok/pretty2.stp000077500000000000000000000004221217430427200207220ustar00rootroot00000000000000#! stap -p2 # A less specific test for tracepoints # # We have an error where base types wouldn't work, PR11785, but it # should still work in $$parms$ as just "=?" %( CONFIG_TRACEPOINTS == "y" %? probe kernel.trace("*") { log($$parms$$) } %: probe never { next } // :( %) systemtap-2.3/testsuite/semok/seven.stp000077500000000000000000000007121217430427200204330ustar00rootroot00000000000000#! stap -p2 global ar1, ar2 function printk (s:string) { return 0 } # to become a built-in function search (key) { if (key in ar1) { ar1[key] ++; return ar2[ar1[key]] } else return "no can do" # implies ar2[]: string } probe begin /* syscall("zamboni") */ { tgid=0 pid=0 tid=0 ar2[tid] = sprint (tgid); search (pid) } probe end { # for (key in ar2) if (key in ar2) printk ("this: " . sprint (key) . " was " . ar2[key]) } systemtap-2.3/testsuite/semok/seventeen.stp000077500000000000000000000004041217430427200213050ustar00rootroot00000000000000#! stap -p2 global foo probe kernel.function( %( kernel_v < "2.6.19" %? "pipe_writev" %: "pipe_write" %) ) { a = $nr_segs foo [a] = 1 # $nr_segs is not an lvalue here (foo is), so this should compile # even in non-guru mode foo [$nr_segs] ++ } systemtap-2.3/testsuite/semok/six.stp000077500000000000000000000001331217430427200201130ustar00rootroot00000000000000#! stap -p2 global bar, baz probe begin { tid=0 pid=0 bar[tid] = 4; baz[pid] = "5"; } systemtap-2.3/testsuite/semok/sixteen.stp000077500000000000000000000005661217430427200210010ustar00rootroot00000000000000#! stap -p2 # all these variables should be type-inferred automatically because the # operators are not overloaded probe begin { a / b; c % d; e + f; g - h; i >> j; k << l; m & n; o | p; q && r; s || t; u . v; x * y; z ^ aa; ~ bb; ! cc; - dd; ++ ee; -- ff; } probe begin { a /= b; c %= d; e += f; g-= h; i >>= j; k <<= l; m &= n; o |= p; u .= v; x *= y; z ^= aa; } systemtap-2.3/testsuite/semok/syscall_return.stp000077500000000000000000000003201217430427200223570ustar00rootroot00000000000000#!/bin/sh # Per bz6588, this should get through the semantic pass without warnings. stap $@ -p2 -e 'probe syscall.*.return { printf("%s returns %s\n", name, retstr) }' 2>&1 | grep -q WARNING && exit 1 exit 0 systemtap-2.3/testsuite/semok/target_addr.stp000077500000000000000000000005251217430427200215750ustar00rootroot00000000000000#! stap -p2 // read the address of various task_struct members. // all should roughly be $p + offsetof(foo) probe kernel.function("release_task") { println(& $p->state) // long println(& $p->usage) // atomic_t println(& $p->comm) // comm[TASK_COMM_LEN] println(& $p->comm[1]) println(& $p->parent) // task_struct* } systemtap-2.3/testsuite/semok/ten.stp000077500000000000000000000004711217430427200201030ustar00rootroot00000000000000#! stap -p2 global arr,rra probe begin { arr["key"]=0 rra[0]="value" } probe end { # confirm that typechecking works the same way for all array indexing if (k in arr) { k.""; arr[k]+0 } foreach (l in arr) { l.""; arr[l]+0 } if (m in rra) { m+0; rra[m]."" } foreach (n in rra) { n+0; rra[n]."" } } systemtap-2.3/testsuite/semok/thirteen.stp000077500000000000000000000007601217430427200211400ustar00rootroot00000000000000#! stap -p2 function trace (s) { return 0 } # define some aliases which resolve to kernel functions probe pipe_read = kernel.function("pipe_read") { fname = "pipe_read" reading_from_pipe = 1 } probe pipe_write = kernel.function("pipe_write") { fname = "pipe_write" reading_from_pipe = 0 } # use the aliases, including variables defined in them probe pipe_read, pipe_write { if (reading_from_pipe) trace("reading from pipe in " . fname) else trace("writing to pipe in " . fname) } systemtap-2.3/testsuite/semok/thirty.stp000077500000000000000000000003101217430427200206300ustar00rootroot00000000000000#! stap -p2 probe foo.a.one = foo.b, foo.c {} // not recursive probe foo.a.two = foo.c, foo.b {} // not recursive probe foo.b = foo.c {} probe foo.c = begin {} probe foo.a.one {} probe foo.a.two {} systemtap-2.3/testsuite/semok/thirtyeight.stp000077500000000000000000000010321217430427200216530ustar00rootroot00000000000000#! stap -Wp2 # Each of the @defined should be a valid symbol, and sometimes their expansion # leads to a new function declaration. We don't want to get warnings when such # functions turn out to be unused and are elided. probe kernel.function("sys_open") { println(@defined($mode) ? 1 : $nosuchvar) } probe kernel.trace("sched_switch")? { println(@defined($next->pid) ? 1 : $nosuchvar) } probe procfs.write { println(@defined($value) ? 1 : $nosuchvar) } probe begin { println(@defined(@cast(0, "task_struct")->pid) ? 1 : $nosuchvar) } systemtap-2.3/testsuite/semok/thirtyfive.stp000077500000000000000000000006331217430427200215120ustar00rootroot00000000000000#! stap -p2 // PR11208 probe kernel.function("do_filp""_""open") {} probe kernel.function("filp" "_" "close") {} probe kernel.function("p" "a" "n" "i" "c") {} // PR11617 probe kernel.function("do_filp[" @# "_]open") {} probe kernel.function("do_filp" %( 1==1 %? "_" %) "open") {} probe kernel.function("do_filp[" %( 1==1 %? @# %) "_]open") {} probe begin { log ( %( 1==1 %? "hello " %) "world" ) } systemtap-2.3/testsuite/semok/thirtyfour.stp000077500000000000000000000003721217430427200215340ustar00rootroot00000000000000#! stap -p2 # PR10495 probe foo = kernel.function("sys_open") { name = "a" } probe foo = kernel.function("sys_close") { name = "c" } probe foo.bar = kernel.function("sys_exit") { name = "nothing" } probe foo { log(name) } probe foo.* { log(name) } systemtap-2.3/testsuite/semok/thirtynine.stp000077500000000000000000000002731217430427200215120ustar00rootroot00000000000000#! stap -p2 # PR 1155 discusses the trouble with inlines, but ideally this should work. probe kernel.function("context_switch") { printf("switch from=0x%x to=0x%x\n", $prev, $next) } systemtap-2.3/testsuite/semok/thirtyone.stp000077500000000000000000000000761217430427200213430ustar00rootroot00000000000000#! stap -p2 # PR5049 probe kernel.function("*@module.c") {} systemtap-2.3/testsuite/semok/thirtyseven.stp000077500000000000000000000001171217430427200216760ustar00rootroot00000000000000#! stap -wWp2 # PR 11075 global foo # evokes warning probe begin { exit() } systemtap-2.3/testsuite/semok/thirtysix-utrace.stp000077500000000000000000000006721217430427200226500ustar00rootroot00000000000000#! stap -p2 probe process("stap").syscall { println(@defined($arg1)?$arg1:$nosuchvar) } # valid probe process("stap").begin { println(@defined($arg7)?$arg7:0) } # invalid probe process("stap").syscall { println(@defined($argZZ)?$argZZ:0) } # invalid probe process("stap").syscall.return { println(@defined($nosuchvar)?$nosuchvar:0) } # invalid probe process("stap").syscall.return { println(@defined($syscall)?$syscall:$nosuchvar) } # valid systemtap-2.3/testsuite/semok/thirtysix.stp000077500000000000000000000043521217430427200213660ustar00rootroot00000000000000#! stap -p2 probe kernel.function("sys_open") { println(@defined($foobar)?$foobar:0) } # invalid probe kernel.function("sys_open") { println(@defined($mode)?$mode:$nosuchvar) } # valid probe kernel.function("sys_open").return { println(@defined($foobar)?$foobar:0) } # invalid probe kernel.function("sys_open").return { println(@defined($mode)?$mode:$nosuchvar) } # valid probe kernel.trace("*")? { println(@defined($rw)?$rw:0) } # valid and invalid in places probe kernel.mark("*")? { println(@defined($foo)?$foo:0) } # invalid probe kernel.mark("*")? { println(@defined($name)?$name:$nosuchvar) } # valid probe kernel.mark("*")? { println(@defined($argJJJ)?$argJJJ:0) } probe process("stap").mark("pass*__*")? { println(@defined($arg1)?$arg1:$nosuchvar) } # valid probe process("stap").mark("pass*__*")? { println(@defined($nosuchvar)?$nosuchvar:0) } # invalid probe procfs("file").read { println(@defined($nosuchvar)?$nosuchvar:0) } # invalid probe procfs("file").write { println(@defined($value)?$value:$nosuchvar) } # valid probe begin,end,error,never { println(@defined($nosuchvar)?$nosuchvar:0) } # invalid probe timer.s(1),timer.jiffies(1) { println(@defined($nosuchvar)?$nosuchvar:0) } # invalid probe timer.profile { println(@defined($nosuchvar)?$nosuchvar:0) } # invalid probe begin { println(@defined(@cast(0, "task_struct")->foo)?$nosuchvar:0) } # invalid probe begin { println(@defined(@cast(0, "task_struct")->pid)?1:$nosuchvar) } # valid probe kernel.function("sys_open") { println(@defined(@cast(0, "task_struct")->foo)?$nosuchvar:0) } # invalid probe kernel.function("sys_open") { println(@defined(@cast(0, "task_struct")->pid)?1:$nosuchvar) } # valid function foo1() { println(@defined(@cast(0, "task_struct")->foo)?$nosuchvar:0) } # invalid function foo2() { println(@defined(@cast(0, "task_struct")->pid)?1:$nosuchvar) } # valid probe begin { foo1(); foo2(); } # PR11598: support @defined(&...) probe begin { println(@defined(@cast(0, "task_struct")->rcu)?$nosuchvar:0) } # invalid probe begin { println(@defined(&@cast(0, "task_struct")->rcu)?1:$nosuchvar) } # valid probe kernel.function("release_task") { println(@defined($p->rcu)?$nosuchvar:0) } # invalid probe kernel.function("release_task") { println(@defined(&$p->rcu)?1:$nosuchvar) } # valid systemtap-2.3/testsuite/semok/thirtythree.stp000077500000000000000000000004511217430427200216660ustar00rootroot00000000000000#! stap -p2 # Per bz3016, this should get through the semantic pass without warnings. probe kernel.function("do_mpage_readpage") { printf("\n page->mapping %p",$page->mapping) %( kernel_v >= "2.6.22" %? printf("\n page->first_page->mapping %p",$page->first_page->mapping) %) } systemtap-2.3/testsuite/semok/thirtytwo.stp000077500000000000000000000001401217430427200213630ustar00rootroot00000000000000#! stap -p2 # PR 6836 probe kernel.function("do_sys_open").return { log($$return . $$parms) } systemtap-2.3/testsuite/semok/three.stp000077500000000000000000000000771217430427200204260ustar00rootroot00000000000000#! stap -p2 global b probe begin { a <<< 2; b[4] <<< 4; } systemtap-2.3/testsuite/semok/transko.stp000077500000000000000000000004721217430427200207770ustar00rootroot00000000000000#! /bin/sh # make sure that we can *semcheck* all transko test files, to ensure # that it is translation-time checks that fail, not earlier ones set -e for file in ${SRCDIR}/testsuite/transko/*.stp do if grep -q /bin/sh $file; then true # can't override stap options else stap $@ -p2 $file fi done systemtap-2.3/testsuite/semok/twelve.stp000077500000000000000000000005141217430427200206210ustar00rootroot00000000000000#! stap -p2 function trace (s) { return 0 } # resolve to a set of kernel functions probe kernel.function("pipe_*") { trace("doing something with a pipe") } # resolve to a set of module functions probe module("jbd").function("journal_get_*_access@*/transaction.c") ? { trace("inside journal_get_*_access, in transaction.c") } systemtap-2.3/testsuite/semok/twenty.stp000077500000000000000000000006401217430427200206450ustar00rootroot00000000000000#! /bin/sh set -e stap $@ -wp2 -e ' probe kernel.function("*") {} probe module("*").function("*") {} probe kernel.function("*").call {} probe module("*").function("*").call {} probe kernel.function("*").return {} probe module("*").function("*").return {} probe kernel.function("*").inline {} probe module("*").function("*").inline {} ' | wc # without the |wc, we'd log the humongous list of stuff stap -p2 prints systemtap-2.3/testsuite/semok/twentyeight.stp000077500000000000000000000001241217430427200216630ustar00rootroot00000000000000#! stap -p2 # Make sure wildcards are handled probe kerne*.funct*("vfs_read").* {} systemtap-2.3/testsuite/semok/twentyfive.stp000077500000000000000000000005061217430427200215200ustar00rootroot00000000000000#! /bin/sh set -e stap $@ -p2 -e 'probe begin {foo$1$2$3}' # $-expansion only at token head stap $@ -p2 -e 'probe $1 $2' 'syscall.open,begin' '{log ("hello\n")}' stap $@ -p2 -e 'probe begin {@1 @2}' 'syscall.open,begin' '{log ("hello\n")}' stap $@ -p2 -e 'probe begin {log (@1.@2)}' 'syscall.open,begin' '{log ("hello\n")}' systemtap-2.3/testsuite/semok/twentyfour.stp000077500000000000000000000002371217430427200215430ustar00rootroot00000000000000#! stap -p2 # read access to target variables should work in .return probes probe kernel.function("vfs_read").return { printf("count is %d\n", $count) } systemtap-2.3/testsuite/semok/twentynine.stp000077500000000000000000000011031217430427200215120ustar00rootroot00000000000000#! stap -p2 global p function dummy:long () {return p;} # alias with a condition probe alias0 = begin if (3) {p=1} # alias with a kernel-variable condition -- not valid probe alias1 = kernel.function("vfs_read").return if (0) { if ($return) {p=0} } # alias with a function-call condition probe blias0 = timer.s(1) if (1 /* dummy() */) {p=10} # multiple probe point with conditions probe alias2 = alias0 if (1), alias1 if (-1) {p=2} # wildcard with a global-variable condition probe *lias0 if (p) {print(p)} # multi level alias with a condition probe alias2 if(4) {print(p)} systemtap-2.3/testsuite/semok/twentyone.stp000077500000000000000000000012321217430427200213450ustar00rootroot00000000000000#! stap -p2 probe abcdefgabc = begin { printf("in abcdefabc\n") } probe a* { printf("in a*\n") } probe a*c { printf("in a*c\n") } probe a*ab* { printf("in a*ab*\n") } probe a*bc* { printf("in a*bc*\n") } probe ab*fg*bc { printf("in ab*fg*bc*\n") } probe ab*fg*ab* { printf("in ab*fg*ab*\n") } probe ab*fg*bc* { printf("in ab*fg*bc*\n") } probe *c { printf("in *c\n") } probe *abc* { printf("in *abc*\n") } probe *def* { printf("in *def*\n") } probe *bc*bc { printf("in *bc*bc\n") } probe *abc*bc { printf("in *abc*bc\n") } probe *bc*ab* { printf("in *bc*ab*\n") } probe *bc*bc* { printf("in *bc*bc*\n") } probe *bc*fg*c { printf("in *bc*fg*c\n") } systemtap-2.3/testsuite/semok/twentyseven.stp000077500000000000000000000006231217430427200217070ustar00rootroot00000000000000#! stap -p2 probe foo.a = kernel.function("sys_read") /* some */ ! /* sufficient */ , kernel.function("no_such_function") { "foo.a" } probe foo.b = module("*scsi*").function("no_such_thing") /* none */ ? , module("*scsi*").function("*queue*") /* some */ ! , /* suff'nt */ module("no_such_module").function("no_such_function") { "foo.b" } probe foo.* { } systemtap-2.3/testsuite/semok/twentysix.stp000077500000000000000000000001231217430427200213650ustar00rootroot00000000000000#! stap -p2 probe begin,begin(10),end,end(10),error,error(10) { println (pp()) } systemtap-2.3/testsuite/semok/twentythree.stp000077500000000000000000000001401217430427200216700ustar00rootroot00000000000000#! stap -p2 global c, a = 1 global b = "hello", d probe begin { print (c = a) print (d = b) } systemtap-2.3/testsuite/semok/twentytwo.stp000077500000000000000000000005071217430427200214010ustar00rootroot00000000000000#! stap -p2 probe foo.a = kernel.function("no_such_function")?, never { } probe foo.* { } probe baz.a = kernel.function("no_such_function") { } probe baz.* ? { } probe bar = kernel.function("no_such_function") { } probe bar ? { } probe bar3 = kernel.function("no_such_function") { } probe bar2 = bar3 { } probe bar2 ? { } systemtap-2.3/testsuite/semok/two.stp000077500000000000000000000002221217430427200201200ustar00rootroot00000000000000#! stap -p2 global bar, baz function koo (p) { baz [p, "p", p] ++; return p + 2; } probe end { bar = 2 + koo (4); foo = bar + koo; } systemtap-2.3/testsuite/semok/utrace01.stp000077500000000000000000000001251217430427200207350ustar00rootroot00000000000000#! stap -p2 # process path doesn't need to be absolute probe process("cat").end { } systemtap-2.3/testsuite/sys/000077500000000000000000000000001217430427200162605ustar00rootroot00000000000000systemtap-2.3/testsuite/sys/sdt.h000066400000000000000000000340441217430427200172300ustar00rootroot00000000000000/* This wrapper is used by testsuite files that do #include "sys/sdt.h". We get either the current sys/sdt.h, or sdt-compat.h. */ #if defined STAP_SDT_V1 || defined STAP_SDT_V2 #include /* Also defined in "sdt_types.h" Defined here for systemtap-testsuite */ #define UPROBE1_TYPE 0x31425250 /* "PRB1" (little-endian) */ #define UPROBE2_TYPE 0x32425055 /* "UPB2" */ #define KPROBE2_TYPE 0x3242504b /* "KPB2" */ #ifdef __LP64__ #define STAP_PROBE_ADDR(arg) "\t.quad " arg #elif defined (__BIG_ENDIAN__) #define STAP_PROBE_ADDR(arg) "\t.long 0\n\t.long " arg #else #define STAP_PROBE_ADDR(arg) "\t.long " arg #endif /* Allocated section needs to be writable when creating pic shared objects because we store relocatable addresses in them. We used to make this read only for non-pic executables, but the new semaphore support relies on having a writable .probes section to put the enabled variables in. */ #define ALLOCSEC "\"aw\"" /* An allocated section .probes that holds the probe names and addrs. */ #if defined STAP_SDT_V1 #define STAP_UPROBE_GUARD UPROBE1_TYPE #define STAP_TYPE(t) __typeof__((t)) #define STAP_CAST(t) t #define STAP_PROBE_DATA_(provider,probe,guard,arg,arg_format,args,semaphore) \ __asm__ volatile (".section .probes," ALLOCSEC "\n" \ "\t.balign 8\n" \ "1:\n\t.asciz " #probe "\n" \ "\t.balign 4\n" \ "\t.int " #guard "\n" \ "\t.balign 8\n" \ STAP_PROBE_ADDR("1b\n") \ "\t.balign 8\n" \ STAP_PROBE_ADDR(#arg "\n") \ "\t.int 0\n" \ "\t.previous\n") #elif defined STAP_SDT_V2 || ! defined STAP_SDT_V1 #define STAP_UPROBE_GUARD UPROBE2_TYPE #define STAP_TYPE(t) size_t #define STAP_CAST(t) (size_t) (t) #define STAP_PROBE_DATA_(provider,probe,guard,argc,arg_format,args,semaphore) \ __asm__ volatile (".section .probes," ALLOCSEC "\n" \ "\t.balign 8\n" \ "\t.int " #guard "\n" \ "\t.balign 8\n" \ STAP_PROBE_ADDR ("1f\n") \ "\t.balign 8\n" \ STAP_PROBE_ADDR ("2f\n") \ "\t.balign 8\n" \ STAP_PROBE_ADDR (#argc "\n") \ "\t.balign 8\n" \ STAP_PROBE_ADDR("3f\n") \ "\t.balign 8\n" \ STAP_PROBE_ADDR("4f\n") \ "\t.balign 8\n" \ STAP_PROBE_ADDR(semaphore "\n") \ "\t.balign 8\n" \ "3:\n\t.asciz " arg_format "\n" \ "\t.balign 8\n" \ "2:\n\t.asciz " #provider "\n" \ "\t.balign 8\n" \ "1:\n\t.asciz " #probe "\n" \ "\t.previous\n" :: __stap_ ## args) #endif #if defined STAP_HAS_SEMAPHORES #if defined STAP_SDT_V1 #define STAP_PROBE_DATA(provider,probe,guard,argc,arg_format,args) \ STAP_PROBE_DATA_(#provider,#probe,guard,argc,#arg_format,args,#probe "_semaphore") #elif defined STAP_SDT_V2 || ! defined STAP_SDT_V1 #define STAP_PROBE_DATA(provider,probe,guard,argc,arg_format,args) \ STAP_PROBE_DATA_(#provider,#probe,guard,argc,#arg_format,args,#provider "_" #probe "_semaphore") #endif #else #define STAP_PROBE_DATA(provider,probe,guard,argc,arg_format,args) \ STAP_PROBE_DATA_(#provider,#probe,guard,argc,#arg_format,args,"") #endif /* Taking the address of a local label and/or referencing alloca prevents the containing function from being inlined, which keeps the parameters visible. */ #if __GNUC__ == 4 && __GNUC_MINOR__ <= 1 #include #define STAP_UNINLINE alloca((size_t)0) #else #define STAP_UNINLINE #endif #if defined __x86_64__ || defined __i386__ || defined __powerpc__ || defined __arm__ || defined __sparc__ #define STAP_NOP "\tnop " #else #define STAP_NOP "\tnop 0 " #endif #ifndef STAP_SDT_VOLATILE /* allow users to override */ #if (__GNUC__ >= 4 && __GNUC_MINOR__ >= 5 \ || (defined __GNUC_RH_RELEASE__ \ && __GNUC__ == 4 && __GNUC_MINOR__ == 4 && __GNUC_PATCHLEVEL__ >= 3 \ && (__GNUC_PATCHLEVEL__ > 3 || __GNUC_RH_RELEASE__ >= 10))) #define STAP_SDT_VOLATILE #else #define STAP_SDT_VOLATILE volatile #endif #endif /* https://bugzilla.redhat.com/show_bug.cgi?id=608768 / http://gcc.gnu.org/PR44707 indicate that "g" is a good general register constraint for these operands, except on AUTO_INC_DEC targets. Let's prefer "g" on fixed compilers and on other architectures. The #if monstrosity was coded by Jakub Jalinek. */ #if defined (__i386__) || defined (__x86_64__) \ || defined (__sparc__) || defined (__s390__) \ || (__GNUC__ > 4) \ || (__GNUC__ == 4 \ && (__GNUC_MINOR__ >= 6 \ || (defined __GNUC_RH_RELEASE__ \ && (__GNUC_MINOR__ > 4 \ || (__GNUC_MINOR__ == 4 \ && (__GNUC_PATCHLEVEL__ > 4 \ || (__GNUC_PATCHLEVEL__ == 4 \ && __GNUC_RH_RELEASE__ >= 9))))))) #define STAP_G_CONSTRAINT "g" #else #define STAP_G_CONSTRAINT "nro" #endif /* variadic macro args not allowed by -ansi -pedantic so... */ /* Use "ron" constraint as "g" constraint sometimes gives an auto increment operand */ #define __stap_arg0 #define __stap_arg1 STAP_G_CONSTRAINT(arg1) #define __stap_arg2 STAP_G_CONSTRAINT(arg1), STAP_G_CONSTRAINT(arg2) #define __stap_arg3 STAP_G_CONSTRAINT(arg1), STAP_G_CONSTRAINT(arg2), STAP_G_CONSTRAINT(arg3) #define __stap_arg4 STAP_G_CONSTRAINT(arg1), STAP_G_CONSTRAINT(arg2), STAP_G_CONSTRAINT(arg3), STAP_G_CONSTRAINT(arg4) #define __stap_arg5 STAP_G_CONSTRAINT(arg1), STAP_G_CONSTRAINT(arg2), STAP_G_CONSTRAINT(arg3), STAP_G_CONSTRAINT(arg4), STAP_G_CONSTRAINT(arg5) #define __stap_arg6 STAP_G_CONSTRAINT(arg1), STAP_G_CONSTRAINT(arg2), STAP_G_CONSTRAINT(arg3), STAP_G_CONSTRAINT(arg4), STAP_G_CONSTRAINT(arg5), STAP_G_CONSTRAINT(arg6) #define __stap_arg7 STAP_G_CONSTRAINT(arg1), STAP_G_CONSTRAINT(arg2), STAP_G_CONSTRAINT(arg3), STAP_G_CONSTRAINT(arg4), STAP_G_CONSTRAINT(arg5), STAP_G_CONSTRAINT(arg6), STAP_G_CONSTRAINT(arg7) #define __stap_arg8 STAP_G_CONSTRAINT(arg1), STAP_G_CONSTRAINT(arg2), STAP_G_CONSTRAINT(arg3), STAP_G_CONSTRAINT(arg4), STAP_G_CONSTRAINT(arg5), STAP_G_CONSTRAINT(arg6), STAP_G_CONSTRAINT(arg7), STAP_G_CONSTRAINT(arg8) #define __stap_arg9 STAP_G_CONSTRAINT(arg1), STAP_G_CONSTRAINT(arg2), STAP_G_CONSTRAINT(arg3), STAP_G_CONSTRAINT(arg4), STAP_G_CONSTRAINT(arg5), STAP_G_CONSTRAINT(arg6), STAP_G_CONSTRAINT(arg7), STAP_G_CONSTRAINT(arg8), STAP_G_CONSTRAINT(arg9) #define __stap_arg10 STAP_G_CONSTRAINT(arg1), STAP_G_CONSTRAINT(arg2), STAP_G_CONSTRAINT(arg3), STAP_G_CONSTRAINT(arg4), STAP_G_CONSTRAINT(arg5), STAP_G_CONSTRAINT(arg6), STAP_G_CONSTRAINT(arg7), STAP_G_CONSTRAINT(arg8), STAP_G_CONSTRAINT(arg9), STAP_G_CONSTRAINT(arg10) #if defined STAP_SDT_V1 #define STAP_PROBE_POINT(provider,probe,argc,arg_format,args) \ STAP_UNINLINE; \ STAP_PROBE_DATA(provider,probe,STAP_UPROBE_GUARD,2f,nil,nil); \ __asm__ volatile ("2:\n" STAP_NOP "/* " arg_format " */" :: __stap_ ## args); #define STAP_PROBE(provider,probe) \ do { \ STAP_PROBE_DATA(provider,probe,STAP_UPROBE_GUARD,2f,nil,nil); \ __asm__ volatile ("2:\n" STAP_NOP); \ } while (0) #elif defined STAP_SDT_V2 || ! defined STAP_SDT_V1 #define STAP_PROBE_POINT(provider,probe,argc,arg_format,args) \ STAP_UNINLINE; \ STAP_PROBE_DATA(provider,probe,STAP_UPROBE_GUARD,argc,arg_format,args); \ __asm__ volatile ("4:\n" STAP_NOP); #define STAP_PROBE(provider,probe) \ do { \ STAP_PROBE_DATA(provider,probe,STAP_UPROBE_GUARD,0,"",arg0); \ __asm__ volatile ("4:\n" STAP_NOP); \ } while (0) #endif #define STAP_PROBE1(provider,probe,parm1) \ do { STAP_SDT_VOLATILE STAP_TYPE(parm1) arg1 = STAP_CAST(parm1); \ STAP_PROBE_POINT(provider,probe, 1, "%0", arg1) \ } while (0) #define STAP_PROBE2(provider,probe,parm1,parm2) \ do { STAP_SDT_VOLATILE STAP_TYPE(parm1) arg1 = STAP_CAST(parm1); \ STAP_SDT_VOLATILE STAP_TYPE(parm2) arg2 = STAP_CAST(parm2); \ STAP_PROBE_POINT(provider,probe, 2, "%0 %1", arg2); \ } while (0) #define STAP_PROBE3(provider,probe,parm1,parm2,parm3) \ do { STAP_SDT_VOLATILE STAP_TYPE(parm1) arg1 = STAP_CAST(parm1); \ STAP_SDT_VOLATILE STAP_TYPE(parm2) arg2 = STAP_CAST(parm2); \ STAP_SDT_VOLATILE STAP_TYPE(parm3) arg3 = STAP_CAST(parm3); \ STAP_PROBE_POINT(provider,probe, 3, "%0 %1 %2", arg3); \ } while (0) #define STAP_PROBE4(provider,probe,parm1,parm2,parm3,parm4) \ do { STAP_SDT_VOLATILE STAP_TYPE(parm1) arg1 = STAP_CAST(parm1); \ STAP_SDT_VOLATILE STAP_TYPE(parm2) arg2 = STAP_CAST(parm2); \ STAP_SDT_VOLATILE STAP_TYPE(parm3) arg3 = STAP_CAST(parm3); \ STAP_SDT_VOLATILE STAP_TYPE(parm4) arg4 = STAP_CAST(parm4); \ STAP_PROBE_POINT(provider,probe, 4, "%0 %1 %2 %3", arg4); \ } while (0) #define STAP_PROBE5(provider,probe,parm1,parm2,parm3,parm4,parm5) \ do { STAP_SDT_VOLATILE STAP_TYPE(parm1) arg1 = STAP_CAST(parm1); \ STAP_SDT_VOLATILE STAP_TYPE(parm2) arg2 = STAP_CAST(parm2); \ STAP_SDT_VOLATILE STAP_TYPE(parm3) arg3 = STAP_CAST(parm3); \ STAP_SDT_VOLATILE STAP_TYPE(parm4) arg4 = STAP_CAST(parm4); \ STAP_SDT_VOLATILE STAP_TYPE(parm5) arg5 = STAP_CAST(parm5); \ STAP_PROBE_POINT(provider,probe, 5, "%0 %1 %2 %3 %4", arg5); \ } while (0) #define STAP_PROBE6(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6) \ do { STAP_SDT_VOLATILE STAP_TYPE(parm1) arg1 = STAP_CAST(parm1); \ STAP_SDT_VOLATILE STAP_TYPE(parm2) arg2 = STAP_CAST(parm2); \ STAP_SDT_VOLATILE STAP_TYPE(parm3) arg3 = STAP_CAST(parm3); \ STAP_SDT_VOLATILE STAP_TYPE(parm4) arg4 = STAP_CAST(parm4); \ STAP_SDT_VOLATILE STAP_TYPE(parm5) arg5 = STAP_CAST(parm5); \ STAP_SDT_VOLATILE STAP_TYPE(parm6) arg6 = STAP_CAST(parm6); \ STAP_PROBE_POINT(provider,probe, 6, "%0 %1 %2 %3 %4 %5", arg6); \ } while (0) #define STAP_PROBE7(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ do { STAP_SDT_VOLATILE STAP_TYPE(parm1) arg1 = STAP_CAST(parm1); \ STAP_SDT_VOLATILE STAP_TYPE(parm2) arg2 = STAP_CAST(parm2); \ STAP_SDT_VOLATILE STAP_TYPE(parm3) arg3 = STAP_CAST(parm3); \ STAP_SDT_VOLATILE STAP_TYPE(parm4) arg4 = STAP_CAST(parm4); \ STAP_SDT_VOLATILE STAP_TYPE(parm5) arg5 = STAP_CAST(parm5); \ STAP_SDT_VOLATILE STAP_TYPE(parm6) arg6 = STAP_CAST(parm6); \ STAP_SDT_VOLATILE STAP_TYPE(parm7) arg7 = STAP_CAST(parm7); \ STAP_PROBE_POINT(provider,probe, 7, "%0 %1 %2 %3 %4 %5 %6", arg7); \ } while (0) #define STAP_PROBE8(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \ do { STAP_SDT_VOLATILE STAP_TYPE(parm1) arg1 = STAP_CAST(parm1); \ STAP_SDT_VOLATILE STAP_TYPE(parm2) arg2 = STAP_CAST(parm2); \ STAP_SDT_VOLATILE STAP_TYPE(parm3) arg3 = STAP_CAST(parm3); \ STAP_SDT_VOLATILE STAP_TYPE(parm4) arg4 = STAP_CAST(parm4); \ STAP_SDT_VOLATILE STAP_TYPE(parm5) arg5 = STAP_CAST(parm5); \ STAP_SDT_VOLATILE STAP_TYPE(parm6) arg6 = STAP_CAST(parm6); \ STAP_SDT_VOLATILE STAP_TYPE(parm7) arg7 = STAP_CAST(parm7); \ STAP_SDT_VOLATILE STAP_TYPE(parm8) arg8 = STAP_CAST(parm8); \ STAP_PROBE_POINT(provider,probe, 8, "%0 %1 %2 %3 %4 %5 %6 %7", arg8); \ } while (0) #define STAP_PROBE9(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \ do { STAP_SDT_VOLATILE STAP_TYPE(parm1) arg1 = STAP_CAST(parm1); \ STAP_SDT_VOLATILE STAP_TYPE(parm2) arg2 = STAP_CAST(parm2); \ STAP_SDT_VOLATILE STAP_TYPE(parm3) arg3 = STAP_CAST(parm3); \ STAP_SDT_VOLATILE STAP_TYPE(parm4) arg4 = STAP_CAST(parm4); \ STAP_SDT_VOLATILE STAP_TYPE(parm5) arg5 = STAP_CAST(parm5); \ STAP_SDT_VOLATILE STAP_TYPE(parm6) arg6 = STAP_CAST(parm6); \ STAP_SDT_VOLATILE STAP_TYPE(parm7) arg7 = STAP_CAST(parm7); \ STAP_SDT_VOLATILE STAP_TYPE(parm8) arg8 = STAP_CAST(parm8); \ STAP_SDT_VOLATILE STAP_TYPE(parm9) arg9 = STAP_CAST(parm9); \ STAP_PROBE_POINT(provider,probe, 9, "%0 %1 %2 %3 %4 %5 %6 %7 %8", arg9); \ } while (0) #define STAP_PROBE10(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \ do { STAP_SDT_VOLATILE STAP_TYPE(parm1) arg1 = parm1; \ STAP_SDT_VOLATILE STAP_TYPE(parm2) arg2 = parm2; \ STAP_SDT_VOLATILE STAP_TYPE(parm3) arg3 = parm3; \ STAP_SDT_VOLATILE STAP_TYPE(parm4) arg4 = parm4; \ STAP_SDT_VOLATILE STAP_TYPE(parm5) arg5 = parm5; \ STAP_SDT_VOLATILE STAP_TYPE(parm6) arg6 = parm6; \ STAP_SDT_VOLATILE STAP_TYPE(parm7) arg7 = parm7; \ STAP_SDT_VOLATILE STAP_TYPE(parm8) arg8 = parm8; \ STAP_SDT_VOLATILE STAP_TYPE(parm9) arg9 = parm9; \ STAP_SDT_VOLATILE STAP_TYPE(parm10) arg10 = parm10; \ STAP_PROBE_POINT(provider,probe, 10, "%0 %1 %2 %3 %4 %5 %6 %7 %8 %9", arg10); \ } while (0) #define DTRACE_PROBE(provider,probe) \ STAP_PROBE(provider,probe) #define DTRACE_PROBE1(provider,probe,parm1) \ STAP_PROBE1(provider,probe,parm1) #define DTRACE_PROBE2(provider,probe,parm1,parm2) \ STAP_PROBE2(provider,probe,parm1,parm2) #define DTRACE_PROBE3(provider,probe,parm1,parm2,parm3) \ STAP_PROBE3(provider,probe,parm1,parm2,parm3) #define DTRACE_PROBE4(provider,probe,parm1,parm2,parm3,parm4) \ STAP_PROBE4(provider,probe,parm1,parm2,parm3,parm4) #define DTRACE_PROBE5(provider,probe,parm1,parm2,parm3,parm4,parm5) \ STAP_PROBE5(provider,probe,parm1,parm2,parm3,parm4,parm5) #define DTRACE_PROBE6(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6) \ STAP_PROBE6(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6) #define DTRACE_PROBE7(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ STAP_PROBE7(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7) #define DTRACE_PROBE8(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \ STAP_PROBE8(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) #define DTRACE_PROBE9(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \ STAP_PROBE9(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) #define DTRACE_PROBE10(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \ STAP_PROBE10(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) #else # include_next #endif systemtap-2.3/testsuite/systemtap.apps/000077500000000000000000000000001217430427200204355ustar00rootroot00000000000000systemtap-2.3/testsuite/systemtap.apps/celsius-bt.stp000066400000000000000000000007621217430427200232440ustar00rootroot00000000000000probe python.function_entry { if (execname() == "python3") frame = python3_frame else frame = python2_frame %( $# >= 1 %? match_filename = @1 %: match_filename = "" %) for (i = 0; frame != 0; i++) { if (execname() == "python3") { python3_backtrace (frame, match_filename) frame = python3_iterate_over_frames (frame, i) } else { python2_backtrace (frame, match_filename) frame = python2_iterate_over_frames (frame, i) } } } systemtap-2.3/testsuite/systemtap.apps/celsius-var.stp000066400000000000000000000024001217430427200234160ustar00rootroot00000000000000probe python.function_entry { if (execname() == "python3") frame = python3_frame else frame = python2_frame %( $# >= 1 %? variable = @1 %: variable = "*" %) %( $# >= 2 %? match_filename = @2 %: match_filename = "" %) for (i = 0; frame != 0; i++) { if (execname() == "python3") python3_get_variable (frame, 1, variable, match_filename) else python2_get_variable (frame, 1, variable, match_filename) if (execname() == "python3") frame = python3_iterate_over_frames (frame, i) else frame = python2_iterate_over_frames (frame, i) } } probe python.function_return { if (execname() == "python3") frame = python3_frame else frame = python2_frame %( $# >= 1 %? variable = @1 %: variable = "*" %) %( $# >= 2 %? match_filename = @2 %: match_filename = "" %) for (i = 0; frame != 0; i++) { if (execname() == "python3") python3_get_variable (frame, 0, variable, match_filename) else python2_get_variable (frame, 0, variable, match_filename) if (execname() == "python3") frame = python3_iterate_over_frames (frame, i) else frame = python2_iterate_over_frames (frame, i) } } systemtap-2.3/testsuite/systemtap.apps/celsius.py000066400000000000000000000011361217430427200224570ustar00rootroot00000000000000#!/usr/bin/python import sys aglobal9 = 9 def celsius_to_farenheit(celsius): atuple = "a", "b", "c" alist = [1, 2, 3] aset = {1, 2, 3} adict = { 1 : "a", 2 : "b", 3 : "c" } nine = aglobal9 five = 5 thirty_two = 32 i = 1 return str((nine * celsius) / five + thirty_two) def main(): if (len(sys.argv) < 2): print ("Usage: " + sys.argv[0] + " Temp") return 1 celsius = int(sys.argv[1]) print (str(celsius) + " Celsius " + " is " + celsius_to_farenheit(celsius) + " Farenheit") return 0 if __name__ == "__main__": sys.exit(main()) systemtap-2.3/testsuite/systemtap.apps/java.exp000066400000000000000000000104271217430427200221000ustar00rootroot00000000000000set test "java" if {[catch { exec which javac } res]} { untested "$test - no javac" return } set test "singleparam" if {! [installtest_p]} then { untested $test; return } if {! [java_p]} then { untested $test; return } # Test per method probing catch { exec javac -d ./ $srcdir/$subdir/singleparam.java } err if {$err == "" && [file exists ./singleparam.class]} then { pass "$test compile" } else { fail "$test compile $err" } spawn stap $srcdir/$subdir/java.stp -c "java singleparam >/dev/null 2>&1" set ok 0 expect { -timeout 40 -re {printMessage\(int\)[^\r\n]*42\r\n} { incr ok; exp_continue} -re {printMessage\(long\)[^\r\n]*254775806\r\n} { incr ok; exp_continue } -re {printMessage\(double\)[^\r\n]*3\r\n} { incr ok; exp_continue } -re {printMessage\(float\)[^\r\n]*2345987\r\n} { incr ok; exp_continue } -re {printMessage\(byte\)[^\r\n]*10\r\n} { incr ok; exp_continue } -re {printMessage\(boolean\)[^\r\n]*1\r\n} { incr ok; exp_continue } -re {printMessage\(char\)[^\r\n]*97\r\n} { incr ok; exp_continue } -re {printMessage\(short\)[^\r\n]*14\r\n} { incr ok; exp_continue } timeout { fail "$test (timeout)" } } if {$ok == 8} then { pass "$test ($ok)" } else { fail "$test ($ok)" } catch {close}; catch {wait} catch {exec rm ./singleparam.class} set test "return" catch { exec javac -d ./ $srcdir/$subdir/returnstatement.java } err1 if {$err1 == "" && [file exists ./returnstatement.class]} then { pass "$test compile" } else { fail "$test compile $err1" } spawn stap $srcdir/$subdir/returnstatement.stp -c "java returnstatement >/dev/null 2>&1" set oka 0 expect { -timeout 40 -re {printMessage\(int\)[^\r\n]*42\ ret\r\n} { incr oka; exp_continue } -re {printMessage\(long\)[^\r\n]*254775806\ ret\r\n} { incr oka; exp_continue } -re {printMessage\(double\)[^\r\n]*3\ ret\r\n} { incr oka; exp_continue } -re {printMessage\(float\)[^\r\n]*2345987\ ret\r\n} { incr oka; exp_continue } -re {printMessage\(byte\)[^\r\n]*10\ ret\r\n} { incr oka; exp_continue } -re {printMessage\(boolean\)[^\r\n]*1\ ret\r\n} { incr oka; exp_continue } -re {printMessage\(char\)[^\r\n]*97\ ret\r\n} { incr oka; exp_continue } -re {printMessage\(short\)[^\r\n]*14\ ret\r\n} { incr oka; exp_continue } timeout { fail "$test unexpected timeout" } } if {$oka == 8} then { pass "$test ($oka)" } else { fail "$test ($oka)" } catch {close}; catch {wait} catch {exec rm ./returnstatement.class} set test "multiparams" catch { exec javac -d ./ $srcdir/$subdir/multiparams.java } err2 if {$err2 == "" && [file exists ./multiparams.class]} then { pass "$test compile" } else { fail "$test compile $err2" } spawn stap $srcdir/$subdir/multiparams.stp -c "java multiparams >/dev/null 2>&1" set okb 0 expect { -timeout 40 -re {printMessage1\(int\)[^\r\n]*42\r\n} { incr okb; exp_continue } -re {printMessage2\(long\,\ int\)[^\r\n]*254775806\ 42\r\n} { incr okb; exp_continue } -re {printMessage3\(double,\ long,\ int\)[^\r\n]*3\ 254775806\ 42\r\n} { incr okb; exp_continue } -re {printMessage4\(float,\ double,\ long,\ int\)[^\r\n]*2345987\ 3\ 254775806\ 42\r\n} { incr okb; exp_continue } -re {printMessage5\(byte,\ float,\ double,\ long,\ int\)[^\r\n]*10\ 2345987\ 3\ 254775806\ 42\r\n} { incr okb; exp_continue } -re {printMessage6\(boolean,\ byte,\ float,\ double,\ long,\ int\)[^\r\n]*1\ 10\ 2345987\ 3\ 254775806\ 42\r\n} { incr okb; exp_continue } -re {printMessage7\(char,\ boolean,\ byte,\ float,\ double,\ long,\ int\)[^\r\n]*97\ 1\ 10\ 2345987\ 3\ 254775806\ 42\r\n} { incr okb; exp_continue } -re {printMessage8\(short,\ char,\ boolean,\ byte,\ float,\ double,\ long,\ int\)[^\r\n]*14\ 97\ 1\ 10\ 2345987\ 3\ 254775806\ 42\r\n} { incr okb; exp_continue } -re {printMessage9\(short,\ short,\ char,\ boolean,\ byte,\ float,\ double,\ long,\ int\)[^\r\n]*14\ 14\ 97\ 1\ 10\ 2345987\ 3\ 254775806\ 42\r\n} { incr okb; exp_continue } -re {printMessage10\(short,\ short,\ short,\ char,\ boolean,\ byte,\ float,\ double,\ long,\ int\)[^\r\n]*14\ 14\ 14\ 97\ 1\ 10\ 2345987\ 3\ 254775806\ 42\r\n} { incr okb; exp_continue } timeout { fail "$test unexpected timeout" } } if {$okb == 10} then { pass "$test ($okb)" } else { fail "$test ($okb)" } catch {close}; catch {wait} catch {exec rm ./multiparams.class} systemtap-2.3/testsuite/systemtap.apps/java.stp000066400000000000000000000016521217430427200221120ustar00rootroot00000000000000#!/usr/bin/env stap probe java("singleparam").class("singleparam").method("printMessage(int)") { printf("%s %d\n", pn(), $arg1) } probe java("singleparam").class("singleparam").method("printMessage(long)") { printf("%s %d\n", pn(), $arg1) } probe java("singleparam").class("singleparam").method("printMessage(double)") { printf("%s %d\n", pn(), $arg1) } probe java("singleparam").class("singleparam").method("printMessage(float)") { printf("%s %d\n", pn(), $arg1) } probe java("singleparam").class("singleparam").method("printMessage(byte)") { printf("%s %d\n", pn(), $arg1) } probe java("singleparam").class("singleparam").method("printMessage(boolean)") { printf("%s %d\n", pn(), $arg1) } probe java("singleparam").class("singleparam").method("printMessage(char)") { printf("%s %d\n", pn(), $arg1) } probe java("singleparam").class("singleparam").method("printMessage(short)") { printf("%s %d\n", pn(), $arg1) } systemtap-2.3/testsuite/systemtap.apps/multiparams.java000066400000000000000000000027421217430427200236430ustar00rootroot00000000000000class multiparams { public static void printMessage1(int a){} public static void printMessage2(long a, int b){} public static void printMessage3(double a, long b, int c){} public static void printMessage4(float a, double b, long c, int d){} public static void printMessage5(byte a, float b, double c, long d, int e){} public static void printMessage6(boolean a, byte b, float c, double d, long e, int f){} public static void printMessage7(char a, boolean b, byte c, float d, double e, long f, int g){} public static void printMessage8(short a, char b, boolean c, byte d, float e, double f, long g, int h){} public static void printMessage9(short a, short b, char c, boolean d, byte e, float f, double g, long h, int i){} public static void printMessage10(short a, short b, short c, char d, boolean e, byte f, float g, double h, long i, int j){} public static void main(String[] args) throws InterruptedException { Thread.sleep(20000); final int i = 42; final long j = 254775806; final double k = 3.14; final float l = 2345987; final byte n = 10; final boolean o = true; final char p = 'a'; final short q = 14; printMessage1(i); printMessage2(j, i); printMessage3(k, j, i); printMessage4(l, k, j, i); printMessage5(n, l, k, j, i); printMessage6(o, n, l, k, j, i); printMessage7(p, o, n, l, k, j, i); printMessage8(q, p, o, n, l, k, j, i); printMessage9(q, q, p, o, n, l, k, j, i); printMessage10(q, q, q, p, o, n, l, k, j, i); } } systemtap-2.3/testsuite/systemtap.apps/multiparams.stp000066400000000000000000000035611217430427200235300ustar00rootroot00000000000000probe java("multiparams").class("multiparams").method("printMessage1(int)") { printf("%s %d\n", pn(), $arg1) } probe java("multiparams").class("multiparams").method("printMessage2(long, int)") { printf("%s %d %d\n", pn(), $arg1, $arg2) } probe java("multiparams").class("multiparams").method("printMessage3(double, long, int)") { printf("%s %d %d %d\n", pn(), $arg1, $arg2, $arg3) } probe java("multiparams").class("multiparams").method("printMessage4(float, double, long, int)") { printf("%s %d %d %d %d\n", pn(), $arg1, $arg2, $arg3, $arg4) } probe java("multiparams").class("multiparams").method("printMessage5(byte, float, double, long, int)") { printf("%s %d %d %d %d %d\n", pn(), $arg1, $arg2, $arg3, $arg4, $arg5) } probe java("multiparams").class("multiparams").method("printMessage6(boolean, byte, float, double, long, int)") { printf("%s %d %d %d %d %d %d\n", pn(), $arg1, $arg2, $arg3, $arg4, $arg5, $arg6) } probe java("multiparams").class("multiparams").method("printMessage7(char, boolean, byte, float, double, long, int)") { printf("%s %d %d %d %d %d %d %d\n", pn(), $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7) } probe java("multiparams").class("multiparams").method("printMessage8(short, char, boolean, byte, float, double, long, int)") { printf("%s %d %d %d %d %d %d %d %d\n", pn(), $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8) } probe java("multiparams").class("multiparams").method("printMessage9(short, short, char, boolean, byte, float, double, long, int)") { printf("%s %d %d %d %d %d %d %d %d %d\n", pn(), $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8, $arg9) } probe java("multiparams").class("multiparams").method("printMessage10(short, short, short, char, boolean, byte, float, double, long, int)") { printf("%s %d %d %d %d %d %d %d %d %d %d\n", pn(), $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8, $arg9, $arg10) } systemtap-2.3/testsuite/systemtap.apps/mysql.exp000066400000000000000000000251371217430427200223300ustar00rootroot00000000000000set test "mysql" # Test sdt support in mysql. global env if {! [info exists env(SYSTEMTAP_TESTAPPS)] || ( ! [string match "mysql" $env(SYSTEMTAP_TESTAPPS)] && ! [string match "all" $env(SYSTEMTAP_TESTAPPS)])} { untested "$test sdt app" return } ########## Create /tmp/stap-mysql.stp ########## set msdata "[pwd]/stap-mysql" set mysqlrelease "mysql-5.5.24" set mysqldir "[pwd]/mysql/install/" set testsuite "[pwd]" set fp [open "$testsuite/stap-mysql.stp" "w"] puts $fp " probe process(@1).mark(\"connection__start\") { arg2 = user_string(\$arg2) arg3 = user_string(\$arg3) printf(\"%s %#x %s %s\\n\",\"connection__start\", \$arg1, arg2, arg3); } probe process(@1).mark(\"connection__done\") { printf(\"%s %#x %#x \\n\",\"connection__done\", \$arg1, \$arg2); } probe process(@1).mark(\"command__start\") { arg3 = user_string(\$arg3) arg4 = user_string(\$arg4) printf(\"%s %#x %#x %s %s\\n\",\"command__start\", \$arg1, \$arg2, arg3, arg4); } probe process(@1).mark(\"command__done\") { printf(\"%s %#x\\n\",\"command__done\", \$arg1); } probe process(@1).mark(\"query__start\") { arg1 = user_string(\$arg1) arg3 = user_string(\$arg3) arg4 = user_string(\$arg4) arg5 = user_string(\$arg5) printf(\"%s %s %#x %s %s %s\\n\",\"query__start\", arg1, \$arg2, arg3, arg4, arg5); } probe process(@1).mark(\"query__done\") { printf(\"%s %#x\\n\",\"query__done\", \$arg1); } probe process(@1).mark(\"query__parse__start\") { arg1 = user_string(\$arg1) printf(\"%s %s\\n\",\"query__parse__start\", arg1); } probe process(@1).mark(\"query__parse__done\") { printf(\"%s %#x\\n\",\"query__parse__done\", \$arg1); } probe process(@1).mark(\"query__cache__hit\") { arg1=user_string(\$arg1) arg2=user_string(\$arg2) printf(\"%s %s %s \\n\",\"query__cache__hit\", arg1, arg2); } probe process(@1).mark(\"query__cache__miss\") { arg1=user_string(\$arg1) printf(\"%s %s\\n\",\"query__cache__miss\", arg1); } probe process(@1).mark(\"query__exec__start\") { arg1=user_string(\$arg1) arg3=user_string(\$arg3) arg4=user_string(\$arg4) arg5=user_string(\$arg5) printf(\"%s %s %#x %s %s %s\\n\",\"query__exec__start\", arg1, \$arg2, arg3, arg4, arg5); } probe process(@1).mark(\"query__exec__done\") { printf(\"%s %#x\\n\",\"query__exec__done\", \$arg1); } probe process(@1).mark(\"insert__row__start\") { arg1=user_string(\$arg1) arg2=user_string(\$arg2) printf(\"%s %s %s \\n\",\"insert__row__start\", arg1, arg2); } probe process(@1).mark(\"insert__row__done\") { printf(\"%s %#x\\n\",\"insert__row__done\", \$arg1); } probe process(@1).mark(\"update__row__start\") { arg1=user_string(\$arg1) arg2=user_string(\$arg2) printf(\"%s %s %s \\n\",\"update__row__start\", arg1, arg2); } probe process(@1).mark(\"update__row__done\") { printf(\"%s %#x\\n\",\"update__row__done\", \$arg1); } probe process(@1).mark(\"delete__row__start\") { arg1=user_string(\$arg1) arg2=user_string(\$arg2) printf(\"%s %s %s \\n\",\"delete__row__start\", arg1, arg2); } probe process(@1).mark(\"delete__row__done\") { printf(\"%s %#x\\n\",\"delete__row__done\", \$arg1); } probe process(@1).mark(\"handler__rdlock__start\") { arg1=user_string(\$arg1) arg2=user_string(\$arg2) printf(\"%s %s %s \\n\",\"handler__rdlock__start\", arg1, arg2); } probe process(@1).mark(\"handler__wrlock__start\") { arg1=user_string(\$arg1) arg2=user_string(\$arg2) printf(\"%s %s %s \\n\",\"handler__wrlock__start\", arg1, arg2); } probe process(@1).mark(\"handler__unlock__start\") { arg1=user_string(\$arg1) arg2=user_string(\$arg2) printf(\"%s %s %s \\n\",\"handler__unlock__start\", arg1, arg2); } probe process(@1).mark(\"handler__rdlock__done\") { printf(\"%s %#x\\n\",\"handler__rdlock__done\", \$arg1); } probe process(@1).mark(\"handler__wrlock__done\") { printf(\"%s %#x\\n\",\"handler__wrlock__done\", \$arg1); } probe process(@1).mark(\"handler__unlock__done\") { printf(\"%s %#x\\n\",\"handler__unlock__done\", \$arg1); } probe process(@1).mark(\"filesort__start\") { printf(\"%s %#x %#x \\n\",\"filesort__start\", \$arg1, \$arg2); } probe process(@1).mark(\"filesort__done\") { printf(\"%s %#x %#x \\n\",\"filesort__done\", \$arg1, \$arg2); } probe process(@1).mark(\"select__start\") { arg1=user_string(\$arg1) printf(\"%s %s\\n\",\"select__start\", arg1); } probe process(@1).mark(\"select__done\") { printf(\"%s %#x %#x \\n\",\"select__done\", \$arg1, \$arg2); } probe process(@1).mark(\"insert__start\") { arg1=user_string(\$arg1) printf(\"%s %s\\n\",\"insert__start\", arg1); } probe process(@1).mark(\"insert__done\") { printf(\"%s %#x %#x \\n\",\"insert__done\", \$arg1, \$arg2); } probe process(@1).mark(\"insert__select__start\") { arg1=user_string(\$arg1) printf(\"%s %s\\n\",\"insert__select__start\", arg1); } probe process(@1).mark(\"insert__select__done\") { printf(\"%s %#x %#x \\n\",\"insert__select__done\", \$arg1, \$arg2); } probe process(@1).mark(\"update__start\") { arg1=user_string(\$arg1) printf(\"%s %s\\n\",\"update__start\", arg1); } probe process(@1).mark(\"update__done\") { printf(\"%s %#x %#x %#x\\n\",\"update__done\", \$arg1, \$arg2, \$arg3); } probe process(@1).mark(\"multi__update__start\") { arg1=user_string(\$arg1) printf(\"%s %s\\n\",\"multi__update__start\", arg1); } probe process(@1).mark(\"multi__update__done\") { printf(\"%s %#x %#x %#x\\n\",\"multi__update__done\", \$arg1, \$arg2, \$arg3); } probe process(@1).mark(\"delete__start\") { arg1=user_string(\$arg1) printf(\"%s %s\\n\",\"delete__start\", arg1); } probe process(@1).mark(\"delete__done\") { printf(\"%s %#x %#x \\n\",\"delete__done\", \$arg1, \$arg2); } probe process(@1).mark(\"multi__delete__start\") { arg1=user_string(\$arg1) printf(\"%s %s\\n\",\"multi__delete__start\", arg1); } probe process(@1).mark(\"multi__delete__done\") { printf(\"%s %#x %#x \\n\",\"multi__delete__done\", \$arg1, \$arg2); } probe process(@1).mark(\"net__read__start\") { printf(\"%s \\n\",\"net__read__start\"); } probe process(@1).mark(\"net__read__done\") { printf(\"%s %#x %#x \\n\",\"net__read__done\", \$arg1, \$arg2); } probe process(@1).mark(\"net__write__start\") { printf(\"%s %#x\\n\",\"net__write__start\", \$arg1); } probe process(@1).mark(\"net__write__done\") { printf(\"%s %#x\\n\",\"net__write__done\", \$arg1); } " close $fp ########## Begin /tmp/stap-mysql.sh ########## set fp [open "$testsuite/stap-mysql.sh" "w"] puts $fp " ##### begin run_tests ##### function run_tests \{ /bin/rm -rf $testsuite/stap-mysql $mysqldir/scripts/mysql_install_db --basedir=$mysqldir --datadir=$msdata --user=\$(whoami) (cd $mysqldir/mysql-test # wait until mysql is running MOD=stapsdt_\$(date +%j%k%M%N | sed 's/ //') $env(SYSTEMTAP_PATH)/stap -m \$MOD -c \"$mysqldir/bin/mysqld --basedir=$mysqldir --datadir=$msdata --log-error=$msdata/mysql.log --pid-file=$msdata/mysql.pid --socket=$msdata/mysql.sock\" $testsuite/stap-mysql.stp $mysqldir/bin/mysqld >$testsuite/stap-mysql-markers.log 2>&1 & STAPPID=\$! for i in \$(seq 0 10) ; do if $mysqldir/bin/mysqladmin ping --socket=$msdata/mysql.sock then break; fi sleep 5 done for i in select join insert query do echo '##### ' \$i ./mysql-test-run.pl --force --extern socket=$msdata/mysql.sock \ --tmpdir=/tmp/,mysql --vardir=/tmp/,mysql --do-test=\$i done > $testsuite/stap-mysql.log ) ACQUIRE=\$(grep 'handler__unlock__start' $testsuite/stap-mysql-markers.log | wc -l) RELEASE=\$(grep 'handler__unlock__done' $testsuite/stap-mysql-markers.log | wc -l) COMMAND=\$(grep 'command__start' $testsuite/stap-mysql-markers.log | wc -l) QUERY=\$(grep 'query__start' $testsuite/stap-mysql-markers.log | wc -l) RDLOCK=\$(grep 'handler__rdlock__start' $testsuite/stap-mysql-markers.log | wc -l) SELECT=\$(grep 'select__start' $testsuite/stap-mysql-markers.log | wc -l) OKAY=\$(grep 'All.*tests were successful' $testsuite/stap-mysql.log | wc -l) echo ACQUIRE=\$ACQUIRE RELEASE=\$RELEASE COMMAND=\$COMMAND QUERY=\$QUERY RDLOCK=\$RDLOCK SELECT=\$SELECT OKAY=\$OKAY # ACQUIRE=10040 RELEASE=10040 COMMAND=11265 QUERY=11167 RDLOCK=5149 SELECT=2895 OKAY=0 if \[ \$ACQUIRE -gt 10000 -a \$RELEASE -gt 10000 -a \$COMMAND -gt 11200 -a \$QUERY -gt 11100 -a \$RDLOCK -gt 5100 -a \$SELECT -gt 2800 \] ; then echo PASS: mysql markers \$1 else echo FAIL: mysql markers \$1 fi if \[ \$OKAY -eq 4 \] ; then echo PASS: mysql tests \$1 else echo XFAIL: mysql tests \$1 fi mv $testsuite/stap-mysql.log $testsuite/stap-mysql-\$1.log cat $testsuite/stap-mysql-markers.log >> $testsuite/stap-mysql-\$1.log rm $testsuite/stap-mysql-markers.log $mysqldir/bin/mysqladmin shutdown -u root --socket=$testsuite/stap-mysql/mysql.sock kill -9 \$STAPPID kill -9 $testsuite/stap-mysql/mysql.pid \} ##### end run_tests ##### if \[ ! -r $mysqlrelease.tar.gz \] ; then wget -q http://downloads.mysql.com/archives/mysql-5.5/$mysqlrelease.tar.gz fi if \[ ! -r $mysqlrelease.tar.gz \] ; then echo FAIL: wget $mysqlrelease.tar.gz exit fi if \[ ! -d mysql/src \] ; then tar -x -z -f $mysqlrelease.tar.gz mkdir mysql mv $mysqlrelease mysql/src fi if \[ ! -d mysql/bld \] ; then mkdir -p mysql/bld cd mysql/bld cmake ../src/ -DENABLE_DTRACE=1 -DCMAKE_INSTALL_PREFIX=$mysqldir for i in \$(find . -name Makefile) ; do sed -i -e 's|^CXXFLAGS =|& -g -I $env(SYSTEMTAP_INCLUDES)|' \$i sed -i -e 's|^CFLAGS =|& -g -I $env(SYSTEMTAP_INCLUDES)|' \$i done fi J=\$(getconf _NPROCESSORS_CONF) # skip the 'make abi_check' step touch do_abi_check # mysql erroneously defines min/max which c++ limits (via sdt.h) also defines sed -i -e '/HAVE_DTRACE/i\\ #pragma push_macro(\"max\")\\ #pragma push_macro(\"min\")\\ #undef max\\ #undef min' -e '/endif.*PROBES_MYSQL_H/i\\ #pragma pop_macro(\"max\")\\ #pragma pop_macro(\"min\")' ../src/include/probes_mysql.h make -j\$J make install run_tests uprobe " ########## End /tmp/stap-mysql.sh ########## close $fp ########## /tmp/stap-mysql.sh does most of the work ########## verbose -log Running mysql testsuite spawn sh stap-mysql.sh 2>&1 expect { -timeout 1000 -re {PASS: [a-z_ ]+} { regexp " .*$" $expect_out(0,string) s; pass "$s"; exp_continue } -re {XFAIL: [a-z_ ]+} { regexp " .*$" $expect_out(0,string) s; xfail "$s"; exp_continue } -re {FAIL: [a-z_ ]+} { regexp " .*$" $expect_out(0,string) s; fail "$s"; exp_continue } -re {UNSUPPORTED: [a-zA-Z_/: ]+} { regexp " .*$" $expect_out(0,string) s; verbose -log "$s" unsupported "$s"; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if { $verbose == 0 } { catch {exec rm -rf $msdata} catch {exec rm -rf $testsuite/stap-mysql.stp $testsuite/stap-mysql.log \ $testsuite/stap-mysql-markers.log $testsuite/stap-mysql.sh $mysqlrelease.tar.gz} catch {exec rm -rf mysql} } systemtap-2.3/testsuite/systemtap.apps/postgres.exp000066400000000000000000000117021217430427200230220ustar00rootroot00000000000000set test "postgres" # Test sdt support in postgres. global env if {! [info exists env(SYSTEMTAP_TESTAPPS)] || ( ! [string match "postgres" $env(SYSTEMTAP_TESTAPPS)] && ! [string match "all" $env(SYSTEMTAP_TESTAPPS)])} { untested "$test sdt app" return } ########## Create /tmp/stap-postgres.stp ########## set pgdata "/tmp/stap-postgres" set postgresrelease "9.1.2" set postgresdir "[pwd]/postgresql-$postgresrelease/install/" set fp [open "$pgdata.stp" "w"] puts $fp " probe process(\"$postgresdir/bin/postgres\").mark(\"transaction__start\") { printf(\"%s %#x\\n\", \$\$name, \$arg1); } probe process(\"$postgresdir/bin/postgres\").mark(\"transaction__commit\") { printf(\"%s\\n\", \$\$name); } probe process(\"$postgresdir/bin/postgres\").mark(\"transaction__abort\") { printf(\"%s\\n\", \$\$name); } probe process(\"$postgresdir/bin/postgres\").mark(\"lock__wait__start\") { printf(\"%s %#x %#x\\n\", \$\$name, \$arg1, \$arg2); } probe process(\"$postgresdir/bin/postgres\").mark(\"lock__wait__done\") { printf(\"%s %#x %#x\\n\", \$\$name, \$arg1, \$arg2); } probe process(\"$postgresdir/bin/postgres\").mark(\"lwlock__wait__done\") { printf(\"%s %#x %#x\\n\", \$\$name, \$arg1, \$arg2); } probe process(\"$postgresdir/bin/postgres\").mark(\"lwlock__acquire\") { printf(\"%s %#x %#x\\n\", \$\$name, \$arg1, \$arg2); } probe process(\"$postgresdir/bin/postgres\").mark(\"lwlock__condacquire__fail\") { printf(\"%s %#x %#x\\n\", \$\$name, \$arg1, \$arg2); } probe process(\"$postgresdir/bin/postgres\").mark(\"lwlock__condacquire\") { printf(\"%s %#x %#x\\n\", \$\$name, \$arg1, \$arg2); } probe process(\"$postgresdir/bin/postgres\").mark(\"lwlock__release\") { printf(\"%s %#x\\n\", \$\$name, \$arg1); } " close $fp ########## Begin /tmp/stap-postgres.sh ########## set fp [open "$pgdata.sh" "w"] puts $fp " function run_tests \{ /bin/rm -rf $pgdata $postgresdir/bin/initdb $pgdata echo '$env(SYSTEMTAP_PATH)/stap -m \$(date +stapsdt_%j%k%M%N | sed 's/ //') -c \"$postgresdir/bin/postgres -D $pgdata\" $pgdata.stp >$pgdata-markers.log' $env(SYSTEMTAP_PATH)/stap -m \$(date +stapsdt_%j%k%M%N | sed 's/ //') -c \"$postgresdir/bin/postgres -D $pgdata\" $pgdata.stp >$pgdata-markers.log 2>&1 & STAPPID=\$! # wait until postgres is running for i in \$(seq 0 10) ; do if $postgresdir/bin/pg_ctl status -D $pgdata then break; fi sleep 5 done (cd $postgresdir/../src/test/regress/ make installcheck > $pgdata.log 2>&1) ACQUIRE=\$(grep 'lwlock__acquire 0x\[0-9\]* 0x\[0-9\]*' $pgdata-markers.log | wc -l) RELEASE=\$(grep 'lwlock__release 0x\[0-9\]*' $pgdata-markers.log | wc -l) START=\$(grep 'transaction__start 0x\[0-9\]*' $pgdata-markers.log | wc -l) COMMIT=\$(grep 'transaction__commit' $pgdata-markers.log | wc -l) OKAY=\$(grep 'test .*ok' $pgdata.log | wc -l) echo lwlock__acquire=\$ACQUIRE lwlock__release=\$RELEASE transaction__start=\$START transaction__commit=\$COMMIT test-ok=\$OKAY : 44873 75325 591 489 0 if \[ \$ACQUIRE -gt 40000 -a \$RELEASE -gt 70000 -a \$START -gt 500 -a \$COMMIT -gt 400 \] ; then echo PASS: postgres tests \$ACQUIRE/\$RELEASE/\$START/\$COMMIT else echo FAIL: postgres tests \$ACQUIRE/\$RELEASE/\$START/\$COMMIT fi if \[ \$OKAY -gt 100 \] ; then echo PASS: postgres markers \$OKAY else echo FAIL: postgres markers \$OKAY fi $postgresdir/bin/pg_ctl stop -D $pgdata kill \$STAPPID \} if \[ ! -r postgresql-$postgresrelease.tar.bz2 \] ; then wget -q http://ftp.postgresql.org/pub/source/v${postgresrelease}/postgresql-$postgresrelease.tar.bz2 fi if \[ ! -r postgresql-$postgresrelease.tar.bz2 \] ; then echo FAIL: wget $postgresrelease.tar.gz exit fi if \[ ! -d $postgresdir/../src/backend \] ; then tar -x -f postgresql-${postgresrelease}.tar.bz2 fi cd postgresql-${postgresrelease}/ # postgres 9.0.4 now seems to want build done from source dir # mkdir bld;cd bld ./configure --enable-dtrace --prefix=$postgresdir sed -i -e 's|^CFLAGS = -O2.*\$|& -g -I $env(SYSTEMTAP_INCLUDES)|' src/Makefile.global if \[ \$(uname -m) = ppc64 \] ; then sed -i -e 's|CFLAGS = |& -DSTAP_SDT_ARG_CONSTRAINT=nr |' src/Makefile.global fi J=\$(getconf _NPROCESSORS_CONF) make -j\$J make install run_tests " ########## End /tmp/stap-postgres.sh ########## close $fp ########## /tmp/stap-postgres.sh does most of the work ########## verbose -log Running postgres testsuite spawn sh $pgdata.sh 2>&1 expect { -timeout 1000 -re {FAIL: [a-z_ ]+} { regexp " .*$" $expect_out(0,string) s; fail "$s"; exp_continue } -re {PASS: [a-z_ ]+} { regexp " .*$" $expect_out(0,string) s; pass "$s"; exp_continue } -re {UNSUPPORTED: [a-zA-Z_/: ]+} { regexp " .*$" $expect_out(0,string) s; verbose -log "$s" unsupported "$s"; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if { $verbose == 0 } { catch {exec rm -rf $pgdata} catch {exec rm -rf $pgdata.stp $pgdata.log \ $pgdata-markers.log $pgdata.sh postgresql-${postgresrelease}.tar.bz2} catch {exec rm -rf postgresql-${postgresrelease}} } systemtap-2.3/testsuite/systemtap.apps/python.exp000066400000000000000000000141111217430427200224720ustar00rootroot00000000000000set test "python" # Test sdt support in python. global env if {! [info exists env(SYSTEMTAP_TESTAPPS)] || ( ! [string match "python" $env(SYSTEMTAP_TESTAPPS)] && ! [string match "all" $env(SYSTEMTAP_TESTAPPS)])} { untested "$test sdt app" return } set msdata "[pwd]/stap-python" set python2release "2.7.2" set python2dir "python2" set python3release "3.2.2" set python3dir "python3" set testsuite "[pwd]" ########## Begin /tmp/stap-python.sh ########## set fp [open "$testsuite/stap-python.sh" "w"] puts $fp " srcdir=`readlink -f \$1` if \[ ! -r Python-$python3release.tar.bz2 \] ; then wget -q http://python.org/ftp/python/$python2release/Python-$python2release.tar.bz2 wget -q http://python.org/ftp/python/$python3release/Python-$python3release.tar.bz2 fi if \[ ! -r Python-$python2release.tar.bz2 -o ! -r Python-$python3release.tar.bz2 \] ; then echo FAIL: wget Python-$python2release.tar.bz2 Python-$python3release.tar.bz2 exit fi if \[ ! -d $python2dir/src -a ! -d $python3dir/src \] ; then tar -x -j -f Python-$python2release.tar.bz2 tar -x -j -f Python-$python3release.tar.bz2 mkdir $python2dir mkdir $python3dir mv Python-$python2release $python2dir/src mv Python-$python3release $python3dir/src cd $testsuite/$python2dir/src patch -p1 -i \$srcdir/$python2dir.patch cd $testsuite/$python3dir/src patch -p1 -i \$srcdir/$python3dir.patch fi # Build python2 cd $testsuite/$python2dir if \[ ! -d bld \] ; then mkdir bld cd bld ../src/configure --with-dtrace --prefix=$testsuite/pyinstall for i in \$(find . -name Makefile) ; do sed -i -e 's|^CXXFLAGS =|& -g -I $env(SYSTEMTAP_INCLUDES)|' \$i sed -i -e 's|^CFLAGS =|& -g -I $env(SYSTEMTAP_INCLUDES)|' \$i done J=\$(getconf _NPROCESSORS_CONF) make -j\$J make install fi # Build python3 cd $testsuite/$python3dir if \[ ! -d bld \] ; then mkdir bld cd bld ../src/configure --with-dtrace --prefix=$testsuite/pyinstall for i in \$(find . -name Makefile) ; do sed -i -e 's|^CXXFLAGS =|& -g -I $env(SYSTEMTAP_INCLUDES)|' \$i sed -i -e 's|^CFLAGS =|& -g -I $env(SYSTEMTAP_INCLUDES)|' \$i done J=\$(getconf _NPROCESSORS_CONF) make -j\$J make install fi cd $testsuite/ mkdir tapset cat \$srcdir/python2.stp | sed -e \"s|PYTHON2|$testsuite/pyinstall/bin/python|g\" >| tapset/python2.stp cat \$srcdir/python3.stp | sed -e \"s|PYTHON3|$testsuite/pyinstall/bin/python3|g\" >| tapset/python3.stp # Run the tests, once for python2, once for python3 for PYTHON in python python3 ; do $env(SYSTEMTAP_PATH)/stap -I `pwd`/tapset \$srcdir/celsius-bt.stp -c \"$testsuite/pyinstall/bin/\$PYTHON -sS \$srcdir/celsius.py 30\" >| $testsuite/python.log 2>&1 MAIN=\$(grep 'main.*at.*systemtap.apps.*celsius.py:\[0-9\]' $testsuite/python.log | wc -l) C2F=\$(grep 'celsius_to_farenheit.*celsius:int.*at.*systemtap.apps.*celsius.py:\[0-9\]' $testsuite/python.log | wc -l) echo \$MAIN \$C2F if \[ \$MAIN -gt 0 -a \$C2F -gt 0 \] ; then echo PASS: \$PYTHON backtrace else echo FAIL: \$PYTHON backtrace fi echo script \" $env(SYSTEMTAP_PATH)/stap -I `pwd`/tapset \$srcdir/celsius-var.stp -c \\\"$testsuite/pyinstall/bin/\$PYTHON -sS \$srcdir/celsius.py 30\\\" '*'\" $testsuite/python.log script -c \" $env(SYSTEMTAP_PATH)/stap -I `pwd`/tapset \$srcdir/celsius-var.stp -c \\\"$testsuite/pyinstall/bin/\$PYTHON -sS \$srcdir/celsius.py 30\\\" '*'\" $testsuite/python.log AGLOBAL9=\$(grep 'global.*str.*aglobal9.*in.*main.*at.*.*systemtap.apps.*celsius.py.*=.*9.*' $testsuite/python.log | wc -l) CELSIUS=\$(grep 'arg1.*int.*celsius.*in.*celsius_to_farenheit.*at.*.*systemtap.apps.*celsius.py.*=.*30.*' $testsuite/python.log | wc -l) ATUPLE=\$(grep 'tuple.*atuple.*in.*celsius_to_farenheit.*at.*.*systemtap.apps.*celsius.py.*=.*.*\"a\",.*\"b\",.*\"c\",' $testsuite/python.log | wc -l) ALIST=\$(grep 'list.*alist.*in.*celsius_to_farenheit.*at.*.*systemtap.apps.*celsius.py.*=.*\[.*1,.*2,.*3,\]' $testsuite/python.log | wc -l) ASET=\$(grep 'set.*aset.*in.*celsius_to_farenheit.*at.*.*systemtap.apps.*celsius.py.*=.*{.*1,.*2,.*3,}' $testsuite/python.log | wc -l) ADICT=\$(grep 'dict.*adict.*in.*celsius_to_farenheit.*at.*.*systemtap.apps.*celsius.py.*=.*{.*1:\"a\".*2:\"b\".*3:\"c\".*}' $testsuite/python.log | wc -l) NINE=\$(grep 'int.*nine.*in.*celsius_to_farenheit.*at.*.*systemtap.apps.*celsius.py.*=.*9.*' $testsuite/python.log | wc -l) FIVE=\$(grep 'int.*five.*in.*celsius_to_farenheit.*at.*.*systemtap.apps.*celsius.py.*=.*5.*' $testsuite/python.log | wc -l) TWO=\$(grep 'int.*thirty_two.*in.*celsius_to_farenheit.*at.*.*systemtap.apps.*celsius.py.*=.*32.*' $testsuite/python.log | wc -l) I=\$(grep 'int.*i.*in.*celsius_to_farenheit.*at.*.*systemtap.apps.*celsius.py.*=.*1.*' $testsuite/python.log | wc -l) echo \$AGLOBAL9 \$CELSIUS \$ATUPLE \$ALIST \$ASET \$ADICT \$NINE \$FIVE \$TWO \$I if \[ \$CELSIUS -gt 0 -a \$ATUPLE -gt 0 -a \$ALIST -gt 0 -a \$ASET -gt 0 -a \$ADICT -gt 0 -a \$NINE -gt 0 -a \$FIVE -gt 0 -a \$TWO -gt 0 -a \$I -gt 0 \] ; then echo PASS: \$PYTHON variable else echo FAIL: \$PYTHON variable fi done " ########## End /tmp/stap-python.sh ########## close $fp ########## /tmp/stap-python.sh does most of the work ########## verbose -log Running python testsuite spawn sh stap-python.sh $srcdir/$subdir/ 2>&1 expect { -timeout 1000 -re {PASS: [a-z0-9 ]+} { regexp " .*$" $expect_out(0,string) s; pass "$s"; exp_continue } -re {XFAIL: [a-z0-9 ]+} { regexp " .*$" $expect_out(0,string) s; xfail "$s"; exp_continue } -re {FAIL: [a-z0-9 ]+} { regexp " .*$" $expect_out(0,string) s; fail "$s"; exp_continue } -re {UNSUPPORTED: [a-z0-9 ]+} { regexp " .*$" $expect_out(0,string) s; verbose -log "$s" unsupported "$s"; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if { $verbose == 0 } { catch {exec rm -rf $testsuite/python2 $testsuite/python3} catch {exec rm -rf $testsuite/stap-python.sh $testsuite/python.log} catch {exec rm -rf Python-$python2release.tar.bz2} catch {exec rm -rf Python-$python3release.tar.bz2} } systemtap-2.3/testsuite/systemtap.apps/python2.patch000066400000000000000000000014521217430427200230630ustar00rootroot00000000000000diff -bB -u -p -Nr Python-2.7.2/Python/ceval.c src-2.7.2/Python/ceval.c --- Python-2.7.2/Python/ceval.c 2011-06-11 11:46:27.000000000 -0400 +++ src-2.7.2/Python/ceval.c 2012-01-24 13:52:11.771437763 -0500 @@ -19,6 +19,8 @@ #include +#include + #ifndef WITH_TSC #define READ_TIMESTAMP(var) @@ -876,6 +878,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int tstate->frame = f; + DTRACE_PROBE1 (python, function__entry, PyEval_GetFrame()); if (tstate->use_tracing) { if (tstate->c_tracefunc != NULL) { /* tstate->c_tracefunc, if defined, is a @@ -3001,6 +3006,7 @@ fast_yield: /* pop frame */ exit_eval_frame: + DTRACE_PROBE1 (python, function__return, PyEval_GetFrame()); Py_LeaveRecursiveCall(); tstate->frame = f->f_back; systemtap-2.3/testsuite/systemtap.apps/python2.stp000066400000000000000000000251041217430427200225720ustar00rootroot00000000000000# Global Python variables global python2_vars_seen # which vars we have seen global python2_frame_n = 0 # set by iterate_over_frames global python2_frame = 0 # set by python2_function_entry # FUNCTION GET_TYPE # OBJ: PyObject # RETURNS: string representation of type function get_type:string (obj) { if (obj == 0) return "" ob_type = @cast (obj, "PyObject", "PYTHON2")->ob_type if (ob_type == 0) return "" ob_type_name = @cast (ob_type, "PyTypeObject", "PYTHON2")->tp_name return set_string (ob_type_name) } # FUNCTION GET_NAME # F_CODE: The python frame code whose filename we are retrieving function get_filename (f_code) { co_filename = @cast (f_code, "PyCodeObject", "PYTHON2")->co_filename; co_filename_s = @cast (co_filename, "PyStringObject", "PYTHON2")->ob_sval; return set_string (co_filename_s) } # FUNCTION GET_NAME # F_CODE: The python frame code whose function name we are retrieving function get_name (f_code) { co_name = @cast (f_code, "PyCodeObject", "PYTHON2")->co_name; co_name_s = @cast (co_name, "PyStringObject", "PYTHON2")->ob_sval; return set_string (co_name_s) } # FUNCTION SET_STRING # STR_P: pointer to string # RETURNS: string as a stap string function set_string (str_p) { if (str_p == 0) return "" else return user_string (str_p) } # FUNCTION GET_SEQUENCE_ITEM # TUPLE: array of PyObject # I: index to retrieve # SEQ_TYPE: PyTupleObject or PyListObject # RETURNS: array entry PyObject function get_sequence_item (tuple, i, seq_type) { if (seq_type == "tuple") ob_items = @cast (tuple, "PyTupleObject", "PYTHON2")->ob_item; else if (seq_type == "list") ob_items = @cast (tuple, "PyListObject", "PYTHON2")->ob_item; ob_item = user_long (ob_items + (i * %{ sizeof (intptr_t) %})) return ob_item } # FUNCTION DISPLAY_VALUE # VALUE: PyObject # PREFIX: prefix string to display # SUFFIX: suffix string to display function display_value (value, prefix, suffix) { if (value == 0) { return 0 } value_type_str = get_type (value) if (value_type_str == "str") { value_s = @cast (value, "PyStringObject", "PYTHON2")->ob_sval; value_str = set_string (value_s) printf ("%s\"%s\"%s", prefix, value_str, suffix) } else if (value_type_str == "int") { arg_value_int = @cast (value, "PyIntObject", "PYTHON2")->ob_ival; printf ("%s%d%s", prefix, arg_value_int, suffix) } else if (value_type_str == "tuple" || value_type_str == "list") { n = @cast (value, "PyTupleObject", "PYTHON2")->ob_size; if (value_type_str == "list") printf (" = [") else printf (" = ") for (i = 0; i < n; i++) display_value (get_sequence_item (value, i, value_type_str), " ", ",") if (value_type_str == "list") printf ("]") } else if (value_type_str == "set") { printf (" = {") n = @cast (value, "PySetObject", "PYTHON2")->used; for (i = 0; i <= n; i++) display_value (get_set_item (value, i), " ", ",") printf ("}") } else if (value_type_str == "dict") { printf (" = {") n = @cast (value, "PyDictObject", "PYTHON2")->ma_used; for (i = 0; i <= n; i++) { dict_hash = get_dict_hash (value, i) dict_key = get_dict_key (value, i) dict_value = get_dict_value (value, i) if (dict_hash == 0 && dict_key == 0) continue display_value (dict_key, " ", ":") display_value (dict_value, "", "") } printf (" }") } } # FUNCTION GET_SET_ITEM # SET: PySetObject # I: set index to retrieve # RETURNS: set entry PyObject function get_set_item (set, i) { entries = @cast (set, "PySetObject", "PYTHON2")->table; n = @cast (set, "PySetObject", "PYTHON2")->used; if (i > n) return 0 return @cast (entries, "setentry", "PYTHON2")[i]->key } # FUNCTION GET_DICT_HASH # DICT: PySetObject # I: set index to retrieve # RETURNS: DICT_HASH function get_dict_hash (dict, i) { entries = @cast (dict, "PyDictObject", "PYTHON2")->ma_table; n = @cast (dict, "PyDictObject", "PYTHON2")->ma_used; if (i > n) return 0 return @cast (entries, "PyDictEntry", "PYTHON2")[i]->me_hash } # FUNCTION GET_DICT_KEY # DICT: PySetObject # I: set index to retrieve # RETURNS: DICT_KEY function get_dict_key (dict, i) { entries = @cast (dict, "PyDictObject", "PYTHON2")->ma_table; n = @cast (dict, "PyDictObject", "PYTHON2")->ma_used; if (i > n) return 0 return @cast (entries, "PyDictEntry", "PYTHON2")[i]->me_key } # FUNCTION GET_DICT_VALUE # DICT: PySetObject # I: set index to retrieve # RETURNS: DICT_VALUE function get_dict_value (dict, i) { entries = @cast (dict, "PyDictObject", "PYTHON2")->ma_table; n = @cast (dict, "PyDictObject", "PYTHON2")->ma_used; if (i > n) return 0 return @cast (entries, "PyDictEntry", "PYTHON2")[i]->me_value; } # FUNCTION DISPLAY_DICT_VARIABLE # DICT: local or global variable name dictionary # VARIABLE: variable to retrieve # NAMESPACE: local or global function display_dict_variable (dict, variable, namespace, co_name_str, co_filename_str) { n = @cast (dict, "PyDictObject", "PYTHON2")->ma_used; for (i = 0; i < n; i++) { dict_key = get_dict_key (dict, i) dict_value = get_dict_value (dict, i) key_str = set_string (@cast (dict_key, "PyStringObject", "PYTHON2")->ob_sval) key_type_str = get_type (dict_key) if (dict_key == 0 || dict_value == 0) break if (wildcard_match (key_str, variable)) { foreach ([var, file] in python2_vars_seen) { if (var == key_str && file == co_filename_str) return 0 } printf ("%s %s %s", namespace, key_type_str, key_str) printf (" in %s at %s", co_name_str, co_filename_str) display_value (dict_value, " = ", " ") printf ("\n") python2_vars_seen[key_str, co_filename_str] = co_name_str } } } # FUNCTION WILDCARD_MATCH # STR: String to check for a wildcard # PATTERN: The wildcard pattern. Wildcard special characters are limited to '*' function wildcard_match (str, pattern) { if (pattern == "*") return 1 # Does pattern start at the beginning of str or is it '*'? if (substr (pattern, 0, 1) != "*" && substr (str, 0, 1) != substr (pattern, 0, 1)) return 0 hunk = tokenize (pattern,"*") while (hunk != "") { # find pattern hunk in str if (isinstr (str, hunk) == 0) { return 0 } match = 0 for (i = 0; i < strlen (str) - strlen (hunk) + 1; i++) { if (hunk == substr (str, i, strlen (hunk))) { match = 1 break } } if (!match) return 0 # skip past hunk in str str = substr (str, i, strlen (str)-i+1) hunk = tokenize ("","*") } # Does pattern end at the end of str or is it '*'? if (substr (pattern, strlen (pattern)-1, 1) != "*" && substr (str, strlen (str)-1, 1) != substr (pattern, strlen (pattern)-1, 1)) return 0 else return 1 } # FUNCTION ITERATE_OVER_FRAMES # FRAME: Pointer to a stack frame # FRAME_N: The frame number of this stack frame function python2_iterate_over_frames (frame, frame_n) { if (frame_n != 0) { python2_frame_n += 1 frame = @cast (frame, "PyFrameObject", "PYTHON2")->f_back } else python2_frame_n = 0 return frame } # FUNCTION BACKTRACE # FRAME: Pointer to first stack frame # SKIP_NAME: Pathnames containing this string are ignored. Default is "/lib/" to # ignore system python libraries function python2_backtrace (frame, skip_name) { if (skip_name == "") skip_name = "/lib/" f_code = @cast (frame, "PyFrameObject", "PYTHON2")->f_code; co_filename_str = get_filename (f_code) if (isinstr (co_filename_str, skip_name) == 1) return 0 co_name_str = get_name (f_code) co_firstlineno = @cast (f_code, "PyCodeObject", "PYTHON2")->co_firstlineno; printf ("#%d %s ", python2_frame_n, co_name_str) co_varnames = @cast (f_code, "PyCodeObject", "PYTHON2")->co_varnames; co_argcount = @cast (f_code, "PyCodeObject", "PYTHON2")->co_argcount; f_localsplus = @cast (frame, "PyFrameObject", "PYTHON2")->f_localsplus; for (i = 0; i < co_argcount; i++) { if (i == 0) print ("("); arg_name_str = user_string (@cast (get_sequence_item (co_varnames, i, "tuple"), "PyStringObject", "PYTHON2")->ob_sval) arg_value = user_long (f_localsplus + (i * %{ sizeof (intptr_t) %})) arg_type_name_str = get_type (arg_value) printf ("%s:%s ", arg_name_str, arg_type_name_str) } if (co_argcount) printf (")"); printf (" at %s:%d\n", co_filename_str, co_firstlineno) } # FUNCTION GET_VARIABLE # FRAME: Pointer to first stack frame # MATCH_ARGS: Match function arguments # VARIABLE: Variable wildcard to be matched. Default is "*" to match all variables. # SKIP_NAME: Pathnames containing this string are ignored. Default is "/lib/" to # ignore system python libraries function python2_get_variable (frame, match_args, variable, skip_name) { if (skip_name == "") skip_name = "/lib/" f_code = @cast (frame, "PyFrameObject", "PYTHON2")->f_code; co_filename_str = get_filename (f_code) if (isinstr (co_filename_str, skip_name) == 1) return 0 co_name_str = get_name (f_code) f_globals = @cast (frame, "PyFrameObject", "PYTHON2")->f_globals; if (f_globals != 0) { display_dict_variable (f_globals, variable, "global", co_name_str, co_filename_str) } f_locals = @cast (frame, "PyFrameObject", "PYTHON2")->f_locals; if (f_locals != 0) { display_dict_variable (f_locals, variable, "local", co_name_str, co_filename_str) } co_varnames = @cast (f_code, "PyCodeObject", "PYTHON2")->co_varnames; co_argcount = @cast (f_code, "PyCodeObject", "PYTHON2")->co_argcount; f_localsplus = @cast (frame, "PyFrameObject", "PYTHON2")->f_localsplus; ob_size = @cast (co_varnames, "PyTypeObject", "PYTHON2")->ob_size; # iterate through the local variable list for (i = 0; i < ob_size; i++) { arg_name_str = user_string (@cast (get_sequence_item (co_varnames, i, "tuple"), "PyStringObject", "PYTHON2")->ob_sval) if (! wildcard_match (arg_name_str, variable)) continue arg_value = user_long (f_localsplus + (i * %{ sizeof (intptr_t) %})) arg_type_name_str = get_type (arg_value) next_var = 0 foreach ([var, file] in python2_vars_seen) if (var == arg_name_str && file == co_filename_str) next_var = 1 if (next_var || arg_type_name_str == "") continue if (i < co_argcount && match_args) printf ("arg%d ", i + 1) python2_vars_seen[arg_name_str, co_filename_str] = co_name_str printf ("%s %s", arg_type_name_str, arg_name_str) printf (" in %s at %s", co_name_str, co_filename_str) display_value (arg_value, " = ", " ") printf ("\n") } } probe python.function_entry = process("PYTHON2").mark ("function__entry") { python2_frame = $arg1 } probe python.function_return = process("PYTHON2").mark ("function__return") { python2_frame = $arg1 } systemtap-2.3/testsuite/systemtap.apps/python3.patch000066400000000000000000000225301217430427200230640ustar00rootroot00000000000000diff -bB -u -p -Nr src-3.2.2/configure src-3.2.2-new/configure --- src-3.2.2/configure 2011-09-03 12:16:50.000000000 -0400 +++ src-3.2.2-new/configure 2012-02-01 10:39:42.332746238 -0500 @@ -619,6 +619,10 @@ TRUE MACHDEP_OBJS DYNLOADFILE DLINCLDIR +DTRACEHDRS +DTRACEOBJS +DFLAGS +DTRACE THREADOBJ LDLAST USE_THREAD_MODULE @@ -766,6 +770,7 @@ with_doc_strings with_tsc with_pymalloc with_valgrind +with_dtrace with_fpectl with_libm with_libc @@ -1439,6 +1444,7 @@ Optional Packages: --with(out)-tsc enable/disable timestamp counter profile --with(out)-pymalloc disable/enable specialized mallocs --with-valgrind Enable Valgrind support + --with(out)-dtrace disable/enable dtrace support --with-fpectl enable SIGFPE catching --with-libm=STRING math library --with-libc=STRING C library @@ -9333,6 +9339,93 @@ fi OPT="-DDYNAMIC_ANNOTATIONS_ENABLED=1 $OPT" fi +# Check for dtrace support +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-dtrace" >&5 +$as_echo_n "checking for --with-dtrace... " >&6; } + +# Check whether --with-dtrace was given. +if test "${with_dtrace+set}" = set; then : + withval=$with_dtrace; +fi + + + + +DTRACE= +DFLAGS= +if test ! -z "$with_dtrace" +then + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 +$as_echo_n "checking size of long... " >&6; } +if ${ac_cv_sizeof_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 +$as_echo "$ac_cv_sizeof_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + + if test "$ac_cv_sizeof_long" -eq 8 + then + DFLAGS="-64" + else + DFLAGS="-32" + fi + + #if dtrace -G -o /dev/null Include/pydtrace.d 2>/dev/null + if true + then + +$as_echo "#define WITH_DTRACE 1" >>confdefs.h + + with_dtrace="Sun" + DTRACEOBJS="Python/dtrace.o" + DTRADEHDRS="" + DTRACE=dtrace + elif dtrace -h -o /dev/null -s Include/pydtrace.d + then + +$as_echo "#define WITH_DTRACE 1" >>confdefs.h + + with_dtrace="Apple" + DTRACEOBJS="" + DTRADEHDRS="pydtrace.h" + DTRACE=dtrace + else + with_dtrace="no" + fi +else + with_dtrace="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_dtrace" >&5 +$as_echo "$with_dtrace" >&6; } + + + # -I${DLINCLDIR} is added to the compile rule for importdl.o DLINCLDIR=. diff -bB -u -p -Nr src-3.2.2/configure.in src-3.2.2-new/configure.in --- src-3.2.2/configure.in 2011-09-03 12:16:50.000000000 -0400 +++ src-3.2.2-new/configure.in 2012-01-23 16:47:44.518908944 -0500 @@ -2525,6 +2525,53 @@ if test "$with_valgrind" != no; then OPT="-DDYNAMIC_ANNOTATIONS_ENABLED=1 $OPT" fi +# Check for dtrace support +AC_MSG_CHECKING(for --with-dtrace) +AC_ARG_WITH(dtrace, + AC_HELP_STRING(--with(out)-dtrace, disable/enable dtrace support)) + +AC_SUBST(DTRACE) +AC_SUBST(DFLAGS) +DTRACE= +DFLAGS= +if test ! -z "$with_dtrace" +then + AC_CHECK_SIZEOF([long]) + if [test "$ac_cv_sizeof_long" -eq 8] + then + DFLAGS="-64" + else + DFLAGS="-32" + fi + + #if dtrace -G -o /dev/null Include/pydtrace.d 2>/dev/null + if true + then + AC_DEFINE(WITH_DTRACE, 1, + [Define if you want to compile in Dtrace support]) + with_dtrace="Sun" + DTRACEOBJS="Python/dtrace.o" + DTRADEHDRS="" + DTRACE=dtrace + elif dtrace -h -o /dev/null -s Include/pydtrace.d + then + AC_DEFINE(WITH_DTRACE, 1, + [Define if you want to compile in Dtrace support]) + with_dtrace="Apple" + DTRACEOBJS="" + DTRADEHDRS="pydtrace.h" + DTRACE=dtrace + else + with_dtrace="no" + fi +else + with_dtrace="no" +fi + +AC_MSG_RESULT($with_dtrace) +AC_SUBST(DTRACEOBJS) +AC_SUBST(DTRACEHDRS) + # -I${DLINCLDIR} is added to the compile rule for importdl.o AC_SUBST(DLINCLDIR) DLINCLDIR=. diff -bB -u -p -Nr src-3.2.2/Include/pydtrace.d src-3.2.2-new/Include/pydtrace.d --- src-3.2.2/Include/pydtrace.d 1969-12-31 19:00:00.000000000 -0500 +++ src-3.2.2-new/Include/pydtrace.d 2012-01-24 10:30:26.643772689 -0500 @@ -0,0 +1,17 @@ +provider python { + probe function__entry(void *, const char *, const char *, int); + probe function__return(void *, const char *, const char *, int); + probe instance__new__start(void *, const char *, const char *); + probe instance__new__done(void *, const char *, const char *); + probe instance__delete__start(void *, const char *, const char *); + probe instance__delete__done(void *, const char *, const char *); + probe line(void *, const char *, const char *, int); + probe gc__start(void *, int); + probe gc__done(void *, long); +}; + +#pragma D attributes Evolving/Evolving/Common provider python provider +#pragma D attributes Private/Private/Common provider python module +#pragma D attributes Private/Private/Common provider python function +#pragma D attributes Evolving/Evolving/Common provider python name +#pragma D attributes Evolving/Evolving/Common provider python args diff -bB -u -p -Nr src-3.2.2/Makefile.pre.in src-3.2.2-new/Makefile.pre.in --- src-3.2.2/Makefile.pre.in 2011-09-03 12:16:45.000000000 -0400 +++ src-3.2.2-new/Makefile.pre.in 2012-01-23 16:47:19.425222658 -0500 @@ -49,6 +49,10 @@ SHELL= /bin/sh # Use this to make a link between python$(VERSION) and python in $(BINDIR) LN= @LN@ +DTRACE= @DTRACE@ +DFLAGS= @DFLAGS@ + + # Portable install script (configure doesn't always guess right) INSTALL= @INSTALL@ INSTALL_PROGRAM=@INSTALL_PROGRAM@ @@ -333,6 +337,7 @@ PYTHON_OBJS= \ Python/formatter_unicode.o \ Python/fileutils.o \ Python/$(DYNLOADFILE) \ + @DTRACEOBJS@ \ $(LIBOBJS) \ $(MACHDEP_OBJS) \ $(THREADOBJ) @@ -654,6 +659,29 @@ Objects/typeobject.o: $(srcdir)/Objects/ $(srcdir)/Objects/typeslots.inc: $(srcdir)/Include/typeslots.h $(srcdir)/Objects/typeslots.py $(PYTHON) $(srcdir)/Objects/typeslots.py < $(srcdir)/Include/typeslots.h > $(srcdir)/Objects/typeslots.inc +# Only generated --with-dtrace +Include/pydtrace.h: $(srcdir)/Include/pydtrace.d + if test ! -d Include ; then mkdir Include ; fi ; \ + if test "$(DTRACE)" != "" ; then \ + $(DTRACE) -o $@ $(DFLAGS) \ + -C -h -s $(srcdir)/Include/pydtrace.d ; \ + else touch $@ ; \ + fi; + +Python/ceval.o: Include/pydtrace.h +Modules/gcmodule.o: Include/pydtrace.h +Objects/typeobject.o: Include/pydtrace.h + +Python/dtrace.o: $(srcdir)/Include/pydtrace.d Python/ceval.o Modules/gcmodule.o \ + Objects/typeobject.o + if test "$(DTRACE)" != "" ; then \ + $(DTRACE) -o $@ $(DFLAGS) \ + -C -G -s $(srcdir)/Include/pydtrace.d \ + Python/ceval.o Modules/gcmodule.o \ + Objects/typeobject.o; \ + else touch $@ ; \ + fi; + ############################################################################ # Header files @@ -1246,6 +1274,7 @@ clean: pycremoval find . -name '*.so.[0-9]*.[0-9]*' -exec rm -f {} ';' find build -name 'fficonfig.h' -exec rm -f {} ';' || true find build -name 'fficonfig.py' -exec rm -f {} ';' || true + rm -f Include/pydtrace.h Include/phelper.h -rm -f Lib/lib2to3/*Grammar*.pickle profile-removal: @@ -1275,6 +1304,7 @@ distclean: clobber -o -name '*.orig' -o -name '*.rej' \ -o -name '*.bak' ')' \ -exec rm -f {} ';' + rm -f Include/pydtrace.h Include/phelper.h # Check for smelly exported symbols (not starting with Py/_Py) smelly: all diff -bB -u -p -Nr src-3.2.2/pyconfig.h.in src-3.2.2-new/pyconfig.h.in --- src-3.2.2/pyconfig.h.in 2011-09-03 12:16:50.000000000 -0400 +++ src-3.2.2-new/pyconfig.h.in 2011-12-07 11:18:03.785658733 -0500 @@ -1095,6 +1095,9 @@ /* Define if you want documentation strings in extension modules */ #undef WITH_DOC_STRINGS +/* Define to compile in Dtrace support */ +#undef WITH_DTRACE + /* Define if you want to use the new-style (Openstep, Rhapsody, MacOS) dynamic linker (dyld) instead of the old-style (NextStep) dynamic linker (rld). Dyld is necessary to support frameworks. */ diff -bB -u -p -Nr src-3.2.2/Python/ceval.c src-3.2.2-new/Python/ceval.c --- src-3.2.2/Python/ceval.c 2011-09-03 12:16:49.000000000 -0400 +++ src-3.2.2-new/Python/ceval.c 2012-01-24 15:27:55.333633359 -0500 @@ -18,6 +18,10 @@ #include +#ifdef WITH_DTRACE +#include "pydtrace.h" +#endif + #ifndef WITH_TSC #define READ_TIMESTAMP(var) @@ -1207,6 +1211,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int } } + PYTHON_FUNCTION_ENTRY(f, 0, 0, 0); + co = f->f_code; names = co->co_names; consts = co->co_consts; @@ -3088,6 +3094,7 @@ fast_yield: /* pop frame */ exit_eval_frame: + PYTHON_FUNCTION_RETURN(f, 0, 0, 0); Py_LeaveRecursiveCall(); tstate->frame = f->f_back; systemtap-2.3/testsuite/systemtap.apps/python3.stp000066400000000000000000000250301217430427200225710ustar00rootroot00000000000000# Global Python variables global python3_vars_seen # which vars we have seen global python3_frame_n = 0 # set by iterate_over_frames global python3_frame = 0 # set by python3_function_entry # FUNCTION P3_GET_TYPE # OBJ: PyObject # RETURNS: string representation of type function p3_get_type:string (obj) { if (obj == 0) return "" ob_type = @cast (obj, "PyObject", "PYTHON3")->ob_type if (ob_type == 0) return "" ob_type_name = @cast (ob_type, "PyTypeObject", "PYTHON3")->tp_name return set_string (ob_type_name) } # FUNCTION GET_FILENAME # F_CODE: The python frame code whose filename we are retrieving function p3_get_filename (f_code) { co_filename = @cast (f_code, "PyCodeObject", "PYTHON3")->co_filename; return get_unicode (co_filename) } # FUNCTION P3_GET_NAME # F_CODE: The python frame code whose function name we are retrieving function p3_get_name (f_code) { co_name = @cast (f_code, "PyCodeObject", "PYTHON3")->co_name; return get_unicode (co_name) } # FUNCTION P3_SET_STRING # STR_P: pointer to string # RETURNS: string as a stap string function p3_set_string (str_p) { if (str_p == 0) return "" else return user_string (str_p) } function get_unicode:string (utf16) { if (utf16 == 0) return "" length = @cast (utf16, "PyUnicodeObject", "PYTHON3")->length; unip = @cast (utf16, "PyUnicodeObject", "PYTHON3")->str; if (length == 0 || unip == 0) return "" newstr = "" # grab every other character # ??? Do we need general purpose UTF routines? for (i = 0; i < length; i++) { if (user_char(unip + (i * 2)) == 0) break val = user_string_n(unip + (i * 2), 1) newstr = newstr . substr(val,0,1) } return newstr } # FUNCTION P3_GET_SEQUENCE_ITEM # TUPLE: array of PyObject # I: index to retrieve # SEQ_TYPE: PyTupleObject or PyListObject # RETURNS: array entry PyObject function p3_get_sequence_item (tuple, i, seq_type) { if (seq_type == "tuple") ob_items = @cast (tuple, "PyTupleObject", "PYTHON3")->ob_item; else if (seq_type == "list") ob_items = @cast (tuple, "PyListObject", "PYTHON3")->ob_item; ob_item = user_long (ob_items + (i * %{ sizeof (intptr_t) %})) return ob_item } # FUNCTION P3_DISPLAY_VALUE # VALUE: PyObject # PREFIX: prefix string to display # SUFFIX: suffix string to display function p3_display_value (value, prefix, suffix) { if (value == 0) { return 0 } value_type_str = p3_get_type (value) if (value_type_str == "str") { value_str = get_unicode (value) printf ("%s\"%s\"%s", prefix, value_str, suffix) } else if (value_type_str == "int") { if (@cast (value, "PyLongObject", "PYTHON3")->ob_base->ob_size == 1) printf ("%s%d%s", prefix, user_int(@cast (value, "PyLongObject", "PYTHON3")[0]->ob_digit), suffix) else if (@cast (value, "PyLongObject", "PYTHON3")->ob_base->ob_size == 2) { printf ("%s%#lx", prefix, user_int(@cast (value, "PyLongObject", "PYTHON3")[0]->ob_digit + 4) >> 2) printf ("%x%s", user_int(@cast (value, "PyLongObject", "PYTHON3")[0]->ob_digit) | ((user_int(@cast (value, "PyLongObject", "PYTHON3")[0]->ob_digit + 4) << 30) & 0xffffffff), suffix) } } else if (value_type_str == "tuple" || value_type_str == "list") { n = @cast (value, "PyTupleObject", "PYTHON3")->ob_base->ob_size; if (value_type_str == "list") printf (" = [") else printf (" = ") for (i = 0; i < n; i++) p3_display_value (p3_get_sequence_item (value, i, value_type_str), " ", ",") if (value_type_str == "list") printf ("]") } else if (value_type_str == "set") { printf (" = {") n = @cast (value, "PySetObject", "PYTHON3")->used; for (i = 0; i <= n; i++) p3_display_value (get_set_item (value, i), " ", ",") printf ("}") } else if (value_type_str == "dict") { printf (" = {") n = @cast (value, "PyDictObject", "PYTHON3")->ma_used; for (i = 0; i <= n; i++) { dict_hash = p3_get_dict_hash (value, i) dict_key = p3_get_dict_key (value, i) dict_value = p3_get_dict_value (value, i) if (dict_hash == 0 && dict_key == 0) continue p3_display_value (dict_key, " ", ":") p3_display_value (dict_value, "", "") } printf (" }") } } # FUNCTION P3_GET_SET_ITEM # SET: PySetObject # I: set index to retrieve # RETURNS: set entry PyObject function p3_get_set_item (set, i) { entries = @cast (set, "PySetObject", "PYTHON3")->table; n = @cast (set, "PySetObject", "PYTHON3")->used; if (i > n) return 0 return @cast (entries, "setentry", "PYTHON3")[i]->key } # FUNCTION P3_GET_DICT_HASH # DICT: PySetObject # I: set index to retrieve # RETURNS: DICT_HASH function p3_get_dict_hash (dict, i) { entries = @cast (dict, "PyDictObject", "PYTHON3")->ma_table; n = @cast (dict, "PyDictObject", "PYTHON3")->ma_used; if (i > n) return 0 return @cast (entries, "PyDictEntry", "PYTHON3")[i]->me_hash } # FUNCTION P3_GET_DICT_KEY # DICT: PySetObject # I: set index to retrieve # RETURNS: DICT_KEY function p3_get_dict_key (dict, i) { entries = @cast (dict, "PyDictObject", "PYTHON3")->ma_table; n = @cast (dict, "PyDictObject", "PYTHON3")->ma_used; if (i > n) return 0 return @cast (entries, "PyDictEntry", "PYTHON3")[i]->me_key } # FUNCTION P3_GET_DICT_VALUE # DICT: PySetObject # I: set index to retrieve # RETURNS: DICT_VALUE function p3_get_dict_value (dict, i) { entries = @cast (dict, "PyDictObject", "PYTHON3")->ma_table; n = @cast (dict, "PyDictObject", "PYTHON3")->ma_used; if (i > n) return 0 return @cast (entries, "PyDictEntry", "PYTHON3")[i]->me_value; } # FUNCTION P3_DISPLAY_DICT_VARIABLE # DICT: local or global variable name dictionary # VARIABLE: variable to retrieve # NAMESPACE: local or global function p3_display_dict_variable (dict, variable, namespace, co_name_str, co_filename_str) { n = @cast (dict, "PyDictObject", "PYTHON3")->ma_used; for (i = 0; i < n; i++) { dict_key = p3_get_dict_key (dict, i) dict_value = p3_get_dict_value (dict, i) dict_hash = p3_get_dict_hash (dict, i) if (dict_hash == 0 || dict_value == 0) continue # key_str = p3_set_string (@cast (dict_key, "PyUnicodeObject", "PYTHON3")->str) key_str = get_unicode (dict_key) key_type_str = p3_get_type (dict_key) if (wildcard_match (key_str, variable)) { foreach ([var, file] in python3_vars_seen) { if (var == key_str && file == co_filename_str) return 0 } printf ("%s %s %s", namespace, key_type_str, key_str) printf (" in %s at %s", co_name_str, co_filename_str) p3_display_value (dict_value, " = ", " ") printf ("\n") python3_vars_seen[key_str, co_filename_str] = co_name_str } } } # FUNCTION ITERATE_OVER_FRAMES # FRAME: Pointer to a stack frame # FRAME_N: The frame number of this stack frame function python3_iterate_over_frames (frame, frame_n) { if (frame_n != 0) { python3_frame_n += 1 frame = @cast (frame, "PyFrameObject", "PYTHON3")->f_back } else python3_frame_n = 0 return frame } # FUNCTION BACKTRACE # FRAME: Pointer to first stack frame # MATCH_FILENAME: Pathnames containing this string are ignored. Default is "/lib/" to # ignore system python libraries function python3_backtrace (frame, match_filename) { f_code = @cast (frame, "PyFrameObject", "PYTHON3")->f_code; co_filename_str = p3_get_filename (f_code) if (isinstr (co_filename_str, "/lib/") == 1) return 0 if (match_filename != "" && isinstr (co_filename_str, match_filename) == 0) return 0 co_name_str = p3_get_name (f_code) co_firstlineno = @cast (f_code, "PyCodeObject", "PYTHON3")->co_firstlineno; printf ("#%d %s ", python3_frame_n, co_name_str) co_varnames = @cast (f_code, "PyCodeObject", "PYTHON3")->co_varnames; co_argcount = @cast (f_code, "PyCodeObject", "PYTHON3")->co_argcount; f_localsplus = @cast (frame, "PyFrameObject", "PYTHON3")->f_localsplus; for (i = 0; i < co_argcount; i++) { if (i == 0) print ("("); arg_name_str = get_unicode (p3_get_sequence_item (co_varnames, i, "tuple")) arg_value = user_long (f_localsplus + (i * %{ sizeof (intptr_t) %})) arg_type_name_str = p3_get_type (arg_value) printf ("%s:%s ", arg_name_str, arg_type_name_str) } if (co_argcount) printf (")"); printf (" at %s:%d\n", co_filename_str, co_firstlineno) } # FUNCTION GET_VARIABLE # FRAME: Pointer to first stack frame # MATCH_ARGS: Match function arguments # VARIABLE: Variable wildcard to be matched. Default is "*" to match all variables. # MATCH_FILENAME: Pathnames containing this string are ignored. Default is "/lib/" to # ignore system python libraries function python3_get_variable (frame, match_args, variable, match_filename) { f_code = @cast (frame, "PyFrameObject", "PYTHON3")->f_code; co_filename_str = p3_get_filename (f_code) if (isinstr (co_filename_str, "/lib/") == 1) return 0 if (match_filename != "" && isinstr (co_filename_str, match_filename) == 0) return 0 co_name_str = p3_get_name (f_code) f_globals = @cast (frame, "PyFrameObject", "PYTHON3")->f_globals; if (f_globals != 0) { p3_display_dict_variable (f_globals, variable, "global", co_name_str, co_filename_str) } f_locals = @cast (frame, "PyFrameObject", "PYTHON3")->f_locals; if (f_locals != 0) { p3_display_dict_variable (f_locals, variable, "local", co_name_str, co_filename_str) } co_varnames = @cast (f_code, "PyCodeObject", "PYTHON3")->co_varnames; co_argcount = @cast (f_code, "PyCodeObject", "PYTHON3")->co_argcount; f_localsplus = @cast (frame, "PyFrameObject", "PYTHON3")->f_localsplus; ob_size = @cast (co_varnames, "PyTypeObject", "PYTHON3")->ob_base->ob_size; # iterate through the local variable list for (i = 0; i < ob_size; i++) { arg_name_str = get_unicode (p3_get_sequence_item (co_varnames, i, "tuple")) if (! wildcard_match (arg_name_str, variable)) continue arg_value = user_long (f_localsplus + (i * %{ sizeof (intptr_t) %})) arg_type_name_str = p3_get_type (arg_value) next_var = 0 foreach ([var, file] in python3_vars_seen) if (var == arg_name_str && file == co_filename_str) next_var = 1 if (next_var || arg_type_name_str == "") continue if (i < co_argcount && match_args) printf ("arg%d ", i + 1) python3_vars_seen[arg_name_str, co_filename_str] = co_name_str printf ("%s %s", arg_type_name_str, arg_name_str) printf (" in %s at %s", co_name_str, co_filename_str) p3_display_value (arg_value, " = ", " ") printf ("\n") } } probe python.function_entry = process("PYTHON3").mark ("function__entry") { python3_frame = $arg1 } probe python.function_return = process("PYTHON3").mark ("function__return") { python3_frame = $arg1 } systemtap-2.3/testsuite/systemtap.apps/returnstatement.java000066400000000000000000000015741217430427200245530ustar00rootroot00000000000000class returnstatement { public static void printMessage(int message){} public static void printMessage(long message){} public static void printMessage(double message){} public static void printMessage(float message){} public static void printMessage(byte message){} public static void printMessage(boolean message){} public static void printMessage(char message){} public static void printMessage(short message){} public static void main(String[] args) throws InterruptedException { Thread.sleep(20000); final int i = 42; final long j = 254775806; final double k = 3.14; final float l = 2345987; final byte n = 10; final boolean o = true; final char p = 'a'; final short q = 14; printMessage(i); printMessage(j); printMessage(k); printMessage(l); printMessage(n); printMessage(o); printMessage(p); printMessage(q); } } systemtap-2.3/testsuite/systemtap.apps/returnstatement.stp000066400000000000000000000020561217430427200244340ustar00rootroot00000000000000 probe java("returnstatement").class("returnstatement").method("printMessage(int)").return { printf("%s %d ret\n", pn(), $arg1) } probe java("returnstatement").class("returnstatement").method("printMessage(long)").return { printf("%s %d ret\n", pn(), $arg1) } probe java("returnstatement").class("returnstatement").method("printMessage(double)").return { printf("%s %d ret\n", pn(), $arg1) } probe java("returnstatement").class("returnstatement").method("printMessage(float)").return { printf("%s %d ret\n", pn(), $arg1) } probe java("returnstatement").class("returnstatement").method("printMessage(byte)").return { printf("%s %d ret\n", pn(), $arg1) } probe java("returnstatement").class("returnstatement").method("printMessage(boolean)").return { printf("%s %d ret\n", pn(), $arg1) } probe java("returnstatement").class("returnstatement").method("printMessage(char)").return { printf("%s %d ret\n", pn(), $arg1) } probe java("returnstatement").class("returnstatement").method("printMessage(short)").return { printf("%s %d ret\n", pn(), $arg1) } systemtap-2.3/testsuite/systemtap.apps/singleparam.java000066400000000000000000000024511217430427200236040ustar00rootroot00000000000000class singleparam { public static void printMessage(int message) { // System.out.println("int: " + message); } public static void printMessage(long message) { // System.out.println("long: " + message); } public static void printMessage(double message) { // System.out.println("double: " + message); } public static void printMessage(float message) { // System.out.println("float: " + message); } public static void printMessage(byte message) { // System.out.println("byte: " + message); } public static void printMessage(boolean message) { // System.out.println("boolean: " + message); } public static void printMessage(char message) { // System.out.println("char: " + message); } public static void printMessage(short message) { // System.out.println("short: " + message); } public static void main(String[] args) throws InterruptedException { Thread.sleep(30000); final int i = 42; final long j = 254775806; final double k = 3.14; final float l = 2345987; final byte n = 10; final boolean o = true; final char p = 'a'; final short q = 14; printMessage(i); printMessage(j); printMessage(k); printMessage(l); printMessage(n); printMessage(o); printMessage(p); printMessage(q); } } systemtap-2.3/testsuite/systemtap.apps/stap-tcl.sh000077500000000000000000000014051217430427200225230ustar00rootroot00000000000000#! /bin/sh set -e tclreleasemajor="8.6" tclrelease="8.6b1" tcldir=`pwd`/tcl/install/ mkdir -p tcl if [ ! -r tcl$tclrelease-src.tar.gz ] ; then wget -q http://sourceforge.net/projects/tcl/files/Tcl/$tclrelease/tcl$tclrelease-src.tar.gz/download mv download tcl$tclrelease-src.tar.gz fi if [ ! -r tcl$tclrelease-src.tar.gz ] ; then echo FAIL: wget tcl$tclrelease-src.tar.gz exit fi if [ ! -d tcl/src ] ; then tar -x -z -f tcl$tclrelease-src.tar.gz mv tcl$tclrelease tcl/src sed -i '/runAllTests/i\ singleProcess true' tcl/src/tests/all.tcl mv tcl/src/tests/obj.test tcl/src/tests/obj.test.1 fi cd tcl/src/unix env CPPFLAGS="-I$SYSTEMTAP_INCLUDES" CFLAGS="-g -O2" ./configure --prefix=$tcldir --enable-dtrace make -j2 make install exit 0 systemtap-2.3/testsuite/systemtap.apps/stap-tcl.stp000066400000000000000000000016061217430427200227170ustar00rootroot00000000000000global counts probe process(@1).library(@2).mark("*") { counts[$$name]<<<1 # PR10878; check also $$parms length } function judge(name, minvalue) { value = @count(counts[name]) printf("%s %s Got: %d Expected Minimum: %d\n", ((value>=minvalue)?"OK":"KO"), name, value, minvalue) } probe end,error { /* foreach (name in counts-) { printf("== %s %d\n", name, @count(counts[name])) } */ judge("proc__entry", 9000) judge("proc__return", 9000) judge("proc__result", 9000) judge("proc__args", 9000) judge("proc__info", 9000) judge("cmd__entry", 37000) judge("cmd__return", 37000) judge("cmd__result", 37000) judge("cmd__args", 37000) judge("cmd__info", 37000) judge("inst__start", 542000) judge("inst__done", 542000) judge("obj__create", 723000) judge("obj__free", 704000) } systemtap-2.3/testsuite/systemtap.apps/tcl.exp000066400000000000000000000043171217430427200217420ustar00rootroot00000000000000set test "tcl" # Test sdt support in tcl. global env if {! [info exists env(SYSTEMTAP_TESTAPPS)] || ( ! [string match "tcl" $env(SYSTEMTAP_TESTAPPS)] && ! [string match "all" $env(SYSTEMTAP_TESTAPPS)])} { untested "$test sdt app" return } ########## Create /tmp/stap-tcl.stp ########## set tclreleasemajor "8.6" set tclrelease "8.6b1" set tcldir "[pwd]/tcl/install/" set testsuite "[pwd]" verbose -log "Building tcl" set test "tcl${tclreleasemajor} build" set rc [catch {exec sh $srcdir/$subdir/stap-tcl.sh 2>@ stdout} out] if {$rc != 0} { clone_output $out fail $test return } else { pass $test } set test "stap-tcl.stp compilation" verbose -log "spawn stap -DMAXSKIPPED=8024 -t -p4 $srcdir/$subdir/stap-tcl.stp tcl/install/bin/tclsh${tclreleasemajor} tcl/install/lib/libtcl${tclreleasemajor}.so" set rc [catch {exec stap -DMAXSKIPPED=8024 -t -p4 $srcdir/$subdir/stap-tcl.stp tcl/install/bin/tclsh${tclreleasemajor} tcl/install/lib/libtcl${tclreleasemajor}.so} out] clone_output $out if {$rc != 0} { fail $test return } else { pass $test } set test "stap-tcl.stp execution" if {![installtest_p]} { untested $test return } set ok 0 set ko 0 set xok 0 set lines 0 verbose -log "spawn stap -DMAXSKIPPED=8024 -t -c \"tcl/install/bin/tclsh${tclreleasemajor} tcl/src/tests/all.tcl > tcl-test.out\" $srcdir/$subdir/stap-tcl.stp tcl/install/bin/tclsh${tclreleasemajor} tcl/install/lib/libtcl${tclreleasemajor}.so" spawn stap -DMAXSKIPPED=8024 -t -c "tcl/install/bin/tclsh${tclreleasemajor} tcl/src/tests/all.tcl > tcl-test.out" $srcdir/$subdir/stap-tcl.stp tcl/install/bin/tclsh${tclreleasemajor} tcl/install/lib/libtcl${tclreleasemajor}.so expect { -timeout 2000 -re {^OK [^\r\n]*[\r\n]} { incr ok; exp_continue } -re {^KO [^\r\n]*[\r\n]} { incr ko; exp_continue } -re {^ERROR: Skipped[^\r\n]*[\r\n]} { incr xok; exp_continue } -re {^ERROR[^\r\n]*[\r\n]} { incr ko; exp_continue } -re {^[^\r\n]*[\r\n]} { incr lines; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 14 && $ko == 0} { pass "$test ($ok $ko $lines)" } else { fail "$test ($ok $ko $lines)" } if {$xok == 1} { xfail "$test (skipped probes)" } systemtap-2.3/testsuite/systemtap.apps/xulrunner.exp000066400000000000000000000100741217430427200232170ustar00rootroot00000000000000set test "xulrunner" # Test sdt support in xulrunner. global env if {! [info exists env(SYSTEMTAP_TESTAPPS)] || ( ! [string match "xulrunner" $env(SYSTEMTAP_TESTAPPS)] && ! [string match "all" $env(SYSTEMTAP_TESTAPPS)])} { untested "$test sdt app" return } ########## Create /tmp/stap-xul.stp ########## set xulrelease "1.9.2rc1" set xuldir "[pwd]/xul/" set testsuite "[pwd]" set fp [open "$testsuite/stap-xul.stp" "w"] puts $fp " global funcinfo global objinfo probe process(@1).mark(\"function__info\") { file = user_string (\$arg1) func = user_string (\$arg3) funcinfo\[file,func\] <<< 1 } probe process(@1).mark(\"object__create\") { file = user_string (\$arg1) class = user_string (\$arg2) objinfo\[file,class\] <<< 1 } probe end { foreach (\[i,j\] in funcinfo+) { printf (\"probes: %-20s %-25s %d\\n\", substr(i,strlen(i)-20,strlen(i)), j, @count(funcinfo\[i,j\])) } foreach (\[i,j\] in objinfo+) { printf (\"probes: %-20s %-25s %d\\n\", substr(i,strlen(i)-20,strlen(i)), j, @count(funcinfo\[i,j\])) } } " close $fp ########## Begin /tmp/stap-xul.sh ########## set fp [open "$testsuite/stap-xul.sh" "w"] puts $fp " ##### begin run_tests ##### function run_tests \{ cd $testsuite/xul/bld/js/src pwd for i in \$(find $xuldir/src/js/src/tests -mindepth 2 -name 'regress*' -prune \ -o -name 'shell.js' -prune -o \\( -name '*js' -print \\)) ; do $env(SYSTEMTAP_PATH)/stap -c \"./js -f $xuldir/src/js/src/tests/shell.js -f \$i\" \ $testsuite/stap-xul.stp ./js done | tee $testsuite/stap-xul-markers.log PROBES=\$(grep 'probes: ' $testsuite/stap-xul-markers.log | wc -l) TESTS=\$(grep '-FAIL' $testsuite/stap-xul-markers.log) echo PROBES=\$PROBES TESTS=\$TESTS if \[ \$PROBES -gt 400 \] ; then echo PASS: xulrunner javascript markers \$1 else echo FAIL: xulrunner javascript markers \$1 fi if \[ -z \$TESTS \] ; then echo PASS: xulrunner javascript testsuite \$1 else echo FAIL: xulrunner javascript testsuite \$1 fi \} ##### end run_tests ##### if \[ ! -r xulrunner-$xulrelease.source.tar.bz2 \] ; then wget -q ftp://ftp.mozilla.org/pub/mozilla.org/xulrunner/releases/$xulrelease/source/xulrunner-$xulrelease.source.tar.bz2 fi if \[ ! -r xulrunner-$xulrelease.source.tar.bz2 \] ; then echo FAIL: wget xulrunner-$xulrelease.source.tar.bz2 exit fi if \[ ! -d xul/src \] ; then bunzip2 xulrunner-$xulrelease.source.tar.bz2 tar -x -f xulrunner-$xulrelease.source.tar mkdir xul mv mozilla-* xul/src fi if \[ ! -f xul/bld/js/src/js \] ; then mkdir xul/bld cd xul/bld JAVA=`yum info available 'java*openjdk' |& awk '/Name/ {print \$3}'` for P in glib-devel ORBit-devel \$JAVA ; do if rpm -q \$P ; then : else echo FAIL: Need to: yum install \$P exit fi done JAVA_HOME=/usr/lib/jvm/\$JAVA.`uname -i` \ CXXFLAGS='-g -I$env(SYSTEMTAP_INCLUDES)' \ CFLAGS='-g -I$env(SYSTEMTAP_INCLUDES)' \ PATH=$env(SYSTEMTAP_PATH)/:\$PATH \ ../src/configure --prefix=$xuldir --enable-dtrace \ --enable-application=xulrunner \ --disable-necko-wifi sed -i '/include.*rules.mk/a\\ ifdef HAVE_DTRACE\\ PROGOBJS += ../mozjs-dtrace.\$(OBJ_SUFFIX)\\ endif\\ ' js/src/shell/Makefile sed -i '/include.*rules.mk/a\\ ifdef HAVE_DTRACE\\ PROGOBJS += ../mozjs-dtrace.\$(OBJ_SUFFIX)\\ endif\\ ' js/src/jsapi-tests/Makefile J=\$(getconf _NPROCESSORS_CONF) make fi run_tests uprobe " ########## End /tmp/stap-xul.sh ########## close $fp ########## /tmp/stap-xul.sh does most of the work ########## verbose -log Running xul testsuite spawn sh stap-xul.sh 2>&1 expect { -timeout 10000 -re {FAIL: [a-z_ ]+} { regexp " .*$" $expect_out(0,string) s; fail "$s"; exp_continue } -re {PASS: [a-z_ ]+} { regexp " .*$" $expect_out(0,string) s; pass "$s"; exp_continue } -re {UNSUPPORTED: [a-zA-Z_/: ]+} { regexp " .*$" $expect_out(0,string) s; verbose -log "$s" unsupported "$s"; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if { $verbose == 0 } { catch {exec rm -rf $testsuite/stap-xul.stp xulrunner-$xulrelease-source.tar \ $testsuite/stap-xul-markers.log $testsuite/stap-xul.sh } catch {exec rm -rf xul} } systemtap-2.3/testsuite/systemtap.base/000077500000000000000000000000001217430427200204045ustar00rootroot00000000000000systemtap-2.3/testsuite/systemtap.base/add.exp000066400000000000000000000004601217430427200216520ustar00rootroot00000000000000# Simple function to test that systemtap addition works set test "add" foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string \ --runtime=$runtime } else { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string } } systemtap-2.3/testsuite/systemtap.base/add.stp000066400000000000000000000005161217430427200216660ustar00rootroot00000000000000/* * add.stp * * Check that systemtap "addition" works */ global x3 global x1 global x2 probe begin { println("systemtap starting probe") x1 = 42; x2 = 53; } probe end { println("systemtap ending probe") x3 = x1 + x2; if (x3 != 95 ) { println("systemtap test failure") } else { println("systemtap test success") } } systemtap-2.3/testsuite/systemtap.base/alias-condition.exp000066400000000000000000000005011217430427200241730ustar00rootroot00000000000000# Check that conditions are copied correctly across aliases set test "alias-condition" foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string \ --runtime=$runtime } else { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string } } systemtap-2.3/testsuite/systemtap.base/alias-condition.stp000066400000000000000000000007061217430427200242140ustar00rootroot00000000000000/* * alias-condition.stp * * Check that conditions are copied correctly across aliases */ /* x should be incremented exactly once */ global x = 0 probe foo = begin { } probe foo if (x < 0), foo { ++x } probe begin(1) { println("systemtap starting probe") exit() } probe end { println("systemtap ending probe") if ( x != 1 ) { println("systemtap test failure") } else { println("systemtap test success") } } systemtap-2.3/testsuite/systemtap.base/alias_suffixes.exp000066400000000000000000000004751217430427200241350ustar00rootroot00000000000000set file $srcdir/$subdir/alias_suffixes foreach runtime [get_runtime_list] { foreach ix {01 02 03 04 05} { set test "alias suffixes $ix" if {$runtime != ""} { stap_run "$file$ix.stp" no_load $all_pass_string \ --runtime=$runtime } else { stap_run "$file$ix.stp" no_load $all_pass_string } } } systemtap-2.3/testsuite/systemtap.base/alias_suffixes01.stp000066400000000000000000000004501217430427200243010ustar00rootroot00000000000000/* * alias_suffixes01.stp * * Check basic alias suffix functionality */ probe begin { println("systemtap starting probe") } probe first.second = end { println("systemtap ending probe") print("systemtap test ") } probe third = first { } probe third.second { println("success") } systemtap-2.3/testsuite/systemtap.base/alias_suffixes02.stp000066400000000000000000000013401217430427200243010ustar00rootroot00000000000000/* * alias_suffixes02.stp * * Check whether alias suffixes and wildcards interact correctly */ /* 1 -- if an expansion includes ordinary matches, suffixes are not included */ probe first.icecream = begin(3) { println("systemtap test failure") } probe third.second = begin(1) { print("systemtap starting ") } probe third.secret = begin(2) { println("probe") } probe third = first { } probe third.*ec* { } /* 2 -- if an expansion has no ordinary matches, suffixes are included */ probe fourth.icecream = end(1) { println("systemtap test failure") } probe fourth.sectarian = end(2) { println("systemtap ending probe") } probe fourth.second = end(3) { println("systemtap test success") } probe fifth = fourth { } probe fifth.*se* { } systemtap-2.3/testsuite/systemtap.base/alias_suffixes03.stp000066400000000000000000000006241217430427200243060ustar00rootroot00000000000000/* * alias_suffixes02.stp * * Check whether alias suffixes are only invoked on ordinary matching failure */ probe begin(1) { println("systemtap starting probe") } probe first.second = begin(2) { println("systemtap test failure") } probe third = first { } probe third.second = end { println("systemtap ending probe") println("systemtap test success") } probe third.second { } systemtap-2.3/testsuite/systemtap.base/alias_suffixes04.stp000066400000000000000000000005221217430427200243040ustar00rootroot00000000000000/* * alias_suffixes02.stp * * Check whether alias suffixes and multiply defined aliases interact correctly */ probe first.second = begin { println("systemtap starting probe") } probe first.second = end { println("systemtap ending probe") println("systemtap test success") } probe third = first { } probe third.second { } systemtap-2.3/testsuite/systemtap.base/alias_suffixes05.stp000066400000000000000000000007121217430427200243060ustar00rootroot00000000000000/* * alias_suffixes05.stp * * Another test for correct behaviour of alias suffixes and wildcards */ global k probe begin { if (k != 1) println("systemtap starting probe") } probe a.return = end { println("systemtap ending probe") } probe unrelated = never { k = 2 } probe myprobe = a { k = 3 } probe myprobe.test = unrelated { k = 4 } probe myprobe.* { println("systemtap test failure") } probe myprobe.ret* { println("systemtap test success") } systemtap-2.3/testsuite/systemtap.base/alias_tapset.exp000066400000000000000000000017461217430427200236030ustar00rootroot00000000000000# This testcase is based on pr10568. It ensures that when an alias # causes a tapset file to be included, the entire files gets included. set test alias_tapset set never_found 0 set kernel_function_found 0 set timer_found 0 set cmd "stap -p2 -I $srcdir/$subdir/${test} $srcdir/$subdir/${test}.stp" verbose -log "running $cmd" eval spawn $cmd expect { -timeout 60 -re {^never[^\r\n]+\r\n} { incr never_found; exp_continue } -re {^kernel\.function[^\r\n]+\r\n} { incr kernel_function_found; exp_continue } -re {^timer[^\r\n]+\r\n} { incr timer_found; exp_continue } -re {^[^\r\n]+\r\n} { # ignore output we're not interested in exp_continue } timeout { verbose -log "TIMEOUT" } } catch { close } # get the return code of the process set rc [lindex [wait -i $spawn_id] 3] if { $rc == 0 && $never_found == 1 && $kernel_function_found == 1 && $timer_found == 1 } { pass $test } else { fail "$test ($rc, $never_found, $kernel_function_found, $timer_found)" } systemtap-2.3/testsuite/systemtap.base/alias_tapset.stp000066400000000000000000000000331217430427200236010ustar00rootroot00000000000000probe tapset_test.foo { } systemtap-2.3/testsuite/systemtap.base/alias_tapset/000077500000000000000000000000001217430427200230555ustar00rootroot00000000000000systemtap-2.3/testsuite/systemtap.base/alias_tapset/tapset_test.stp000066400000000000000000000002051217430427200261410ustar00rootroot00000000000000global _reads probe tapset_test.foo = never { next } probe syscall.read { _reads++ } probe timer.s(5) { printf("%d\n", _reads) } systemtap-2.3/testsuite/systemtap.base/alternatives.exp000066400000000000000000000026271217430427200236320ustar00rootroot00000000000000# alternatives.exp # # 2 simple tests: # # LOCAL1: makes sure that when a probe is compiled that accesses a # non-existent local variable, the local variables that do exist are # listed as alternatives. # # STRUCT1: makes sure that when a probe is compiled that accesses a # non-existent structure member, the structure members that do exist # are listed as alternatives. # # Note that the tests don't check if the correct alternatives are # listed, but that some alternatives are listed. set local1_script { probe kernel.function("vfs_write") { ret = $z; } } set struct1_script { probe kernel.function("vfs_write") { f_pos = $file->f_po; } } proc stap_run_alternatives {args} { set alternatives_found 0 verbose -log "starting $args" eval spawn $args expect { -timeout 60 -re {semantic error: .+ \(alternatives: \$?[a-zA-Z_]} {incr alternatives_found; exp_continue} -re {[^\r]*\r} { verbose -log $expect_out(0,string); exp_continue } eof { verbose -log "EOF" } timeout { verbose -log "TIMEOUT" } } set results [wait] verbose -log "wait results: $results" return $alternatives_found } set test "LOCAL1" set rc [stap_run_alternatives stap -u -p2 -e $local1_script] if {$rc >= 1} { pass $test } else { fail "$test ($rc)" } set test "STRUCT1" set rc [stap_run_alternatives stap -u -p2 -e $struct1_script] if {$rc >= 1} { pass $test } else { fail "$test ($rc)" } systemtap-2.3/testsuite/systemtap.base/arith.exp000066400000000000000000000010141217430427200222250ustar00rootroot00000000000000set test "arith" if {![installtest_p]} { untested $test; return } foreach runtime [get_runtime_list] { set test "arith" set args "" if {$runtime != ""} { lappend test "($runtime)" set args "--runtime=$runtime" } spawn stap -DMAXNESTING=5 $srcdir/$subdir/arith.stp $args set ok 0 expect { -timeout 150 -re {passes: [0-9]* failures: 0} { incr ok } timeout { fail "$test (timeout)" } eof { } } catch { close } catch { wait } if {$ok == 1} { pass "$test" } { fail "$test" } } systemtap-2.3/testsuite/systemtap.base/arith.stp000066400000000000000000000037351217430427200222530ustar00rootroot00000000000000global testno, passes, failures function test (v,n1,n2) { if (n1 == n2) { passes ++ result = "pass" } else { failures ++ result = "fail" } println ("test " . (sprint (++testno)) . " [" . v . "]\t" . result) } function stest (v,n1,n2) { if (n1 == n2) { passes ++ result = "pass" } else { failures ++ result = "fail" } println ("test " . (sprint (++testno)) . " [" . v . "]\t" . result) } probe begin { test ("+", 0, 0+0) test ("+", 33339999, 33330000+9999) test ("-", -1, 2-3) test ("==", 1, -1==-1) test ("!=", 1, -1!=1) test ("== s", 1, "foobar"=="foobar") test ("<= s", 1, "fooban"<="foobar") test ("> s", 1, "xxx">"aaa") test ("<", 1, -1<0) test ("<", 1, 85723838<8273823892) test ("*", 100300400500, 1003004005 * 100) test ("*", -1*-500, 500) test ("/", 1003004005/1000, 1003004) test ("%", 1003004005%1000, 5) test ("/", -1/-1, 1) test ("%", -1%-1, 0) test ("/", 0/-100, 0) test ("%", 0%-100, 0) test ("/", (-2147483647-1)/-1, 2147483648) test ("%", (-2147483647-1)%-1, 0) # but (-9223372036854775807-1)/-1 may overflow test ("%", (-9223372036854775807-1)%-1, 0) test ("&", 0x555&0xaaa, 0) test ("|", 0x555|0xaaa, 0xfff) test ("^", 0x55f^0xaaf, 0xff0) test ("&&", 0x555&&0xaaa, 1) test ("||", 0x555||0xaaa, 1) test ("<<", 0<<5, 0) test ("<<", 1<<8, 0x100) test ("<<", 120<<-2, 120) test ("<<", 120<<0, 120) test ("<<", -4096<<-3, -4096) test (">>", -4096>>3, -512) test (">>", -4096>>-3, -4096) test (">>", 120>>-2, 120) test (">>", 120>>0, 120) i=1; test ("--i", --i, 0) i=1; test ("++i", ++i, 2) i=1; test ("i--", i--, 1) i=1; test ("i++", i++, 1) i=1; test ("+=", i+=4, 5) test ("after +=", i, 5) i=5; test ("/=", i/=2, 2) test ("after /=", i, 2) a="1" b="2"; stest (".=", a .= b, "12") stest ("after .=", a, "12") } probe timer.sec(1) { # some time after all the begin probes exit () } probe end { printf ("passes: %d failures: %d\n", passes, failures) } systemtap-2.3/testsuite/systemtap.base/arith_limits.exp000066400000000000000000000010411217430427200236060ustar00rootroot00000000000000set test "arith_limits" if {![installtest_p]} { untested $test; return } foreach runtime [get_runtime_list] { set test "arith_limits" set args "" if {$runtime != ""} { lappend test "($runtime)" set args "--runtime=$runtime" } spawn stap -DMAXNESTING=5 $srcdir/$subdir/arith_limits.stp $args set ok 0 expect { -timeout 150 -re {passes: [0-9]* failures: 0} { incr ok } timeout { fail "$test (timeout)" } eof { } } catch { close } catch { wait } if {$ok == 1} { pass "$test" } { fail "$test" } } systemtap-2.3/testsuite/systemtap.base/arith_limits.stp000066400000000000000000000040731217430427200236300ustar00rootroot00000000000000global testno, passes, failures function test (v,n1,n2) { if (n1 == n2) { passes ++ result = "pass" } else { failures ++ result = "fail" } printf ("test %d [%s]\t\t%s\n", testno++, v, result) } # Exactly the same as test() except it will magically work for strings. # Wouldn't it be nice if we didn't have to do this? function teststr (v,n1,n2) { if (n1 == n2) { passes ++ result = "pass" } else { failures ++ result = "fail" } printf ("test %d [%s]\t\t%s\n", testno++, v, result) } probe begin { # max/minimum signed 32-bit values. # these could cause problems for 32-bit cpus when overflows # occur into 64-but values lmax = 0x7fffffff lmin = -0x80000000 # max/minimum signed 64-bit values llmax = 0x7fffffffffffffff llmin = -0x7fffffffffffffff-1 # 32-bit limit tests teststr ("string lmax", sprint(lmax), "2147483647") teststr ("hex lmax", sprintf("0x%x", lmax), "0x7fffffff") teststr ("string lmin", sprint(lmin), "-2147483648") teststr ("hex lmin", sprintf("0x%x", lmin), "0xffffffff80000000") test ("lmax/-1", lmax/-1, -2147483647); test ("lmin/-1", lmin/-1, 2147483648); test ("lmax +1", lmax+1, 2147483648); test ("lmin -1", lmin-1, -2147483649); # 64-bit limits teststr ("string llmax", sprint(llmax), "9223372036854775807") teststr ("hex llmax", sprintf("0x%x", llmax), "0x7fffffffffffffff") teststr ("string llmin", sprint(llmin), "-9223372036854775808") teststr ("hex llmin", sprintf("0x%x", llmin), "0x8000000000000000") test ("llmax/-1", llmax/-1, -llmax) test ("llmax*-1", llmax*-1, -llmax) # the next three overflow and produce predictable, although # wrong results test ("llmin/-1", llmin/-1, llmin) test ("llmin*-1", llmin*-1, llmin) test ("llmax +1", llmax+1, llmin) test ("llmin -1", llmin-1, llmax) # modulo tests test ("llmax%1", llmax%1, 0) test ("llmin%1", llmin%1, 0) test ("0%1 ", 0%1, 0) test ("0%lmax", 0%lmax, 0) test ("1%lmax", 1%lmax, 1) test ("0%lmin", 0%lmin, 0) test ("1%lmin", 1%lmin, 1) exit() } probe end { printf ("passes: %d failures: %d\n", passes, failures) } systemtap-2.3/testsuite/systemtap.base/array_size.exp000066400000000000000000000005561217430427200233000ustar00rootroot00000000000000# Check that specifying an array size gives more room than MAXMAPENTRIES set test "array_size" foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string \ -DMAXMAPENTRIES=1 --runtime=$runtime } else { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string -DMAXMAPENTRIES=1 } } systemtap-2.3/testsuite/systemtap.base/array_size.stp000066400000000000000000000011321217430427200233010ustar00rootroot00000000000000/* * array_size.stp * * Check that specifying an array size gives more room than MAXMAPENTRIES * * Call with MAXMAPENTRIES << 100 */ probe begin { println("systemtap starting probe") } probe end { println("systemtap ending probe") } global a[100] probe begin { for (i=42; i<142; ++i) a[i] = i*i } probe end(1) { for (i=42; i<142; ++i) { if (a[i] == i*i) ++ok else ++bad } if (ok == 100 && bad == 0) println("systemtap test success") else printf("systemtap test failure - ok:%d, bad:%d\n", ok, bad) } systemtap-2.3/testsuite/systemtap.base/array_string.exp000066400000000000000000000033731217430427200236340ustar00rootroot00000000000000# PR 11220. Make sure we can store large strings in arrays. if {![installtest_p]} { untested $test; return } set test "ARRAY_STRING" set test_script { global str global str_array[1] probe begin { str = " 0:123456789+123456789+123456789+123456789+123456789+123456789 1:123456789+123456789+123456789+123456789+123456789+123456789 2:123456789+123456789+123456789+123456789+123456789+123456789 3:123456789+123456789+123456789+123456789+123456789+123456789 4:123456789+123456789+123456789+123456789+123456789+123456789 5:123456789+123456789+123456789+123456789+123456789+123456789 6:123456789+123456789+123456789+123456789+123456789+123456789 7:123456789+123456789+123456789+123456789+123456789+123456789" str_array[0] = str printf("systemtap starting probe\n") } probe end { printf("systemtap ending probe\n") if (strlen(str) < 500) { printf("string str is too short: %d\n", strlen(str)) printf("%s\n", str) } if (strlen(str) == strlen(str_array[0])) { printf("string lengths match\n") } else { printf("string lengths *don't* match\n") printf("str: %d\n", strlen(str)) printf("str_array[0]: %d\n", strlen(str_array[0])) } if (str_array[0] == str) { printf("strings match\n") } else { printf("strings *don't* match!\n") printf("str: %s\n", str) printf("str_array[0]: %s\n", str_array[0]) } } } set output "string lengths match\r\nstrings match\r\n" # Set MAXSTRINGLEN to 512 to be sure we're testing what we intend. foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run "$test ($runtime)" no_load $output -DMAXSTRINGLEN=512 \ --runtime=$runtime -e $test_script } else { stap_run $test no_load $output -DMAXSTRINGLEN=512 -e $test_script } } systemtap-2.3/testsuite/systemtap.base/at_var.c000066400000000000000000000005661217430427200220330ustar00rootroot00000000000000#include struct foo { int bar; }; static struct foo foo; void sub(const char *file) { struct timeval times[2]; times[0].tv_sec = 1; times[0].tv_usec = 2; times[1].tv_sec = 3; times[1].tv_usec = 4; utimes (file, times); foo.bar -= 2; /* 40 */ } int main (int argc, char **argv) { foo.bar = 41 + argc; /* 42 */ sub(argv[0]); return 0; } systemtap-2.3/testsuite/systemtap.base/at_var.exp000066400000000000000000000024261217430427200224020ustar00rootroot00000000000000set test "at_var" set testpath "$srcdir/$subdir" # Test that $var and @var("var") work identically for parameters, variables, # for uprobes and kprobes with members, arrays, taking the address and also # plays nice when used in combination with @cast and @entry. set ::result_string {$argc: 1 @var("argc"): 1 user_string($argv[0]): ./at_var user_string(@var("argv")[0]): ./at_var $foo->bar: 42 @var("foo")->bar: 42 $utimes$$: {.tv_sec=1, .tv_usec=2} $utimes[1]$$: {.tv_sec=3, .tv_usec=4} @var("utimes")$$: {.tv_sec=1, .tv_usec=2} @var("utimes")[1]$$: {.tv_sec=3, .tv_usec=4} user_int(&$foo->bar): 40 user_int(&@var("foo")->bar): 40 &@cast($foo->bar, "struct foo")->bar: 42 &@cast(@var("foo")->bar, "struct foo")->bar: 42 $foo->bar == @entry($foo->bar): true @var("foo")->bar == @entry(@var("foo")->bar): true} # Only run on make installcheck and uprobes present. if {! [installtest_p]} { untested "$test"; return } if {! [uretprobes_p]} { untested "$test"; return } set res [target_compile ${testpath}/${test}.c ${test} executable "additional_flags=-O2 additional_flags=-g"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile ${test}.c" } stap_run3 $test $srcdir/$subdir/$test.stp -c ./${test} # Cleanup if { $verbose == 0 } { catch { exec rm -f $test } } systemtap-2.3/testsuite/systemtap.base/at_var.stp000066400000000000000000000033531217430427200224140ustar00rootroot00000000000000probe process.function("main") { printf("$argc: %d\n", $argc); printf("@var(\"argc\"): %d\n", @var("argc")); printf("user_string($argv[0]): %s\n", user_string($argv[0])); printf("user_string(@var(\"argv\")[0]): %s\n", user_string(@var("argv")[0])); } probe process.function("sub") { printf("$foo->bar: %d\n", $foo->bar); printf("@var(\"foo\")->bar: %d\n", @var("foo")->bar); } /* NB: can't just use syscall.utimes, because with HAVE_SYSCALL_WRAPPERS the * primary sys_utimes function has all long types. Also, all architectures * effectively HAVE_SYSCALL_WRAPPERS starting in 3.10! */ probe kernel.function("SYSC_utimes")!, kernel.function("sys_utimes") { printf("$utimes$$: %s\n", $utimes$$); printf("$utimes[1]$$: %s\n", $utimes[1]$$); printf("@var(\"utimes\")$$: %s\n", @var("utimes")$$); printf("@var(\"utimes\")[1]$$: %s\n", @var("utimes")[1]$$); } probe process.function("sub").return { /* Take the address and dereference to get current value. */ printf("user_int(&$foo->bar): %d\n", user_int(&$foo->bar)); printf("user_int(&@var(\"foo\")->bar): %d\n", user_int(&@var("foo")->bar)); /* $foo->bar is 42 (on entry), the offset of bar in struct foo is zero, so taking the address of that field is 42 again. */ printf("&@cast($foo->bar, \"struct foo\")->bar: %d\n", &@cast($foo->bar, "struct foo")->bar); printf("&@cast(@var(\"foo\")->bar, \"struct foo\")->bar: %d\n", &@cast(@var("foo")->bar, "struct foo")->bar); /* Note that variables are taken at entry in both cases. */ printf("$foo->bar == @entry($foo->bar): %s\n", $foo->bar == @entry($foo->bar) ? "true" : "false"); printf("@var(\"foo\")->bar == @entry(@var(\"foo\")->bar): %s\n", @var("foo")->bar == @entry(@var("foo")->bar) ? "true" : "false"); } systemtap-2.3/testsuite/systemtap.base/at_var_cu.exp000066400000000000000000000033731217430427200230730ustar00rootroot00000000000000set test "at_var_cu" set testpath "$srcdir/$subdir" set exefile "[pwd]/$test" set stap_path $env(SYSTEMTAP_PATH)/stap set staprun_path $env(SYSTEMTAP_PATH)/staprun # Test that @var("var@cu", "module") and @var("var@cu") search # in all the CUs that look like a match for the pattern "cu". set ::result_string {foo: @var("counter", @1): 0 foo: @var("counter@at_var_cu_2.c", @1): 0 foo: @var("counter@at_var_cu_3.c", @1): 0 foo: @var("counter@at_var_cu*.c", @1): 0 bar: @var("counter", @1): 7 bar: @var("counter@at_var_cu_2.c", @1): 7 bar: @var("counter@at_var_cu_3.c", @1): 0 bar: @var("counter@at_var_cu*.c", @1): 7 baz: @var("counter", @1): 8 baz: @var("counter@at_var_cu_2.c", @1): 8 baz: @var("counter@at_var_cu_3.c", @1): 0 baz: @var("counter@at_var_cu*.c", @1): 8 bah: @var("counter", @1): 8 bah: @var("counter@at_var_cu_2.c", @1): 8 bah: @var("counter@at_var_cu_3.c", @1): 3 bah: @var("counter@at_var_cu*.c", @1): 8 bah': @var("counter@at_var_cu*.c"): 8 bah': @var("main_global"): 5} # Only run on make installcheck and uprobes present. if {! [installtest_p]} { untested "$test"; return } set sources \ "$testpath/${test}_1.c $testpath/${test}_2.c $testpath/${test}_3.c" set res [target_compile "$sources" $exefile executable \ "additional_flags=-O2 additional_flags=-g"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile ${test}.c" } foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run3 "$test ($runtime)" $srcdir/$subdir/$test.stp -c ./$test \ $exefile --runtime=$runtime } elseif {[uprobes_p]} { stap_run3 $test $srcdir/$subdir/$test.stp -c ./$test $exefile } else { untested "$test" } } # Cleanup if { $verbose == 0 } { catch { exec rm -f $test } } systemtap-2.3/testsuite/systemtap.base/at_var_cu.stp000066400000000000000000000014051217430427200230770ustar00rootroot00000000000000function out(ctx) { printf("%s: @var(\"counter\", @1): %d\n", ctx, @var("counter", @1)) printf("%s: @var(\"counter@at_var_cu_2.c\", @1): %d\n", ctx, @var("counter@at_var_cu_2.c", @1)) printf("%s: @var(\"counter@at_var_cu_3.c\", @1): %d\n", ctx, @var("counter@at_var_cu_3.c", @1)) printf("%s: @var(\"counter@at_var_cu*.c\", @1): %d\n", ctx, @var("counter@at_var_cu*.c", @1)) } probe process.function("foo") { out("foo") } probe process.function("bar") { out("bar") } probe process.function("baz") { out("baz") } probe process.function("bah") { out("bah") printf("bah': @var(\"counter@at_var_cu*.c\"): %d\n", @var("counter@at_var_cu*.c")) printf("bah': @var(\"main_global\"): %d\n", @var("main_global")) } systemtap-2.3/testsuite/systemtap.base/at_var_cu_1.c000066400000000000000000000002171217430427200227330ustar00rootroot00000000000000extern void foo(void); extern void bar(void); static int main_global = 5; int main(void) { foo(); bar(); baz(); bah(); return 0; } systemtap-2.3/testsuite/systemtap.base/at_var_cu_2.c000066400000000000000000000001301217430427200227260ustar00rootroot00000000000000static int counter; void foo(void) { counter = 7; } void bar(void) { counter++; } systemtap-2.3/testsuite/systemtap.base/at_var_cu_3.c000066400000000000000000000001301217430427200227270ustar00rootroot00000000000000static int counter; void baz(void) { counter = 3; } void bah(void) { counter--; } systemtap-2.3/testsuite/systemtap.base/at_var_func.exp000066400000000000000000000031261217430427200234130ustar00rootroot00000000000000set test "at_var_func" set testpath "$srcdir/$subdir" set exefile "[pwd]/$test" set stap_path $env(SYSTEMTAP_PATH)/stap set staprun_path $env(SYSTEMTAP_PATH)/staprun # Test that @var("var@cu", "module") work in contextless stap functions. # Also ensure that the module argument can be multiple module names # separated by colon, e.g., "module1:module2:module3". # Also test that unresolved @var() can be properly caught by @defined(). set ::result_string {@var("foo", @1)->bar: 42 @var("foo@at_var.c", @1)->bar: 42 @var("foo@at_var.c", @2)->bar: 42 @var("foo", @1)$: {.bar=42} @var("foo", @1)$$: {.bar=42} @defined(@var("foo", "badmodle")->bar): NO @defined(@var("foo", @3)->bar): NO @defined(@var("foo@blah.c", @1)->bar): NO @var("foo")->bar: 42} # Only run on make installcheck and uprobes present. if {! [installtest_p]} { untested "$test"; return } set res [target_compile ${testpath}/at_var.c $exefile executable \ "additional_flags=-O2 additional_flags=-g"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile ${test}.c" } foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run3 "$test ($runtime)" $srcdir/$subdir/$test.stp -c ./$test \ $exefile "$stap_path:$exefile:$staprun_path" \ "$stap_path:$staprun_path" --runtime=$runtime } elseif {[uprobes_p]} { stap_run3 $test $srcdir/$subdir/$test.stp -c ./$test $exefile \ "$stap_path:$exefile:$staprun_path" "$stap_path:$staprun_path" } else { untested "$test" } } # Cleanup if { $verbose == 0 } { catch { exec rm -f $test } } systemtap-2.3/testsuite/systemtap.base/at_var_func.stp000066400000000000000000000014741217430427200234310ustar00rootroot00000000000000function f() { printf("@var(\"foo\", @1)->bar: %d\n", @var("foo", @1)->bar); printf("@var(\"foo@at_var.c\", @1)->bar: %d\n", @var("foo@at_var.c", @1)->bar); printf("@var(\"foo@at_var.c\", @2)->bar: %d\n", @var("foo@at_var.c", @2)->bar); printf("@var(\"foo\", @1)$: %s\n", @var("foo", @1)$); printf("@var(\"foo\", @1)$$: %s\n", @var("foo", @1)$$); printf("@defined(@var(\"foo\", \"badmodle\")->bar): %s\n", @defined(@var("foo", "badmodule")->bar) ? "YES" : "NO") printf("@defined(@var(\"foo\", @3)->bar): %s\n", @defined(@var("foo", @3)->bar) ? "YES" : "NO") printf("@defined(@var(\"foo@blah.c\", @1)->bar): %s\n", @defined(@var("foo@blah.c", @1)->bar) ? "YES" : "NO") } probe process.function("sub") { f() printf("@var(\"foo\")->bar: %d\n", @var("foo")->bar); } systemtap-2.3/testsuite/systemtap.base/at_var_lvalue.c000066400000000000000000000006261217430427200234000ustar00rootroot00000000000000#include struct foo { int bar; }; static struct foo foo; void sub(const char *file) { struct timeval times[2]; times[0].tv_sec = 1; times[0].tv_usec = 2; times[1].tv_sec = 3; times[1].tv_usec = 4; utimes (file, times); foo.bar -= 2; /* 40 */ } int main (int argc, char **argv) { foo.bar = 41 + argc; /* 42 */ sub(argv[0]); sub(argv[0]); sub(argv[0]); return 0; } systemtap-2.3/testsuite/systemtap.base/at_var_lvalue.exp000066400000000000000000000020211217430427200237410ustar00rootroot00000000000000set test "at_var_lvalue" set testpath "$srcdir/$subdir" set exefile "[pwd]/$test" # Test that @var("var") can be used as an lvalue in guru mode. set ::result_string {0: @var("foo")->bar: 41 0: @var("foo@at_var_lvalue.c")->bar: 40 1: @var("foo@at_var_lvalue.c", @1)->bar: 37 2: @var("foo@at_var_lvalue.c", @1)->bar: 34} # Only run on make installcheck and uprobes present. if {! [installtest_p]} { untested "$test"; return } set res [target_compile ${testpath}/${test}.c ${test} executable "additional_flags=-O2 additional_flags=-g"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile ${test}.c" } foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run3 "$test ($runtime)" $srcdir/$subdir/$test.stp -c ./${test} -g $exefile \ --runtime=$runtime } elseif {[uprobes_p]} { stap_run3 $test $srcdir/$subdir/$test.stp -c ./${test} -g $exefile } else { untested "$test" } } # Cleanup if { $verbose == 0 } { catch { exec rm -f $test } } systemtap-2.3/testsuite/systemtap.base/at_var_lvalue.stp000066400000000000000000000011411217430427200237550ustar00rootroot00000000000000global i = 0 function f(n) { @var("foo@at_var_lvalue.c", @1)->bar = @var("foo@at_var_lvalue.c", @1)->bar - 1 printf("%d: @var(\"foo@at_var_lvalue.c\", @1)->bar: %d\n", n, @var("foo@at_var_lvalue.c", @1)->bar) } probe process.function("sub") { if (i == 0) { @var("foo")->bar = @var("foo")->bar - 1 printf("0: @var(\"foo\")->bar: %d\n", @var("foo")->bar) @var("foo@at_var_lvalue.c")->bar = @var("foo@at_var_lvalue.c")->bar - 1 printf("0: @var(\"foo@at_var_lvalue.c\")->bar: %d\n", @var("foo@at_var_lvalue.c")->bar) } else { f(i) } i++ } systemtap-2.3/testsuite/systemtap.base/at_var_mark.exp000066400000000000000000000015301217430427200234070ustar00rootroot00000000000000set test "at_var_mark" set testpath "$srcdir/$subdir" set stap_path $env(SYSTEMTAP_PATH)/stap # Check @var, even when var doesn't exist, works in process.mark probes. set output_string "s = \\d+\r\n.*pass:yes:0\r\n" set invoke "$stap_path -e 'probe begin \{ exit() \}'" # Only run on make installcheck and uprobes present. if {! [installtest_p]} { untested "$test"; return } foreach runtime [get_runtime_list] { if {$runtime != ""} { if {$runtime == "dyninst"} { # dyninst lacks support for VMA-tracking setup_kfail 15052 "*-*-*" } stap_run "${test} ($runtime)" wait_5_secs $output_string \ --runtime=$runtime ${testpath}/${test}.stp -c $invoke } elseif {[uprobes_p]} { stap_run ${test} wait_5_secs $output_string \ ${testpath}/${test}.stp -c $invoke } else { untested "$test" } } systemtap-2.3/testsuite/systemtap.base/at_var_mark.stp000066400000000000000000000007561217430427200234320ustar00rootroot00000000000000global more_addr = 0; probe process.mark("pass*") { if (more_addr == 0) { log("systemtap starting probe"); log("systemtap ending probe"); more_addr = @var("morehelp@session.cxx"); printf("s = %d\n", @var("s")) } else { name = substr($$name, 0, 4); correct = @defined(@var("no_such_var_really_not")) ? "no" : "yes"; diff = more_addr - @var("morehelp@session.cxx"); printf("%s:%s:%d\n", name, correct, diff); exit(); } } systemtap-2.3/testsuite/systemtap.base/at_var_mark_func.exp000066400000000000000000000016571217430427200244340ustar00rootroot00000000000000set test "at_var_mark_func" set testpath "$srcdir/$subdir" set stap_path $env(SYSTEMTAP_PATH)/stap # Check @var in contextless stap functions, even when @var # doesn't exist, works in process.mark probes. set output_string "pass:yes:0\r\n" set invoke "$stap_path -e 'probe begin \{ exit() \}'" # Only run on make installcheck and uprobes present. if {! [installtest_p]} { untested "$test"; return } foreach runtime [get_runtime_list] { if {$runtime != ""} { if {$runtime == "dyninst"} { # dyninst lacks support for VMA-tracking setup_kfail 15052 "*-*-*" } stap_run "${test} ($runtime)" wait_5_secs $output_string \ ${testpath}/${test}.stp "$stap_path" -c $invoke --runtime=$runtime } elseif {[uprobes_p]} { stap_run "${test}" wait_5_secs $output_string \ ${testpath}/${test}.stp "$stap_path" -c $invoke } else { untested "$test" } } systemtap-2.3/testsuite/systemtap.base/at_var_mark_func.stp000066400000000000000000000007721217430427200244430ustar00rootroot00000000000000global more_addr = 0; function foo(name) { if (more_addr == 0) { log("systemtap starting probe"); more_addr = @var("morehelp@session.cxx", @1); } else { log("systemtap ending probe"); name = substr(name, 0, 4); correct = @defined(@var("no_such_var_really_not", @1)) ? "no" : "yes"; diff = more_addr - @var("morehelp@session.cxx", @1); printf("%s:%s:%d\n", name, correct, diff); exit(); } } probe process.mark("pass*") { foo($$name) } systemtap-2.3/testsuite/systemtap.base/at_var_pie.exp000066400000000000000000000031221217430427200232310ustar00rootroot00000000000000set test "at_var_pie" set testpath "$srcdir/$subdir" set exefile "[pwd]/$test" set stap_path $env(SYSTEMTAP_PATH)/stap set staprun_path $env(SYSTEMTAP_PATH)/staprun # Test that @var("var@cu", "module") work with PIE. set ::result_string {@var("foo", @1)->bar: 42 @var("foo@at_var.c", @1)->bar: 42 @var("foo@at_var.c", @2)->bar: 42 @var("foo", @1)$: {.bar=42} @var("foo", @1)$$: {.bar=42} @defined(@var("foo", "badmodle")->bar): NO @defined(@var("foo", @3)->bar): NO @defined(@var("foo@blah.c", @1)->bar): NO @var("foo")->bar: 42} # Only run on make installcheck and uprobes present. if {! [installtest_p]} { untested "$test"; return } set res [target_compile ${testpath}/at_var.c $exefile executable \ "additional_flags=-O2 additional_flags=-g additional_flags=-fPIE additional_flags=-pie"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile ${test}.c" } foreach runtime [get_runtime_list] { if {$runtime != ""} { if {$runtime == "dyninst"} { # dyninst lacks support for relocations as required by PIE setup_kfail 15052 "*-*-*" } stap_run3 "$test ($runtime)" $srcdir/$subdir/at_var_func.stp -c ./$test \ $exefile "$stap_path:$exefile:$staprun_path" \ "$stap_path:$staprun_path" --runtime=$runtime } elseif {[uprobes_p]} { stap_run3 $test $srcdir/$subdir/at_var_func.stp -c ./$test $exefile \ "$stap_path:$exefile:$staprun_path" "$stap_path:$staprun_path" } else { untested "$test" } } # Cleanup if { $verbose == 0 } { catch { exec rm -f $test } } systemtap-2.3/testsuite/systemtap.base/at_var_timer_profile.c000066400000000000000000000004761217430427200247530ustar00rootroot00000000000000#include #include struct foo { int bar; }; static struct foo foo; int sub(int a) { int i, j; for (i = 0; i < 1000; i++) for (j = 0; j < 1000; j++) a += i + j + rand(); return a; } int main (int argc, char **argv) { foo.bar = 41 + argc; /* 42 */ sub(argc); return 0; } systemtap-2.3/testsuite/systemtap.base/at_var_timer_profile.exp000066400000000000000000000033001217430427200253120ustar00rootroot00000000000000set test "at_var_timer_profile" set testpath "$srcdir/$subdir" set exefile "[pwd]/$test" set stap_path $env(SYSTEMTAP_PATH)/stap set staprun_path $env(SYSTEMTAP_PATH)/staprun # Test that @var("var@cu", "module") work in the context of # timer.profile. # Also ensure that the module argument can be multiple module names # separated by colon, e.g., "module1:module2:module3". # Also test that unresolved @var() can be properly caught by @defined(). set ::result_string {@var("foo", @1)->bar: 42 @var("foo@at_var_timer_profile.c", @1)->bar: 42 @var("foo@at_var_timer_profile.c", @2)->bar: 42 @var("foo", @1)$: {.bar=42} @var("foo", @1)$$: {.bar=42} @defined(@var("foo", "badmodle")): NO @defined(@var("foo", @3)): NO} # Only run on make installcheck and uprobes present. if {! [installtest_p]} { untested "$test"; return } set res [target_compile ${testpath}/$test.c $exefile executable "additional_flags=-O2 additional_flags=-g"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile ${test}.c" } foreach runtime [get_runtime_list] { if {$runtime != ""} { if {$runtime == "dyninst"} { # dyninst lacks support for probe timer.profile setup_kfail 15540 "*-*-*" } stap_run3 "$test ($runtime)" $srcdir/$subdir/$test.stp -c ./$test $exefile \ "$stap_path:$exefile:$staprun_path" "$stap_path:$staprun_path" \ --runtime=$runtime } elseif {[uprobes_p]} { stap_run3 $test $srcdir/$subdir/$test.stp -c ./$test $exefile \ "$stap_path:$exefile:$staprun_path" "$stap_path:$staprun_path" } else { untested "$test" } } # Cleanup if { $verbose == 0 } { catch { exec rm -f $test } } systemtap-2.3/testsuite/systemtap.base/at_var_timer_profile.stp000066400000000000000000000014621217430427200253330ustar00rootroot00000000000000global active = 0 probe process.function("sub") { active = 1 } probe timer.profile { if (active && pid() == target()) { printf("@var(\"foo\", @1)->bar: %d\n", @var("foo", @1)->bar); printf("@var(\"foo@at_var_timer_profile.c\", @1)->bar: %d\n", @var("foo@at_var_timer_profile.c", @1)->bar); printf("@var(\"foo@at_var_timer_profile.c\", @2)->bar: %d\n", @var("foo@at_var_timer_profile.c", @2)->bar); printf("@var(\"foo\", @1)$: %s\n", @var("foo", @1)$); printf("@var(\"foo\", @1)$$: %s\n", @var("foo", @1)$$); printf("@defined(@var(\"foo\", \"badmodle\")): %s\n", @defined(@var("foo", "badmodule")) ? "YES" : "NO") printf("@defined(@var(\"foo\", @3)): %s\n", @defined(@var("foo", @3)) ? "YES" : "NO") exit() } } systemtap-2.3/testsuite/systemtap.base/at_var_tracepoint.exp000066400000000000000000000005251217430427200246300ustar00rootroot00000000000000set test "at_var_tracepoint" set testpath "$srcdir/$subdir" # Check @var() is usable in the kernel tracepoint probes. set output_string "sys_tz = {.tz_minuteswest=-?\\d+, .tz_dsttime=\\d+}" # Only run on make installcheck if {! [installtest_p]} { untested "$test"; return } stap_run ${test} no_load $output_string ${testpath}/${test}.stp systemtap-2.3/testsuite/systemtap.base/at_var_tracepoint.stp000066400000000000000000000003601217430427200246370ustar00rootroot00000000000000# Test global vars are usable in the kernel tracepoint probes. probe kernel.trace("sched_switch") { log("systemtap starting probe"); log("systemtap ending probe"); printf("sys_tz = %s\n", @var("sys_tz@kernel/time.c")$$); exit(); } systemtap-2.3/testsuite/systemtap.base/at_var_unresolved.exp000066400000000000000000000024341217430427200246470ustar00rootroot00000000000000set test "at_var_unresolved" # Ensure that there is only one error message for an unresolved @var. # Only run on make installcheck if {! [installtest_p]} { untested "$test"; return } # Case 1: Test @var("name"): spawn stap -e "probe begin { println(@var(\"var_really_not_exist\")) exit() }" set errs 0 expect { -timeout 180 -re {^semantic error: unable to find global 'var_really_not_exist'.*? in kernel: operator '@var'} { incr errs; exp_continue } -re {^sematnic error: } { incr errs; exp_continue } -re {^[^\r\n]*\r\n} { exp_continue } timeout { fail "$test (timeout)" } eof { } } wait if {$errs == 1} { pass "$test ($errs)" } { fail "$test ($errs)" } # Case 2: Test @var("name@cuname"): set errs 0 spawn stap -e "probe begin { println(@var(\"var_really_not_exist@*.c\")) exit() }" set ok 0 expect { -timeout 180 -re {^semantic error: unable to find global 'var_really_not_exist'.*? in kernel, in \*\.c} { incr ok; exp_continue } -re {^sematnic error: } { incr errs; exp_continue } -re {^[^\r\n]*\r\n} { exp_continue } timeout { fail "$test (timeout)" } eof { } } wait if {$ok == 1 && $errs == 0} { pass "$test (cuname: $ok, $errs)" } { fail "$test (cuname: $ok, $errs)" } systemtap-2.3/testsuite/systemtap.base/at_var_unresolved_lvalue.exp000066400000000000000000000016431217430427200262200ustar00rootroot00000000000000set test "at_var_unresolved_lvalue" set testpath "$srcdir/$subdir" # Check unresolved @var used as lvalue. # Only run on make installcheck and uprobes present. if {! [installtest_p]} { untested "$test"; return } if {! [uprobes_p]} { untested "$test"; return } set res [target_compile ${testpath}/at_var.c $test executable \ "additional_flags=-O2 additional_flags=-g"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile ${test}.c" } spawn stap $srcdir/$subdir/$test.stp -c ./$test $test -g set ok 0 expect { -timeout 180 -re {^semantic error: unable to find global 'no_such_variable' in at_var_unresolved_lvalue} { incr ok; exp_continue } -re {^[^\r\n]*\r\n} { exp_continue } timeout { fail "$test (timeout)" } eof { } } wait if {$ok == 1} { pass "$test" } { fail "$test" } # Cleanup if { $verbose == 0 } { catch { exec rm -f $test } } systemtap-2.3/testsuite/systemtap.base/at_var_unresolved_lvalue.stp000066400000000000000000000001161217430427200262240ustar00rootroot00000000000000probe process.function("sub") { @var("no_such_variable", @1) = 3 exit() } systemtap-2.3/testsuite/systemtap.base/at_var_void_stmt.c000066400000000000000000000006001217430427200241100ustar00rootroot00000000000000#include struct foo { int bar[1]; }; static struct foo foo; void sub(const char *file) { struct timeval times[2]; times[0].tv_sec = 1; times[0].tv_usec = 2; times[1].tv_sec = 3; times[1].tv_usec = 4; utimes (file, times); foo.bar[0] -= 2; /* 40 */ } int main (int argc, char **argv) { foo.bar[0] = 41 + argc; /* 42 */ sub(argv[0]); return 0; } systemtap-2.3/testsuite/systemtap.base/at_var_void_stmt.exp000066400000000000000000000021131217430427200244630ustar00rootroot00000000000000set test "at_var_void_stmt" set testpath "$srcdir/$subdir" # Check the void statement reducer with @var. set output_string ".*?enter func sub\r\n" # Only run on make installcheck and uprobes present. if {! [installtest_p]} { untested "$test"; return } set res [target_compile ${testpath}/$test.c $test executable \ "additional_flags=-O2 additional_flags=-g"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile ${test}.c" } spawn stap -vvv $srcdir/$subdir/$test.stp -c ./$test $test set ok 0 set logs 0 expect { -timeout 180 -re {^Eliding unused target symbol operator '@var'} { incr logs; exp_continue } -re {^Eliding side-effect-free singleton block operator '@var'} { incr logs; exp_continue } -re {^count = 3\r\n} { incr ok; exp_continue; } -re {^[^\r\n]*\r\n} { exp_continue } timeout { fail "$test (timeout)" } eof { } } wait if {$ok == 1 && $logs == 2} { pass "$test ($ok, $logs)" } { fail "$test ($ok, $logs)" } # Cleanup if { $verbose == 0 } { catch { exec rm -f $test } } systemtap-2.3/testsuite/systemtap.base/at_var_void_stmt.stp000066400000000000000000000002471217430427200245030ustar00rootroot00000000000000global count = 1 function foo() { count += 2 return 0 } probe process.function("sub") { @var("foo", @1)->bar[foo()] printf("count = %d\n", count) exit() } systemtap-2.3/testsuite/systemtap.base/atomic.exp000066400000000000000000000074751217430427200224130ustar00rootroot00000000000000set test "atomic" if {![installtest_p]} {untested $test; return} # # First test atomic_long_read() # set script_template { probe begin { print("systemtap starting probe\n") exit() } probe end { print("systemtap ending probe\n") printf("%%d\n", %s_read(%s)) } } # First try reading from address 0, which should fail. set test "atomic1" set error {read fault .* at 0x[^\r]+} set script [format $script_template "atomic_long" "0"] stap_run_error $test 1 $error "0\r\n" -e $script # Try reading from address -1 (top of memory), which should fail. set test "atomic2" set script [format $script_template "atomic_long" "-1"] stap_run_error $test 1 $error "0\r\n" -e $script # Try reading from address 3, which should fail (if nothing else # because it isn't aligned properly). set test "atomic3" set script [format $script_template "atomic_long" "3"] stap_run_error $test 1 $error "0\r\n" -e $script # Since we want to fail semi-gracefully (no compile errors), if we # don't have atomic_long_t support on this kernel (no # ATOMIC_LONG_INIT) the testcase will compile, but fail. set atomic_long_script_module_template { %%{ #include #ifdef ATOMIC_LONG_INIT struct { ulong barrier1; atomic_long_t a; ulong barrier2; } stp_atomic_struct = { ULONG_MAX, ATOMIC_LONG_INIT(5), ULONG_MAX }; #else struct { ulong barrier1; long a; ulong barrier2; } stp_atomic_struct = { ULONG_MAX, 5, ULONG_MAX }; #endif %%} function get_atomic_long_addr:long() %%{ STAP_RETVALUE = (long)&stp_atomic_struct.a; %%} probe begin { print("systemtap starting probe\n") exit() } probe end { print("systemtap ending probe\n") printf("%%d\n", atomic_long_read(get_atomic_long_addr() + %s)) } } set test "atomic4" set script [format $atomic_long_script_module_template "0"] stap_run_error $test 0 $error "5\r\n" -ge $script # We should be able to check for trying to read the atomic_long_t with # bad alignment here, but it succeeds on {x86, x86_64} and fails on # ia64. Since it doesn't fail consistently, we'll comment this out. #set test "atomic5" #set script [format $atomic_long_script_module_template "3"] #stap_run_error $test 1 $error "" -ge $script # # Now test atomic_read() # # First try reading from address 0, which should fail. set test "atomic5" set error {read fault .* at 0x[^\r]+} set script [format $script_template "atomic" "0"] stap_run_error $test 1 $error "0\r\n" -e $script # Try reading from address -1 (top of memory), which should fail. set test "atomic6" set script [format $script_template "atomic" "-1"] stap_run_error $test 1 $error "0\r\n" -e $script # Try reading from address 3, which should fail (if nothing else # because it isn't aligned properly). set test "atomic7" set script [format $script_template "atomic" "3"] stap_run_error $test 1 $error "0\r\n" -e $script set atomic_script_module_template { %%{ #include struct { ulong barrier1; atomic_t a; ulong barrier2; } stp_atomic_struct = { ULONG_MAX, ATOMIC_INIT(5), ULONG_MAX }; %%} function get_atomic_addr:long() %%{ STAP_RETVALUE = (long)&stp_atomic_struct.a; %%} probe begin { print("systemtap starting probe\n") exit() } probe end { print("systemtap ending probe\n") printf("%%d\n", atomic_read(get_atomic_addr() + %s)) } } set test "atomic8" set script [format $atomic_script_module_template "0"] stap_run_error $test 0 $error "5\r\n" -ge $script # We should be able to check for trying to read the atomic_t with # bad alignment here, but it succeeds on {x86, x86_64} and fails on # ia64. Since it doesn't fail consistently, we'll comment this out. #set test "atomic9" #set script [format $atomic_script_module_template "3"] #stap_run_error $test 1 $error "" -ge $script systemtap-2.3/testsuite/systemtap.base/backtrace.exp000066400000000000000000000017711217430427200230470ustar00rootroot00000000000000set test "backtrace" if {![installtest_p]} { untested $test; return } if {![istarget "x86_64-*-*"] && ![istarget "i*86-*-*"]} { setup_kfail 10739 [istarget] } set ok 0 set ok2 0 spawn stap $srcdir/$subdir/backtrace.stp expect { -timeout 30 -re {^[^\r\n ]*\r\n} { incr ok; exp_continue } -re {^ [^\r\n]*\r\n} { incr ok2; exp_continue } eof { } timeout { fail "$test (timeout)" } } catch { close }; wait if {$ok == 3 && $ok2 >= $ok} then { pass "$test ($ok $ok2)" } else { fail "$test ($ok $ok2)" } set test "backtrace-unwindsyms" if {![istarget "x86_64-*-*"] && ![istarget "i*86-*-*"]} { setup_kfail 10739 [istarget] } set ok 0 set ok2 0 spawn stap $srcdir/$subdir/backtrace.stp -d kernel expect { -timeout 30 -re {^[^\r\n ]*\r\n} { incr ok; exp_continue } -re {^ [^\r\n]*\r\n} { incr ok2; exp_continue } eof { } timeout { fail "$test (timeout)" } } catch { close }; wait if {$ok == 3 && $ok2 >= $ok} then { pass "$test ($ok $ok2)" } else { fail "$test ($ok $ok2)" } systemtap-2.3/testsuite/systemtap.base/backtrace.stp000066400000000000000000000002251217430427200230520ustar00rootroot00000000000000probe begin, end, procfs("foo").read, procfs("foo").write { log(pp()) print_backtrace() } probe timer.ms(100) { log(pp()) print_backtrace() exit() } systemtap-2.3/testsuite/systemtap.base/bad-code.c000066400000000000000000000004221217430427200222040ustar00rootroot00000000000000// Testcase for PR14107. Missing kernel asm CFI. #include #include void sigseg(int sig) { exit(0); } int func (void) { int *foo = (void *) 0x1234; *foo = 0x12345; return 0; } int main (void) { signal(SIGSEGV, sigseg); return func (); } systemtap-2.3/testsuite/systemtap.base/bad-code.exp000066400000000000000000000024651217430427200225670ustar00rootroot00000000000000# Testcase for PR14107 missing kernel ASM CFI. set test "bad-code" set testpath "$srcdir/$subdir" set output_string {0x[\\da-f]+ : func+[^\\r\\n]+\r\n0x[\\da-f]+ : main+[^\\r\\n]+\r\n} # Note don't optimize we are really interested in the non-inlined case set test_flags "additional_flags=-g" set res [target_compile $srcdir/$subdir/$test.c $test executable "$test_flags"] if { $res != "" } { verbose "target_compile $test failed: $res" 2 fail "$test.c compile" untested "$test" continue } else { pass "$test.c compile" if {[installtest_p]} { set main 0 set func 0 set libc 0 send_log "Running: stap ${testpath}/${test}.stp -w -d ./$test -c ./$test\n" spawn stap ${testpath}/${test}.stp -w -d ./$test -c ./$test expect { -timeout 60 -re {^ 0x[a-f0-9]+ : func\+0x[^\r\n]+\r\n} {incr func; exp_continue} -re {^ 0x[a-f0-9]+ : main\+0x[^\r\n]+\r\n} {incr main; exp_continue} -re {^ 0x[a-f0-9]+ [^\r\n]+/libc-[^\r\n]+\r\n} {incr libc; exp_continue} timeout { fail "$test (timeout)"; exec kill -INT -[exp_pid] } eof { } } exec kill -INT -[exp_pid] catch {close}; catch {wait} send_log "main: $main, func: $func, libc: $libc\n" if {$main == 1 && $func == 1 && $libc == 1} {pass "$test"} {fail "$test"} } else { untested "$test" } } systemtap-2.3/testsuite/systemtap.base/bad-code.stp000066400000000000000000000002251217430427200225710ustar00rootroot00000000000000// Testcase for PR14107 missing kernel asm CFI. probe kernel.function("force_sig_info") { if (pid() == target()) { print_ubacktrace() } } systemtap-2.3/testsuite/systemtap.base/badkprobe.exp000066400000000000000000000017051217430427200230560ustar00rootroot00000000000000set test "bad kprobe registration" set script { probe $1 { k++ } global k probe timer.ms(100) { exit() } probe end { println("cleanup ok") } } if {! [installtest_p]} { untested $test; return } set bad_kprobes { kernel.statement(-1).absolute kprobe.statement(-1).absolute } foreach bk $bad_kprobes { set test "bad kprobe registration: $bk" spawn stap -g -e "$script" "$bk" expect { -timeout 60 -re "^WARNING: probe .*registration error.*\r\ncleanup ok\r\n" { pass $test } eof { fail "$test (eof)" } timeout { fail "$test (timeout)" } } catch {close} catch {wait} } foreach bk $bad_kprobes { set test "bad optional kprobe registration: $bk" spawn stap -g -w -e "$script" "$bk ?" expect { -timeout 60 -re "^cleanup ok\r\n" { pass $test } eof { fail "$test (eof)" } timeout { fail "$test (timeout)" } } catch {close} catch {wait} } systemtap-2.3/testsuite/systemtap.base/be_loaded.exp000066400000000000000000000005411217430427200230200ustar00rootroot00000000000000# Simple test that begin/end probes work with a command loaded set test "be_loaded" set ::result_string {begin end} set script $srcdir/$subdir/$test.stp foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run3 "$test ($runtime)" $script --runtime=$runtime -c true } else { stap_run3 $test $script -c true } } systemtap-2.3/testsuite/systemtap.base/be_loaded.stp000066400000000000000000000001771217430427200230370ustar00rootroot00000000000000/* * be_loaded.stp * * Simple test that begin/end probes work with a command loaded */ probe begin, end { println(pp()) } systemtap-2.3/testsuite/systemtap.base/be_order.exp000066400000000000000000000004771217430427200227130ustar00rootroot00000000000000# Simple function to test that ordering of begin/end probes works set test "be_order" foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string \ --runtime=$runtime } else { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string } } systemtap-2.3/testsuite/systemtap.base/be_order.stp000066400000000000000000000017101217430427200227140ustar00rootroot00000000000000/* * be_order.stp * * Check that ordering of begin/end probes works */ probe begin { println("systemtap starting probe") } probe end { println("systemtap ending probe") } global beginstr, endstr probe begin { beginstr .= "c" } probe begin(1) { beginstr .= "d" } probe begin(-1) { beginstr .= "b" } probe begin(0) { beginstr .= "c" } probe begin(9223372036854775807) { beginstr .= "e" } probe begin(-9223372036854775808) { beginstr .= "a" } probe end { endstr .= "x" } probe end(1) { endstr .= "y" } probe end(-1) { endstr .= "w" } probe end(0) { endstr .= "x" } probe end(9223372036854775807) { endstr .= "z" if (beginstr == "abccde") println("systemtap test success") else printf("systemtap test failure - beginstr:%s != abccde\n", beginstr) if (endstr == "vwxxyz") println("systemtap test success") else printf("systemtap test failure - endstr:%s != vwxxyz\n", endstr) } probe end(-9223372036854775808) { endstr .= "v" } systemtap-2.3/testsuite/systemtap.base/beginenderror.exp000066400000000000000000000014361217430427200237530ustar00rootroot00000000000000set test "beginenderror" if {![installtest_p]} {untested $test; return} foreach runtime [get_runtime_list] { set test "beginenderror" set args "" if {$runtime != ""} { lappend test "($runtime)" set args "--runtime=$runtime" } spawn stap $srcdir/$subdir/beginenderror.stp $args set ok1 0 set ok2 0 set ko 0 expect { -timeout 30 -re {^ERROR:[^\r\n]*\r\n} { incr ok1; exp_continue } -re {^WARNING:[^\r\n]*\r\n} { incr ok1; exp_continue } -re {^ok[^\r\n]*\r\n} { incr ok2; exp_continue } -re {^ko[^\r\n]*\r\n} { incr ko; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch { close }; catch { wait } if {$ok1 == 5 && $ok2 == 3 && $ko == 0} then { pass "$test ($ok1 $ok2 $ko)" } else { fail "$test ($ok1 $ok2 $ko)" } } systemtap-2.3/testsuite/systemtap.base/beginenderror.stp000066400000000000000000000007021217430427200237600ustar00rootroot00000000000000probe begin { println ("ok ".pp()) println (1/0) println ("ko ".pp()) } # handler should unwind before seemenot message probe begin(10) { println ("ko ".pp()) } # this late begin probe shouldn't run, ERROR probe end, end(10) { println ("ko ".pp()) } # end probes won't be run due to ERROR state probe error, error(10) { println ("ok ".pp()) } # these handlers should be run probe error(20),error(30) { println (1/0) println ("ko ".pp()) } # likewise systemtap-2.3/testsuite/systemtap.base/bench.exp000066400000000000000000000010621217430427200222000ustar00rootroot00000000000000set test "bench" if {![installtest_p]} {untested $test; return} foreach runtime [get_runtime_list] { set test "bench" if {$runtime != ""} { lappend test "($runtime)" spawn stap -tu $srcdir/$subdir/bench.stp --runtime=$runtime } else { spawn stap -tu $srcdir/$subdir/bench.stp } set ok 0 expect { -timeout 180 -re {^[^\r\n]+, hits: [0-9]+[^\r\n]+\r\n} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch { close }; catch { wait } if {$ok >= 18} { pass "$test ($ok)" } { fail "$test ($ok)" } } systemtap-2.3/testsuite/systemtap.base/bench.stp000066400000000000000000000030511217430427200222120ustar00rootroot00000000000000 // This bucket aims to trigger all basic generated C code constructs. // It should be run with "-tu". probe repeat = begin,begin,begin,begin,begin,begin,begin,begin, begin,begin,begin,begin,begin,begin,begin,begin, begin,begin,begin,begin,begin,begin,begin,begin, begin,begin,begin,begin,begin,begin,begin,begin, begin,begin,begin,begin,begin,begin,begin,begin {} probe test.null = repeat {} probe test.null {} // null probe probe test.intassmt = repeat {i = 0} probe test.intassmt {} probe test.gintassmt = repeat {gn = 0} probe test.gintassmt {} global gn probe test.intincr = repeat {i++} probe test.intincr {} probe test.gintincr = repeat {gn++} probe test.gintincr {} probe test.strassmt = repeat {s=""} probe test.strassmt {} probe test.gstrassmt = repeat {gs=""} probe test.gstrassmt {} global gs probe test.forloop = repeat {for(i=0;i<10;i++) ;} probe test.forloop {} probe test.ifgint = repeat {if (gn>0) ;} probe test.ifgint {} probe test.next = repeat {next} probe test.next {} probe test.stataccum = repeat {gS <<< 1} probe test.stataccum {} global gS probe test.statcount = repeat {@count(gS)} probe test.statcount {} probe test.nnarrassmt = repeat {gnn[1] = 1} probe test.nnarrassmt {} global gnn probe test.ssarrassmt = repeat {gss["foo"] = "bar"} probe test.ssarrassmt {} global gss probe begin(9999 /* ... after all the others! */) { exit () } systemtap-2.3/testsuite/systemtap.base/bitfield.exp000066400000000000000000000001741217430427200227060ustar00rootroot00000000000000# test that bitfield r/w works correctly set test "bitfield" stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string -g systemtap-2.3/testsuite/systemtap.base/bitfield.stp000066400000000000000000000022311217430427200227140ustar00rootroot00000000000000%{ #include static struct tcphdr foo = {0}; %} function get_ptr:long() %{ STAP_RETVALUE = (long)&foo; /* pure */ %} function get_ack:long() %{ STAP_RETVALUE = foo.ack; /* pure */ %} function get_urg:long() %{ STAP_RETVALUE = foo.urg; /* pure */ %} function check:long(ack:long, urg:long) { ptr = get_ptr() /* set the bits with cast */ @cast(ptr, "tcphdr")->ack = ack @cast(ptr, "tcphdr")->urg = urg /* check that reading with embedded-C is ok */ real_ack = get_ack() real_urg = get_urg() errors = (ack != real_ack) + (urg != real_urg) /* check that reading with a cast is ok */ cast_ack = @cast(ptr, "tcphdr")->ack cast_urg = @cast(ptr, "tcphdr")->urg errors += (ack != cast_ack) + (urg != cast_urg) if (errors) printf("bitfield had %d errors; expect(%d%d), real(%d%d), cast(%d%d)\n", errors, ack, urg, real_ack, real_urg, cast_ack, cast_urg) return errors } probe begin { println("systemtap starting probe") errors = check(0, 0) errors += check(0, 1) errors += check(1, 0) errors += check(1, 1) println("systemtap ending probe") if (errors == 0) println("systemtap test success") exit() } systemtap-2.3/testsuite/systemtap.base/buildid.c000066400000000000000000000001571217430427200221670ustar00rootroot00000000000000#ifndef ONLY_MAIN foo () { int x = 1; label: x = 2; } #endif #ifndef NO_MAIN main () { foo(); } #endif systemtap-2.3/testsuite/systemtap.base/buildid.exp000066400000000000000000000177521217430427200225520ustar00rootroot00000000000000set test "buildid" set bid_stp $srcdir/$subdir/buildid.stp if {![installtest_p]} { untested $test; return } if {![uprobes_p]} { untested "$test (uprobes)"; return } proc cleanup_handler { verbose } { if { $verbose == 0 } { catch {exec rm -f bid.hex bid.ko bid_nocheck.ko bid_shared.ko bid.stp buildid1.ro buildid2.ro buildid.c buildid.o buildid.ro buildid.x libbid1.so libbid.so } } } proc error_handler { res message } { global verbose if { $res == 0 } { verbose $message 2 fail $message cleanup_handler $verbose return 1 } else { pass $message return 0 } } # Not Shared set bid_srcpath $srcdir/$subdir/buildid.c set res [target_compile $bid_srcpath "[pwd]/buildid.o" object "additional_flags=-g"] if { [error_handler [expr {$res==""}] "buildid.o"] } { return } set res [target_link "buildid.o" "buildid.ro" "-r"] if { [error_handler [expr {$res==""}] "buildid.ro"] } { return } set bid_exepath ./buildid.x set res [target_compile "" $bid_exepath executable "additional_flags=buildid.ro"] if { [error_handler [expr {$res==""}] "$bid_exepath"] } { return } # Check that the build ID exists on this system set bid_check_passed 0 set cmd [concat {/usr/bin/eu-readelf -n $bid_exepath}] eval spawn $cmd expect { -timeout 180 -re {^[^\r\n]*GNU_BUILD_ID[^\r\n]*\r\n} { set bid_check_passed 1 exp_continue } -re {^[^\r\n]*\r\n} { exp_continue } timeout { set bid_check_passed 0 } } catch {close}; catch {wait} if {$bid_check_passed == 0} { untested "Build IDs do not exist on this system" cleanup_handler $verbose return } set test "nonshared build id" # Since uprobes.ko may not be prebuilt in the runtime, and we don't # yet have a way to discover the path to the cache-build uprobes.ko, # we need to preload it. This dummy run lets us go through the # motions to get uprobes loaded, and then we don't need to worry about # each staprun -u finding its module. # # PR13536: it turns out PR5163 makes staprun -u (without /path) # impossible, so stop using it in this test case. Instead we hope and # pray and beseech the almighty spaghetti monster that uprobes stay # loaded after the following ditty: set bid_ko [pwd]/bid.ko catch {exec rm -f $bid_ko} set status 0 if {[catch {exec stap -m bid $bid_stp $bid_exepath -c /bin/true} res]} { if {[lindex $::errorCode 0] eq "CHILDSTATUS"} { set status [lindex $::errorCode 2] } } if {$status == 0 && [file exists $bid_ko]} { pass "$test (module compilation)" } else { verbose -log $res fail "$test (module compilation)" cleanup_handler $verbose return } set ok 0 spawn staprun $bid_ko -c $bid_exepath expect { -timeout 180 -re {x=1} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if { [error_handler [expr $ok==1] "$test ok ($ok)"] } { return } # Alter the build id using objcopy. First, remove the build id from # the target executable. (Since the next test relinks the target # executable, this is OK.) set status 0 if {[catch {exec objcopy --remove-section=.note.gnu.build-id $bid_exepath} \ res]} { if {[lindex $::errorCode 0] eq "CHILDSTATUS"} { set status [lindex $::errorCode 2] } } if {$status == 0 && [file exists $bid_exepath]} { pass "$test (build id removal)" } else { verbose -log $res fail "$test (build id removal)" cleanup_handler $verbose return } set ok 0 spawn staprun $bid_ko -c $bid_exepath expect { -timeout 180 -re {ERROR: Build-id mismatch} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if { [error_handler [expr $ok==1] "$test !ok - removed ($ok)"] } { return } # Alter the build id using objcopy. Add in an additional build id section. set bid_bid $srcdir/$subdir/buildid.hex system "objcopy --remove-section=.note.gnu.build-id buildid.ro buildid1.ro" system "objcopy --add-section .note.gnu.build-id=$bid_bid buildid1.ro buildid2.ro" set res [target_compile "" $bid_exepath executable "additional_flags=buildid2.ro"] if { [error_handler [expr {$res==""}] "$test (build id modified)"] } { return } set ok 0 spawn staprun $bid_ko -c $bid_exepath expect { -timeout 180 -re {ERROR: Build-id mismatch} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} error_handler [expr $ok==1] "$test !ok - modified ($ok)" # stap -DSTP_NO_BUILDID_CHECK with altered build id set test "STP_NO_BUILDID_CHECK" # Compile a stap module with STP_NO_BUILDID_CHECK. set ok 0 set bid_nocheck_ko [pwd]/bid_nocheck.ko catch {exec rm -f $bid_nocheck_ko} set status 0 if {[catch {exec stap -m bid_nocheck -p4 -DSTP_NO_BUILDID_CHECK $bid_stp $bid_exepath} res]} { if {[lindex $::errorCode 0] eq "CHILDSTATUS"} { set status [lindex $::errorCode 2] } } if {$status == 0 && [file exists $bid_nocheck_ko]} { pass "$test (module compilation)" } else { verbose -log $res fail "$test (module compilation)" cleanup_handler $verbose return } spawn staprun $bid_nocheck_ko -c $bid_exepath expect { -timeout 180 -re {x=1} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} error_handler [expr $ok==1] "$test ok ($ok)" # Shared set test "shared build id" set bid_flags "additional_flags=-DNO_MAIN" set bid_flags "$bid_flags additional_flags=-shared" set bid_flags "$bid_flags additional_flags=-g" set res [target_compile $bid_srcpath "libbid.so" executable $bid_flags] if { [error_handler [expr {$res==""}] "libbid.so -DNO_MAIN"] } { return } set bid_flags "additional_flags=-DONLY_MAIN" set bid_flags "$bid_flags additional_flags=-Wl,-rpath,[pwd]" set bid_flags "$bid_flags additional_flags=-L[pwd]" set bid_flags "$bid_flags additional_flags=-lbid" set res [target_compile $bid_srcpath "$bid_exepath" executable $bid_flags] if { [error_handler [expr {$res==""}] "$bid_exepath -DONLY_MAIN"] } { return } # Compile a stap module for the shared library testcase set bid_shared_ko [pwd]/bid_shared.ko catch {exec rm -f $bid_shared_ko} set status 0 if {[catch {exec stap -m bid_shared -p4 $bid_stp libbid.so} res]} { if {[lindex $::errorCode 0] eq "CHILDSTATUS"} { set status [lindex $::errorCode 2] } } if {$status == 0 && [file exists $bid_shared_ko]} { pass "$test (module compilation)" } else { verbose -log $res fail "$test (module compilation)" cleanup_handler $verbose return } set ok 0 spawn staprun $bid_shared_ko -c $bid_exepath expect { -timeout 180 -re {x=1} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if { [error_handler [expr $ok==1] "$test ok ($ok)"] } { return } # Alter the build id using objcopy. First, remove the build id from # the target library. set status 0 if {[catch {exec objcopy --remove-section=.note.gnu.build-id libbid.so} res]} { if {[lindex $::errorCode 0] eq "CHILDSTATUS"} { set status [lindex $::errorCode 2] } } if {$status == 0 && [file exists libbid.so]} { pass "$test (build id removal)" } else { verbose -log $res fail "$test (build id removal)" cleanup_handler $verbose return } set ok 0 spawn staprun $bid_shared_ko -c $bid_exepath expect { -timeout 180 -re {ERROR: Build-id mismatch} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if { [error_handler [expr $ok==1] "$test !ok - removed ($ok)"] } { return } # Alter the build id using objcopy. Add in an "bad" build id # section. catch {exec objcopy --add-section .note.gnu.build-id=$bid_bid libbid.so} res if {[file exists libbid.so]} { pass "$test (build id modified)" } else { verbose -log $res fail "$test (build id modified)" cleanup_handler $verbose return } set ok 0 spawn staprun $bid_shared_ko -c $bid_exepath expect { -timeout 180 -re {ERROR: Build-id mismatch} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} error_handler [expr $ok==1] "$test !ok - modified ($ok)" cleanup_handler $verbose systemtap-2.3/testsuite/systemtap.base/buildid.hex000066400000000000000000000000451217430427200225250ustar00rootroot00000000000000GNUW5ƅȏ11v systemtap-2.3/testsuite/systemtap.base/buildid.stp000066400000000000000000000001111217430427200225410ustar00rootroot00000000000000probe process (@1).function("foo").label("label") {printf("x=%d\n",$x)} systemtap-2.3/testsuite/systemtap.base/bz10078.c000066400000000000000000000006011217430427200215600ustar00rootroot00000000000000#include #include struct point { int x, y; }; struct point mkpoint2(void) __attribute__((noinline)); struct point mkpoint2(void) { struct point p = { 1, 2 }; return p; } struct point mkpoint1(void) __attribute__((noinline)); struct point mkpoint1(void) { return mkpoint2(); } main() { struct point p = mkpoint1(); printf("%d,%d\n", p.x, p.y); exit(0); } systemtap-2.3/testsuite/systemtap.base/bz10078.exp000066400000000000000000000015121217430427200221340ustar00rootroot00000000000000set test bz10078 catch {exec gcc -g -o $test $srcdir/$subdir/$test.c} err if {$err == "" && [file exists $test]} then { pass "$test compile" } else { fail "$test compile" } if {![uprobes_p]} { catch {exec rm -f $test} untested "$test -p4" untested "$test -p5" return } set rc [stap_run_batch $srcdir/$subdir/$test.stp] if {$rc == 0} then { pass "$test -p4" } else { fail "$test -p4" } if {! [installtest_p] || ! [uretprobes_p]} { catch {exec rm -f $test} untested "$test -p5" return } spawn stap $srcdir/$subdir/$test.stp -c ./$test set ok 0 expect { -timeout 60 -re {^mkpoint[^\r\n]* returns\r\n} { incr ok; exp_continue } -re {^1,2\r\n} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } wait if {$ok == 3} then { pass "$test -p5" } else { fail "$test -p5 ($ok)" } exec rm -f $test systemtap-2.3/testsuite/systemtap.base/bz10078.stp000077500000000000000000000001541217430427200221520ustar00rootroot00000000000000#! stap -p4 probe process("./bz10078").function("mkpoint*").return { printf("%s returns\n", probefunc()) } systemtap-2.3/testsuite/systemtap.base/bz10294.c000066400000000000000000000002541217430427200215640ustar00rootroot00000000000000int func_a(int a) { a = a + 1; return a; } int func_b(int b) { b = b + 2; return b; } int main() { int a; a = func_a(1); a = a + func_b(a); return 0; } systemtap-2.3/testsuite/systemtap.base/bz10294.stp000077500000000000000000000001321217430427200221460ustar00rootroot00000000000000#! stap -p2 probe process("./bz10294").statement("*@bz10294.c:10-10") { printf("ok") } systemtap-2.3/testsuite/systemtap.base/bz13338.exp000066400000000000000000000012261217430427200221400ustar00rootroot00000000000000set test bz13338 spawn stap -vvl {process("/usr/bin/?").function("main")} set ok 0 set ko 0 expect { -timeout 60 # this will only match if sufficient *-debuginfo happens to be installed -re {[process^\r\n]*function..main@[^\r\n]*\r\n} { incr ok; exp_continue } # this is the buggy old case {Expanded process("/usr/bin/[") to process("/usr/bin/[")\r\n} { incr ko } # this will show if the base RPMs are installed, even without -debuginfo -re {Expanded process[^\r\n]*\r\n} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } wait if {$ok > 0 && $ko == 0} then { pass "$test" } else { fail "$test $ok $ko" } systemtap-2.3/testsuite/systemtap.base/bz14774.c000066400000000000000000000002711217430427200215720ustar00rootroot00000000000000int a(int i) { return i + 1; } int b(int i) { return i + 2; } int c(int i) { return i + 3; } int main() { int i = c( b( a(1))); return i; } systemtap-2.3/testsuite/systemtap.base/bz5274.a.stp000077500000000000000000000007021217430427200223120ustar00rootroot00000000000000#! /bin/env stap probe process("./bz5274").function("funcb").call, process("./bz5274").function("funcc").call, process("./bz5274").function("funcd").call { printf("%s Entering %s\n", pp(), thread_indent(1)) } probe process("./bz5274").function("funcb").return, process("./bz5274").function("funcc").return, process("./bz5274").function("funcd").return { printf("%s %s returns %s\n", pp(), thread_indent(-1), returnstr(2)) } systemtap-2.3/testsuite/systemtap.base/bz5274.c000066400000000000000000000012431217430427200215050ustar00rootroot00000000000000#include #include #include void funcd(int i, jmp_buf env) { printf("In %s: %s :%d : i=%d. Calling longjmp\n", "bz5274.c",__func__,__LINE__,i); longjmp(env, i); } void funcc(int i, jmp_buf env) { printf("In %s: %s :%d : i=%d. Calling funcd\n", "bz5274.c",__func__,__LINE__,i); funcd(i,env); } void funcb(int i, jmp_buf env) { printf("In %s: %s :%d : i=%d. Calling funcc\n", "bz5274.c",__func__,__LINE__,i); funcc(i,env); } void funca(char *s, jmp_buf env) { int i; i = setjmp(env); if (i == 4) return; funcb(++i, env); return; } int main(int argc, char **argv) { jmp_buf env; funca("Hello World", env); exit(0); } systemtap-2.3/testsuite/systemtap.base/bz5274.exp000066400000000000000000000027221217430427200220620ustar00rootroot00000000000000set test "./bz5274" set tpath "$srcdir/$subdir/$test" set arch [exec uname -i] if {! [installtest_p]} { untested "$test -p5" return } if {![uretprobes_p]} { untested "$test -p5" return } if {$arch == "ppc64"} { catch {exec gcc -o $test -g -m64 $srcdir/$subdir/$test.c} err } else { catch {exec gcc -o $test -g $srcdir/$subdir/$test.c} err } if {$err == "" && [file exists $test]} then { pass "$test compile" } else { fail "$test compile" } if {[catch {exec stap $tpath.stp -c "$srcdir/$subdir/$test.sh"} res]} { untested "$test longjmp to a uretprobed function" verbose -log "$res" catch {exec rm -f $test.out} } else { if {[catch {exec cmp $test.out $srcdir/$subdir/$test.exp_out} res]} { fail "$test longjmp to a uretprobed function" verbose -log "$res" catch {exec rm -f $test.out} } else { pass "$test longjmp to a uretprobed function" catch {exec rm -f $test.out} } } if {[catch {exec stap $tpath.a.stp -c $srcdir/$subdir/$test.sh} res]} { untested "$test longjmp to a non-uretprobed function" verbose -log "$res" catch {exec rm -f $test.out $test} } else { if {[catch {exec cmp $test.out $srcdir/$subdir/$test.exp_out} res]} { fail "$test longjmp to a non-uretprobed function" verbose -log "$res" catch {exec rm -f $test.out $test} } else { pass "$test longjmp to a non-uretprobed function" catch {exec rm -f $test.out $test} } } systemtap-2.3/testsuite/systemtap.base/bz5274.exp_out000066400000000000000000000010401217430427200227410ustar00rootroot00000000000000In bz5274.c: funcb :20 : i=1. Calling funcc In bz5274.c: funcc :13 : i=1. Calling funcd In bz5274.c: funcd :7 : i=1. Calling longjmp In bz5274.c: funcb :20 : i=2. Calling funcc In bz5274.c: funcc :13 : i=2. Calling funcd In bz5274.c: funcd :7 : i=2. Calling longjmp In bz5274.c: funcb :20 : i=3. Calling funcc In bz5274.c: funcc :13 : i=3. Calling funcd In bz5274.c: funcd :7 : i=3. Calling longjmp In bz5274.c: funcb :20 : i=4. Calling funcc In bz5274.c: funcc :13 : i=4. Calling funcd In bz5274.c: funcd :7 : i=4. Calling longjmp systemtap-2.3/testsuite/systemtap.base/bz5274.sh000077500000000000000000000000451217430427200216770ustar00rootroot00000000000000#! /bin/bash ./bz5274 > ./bz5274.out systemtap-2.3/testsuite/systemtap.base/bz5274.stp000077500000000000000000000003651217430427200221000ustar00rootroot00000000000000#! /bin/env stap probe process("./bz5274").function("*").call { printf("%s Entering %s\n", pp(), thread_indent(1)) } probe process("./bz5274").function("*").return { printf("%s %s returns %s\n", pp(), thread_indent(-1), returnstr(2)) } systemtap-2.3/testsuite/systemtap.base/bz6503.exp000066400000000000000000000035031217430427200220540ustar00rootroot00000000000000# Note that this test is *really* testing the bug fix for pr6503: # permit probes on module .init and __exit functions # # # Not BZ6503: # ypserve does not work # set test bz6503 if {! [installtest_p]} { untested "$test" return } # If we aren't root, make sure the test still succeeds. set effective_pid [exec /usr/bin/id -u] if {$effective_pid != 0} { set root_cmd "sudo " } else { set root_cmd "" } # jffs2/ext2/fat/vfat should cover a span of kernels. # # Note that this test might fail if there is a filesystem of one of # these types already mounted. The filesystem mount will be # unaffected (since the module can't be removed). spawn stap -t $srcdir/$subdir/bz6503.stp -c "( ($root_cmd /sbin/modprobe jffs2; $root_cmd /sbin/modprobe ext2; $root_cmd /sbin/modprobe fat; $root_cmd /sbin/modprobe vfat); wait; ($root_cmd /sbin/rmmod jffs2; $root_cmd /sbin/rmmod ext2; $root_cmd /sbin/rmmod vfat; $root_cmd /sbin/rmmod fat); wait) 2>/dev/null" set ok 0 set ko 0 expect { -timeout 60 timeout { fail "$test (timeout)" } -re {^-----[^\r\n]*\r\n} { exp_continue } -re {^module[^\r\n]*hits:[^\r\n]*\r\n} { incr ok; exp_continue } -re {^WARNING:[\r\n]*\r\n} { incr ko; exp_continue } -re {^ERROR:[\r\n]*\r\n} { incr ko; exp_continue } eof { } } catch { close} ; catch { wait } # Mark kernels < 2.6.29 as xfail set kv [exec uname -r | grep -o -G {^[0-9]\+.[0-9]\+.[0-9]\+}] set kvbits [split $kv .] set k1 [lindex $kvbits 0] set k2 [lindex $kvbits 1] set k3 [lindex $kvbits 2] verbose -log "xfailing if $k1.$k2.$k3 < 2.6.29" if {($k1*256*256 + $k2*256 + $k3) < (2*256*256 + 6*256 + 29)} then { setup_xfail *-*-* } if {$ok > 0 && $ko == 0} then { pass "$test $ok" } else { fail "$test $ok $ko"} systemtap-2.3/testsuite/systemtap.base/bz6503.stp000066400000000000000000000002741217430427200220700ustar00rootroot00000000000000probe module("jffs2").function("*").call ?, module("ext2").function("*").call ?, module("fat").function("*").call ?, module("vfat").function("*").call ?, never { } systemtap-2.3/testsuite/systemtap.base/bz6850.c000066400000000000000000000036361217430427200215160ustar00rootroot00000000000000/* Regression test for bugzilla 6850 */ #include #include #include #include #include #include #define PASS_MARKER "./bz6850_pass" /* All this in an attempt to defeat gcc's over-aggressive inlining... */ typedef pid_t (*forker)(int); static forker call_chain[]; /* * Both parent and child return from fork2() and fork1(). Both * processes will hit the uretprobe trampolines. The handlers should * run in the parent. With the bug fix in place, the child will return * correctly and do the exec (but won't run the handlers). */ static pid_t fork2(int ignored) { return fork(); } static pid_t fork1(int func_index) { ++func_index; return call_chain[func_index](func_index); /* fork2() */ } static pid_t fork_and_exec2(int func_index) { pid_t child; ++func_index; child = call_chain[func_index](func_index); /* fork1() */ if (child == 0) { /* I'm the child. Create the marker file. */ char *child_args[] = { "/bin/touch", PASS_MARKER, NULL }; char *child_env[] = { NULL }; execve(child_args[0], child_args, child_env); perror("execve"); fprintf(stderr, "FAIL: child couldn't exec.\n"); exit(2); } return child; } static pid_t fork_and_exec1(int func_index) { ++func_index; return call_chain[func_index](func_index); /* fork_and_exec2() */ } static forker call_chain[] = { fork_and_exec1, fork_and_exec2, fork1, fork2, NULL }; main() { pid_t child, wait_child; int status = 0; (void) unlink(PASS_MARKER); child = call_chain[0](0); /* fork_and_exec1() */ if (child < 0) { fprintf(stderr, "FAIL: fork_and_exec1() failed.\n"); exit(1); } wait_child = wait(&status); if (wait_child != child) { fprintf(stderr, "FAIL: waited for %d but got %d\n", child, wait_child); exit(1); } if (WEXITSTATUS(status) != 0) { fprintf(stderr, "FAIL: child died with status = %d\n", WEXITSTATUS(status)); exit(1); } exit(0); } systemtap-2.3/testsuite/systemtap.base/bz6850.exp000066400000000000000000000014741217430427200220660ustar00rootroot00000000000000set test bz6850 catch {exec gcc -g -o bz6850 $srcdir/$subdir/bz6850.c} err if {$err == "" && [file exists bz6850]} then { pass "$test compile" } else { fail "$test compile" } if {![uretprobes_p]} { catch {exec rm -f $test} untested "$test -p4" untested "$test -p5" return } set rc [stap_run_batch $srcdir/$subdir/bz6850.stp] if {$rc == 0} then { pass "$test -p4" } else { fail "$test -p4" } if {! [installtest_p]} { catch {exec rm -f $test} untested "$test -p5" return } spawn stap $srcdir/$subdir/bz6850.stp -c ./bz6850 expect { -timeout 60 -re {[^\r\n]*called\r\n} { exp_continue } -re {[^\r\n]*returns\r\n} { exp_continue } timeout { fail "$test (timeout)" } eof { } } wait if {[file exists bz6850_pass]} then { pass "$test -p5" } else { fail "$test -p5" } exec rm -f bz6850_pass bz6850 systemtap-2.3/testsuite/systemtap.base/bz6850.stp000077500000000000000000000002711217430427200220750ustar00rootroot00000000000000#! stap -p4 probe process("./bz6850").function("*").call { printf("%s called\n", probefunc()) } probe process("./bz6850").function("*").return { printf("%s returns\n", probefunc()) } systemtap-2.3/testsuite/systemtap.base/bz6905.c000066400000000000000000000000621217430427200215050ustar00rootroot00000000000000int main() { int a; a = a + 1; return 0; } systemtap-2.3/testsuite/systemtap.base/bz6905.stp000077500000000000000000000001261217430427200220750ustar00rootroot00000000000000#! stap -p2 probe process("./bz6905").statement("main@bz6905.c:*") { printf("ok") } systemtap-2.3/testsuite/systemtap.base/cache.exp000066400000000000000000000052521217430427200221710ustar00rootroot00000000000000# cache.exp # Since we need a clean cache directory, we'll use a temporary # systemtap directory and cache (add user name so make check and # sudo make installcheck don't clobber each others) set local_systemtap_dir [exec pwd]/.cache_test-[exec whoami] exec /bin/rm -rf $local_systemtap_dir if [info exists env(SYSTEMTAP_DIR)] { set old_systemtap_dir $env(SYSTEMTAP_DIR) } set env(SYSTEMTAP_DIR) $local_systemtap_dir # Set up the scripts we'll use. set basic_script1 "\"probe begin { println(1) }\"" set basic_script2 "\"probe begin, end { println(2) }\"" set error_script "\"probe XbeginX { }\"" # Check basic functionality. The 1st compilation of a script won't # be cached, the 2nd should be cached. cache_compile BASIC1 [F_UNCACHED_COMPILE] $basic_script1 cache_compile BASIC2 [F_CACHED_COMPILE] $basic_script1 # Adding in a macro definition should change the hash cache_compile OPTION1 [F_UNCACHED_COMPILE] $basic_script1 -DFOO=1 cache_compile OPTION2 [F_CACHED_COMPILE] $basic_script1 -DFOO=1 # Using '-b' (bulk/relayfs mode) should change the hash cache_compile BULK1 [F_UNCACHED_COMPILE] $basic_script1 -b cache_compile BULK2 [F_CACHED_COMPILE] $basic_script1 -b # Using '-t' (benchmark timing) should change the hash cache_compile TIMING1 [F_UNCACHED_COMPILE] $basic_script1 -t cache_compile TIMING2 [F_CACHED_COMPILE] $basic_script1 -t # Changing the runtime directory should change the hash set new_runtime [exec pwd]/.cache_test_runtime exec /bin/rm -f $new_runtime exec /bin/ln -s $env(SYSTEMTAP_RUNTIME) $new_runtime cache_compile RUNTIME1 [F_UNCACHED_COMPILE] $basic_script1 -R $new_runtime cache_compile RUNTIME2 [F_CACHED_COMPILE] $basic_script1 -R $new_runtime exec /bin/rm -f $new_runtime # Disable the cache with SYSTEMTAP_DIR set env(SYSTEMTAP_DIR) /dev/null cache_compile DISABLED1 [F_UNCACHED_COMPILE] $basic_script1 cache_compile DISABLED2 [F_UNCACHED_COMPILE] $basic_script1 set env(SYSTEMTAP_DIR) $local_systemtap_dir eval [list exec /bin/rm -f] [glob "stap_*.ko"] # Disable the cache with '-m' cache_compile MODNAM1 [F_UNCACHED_COMPILE] $basic_script1 -m modnam exec /bin/rm -f modnam.ko cache_compile MODNAM2 [F_UNCACHED_COMPILE] $basic_script1 -m modnam exec /bin/rm -f modnam.ko # Make sure scripts that don't actually compile don't get cached cache_compile ERROR1 [F_UNCACHED_NO_COMPILE] $error_script cache_compile ERROR2 [F_UNCACHED_NO_COMPILE] $error_script # Make sure basic stuff still works. cache_compile BASIC3 [F_UNCACHED_COMPILE] $basic_script2 cache_compile BASIC4 [F_CACHED_COMPILE] $basic_script2 # Cleanup. exec /bin/rm -rf $local_systemtap_dir if [info exists old_systemtap_dir] { set env(SYSTEMTAP_DIR) $old_systemtap_dir } else { unset env(SYSTEMTAP_DIR) } systemtap-2.3/testsuite/systemtap.base/cache_clean.exp000066400000000000000000000037361217430427200233400ustar00rootroot00000000000000# cache_clean.exp # Since we need a clean cache directory, we'll use a temporary # systemtap directory and cache (add user name so make check and # sudo make installcheck don't clobber each others) set local_systemtap_dir [exec pwd]/.cache_test-[exec whoami] exec /bin/rm -rf $local_systemtap_dir exec /bin/mkdir $local_systemtap_dir exec /bin/mkdir $local_systemtap_dir/cache if [info exists env(SYSTEMTAP_DIR)] { set old_systemtap_dir $env(SYSTEMTAP_DIR) } set env(SYSTEMTAP_DIR) $local_systemtap_dir # Set up the scripts we'll use. set script1 "\"probe begin {println(1)}\"" set script2 "\"probe begin {println(2)}\"" #Set a high interval, so we can make sure that the cache isn't cleaned exec /bin/echo 100000 > $local_systemtap_dir/cache/cache_clean_interval_s # Make sure the cache isn't cleaned when it hasn't passed the interval set test "cache_clean" set cmd [concat {stap -vv -p4 -e} $script1] eval spawn $cmd set cleaned -1 expect { -timeout 180 -re {^Cleaning cache, interval reached [^\r\n]*\r\n} {fail "$test premature cleaning"} -re {^Cache cleaning skipped, interval not reached [^\r\n]*\r\n} {pass "$test premature cleaning"} -re {^[^\r\n]*\r\n} {exp_continue} timeout { fail "$test (timeout)" } } catch close wait # Set a small interval to insure the next stap call cleans the cache exec /bin/echo 1 > $local_systemtap_dir/cache/cache_clean_interval_s sleep 1 # Make sure the cache is cleaned when it has passed the interval set cmd [concat {stap -vv -p4 -e} $script2] eval spawn $cmd set cleaned -1 expect { -timeout 180 -re {^Cleaning cache, interval reached [^\r\n]*\r\n} {pass "$test timed cleaning"} -re {^Cache cleaning skipped, interval not reached [^\r\n]*\r\n} {fail "$test timed cleaning"} -re {^[^\r\n]*\r\n} {exp_continue} timeout { fail "$test (timeout)" } } catch close wait # Cleanup. exec /bin/rm -rf $local_systemtap_dir if [info exists old_systemtap_dir] { set env(SYSTEMTAP_DIR) $old_systemtap_dir } else { unset env(SYSTEMTAP_DIR) } systemtap-2.3/testsuite/systemtap.base/cast-scope.cxx000066400000000000000000000006631217430427200231760ustar00rootroot00000000000000#include "sys/sdt.h" #include size_t length(const std::string& str) { int res, r; STAP_PROBE1(cast-scope, length, &str); r = str.length() * 2; STAP_PROBE(cast-scope, dummy); /* Just here to probe line +4. */ res = r / 2; STAP_PROBE(cast-scope, dummy2); /* Just here prevent line reordering. */ return res; } int main() { std::string hello = "Hello World!"; return 12 != length(hello); } systemtap-2.3/testsuite/systemtap.base/cast-scope.exp000066400000000000000000000035151217430427200231670ustar00rootroot00000000000000set test "cast-scope" set ::result_string {function direct: {._M_dataplus={._M_p="Hello World!"}} function cast: {._M_dataplus={._M_p="Hello World!"}} mark cast: {._M_dataplus={._M_p="Hello World!"}} statement direct: {._M_dataplus={._M_p="Hello World!"}} statement cast: {._M_dataplus={._M_p="Hello World!"}}} set srcfile "$srcdir/$subdir/$test.cxx" set stpfile "$srcdir/$subdir/$test.stp" proc dyninst_kfails {index} { # The dyninst runtime isn't multi-arch, it only works on the # native architecture. PR14490. if {! [all_compile_flag_native_p $index]} { setup_kfail 14490 "*-*-*" } } for {set i 0} {$i < [all_compile_flags]} {incr i} { set extra_flag [all_compile_flag $i] set extra_name [all_compile_flag_name $i] set test_flags "compiler=g++ additional_flags=-g [sdt_includes] $extra_flag" set res [target_compile "$srcfile" $test-$extra_name.exe \ executable "$test_flags"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test-$extra_name compile" untested "$test-$extra_name" continue } else { pass "$test-$extra_name compile" } if {[installtest_p]} { foreach runtime [get_runtime_list] { # On some builds without any optimization our prologue # detection fails. PR13420. if {$extra_name == "m64" || $extra_name == "m32" \ || $extra_name == "m31"} { setup_kfail 13420 "*-*-*" } if {$runtime != ""} { if {[info procs ${runtime}_kfails] ne ""} { ${runtime}_kfails $i } stap_run3 "$test-$extra_name-$runtime" "$stpfile" \ -c ./$test-$extra_name.exe --runtime=$runtime } elseif {[uprobes_p]} { stap_run3 "$test-$extra_name" "$stpfile" \ -c ./$test-$extra_name.exe } else { untested "$test-$extra_name" } } } else { untested "$test-$extra_name" } catch {exec rm -f $test-$extra_name.exe} } systemtap-2.3/testsuite/systemtap.base/cast-scope.stp000066400000000000000000000016511217430427200232000ustar00rootroot00000000000000global function_string, statement_string, mark_string probe process.function("length@cast-scope.cxx") { function_string .= sprintf("function direct: %s\n", $str$$) function_string .= sprintf("function cast: %s\n", @cast($str, "std::string")$$) } probe process.statement("length@cast-scope.cxx+4") { statement_string .= sprintf("statement direct: %s\n", $str$$) statement_string .= sprintf("statement cast: %s\n", @cast($str, "std::string")$$) } probe process.mark("length") { mark_string .= sprintf("mark cast: %s\n", @cast($arg1, "std::string")$$) } probe end { # Why print the strings this way? cast-scope.exp expects the # output in a certain order. If the probe addresses end up # the same, the process.function/process.mark probes might get # called in any order. # # So, we'll print the strings in a defined order. printf("%s", function_string); printf("%s", mark_string); printf("%s", statement_string); } systemtap-2.3/testsuite/systemtap.base/cast-user.c000066400000000000000000000002651217430427200224610ustar00rootroot00000000000000#include int main() { struct sockaddr sa = { .sa_family = (sa_family_t) -1, .sa_data = 42, }; bind(-1, &sa, sizeof(sa)); return 0; } systemtap-2.3/testsuite/systemtap.base/cast-user.exp000066400000000000000000000010311217430427200230230ustar00rootroot00000000000000set test "cast-user" set ::result_string {binary sa_family OK binary sa_data OK header sa_family OK header sa_data OK} set srcfile "$srcdir/$subdir/$test.c" set stpfile "$srcdir/$subdir/$test.stp" set exefile "[pwd]/$test.exe" set test_flags "additional_flags=-g" set res [target_compile "$srcfile" "$exefile" executable "$test_flags"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test compile" untested "$test" return } else { pass "$test compile" } stap_run3 $test "$stpfile" "$exefile" -c "$exefile" systemtap-2.3/testsuite/systemtap.base/cast-user.stp000066400000000000000000000020631217430427200230430ustar00rootroot00000000000000probe syscall.bind!, nd_syscall.bind { if (pid() != target()) next sa = my_addr_uaddr family = 0xffff data = 42 // Compare sa_family and sa_data using the target binary cast_family = @cast(sa, "sockaddr", @1)->sa_family if (family == cast_family) println("binary sa_family OK") else printf("binary sa_family %#x != %#x\n", family, cast_family) cast_data = @cast(sa, "sockaddr", @1)->sa_data[0] if (data == cast_data) println("binary sa_data OK") else printf("binary sa_data %d != %d\n", data, cast_data) // Compare sa_family and sa_data using a generated user module cast_family = @cast(sa, "sockaddr", "")->sa_family if (family == cast_family) println("header sa_family OK") else printf("header sa_family %#x != %#x\n", family, cast_family) cast_data = @cast(sa, "sockaddr", "")->sa_data[0] if (data == cast_data) println("header sa_data OK") else printf("header sa_data %d != %d\n", data, cast_data) } systemtap-2.3/testsuite/systemtap.base/cast.exp000066400000000000000000000001661217430427200220570ustar00rootroot00000000000000set test "cast" set ::result_string {PID OK PID2 OK PID3 OK execname OK usage OK} stap_run2 $srcdir/$subdir/$test.stp systemtap-2.3/testsuite/systemtap.base/cast.stp000066400000000000000000000023741217430427200220740ustar00rootroot00000000000000probe begin { curr = task_current() // Compare PIDs pid = pid() cast_pid = @cast(curr, "task_struct")->tgid if (pid == cast_pid) println("PID OK") else printf("PID %d != %d\n", pid, cast_pid) // Compare PIDs using a generated kernel module cast_pid = @cast(curr, "task_struct", "kernel")->tgid if (pid == cast_pid) println("PID2 OK") else printf("PID2 %d != %d\n", pid, cast_pid) // Compare PIDs with an array access (PR11556) cast_pid = @cast(curr, "task_struct")[0]->tgid if (pid == cast_pid) println("PID3 OK") else printf("PID3 %d != %d\n", pid, cast_pid) // Compare execnames name = execname() cast_name = kernel_string(@cast(curr, "task_struct")->comm) if (name == cast_name) println("execname OK") else printf("execname \"%s\" != \"%s\"\n", name, cast_name) // Compare usage counter values through a struct address usage = @cast(curr, "task_struct")->usage->counter pusage = & @cast(curr, "task_struct")->usage cast_usage = @cast(pusage, "atomic_t")->counter if (usage == cast_usage) println("usage OK") else printf("usage %d != %d\n", usage, cast_usage) exit() } systemtap-2.3/testsuite/systemtap.base/cmd_parse.exp000066400000000000000000000112571217430427200230650ustar00rootroot00000000000000if {![installtest_p]} { for {set i 0} { $i < 16} {incr i} { untested cmd_parse$i } return } spawn stap -c {echo "hello world"} -we {probe begin {}} expect { -timeout 60 "hello world" {pass "cmd_parse1"} timeout {fail "cmd_parse1: unexpected timeout"} eof {fail "cmd_parse1: unexpected EOF"} } wait;catch {close} spawn stap -c {echo "hello "\"world\"} -we {probe begin {}} expect { -timeout 60 "hello \"world\"" {pass "cmd_parse2"} timeout {fail "cmd_parse2: unexpected timeout"} eof {fail "cmd_parse2: unexpected EOF"} } wait;catch {close} spawn stap -c {sh -c '(a="hello world"; echo $a)'} -we {probe begin {}} expect { -timeout 60 "hello world" {pass "cmd_parse3"} timeout {fail "cmd_parse3: unexpected timeout"} eof {fail "cmd_parse3: unexpected EOF"} } wait;catch {close} spawn stap -c {sh -c '(a="hello "\"world\"; echo $a)'} -we {probe begin {}} expect { -timeout 60 "hello \"world\"" {pass "cmd_parse4"} timeout {fail "cmd_parse4: unexpected timeout"} eof {fail "cmd_parse4: unexpected EOF"} } wait;catch {close} spawn stap -c {sh -c '(a="hello "world; echo $a)'} -we {probe begin {}} expect { -timeout 60 "hello world" {pass "cmd_parse5"} timeout {fail "cmd_parse5: unexpected timeout"} eof {fail "cmd_parse5: unexpected EOF"} } wait;catch {close} spawn stap -c {bash -c '((a=42+7)); echo "The answer is $a"'} -we {probe begin {}} expect { -timeout 60 "The answer is 49" {pass "cmd_parse6"} timeout {fail "cmd_parse6: unexpected timeout"} eof {fail "cmd_parse6: unexpected EOF"} } wait;catch {close} spawn stap -c {sh -c '(echo "Hello World" 1>&2) > /dev/null'} -we {probe begin {}} expect { -timeout 60 "Hello World" {pass "cmd_parse7"} timeout {fail "cmd_parse7: unexpected timeout"} eof {fail "cmd_parse7: unexpected EOF"} } wait;catch {close} # slow test case; requires kernel tracepoint query modules spawn stap -l {vm.*} expect { -timeout 240 -re {^vm[^\r\n]*\r\n} {pass "cmd_parse8"} -re "^Warning: make exited with status: 2\r\n" {exp_continue} timeout {fail "cmd_parse8: unexpected timeout"} eof {fail "cmd_parse8: unexpected EOF"} } wait;catch {close} spawn stap -e {probe begin { printf("%d %s\n", argc, argv[$1]) exit() }} 1 expect { -timeout 60 "1 1" { pass cmd_parse9 } timeout { fail "cmd_parse9 timeout" } eof { fail "cmd_parse9 eof" } } wait;catch {close} spawn stap -e {probe begin { printf("%d %s\n", argc, argv[$1]) exit() }} 5 a b c d expect { -timeout 60 "5 d" { pass cmd_parse10 } timeout { fail "cmd_parse10 timeout" } eof { fail "cmd_parse10 eof" } } wait;catch {close} spawn stap -e {probe begin { printf("%d %s\n", argc, argv[$1]) exit() }} 10 a b c d expect { -timeout 60 "5 " { pass cmd_parse11 } timeout { fail "cmd_parse11 timeout" } eof { fail "cmd_parse11 eof" } } wait;catch {close} spawn stap -e {probe begin { printf("%d %s\n", argc, argv[0]) exit() }} expect { -timeout 60 "0 " { pass cmd_parse12 } timeout { fail "cmd_parse12 timeout" } eof { fail "cmd_parse12 eof" } } wait;catch {close} spawn stap -L syscall.a* expect { -timeout 60 -re {(syscall\.a[_a-zA-Z0-9]*(\ [_a-zA-Z0-9\$]+:[^:]+?)+\r\n)+} { pass "cmd_parse13" } timeout {fail "cmd_parse13: unexpected timeout"} eof {fail "cmd_parse13: unexpected EOF"} } wait;catch {close} if {![catch { exec sh -c "stap -v -v --vp 01020 -h 2>&1 | grep -q 'add per-pass verbosity .23242.'" }]} { pass "cmd_parse14" } else { fail "cmd_parse14" } set uname [exec uname -r] set triplet [split $uname {.-}] if {[lindex $triplet 0] == 2 && [lindex $triplet 1] == 6 && [lindex $triplet 2] < 29} { # verbose -log "kfail, see commit e0ccd3\n"; setup_kfail 4186 "*-*-*" } spawn sh -c "stap -m do_not_cache_me -B kernelrelease -p4 -e 'probe begin {exit()}'" # the \r below is meant to match the "kernelrelease" output, as distinct from # any possible auxiliary make verbosity. expect { -timeout 60 -re "$uname\r" { pass "cmd_parse15" } timeout { fail "cmd_parse15: timeout" } eof { fail "cmd_parse15: eof" } } wait;catch {close} set uname [exec uname -i] # normalize arch set uname [normalize_arch $uname] spawn sh -c "stap -m do_not_cache_me -a $uname -p4 -e 'probe begin {exit()}'" # the \r below is meant to match the "kernelrelease" output, as distinct from # any possible auxiliary make verbosity. expect { -timeout 60 -re "do_not_cache_me.ko\r" { pass "cmd_parse16" } timeout { fail "cmd_parse16: timeout" } eof { fail "cmd_parse16: eof" } } wait;catch {close} # NB: when adding extra tests here, increment the ![installtest_p] # loop count too at the top. catch {exec rm -f do_not_cache_me.ko} systemtap-2.3/testsuite/systemtap.base/color_parsing.exp000066400000000000000000000100231217430427200237570ustar00rootroot00000000000000set test "color_parsing" # checker runs stap/staprun and looks for the SGR parameters inside the # ANSI escape code before a specific string known to be colored. It then # checks if the SGR param matches what was expected. # TEST: name of the test # EXE: set to "stap" to test stap, or "staprun" for staprun # EXP: expected SGR parameter, such as "01;31" proc checker { TEST EXE EXP } { global test if {[string equal $EXE "stap"]} { set cmd "stap --color -e junk" set STR "parse error:" } else { set cmd "staprun -C always" set STR "ERROR:" } set failed 1 set str {^\e\[([;0-9]*)m\e\[K} append str "$STR" # The expect statements below rely on the fact that both stap and # staprun only output ANSI codes when the color code is nonempty. # so e.g. {parse error:} will go through iff the parse() func # returned an empty string. eval spawn $cmd set stap_id $spawn_id expect { -timeout 30 -re "$str" { set stap_seq $expect_out(1,string) set failed 0 exp_continue } -re "^$STR" { set stap_seq "" set failed 0 exp_continue } timeout { fail "$test ($TEST - $EXE: timeout)" exec kill -s KILL -[exp_pid -i $stap_id] } eof { if {$failed} {fail "$test ($TEST - $EXE: unexpected EOF)"} } } catch { close -i $stap_id } ; catch { wait -i $stap_id } if {$failed} { return } if {![string equal $stap_seq $EXP]} { fail "$test ($TEST - $EXE: output didn't match)" verbose -log "expected: $EXP" verbose -log "received: $stap_seq" return } pass "$test ($TEST - $EXE: output matched)" } # stap_check_parse initializes SYSTEMTAP_COLORS to a specified value and # runs the checker for stap and staprun # TEST: name of the test # ENV: value of SYSTEMTAP_COLORS to test # EXP: output expected proc stap_check_parse { TEST ENV EXP } { global test env set env(SYSTEMTAP_COLORS) "$ENV" verbose -log "SYSTEMTAP_COLORS set to \"$env(SYSTEMTAP_COLORS)\"" # Test stap and staprun checker "$TEST" "stap" "$EXP" checker "$TEST" "staprun" "$EXP" } stap_check_parse "empty" "" "01;31" stap_check_parse "short_key1" "a" "" stap_check_parse "short_key2" "a:" "" stap_check_parse "short_key3" "a:error=41" "" stap_check_parse "short_key4" ":a" "" stap_check_parse "short_key5" ":a:" "" stap_check_parse "short_key6" ":a:error=41" "" stap_check_parse "short_key7" "error=32:a:" "32" stap_check_parse "short_key8" "error=32:a=:" "32" stap_check_parse "short_key9" "error=32:a=val:" "32" stap_check_parse "no_eq1" "asd:dsa:error=41" "" stap_check_parse "no_eq2" "asd41" "" stap_check_parse "no_eq3" "asd41:" "" stap_check_parse "no_eq4" "asd41:error=41" "" stap_check_parse "no_eq5" "asd41:hfd" "" stap_check_parse "no_eq6" "asd41:hfd:" "" stap_check_parse "no_eq7" "asd41:hfd:error=41" "" stap_check_parse "no_eq8" "asd=41:hfd" "" stap_check_parse "no_eq9" "asd=41:hfd:" "" stap_check_parse "no_eq10" "asd=41:hfd:error=41" "" stap_check_parse "no_key1" ":" "" stap_check_parse "no_key2" ":error=41" "" stap_check_parse "no_key3" "=" "" stap_check_parse "no_key4" "=:error=41" "" stap_check_parse "no_key5" "=1" "" stap_check_parse "no_key6" "=1:error=41" "" stap_check_parse "no_key7" "=31" "" stap_check_parse "no_key8" "=31:error=41" "" stap_check_parse "no_key9" ":=31" "" stap_check_parse "no_key10" ":=31:error=41" "" stap_check_parse "no_key11" "=:31" "" stap_check_parse "no_key12" "=:31:error=41" "" stap_check_parse "no_key13" "error=41:31" "41" stap_check_parse "no_val1" "asd=" "" stap_check_parse "no_val2" "asd=:error=41" "" stap_check_parse "no_val3" "asd=:" "" stap_check_parse "no_val4" "asd=:error=41" "" stap_check_parse "no_val5" "error=41:asd=:" "41" stap_check_parse "bad_val1" "asd=x" "" stap_check_parse "bad_val2" "asd=x:" "" stap_check_parse "bad_val3" "asd=x:error=41" "" stap_check_parse "bad_val4" "asd=x1:error=41" "" stap_check_parse "bad_val5" "asd=1x:error=41" "" stap_check_parse "valid1" "error=41" "41" stap_check_parse "valid2" "error=41:" "41" stap_check_parse "valid3" "error=41:asd" "41" stap_check_parse "valid4" "error=41:asd=dsa" "41" stap_check_parse "valid5" "asd=;:dsa=12;3;;22;4;2:error=41" "41" pass $test systemtap-2.3/testsuite/systemtap.base/const_value.c000066400000000000000000000006261217430427200230760ustar00rootroot00000000000000#include "sys/sdt.h" struct foo { const int i; const long j; }; typedef struct foo fooer; static int bar (const int i, const long j) { return i * j; } static int func (int (*f) ()) { const int a[] = { 17, 23 }; const fooer baz = { .i = 2, .j = 21 }; STAP_PROBE (test, constvalues); return f(baz.i, baz.j); } int main (int argc, char *argv[], char *envp[]) { return func (&bar) - 42; } systemtap-2.3/testsuite/systemtap.base/const_value.exp000066400000000000000000000045661217430427200234570ustar00rootroot00000000000000# DW_AT_const_value (blocks). set test "const_value" set ::result_string {i: 2 j: 21 a: {17, 23}} set test_flags "additional_flags=-g" # We need -O2 to get const_value encodings in dwarf. set test_flags "$test_flags additional_flags=-O2" set test_flags "$test_flags [sdt_includes]" set res [target_compile $srcdir/$subdir/$test.c $test.exe executable "$test_flags"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test.c compile" untested "$test" return } else { pass "$test.c compile" } # Test only when we are running an install test (can execute) and when # gcc generated DW_AT_const_values for us. We are interested in block # constant values. if {[installtest_p]} { set dw_at_c {DW_AT_const_value} if {![catch {exec readelf --debug-dump=info $test.exe | grep "$dw_at_c"}]} { foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run2 $srcdir/$subdir/$test.stp -c ./$test.exe --runtime=$runtime } elseif {[uprobes_p]} { stap_run2 $srcdir/$subdir/$test.stp -c ./$test.exe } else { untested "$test" } } } else { untested "$test (no-const-value)" } } else { untested "$test" } catch {exec rm -f $test.exe} # DW_AT_const_value (address). set test "const_value_func" set ::result_string {f: bar} set test_flags "additional_flags=-g" # We need -O2 to get const_value encodings in dwarf. set test_flags "$test_flags additional_flags=-O2" set test_flags "$test_flags [sdt_includes]" set res [target_compile $srcdir/$subdir/$test.c $test.exe executable "$test_flags"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test.c compile" untested "$test" return } else { pass "$test.c compile" } # Test only when we are running an install test (can execute) and when # gcc generated DW_AT_const_values for us. We are interested in pure # constant addresses. if {[installtest_p]} { set dw_at_c {DW_AT_const_value} if {![catch {exec readelf --debug-dump=info $test.exe | grep "$dw_at_c"}]} { foreach runtime [get_runtime_list] { setup_kfail 10739 "*-*-*" if {$runtime != ""} { stap_run2 $srcdir/$subdir/$test.stp -c ./$test.exe --runtime=$runtime } elseif {[uprobes_p]} { stap_run2 $srcdir/$subdir/$test.stp -c ./$test.exe } else { untested "$test" } } } else { untested "$test (no-const-value)" } } else { untested "$test" } catch {exec rm -f $test.exe} systemtap-2.3/testsuite/systemtap.base/const_value.stp000066400000000000000000000002361217430427200234570ustar00rootroot00000000000000probe process("const_value.exe").mark("constvalues") { printf("i: %d\n", $baz->i); printf("j: %d\n", $baz->j); printf("a: {%d, %d}\n", $a[0], $a[1]); } systemtap-2.3/testsuite/systemtap.base/const_value_func.c000066400000000000000000000004361217430427200241100ustar00rootroot00000000000000#include "sys/sdt.h" static int bar (int i, long j) { return i * j; } static int func (int (*f) ()) { volatile int i = 2; volatile long j = 21; STAP_PROBE (test, constvalues); return f(i, j); } int main (int argc, char *argv[], char *envp[]) { return func (&bar) - 42; } systemtap-2.3/testsuite/systemtap.base/const_value_func.stp000066400000000000000000000001401217430427200244640ustar00rootroot00000000000000probe process("const_value_func.exe").mark("constvalues") { printf("f: %s\n", usymname($f)); }systemtap-2.3/testsuite/systemtap.base/control_limits.exp000066400000000000000000000044711217430427200241710ustar00rootroot00000000000000set test "control_limits MAXNESTING" if {![installtest_p]} { untested $test; return } foreach runtime [get_runtime_list] { set test "control_limits MAXNESTING" if {$runtime != ""} { lappend test "($runtime)" spawn stap -u -DMAXNESTING=5 $srcdir/$subdir/control_limits.stp \ --runtime=$runtime } else { spawn stap -u -DMAXNESTING=5 $srcdir/$subdir/control_limits.stp } set ok 0 expect { -timeout 150 -re {ERROR.*MAXNESTING} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 1} { pass "$test ($ok)" } { fail "$test ($ok)" } } foreach runtime [get_runtime_list] { set test "control_limits MAXACTION" if {$runtime != ""} { lappend test "($runtime)" spawn stap -u -DMAXACTION_INTERRUPTIBLE=500 \ $srcdir/$subdir/control_limits.stp --runtime=$runtime } else { spawn stap -u -DMAXACTION_INTERRUPTIBLE=500 \ $srcdir/$subdir/control_limits.stp } set ok 0 expect { -timeout 150 -re {ERROR.*MAXACTION} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 1} { pass "$test ($ok)" } { fail "$test ($ok)" } } foreach runtime [get_runtime_list] { set test "control_limits MAXSTRINGLEN small" if {$runtime != ""} { lappend test "($runtime)" spawn stap -u -DMAXSTRINGLEN=50 \ $srcdir/$subdir/control_limits.stp --runtime=$runtime } else { spawn stap -u -DMAXSTRINGLEN=50 $srcdir/$subdir/control_limits.stp } set ok 0 expect { -timeout 150 -re {ERROR.*MAXSTRINGLEN reduced} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 1} { pass "$test ($ok)" } { fail "$test ($ok)" } } foreach runtime [get_runtime_list] { set test "control_limits MAXSTRINGLEN large" if {$runtime != ""} { lappend test "($runtime)" spawn stap -u -DMAXSTRINGLEN=500 \ $srcdir/$subdir/control_limits.stp --runtime=$runtime } else { spawn stap -u -DMAXSTRINGLEN=500 $srcdir/$subdir/control_limits.stp } set ok 0 expect { -timeout 150 -re {ERROR.*MAXSTRINGLEN enlarged} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 1} { pass "$test ($ok)" } { fail "$test ($ok)" } } systemtap-2.3/testsuite/systemtap.base/control_limits.stp000066400000000000000000000010031217430427200241670ustar00rootroot00000000000000 # for MAXNESTING testing function recurse (n) { if (n > 0) recurse (n-1) } probe begin { recurse (7) } # for MAXACTION testing probe begin { for (i=0; i<498; i++) {} } # for MAXSTRINGLEN testing probe begin { s = "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678" # last 8 will be \0'd if (strlen(s) < 127) error ("MAXSTRINGLEN reduced") if (strlen(s) > 127) error ("MAXSTRINGLEN enlarged") } probe begin { exit () } systemtap-2.3/testsuite/systemtap.base/crash.exp000066400000000000000000000025461217430427200222310ustar00rootroot00000000000000# Simple test for staplog.so crash(8) extension set test "crash" if {![installtest_p]} { untested $test; return } if {![file exists $env(CRASH_LIBDIR)/staplog.so]} { untested "$test - no staplog.so"; return } # Load a test script spawn stap -e {probe begin {print("HelloWorld\n")}} -m testlog expect { -timeout 120 "HelloWorld\r\n" { pass "$test - testlog.stp" # Need to run crash(8) while this script is still running. # Since crash(8) needs /dev/mem access, need it run as_root too. # This [ eval ... \{ \} ] business is necessary because as_root # evals the given list/variables in its own scope. eval as_root \{ $srcdir/$subdir/crash.sh $env(CRASH_LIBDIR) \} } timeout { fail "$test - testlog.stp timeout" } timeout { fail "$test - testlog.stp eof" } } catch { exec kill -INT -[exp_pid]; close ; wait } # The crash(8) script creates testlog/global or testlog/cpu as_root { chmod -R a+rX testlog } set ok 0 foreach f [glob -nocomplain testlog/*] { pass "$test - crash(8) generated $f" set fp [open $f] set chars [read $fp] close $fp if [string match "HelloWorld*" $chars] { incr ok pass "$test - crash(8) data" } else { fail "$test - crash(8) data $chars" } } if {$ok == 0} { fail "$test - crash(8) data" } as_root { rm -rf testlog testlog.ko } systemtap-2.3/testsuite/systemtap.base/crash.sh000077500000000000000000000001531217430427200220420ustar00rootroot00000000000000#! /bin/sh crash --readnow << END mod -s testlog testlog.ko extend $1/staplog.so staplog testlog exit END systemtap-2.3/testsuite/systemtap.base/ctime.exp000066400000000000000000000022161217430427200222240ustar00rootroot00000000000000set test "ctime" set linux_result_string {Thu Jan 1 00:00:00 1970 Wed Dec 31 23:59:59 1969 Thu Jan 1 00:00:01 1970 Sat Mar 3 09:46:40 1973 Fri Feb 13 23:31:30 2009 Sat Jan 10 13:37:04 2004 Fri Jul 13 11:01:20 2012 conversion error conversion error Fri Dec 13 20:45:52 1901 conversion error Tue Jan 19 03:14:07 2038 conversion error conversion error conversion error} # Notice the dyninst result string is different than the linux result # string. The userspace glibc library can convert more values. set dyninst_result_string {Thu Jan 1 00:00:00 1970 Wed Dec 31 23:59:59 1969 Thu Jan 1 00:00:01 1970 Sat Mar 3 09:46:40 1973 Fri Feb 13 23:31:30 2009 Sat Jan 10 13:37:04 2004 Fri Jul 13 11:01:20 2012 Sun Aug 24 00:00:00 1000 Thu Sep 2 00:00:00 9993 Fri Dec 13 20:45:52 1901 Fri Dec 13 20:45:51 1901 Tue Jan 19 03:14:07 2038 Tue Jan 19 03:14:08 2038 conversion error conversion error} foreach runtime [get_runtime_list] { if {$runtime != ""} { set ::result_string [subst $${runtime}_result_string] stap_run2 $srcdir/$subdir/$test.stp --runtime=$runtime } else { set ::result_string $linux_result_string stap_run2 $srcdir/$subdir/$test.stp } } systemtap-2.3/testsuite/systemtap.base/ctime.stp000066400000000000000000000051051217430427200222360ustar00rootroot00000000000000# Note this test is written in a bit of an odd way. In systemtap 2.2 # and above, ctime will raise an error. For systemtap versions before # 2.2, ctime returned one of three error strings. Map those error # strings to one error. probe begin { // epoch println(ctime(0)) // epoch - 1 println(ctime(-1)) // epoch + 1 println(ctime(1)) // Some funny numbers println(ctime(100000000)) println(ctime(1234567890)) println(ctime(1073741824)) println(ctime(0x50000000)) // some time really long ago secspermin = 60 minsperhour = 60 hoursperday = 24 secsperhour = secspermin * minsperhour secsperday = secsperhour * hoursperday epoch_year = 1970 time = -1 * (epoch_year - 1000) * 365 * secsperday try { result = ctime(time) if (result == "far far in the future..." || result == "a long, long time ago..." || result == "") println("conversion error") else println(result) } catch { println("conversion error") } // some time in the far future time = (9999 - epoch_year) * 365 * secsperday try { result = ctime(time) if (result == "far far in the future..." || result == "a long, long time ago..." || result == "") println("conversion error") else println(result) } catch { println("conversion error") } // min 32 bit time = -2147483648 println(ctime(time)) // over the edge, a long, long time ago... time-- try { result = ctime(time) if (result == "far far in the future..." || result == "a long, long time ago..." || result == "") println("conversion error") else println(result) } catch { println("conversion error") } // max 32 bit time = 2147483647 println(ctime(time)) // over the edge, far far in the future... time++ try { result = ctime(time) if (result == "far far in the future..." || result == "a long, long time ago..." || result == "") println("conversion error") else println(result) } catch { println("conversion error") } // min 64 bit try { result = ctime(-9223372036854775808) if (result == "far far in the future..." || result == "a long, long time ago..." || result == "") println("conversion error") else println(result) } catch { println("conversion error") } // max 64 bit try { result = ctime(9223372036854775807) if (result == "far far in the future..." || result == "a long, long time ago..." || result == "") println("conversion error") else println(result) } catch { println("conversion error") } exit() } systemtap-2.3/testsuite/systemtap.base/cu-decl-1.c000066400000000000000000000002451217430427200222230ustar00rootroot00000000000000#include struct foo; struct foo* get_foo(void); void print(struct foo* f) { printf("%p\n", f); } int main() { print(get_foo()); return 0; } systemtap-2.3/testsuite/systemtap.base/cu-decl-2.c000066400000000000000000000001541217430427200222230ustar00rootroot00000000000000struct foo { int x, y; }; struct foo* get_foo() { static struct foo f = { 6, 7 }; return &f; } systemtap-2.3/testsuite/systemtap.base/cu-decl.exp000066400000000000000000000020401217430427200224320ustar00rootroot00000000000000# Check that we can dereference a type declaration that is # defined in a separate CU from the function. set test "cu-decl" set script { probe process("cu-decl").function("print") { println($f->x * $f->y) } } set sources "$srcdir/$subdir/$test-1.c $srcdir/$subdir/$test-2.c" set flags "additional_flags=-g" for {set i 0} {$i < [all_compile_flags]} {incr i} { set extra_flag [all_compile_flag $i] set extra_name [all_compile_flag_name $i] set res [target_compile $sources $test executable "$flags $extra_flag"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test-$extra_name target compilation" untested "$test-$extra_name" } else { pass "$test-$extra_name target compilation" } foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_compile $test-$extra_name-$runtime 1 "{$script}" \ --runtime=$runtime } elseif {[uprobes_p]} { stap_compile $test-$extra_name 1 "{$script}" } else { untested "$test-$extra_name" } } catch {exec rm $test} } systemtap-2.3/testsuite/systemtap.base/cxxclass.cxx000066400000000000000000000017011217430427200227570ustar00rootroot00000000000000#include "sys/sdt.h" #include class ProbeClass { private: int& ref; const char *name; public: ProbeClass(int& v, const char *n) : ref(v), name(n) { STAP_PROBE2(_test_, cons, name, ref); } void method(int min) { STAP_PROBE3(_test_, meth, name, ref, min); ref -= min; } ~ProbeClass() { STAP_PROBE2(_test_, dest, name, ref); } }; static void call() { int i = 64; STAP_PROBE1(_test_, call, i); ProbeClass inst = ProbeClass(i, "call"); inst.method(24); i += 2; // Here the destructor goes out of scope and uses i as ref one last time. } static void call2() { int j = 24; STAP_PROBE1(_test_, call2, j); ProbeClass inst = ProbeClass(j, "call2"); inst.method(40); j += 58; // Here the destructor goes out of scope and uses i as ref one last time. } int main (int argc, char **argv) { STAP_PROBE(_test_, main_enter); call(); call2(); STAP_PROBE(_test_, main_exit); return 0; } systemtap-2.3/testsuite/systemtap.base/cxxclass.exp000066400000000000000000000032571217430427200227610ustar00rootroot00000000000000set test "cxxclass" set ::result_string {main_enter call: 64 cons call: 64 meth call: 64 24 dest call: 42 call2: 24 cons call2: 24 meth call2: 24 40 dest call2: 42 main_exit} set test_flags "additional_flags=-g" set test_flags "$test_flags [sdt_includes]" set test_flags "$test_flags compiler=g++" # ppc64 needs a more restrictive constraint for the probe args if {[regexp "^(x86_64|i.86)$" $::tcl_platform(machine)] == 0} { set test_flags "$test_flags additional_flags=-DSTAP_SDT_ARG_CONSTRAINT=nr" } proc dyninst_kfails {index} { # The dyninst runtime isn't multi-arch, it only works on the # native architecture. PR14490. if {! [all_compile_flag_native_p $index]} { setup_kfail 14490 "*-*-*" } } for {set i 0} {$i < [all_compile_flags]} {incr i} { set extra_flag [all_compile_flag $i] set extra_name [all_compile_flag_name $i] set res [target_compile $srcdir/$subdir/$test.cxx $test.exe executable "$test_flags $extra_flag"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "compiling $extra_name $test.c" untested "$extra_name $test.c compile" continue } else { pass "$extra_name $test.c compile" } if {[installtest_p]} { foreach runtime [get_runtime_list] { if {$runtime != ""} { if {[info procs ${runtime}_kfails] ne ""} { ${runtime}_kfails $i } stap_run3 "$test-$extra_name-$runtime" -w \ $srcdir/$subdir/$test.stp $test.exe -c ./$test.exe --runtime=$runtime } elseif {[uprobes_p]} { stap_run3 "$test-$extra_name" -w $srcdir/$subdir/$test.stp \ $test.exe -c ./$test.exe } else { untested "$test-$extra_name" } } } else { untested "$test-$extra_name" } catch {exec rm -f $test.exe} } systemtap-2.3/testsuite/systemtap.base/cxxclass.stp000066400000000000000000000011571217430427200227700ustar00rootroot00000000000000probe process("cxxclass.exe").mark("main_enter") { log("main_enter"); } probe process("cxxclass.exe").mark("main_exit") { log("main_exit"); } probe process("cxxclass.exe").mark("call") { printf("call: %d\n", $arg1); } probe process("cxxclass.exe").mark("call2") { printf("call2: %d\n", $arg1); } probe process("cxxclass.exe").mark("cons") { printf("cons %s: %d\n", user_string($arg1), $arg2); } probe process("cxxclass.exe").mark("meth") { printf("meth %s: %d %d\n", user_string($arg1), $arg2, $arg3); } probe process("cxxclass.exe").mark("dest") { printf("dest %s: %d\n", user_string($arg1), $arg2); } systemtap-2.3/testsuite/systemtap.base/debugpath.exp000066400000000000000000000014751217430427200230740ustar00rootroot00000000000000 set test "debugpath-bad" spawn env SYSTEMTAP_DEBUGINFO_PATH=/dev/null stap -e "probe kernel.function(\"vfs_read\") {}" -wp4 expect { -re {^semantic error:.*missing.*debuginfo} { pass $test } timeout { fail "$test (timeout1)" } eof { fail "$test (eof)" } } wait set test "debugpath-good" set uname [exec /bin/uname -r] # Guess where debuginfo is installed if [file isdirectory /usr/lib/debug] { set debuginfo_path "/usr/lib/debug" } elseif [file isdirectory /lib/modules/$uname/build] { set debuginfo_path "/lib/modules/$uname/build" } else { set debuginfo_path "/lib/modules/$uname" } spawn env SYSTEMTAP_DEBUGINFO_PATH=$debuginfo_path stap -e "probe kernel.function(\"vfs_read\") {}" -wp2 expect { -re {kernel.function.*pc=} { pass $test } timeout { fail "$test (timeout2)" } eof { fail "$test (eof)" } } wait systemtap-2.3/testsuite/systemtap.base/deref.exp000066400000000000000000000004621217430427200222110ustar00rootroot00000000000000# Check that the deref mechanisms work correctly. set test "deref" foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string -g \ --runtime=$runtime } else { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string -g } } systemtap-2.3/testsuite/systemtap.base/deref.stp000066400000000000000000000070341217430427200222250ustar00rootroot00000000000000/* * deref.stp * * Check that the deref mechanisms work correctly. */ probe begin { println("systemtap starting probe") } probe end { println("systemtap ending probe") } global error_count = 0 probe end(1) { log_test("kread u8", kread_u8()) log_test("kread u16", kread_u16()) log_test("kread u32", kread_u32()) log_test("kread u64", kread_u64()) log_test("kread ptr", kread_ptr()) log_test("kread const u8", kread_const_u8()) log_test("kread const u16", kread_const_u16()) log_test("kread const u32", kread_const_u32()) log_test("kread const u64", kread_const_u64()) log_test("kread const ptr", kread_const_ptr()) log_test("kwrite u8", kwrite_u8()) log_test("kwrite u16", kwrite_u16()) log_test("kwrite u32", kwrite_u32()) log_test("kwrite u64", kwrite_u64()) log_test("kwrite ptr", kwrite_ptr()) if (!error_count) println("systemtap test success") } function log_test(test:string, result:long) { if (!result) { printf("systemtap test failure - %s\n", test) error_count += 1 } } function kread_u8:long() %{ uint8_t local = 0x42; STAP_RETVALUE = (local == kread(&local)); CATCH_DEREF_FAULT(); %} function kread_u16:long() %{ uint16_t local = 0xBEEF; STAP_RETVALUE = (local == kread(&local)); CATCH_DEREF_FAULT(); %} function kread_u32:long() %{ uint32_t local = 0xDEADBEEF; STAP_RETVALUE = (local == kread(&local)); CATCH_DEREF_FAULT(); %} function kread_u64:long() %{ uint64_t local = 0xDEADBEEFBAADF00DLL; STAP_RETVALUE = (local == kread(&local)); CATCH_DEREF_FAULT(); %} function kread_ptr:long() %{ void *local = &systemtap_module_init; STAP_RETVALUE = (local == kread(&local)); CATCH_DEREF_FAULT(); %} function kread_const_u8:long() %{ const uint8_t local = 0x42; STAP_RETVALUE = (local == kread(&local)); CATCH_DEREF_FAULT(); %} function kread_const_u16:long() %{ const uint16_t local = 0xBEEF; STAP_RETVALUE = (local == kread(&local)); CATCH_DEREF_FAULT(); %} function kread_const_u32:long() %{ const uint32_t local = 0xDEADBEEF; STAP_RETVALUE = (local == kread(&local)); CATCH_DEREF_FAULT(); %} function kread_const_u64:long() %{ const uint64_t local = 0xDEADBEEFBAADF00DLL; STAP_RETVALUE = (local == kread(&local)); CATCH_DEREF_FAULT(); %} function kread_const_ptr:long() %{ const void *local = &systemtap_module_init; STAP_RETVALUE = (local == kread(&local)); CATCH_DEREF_FAULT(); %} // NB: kwrite uses system macros with inline asm, with this comment: // // Tell gcc we read from memory instead of writing: this is because we do not // write to any memory gcc knows about, so there are no aliasing issues. // // In this test I'm writing to memory that gcc *does* know about, thus we need // the memory marked volatile to force gcc to re-read it. function kwrite_u8:long() %{ volatile uint8_t local = 0; kwrite(&local, 0x42); STAP_RETVALUE = (local == 0x42); CATCH_DEREF_FAULT(); %} function kwrite_u16:long() %{ volatile uint16_t local = 0; kwrite(&local, 0xBEEF); STAP_RETVALUE = (local == 0xBEEF); CATCH_DEREF_FAULT(); %} function kwrite_u32:long() %{ volatile uint32_t local = 0; kwrite(&local, 0xDEADBEEF); STAP_RETVALUE = (local == 0xDEADBEEF); CATCH_DEREF_FAULT(); %} function kwrite_u64:long() %{ volatile uint64_t local = 0; kwrite(&local, 0xDEADBEEFBAADF00DLL); STAP_RETVALUE = (local == 0xDEADBEEFBAADF00DLL); CATCH_DEREF_FAULT(); %} function kwrite_ptr:long() %{ const void *local = NULL; kwrite(&local, &systemtap_module_init); STAP_RETVALUE = (local == &systemtap_module_init); CATCH_DEREF_FAULT(); %} systemtap-2.3/testsuite/systemtap.base/deref2.exp000066400000000000000000000015471217430427200223000ustar00rootroot00000000000000set test "deref2" # XXX: the load-generation code below doesn't trigger reliably under dejagnu untested $test; continue if {![installtest_p]} { untested $test; continue } # This is asking perl to consume all of its file handles with sockets. # When there are no more, sock_alloc_fd will start returning errors (negatives). set load_gen_cmd {perl -e {use Socket; while ($i < 65536) { $i++; socket $Foo[$i], AF_UNIX, SOC_STREAM, PF_UNSPEC;} print "Toodaloo\n"; }} spawn stap $srcdir/$subdir/deref2.stp set pos 0 set neg 0 expect { start\r\n { catch { eval exec $load_gen_cmd } verbose -log "starting loadgen" } pos\r\n { verobse -log "pos"; incr pos; exp_continue } neg\r\n { verbose -log "neg"; incr neg; exp_continue } eof { } timeout { } } wait if {$neg > 0} { pass "$test ($pos $neg)" } else { fail "$test ($pos $neg)" } systemtap-2.3/testsuite/systemtap.base/deref2.stp000066400000000000000000000004101217430427200222760ustar00rootroot00000000000000# PR 3331 # It's just an ordinary function that returns a 4-byte signed value, # even on a 64-bit hosts. probe kernel.function("sock_alloc_fd").return { println ($return < 0 ? "neg" : "pos") } probe timer.s (5) { exit () } probe begin { println ("start") } systemtap-2.3/testsuite/systemtap.base/div0.exp000066400000000000000000000005651217430427200217720ustar00rootroot00000000000000# Simple function to test that systemtap divide by 0 doesn't kill the machine set test "div0" set output_string "(.*)division by 0 near(.*)" foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run $srcdir/$subdir/$test.stp no_load $output_string \ --runtime=$runtime } else { stap_run $srcdir/$subdir/$test.stp no_load $output_string } } systemtap-2.3/testsuite/systemtap.base/div0.stp000066400000000000000000000012021217430427200217710ustar00rootroot00000000000000/* * div.stp0 * * Check the systemtap divide by 0 does not kill the machine * * Note: Error messages are written to stderr. That means it is * possible that if a printf is followed by something that * generates an error, the error will get displayed before the printf. * That is why both print's are in the begin probe. * */ global x3 global x1 global x2 probe begin { print("systemtap starting probe\n") print("systemtap ending probe\n") x1 = 56088; x2 = 0; } probe end { x3 = x1 / x2 /* this part does not get executed */ if (x3 != 456 ) print("systemtap test failure\n") else print("systemtap test failure\n") } systemtap-2.3/testsuite/systemtap.base/dtrace.exp000066400000000000000000000103471217430427200223710ustar00rootroot00000000000000set test "dtrace" # Test the dtrace compatible python script if {[installtest_p]} { set dtrace $env(SYSTEMTAP_PATH)/dtrace } else { set dtrace ../dtrace } exec mkdir -p /tmp/dtrace set dpath "/tmp/dtrace/test.d" set fp [open $dpath "w"] puts $fp " #define INT16 short #define INT32 int provider tstsyscall { probe test(INT16 arg1, INT32 arg2, INT32 arg3, INT32 arg4, struct astruct arg5) } " close $fp exec mkdir -p /tmp/dtrace_inc set ipath "/tmp/dtrace_inc/dtest.h" set $fp [open $ipath "w"] puts $fp " #define INT16 short #define INT32 int " close $fp set idpath "/tmp/dtrace/itest.d" set $fp [open $idpath "w"] puts $fp " #include provider tstsyscall { probe test(INT16 arg1, INT32 arg2, INT32 arg3, INT32 arg4, struct astruct arg5) } " close $fp set incpath "/tmp/dtrace_inc" # ----------------------------------------------------------------- # test command line option and file handling verbose -log "$dtrace -G -s $dpath -o XXX.o" catch {exec $dtrace -G -s $dpath -o XXX.o} if {[file exists XXX.o]} then { pass "dtrace -G -o XXX.o" } else { fail "dtrace -G -o XXX.o" } exec rm -f XXX.o verbose -log "$dtrace -G -s $dpath -o XXX" catch {exec $dtrace -G -s $dpath -o XXX} if {[file exists XXX]} then { pass "dtrace -G -o XXX" } else { fail "dtrace -G -o XXX" } exec rm -f XXX verbose -log "$dtrace -h -s $dpath -o XXX.h" catch {exec $dtrace -h -s $dpath -o XXX.h} if {[file exists XXX.h]} then { pass "dtrace -h -o XXX.h" } else { fail "dtrace -h -o XXX.h" } exec rm -f XXX.h verbose -log "$dtrace -h -s $dpath -o XXX" catch {exec $dtrace -h -s $dpath -o XXX} if {[file exists XXX]} then { pass "dtrace -h -o XXX" } else { fail "dtrace -h -o XXX" } exec rm -f XXX verbose -log "$dtrace -G -s $dpath -o /tmp/XXX.o" catch {exec $dtrace -G -s $dpath -o /tmp/XXX.o} if {[file exists /tmp/XXX.o]} then { pass "dtrace -G -o /tmp/XXX.o" } else { fail "dtrace -G -o /tmp/XXX.o" } exec rm -f /tmp/XXX.o verbose -log "$dtrace -G -s $dpath -o /tmp/XXX" catch {exec $dtrace -G -s $dpath -o /tmp/XXX} if {[file exists /tmp/XXX]} then { pass "dtrace -G -o /tmp/XXX" } else { fail "dtrace -G -o /tmp/XXX" } exec rm -f /tmp/XXX verbose -log "$dtrace -h -s $dpath -o /tmp/XXX.h" catch {exec $dtrace -h -s $dpath -o /tmp/XXX.h} if {[file exists /tmp/XXX.h]} then { pass "dtrace -h -o /tmp/XXX.h" } else { fail "dtrace -h -o /tmp/XXX.h" } exec rm -f /tmp/XXX.h verbose -log "$dtrace -h -s $dpath -o /tmp/XXX" catch {exec $dtrace -h -s $dpath -o /tmp/XXX} if {[file exists /tmp/XXX]} then { pass "dtrace -h -o /tmp/XXX" } else { fail "dtrace -h -o /tmp/XXX" } exec rm -f /tmp/XXX verbose -log "$dtrace -G -s $dpath" catch {exec $dtrace -G -s $dpath} if {[file exists test.o]} then { pass "dtrace -G" } else { fail "dtrace -G" } exec rm -f test.o verbose -log "$dtrace -h -s $dpath" catch {exec $dtrace -h -s $dpath} if {[file exists test.h]} then { pass "dtrace -h" } else { fail "dtrace -h" } exec rm -f test.o set ok 0 verbose -log "CFLAGS=\"MYCFLAGS\" CC=echo $dtrace -G -s $dpath" spawn env CFLAGS=MYCFLAGS CC=echo $dtrace -G -s $dpath expect { -re {-g MYCFLAGS} {incr ok} } catch {close}; catch {wait} if { $ok != 0} { pass "dtrace CFLAGS= CC=" } else { fail "dtrace CFLAGS= CC=" } set ok 0 verbose -log "$dtrace -C -h -s $dpath -o XXX.h" catch {exec $dtrace -C -h -s $dpath -o XXX.h} spawn cat XXX.h expect { "short arg1, int arg2, int arg3, int arg4" {incr ok} } catch {close}; catch {wait} if { $ok != 0} { pass "dtrace -C -h -o XXX.h" } else { fail "dtrace -C -h -o XXX.h" } exec rm -f XXX.h set ok 0 verbose -log "$dtrace -C -I$incpath -h -s $idpath -o XXX.h" catch {exec $dtrace -C -I$incpath -h -s $idpath -o XXX.h} spawn cat XXX.h expect { "short arg1, int arg2, int arg3, int arg4" {incr ok} } catch {close}; catch {wait} if { $ok != 0} { pass "dtrace -C -Iincpath -h -o XXX.h" } else { fail "dtrace -C -Iincpath -h -o XXX.h" } exec rm -f XXX.h verbose -log "$dtrace -I$incpath -G -s $idpath" catch {exec $dtrace -G -s $dpath} if {[file exists test.o]} then { pass "dtrace -Iincpath -G" } else { fail "dtrace -Iincpath -G" } exec rm -f test.o exec /bin/rm -r /tmp/dtrace /tmp/dtrace_inc # ----------------------------------------------------------------- systemtap-2.3/testsuite/systemtap.base/equal.exp000066400000000000000000000004501217430427200222300ustar00rootroot00000000000000# Simple function to test that equal operation works set test "equal" # better have a count other than zero to show that probe fired set output_string "count = \[1-9\]\[0-9\]*\r\ncount2 = \[1-9\]\[0-9\]*\r\nsystemtap test success\r\n" stap_run $srcdir/$subdir/$test.stp no_load $output_string systemtap-2.3/testsuite/systemtap.base/equal.stp000066400000000000000000000010161217430427200222410ustar00rootroot00000000000000/* * equal.stp * * Simple function to test that equal operation works */ global count global count2 probe begin { println("systemtap starting probe") } probe kernel.function("schedule") { ++count; ++count2; } probe end { println("systemtap ending probe") printf("count = %d\n", count) printf("count2 = %d\n", count) if ( count == count2) { if ( (count-1) == count2 ) { println("systemtap test failure"); } else { println("systemtap test success"); } } else { println("systemtap test failure"); } } systemtap-2.3/testsuite/systemtap.base/error_fn.exp000066400000000000000000000005301217430427200227340ustar00rootroot00000000000000# check that errors in nested functions are not lost on return # bugzilla 6529 set test "error_fn" foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run $srcdir/$subdir/$test.stp no_load ".*synthetic error.*" \ --runtime=$runtime } else { stap_run $srcdir/$subdir/$test.stp no_load ".*synthetic error.*" } } systemtap-2.3/testsuite/systemtap.base/error_fn.stp000066400000000000000000000004021217430427200227440ustar00rootroot00000000000000probe begin { println("systemtap starting probe") println("systemtap ending probe") } function generate_error:long() { error("synthetic error") return 1 } function compute:long() { return generate_error() } probe end { compute() } systemtap-2.3/testsuite/systemtap.base/execve.exp000066400000000000000000000001441217430427200224000ustar00rootroot00000000000000set test "execve" set ::result_string {/bin/true} stap_run2 $srcdir/$subdir/$test.stp -c /bin/true systemtap-2.3/testsuite/systemtap.base/execve.stp000066400000000000000000000001261217430427200224120ustar00rootroot00000000000000probe syscall.execve { if (pid() == target()) { println(filename) } } systemtap-2.3/testsuite/systemtap.base/externalvar.c000066400000000000000000000022411217430427200231020ustar00rootroot00000000000000/* externalvar test case * Copyright (C) 2009, Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. * * Tests that an external exported variable can be accessed. */ #include // function from our library int lib_main (void); struct exestruct { char c; int i; long l; struct exestruct *s1; struct exestruct *s2; }; char exevar_c; int exevar_i; long exevar_l; struct exestruct *exe_s; static char stat_exevar_c; static int stat_exevar_i; static long stat_exevar_l; static struct exestruct *stat_exe_s; static void main_call () { asm (""); // dummy method, just to probe and extract and jump into lib. lib_main (); } int main () { exevar_c = 42; stat_exevar_c = exevar_c; exevar_i = 2; stat_exevar_i = exevar_i; exevar_l = 21; stat_exevar_l = exevar_l; exe_s = (struct exestruct *) malloc(sizeof(struct exestruct)); exe_s->i =1; exe_s->l =2; exe_s->c =3; exe_s->s1 = NULL; exe_s->s2 = exe_s; stat_exe_s = exe_s; main_call (); return 0; } systemtap-2.3/testsuite/systemtap.base/externalvar.exp000066400000000000000000000065221217430427200234620ustar00rootroot00000000000000set test "externalvar" set testpath "$srcdir/$subdir" set testsrc "$testpath/$test.c" set testsrclib "$testpath/${test}_lib.c" set testexe "[pwd]/$test" set testlibname "$test" set testlibdir "[pwd]" set testso "$testlibdir/lib${testlibname}.so" set testflags "additional_flags=-g" set testlibflags "$testflags additional_flags=-fPIC additional_flags=-shared" set maintestflags "$testflags additional_flags=-L$testlibdir additional_flags=-l$testlibname additional_flags=-Wl,-rpath,$testlibdir" set output {exevar_c = 42 exevar_i = 2 exevar_l = 21 stat_exevar_c = 42 stat_exevar_i = 2 stat_exevar_l = 21 exe_s->i = 1 exe_s->l = 2 exe_s->c = 3 stat_exe_s->i = 1 stat_exe_s->l = 2 stat_exe_s->c = 3 exe_s->s1 = 0x0 exe_s == exe_s->s2 stat_exe_s->s1 = 0x0 stat_exe_s == exe_s->s2 libvar = 42 stat_libvar = 42 lib_s->i = 1 lib_s->l = 2 lib_s->c = 3 stat_lib_s->i = 1 stat_lib_s->l = 2 stat_lib_s->c = 3 lib_s == lib_s->s1 lib_s->s2 = 0x0 stat_lib_s == lib_s->s1 stat_lib_s->s2 = 0x0} # Only run on make installcheck and utrace present. if {! [installtest_p]} { untested "$test"; return } proc dyninst_kfails {index} { # The dyninst runtime isn't multi-arch, it only works on the # native architecture. PR14490. # It also doesn't do vma tracking anyway. PR15052. if {! [all_compile_flag_native_p $index]} { setup_kfail 14490 "*-*-*" } else { setup_kfail 15052 "*-*-*" } } for {set i 0} {$i < [all_compile_flags]} {incr i} { set extra_flag [all_compile_flag $i] set extra_name [all_compile_flag_name $i] # Compile our test program and library. set res [target_compile $testsrclib $testso executable \ "$testlibflags $extra_flag"] if { $res != "" } { verbose "target_compile for $testso failed: $res" 2 fail "unable to compile $testsrclib $extra_name" continue } set res [target_compile $testsrc $testexe executable \ "$maintestflags $extra_flag"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile $testsrc $extra_name" continue } foreach runtime [get_runtime_list] { set test_name "$test-$extra_name" if {$runtime != ""} { # Got to run stap with both the exe and the libraries used as -d # args. if {[info procs ${runtime}_kfails] ne ""} { ${runtime}_kfails $i } set test_name "$test_name-$runtime" set cmd [concat stap --runtime=$runtime -d $testso \ -d $testexe -c $testexe $testpath/$test.stp] } elseif {[utrace_p] && [uprobes_p]} { # Got to run stap with both the exe and the libraries used as -d # args. set cmd [concat stap -d $testso -d $testexe -c $testexe \ $testpath/$test.stp] } else { untested "$test_name" continue } send_log "cmd: $cmd\n" catch {eval exec $cmd} res send_log "cmd output: $res\n" set n 0 set m [llength [split $output "\n"]] set expected [split $output "\n"] foreach line [split $res "\n"] { if {![string equal $line [lindex $expected $n]]} { fail "$test_name" send_log "line [expr $n + 1]: expected \"[lindex $expected $n]\", " send_log "Got \"$line\"\n" set n -1 break } incr n } if { $n < 0 } { continue } if { $n != $m } { fail "$test_name" send_log "Got \"$n\" lines, expected \"$m\" lines\n" } else { pass $test_name } } catch {exec rm -f $testexe $testso} } systemtap-2.3/testsuite/systemtap.base/externalvar.stp000066400000000000000000000033701217430427200234720ustar00rootroot00000000000000probe process("externalvar").function("main_call") { printf("exevar_c = %d\n", $exevar_c); printf("exevar_i = %d\n", $exevar_i); printf("exevar_l = %d\n", $exevar_l); printf("stat_exevar_c = %d\n", $stat_exevar_c); printf("stat_exevar_i = %d\n", $stat_exevar_i); printf("stat_exevar_l = %d\n", $stat_exevar_l); printf("exe_s->i = %d\n", $exe_s->i); printf("exe_s->l = %d\n", $exe_s->l); printf("exe_s->c = %d\n", $exe_s->c); printf("stat_exe_s->i = %d\n", $stat_exe_s->i); printf("stat_exe_s->l = %d\n", $stat_exe_s->l); printf("stat_exe_s->c = %d\n", $stat_exe_s->c); printf("exe_s->s1 = 0x%x\n", $exe_s->s1); if ($exe_s == $exe_s->s2) { printf("exe_s == exe_s->s2\n"); } else { printf("exe_s != exe_s->s2\n"); } printf("stat_exe_s->s1 = 0x%x\n", $stat_exe_s->s1); if ($stat_exe_s == $exe_s->s2) { printf("stat_exe_s == exe_s->s2\n"); } else { printf("stat_exe_s != exe_s->s2\n"); } } probe process("libexternalvar.so").function("lib_call") { printf("libvar = %d\n", $libvar); printf("stat_libvar = %d\n", $stat_libvar); printf("lib_s->i = %d\n", $lib_s->i); printf("lib_s->l = %d\n", $lib_s->l); printf("lib_s->c = %d\n", $lib_s->c); printf("stat_lib_s->i = %d\n", $stat_lib_s->i); printf("stat_lib_s->l = %d\n", $stat_lib_s->l); printf("stat_lib_s->c = %d\n", $stat_lib_s->c); if ($lib_s == $lib_s->s1) { printf("lib_s == lib_s->s1\n"); } else { printf("lib_s != lib_s->s2\n"); } printf("lib_s->s2 = 0x%x\n", $lib_s->s2); if ($stat_lib_s == $lib_s->s1) { printf("stat_lib_s == lib_s->s1\n"); } else { printf("stat_lib_s != lib_s->s2\n"); } printf("stat_lib_s->s2 = 0x%x\n", $stat_lib_s->s2); } systemtap-2.3/testsuite/systemtap.base/externalvar_lib.c000066400000000000000000000016411217430427200237330ustar00rootroot00000000000000/* external var test case - library helper * Copyright (C) 2009, Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. * * Tests that an external exported variable can be accessed. */ #include struct libstruct { int i; long l; char c; struct libstruct *s1; struct libstruct *s2; }; int libvar; struct libstruct *lib_s; static int stat_libvar; static struct libstruct *stat_lib_s; static void lib_call () { asm(""); // dummy method, just to probe and extract. } void lib_main () { libvar = 42; stat_libvar = libvar; lib_s = (struct libstruct *) malloc(sizeof(struct libstruct)); lib_s->i = 1; lib_s->l = 2; lib_s->c = 3; lib_s->s1 = lib_s; lib_s->s2 = NULL; stat_lib_s = lib_s; lib_call (); } systemtap-2.3/testsuite/systemtap.base/finloop2.exp000066400000000000000000000006001217430427200226460ustar00rootroot00000000000000# Simple function to test that systemtap can generate a kernel module that # instruments a function, install it, and get some output. set test "finloop2" # better have a count other than zero to show that probe fired set output_string "count = \[1-9\]\[0-9\]*\r\nloop_count = \[1-9\]\[0-9\]*\r\nsystemtap test success\r\n" stap_run $srcdir/$subdir/$test.stp no_load $output_string systemtap-2.3/testsuite/systemtap.base/finloop2.stp000066400000000000000000000010211217430427200226560ustar00rootroot00000000000000/* * kfunct.stp * * Check the systemtap avoids infinite loops * install it, and get some output. */ global count global loop_count probe begin { println("systemtap starting probe") } probe kernel.function("schedule") { ++count; for(a = 1; a <=10; ++a) { ++loop_count; } } probe end { println("systemtap ending probe") printf("count = %d\n", count) printf("loop_count = %d\n", loop_count) if ( count * 10 == loop_count) { println("systemtap test success"); } else { println("systemtap test failure"); } } systemtap-2.3/testsuite/systemtap.base/flightrec1.exp000066400000000000000000000022671217430427200231610ustar00rootroot00000000000000set test "flightrec1" if {![installtest_p]} { untested $test; return } # Make sure we start with a clean slate. catch {exec rm -f $test.out*} # run stapio in background mode spawn stap -F -o $test.out -we {probe begin {}} # check whether stap outputs stapio pid set pid 0 expect { -timeout 240 -re {([0-9]+)\r\n} { pass "$test (flight recorder option)" set pid $expect_out(1,string) exp_continue} timeout { fail "$test (timeout)" } eof { } } wait; catch {close} if {$pid == 0} { fail "$test (no pid)" return -1 } # check whether stapio is running in background spawn ps -o cmd hc $pid expect { -timeout 10 "stapio" {pass "$test (stapio in background)"} # don't contine timeout { fail "$test (timeout)"} eof { fail "$test (stapio was not found)" } } wait; catch {close} # switch file exec sleep 2 exec kill -USR2 $pid # check output file exec sleep 2 if {[catch {exec rm $test.out}]} { fail "$test (no output file)" return -1 } else { pass "$test (output file)" } exec kill -TERM $pid # check switched output file if {[catch {exec rm $test.out.1}]} { fail "$test (failed to switch output file)" return -1 } else { pass "$test (switch output file)" } systemtap-2.3/testsuite/systemtap.base/flightrec2.exp000066400000000000000000000026701217430427200231600ustar00rootroot00000000000000set test "flightrec2" if {![installtest_p]} { untested $test; return } # cleanup system "rm -f flightlog.out*" set pid 0 # check -S option spawn stap -F -o flightlog.out -S 1,3 $srcdir/$subdir/$test.stp expect { -timeout 240 -re {([0-9]+)\r\n} { pass "$test (-S option)" set pid $expect_out(1,string) exp_continue} timeout { fail "$test (timeout)"} eof { } } wait; catch {close} if {$pid == 0} { fail "$test (no pid)" return -1 } exec sleep 4 set scnt 0 set cnt1 0 # wait for log files eval spawn stat -c %s [glob flightlog.out.*] expect { -timeout 100 -re {[0-9]+} { incr cnt1; if {$expect_out(buffer) <= 1048576 } {incr scnt} exp_continue} timeout { fail "$test (logfile timeout)"} } wait; catch {close} exec sleep 3 set cnt2 0 # wait for log files eval spawn stat -c %s [glob flightlog.out.*] expect { -timeout 100 -re {[0-9]+} { incr cnt2; if {$expect_out(buffer) <= 1048576 } {incr scnt} exp_continue} timeout { fail "$test (logfile timeout)"} } wait; catch {close} # check logfile number if {$cnt1 == 3 && $cnt2 == 3} { pass "$test (log file numbers limitation)" } else { fail "$test (log file numbers ($cnt1, $cnt2))" } # check logfile size if {$scnt == $cnt1 + $cnt2 } { pass "$test (log file size limitation)" } else { fail "$test (log file size ($scnt != $cnt1 + $cnt2))" } exec kill -TERM $pid # wait for exiting... exec sleep 1 system "rm -f flightlog.out*" systemtap-2.3/testsuite/systemtap.base/flightrec2.stp000066400000000000000000000001171217430427200231640ustar00rootroot00000000000000probe timer.ms(10) { for (j = 0; j < 1000; j++) printf("1234567890\n") } systemtap-2.3/testsuite/systemtap.base/flightrec3.exp000066400000000000000000000042341217430427200231570ustar00rootroot00000000000000set test "flightrec3" if {![installtest_p]} { untested $test; return } # cleanup system "rm -f flightlog.out*" set pid 0 # check -S option with bulk(percpu file) mode catch {spawn stap -F -o flightlog.out -S 1,3 -b $srcdir/$subdir/$test.stp} expect { -timeout 240 -re {([0-9]+)\r\n} { pass "$test (-S option with bulk mode)" set pid $expect_out(1,string) exp_continue} timeout { fail "$test (timeout)"} eof { } } wait; catch {close} if {$pid == 0} { fail "$test (no pid)" return -1 } exec sleep 4 array set cpus {} set scnt 0 # wait for log files catch {exec kill -STOP $pid} exec sleep 1 catch {eval spawn stat -c \"%n %s\" [glob -nocomplain flightlog.out_cpu*]} expect { -timeout 100 -re {flightlog.out_cpu([0-9]+).[0-9]+ ([0-9]+)\r\n} { set cpuid $expect_out(1,string) set size $expect_out(2,string) if {[array get cpus $cpuid] == ""} {set cpus($cpuid) 0} incr cpus($cpuid); if {$size <= 1048576 } {incr scnt} exp_continue} timeout { fail "$test (logfile timeout)"} } wait; catch {close} catch {exec kill -CONT $pid} exec sleep 3 catch {exec kill -STOP $pid} catch {eval spawn stat -c \"%n %s\" [glob -nocomplain flightlog.out_cpu*]} expect { -timeout 100 -re {flightlog.out_cpu([0-9]+).[0-9]+ ([0-9]+)\r\n} { set cpuid $expect_out(1,string) set size $expect_out(2,string) if {[array get cpus $cpuid] == ""} {set cpus($cpuid) 0} incr cpus($cpuid); if {$size <= 1048576 } {incr scnt} exp_continue} timeout { fail "$test (logfile timeout)"} } wait; catch {close} catch {exec kill -CONT $pid} # check logfile number set cnt 0 foreach e [array names cpus] { # If we have more than 6 files per cpu, something is wrong. We # might have less than 6 files per cpu if the machine is slow. if {$cpus($e) > 6} { fail "$test (log file numbers cpu:$e, cnt:$cpus($e)))" } set cnt [expr $cnt + $cpus($e)] } # check logfile size if {$scnt == $cnt} { pass "$test (log file size limitation with bulk mode)" } else { fail "$test (log file size ($scnt != $cnt))" } catch {exec kill -TERM $pid} # wait for exiting... exec sleep 1 catch {system "rm -f flightlog.out*"} systemtap-2.3/testsuite/systemtap.base/flightrec3.stp000066400000000000000000000001511217430427200231630ustar00rootroot00000000000000probe kernel.function("update_process_times") { for (j = 0; j < 100; j++) printf("1234567890\n") } systemtap-2.3/testsuite/systemtap.base/flightrec4.exp000066400000000000000000000024431217430427200231600ustar00rootroot00000000000000set test "flightrec4" if {![installtest_p]} { untested $test; return } # Make sure we start with a clean slate. catch {exec rm -f $test.out*} # run stapio in background mode with number limit spawn stap -F -S 1,2 -o $test.out -we {probe begin {}} # check whether stap outputs stapio pid set pid 0 expect { -timeout 240 -re {([0-9]+)\r\n} { pass "$test (flight recorder option)" set pid $expect_out(1,string) exp_continue} timeout { fail "$test (timeout)" } eof { } } wait; catch {close} if {$pid == 0} { fail "$test (no pid)" return -1 } # switch file to .1 exec sleep 2 exec kill -USR2 $pid # check output file if {[catch {exec rm $test.out.0}]} { fail "$test (no output file)" return -1 } else { pass "$test (output file)" } # switch file to .2 exec sleep 2 exec kill -USR2 $pid # switch file to .3 (this time, .1 file should be deleted) exec sleep 2 exec kill -USR2 $pid # check switched output file exec sleep 2 if {[catch {exec rm $test.out.1}]} { pass "$test (old output file is removed)" } else { fail "$test (failed to remove output file)" return -1 } exec kill -TERM $pid # check switched output file if {[catch {exec rm $test.out.2 $test.out.3}]} { fail "$test (failed to switch output file)" return -1 } else { pass "$test (switch output file)" } systemtap-2.3/testsuite/systemtap.base/flightrec5.exp000066400000000000000000000030321217430427200231540ustar00rootroot00000000000000set test "flightrec5" if {![installtest_p]} { untested $test; return } # Make sure we start with a clean slate. catch {exec rm -f $test.out*} # run stapio in background mode with number limit and bulk mode spawn stap -F -S 1,2 -b -o $test.out -we {probe begin {}} # check whether stap outputs stapio pid set pid 0 expect { -timeout 240 -re {([0-9]+)\r\n} { pass "$test (flight recorder option)" set pid $expect_out(1,string) exp_continue} timeout { fail "$test (timeout)" } eof { } } wait; catch {close} if {$pid == 0} { fail "$test (no pid)" return -1 } # switch file to .1 exec sleep 2 exec kill -USR2 $pid # check output file exec sleep 2 eval set outfile {[glob -nocomplain $test.out_cpu*.0]} if {$outfile == ""} { fail "$test (no output file) $outfile" exec kill -TERM $pid return -1 } else { pass "$test (output file)" } eval exec rm $outfile # switch file to .2 exec kill -USR2 $pid # switch file to .3 (this time, .1 file should be deleted) exec sleep 2 exec kill -USR2 $pid exec sleep 2 exec kill -TERM $pid # check switched output file exec sleep 2 eval set outfile {[glob -nocomplain $test.out_cpu*.1]} if {$outfile == ""} { pass "$test (old output file is removed)" } else { fail "$test (failed to remove output file) $outfile" eval exec rm $outfile return -1 } # check switched output file eval set outfile {[glob -nocomplain $test.out_cpu*.*]} if {$outfile == ""} { fail "$test (failed to switch output file)" return -1 } else { pass "$test (switch output file)" } eval exec rm $outfile systemtap-2.3/testsuite/systemtap.base/foreach_aggrsort.exp000066400000000000000000000053051217430427200244440ustar00rootroot00000000000000# test aggregate sorting set test "foreach_aggrsort" set ::result_string {sort default+ stats[1]: @count=1 @sum=-1 @min=-1 @max=-1 @avg=-1 stats[2]: @count=2 @sum=7 @min=1 @max=6 @avg=3 stats[3]: @count=3 @sum=12 @min=3 @max=5 @avg=4 stats[4]: @count=4 @sum=1 @min=0 @max=1 @avg=0 sort default- stats[4]: @count=4 @sum=1 @min=0 @max=1 @avg=0 stats[3]: @count=3 @sum=12 @min=3 @max=5 @avg=4 stats[2]: @count=2 @sum=7 @min=1 @max=6 @avg=3 stats[1]: @count=1 @sum=-1 @min=-1 @max=-1 @avg=-1 sort @count+ stats[1]: @count=1 @sum=-1 @min=-1 @max=-1 @avg=-1 stats[2]: @count=2 @sum=7 @min=1 @max=6 @avg=3 stats[3]: @count=3 @sum=12 @min=3 @max=5 @avg=4 stats[4]: @count=4 @sum=1 @min=0 @max=1 @avg=0 sort @count- stats[4]: @count=4 @sum=1 @min=0 @max=1 @avg=0 stats[3]: @count=3 @sum=12 @min=3 @max=5 @avg=4 stats[2]: @count=2 @sum=7 @min=1 @max=6 @avg=3 stats[1]: @count=1 @sum=-1 @min=-1 @max=-1 @avg=-1 sort @sum+ stats[1]: @count=1 @sum=-1 @min=-1 @max=-1 @avg=-1 stats[4]: @count=4 @sum=1 @min=0 @max=1 @avg=0 stats[2]: @count=2 @sum=7 @min=1 @max=6 @avg=3 stats[3]: @count=3 @sum=12 @min=3 @max=5 @avg=4 sort @sum- stats[3]: @count=3 @sum=12 @min=3 @max=5 @avg=4 stats[2]: @count=2 @sum=7 @min=1 @max=6 @avg=3 stats[4]: @count=4 @sum=1 @min=0 @max=1 @avg=0 stats[1]: @count=1 @sum=-1 @min=-1 @max=-1 @avg=-1 sort @avg+ stats[1]: @count=1 @sum=-1 @min=-1 @max=-1 @avg=-1 stats[4]: @count=4 @sum=1 @min=0 @max=1 @avg=0 stats[2]: @count=2 @sum=7 @min=1 @max=6 @avg=3 stats[3]: @count=3 @sum=12 @min=3 @max=5 @avg=4 sort @avg- stats[3]: @count=3 @sum=12 @min=3 @max=5 @avg=4 stats[2]: @count=2 @sum=7 @min=1 @max=6 @avg=3 stats[4]: @count=4 @sum=1 @min=0 @max=1 @avg=0 stats[1]: @count=1 @sum=-1 @min=-1 @max=-1 @avg=-1 sort @min+ stats[1]: @count=1 @sum=-1 @min=-1 @max=-1 @avg=-1 stats[4]: @count=4 @sum=1 @min=0 @max=1 @avg=0 stats[2]: @count=2 @sum=7 @min=1 @max=6 @avg=3 stats[3]: @count=3 @sum=12 @min=3 @max=5 @avg=4 sort @min- stats[3]: @count=3 @sum=12 @min=3 @max=5 @avg=4 stats[2]: @count=2 @sum=7 @min=1 @max=6 @avg=3 stats[4]: @count=4 @sum=1 @min=0 @max=1 @avg=0 stats[1]: @count=1 @sum=-1 @min=-1 @max=-1 @avg=-1 sort @max+ stats[1]: @count=1 @sum=-1 @min=-1 @max=-1 @avg=-1 stats[4]: @count=4 @sum=1 @min=0 @max=1 @avg=0 stats[3]: @count=3 @sum=12 @min=3 @max=5 @avg=4 stats[2]: @count=2 @sum=7 @min=1 @max=6 @avg=3 sort @max- stats[2]: @count=2 @sum=7 @min=1 @max=6 @avg=3 stats[3]: @count=3 @sum=12 @min=3 @max=5 @avg=4 stats[4]: @count=4 @sum=1 @min=0 @max=1 @avg=0 stats[1]: @count=1 @sum=-1 @min=-1 @max=-1 @avg=-1 } foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run_exact "${test}_${runtime}" $srcdir/$subdir/$test.stp \ --runtime=$runtime } else { stap_run_exact $test $srcdir/$subdir/$test.stp } } systemtap-2.3/testsuite/systemtap.base/foreach_aggrsort.stp000066400000000000000000000023431217430427200244550ustar00rootroot00000000000000global stats @define sortloop(x) %( printf("stats[%d]: @count=%d @sum=%d @min=%d @max=%d @avg=%d\n", @x, @count(stats[@x]), @sum(stats[@x]), @min(stats[@x]), @max(stats[@x]), @avg(stats[@x])) %) probe begin { stats[1] <<< -1; stats[2] <<< 1; stats[2] <<< 6; stats[3] <<< 3; stats[3] <<< 4; stats[3] <<< 5; stats[4] <<< 0; stats[4] <<< 0; stats[4] <<< 0; stats[4] <<< 1; println("sort default+") foreach(x in stats+) @sortloop(x) println("sort default-") foreach(x in stats-) @sortloop(x) println("sort @count+") foreach(x in stats @count+) @sortloop(x) println("sort @count-") foreach(x in stats @count-) @sortloop(x) println("sort @sum+") foreach(x in stats @sum+) @sortloop(x) println("sort @sum-") foreach(x in stats @sum-) @sortloop(x) println("sort @avg+") foreach(x in stats @avg+) @sortloop(x) println("sort @avg-") foreach(x in stats @avg-) @sortloop(x) println("sort @min+") foreach(x in stats @min+) @sortloop(x) println("sort @min-") foreach(x in stats @min-) @sortloop(x) println("sort @max+") foreach(x in stats @max+) @sortloop(x) println("sort @max-") foreach(x in stats @max-) @sortloop(x) exit() } systemtap-2.3/testsuite/systemtap.base/foreach_value.exp000066400000000000000000000012601217430427200237240ustar00rootroot00000000000000# test values assigned in foreach iteration set test "foreach_value" set ::result_string {longs[9] = 324 longs[8] = 192 longs[7] = 98 longs[6] = 36 longs[5] = 0 longs[1] = -4 longs[2] = -12 longs[4] = -16 longs[3] = -18 strings[5] = five strings[4] = four strings[1] = one strings[3] = three strings[2] = two 2 strings in bucket 66 3 strings in bucket 67 2 strings in [f] bucket 67 1 strings in [o] bucket 66 1 strings in [t] bucket 66 1 strings in [t] bucket 67 } foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run_exact "${test}_${runtime}" $srcdir/$subdir/$test.stp \ --runtime=$runtime } else { stap_run_exact $test $srcdir/$subdir/$test.stp } } systemtap-2.3/testsuite/systemtap.base/foreach_value.stp000066400000000000000000000013121217430427200237340ustar00rootroot00000000000000global longs global strings global stat global stats probe begin { for (i=1; i<10; ++i) longs[i] = i*i*(i-5) foreach (n- = i in longs) printf("longs[%d] = %d\n", i, n) strings[1] = "one" strings[2] = "two" strings[3] = "three" strings[4] = "four" strings[5] = "five" foreach (s+ = i in strings) printf("strings[%d] = %s\n", i, s) foreach (s = i in strings) stat <<< strlen(s) foreach (n = i in @hist_log(stat)) if (n) printf("%d strings in bucket %d\n", n, i) foreach (s = i in strings) stats[stringat(s,0)] <<< strlen(s) foreach (c+ in stats) foreach (n = i in @hist_log(stats[c])) if (n) printf("%d strings in [%c] bucket %d\n", n, c, i) exit() } systemtap-2.3/testsuite/systemtap.base/func_alias.c000066400000000000000000000001241217430427200226510ustar00rootroot00000000000000int main() { return 0; } extern int (*func_alias) __attribute__ ((alias ("main"))); systemtap-2.3/testsuite/systemtap.base/func_alias.exp000066400000000000000000000031441217430427200232300ustar00rootroot00000000000000set test "func_alias" if {![utrace_p]} { untested $test; return } proc run {subtest pp} { global test verbose -log "subtest $subtest" verbose -log "Running stap -l $pp" set match 0 spawn stap -l $pp expect { timeout { fail "$subtest (timeout)" } -re "never" { untested $subtest } -re "main@.*$test\\.c" { if {$match == 0} { pass $subtest; incr match } exp_continue } eof { if {$match == 0} { fail $subtest } } } wait } proc run_one_test {flags bits} { global test srcdir subdir verbose -log "testing $bits-bit $test" set source "$srcdir/$subdir/$test.c" set target "[pwd]/$test.x$bits" set flags "additional_flags=-g $flags" set res [target_compile $source $target executable $flags] if { $res != "" } { verbose -log "$target failed: $res" untested "$bits-bit $test" return } run "$bits-bit $test direct" "process(\"$target\").function(\"$test\")" run "$bits-bit $test wildcard" "process(\"$target\").function(\"$test*\")" exec rm -f $target } set do_32_bit_pass 1 set do_64_bit_pass 0 set flags32 "" set flags64 "" switch -regexp $::tcl_platform(machine) { ^ia64$ { set do_32_bit_pass 0 set do_64_bit_pass 1 } ^(x86_64|ppc64)$ { set do_64_bit_pass 1 set flags32 "additional_flags=-m32" set flags64 "additional_flags=-m64" } ^s390x$ { set do_64_bit_pass 1 set flags32 "additional_flags=-m31" set flags64 "additional_flags=-m64" } } if {$do_64_bit_pass} { run_one_test $flags64 64 } if {$do_32_bit_pass} { run_one_test $flags32 32 } systemtap-2.3/testsuite/systemtap.base/global_end.exp000066400000000000000000000045401217430427200232130ustar00rootroot00000000000000# test end probe creation and display of written and unread global variables set test "global_end" if {![installtest_p]} {untested $test; return} foreach runtime [get_runtime_list] { set test "global_end" if {$runtime != ""} { set test "${test}_${runtime}" spawn stap $srcdir/$subdir/global_end.stp --runtime=$runtime } else { spawn stap $srcdir/$subdir/global_end.stp } set ok 0 expect { -timeout 180 -re {one,0x1.*one,0x2.*two,0x1.*two,0x2} { incr ok; exp_continue } -re {epsilon."one", 1. count:4 min:1 max:4 sum:10 avg:2} { incr ok; exp_continue } -re {epsilon."two", 2. count:4 min:10 max:40 sum:100 avg:25} { incr ok; exp_continue } -re {alpha."two".2.=0x4} { incr ok; exp_continue } -re {alpha."two".1.=0x3} { incr ok; exp_continue } -re {alpha."one".2.=0x2} { incr ok; exp_continue } -re {alpha."one".1.=0x1} { incr ok; exp_continue } -re {gamma="abcdefghijklmnopqrstuvwxyz"} { incr ok; exp_continue } -re {iota."two".="twelve"} { incr ok; exp_continue } -re {iota."one".="eleven"} { incr ok; exp_continue } -re {phi @count=4 @min=1 @max=4 @sum=10 @avg=2} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$runtime != ""} { set test "${test}_${runtime}" spawn stap $srcdir/$subdir/global_end2.stp --runtime=$runtime } else { spawn stap $srcdir/$subdir/global_end2.stp } # above should not do any tapset global variable display so # ok should only change by 1 expect { -timeout 180 -re {Avg time = [1-9]} { incr ok; exp_continue } } catch {close}; catch {wait} if {$ok == 12} { pass "$test ($ok)" } { fail "$test ($ok)" } # test PR6954 set test "global_end_var" if {$runtime != ""} { set test "${test}_${runtime}" spawn stap $srcdir/$subdir/global_end_var.stp --runtime=$runtime } else { spawn stap $srcdir/$subdir/global_end_var.stp } set ok 0 expect { -timeout 180 -re {gs0_save=0x29} { incr ok; exp_continue } -re {gs2=0x4} { incr ok; exp_continue } -re {gs3=0x4} { incr ok; exp_continue } -re {gs4=0x5} { incr ok; exp_continue } -re {ga1."foo".=0x2} { incr ok; exp_continue } -re {ga2."foo".=0x1} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 6} { pass "$test ($ok)" } { fail "$test ($ok)" } } systemtap-2.3/testsuite/systemtap.base/global_end.stp000066400000000000000000000016221217430427200232230ustar00rootroot00000000000000global alpha, beta, gamma, iota, epsilon, phi probe begin { gamma = "abcdefghijklmnopqrstuvwxyz" iota["one"] = "eleven" iota["two"] = "twelve" alpha["one",1] = 1 alpha["one",2] = 2 alpha["two",1] = 3 alpha["two",2] = 4 beta["one",1] = 1 beta["one",2] = 2 beta["two",1] = 3 beta["two",2] = 4 phi <<< 1 phi <<< 2 phi <<< 3 phi <<< 4 epsilon["one",1] <<< 1 epsilon["one",1] <<< 2 epsilon["one",1] <<< 3 epsilon["one",1] <<< 4 epsilon["two",2] <<< 10 epsilon["two",2] <<< 20 epsilon["two",2] <<< 30 epsilon["two",2] <<< 40 } probe timer.ms(100) { exit () } probe end { foreach ([i,j] in beta) printf("[%#s,%#x]=%#x ", i, j, beta[i,j]) print("\n") foreach([i,j+] in epsilon) printf("epsilon[\"%s\", %d] count:%d min:%d max:%d sum:%d avg:%d\n", i, j, @count(epsilon[i,j]), @min(epsilon[i,j]), @max(epsilon[i,j]), @sum(epsilon[i,j]), @avg(epsilon[i,j])) exit() } systemtap-2.3/testsuite/systemtap.base/global_end2.stp000066400000000000000000000002371217430427200233060ustar00rootroot00000000000000probe begin { qsq_start("test") qs_wait("test") qs_run("test") qs_done("test") log(sprintf("Avg time = %d", qsq_service_time("test", 1))) exit() } systemtap-2.3/testsuite/systemtap.base/global_end_var.stp000066400000000000000000000013171217430427200240740ustar00rootroot00000000000000global gs0_save global gs0 = 41 global gs1 = 1 global gs2 = 2 global gs3 = 3 global gs4 = 4 global gs5 = 5 global gs6 = 6 global gs7 = 7 global gs8 = 8 global gs9 = 9 global gs10 = 10 global gs11 = 11 global ga1 global ga2 global gtemp function fna(a:long) {return a} probe begin(-9223372036854775808) { gs0_save = gs0 } probe begin { temp = 2; gs1 = gs1 + 2; gs2 += 2; ++ gs3; gs4 ++; gs5 ++; gs6 = gs6 + temp; printf ("gs7=%d ",fna(gs7)) gtemp = (gs8++) & (gtemp = (gs9++)) ls0 = gtemp + gs10++; println(gs11++) ga1 ["foo"] += 2; ga2 ["foo"] ++; ls1 = ls1 + 2; ls2 += ls2; ls3 = 0; printf ("ls0=%d ls1=%d ",ls0, ls1); ++ ls3; ls4 ++; ls5 = gs5; printf ("ls5=%d\n",ls5); exit() } systemtap-2.3/testsuite/systemtap.base/global_init.exp000066400000000000000000000005071217430427200234070ustar00rootroot00000000000000# Check that global variables are initialized before all begin probes set test "global_init" foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string \ --runtime=$runtime } else { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string } } systemtap-2.3/testsuite/systemtap.base/global_init.stp000066400000000000000000000012501217430427200234150ustar00rootroot00000000000000/* * global_init.stp * * Check that global variables are initialized before all begin probes */ probe begin { println("systemtap starting probe") } probe end { println("systemtap ending probe") } global gnum = 42 global gstr = "foobar" global gnum_saved global gstr_saved probe begin(-9223372036854775808) { gnum_saved = gnum gstr_saved = gstr } probe end { if (gnum_saved == 42) println("systemtap test success") else printf("systemtap test failure - gnum_saved:%d != 42\n", gnum_saved) if (gstr_saved == "foobar") println("systemtap test success") else printf("systemtap test failure - gstr_saved:%s != foobar\n", gstr_saved) } systemtap-2.3/testsuite/systemtap.base/global_opt.exp000066400000000000000000000013241217430427200232440ustar00rootroot00000000000000# Check stap global variable option (-G) set test "global_opt" if {![installtest_p]} { untested $test return } set script "global var1=9 ; probe begin { if (var1 == 29) println(\"systemtap test success\") else println(\"systemtap test failure\") ; exit() }" foreach runtime [get_runtime_list] { set test "global_opt" if {$runtime != ""} { set test "${test}_${runtime}" spawn stap -G var1=29 -e $script --runtime=$runtime } else { spawn stap -G var1=29 -e $script } expect { -timeout 60 "systemtap test success" { pass $test } "systemtap test failure" { fail $test } timeout {fail "$test: unexpected timeout"} eof {fail "$test: unexpected EOF"} } catch {close}; catch {wait} } systemtap-2.3/testsuite/systemtap.base/global_stat.exp000066400000000000000000000010721217430427200234150ustar00rootroot00000000000000set test "global_stat" if {![installtest_p]} { untested $test return } foreach runtime [get_runtime_list] { set test "global_stat" if {$runtime != ""} { set test "${test}_${runtime}" spawn stap --runtime=$runtime \ -e {global var; probe never {var<<<1} probe begin {exit()}} } else { spawn stap -e {global var; probe never {var<<<1} probe begin {exit()}} } expect { -timeout 60 "var @count=0x0" { pass $test } timeout {fail "$test: unexpected timeout"} eof {fail "$test: unexpected EOF"} } catch {close}; catch {wait} } systemtap-2.3/testsuite/systemtap.base/global_var.exp000066400000000000000000000053431217430427200232370ustar00rootroot00000000000000set test "global_var" set testpath "$srcdir/$subdir" # Check each "global" value picks up the right one. # See GCC PR51410 and Systemtap PR10622 set ::result_string {main value@main: 42 getdistance value: 60 getdistance value@main: 42 getdistance value@speed: 6 getdistance value@distance: 60 getspeed value: 6 getspeed value@main: 42 getspeed value@speed: 6 getspeed value@distance: 60 compare value: 42 compare value@main: 42 compare value@speed: 6 compare value@distance: 60 main return value@main: 42} # Only run on make installcheck and uprobes present. if {! [installtest_p]} { untested "$test"; return } proc dyninst_kfails {index} { # The dyninst runtime isn't multi-arch, it only works on the # native architecture. PR14490. if {! [all_compile_flag_native_p $index]} { setup_kfail 14490 "*-*-*" } } set compiled_objs {} for {set i 0} {$i < [all_compile_flags]} {incr i} { set extra_flag [all_compile_flag $i] set extra_name [all_compile_flag_name $i] # Compile our object files separately, then combine with main. set oname "${test}_speed" set res [target_compile ${testpath}/${oname}.c ${oname}_${extra_name}.o object "$extra_flag additional_flags=-g"] if { $res != "" } { verbose "target_compile for ${oname} failed: $res" 2 fail "unable to compile ${oname} $extra_name" continue } lappend compiled_objs ${oname}_${extra_name}.o set oname2 "${test}_distance" set res [target_compile ${testpath}/${oname2}.c ${oname2}_${extra_name}.o object "$extra_flag additional_flags=-g"] if { $res != "" } { verbose "target_compile for ${oname2} failed: $res" 2 fail "unable to compile ${oname2} $extra_name" continue } lappend compiled_objs ${oname2}_${extra_name}.o set mname "${test}_main" set res [target_compile "${testpath}/${mname}.c ${oname}_${extra_name}.o ${oname2}_${extra_name}.o" ${mname}_${extra_name} executable "$extra_flag additional_flags=-g"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile ${mname} $extra_name" continue } lappend compiled_objs ${mname}_${extra_name} foreach runtime [get_runtime_list] { if {$runtime != ""} { if {[info procs ${runtime}_kfails] ne ""} { ${runtime}_kfails $i } stap_run3 $test-$extra_name-$runtime $srcdir/$subdir/$test.stp \ -c ./${mname}_${extra_name} --runtime=$runtime } elseif {[uretprobes_p]} { stap_run3 $test-$extra_name $srcdir/$subdir/$test.stp \ -c ./${mname}_${extra_name} } else { untested "$test-$extra_name" } } } # Cleanup. Note we remove objects individually to avoid the command # line getting too long. if { $verbose == 0 && [llength compiled_objs] > 0 } { foreach obj $compiled_objs { catch { exec rm -f $obj } } } systemtap-2.3/testsuite/systemtap.base/global_var.stp000066400000000000000000000022411217430427200232430ustar00rootroot00000000000000probe process.function("getdistance") { printf("getdistance value: %d\n", $value); printf("getdistance value@main: %d\n", @var("value@global_var_main.c")); printf("getdistance value@speed: %d\n", @var("value@global_var_speed.c")); printf("getdistance value@distance: %d\n", @var("value@global_var_distance.c")); } probe process.function("getspeed") { printf("getspeed value: %d\n", $value); printf("getspeed value@main: %d\n", @var("value@global_var_main.c")); printf("getspeed value@speed: %d\n", @var("value@global_var_speed.c")); printf("getspeed value@distance: %d\n", @var("value@global_var_distance.c")); } probe process.function("compare_value") { printf("compare value: %d\n", $value); printf("compare value@main: %d\n", @var("value@global_var_main.c")); printf("compare value@speed: %d\n", @var("value@global_var_speed.c")); printf("compare value@distance: %d\n", @var("value@global_var_distance.c")); } probe process.function("main") { // Global, not local. printf("main value@main: %d\n", @var("value@global_var_main.c")); } probe process.function("main").return { printf("main return value@main: %d\n", @var("value@global_var_main.c")); } systemtap-2.3/testsuite/systemtap.base/global_var_distance.c000066400000000000000000000001361217430427200245320ustar00rootroot00000000000000static int value; void setdistance(int v) { value = v; } int getdistance() { return value; } systemtap-2.3/testsuite/systemtap.base/global_var_kernel.exp000066400000000000000000000007211217430427200245720ustar00rootroot00000000000000set test "global_var_kernel" set testpath "$srcdir/$subdir" # Check the righ "kernel/time.c" is picked up (both in the syscall probe # context and the stap function context. set output_string "sys_tz = {.tz_minuteswest=-?\\d+, .tz_dsttime=\\d+}\r\nf: {.tz_minuteswest=-?\\d+, .tz_dsttime=\\d+}" # Only run on make installcheck if {! [installtest_p]} { untested "$test"; return } stap_run ${test} no_load $output_string ${testpath}/${test}.stp -c {cat /dev/null} systemtap-2.3/testsuite/systemtap.base/global_var_kernel.stp000066400000000000000000000004371217430427200246100ustar00rootroot00000000000000# Test the correct kernel/time.c CU is selected. function f() { printf("f: %s\n", @var("sys_tz@kernel/time.c")$$); } probe syscall.open { log("systemtap starting probe"); log("systemtap ending probe"); printf("sys_tz = %s\n", @var("sys_tz@kernel/time.c")$$); f() exit(); } systemtap-2.3/testsuite/systemtap.base/global_var_main.c000066400000000000000000000006251217430427200236670ustar00rootroot00000000000000void setspeed(int v); int getspeed(); void setdistance(int v); int getdistance(); int value = 42; int compare_value (int v) { asm(""); return v - value; } int calculate_value () { asm(""); return getdistance () / getspeed (); } int main (int argc, char **argv) { int value; setspeed (6); setdistance (60); value = calculate_value (); return compare_value (value) == 0 ? -1 : 0; } systemtap-2.3/testsuite/systemtap.base/global_var_speed.c000066400000000000000000000001301217430427200240320ustar00rootroot00000000000000static int value; void setspeed(int v) { value = v; } int getspeed() { return value; } systemtap-2.3/testsuite/systemtap.base/global_vars.exp000066400000000000000000000004751217430427200234230ustar00rootroot00000000000000# Check that global variables terminated with a ; work fine set test "global_vars" foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string \ --runtime=$runtime } else { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string } } systemtap-2.3/testsuite/systemtap.base/global_vars.stp000066400000000000000000000022451217430427200234320ustar00rootroot00000000000000/* * global_vars.stp * * Check that global variables with a ; termination work fine */ probe begin { println("systemtap starting probe") } probe end { println("systemtap ending probe") } global a; global c, d; global g = 42; global e[1], f; global gstr = "foobar"; global gstr_saved; probe begin(-9223372036854775808) { c = g d = c + g a = d f = c e[0] = "a"; gstr_saved = gstr } probe end { if (c == 42) println("systemtap test success") else printf("systemtap test failure - c:%d != 42\n", c) if (d == (c + g)) println("systemtap test success") else printf("systemtap test failure - d:%d != %d\n", d, (c+g)) if (a == d) println("systemtap test success") else printf("systemtap test failure - a:%d != %d\n", a, d) if (f == c) println("systemtap test success") else printf("systemtap test failure - f:%d != %d\n", f, c) if (e[0] == "a") println("systemtap test success") else printf("systemtap test failure - e:%s != a\n", e[0]) if (gstr_saved == "foobar") println("systemtap test success") else printf("systemtap test failure - gstr_saved:%s != foobar\n", gstr_saved) } systemtap-2.3/testsuite/systemtap.base/gtod.c000066400000000000000000000011521217430427200215040ustar00rootroot00000000000000#include #include #include #include int main (int argc, char *argv[]) { int i; struct timeval tv[100][2]; int us = 0; if (argc == 2) us = atoi(argv[1]); for (i=0; i<100; i++) { gettimeofday(&tv[i][0], NULL); setsid(); gettimeofday(&tv[i][1], NULL); if (us) usleep(us); } for (i=0; i<100; i++) { // change last 4 chars for correctly sorting even if the // time stamps are completely same. printf("%8ld%06ld :%02d appl\n", tv[i][0].tv_sec, tv[i][0].tv_usec, i); printf("%8ld%06ld :%02d prog\n", tv[i][1].tv_sec, tv[i][1].tv_usec, i); } return 0; } systemtap-2.3/testsuite/systemtap.base/gtod.exp000066400000000000000000000053261217430427200220650ustar00rootroot00000000000000# test for checking monotonic timer (PR3916) set test "gtod" if {![installtest_p]} { untested $test; continue } set wd [pwd] set filename "$srcdir/$subdir/gtod.c" target_compile $filename $wd/gtod executable "" # Notice the state machine when checking output. We're looking for # lines in the following format: # # 1336494634008794 :00 appl # 1336494634008971 :00 kern # 1336494634009194 :00 prog # 1336494634009196 :01 appl # 1336494634009199 :01 kern # 1336494634009203 :01 prog # ... # # The lines must be in the order 'appl', 'kern', and 'prog'. The # second number, the count, must match on each of the 3 lines. # # The state machine should hopefully give a better ok count than the # old multi-line matching (which once it got out of sync could never # seem to get back into sync). # non interval (check timer drift in short range) set state -1 set count "XX" spawn $srcdir/$subdir/gtod.sh $srcdir/$subdir/gtod.stp $wd/gtod set ok 0 expect { -timeout 120 -re {^[0-9]+ \:([0-9]+) appl\r\n} { set state 0 set count $expect_out(1,string) exp_continue } -re {^[0-9]+ \:([0-9]+) kern\r\n} { if {$state == 0 && $count == $expect_out(1,string)} { set state 1 } else { set state -1 } exp_continue } -re {^[0-9]+ \:([0-9]+) prog\r\n} { if {$state == 1 && $count == $expect_out(1,string)} { incr ok } set state -1 exp_continue } timeout { fail "$test (timeout)" } eof { } } wait #10ms interval (check timer drift in middle range) set state -1 set count "XX" spawn $srcdir/$subdir/gtod.sh $srcdir/$subdir/gtod.stp $wd/gtod 10000 expect { -timeout 120 -re {^[0-9]+ \:([0-9]+) appl\r\n} { set state 0 set count $expect_out(1,string) exp_continue } -re {^[0-9]+ \:([0-9]+) kern\r\n} { if {$state == 0 && $count == $expect_out(1,string)} { set state 1 } else { set state -1 } exp_continue } -re {^[0-9]+ \:([0-9]+) prog\r\n} { if {$state == 1 && $count == $expect_out(1,string)} { incr ok } set state -1 exp_continue } timeout { fail "$test (timeout)" } eof { } } wait #100ms interval (calm down processors and CPU freq might be changed) set state -1 set count "XX" spawn $srcdir/$subdir/gtod.sh $srcdir/$subdir/gtod.stp $wd/gtod 100000 expect { -timeout 120 -re {^[0-9]+ \:([0-9]+) appl\r\n} { set state 0 set count $expect_out(1,string) exp_continue } -re {^[0-9]+ \:([0-9]+) kern\r\n} { if {$state == 0 && $count == $expect_out(1,string)} { set state 1 } else { set state -1 } exp_continue } -re {^[0-9]+ \:([0-9]+) prog\r\n} { if {$state == 1 && $count == $expect_out(1,string)} { incr ok } set state -1 exp_continue } timeout { fail "$test (timeout)" } eof { } } wait exec rm -f $wd/gtod if {$ok == 300} { pass "$test ($ok)" } { fail "$test ($ok)" } systemtap-2.3/testsuite/systemtap.base/gtod.sh000077500000000000000000000000461217430427200217000ustar00rootroot00000000000000#!/bin/sh stap $1 -c "$2 $3" | sort systemtap-2.3/testsuite/systemtap.base/gtod.stp000066400000000000000000000002161217430427200220700ustar00rootroot00000000000000global count = 0 probe syscall.setsid { if (pid() == target()) { printf("%014d :%02d kern\n", gettimeofday_us(), count); count ++; } } systemtap-2.3/testsuite/systemtap.base/hash_add_buildid.exp000066400000000000000000000061711217430427200243560ustar00rootroot00000000000000# hash_add_buildid.exp set test "hash_add_buildid" if {![uprobes_p]} { untested $test; return } # Since we need a clean cache directory, we'll use a temporary # systemtap directory and cache (add user name so make check and # sudo make installcheck don't clobber each others) set exe hash_add_buildid set at_least_one_run 0 set passed 0 set local_systemtap_dir [exec pwd]/.cache_test-[exec whoami] exec /bin/rm -rf $local_systemtap_dir exec /bin/mkdir $local_systemtap_dir if [info exists env(SYSTEMTAP_DIR)] { set old_systemtap_dir $env(SYSTEMTAP_DIR) } set env(SYSTEMTAP_DIR) $local_systemtap_dir # Set up the script we'll use. set basic_script {"probe process(\"hash_add_buildid\").function(\"main\") { println(1) }" } # Force 64-bit (when necessary) to be sure of what we're testing. switch -regexp $::tcl_platform(machine) { {^i\d86$} { set arches [list "-default"] } {^x86_64$} { set arches [list "-m64" "-m32" "ia64" "ppc" "s390"]} default { unsupported "$test"; return } } foreach arch $arches { set test_flags "additional_flags=-g" if {$arch != "-default"} { set test_flags "$test_flags additional_flags=$arch" } # Compile hash_add_buildid1.c and change the timestamp # of the binary exec cp $srcdir/$subdir/hash_add_buildid1.c $local_systemtap_dir/hash_add_buildid.c set res [target_compile $local_systemtap_dir/hash_add_buildid.c $exe executable "$test_flags"] if { $res != "" } { continue } # Check that the build ID exists on this system set cmd [concat {/usr/bin/eu-readelf -n hash_add_buildid}] eval spawn $cmd expect { -timeout 180 -re {^[^\r\n]*GNU_BUILD_ID[^\r\n]*\r\n} { set passed 1 exp_continue } -re {^[^\r\n]*\r\n} { exp_continue } timeout { set passed 0 } } catch { close }; catch { wait } if {$passed == 0} { continue } # Change the timestamp to a known value file mtime $exe 970399800 file stat $exe stat1 # The 1st compilation of a script won't be cached, # the 2nd should not be cached either. cache_compile RUN1-($arch) [F_UNCACHED_COMPILE] $basic_script # Recompile the test binary using hash_add_buildid2.c # and change the timestamp to the same as the previous one. exec cp $srcdir/$subdir/hash_add_buildid2.c $local_systemtap_dir/hash_add_buildid.c set res [target_compile $local_systemtap_dir/hash_add_buildid.c $exe executable "$test_flags"] if { $res != "" } { continue } #Change the timestamp to the same as the previous one. file mtime $exe 970399800 file stat $exe stat2 # This one should also not be cached. cache_compile RUN2-($arch) [F_UNCACHED_COMPILE] $basic_script set at_least_one_run 1 if {$stat1(size)!=$stat2(size)} { fail "$exe.c file sizes are not the same" } if {$stat1(mtime) != $stat2(mtime)} { fail "$exe.c files don't have the same timestamp" } } if {$passed == 0} { untested "$exe no build id available" } elseif {$at_least_one_run == 0 } { fail "$exe arch not supported" } # Cleanup. exec /bin/rm -rf $local_systemtap_dir if [info exists old_systemtap_dir] { set env(SYSTEMTAP_DIR) $old_systemtap_dir } else { unset env(SYSTEMTAP_DIR) } systemtap-2.3/testsuite/systemtap.base/hash_add_buildid1.c000066400000000000000000000001071217430427200240560ustar00rootroot00000000000000#include int main() { printf("hello world\n"); return 0; } systemtap-2.3/testsuite/systemtap.base/hash_add_buildid2.c000066400000000000000000000001071217430427200240570ustar00rootroot00000000000000#include int main() { printf("world hello\n"); return 0; } systemtap-2.3/testsuite/systemtap.base/if.exp000066400000000000000000000005761217430427200215300ustar00rootroot00000000000000# Simple function to test that systemtap can generate a kernel module that # instruments a function, install it, and get some output. set test "if" foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string \ --runtime=$runtime } else { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string } } systemtap-2.3/testsuite/systemtap.base/if.stp000066400000000000000000000005471217430427200215400ustar00rootroot00000000000000/* * if.stp * * Check the systemtap if statement works */ probe begin { println("systemtap starting probe") } probe end { println("systemtap ending probe") if (1) { println("systemtap test success"); } else { println("systemtap test failure"); } if (0) { println("systemtap test failure"); } else { println("systemtap test success"); } } systemtap-2.3/testsuite/systemtap.base/implicitptr.c000066400000000000000000000015761217430427200231210ustar00rootroot00000000000000#include #define MARK(name) STAP_PROBE(implicitptr, name) int z; static int foo (int i) { int *j = &i; int **k = &j; int ***l = &k; l1: MARK (foo_l1); z++; /* side effect helps the probe placement hit right */ i++; return i; } struct S { int *x, y; }; int u[6]; static inline int add (struct S *a, struct S *b, int c) { *a->x += *b->x; a->y += b->y; l1: MARK (add_l1); u[c + 0]++; a = (struct S *) 0; u[c + 1]++; a = b; l2: MARK (add_l2); u[c + 2]++; return *a->x + *b->x + a->y + b->y; } static int bar (int i) { int j = i; int k; struct S p[2] = { { &i, i * 2 }, { &j, j * 2 } }; l1: MARK (bar_l1); k = add (&p[0], &p[1], 0); l2: MARK (bar_l2); p[0].x = &j; p[1].x = &i; k += add (&p[0], &p[1], 3); l3: MARK (bar_l3); return i + j + k; } int x = 22; int main (void) { x = foo (x); x = bar (x); return 0; } systemtap-2.3/testsuite/systemtap.base/implicitptr.exp000066400000000000000000000050111217430427200234570ustar00rootroot00000000000000set test "implicitptr" set ::result_string {foo: 22 22 22 22 changed foo (99): 99 99 99 99 p = { { &100, 200 }, { &100, 200 } } *a->x=200, a->y=400, *b->x=100, b->y=200 *a->x=100, a->y=200, *b->x=100, b->y=200 p = { { &200, 400 }, { &100, 200 } } *a->x=300, a->y=600, *b->x=200, b->y=200 *a->x=200, a->y=200, *b->x=200, b->y=200 p = { { &300, 600 }, { &200, 200 } }} set listspec "process(\"$test.exe\").statement(\"foo@*:7\")" proc exe_uses_implicit_ptr {exe} { if {[catch {exec readelf --debug-dump=info,loc $exe | \ egrep -q {implicit_pointer| f2 .*User defined location op}} \ results]} { verbose -log "exe_uses_implicit_ptr caught: $results" return 0 } else { verbose -log "exe_uses_implicit_ptr ran: {$results}" if {$results == ""} { return 1 } else { return 0 } } } for {set i 0} {$i < [all_compile_flags]} {incr i} { set extra_flag [all_compile_flag $i] set extra_name [all_compile_flag_name $i] set test_flags "additional_flags=-g $extra_flag" set test_flags "$test_flags [sdt_includes]" set res [target_compile $srcdir/$subdir/$test.c $test.exe executable "$test_flags"] if {$res != ""} { verbose -log "target_compile failed: $res" 2 fail "$test.c compile $extra_name" untested "probe listing $test-$extra_name" untested "$test-$extraname" continue } else { pass "$test.c compile $extra_name" } set listing "" catch {set listing [exec stap -L $listspec 2>@1]} verbose -log "stap -L $listspec reports: $listing" set listing [lsort [lrange [split $listing] 1 end]] if {$listing == {{$i:int}}} { set avail 0 pass "probe listing $test-$extra_name (i)" } elseif {$listing == {{$i:int} {$j:int*} {$k:int**} {$l:int***}}} { set avail 1 pass "probe listing $test-$extra_name (ijkl)" } else { verbose -log "listified: $listing" if {[exe_uses_implicit_ptr $test.exe]} { fail "probe listing $test-$extra_name" set avail -1 } else { untested "probe listing $test-$extra_name" set avail 0 } } if {$avail} { if {[installtest_p] && [uprobes_p]} { stap_run3 "$test-$extra_name" $srcdir/$subdir/$test.stp \ -g -c ./$test.exe $test.exe } else { untested "$test-$extra_name" } } elseif {[exe_uses_implicit_ptr $test.exe]} { verbose -log "$test-$extraname uses implicit_ptr but -L missed it" fail "$test-$extra_name" } else { verbose -log "$test-$extra_name did not use implicit_ptr, skipping" untested "$test-$extra_name" } catch {exec rm -f $test.exe} } systemtap-2.3/testsuite/systemtap.base/implicitptr.stp000066400000000000000000000007431217430427200235000ustar00rootroot00000000000000probe process(@1).mark("foo_*") { printf("foo: %d %d %d %d\n", $i, $j[0], $k[0][0], $l[0][0][0]); newval = 99; $i = newval; printf("changed foo (%d): %d %d %d %d\n", newval, $i, $j[0], $k[0][0], $l[0][0][0]); } probe process(@1).mark("bar_*") { printf("p = { { &%d, %d }, { &%d, %d } }\n", $p[0]->x[0], $p[0]->y, $p[1]->x[0], $p[1]->y); } probe process(@1).mark("add_*") { printf("*a->x=%d, a->y=%d, *b->x=%d, b->y=%d\n", $a->x[0], $a->y, $b->x[0], $b->y); } systemtap-2.3/testsuite/systemtap.base/inc.exp000066400000000000000000000004531217430427200216750ustar00rootroot00000000000000# Simple function to test that systemtap ++ works set test "inc" foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string \ --runtime=$runtime } else { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string } } systemtap-2.3/testsuite/systemtap.base/inc.stp000066400000000000000000000005501217430427200217050ustar00rootroot00000000000000/* * inc.stp * * Check that systemtap ++ works */ global x1 probe begin { println("systemtap starting probe") x1 = 41 } probe end { println("systemtap ending probe") x1++ if (x1 == 42) { ++x1 if (x1 != 43 ) { println("systemtap test failure") } else { println("systemtap test success") } } else println("systemtap test failure") } systemtap-2.3/testsuite/systemtap.base/inherit.cxx000066400000000000000000000005161217430427200225740ustar00rootroot00000000000000struct point { int x, y; point(int x, int y): x(x), y(y) {} }; struct A { point foo, bar; A(int i): foo(i, i + 1), bar(i + 2, i + 3) {} }; struct B : A { int foo; B(): A(1), foo(42) {} }; static B b; int main() { int sum = b.A::foo.x + b.A::foo.y + b.bar.x + b.bar.y + b.foo; return sum != 10 + 42; } systemtap-2.3/testsuite/systemtap.base/inherit.exp000066400000000000000000000025561217430427200225740ustar00rootroot00000000000000set test "inherit" set ::result_string {1 2 3 4 42 {.foo=42, .bar={...}} {.foo=42, .bar={.x=3, .y=4}}} proc dyninst_kfails {index} { # The dyninst runtime isn't multi-arch, it only works on the # native architecture. PR14490. if {! [all_compile_flag_native_p $index]} { setup_kfail 14490 "*-*-*" } } set srcfile "$srcdir/$subdir/$test.cxx" set stpfile "$srcdir/$subdir/$test.stp" for {set i 0} {$i < [all_compile_flags]} {incr i} { set extra_flag [all_compile_flag $i] set extra_name [all_compile_flag_name $i] set test_flags "compiler=g++ additional_flags=-g $extra_flag" set res [target_compile "$srcfile" $test.exe executable "$test_flags"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test-$extra_name compile" untested "$test-$extra_name" continue } else { pass "$test-$extra_name compile" } if {[installtest_p]} { foreach runtime [get_runtime_list] { if {$runtime != ""} { if {[info procs ${runtime}_kfails] ne ""} { ${runtime}_kfails $i } stap_run3 "$test-$extra_name-$runtime" -w "$stpfile" $test.exe \ -c ./$test.exe --runtime=$runtime } elseif {[uprobes_p]} { stap_run3 "$test-$extra_name" -w "$stpfile" $test.exe -c ./$test.exe } else { untested "$test-$extra_name" } } } else { untested "$test-$extra_name" } catch {exec rm -f $test.exe} } systemtap-2.3/testsuite/systemtap.base/inherit.stp000066400000000000000000000011001217430427200225660ustar00rootroot00000000000000probe process("inherit.exe").function("main") { // A::foo is masked, so @cast is necessary. println(@cast(&$b, "A")->foo->x) println(@cast(&$b, "A")->foo->y) // A::bar is not masked, so inheritance should find it. println($b->bar->x) println($b->bar->y) // B::foo masks A::foo, so should be found first. // NB: We can't treat a struct as a scalar, so this will fail if it // tries to go through A::foo. B::foo should be fine as an int. println($b->foo) // Pretty-printing should skip the masked A::foo altogether println($b$) println($b$$) } systemtap-2.3/testsuite/systemtap.base/inlinedvars.c000066400000000000000000000021111217430427200230610ustar00rootroot00000000000000static inline int m(char *name, int i, long j) { // Random syntactical block to be inlined. // Mimics what STAP_PROBE macro does a bit. do { // Dummy (volatile) counter to trick gcc into thinking we are actually // using the label. If not it will partially optimize the label away, // but still emits a somewhat bogus DW_AT_low_pc for it... volatile int c = 0; volatile __typeof__(name) p_name = name; volatile __typeof__(i) p_i = i; volatile __typeof__(j) p_j = j; // empty asm to force locals into regs. inlined_label: asm volatile ("" : "=g"(c) : "g"(p_name), "g"(p_i), "g"(p_j)); if (c != 0) goto inlined_label; } while (0); return i + 32; } static inline int call(int pi, long pj) { volatile ic = pi - 42; volatile jc = pj + 42; return m("call", ic, jc); } static inline int call2(int pi2, long pj2) { volatile ic2 = pi2 + 64; volatile jc2 = pj2 - 64; return m("call2", ic2, jc2); } int main (int argc, char **argv) { volatile int i = 64; volatile long j = 42; call(i, j); call2(i, j); m("main", i, j); return 0; } systemtap-2.3/testsuite/systemtap.base/inlinedvars.exp000066400000000000000000000025171217430427200234450ustar00rootroot00000000000000set test "inlinedvars" set ::result_string {call (22,84) call2 (128,-22) main (64,42)} proc dyninst_kfails {index} { # The dyninst runtime isn't multi-arch, it only works on the # native architecture. PR14490. if {! [all_compile_flag_native_p $index]} { setup_kfail 14490 "*-*-*" } } # Try both inlined and non-inlined compiles. for {set i 0} {$i < [all_compile_flags]} {incr i} { set extra_flag [all_compile_flag $i] set extra_name [all_compile_flag_name $i] set test_flags "additional_flags=-g $extra_flag" set res [target_compile $srcdir/$subdir/$test.c $test.exe executable "$test_flags"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test-$extra_name compile" untested "$test-$extra_name" continue } else { pass "$test-$extra_name compile" } if {[installtest_p]} { foreach runtime [get_runtime_list] { if {$runtime != ""} { if {[info procs ${runtime}_kfails] ne ""} { ${runtime}_kfails $i } stap_run3 "$test-$extra_name-$runtime" $srcdir/$subdir/$test.stp \ $test.exe -c ./$test.exe --runtime=$runtime } elseif {[uprobes_p]} { stap_run3 "$test-$extra_name" $srcdir/$subdir/$test.stp \ $test.exe -c ./$test.exe } else { untested "$test-$extra_name" } } } else { untested "$test-$extra_name" } catch {exec rm -f $test.exe} } systemtap-2.3/testsuite/systemtap.base/inlinedvars.stp000066400000000000000000000002061217430427200234500ustar00rootroot00000000000000probe process("inlinedvars.exe").function("m").label("inlined_label") { printf("%s (%d,%d)\n", user_string($p_name), $p_i, $p_j); } systemtap-2.3/testsuite/systemtap.base/ipaddr.exp000066400000000000000000000067521217430427200223770ustar00rootroot00000000000000set TEST_NAME_BASE "ipaddr" if {![installtest_p]} { untested $TEST_NAME_BASE; return } # nc server management variables set IPV4_ONLY -1 set nc_pipe 0 # Start an 'nc' server. To start an IPv4 server, pass 1 as the # argument. To start an IPv6 server, pass 0 as the argument. proc start_nc_server { IPV4 } { global TEST_NAME IPV4_ONLY nc_pipe if {$IPV4_ONLY < 0} { # First, does 'nc' exist on this system? if {[catch { exec which nc } res]} { fail "$TEST_NAME find 'nc'" return -1 } pass "$TEST_NAME find 'nc'" # Older versions of 'nc' (on RHEL4 for instance) don't support # IPv6. Does this 'nc' support IPv6? set IPV4_ONLY 0 if {[catch { exec sh -c "nc -h 2>&1 | grep -qi IPv6" } res]} { # If we're here, 'nc' doesn't support IPv6. So, it # supports IPv4 only. set IPV4_ONLY 1 } } # Figure out the 'nc' command line. if {$IPV4} { if {$IPV4_ONLY} { set nc_cmd "| nc -l localhost -p 8079" } else { set nc_cmd "| nc -l -4 localhost 8079" } } else { if {$IPV4_ONLY} { untested "$TEST_NAME starting IPv6 nc server" return -1 } set nc_cmd "| nc -l -6 localhost6 8079" } # Actually start the 'nc' server. verbose -log "starting $nc_cmd" if {[catch {open $nc_cmd} nc_pipe]} { verbose -log "nc command failed: $fl" fail "$TEST_NAME nc server start" return -1 } pass "$TEST_NAME nc server start" return 0 } # Stop the nc server. proc stop_nc_server {} { global TEST_NAME nc_pipe exec kill -s SIGINT [pid $nc_pipe] catch { close $nc_pipe } res pass "$TEST_NAME nc server stop" return } # "load" generation function for stap_run. It runs a client version # of 'nc' and sends some IPv4 data through it. proc run_ipv4_client {} { global srcdir subdir global IPV4_ONLY catch { exec bash -c "cat $srcdir/$subdir/ipaddr.txt > /dev/tcp/127.0.0.1/8079" } return 0 } # "load" generation function for stap_run. It runs a client version # of 'nc' and sends some IPv6 data through it. proc run_ipv6_client {} { global srcdir subdir global IPV4_ONLY if {$IPV4_ONLY} { verbose -log "error: nc only supports IPv4" return 1 } catch { exec bash -c "cat $srcdir/$subdir/ipaddr.txt > /dev/tcp/::1/8079" } return 0 } # Start the 1st IPv4 test set TEST_NAME "${TEST_NAME_BASE}_IPv4_recvmsg" if {[start_nc_server 1]} { # If we couldn't start the server, we're done. return } set script_output "packets = \[0-9\]+\r\naddress errors = 0\r\nbad family errors = 0\r\n" stap_run $TEST_NAME run_ipv4_client $script_output $srcdir/$subdir/ipaddr1.stp # Stop/cleanup the IPv4 server. stop_nc_server # Start the 2nd IPv4 test set TEST_NAME "${TEST_NAME_BASE}_IPv4_receive" if {[start_nc_server 1]} { # If we couldn't start the server, we're done. return } stap_run $TEST_NAME run_ipv4_client $script_output $srcdir/$subdir/ipaddr2.stp # Stop/cleanup the IPv4 server stop_nc_server # Start the 1st IPv6 test set TEST_NAME "${TEST_NAME_BASE}_IPv6_recvmsg" if {[start_nc_server 0]} { # If we couldn't start the server, we're done. return } stap_run $TEST_NAME run_ipv6_client $script_output $srcdir/$subdir/ipaddr1.stp # Stop/cleanup the IPv6 server. stop_nc_server # Start the 2nd IPv6 test set TEST_NAME "${TEST_NAME_BASE}_IPv6_receive" if {[start_nc_server 0]} { # If we couldn't start the server, we're done. return } stap_run $TEST_NAME run_ipv6_client $script_output $srcdir/$subdir/ipaddr2.stp # Stop/cleanup the IPv6 server. stop_nc_server systemtap-2.3/testsuite/systemtap.base/ipaddr.txt000066400000000000000000000002141217430427200224050ustar00rootroot00000000000000line1 this is line2 this might be line3 line4 reporting! line5 line6 this must be line7... this is the 8th line of text line9 line10! done! systemtap-2.3/testsuite/systemtap.base/ipaddr1.stp000066400000000000000000000022241217430427200224600ustar00rootroot00000000000000global packets, addr_errors, family_errors global localhost probe tcp.recvmsg { if (sport != 8079 && dport != 8079) { next } #printf("receive [%s]:%d -> [%s]:%d\n", saddr, sport, daddr, dport) # We got a packet with either a source or destination port of 8079. packets <<< 1 # Did the IP address get converted correctly? if (family == AF_INET() || family == AF_INET6()) { if (sport == 8079 && saddr != localhost[family]) { addr_errors <<< 1 printf("error: saddr %s isn't %s\n", saddr, localhost[family]) } else if (dport == 8079 && daddr != localhost[family]) { addr_errors <<< 1 printf("error: daddr %s isn't %s\n", daddr, localhost[family]) } } else { family_errors <<< 1 } } probe begin { printf("systemtap starting probe\n") localhost[AF_INET()] = "127.0.0.1" localhost[AF_INET6()] = "0000:0000:0000:0000:0000:0000:0000:0001" } probe end { printf("systemtap ending probe\n") if (@count(packets) > 0) { printf("packets = %d\n", @count(packets)) } else { printf("no packets seen\n") } printf("address errors = %d\n", @count(addr_errors)) printf("bad family errors = %d\n", @count(family_errors)) } systemtap-2.3/testsuite/systemtap.base/ipaddr2.stp000066400000000000000000000021171217430427200224620ustar00rootroot00000000000000global packets, addr_errors, family_errors global localhost probe tcp.receive { if (sport != 8079 && dport != 8079) { next } # We got a packet with either a source or destination port of 8079. packets <<< 1 # Did the IP address get converted correctly? if (family == AF_INET() || family == AF_INET6()) { if (sport == 8079 && saddr != localhost[family]) { addr_errors <<< 1 printf("error: saddr %s isn't %s\n", saddr, localhost[family]) } else if (dport == 8079 && daddr != localhost[family]) { addr_errors <<< 1 printf("error: daddr %s isn't %s\n", daddr, localhost[family]) } } else { family_errors <<< 1 } } probe begin { printf("systemtap starting probe\n") localhost[AF_INET()] = "127.0.0.1" localhost[AF_INET6()] = "0000:0000:0000:0000:0000:0000:0000:0001" } probe end { printf("systemtap ending probe\n") if (@count(packets) > 0) { printf("packets = %d\n", @count(packets)) } else { printf("no packets seen\n") } printf("address errors = %d\n", @count(addr_errors)) printf("bad family errors = %d\n", @count(family_errors)) } systemtap-2.3/testsuite/systemtap.base/itrace.exp000066400000000000000000000144731217430427200224020ustar00rootroot00000000000000# itrace test # Initialize variables set exepath "[pwd]/ls_[pid]" # Why check for 1000 instructions executed? We can't know the actual # number to look for, so we just look for a reasonable number that # should work for all platforms. set itrace_single1_script { global instrs = 0 probe begin { printf("systemtap starting probe\n") } probe process("%s").insn { instrs += 1 } probe end { printf("systemtap ending probe\n") if (instrs > 1000) { printf("instrs > 1000 (%%d)\n", instrs) } else { printf("instrs <= 1000 (%%d)\n", instrs) } } } set itrace_single1_script_output "instrs > 1000 \\(\[0-9\]\[0-9\]*\\)\r\n" set itrace_single2_script { global instrs = 0, itrace_on = 0, start_timer = 0 probe begin { start_timer = 1; printf("systemtap starting probe\n") } probe process("%s").insn if (itrace_on) { instrs += 1 if (instrs == 5) exit() } probe timer.ms(1) if (start_timer) { itrace_on = 1 } probe timer.ms(10) if (start_timer) { itrace_on = 0 } probe end { printf("systemtap ending probe\n") printf("itraced = %%d\n", instrs) } } set itrace_single2_script_output "itraced = 5\r\n" set itrace_block1_script { global branches = 0 probe begin { printf("systemtap starting probe\n") } probe process("%s").insn.block { branches += 1 if (branches == 5) exit() } probe end { printf("systemtap ending probe\n") printf("itraced block mode = %%d\n", branches) } } set itrace_block1_script_output "itraced block mode = 5\r\n" set itrace_block2_script { global instrs = 0, itrace_on = 0, start_timer = 0 probe begin { start_timer = 1; printf("systemtap starting probe\n") } probe process("%s").insn.block if (itrace_on) { instrs += 1 if (instrs == 5) exit() } probe timer.ms(1) if (start_timer) { itrace_on = 1 } probe timer.ms(10) if (start_timer) { itrace_on = 0 } probe end { printf("systemtap ending probe\n") printf("itraced = %%d\n", instrs) } } set itrace_block2_script_output "itraced = 5\r\n" set itrace_single_step_script { %{ #include "ptrace_compatibility.h" %} function has_single_step() %{ STAP_RETVALUE = arch_has_single_step(); /* pure */ %} probe begin { printf("has_single_step: %d\n", has_single_step()) exit() } } set itrace_block_step_script { %{ #include "ptrace_compatibility.h" %} function has_block_step() %{ STAP_RETVALUE = arch_has_block_step(); /* pure */ %} probe begin { printf("has_block_step: %d\n", has_block_step()) exit() } } proc stap_check_feature { test_name script feature } { set rc -1 verbose -log "stap -g -e \"$script\"" spawn stap -g -e "$script" expect { -timeout 60 -re "^$feature: 0" { set rc 0; pass $test_name } -re "^$feature: 1" { set rc 1; pass $test_name } eof { fail "$test_name (eof)" } timeout { fail "$test_name (timeout)" } } catch {close} catch {wait} return $rc } # Set up our own copy of /bin/ls, to make testing for a particular # executable easy. We can't use 'ln' here, since we might be creating # a cross-device link. We can't use 'ln -s' here, since the kernel # resolves the symbolic link and reports that /bin/ls is being # exec'ed (instead of our local copy). if {[catch {exec cp /bin/ls $exepath} res]} { fail "unable to copy /bin/ls: $res" return } # "load" generation function for stap_run. It spawns our own copy of # /bin/ls, waits 1 second, then kills it. proc run_ls_1_sec {} { global exepath spawn $exepath set exe_id $spawn_id after 1000; exec kill -INT -[exp_pid -i $exe_id] catch {close -i $exe_id} catch {wait -i $exe_id} return 0; } # figure out if this system supports single stepping (if we've got # utrace and we're doing install testing) set TEST_NAME "itrace single step check" set single_step_p 0 if {![utrace_orig_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested $TEST_NAME } else { set single_step_p [stap_check_feature $TEST_NAME \ $itrace_single_step_script "has_single_step"] } # figure out if this system supports block stepping (if we've got # utrace and we're doing install testing) set TEST_NAME "itrace block step check" set block_step_p 0 if {![utrace_orig_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested $TEST_NAME } else { set block_step_p [stap_check_feature $TEST_NAME \ $itrace_block_step_script "has_block_step"] } # Run the single step tests set TEST_NAME "itrace_single1" if {![utrace_orig_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested $TEST_NAME } elseif {$single_step_p != 1} { xfail "$TEST_NAME : no kernel single step support" } else { set script [format $itrace_single1_script $exepath] stap_run $TEST_NAME run_ls_1_sec $itrace_single1_script_output -e $script } set TEST_NAME "itrace_single2" if {![utrace_orig_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested $TEST_NAME } elseif {$single_step_p != 1} { xfail "$TEST_NAME : no kernel single step support" } else { set script [format $itrace_single2_script $exepath] stap_run $TEST_NAME run_ls_1_sec $itrace_single2_script_output -e $script } # Run the block step tests set TEST_NAME "itrace_block1" if {![utrace_orig_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested $TEST_NAME } elseif {$block_step_p != 1} { xfail "$TEST_NAME : no kernel block step support" } else { set script [format $itrace_block1_script $exepath] stap_run $TEST_NAME run_ls_1_sec $itrace_block1_script_output -e $script } set TEST_NAME "itrace_block2" if {![utrace_orig_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested $TEST_NAME } elseif {$block_step_p != 1} { xfail "$TEST_NAME : no kernel block step support" } else { set script [format $itrace_block2_script $exepath] stap_run $TEST_NAME run_ls_1_sec $itrace_block2_script_output -e $script } # Cleanup exec rm -f $exepath systemtap-2.3/testsuite/systemtap.base/jennie.c000066400000000000000000000001251217430427200220160ustar00rootroot00000000000000int main (int argc, char *argv[]) { if (argc > 1) main (argc - 1, argv); return 0; } systemtap-2.3/testsuite/systemtap.base/kallsyms_expand_symbol.exp000066400000000000000000000007111217430427200257040ustar00rootroot00000000000000# Alternate "pointer array" test that works on all systems. # See also PR13467. set test "kallsyms_expand_symbol" # Test that the script can decode the kallsyms table to produce # the first ten elements. set plain_head [exec head /proc/kallsyms] set syms_head [exec head /proc/kallsyms | cut -f3 -d\ ] set ::result_string ${plain_head}\n${syms_head} verbose -log "Expecting:\n$::result_string" stap_run2 $srcdir/$subdir/$test.stp -c {head /proc/kallsyms} systemtap-2.3/testsuite/systemtap.base/kallsyms_expand_symbol.stp000066400000000000000000000023421217430427200257200ustar00rootroot00000000000000# Test various array operations on a kernel variable. # This is a pretty direct translation of the C source code of # kernel/kallsyms.c (kallsyms_expand_symbol). global symbols = 0; probe kernel.function("kallsyms_expand_symbol") { /* We are only interested in the head -10 symbols for comparison. */ if (target() != pid()) next; skipped_first = 0; /* Get the compressed symbol length from the first symbol byte. */ data = &$kallsyms_names[$off]; len = kernel_char(data) & 0xff; data++; /* * Update the offset to return the offset for the next symbol on * the compressed stream. */ off += len + 1; /* * For every byte on the compressed symbol data, copy the table * entry for that byte. */ while (len) { idx = kernel_char(data) & 0xff; tptr = &$kallsyms_token_table[$kallsyms_token_index[idx]]; data++; len--; t = kernel_char(tptr) & 0xff; while (t) { if (skipped_first) { printf("%c", t); } else skipped_first = 1; tptr++; t = kernel_char(tptr) & 0xff; } } printf("\n"); /* Are we done yet? */ symbols++; if (symbols == 10) exit(); } systemtap-2.3/testsuite/systemtap.base/kbuildenv.exp000066400000000000000000000004721217430427200231100ustar00rootroot00000000000000set test "kbuild PATH sanitization" exec rm -rf kbuild_path exec mkdir kbuild_path exec ln -s /bin/false kbuild_path/gcc if {[catch {exec env "PATH=[pwd]/kbuild_path:$env(PATH)" stap -p4 -e {probe begin {}} -w} res]} { verbose -log "rc $res" fail $test } else { pass $test } exec rm -rf kbuild_path systemtap-2.3/testsuite/systemtap.base/kfunct.exp000066400000000000000000000005041217430427200224130ustar00rootroot00000000000000# Simple function to test that systemtap can generate a kernel module that # instruments a function, install it, and get some output. set test "kfunct" # better have a count other than zero to show that probe fired set output_string "count = \[1-9\]\[0-9\]*\r\n" stap_run $srcdir/$subdir/$test.stp no_load $output_string systemtap-2.3/testsuite/systemtap.base/kfunct.stp000066400000000000000000000005171217430427200224310ustar00rootroot00000000000000/* * kfunct.stp * * Very simple function to test that systemtap can generate a kernel module, * install it, and get some output. */ global count probe begin { println("systemtap starting probe") } probe kernel.function("schedule") { ++count; } probe end { println("systemtap ending probe") printf("count = %d\n", count) } systemtap-2.3/testsuite/systemtap.base/kmodule.exp000066400000000000000000000040451217430427200225650ustar00rootroot00000000000000# Simple function to test that systemtap can generate instument a module # function, install it, and get some output. set test "kmodule" if {![installtest_p]} { untested $test return } set build_dir "" set uname [exec /bin/uname -r] proc build_and_install_module {} { global build_dir global srcdir subdir # Create the build directory and populate it if {[catch {exec mktemp -d staptestXXXXXX} build_dir]} { verbose -log "Failed to create temporary directory: $build_dir" return 0 } exec cp $srcdir/$subdir/stap_kmodule.c $build_dir/ exec cp -p $srcdir/$subdir/stap_kmodule.Makefile $build_dir/Makefile # Build the module if {[catch {exec make -C $build_dir clean} res]} { verbose -log "$res" return 0 } catch {exec make -C $build_dir} res if {![file exists $build_dir/stap_kmodule.ko]} { verbose -log "$res" return 0 } set res [as_root [list cp $build_dir/stap_kmodule.ko /lib/modules/$::uname/kernel/]] if { $res != 0 } { verbose -log "$res" return 0 } # Install the module set res [as_root [list /sbin/insmod $build_dir/stap_kmodule.ko]] if {$res != 0} { verbose -log "$res" return 0 } return 1 } proc cleanup_module {} { global build_dir as_root [list /bin/rm -f /lib/modules/$::uname/kernel/stap_kmodule.ko] as_root [list /sbin/rmmod stap_kmodule] if {$build_dir != ""} { catch { exec rm -rf $build_dir } } } proc kmodule_load {} { # Trigger the test module if {[file exists /proc/stap_kmodule_cmd]} { exec echo 0 > /proc/stap_kmodule_cmd return 0 } else { return 1 } } set output_string "count = 1\r\n" if {[build_and_install_module] == 0} { verbose -log "BUILD FAILED" fail "$test (could not build/install module)" return } else { pass "$test (built and installed module)" } # Test 'module("foo").function("bar") stap_run $srcdir/$subdir/$test.stp kmodule_load $output_string # Test 'kprobe.module("foo").function("bar") stap_run $srcdir/$subdir/kprobe_module.stp kmodule_load $output_string cleanup_module systemtap-2.3/testsuite/systemtap.base/kmodule.stp000066400000000000000000000005701217430427200225760ustar00rootroot00000000000000/* * kmodule.stp * * Simple function to test that systemtap can generate instrumentation * for a module function, install it, and get some output. */ global count probe begin { printf("systemtap starting probe\n") } probe module("stap_kmodule").function("stm_write_cmd") { ++count; } probe end { printf("systemtap ending probe\n") printf("count = %d\n", count) } systemtap-2.3/testsuite/systemtap.base/kprobe_module.stp000066400000000000000000000006051217430427200237640ustar00rootroot00000000000000/* * kprobe_module.stp * * Simple function to test that systemtap can generate instrumentation * for a module function, install it, and get some output. */ global count probe begin { printf("systemtap starting probe\n") } probe kprobe.module("stap_kmodule").function("stm_write_cmd") { ++count; } probe end { printf("systemtap ending probe\n") printf("count = %d\n", count) } systemtap-2.3/testsuite/systemtap.base/kprobes.exp000066400000000000000000000001201217430427200225600ustar00rootroot00000000000000set test "kprobes" stap_run $srcdir/$subdir/$test.stp no_load "probe point hit" systemtap-2.3/testsuite/systemtap.base/kprobes.stp000066400000000000000000000005461217430427200226060ustar00rootroot00000000000000/* * kprobes.stp * Probe to test the functionality of kprobe-based probes * (Dwarfless Probing) */ global hit_str probe begin { println("systemtap starting probe"); hit_str = "" } probe kprobe.function("vfs_read") { hit_str = "probe point hit" exit(); } probe end { println("systemtap ending probe"); println(hit_str); delete hit_str; } systemtap-2.3/testsuite/systemtap.base/kretprobe-vars.exp000066400000000000000000000003211217430427200240640ustar00rootroot00000000000000# Check that implicitly-saved $target variables have the same # value as those manually saved on entry. set test "kretprobe-vars" stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string -c "cat /dev/null" systemtap-2.3/testsuite/systemtap.base/kretprobe-vars.stp000066400000000000000000000024201217430427200241000ustar00rootroot00000000000000# Check that implicitly-saved $target variables have the same # value as those manually saved on entry. # saved individual parameters global read_file global read_file_mode global read_buf global read_count global read_pos # the saved string $$parms global read_parms # error count global errors probe begin { println("systemtap starting probe") } function check_num(name, ent, ret) { if (ent != ret) { printf("%s mismatch, entry:%#x vs. return:%#x\n", name, ent, ret) errors++ } } function check_str(name, ent, ret) { if (ent != ret) { printf("%s mismatch, entry:'%s' vs. return:'%s'\n", name, ent, ret) errors++ } } probe kernel.function("vfs_read").call { if (tid() != target()) next read_file = $file read_file_mode = $file->f_mode read_buf = $buf read_count = $count read_pos = $pos read_parms = $$parms } probe kernel.function("vfs_read").return { if (tid() != target()) next println("systemtap ending probe") check_num("file", read_file, $file) check_num("file->f_mode", read_file_mode, $file->f_mode) check_num("buf", read_buf, $buf) check_num("count", read_count, $count) check_num("pos", read_pos, $pos) check_str("parms", read_parms, $$parms) if (!errors) println("systemtap test success") exit() } systemtap-2.3/testsuite/systemtap.base/labels.exp000066400000000000000000000142531217430427200223710ustar00rootroot00000000000000set test "labels" if {![installtest_p]} {untested $test; return} if {![utrace_p]} { untested $test; return } # Compile a C program to use as the user-space probing target set label_srcpath "[pwd]/labels.c" set label_exepath "[pwd]/labels.x" set label_sopath "[pwd]/labels.so" set label_flags "additional_flags=-g" set fp [open $label_srcpath "w"] puts $fp " int foo () { init_an_int: return 1; } int main () { sleep(5); foo(); int a = 0; int b = 0; char *c; init_an_int: a = 2; init_an_int_again: b = 3; c = \"abc\"; ptr_inited: return 1; } " close $fp set label_stppath "[pwd]/labels.stp" set fp [open $label_stppath "w"] puts $fp " probe process(\"labels.x\").function(\"main@labels.c\").label(\"init_*\") {printf (\"VARS %s\\n\",\$\$vars)} probe process(\"labels.x\").function(\"main@labels.c\").label(\"ptr_inited\") {printf (\"VARS %s\\n\",\$\$vars)} probe process(\"labels.x\").function(\"main@labels.c\").label(\"init_an_int\") {printf (\"init_an_int\\n\")} " close $fp set ok 0 set res [target_compile $label_srcpath $label_exepath executable $label_flags] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "compiling labels.c $label_flags" catch {exec rm -f $label_srcpath $label_stppath} return } else { pass "compiling labels.c $label_flags" } # line number error (expect no output at all, since no label found) set ok 0 spawn stap --use-server-on-error=no -l "process(\"$label_exepath\").function(\"foo@${label_srcpath}:10\").label(\"*\")" expect { -timeout 180 -re {[^\r\n]+} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch { close }; catch { wait } if {$ok == 0} { pass "$test :N .label $ok" } { fail "$test :N .label $ok" } # line number set ok 0 spawn stap -l "process(\"$label_exepath\").function(\"foo@${label_srcpath}:4\").label(\"*\")" expect { -timeout 180 -re {process.*function.*labels.c:5...label..init_an_int} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch { close }; catch { wait } if {$ok == 1} { pass "$test :N .label $ok" } { fail "$test :N .label $ok" } # list of labels spawn stap -l "process(\"$label_exepath\").function(\"*\").label(\"*\")" set ok 0 expect { -timeout 180 -re {^process[^\r\n]*function[^\r\n]*labels.c:5...label..init_an_int..\r\n} { incr ok; exp_continue } -re {^process[^\r\n]*function[^\r\n]*labels.c:16...label..init_an_int..\r\n} { incr ok; exp_continue } -re {^process[^\r\n]*function[^\r\n]*labels.c:18...label..init_an_int_again..\r\n} { incr ok; exp_continue } -re {^process[^\r\n]*function[^\r\n]*labels.c:21...label..ptr_inited..\r\n} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch { close }; catch { wait } if {$ok == 4} { pass "$test -l .label" } { fail "$test -l .label $ok" } # label in an executable (only if we have uprobes) foreach runtime [get_runtime_list] { set test_name "$test exe .label" if {$runtime != ""} { lappend test_name $runtime verbose -log "spawn stap -c $label_exepath $label_stppath --runtime=$runtime" spawn stap -c $label_exepath $label_stppath --runtime=$runtime } elseif {[uprobes_p]} { verbose -log "spawn stap -c $label_exepath $label_stppath" spawn stap -c $label_exepath $label_stppath } else { untested "$test_name" continue } # Note that the output can come out in a bit different order # depending on when the probes fire. This is reasonable since # we've got 2 probes at the same probe point (.label("init_*") and # .label("init_an_int")) set ok 0 expect { -timeout 180 -re {VARS a=0x0 b=0x0.*init_an_int.*VARS a=0x2 b=0x0.*VARS a=0x2 b=0x3 c=0x[a-f01-9]} { incr ok; exp_continue } -re {init_an_int.*VARS a=0x0 b=0x0.*VARS a=0x2 b=0x0.*VARS a=0x2 b=0x3 c=0x[a-f01-9]} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch { close }; catch { wait } if {$ok == 1} { pass "$test_name" } { fail "$test_name $ok" } } # address of label in an executable set label_shpath "[pwd]/label.sh" set fp [open $label_shpath "w"] puts $fp " readelf --debug-dump $label_exepath | awk \" /init_an_int_again/ {have_label=1} /DW_AT_low_pc/ {if (have_label) {print \$3;exit;}} \" " close $fp spawn sh $label_shpath expect { -re {0x[0-9a-f]*} } catch { close }; catch { wait } set nomatch 0 spawn stap -p2 -l "process\(\"$label_exepath\"\).statement($expect_out(0,string))" expect { -timeout 180 -re {semantic error: no match} { incr nomatch; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch { close }; catch { wait } if {$nomatch == 0} { pass "$test exe .statement" } { fail "$test exe .statement" } set ok 0 set label_flags "additional_flags=-g additional_flags=-shared additional_flags=-fPIC" set res [target_compile $label_srcpath $label_sopath executable $label_flags] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "compiling labels.c $label_flags" catch {exec rm -f $label_srcpath $label_stppath} return } else { pass "compiling labels.c $label_flags" } # label in a shared object spawn stap -p2 -l "process\(\"$label_sopath\"\).function\(\"\*\"\).label\(\"init_an_int_again\"\)" expect { -timeout 180 -re {process.*function} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch { close }; catch { wait } if {$ok == 1} { pass "$test so .label" } { fail "$test so .label $ok" } # address of label in a shared object set label_shpath "[pwd]/label.sh" set fp [open $label_shpath "w"] puts $fp " readelf --debug-dump $label_sopath | awk \" /init_an_int_again/ {have_label=1} /DW_AT_low_pc/ {if (have_label) {print \$3;exit;}} \" " close $fp spawn sh $label_shpath expect { -re {0x[0-9a-f]*} } catch { close }; catch { wait } set nomatch 0 spawn stap -p2 -l "process\(\"$label_sopath\"\).statement($expect_out(0,string))" expect { -timeout 180 -re {semantic error: no match} { incr nomatch; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch { close }; catch { wait } if {$nomatch == 0} { pass "$test so .statement" } { fail "$test so .statement" } catch {exec rm -f $label_srcpath $label_stppath $label_exepath $label_shpath $label_sopath} systemtap-2.3/testsuite/systemtap.base/library.exp000066400000000000000000000136061217430427200225740ustar00rootroot00000000000000set test "library" proc cleanup_handler { verbose } { if { $verbose == 0 } { catch {exec rm -f libsdt.so sdt_misc.x } } catch {exec rm -f sdt_misc_.c sdt_misc_.h sdt_misc_.o } } proc error_handler { res message } { global test if { $res == 0 } { verbose $message 2 fail "$test $message" return 1 } else { pass "$test $message" return 0 } } if {![installtest_p]} {untested $test; return} if {![utrace_p]} { untested "$test" return } set stap_path $env(SYSTEMTAP_PATH)/stap set dpath "[pwd]/sdt_misc_.d" set hpath "[pwd]/sdt_misc_.h" set opath "[pwd]/sdt_misc_.o" set exepath "[pwd]/sdt_misc.x" set sopath "libsdt.so" # Run dtrace if {[installtest_p]} { set dtrace $env(SYSTEMTAP_PATH)/dtrace } else { set dtrace ../dtrace } verbose -log "$dtrace -DSTAP_SDT_V3 --types -h -s $srcdir/$subdir/sdt_misc_.d" if {[catch {exec $dtrace --types -h -s $srcdir/$subdir/sdt_misc_.d} res]} { verbose -log "unable to run $dtrace: $res" } verbose -log "$dtrace -DSTAP_SDT_V3 --types -G -s $srcdir/$subdir/sdt_misc_.d" if {[catch {exec $dtrace -DSTAP_SDT_V3 --types -G \ -s $srcdir/$subdir/sdt_misc_.d} res]} { verbose -log "unable to run $dtrace: $res" } if { [error_handler [expr {[file exists $hpath] && [file exists $opath]}] "dtrace"] } { cleanup_handler $verbose return } set F additional_flags set flags "$F=[sdt_includes] $F=$opath $F=-I. $F=-shared $F=-fPIC $F=-DNO_MAIN $F=-g" set res [target_compile $srcdir/$subdir/sdt_misc.c $sopath executable $flags ] if { [error_handler [expr {$res == ""}] "target_compile libsdt.so"] } { cleanup_handler $verbose return } set flags "$F=-Wl,-rpath,[pwd] $F=-L[pwd] $F=-lsdt $F=-DONLY_MAIN $F=-g" set res [target_compile $srcdir/$subdir/sdt_misc.c $exepath executable $flags ] if { [error_handler [expr {$res == ""}] "target_compile sdt_misc.x"] } { cleanup_handler $verbose return } # Test globbing proc globbing_test { mssg script } { global sopath exepath srcdir subdir stap_path eval set globs "{{*} {*libsdt*} $sopath}" foreach glob $globs { foreach runtime [get_runtime_list] { set test_name "sdt_misc" if {$runtime != ""} { lappend test_name "($runtime)" spawn $stap_path --runtime=$runtime -c $exepath \ $script $exepath "$glob" } elseif {[uretprobes_p]} { spawn $stap_path -c $exepath $script $exepath "$glob" } else { untested "library $test_name $glob $mssg" continue } set ok 0 expect { -timeout 180 -re {^bar begin\r\n} { incr ok; exp_continue } -re {^bar 2\r\n} { incr ok; exp_continue } -re {^In test_probe_2 probe 0x2\r\n} { incr ok; exp_continue } -re {^bar end\r\n} { incr ok; exp_continue } -re {^baz begin\r\n} { incr ok; exp_continue } -re {^baz 3 abc\r\n} { incr ok; exp_continue } -re {^In test_probe_0 probe 0x3\r\n} { incr ok; exp_continue } -re {^In test_probe_3 probe 0x3 0x[0-9a-f][0-9a-f]*\r\n} { incr ok; exp_continue } -re {^baz end\r\n} { incr ok; exp_continue } -re {^buz begin\r\n} { incr ok; exp_continue } -re {^buz 4\r\n} { incr ok; exp_continue } -re {^In test_probe_4 dtrace probe 0x[0-9a-f][0-9a-f]*\r\n} { incr ok; exp_continue } -re {^In test_probe_1 probe 0x0\r\n} { incr ok; exp_continue } -re {^buz end\r\n} { incr ok; exp_continue } -re {^WARNING:.*No DWARF information found.*\r\n} { exp_continue } -re {^Missing separate debuginfos.*\r\n} { exp_continue } timeout { fail "$test_name (timeout)" } eof { } } catch {close}; catch {wait} error_handler [expr {$ok == 15}] \ "$test_name $glob $mssg ($ok != 15)" } ; # foreach runtime } ; # foreach glob } ; # proc globbing_test set script_path [fullpath $srcdir/$subdir/library.stp] globbing_test "" $script_path set savedir [pwd] cd /tmp globbing_test "rpath" $script_path cd $savedir # Test --ldd foreach runtime [get_runtime_list] { set test_name "printf --ldd" if {$runtime != ""} { lappend test_name "($runtime)" spawn $stap_path --ldd -v -v -v -c $exepath -e "probe process(\"$exepath\").library(\"*\").statement(\"baz@sdt_misc.c\") \{printf(\"%s \", pn())\}" } elseif {[uprobes_p]} { spawn $stap_path --ldd -v -v -v -c $exepath -e "probe process(\"$exepath\").library(\"*\").statement(\"baz@sdt_misc.c\") \{printf(\"%s \", pn())\}" } else { untested "library $test_name" continue } set ok 0 expect { -timeout 180 -re {Added -d '.*libsdt.so' due to 'libsdt.so'} { incr ok; exp_continue } -re {Added -d '/lib.*/libm.so.[0-9]' due to 'libm.so.[0-9]'} { incr ok; exp_continue } -re {Added -d '/lib.*/libc.so.[0-9]' due to 'libc.so.[0-9]'} { incr ok; exp_continue } -re {Added -d '/lib.*/.*ld.*so'} { incr ok; exp_continue } timeout { fail "$test_name (timeout)" } eof { } } catch {close}; catch {wait} error_handler [expr {$ok == 4}] "$test_name ($ok) ($ok != 4)" } # Test .exported. Notice we're only testing exported functions in our # compiled 'libsdt' shared library. We could test exported functions # in glibc, but to find them we'd need glibc debuginfo installed, # which might or might not be present. foreach runtime [get_runtime_list] { set test_name ".exported" if {$runtime != ""} { lappend test_name "($runtime)" spawn $stap_path --runtime=$runtime -c $exepath -e "probe process(\"$exepath\").library(\"$sopath\").function(\"*\").exported \{printf(\"%s \", pp())\}" } elseif {[uprobes_p]} { spawn $stap_path -c $exepath -e "probe process(\"$exepath\").library(\"$sopath\").function(\"*\").exported \{printf(\"%s \", pp())\}" } else { untested "library $test_name" continue } set ok 0 expect { -timeout 180 -re {libsdt.so.*bar} { incr ok; exp_continue } -re {libsdt.so.*baz} { incr ok; exp_continue } -re {libsdt.so.*buz} { incr ok; exp_continue } timeout { fail "$test_name (timeout)" } eof { } } catch {close}; catch {wait} error_handler [expr {$ok >= 3}] "$test_name ($ok) ($ok >= 3)" } cleanup_handler $verbose systemtap-2.3/testsuite/systemtap.base/library.stp000066400000000000000000000023451217430427200226040ustar00rootroot00000000000000probe process (@1).library(@2).statement("bar@sdt_misc.c+9") {printf ("bar %d\n",$i)} probe process (@1).library(@2).statement("baz@sdt_misc.c+1") {printf ("baz %d %s\n",$i,user_string($s))} probe process (@1).library(@2).statement("buz@sdt_misc.c+1") {printf ("buz %d\n",$parm)} probe process (@1).library(@2).function("bar") {printf ("bar begin\n")} probe process (@1).library(@2).function("baz") {printf ("baz begin\n")} probe process (@1).library(@2).function("buz") {printf ("buz begin\n")} probe process (@1).library(@2).function("bar").return {printf ("bar end\n")} probe process (@1).library(@2).function("baz").return {printf ("baz end\n")} probe process (@1).library(@2).function("buz").return {printf ("buz end\n")} probe process(@1).library(@2).mark("test_probe_0") { printf("In %s probe %#x\n", $$name, $arg1) } probe process(@1).library(@2).mark("test_probe_1") { printf("In %s probe %#x\n", $$name, $arg1) } probe process(@1).library(@2).mark("test_probe_2") { printf("In %s probe %#x\n", $$name, $arg1) } probe process(@1).library(@2).mark("test_probe_3") { printf("In %s probe %#x %#x\n", $$name, $arg1, $arg2) } probe process(@1).library(@2).mark("test_probe_4") { printf("In %s dtrace probe %#x\n", $$name, $arg1) } systemtap-2.3/testsuite/systemtap.base/limits.exp000066400000000000000000000022161217430427200224240ustar00rootroot00000000000000# test integer limits. Set and print variables and print constants. set test "limits" set ::result_string {Maximum signed 32-bit number 2147483647 0x7fffffff 2147483647 0x7fffffff 2147483647 0x7fffffff Maximum unsigned 32-bit number 4294967295 0xffffffff 4294967295 0xffffffff 4294967295 0xffffffff Minimum signed 32-bit number -2147483648 0xffffffff80000000 -2147483648 0xffffffff80000000 -2147483648 0xffffffff80000000 -2147483648 0xffffffff80000000 Maximum signed 64-bit number 9223372036854775807 0x7fffffffffffffff 9223372036854775807 0x7fffffffffffffff 9223372036854775807 0x7fffffffffffffff Maximum unsigned 64-bit number 18446744073709551615d 0xffffffffffffffff 18446744073709551615d 0xffffffffffffffff 18446744073709551615d 0xffffffffffffffff Minimum signed 64-bit number -9223372036854775808 0x8000000000000000 -9223372036854775808 0x8000000000000000 -9223372036854775808 0x8000000000000000 -9223372036854775808 0x8000000000000000 -9223372036854775808 0x8000000000000000} foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run2 $srcdir/$subdir/$test.stp --runtime=$runtime } else { stap_run2 $srcdir/$subdir/$test.stp } } systemtap-2.3/testsuite/systemtap.base/limits.stp000066400000000000000000000032601217430427200224360ustar00rootroot00000000000000# test integer limits. Set and print variables and print constants. probe begin { long_max = 2147483647; ulong_max = 4294967295; long_min = -2147483647-1; long_min2 = -2147483648; printf("Maximum signed 32-bit number\n") printf("%d 0x%x\n", long_max, long_max) printf("%d 0x%x\n", 2147483647, 2147483647) printf("%d 0x%x\n", 0x7fffffff, 0x7fffffff) printf("\nMaximum unsigned 32-bit number\n") printf("%d 0x%x\n", ulong_max, ulong_max) printf("%d 0x%x\n", 4294967295, 4294967295) printf("%d 0x%x\n", 0xffffffff, 0xffffffff) printf("\nMinimum signed 32-bit number\n") printf("%d 0x%x\n", long_min, long_min) printf("%d 0x%x\n", long_min2, long_min2) printf("%d 0x%x\n", -2147483648, -2147483648) printf("%d 0x%x\n", 0xffffffff80000000, 0xffffffff80000000) llong_max = 9223372036854775807; ullong_max = 18446744073709551615; llong_min = -9223372036854775807-1; llong_min2 = -9223372036854775808; llong_min3 = 9223372036854775808; printf("\nMaximum signed 64-bit number\n") printf("%d 0x%x\n", llong_max, llong_max) printf("%d 0x%x\n", 9223372036854775807, 9223372036854775807) printf("%d 0x%x\n", 0x7fffffffffffffff, 0x7fffffffffffffff) printf("\nMaximum unsigned 64-bit number\n") printf("%ud 0x%x\n", ullong_max, ullong_max) printf("%ud 0x%x\n", 18446744073709551615, 18446744073709551615) printf("%ud 0x%x\n", 0xffffffffffffffff, 0xffffffffffffffff) printf("\nMinimum signed 64-bit number\n") printf("%d 0x%x\n", llong_min, llong_min) printf("%d 0x%x\n", llong_min2, llong_min2) printf("%d 0x%x\n", llong_min3, llong_min3) printf("%d 0x%x\n", -9223372036854775808, -9223372036854775808) printf("%d 0x%x\n", 0x8000000000000000, 0x8000000000000000) exit() } systemtap-2.3/testsuite/systemtap.base/list.exp000066400000000000000000000046771217430427200221130ustar00rootroot00000000000000# PR14297-related testing proc test_list { test input output_re } { spawn stap -l $input expect { -timeout 180 -re $output_re { pass $test } -re {^[^\r\n]*\r\n} { exp_continue } timeout { fail $test } eof { fail $test } } catch { close }; catch { wait } } proc test_uprobes_list { test input output_re } { if {[uprobes_p]} { test_list $test $input $output_re } else { unsupported $test } } test_uprobes_list plt-glob {process("stap").plt("re??")} \ {process."stap"..plt."read".\r\n} test_uprobes_list plt-glob2 {process("stap").plt("re*")} \ {process."stap"..plt."read".\r\n} # NB: this would be nice to probe, but we don't have the # autoconf $prefix available here in the dejagnu scripts. # spawn stap -l "process(\"${prefix}/bin/stap*\").plt(\"re*\"" # NB: we expect the extra "?" suffix due to filename globbing # -re {process."[^\r\n]*stap"..plt."read"..\r\n} { pass $test } test_uprobes_list plt-non-glob {process("stap").plt("read")} \ {process."stap"..plt."read".\r\n} test_uprobes_list mark-non-glob {process("stap").mark("pass5__end")} \ {process."stap"..mark."pass5__end".\r\n} test_uprobes_list mark-non-glob2 {process("stap").mark("pass5-end")} \ {process."stap"..mark."pass5__end".\r\n} test_uprobes_list mark-glob {process("stap").mark("pass[12345678]__end")} \ {process."stap"..mark."pass5__end".\r\n} test_uprobes_list mark-glob2 {process("stap").mark("pass*__end")} \ {process."stap"..mark."pass5__end".\r\n} test_list syscall-glob {syscall.rea*} \ {syscall.read\r\n} test_list syscall-noglob {syscall.read} \ {syscall.read\r\n} test_list init_once-glob {kernel.function("init_once*")} \ {kernel.function."init_once@fs/inode.c:\d+".\r\n} test_list init_once-noglob {kernel.function("init_once")} \ {kernel.function."init_once@fs/inode.c:\d+".\r\n} test_list begin-glob {begin*} \ {begin\r\n} test_list begin-noglob {begin} \ {begin\r\n} # This one is not so interesting, but we want to make sure the following test # statements are actually within an inline. test_list copy_flags-inline {kernel.function("copy_flags@kernel/fork.c").inline} \ {kernel.function."copy_flags@kernel/fork.c:\d+"..inline\r\n} # PR15587: make sure we have line numbers on statements of an inline function test_list copy_flags-statement {kernel.statement("copy_flags@kernel/fork.c:*")} \ {kernel.statement."copy_flags@kernel/fork.c:\d+".\r\n} systemtap-2.3/testsuite/systemtap.base/logical_and.exp000066400000000000000000000004731217430427200233620ustar00rootroot00000000000000# Simple function to test that systemtap logial and works set test "logical_and" foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string \ --runtime=$runtime } else { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string } } systemtap-2.3/testsuite/systemtap.base/logical_and.stp000066400000000000000000000012771217430427200233770ustar00rootroot00000000000000/* * logical_and.stp * * Check that systemtap "logical and" works */ global x1_0 global x2_1 global x3_0 global x4_1 probe begin { println("systemtap starting probe") x1_0 = 0; x2_1 = 1; x3_0 = 0; x4_1 = 1; } probe end { println("systemtap ending probe") if (x1_0 && x3_0 ) { println("systemtap test failure"); } else { println("systemtap test success"); } if (x2_1 && x3_0 ) { println("systemtap test failure"); } else { println("systemtap test success"); } if (x1_0 && x4_1 ) { println("systemtap test failure"); } else { println("systemtap test success"); } if (x2_1 && x4_1 ) { println("systemtap test success"); } else { println("systemtap test failure"); } } systemtap-2.3/testsuite/systemtap.base/marker.exp000066400000000000000000000233471217430427200224140ustar00rootroot00000000000000# Marker tests. Note that we can't really run (pass 5) marker tests, # since we have no idea where in the kernel they are (and what would # trigger a specific marker). So, we'll try to compile lots of tests # to do as much as we can. # Initialize variables set kernel_markers_found 0 set kernel_marker_names {} set kernel_marker_formats {} set num_marker_found 0 set num_marker_name "" set kernel_script {"probe kernel.mark(\"%s\") { }"} set kernel_script_arg {"probe kernel.mark(\"%s\") { print(%s) print_backtrace() }"} set kernel_script_arg2 {"probe kernel.mark(\"%s\") { %s = 0 }"} set kernel_script_arg3 {"probe kernel.mark(\"%s\") { print(\$arg1%s) }"} set kernel_format_script {"probe kernel.mark(\"%s\").format(\"%s\") { }"} # Try to read in the marker list from the Module.markers file. set uname [exec /bin/uname -r] set path "/lib/modules/$uname/build/Module.markers" if {! [catch {open $path RDONLY} fl]} { while {[gets $fl s] >= 0} { # This regexp only picks up markers that contain arguments. # This helps ensure that K_MARKER04 passes correctly. if [regexp {^([^ \t]+)\t[^ \t]+\t(.*%.+)$} $s match name fmt] { set kernel_markers_found 1 lappend kernel_marker_names $name lappend kernel_marker_formats $fmt # Look for a marker whose first argument is numeric # (either '%d', '%u', or '%p'). If we find such a marker, # we can run K_MARKER09, K_MARKER10, etc. if {$num_marker_found == 0 && [regexp {^[^%]*%[dup]} $fmt]} { set num_marker_found 1 set num_marker_name $name } } } catch {close $fl} } # # Do some marker tests. # set TEST_NAME "K_MARKER01" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that probes all kernel markers using a # wildcard. set script [format $kernel_script "*"] stap_compile $TEST_NAME 1 $script } set TEST_NAME "K_MARKER02" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that probes the first kernel marker # found. set script [format $kernel_script [lindex $kernel_marker_names 0]] stap_compile $TEST_NAME 1 $script } # We can go ahead and try this test even if the kernel doesn't have # marker support, since we're probing a marker that doesn't exist. set TEST_NAME "K_MARKER03" # Try compiling a script that probes a kernel marker that doesn't # exist. set script [format $kernel_script "X_marker_that_does_not_exist_X"] stap_compile $TEST_NAME 0 $script set TEST_NAME "K_MARKER04" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that prints the first argument of a # marker. This one might fail if the marker we pick doesn't have # any arguments (but hopefully our kernel marker list only # contains markers that have at least one argument). set script [format $kernel_script_arg \ [lindex $kernel_marker_names 0] {\$arg1}] stap_compile $TEST_NAME 1 $script } set TEST_NAME "K_MARKER05" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that prints an marker argument that # doesn't exist. This one might fail if the marker we pick # has a 200th argument (which isn't likely). set script [format $kernel_script_arg \ [lindex $kernel_marker_names 0] {\$arg200}] stap_compile $TEST_NAME 0 $script } set TEST_NAME "K_MARKER06" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that prints marker argument $arg0 # (which doesn't exist). set script [format $kernel_script_arg \ [lindex $kernel_marker_names 0] {\$arg0}] stap_compile $TEST_NAME 0 $script } set TEST_NAME "K_MARKER07" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that prints marker argument $foo1 (which # doesn't exist). set script [format $kernel_script_arg \ [lindex $kernel_marker_names 0] {\$foo1}] stap_compile $TEST_NAME 0 $script } set TEST_NAME "K_MARKER08" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that writes to marker argument $arg1 (which # isn't allowed). set script [format $kernel_script_arg2 \ [lindex $kernel_marker_names 0] {\$arg1}] stap_compile $TEST_NAME 0 $script } set TEST_NAME "K_MARKER09" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } elseif {$num_marker_found == 0} { untested "$TEST_NAME : no kernel marker found with a numeric first argument" } else { # Try compiling a script that treats its first marker argument # as a structure (which isn't allowed). set script [format $kernel_script_arg3 $num_marker_name "->foo"] stap_compile $TEST_NAME 0 $script } set TEST_NAME "K_MARKER10" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } elseif {$num_marker_found == 0} { untested "$TEST_NAME : no kernel marker found with a numeric first argument" } else { # Try compiling a script that treats its first marker argument # like an array (which isn't allowed). set script [format $kernel_script_arg3 $num_marker_name {\[0\]}] stap_compile $TEST_NAME 0 $script } set TEST_NAME "K_MARKER11" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that prints the format string of a # marker. set script [format $kernel_script_arg \ [lindex $kernel_marker_names 0] {\$format}] stap_compile $TEST_NAME 1 $script } set TEST_NAME "K_MARKER12" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that writes to a marker format string # (which isn't allowed). set script [format $kernel_script_arg2 \ [lindex $kernel_marker_names 0] {\$format}] stap_compile $TEST_NAME 0 $script } set TEST_NAME "K_MARKER13" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that treats the marker format string as a # structure (which isn't allowed). set script [format $kernel_script_arg \ [lindex $kernel_marker_names 0] {\$format->foo}] stap_compile $TEST_NAME 0 $script } set TEST_NAME "K_MARKER14" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that treats the marker format string like # an array (which isn't allowed). set script [format $kernel_script_arg \ [lindex $kernel_marker_names 0] {\$format\[0\]}] stap_compile $TEST_NAME 0 $script } set TEST_NAME "K_MARKER15" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that specifies the marker format as a # wildcard. set script [format $kernel_format_script \ [lindex $kernel_marker_names 0] "*"] stap_compile $TEST_NAME 1 $script } set TEST_NAME "K_MARKER16" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that specifies the marker format. set script [format $kernel_format_script \ [lindex $kernel_marker_names 0] \ [lindex $kernel_marker_formats 0]] stap_compile $TEST_NAME 1 $script } set TEST_NAME "K_MARKER17" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that specifies the wrong marker format. set script [format $kernel_format_script \ [lindex $kernel_marker_names 0] "foo"] stap_compile $TEST_NAME 0 $script } set TEST_NAME "K_MARKER18" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that prints the name string of a # marker. set script [format $kernel_script_arg \ [lindex $kernel_marker_names 0] {\$name}] stap_compile $TEST_NAME 1 $script } set TEST_NAME "K_MARKER19" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that writes to a marker name string # (which isn't allowed). set script [format $kernel_script_arg2 \ [lindex $kernel_marker_names 0] {\$name}] stap_compile $TEST_NAME 0 $script } set TEST_NAME "K_MARKER20" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that treats the marker name string as a # structure (which isn't allowed). set script [format $kernel_script_arg \ [lindex $kernel_marker_names 0] {\$name->foo}] stap_compile $TEST_NAME 0 $script } set TEST_NAME "K_MARKER21" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that treats the marker name string like # an array (which isn't allowed). set script [format $kernel_script_arg \ [lindex $kernel_marker_names 0] {\$name\[0\]}] stap_compile $TEST_NAME 0 $script } set TEST_NAME "K_MARKER22" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that print $$parms. set script_vars {"probe kernel.mark(\"*\") { printf(\"%s\",\$\$parms) }"} stap_compile $TEST_NAME 1 $script_vars } set TEST_NAME "K_MARKER23" if {$kernel_markers_found == 0} { untested "$TEST_NAME : no kernel markers present" } else { # Try compiling a script that print $$vars. set script_parms {"probe kernel.mark(\"*\") { printf(\"%s\",\$\$vars) }"} stap_compile $TEST_NAME 1 $script_parms } systemtap-2.3/testsuite/systemtap.base/maxactive.exp000066400000000000000000000035431217430427200231100ustar00rootroot00000000000000# maxactive.exp # # Check to see if using the 'maxactive(N)' limit on return probes # works, by seeing if skipped probes increases when using it. if {![installtest_p]} { untested "MAXACTIVE"; return } proc sleep_one_sec {} { after 1000; return 0; } # Script1. For 1 second, probe the return of "vfs_read" and # "do_select". See if we skip any probes. set script1 { global foo probe kernel.function("vfs_read").return, kernel.function("do_select").return { foo++ } probe timer.ms(1000) { exit(); } probe begin { log("systemtap starting probe"); log("systemtap ending probe");} } # Run script1 and save the number of skipped probes (which will most # likely be 0). stap_run "MAXACTIVE01" sleep_one_sec "" -e $script1 set skipped1 $skipped_probes # Script2. For 1 second, probe the return of "vfs_read" and # "do_select", with a limit of 1 probe active at a time. See if we # skip any probes. set script2 { global foo probe kernel.function("vfs_read").return.maxactive(1), kernel.function("do_select").return.maxactive(1) { foo++ } probe timer.ms(1000) { exit(); } probe begin { log("systemtap starting probe"); log("systemtap ending probe");} } # Run script2 and save the number of skipped probes. set output_string "(WARNING: Number of errors: 0, skipped probes: \\d+\r\n)?" stap_run "MAXACTIVE02" sleep_one_sec $output_string -e $script2 set skipped2 $skipped_probes # If the number of skipped probes for script 1 is less than the number # of skipped probes for script 2, we can assume that "maxactive(N)" is # working. # # Note that this isn't 100% accurate based on the system load at the # time of the scripts. set test "MAXACTIVE03" verbose -log "skipped1: $skipped1, skipped2: $skipped2\n" if {$skipped1 <= $skipped2} { pass $test } else { fail "$test ($skipped1 skipped probes > $skipped2 skipped probes)" } systemtap-2.3/testsuite/systemtap.base/maxmemory.exp000066400000000000000000000013461217430427200231440ustar00rootroot00000000000000if {![installtest_p]} {untested "MAXMEMORY"; return} set script { global k probe begin { print("systemtap starting probe\n") k["foo"] = 0 } probe kernel.function("vfs_read"), kernel.function("vfs_write") { k["foo"]++ } probe end { print("systemtap ending probe\n") } } # MAXMEMORY1 tests to make sure normal operation doesn't receive a # max memory error set test "MAXMEMORY1" set error {[^\r]+ allocation failed} stap_run_error $test 0 $error "" -u -e $script # MAXMEMORY2 is the same script, but we're adjusting STP_MAXMEMORY to # a low value so that we *will* get an allocation error or an insert # module error. set test "MAXMEMORY2" stap_run_error $test 1 $error "" -u -DSTP_MAXMEMORY=200 -e $script systemtap-2.3/testsuite/systemtap.base/modargs.exp000066400000000000000000000013411217430427200225550ustar00rootroot00000000000000# This test is to check that modargs work fine # Tests initialized and uninitialized global variables, string/number set test "modargs" # precompile the script module set compile { exec stap $srcdir/$subdir/$test.stp -p4 -w } if { [catch { set module [eval $compile] } msg ] } { fail "$test compilation: $msg" untested "$test module arguments" continue } else { pass "$test compilation" } set test "modargs execution" if {! [installtest_p]} { untested $test; return } set ::result_string {initializedname=foo initializednumber=999 name=charley number=-1} set res [ exec staprun $module $::result_string ] if {[string compare $res $::result_string] == 0} { pass "$test" } else { fail "$test, result: $res" } systemtap-2.3/testsuite/systemtap.base/modargs.stp000066400000000000000000000003501217430427200225660ustar00rootroot00000000000000 global initializedname="bar" global initializednumber=0 global name global number probe begin { printf ("initializedname=%s initializednumber=%d name=%s number=%d", initializedname, initializednumber, name, number); exit(); } systemtap-2.3/testsuite/systemtap.base/modinfo.exp000066400000000000000000000007341217430427200225610ustar00rootroot00000000000000set test modinfo set module [exec stap --modinfo foo=bar -p4 -e "probe begin { exit() }"] if [file exists $module] { pass "$test compilation" } else { fail "$test compilation"; return } set ok 0 set ko 0 spawn /sbin/modinfo $module expect { -re {^foo:[ ]*bar\r\n} { incr ok; exp_continue } -re {^[a-zA-Z0-9_]*:[^\r\n]*\r\n} { exp_continue } eof { } } catch { close }; catch { wait } if {$ok == 1} { pass "$test modinfo" } else { fail "$test modinfo ($ok $ko)" } systemtap-2.3/testsuite/systemtap.base/net-sanity.exp000066400000000000000000000014001217430427200232100ustar00rootroot00000000000000# Testcase for various embedded-C functions in tcp.stp and netfilter.stp. set file $srcdir/$subdir/net-sanity.stp foreach value {0 0xffffffff 0xffffffffffffffff} { foreach ix {0 1 2 3 4} { set test "net-sanity $value $ix" if {![installtest_p]} {untested $test; continue} spawn stap $file $value $ix set errs 0 verbose -log "exp $test $errs" expect { -timeout 180 -re {(ERROR)[^\r\n]*\r\n} { incr errs; exp_continue } eof { } timeout { fail "$test (timeout)" } } verbose -log "done exp $test $errs" catch {close}; catch {wait} if {$errs == 1} { pass $test } else { fail "$test ($errs)" } verbose -log "done $test $errs" } } systemtap-2.3/testsuite/systemtap.base/net-sanity.stp000066400000000000000000000006541217430427200232340ustar00rootroot00000000000000#! stap # Test sensitive embedded-C functions with nonsense values! probe begin(-1) { print("\n") } probe begin { if ($2 == 0) print(__ip6_skb_proto($1)) else if ($2 == 1) print(__get_skb_tcphdr($1)) else if ($2 == 2) print(__get_skb_iphdr($1)) else if ($2 == 3) print(tcp_ts_get_info_snd_ssthresh($1)) else if ($2 == 4) print(tcp_ts_get_info_rcv_mss($1)) } probe begin(1) { print("\n"); exit() } systemtap-2.3/testsuite/systemtap.base/not.exp000066400000000000000000000004631217430427200217250ustar00rootroot00000000000000# Simple function to test that systemtap binary not works set test "not" foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string \ --runtime=$runtime } else { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string } } systemtap-2.3/testsuite/systemtap.base/not.stp000066400000000000000000000005161217430427200217360ustar00rootroot00000000000000/* * neg.stp * * Check that systemtap negation works */ global x2, x1 probe begin { println("systemtap starting probe") x1 = 0xaaaaaaaaaaaaaaaa } probe end { println("systemtap ending probe") x2 = ~x1 if ( x2 != 0x5555555555555555 ) { println("systemtap test failure") } else { println("systemtap test success") } } systemtap-2.3/testsuite/systemtap.base/onoffprobe.exp000066400000000000000000000030431217430427200232610ustar00rootroot00000000000000set test "onoffprobe" if {![installtest_p]} { untested $test; return } spawn stap $srcdir/$subdir/$test.stp set pid $spawn_id set ok 0 proc advance {} { global test global expect_out global ok global modname set procfs_file "/proc/systemtap/$modname/switch" pass "$test $expect_out(1,string)" # If this is the first time, wait until the procfs file exists # (for up to 10 seconds). if {$ok == 0} { set i 0 while {![file exists $procfs_file]} { sleep 1 incr i if {$i >= 10} { break } } # If the procfs file still doesn't exist, fail. if {![file exists $procfs_file]} { fail "$test (missing procfs file)" } } incr ok if {[file exists $procfs_file]} { exec echo $ok > $procfs_file } exec echo dummy > /dev/null exp_continue } expect { -timeout 240 -re {(begin1 probed): ([^\r\n]+)\r\n} { set modname "$expect_out(2,string)"; advance } -re "(function return probed)\r\n" { advance } -re "(function entry probed)\r\n" { advance } -re "(timer probed)\r\n" { advance } -re "(profile probed)\r\n" { advance } -re "(alias\.one\.a and alias\.one and alias\.\* probed)\r\n" { advance } -re "(alias\.one\.b and alias\.one and alias\.\* probed)\r\n" { advance } -re "(alias\.two and alias\.\* probed)\r\n" { pass "$test $expect_out(1,string)" incr ok } timeout { fail "$test (timeout)" } eof { } } exec kill -INT -[exp_pid] #FIXME does not handle case of hanging pfaults.stp correctly wait exec rm -f $test.ko if {$ok != 8} {fail "conditional probes ($ok)"} systemtap-2.3/testsuite/systemtap.base/onoffprobe.stp000066400000000000000000000020411217430427200232700ustar00rootroot00000000000000global switch=-1 #begin probe probe begin if (switch==-1) { printf("begin1 probed: %s\n", module_name()); } probe begin if (switch==0) { log("begin2 probed"); } #dwarf probe (return) probe kernel.function("vfs_write").return if (switch == 1) { log("function return probed") switch = 0 } #dwarf probe (entry) probe kernel.function("vfs_write").return if (switch == 2) { log("function entry probed") switch = 0 } #timer probe probe timer.ms(100) if (switch == 3) { log("timer probed") switch = 0 } #profile probe probe timer.profile if (switch == 4) { log("profile probed") switch = 0 } # aliasess probe alias.one.a = timer.ms(150) if (switch == 5) { print("alias.one.a and") } probe alias.one.b = timer.ms(200) if (switch == 6) { print("alias.one.b and") } probe alias.one = alias.one.* if (switch >= 5 && switch < 7) { print(" alias.one and") } probe alias.two = timer.ms(250) if (switch == 7) { print("alias.two and") } probe alias.* if (switch) { log(" alias.* probed") } probe procfs("switch").write { switch = strtol($value, 10) } systemtap-2.3/testsuite/systemtap.base/optim.exp000066400000000000000000000010221217430427200222450ustar00rootroot00000000000000set test "optim" if {![installtest_p]} { untested $test; return } foreach runtime [get_runtime_list] { set test "optim" if {$runtime != ""} { lappend test "($runtime)" spawn stap --runtime=$runtime $srcdir/$subdir/optim.stp } else { spawn stap $srcdir/$subdir/optim.stp } set ok 0 expect { -timeout 120 -re {i=1} { incr ok ; exp_continue } -re {j=2} { incr ok } timeout { fail "$test (timeout)" } eof { } } catch { close }; catch { wait } if {$ok == 2} { pass $test } { fail $test } } systemtap-2.3/testsuite/systemtap.base/optim.stp000066400000000000000000000003511217430427200222630ustar00rootroot00000000000000global array function func(i) { array[i++] = 0; return i; } function bart() { # rhbz# 300121 if (1) var=2 else dummy=0 return var } probe begin { printf ("i=%d\n", func(0)) printf ("j=%d\n", bart()) exit () } systemtap-2.3/testsuite/systemtap.base/optim_arridx.exp000066400000000000000000000030561217430427200236270ustar00rootroot00000000000000# test integer limits. Set and print variables and print constants. set test "optim_arridx" set ::result_string {# globals arr1:long [long, long] arr2:long [long] arr3:long [long] elide_idx1:long elide_global_a:long elide_global_b:long # functions exit:unknown () %{ /* unprivileged */ atomic_set (session_state(), STAP_SESSION_STOPPING); _stp_exit (); %} fna:long (a:long) return a fnb:long (a:long, b:long) return (a) + (b) # probes begin /* <- begin */ # locals idx2:long j:long k:long b:long m:long aa:long bb:long cc:long dd:long ee:long { (arr2[(elide_idx1) = (1)]) = (10) (arr2[(idx2) = (2)]) = (20) (arr2[3]) = (30) (arr2[(j) = (4)]) = (40) (arr1[fna((k) = (0)), k]) = (1) (arr1[(b) = (1), b]) = (2) (arr1[2, 2]) = (3) (arr3[0]) = (4) (m) = (1) for (2; (m) <= (10); (m)++) (arr2[m]) = ((m) * (10)) printf("%d %d %d %d\\n", arr1[0, 0], arr2[0], idx2, j) (aa) = (fna(1)) (bb) = (fnb((cc) = (1), (elide_global_a) = (2))) for (1; (bb) < (10); (bb)++) (cc) += (bb) for ((dd) = (1); (dd) < (10); 1) (dd) += (1) if ((elide_global_b) = (1)) (ee) = (1) (cc) = ((dd) = (5)) (cc) = ((4) + ((cc) = (1))) printf("%d %d %d %d %d\\n", aa, bb, cc, dd, ee) exit() } end /* <- end */ # locals idx0:long val:long { foreach (val = [idx0] in arr3-) printf("arr3[%#d]=%#x\\n", idx0, val) } end /* <- end */ { printf("elide_idx1=%#x\\n", elide_idx1) } end /* <- end */ { printf("elide_global_a=%#x\\n", elide_global_a) } end /* <- end */ { printf("elide_global_b=%#x\\n", elide_global_b) } } stap_run_exact $test $srcdir/$subdir/$test.stp -p2 -v 2>/dev/null systemtap-2.3/testsuite/systemtap.base/optim_arridx.stp000066400000000000000000000016611217430427200236410ustar00rootroot00000000000000global arr1, arr2, arr3, elide_idx1, elide_global_a, elide_global_b function fna(a:long) {return a} function fnb(a:long, b:long) {return a+b} probe begin { // array indices arr2[elide_idx1 = 1] = 10 arr2[idx2 = 2] = 20 arr2[elide_i=3] = 30 arr2[j=4] = 40 arr1[fna(k = 0), k] = 1 arr1[b = 1, b] = 2 arr1[elide_c = 2,2] = 3 fnb(arr3[0] = 4, arr3[0]) m = 1 for (elide_n=2; m <= 10; m++) arr2[m] = m * 10 printf ("%d %d %d %d\n", arr1[0,0], arr2[0], idx2, j) // function args aa = fna(elide_aa = 1) bb = fnb(cc = 1, elide_global_a = 2) // loop for (elide_bb = 1; bb < 10; bb++) cc += bb for (dd = 1; dd < 10; elide_ee = 1) dd += 1 // conditional if (elide_ff = 0) elide_ff = 1 if (elide_global_b = 1) ee = 1 // compound assignment cc = elide_gg=dd=5 // binary expression cc = ((elide_hh = 4) + (cc = 1)) printf("%d %d %d %d %d\n", aa, bb, cc, dd, ee) exit () } systemtap-2.3/testsuite/systemtap.base/optim_voidstmt.exp000066400000000000000000000005111217430427200242000ustar00rootroot00000000000000# Make sure that optimization works with void statements set test "optim_voidstmt" foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string \ --runtime=$runtime -w -g } else { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string -w -g } } systemtap-2.3/testsuite/systemtap.base/optim_voidstmt.stp000066400000000000000000000045661217430427200242300ustar00rootroot00000000000000/* * optim_voidstmt.stp * * Verify statement optimizations in void contexts. */ /* The printfs here force it not to be pure. */ function goodL() { printf(""); return 1 } function goodS() { printf(""); return "1" } /* These two functions lie about being pure, so they should be optimized out. * If they get called, you get an error, and the test fails. */ function badL:long() %{ /* pure */ CONTEXT->last_error = "NOSEE"; %} function badS:string() %{ /* pure */ CONTEXT->last_error = "NOSEE"; %} function fn1(x) { return x } function fn2(x, y) { return x * y } probe begin { println("systemtap starting probe") } probe end { println("systemtap ending probe") // most of these wouldn't have been optimized before, because part of the // expression has an apparant side-effect in the good* calls // unary numeric operators (+(goodL() + badL())) (-(goodL() + badL())) (!(goodL() + badL())) (~(goodL() + badL())) // binary numeric operators goodL() * badL() goodL() / badL() goodL() % badL() goodL() + badL() goodL() - badL() goodL() >> badL() goodL() << badL() goodL() & badL() goodL() ^ badL() goodL() | badL() goodL() < badL() goodL() > badL() goodL() <= badL() goodL() >= badL() goodL() == badL() goodL() != badL() // logical operators goodL() && badL() badL() && badL() goodL() || badL() badL() || badL() // ternary operator goodL() ? badL() : goodL() goodL() ? goodL() : badL() badL() ? badL() : badL() // binary string operators goodS() . badS() goodS() < badS() goodS() > badS() goodS() <= badS() goodS() >= badS() goodS() == badS() goodS() != badS() // string-printing sprintf("%d\n", goodL() + badL()) sprintf("%d %d %s %s\n", goodL(), badL(), goodS(), badS()) // function calls fn1(badL() + goodL()) fn2(badL(), goodL()) // something complex, but harmless enough that only // the good* calls should survive fn1(fn2(goodL() - strlen(badL() + badL() * badL() / strlen(goodS()) ? badS() . badS() . sprint(badL()) : sprint(badL(), badS())), badL() < badL() || badS() == badS()) + goodL() % strlen(goodS())) println("systemtap test success") } probe never { print(goodL(), badL(), goodS(), badS(), fn1(1), fn2(1, 1)) } systemtap-2.3/testsuite/systemtap.base/optionalprobe.exp000066400000000000000000000004141217430427200237760ustar00rootroot00000000000000set test "optionalprobe" spawn stap -p2 -w $srcdir/$subdir/$test.stp expect { -timeout 120 -re "# probes\r\n" { exp_continue } -re "^begin" { pass $test } eof { fail $test } timeout { fail "$test unexpected timeout" } } catch {close}; catch {wait} systemtap-2.3/testsuite/systemtap.base/optionalprobe.stp000077500000000000000000000005101217430427200240100ustar00rootroot00000000000000#! stap # test optional probe probe foo ?, process("/do/not/exist").function("main") !, kernel.mark("no such mark") ?, kernel.trace("no trace") !, process.foo ?, kernel.statement("no statement") !, module("no mod").function("*") ?, kernel.function("no such func*") !, begin { } systemtap-2.3/testsuite/systemtap.base/overcatcher.exp000066400000000000000000000006131217430427200234270ustar00rootroot00000000000000# make sure that we don't overcatch -- return and next should be able to break # out of a try/catch block. PR11664 set test "overcatcher" set ::result_string {return next } foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run_exact "$test ($runtime)" $srcdir/$subdir/$test.stp \ --runtime=$runtime } else { stap_run_exact $test $srcdir/$subdir/$test.stp } } systemtap-2.3/testsuite/systemtap.base/overcatcher.stp000066400000000000000000000007041217430427200234420ustar00rootroot00000000000000# make sure that we don't overcatch -- return and next should be able to break # out of a try/catch block. PR11664 probe begin { f() try { println("next") next } catch { println("next-catch") } println("next-fallthrough") } function f() { try { println("return") return 0 } catch { println("return-catch") } println("return-fallthrough") } probe begin(1) { exit() } systemtap-2.3/testsuite/systemtap.base/overflow_error.exp000066400000000000000000000020331217430427200241740ustar00rootroot00000000000000# Test overflow errors point to the correct thing. set test "overflow_error" if {![installtest_p]} { untested $test; return } set error_msg1 "ERROR: Array overflow, check size limit (3) near identifier 'overflow1' at $srcdir/$subdir/$test.stp" set error_msg2 "ERROR: Array overflow, check size limit (5) near identifier 'overflow2' at $srcdir/$subdir/$test.stp" set exit_warning "WARNING: Number of errors: 2, skipped probes: 0" foreach runtime [get_runtime_list] { set test_name $test if {$runtime != ""} { lappend test_name "($runtime)" spawn stap -DMAXERRORS=1 $srcdir/$subdir/$test.stp } else { spawn stap -DMAXERRORS=1 $srcdir/$subdir/$test.stp } set pass 0 expect { -timeout 60 $error_msg1 {incr pass; exp_continue} $error_msg2 {incr pass; exp_continue} $exit_warning {incr pass; exp_continue} timeout { exec kill -INT -[exp_pid] fail "$test_name timed out" } eof {} } catch { close }; catch { wait } if {$pass == 3} { pass $test_name } else { fail "$test_name ($pass)" } } systemtap-2.3/testsuite/systemtap.base/overflow_error.stp000066400000000000000000000005121217430427200242060ustar00rootroot00000000000000# overflow some stuff to see if error message point to the correct thing. global count; global overflow1[3]; global overflow2[5]; probe timer.ms(10) { if (count <= 3) { overflow1[count++] = gettimeofday_ns(); } else { overflow2[count++] <<< gettimeofday_ns(); } } probe timer.s(3) { exit(); } systemtap-2.3/testsuite/systemtap.base/overload.exp000066400000000000000000000023101217430427200227310ustar00rootroot00000000000000if {![installtest_p]} {untested "OVERLOAD"; return} set script { global k probe begin { print("systemtap starting probe\n") k["foo"] = 0 } probe kernel.function("vfs_read"), kernel.function("vfs_write") { k["foo"]++ } probe end { print("systemtap ending probe\n") } } # OVERLOAD1 tests to make sure normal operation doesn't receive an # overload indication set test "OVERLOAD1" set error "probe overhead exceeded threshold" stap_run_error $test 0 $error "" -u -e $script # OVERLOAD2 is the same script, but we're adjusting the # STP_OVERLOAD_INTERVAL and STP_OVERLOAD_THRESHOLD to low values so # that we *will* get an overload. set test "OVERLOAD2" stap_run_error $test 1 $error "" -u -DSTP_OVERLOAD_INTERVAL=1000LL -DSTP_OVERLOAD_THRESHOLD=100LL -e $script # OVERLOAD3 is the same script with the same low STP_OVERLOAD_INTERVAL # and STP_OVERLOAD_THRESHOLD values, but we're also specifying # STP_NO_OVERLOAD, which should turn overload processing off. So, # even though we have low overhead tuning values, we *shouldn't* # overload. set test "OVERLOAD3" stap_run_error $test 0 $error "" -u -DSTP_NO_OVERLOAD -DSTP_OVERLOAD_INTERVAL=1000LL -DSTP_OVERLOAD_THRESHOLD=100LL -e $script systemtap-2.3/testsuite/systemtap.base/partial-class-type-heap.cxx000066400000000000000000000004001217430427200255530ustar00rootroot00000000000000#include "partial-class-type.hxx" size_t Heap::header_size () { return 42; } Heap::Heap() { _size = header_size () + 32; _memory = (char *) malloc (_size); } void* Heap::allocate(size_t size) { _size += size; return _memory + header_size(); } systemtap-2.3/testsuite/systemtap.base/partial-class-type-main.cxx000066400000000000000000000002451217430427200255710ustar00rootroot00000000000000#include "partial-class-type.hxx" int size (int resize) { return (int)Heap::header_size() - resize; } int main (int argc, char **argv) { return size (argc); } systemtap-2.3/testsuite/systemtap.base/partial-class-type.exp000066400000000000000000000025301217430427200246400ustar00rootroot00000000000000set test "partial-class-type" # PR14434 dwflpp sometimes caches incomplete class_type proc error_handler { res message } { global verbose test if { $res == 0 } { verbose $message 2 fail "$test $message" return 1 } else { pass "$test $message" return 0 } } set srcpath "$srcdir/$subdir" set res [target_compile $srcpath/partial-class-type-heap.cxx "partial-class-type-heap.o" object "compiler=g++ additional_flags=-g additional_flags=-O2"] if { [error_handler [expr {$res==""}] "partial-class-type-heap.cxx"] } { return } set res [target_compile $srcpath/partial-class-type-main.cxx "partial-class-type-main.o" object "compiler=g++ additional_flags=-g additional_flags=-O2"] if { [error_handler [expr {$res==""}] "partial-class-type-main.cxx"] } { return } set res [target_compile "partial-class-type-main.o partial-class-type-heap.o" "partial-class-type" executable "compiler=g++ additional_flags=-g additional_flags=-O2"] if { [error_handler [expr {$res==""}] "partial-class-type"] } { return } set script {"probe process(\"./partial-class-type\").function(\"main\") { printf(\"_size member offset: %d\\n\", &@cast(0, \"Heap\")->_size); }"} # Try compiling a couple of times, to make sure we always pick the right DIE. # See PR14434 for the non-determinism. for {set i 0} {$i < 7} {incr i} { stap_compile $test-$i 1 $script -p2 } systemtap-2.3/testsuite/systemtap.base/partial-class-type.hxx000066400000000000000000000002571217430427200246570ustar00rootroot00000000000000#include class Heap { private: char *_memory; size_t _size; public: Heap(); void* allocate (size_t size); static size_t header_size(); }; systemtap-2.3/testsuite/systemtap.base/perf.exp000066400000000000000000000113321217430427200220560ustar00rootroot00000000000000set test "perf" if {! [installtest_p]} { untested "$test"; return } proc cleanup_handler { verbose } { catch {exec rm -f towers.x} } set stap_path $env(SYSTEMTAP_PATH)/stap set exepath "[pwd]/towers.x" set subtest "process()" set res [target_compile $srcdir/$subdir/towers.c $exepath executable ""] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test compiling towers.c" cleanup_handler $verbose return } else { pass "$test compiling towers.c" } spawn $stap_path -c $exepath -e " global towers_n global XXX_n probe perf.sw.task_clock.process(\"$exepath\") { towers_n += 1 } probe perf.sw.task_clock.process(\"XXX\") { XXX_n += 1 } " # there is no "XXX" process so this probe should have been ignored set ok 0 expect { -timeout 180 -re {towers_n=0x[0-9a-f][0-9a-f]} { incr ok; exp_continue } -re {XXX_n=0x0} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 2} { pass "$test $subtest" } else { fail "$test $subtest ($ok)" } set subtest "process" spawn $stap_path -c $exepath -e " global towers_n probe perf.sw.task_clock.process { towers_n += 1 } " set ok 0 expect { -timeout 180 -re {towers_n=0x[0-9a-f][0-9a-f]} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 1} { pass "$test $subtest" } else { fail "$test $subtest ($ok)" } set subtest "counter" target_compile $srcdir/$subdir/towers.c $exepath executable "additional_flags=-g" spawn $stap_path -c $exepath -e " global towers global main probe perf.hw.instructions.process(\"$exepath\").counter(\"a\") { counter_a += 1 } probe perf.hw.instructions.process(\"$exepath\").counter(\"b\") { counter_b += 1 } probe process(\"$exepath\").statement(\"towers@towers.c\") { towers <<< @perf(\"a\") } probe process(\"$exepath\").statement(\"main@towers.c\") { main <<< @perf(\"b\") } probe end { printf(\"count main=%d\\ncount towers=%d\\ncounter %d/%d\\n\", @count(main), @count(towers), counter_a, counter_b) printf(\"min main=%d\\nmin towers=%d\\n\", @min(main), @min(towers)) printf(\"max main=%d\\nmax towers=%d\\n\", @max(main), @max(towers)) } " set ok 0 expect { -timeout 180 -re {count main=1} { incr ok; exp_continue } -re {count towers=500} { incr ok; exp_continue } -re {min main=[0-9][0-9][0-9][0-9][0-9][0-9]} { incr ok; exp_continue } -re {min towers=[0-9][0-9][0-9][0-9][0-9][0-9]} { incr ok; exp_continue } -re {max main=[0-9][0-9][0-9][0-9][0-9][0-9]} { incr ok; exp_continue } -re {max towers=[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]} { incr ok; exp_continue } -re {not supported by this kernel} { # If this type of perf probe isn't supported by this kernel, # kfail the test. setup_kfail 15727 *-*-*; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} spawn $stap_path -c $exepath -e " global main global counter_a probe perf.hw.instructions.counter(\"a\") { counter_a += 1 } probe process(\"$exepath\").statement(\"main@towers.c\") { # counter \"a\" has no defined process so the default is $exepath main <<< @perf(\"a\") } probe end { printf(\"count main=%d\\n\", @count(main)) } " expect { -timeout 180 -re {count main=1} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 7} { pass "$test $subtest" } else { fail "$test $subtest ($ok)" } set subtest "error check" spawn $stap_path -e " global x probe perf.hw.cpu_cycles.process(\"$exepath\").counter(\"a\") {} probe process(\"$exepath\").function(\"main\") { # wrong type x = \"b\" . @perf(\"a\") }" set ok 0 expect { -timeout 180 -re {semantic error:.*type mismatch.*long vs. string} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} spawn $stap_path -e " global x probe perf.hw.cpu_cycles.process(\"/bin/ls\").counter(\"b\") {} probe process(\"$exepath\").function(\"main\") { # wrong process y = @perf(\"b\") }" expect { -timeout 180 -re {semantic error: perf counter 'b' not defined} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} spawn $stap_path -e " global x probe perf.hw.cpu_cycles.process(\"/bin/ls\").counter(\"a\") {} probe process(\"$exepath\").function(\"main\") { # wrong counter y = @perf(\"b\") }" expect { -timeout 180 -re {semantic error: perf counter 'b' not defined} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 3} { pass "$test $subtest" } else { fail "$test $subtest ($ok)" } cleanup_handler $verbose systemtap-2.3/testsuite/systemtap.base/plt.c000066400000000000000000000124741217430427200213570ustar00rootroot00000000000000#define _GNU_SOURCE #include #include #include #include #include #include #include #include #define SIZE 256 /* Examples from libc.info */ #if defined (LIBPLT2) || defined (NOLIBPLT) void * fatal (const char *ptr) { puts (ptr); exit (1); } void * xmalloc (size_t size) { register void *value = malloc (size); if (value == 0) fatal ("virtual memory exhausted"); return value; } char * savestring (const char *ptr) { size_t len = sizeof (ptr); register char *value = (char *) xmalloc (len + 1); value[len] = '\0'; return (char *) memcpy (value, ptr, len); } int open2 (char *str1, char *str2, int flags) { char *end; char *name = (char *) alloca (strlen (str1) + strlen (str2) + 1); end = stpcpy (stpcpy (name, str1), str2); return open (name, flags) && end == name; } int open3 (char *str1, char *str2, int flags) { char *end; char *name = (char *) malloc (strlen (str1) + strlen (str2) + 1); int desc; if (name == 0) fatal ("virtual memory exceeded"); end = stpcpy (stpcpy (name, str1), str2); desc = open (name, flags); free (name); return desc && end == str1; } char * basename2 (char *prog) { return basename (prog); } /* Define an array of critters to sort. */ struct critter { const char *name; const char *species; }; struct critter muppets[] = { {"Kermit", "frog"}, {"Piggy", "pig"}, {"Gonzo", "whatever"}, {"Fozzie", "bear"}, {"Sam", "eagle"}, {"Robin", "frog"}, {"Animal", "animal"}, {"Camilla", "chicken"}, {"Sweetums", "monster"}, {"Dr. Strangepork", "pig"}, {"Link Hogthrob", "pig"}, {"Zoot", "human"}, {"Dr. Bunsen Honeydew", "human"}, {"Beaker", "human"}, {"Swedish Chef", "human"} }; int count = sizeof (muppets) / sizeof (struct critter); /* This is the comparison function used for sorting and searching. */ int critter_cmp (const void *c1, const void *c2) { return strcmp (((const struct critter*)c1)->name, ((const struct critter*)c2)->name); } /* Print information about a critter. */ void print_critter (const struct critter *c) { printf ("%s, the %s\n", c->name, c->species); } /* Do the lookup into the sorted array. */ void find_critter (const char *name) { struct critter target, *result; target.name = name; result = bsearch (&target, muppets, count, sizeof (struct critter), critter_cmp); if (result) print_critter (result); else printf ("Couldn't find %s.\n", name); } int critters (void) { int i; for (i = 0; i < count; i++) print_critter (&muppets[i]); printf ("\n"); qsort (muppets, count, sizeof (struct critter), critter_cmp); for (i = 0; i < count; i++) print_critter (&muppets[i]); printf ("\n"); find_critter ("Kermit"); find_critter ("Gonzo"); find_critter ("Janice"); return 0; } typedef struct { char *name; } Widget; int print_widget (FILE *stream, const struct printf_info *info, const void *const *args) { const Widget *w; char *buffer; int len; /* Format the output into a string. */ w = *((const Widget **) (args[0])); len = asprintf (&buffer, "", w, w->name); if (len == -1) return -1; /* Pad to the minimum field width and print to the stream. */ len = fprintf (stream, "%*s", (info->left ? -info->width : info->width), buffer); /* Clean up and return. */ free (buffer); return len; } /* Type of a printf specifier-arginfo function. INFO gives information about the format specification. N, ARGTYPES, *SIZE has to contain the size of the parameter for user-defined types, and return value are as for parse_printf_format except that -1 should be returned if the handler cannot handle this case. This allows to partially overwrite the functionality of existing format specifiers. */ int print_widget_arginfo (const struct printf_info *info, size_t n, int *argtypes) { /* We always take exactly one argument and this is a pointer to the structure.. */ if (n > 0) argtypes[0] = PA_POINTER; return 1; } int widgets (void) { /* Make a widget to print. */ Widget mywidget; mywidget.name = "mywidget"; /* Register the print function for widgets. */ register_printf_function ('W', print_widget, print_widget_arginfo); /* Now print the widget. */ printf ("|%W|\n", &mywidget); printf ("|%35W|\n", &mywidget); printf ("|%-35W|\n", &mywidget); return; } int datetime (void) { char buffer[SIZE]; time_t curtime; struct tm *loctime; /* Get the current time. */ curtime = time (NULL); /* Convert it to local time representation. */ loctime = localtime (&curtime); /* Print out the date and time in the standard format. */ fputs (asctime (loctime), stdout); /* Print it out in a nice format. */ strftime (buffer, SIZE, "Today is %A, %B %d.\n", loctime); fputs (buffer, stdout); strftime (buffer, SIZE, "The time is %I:%M %p.\n", loctime); fputs (buffer, stdout); return 0; } #endif #if defined (LIBPLT1) || defined (NOLIBPLT) void zenme () { xmalloc (32); savestring ("abcdefghijklmnopqrstuvwxyz"); open2 ("/dev", "/null", O_RDONLY); open3 ("/dev", "/null", O_RDONLY); basename2 ("/dev/null"); critters(); widgets(); datetime(); } #endif #if defined (NOLIBPLT) || defined (ONLY_MAIN) int main () { zenme (); } #endif systemtap-2.3/testsuite/systemtap.base/plt.exp000066400000000000000000000134421217430427200217250ustar00rootroot00000000000000set test "plt" proc cleanup_handler { verbose } { if { $verbose == 0 } { catch {exec rm -f libplt1.so libplt2.so plt.x } } } proc error_handler { res test message } { global verbose if { $res == 0 } { verbose "$test $message" 2 fail "$test $message" return 1 } elseif { $message != "" } { pass $test return 0 } else {return 0} } if {![installtest_p]} {untested $test; return} if {![uprobes_p]} {untested $test; return} if {![utrace_p]} { untested "$test" cleanup_handler $verbose return } if {![regexp "^(x86_64|i.86)$" $::tcl_platform(machine)]} { untested "$test" cleanup_handler $verbose return } set stap_path $env(SYSTEMTAP_PATH)/stap set exepath "./plt.x" set F additional_flags set flags "$F=-I. $F=-shared $F=-fPIC $F=-DLIBPLT1 $F=-g $F=-Wno-deprecated-declarations $F=-Wno-format" set res [target_compile $srcdir/$subdir/plt.c ./libplt1.so executable $flags ] if { [error_handler [expr {$res == ""}] "target_compile libplt1.so" ""] } { return } set flags "$F=-I. $F=-shared $F=-fPIC $F=-DLIBPLT2 $F=-g $F=-Wno-deprecated-declarations $F=-Wno-format" set res [target_compile $srcdir/$subdir/plt.c ./libplt2.so executable $flags ] if { [error_handler [expr {$res == ""}] "target_compile libplt2.so" ""] } { return } set flags "$F=-Wl,-rpath,[pwd] $F=-L[pwd] $F=-lplt1 $F=-lplt2 $F=-DONLY_MAIN $F=-g $F=-Wno-deprecated-declarations $F=-Wno-format" set res [target_compile $srcdir/$subdir/plt.c $exepath executable $flags ] if { [error_handler [expr {$res == ""}] "target_compile plt.x" ""] } { return } # test process.plt set ok 0 spawn $stap_path -c $exepath -e "global calls probe process(\"./plt.x\").plt {calls\[\$\$name\] += 1} probe process(\"./libplt1.so\").plt {calls\[\$\$name\] += 1} probe process(\"./libplt2.so\").plt {calls\[\$\$name\] += 1} probe end {foreach (x in calls) printf (\"%s %d\\n\", x, calls\[x\])}" expect { -timeout 180 -re {__libc_start_main 1\r\n} { incr ok; exp_continue } -re {xmalloc 2\r\n} { incr ok; exp_continue } -re {savestring 1\r\n} { incr ok; exp_continue } -re {memcpy 1\r\n} { incr ok; exp_continue } -re {open2 1\r\n} { incr ok; exp_continue } -re {stpcpy 4\r\n} { incr ok; exp_continue } -re {open 2\r\n} { incr ok; exp_continue } -re {open3 1\r\n} { incr ok; exp_continue } -re {basename2 1\r\n} { incr ok; exp_continue } -re {__xpg_basename 1\r\n} { incr ok; exp_continue } -re {critters 1\r\n} { incr ok; exp_continue } -re {print_critter 32\r\n} { incr ok; exp_continue } -re {printf 36\r\n} { incr ok; exp_continue } -re {putchar 2\r\n} { incr ok; exp_continue } -re {qsort 1\r\n} { incr ok; exp_continue } -re {strcmp 51\r\n} { incr ok; exp_continue } -re {find_critter 3\r\n} { incr ok; exp_continue } -re {bsearch 3\r\n} { incr ok; exp_continue } -re {widgets 1\r\n} { incr ok; exp_continue } -re {register_printf_function 1\r\n} { incr ok; exp_continue } -re {asprintf 3\r\n} { incr ok; exp_continue } -re {fprintf 3\r\n} { incr ok; exp_continue } -re {datetime 1\r\n} { incr ok; exp_continue } -re {time 1\r\n} { incr ok; exp_continue } -re {localtime 1\r\n} { incr ok; exp_continue } -re {asctime 1\r\n} { incr ok; exp_continue } -re {fputs 3\r\n} { incr ok; exp_continue } -re {strftime 2\r\n} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch { close}; catch { wait} error_handler [expr {$ok == 28}] "plt" "($ok != 28)" # test process.library.plt set ok 0 spawn $stap_path -c $exepath -e "global calls probe process(\"./plt.x\").plt {calls\[\$\$name\] += 1} probe process(\"./plt.x\").library(\"*\").plt {calls\[\$\$name\] += 1} probe end {foreach (x in calls) printf (\"%s %d\\n\", x, calls\[x\])}" expect { -timeout 180 -re {__libc_start_main 1\r\n} { incr ok; exp_continue } -re {xmalloc 2\r\n} { incr ok; exp_continue } -re {savestring 1\r\n} { incr ok; exp_continue } -re {memcpy 1\r\n} { incr ok; exp_continue } -re {open2 1\r\n} { incr ok; exp_continue } -re {stpcpy 4\r\n} { incr ok; exp_continue } -re {open 2\r\n} { incr ok; exp_continue } -re {open3 1\r\n} { incr ok; exp_continue } -re {basename2 1\r\n} { incr ok; exp_continue } -re {__xpg_basename 1\r\n} { incr ok; exp_continue } -re {critters 1\r\n} { incr ok; exp_continue } -re {print_critter 32\r\n} { incr ok; exp_continue } -re {printf 36\r\n} { incr ok; exp_continue } -re {putchar 2\r\n} { incr ok; exp_continue } -re {qsort 1\r\n} { incr ok; exp_continue } -re {strcmp 51\r\n} { incr ok; exp_continue } -re {find_critter 3\r\n} { incr ok; exp_continue } -re {bsearch 3\r\n} { incr ok; exp_continue } -re {widgets 1\r\n} { incr ok; exp_continue } -re {register_printf_function 1\r\n} { incr ok; exp_continue } -re {asprintf 3\r\n} { incr ok; exp_continue } -re {fprintf 3\r\n} { incr ok; exp_continue } -re {datetime 1\r\n} { incr ok; exp_continue } -re {time 1\r\n} { incr ok; exp_continue } -re {localtime 1\r\n} { incr ok; exp_continue } -re {asctime 1\r\n} { incr ok; exp_continue } -re {fputs 3\r\n} { incr ok; exp_continue } -re {strftime 2\r\n} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch { close}; catch { wait} error_handler [expr {$ok == 28}] "plt library" "($ok != 28)" # test process.plt("glob") set ok 0 spawn $stap_path -c $exepath -e "global calls probe process(\"./libplt2.so\").plt(\"strcmp\") {calls\[\$\$name\] += 1} probe end {foreach (x in calls) printf (\"%s %d\\n\", x, calls\[x\])}" expect { -timeout 180 -re {strcmp 51\r\n} { incr ok; exp_continue } -re {printf 36\r\n} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch { close}; catch { wait} error_handler [expr {$ok == 1}] "plt glob" "($ok != 1)" cleanup_handler $verbose systemtap-2.3/testsuite/systemtap.base/pointer_array.exp000066400000000000000000000004231217430427200237770ustar00rootroot00000000000000set test "pointer_array" set ::result_string {/bin/true / b i n / t r u e 0} # Note this uses a user pointer to access the array, which # won't work on s390x. PR13467. if {[istarget s390x-*-*]} { setup_kfail 13467 [istarget] } stap_run2 $srcdir/$subdir/$test.stp -c/bin/true systemtap-2.3/testsuite/systemtap.base/pointer_array.stp000066400000000000000000000004731217430427200240160ustar00rootroot00000000000000probe kernel.function("do_execve") { if (pid() == target()) { println(user_string(@defined($__argv) ? $__argv[0] : $argv[0])) for (i=0; i<9; ++i) printf("%c\n", @defined($__argv) ? $__argv[0][i] : $argv[0][i]) println(@defined($__argv) ? $__argv[0][9] : $argv[0][9]) } } systemtap-2.3/testsuite/systemtap.base/poll_map.exp000066400000000000000000000004701217430427200227260ustar00rootroot00000000000000set test "poll_map" if {![installtest_p]} { untested $test; return } spawn stap -g $srcdir/$subdir/poll_map.stp set ok 0 expect { -timeout 400 -ex "SUCCESS" { incr ok } timeout { fail "$test (timeout)" } eof { } } catch { close } wait if {$ok == 1} { pass "$test ($ok)" } { fail "$test ($ok)" } systemtap-2.3/testsuite/systemtap.base/poll_map.stp000077500000000000000000000010061217430427200227370ustar00rootroot00000000000000#! stap # test that polling loops do not exit when conflicts happen # see PR 1379 global called, num_polls probe kernel.function( "vfs_*" ).call { called[execname(),probefunc()]++ } probe timer.ms(100) { print("\n\n") num_to_do = 10 foreach ([n,f] in called-) { printf("%s called %s\t%d times\n", n, f, called[n,f]) num_to_do-- if (num_to_do <= 0) break } delete called num_polls++ if (num_polls > 30) exit() } probe end { if (num_polls <= 30) print ("FAIL\n") else print ("SUCCESS\n") } systemtap-2.3/testsuite/systemtap.base/pp.exp000066400000000000000000000007211217430427200215410ustar00rootroot00000000000000# Simple function to test that pp() and pn() work proc opener {} { # the test uses syscall.open -- make sure it happens exec cat /dev/null return 0; } set test "pp" set file $srcdir/$subdir/pp.stp set output_string "(kernel\\.function\[^\r\n]*\r\n)+systemtap test success\r\n" stap_run $test opener $output_string $file $test set test "pn" set output_string "syscall\\.open\r\nsystemtap test success\r\n" stap_run $test opener $output_string $file $test systemtap-2.3/testsuite/systemtap.base/pp.stp000066400000000000000000000006271217430427200215600ustar00rootroot00000000000000/* * pp.stp * * Test that pp() and pn() output the right thing */ global hits probe begin { println("systemtap starting probe") } probe syscall.open { hits[$1()] <<< 1 } probe end { println("systemtap ending probe") foreach (s in hits) { ++count println(s) } if (count) println("systemtap test success"); else println("systemtap test failure"); } systemtap-2.3/testsuite/systemtap.base/pr10854.exp000066400000000000000000000021341217430427200221450ustar00rootroot00000000000000# This test is to make sure that we've resolved PR10854's race between probe # initialization and shutdown. Here we load a module and then kill the stapio # process as soon as we can to try to make the init and shutdown overlap. set test "pr10854" # precompile the script module set compile { exec stap $srcdir/$subdir/$test.stp sys_read vfs*@fs/*.c -p4 } if { [catch { set module [eval $compile] } msg ] } { fail "compiling $test.stp: $msg" untested "$test runloop" continue } else { pass "compiling $test.stp" } if {![installtest_p]} { untested "$test runloop" continue } # run & kill the module 10 times # (this was usually enough to trigger the fault) for {set i 0} {$i < 10} {incr i} { spawn staprun $module -o /dev/null sleep 1 catch { exec pkill stapio -P [pid] 2>/dev/null } catch { exec pkill -9 stapio -P [pid] 2>/dev/null } catch { close } catch { wait } # don't delay before the next staprun } # Killing stapio with SIGKILL can leave the module behind. catch { exec staprun -d $module } # if we're still alive, we pass :) pass "$test runloop" systemtap-2.3/testsuite/systemtap.base/pr10854.stp000066400000000000000000000010171217430427200221560ustar00rootroot00000000000000function trace(entry_p) { if(tid() in trace) printf("%s%s%s\n",thread_indent(entry_p), (entry_p>0?"->":"<-"), probefunc()) } global trace probe kernel.function(@1).call { if (pid() == stp_pid()) next # skip our own helper process trace[tid()] = 1 trace(1) } probe kernel.function(@1).return { if (pid() == stp_pid()) next # skip our own helper process trace(-1) delete trace[tid()] } probe kernel.function(@2).call { trace(1) } probe kernel.function(@2).return { trace(-1) } systemtap-2.3/testsuite/systemtap.base/pr13158.exp000066400000000000000000000030471217430427200221510ustar00rootroot00000000000000set TEST_NAME "pr13158" if {![installtest_p]} { untested $TEST_NAME; return } # This is a section of the original rename_module.exp test that caused # the problem of a systemtap module sticking around to be found. That # test case bug found a real problem - that staprun didn't handle # SIGINT. ########## Inserting 2 Identical Modules: Staprun without -R ################# # Should give an error when inserting 2 identical modules # when calling staprun directly without using -R set test "$TEST_NAME: Inserting 2 Identical Modules: Staprun without -R" set failed 0 set compile { exec stap -e {probe begin{printf("Hello\n");}} -p4 } set module_path [eval $compile] set module_name [file rootname [file tail $module_path]] spawn staprun $module_path set firstid $spawn_id spawn staprun $module_path set secondid $spawn_id # Make sure it fails expect { -re {^ERROR: Couldn't insert module .*: File exists\r\n} { exp_continue } -re {^ERROR: Rerun with staprun option '\-R' to rename this module.\r\n} { exp_continue } -re {^[^\r\n]*\r\n} { set failed 1 } } # Kill both of the hanging processes set firstpid [exp_pid -i $firstid] set secondpid [exp_pid -i $secondid] exec kill $firstpid exec kill $secondpid catch { wait -i $firstid; wait -i $secondid; close } if {$failed} { fail "$test" } else { pass "$test" } # Is the module still loaded? if {[catch { exec lsmod | grep -q $module_name }]} { pass "$TEST_NAME: module was correctly removed" } else { fail "$TEST_NAME: module is still loaded!" catch {exec staprun -d $module_name} } systemtap-2.3/testsuite/systemtap.base/pr13306.exp000066400000000000000000000040571217430427200221460ustar00rootroot00000000000000set test "pr13306" if {! [installtest_p]} { untested "$test" return } set test "pr13306 plain" spawn stap $srcdir/$subdir/pr13306.stp set ok 0 set ko 0 expect { -timeout 60 timeout { fail "$test (timeout)" } -re {^ERROR: [^\r\n]*\r\n} { incr ok; exp_continue } -re {^WARNING: Number of errors: [0-9]*[^\r\n]*\r\n} { incr ok; exp_continue } eof { } } if {$ok >= 2 && $ko == 0} then { pass $test } else { fail "$test ($ok $ko)" } catch { wait } ; catch { close } set test "pr13306 -t" spawn stap -t $srcdir/$subdir/pr13306.stp set ok 0 set ko 0 expect { -timeout 60 timeout { fail "$test (timeout)" } -re {^ERROR: [^\r\n]*\r\n} { incr ok; exp_continue } -re {^WARNING: Number of errors: [0-9]*[^\r\n]*\r\n} { incr ok; exp_continue } -re {^----- probe hit report: \r\n} { incr ok; exp_continue } -re {^[^\r\n]*hits:[^\r\n]*cycles:[^\r\n]*from:[^\r\n]*\r\n} { exp_continue } } if {$ok >=3 && $ko == 0} then { pass $test } else { fail "$test ($ok $ko)" } catch { wait } ; catch { close } set test "pr13306 --suppress-handler-errors" spawn stap --suppress-handler-errors $srcdir/$subdir/pr13306.stp set ok 0 set ko 0 expect { -timeout 60 timeout { fail "$test (timeout)" } -re {^ERROR: [^\r\n]*\r\n} { incr ko; exp_continue } -re {^WARNING: Number of errors: [0-9]*[^\r\n]*\r\n} { incr ok; exp_continue } eof { } } if {$ok == 1 && $ko == 0} then { pass $test } else { fail "$test ($ok $ko)" } catch { wait } ; catch { close } set test "pr13306 --suppress-handler-errors -t" spawn stap --suppress-handler-errors -t $srcdir/$subdir/pr13306.stp set ok 0 set ko 0 expect { -timeout 60 timeout { fail "$test (timeout)" } -re {^ERROR: [^\r\n]*\r\n} { incr ko; exp_continue } -re {^WARNING: Number of errors: [0-9]*[^\r\n]*\r\n} { incr ok; exp_continue } -re {^----- probe hit report: \r\n} { incr ok; exp_continue } -re {^[^\r\n]*hits:[^\r\n]*cycles:[^\r\n]*from:[^\r\n]*\r\n} { exp_continue } } if {$ok >= 2 && $ko == 0} then { pass $test } else { fail "$test ($ok $ko)" } catch { wait } ; catch { close } systemtap-2.3/testsuite/systemtap.base/pr13306.stp000066400000000000000000000001631217430427200221520ustar00rootroot00000000000000probe begin { error("look out") } probe timer.profile { error("the sky is falling!") } probe timer.s(4) { exit() } systemtap-2.3/testsuite/systemtap.base/pr14546.exp000066400000000000000000000031021217430427200221430ustar00rootroot00000000000000set test "pr14546" if {! [installtest_p]} { untested "$test" return } set test "pr14546 once" spawn stap $srcdir/$subdir/pr14546.stp "println(backtrace())" set ko 0 expect { -timeout 60 timeout { fail "$test (timeout)"; exec kill -INT -[exp_pid] } -re {^ERROR: [^\r\n]*\r\n} { incr ko; exp_continue } eof { } } if {$ko == 0} then { pass $test } else { fail "$test ($ko)" } catch { wait } ; catch { close } set test "pr14546 twice" spawn stap $srcdir/$subdir/pr14546.stp "println(backtrace()); println(backtrace())" set ko 0 expect { -timeout 60 timeout { fail "$test (timeout)"; exec kill -INT -[exp_pid] } -re {^ERROR: [^\r\n]*\r\n} { incr ko; exp_continue } eof { } } if {$ko == 0} then { pass $test } else { fail "$test ($ko)" } catch { wait } ; catch { close } set test "pr14546 thrice" spawn stap $srcdir/$subdir/pr14546.stp "println(backtrace()); println(backtrace()); println(backtrace())" set ko 0 expect { -timeout 60 timeout { fail "$test (timeout)"; exec kill -INT -[exp_pid] } -re {^ERROR: [^\r\n]*\r\n} { incr ko; exp_continue } eof { } } if {$ko == 0} then { pass $test } else { fail "$test ($ko)" } catch { wait } ; catch { close } set test "pr14546 followed by ubacktrace()" spawn stap $srcdir/$subdir/pr14546.stp "println(backtrace()); println(ubacktrace())" set ko 0 expect { -timeout 60 timeout { fail "$test (timeout)"; exec kill -INT -[exp_pid] } -re {^ERROR: [^\r\n]*\r\n} { incr ko; exp_continue } eof { } } if {$ko == 0} then { pass $test } else { fail "$test ($ko)" } catch { wait } ; catch { close } systemtap-2.3/testsuite/systemtap.base/pr14546.stp000066400000000000000000000003071217430427200221610ustar00rootroot00000000000000probe kernel.function("irq_*").call { x = 10; y = 10; z = 10; w = 10 $1 if (x != 10 || y != 10 || z != 10 || w != 10) error("memory got corrupted by " . @1) exit() } systemtap-2.3/testsuite/systemtap.base/prcwildcard.exp000066400000000000000000000013541217430427200234230ustar00rootroot00000000000000 set stap_path $env(SYSTEMTAP_PATH)/stap set test "prcwildcard function" # Looking for functions in stap will only work if it isn't stripped. if {[stripped_p $stap_path]} { untested $test } else { spawn stap -L "process(\"$stap_path\").function(\"*\")" set count 0 expect { -re {^process[^\r\n]+\r\n} { incr count; exp_continue } timeout { } eof { } } catch {close}; catch {wait} if {$count > 100} then { pass $test } else { fail $test } } set test "prcwildcard mark" spawn stap -L "process(\"$stap_path\").mark(\"*\")" set count 0 expect { -re {^process[^\r\n]+\r\n} { incr count; exp_continue } timeout { } eof { } } catch {close}; catch {wait} if {$count > 5} then { pass $test } else { fail $test } systemtap-2.3/testsuite/systemtap.base/prepost_optim.exp000066400000000000000000000012161217430427200240260ustar00rootroot00000000000000# PR11590 optimized pre/postfix operators on variable throw away # initial variable assignment set test "prepost_optim" if {![installtest_p]} {untested $test; return} foreach runtime [get_runtime_list] { set test_name $test if {$runtime != ""} { set test_name "${test}_${runtime}" spawn stap --runtime=$runtime $srcdir/$subdir/$test.stp } else { spawn stap $srcdir/$subdir/$test.stp } set ok 0 expect { -timeout 180 -re {5 7 7 5} { incr ok; exp_continue } timeout { fail "$test_name (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 1} { pass "$test_name ($ok)" } { fail "$test_name ($ok)" } } systemtap-2.3/testsuite/systemtap.base/prepost_optim.stp000066400000000000000000000004411217430427200240370ustar00rootroot00000000000000// PR11590 optimized pre/postfix operators on variable throw away // initial variable assignment probe begin { a = 5 // printf("%d ", a) printf("%d ", (a++)) printf("%d ", (++a)) printf("%d ", (a--)) printf("%d\n", (--a)) exit() } systemtap-2.3/testsuite/systemtap.base/preprocessor.exp000066400000000000000000000045421217430427200236550ustar00rootroot00000000000000 set kvr [exec uname -r] set kv [exec uname -r | cut -f1 -d-] # a pattern bound to match set kr {[23]?[0-9]*} # a pattern bound to mismatch set krx {?noSuchKernel*} set arch [exec uname -i] # normalize arch; PR4186 set arch [normalize_arch $arch] set ar "?[string range $arch 1 end-1]?" set arx {?noSuchArch?} # This test works so that if all the preprocessor conditionals # work as expected, stap will indicate no error. foreach runtime [get_runtime_list] { set test "preprocessor basic ops" if {$runtime != ""} { lappend test "($runtime)" set runtime_arg "--runtime=$runtime" } else { set runtime "kernel" set runtime_arg "" } spawn stap -w -p2 ${runtime_arg} -e "probe never {} %( kernel_v == \"$kv\" %? %: ERROR %) %( kernel_v == \"$kr\" %? %: ERROR %) %( kernel_v == \"$krx\" %? ERROR %: %) %( kernel_v != \"$kv\" %? ERROR %: %) %( kernel_v != \"$kr\" %? ERROR %: %) %( kernel_v != \"$krx\" %? %: ERROR %) %( kernel_v < \"9.9999\" %? %: ERROR %) %( kernel_v <= \"9.9999\" %? %: ERROR %) %( kernel_v > \"9.9999\" %? ERROR %: %) %( kernel_v >= \"9.9999\" %? ERROR %: %) %( kernel_vr == \"$kvr\" %? %: ERROR %) %( kernel_vr == \"$kr\" %? %: ERROR %) %( kernel_vr == \"$krx\" %? ERROR %: %) %( kernel_vr != \"$kvr\" %? ERROR %: %) %( kernel_vr != \"$kr\" %? ERROR %: %) %( kernel_vr != \"$krx\" %? %: ERROR %) %( kernel_vr < \"9.9999\" %? %: ERROR %) %( kernel_vr <= \"9.9999\" %? %: ERROR %) %( kernel_vr > \"9.9999\" %? ERROR %: %) %( kernel_vr >= \"9.9999\" %? ERROR %: %) %( arch == \"$arch\" %? %: ERROR %) %( arch == \"$ar\" %? %: ERROR %) %( arch == \"$arx\" %? ERROR %: %) %( arch != \"$arch\" %? ERROR %: %) %( arch != \"$ar\" %? ERROR %: %) %( arch != \"$arx\" %? %: ERROR %) %( runtime == \"$runtime\" %? %: ERROR %) %( runtime != \"$runtime\" %? ERROR %: %) %( runtime == \"noSuchRuntime\" %? ERROR %: %) %( runtime != \"noSuchRuntime\" %? %: ERROR %) " set ok 0 expect { "never" { incr ok } eof { } timeout { } } catch {close}; catch {wait} if {$ok == 1} { pass $test } { fail $test } } systemtap-2.3/testsuite/systemtap.base/print.exp000066400000000000000000000004451217430427200222610ustar00rootroot00000000000000# Test that all the print statements work set test "print" foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string \ --runtime=$runtime } else { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string } } systemtap-2.3/testsuite/systemtap.base/print.stp000066400000000000000000000013641217430427200222740ustar00rootroot00000000000000/* * print.stp * * Test that all the print statements work */ global s1, s2, s3 probe begin { println("systemtap starting probe") s1 = "systemtap" s2 = "test" s3 = "success" } probe end { println("systemtap ending probe") print(s1, " ", s2, " ", s3, "\n") print(sprint(s1, " ", s2, " ", s3, "\n")) println(s1, " ", s2, " ", s3) print(sprintln(s1, " ", s2, " ", s3)) printd(" ", s1, s2, s3 . "\n") print(sprintd(" ", s1, s2, s3 . "\n")) printdln(" ", s1, s2, s3) print(sprintdln(" ", s1, s2, s3)) // Check that formatting characters get escaped correctly // in the delimiter. s = sprintd("%% % \\ \"", 1, 2, 3) if (s == "1%% % \\ \"2%% % \\ \"3") println("systemtap test success") else println("systemtap test failure") } systemtap-2.3/testsuite/systemtap.base/probe_list.exp000066400000000000000000000014201217430427200232610ustar00rootroot00000000000000# This test ensures that "-l" lists only include probe names, and not any of # the local variables. There was a bug that "-l" would print variables that # couldn't be optimized away, due to an incorrect assumption in the # implementation. # NB: This is a bit abusively formed. Currently -l internally writes "probe" # and "{}" around its argument. For this test we want to introduce a variable # that can't be optimized away. The trailing comment mark lets the auto "{}" # get ignored. spawn stap -l "begin { if (a) next }#" set ok 0 expect { # the output should not include anything else, like the 'a' local. -re "^begin\r\n$" { incr ok } } catch {close}; catch {wait} if {$ok == 1} { pass "probe list is correct" } else { fail "probe list is incorrect" } systemtap-2.3/testsuite/systemtap.base/probefunc.exp000066400000000000000000000037171217430427200231150ustar00rootroot00000000000000# Test cases for probefunc() function proc grep {fd re } { while {[gets $fd s] >= 0} { if [regexp $re $s] { return $s } } } proc sleep_one_sec {} { after 1000; return 0; } set systemtap_script { global funcname probe %s { funcname = probefunc() exit() } probe begin { log("systemtap starting probe") } probe end { log("systemtap ending probe") printf("%%s\n", funcname) } } # open /proc/kallsyms to get address for scheduler_tick symbol set symf "/proc/kallsyms" set symfd [open $symf r] set re "\\mscheduler_tick\\M" set rs [grep $symfd $re] set flds [split $rs " "] set addr [lindex $flds 0] close $symfd set prefix "probefunc:" # test probefunc() with kernel.statement().absolute set output_string "\\mscheduler_tick\\M\r\n" set probepoint "kernel.statement(0x$addr).absolute" set script [format $systemtap_script $probepoint] stap_run "${prefix}.statement.(0xaddr).absolute" sleep_one_sec $output_string -g -e $script # test probefunc() with kernel.function() set probepoint "kernel.function(\"scheduler_tick\")" set script [format $systemtap_script $probepoint] stap_run $prefix$probepoint sleep_one_sec $output_string -e $script # test probefunc() with kernel.function().inline # NOTE probefunc inline behavior changed after 1.8. # # Notice we're keeping the name of the test the same # 'probefunc:kernel.function("context_switch").inline', but broadening # the test a bit to also include 'kernel.function("should_resched")' # for newer kernels. Keeping the name the same helps in comparing # results between releases. set output_string "\\m(context_switch|should_resched)\\M\r\n" set testname "kernel.function(\"context_switch\").inline" set probepoint "kernel.function(\"context_switch\").inline ?, kernel.function(\"should_resched\").inline ?" set script [format $systemtap_script $probepoint] stap_run $prefix$testname sleep_one_sec $output_string -e $script --compatible=1.8 systemtap-2.3/testsuite/systemtap.base/proc_exec.c000066400000000000000000000005351217430427200225220ustar00rootroot00000000000000#include #include int main(int argc, char **argv) { char *new_argv[] = { NULL, "3", NULL }; if (argc != 2) { fprintf(stderr, "Usage: %s exepath\n", argv[0]); return -1; } new_argv[0] = argv[1]; /* Actually run the command. */ if (execv(new_argv[0], new_argv) < 0) perror("execv"); _exit(1); } systemtap-2.3/testsuite/systemtap.base/proc_exec.exp000066400000000000000000000136011217430427200230720ustar00rootroot00000000000000# process exec tests. # value gets set later set test_exepath "" # "load" generation function for stap_run. It spawns our test # executable, which execs our copy of /bin/sleep. proc run_test_exe {} { global test_exepath global exepath spawn $test_exepath $exepath set exe_id $spawn_id after 5000 catch {close -i $exe_id} catch {wait -i $exe_id} return 0; } # Set up our own copy of /bin/sleep, to make testing for a particular # executable easy. We can't use 'ln' here, since we might be creating # a cross-device link. We can't use 'ln -s' here, since the kernel # resolves the symbolic link and reports that /bin/sleep is being # exec'ed (instead of our local copy). set exepath "[pwd]/sleep_[pid]" if {[catch {exec cp /bin/sleep $exepath} res]} { fail "unable to copy /bin/sleep: $res" return } # Note use of '%1$s' - the 'N$' is the 'argpos', the argument position # passed to 'format'. set test_script { global output global sleep_start, sleep_end probe begin { printf("systemtap starting probe\n") } probe process("%1$s").begin { output .= sprintf("exe(%%d) begin\n", tid()) } probe process("%1$s").thread.begin { output .= sprintf("exe(%%d) thread begin\n", tid()) } probe process("%1$s").end { output .= sprintf("exe(%%d) end\n", tid()) } probe process("%1$s").thread.end { output .= sprintf("exe(%%d) thread end\n", tid()) } probe process("%2$s").begin { sleep_start = gettimeofday_s() output .= sprintf("sleep(%%d) begin\n", tid()) } probe process("%2$s").end { output .= sprintf("sleep(%%d) end\n", tid()) sleep_end = gettimeofday_s() } probe end { printf("systemtap ending probe\n%%s", output) time_slept = sleep_end - sleep_start if (time_slept >= 2 && time_slept <= 4) printf("time slept: OK\n") else printf("time slept: ERROR (%%d)\n", time_slept) } } ####### # # Test a normal fork/exec pair. # set fork_exec_srcpath "$srcdir/systemtap.base/proc_fork_exec.c" set fork_exec_exepath "[pwd]/proc_fork_exec_[pid]" set fork_exec_flags "" # We make sure the outputs looks like the following using regexp # subexpressions: # exe(PARENT_PID) begin # exe(CHILD_PID) begin # exe(CHILD_PID) end # sleep(CHILD_PID) begin # sleep(CHILD_PID) end # exe(PARENT_PID) end # time slept: OK # # Accept the 'sleep(CHILD_PID)' end and 'exe(PARENT_PID) end' lines in # any order. set fork_exec_script_output "exe\\((\\d+)\\) begin\r\nexe\\((\\d+)\\) begin\r\nexe\\(\\2\\) end\r\nsleep\\(\\2\\) begin\r\n(sleep\\(\\2\\)|exe\\(\\1\\)) end\r\n(sleep\\(\\2\\)|exe\\(\\1\\)) end\r\ntime slept: OK\r\n" # Compile our program that forks/exec's /bin/sleep. set test_exepath $fork_exec_exepath set res [target_compile $fork_exec_srcpath $fork_exec_exepath executable $fork_exec_flags] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile $fork_exec_srcpath" return } set TEST_NAME "PROC_EXEC_01" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" } else { set script [format $test_script $fork_exec_exepath $exepath] stap_run $TEST_NAME run_test_exe $fork_exec_script_output -e $script } ####### # # Test a straight exec (no fork). # set exec_srcpath "$srcdir/systemtap.base/proc_exec.c" set exec_exepath "[pwd]/proc_exec_[pid]" set exec_flags "" # We make sure the outputs looks like the following using regexp # subexpressions: # exe(PID) begin # exe(PID) end # sleep(PID) begin # sleep(PID) end # time slept: OK set exec_script_output "exe\\((\\d+)\\) begin\r\nexe\\(\\1\\) end\r\nsleep\\(\\1\\) begin\r\nsleep\\(\\1\\) end\r\ntime slept: OK\r\n" # Compile our program that exec's /bin/sleep. set test_exepath $exec_exepath set res [target_compile $exec_srcpath $exec_exepath executable $exec_flags] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile $exec_srcpath" return } set TEST_NAME "PROC_EXEC_02" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" } else { set script [format $test_script $exec_exepath $exepath] stap_run $TEST_NAME run_test_exe $exec_script_output -e $script } ####### # # Test a multi-threaded exec, which programs aren't supposed to do, # but... # set thread_exec_srcpath "$srcdir/systemtap.base/proc_thread_exec.c" set thread_exec_exepath "[pwd]/proc_thread_exec_[pid]" set thread_exec_flags "libs=-lpthread" # We make sure the outputs looks like the following using regexp # subexpressions. # exe(PID1) begin # exe(PID2) thread begin # exe(PID1) thread end # exe(PID1) end # sleep(PID1) begin # sleep(PID1) end # time slept: OK # # Why no PID2 thread end and why isn't sleep using PID2? When the # thread calls exec (which it isn't supposed to do), the kernel has to # clean up the best it can. It really kills the original task, # promotes the thread to be the process group leader (and changes the # thread's pid to the original process group leader's pid). set thread_exec_script_output "exe\\((\\d+)\\) begin\r\nexe\\(\\d+\\) thread begin\r\nexe\\(\\1\\) thread end\r\nexe\\(\\1\\) end\r\nsleep\\(\\1\\) begin\r\nsleep\\(\\1\\) end\r\ntime slept: OK\r\n" # Compile our multi-threaded program that exec's /bin/sleep. set test_exepath $thread_exec_exepath set res [target_compile $thread_exec_srcpath $thread_exec_exepath executable $thread_exec_flags] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile $exec_srcpath" return } set TEST_NAME "PROC_EXEC_03" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" } else { set script [format $test_script $thread_exec_exepath $exepath] stap_run $TEST_NAME run_test_exe $thread_exec_script_output -e $script } # Cleanup exec rm -f $exepath $fork_exec_exepath $exec_exepath $thread_exec_exepath systemtap-2.3/testsuite/systemtap.base/proc_fork_exec.c000066400000000000000000000013001217430427200235320ustar00rootroot00000000000000#include #include #include #include int main(int argc, char **argv) { pid_t pid; int rstatus; char *new_argv[] = { NULL, "3", NULL }; if (argc != 2) { fprintf(stderr, "Usage: %s exepath\n", argv[0]); return -1; } new_argv[0] = argv[1]; pid = fork(); if (pid < 0) { perror("fork"); return -1; } if (pid == 0) /* child process */ { /* Actually run the command. */ if (execv(new_argv[0], new_argv) < 0) perror("execv"); _exit(1); } if (waitpid(pid, &rstatus, 0) < 0) { perror("waitpid"); return -1; } if (WIFEXITED(rstatus)) return WEXITSTATUS(rstatus); return -1; } systemtap-2.3/testsuite/systemtap.base/proc_thread_exec.c000066400000000000000000000007531217430427200240530ustar00rootroot00000000000000#include #include #include char *new_argv[] = { NULL, "3", NULL }; void *tfunc(void *arg) { /* Actually run the command. */ if (execv(new_argv[0], new_argv) < 0) perror("execv"); return NULL; } int main(int argc, char **argv) { pthread_t thr; if (argc != 2) { fprintf(stderr, "Usage: %s exepath\n", argv[0]); return -1; } new_argv[0] = argv[1]; pthread_create(&thr, NULL, tfunc, NULL); pause(); return 0; } systemtap-2.3/testsuite/systemtap.base/process_by_cmd.c000066400000000000000000000003511217430427200235420ustar00rootroot00000000000000#include "stdio.h" #include "sys/sdt.h" void third(){} void second(){third();} void first(){second();} int main() { l1: STAP_PROBE(process_by_cmd, main_start); first(); STAP_PROBE(process_by_cmd, main_end); return 0; } systemtap-2.3/testsuite/systemtap.base/process_by_cmd.exp000066400000000000000000000036471217430427200241270ustar00rootroot00000000000000set test "process_by_cmd" # Only run on make installcheck and uprobes present. if {! [installtest_p]} { untested "$test"; return } # Test for PR12427 [implied process("...") target for stap -c CMD # invocation]. # We've got a problem in testing all the 'process.*' probe # variants. Depending on the compiler, debuginfo generation, # optimization level, etc., the probes can get hit in different # orders. For instance, a 'process.function("main")' probe might get # hit before or after the first # 'process.statement("*@process_by_cmd.c")' probe (they sometimes get # inserted at the same address, but might get installed in different # orders). # # To ensure we're testing the right thing, this test has been split # into two subtests, so we can hopefully depend on the order output. set ::result_string {func end mark end func return end func return end func return end mark end func return end} set test_flags "additional_flags=-g" set test_flags "$test_flags [sdt_includes]" set res [target_compile $srcdir/$subdir/$test.c $test executable "$test_flags"] if {$res != ""} { verbose -log "target_compile failed: $res" 2 fail "$test.c compile" untested "$test" return } else { pass "$test.c compile" } foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run3 "${test}.stp ($runtime)" \ $srcdir/$subdir/${test}.stp -c ./$test --runtime=$runtime } elseif {[uretprobes_p]} { stap_run3 ${test}.stp $srcdir/$subdir/${test}.stp -c ./$test } else { untested ${test}.stp } } set ::result_string {state end func label end state end state end state end} foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run3 "${test}2.stp ($runtime)" \ $srcdir/$subdir/${test}2.stp -c ./$test --runtime=$runtime } elseif {[uprobes_p]} { stap_run3 ${test}2.stp $srcdir/$subdir/${test}2.stp -c ./$test } else { untested ${test}2.stp } } if { $verbose == 0 } { catch {exec rm -f $test} } systemtap-2.3/testsuite/systemtap.base/process_by_cmd.stp000066400000000000000000000002541217430427200241300ustar00rootroot00000000000000probe process.function("main") { printf("func end\n") } probe process.function("*").return { printf("func return end\n") } probe process.mark("*") { printf("mark end\n") } systemtap-2.3/testsuite/systemtap.base/process_by_cmd2.stp000066400000000000000000000002221217430427200242050ustar00rootroot00000000000000probe process.function("main").label("l1") { printf("func label end\n") } probe process.statement("*@process_by_cmd.c") { printf("state end\n") } systemtap-2.3/testsuite/systemtap.base/procfs.exp000066400000000000000000000053111217430427200224160ustar00rootroot00000000000000# Test cases for procfs probes set test "PROCFS" if {![installtest_p]} { untested $test; return } proc proc_read_value { test path} { set value "" if [catch {open $path RDONLY} channel] { fail "$test $channel" } else { set value [read -nonewline $channel] close $channel pass "$test read $value" } return $value } proc proc_write_value { test path value} { if [catch {open $path WRONLY} channel] { fail "$test $channel" } else { puts $channel $value close $channel pass "$test wrote $value" } } proc proc_read_write {} { global test set path "/proc/systemtap/$test/command" # read the initial value, which should be '100' set value [proc_read_value $test $path] if { $value == "100" } { pass "$test received correct initial value" } else { fail "$test received incorrect initial value: $value" } # write a new value of '200' proc_write_value $test $path "200" # make sure it got set to '200' set value [proc_read_value $test $path] if { $value == "200" } { pass "$test received correct value: 200" } else { fail "$test received incorrect value: $value" } # read it again to make sure nothing changed set value [proc_read_value "$test again" $path] if { $value == "200" } { pass "$test received correct value: 200 again" } else { fail "$test received incorrect value: $value again" } # write a new value of 'hello' proc_write_value $test $path "hello" # make sure it got set to 'hello' set value [proc_read_value $test $path] if { $value == "hello" } { pass "$test received correct value: hello" } else { fail "$test received incorrect value: $value" } # write a new value of 'goodbye' proc_write_value $test $path "goodbye" # make sure it got set to 'goodbye' set value [proc_read_value $test $path] if { $value == "goodbye" } { pass "$test received correct value: goodbye" } else { fail "$test received incorrect value: $value" } return 0; } # The script starts with a value of "100". If the user writes into # /proc/systemtap/MODNAME/command, that value is returned by the next # read. set systemtap_script { global saved_value probe procfs("command").read { $value = saved_value } probe procfs("command").write { saved_value = $value } probe begin { saved_value = "100\n" printf("systemtap starting probe\n") } probe end { printf("systemtap ending probe\n") printf("final value = %s", saved_value) } } # test procfs probes set output_string "\\mfinal value = goodbye\\M\r\n" stap_run $test proc_read_write $output_string -e $systemtap_script -m $test exec /bin/rm -f ${test}.ko systemtap-2.3/testsuite/systemtap.base/procfs_maxsize.exp000066400000000000000000000207371217430427200241670ustar00rootroot00000000000000# Handle varying sizes of procfs buffers. set test "PROCFS_BUFFER" if {![installtest_p]} { untested $test; return } proc proc_read_value { test path} { set value "" if [catch {open $path RDONLY} channel] { fail "$test $channel" } else { set value [read -nonewline $channel] close $channel pass "$test read $value" } return $value } proc proc_write_value { test path value } { if [catch {open $path WRONLY} channel] { fail "$test $channel" } else { puts -nonewline $channel $value close $channel pass "$test wrote $value" } } proc proc_read_write_counted { test maxsize } { set path "/proc/systemtap/$test/command" set fullstring "abcdefghijklmnoABCDEFGHIJKLMNOpqrstuvwxyz123456789" # Read the file set value [proc_read_value $test $path] set value2 [string range $fullstring 0 [expr $maxsize - 2]] if { $value == $value2 } { pass "$test received correct initial value maxsize: $maxsize" } else { fail "$test received incorrect initial value: $value ($value2)" } # Write a new value. proc_write_value $test $path $fullstring return 0; } # Expect 32 byte return from reading procfs file. proc proc_read_write_32 {} { global test proc_read_write_counted $test 32 } # Expect 16 byte return from reading procfs file. proc proc_read_write_16 {} { global test proc_read_write_counted $test 16 } set script1 { global values[10] global idx = 0 probe procfs.read { $value = "abcdefghijklmno" $value .= "ABCDEFGHIJKLMNO" $value .= "pqrstuvwxyz1234" } probe procfs.write { values[idx] = $value idx++ } probe begin { printf("systemtap starting probe\n") } probe end { printf("systemtap ending probe\n") for (i = 0; i < idx; i++) { printf("value%d=%s\n", i, values[i]) } } } # Output strings in 16 and 32 byte chunks. set output_string_16 "value0=abcdefghijklmno\r\nvalue1=ABCDEFGHIJKLMNO\r\nvalue2=pqrstuvwxyz1234\r\nvalue3=56789\r\n" set output_string_32 "value0=abcdefghijklmnoABCDEFGHIJKLMNOp\r\nvalue1=qrstuvwxyz123456789\r\n" # By default, setting MAXSTRINGLEN should set the size of # procfs read and write buffers. set test "PROCFS_BUFFER1" stap_run $test proc_read_write_32 $output_string_32 -DMAXSTRINGLEN=32 -e $script1 -m $test exec /bin/rm -f ${test}.ko # Try with MAXSTRINGLEN=32 and STP_PROCFS_BUFSIZE=16 set test "PROCFS_BUFFER2" stap_run $test proc_read_write_16 $output_string_16 -DMAXSTRINGLEN=32 -DSTP_PROCFS_BUFSIZE=16 -e $script1 -m $test exec /bin/rm -f ${test}.ko # Try with MAXSTRINGLEN=16 and STP_PROCFS_BUFSIZE=32. Note that in # this case, even though the procfs buffer is 32 bytes in size, since # strings can only hold 16 bytes, the expected output is the same as # in the previous test. set test "PROCFS_BUFFER3" stap_run $test proc_read_write_32 $output_string_16 -DMAXSTRINGLEN=16 -DSTP_PROCFS_BUFSIZE=32 -e $script1 -m $test exec /bin/rm -f ${test}.ko # script2 has a '.maxsize(32). override set script2 { global values[10] global idx = 0 probe procfs.read.maxsize(32) { $value = "abcdefghijklmno" $value .= "ABCDEFGHIJKLMNO" $value .= "pqrstuvwxyz1234" } probe procfs.write { values[idx] = $value idx++ } probe begin { printf("systemtap starting probe\n") } probe end { printf("systemtap ending probe\n") for (i = 0; i < idx; i++) { printf("value%d=%s\n", i, values[i]) } } } # By default, setting MAXSTRINGLEN should set the size of # procfs read and write buffers. But script2 has a '.maxsize(32)' # override. set test "PROCFS_BUFFER4" stap_run $test proc_read_write_32 $output_string_16 -DMAXSTRINGLEN=16 -e $script2 -m $test exec /bin/rm -f ${test}.ko # The script2 '.maxsize(32)' override should override even setting # STP_PROCFS_BUFSIZE. set test "PROCFS_BUFFER5" stap_run $test proc_read_write_32 $output_string_16 -DMAXSTRINGLEN=16 -DSTP_PROCFS_BUFSIZE=64 -e $script2 -m $test exec /bin/rm -f ${test}.ko # script3 has a maxsize override and a default size file set script3 { global values[10] global idx = 0 probe procfs("default").read { $value = "abcdefghijklmno" $value .= "ABCDEFGHIJKLMNO" $value .= "pqrstuvwxyz1234" } probe procfs.read.maxsize(32) { $value = "abcdefghijklmno" $value .= "ABCDEFGHIJKLMNO" $value .= "pqrstuvwxyz1234" } probe procfs.write { values[idx] = $value idx++ } probe begin { printf("systemtap starting probe\n") } probe end { printf("systemtap ending probe\n") for (i = 0; i < idx; i++) { printf("value%d=%s\n", i, values[i]) } } } proc proc_read_write_default_32 {} { global test set path "/proc/systemtap/$test/default" set value2 "abcdefghijklmno" # Read the file set value [proc_read_value $test $path] if { $value == $value2 } { pass "$test received correct initial value" } else { fail "$test received incorrect initial value: $value ($value2)" } proc_read_write_counted $test 32 } set test "PROCFS_BUFFER6" stap_run $test proc_read_write_default_32 $output_string_16 -DMAXSTRINGLEN=16 -e $script3 -m $test exec /bin/rm -f ${test}.ko set script4 { global large_strings[10] # Put more data than we can really handle into $value probe procfs.read.maxsize(2048) { $value = large_strings[0] for (i = 1; i < 10; i+=1) { $value .= large_strings[i] } } probe begin { # build up several maximum length strings max = 512 for (i = 0; i < max/64; i+=1) { for (j = 0; j < 10; j++) { if (i < (max/64 - 1)) { large_strings[j] .= sprintf("%3d:12345678901234567890123456789012345678901234567890123456789\n", i + (j * (max/64))) } else { large_strings[j] .= sprintf("%3d:1234567890123456789012345678901234567890123456789012345678\n", i + (j * (max/64))) } } } printf("systemtap starting probe\n") } probe end { printf("systemtap ending probe\n") } } proc proc_read_big {} { global test global test_string set path "/proc/systemtap/$test/command" # Read the file set value [proc_read_value $test $path] # set value2 [string range $fullstring 0 [expr $maxsize - 2]] if { $value == $test_string } { pass "$test received correct initial value" } else { fail "$test received incorrect initial value: $value ($test_string)" } return 0; } set test_string \ " 0:12345678901234567890123456789012345678901234567890123456789 1:12345678901234567890123456789012345678901234567890123456789 2:12345678901234567890123456789012345678901234567890123456789 3:12345678901234567890123456789012345678901234567890123456789 4:12345678901234567890123456789012345678901234567890123456789 5:12345678901234567890123456789012345678901234567890123456789 6:12345678901234567890123456789012345678901234567890123456789 7:1234567890123456789012345678901234567890123456789012345678 8:12345678901234567890123456789012345678901234567890123456789 9:12345678901234567890123456789012345678901234567890123456789 10:12345678901234567890123456789012345678901234567890123456789 11:12345678901234567890123456789012345678901234567890123456789 12:12345678901234567890123456789012345678901234567890123456789 13:12345678901234567890123456789012345678901234567890123456789 14:12345678901234567890123456789012345678901234567890123456789 15:1234567890123456789012345678901234567890123456789012345678 16:12345678901234567890123456789012345678901234567890123456789 17:12345678901234567890123456789012345678901234567890123456789 18:12345678901234567890123456789012345678901234567890123456789 19:12345678901234567890123456789012345678901234567890123456789 20:12345678901234567890123456789012345678901234567890123456789 21:12345678901234567890123456789012345678901234567890123456789 22:12345678901234567890123456789012345678901234567890123456789 23:1234567890123456789012345678901234567890123456789012345678 24:12345678901234567890123456789012345678901234567890123456789 25:12345678901234567890123456789012345678901234567890123456789 26:12345678901234567890123456789012345678901234567890123456789 27:12345678901234567890123456789012345678901234567890123456789 28:12345678901234567890123456789012345678901234567890123456789 29:12345678901234567890123456789012345678901234567890123456789 30:12345678901234567890123456789012345678901234567890123456789 31:1234567890123456789012345678901234567890123456789012345678 32" # Test outputting 2K worth of data in one shot. set test "PROCFS_BUFFER7" stap_run $test proc_read_big "" -DMAXSTRINGLEN=512 -e $script4 -m $test exec /bin/rm -f ${test}.ko systemtap-2.3/testsuite/systemtap.base/procfs_umask.exp000066400000000000000000000044711217430427200236240ustar00rootroot00000000000000#procfs_umask.exp # Test cases for procfs umask probes set test "PROCFS_UMASK" set ok 0 set ko 0 if {![installtest_p]} { untested $test; return } proc match_perm_val {paths perms} { global test global ok global ko if {![catch { exec stat --format=%a "/proc/systemtap/$test/$paths"} permission]} { if { $permission == $perms } { incr ok } else { incr ko verbose -log "permissions problem, $paths should have $perms permissions, not $permission." } } else { incr ko verbose -log "stat problem, an error has occured while testing the $paths file." } } proc check_perm_val {} { global test global ok global ko foreach paths { "umask-000-r" "umask-000-w" "umask-004-r" "umask-020-w" "umask-044-r" "umask-022-w" "umask-400-r" "umask-200-w" "umask-440-r" "umask-202-w" "umask-404-r" "umask-002-w" } perms { 444 222 440 202 400 200 44 22 4 20 40 220 } { match_perm_val $paths $perms } if {$ok > 0 && $ko == 0} { pass "$test" } else { fail "$test" } } set systemtap_script { global value probe procfs("umask-000-r").umask(000).read {$value = "100\n" } probe procfs("umask-000-w").umask(000).write {printf("the val is, %s", $value)} probe procfs("umask-004-r").umask(004).read {$value = "200\n"} probe procfs("umask-020-w").umask(020).write {printf("the val is, %s", $value)} probe procfs("umask-044-r").umask(044).read {$value = "300\n"} probe procfs("umask-022-w").umask(022).write {printf("the val is, %s", $value)} probe procfs("umask-400-r").umask(400).read {$value = "400\n"} probe procfs("umask-200-w").umask(200).write {printf("the val is, %s", $value)} probe procfs("umask-440-r").umask(440).read {$value = "500\n"} probe procfs("umask-202-w").umask(202).write {printf("the val is, %s", $value)} probe procfs("umask-404-r").umask(404).read {$value = "600\n"} probe procfs("umask-002-w").umask(002).write {printf("the val is, %s", $value)} probe begin { value = "600\n" printf("systemtap starting probe\n") } probe end { printf("systemtap ending probe\n") printf("Testing permissions\n") } } # test procfs umask probes set output_string "Testing permissions\r\n" stap_run $test check_perm_val $output_string -e $systemtap_script -m $test exec /bin/rm -f ${test}.ko systemtap-2.3/testsuite/systemtap.base/procfs_write.exp000066400000000000000000000137661217430427200236450ustar00rootroot00000000000000# PR 11223. Make sure we can handle large amounts of procfs write data. set test "PROCFS_WRITE" if {![installtest_p]} { untested $test; return } proc proc_write_value { test path value} { if [catch {open $path WRONLY} channel] { fail "$test $channel" } else { puts $channel $value close $channel pass "$test wrote $value" } } # This test string is ~4224 bytes long (66 lines of 64 chars). The # procfs kernel system will use a buffer of 4K. Our string of ~4224 # should take around 9 trips through the write function (4224 chars / # 512 bytes per systemtap string = ~9 trips). # # The kernel reuses the 4K buffer for the 9th trip and doesn't null # terminate the string. Instead, it tells consumers how many bytes # are present. # # We want to make sure we can handle > 4K worth of data properly. set test_string \ " 0:12345678901234567890123456789012345678901234567890123456789 1:12345678901234567890123456789012345678901234567890123456789 2:12345678901234567890123456789012345678901234567890123456789 3:12345678901234567890123456789012345678901234567890123456789 4:12345678901234567890123456789012345678901234567890123456789 5:12345678901234567890123456789012345678901234567890123456789 6:12345678901234567890123456789012345678901234567890123456789 7:12345678901234567890123456789012345678901234567890123456789 8:12345678901234567890123456789012345678901234567890123456789 9:12345678901234567890123456789012345678901234567890123456789 10:12345678901234567890123456789012345678901234567890123456789 11:12345678901234567890123456789012345678901234567890123456789 12:12345678901234567890123456789012345678901234567890123456789 13:12345678901234567890123456789012345678901234567890123456789 14:12345678901234567890123456789012345678901234567890123456789 15:12345678901234567890123456789012345678901234567890123456789 16:12345678901234567890123456789012345678901234567890123456789 17:12345678901234567890123456789012345678901234567890123456789 18:12345678901234567890123456789012345678901234567890123456789 19:12345678901234567890123456789012345678901234567890123456789 20:12345678901234567890123456789012345678901234567890123456789 21:12345678901234567890123456789012345678901234567890123456789 22:12345678901234567890123456789012345678901234567890123456789 23:12345678901234567890123456789012345678901234567890123456789 24:12345678901234567890123456789012345678901234567890123456789 25:12345678901234567890123456789012345678901234567890123456789 26:12345678901234567890123456789012345678901234567890123456789 27:12345678901234567890123456789012345678901234567890123456789 28:12345678901234567890123456789012345678901234567890123456789 29:12345678901234567890123456789012345678901234567890123456789 30:12345678901234567890123456789012345678901234567890123456789 31:12345678901234567890123456789012345678901234567890123456789 32:12345678901234567890123456789012345678901234567890123456789 33:12345678901234567890123456789012345678901234567890123456789 34:12345678901234567890123456789012345678901234567890123456789 35:12345678901234567890123456789012345678901234567890123456789 36:12345678901234567890123456789012345678901234567890123456789 37:12345678901234567890123456789012345678901234567890123456789 38:12345678901234567890123456789012345678901234567890123456789 39:12345678901234567890123456789012345678901234567890123456789 40:12345678901234567890123456789012345678901234567890123456789 41:12345678901234567890123456789012345678901234567890123456789 42:12345678901234567890123456789012345678901234567890123456789 43:12345678901234567890123456789012345678901234567890123456789 44:12345678901234567890123456789012345678901234567890123456789 45:12345678901234567890123456789012345678901234567890123456789 46:12345678901234567890123456789012345678901234567890123456789 47:12345678901234567890123456789012345678901234567890123456789 48:12345678901234567890123456789012345678901234567890123456789 49:12345678901234567890123456789012345678901234567890123456789 50:12345678901234567890123456789012345678901234567890123456789 51:12345678901234567890123456789012345678901234567890123456789 52:12345678901234567890123456789012345678901234567890123456789 53:12345678901234567890123456789012345678901234567890123456789 54:12345678901234567890123456789012345678901234567890123456789 55:12345678901234567890123456789012345678901234567890123456789 56:12345678901234567890123456789012345678901234567890123456789 57:12345678901234567890123456789012345678901234567890123456789 58:12345678901234567890123456789012345678901234567890123456789 59:12345678901234567890123456789012345678901234567890123456789 60:12345678901234567890123456789012345678901234567890123456789 61:12345678901234567890123456789012345678901234567890123456789 62:12345678901234567890123456789012345678901234567890123456789 63:12345678901234567890123456789012345678901234567890123456789 64:12345678901234567890123456789012345678901234567890123456789 65:12345678901234567890123456789012345678901234567890123456789 66:12345678901234567890123456789012345678901234567890123456789" # Now we need the version of the above string that expect will look # for. So, we need to convert all '\n' to '\r\n' and add a trailing # '\r\n'. regsub -all {\n} $test_string "\r\n" test_string2 set test_string2 "$test_string2\r\n" proc proc_write_test {} { global test test_string set path "/proc/systemtap/$test/command" proc_write_value $test $path $test_string return 0; } set systemtap_write_script { global iteration = 0 global saved_value[20] probe procfs("command").write { saved_value[iteration] = $value iteration++ } probe begin { printf("systemtap starting probe\n") } probe end { printf("systemtap ending probe\n") for (i = 0; i < iteration; i++) { printf("%s", saved_value[i]) } } } # We're forcing the MAXSTRINGLEN to be 512 chars to make sure we know # what we're testing. stap_run $test proc_write_test $test_string2 -DMAXSTRINGLEN=512 \ -e $systemtap_write_script -m $test exec /bin/rm -f ${test}.ko systemtap-2.3/testsuite/systemtap.base/prologues.exp000066400000000000000000000014611217430427200231430ustar00rootroot00000000000000set test "prologues -P" if {! [installtest_p]} { untested $test } else { set ok 0 spawn stap -P $srcdir/$subdir/prologues.stp expect { -timeout 240 -re {read[^\r\n]*\r\n} { incr ok; exp_continue } -re {write[^\r\n]*\r\n} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof } wait if {$ok > 10} { pass $test } else { fail $test } } set test "prologues no-P" if {! [installtest_p]} { untested $test } else { set ok 0 spawn stap $srcdir/$subdir/prologues.stp expect { -timeout 240 -re {read[^\r\n]*\r\n} { incr ok; exp_continue } -re {write[^\r\n]*\r\n} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof } wait if {$ok > 10} { pass $test } else { fail $test } } systemtap-2.3/testsuite/systemtap.base/prologues.stp000066400000000000000000000002501217430427200231500ustar00rootroot00000000000000# These sys_ functions often display prologue sensitivity probe syscall.read, syscall.write { printf("%s (%s)\n", name, argstr) if (num++ > 20) exit() } global num systemtap-2.3/testsuite/systemtap.base/pt_user_mode.exp000066400000000000000000000007401217430427200236100ustar00rootroot00000000000000# Check that perf/timer probes trigger in both kernel and user space. set test "pt_user_mode" set effective_pid [exec /usr/bin/id -u] if { $effective_pid != 0 } { untested "$test (perf probes require root access)" return } proc run_test_load {} { # do something silly that uses both user and kernel time. catch { exec dd if=/dev/zero of=/dev/null bs=17 count=502432 conv=ebcdic } return 0 } stap_run $srcdir/$subdir/$test.stp run_test_load $all_pass_string systemtap-2.3/testsuite/systemtap.base/pt_user_mode.stp000066400000000000000000000006141217430427200236220ustar00rootroot00000000000000/* * Check perf/timer trigger in both user/kernel mode. */ global u, k probe begin { println("systemtap starting probe"); } probe perf.sw.cpu_clock!, timer.profile { if (user_mode()) u <<< 1 else k <<< 1 } probe end { println("systemtap ending probe") if (@count(u) == 0 || @count(k) == 0) { println("systemtap test failure"); } else { println("systemtap test success"); } } systemtap-2.3/testsuite/systemtap.base/pthread_stacks.c000066400000000000000000000031151217430427200235470ustar00rootroot00000000000000#include #include #include #include #include static pthread_once_t printed_p = PTHREAD_ONCE_INIT; void print_it () { int rc; pthread_attr_t foo; size_t size; rc = pthread_getattr_np (pthread_self(), & foo); assert (rc == 0); rc = pthread_attr_getstacksize(&foo, &size); assert (rc == 0); printf ("stacksize=%u\n", size); rc = pthread_attr_destroy (&foo); assert (rc == 0); } void *tfunc(void *arg) { /* Choose some random thread to print stack size */ (void) pthread_once(&printed_p, &print_it); sleep (4); return NULL; } int main(int argc, char **argv) { pthread_t thr; pthread_attr_t attr; int numthreads; int stacksize; int rc; int threads_created = 0; if (argc != 3) { fprintf(stderr, "Usage: %s numthreads stacksize|0\n", argv[0]); return -1; } numthreads = atoi(argv[1]); stacksize = atoi(argv[2]); rc = pthread_attr_init(&attr); assert (rc == 0); if (stacksize > 0) { rc = pthread_attr_setstacksize(&attr, (size_t) stacksize); assert (rc == 0); } while (numthreads--) { rc = pthread_create(&thr, (stacksize == 0 ? NULL : &attr), tfunc, NULL); /* On systems with not enough memory, pthread_create() can fail * after creating lots of threads. Just ignore this error (if * we've already created at least 100 threads). */ if (rc == EAGAIN && threads_created > 100) break; assert (rc == 0); threads_created++; } rc = pthread_attr_destroy(&attr); assert (rc == 0); return 0; } systemtap-2.3/testsuite/systemtap.base/pthread_stacks.exp000066400000000000000000000044201217430427200241210ustar00rootroot00000000000000set test "pthread_stacks" set exepath "[pwd]/pthread_stacks.x" set flags "additional_flags=-pthread additional_flags=-g" set res [target_compile $srcdir/$subdir/pthread_stacks.c $exepath executable $flags] if { $res != "" } { fail "$test compiling" return } else { pass "$test compiling" } # This test won't work if we don't have glibc's debuginfo # installed. So, try to compile threadstacks.stp first to see if we've # got glibc debuginfo. Note that on multilib systems like x86_64, you # need both architecture's glibc debuginfo installed. set test "pthread_stacks debuginfo check" spawn stap -gp4 $srcdir/systemtap.examples/process/threadstacks.stp \ -Gsize=65536 -d $exepath set compile_errors 0 expect { -timeout 60 -re {^WARNING:[^\r\n]*debuginfo[^\r\n]*\r\n} { incr compile_errors 1; exp_continue} -re {^parse error[^\r\n]*\r\n} { incr compile_errors 1; exp_continue } -re {^[^\r\n]*compilation failed[^\r\n]*\r\n} { incr compile_errors 1; exp_continue } -re {^semantic error[^\r\n]*\r\n} { incr compile_errors 1; exp_continue } timeout { fail "$test timeout" } eof { } } set res [wait -i $spawn_id] catch { close } set res [lindex $res 3] if { $res != 0 || $compile_errors > 0 } { fail $test untested "pthread_stacks" catch {exec rm -f $exepath} return } pass $test set test "pthread_stacks no -Gsize" spawn stap -w -g $srcdir/systemtap.examples/process/threadstacks.stp -c "$exepath 1024 0" -d $exepath set ok 0 set ko 0 expect { -re {^stacksize=[0-9]*\r\n} { incr ok; exp_continue } -re {^WARNING[^\r\n]*\r\n} { incr ko; exp_continue } timeout { fail "$test timeout" } eof { } } catch { close } catch { wait } if { $ok == 1 } then { pass $test } else { fail "$test ($ok $ko)" } set test "pthread_stacks -Gsize" spawn stap -g $srcdir/systemtap.examples/process/threadstacks.stp -Gsize=65536 -c "$exepath 1024 0" -d $exepath set ok 0 set ko 0 expect { -re {^stacksize=[0-9]*\r\n} { incr ok; exp_continue } -re {^pthread_stacks[^\r\n]*overwrote[^\r\n]*\r\n} { incr ok; exp_continue } -re {^WARNING[^\r\n]*\r\n} { incr ko; exp_continue } timeout { fail "$test timeout" } eof { } } catch { close } catch { wait } if { $ok == 2 } then { pass $test } else { fail "$test ($ok $ko)" } catch {exec rm -f $exepath} systemtap-2.3/testsuite/systemtap.base/ptrace.exp000066400000000000000000000021041217430427200223750ustar00rootroot00000000000000# Make sure we can use ptrace() on a process probed with systemtap. set TEST_NAME "ptrace" if {![uprobes_p]} { untested "$TEST_NAME : no uprobes support found" return } elseif {![installtest_p]} { untested $TEST_NAME return } # Test process.begin set subcmd {strace -e read true} set TEST_NAME "ptrace (begin)" set script {probe process.begin { next }} set cmd {stap -e $script -c $subcmd} set output_found 0 eval spawn $cmd expect { -timeout 180 -re {^read\(\d+, .+\) = \d+\r\n} { set output_found 1 exp_continue } } catch close wait if { $output_found } { pass "$TEST_NAME" } else { fail "$TEST_NAME" } # The never probe won't get hit, but including 'print_ubacktrace()' # will enable task_finder and vma tracking. set TEST_NAME "ptrace (never)" set script {probe never{print_ubacktrace()}} set cmd {stap -e $script -c $subcmd} set output_found 0 eval spawn $cmd expect { -timeout 180 -re {^read\(\d+, .+\) = \d+\r\n} { set output_found 1 exp_continue } } catch close wait if { $output_found } { pass "$TEST_NAME" } else { fail "$TEST_NAME" } systemtap-2.3/testsuite/systemtap.base/ptridx.c000066400000000000000000000002421217430427200220600ustar00rootroot00000000000000#include static void foo (int *p) { l1: printf ("%d, %d\n", p[0], p[1]); } int main (void) { int a[] = { 17, 23 }; l1: foo (a); return 0; } systemtap-2.3/testsuite/systemtap.base/ptridx.exp000066400000000000000000000026571217430427200224460ustar00rootroot00000000000000set test "ptridx" for {set i 0} {$i < [all_compile_flags]} {incr i} { set extra_flag [all_compile_flag $i] set extra_name [all_compile_flag_name $i] set test_flags "additional_flags=-g $extra_flag" set res [target_compile $srcdir/$subdir/$test.c $test.exe executable "$test_flags"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test-$test_name compile" untested "$test-$extra_name" continue } else { pass "$test-$extra_name compile" } if {[catch {exec stap -L {process("./ptridx.exe").function("*").label("*")}}]} { fail "$test-$extra_name (list labels)" untested "$test-$extra_name" } else { pass "$test-$extra_name (list labels)" if {[installtest_p] && [uprobes_p]} { set ok 0 spawn stap $srcdir/$subdir/$test.stp -c ./$test.exe -w expect { -re {failed to retrieve location attribute} { # the variables may have no location setup_kfail GCC *-*-* } -re {^17, 23\r\n} { # output from ptridx.exe itself exp_continue } -re {^[ap] (0x[0-9a-f]+ => )?17, 23\r\n} { incr ok; exp_continue } timeout { fail "$test-$extra_name (timeout)" } eof { } } wait if {$ok == 2} { pass "$test-$extra_name" } else { fail "$test-$extra_name ($ok)" } } else { untested "$test-$extra_name" } } catch {exec rm -f $test.exe} } systemtap-2.3/testsuite/systemtap.base/ptridx.stp000066400000000000000000000004731217430427200224520ustar00rootroot00000000000000probe process("./ptridx.exe").function("main").label("l1") { printf ("a "); if (@defined($a)) printf("%p => ", $a); printf("%d, %d\n", $a[0], $a[1]); } probe process("./ptridx.exe").function("foo").label("l1") { printf ("p "); if (@defined($p)) printf("%p => ", $p); printf("%d, %d\n", $p[0], $p[1]); } systemtap-2.3/testsuite/systemtap.base/rand.exp000066400000000000000000000003341217430427200220460ustar00rootroot00000000000000set test "rand" set ::result_string {PASS} foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run2 $srcdir/$subdir/$test.stp --runtime=$runtime } else { stap_run2 $srcdir/$subdir/$test.stp } } systemtap-2.3/testsuite/systemtap.base/rand.stp000066400000000000000000000004271217430427200220630ustar00rootroot00000000000000function checkStatus(status:long){ if (status == 1){ printf("%s\n","FAIL") }else{ printf("%s\n","PASS") } } probe begin { status = 0 for (i=1; i <= 100; i++){ if (randint(i) < 0 || randint(i) > i) { status = 1 } } checkStatus(status) exit() } systemtap-2.3/testsuite/systemtap.base/regex.exp000066400000000000000000000036161217430427200222420ustar00rootroot00000000000000global script_path set script_path $srcdir/$subdir/regex.stp proc stap_test_regex {expected re match} { global script_path set test "regex $expected:$re:$match" if {! [installtest_p]} { untested "$test"; return } eval spawn stap $script_path "$re" "$match" set got -1 expect { -timeout 60 -re {answer: 1 0} {set got 0} -re {answer: 0 1} {set got 1} eof { } } catch {close}; catch { wait } # XXX: also expect and test for other results? # XXX: also expect and test for errors? if {$expected == $got} then { pass $test } else { fail "$test (wrong answer)" } } ################################## # testsuite courtesy of glibc 2.17 # to run the full testsuite, run make check in re2c-migrate/ # here, just test a dozen or so of our coolest regexes to avoid wasting time # (loading one systemtap script per regex takes non-negligible time) # note on backslash escaping: two '\' in Tcl --> one '\' in final regex # note on [] escaping: sq. brackets need extra '\' to avoid triggering Tcl stap_test_regex 0 {\\\\} {\\} stap_test_regex 0 {abc} {xabcy} stap_test_regex 0 {ab*bc} {abbbbc} stap_test_regex 0 {ab?bc} {abbc} stap_test_regex 1 {^abc$} {abcc} stap_test_regex 1 {a\[b-d\]e} {abd} stap_test_regex 0 {a\[b-d\]e} {ace} stap_test_regex 0 {a\\(*b} {ab} stap_test_regex 0 {a\\(*b} {a((b} stap_test_regex 0 {(a+|b)*} {ab} stap_test_regex 0 {(a+|b)+} {ab} stap_test_regex 0 {(\[abc\])*d} {abbbcd} stap_test_regex 1 {^(ab|cd)e} {abcde} stap_test_regex 0 {\[A-Za-z_\]\[A-Za-z0-9_\]*} {alpha} stap_test_regex 0 {(bc+d$|ef*g.|h?i(j|k))} {ij} stap_test_regex 1 {(bc+d$|ef*g.|h?i(j|k))} {effg} stap_test_regex 0 {(((((((((a)))))))))} {a} stap_test_regex 1 {\\((.*),} {(.*)\\)} stap_test_regex 1 {\[k\]} {ab} stap_test_regex 0 {abcd} {abcd} stap_test_regex 0 {a(bc)d} {abcd} # TODOXXX: add further tests to do specifically with unescaping systemtap-2.3/testsuite/systemtap.base/regex.stp000066400000000000000000000002121217430427200222410ustar00rootroot00000000000000probe begin { printf ("match: regex '%s', str '%s'\n", @1, @2) printf ("answer: %d %d\n", @2 =~ @1, @2 !~ @1) exit () } systemtap-2.3/testsuite/systemtap.base/remote.exp000066400000000000000000000045631217430427200224250ustar00rootroot00000000000000# Test that the --remote=host mechanism is working # Requires the test user to specify hosts with automated ssh access. set test "remote" if {[info exists env(SYSTEMTAP_TESTREMOTES)]} { set remotes [split $env(SYSTEMTAP_TESTREMOTES) ,] } if {[llength $remotes] == 0} { set remotes {direct: stapsh:} } set batch_remotes [list] verbose -log "$test: using $remotes" if {![llength $remotes] || ![installtest_p]} { untested $test; return } # Test each remote individually foreach remote $remotes { # Try building for the remote spawn stap $srcdir/$subdir/$test.stp --remote=$remote -p4 expect { -timeout 180 timeout { fail "$test build $remote (timeout)" } eof { } } catch {close}; catch {wait} res set rc [lindex $res 3] if {$rc == 0} { pass "$test build $remote" } else { fail "$test build $remote ($rc)" untested "$test run $remote" continue } # Try running on the remote set begin 0 set end 0 set err 0 spawn stap $srcdir/$subdir/$test.stp --remote=$remote expect { -timeout 180 -re "^begin0:$remote\r\n" { incr begin; exec kill -INT [exp_pid]; exp_continue } -re "^end0:$remote\r\n" { incr end; exp_continue } -re {^[^\r\n]*\r\n} { incr err; exp_continue } timeout { fail "$test run $remote (timeout)" } eof { } } catch {close}; catch {wait} if {!$err && $begin == 1 && $end == 1} { pass "$test run $remote" lappend batch_remotes "--remote=$remote" } else { fail "$test run $remote ($begin $end $err)" } } verbose -log "$test: batch $batch_remotes" if {[llength $batch_remotes] < 2} { untested "$test batch" } else { # Try running the good ones together set begin 0 set end 0 set err 0 eval spawn stap {$srcdir/$subdir/$test.stp} $batch_remotes expect { -timeout 180 -re {^begin[0-9]+:[^\r\n]+\r\n} { incr begin if {$begin == [llength $batch_remotes]} {exec kill -INT [exp_pid]} exp_continue } -re {^end[0-9]+:[^\r\n]+\r\n} { incr end; exp_continue } -re {^[^\r\n]*\r\n} { incr err; if {$err == 1} {exec kill -INT [exp_pid]} exp_continue } timeout { fail "$test batch $batch_remotes (timeout)" } eof { } } catch {close}; catch {wait} if {!$err && [llength $batch_remotes] == $begin && $begin == $end} { pass "$test batch $batch_remotes" } else { fail "$test batch $batch_remotes ($begin $end $err)" } } systemtap-2.3/testsuite/systemtap.base/remote.stp000066400000000000000000000002011217430427200224200ustar00rootroot00000000000000probe begin, end { println(pp(), remote_id(), ":", remote_uri()) } probe timer.s(30) { println("timeout!") exit() } systemtap-2.3/testsuite/systemtap.base/rename_module.exp000066400000000000000000000077261217430427200237520ustar00rootroot00000000000000if {![installtest_p]} { untested "rename_module"; return } # Script we'll use while testing: set script {probe begin{printf("Hello\n");}} ########## Inserting 2 Identical Modules: Basic Stap call ################# # Should not give an error when inserting 2 identical modules set test "Inserting 2 Identical Modules: Basic Stap Call" if {![installtest_p]} { untested $test; return } set failed1 1 set failed2 1 # Run first module. Stays running since no exit() call. # Also keep track of its PID, so we can kill it later. spawn stap -e $script set firstid $spawn_id # Run second, identical module. Before, it would cause an # error, since it would have the same name as the previous # one, but now it inserts without a problem, since it is # renamed. # Note: The outputs must also be the same - they will have # different names to begin with otherwise. spawn stap -e $script set secondid $spawn_id # Make sure they both output "Hello" expect { -i $firstid Hello { set failed1 0 exp_continue } -i $secondid Hello { set failed2 0 exp_continue } } # Kill both of the spawned processes catch {exec kill -INT -[exp_pid -i $firstid]} catch {close -i $firstid}; catch {wait -i $firstid} catch {exec kill -INT -[exp_pid -i $secondid]} catch {close -i $secondid}; catch {wait -i $secondid} if {$failed1 || $failed2} { fail "$test ($failed1, $failed2)" } else { pass "$test" } ########## Compile test module ################# # Compile the module we'll be using for the rest of the tests (which # is actually already compiled, but we need the filename of the cached # module). set test "test module" if {[catch { exec stap -e $script -p4 } module]} { verbose -log "$module" fail "$test - compile problem" return } elseif {![file exists $module]} { verbose -log "$module" fail "$test - file exist problem" return } else { pass "$test compiles" } ########## Inserting 2 Identical Modules: Staprun without -R ################# # Should give an error when inserting 2 identical modules # when calling staprun directly without using -R set test "Inserting 2 Identical Modules: Staprun without -R" set failed1 1 set failed2 0 spawn staprun $module set firstid $spawn_id # Make sure the first staprun works expect { -i $firstid Hello { set failed1 0 exp_continue } } spawn staprun $module set secondid $spawn_id # Make sure the second staprun fails expect { -timeout 60 -re {^ERROR: Couldn't insert module .*: File exists\r\n} { exp_continue } -re {^ERROR: Rerun with staprun option '\-R' to rename this module.\r\n} { exp_continue } -re {^[^\r\n]*\r\n} { set failed2 1 exp_continue } timeout { set failed2 1 } } # Kill both of the spawned processes catch {exec kill -INT -[exp_pid -i $firstid]} catch {close -i $firstid}; catch {wait -i $firstid} catch {exec kill -INT -[exp_pid -i $secondid]} catch {close -i $secondid}; catch {wait -i $secondid} if {$failed1 || $failed2} { verbose -log "$failed1, $failed2" # On failure, don't leave any modules behind. catch {exec staprun -d $module} fail "$test ($failed1, $failed2)" } else { pass "$test" } ########## Inserting 2 Identical Modules: Staprun with -R ################# # Should not give an error when inserting 2 identical modules # when calling staprun directly with -R set test "Inserting 2 Identical Modules: Staprun with -R" set failed1 1 set failed2 1 spawn staprun -R $module set firstid $spawn_id spawn staprun -R $module set secondid $spawn_id # Make sure they both output "Hello" expect { -i $firstid Hello { set failed1 0 exp_continue } -i $secondid Hello { set failed2 0 exp_continue } } # Kill both of the spawned processes catch {exec kill -INT -[exp_pid -i $firstid]} catch {close -i $firstid}; catch {wait -i $firstid} catch {exec kill -INT -[exp_pid -i $secondid]} catch {close -i $secondid}; catch {wait -i $secondid} if {$failed1 || $failed2} { # On failure, don't leave any modules behind. catch {exec staprun -d $module} fail "$test ($failed1, $failed2)" } else { pass "$test" } systemtap-2.3/testsuite/systemtap.base/rep_ret.c000066400000000000000000000003321217430427200222060ustar00rootroot00000000000000// Use -fomit-frame-pointer so this doesn't blow the stack void rep_ret() { asm("rep; ret"); } // uprobes allowed void repnz_ret() { asm("repnz; ret"); } // NOT allowed int main() { rep_ret(); repnz_ret(); return 0; } systemtap-2.3/testsuite/systemtap.base/rep_ret.exp000066400000000000000000000027611217430427200225700ustar00rootroot00000000000000set test "rep_ret" # This test is only for i386 and x86_64 # Test 32-on-64 when available switch -regexp $::tcl_platform(machine) { {^i\d86$} { set arches [list "-default"] } {^x86_64$} { set arches [list "-m64" "-m32"]} default { unsupported "$test"; return } } foreach arch $arches { set exe ${test}${arch} verbose "testing $exe" set test_flags "additional_flags=-g" set test_flags "$test_flags additional_flags=-fomit-frame-pointer" if {$arch != "-default"} { set test_flags "$test_flags additional_flags=$arch" } set res [target_compile $srcdir/$subdir/$test.c $exe executable "$test_flags"] if { $res != "" } { verbose "target_compile $exe failed: $res" 2 fail "${test}.c compile ${arch}" untested "$exe" return } else { pass "${test}.c compile ${arch}" } if {[installtest_p] && [uprobes_p]} { set ok 0 set bad 0 set warn 0 spawn stap -e {probe process(@1).function("*") { println(probefunc()) }} ./$exe -c ./$exe expect { -re {^main\r\n} { incr ok; exp_continue } -re {^rep_ret\r\n} { incr ok; exp_continue } -re {^repnz_ret\r\n} { incr ok; exp_continue } -re {^WARNING: Number of errors: 0, skipped probes: [^\r\n]*\r\n} { incr warn; exp_continue } timeout { fail "$exe (timeout)" } eof { } } wait if {$ok == 3 && $bad == 0 && $warn == 0} { pass "$exe" } else { fail "$exe ($ok, $bad, $warn)" } } else { untested "$exe" } catch {exec rm -f $exe} } systemtap-2.3/testsuite/systemtap.base/rlimit.exp000066400000000000000000000103051217430427200224210ustar00rootroot00000000000000# rlimit tests # many of these tests use as_root or as_non_root if {! [installtest_p]} { return } # To make sure "sudo stap" works correctly, use the full path. set installed_stap "$env(SYSTEMTAP_PATH)/stap" # Unlimited set test "rlimit unlimited" if {[catch { exec $installed_stap -p4 $srcdir/$subdir/rlimit.stp} res ]} { fail $test } else { pass $test } # Increase AS limit (as non root) set test "rlimit AS increase (as non root)" if {[as_non_root "$installed_stap --rlimit-as=1 --rlimit-as=999999999999 -p4 $srcdir/$subdir/rlimit.stp" ]} { pass $test } else { fail $test } # Increase AS limit (as root) set test "rlimit AS increase (as root)" if {[as_root "$installed_stap --rlimit-as=1 --rlimit-as=999999999999 -p4 $srcdir/$subdir/rlimit.stp" ]} { fail $test } else { pass $test } # Realistic AS limit set test "rlimit AS realistic" if {[catch { exec $installed_stap --rlimit-as=614400000 -p4 $srcdir/$subdir/rlimit.stp} res ]} { fail $test } else { pass $test } # Small AS limit set test "rlimit AS small" if {[catch { exec $installed_stap --rlimit-as=1 -p4 $srcdir/$subdir/rlimit.stp} res ]} { pass $test } else { fail $test } # Increase CPU limit (as non root) set test "rlimit CPU increase (as non root)" if {[as_non_root "$installed_stap --rlimit-cpu=1 --rlimit-cpu=999999999999 -p4 $srcdir/$subdir/rlimit.stp" ]} { pass $test } else { fail $test } # Increase CPU limit (as root) set test "rlimit CPU increase (as root)" if {[as_root "$installed_stap --rlimit-cpu=1 --rlimit-cpu=999999999999 -p4 $srcdir/$subdir/rlimit.stp" ]} { fail $test } else { pass $test } # Realistic CPU limit set test "rlimit CPU realistic" if {[catch { exec $installed_stap --rlimit-cpu=60 -p4 $srcdir/$subdir/rlimit.stp} res ]} { fail $test } else { pass $test } # Small CPU limit set test "rlimit CPU small" if {[catch { exec $installed_stap --disable-cache --rlimit-cpu=1 -p4 $srcdir/$subdir/rlimit.stp} res ]} { pass $test } else { fail $test } # Increase NPROC limit (as non root) set test "rlimit NPROC increase (as non root)" if {[as_non_root "$installed_stap --rlimit-nproc=1 --rlimit-nproc=999999999999 -p4 $srcdir/$subdir/rlimit.stp" ]} { pass $test } else { fail $test } # Increase NPROC limit (as root) set test "rlimit NPROC increase (as root)" if {[as_root "$installed_stap --rlimit-nproc=1 --rlimit-nproc=999999999999 -p4 $srcdir/$subdir/rlimit.stp" ]} { fail $test } else { pass $test } # Realistic NPROC limit set test "rlimit NPROC realistic" if {[catch { exec $installed_stap --rlimit-nproc=20 -p4 $srcdir/$subdir/rlimit.stp} res ]} { fail $test } else { pass $test } # Small NPROC limit # Did not seem to change functionality # Increase STACK limit (as non root) set test "rlimit STACK increase (as non root)" if {[as_non_root "$installed_stap --rlimit-stack=1 --rlimit-stack=999999999999 -p4 $srcdir/$subdir/rlimit.stp" ]} { pass $test } else { fail $test } # Increase STACK limit (as root) set test "rlimit STACK increase (as root)" if {[as_root "$installed_stap --rlimit-stack=1 --rlimit-stack=999999999999 -p4 $srcdir/$subdir/rlimit.stp" ]} { fail $test } else { pass $test } # Realistic STACK limit set test "rlimit STACK realistic" if {[catch { exec $installed_stap --rlimit-stack=1024000 -p4 $srcdir/$subdir/rlimit.stp} res ]} { fail $test } else { pass $test } # Small STACK limit # PR13977. The setrlimit() call in stap succeeds, but some kernels ignore # the small limit. # Increase FSIZE limit (as non root) set test "rlimit FSIZE increase (as non root)" if {[as_non_root "$installed_stap --rlimit-fsize=1 --rlimit-fsize=999999999999 -p4 $srcdir/$subdir/rlimit.stp" ]} { pass $test } else { fail $test } # Increase FSIZE limit (as root) set test "rlimit FSIZE increase (as root)" if {[as_root "$installed_stap --rlimit-fsize=1 --rlimit-fsize=999999999999 -p4 $srcdir/$subdir/rlimit.stp" ]} { fail $test } else { pass $test } # Realistic FSIZE limit set test "rlimit FSIZE realistic" if {[catch { exec $installed_stap --rlimit-fsize=51200000 -p4 $srcdir/$subdir/rlimit.stp} res ]} { fail $test } else { pass $test } # Small FSIZE limit # Did not seem to change functionality systemtap-2.3/testsuite/systemtap.base/rlimit.stp000066400000000000000000000000671217430427200224370ustar00rootroot00000000000000probe kernel.function("*ar*").call { println($$vars) } systemtap-2.3/testsuite/systemtap.base/sdt.c000066400000000000000000000042331217430427200213440ustar00rootroot00000000000000#include "sys/sdt.h" int my_global_var = 56; static void call0(void) { STAP_PROBE(test, mark_z); my_global_var++; } static void call1(int a) { STAP_PROBE1(test, mark_a, a); } static void call2(int a, int b) { STAP_PROBE2(test, mark_b, a, b); } static void call3(int a, int b, int c) { STAP_PROBE3(test, mark_c, a, b, c); } static void call4(int a, int b, int c, int d) { STAP_PROBE4(test, mark_d, a, b, c, d); } static void call5(int a, int b, int c, int d, int e) { STAP_PROBE5(test, mark_e, a, b, c, d, e); } static void call6(int a, int b, int c, int d, int e, int f) { STAP_PROBE6(test, mark_f, a, b, c, d, e, f); } static void call7(int a, int b, int c, int d, int e, int f, int g) { STAP_PROBE7(test, mark_g, a, b, c, d, e, f, g); } static void call8(int a, int b, int c, int d, int e, int f, int g, int h) { STAP_PROBE8(test, mark_h, a, b, c, d, e, f, g, h); } static void call9(int a, int b, int c, int d, int e, int f, int g, int h, int i) { STAP_PROBE9(test, mark_i, a, b, c, d, e, f, g, h, i); } static void call10(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) { STAP_PROBE10(test, mark_j, a, b, c, d, e, f, g, h, i, j); } /* I CAN HAZ MOAR ARGS? */ #ifdef STAP_PROBE12 static void call11(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k) { STAP_PROBE11(test, mark_k, a, b, c, d, e, f, g, h, i, j, k); } static void call12(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) { STAP_PROBE12(test, mark_l, a, b, c, d, e, f, g, h, i, j, k, l); } #endif int main (int argc, char **argv) { int a, b, c, d, e, f, g, h, i, j, k, l; a = 1; b = 2; c = 3; d = 4; e = 5; f = 6; g = 7; h = 8; i = 9; j = 10; k = 11; l = 12; call0(); call1(a); call2(a, b); call3(a, b, c); call4(a, b, c, d); call5(a, b, c, d, e); call6(a, b, c, d, e, f); call7(a, b, c, d, e, f, g); call8(a, b, c, d, e, f, g, h); call9(a, b, c, d, e, f, g, h, i); call10(a, b, c, d, e, f, g, h, i, j); #ifdef STAP_PROBE12 call11(a, b, c, d, e, f, g, h, i, j, k); call12(a, b, c, d, e, f, g, h, i, j, k, l); #else (void)(k + l); #endif (void) argv; (void) argc; return 0; } systemtap-2.3/testsuite/systemtap.base/sdt.exp000066400000000000000000000102571217430427200217210ustar00rootroot00000000000000set test "sdt" set result_string10 {_ 1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6 1 2 3 4 5 6 7 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 10} set result_string12 { 1 2 3 4 5 6 7 8 9 10 11 1 2 3 4 5 6 7 8 9 10 11 12} set extra_flags {{additional_flags=-O2} {additional_flags=-O3} {additional_flags=-std=c89} {additional_flags=-std=c99} {additional_flags=-std=gnu99} {c++ additional_flags=-std=c++98 additional_flags=-x additional_flags=c++} {c++ additional_flags=-std=gnu++98 additional_flags=-x additional_flags=c++} {c++ additional_flags=-std=c++0x additional_flags=-x additional_flags=c++} {c++ additional_flags=-std=gnu++0x additional_flags=-x additional_flags=c++} } set extra_mssgs {-O2 -O3 c89 c99 gnu99 c++98 gnu++98 c++0x gnu++0x} set type_pedantics_idx {1 1 2 2 2 2 2 2 2} set type_pedantics {{} additional_flags=-pedantic} ; # don't compile -O2 -O3 with -pedantic set type_pedantic_mssgs {{} -pedantic} set pbtype_flags {{""} {additional_flags=-DSTAP_SDT_V2}} set pbtype_mssgs {{uprobe} {V2_uprobe}} proc sdt_stap_run { TEST_NAME TEST_FILE FAIL args } { foreach runtime [get_runtime_list] { set full_test_name $TEST_NAME if {$runtime != ""} { lappend full_test_name "($runtime)" set cmd [concat stap --runtime=$runtime $TEST_FILE $args] } elseif {[uprobes_p]} { set cmd [concat stap $TEST_FILE $args] } else { untested $full_test_name continue } send_log "executing: $cmd\n" catch {eval exec $cmd} res set skip 0 set n 0 set expected [split $::result_string "\n"] foreach line [split $res "\n"] { if {![string equal $line [lindex $expected $n]]} { $FAIL "$full_test_name" send_log "line [expr $n + 1]: expected \"[lindex $expected $n]\"\n" send_log "Got \"$line\"\n" set skip 1 break } incr n } if {$skip != 0} { continue } if {[expr $n == [llength $expected]]} { pass "$full_test_name" } else { $FAIL "$full_test_name" send_log "too few lines of output, got $n, expected [llength $expected]\n" } } } # Iterate pbtype_flags for {set p 0} {$p < [llength $pbtype_flags]} {incr p} { set pbtype_flag [lindex $pbtype_flags $p] set pbtype_mssg [lindex $pbtype_mssgs $p] # Iterate extra_flags, trying each with C and C++ for {set i 0} {$i < [llength $extra_flags]} {incr i} { set extra_flag [lindex $extra_flags $i] set extra_mssg [lindex $extra_mssgs $i] set testprog "sdt.c.exe.$i" for {set j 0} {$j < [lindex $type_pedantics_idx $i]} {incr j} { set type_pedantic_mssg [lindex $type_pedantic_mssgs $j] set test_flags "additional_flags=-g" set test_flags "$test_flags [sdt_includes]" set test_flags "$test_flags additional_flags=-Wall" set test_flags "$test_flags additional_flags=-Wextra" set test_flags "$test_flags additional_flags=-Werror $pbtype_flag" set saveidx 0 set res [target_compile $srcdir/$subdir/$test.c $testprog executable "$test_flags $extra_flag [lindex $type_pedantics $j]"] if { $res != "" } { verbose "target_compile failed: $res" 2 # -std=gnu++0x and -std=c++0x are not universally accepted if {[string first "unrecognized command line option" $res] == -1} { fail "compiling $test.c $extra_mssg $type_pedantic_mssg $pbtype_mssg" } else { untested "compiling $test.c $extra_mssg $type_pedantic_mssg $pbtype_mssg" } untested "$test $extra_mssg $type_pedantic_mssg $pbtype_mssg" continue } else { pass "compiling $test.c $extra_mssg $type_pedantic_mssg $pbtype_mssg" } if {[installtest_p]} { if {[regexp "^(ppc64|s390x)$" $::tcl_platform(machine)] \ && [regexp "^(-O)" $extra_mssg]} { # register name and constant is ambiguous in ppc/s390 asm syntax # thus constant folding can throw the result off set FAIL xfail } else { set FAIL fail } set ::result_string $result_string10 if { $pbtype_mssg == "uprobe" } { append ::result_string $result_string12 } sdt_stap_run "$test $extra_mssg $type_pedantic_mssg $pbtype_mssg" \ -w $FAIL $srcdir/$subdir/$test.stp $testprog -c ./$testprog } else { untested "$test $extra_mssg $type_pedantic_mssg $pbtype_mssg" } catch {exec rm -f $testprog} } ; # type_pedantics_idx } ; # for {set i 0} {$i < [llength $extra_flags]} } ; # for {set i 0} {$i < [llength $pbtype_flags]} systemtap-2.3/testsuite/systemtap.base/sdt.stp000066400000000000000000000027101217430427200217260ustar00rootroot00000000000000probe process(@1).mark("mark_z") { printf("_\n"); } probe process(@1).mark("mark_a") { printf("%d\n", $arg1); } probe process(@1).mark("mark_b") { printf("%d %d\n", $arg1, $arg2); } probe process(@1).mark("mark_c") { printf("%d %d %d\n", $arg1, $arg2, $arg3); } probe process(@1).mark("mark_d") { printf("%d %d %d %d\n", $arg1, $arg2, $arg3, $arg4); } probe process(@1).mark("mark_e") { printf("%d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5); } probe process(@1).mark("mark_f") { printf("%d %d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5, $arg6); } probe process(@1).mark("mark_g") { printf("%d %d %d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7); } probe process(@1).mark("mark_h") { printf("%d %d %d %d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8); } probe process(@1).mark("mark_i") { printf("%d %d %d %d %d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8, $arg9); } probe process(@1).mark("mark_j") { printf("%d %d %d %d %d %d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8, $arg9, $arg10); } probe process(@1).mark("mark_k") ? { printf("%d %d %d %d %d %d %d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8, $arg9, $arg10, $arg11); } probe process(@1).mark("mark_l") ? { printf("%d %d %d %d %d %d %d %d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8, $arg9, $arg10, $arg11, $arg12); } systemtap-2.3/testsuite/systemtap.base/sdt_asm.S000066400000000000000000000042071217430427200221650ustar00rootroot00000000000000#include "sys/sdt.h" .file "sdt_asm.c" .text .p2align 4,,15 .globl main .type main, @function main: .cfi_startproc #if defined __i386__ pushl %ebp movl %esp, %ebp movl $7, -4(%ebp) STAP_PROBE3(provider,memory,-4(%ebp),-8+4(%ebp),-8+3+1(%ebp)); #elif defined __x86_64__ pushq %rbp mov %rsp, %rbp movl $7, -4(%rbp) STAP_PROBE3(provider,memory,-4(%rbp),-8+4(%rbp),-8+3+1(%rbp)); #endif #if defined __i386__ || defined __x86_64__ mov $0x10203040, %eax STAP_PROBE4(provider,a,%ah,%al,%ax,%eax); mov $0x11213141, %ebx STAP_PROBE4(provider,b,%bh,%bl,%bx,%ebx); mov $0x12223242, %ecx STAP_PROBE4(provider,c,%ch,%cl,%cx,%ecx); mov $0x13233343, %edx STAP_PROBE4(provider,d,%dh,%dl,%dx,%edx); mov $0x14243444, %esi STAP_PROBE3(provider,si,%sil,%si,%esi); mov $0x15253545, %edi STAP_PROBE3(provider,di,%dil,%di,%edi); mov $0x16263646, %ebp STAP_PROBE2(provider,bp,%bp,%ebp); mov $0x17273747, %esp STAP_PROBE2(provider,sp,%sp,%esp); #endif #if defined __x86_64__ mov $0x1020304010203040, %rax STAP_PROBE1(provider,rax,%rax); mov $0x1121314111213141, %rbx STAP_PROBE1(provider,rbx,%rbx); mov $0x1222324212223242, %rcx STAP_PROBE1(provider,rcx,%rcx); mov $0x1323334313233343, %rdx STAP_PROBE1(provider,rdx,%rdx); mov $0x1424344414243444, %rsi STAP_PROBE1(provider,rsi,%rsi); mov $0x1525354515253545, %rdi STAP_PROBE1(provider,rdi,%rdi); mov $0x1626364616263646, %rbp STAP_PROBE1(provider,rbp,%rbp); mov $0x1727374717273747, %rsp STAP_PROBE1(provider,rsp,%rsp); mov $0x1828384818283848, %r8 STAP_PROBE4(provider,r8,%r8b,%r8w,%r8d,%r8); mov $0x1929394919293949, %r9 STAP_PROBE4(provider,r9,%r9b,%r9w,%r9d,%r9); mov $0x1a2a3a4a1a2a3a4a, %r10 STAP_PROBE4(provider,r10,%r10b,%r10w,%r10d,%r10); mov $0x1b2b3b4b1b2b3b4b, %r11 STAP_PROBE4(provider,r11,%r11b,%r11w,%r11d,%r11); mov $0x1c2c3c4c1c2c3c4c, %r12 STAP_PROBE4(provider,r12,%r12b,%r12w,%r12d,%r12); mov $0x1d2d3d4d1d2d3d4d, %r13 STAP_PROBE4(provider,r13,%r13b,%r13w,%r13d,%r13); mov $0x1e2e3e4e1e2e3e4e, %r14 STAP_PROBE4(provider,r14,%r14b,%r14w,%r14d,%r14); mov $0x1f2f3f4f1f2f3f4f, %r15 STAP_PROBE4(provider,r15,%r15b,%r15w,%r15d,%r15); #endif ret .cfi_endproc systemtap-2.3/testsuite/systemtap.base/sdt_asm.stp000066400000000000000000000221351217430427200225710ustar00rootroot00000000000000probe process(@1).mark("a") { if ($arg1 == 0x30) {printf ("PASS: %sh\n", $$name)} else {printf ("FAIL: %sh (%#x != 0x30)\n",$$name, $arg1)} if ($arg2 == 0x40) {printf ("PASS: %sl\n", $$name)} else {printf ("FAIL: %sl (%#x != 0x40)\n", $$name, $arg2)} if ($arg3 == 0x3040) {printf ("PASS: %sx\n", $$name)} else {printf ("FAIL: %sx (%#x != 0x3040)\n", $$name, $arg3)} if ($arg4 == 0x10203040) {printf ("PASS: e%sx\n", $$name)} else {printf ("FAIL: e%sx (%#x != 0x10203040)\n", $$name, $arg4)} } probe process(@1).mark("rax") ? { if ($arg1 == 0x1020304010203040) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %s (%#x != 0x1020304010203040)\n", $$name, $arg1)} } probe process(@1).mark("b") { if ($arg1 == 0x31) {printf ("PASS: %sh\n", $$name)} else {printf ("FAIL: %sh (%#x != 0x31)\n",$$name, $arg1)} if ($arg2 == 0x41) {printf ("PASS: %sl\n", $$name)} else {printf ("FAIL: %sl (%#x != 0x41)\n", $$name, $arg2)} if ($arg3 == 0x3141) {printf ("PASS: %sx\n", $$name)} else {printf ("FAIL: %sx (%#x != 0x3141)\n", $$name, $arg3)} if ($arg4 == 0x11213141) {printf ("PASS: e%sx\n", $$name)} else {printf ("FAIL: e%sx (%#x != 0x11213141)\n", $$name, $arg4)} } probe process(@1).mark("rbx") ? { if ($arg1 == 0x1121314111213141) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %s (%#x != 0x1121314111213141)\n", $$name, $arg1)} } probe process(@1).mark("c") { if ($arg1 == 0x32) {printf ("PASS: %sh\n", $$name)} else {printf ("FAIL: %sh (%#x != 0x32)\n",$$name, $arg1)} if ($arg2 == 0x42) {printf ("PASS: %sl\n", $$name)} else {printf ("FAIL: %sl (%#x != 0x42)\n", $$name, $arg2)} if ($arg3 == 0x3242) {printf ("PASS: %sx\n", $$name)} else {printf ("FAIL: %sx (%#x != 0x3242)\n", $$name, $arg3)} if ($arg4 == 0x12223242) {printf ("PASS: e%sx\n", $$name)} else {printf ("FAIL: e%sx (%#x != 0x12223242)\n", $$name, $arg4)} } probe process(@1).mark("rcx") ? { if ($arg1 == 0x1222324212223242) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %s (%#x != 0x1222324212223242)\n", $$name, $arg1)} } probe process(@1).mark("d") { if ($arg1 == 0x33) {printf ("PASS: %sh\n", $$name)} else {printf ("FAIL: %sh (%#x != 0x33)\n",$$name, $arg1)} if ($arg2 == 0x43) {printf ("PASS: %sl\n", $$name)} else {printf ("FAIL: %sl (%#x != 0x43)\n", $$name, $arg2)} if ($arg3 == 0x3343) {printf ("PASS: %sx\n", $$name)} else {printf ("FAIL: %sx (%#x != 0x3343)\n", $$name, $arg3)} if ($arg4 == 0x13233343) {printf ("PASS: e%sx\n", $$name)} else {printf ("FAIL: e%sx (%#x != 0x13233343)\n", $$name, $arg4)} } probe process(@1).mark("rdx") ? { if ($arg1 == 0x1323334313233343) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %s (%#x != 0x1323334313233343)\n", $$name, $arg1)} } probe process(@1).mark("si") { if ($arg1 == 0x44) {printf ("PASS: %sl\n", $$name)} else {printf ("FAIL: %sl (%#x != 0x44)\n",$$name, $arg1)} if ($arg2 == 0x3444) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %s (%#x != 0x3444)\n", $$name, $arg2)} if ($arg3 == 0x14243444) {printf ("PASS: e%s\n", $$name)} else {printf ("FAIL: e%s (%#x != 0x14243444)\n", $$name, $arg3)} } probe process(@1).mark("rsi") ? { if ($arg1 == 0x1424344414243444) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %s (%#x != 0x1424344414243444)\n", $$name, $arg1)} } probe process(@1).mark("di") { if ($arg1 == 0x45) {printf ("PASS: %sl\n", $$name)} else {printf ("FAIL: %sl (%#x != 0x45)\n",$$name, $arg1)} if ($arg2 == 0x3545) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %s (%#x != 0x3545)\n", $$name, $arg2)} if ($arg3 == 0x15253545) {printf ("PASS: e%s\n", $$name)} else {printf ("FAIL: e%s (%#x != 0x15253545)\n", $$name, $arg3)} } probe process(@1).mark("rdi") ? { if ($arg1 == 0x1525354515253545) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %s (%#x != 0x1525354515253545)\n", $$name, $arg1)} } probe process(@1).mark("bp") { if ($arg2 == 0x16263646) {printf ("PASS: e%s\n", $$name)} else {printf ("FAIL: e%s (%#x != 0x16263646)\n", $$name, $arg2)} } probe process(@1).mark("rbp") ? { if ($arg1 == 0x1626364616263646) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %s (%#x != 0x1626364616263646)\n", $$name, $arg1)} } probe process(@1).mark("sp") { if ($arg2 == 0x17273747) {printf ("PASS: e%s\n", $$name)} else {printf ("FAIL: e%s (%#x != 0x17273747)\n", $$name, $arg2)} } probe process(@1).mark("rsp") ? { if ($arg1 == 0x1727374717273747) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %s (%#x != 0x1727374717273747)\n", $$name, $arg1)} } probe process(@1).mark("r8") ? { if ($arg1 == 0x48) {printf ("PASS: %sb\n", $$name)} else {printf ("FAIL: %sb (%#x != 0x48)\n",$$name, $arg1)} if ($arg2 == 0x3848) {printf ("PASS: %sw\n", $$name)} else {printf ("FAIL: %sw (%#x != 0x3848)\n", $$name, $arg2)} if ($arg3 == 0x18283848) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %sd (%#x != 0x18283848)\n", $$name, $arg3)} if ($arg4 == 0x1828384818283848) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %sx (%#x != 0x1828384818283848)\n", $$name, $arg4)} } probe process(@1).mark("r9") ? { if ($arg1 == 0x49) {printf ("PASS: %sb\n", $$name)} else {printf ("FAIL: %sb (%#x != 0x49)\n",$$name, $arg1)} if ($arg2 == 0x3949) {printf ("PASS: %sw\n", $$name)} else {printf ("FAIL: %sw (%#x != 0x3949)\n", $$name, $arg2)} if ($arg3 == 0x19293949) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %sd (%#x != 0x19293949)\n", $$name, $arg3)} if ($arg4 == 0x1929394919293949) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %sx (%#x != 0x1929394919293949)\n", $$name, $arg4)} } probe process(@1).mark("r10") ? { if ($arg1 == 0x4a) {printf ("PASS: %sb\n", $$name)} else {printf ("FAIL: %sb (%#x != 0x4a)\n",$$name, $arg1)} if ($arg2 == 0x3a4a) {printf ("PASS: %sw\n", $$name)} else {printf ("FAIL: %sw (%#x != 0x3a4a)\n", $$name, $arg2)} if ($arg3 == 0x1a2a3a4a) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %sd (%#x != 0x1a2a3a4a)\n", $$name, $arg3)} if ($arg4 == 0x1a2a3a4a1a2a3a4a) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %sx (%#x != 0x1a2a3a4a1a2a3a4a)\n", $$name, $arg4)} } probe process(@1).mark("r11") ? { if ($arg1 == 0x4b) {printf ("PASS: %sb\n", $$name)} else {printf ("FAIL: %sb (%#x != 0x4b)\n",$$name, $arg1)} if ($arg2 == 0x3b4b) {printf ("PASS: %sw\n", $$name)} else {printf ("FAIL: %sw (%#x != 0x3b4b)\n", $$name, $arg2)} if ($arg3 == 0x1b2b3b4b) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %sd (%#x != 0x1b2b3b4b)\n", $$name, $arg3)} if ($arg4 == 0x1b2b3b4b1b2b3b4b) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %sx (%#x != 0x1b2b3b4b1b2b3b4b)\n", $$name, $arg4)} } probe process(@1).mark("r12") ? { if ($arg1 == 0x4c) {printf ("PASS: %sb\n", $$name)} else {printf ("FAIL: %sb (%#x != 0x4c)\n",$$name, $arg1)} if ($arg2 == 0x3c4c) {printf ("PASS: %sw\n", $$name)} else {printf ("FAIL: %sw (%#x != 0x3c4c)\n", $$name, $arg2)} if ($arg3 == 0x1c2c3c4c) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %sd (%#x != 0x1c2c3c4c)\n", $$name, $arg3)} if ($arg4 == 0x1c2c3c4c1c2c3c4c) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %sx (%#x != 0x1c2c3c4c1c2c3c4c)\n", $$name, $arg4)} } probe process(@1).mark("r13") ? { if ($arg1 == 0x4d) {printf ("PASS: %sb\n", $$name)} else {printf ("FAIL: %sb (%#x != 0x4d)\n",$$name, $arg1)} if ($arg2 == 0x3d4d) {printf ("PASS: %sw\n", $$name)} else {printf ("FAIL: %sw (%#x != 0x3d4d)\n", $$name, $arg2)} if ($arg3 == 0x1d2d3d4d) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %sd (%#x != 0x1d2d3d4d)\n", $$name, $arg3)} if ($arg4 == 0x1d2d3d4d1d2d3d4d) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %sx (%#x != 0x1d2d3d4d1d2d3d4d)\n", $$name, $arg4)} } probe process(@1).mark("r14") ? { if ($arg1 == 0x4e) {printf ("PASS: %sb\n", $$name)} else {printf ("FAIL: %sb (%#x != 0x4e)\n",$$name, $arg1)} if ($arg2 == 0x3e4e) {printf ("PASS: %sw\n", $$name)} else {printf ("FAIL: %sw (%#x != 0x3e4e)\n", $$name, $arg2)} if ($arg3 == 0x1e2e3e4e) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %sd (%#x != 0x1e2e3e4e)\n", $$name, $arg3)} if ($arg4 == 0x1e2e3e4e1e2e3e4e) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %sx (%#x != 0x1e2e3e4e1e2e3e4e)\n", $$name, $arg4)} } probe process(@1).mark("r15") ? { if ($arg1 == 0x4f) {printf ("PASS: %sb\n", $$name)} else {printf ("FAIL: %sb (%#x != 0x4f)\n",$$name, $arg1)} if ($arg2 == 0x3f4f) {printf ("PASS: %sw\n", $$name)} else {printf ("FAIL: %sw (%#x != 0x3f4f)\n", $$name, $arg2)} if ($arg3 == 0x1f2f3f4f) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %sd (%#x != 0x1f2f3f4f)\n", $$name, $arg3)} if ($arg4 == 0x1f2f3f4f1f2f3f4f) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %sx (%#x != 0x1f2f3f4f1f2f3f4f)\n", $$name, $arg4)} } probe process(@1).mark("memory") ? { if ($arg1 == 7 && $arg2 == 7 && $arg3 == 7) {printf ("PASS: %s\n", $$name)} else {printf ("FAIL: %s ((%d|%d|%d) != 7)\n", $$name, $arg1, $arg2, $arg3)} } # PR14369: make sure a bad $var doesn't prevent the probes from being found at all probe process(@1).mark("*") { if (! @defined($no_such_var)) {printf ("PASS: %s @defined\n", $$name)} else {printf ("FAIL: %s @defined\n")} # shouldn't get here, failure is actually in translation } systemtap-2.3/testsuite/systemtap.base/sdt_global_var.exp000066400000000000000000000066711217430427200241160ustar00rootroot00000000000000set test "sdt_global_var" # Test accessing global variables in SDT probes. set result_string10 "z: @(\"my_global_var\") = 56 z: \$my_global_var = 56 j: @(\"my_global_var\") = 57 j: \$my_global_var = 57" set result_string12 " l: @(\"my_global_var\") = 57 l: \$my_global_var = 57" set extra_flags {{additional_flags=-O2} {additional_flags=-fPIE additional_flags=-pie additional_flags=-O2}} set extra_mssgs {-O2} set pbtype_flags {{""} {additional_flags=-DSTAP_SDT_V2}} set pbtype_mssgs {{uprobe} {V2_uprobe}} proc sdt_stap_run { TEST_NAME TEST_FILE FAIL args } { foreach runtime [get_runtime_list] { set full_test_name $TEST_NAME if {$runtime != ""} { if {$runtime == "dyninst" && [regexp "\-pie" $TEST_NAME]} { setup_kfail 15052 "*-*-*" } lappend full_test_name "($runtime)" set cmd [concat stap --runtime=$runtime $TEST_FILE $args] } elseif {[uprobes_p]} { set cmd [concat stap $TEST_FILE $args] } else { untested $full_test_name continue } send_log "executing: $cmd\n" catch {eval exec $cmd} res set skip 0 set n 0 set expected [split $::result_string "\n"] foreach line [split $res "\n"] { if {![string equal $line [lindex $expected $n]]} { $FAIL "$full_test_name" send_log "line [expr $n + 1]: expected \"[lindex $expected $n]\"\n" send_log "Got \"$line\"\n" set skip 1 break } incr n } if {$skip != 0} { continue } if {[expr $n == [llength $expected]]} { pass "$full_test_name" } else { $FAIL "$full_test_name" send_log "too few lines of output, got $n, expected [llength $expected]\n" } } } # Iterate pbtype_flags for {set p 0} {$p < [llength $pbtype_flags]} {incr p} { set pbtype_flag [lindex $pbtype_flags $p] set pbtype_mssg [lindex $pbtype_mssgs $p] # Iterate extra_flags, trying the cases with and without PIE for {set i 0} {$i < [llength $extra_flags]} {incr i} { set extra_flag [lindex $extra_flags $i] set extra_mssg [lindex $extra_mssgs $i] set testprog "sdt.c.exe.$i" set test_flags "additional_flags=-g" set test_flags "$test_flags [sdt_includes]" set test_flags "$test_flags additional_flags=-Wall" set test_flags "$test_flags additional_flags=-Wextra" set test_flags "$test_flags additional_flags=-Werror $pbtype_flag" set saveidx 0 set res [target_compile $srcdir/$subdir/sdt.c $testprog executable "$test_flags $extra_flag"] if { $res != "" } { verbose "target_compile failed: $res" 2 if {[string first "unrecognized command line option" $res] == -1} { fail "compiling sdt.c $extra_mssg $pbtype_mssg" } else { untested "compiling sdt.c $extra_mssg $pbtype_mssg" } untested "$test $extra_mssg $pbtype_mssg" continue } else { pass "compiling sdt.c $extra_mssg $pbtype_mssg" } if {[installtest_p]} { if {[regexp "^(ppc64|s390x)$" $::tcl_platform(machine)] \ && [regexp "^(-O)" $extra_mssg]} { # register name and constant is ambiguous in ppc/s390 asm syntax # thus constant folding can throw the result off set FAIL xfail } else { set FAIL fail } set ::result_string $result_string10 if { $pbtype_mssg == "uprobe" } { append ::result_string $result_string12 } sdt_stap_run "$test $extra_mssg $pbtype_mssg $extra_flag" \ -w $FAIL $srcdir/$subdir/$test.stp $testprog -c ./$testprog } else { untested "$test $extra_mssg $pbtype_mssg" } catch {exec rm -f $testprog} } ; # for {set i 0} {$i < [llength $extra_flags]} } ; # for {set i 0} {$i < [llength $pbtype_flags]} systemtap-2.3/testsuite/systemtap.base/sdt_global_var.stp000066400000000000000000000007361217430427200241240ustar00rootroot00000000000000probe process(@1).mark("mark_z") { printf("z: @(\"my_global_var\") = %d\n", @var("my_global_var")); printf("z: $my_global_var = %d\n", $my_global_var); } probe process(@1).mark("mark_j") { printf("j: @(\"my_global_var\") = %d\n", @var("my_global_var")); printf("j: $my_global_var = %d\n", $my_global_var); } probe process(@1).mark("mark_l") ? { printf("l: @(\"my_global_var\") = %d\n", @var("my_global_var")); printf("l: $my_global_var = %d\n", $my_global_var); } systemtap-2.3/testsuite/systemtap.base/sdt_misc.c000066400000000000000000000041241217430427200223560ustar00rootroot00000000000000#include #include #include #include #ifdef LOOP static struct timespec req = {0, 200000000}; #endif #ifndef ONLY_MAIN #include "sdt_misc_.h" void sem_display () { printf("%s epilogue %s=%ld\n", (SDT_MISC_TEST_PROBE_0_ENABLED() ? "FAIL" : "PASS"), "test_probe_0_semaphore", SDT_MISC_TEST_PROBE_0_ENABLED()); printf("%s epilogue %s=%ld\n", (SDT_MISC_TEST_PROBE_2_ENABLED() ? "FAIL" : "PASS"), "test_probe_2_semaphore", SDT_MISC_TEST_PROBE_2_ENABLED()); printf("%s epilogue %s=%ld\n", (SDT_MISC_TEST_PROBE_3_ENABLED() ? "FAIL" : "PASS"), "test_probe_3_semaphore", SDT_MISC_TEST_PROBE_3_ENABLED()); printf("%s epilogue %s=%ld\n", (SDT_MISC_TEST_PROBE_4_ENABLED() ? "FAIL" : "PASS"), "test_probe_4_semaphore", SDT_MISC_TEST_PROBE_4_ENABLED()); } #ifdef LOOP int loop_check() { return SDT_MISC_TEST_PROBE_0_ENABLED(); } #endif void bar (int i) { #ifdef LOOP while (!loop_check()) { nanosleep(&req, NULL); } #endif #ifndef NO_SLEEP sleep (3); #endif SDT_MISC_TEST_PROBE_2(i); if (i == 0) i = 1000; if (SDT_MISC_TEST_PROBE_2_ENABLED()) STAP_PROBE1(sdt_misc,test_probe_2,i); } void baz (int i, char* s) { if (SDT_MISC_TEST_PROBE_0_ENABLED()) STAP_PROBE1(sdt_misc,test_probe_0,i); if (i == 0) i = 1000; if (SDT_MISC_TEST_PROBE_3_ENABLED()) SDT_MISC_TEST_PROBE_3(i,s); } void buz (int parm) { struct astruct { int a; int b; int *c; }; struct astruct bstruct = {parm, parm + 1}; struct astruct *cstruct = &bstruct; if (parm == 0) parm = 1000; if (SDT_MISC_TEST_PROBE_4_ENABLED()) DTRACE_PROBE1(sdt_misc,test_probe_4,&bstruct); SDT_MISC_TEST_PROBE_1(cstruct->c != ((void*)0)); } #endif #ifndef NO_MAIN void int_handler(int sig) { sem_display(); exit(1); } void alrm_handler(int sig) { exit (1); } #ifdef LOOP #include #endif int main () { #ifdef LOOP signal (SIGINT, &int_handler); // signal (SIGALRM, &alrm_handler); // alarm (300); #endif bar(2); baz(3,(char*)"abc"); buz(4); #ifdef LOOP while (1) {nanosleep(&req, NULL);} #endif return 0; } #endif systemtap-2.3/testsuite/systemtap.base/sdt_misc.exp000066400000000000000000000551341217430427200227370ustar00rootroot00000000000000set test "sdt_misc" # Test miscellaneous features of .mark probes # 1. Test executable built with dtrace generated header file # 2. Test attaching to a running process # 3. Test passing various C types to .mark probes # 4. Test probe in shared object # 5. Test attaching to a running process with markers in a shared object # 6. Test .mark probe wildcard matching # 7. Test types defined in sdt_misc_.d. This requires -g # 8. Test V3 asm support set v_flags {{-DSTAP_SDT_V1} {-DSTAP_SDT_V2} {-DSTAP_SDT_V3}} set pbtype_mssgs {{V1_uprobe} {V2_uprobe} {V3_uprobe}} set pbtype_flags {{additional_flags=-g} {} {}} proc cleanup_handler { verbose } { global pbtype_mssgs if { $verbose == 0 } { foreach x $pbtype_mssgs { catch {exec rm -f libsdt_${x}.so libsdt_${x}_shared.so \ sdt_misc_${x}.x sdt_misc_${x}_loop.x \ sdt_misc_${x}_shared.x sdt_misc_${x}_loop_shared.x \ sdt_misc_${x}.x sdt_misc_${x}_compatibility.x \ sdt_misc_${x}_types.x libsdt_${x}_loop.so } } catch {exec rm -f sdt_misc_.c sdt_misc_.h sdt_misc_.o sdt_types.x \ sdt_asm.x ,semclean ,semout} } } # Compile a C program to use as the user-space probing target set stap_path $env(SYSTEMTAP_PATH)/stap set sup_dpath "[pwd]/sdt_misc_.d" set sup_hpath "[pwd]/sdt_misc_.h" set sup_opath "[pwd]/sdt_misc_.o" # Iterate pbtype_flags for {set i 0} {$i < [llength $pbtype_flags]} {incr i} { set v_flag [lindex $v_flags $i] set pbtype_flag "[lindex $pbtype_flags $i] additional_flags=$v_flag" set pbtype_mssg [lindex $pbtype_mssgs $i] set sup_exepath "[pwd]/sdt_misc_$pbtype_mssg.x" # Run dtrace if {[installtest_p]} { set dtrace $env(SYSTEMTAP_PATH)/dtrace } else { set dtrace ../dtrace } verbose -log "$dtrace $v_flag --types -h -s $srcdir/$subdir/sdt_misc_.d" if {[catch {exec $dtrace $v_flag --types -h -s \ $srcdir/$subdir/sdt_misc_.d} res]} { verbose -log "unable to run $dtrace: $res" } verbose -log "$dtrace $v_flag --types -G -s $srcdir/$subdir/sdt_misc_.d" if {[catch {exec $dtrace $v_flag --types -G -s \ $srcdir/$subdir/sdt_misc_.d} res]} { verbose -log "unable to run $dtrace: $res" } if {[file exists $sup_hpath] && [file exists $sup_opath]} then { pass "$test dtrace $pbtype_mssg" } else { fail "$test dtrace $pbtype_mssg" cleanup_handler $verbose return } set sup_flags [sdt_includes] set sup_flags "$sup_flags additional_flags=-Wall" set sup_flags "$sup_flags additional_flags=-Werror" set sup_flags "$sup_flags additional_flags=$sup_opath" set sup_flags "$sup_flags additional_flags=-I. $pbtype_flag" set res [target_compile $srcdir/$subdir/sdt_misc.c $sup_exepath \ executable $sup_flags] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test compiling $pbtype_mssg" cleanup_handler $verbose return } else { pass "$test compiling $pbtype_mssg" } if {![installtest_p]} { untested $test cleanup_handler $verbose return } # 1. Test executable built with dtrace generated header file foreach runtime [get_runtime_list] { set test_xtra "" if {$runtime != ""} { set test_xtra " ($runtime)" verbose -log "spawn $stap_path --runtime=$runtime -c $sup_exepath $srcdir/$subdir/sdt_misc.stp $sup_exepath" spawn $stap_path --runtime=$runtime -c $sup_exepath \ $srcdir/$subdir/sdt_misc.stp $sup_exepath } elseif {[uprobes_p]} { verbose -log "spawn $stap_path -c $sup_exepath $srcdir/$subdir/sdt_misc.stp $sup_exepath" spawn $stap_path -c $sup_exepath $srcdir/$subdir/sdt_misc.stp \ $sup_exepath } else { untested "$test ${pbtype_mssg}" continue } set ok 0 expect { -timeout 180 -re {In test_probe_2 probe 0x2} { incr ok; exp_continue } -re {In test_probe_0 probe 0x3} { incr ok; exp_continue } -re {In test_probe_3 probe 0x3 0x[0-9a-f][0-9a-f]} { incr ok; exp_continue } -re {In test_probe_4 dtrace probe 0x[0-9a-f]} { incr ok; exp_continue } -re {In test_probe_1 probe 0x0} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 6} { pass "$test ${pbtype_mssg}${test_xtra}" } else { if {[istarget "arm-*-*"] && $pbtype_mssg == "V2_uprobe"} { xfail "$test ($ok) ${pbtype_mssg}${test_xtra}" } else { fail "$test ($ok) ${pbtype_mssg}${test_xtra}" } } } # 2. Test attaching to a running process set loop_flags "$sup_flags additional_flags=-DLOOP" set loop_exepath "[pwd]/sdt_misc_${pbtype_mssg}_loop.x" set res [target_compile $srcdir/$subdir/sdt_misc.c $loop_exepath \ executable $loop_flags] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test compiling $pbtype_mssg -DLOOP" cleanup_handler $verbose return } else { pass "$test compiling $pbtype_mssg -DLOOP" } foreach runtime [get_runtime_list] { set test_xtra "" if {$runtime != ""} { set test_xtra " ($runtime)" # This is perhaps a wee bit clumsy verbose -log "$loop_exepath >| ,semclean 2>&1 & TEST=\$! ; \ $stap_path --runtime=$runtime $srcdir/$subdir/sdt_misc.stp $loop_exepath >| ,semout ; \ /usr/bin/kill -SIGINT \$TEST" system "$loop_exepath >,semclean 2>&1 & TEST=\$! ; \ $stap_path --runtime=$runtime $srcdir/$subdir/sdt_misc.stp $loop_exepath >| ,semout ; \ /usr/bin/kill -SIGINT \$TEST" } elseif {[uprobes_p]} { # This is perhaps a wee bit clumsy verbose -log "$loop_exepath >| ,semclean 2>&1 & TEST=\$! ; \ $stap_path $srcdir/$subdir/sdt_misc.stp $loop_exepath >| ,semout ; \ /usr/bin/kill -SIGINT \$TEST" system "$loop_exepath >,semclean 2>&1 & TEST=\$! ; \ $stap_path $srcdir/$subdir/sdt_misc.stp $loop_exepath >| ,semout ; \ /usr/bin/kill -SIGINT \$TEST" } else { untested "$test $pbtype_mssg attach" continue } set ok 0 set ko 0 spawn cat ,semout expect { -re {In test_probe_2 probe 0x2} { incr ok; exp_continue } -re {In test_probe_0 probe 0x3} { incr ok; exp_continue } -re {In test_probe_3 probe 0x3 0x[0-9a-f][0-9a-f]} { incr ok; exp_continue } -re {In test_probe_4 dtrace probe 0x[0-9a-f]} { incr ok; exp_continue } -re {In test_probe_1 probe 0x0} { incr ok; exp_continue } eof { } } catch {close}; catch {wait} if {$ok == 6} { pass "$test ${pbtype_mssg}${test_xtra} attach" } else { if {[istarget "arm-*-*"] && $pbtype_mssg == "V2_uprobe"} { xfail "$test ($ok) ${pbtype_mssg}${test_xtra} attach" } else { fail "$test ($ok) ${pbtype_mssg}${test_xtra} attach" } } set ok 0 spawn cat ,semclean expect { -timeout 180 -re {PASS} { incr ok; exp_continue } -re {FAIL} { incr ko; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 4 && $ko == 0} { pass "$test ${pbtype_mssg}${test_xtra} epilogue" } else { fail "$test ($ok) ${pbtype_mssg}${test_xtra} epilogue" } } # 3. Test passing various C types to .mark probes # same set of flags as sdt.exp set extra_type_flags {{additional_flags=-O2} {additional_flags=-O3} {additional_flags=-std=c89} {additional_flags=-std=c99} {additional_flags=-std=gnu99} {c++ additional_flags=-std=c++98 additional_flags=-x \ additional_flags=c++} {c++ additional_flags=-std=gnu++98 additional_flags=-x \ additional_flags=c++} {c++ additional_flags=-std=c++0x additional_flags=-x \ additional_flags=c++} {c++ additional_flags=-std=gnu++0x additional_flags=-x \ additional_flags=c++} } set extra_type_mssgs {-O2 -O3 c89 c99 gnu99 c++98 gnu++98 c++0x gnu++0x} # __STDC_VERSION__ could be used, but g++ has no equivalent set has_long_long {{} {} additional_flags=-DNO_LONG_LONG {} {} \ additional_flags=-DNO_LONG_LONG \ additional_flags=-DNO_LONG_LONG {} {}} set type_xfail {1 1 0 0 0 0 0 0 0} set type_pedantics_idx {1 1 2 2 2 2 2 2 2} # don't compile -O2 -O3 with -pedantic set type_pedantics {{} additional_flags=-pedantic} set type_pedantic_mssgs {{} -pedantic} for {set j 0} {$j < [llength $extra_type_flags]} {incr j} { set extra_type_mssg [lindex $extra_type_mssgs $j] for {set p 0} {$p < [lindex $type_pedantics_idx $j]} {incr p} { set type_pedantic_mssg [lindex $type_pedantic_mssgs $p] set type_flags "[sdt_includes] additional_flags=-Wall additional_flags=-Werror" set type_flags "$type_flags additional_flags=-I. $pbtype_flag" set type_flags "$type_flags [lindex $extra_type_flags $j] [lindex $type_pedantics $p] [lindex $has_long_long $j]" if {![istarget "i*86-*-*"] && ![istarget "arm-*-*"]} { set type_flags "$type_flags additional_flags=-m64" } set test_suffix "$pbtype_mssg $extra_type_mssg $type_pedantic_mssg" # On ARM these tests are known to fail with timeout for V1 # and V2 probes. Skip them altogether to speed execution. if {[istarget "arm-*-*"] \ && ($pbtype_mssg == "V1_uprobe" \ || $pbtype_mssg == "V2_kprobe" \ || $pbtype_mssg == "V2_uprobe")} { xfail "$test types $test_suffix" continue } set res [target_compile $srcdir/$subdir/sdt_types.c \ sdt_types.x executable $type_flags] if { $res != "" } { verbose "target_compile failed: $res" 2 # -std=gnu++0x and -std=c++0x are not universally accepted if {[string first "unrecognized command line option" $res] == -1} { fail "$test compiling types $test_suffix" } else { untested "$test compiling types $test_suffix" } untested "$test types $test_suffix" continue ; # type_pedantics_idx } else { pass "$test compiling types $test_suffix" } foreach runtime [get_runtime_list] { set test_xtra "" if {$runtime != ""} { set test_xtra " ($runtime)" verbose -log "spawn $stap_path --runtime=$runtime -g -c ./sdt_types.x $srcdir/$subdir/sdt_types.stp ./sdt_types.x # $pbtype_mssg $extra_type_mssg" spawn $stap_path --runtime=$runtime -g -c ./sdt_types.x $srcdir/$subdir/sdt_types.stp ./sdt_types.x } elseif {[uprobes_p]} { verbose -log "spawn $stap_path -g -c ./sdt_types.x $srcdir/$subdir/sdt_types.stp ./sdt_types.x # $pbtype_mssg $extra_type_mssg" spawn $stap_path -g -c ./sdt_types.x $srcdir/$subdir/sdt_types.stp ./sdt_types.x } else { untested "$test types $test_suffix" continue } set test_suffix "${pbtype_mssg}${test_xtra} $extra_type_mssg $type_pedantic_mssg" set ok 0 set notok 0 set fail "types" set uns_notok 0 expect { -timeout 180 # i386 unsigned may xfail because of sign extension # but fail anything else -re {FAIL: [a-z_]+var} { regexp " .*$" $expect_out(0,string) s if {[regexp "unsigned" $s] && [istarget "i*86-*-*"]} { incr uns_notok } incr notok; set fail "$fail $s"; exp_continue } -re {PASS: [a-z_]+var} { incr ok; exp_continue } timeout { fail "$test types (timeout) $test_suffix" } eof { } } catch {close}; catch {wait} if { $notok != 0 || $ok == 0} { if { [lindex $type_xfail $j] || $notok == $uns_notok} { xfail "$test types $fail $test_suffix" } else { fail "$test types $fail $test_suffix" } } else { pass "$test types $test_suffix" } } } ; # end type_pedantics_idx } ; # end extra_type_flags # 4. Test probe in shared object set sup41_flags "$sup_flags additional_flags=-shared" set sup41_flags "$sup41_flags additional_flags=-fPIC" set sup41_flags "$sup41_flags additional_flags=-DNO_MAIN" set sup_sopath "[pwd]/libsdt_$pbtype_mssg.so" set sup_exepath "[pwd]/sdt_misc_${pbtype_mssg}_shared.x" set res0 [target_compile $srcdir/$subdir/sdt_misc.c $sup_sopath \ executable $sup41_flags ] set sup42_flags "additional_flags=-Wl,-rpath,[pwd]" set sup42_flags "$sup42_flags additional_flags=-L[pwd] additional_flags=-lsdt_${pbtype_mssg}" set sup42_flags "$sup42_flags additional_flags=-DONLY_MAIN" set res [target_compile $srcdir/$subdir/sdt_misc.c $sup_exepath \ executable $sup42_flags ] if { $res0 != "" || $res != "" } { verbose "target_compile failed: $res0 $res" 2 fail "$test compiling -shared $pbtype_mssg" cleanup_handler $verbose return } else { pass "$test compiling -shared $pbtype_mssg" } foreach runtime [get_runtime_list] { set test_xtra "" if {$runtime != ""} { set test_xtra " ($runtime)" verbose -log "spawn $stap_path --runtime=$runtime -c $sup_exepath $srcdir/$subdir/sdt_misc.stp $sup_exepath $sup_sopath" spawn $stap_path --runtime=$runtime -c $sup_exepath $srcdir/$subdir/sdt_misc.stp $sup_exepath $sup_sopath } elseif {[uprobes_p]} { verbose -log "spawn $stap_path -c $sup_exepath $srcdir/$subdir/sdt_misc.stp $sup_exepath $sup_sopath" spawn $stap_path -c $sup_exepath $srcdir/$subdir/sdt_misc.stp $sup_exepath $sup_sopath } else { untested "$test shared $pbtype_mssg" continue } set ok 0 expect { -timeout 180 -re {In test_probe_2 probe 0x2} { incr ok; exp_continue } -re {In test_probe_0 probe 0x3} { incr ok; exp_continue } -re {In test_probe_3 probe 0x3 0x[0-9a-f][0-9a-f]} { incr ok; exp_continue } -re {In test_probe_4 dtrace probe 0x[0-9a-f]} { incr ok; exp_continue } -re {In test_probe_1 probe 0x0} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 6} { pass "$test shared ${pbtype_mssg}${test_xtra}" } else { if {[istarget "arm-*-*"] && $pbtype_mssg == "V2_uprobe"} { xfail "$test ($ok) shared ${pbtype_mssg}${test_xtra}" } else { fail "$test ($ok) shared ${pbtype_mssg}${test_xtra}" } } } # 5. Test attaching to a running process with markers in a shared object set supl_flags "$sup41_flags additional_flags=-DLOOP" set supl_sopath "[pwd]/libsdt_${pbtype_mssg}_loop.so" set res0 [target_compile $srcdir/$subdir/sdt_misc.c $supl_sopath \ executable $supl_flags ] set loop_flags [sdt_includes] set loop_flags "$loop_flags additional_flags=-I. $pbtype_flag" set loop_flags "$loop_flags additional_flags=-DLOOP" set loop_flags "$loop_flags additional_flags=-DONLY_MAIN" set loop_flags "$loop_flags additional_flags=-Wl,-rpath,[pwd]" set loop_flags "$loop_flags additional_flags=-L[pwd] additional_flags=-lsdt_${pbtype_mssg}_loop" set loop_exepath "[pwd]/sdt_misc_${pbtype_mssg}_loop_shared.x" set res [target_compile $srcdir/$subdir/sdt_misc.c $loop_exepath \ executable $loop_flags] set test_suffix "$pbtype_mssg -DLOOP with markers in a shared object" if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test compiling $test_suffix" cleanup_handler $verbose return } else { pass "$test compiling $test_suffix" } foreach runtime [get_runtime_list] { set test_xtra "" if {$runtime != ""} { set test_xtra " ($runtime)" # With --runtime=dyninst these tests will fail since the # dyninst runtime needs a target executable (either '-c # exe' or '-x pid'). So, skip these tests to speed up test # execution. xfail "$test ${pbtype_mssg}${test_xtra} shared attach" continue } elseif {[uprobes_p]} { # This is perhaps a wee bit clumsy verbose -log "$loop_exepath >| ,semclean 2>&1 & TEST=\$! ; \ $stap_path $srcdir/$subdir/sdt_misc.stp $loop_exepath $supl_sopath >| ,semout ; \ /usr/bin/kill -SIGINT \$TEST" system "$loop_exepath >,semclean 2>&1 & TEST=\$! ; \ $stap_path $srcdir/$subdir/sdt_misc.stp $loop_exepath $supl_sopath >| ,semout ; \ /usr/bin/kill -SIGINT \$TEST" } else { untested "$test $pbtype_mssg shared attach" continue } set ok 0 set ko 0 spawn cat ,semout expect { -re {In test_probe_2 probe 0x2} { incr ok; exp_continue } -re {In test_probe_0 probe 0x3} { incr ok; exp_continue } -re {In test_probe_3 probe 0x3 0x[0-9a-f][0-9a-f]} { incr ok; exp_continue } -re {In test_probe_4 dtrace probe 0x[0-9a-f]} { incr ok; exp_continue } -re {In test_probe_1 probe 0x0} { incr ok; exp_continue } eof { } } catch {close}; catch {wait} if {$ok == 6} { pass "$test ${pbtype_mssg}${test_xtra} shared attach" } else { if {[istarget "arm-*-*"] && $pbtype_mssg == "V2_uprobe"} { xfail "$test ($ok) ${pbtype_mssg}${test_xtra} shared attach" } else { fail "$test ($ok) ${pbtype_mssg}${test_xtra} shared attach" } } set ok 0 spawn cat ,semclean expect { -timeout 180 -re {PASS} { incr ok; exp_continue } -re {FAIL} { incr ko; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 4 && $ko == 0} { pass "$test ${pbtype_mssg}${test_xtra} shared shared epilogue" } else { fail "$test ($ok) ${pbtype_mssg}${test_xtra} shared epilogue" } } # 6. Test .mark probe wildcard matching set ok 0 verbose -log "spawn $stap_path -L \"process(\"./sdt_types.x\").mark(\"*\")" spawn $stap_path -L "process(\"./sdt_types.x\").mark(\"*\")" expect { -timeout 180 -re {mark\(\"[a-z_]+\"\) .arg1:long .arg2:long .arg3:long .arg4:long .arg5:long .arg6:long .arg7:long .arg8:long\n} { incr ok; exp_continue } -re {mark\(\"[a-z_]+\"\) .arg1:long .arg2:long\n} { incr ok; exp_continue } -re {mark\(\"[a-z_]+\"\) .arg1:long\n} { incr ok; exp_continue } -re {mark\(\"[a-z_]+\"\)} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} # PR10245: match the __ one here spawn $stap_path -l "process(\"./sdt_types.x\").mark(\"*-*-*\")" expect { -timeout 180 -re {mark\(\"[a-z_]+\"\)} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if { $ok == 51 || $ok == 48 \ || (($ok == 43 || $ok == 40 ) && ([istarget "i.86-*-*"] \ || [istarget "arm-*-*"]))} { pass "$test wildcard $pbtype_mssg" } else { fail "$test wildcard ($ok) $pbtype_mssg" } # 7. Test types defined in sdt_misc_.d. This requires -g set supbc_flags "$sup_flags additional_flags=-g additional_flags=-DNO_SLEEP" set supbc_exepath "[pwd]/sdt_misc_${pbtype_mssg}_types.x" set res [target_compile $srcdir/$subdir/sdt_misc.c $supbc_exepath \ executable $supbc_flags] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test compiling -g $pbtype_mssg --types" cleanup_handler $verbose return } else { pass "$test compiling -g $pbtype_mssg --types" } foreach runtime [get_runtime_list] { set test_xtra "" if {$runtime != ""} { set test_xtra " ($runtime)" verbose -log "spawn $stap_path --runtime=$runtime -c $supbc_exepath -e \"probe process(\"$supbc_exepath\").mark(\"test_probe_4\") {printf(\"In %s dtrace probe %#x %#x\\n\", \$\$name, \$arg1->a, \$arg1->b)}\"" spawn $stap_path --runtime=$runtime -c $supbc_exepath -e "probe process(\"$supbc_exepath\").mark(\"test_probe_4\") {printf(\"In %s dtrace probe %#x %#x\\n\", \$\$name, \$arg1->a, \$arg1->b)}" } elseif {[uprobes_p]} { verbose -log "spawn $stap_path -c $supbc_exepath -e \"probe process(\"$supbc_exepath\").mark(\"test_probe_4\") {printf(\"In %s dtrace probe %#x %#x\\n\", \$\$name, \$arg1->a, \$arg1->b)}\"" spawn $stap_path -c $supbc_exepath -e "probe process(\"$supbc_exepath\").mark(\"test_probe_4\") {printf(\"In %s dtrace probe %#x %#x\\n\", \$\$name, \$arg1->a, \$arg1->b)}" } else { untested "$test $pbtype_mssg --types" continue } set ok 0 expect { -timeout 180 -re {In test_probe_4 dtrace probe 0x4 0x5} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 1} { pass "$test ${pbtype_mssg}${test_xtra} --types" } else { if {[istarget "arm-*-*"] && $pbtype_mssg == "V2_uprobe"} { xfail "$test ($ok) ${pbtype_mssg}${test_xtra} --types" } else { fail "$test ($ok) ${pbtype_mssg}${test_xtra} --types" } } } } ; # end pbtype_flags # 8. Test V3 asm support if {[istarget "x86_64-*-*"] || [istarget "i*86-*-*"]} { set asm_flags [sdt_includes] # avoid WARNING for @defined($no_such_var) set asm_flags "$asm_flags additional_flags=-g" set res [target_compile $srcdir/$subdir/sdt_asm.S sdt_asm.x \ executable $asm_flags] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test compiling sdt_asm.S" } else { pass "$test compiling sdt_asm.S" } foreach runtime [get_runtime_list] { set test_xtra "" if {$runtime != ""} { set test_xtra " ($runtime)" verbose -log "spawn $stap_path --runtime=$runtime -c [pwd]/sdt_asm.x $srcdir/$subdir/sdt_asm.stp [pwd]/sdt_asm.x" spawn $stap_path --runtime=$runtime -c [pwd]/sdt_asm.x $srcdir/$subdir/sdt_asm.stp [pwd]/sdt_asm.x } elseif {[uprobes_p]} { verbose -log "spawn $stap_path -c [pwd]/sdt_asm.x $srcdir/$subdir/sdt_asm.stp [pwd]/sdt_asm.x" spawn $stap_path -c [pwd]/sdt_asm.x $srcdir/$subdir/sdt_asm.stp [pwd]/sdt_asm.x } else { untested "$test asm" continue } set ok 0 set notok 0 set fail "asm" expect { -timeout 180 -re {FAIL: [a-z0-9]} { regexp " .*$" $expect_out(0,string) s; incr notok; set fail "$fail $s"; exp_continue } -re {PASS: [a-z0-9]} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if { $notok != 0 || $ok == 0} { fail "$test asm${test_xtra} ($ok) $fail" } else { pass "$test asm${test_xtra} ($ok)" } } } ; # x86_64 | i.86 foreach runtime [get_runtime_list] { set test_xtra "" if {$runtime != ""} { set test_xtra " ($runtime)" verbose -log "spawn $stap_path --runtime=$runtime -c ./sdt_misc_V3_uprobe.x -e \"probe process(\"./sdt_misc_V3_uprobe.x\").mark(\"test_probe_5\") {printf(\"%s %s %s\\n\", \$\$provider, \$\$name, \$\$parms)}\"" spawn $stap_path --runtime=$runtime -c ./sdt_misc_V3_uprobe.x -e "probe process(\"./sdt_misc_V3_uprobe.x\").mark(\"test_probe_3\") {printf(\"%s %s %s\\n\", \$\$provider, \$\$name, \$\$parms)}" } elseif {[uprobes_p]} { verbose -log "spawn $stap_path -c ./sdt_misc_V3_uprobe.x -e \"probe process(\"./sdt_misc_V3_uprobe.x\").mark(\"test_probe_5\") {printf(\"%s %s %s\\n\", \$\$provider, \$\$name, \$\$parms)}\"" spawn $stap_path -c ./sdt_misc_V3_uprobe.x -e "probe process(\"./sdt_misc_V3_uprobe.x\").mark(\"test_probe_3\") {printf(\"%s %s %s\\n\", \$\$provider, \$\$name, \$\$parms)}" } else { untested "$test \$\$parms" continue } set ok 0 expect { -timeout 180 -re {sdt_misc test_probe_3 \$arg1=0x3 \$arg2=0x[0-9a-f][0-9a-f]} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 1} { pass "$test \$\$parms${test_xtra}" } else { fail "$test ($ok) \$\$parms${test_xtra}" } } cleanup_handler $verbose systemtap-2.3/testsuite/systemtap.base/sdt_misc.stp000066400000000000000000000015151217430427200227430ustar00rootroot00000000000000%( $# > 1 %? probe process(@1).library(@2).mark("test_probe_0") %: probe process(@1).mark("test_probe_0") %) { printf("In %s probe %#x\n", $$name, $arg1) } %( $# > 1 %? probe process(@1).library(@2).mark("test_probe_1") %: probe process(@1).mark("test_probe_1") %) { printf("In %s probe %#x\n", $$name, $arg1) } %( $# > 1 %? probe process(@1).library(@2).mark("test_probe_2") %: probe process(@1).mark("test_probe_2") %) { printf("In %s probe %#x\n", $$name, $arg1) } %( $# > 1 %? probe process(@1).library(@2).mark("test_probe_3") %: probe process(@1).mark("test_probe_3") %) { printf("In %s probe %#x %#x\n", $$name, $arg1, $arg2) } %( $# > 1 %? probe process(@1).library(@2).mark("test_probe_4") %: probe process(@1).mark("test_probe_4") %) { printf("In %s dtrace probe %#x\n", $$name, $arg1) } probe timer.sec(30) { exit() } systemtap-2.3/testsuite/systemtap.base/sdt_misc_.d000066400000000000000000000003401217430427200225120ustar00rootroot00000000000000provider sdt_misc { probe test_probe_0 (); probe test_probe_1 (int i); probe test_probe_2 (int i); probe test_probe_3 (int i, char* x); probe test_probe_4 (struct astruct arg); }; struct astruct {int a; int b;}; systemtap-2.3/testsuite/systemtap.base/sdt_types.c000066400000000000000000000202431217430427200225670ustar00rootroot00000000000000#include "sys/sdt.h" #include #include struct opaque; int main (int argc, char **argv) { char char_var = '~'; const char const_char_var = '!'; volatile char volatile_char_var = '!'; char *ptr_char_var = &char_var; const char *ptr_const_char_var = &char_var; char * const char_ptr_const_var = &char_var; volatile char *ptr_volatile_char_var = &char_var; char * volatile char_ptr_volatile_var = &char_var; short int short_int_var = 32767; const short int const_short_int_var = -32767; volatile short int volatile_short_int_var = -32767; short int *ptr_short_int_var = &short_int_var; const short int *ptr_const_short_int_var = &short_int_var; short int * const short_int_ptr_const_var = &short_int_var; volatile short int *ptr_volatile_short_int_var = &short_int_var; short int * volatile short_int_ptr_volatile_var = &short_int_var; unsigned short int short_uint_var = (unsigned short)0xffff8001; int int_var = 65536; const int const_int_var = -65536; volatile int volatile_int_var = -65536; int *ptr_int_var = &int_var; const int *ptr_const_int_var = &int_var; int * const int_ptr_const_var = &int_var; volatile int *ptr_volatile_int_var = &int_var; int * volatile int_ptr_volatile_var = &int_var; unsigned int uint_var = (unsigned int)0xffff8001; long int long_int_var = 65536; const long int const_long_int_var = -65536; volatile long int volatile_long_int_var = -65536; long int *ptr_long_int_var = &long_int_var; const long int *ptr_const_long_int_var = &long_int_var; long int * const long_int_ptr_const_var = &long_int_var; volatile long int *ptr_volatile_long_int_var = &long_int_var; long int * volatile long_int_ptr_volatile_var = &long_int_var; /* c89 doesn't define __STDC_VERSION. With -pedantic warns about long long. */ #if ! defined NO_LONG_LONG && __SIZEOF_SIZE_T__ == 8 long long int long_long_int_var = 65536; const long long int const_long_long_int_var = -65536; volatile long long int volatile_long_long_int_var = -65536; long long int *ptr_long_long_int_var = &long_long_int_var; const long long int *ptr_const_long_long_int_var = &long_long_int_var; long long int * const long_long_int_ptr_const_var = &long_long_int_var; volatile long long int *ptr_volatile_long_long_int_var = &long_long_int_var; long long int * volatile long_long_int_ptr_volatile_var = &long_long_int_var; #endif #if defined(STAP_SDT_V1) #define ARRAY(x) (&(x)[0]) #else #define ARRAY(x) (x) #endif char arr_char [] = "!~"; struct { unsigned int bit1_0:1; unsigned int bit1_1:1; char char_2; unsigned int bit1_6:1; unsigned int bit1_7:1; char char_8; unsigned int bit1_9:1; unsigned int bit1_10:1; } bitfields_a_var = { 1, 0, 'a', 1, 0, 'z', 1, 0}; struct { unsigned char char_0; int bit1_4:1; unsigned int bit1_5:1; int bit2_6:2; unsigned int bit2_8:2; int bit3_10:3; unsigned int bit3_13:3; int bit9_16:9; unsigned int bit9_25:9; char char_34; } bitfields_b_var = {'A', -1, 1, 1, 3, 3, 7, 255, 511, 'Z'}; # if !defined(__cplusplus) || \ ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) && __GXX_EXPERIMENTAL_CXX0X__) struct { int int_var; } arr_struct [2] = {{1},{2}}; enum { red = 0, green = 1, blue = 2 } primary_colors_var = green; struct opaque_struct *incomplete_struct_type = 0; # endif /* gnu90 and gnu99 don't support this so for now don't test it enum opaque_enum *incomplete_enum_type = 0; */ /* char */ STAP_PROBE1(provider,char_var,char_var); STAP_PROBE1(provider,const_char_var,const_char_var); STAP_PROBE1(provider,volatile_char_var,volatile_char_var); STAP_PROBE3(provider,ptr_char_var,ptr_char_var,&char_var,char_var); STAP_PROBE2(provider,ptr_const_char_var,ptr_const_char_var,&char_var); STAP_PROBE2(provider,char_ptr_const_var,char_ptr_const_var,&char_var); STAP_PROBE2(provider,ptr_volatile_char_var,ptr_volatile_char_var,&char_var); STAP_PROBE2(provider,char_ptr_volatile_var,char_ptr_volatile_var,&char_var); /* short */ STAP_PROBE1(provider,short_int_var,short_int_var); STAP_PROBE1(provider,const_short_int_var,const_short_int_var); STAP_PROBE1(provider,volatile_short_int_var,volatile_short_int_var); STAP_PROBE3(provider,ptr_short_int_var,ptr_short_int_var,&short_int_var, short_int_var); STAP_PROBE2(provider,ptr_const_short_int_var,ptr_const_short_int_var,&short_int_var); STAP_PROBE2(provider,short_int_ptr_const_var,short_int_ptr_const_var,&short_int_var); STAP_PROBE2(provider,ptr_volatile_short_int_var,ptr_volatile_short_int_var,&short_int_var); STAP_PROBE2(provider,short_int_ptr_volatile_var,short_int_ptr_volatile_var,&short_int_var); STAP_PROBE3(provider,unsigned_short_int_var,short_uint_var, 0x8001, &short_uint_var); /* int */ STAP_PROBE1(provider,int_var,int_var); STAP_PROBE1(provider,const_int_var,const_int_var); STAP_PROBE1(provider,volatile_int_var,volatile_int_var); STAP_PROBE3(provider,ptr_int_var,ptr_int_var,&int_var,int_var); STAP_PROBE2(provider,ptr_const_int_var,ptr_const_int_var,&int_var); STAP_PROBE2(provider,int_ptr_const_var,int_ptr_const_var,&int_var); STAP_PROBE2(provider,ptr_volatile_int_var,ptr_volatile_int_var,&int_var); STAP_PROBE2(provider,int_ptr_volatile_var,int_ptr_volatile_var,&int_var); STAP_PROBE3(provider,unsigned_int_var,uint_var, 0x8001, &uint_var); /* long */ STAP_PROBE1(provider,long_int_var,long_int_var); STAP_PROBE1(provider,const_long_int_var,const_long_int_var); STAP_PROBE1(provider,volatile_long_int_var,volatile_long_int_var); STAP_PROBE2(provider,ptr_long_int_var,ptr_long_int_var,&long_int_var); STAP_PROBE2(provider,ptr_const_long_int_var,ptr_const_long_int_var,&long_int_var); STAP_PROBE2(provider,long_int_ptr_const_var,long_int_ptr_const_var,&long_int_var); STAP_PROBE2(provider,ptr_volatile_long_int_var,ptr_volatile_long_int_var,&long_int_var); STAP_PROBE2(provider,long_int_ptr_volatile_var,long_int_ptr_volatile_var,&long_int_var); /* long long */ #if ! defined NO_LONG_LONG && __SIZEOF_SIZE_T__ == 8 STAP_PROBE1(provider,long_long_int_var,long_long_int_var); STAP_PROBE1(provider,const_long_long_int_var,const_long_long_int_var); STAP_PROBE1(provider,volatile_long_long_int_var,volatile_long_long_int_var); STAP_PROBE3(provider,ptr_long_long_int_var,ptr_long_long_int_var,&long_long_int_var,long_long_int_var); STAP_PROBE2(provider,ptr_const_long_long_int_var,ptr_const_long_long_int_var,&long_long_int_var); STAP_PROBE2(provider,long_long_int_ptr_const_var,long_long_int_ptr_const_var,&long_long_int_var); STAP_PROBE2(provider,ptr_volatile_long_long_int_var,ptr_volatile_long_long_int_var,&long_long_int_var); STAP_PROBE2(provider,long_long_int_ptr_volatile_var,long_long_int_ptr_volatile_var,&long_long_int_var); #endif STAP_PROBE1(provider,arr_char,ARRAY(arr_char)); # if !defined(__cplusplus) || \ ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) && __GXX_EXPERIMENTAL_CXX0X__) STAP_PROBE1(provider,arr_struct,ARRAY(arr_struct)); # endif STAP_PROBE8(provider,bitfields_a_var, (int)bitfields_a_var.bit1_0, (int)bitfields_a_var.bit1_1, bitfields_a_var.char_2, (int)bitfields_a_var.bit1_6, (int)bitfields_a_var.bit1_7, bitfields_a_var.char_8, (int)bitfields_a_var.bit1_9, (int)bitfields_a_var.bit1_10); STAP_PROBE10(provider,bitfields_b_var,bitfields_b_var.char_0, (int)bitfields_b_var.bit1_4, (int)bitfields_b_var.bit1_5, (int)bitfields_b_var.bit2_6, (int)bitfields_b_var.bit2_8, (int)bitfields_b_var.bit3_10, (int)bitfields_b_var.bit3_13, (int)bitfields_b_var.bit9_16, (int)bitfields_b_var.bit9_25, bitfields_b_var.char_34); # if !defined(__cplusplus) || \ ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) && __GXX_EXPERIMENTAL_CXX0X__) STAP_PROBE1(provider,primary_colors_var,primary_colors_var); # endif STAP_PROBE3(provider,constants,0x7fffffff,'~',"constants"); # if !defined(__cplusplus) || \ ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) && __GXX_EXPERIMENTAL_CXX0X__) STAP_PROBE1(provider, incomplete_struct_type, incomplete_struct_type); # endif STAP_PROBE(provider,something__dash__dash__something); return 0; } systemtap-2.3/testsuite/systemtap.base/sdt_types.stp000066400000000000000000000256061217430427200231630ustar00rootroot00000000000000probe process(@1).mark("char_var") { if ($arg1 != 126) printf("FAIL: char_var (%#d != 126)\n", $arg1) else printf("PASS: char_var\n") } probe process(@1).mark("const_char_var") { if ($arg1 != 33) printf("FAIL: const_char_var (%#d != 33)\n", $arg1) else printf("PASS: const_char_var\n") } probe process(@1).mark("volatile_char_var") { if ($arg1 != 33) printf("FAIL: volatile_char_var (%#d != 33)\n", $arg1) else printf("PASS: volatile_char_var\n") } probe process(@1).mark("ptr_char_var") { if ($arg1 != $arg2) printf("FAIL: ptr_char_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: ptr_char_var\n") if (user_int8($arg2) != $arg3) printf("FAIL: ptr_char_var (%#x != %#x)\n", user_int8($arg2), $arg3) else printf("PASS: ptr_char_var\n") } probe process(@1).mark("ptr_const_char_var") { if ($arg1 != $arg2) printf("FAIL: ptr_const_char_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: ptr_const_char_var\n") } probe process(@1).mark("char_ptr_const_var") { if ($arg1 != $arg2) printf("FAIL: char_ptr_const_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: char_ptr_const_var\n") } probe process(@1).mark("ptr_volatile_char_var") { if ($arg1 != $arg2) printf("FAIL: ptr_volatile_char_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: ptr_volatile_char_var\n") } probe process(@1).mark("char_ptr_volatile_var") { if ($arg1 != $arg2) printf("FAIL: char_ptr_volatile_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: char_ptr_volatile_var\n") } probe process(@1).mark("short_int_var") { if ($arg1 != 32767) printf("FAIL: short_int_var (%#d != 32767)\n", $arg1) else printf("PASS: short_int_var\n") } probe process(@1).mark("unsigned_short_int_var") { if ($arg1 != 0x8001) printf("FAIL: unsigned_short_int_var (%#x != 0xffff8001)\n", $arg1) else printf("PASS: unsigned_short_int_var\n") if ($arg1 != user_uint16($arg3)) printf("FAIL: unsigned_short_int_var (%#x != %#x)\n", $arg1, user_uint16($arg3)) else printf("PASS: unsigned_short_int_var\n") } probe process(@1).mark("const_short_int_var") { if ($arg1 != -32767) printf("FAIL: const_short_int_var (%#d != -32767)\n", $arg1) else printf("PASS: const_short_int_var\n") } probe process(@1).mark("volatile_short_int_var") { if ($arg1 != -32767) printf("FAIL: volatile_short_int_var (%#d != -32767)\n", $arg1) else printf("PASS: volatile_short_int_var\n") } probe process(@1).mark("ptr_short_int_var") { if ($arg1 != $arg2) printf("FAIL: ptr_short_int_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: ptr_short_int_var\n") if (user_int16($arg2) != $arg3) printf("FAIL: ptr_short_int_var (%#x != %#x)\n",user_int16($arg2), $arg3) else printf("PASS: ptr_short_int_var\n") } probe process(@1).mark("ptr_const_short_int_var") { if ($arg1 != $arg2) printf("FAIL: ptr_const_short_int_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: ptr_const_short_int_var\n") } probe process(@1).mark("short_int_ptr_const_var") { if ($arg1 != $arg2) printf("FAIL: short_int_ptr_const_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: short_int_ptr_const_var\n") } probe process(@1).mark("ptr_volatile_short_int_var") { if ($arg1 != $arg2) printf("FAIL: ptr_volatile_short_int_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: ptr_volatile_short_int_var\n") } probe process(@1).mark("short_int_ptr_volatile_var") { if ($arg1 != $arg2) printf("FAIL: short_int_ptr_volatile_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: short_int_ptr_volatile_var\n") } probe process(@1).mark("int_var") { if ($arg1 != 65536) printf("FAIL: int_var (%#d != 65536)\n", $arg1) else printf("PASS: int_var\n") } probe process(@1).mark("unsigned_int_var") { if ($arg1 != 0xffff8001) printf("FAIL: unsigned_int_var (%#x != 0xffff8001)\n", $arg1) else printf("PASS: unsigned_int_var\n") if ($arg1 != user_uint32($arg3)) printf("FAIL: unsigned_int_var (%#x != %#x)\n", $arg1, user_uint32($arg3)) else printf("PASS: unsigned_int_var\n") } probe process(@1).mark("const_int_var") { if ($arg1 != -65536) printf("FAIL: const_int_var (%#d != -65536)\n", $arg1) else printf("PASS: const_int_var\n") } probe process(@1).mark("volatile_int_var") { if ($arg1 != -65536) printf("FAIL: volatile_int_var (%#d != -65536)\n", $arg1) else printf("PASS: volatile_int_var\n") } probe process(@1).mark("ptr_int_var") { if ($arg1 != $arg2) printf("FAIL: ptr_int_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: ptr_int_var\n") if (user_int32($arg2) != $arg3) printf("FAIL: ptr_int_var (%#x != %#x)\n", user_int32($arg2), $arg3) else printf("PASS: ptr_int_var\n") } probe process(@1).mark("ptr_const_int_var") { if ($arg1 != $arg2) printf("FAIL: ptr_const_int_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: ptr_const_int_var\n") } probe process(@1).mark("int_ptr_const_var") { if ($arg1 != $arg2) printf("FAIL: int_ptr_const_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: int_ptr_const_var\n") } probe process(@1).mark("ptr_volatile_int_var") { if ($arg1 != $arg2) printf("FAIL: ptr_volatile_int_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: ptr_volatile_int_var\n") } probe process(@1).mark("int_ptr_volatile_var") { if ($arg1 != $arg2) printf("FAIL: int_ptr_volatile_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: int_ptr_volatile_var\n") } probe process(@1).mark("long_int_var") { if ($arg1 != 65536) printf("FAIL: long_int_var (%#d != 65536)\n", $arg1) else printf("PASS: long_int_var\n") } probe process(@1).mark("const_long_int_var") { if ($arg1 != -65536) printf("FAIL: const_long_int_var (%#d != -65536)\n", $arg1) else printf("PASS: const_long_int_var\n") } probe process(@1).mark("volatile_long_int_var") { if ($arg1 != -65536) printf("FAIL: volatile_long_int_var (%#d != -65536)\n", $arg1) else printf("PASS: volatile_long_int_var\n") } probe process(@1).mark("ptr_long_int_var") { if ($arg1 != $arg2) printf("FAIL: ptr_long_int_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: ptr_long_int_var\n") } probe process(@1).mark("ptr_const_long_int_var") { if ($arg1 != $arg2) printf("FAIL: ptr_const_long_int_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: ptr_const_long_int_var\n") } probe process(@1).mark("long_int_ptr_const_var") { if ($arg1 != $arg2) printf("FAIL: long_int_ptr_const_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: long_int_ptr_const_var\n") } probe process(@1).mark("ptr_volatile_long_int_var") { if ($arg1 != $arg2) printf("FAIL: ptr_volatile_long_int_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: ptr_volatile_long_int_var\n") } probe process(@1).mark("long_int_ptr_volatile_var") { if ($arg1 != $arg2) printf("FAIL: long_int_ptr_volatile_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: long_int_ptr_volatile_var\n") } probe process(@1).mark("long_long_int_var") ? { if ($arg1 != 65536) printf("FAIL: long_long_int_var (%#d != 65536)\n", $arg1) else printf("PASS: long_long_int_var\n") } probe process(@1).mark("const_long_long_int_var") ? { if ($arg1 != -65536) printf("FAIL: const_long_long_int_var (%#d != -65536)\n", $arg1) else printf("PASS: const_long_long_int_var\n") } probe process(@1).mark("volatile_long_long_int_var") ? { if ($arg1 != -65536) printf("FAIL: volatile_long_long_int_var (%#x != -65536)\n", $arg1) else printf("PASS: volatile_long_long_int_var\n") } probe process(@1).mark("ptr_long_long_int_var") ? { if ($arg1 != $arg2) printf("FAIL: ptr_long_long_int_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: ptr_long_long_int_var\n") if (user_int64($arg2) != $arg3) printf("FAIL: ptr_long_long_int_var (%#x != %#x)\n", user_int64($arg2), $arg3) else printf("PASS: ptr_long_long_int_var\n") } probe process(@1).mark("ptr_const_long_long_int_var") ? { if ($arg1 != $arg2) printf("FAIL: ptr_const_long_long_int_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: ptr_const_long_long_int_var\n") } probe process(@1).mark("long_long_int_ptr_const_var") ? { if ($arg1 != $arg2) printf("FAIL: long_long_int_ptr_const_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: long_long_int_ptr_const_var\n") } probe process(@1).mark("ptr_volatile_long_long_int_var") ? { if ($arg1 != $arg2) printf("FAIL: ptr_volatile_long_long_int_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: ptr_volatile_long_long_int_var\n") } probe process(@1).mark("long_long_int_ptr_volatile_var") ? { if ($arg1 != $arg2) printf("FAIL: long_long_int_ptr_volatile_var (%#d != %#d)\n", $arg1, $arg2) else printf("PASS: long_long_int_ptr_volatile_var\n") } probe process(@1).mark("arr_char") { arr_char = user_string ($arg1); arr_short = user_short ($arg1); if (arr_char != "!~") printf("FAIL: arr_char_var (%#x != \"!~\")\n", arr_short) else printf("PASS: arr_char_var\n") } probe process(@1).mark("arr_struct") ? { arr_struct_int_var = user_int ($arg1) if (arr_struct_int_var != 1) printf("FAIL: arr_struct_var (%d != 1)\n", arr_struct_int_var) else printf("PASS: arr_struct_var\n") } probe process(@1).mark("bitfields_a_var") { if ($arg1 != 1 || $arg2 != 0 || $arg3 != 97 || $arg4 != 1 || $arg5 != 0 || $arg6 != 122 || $arg7 != 1 || $arg8 != 0) printf("FAIL: bitfields_a_var\n") else printf("PASS: bitfields_a_var\n") } probe process(@1).mark("bitfields_b_var") { if ($arg1 != 65 || ($arg2 != -1) || $arg3 != 1 || $arg4 != 1 || $arg5 != 3 || $arg6 != 3 || $arg7 != 7 || $arg8 != 255 || $arg9 != 511 || $arg10 != 90) printf("FAIL: bitfields_b_var (%#d/%#d/%#d/%#d/%#d/%#d/%#d/%#d/%#d/%#d != 65/-1/1/1/3/3/7/255/511/90\n",$arg1,$arg2,$arg3,$arg4,$arg5,$arg6,$arg7,$arg8,$arg9,$arg10) else printf("PASS: bitfields_b_var\n") } probe process(@1).mark("primary_colors_var") ? { if ($arg1 != 1) printf("FAIL: primary_colors_var (%#d != 1)\n", $arg1) else printf("PASS: primary_colors_var\n") } probe process(@1).mark("constants") { if ($arg1 != 0x7fffffff) printf("FAIL: constants (%#x != 0x7fffffff)\n", $arg1) else printf("PASS: constants\n") if ($arg2 != 0x7e) printf("FAIL: constants (%#x != '~' 0x7e)\n", $arg2) else printf("PASS: constants\n") arr_char = user_string ($arg3); if (arr_char != "constants") printf("FAIL: constants (%s !+ \"constants\")\n", arr_char) else printf("PASS: constants\n") } probe process(@1).mark("incomplete_struct_type") ? { if ($arg1 != 0) printf("FAIL: incomplete_struct_type (%#x != 0)\n", $arg1) else printf("PASS: incomplete_struct_type\n") } probe process(@1).mark("incomplete_enum_type") ? { if ($arg1 != 0) printf("FAIL: incomplete_enum_type (%#x != 0)\n", $arg1) else printf("PASS: incomplete_enum_type\n") } systemtap-2.3/testsuite/systemtap.base/sdt_va_args.c000066400000000000000000000013201217430427200230400ustar00rootroot00000000000000#define SDT_USE_VARIADIC #include "sys/sdt.h" int main() { STAP_PROBEV(test, mark_z); STAP_PROBEV(test, mark_a, 1); STAP_PROBEV(test, mark_b, 1, 2); STAP_PROBEV(test, mark_c, 1, 2, 3); STAP_PROBEV(test, mark_d, 1, 2, 3, 4); STAP_PROBEV(test, mark_e, 1, 2, 3, 4, 5); STAP_PROBEV(test, mark_f, 1, 2, 3, 4, 5, 6); STAP_PROBEV(test, mark_g, 1, 2, 3, 4, 5, 6, 7); STAP_PROBEV(test, mark_h, 1, 2, 3, 4, 5, 6, 7, 8); STAP_PROBEV(test, mark_i, 1, 2, 3, 4, 5, 6, 7, 8, 9); STAP_PROBEV(test, mark_j, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); STAP_PROBEV(test, mark_k, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); STAP_PROBEV(test, mark_l, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); return 0; } systemtap-2.3/testsuite/systemtap.base/sdt_va_args.exp000066400000000000000000000042341217430427200234210ustar00rootroot00000000000000set test "sdt_va_args" set ::result_string {_ 1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6 1 2 3 4 5 6 7 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 11 1 2 3 4 5 6 7 8 9 10 11 12} set extra_flags { {} {additional_flags=-std=c89} {additional_flags=-std=c99} {additional_flags=-std=gnu99} {c++ additional_flags=-std=c++98 additional_flags=-x additional_flags=c++} {c++ additional_flags=-std=gnu++98 additional_flags=-x additional_flags=c++} {c++ additional_flags=-std=c++0x additional_flags=-x additional_flags=c++} {c++ additional_flags=-std=gnu++0x additional_flags=-x additional_flags=c++} } set extra_mssgs {base c89 c99 gnu99 c++98 gnu++98 c++0x gnu++0x} # Iterate extra_flags, trying each with C and C++ for {set i 0} {$i < [llength $extra_flags]} {incr i} { set extra_flag [lindex $extra_flags $i] set extra_mssg [lindex $extra_mssgs $i] set testprog "$test.c.exe.$i" set test_flags "additional_flags=-g" set test_flags "$test_flags [sdt_includes]" set test_flags "$test_flags additional_flags=-Wall" set test_flags "$test_flags additional_flags=-Wextra" set test_flags "$test_flags additional_flags=-Werror" set saveidx 0 set res [target_compile $srcdir/$subdir/$test.c $testprog executable "$test_flags $extra_flag"] if { $res != "" } { verbose "target_compile failed: $res" 2 # -std=gnu++0x and -std=c++0x are not universally accepted if {[string first "unrecognized command line option" $res] == -1} { fail "compiling $test.c $extra_mssg" } else { untested "compiling $test.c $extra_mssg" } untested "$test $extra_mssg" continue } else { pass "compiling $test.c $extra_mssg" } if {[installtest_p]} { foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run3 "$test $extra_mssg ($runtime)" \ --runtime=$runtime -w $srcdir/$subdir/sdt.stp \ $testprog -c ./$testprog } elseif {[uprobes_p]} { stap_run3 "$test $extra_mssg" -w $srcdir/$subdir/sdt.stp \ $testprog -c ./$testprog } else { untested "$test $extra_mssg" } } } else { untested "$test $extra_mssg" } catch {exec rm -f $testprog} } ; # for {set i 0} {$i < [llength $extra_flags]} systemtap-2.3/testsuite/systemtap.base/set_kernel.exp000066400000000000000000000002171217430427200232550ustar00rootroot00000000000000# Check that the set_kernel_* functions work correctly. set test "set_kernel" stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string -g systemtap-2.3/testsuite/systemtap.base/set_kernel.stp000066400000000000000000000057541217430427200233020ustar00rootroot00000000000000/* * set_kernel.stp * * Check that the set_kernel_* functions work correctly. */ probe begin { println("systemtap starting probe") } probe end { println("systemtap ending probe") } global errors = 0 function assert_string(test, expected, value) { if (value == expected) return 1 printf("systemtap test failure - %s: expected \"%s\", got \"%s\"\n", test, expected, value) errors++ return 0 } function assert_number(test, expected, value) { if (value == expected) return 1 printf("systemtap test failure - %s: expected %#x, got %#x\n", test, expected, value) errors++ return 0 } function assert_not_reached(test) { printf("systemtap test failure - %s: missing exception\n", test) errors++ } probe end(1) { test = "set_kernel_string" addr = get_buffer() if (assert_string(test, "", kernel_string(addr))) { set_kernel_string(addr, "foobar") assert_string(test, "foobar", kernel_string(addr)) } try { set_kernel_string(-1, "foobar") assert_not_reached(test) } catch {} test = "set_kernel_string_n" addr = get_buffer() if (assert_string(test, "", kernel_string(addr))) { set_kernel_string_n(addr, 10, "foobar") if (assert_string(test, "foobar", kernel_string(addr))) { set_kernel_string_n(addr, 3, "foobar") assert_string(test, "foo", kernel_string(addr)) } } try { set_kernel_string_n(-1, 10, "foobar") assert_not_reached(test) } catch {} test = "set_kernel_long" addr = get_buffer() long_val = %( CONFIG_64BIT == "y" %? 0x123456789ABCDEF0 %: 0x12345678 %) if (assert_number(test, 0, kernel_long(addr))) { set_kernel_long(addr, long_val) assert_number(test, long_val, kernel_long(addr)) } try { set_kernel_long(-1, 42) assert_not_reached(test) } catch {} test = "set_kernel_int" addr = get_buffer() if (assert_number(test, 0, kernel_int(addr))) { set_kernel_int(addr, 0x12345678) assert_number(test, 0x12345678, kernel_int(addr)) } try { set_kernel_int(-1, 42) assert_not_reached(test) } catch {} test = "set_kernel_short" addr = get_buffer() if (assert_number(test, 0, kernel_short(addr))) { set_kernel_short(addr, 0x1234) assert_number(test, 0x1234, kernel_short(addr)) } try { set_kernel_short(-1, 42) assert_not_reached(test) } catch {} test = "set_kernel_char" addr = get_buffer() if (assert_number(test, 0, kernel_char(addr))) { set_kernel_char(addr, 0x12) assert_number(test, 0x12, kernel_char(addr)) } try { set_kernel_char(-1, 42) assert_not_reached(test) } catch {} if (!errors) println("systemtap test success") } function get_buffer:long () %{ static char buffer[MAXSTRINGLEN]; memset(buffer, 0, sizeof(buffer)); STAP_RETVALUE = (long)buffer; %} systemtap-2.3/testsuite/systemtap.base/setjmp.c000066400000000000000000000013311217430427200220500ustar00rootroot00000000000000#include #ifdef SIGJMP # define SETJMP(env) sigsetjmp (env, 1) # define LONGJMP(env, x) siglongjmp (env, x) #elif defined UNDERJMP # define SETJMP(env) _setjmp (env) # define LONGJMP(env, x) _longjmp (env, x) #else # define SETJMP(env) setjmp (env) # define LONGJMP(env, x) longjmp (env, x) #endif struct env { jmp_buf jmp; }; struct env saved; void __attribute__ ((noinline)) jumper (struct env *env, int x) { if (x == 0) siglongjmp (env->jmp, 1); } void __attribute__ ((noinline)) jumped (void) { asm volatile (""); } void __attribute__ ((noinline)) setter (void) { if (sigsetjmp (saved.jmp, 1) == 0) jumper (&saved, 0); else jumped (); } int main (void) { setter (); return 0; } systemtap-2.3/testsuite/systemtap.base/setjmp.exp000066400000000000000000000031171217430427200224260ustar00rootroot00000000000000set test "setjmp" set ::result_string {hit longjmp_target} foreach variant [list "" "-DSIGJMP" "-DUNDERJMP"] { foreach flags [list "" "-O" "-O -D_FORTIFY_SOURCE=2"] { set this_test "$test $variant $flags" set testprog [regsub { } "setjmp.exe${variant}${flags}" ""] set test_flags "additional_flags=-g" foreach arg "$variant $flags" { set test_flags "$test_flags additional_flags=$arg" } set res [target_compile $srcdir/$subdir/$test.c $testprog executable \ "$test_flags"] if {$res != ""} { verbose "target_compile failed: $res" 2 fail "compiling $test.c $variant $flags" untested $this_test continue } else { pass "compiling $test.c $variant $flags" } if {[catch \ {exec stap -l "process(\"/lib*/libc.so.*\").mark(\"*jmp*\")" \ 2>@1} res]} { if {[lindex $::errorCode 0] eq "CHILDSTATUS"} { set status [lindex $::errorCode 2] if {$status == 1} { verbose -log "stap -l check found no libc probes" 1 untested $this_test continue } } verbose -log "stap -l failed: $res" fail "stap -l check for libc probes" untested $this_test continue } else { verbose -log "stap -l yields: $res" if {$res == ""} { verbose -log "stap -l check found no libc probes" 1 untested $this_test continue } } if {[installtest_p] && [utrace_p] && [uprobes_p]} { stap_run3 $this_test -w --ldd $srcdir/$subdir/$test.stp \ $testprog ./$testprog -c ./$testprog } else { untested $this_test } } } if { $verbose == 0 } { catch { eval [list exec /bin/rm -f] [glob "setjmp.exe*"] } } systemtap-2.3/testsuite/systemtap.base/setjmp.stp000066400000000000000000000034251217430427200224420ustar00rootroot00000000000000global jmp_buf, jmp_target, jmp_backtrace function callers:string() { bt = ubacktrace(); // Skip the first caller, which is setjmp or longjmp itself. callers = ""; token = tokenize(bt, " "); while ((token = tokenize("", " ")) != "") callers = callers . " " . token; return callers; } function nth_caller:long(n, bt) { token = tokenize(bt, " "); while (n-- > 0) token = tokenize("", " "); return strtol(token, 16); } global started = 0 probe process(@1).function("main") { started = 1; } probe process("/lib*/libc.so.*").mark("setjmp") { if (!started) next; jmp_buf[tid()] = $arg1; jmp_target[tid()] = $arg3; bt = jmp_backtrace[tid()] = callers(); for (i = 0; i < 5; ++i) if (usymname(nth_caller(i, bt)) == "setter") next; printf("setjmp backtrace doesn't include setter:\n"); print_ubacktrace(); } function check_jmp(buf, target) { if (jmp_buf[tid()] != buf) printf("longjmp env %p, expected %p\n", buf, jmp_buf[tid()]); if (jmp_target[tid()] != target) printf("longjmp target %p, expected %p\n", target, jmp_target[tid()]); } probe process("/lib*/libc.so.*").mark("longjmp") { if (!started) next; check_jmp($arg1, $arg3); bt = callers(); if (bt == jmp_backtrace[tid()]) printf("longjmp backtrace matches setjmp backtrace!\n"); for (i = 0; i < 5; ++i) if (usymname(nth_caller(i, bt)) == "jumper") next; printf("longjmp backtrace doesn't include jumper:\n"); print_ubacktrace(); } probe process("/lib*/libc.so.*").mark("longjmp_target") { if (!started) next; check_jmp($arg1, $arg3); bt = callers(); if (bt != jmp_backtrace[tid()]) printf("longjmp_target backtrace does not match setjmp:\n\t%s\nvs\t%s", sprint_usyms(jmp_backtrace[tid()]), sprint_usyms(bt)); printf("hit longjmp_target\n"); } systemtap-2.3/testsuite/systemtap.base/simple.exp000066400000000000000000000007531217430427200224200ustar00rootroot00000000000000# Very simple function to test that systemtap can generate a kernel module, # install it, and get some output. set test "simple" #check to see whether get the marker indicating the probe is loaded and running #should check to see whether exited for some reason #should be error is something else is printed. foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run $srcdir/$subdir/$test.stp "" "" --runtime=$runtime } else { stap_run $srcdir/$subdir/$test.stp } } systemtap-2.3/testsuite/systemtap.base/simple.stp000066400000000000000000000003611217430427200224250ustar00rootroot00000000000000/* * simple.stp * * Very simple function to test that systemtap can generate a kernel module, * install it, and get some output. */ probe begin { println("systemtap starting probe") } probe end { println("systemtap ending probe") } systemtap-2.3/testsuite/systemtap.base/skipped.exp000066400000000000000000000023531217430427200225640ustar00rootroot00000000000000set test "skip tracking" if {! [installtest_p]} { untested $test; return } set nr_cpus [exec sh -c "grep ^processor /proc/cpuinfo | wc -l"] if {$nr_cpus < 2} { unsupported $test; return } # See PR13332 skipped.exp testcase can freeze processes/system untested "$test PR13332 skipped.exp testcase can freeze processes/system" return set script { global f probe timer.profile { f++; snooze() } function snooze() %{ udelay(10000); %} } set errs 0 set warns 0 set oks 0 spawn stap -e $script -DMAXTRYLOCK=0 -DSTP_NO_OVERLOAD -tug expect { -timeout 60 -re {^ERROR: Skipped too many probes, check MAXSKIPPED or try again with stap -t for more details.\r\n} { incr errs; exp_continue } -re {^WARNING: Number of errors: 0, skipped probes: [0-9]+\r\n} { incr warns; exp_continue } -re {^WARNING: Skipped due to global .f. lock timeout: [0-9]+\r\n} { incr warns; exp_continue } -re {^[^\r\n]*probe hit report:[ ]*\r\n} { exp_continue } -re {^timer.profile[^\r\n]+, hits: [0-9]+[^\r\n]+\r\n} { incr oks; exp_continue } eof { } timeout { fail "$test (timeout)" } } catch {close} catch {wait} if {$oks >= 1 && $warns == 2 && $errs == 1} { pass "$test ($nr_cpus $oks $warns $errs)" } else { fail "$test ($nr_cpus $oks $warns $errs)" } systemtap-2.3/testsuite/systemtap.base/stap_kmodule.Makefile000066400000000000000000000003441217430427200245330ustar00rootroot00000000000000obj-m := stap_kmodule.o KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules clean: rm -f *.mod.c stap_kmodule.ko *.o .*.cmd Modules.symvers rm -rf .tmp_versions systemtap-2.3/testsuite/systemtap.base/stap_kmodule.c000066400000000000000000000033331217430427200232410ustar00rootroot00000000000000/* -*- linux-c -*- * Systemtap Test Module 1 * Copyright (C) 2007 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. */ #include #include #include #include #include /* * The purpose of this module is to provide a function that can be * triggered from user context via a /proc file. Systemtap scripts * set probes on the function and run tests to see if the expected * output is received. This is better than using the kernel's modules * because kernel internals frequently change. */ /************ Below are the functions to create this module ************/ static struct proc_dir_entry *stm_ctl = NULL; static int last_cmd = -1; static ssize_t stm_write_cmd (struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char type; if (get_user(type, (char __user *)buf)) return -EFAULT; switch (type) { case '0': last_cmd = 0; break; case '1': last_cmd = 1; break; case '2': last_cmd = 2; break; default: printk ("stap_kmodule: invalid command type %d\n", (int)type); return -EINVAL; } return count; } static struct file_operations stm_fops_cmd = { .owner = THIS_MODULE, .write = stm_write_cmd, }; int init_module(void) { stm_ctl = proc_create ("stap_kmodule_cmd", 0666, NULL, &stm_fops_cmd); if (stm_ctl == NULL) return -1; return 0; } void cleanup_module(void) { if (stm_ctl) remove_proc_entry ("stap_kmodule_cmd", NULL); } MODULE_DESCRIPTION("systemtap test module"); MODULE_LICENSE("GPL"); systemtap-2.3/testsuite/systemtap.base/stapsh-unix.exp000066400000000000000000000012411217430427200234030ustar00rootroot00000000000000# Test that the stapsh mechanism is working over a unix socket # - ensure that stapsh and socat are in our process hierarchy set test "stapsh-unix" set ::result_string {begin ^ stapio ^ stapsh ^ socat timer.s(1) end} if {![installtest_p] || [catch {exec test -f /usr/bin/socat}]} { untested "$test" } else { # use a fixed name, to enable simple systemtap.sum comparability set sock /tmp/$test.sock set socat_pid [spawn /usr/bin/socat UNIX-LISTEN:$sock EXEC:stapsh] set socat_sid $spawn_id stap_run2 $srcdir/$subdir/$test.stp --remote=unix:$sock set spawn_id $socat_sid catch {exec kill $socat_pid} catch {close} catch {wait} } systemtap-2.3/testsuite/systemtap.base/stapsh-unix.stp000066400000000000000000000007311217430427200234200ustar00rootroot00000000000000probe begin { println(pp()) // Print our process chain, should be stapio, stapsh, socat for (t = task_current(); t && task_parent(t) != t; t = task_parent(t)) { name = task_execname(t) println("^ ", name) if (name == "socat") { break } } } probe timer.s(1) { println(pp()) exit() } probe timer.s(10) { println(pp()) println("timeout!") exit() } probe end { println(pp()) } systemtap-2.3/testsuite/systemtap.base/stapsh.exp000066400000000000000000000004651217430427200224310ustar00rootroot00000000000000# Test that the stapsh mechanism is working # - ensure that stapsh is in our process hierarchy # - ensure that a signal sent to the stap process is propagated correctly set test "stapsh" set ::result_string {begin ^ stapio ^ stapsh ^ stap timer.s(1) end} stap_run2 $srcdir/$subdir/$test.stp --remote=stapsh: systemtap-2.3/testsuite/systemtap.base/stapsh.stp000066400000000000000000000014101217430427200224320ustar00rootroot00000000000000global kill_pid probe begin { println(pp()) // Print our process chain, should be stapio, stapsh, stap t = task_current() while (t && task_parent(t) != t) { name = task_execname(t) println("^ ", name) if (name == "stap") { // Remember this pid for killing later kill_pid = task_pid(t) break } t = task_parent(t) } } probe timer.s(1) { if (kill_pid) { println(pp()) // Kill our stap pid, and it should be propagated back // through stapsh to end this script. system(sprint("/bin/kill -INT ", kill_pid)) kill_pid = 0 } } probe timer.s(10) { println(pp()) println("timeout!") exit() } probe end { println(pp()) } systemtap-2.3/testsuite/systemtap.base/statement.exp000066400000000000000000000051451217430427200231330ustar00rootroot00000000000000set test bz6905 catch {exec gcc -g -o $test $srcdir/$subdir/$test.c} err if {$err == "" && [file exists $test]} then { pass "$test compile" } else { fail "$test compile" } if {![utrace_p]} { untested "$test -p2" } else { spawn stap -p2 $srcdir/$subdir/$test.stp set hint 0 set probes 0 expect { -timeout 60 -re "# probes" { incr hint; exp_continue } -re {process.*statement.*} { incr probes; exp_continue } timeout { fail "$test (timeout)" } eof { } } wait if { $hint == 1 && $probes > 0 } then { pass "$test -p2" } else { fail "$test -p2 ($probes)" } } if { $verbose == 0 } { catch { exec rm -f $test } } set test bz10294 catch {exec gcc -g -o $test $srcdir/$subdir/$test.c} err if {$err == "" && [file exists $test]} then { pass "$test compile" } else { fail "$test compile" } if {![utrace_p]} { untested "$test -p2" } else { spawn stap -p2 $srcdir/$subdir/$test.stp set hint 0 set probes 0 expect { -timeout 60 -re "# probes" { incr hint; exp_continue } -re {process.*statement.*} { incr probes; exp_continue } timeout { fail "$test (timeout)" } eof { } } wait if { $hint == 1 && $probes == 1 } then { pass "$test -p2" } else { fail "$test -p2 ($probes)" } } set no_func stmtnofunc if {![utrace_p]} { untested "$no_func" } else { set func_script "probe process(\"%s\").statement(\"foo@%s.c:*\") {}" set script [format $func_script "./$test" "$test"] spawn stap -p2 -we $script expect { -timeout 60 -re {semantic error: .*while resolving probe point.*\r\n} { xfail $no_func } timeout { fail "$no_func (timeout)" } eof { fail $no_func } } wait } if { $verbose == 0 } { catch { exec rm -f $test } } set test bz14774 catch {exec gcc -g -o $test $srcdir/$subdir/$test.c} err if {$err == "" && [file exists $test]} then { pass "$test compile" } else { fail "$test cmpile" } if {![utrace_p]} { untested "$test -p2" } else { set func_script "probe process(\"%s\").statement(\"*@%s.c:*\") {}" set script [format $func_script "./$test" "$test"] spawn stap -p2 -we $script set hint 0 set probes 0 set skipped 0 expect { -timeout 60 -re "# probes" { incr hint; exp_continue } -re {process\("[^"]+"\)\.statement\("[^"]+"\) /\*} { incr probes; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch { wait } catch { close } if { $hint == 1 && $probes >= 9 } then { pass "$test -p2" } else { fail "$test -p2 ($probes)" } } if { $verbose == 0 } { catch { exec rm -f $test } } systemtap-2.3/testsuite/systemtap.base/stmt_rel.c000066400000000000000000000037721217430427200224120ustar00rootroot00000000000000#include #define stackrange 3 #define maxcells 18 #define false 0 #define true 1 int stack[stackrange + 1]; int freelist, movesdone; struct element { int discsize; int next; }; struct element cellspace[maxcells + 1]; static inline void Error (char *emsg) { printf (" Error in Towers: %s\n", emsg); } static inline void Makenull (s) { stack[s] = 0; } static inline int Getelement () { int temp = 0; if (freelist > 0) { temp = freelist; freelist = cellspace[freelist].next; } else Error ("out of space "); return (temp); } static inline void Push (int i, int s) { int errorfound, localel; errorfound = false; if (stack[s] > 0) if (cellspace[stack[s]].discsize <= i) { errorfound = true; Error ("disc size error"); }; if (!errorfound) { localel = Getelement (); cellspace[localel].next = stack[s]; stack[s] = localel; cellspace[localel].discsize = i; } } static inline void Init (int s, int n) { int discctr; Makenull (s); for (discctr = n; discctr >= 1; discctr--) Push (discctr, s); } static inline int Pop (int s) { int temp, temp1; if (stack[s] > 0) { temp1 = cellspace[stack[s]].discsize; temp = cellspace[stack[s]].next; cellspace[stack[s]].next = freelist; freelist = stack[s]; stack[s] = temp; return (temp1); } else Error ("nothing to pop "); return -1; } static inline void Move (int s1, int s2) { Push (Pop (s1), s2); movesdone = movesdone + 1; } static void tower (int i, int j, int k) { int other; if (k == 1) Move (i, j); else { other = 6 - i - j; tower (i, other, k - 1); Move (i, j); tower (other, j, k - 1); } } int main () { int i; for (i = 1; i <= maxcells; i++) cellspace[i].next = i - 1; freelist = maxcells; Init (1, 14); Makenull (2); Makenull (3); movesdone = 0; tower (1, 2, 14); if (movesdone != 16383) printf (" Error in Towers.\n"); return 0; } systemtap-2.3/testsuite/systemtap.base/stmt_rel.exp000066400000000000000000000020371217430427200227550ustar00rootroot00000000000000set test "stmt_rel" set line1 "" spawn stap -l "kernel.statement(\"bio_init@fs/bio.c+2\")" expect { -timeout 180 -re {[0-9][0-9][0-9]} { regexp "\[0-9\]\[0-9\]\[0-9\]" $expect_out(0,string) line1; } timeout { fail "$test C (timeout)" } eof { } } catch {close}; catch {wait} set line2 "" spawn stap -l "kernel.statement(\"bio_init@fs/bio.c+3\")" expect { -timeout 180 -re {[0-9][0-9][0-9]} { regexp "\[0-9\]\[0-9\]\[0-9\]" $expect_out(0,string) line2; } timeout { fail "$test C (timeout)" } eof { } } catch {close}; catch {wait} if { $line1 < $line2 } { pass "$test line numbers" } else { fail "$test line numbers" } set ok 0 spawn stap -l "kernel.statement(\"bio_init@fs/bio.c:*\")" expect { -timeout 180 -re {[0-9][0-9][0-9]} { incr ok; exp_continue } timeout { fail "$test C (timeout)" } eof { } } catch {close}; catch {wait} # bio_init drifts a bit in different kernels. # maybe 3, 4 or 15 lines in it. if { $ok >= 3 } { pass "$test wildcard" } else { fail "$test wildcard ($ok)" } systemtap-2.3/testsuite/systemtap.base/stmt_rel_user.exp000066400000000000000000000041331217430427200240120ustar00rootroot00000000000000set test "stmt_rel_user" proc dyninst_kfails {index} { # The dyninst runtime isn't multi-arch, it only works on the # native architecture. PR14490. if {! [all_compile_flag_native_p $index]} { setup_kfail 14490 "*-*-*" } } # Compile with inlining and check we can set a relative statement there for {set i 0} {$i < [all_compile_flags]} {incr i} { set extra_flag [all_compile_flag $i] set extra_name [all_compile_flag_name $i] set rel_flags "additional_flags=-Wall additional_flags=-Werror" set rel_flags "$rel_flags additional_flags=-Winline" set rel_flags "$rel_flags additional_flags=-g" set rel_flags "$rel_flags $extra_flag" set res [target_compile $srcdir/$subdir/stmt_rel.c [pwd]/stmt_rel.x executable $rel_flags] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test-$extra_name compiling" cleanup_handler $verbose continue } else { pass "$test-$extra_name compiling" } if {![installtest_p]} { untested "$test-$extra_name"; return } foreach runtime [get_runtime_list] { if {$runtime != ""} { set test_name "$test-$extra_name-$runtime" if { [info procs ${runtime}_kfails] ne "" } { ${runtime}_kfails $i } spawn stap --runtime=$runtime -c ./stmt_rel.x -e "probe process(\"./stmt_rel.x\").statement(\"Move@stmt_rel.c+1\") {printf(\"Move %d\\n\",\$s1)}" } elseif {[uprobes_p]} { set test_name "$test-$extra_name" spawn stap -c ./stmt_rel.x -e "probe process(\"./stmt_rel.x\").statement(\"Move@stmt_rel.c+1\") {printf(\"Move %d\\n\",\$s1)}" } else { untested "$test-$extra_name" continue } set ok 0 expect { -timeout 180 -re {Move [0-9]} { incr ok; exp_continue } timeout { fail "$test_name (timeout)" } eof { } } catch {close}; catch {wait} # PR13430 when optimizing we fail to set probes on all inlined lines. if { [string first "O" $extra_name] != -1 } { setup_kfail 13430 "*-*-*" } # A hanoi tower needs 2^n - 1 moves (n == 14 in the test program) if { $ok == 16383 } { pass "$test_name" } else { fail "$test_name ($ok)" } } } systemtap-2.3/testsuite/systemtap.base/stmtvars.exp000066400000000000000000000017471217430427200230160ustar00rootroot00000000000000set test "stmtvars" # PR 5787 set pc 0 set vars "" spawn stap -e "probe kernel.function(\"do_sys_open\") {\$foo}" -p4 -vv -u expect { -re {probe do_sys_open[^\r\n]*pc=(0x[^\r\n]*)\r\n} { set pc $expect_out(1,string); exp_continue } -re {alternatives: ([^\r\n]*)\): identifier [^\r\n]*\r\n} { set vars $expect_out(1,string); exp_continue } timeout { fail "$test (timeout)" } eof } wait verbose -log "pc=$pc vars=$vars" if {$pc != 0 && $vars != ""} { pass "$test - .function" } { fail "$test - .function" } set pc2 0 set vars2 "" spawn stap -e "probe kernel.statement($pc) {\$foo}" -p4 -vv -u expect { -re {probe do_sys_open[^\r\n]*pc=(0x[^\r\n]*)\r\n} { set pc2 $expect_out(1,string); exp_continue } -re {alternatives: ([^\r\n]*)\): identifier [^\r\n]*\r\n} { set vars2 $expect_out(1,string); exp_continue } timeout { fail "$test (timeout)" } eof } wait verbose -log "pc2=$pc2 vars2=$vars2" if {$pc == $pc2 && $vars == $vars2} { pass $test } { fail $test } systemtap-2.3/testsuite/systemtap.base/strftime.exp000066400000000000000000000024111217430427200227550ustar00rootroot00000000000000set test "strftime" if {![installtest_p]} { untested $test; return } # cleanup system "rm -f %*" foreach runtime [get_runtime_list] { set test "strftime" if {$runtime != ""} { lappend test "($runtime)" } # check %S and %T set format %%%S_%T if {$runtime != ""} { catch { exec stap --runtime=$runtime -o $format -we {probe begin {println("hello");exit()}} } res } else { catch { exec stap -o $format -we {probe begin {println("hello");exit()}} } res } verbose -log $res set file [glob -nocomplain -types f %\[0-9\]\[0-9\]_\[0-9\]\[0-9\]:\[0-9\]\[0-9\]:\[0-9\]\[0-9\]] if {[llength $file] == 1} { pass "$test (%S and %T)" } else { fail "$test (%S and %T)" } # check except for %S and %T set format %%,%C,%Y,%y,%m,%d,%e,%F,%H,%I,%j,%k,%l,%M,%R,%u,%w set date1 [exec date +$format] # run stapio with strftime if {$runtime != ""} { catch { exec stap --runtime=$runtime -o $format -we {probe begin {println("hello");exit()}} } res } else { catch { exec stap -o $format -we {probe begin {println("hello");exit()}} } res } verbose -log $res if {[file exists $date1]} { pass "$test (except %S and %T)" } else { fail "$test (except %S and %T)" } # cleanup system "rm -f %*" } systemtap-2.3/testsuite/systemtap.base/suppress-time-limit.exp000066400000000000000000000036461217430427200250670ustar00rootroot00000000000000set test "suppress-time-limit" if {! [installtest_p]} { untested "$test"; return } foreach runtime [get_runtime_list] { set test_extra "" if {$runtime != ""} { set test_extra " ($runtime)" spawn stap --runtime=$runtime -g --suppress-time-limits \ $srcdir/$subdir/$test.stp } else { spawn stap -g --suppress-time-limits $srcdir/$subdir/$test.stp } set ok 0 set ko 0 # Testing that -g --suppress-time-limits works properly # by looping 100000 time and confirming the number of iterations # to what we expect. # The default setting only allows for 10000, so we want to test # against a value significantly larger than that. expect { -timeout 30 -re {^100000\r\n} { incr ok; exp_continue } timeout { fail "$test active${test_extra} (timeout)" } eof { } } catch {close}; catch {wait} # The actual comparing of active values to what we expect. # For debugging purposes, output the value of the variables # so we can see which value failed (if any) if {$ok == 1} then { pass "$test active${test_extra} ($ok)" } else { fail "$test active${test_extra} ($ok)" } # Testing the case which should fail, without the new option, # and comparing the number of iterations to what we expect (ie 9997). if {$runtime != ""} { spawn stap --runtime=$runtime $srcdir/$subdir/$test.stp } else { spawn stap $srcdir/$subdir/$test.stp } expect { -timeout 30 -re {^ERROR:[^\r\n]*\r\n} { incr ko; exp_continue } -re {^9997\r\n} { incr ko; exp_continue } eof { } timeout { fail "$test passive${test_extra} (timeout)" } } catch {close}; catch {wait} # The actual comparing of passive values to what we expect. # For debugging purposes, output the value of the variables # so we can see which value failed (if any) if {$ko == 2} then { pass "$test passive${test_extra} ($ko)" } else { fail "$test passive${test_extra} ($ko)" } } systemtap-2.3/testsuite/systemtap.base/suppress-time-limit.stp000066400000000000000000000001521217430427200250660ustar00rootroot00000000000000global i probe begin { for(i = 0; i < 100000; i++){}} probe begin(1) {exit()} probe end,error {println(i)}systemtap-2.3/testsuite/systemtap.base/sysroot_sysenv.exp000066400000000000000000000005651217430427200242610ustar00rootroot00000000000000set test "sysroot_sysenv" if {[installtest_p] && [utrace_p] && [uprobes_p]} { spawn stap --sysroot=/ --sysenv=PATH=$env(PATH) $srcdir/$subdir/$test.stp ls -c "ls > /dev/null" expect { -timeout 180 -re {^process begin\r\n} { pass "$test" } timeout { fail "$test (timeout)" } eof { fail "$test" } } catch {close} wait } else { untested "$test" } systemtap-2.3/testsuite/systemtap.base/sysroot_sysenv.stp000066400000000000000000000000671217430427200242700ustar00rootroot00000000000000probe process(@1).begin { println("process begin") } systemtap-2.3/testsuite/systemtap.base/system_func.exp000066400000000000000000000014371217430427200234660ustar00rootroot00000000000000set test "system_func" if {![installtest_p]} { untested $test; return } foreach runtime [get_runtime_list] { set test "system_func" if {$runtime != ""} { lappend test "($runtime)" spawn stap --runtime=$runtime $srcdir/$subdir/system_func.stp } else { spawn stap $srcdir/$subdir/system_func.stp } set open 0 set done 0 set saw_user 0 set user [exec whoami] expect { -timeout 30 -re "($user|sys_open|DONE)\r" { switch $expect_out(1,string) { sys_open {incr open} DONE {incr done} default {incr saw_user} } exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$open == 1 && $saw_user == 1 && $done == 1 } { pass "$test" } else { fail "$test ($open,$saw_user,$done)" } } systemtap-2.3/testsuite/systemtap.base/system_func.stp000077500000000000000000000012611217430427200234760ustar00rootroot00000000000000#! stap # test the system() function global saw_echo, did_cat %(runtime == "kernel" %? probe kernel.function("do_sys_open") %: # The dyninst runtime doesn't have kernel.function probes. Instead, # we'll just use a begin probe to run system(). probe begin %) { if (!saw_echo) { # very inefficient. Testing only. DO NOT DO THIS msg="echo do_sys_open" system(msg) saw_echo = 1 } } probe timer.ms(100) { # should fail if (!did_cat) { system("cat __xyzzy123ABC__") did_cat = 1 } } probe timer.ms(150) { if (saw_echo && did_cat) exit() } probe begin { # should succeed system("whoami") } probe end { # should succeed system("echo DONE") } systemtap-2.3/testsuite/systemtap.base/tapset/000077500000000000000000000000001217430427200217045ustar00rootroot00000000000000systemtap-2.3/testsuite/systemtap.base/tapset/alias.stp000066400000000000000000000001311217430427200235200ustar00rootroot00000000000000probe test_alias = end { alias_local = 1 } probe begin { println("included alias") } systemtap-2.3/testsuite/systemtap.base/tapset/function.stp000066400000000000000000000001341217430427200242570ustar00rootroot00000000000000function test_function:long() { return 1 } probe begin { println("included function") } systemtap-2.3/testsuite/systemtap.base/tapset/global.stp000066400000000000000000000001041217430427200236670ustar00rootroot00000000000000global test_global = 1 probe begin { println("included global") } systemtap-2.3/testsuite/systemtap.base/tapset_includes.exp000066400000000000000000000014061217430427200243110ustar00rootroot00000000000000# Check that globals, functions, and aliases will pull in probes from the # tapset file in which they are defined. if {![installtest_p]} { untested "tapset includes"; return } set tapset "$srcdir/$subdir/tapset" # global set script "probe end { if (test_global) println(\"end\") }" set ::result_string "included global\nend" stap_run_exact "tapset include global" -I$tapset -e $script -c true # function set script "probe end { if (test_function()) println(\"end\") }" set ::result_string "included function\nend" stap_run_exact "tapset include function" -I$tapset -e $script -c true # alias set script "probe test_alias { if (alias_local) println(\"end\") }" set ::result_string "included alias\nend" stap_run_exact "tapset include alias" -I$tapset -e $script -c true systemtap-2.3/testsuite/systemtap.base/target_set.exp000066400000000000000000000037001217430427200232630ustar00rootroot00000000000000# Test for target_set tapset set test target_set if {![installtest_p]} { untested $test; continue } set file $srcdir/$subdir/target_set.stp set time 12345 set stap_cmd "( ( /bin/sleep $time ) ; ( /bin/sleep $time ) ; ( /bin/sleep $time ) )" set stap_cmd_sleep_count 3 set stap_cmd_child_level 3 proc failtest {reason} { global test catch close; catch wait; fail "$test - $reason" } proc expect_target_set_string {} { expect { "^target set:\r\n" { } -re {^WARNING: Child process exited.+\r\n} { exp_continue } timeout { failtest "timeout (expect_target_set_string)" return -code return } eof { failtest "eof (expect_target_set_string)" return -code return } } } proc expect_target_set_pids generations { global test global stp_pid for {set i 0} {$i < $generations} {incr i} { expect { -re {^([0-9]+) begat ([0-9]+)\r\n} { set pid_array($expect_out(1,string)) $expect_out(2,string) } -re {^WARNING: Child process exited.+\r\n} { exp_continue } timeout { failtest "timeout (expect_target_set_pids)" return -code return } eof { failtest "eof (expect_target_set_pids)" return -code return } } } set pid_it $stp_pid while {[info exists pid_array($pid_it)]} { if {[exec pgrep -P $pid_it] != $pid_array($pid_it)} { failtest "(expect_target_set_pids)" return -code return } set pid_it $pid_array($pid_it) } if {$generations > 1} { exec kill -INT $pid_it } } spawn stap $file $time -c "$stap_cmd" expect { -timeout 180 -re "semantic error:" { failtest; return } -re {^(\d+)\r\n} { set stp_pid $expect_out(1,string) } timeout { failtest "timeout (main1)"; return } eof { failtest "eof (main1)"; return } } expect_target_set_pids 1 for {set i 0} {$i < $stap_cmd_sleep_count} {incr i} { expect_target_set_string expect_target_set_pids $stap_cmd_child_level } expect_target_set_string expect_target_set_pids 0 expect { eof {} timeout { failtest "timeout (main2)"; return } } catch close; catch wait; pass $test systemtap-2.3/testsuite/systemtap.base/target_set.stp000066400000000000000000000010621217430427200232740ustar00rootroot00000000000000probe begin { stp_pid = stp_pid() printf("%d\n%d begat %d\n", stp_pid, stp_pid, target()) } # Why is the @cast() necessary? Why not just do '$rqtp->tv_sec'? On # s390x and ppc64, because of syscall wrappers, $rqtp gets turned into # a long. probe syscall.nanosleep { if (target_set_pid(pid()) && @cast($rqtp, "struct timespec")->tv_sec == $1) target_set_report() } probe syscall.compat_nanosleep ? { if (target_set_pid(pid()) && @cast($rqtp, "struct compat_timespec")->tv_sec == $1) target_set_report() } probe end { target_set_report() } systemtap-2.3/testsuite/systemtap.base/target_set_thread.exp000066400000000000000000000011571217430427200246160ustar00rootroot00000000000000set test "target_set_thread" # target_set should not forget a process once one of its threads ends. # (this is an issue with using syscall.exit, which is only a true process exit # if that was the last thread in the thread group.) set ::result_string {benchmark__start benchmark__thread__end benchmark__end} set script $srcdir/$subdir/$test.stp set command {stap --benchmark-sdt-loops=1 --benchmark-sdt-threads=1} foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run3 "$test ($runtime)" $script --runtime=$runtime -c $command } else { stap_run3 $test $script -c $command } } systemtap-2.3/testsuite/systemtap.base/target_set_thread.stp000066400000000000000000000002661217430427200246300ustar00rootroot00000000000000probe process.mark("benchmark__start"), process.mark("benchmark__thread__end"), process.mark("benchmark__end") { if (target_set_pid(pid())) println($$name) } systemtap-2.3/testsuite/systemtap.base/timeofday.exp000066400000000000000000000012311217430427200231000ustar00rootroot00000000000000# timeofday.exp # # This test is meant to make sure that our time functions can still be called # from contexts where do_gettimeofday is unsafe (e.g. when xtime_lock is held). # See bug #2525 for more details. proc sleep_one_sec {} { after 1000; return 0; } set systemtap_script { global timeofday probe kernel.function("do_timer") { timeofday = gettimeofday_us() } probe begin { log("systemtap starting probe") } probe end { log("systemtap ending probe") printf("%d\n", timeofday) } } set output_string "\\d+\\r\\n" stap_run "timeofday test" sleep_one_sec $output_string -e $systemtap_script systemtap-2.3/testsuite/systemtap.base/timers.exp000066400000000000000000000010011217430427200224150ustar00rootroot00000000000000# Test the functionality of the various timer.* probes. set test "timers" # A simple load that give the timers a chance to run proc sleep_ten_secs {} { after 10000; return 0; } #check to see whether get the marker indicating the probe is loaded and running #should check to see whether exited for some reason #should be error is something else is printed. set output_string "(\\w+ = \\d+\r\n){7}${all_pass_string}(WARNING.*skipped.*)?" stap_run $srcdir/$subdir/$test.stp sleep_ten_secs $output_string systemtap-2.3/testsuite/systemtap.base/timers.stp000066400000000000000000000034411217430427200224410ustar00rootroot00000000000000/* * timers.stp * * Test the functionality of the various timer.* probes. */ global p global j1, j2, jmax global ms1, ms500, msmax probe begin { printf("systemtap starting probe\n") } probe timer.profile { ++p } probe timer.jiffies(1) { ++j1 } probe timer.jiffies(2) { ++j2 } probe timer.jiffies(1000000) { ++jmax } /* as long as HZ>2, ms(1) and ms(500) * will produce different counts */ probe timer.ms(1) { ++ms1 } probe timer.ms(500) { ++ms500 } probe timer.ms(1000000) { ++msmax } probe end { printf("systemtap ending probe\n") printf("p = %d\n", p) printf("j1 = %d\n", j1) printf("j2 = %d\n", j2) printf("jmax = %d\n", jmax) printf("ms1 = %d\n", ms1) printf("ms500 = %d\n", ms500) printf("msmax = %d\n", msmax) /* profile counter should be non-zero, and at * least as many as the jiffies(1) counter */ /* (fudge comparison by ~1% since start & end aren't synchronized) */ if ((p > 0) && (p*100 >= j1*99)) { printf("systemtap test success\n") } else { printf("unexpected profile count: %d profiles and %d jiffies\n", p, j1) printf("systemtap test failure\n"); } /* jiffies(1) should count more than jiffies(2), * and both should be non-zero. */ if ((j2 > 0) && (j2 < j1)) { printf("systemtap test success\n") } else { printf("unexpected jiffies count\n") printf("systemtap test failure\n"); } /* ms(1) should count more than ms(500), * and both should be non-zero. */ if ((ms500 > 0) && (ms500 < ms1)) { printf("systemtap test success\n") } else { printf("unexpected ms count\n") printf("systemtap test failure\n"); } /* both 'infinite' intervals should register zero counts */ if ((jmax == 0) && (msmax == 0)) { printf("systemtap test success\n") } else { printf("unexpected count on 'infinite' interval\n") printf("systemtap test failure\n"); } } systemtap-2.3/testsuite/systemtap.base/towers.c000066400000000000000000000042421217430427200220750ustar00rootroot00000000000000# include # include #define towersbase 2.39 /* Towers */ #define maxcells 18 #define stackrange 3 #define true 1 #define false 0 struct element { int discsize; int next; }; /* Towers */ int stack[stackrange + 1]; struct element cellspace[maxcells + 1]; int freelist, movesdone; /* Program to Solve the Towers of Hanoi */ void error (emsg) char *emsg; { printf ("Error in Towers: %s\n", emsg); } void makenull (s) { stack[s] = 0; } int get_element () { int temp; if (freelist > 0) { temp = freelist; freelist = cellspace[freelist].next; } else error ("out of space "); return (temp); } void push (i, s) int i, s; { int errorfound, localel; errorfound = false; if (stack[s] > 0) if (cellspace[stack[s]].discsize <= i) { errorfound = true; error ("disc size error"); }; if (!errorfound) { localel = get_element (); cellspace[localel].next = stack[s]; stack[s] = localel; cellspace[localel].discsize = i; } } void init (s, n) int s, n; { int discctr; makenull (s); for (discctr = n; discctr >= 1; discctr--) push (discctr, s); } int pop (s) int s; { int temp, temp1; if (stack[s] > 0) { temp1 = cellspace[stack[s]].discsize; temp = cellspace[stack[s]].next; cellspace[stack[s]].next = freelist; freelist = stack[s]; stack[s] = temp; return (temp1); } else error ("nothing to pop "); return 0; } void move (s1, s2) int s1, s2; { push (pop (s1), s2); movesdone = movesdone + 1; } void tower (i, j, k) int i, j, k; { int other; if (k == 1) move (i, j); else { other = 6 - i - j; tower (i, other, k - 1); move (i, j); tower (other, j, k - 1); } } void towers () { int i; for (i = 1; i <= maxcells; i++) cellspace[i].next = i - 1; freelist = maxcells; init (1, 14); makenull (2); makenull (3); movesdone = 0; tower (1, 2, 14); if (movesdone != 16383) printf (" error in Towers.\n"); } #ifndef LOOP #define LOOP 500 #endif int main () { int i; for (i= 0; i < LOOP; i++) towers(); return 0; } systemtap-2.3/testsuite/systemtap.base/tracepoints.exp000066400000000000000000000020241217430427200234530ustar00rootroot00000000000000set test "tracepoints" set tracepoints {} spawn stap -l {kernel.trace("*")} expect { -timeout 60 -re {^kernel.trace[^\r\n]*\r\n} { append tracepoints $expect_out(0,string) exp_continue } timeout {} eof {} } catch {close}; catch { wait } pass "$test list [llength $tracepoints]" # Use this to test each tracepoint individually. #foreach tp $tracepoints { # set test "tracepoint $tp -p4" # if {[catch {exec stap -w -p4 -e "probe $tp { println($\$name, $\$vars) }"} res]} { # fail "$test $res" # } else { # pass "$test" # } #} # This tests all tracepoints all at once (much faster than the above) set script "probe begin {}" foreach tp $tracepoints { set script "$script probe $tp { println($\$name, $\$vars) }" } send_log "Trying stap -w -p4 -e $script\n" if {[catch {exec stap -w -p4 -e "$script"} res]} { fail "$test $res" } else { pass "$test" } if {![installtest_p]} { untested $test; return } set ::result_string {tracepoints OK} stap_run2 $srcdir/$subdir/$test.stp -w systemtap-2.3/testsuite/systemtap.base/tracepoints.stp000066400000000000000000000013131217430427200234650ustar00rootroot00000000000000// This checks that we can compile and register every tracepoint // we can find, along with all of their context variables. global hits probe all_tracepoints = kernel.trace("*") { if ($$name . $$vars . $$parms == "") next // Allow it to quit once we hit our hundredth tracepoint if (++hits < 100) next } // If there aren't any tracepoints in the kernel, // we use "begin" instead to quit right away. probe all_tracepoints!, begin { // Only print once (after enough hits, or at the begin probe). PR10427 if (hits == 0 || hits == 100) println("tracepoints OK") exit() } // give hits a use so there's no warning // when we don't have tracepoints probe never { hits++ } systemtap-2.3/testsuite/systemtap.base/tracescripts.exp000066400000000000000000000004121217430427200236250ustar00rootroot00000000000000set stap_path $env(SYSTEMTAP_PATH)/stap exec echo "#!$stap_path" > tracescripts.sh if {[catch {exec stap -L {process("tracescripts.sh").mark("*")}} res]} { fail "tracescripts $res" } else { pass "tracescripts" } catch {exec rm -f tracescripts.sh} systemtap-2.3/testsuite/systemtap.base/tri.exp000066400000000000000000000004651217430427200217250ustar00rootroot00000000000000# Simple function to test that systemtap ?: operation works set test "tri" foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string \ --runtime=$runtime } else { stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string } } systemtap-2.3/testsuite/systemtap.base/tri.stp000066400000000000000000000011261217430427200217320ustar00rootroot00000000000000/* * tri.stp * * Check the systemtap ?: operator works */ global x1, x2, x3, x4, x5, x6 probe begin { println("systemtap starting probe"); x1 = 0; x2 = 1; x3=30; } probe end { println("systemtap ending probe") x4 = x1 ? 9: 10; x5 = x2 ? 99: 100; x6 = x3 ? 999: 1000; if (x4 != 10 ) { println("systemtap test failure"); } else { println("systemtap test success"); } if (x5 != 99 ) { println("systemtap test failure"); } else { println("systemtap test success"); } if (x6 != 999 ) { println("systemtap test failure"); } else { println("systemtap test success"); } } systemtap-2.3/testsuite/systemtap.base/trycatch.exp000066400000000000000000000032521217430427200227450ustar00rootroot00000000000000set test "trycatch" if {! [installtest_p]} { untested $test; return } foreach runtime [get_runtime_list] { set test "trycatch" set ok 0 set ko 0 if {$runtime != ""} { lappend test "($runtime)" spawn stap --runtime=$runtime $srcdir/buildok/fortyone.stp } else { spawn stap $srcdir/buildok/fortyone.stp } expect { -timeout 30 -re {^ERROR: MAXACTION[^\r\n]*\r\n} { incr ok; exp_continue } -re {^WARNING: Number of errors[^\r\n]*\r\n} { incr ok; exp_continue } -re {^WARNING:[^\r\n]* exited with status:[^\r\n]*\r\n} {incr ok; exp_continue } -re {^Pass 5: run failed[^\r\n]*\r\n} { incr ok; exp_continue } -re {^OK[^\r\n]*\r\n} { incr ok; exp_continue } -re {^KO[^\r\n]*\r\n} { incr ko; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 13 && $ko == 0} then {pass $test} else {fail "$test ($ok $ko)"} set test "trycatch -u" set ok 0 set ko 0 if {$runtime != ""} { lappend test "($runtime)" spawn stap --runtime=$runtime -u $srcdir/buildok/fortyone.stp } else { spawn stap -u $srcdir/buildok/fortyone.stp } expect { -timeout 30 -re {^ERROR: MAXACTION[^\r\n]*\r\n} { incr ok; exp_continue } -re {^WARNING: Number of errors[^\r\n]*\r\n} { incr ok; exp_continue } -re {^WARNING:[^\r\n]* exited with status:[^\r\n]*\r\n} {incr ok; exp_continue } -re {^Pass 5: run failed[^\r\n]*\r\n} { incr ok; exp_continue } -re {^OK[^\r\n]*\r\n} { incr ok; exp_continue } -re {^KO[^\r\n]*\r\n} { incr ko; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch {close}; catch {wait} if {$ok == 13 && $ko == 0} then {pass $test} else {fail "$test ($ok $ko)"} } systemtap-2.3/testsuite/systemtap.base/unresolved-struct-typedef.c000066400000000000000000000016011217430427200257140ustar00rootroot00000000000000#include // PR12121 // // This kind of "repeated" typedef used to cause bad things for us. When // resolving $epoch->foo below, we start at the typedef-tm and dereference to // the struct-tm. That's just a declaration, so we use declaration_resolve to // look for the struct definition. But since we were looking by the name "tm" // only, we would find the typedef again, getting us nowhere. // // The fixed code does declaration_resolve on "struct tm" in the global cache, // so in this case we won't find anything locally, and thus we continue looking // in other CUs. The test harness compiles this with time.h in another CU to // provide the actual definition for "struct tm". typedef struct tm tm; typedef long time_t; extern struct tm *localtime(const time_t *timep); int main() { tm* epoch = localtime(0); STAP_PROBE1(test, epoch, (void*)epoch); return 0; } systemtap-2.3/testsuite/systemtap.base/unresolved-struct-typedef.exp000066400000000000000000000025601217430427200262730ustar00rootroot00000000000000# test the resolution of unresolved struct typedefs set test "unresolved-struct-typedef" # process probes need utrace if {![uprobes_p]} { untested "$test"; return } for {set i 0} {$i < [all_compile_flags]} {incr i} { set extra_flag [all_compile_flag $i] set extra_name [all_compile_flag_name $i] set test_flags "additional_flags=-g" set test_flags "$test_flags [sdt_includes]" set test_flags "$test_flags $extra_flag" # we deliberately don't #include time.h in the main CU # instead we pull the header in as a separate CU set test_flags "$test_flags additional_flags=-fno-eliminate-unused-debug-types" set test_flags "$test_flags additional_flags=-xc" set test_flags "$test_flags additional_flags=/usr/include/time.h" set res [target_compile "$srcdir/$subdir/$test.c" "$test.exe" executable "$test_flags"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test-$extra_name compile" untested "$test-$extra_name" return } else { pass "$test-$extra_name compile" } set script {{ probe process(@1).mark("epoch") { println($epoch->tm_year) } }} foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_compile "$test-$extra_name-$runtime" 1 "$script" \ --runtime=$runtime "$test.exe" } else { stap_compile "$test-$extra_name" 1 "$script" "$test.exe" } } catch {exec rm -f "$test.exe"} } systemtap-2.3/testsuite/systemtap.base/uprobes.exp000066400000000000000000000037721217430427200226120ustar00rootroot00000000000000# We've got 3 main tests: # (1) uprobes_call, which probes function entry # (2) uprobes_return, which probes function exit # (3) uprobes, which combines the above two tests # 'test_array' holds the name of each test and its expected number of # output lines set test_array(uprobes_call) 5 set test_array(uprobes_return) 5 set test_array(uprobes) 10 set test uprobes catch {exec gcc -g -o jennie $srcdir/$subdir/jennie.c} err if {$err == "" && [file exists jennie]} then { pass "$test compile" } else { fail "$test compile" } foreach test [lsort [array names test_array]] { foreach runtime [get_runtime_list] { # Try to compile the script set test_xtra "" if {$runtime != ""} { set test_xtra " ($runtime)" set rc [stap_run_batch $srcdir/$subdir/${test}.stp \ --runtime=$runtime] } else { if {! [uprobes_p]} { foreach test [lsort [array names test_array]] { untested "$test -p4"; untested "$test -p5" } continue } set rc [stap_run_batch $srcdir/$subdir/${test}.stp] } if {$rc == 0} then { pass "$test -p4${test_xtra}" } else { fail "$test -p4${test_xtra}" } if {! [installtest_p]} { untested "$test -p5${test_xtra}"; continue } elseif {$rc != 0} { # If the compile failed, don't bother trying to run it. fail "$test -p5${test_xtra}"; continue } # Try to run the script if {$runtime != ""} { spawn stap $srcdir/$subdir/${test}.stp --runtime=$runtime \ -w -c "./jennie 1 2 3 4" } else { spawn stap $srcdir/$subdir/${test}.stp -w -c "./jennie 1 2 3 4" } set ok 0 expect { -re {^process[^\r\n]+jennie[^\r\n]+main[^\r\n]+arg[cv]=0x[0-9a-f]+\ +arg[cv]=0x[0-9a-f]+\r\n} { incr ok; exp_continue } -re {^process[^\r\n]+jennie[^\r\n]+main[^\r\n]+return=0x0\r\n} { incr ok; exp_continue } -timeout 30 timeout { } eof { } } catch { close }; catch { wait } if {$ok == $test_array($test)} then { pass "$test -p5${test_xtra}" } else { fail "$test -p5${test_xtra} ($ok)" } } } catch {exec rm -f jennie} systemtap-2.3/testsuite/systemtap.base/uprobes.stp000077500000000000000000000002651217430427200226210ustar00rootroot00000000000000#! stap -p4 probe process("./jennie").function("main").call { printf("%s %s\n",pp(),$$parms) } probe process("./jennie").function("main").return { printf("%s %s\n",pp(),$$return) } systemtap-2.3/testsuite/systemtap.base/uprobes_call.stp000077500000000000000000000001371217430427200236120ustar00rootroot00000000000000#! stap -p4 probe process("./jennie").function("main").call { printf("%s %s\n",pp(),$$parms) } systemtap-2.3/testsuite/systemtap.base/uprobes_filtering.exp000066400000000000000000000126111217430427200246450ustar00rootroot00000000000000# This test has two purposes: # 1. To verify that uprobes is correctly filtering unwanted processes, # allowing stap scripts to run at full speed # 2. To verify that stapiu_probe_prehandler() is correctly filtering # unwanted processes # This is done by comparing the number of calls to # stapiu_probe_prehandler() and stapiu_probe_handler() using the # -DUPROBES_HITCOUNT define.added in commit 68561b3. # Note that this test relies on the basic assumption that there are no # other stap sessions or uprobes inserted in the benchmark inode of # stap. Otherwise, all hitcounts will be thrown off. set test "uprobes_filtering" # We need to actually run things if {! [installtest_p]} { untested $test; return } # If we're not using inode uprobes, don't bother testing. if {! [inode_uprobes_p]} { untested $test; return } # So that sudo stap works in case we're not running the test as root set installed_stap "$env(SYSTEMTAP_PATH)/stap" # Testing steps: # 1. check if we're root or user using id -u # 2. run mark("benchmark") w/ --privilege=stapusr # 3. run benchmark as user # 4. run benchmark as root # 5. stop process in 2. # 6. Check that the handler was called only for the right process # 7. Check that the wrong process was filtered out # 7a. First check if kernel prefiltering is supported # 7b. Verify hitcount results depending on prefiltering support # 1. Check if we're root or user set am_root [expr 0 == [exec id -u]] # 2. Start the background benchmark hitcounter spawn stap -DUPROBES_HITCOUNT --privilege=stapusr --vp 00003 \ -e "probe process(\"stap\").mark(\"benchmark\") \{ next \}" set stap_id $spawn_id set failed 1 expect { -timeout 30 -re {systemtap_module_init\(\)\ returned\ 0} { set failed 0 } timeout {exec kill -s KILL -[exp_pid -i $stap_id]} } if {$failed} { fail "$test (timeout: can't start benchmark monitor)" catch { close -i $stap_id } ; catch { wait -i $stap_id } return } else { pass "$test (started benchmark monitor)" } # 3. Run benchmark as user set non_root_loops 11111111 if {[as_non_root "$installed_stap \ --benchmark-sdt-loops=$non_root_loops"]} { fail "$test (can't start non-root benchmark)" } else { pass "$test (started non-root benchmark)" } # 4. Run benchmark as root set root_loops 10101010 if {[as_root "$installed_stap --benchmark-sdt-loops=$root_loops"]} { fail "$test (can't start root benchmark)" } else { pass "$test (started root benchmark)" } # 5. Stop process from step 2 exec kill -s TERM [exp_pid -i $stap_id] set prehandler_hitcount -1 set handler_hitcount -1 expect { -timeout 30 -i $stap_id -re {stapiu_probe_prehandler\(\)\ called\ ([0-9]+)\ times} { set prehandler_hitcount $expect_out(1,string) exp_continue } -re {stapiu_probe_handler\(\)\ called\ ([0-9]+)\ times} { set handler_hitcount $expect_out(1,string) } timeout { fail "$test (timeout: can't stop benchmark monitor)" exec kill -s KILL -[exp_pid -i $stap_id] } } catch { close -i $stap_id } ; catch { wait -i $stap_id } if {$prehandler_hitcount == -1 || $handler_hitcount == -1} { fail "$test (could not get prehandler/handler hitcount)" verbose -log "this happens if stap doesn't support UPROBES_HITCOUNT" return } # 6. Check that the handler was called only for the right process # This means that if we're root, then handler() should have been # called $root_loops times only, and vice-versa for not root if {(!$am_root && $handler_hitcount != $non_root_loops) || ($am_root && $handler_hitcount != $root_loops)} { fail "$test (handler was not called the right number of times)" if {$am_root} {set n $root_loops} else {set n $non_root_loops} verbose -log "expected number of calls: $n" verbose -log "actual number of calls: $handler_hitcount" return } # 7. Check that the wrong process was filtered out # 7a. First check if kernel prefiltering is supported # Relies on the fact that stap won't pass compilation if not supported set prefilter_support [expr ![catch {exec stap -p4 -g \ -e "probe begin \{%\{UPROBE_HANDLER_REMOVE%\}\}" 2> /dev/null}]] verbose -log "kernel prefiltering support = $prefilter_support" # 7b. Verify hitcount results depending on prefiltering support # If prefiltering is not supported, then we expect the prehandler to # be called $root_loops + $non_root_loops times if {!$prefilter_support} { set total [expr {$root_loops + $non_root_loops}] if {$prehandler_hitcount != $total} { fail "$test (prehandler was not called the right number of times)" verbose -log "expected number of calls: $total" verbose -log "actual number of calls: $prehandler_hitcount" return } } else { # Prefiltering is supported, so we expect the prehandler to be called # only one time more than handler. # TODO: Verify that it will always be only 1 greater. From a look at # kernel/events/uprobes.c, it seems that in the handler_chain() func, # after handler() returns, the next call is unapply_uprobe() (assuming # we are the only consumers for this probe), which will remove the # uprobe. Since the handler() call is wrapped in semaphores, we should # get no other calls before the first handler_chain() finishes. set total [expr {$handler_hitcount + 1}] if {$prehandler_hitcount != $total} { fail "$test (prehandler was not called the right number of times)" verbose -log "expected number of calls: $total" verbose -log "actual number of calls: $prehandler_hitcount" verbose -log "this can happen if other uprobes are inserted at\ the same location" return } } pass $test systemtap-2.3/testsuite/systemtap.base/uprobes_return.stp000077500000000000000000000001421217430427200242120ustar00rootroot00000000000000#! stap -p4 probe process("./jennie").function("main").return { printf("%s %s\n",pp(),$$return) } systemtap-2.3/testsuite/systemtap.base/utf_kernel.exp000066400000000000000000000002771217430427200232660ustar00rootroot00000000000000set test "utf_kernel" set ::result_string {73 74 61 70 391 3A9 263A D83D DE08 : stapΑΩ☺😈 73 74 61 70 391 3A9 263A 1F608 : stapΑΩ☺😈} stap_run3 $test $srcdir/$subdir/$test.stp -g systemtap-2.3/testsuite/systemtap.base/utf_kernel.stp000066400000000000000000000020641217430427200232740ustar00rootroot00000000000000function utf16_addr:long() %{ static u16 utf16_string[] = { 0x73, 0x74, 0x61, 0x70, // "stap" (one-byte UTF-8 each) 0x391, 0x3A9, // "ΑΩ" (two-byte UTF-8 each) 0x263A, // "☺" (three-byte UTF-8) 0xD83D, 0xDE08, // U+1F608 "😈" (four-byte UTF-8) 0 }; STAP_RETVALUE = (intptr_t)utf16_string; %} function utf32_addr:long() %{ static u32 utf32_string[] = { 0x73, 0x74, 0x61, 0x70, // "stap" (one-byte UTF-8 each) 0x391, 0x3A9, // "ΑΩ" (two-byte UTF-8 each) 0x263A, // "☺" (three-byte UTF-8) 0x1F608, // "😈" (four-byte UTF-8) 0 }; STAP_RETVALUE = (intptr_t)utf32_string; %} probe begin { s = utf16_addr(); for (p = s; i = kernel_short(p) & 0xffff; p += 2) printf("%X ", i) println(":") println(kernel_string_utf16(s)) s = utf32_addr(); for (p = s; i = kernel_int(p) & 0xffffffff; p += 4) printf("%X ", i) println(":") println(kernel_string_utf32(s)) exit() } systemtap-2.3/testsuite/systemtap.base/utf_kernel_trunc.exp000066400000000000000000000011251217430427200244720ustar00rootroot00000000000000set test "utf_kernel_trunc" set ::result_string {utf-16:012345678Z utf-16:0123456789 utf-16:01234567Ω utf-16:012345678 utf-16:0123456789 utf-16:0123456☺ utf-16:01234567 utf-16:012345678 utf-16:0123456789 utf-16:012345😈 utf-16:0123456 utf-16:01234567 utf-16:012345678 utf-16:0123456789 utf-32:012345678Z utf-32:0123456789 utf-32:01234567Ω utf-32:012345678 utf-32:0123456789 utf-32:0123456☺ utf-32:01234567 utf-32:012345678 utf-32:0123456789 utf-32:012345😈 utf-32:0123456 utf-32:01234567 utf-32:012345678 utf-32:0123456789} stap_run3 $test $srcdir/$subdir/$test.stp -g -DMAXSTRINGLEN=11 systemtap-2.3/testsuite/systemtap.base/utf_kernel_trunc.stp000066400000000000000000000046101217430427200245060ustar00rootroot00000000000000%{ #if MAXSTRINGLEN != 11 #error This test is hard-coded for MAXSTRINGLEN==11 #endif #define UPTO5 '0', '1', '2', '3', '4', '5' #define UPTO6 UPTO5, '6' #define UPTO7 UPTO6, '7' #define UPTO8 UPTO7, '8' #define UPTO9 UPTO8, '9' static u16 s16_len1_0[] = {UPTO8, 0x5A, 0}; // Z static u16 s16_len1_1[] = {UPTO9, 0x5A, 0}; static u16 s16_len2_0[] = {UPTO7, 0x3A9, 0}; // Ω static u16 s16_len2_1[] = {UPTO8, 0x3A9, 0}; static u16 s16_len2_2[] = {UPTO9, 0x3A9, 0}; static u16 s16_len3_0[] = {UPTO6, 0x263A, 0}; // ☺ static u16 s16_len3_1[] = {UPTO7, 0x263A, 0}; static u16 s16_len3_2[] = {UPTO8, 0x263A, 0}; static u16 s16_len3_3[] = {UPTO9, 0x263A, 0}; static u16 s16_len4_0[] = {UPTO5, 0xD83D, 0xDE08, 0}; // 😈 static u16 s16_len4_1[] = {UPTO6, 0xD83D, 0xDE08, 0}; static u16 s16_len4_2[] = {UPTO7, 0xD83D, 0xDE08, 0}; static u16 s16_len4_3[] = {UPTO8, 0xD83D, 0xDE08, 0}; static u16 s16_len4_4[] = {UPTO9, 0xD83D, 0xDE08, 0}; static u16 *utf16_strings[] = { s16_len1_0, s16_len1_1, s16_len2_0, s16_len2_1, s16_len2_2, s16_len3_0, s16_len3_1, s16_len3_2, s16_len3_3, s16_len4_0, s16_len4_1, s16_len4_2, s16_len4_3, s16_len4_4, 0 }; static u32 s32_len1_0[] = {UPTO8, 0x5A, 0}; // Z static u32 s32_len1_1[] = {UPTO9, 0x5A, 0}; static u32 s32_len2_0[] = {UPTO7, 0x3A9, 0}; // Ω static u32 s32_len2_1[] = {UPTO8, 0x3A9, 0}; static u32 s32_len2_2[] = {UPTO9, 0x3A9, 0}; static u32 s32_len3_0[] = {UPTO6, 0x263A, 0}; // ☺ static u32 s32_len3_1[] = {UPTO7, 0x263A, 0}; static u32 s32_len3_2[] = {UPTO8, 0x263A, 0}; static u32 s32_len3_3[] = {UPTO9, 0x263A, 0}; static u32 s32_len4_0[] = {UPTO5, 0x1F608, 0}; // 😈 static u32 s32_len4_1[] = {UPTO6, 0x1F608, 0}; static u32 s32_len4_2[] = {UPTO7, 0x1F608, 0}; static u32 s32_len4_3[] = {UPTO8, 0x1F608, 0}; static u32 s32_len4_4[] = {UPTO9, 0x1F608, 0}; static u32 *utf32_strings[] = { s32_len1_0, s32_len1_1, s32_len2_0, s32_len2_1, s32_len2_2, s32_len3_0, s32_len3_1, s32_len3_2, s32_len3_3, s32_len4_0, s32_len4_1, s32_len4_2, s32_len4_3, s32_len4_4, 0 }; %} function utf16_addr:long(i:long) %{ STAP_RETVALUE = (intptr_t)utf16_strings[STAP_ARG_i]; %} function utf32_addr:long(i:long) %{ STAP_RETVALUE = (intptr_t)utf32_strings[STAP_ARG_i]; %} probe begin { for (i = 0; s = utf16_addr(i); ++i) println("utf-16:", kernel_string_utf16(s)) for (i = 0; s = utf32_addr(i); ++i) println("utf-32:", kernel_string_utf32(s)) exit() } systemtap-2.3/testsuite/systemtap.base/utf_pretty.cxx000066400000000000000000000006131217430427200233350ustar00rootroot00000000000000#include static struct { char c8; char16_t c16; char32_t c32; const char *s8; const char16_t *s16; const char32_t *s32; } strings = { 's', u't', U'p', // various encodings of "stapΑΩ☺😈" u8"stap\u0391\u03A9\u263A\U0001F608", u"stap\u0391\u03A9\u263A\U0001F608", U"stap\u0391\u03A9\u263A\U0001F608", }; int main() { return 0; } systemtap-2.3/testsuite/systemtap.base/utf_pretty.exp000066400000000000000000000014531217430427200233320ustar00rootroot00000000000000set test "utf_pretty" set ::result_string {{.c8='s', .c16='t', .c32='p', .s8="stapΑΩ☺😈", .s16="stapΑΩ☺😈", .s32="stapΑΩ☺😈"}} set srcfile "$srcdir/$subdir/$test.cxx" set stpfile "$srcdir/$subdir/$test.stp" set exefile "[pwd]/$test.exe" set test_flags "compiler=g++ additional_flags=-g additional_flags=-std=c++0x" set res [target_compile "$srcfile" "$exefile" executable "$test_flags"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test compile" untested "$test" return } else { pass "$test compile" } foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run3 "$test ($runtime)" "$stpfile" -c "$exefile" --runtime=$runtime } else { stap_run3 $test "$stpfile" -c "$exefile" } } if { $verbose == 0 } { catch { exec rm -f $exefile } } systemtap-2.3/testsuite/systemtap.base/utf_pretty.stp000066400000000000000000000000711217430427200233370ustar00rootroot00000000000000probe process.function("main") { println($strings$) } systemtap-2.3/testsuite/systemtap.base/utf_user.c000066400000000000000000000011441217430427200224040ustar00rootroot00000000000000#include static uint16_t utf16_string[] = { 0x73, 0x74, 0x61, 0x70, // "stap" (one-byte UTF-8 each) 0x391, 0x3A9, // "ΑΩ" (two-byte UTF-8 each) 0x263A, // "☺" (three-byte UTF-8) 0xD83D, 0xDE08, // U+1F608 "😈" (four-byte UTF-8) 0 }; static uint32_t utf32_string[] = { 0x73, 0x74, 0x61, 0x70, // "stap" (one-byte UTF-8 each) 0x391, 0x3A9, // "ΑΩ" (two-byte UTF-8 each) 0x263A, // "☺" (three-byte UTF-8) 0x1F608, // "😈" (four-byte UTF-8) 0 }; int main() { return 0; } systemtap-2.3/testsuite/systemtap.base/utf_user.exp000066400000000000000000000013731217430427200227620ustar00rootroot00000000000000set test "utf_user" set ::result_string {73 74 61 70 391 3A9 263A D83D DE08 : stapΑΩ☺😈 73 74 61 70 391 3A9 263A 1F608 : stapΑΩ☺😈} set srcfile "$srcdir/$subdir/$test.c" set stpfile "$srcdir/$subdir/$test.stp" set exefile "[pwd]/$test.exe" set test_flags "additional_flags=-g" set res [target_compile "$srcfile" "$exefile" executable "$test_flags"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test compile" untested "$test" return } else { pass "$test compile" } foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run3 "$test $runtime" "$stpfile" -c "$exefile" --runtime=$runtime } else { stap_run3 $test "$stpfile" -c "$exefile" } } if { $verbose == 0 } { catch { exec rm -f $exefile } } systemtap-2.3/testsuite/systemtap.base/utf_user.stp000066400000000000000000000004751217430427200227760ustar00rootroot00000000000000probe process.function("main") { s = $utf16_string; for (p = s; i = user_short(p) & 0xffff; p += 2) printf("%X ", i) println(":") println(user_string_utf16(s)) s = $utf32_string; for (p = s; i = user_int(p) & 0xffffffff; p += 4) printf("%X ", i) println(":") println(user_string_utf32(s)) } systemtap-2.3/testsuite/systemtap.base/utf_user_trunc.c000066400000000000000000000041351217430427200236220ustar00rootroot00000000000000#include typedef uint16_t u16; typedef uint32_t u32; #if MAXSTRINGLEN != 11 #error This test is hard-coded for MAXSTRINGLEN==11 #endif #define UPTO5 '0', '1', '2', '3', '4', '5' #define UPTO6 UPTO5, '6' #define UPTO7 UPTO6, '7' #define UPTO8 UPTO7, '8' #define UPTO9 UPTO8, '9' static u16 s16_len1_0[] = {UPTO8, 0x5A, 0}; // Z static u16 s16_len1_1[] = {UPTO9, 0x5A, 0}; static u16 s16_len2_0[] = {UPTO7, 0x3A9, 0}; // Ω static u16 s16_len2_1[] = {UPTO8, 0x3A9, 0}; static u16 s16_len2_2[] = {UPTO9, 0x3A9, 0}; static u16 s16_len3_0[] = {UPTO6, 0x263A, 0}; // ☺ static u16 s16_len3_1[] = {UPTO7, 0x263A, 0}; static u16 s16_len3_2[] = {UPTO8, 0x263A, 0}; static u16 s16_len3_3[] = {UPTO9, 0x263A, 0}; static u16 s16_len4_0[] = {UPTO5, 0xD83D, 0xDE08, 0}; // 😈 static u16 s16_len4_1[] = {UPTO6, 0xD83D, 0xDE08, 0}; static u16 s16_len4_2[] = {UPTO7, 0xD83D, 0xDE08, 0}; static u16 s16_len4_3[] = {UPTO8, 0xD83D, 0xDE08, 0}; static u16 s16_len4_4[] = {UPTO9, 0xD83D, 0xDE08, 0}; static u16 *utf16_strings[] = { s16_len1_0, s16_len1_1, s16_len2_0, s16_len2_1, s16_len2_2, s16_len3_0, s16_len3_1, s16_len3_2, s16_len3_3, s16_len4_0, s16_len4_1, s16_len4_2, s16_len4_3, s16_len4_4, 0 }; static u32 s32_len1_0[] = {UPTO8, 0x5A, 0}; // Z static u32 s32_len1_1[] = {UPTO9, 0x5A, 0}; static u32 s32_len2_0[] = {UPTO7, 0x3A9, 0}; // Ω static u32 s32_len2_1[] = {UPTO8, 0x3A9, 0}; static u32 s32_len2_2[] = {UPTO9, 0x3A9, 0}; static u32 s32_len3_0[] = {UPTO6, 0x263A, 0}; // ☺ static u32 s32_len3_1[] = {UPTO7, 0x263A, 0}; static u32 s32_len3_2[] = {UPTO8, 0x263A, 0}; static u32 s32_len3_3[] = {UPTO9, 0x263A, 0}; static u32 s32_len4_0[] = {UPTO5, 0x1F608, 0}; // 😈 static u32 s32_len4_1[] = {UPTO6, 0x1F608, 0}; static u32 s32_len4_2[] = {UPTO7, 0x1F608, 0}; static u32 s32_len4_3[] = {UPTO8, 0x1F608, 0}; static u32 s32_len4_4[] = {UPTO9, 0x1F608, 0}; static u32 *utf32_strings[] = { s32_len1_0, s32_len1_1, s32_len2_0, s32_len2_1, s32_len2_2, s32_len3_0, s32_len3_1, s32_len3_2, s32_len3_3, s32_len4_0, s32_len4_1, s32_len4_2, s32_len4_3, s32_len4_4, 0 }; int main() { return 0; } systemtap-2.3/testsuite/systemtap.base/utf_user_trunc.exp000066400000000000000000000023201217430427200241660ustar00rootroot00000000000000set test "utf_user_trunc" set ::result_string {utf-16:012345678Z utf-16:0123456789 utf-16:01234567Ω utf-16:012345678 utf-16:0123456789 utf-16:0123456☺ utf-16:01234567 utf-16:012345678 utf-16:0123456789 utf-16:012345😈 utf-16:0123456 utf-16:01234567 utf-16:012345678 utf-16:0123456789 utf-32:012345678Z utf-32:0123456789 utf-32:01234567Ω utf-32:012345678 utf-32:0123456789 utf-32:0123456☺ utf-32:01234567 utf-32:012345678 utf-32:0123456789 utf-32:012345😈 utf-32:0123456 utf-32:01234567 utf-32:012345678 utf-32:0123456789} set srcfile "$srcdir/$subdir/$test.c" set stpfile "$srcdir/$subdir/$test.stp" set exefile "[pwd]/$test.exe" set test_flags "additional_flags=-g additional_flags=-DMAXSTRINGLEN=11" set res [target_compile "$srcfile" "$exefile" executable "$test_flags"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test compile" untested "$test" return } else { pass "$test compile" } foreach runtime [get_runtime_list] { if {$runtime != ""} { stap_run3 "$test ($runtime)" "$stpfile" -c "$exefile" \ -DMAXSTRINGLEN=11 --runtime=$runtime } else { stap_run3 $test "$stpfile" -c "$exefile" -DMAXSTRINGLEN=11 } } if { $verbose == 0 } { catch { exec rm -f $exefile } } systemtap-2.3/testsuite/systemtap.base/utf_user_trunc.stp000066400000000000000000000003351217430427200242040ustar00rootroot00000000000000probe process.function("main") { for (i = 0; s = $utf16_strings[i]; ++i) println("utf-16:", user_string_utf16(s)) for (i = 0; s = $utf32_strings[i]; ++i) println("utf-32:", user_string_utf32(s)) exit() } systemtap-2.3/testsuite/systemtap.base/utrace_p4.exp000066400000000000000000000220241217430427200230100ustar00rootroot00000000000000# Utrace compile (pass 4) tests. We can't run these as # testsuite/buildok tests, since if the current kernel has no utrace # support, those will fail - but not because of a problem with # systemtap's utrace probes (but because of the lack of utrace). So, # this test script checks for the existence of utrace in the kernel. # If utrace exists in the kernel, it tries some compile tests. If # utrace doesn't exist in the kernel, marks the tests as 'untested'. proc dyninst_xfails {test} { # Use setup_xfail for known bugs. # # (Note that tcl doesn't like comments directly inside the switch # statement, but comments can go in sub-blocks.) switch $test { "UTRACE_P4_03 (dyninst)" - "UTRACE_P4_03_pid (dyninst)" - "UTRACE_P4_04 (dyninst)" - "UTRACE_P4_04_pid (dyninst)" - "UTRACE_P4_08 (dyninst)" - "UTRACE_P4_09 (dyninst)" { # Use setup_xfail DYNINST for known # failures when running with the dyninst runtime (scripts # that use unimplemented features, like 'process.syscall' # probes). setup_xfail DYNINST *-*-* } } } # Initialize variables set begin_script {"probe process(\"/bin/ls\").begin { print(\"ls begin\") }"} set end_script {"probe process(\"/bin/ls\").end { print(\"ls end\") }"} set syscall_script {"probe process(\"/bin/ls\").syscall { printf(\"|%d\", \$syscall) }"} set syscall_parms_script {"probe process(\"/bin/ls\").syscall { printf(\"|%s\", \$\$parms) }"} set syscall_return_script {"probe process(\"/bin/ls\").syscall.return { printf(\"|%d\", \$syscall) }"} set thread_begin_script {"probe process(\"/bin/ls\").thread.begin { print(\"ls thread.begin\") }"} set thread_end_script {"probe process(\"/bin/ls\").thread.end { print(\"ls thread.end\") }"} set all_begin_script {"probe process.begin { print(\"begin\") }"} set pid_begin_script {"probe process(123).begin { print(\"123 begin\") }"} set pid_end_script {"probe process(123).end { print(\"123 end\") }"} set pid_syscall_script {"probe process(123).syscall { printf(\"|%d\", \$syscall) }"} set pid_parms_script {"probe process(123).syscall { printf(\"|%s\", \$\$parms) }"} set pid_syscall_return_script {"probe process(123).syscall.return { printf(\"|%d\", \$syscall) }"} set pid_thread_begin_script {"probe process(123).thread.begin { print(\"123 thread.begin\") }"} set pid_thread_end_script {"probe process(123).thread.end { print(\"123 thread.end\") }"} # # Do some utrace compile tests. # set TEST_NAME "UTRACE_P4_01" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a begin script using a path foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { lappend test "($runtime)" ${runtime}_xfails $test stap_compile $test 1 $begin_script --runtime=$runtime } else { stap_compile $test 1 $begin_script } } } set TEST_NAME "UTRACE_P4_01_pid" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a begin script using a pid foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { lappend test "($runtime)" ${runtime}_xfails $test stap_compile $test 1 $pid_begin_script --runtime=$runtime } else { stap_compile $test 1 $pid_begin_script } } } set TEST_NAME "UTRACE_P4_02" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a end script using a path foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { lappend test "($runtime)" ${runtime}_xfails $test stap_compile $test 1 $end_script --runtime=$runtime } else { stap_compile $test 1 $end_script } } } set TEST_NAME "UTRACE_P4_02_pid" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a end script using a pid foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { lappend test "($runtime)" ${runtime}_xfails $test stap_compile $test 1 $pid_end_script --runtime=$runtime } else { stap_compile $test 1 $pid_end_script } } } set TEST_NAME "UTRACE_P4_03" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a syscall script using a path foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { lappend test "($runtime)" ${runtime}_xfails $test #setup_xfail DYNINST *-*-* stap_compile $test 1 $syscall_script --runtime=$runtime } else { stap_compile $test 1 $syscall_script } } } set TEST_NAME "UTRACE_P4_03_pid" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a syscall script using a pid foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { lappend test "($runtime)" ${runtime}_xfails $test stap_compile $test 1 $pid_syscall_script --runtime=$runtime } else { stap_compile $test 1 $pid_syscall_script } } } set TEST_NAME "UTRACE_P4_04" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a syscall return script using a path foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { lappend test "($runtime)" ${runtime}_xfails $test stap_compile $test 1 $syscall_return_script --runtime=$runtime } else { stap_compile $test 1 $syscall_return_script } } } set TEST_NAME "UTRACE_P4_04_pid" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a syscall return script using a pid foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { lappend test "($runtime)" ${runtime}_xfails $test stap_compile $test 1 $pid_syscall_return_script --runtime=$runtime } else { stap_compile $test 1 $pid_syscall_return_script } } } set TEST_NAME "UTRACE_P4_05" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling an thread.begin script using a path foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { lappend test "($runtime)" ${runtime}_xfails $test stap_compile $test 1 $thread_begin_script --runtime=$runtime } else { stap_compile $test 1 $thread_begin_script } } } set TEST_NAME "UTRACE_P4_05_pid" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling an thread.begin script using a pid foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { lappend test "($runtime)" ${runtime}_xfails $test stap_compile $test 1 $pid_thread_begin_script --runtime=$runtime } else { stap_compile $test 1 $pid_thread_begin_script } } } set TEST_NAME "UTRACE_P4_06" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling an thread.end script using a path foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { lappend test "($runtime)" ${runtime}_xfails $test stap_compile $test 1 $thread_end_script --runtime=$runtime } else { stap_compile $test 1 $thread_end_script } } } set TEST_NAME "UTRACE_P4_06_pid" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling an thread.end script using a pid foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { lappend test "($runtime)" ${runtime}_xfails $test stap_compile $test 1 $pid_thread_end_script --runtime=$runtime } else { stap_compile $test 1 $pid_thread_end_script } } } set TEST_NAME "UTRACE_P4_07" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling an system-wide begin script foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { lappend test "($runtime)" ${runtime}_xfails $test stap_compile $test 1 $all_begin_script --runtime=$runtime } else { stap_compile $test 1 $all_begin_script } } } set TEST_NAME "UTRACE_P4_08" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a syscall parms script using a path foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { lappend test "($runtime)" ${runtime}_xfails $test stap_compile $test 1 $syscall_parms_script --runtime=$runtime } else { stap_compile $test 1 $syscall_parms_script } } } set TEST_NAME "UTRACE_P4_09" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a syscall parms script using a pid foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { lappend test "($runtime)" ${runtime}_xfails $test stap_compile $test 1 $pid_parms_script --runtime=$runtime } else { stap_compile $test 1 $pid_parms_script } } } systemtap-2.3/testsuite/systemtap.base/utrace_p5.exp000066400000000000000000000221371217430427200230160ustar00rootroot00000000000000# Utrace run (pass 5) tests. # Initialize variables set exepath "[pwd]/cat_[pid]" set multi_srcpath "$srcdir/systemtap.base/utrace_p5_multi.c" set multi_exepath "[pwd]/utrace_p5_multi_[pid]" set multi_flags "libs=-lpthread" set end_script { global end_probes_fired = 0 probe begin { printf("systemtap starting probe\n") } probe process("%s").end { end_probes_fired++ } probe end { printf("systemtap ending probe\n") printf("end probes = %%d\n", end_probes_fired) } } set end_script_output "end probes = 1\r\n" set begin_script { global begin_probes_fired = 0 probe begin { printf("systemtap starting probe\n") } probe process("%s").begin { begin_probes_fired++ } probe end { printf("systemtap ending probe\n") printf("begin probes = %%d\n", begin_probes_fired) } } set begin_script_output "begin probes = 1\r\n" set syscall_script { global syscall_probes_fired = 0 probe begin { printf("systemtap starting probe\n") } probe process("%s").syscall { syscall_probes_fired++ } probe end { printf("systemtap ending probe\n") if (syscall_probes_fired > 0) { printf("syscalls = %%d\n", syscall_probes_fired) } } } set syscall_script_output "syscalls = \\d+\r\n" set syscall_return_script { global syscall_return_probes_fired = 0 probe begin { printf("systemtap starting probe\n") } probe process("%s").syscall.return { syscall_return_probes_fired++ } probe end { printf("systemtap ending probe\n") if (syscall_return_probes_fired > 0) { printf("syscall_returns = %%d\n", syscall_return_probes_fired) } } } set syscall_return_script_output "syscall_returns = \\d+\r\n" set thread_begin_script { global thread_begin_probes_fired = 0 probe begin { printf("systemtap starting probe\n") } probe process("%s").thread.begin { thread_begin_probes_fired++ } probe end { printf("systemtap ending probe\n") if (thread_begin_probes_fired > 0) { printf("thread_begins = %%d\n", thread_begin_probes_fired) } } } set thread_begin_script_output "thread_begins = \\d+\r\n" set thread_end_script { global thread_end_probes_fired = 0 probe begin { printf("systemtap starting probe\n") } probe process("%s").thread.end { thread_end_probes_fired++ } probe end { printf("systemtap ending probe\n") if (thread_end_probes_fired > 0) { printf("thread_ends = %%d\n", thread_end_probes_fired) } } } set thread_end_script_output "thread_ends = \\d+\r\n" # Script that tests the bug 6841 fix. set bz6841_script { global proc,name probe begin { printf("systemtap starting probe\n") } probe process.syscall { proc[pid()] <<< 1 name[pid()] = execname() } probe end { printf("systemtap ending probe\n") foreach(p+ in proc) { printf("%s(%d) issues syscall %d times\n", name[p], p, @sum(proc[p])) } } } set bz6841_script_output ".+ issues syscall \\d+ times\r\n" set syscall_parms_script { global syscall_parms_string probe begin { printf("systemtap starting probe\n") } probe process.syscall { syscall_parms_string = $$parms exit() } probe end { printf("systemtap ending probe\n") printf("%s\n",syscall_parms_string) delete syscall_parms_string } } set syscall_parms_script_output "(.+arg\[1-6\]=0x\[0-9a-f\]+)+\r\n" # Set up our own copy of /bin/cat, to make testing for a particular # executable easy. We can't use 'ln' here, since we might be creating # a cross-device link. We can't use 'ln -s' here, since the kernel # resolves the symbolic link and reports that /bin/cat is being # exec'ed (instead of our local copy). if {[catch {exec cp /bin/cat $exepath} res]} { fail "unable to copy /bin/cat: $res" return } # "load" generation function for stap_run. It spawns our own copy of # /bin/cat, waits 5 seconds, then kills it. proc run_cat_5_sec {} { global exepath spawn $exepath set exe_id $spawn_id after 5000; exec kill -INT -[exp_pid -i $exe_id] catch {close -i $exe_id} catch {wait -i $exe_id} return 0; } # Compile our multi-threaded test program. set res [target_compile $multi_srcpath $multi_exepath executable $multi_flags] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile $multi_srcpath" return } # "load" generation function for stap_run. It spawns our # multi-threaded test program and waits for it to finish. proc run_utrace_p5_multi {} { global multi_exepath if {[catch {exec $multi_exepath} res]} { verbose "unable to run $multi_exepath: $res" } return 0; } set TEST_NAME "UTRACE_P5_01" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" } else { set script [format $end_script $exepath] stap_run $TEST_NAME run_cat_5_sec $end_script_output -e $script } set TEST_NAME "UTRACE_P5_01_cmd" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" } else { set script [format $end_script $exepath] foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { set test "${test}_${runtime}" stap_run $test wait_5_secs $end_script_output \ -e $script --runtime=$runtime -c "$exepath /dev/null" } else { stap_run $test wait_5_secs $end_script_output \ -e $script -c "$exepath /dev/null" } } } set TEST_NAME "UTRACE_P5_02" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" } else { set script [format $begin_script $exepath] stap_run $TEST_NAME run_cat_5_sec $begin_script_output -e $script } set TEST_NAME "UTRACE_P5_02_cmd" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" } else { set script [format $begin_script $exepath] foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { set test "${test}_${runtime}" stap_run $test wait_5_secs $begin_script_output \ -e $script --runtime=$runtime -c "$exepath /dev/null" } else { stap_run $test wait_5_secs $begin_script_output \ -e $script -c "$exepath /dev/null" } } } set TEST_NAME "UTRACE_P5_03" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" } else { set script [format $syscall_script $exepath] stap_run $TEST_NAME run_cat_5_sec $syscall_script_output -e $script } set TEST_NAME "UTRACE_P5_04" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" } else { set script [format $syscall_return_script $exepath] stap_run $TEST_NAME run_cat_5_sec $syscall_return_script_output -e $script } set TEST_NAME "UTRACE_P5_05" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" } else { set script [format $thread_begin_script $multi_exepath] stap_run $TEST_NAME run_utrace_p5_multi $thread_begin_script_output \ -e $script } set TEST_NAME "UTRACE_P5_05_cmd" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" } else { set script [format $thread_begin_script $multi_exepath] foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { set test "${test}_${runtime}" stap_run $test wait_5_secs $thread_begin_script_output \ -e $script --runtime=$runtime -c $multi_exepath } else { stap_run $test wait_5_secs $thread_begin_script_output \ -e $script -c $multi_exepath } } } set TEST_NAME "UTRACE_P5_06" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" } else { set script [format $thread_end_script $multi_exepath] stap_run $TEST_NAME run_utrace_p5_multi $thread_end_script_output \ -e $script } set TEST_NAME "UTRACE_P5_06_cmd" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" } else { set script [format $thread_end_script $multi_exepath] foreach runtime [get_runtime_list] { set test "$TEST_NAME" if {$runtime != ""} { set test "${test}_${runtime}" stap_run $test wait_5_secs $thread_end_script_output \ -e $script --runtime=$runtime -c $multi_exepath } else { stap_run $test wait_5_secs $thread_end_script_output \ -e $script -c $multi_exepath } } } set TEST_NAME "UTRACE_P5_07" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" } else { stap_run $TEST_NAME run_utrace_p5_multi $bz6841_script_output \ -e $bz6841_script } set TEST_NAME "UTRACE_P5_08" if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" } else { set script [format $syscall_parms_script "%s"] stap_run $TEST_NAME no_load $syscall_parms_script_output -e $script } # Cleanup exec rm -f $exepath $multi_exepath systemtap-2.3/testsuite/systemtap.base/utrace_p5_multi.c000066400000000000000000000017731217430427200236610ustar00rootroot00000000000000#include #include #include #include #include #include void *thread_function( void *ptr ); struct thread_data { int tnum; }; int main() { pthread_t thread1, thread2; int iret1, iret2; /* Create independent threads each of which will execute function */ struct thread_data t1 = { 1 }; struct thread_data t2 = { 2 }; iret1 = pthread_create(&thread1, NULL, thread_function, (void*) &t1); iret2 = pthread_create(&thread2, NULL, thread_function, (void*) &t2); /* Wait till threads are complete before main continues. Unless we * wait we run the risk of executing an exit which will terminate * the process and all threads before the threads have * completed. */ pthread_join(thread1, NULL); pthread_join(thread2, NULL); exit(0); } void *thread_function(void *ptr) { struct thread_data *td = ptr; if (td->tnum == 1) { int fd = open("/dev/null", O_RDONLY); close(fd); } } systemtap-2.3/testsuite/systemtap.base/utrace_syscall_args.c000066400000000000000000000034601217430427200246040ustar00rootroot00000000000000#include #include #include #include #include #include /* For SYS_xxx definitions */ int main() { int fd, ret; struct stat fs; void *r; int rc; /* create a file with something in it */ fd = open("foobar", O_WRONLY|O_CREAT|O_TRUNC, 0600); lseek(fd, 1024, SEEK_SET); write(fd, "abcdef", 6); close(fd); fd = open("foobar", O_RDONLY); /* stat for file size */ ret = fstat(fd, &fs); /* mmap file file, then unmap it. */ r = mmap(NULL, fs.st_size, PROT_READ, MAP_SHARED, fd, 0); if (r != MAP_FAILED) munmap(r, fs.st_size); close(fd); /* OK, try some system calls to see if we get the arguments * correctly. */ #if (__LONG_MAX__ > __INT_MAX__) rc = syscall (__NR_dup, (unsigned long)-12345, (unsigned long)0xffffffffffffffff, (unsigned long)0xa5a5a5a5a5a5a5a5, (unsigned long)0xf0f0f0f0f0f0f0f0, (unsigned long)0x5a5a5a5a5a5a5a5a, (unsigned long)0xe38e38e38e38e38e); #else rc = syscall (__NR_dup, (unsigned long)-12345, (unsigned long)0xffffffff, (unsigned long)0xa5a5a5a5, (unsigned long)0xf0f0f0f0, (unsigned long)0x5a5a5a5a, (unsigned long)0xe38e38e3); #endif #if (__LONG_MAX__ > __INT_MAX__) rc = syscall ((unsigned long)-1, (unsigned long)0x1c71c71c71c71c71, (unsigned long)0x0f0f0f0f0f0f0f0f, (unsigned long)0xdb6db6db6db6db6d, (unsigned long)0x2492492492492492, (unsigned long)0xad6b5ad6b5ad6b5a, (unsigned long)0xdef7ddef7ddef7dd); #else rc = syscall ((unsigned long)-1, (unsigned long)0x1c71c71c, (unsigned long)0x0f0f0f0f, (unsigned long)0xdb6db6db, (unsigned long)0x24924924, (unsigned long)0xad6b5ad6, (unsigned long)0xdef7ddef); #endif return 0; } systemtap-2.3/testsuite/systemtap.base/utrace_syscall_args.exp000066400000000000000000000053731217430427200251630ustar00rootroot00000000000000# Utrace system call argument tests. set flags "" set srcpath "$srcdir/$subdir/utrace_syscall_args.c" set exepath "[pwd]/utrace_syscall_args" set stppath "$srcdir/$subdir/utrace_syscall_args.stp" set output_string "mmap\\(\[0-9\]+\\)\\(0x\[0-9a-f]+, 0x\[0-9a-f]+, 0x\[0-9a-f]+, 0x\[0-9a-f]+, 0x\[0-9a-f]+, 0x\[0-9a-f]+\\) = 0x\[0-9a-f]+\r\nmunmap\\(\[0-9\]+\\)\\(0x\[0-9a-f]+, 0x\[0-9a-f]+\\) = 0x\[0-9a-f]+\r\nclose\\(\[0-9\]+\\)\\(0x\[0-9a-f]+\\) = 0x\[0-9a-f]+\r\ndup\\(\[0-9\]+\\)\\(0x\[0-9a-f]+, 0x\[0-9a-f]+, 0x\[0-9a-f]+, 0x\[0-9a-f]+, 0x\[0-9a-f]+, 0x\[0-9a-f]+\\) = 0x\[0-9a-f]+\r\nbad_syscall\\(-?\[0-9\]+\\)\\(0x\[0-9a-f]+, 0x\[0-9a-f]+, 0x\[0-9a-f]+, 0x\[0-9a-f]+, 0x\[0-9a-f]+, 0x\[0-9a-f]+\\) = 0x\[0-9a-f]+\r\nsystemtap test success\r\n" # For first pass, force 64-bit compilation for 64-bit systems. Add # any other 64-bit architecture you want tested below. # # To find tcl's platform name for your machine, run the following: # echo "puts $::tcl_platform(machine)" | tclsh switch -regexp $::tcl_platform(machine) { ^ia64$ { set do_64_bit_pass 1 set flags "" } ^(x86_64|ppc64|s390x)$ { set do_64_bit_pass 1 set flags "additional_flags=-m64" } default { set do_64_bit_pass 0 } } if {$do_64_bit_pass} { set testname "64_BIT_UTRACE_SYSCALL_ARGS" if {![installtest_p]} { untested $testname; continue } if {![utrace_p]} { untested $testname; continue } send_log "Testing ${testname}\n" # Compile our test program. set res [target_compile $srcpath $exepath executable $flags] if { $res != "" } { verbose "target_compile for $exepath failed: $res" 2 send_log "$testname: unable to compile $srcpath\n" untested $testname return } # Run the test. stap_run $testname no_load $output_string -g $stppath -c $exepath catch {exec rm -f $exepath foobar} } # The second pass is for systems that support 32-bit executables # (either exclusively or in addition to 64-bit executables). set do_32_bit_pass 1 switch -regexp $::tcl_platform(machine) { ^(x86_64|ppc64)$ { set flags "additional_flags=-m32" } ^s390x$ { set flags "additional_flags=-m31" } ^ia64$ { set do_32_bit_pass 0 } } if {$do_32_bit_pass} { set testname "32_BIT_UTRACE_SYSCALL_ARGS" if {![installtest_p]} { untested $testname; continue } if {![utrace_p]} { untested $testname; continue } send_log "Testing ${testname}\n" # Compile our test program set res [target_compile $srcpath $exepath executable $flags] if { $res != "" } { verbose "target_compile for $exepath failed: $res" 2 send_log "$testname: unable to compile $srcpath\n" untested $testname return } stap_run $testname no_load $output_string -g $stppath -c $exepath catch {exec rm -f $exepath foobar} } systemtap-2.3/testsuite/systemtap.base/utrace_syscall_args.stp000066400000000000000000000266231217430427200251760ustar00rootroot00000000000000%{ #include "syscall.h" %} function mmap_syscall_no:long () %{ STAP_RETVALUE = MMAP_SYSCALL_NO(current); /* pure */ %} function mmap2_syscall_no:long () %{ STAP_RETVALUE = MMAP2_SYSCALL_NO(current); /* pure */ %} function munmap_syscall_no:long () %{ STAP_RETVALUE = MUNMAP_SYSCALL_NO(current); /* pure */ %} global syscalls_seen = 0 global failures = 0 global mmap_found = 0 global mmap_args[10] global munmap_found = 0 global munmap_args[10] global close_found = 0 global close_args[10] global dup_found = 0 global dup_args[10] global bad_syscall_found = 0 global bad_syscall_args[10] probe begin { printf("systemtap starting probe\n") } probe syscall.open { if (pid() == target() && filename == "\"foobar\"") { syscalls_seen += 1 } } probe process("utrace_syscall_args").syscall { if (syscalls_seen >= 2) { syscalls_seen += 1 # We skip the fstat() syscall, which is the 1st syscall after # the open() by not looking at 'syscalls_seen == 3'. if (syscalls_seen == 4 && ($syscall == mmap_syscall_no() || $syscall == mmap2_syscall_no())) { mmap_found = 1 mmap_args[0] = $syscall mmap_args[1] = $arg1 mmap_args[2] = $arg2 mmap_args[3] = $arg3 mmap_args[4] = $arg4 mmap_args[5] = $arg5 mmap_args[6] = $arg6 %(arch == "s390" && kernel_v < "2.6.33" %? # For s390, mmap was handled by arch-specific code in # kernels before 2.6.33 that got a structure pointer in # argument 1 that holds all the actual arguments. Handle # this. addr = mmap_args[1] if (! %{ _stp_is_comat_task() %}) { mmap_args[1] = user_long(&@cast(addr, "mmap_arg_struct")->addr) mmap_args[2] = user_long(&@cast(addr, "mmap_arg_struct")->len) mmap_args[3] = user_long(&@cast(addr, "mmap_arg_struct")->prot) mmap_args[4] = user_long(&@cast(addr, "mmap_arg_struct")->flags) mmap_args[5] = user_long(&@cast(addr, "mmap_arg_struct")->fd) mmap_args[6] = user_long(&@cast(addr, "mmap_arg_struct")->offset) } else { mmap_args[1] = user_int(&@cast(addr, "mmap_arg_struct_emu31")->addr) mmap_args[2] = user_int(&@cast(addr, "mmap_arg_struct_emu31")->len) mmap_args[3] = user_int(&@cast(addr, "mmap_arg_struct_emu31")->prot) mmap_args[4] = user_int(&@cast(addr, "mmap_arg_struct_emu31")->flags) mmap_args[5] = user_int(&@cast(addr, "mmap_arg_struct_emu31")->fd) mmap_args[6] = user_int(&@cast(addr, "mmap_arg_struct_emu31")->offset) } %) } else if (syscalls_seen == 5 && $syscall == munmap_syscall_no()) { munmap_found = 1 munmap_args[0] = $syscall munmap_args[1] = $arg1 munmap_args[2] = $arg2 } else if (syscalls_seen == 6) { close_found = 1 close_args[0] = $syscall close_args[1] = $arg1 } else if (syscalls_seen == 7) { dup_found = 1 dup_args[0] = $syscall dup_args[1] = $arg1 dup_args[2] = $arg2 dup_args[3] = $arg3 dup_args[4] = $arg4 dup_args[5] = $arg5 dup_args[6] = $arg6 } else if (syscalls_seen == 8) { bad_syscall_found = 1 bad_syscall_args[0] = $syscall bad_syscall_args[1] = $arg1 bad_syscall_args[2] = $arg2 bad_syscall_args[3] = $arg3 bad_syscall_args[4] = $arg4 bad_syscall_args[5] = $arg5 bad_syscall_args[6] = $arg6 } } } probe process("utrace_syscall_args").syscall.return { if (syscalls_seen >= 4) { if (syscalls_seen == 4) { mmap_args[7] = $return mmap_args[8] = $syscall } else if (syscalls_seen == 5) { munmap_args[3] = $return munmap_args[4] = $syscall } else if (syscalls_seen == 6) { close_args[2] = $return close_args[3] = $syscall } else if (syscalls_seen == 7) { dup_args[7] = $return dup_args[8] = $syscall } else if (syscalls_seen == 8) { bad_syscall_args[7] = $return bad_syscall_args[8] = $syscall syscalls_seen = 0 } } } probe end { printf("systemtap ending probe\n") # print mmap info if (mmap_found == 0) { printf("error: no mmap system call found\n") failures += 1 } else { printf("mmap(%d)(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) = 0x%x\n", mmap_args[0], mmap_args[1], mmap_args[2], mmap_args[3], mmap_args[4], mmap_args[5], mmap_args[6], mmap_args[7]) # Validate arguments. We can only check certain arguments. # It is possible that mmap's 'prot' and 'flags' arguments # could vary per platform, so we'll ignore them. if (mmap_args[1] != 0) { failures += 1 printf("mmap bad arg 1: 0x%x vs 0x0\n", mmap_args[1]) } if (mmap_args[2] != 0x406) { failures += 1 printf("mmap bad arg 2: 0x%x vs 0x406\n", mmap_args[2]) } if (mmap_args[6] != 0) { failures += 1 printf("mmap bad arg 6: 0x%x vs 0x0\n", mmap_args[6]) } # Validate syscall number if (mmap_args[0] != mmap_args[8]) { failures += 1 printf("mmap $syscall mismatch: %d vs. %d\n", mmap_args[0], mmap_args[8]) } } # print munmap info if (munmap_found == 0) { printf("error: no munmap system call found\n") failures += 1 } else if (munmap_found == 0 || mmap_found == 0) { printf("error: no munmap/mmap system call found\n") failures += 1 } else { printf("munmap(%d)(0x%x, 0x%x) = 0x%x\n", munmap_args[0], munmap_args[1], munmap_args[2], munmap_args[3]) # Validate arguments. munmap()'s first argument should be the # same as the mmap() return value. if (munmap_args[1] != mmap_args[7]) { failures += 1 printf("munmap bad arg 1: 0x%x vs 0x%x\n", munmap_args[1], mmap_args[7]) } if (munmap_args[2] != mmap_args[2]) { failures += 1 printf("munmap bad arg 2: 0x%x vs 0x%x\n", munmap_args[2], mmap_args[2]) } # Validate return value if (munmap_args[7] != 0) { failures += 1 printf("munmap bad return value: 0x%x vs 0x0\n", munmap_args[7]) } # Validate syscall number if (munmap_args[0] != munmap_args[4]) { failures += 1 printf("munmap $syscall mismatch: %d vs. %d\n", munmap_args[0], munmap_args[4]) } } # print close info if (close_found == 0) { printf("error: no close system call found\n") failures += 1 } else if (close_found == 1) { printf("close(%d)(0x%x) = 0x%x\n", close_args[0], close_args[1], close_args[2]) if (mmap_args[5] != close_args[1]) { failures += 1 printf("close bad arg 1: 0x%x vs 0x%x\n", close_args[1], mmap_args[5]) } # Validate syscall number if (close_args[0] != close_args[3]) { failures += 1 printf("close $syscall mismatch: %d vs. %d\n", close_args[0], close_args[3]) } } # print dup info if (dup_found == 0) { printf("error: no dup system call found\n") failures += 1 } else { printf("dup(%d)(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) = 0x%x\n", dup_args[0], dup_args[1], dup_args[2], dup_args[3], dup_args[4], dup_args[5], dup_args[6], dup_args[7]) # Validate arguments - handle 32-bit vs. 64-bit. if ((dup_args[1] & 0xffffffff00000000) != 0) { if (dup_args[1] != 0xffffffffffffcfc7) { failures += 1 printf("dup bad arg 1: 0x%x vs 0xffffffffffffcfc7\n", dup_args[1]) } if (dup_args[2] != 0xffffffffffffffff) { failures += 1 printf("dup bad arg 2: 0x%x vs 0xffffffffffffffff\n", dup_args[2]) } if (dup_args[3] != 0xa5a5a5a5a5a5a5a5) { failures += 1 printf("dup bad arg 3: 0x%x vs 0xa5a5a5a5a5a5a5a5\n", dup_args[3]) } if (dup_args[4] != 0xf0f0f0f0f0f0f0f0) { failures += 1 printf("dup bad arg 4: 0x%x vs 0xf0f0f0f0f0f0f0f0\n", dup_args[4]) } if (dup_args[5] != 0x5a5a5a5a5a5a5a5a) { failures += 1 printf("dup bad arg 5: 0x%x vs 0x5a5a5a5a5a5a5a5a\n", dup_args[5]) } if (dup_args[6] != 0xe38e38e38e38e38e) { failures += 1 printf("dup bad arg 6: 0x%x vs 0xe38e38e38e38d38e\n", dup_args[6]) } } else { if (dup_args[1] != 0xffffcfc7) { failures += 1 printf("dup bad arg 1: 0x%x vs 0xffffcfc7\n", dup_args[1]) } if (dup_args[2] != 0xffffffff) { failures += 1 printf("dup bad arg 2: 0x%x vs 0xffffffff\n", dup_args[2]) } if (dup_args[3] != 0xa5a5a5a5) { failures += 1 printf("dup bad arg 3: 0x%x vs 0xa5a5a5a5\n", dup_args[3]) } if (dup_args[4] != 0xf0f0f0f0) { failures += 4 printf("dup bad arg 4: 0x%x vs 0xf0f0f0f0\n", dup_args[4]) } if (dup_args[5] != 0x5a5a5a5a) { failures += 1 printf("dup bad arg 5: 0x%x vs 0x5a5a5a5a\n", dup_args[5]) } if (dup_args[6] != 0xe38e38e3) { failures += 1 printf("dup bad arg 6: 0x%x vs 0xe38e38e3\n", dup_args[6]) } } # Validate syscall number if (dup_args[0] != dup_args[8]) { failures += 1 printf("dup $syscall mismatch: %d vs. %d\n", dup_args[0], dup_args[8]) } } # print bad_syscall info if (bad_syscall_found == 0) { printf("error: no bad_syscall system call found\n") failures += 1 } else { printf("bad_syscall(%d)(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) = 0x%x\n", bad_syscall_args[0], bad_syscall_args[1], bad_syscall_args[2], bad_syscall_args[3], bad_syscall_args[4], bad_syscall_args[5], bad_syscall_args[6], bad_syscall_args[7]) # Validate arguments - handle 32-bit vs. 64-bit. if (bad_syscall_args[1] > 0xffffffff) { if (bad_syscall_args[1] != 0x1c71c71c71c71c71) { failures += 1 printf("bad_syscall bad arg 1: 0x%x vs 0x1c71c71c71c71c71\n", bad_syscall_args[1]) } if (bad_syscall_args[2] != 0x0f0f0f0f0f0f0f0f) { failures += 1 printf("bad_syscall bad arg 2: 0x%x vs 0x0f0f0f0f0f0f0f0f\n", bad_syscall_args[2]) } if (bad_syscall_args[3] != 0xdb6db6db6db6db6d) { failures += 1 printf("bad_syscall bad arg 3: 0x%x vs 0xdb6db6db6db6db6d\n", bad_syscall_args[3]) } if (bad_syscall_args[4] != 0x2492492492492492) { failures += 1 printf("bad_syscall bad arg 4: 0x%x vs 0x2492492492492492\n", bad_syscall_args[4]) } if (bad_syscall_args[5] != 0xad6b5ad6b5ad6b5a) { failures += 1 printf("bad_syscall bad arg 5: 0x%x vs 0xad6b5ad6b5ad6b5a\n", bad_syscall_args[5]) } if (bad_syscall_args[6] != 0xdef7ddef7ddef7dd) { failures += 1 printf("bad_syscall bad arg 6: 0x%x vs 0xdef7ddef7ddef7dd\n", bad_syscall_args[6]) } } else { if (bad_syscall_args[1] != 0x1c71c71c) { failures += 1 printf("bad_syscall bad arg 1: 0x%x vs 0x1c71c71c\n", bad_syscall_args[1]) } if (bad_syscall_args[2] != 0x0f0f0f0f) { failures += 1 printf("bad_syscall bad arg 2: 0x%x vs 0x0f0f0f0f\n", bad_syscall_args[2]) } if (bad_syscall_args[3] != 0xdb6db6db) { failures += 1 printf("bad_syscall bad arg 3: 0x%x vs 0xdb6db6db\n", bad_syscall_args[3]) } if (bad_syscall_args[4] != 0x24924924) { failures += 4 printf("bad_syscall bad arg 4: 0x%x vs 0x24924924\n", bad_syscall_args[4]) } if (bad_syscall_args[5] != 0xad6b5ad6) { failures += 1 printf("bad_syscall bad arg 5: 0x%x vs 0xad6b5ad6\n", bad_syscall_args[5]) } if (bad_syscall_args[6] != 0xdef7ddef) { failures += 1 printf("bad_syscall bad arg 6: 0x%x vs 0xdef7ddef\n", bad_syscall_args[6]) } } # Validate syscall number if (bad_syscall_args[0] != bad_syscall_args[8]) { failures += 1 printf("bad_syscall $syscall mismatch: %d vs. %d\n", bad_syscall_args[0], bad_syscall_args[8]) } } if (failures == 0) { printf("systemtap test success\n") } else { printf("systemtap test failure\n") } } systemtap-2.3/testsuite/systemtap.base/vars.exp000066400000000000000000000025151217430427200221000ustar00rootroot00000000000000# Script for testing $$vars, $$parms, $$locals # # This works by grep'ing for the format strings produced in pass-3, then # comparing that $$vars is the same as $$parms + $$locals. # # NB: With PR3217 compiled-printf code, we can't tell as easily what was # generated. However, there's still the ifdef'ed STP_LEGACY_PRINT code which # has the format string we care about here. If that ever goes away, we'll # probably have to fall back to comparing pass-2 output instead. set test "vars" # grab C statement that $$vars yields set cmd [concat stap -p3 -e {"probe kernel.statement(\"bio_copy_user@fs/bio.c+1\") \{print (\$\$vars)\}"} | grep {"_stp_snprintf.*="} | sed -e {"s/^.*MAXSTRINGLEN, \"//"} -e {s/\".*$//}] catch {eval exec $cmd} vars # grab C statement that $$parms yields set cmd [regsub "vars" $cmd "parms"] catch {eval exec $cmd} parms # grab C statement that $$locals yields set cmd [regsub "parms" $cmd "locals"] catch {eval exec $cmd} locals # syntax check of $$vars C statement set vars_ok [regexp "(\[a-z_\]+=%#llx *)+" $vars] if {!$vars_ok} { fail "$test" } else { pass "$test" } # $$vars should be equivalent to $$parms + $$locals if {![string equal $vars "$parms $locals"]} { fail "$test parms/locals" verbose -log "vars=$vars=" verbose -log "rest=$parms $locals=" } else { pass "$test parms/locals" } systemtap-2.3/testsuite/systemtap.base/vma_vdso.c000066400000000000000000000006631217430427200223730ustar00rootroot00000000000000#define _GNU_SOURCE #include #include #include int main (int argc, char *argv[]) { int res; struct timespec ts; uid_t uid1, uid2; /* Give an invalid clockid_t on purpose so the vdso has to call through to the kernel syscall. */ res = clock_gettime(6667, &ts); uid1 = syscall(SYS_getuid); uid2 = getuid(); return res + 1 + uid1 - uid2; /* -1 from clock_gettime + 1 == 0 */ } systemtap-2.3/testsuite/systemtap.base/vma_vdso.exp000066400000000000000000000026621217430427200227460ustar00rootroot00000000000000# Make sure however we entered a syscall, we know the calling module name. # the task finder vma tracker should have recorded it. set test "vma_vdso" # Expect the following three syscalls set ::result_string {clock_gettime getuid getuid} # Force 64-bit (when necessary) to be sure of what we're testing. switch -regexp $::tcl_platform(machine) { {^(x86_64|ppc64|s390x)$} { set arches [list "-m64"] } default { set arches [list "default"] } } # Test 32-on-64 when available switch -regexp $::tcl_platform(machine) { {^(x86_64|ppc64)$} { lappend arches "-m32" } {^s390x$} { lappend arches "-m31" } } foreach arch $arches { verbose "testing $test $arch" set test_flags "additional_flags=-g" set test_flags "$test_flags additional_flags=-lrt" if {$arch != "default"} { set test_flags "$test_flags additional_flags=$arch" } set res [target_compile $srcdir/$subdir/$test.c ${test}${arch}.exe executable "$test_flags"] if { $res != "" } { verbose "target_compile ${test}${arch} failed: $res" 2 fail "${test}.c compile ${arch}" untested "${test}${arch}" return } else { pass "${test}.c compile ${arch}" } # Test only when we are running an install test (can execute) if {[installtest_p]} { stap_run3 ${test}${arch} $srcdir/$subdir/$test.stp ./${test}${arch}.exe -c ./${test}${arch}.exe } else { untested "${test}${arch}" } } systemtap-2.3/testsuite/systemtap.base/vma_vdso.stp000066400000000000000000000010601217430427200227470ustar00rootroot00000000000000/* Make sure however we entered a syscall, we know the calling module name. The The task finder vma tracker should have recorded it. */ probe syscall.clock_gettime, syscall.getuid { if (target() == pid()) { try { // Bogus if-statement so that there is no elision // (This happens because umodname() is marked as /* pure */) if (umodname(uaddr()) == "") log(name) else log(name) } catch { printf("%s@%x unknown\n", name, uaddr()); } } } systemtap-2.3/testsuite/systemtap.base/vta-test.c000066400000000000000000000016371217430427200223260ustar00rootroot00000000000000#include #include "sys/sdt.h" struct ci { int i; }; struct cui { unsigned int i; }; struct cull { unsigned long long i; }; int t1 (int i) { int a[] = { 17, 23 }; struct ci c; c.i = i; srandom (c.i); i = 6; c.i = i; srandom (c.i); STAP_PROBE(test, t1); c.i = i; srandom (c.i + 4); return a[0] + a[1]; } int t2 (unsigned int i) { int a[] = { 17, 23 }; struct cui c; c.i = i; srandom (c.i); i = 0xdeadbeef; c.i = i; srandom (c.i); STAP_PROBE(test, t2); c.i = i; srandom (c.i + 4); return a[0] + a[1]; } int t3 (unsigned long long i) { int a[] = { 17, 23 }; struct cull c; c.i = i; srandom (c.i); i = 0xdeadbeef87654321LL; c.i = i; srandom (c.i); STAP_PROBE(test, t3); c.i = i; srandom (c.i + 4); return a[0] + a[1]; } int main (int argc, char **argv) { int i1 = t1 (42); int i2 = t2 (42); int i3 = t3 (42); return 2*i1 - i2 - i3; } systemtap-2.3/testsuite/systemtap.base/vta-test.exp000066400000000000000000000037371217430427200227030ustar00rootroot00000000000000set test "vta-test" set ::result_string {a: {17, 23} i: 0x6 a: {17, 23} i: 0xdeadbeef a: {17, 23} i: 0xdeadbeef87654321} proc dyninst_kfails {index} { # The dyninst runtime isn't multi-arch, it only works on the # native architecture. PR14490. if {! [all_compile_flag_native_p $index]} { setup_kfail 14490 "*-*-*" } } for {set i 0} {$i < [all_compile_flags]} {incr i} { set extra_flag [all_compile_flag $i] set extra_name [all_compile_flag_name $i] verbose "testing vta-$extra_name" set test_flags "additional_flags=-g" set test_flags "$test_flags [sdt_includes]" set test_flags "$test_flags $extra_flag" set res [target_compile $srcdir/$subdir/$test.c $test-$extra_name.exe executable "$test_flags"] if { $res != "" } { verbose "target_compile $test-$extra_name failed: $res" 2 fail "$test.c compile $extra_name" untested "$test-$extra_name" continue } else { pass "$test.c compile $extra_name" } # Test only when we are running an install test (can execute) and # when gcc vta generated DW_OP_{stack|implicit}_values for us. See # PR10417. if {[installtest_p]} { # See if GCC produce DW_OP_implicit_value and/or # DW_OP_stack_value for us. set regexp {[stack|implicit]_value} if {![catch {exec readelf --debug-dump=loc $test-$extra_name.exe \ | egrep "$regexp"}]} { foreach runtime [get_runtime_list] { if {$runtime != ""} { if { [info procs ${runtime}_kfails] ne "" } { ${runtime}_kfails $i } stap_run3 $test-$extra_name-$runtime \ $srcdir/$subdir/$test.stp ./$test-$extra_name.exe \ -c ./$test-$extra_name.exe --runtime=$runtime } elseif {[uprobes_p]} { stap_run3 $test-$extra_name $srcdir/$subdir/$test.stp \ ./$test-$extra_name.exe -c ./$test-$extra_name.exe } else { untested "$test-$extra_name" } } } else { untested "$test-$extra_name (no-gcc-vta)" } } else { untested "$test-$extra_name" } catch {exec rm -f $test-$extra_name.exe} } systemtap-2.3/testsuite/systemtap.base/vta-test.stp000066400000000000000000000001501217430427200226770ustar00rootroot00000000000000probe process(@1).mark("t?") { printf("a: {%d, %d}\n", $a[0], $a[1]); printf("i: 0x%x\n", $c->i); } systemtap-2.3/testsuite/systemtap.base/wakeup.exp000066400000000000000000000015171217430427200224220ustar00rootroot00000000000000set test "wakeup" if {![installtest_p]} {untested $test; return} # There have been issues with kernel probes put into the wake_up path. # see http://sourceware.org/ml/systemtap/2011-q3/msg00163.html spawn stap -DMAXERRORS=8 $srcdir/$subdir/$test.stp -c {ls -laR /dev/* /proc/* > /dev/null 2>&1} set systems 0 set warns 0 set errors 0 set prints 0 expect { -timeout 180 -re {^sleeping\r\n} { incr systems; exp_continue } -re {^WARNING: wake_up\r\n} { incr warns; exp_continue } -re {^ERROR: wake_down\r\n} { incr errors; exp_continue } -re {^count: 25\r\n} { incr prints; exp_continue } timeout { fail "$test (timeout)" } eof { } } wait # WARNINGs get collapsed, so only 1 expected. if {$systems == 8 && $warns == 1 && $errors == 8 && $prints == 1} { pass "$test" } { fail "$test ($systems,$warns,$errors,$prints)" } systemtap-2.3/testsuite/systemtap.base/wakeup.stp000066400000000000000000000004171217430427200224320ustar00rootroot00000000000000global count; probe kernel.function("__wake_up_common") { count++ if (count <= 8) { system("echo sleeping") } else if (count <= 16) { warn("wake_up") } else if (count <= 24) { error("wake_down") } else { printf("count: %d\n", count); exit() } } systemtap-2.3/testsuite/systemtap.base/warn_overflow.exp000066400000000000000000000020531217430427200240140ustar00rootroot00000000000000# Test proper shutdown while "overflowing" warning and system messages set test "warn_overflow" if {![installtest_p]} { untested $test; return } # -vv suppresses WARNING duplication filtering in staprun. # The syscall.* probe handlers try to overflow the cmd message buffers # which might take some time, so add -DMAXSKIPPED=9999 to not error # out because some probes take too long. spawn stap -vv -DMAXSKIPPED=9999 $srcdir/$subdir/$test.stp set ok 0 set warn 0 expect { -timeout 180 -re {^WARNING: too many pending \([a-z]+\) messages\r\n} { incr warn; exp_continue } -re {^stap_begin\r\n} { incr ok; exp_continue; } -re {^stap_syscall\r\n} { incr ok; exp_continue; } -re {^stap_end\r\n} { incr ok; exp_continue; } -re {^[^\r\n]*\r\n} { exp_continue } timeout { fail "$test (timeout)" } eof { } } wait # There can be more than 3 "too many pending" messages in case # stap recovered quick enough and then overflowed again. if {$ok == 3 && $warn >= 3} { pass "$test ($ok,$warn)" } { fail "$test ($ok,$warn)" } systemtap-2.3/testsuite/systemtap.base/warn_overflow.stp000066400000000000000000000003651217430427200240320ustar00rootroot00000000000000global i; probe begin {while (++i < 128) warn("begin..."); log("stap_begin");} probe syscall.* {system("echo syscall: " . name); if (++i == 256) { log("stap_syscall"); exit(); }} probe end {while (--i > 0) warn("end..."); log("stap_end");} systemtap-2.3/testsuite/systemtap.base/warnings.exp000066400000000000000000000006641217430427200227600ustar00rootroot00000000000000set test "warnings" spawn stap -p4 $srcdir/$subdir/warnings.stp set ok 0 expect { -timeout 180 -re {^WARNING:[^\r\n]*\r\n} { incr ok; exp_continue } -re {^[^\r\n]*.ko\r\n} { incr ok; exp_continue } -re {^[^\r]*source:[^\r\n]*\r\n} {exp_continue} -re {^[^\r\n]*\^[^\r\n]*\r\n} {exp_continue} timeout { fail "$test (timeout)" } eof { } } wait if {$ok == 14} { pass $test } else { fail "$test ($ok)" } systemtap-2.3/testsuite/systemtap.base/warnings.stp000066400000000000000000000010071217430427200227620ustar00rootroot00000000000000# PR 1119 global elide_me1 function elide_me2 () {} function foo:long () { elide_me3 = 1 } function bar() { print(elide+me1) ; ; ; } probe never { elide_me4 = 1; (elide_me5+5); print (foo()) } probe never { print(elide+me1) bar () } # PR 6611 probe probea = kernel.statement("bio_init@fs/bio.c:*") { printf("%d", funca(2)); elide_me6="foo" } probe probea { printf("%d", funcb(2,3)); printf("%s",var) } function funcb(a:long, b:long) {return a + b} function funca(a:long) {a=b; elide_me7=1; return a} systemtap-2.3/testsuite/systemtap.base/warnings2.exp000066400000000000000000000037551217430427200230460ustar00rootroot00000000000000if {! [installtest_p]} { return } foreach runtime [get_runtime_list] { set test "warnings2 default" if {$runtime != ""} { lappend test "($runtime)" spawn stap --runtime=$runtime \ -e {probe begin {warn ("1") warn ("2") warn ("1") exit ()}} } else { spawn stap -e {probe begin {warn ("1") warn ("2") warn ("1") exit ()}} } set ok1 0 set ok2 0 expect { -timeout 30 -re {^WARNING: 1\r\n} { incr ok1; exp_continue } -re {^WARNING: 2\r\n} { incr ok2; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch { close }; catch { wait } if {$ok1 == 1 && $ok2 == 1} { pass $test } else { fail "$test ($ok1 $ok2)" } set test "warnings2 -w" if {$runtime != ""} { lappend test "($runtime)" if { [info procs ${runtime}_kfails] ne "" } { ${runtime}_kfails $i } spawn stap --runtime=$runtime -w \ -e {probe begin {warn ("1") warn ("2") warn ("1") exit ()}} } else { spawn stap -w \ -e {probe begin {warn ("1") warn ("2") warn ("1") exit ()}} } set ok1 0 set ok2 0 expect { -timeout 30 -re {^WARNING: 1\r\n} { incr ok1; exp_continue } -re {^WARNING: 2\r\n} { incr ok2; exp_continue } timeout { fail "$test (timeout)" } eof { } } catch { close }; catch { wait } if {$ok1 == 0 && $ok2 == 0} { pass $test } else { fail "$test ($ok1 $ok2)" } set test "warnings2 -v" if {$runtime != ""} { lappend test "($runtime)" spawn stap --runtime=$runtime -vv \ -e {probe begin {warn ("1") warn ("2") warn ("1") exit ()}} } else { spawn stap -vv \ -e {probe begin {warn ("1") warn ("2") warn ("1") exit ()}} } set ok1 0 set ok2 0 expect { -timeout 30 -re {^WARNING: 1\r\n} { incr ok1; exp_continue } -re {^WARNING: 2\r\n} { incr ok2; exp_continue } -re {^[^\r\n]*\r\n} { exp_continue } timeout { fail "$test (timeout)" } eof { } } catch { close }; catch { wait } if {$ok1 == 2 && $ok2 == 1} { pass $test } else { fail "$test ($ok1 $ok2)" } } systemtap-2.3/testsuite/systemtap.base/x86_gs.exp000066400000000000000000000005561217430427200222460ustar00rootroot00000000000000set test "x86_gs" if {![installtest_p]} { untested $test; return } set arch [exec uname -i] if {$arch!="i386"} { untested $test; return } spawn stap $srcdir/$subdir/x86_gs.stp expect { -timeout 60 -re "0\r\n" { pass $test } -re "140\r\n" { pass $test } eof { fail $test } timeout { fail "$test unexpected timeout" } } catch {close}; catch {wait} systemtap-2.3/testsuite/systemtap.base/x86_gs.stp000077500000000000000000000002721217430427200222560ustar00rootroot00000000000000#! stap # test x86 gs register probe begin { if (!_stp_regs_registered) _stp_register_regs() printf("%d\n",test_x86_gs() * 100 + _reg_offsets["gs"]) /* 0 or 140 */ exit() } systemtap-2.3/testsuite/systemtap.clone/000077500000000000000000000000001217430427200205725ustar00rootroot00000000000000systemtap-2.3/testsuite/systemtap.clone/Makefile.clone000066400000000000000000000005421217430427200233320ustar00rootroot00000000000000CFLAGS += -g -O2 DTRACE := dtrace OBJS := dtrace_clone.o dtrace_clone_probes.o TARGETS := dtrace_clone BUILT_SOURCES := dtrace_clone_probes.h all: $(TARGETS) dtrace_clone: $(OBJS) dtrace_clone.c: dtrace_clone_probes.h %.h: %.d $(DTRACE) -C -h -s $< -o $@ %.o: %.d $(DTRACE) -C -G -s $< -o $@ clean: rm -f $(OBJS) $(TARGETS) $(BUILT_SOURCES) systemtap-2.3/testsuite/systemtap.clone/Makefile.fork_exec000066400000000000000000000011121217430427200241710ustar00rootroot00000000000000CFLAGS += -g -O2 DTRACE := dtrace PARENT_OBJS := dtrace_fork_parent.o dtrace_fork_parent_probes.o CHILD_OBJS := dtrace_child.o dtrace_child_probes.o TARGETS := dtrace_fork_parent dtrace_child BUILT_SOURCES := dtrace_fork_parent_probes.h dtrace_child_probes.h all: $(TARGETS) dtrace_fork_parent: $(PARENT_OBJS) dtrace_fork_parent.c: dtrace_fork_parent_probes.h dtrace_child: $(CHILD_OBJS) dtrace_child.c: dtrace_child_probes.h %.h: %.d $(DTRACE) -C -h -s $< -o $@ %.o: %.d $(DTRACE) -C -G -s $< -o $@ clean: rm -f $(PARENT_OBJS) $(CHILD_OBJS) $(TARGETS) $(BUILT_SOURCES) systemtap-2.3/testsuite/systemtap.clone/Makefile.probe_by_pid000066400000000000000000000002441217430427200246660ustar00rootroot00000000000000override CFLAGS += -g -O2 OBJS := probe_by_pid.o TARGETS := probe_by_pid all: $(TARGETS) $(TARGETS): $(OBJS) clean: rm -f $(OBJS) $(TARGETS) $(BUILT_SOURCES) systemtap-2.3/testsuite/systemtap.clone/Makefile.vfork_exec000066400000000000000000000011211217430427200243570ustar00rootroot00000000000000CFLAGS += -g -O2 DTRACE := dtrace PARENT_OBJS := dtrace_vfork_parent.o dtrace_vfork_parent_probes.o CHILD_OBJS := dtrace_child.o dtrace_child_probes.o TARGETS := dtrace_vfork_parent dtrace_child BUILT_SOURCES := dtrace_vfork_parent_probes.h dtrace_child_probes.h all: $(TARGETS) dtrace_vfork_parent: $(PARENT_OBJS) dtrace_vfork_parent.c: dtrace_vfork_parent_probes.h dtrace_child: $(CHILD_OBJS) dtrace_child.c: dtrace_child_probes.h %.h: %.d $(DTRACE) -C -h -s $< -o $@ %.o: %.d $(DTRACE) -C -G -s $< -o $@ clean: rm -f $(PARENT_OBJS) $(CHILD_OBJS) $(TARGETS) $(BUILT_SOURCES) systemtap-2.3/testsuite/systemtap.clone/dtrace_child.c000066400000000000000000000012121217430427200233370ustar00rootroot00000000000000/* Systemtap test case * Copyright (C) 2010, Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. */ #include #include #include #include "dtrace_child_probes.h" #if !defined(USE_SEMAPHORES) #undef CHILD_MAIN_ENABLED #define CHILD_MAIN_ENABLED() (1) #endif int main(int argc, char **argv) { if (CHILD_MAIN_ENABLED()) { CHILD_MAIN(getpid()); } return 0; } systemtap-2.3/testsuite/systemtap.clone/dtrace_child_probes.d000066400000000000000000000000551217430427200247160ustar00rootroot00000000000000provider child { probe main(pid_t pid); }; systemtap-2.3/testsuite/systemtap.clone/dtrace_clone.c000066400000000000000000000063631217430427200233700ustar00rootroot00000000000000/* Systemtap test case * Copyright (C) 2010, Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include "dtrace_clone_probes.h" #if !defined(CLONE_NEWPID) #define CLONE_NEWPID 0 #endif #define CLONE_FLAGS (CLONE_NEWPID|CLONE_FILES|CLONE_FS|CLONE_VM|SIGCHLD) #if !defined(USE_SEMAPHORES) #undef TEST_CHILD2_ENABLED #define TEST_CHILD2_ENABLED() (1) #undef TEST_CHILD1_ENABLED #define TEST_CHILD1_ENABLED() (1) #undef TEST_CHILD2_PID_ENABLED #define TEST_CHILD2_PID_ENABLED() (1) #undef TEST_MAIN_ENABLED #define TEST_MAIN_ENABLED() (1) #undef TEST_CHILD1_PID_ENABLED #define TEST_CHILD1_PID_ENABLED() (1) #undef TEST_MAIN2_ENABLED #define TEST_MAIN2_ENABLED() (1) #endif void *stack_base2 = NULL; void *stack_top2 = NULL; static int uprobes_ns_child2(void *argv __attribute__((__unused__))) { if (TEST_CHILD2_ENABLED()) { TEST_CHILD2(getpid()); } _exit(0); } static int uprobes_ns_child1(void *argv __attribute__((__unused__))) { int pid; int rc = 0; /* Create the second clone. */ if (TEST_CHILD1_ENABLED()) { TEST_CHILD1(getpid()); } pid = clone(uprobes_ns_child2, stack_top2, CLONE_FLAGS, NULL); if (TEST_CHILD2_PID_ENABLED()) { TEST_CHILD2_PID(pid); } if (pid < 0) { /* Error. */ char *msg2 = "clone 2 failed\n"; write(2, msg2, strlen(msg2)); rc = errno; } else { int status; waitpid(pid, &status, 0); rc = WEXITSTATUS(status); } _exit(rc); } int main(int argc, char **argv) { long pagesize = sysconf(_SC_PAGESIZE); void *stack_base1, *stack_top1; int pid; int rc = 0; /* Allocate both stacks here. */ stack_base1 = calloc(pagesize * 4, 1); if (stack_base1 == NULL) { perror("calloc 1 failed:"); return -1; } stack_base2 = calloc(pagesize * 4, 1); if (stack_base2 == NULL) { perror("calloc 2 failed:"); return -1; } /* * Get top of stacks. According to the clone() manpage: * Stacks grow downwards on all processors that run Linux * (except the HP PA processors), so child_stack usually points * to the topmost address of the memory space set up for the * child stack. */ stack_top1 = stack_base1 + (pagesize * 4); stack_top2 = stack_base2 + (pagesize * 4); /* Create the first clone (which will create the 2nd). */ if (TEST_MAIN_ENABLED()) { TEST_MAIN(getpid()); } pid = clone(uprobes_ns_child1, stack_top1, CLONE_FLAGS, NULL); if (TEST_CHILD1_PID_ENABLED()) { TEST_CHILD1_PID(pid); } if (pid < 0) { /* error */ perror("clone 1 failed:"); rc = -1; } else { int status; /* Wait on the first clone to finish. */ waitpid(pid, &status, 0); rc = WEXITSTATUS(status); } /* Cleanup */ free(stack_base1); free(stack_base2); if (TEST_MAIN2_ENABLED()) { TEST_MAIN2(); } return rc; } systemtap-2.3/testsuite/systemtap.clone/dtrace_clone.exp000066400000000000000000000035631217430427200237410ustar00rootroot00000000000000set TEST_NAME "dtrace_clone" set build_dir "" set test_progs {"dtrace_clone"} if {![installtest_p]} { untested $TEST_NAME; return } if {![uprobes_p]} { untested $TEST_NAME; return } source $srcdir/$subdir/test_progs.tcl # We have to be root to use CLONE_NEWPID. proc run_test_prog {} { global build_dir as_root $build_dir/dtrace_clone return 0 } # Here's an explanation of the output. On kernels that support # CLONE_NEWPID (new pid namespace), we'll see the following output: # main - pid: XXX # main - child pid: YYY # child1 - pid: 1 # child1 - child2 pid: 2 # child2 - pid: 1 # main - finished # On kernels with CLONE_NEWPID, the pids assigned to the children are # fixed since they exist in their own pid namespace. Because not all # kernels support CLONE_NEWPID, we have to accept all pids. set output_string "main - pid: \[0-9\]+\r\nmain - child pid: \[0-9\]+\r\nchild1 - pid: \[0-9\]+\r\nchild1 - child2 pid: \[0-9\]+\r\nchild2 - pid: \[0-9\]+\r\nmain - finished\r\n" # Build everything (without semaphores) set TEST_NAME "dtrace_clone1" if {[build_test_progs "Makefile.clone" $test_progs] == 0} { fail "$TEST_NAME - build failure" cleanup_test_progs return } else { pass "$TEST_NAME - build success" } # Run the test (without semaphores) set TEST_NAME "dtrace_clone2" stap_run $TEST_NAME run_test_prog $output_string \ $srcdir/$subdir/dtrace_clone.stp $build_dir/dtrace_clone # Build everything (with semaphores) set TEST_NAME "dtrace_clone3" if {[build_test_progs "Makefile.clone" $test_progs "-DUSE_SEMAPHORES"] == 0} { fail "$TEST_NAME - build failure" cleanup_test_progs return } else { pass "$TEST_NAME - build success" } # Run the test (with semaphores) set TEST_NAME "dtrace_clone4" stap_run $TEST_NAME run_test_prog $output_string \ $srcdir/$subdir/dtrace_clone.stp $build_dir/dtrace_clone # Cleanup cleanup_test_progs systemtap-2.3/testsuite/systemtap.clone/dtrace_clone.stp000066400000000000000000000014451217430427200237500ustar00rootroot00000000000000global output_string # Original (parent) probes probe process(@1).mark("main") { output_string .= sprintf("main - pid: %d\n", $arg1) } probe process(@1).mark("child1_pid") { output_string .= sprintf("main - child pid: %d\n", $arg1) } probe process(@1).mark("main2") { output_string .= sprintf("main - finished\n") exit() } # Child1 probes probe process(@1).mark("child1") { output_string .= sprintf("child1 - pid: %d\n", $arg1) } probe process(@1).mark("child2_pid") { output_string .= sprintf("child1 - child2 pid: %d\n", $arg1) } # Child2 probes probe process(@1).mark("child2") { output_string .= sprintf("child2 - pid: %d\n", $arg1) } # Testsuite glue probe begin { printf("systemtap starting probe\n"); } probe end { printf("systemtap ending probe\n"); printf("%s", output_string); } systemtap-2.3/testsuite/systemtap.clone/dtrace_clone_probes.d000066400000000000000000000002611217430427200247320ustar00rootroot00000000000000provider test { probe main(pid_t pid); probe main2(); probe child1(pid_t pid); probe child1_pid(pid_t pid); probe child2(pid_t pid); probe child2_pid(pid_t pid); }; systemtap-2.3/testsuite/systemtap.clone/dtrace_fork_exec.exp000066400000000000000000000032061217430427200246000ustar00rootroot00000000000000set TEST_NAME "dtrace_fork_exec" set build_dir "" set test_progs {"dtrace_fork_parent" "dtrace_child"} if {![installtest_p]} { untested $TEST_NAME; return } if {![uprobes_p]} { untested $TEST_NAME; return } source $srcdir/$subdir/test_progs.tcl proc run_test_prog {} { global build_dir catch { exec $build_dir/dtrace_fork_parent $build_dir/dtrace_child } return 0 } # Since we can't guarentee the order of parent/child execution, we # have to be flexible on output. set output_string "parent - pid: \[0-9\]+\r\nparent - child pid( before exec)?: \[0-9\]+\r\nparent - child pid( before exec)?: \[0-9\]+\r\nchild - pid: \[0-9\]+\r\nparent - finished\r\n" # Build everything (without semaphores) set TEST_NAME "dtrace_fork_exec1" if {[build_test_progs "Makefile.fork_exec" $test_progs] == 0} { fail "$TEST_NAME - build failure" cleanup_test_progs return } else { pass "$TEST_NAME - build success" } # Run the test (without semaphores) set TEST_NAME "dtrace_fork_exec2" stap_run $TEST_NAME run_test_prog $output_string \ $srcdir/$subdir/dtrace_fork_exec.stp $build_dir/dtrace_fork_parent \ $build_dir/dtrace_child # Build everything (with semaphores) set TEST_NAME "dtrace_fork_exec3" if {[build_test_progs "Makefile.fork_exec" $test_progs "-DUSE_SEMAPHORES"] == 0} { fail "$TEST_NAME - build failure" cleanup_test_progs return } else { pass "$TEST_NAME - build success" } # Run the test (with semaphores) set TEST_NAME "dtrace_fork_exec4" stap_run $TEST_NAME run_test_prog $output_string \ $srcdir/$subdir/dtrace_fork_exec.stp $build_dir/dtrace_fork_parent \ $build_dir/dtrace_child # Cleanup cleanup_test_progs systemtap-2.3/testsuite/systemtap.clone/dtrace_fork_exec.stp000066400000000000000000000012661217430427200246160ustar00rootroot00000000000000global output_string # Parent probes probe process(@1).mark("main") { output_string .= sprintf("parent - pid: %d\n", $arg1) } probe process(@1).mark("child") { output_string .= sprintf("parent - child pid before exec: %d\n", $arg1) } probe process(@1).mark("child_pid") { output_string .= sprintf("parent - child pid: %d\n", $arg1) } probe process(@1).mark("finished") { output_string .= sprintf("parent - finished\n") exit() } # Child probes probe process(@2).mark("main") { output_string .= sprintf("child - pid: %d\n", $arg1) } # Testsuite glue probe begin { printf("systemtap starting probe\n"); } probe end { printf("systemtap ending probe\n"); printf("%s", output_string); } systemtap-2.3/testsuite/systemtap.clone/dtrace_fork_parent.c000066400000000000000000000027731217430427200246030ustar00rootroot00000000000000/* Systemtap test case * Copyright (C) 2010, Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. */ #include #include #include #include #include #include #include #include #include "dtrace_fork_parent_probes.h" #if !defined(USE_SEMAPHORES) #undef PARENT_MAIN_ENABLED #define PARENT_MAIN_ENABLED() (1) #undef PARENT_CHILD_ENABLED #define PARENT_CHILD_ENABLED() (1) #undef PARENT_CHILD_PID_ENABLED #define PARENT_CHILD_PID_ENABLED() (1) #undef PARENT_FINISHED_ENABLED #define PARENT_FINISHED_ENABLED() (1) #endif int main(int argc, char **argv) { int pid; int rc = 0; char *child_argv[] = { argv[1], NULL }; /* Create the child. */ if (PARENT_MAIN_ENABLED()) { PARENT_MAIN(getpid()); } pid = fork(); if (pid == 0) { /* child */ if (PARENT_CHILD_ENABLED()) { PARENT_CHILD(getpid()); } rc = execve(argv[1], child_argv, NULL); _exit(rc); } if (PARENT_CHILD_PID_ENABLED()) { PARENT_CHILD_PID(pid); } if (pid < 0) { /* error */ perror("fork failed:"); rc = -1; } else { int status; waitpid(pid, &status, 0); rc = WEXITSTATUS(status); } if (PARENT_FINISHED_ENABLED()) { PARENT_FINISHED(); } return rc; } systemtap-2.3/testsuite/systemtap.clone/dtrace_fork_parent_probes.d000066400000000000000000000001721217430427200261450ustar00rootroot00000000000000provider parent { probe main(pid_t pid); probe child(pid_t pid); probe child_pid(pid_t pid); probe finished(); }; systemtap-2.3/testsuite/systemtap.clone/dtrace_vfork_exec.exp000066400000000000000000000027611217430427200247730ustar00rootroot00000000000000set TEST_NAME "dtrace_vfork_exec" set build_dir "" set test_progs {"dtrace_vfork_parent" "dtrace_child"} if {![installtest_p]} { untested $TEST_NAME; return } if {![uprobes_p]} { untested $TEST_NAME; return } source $srcdir/$subdir/test_progs.tcl proc run_test_prog {} { global build_dir catch { exec $build_dir/dtrace_vfork_parent $build_dir/dtrace_child } return 0 } set output_string "parent - pid: \[0-9\]+\r\nparent - child pid: \[0-9\]+\r\nchild - pid: \[0-9\]+\r\nparent - finished\r\n" # Build everything (without semaphores) set TEST_NAME "dtrace_vfork_exec1" if {[build_test_progs "Makefile.vfork_exec" $test_progs] == 0} { fail "$TEST_NAME - build failure" cleanup_test_progs return } else { pass "$TEST_NAME - build success" } # Run the test (without semaphores) set TEST_NAME "dtrace_vfork_exec2" stap_run $TEST_NAME run_test_prog $output_string \ $srcdir/$subdir/dtrace_vfork_exec.stp $build_dir/dtrace_vfork_parent \ $build_dir/dtrace_child # Build everything (with semaphores) set TEST_NAME "dtrace_vfork_exec3" if {[build_test_progs "Makefile.vfork_exec" $test_progs "-DUSE_SEMAPHORES"] == 0} { fail "$TEST_NAME - build failure" cleanup_test_progs return } else { pass "$TEST_NAME - build success" } # Run the test (with semaphores) set TEST_NAME "dtrace_vfork_exec4" stap_run $TEST_NAME run_test_prog $output_string \ $srcdir/$subdir/dtrace_vfork_exec.stp $build_dir/dtrace_vfork_parent \ $build_dir/dtrace_child # Cleanup cleanup_test_progs systemtap-2.3/testsuite/systemtap.clone/dtrace_vfork_exec.stp000066400000000000000000000011111217430427200247710ustar00rootroot00000000000000global output_string # Parent probes probe process(@1).mark("main") { output_string .= sprintf("parent - pid: %d\n", $arg1) } probe process(@1).mark("child_pid") { output_string .= sprintf("parent - child pid: %d\n", $arg1) } probe process(@1).mark("finished") { output_string .= sprintf("parent - finished\n") exit() } # Child probes probe process(@2).mark("main") { output_string .= sprintf("child - pid: %d\n", $arg1) } # Testsuite glue probe begin { printf("systemtap starting probe\n"); } probe end { printf("systemtap ending probe\n"); printf("%s", output_string); } systemtap-2.3/testsuite/systemtap.clone/dtrace_vfork_parent.c000066400000000000000000000025771217430427200247730ustar00rootroot00000000000000/* Systemtap test case * Copyright (C) 2010, Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. */ #include #include #include #include #include #include #include #include #include "dtrace_vfork_parent_probes.h" #if !defined(USE_SEMAPHORES) #undef PARENT_MAIN_ENABLED #define PARENT_MAIN_ENABLED() (1) #undef PARENT_CHILD_PID_ENABLED #define PARENT_CHILD_PID_ENABLED() (1) #undef PARENT_FINISHED_ENABLED #define PARENT_FINISHED_ENABLED() (1) #endif int main(int argc, char **argv) { int pid; int rc = 0; char *child_argv[] = { argv[1], NULL }; /* Create the child. */ if (PARENT_MAIN_ENABLED()) { PARENT_MAIN(getpid()); } pid = vfork(); if (pid == 0) { /* child */ rc = execve(argv[1], child_argv, NULL); _exit(rc); } if (PARENT_CHILD_PID_ENABLED()) { PARENT_CHILD_PID(pid); } if (pid < 0) { /* error */ perror("fork failed:"); rc = -1; } else { int status; waitpid(pid, &status, 0); rc = WEXITSTATUS(status); } if (PARENT_FINISHED_ENABLED()) { PARENT_FINISHED(); } return rc; } systemtap-2.3/testsuite/systemtap.clone/dtrace_vfork_parent_probes.d000066400000000000000000000001401217430427200263260ustar00rootroot00000000000000provider parent { probe main(pid_t pid); probe child_pid(pid_t pid); probe finished(); }; systemtap-2.3/testsuite/systemtap.clone/main_quiesce.c000066400000000000000000000007021217430427200233770ustar00rootroot00000000000000#include #include void spool_write_script(int jobid) __attribute__ ((noinline)); void spool_write_script(int jobid) { printf("sleeping... %d\n", 1 + (jobid % 2)); sleep(1 + (jobid % 2)); } void *mythread(void *unused) { int i; for (i = 0; i < 30; i++) spool_write_script(i); return NULL; } int main() { pthread_t tid; pthread_create(&tid, NULL, mythread, NULL); pthread_join(tid, NULL); } systemtap-2.3/testsuite/systemtap.clone/main_quiesce.exp000066400000000000000000000030311217430427200237470ustar00rootroot00000000000000set test main_quiesce if {! [installtest_p]} { untested $test return } # This test makes sure we don't miss events when the main thread # doesn't quiesce (without us interrupting it). # Compile our threaded test program. set srcpath "$srcdir/$subdir/${test}.c" set exepath "./${test}_exe" set res [target_compile $srcpath $exepath executable "additional_flags=-g libs=-lpthread"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "$test - unable to compile [file tail $srcpath]" return } else { pass "$test - compiled [file tail $srcpath]" } set test_script { global hits probe begin { printf("systemtap starting probe\n") } probe process("%s").function("spool_write_script") { hits <<< 1 } probe end { printf("systemtap ending probe\n") printf("hits = %%d\n", @sum(hits)) } } set output "hits = \[1-9\]\[0-9\]*\r\n" set script [format $test_script $exepath] verbose -log $script foreach runtime [get_runtime_list] { set test_name "$test" # Run the test executable. spawn $exepath set exe_id $spawn_id if {$runtime != ""} { lappend test_name "($runtime)" stap_run $test_name wait_5_secs $output --runtime=$runtime \ -e $script -x [exp_pid -i $exe_id] } elseif {[uprobes_p]} { stap_run $test_name wait_5_secs $output -e $script \ -x [exp_pid -i $exe_id] } else { untested "$test (uprobes)" continue } exec kill -INT -[exp_pid -i $exe_id] catch {close -i $exe_id} catch {wait -i $exe_id} } exec rm -f $test systemtap-2.3/testsuite/systemtap.clone/probe_by_pid.c000066400000000000000000000002441217430427200233730ustar00rootroot00000000000000#include #include void test_function(void) { sleep(1); (void) getpid(); } int main(void) { while (1) { test_function(); } } systemtap-2.3/testsuite/systemtap.clone/probe_by_pid.exp000066400000000000000000000061771217430427200237600ustar00rootroot00000000000000set TEST_BASENAME "probe_by_pid" set TEST_NAME ${TEST_BASENAME} set build_dir "" set test_progs {"probe_by_pid"} if {![installtest_p]} { untested $TEST_NAME; return } if {![utrace_p]} { untested $TEST_NAME; return } source $srcdir/$subdir/test_progs.tcl proc run_test_prog {} { global test_prog # Start yet another copy of the test program. This one should be # ignored by stap. spawn $test_prog set id $spawn_id # Wait 3 seconds after 3000 # Kill the test program catch {exec kill -INT -[exp_pid -i $id]} catch {close -i $id}; catch {wait -i $id} return 0 } # Do strict utrace-only tests here... # Build base test program set TEST_NAME "probe_by_pid(utrace)" if {[build_test_progs "Makefile.probe_by_pid" $test_progs] == 0} { fail "$TEST_NAME - build failure" cleanup_test_progs # In theory we could go on here and test the uprobe tests, but # let's just quit. return } else { pass "$TEST_NAME - build success" } # Run the 1st instance of the test program. verbose -log "running test programs..." set test_prog $build_dir/[lindex $test_progs 0] spawn $test_prog set id1 $spawn_id # Run the 2nd instance of the test program. spawn $test_prog set id2 $spawn_id set pid2 [exp_pid -i $id2] # Run stap on the 2nd instance. set output_string "${pid2}: 1 begin probes\r\n${pid2}: \[0-9\]+ syscall probes\r\n" stap_run $TEST_NAME run_test_prog $output_string \ $srcdir/$subdir/probe_by_pid_utrace.stp $pid2 # Kill both of the spawned processes catch {exec kill -INT -[exp_pid -i $id1]} catch {close -i $id1}; catch {wait -i $id1} catch {exec kill -INT -[exp_pid -i $id2]} catch {close -i $id2}; catch {wait -i $id2} # Here we'd like to test 'process(PID).function(FUNC)', but process # function probes only support .process(PATH).function(FUNC)' probes. # See PR6897 "stap should assert valid PIDs for process(PID) probes" # and PR11644 "process(PID).function/statement probes". # # So, instead we'll use hard-links to try and confuse things. If we # probe 'process(PATH").function("*")' and link PATH to PATH2, do the # probes get hit in PATH2? set TEST_NAME "probe_by_pid(function)" if {![uprobes_p]} { untested $TEST_NAME; return } # do uprobes tests here - both function and sdt marker # Run the 1st instance of the test program. verbose -log "running test programs..." set test_prog $build_dir/[lindex $test_progs 0] spawn $test_prog set id1 $spawn_id # Link... set test_prog2 "${test_prog}2" exec ln $test_prog $test_prog2 # Run the 2nd instance of the test program. spawn $test_prog2 set id2 $spawn_id set pid2 [exp_pid -i $id2] # Run stap on the 2nd instance. set output_string "${pid2}: \[0-9\]+ test_function probes\r\n" stap_run $TEST_NAME run_test_prog $output_string \ $srcdir/$subdir/probe_by_pid_function.stp -d $test_prog2 $test_prog2 # Kill both of the spawned processes catch {exec kill -INT -[exp_pid -i $id1]} catch {close -i $id1}; catch {wait -i $id1} catch {exec kill -INT -[exp_pid -i $id2]} catch {close -i $id2}; catch {wait -i $id2} # FIXME: we could also test hard-linked paths with # 'process(PATH).mark(MARK)' probes (with and without semaphores). # Cleanup cleanup_test_progs systemtap-2.3/testsuite/systemtap.clone/probe_by_pid_function.stp000066400000000000000000000013621217430427200256660ustar00rootroot00000000000000global main_probes global test_function_probes #global end_probes probe timer.s(5) { exit() } # Actual probes #probe process("probe_by_pid").function("main") probe process(@1).function("main").call { main_probes[pid()]++ } probe process(@1).function("test_function") { test_function_probes[pid()]++ } # Testsuite glue probe begin { printf("systemtap starting probe\n"); } probe end { printf("systemtap ending probe\n"); # We really shouldn't see any main_probes, since the system # has already called main before we start probing. foreach (pid in main_probes) { printf("%d: %d main probes\n", pid, main_probes[pid]) } foreach (pid in test_function_probes) { printf("%d: %d test_function probes\n", pid, test_function_probes[pid]) } } systemtap-2.3/testsuite/systemtap.clone/probe_by_pid_utrace.stp000066400000000000000000000013201217430427200253160ustar00rootroot00000000000000global begin_probes global syscall_probes global end_probes probe timer.s(5) { exit() } # Actual probes probe process($1).begin { begin_probes[pid()]++ } probe process($1).syscall { syscall_probes[pid()]++ } probe process($1).end { end_probes[pid()]++ } # Testsuite glue probe begin { printf("systemtap starting probe\n"); } probe end { printf("systemtap ending probe\n"); foreach (pid in begin_probes) { printf("%d: %d begin probes\n", pid, begin_probes[pid]) } foreach (pid in syscall_probes) { printf("%d: %d syscall probes\n", pid, syscall_probes[pid]) } # We really shouldn't see any end_probes fired... foreach (pid in end_probes) { printf("%d: %d end probes\n", pid, end_probes[pid]) } } systemtap-2.3/testsuite/systemtap.clone/test_progs.tcl000066400000000000000000000027651217430427200235010ustar00rootroot00000000000000proc create_build_dir {Makefile} { global build_dir global srcdir subdir # If build_dir hasn't been set, create it. if {[string length $build_dir] == 0} { if {[catch {exec mktemp -d staptestXXXXXX} build_dir]} { verbose -log "Failed to create temporary directory: $build_dir" return 0 } foreach f [glob $srcdir/$subdir/*.c $srcdir/$subdir/*.d] { exec cp $f $build_dir/ } exec cp $srcdir/$subdir/$Makefile $build_dir/Makefile } else { # Otherwise, run "make clean" verbose -log "exec make -C $build_dir clean" set res [catch "exec make -C $build_dir clean" output] verbose -log "$output" } return 1 } proc build_test_progs {Makefile test_progs {CFLAGS ""}} { global build_dir global env # Create the build directory and populate it create_build_dir $Makefile # Run make. set includes "-isystem$env(SYSTEMTAP_INCLUDES)" if {$CFLAGS != ""} { set CFLAGS "$includes $CFLAGS" } else { set CFLAGS "$includes" } verbose -log "exec make -C $build_dir CFLAGS=\"$CFLAGS\"" set res [catch {eval { exec make -C $build_dir CFLAGS=$CFLAGS} } output] verbose -log "$output" # Check that the test progs were created foreach f $test_progs { if {![file exists $build_dir/$f]} { verbose -log "Test program $f doesn't exist!" return 0 } } return 1 } proc cleanup_test_progs {} { global build_dir catch { exec kill -INT -[exp_pid] } if {$build_dir != ""} { catch { exec rm -rf $build_dir } } } systemtap-2.3/testsuite/systemtap.context/000077500000000000000000000000001217430427200211565ustar00rootroot00000000000000systemtap-2.3/testsuite/systemtap.context/args.stp000066400000000000000000000026071217430427200226470ustar00rootroot00000000000000probe module("systemtap_test_module2").function("yyy_int") { printf("yyy_int %d %d %d\n", $a, $b, $c) } probe module("systemtap_test_module2").function("yyy_int").return { printf("yyy_int returns %d\n", $return) } probe module("systemtap_test_module2").function("yyy_uint") { printf("yyy_uint %d %d %d\n", $a, $b, $c) } probe module("systemtap_test_module2").function("yyy_uint").return { printf("yyy_uint returns %d\n", $return) } probe module("systemtap_test_module2").function("yyy_long") { printf("yyy_long %d %d %d\n", $a, $b, $c) } probe module("systemtap_test_module2").function("yyy_long").return { printf("yyy_long returns %d\n", $return) } probe module("systemtap_test_module2").function("yyy_int64") { printf("yyy_int64 %d %d %d\n", $a, $b, $c) } probe module("systemtap_test_module2").function("yyy_int64").return { printf("yyy_int64 returns %d\n", $return) } probe module("systemtap_test_module2").function("yyy_char") { printf("yyy_char %1b %1b %1b\n", $a, $b, $c) } probe module("systemtap_test_module2").function("yyy_char").return { printf("yyy_char returns %1b\n", $return) } probe module("systemtap_test_module2").function("yyy_str") { printf("yyy_str %s-%s-%s\n", kernel_string($a), kernel_string($b), kernel_string($c)) } probe module("systemtap_test_module2").function("yyy_str").return { printf("yyy_str returns %s\n", kernel_string($return)) } probe begin { printf("READY\n") } systemtap-2.3/testsuite/systemtap.context/args.tcl000066400000000000000000000027361217430427200226260ustar00rootroot00000000000000spawn stap $srcdir/$subdir/args.stp expect { -timeout 120 "READY" { exec echo 1 > /proc/stap_test_cmd expect { -timeout 5 "yyy_int -1 200 300\r\nyyy_int returns 499\r\n" { pass "integer function arguments" } timeout {fail "integer function arguments"} } exec echo 2 > /proc/stap_test_cmd expect { -timeout 5 "yyy_uint 4294967295 200 300\r\nyyy_uint returns 499\r\n" { pass "unsigned function arguments" } timeout {fail "unsigned function arguments"} } exec echo 3 > /proc/stap_test_cmd expect { -timeout 5 "yyy_long -1 200 300\r\nyyy_long returns 499\r\n" { pass "long function arguments" } timeout {fail "long function arguments"} } exec echo 4 > /proc/stap_test_cmd expect { -timeout 5 "yyy_int64 -1 200 300\r\nyyy_int64 returns 499\r\n" { pass "int64 function arguments" } timeout {fail "int64 function arguments"} } exec echo 5 > /proc/stap_test_cmd expect { -timeout 5 "yyy_char a b c\r\nyyy_char returns Q\r\n" { pass "char function arguments" } timeout {fail "char function arguments"} } exec echo 6 > /proc/stap_test_cmd expect { -timeout 5 "yyy_str Hello-System-Tap\r\nyyy_str returns XYZZY\r\n" { pass "string function arguments" } timeout {fail "string function arguments"} } } timeout {fail "all args tests - timeout"} eof {fail "function arguments: unexpected timeout"} } exec kill -INT -[exp_pid] catch { close } wait systemtap-2.3/testsuite/systemtap.context/backtrace.stp000066400000000000000000000014101217430427200236210ustar00rootroot00000000000000function print_all_trace_info(point) { printf("backtrace from %s:\n", pp()) print_backtrace() printf("--- %s ---\n", point) bt = backtrace() printf("the stack is %s\n", bt) print_syms(bt); print("--------\n") } probe begin { // Too difficult/different on different arches/kernels to check. // print_backtrace() log(""); } probe end { print_backtrace() } global flag = 0 probe module("systemtap_test_module2").function("yyy_func2") { print_all_trace_info("yyy_func2") flag ++ } probe module("systemtap_test_module2").function("yyy_func3") { print_all_trace_info("yyy_func3") flag ++ } probe module("systemtap_test_module2").function("yyy_func4") { print_all_trace_info("yyy_func4") flag ++ exit(); } systemtap-2.3/testsuite/systemtap.context/backtrace.tcl000066400000000000000000000154211217430427200236040ustar00rootroot00000000000000set m1 0 set m2 0 set m3 0 set m4 0 set m5 0 set m6 0 set module1 0 set kernel 0 set script_exit 0 set eof_found 0 spawn stap -d kernel -d systemtap_test_module1 $srcdir/$subdir/backtrace.stp #exp_internal 1 expect { -timeout 120 "\r\n" { pass "backtrace of begin probe" exec echo 0 > /proc/stap_test_cmd exp_continue } #backtrace from yyy_func2 -re {^backtrace from module\(\"systemtap_test_module2\"\)\.function\(\"yyy_func2@[^\r\n]+\r\n} { incr m1 expect { -timeout 5 -re {^ 0x[a-f0-9]+ : yyy_func2[^\[]+\[systemtap_test_module2\]\r\n} { if {$m1 == 1} {incr m1} exp_continue } -re {^ 0x[a-f0-9]+ : yyy_func1[^\[]+\[systemtap_test_module2\]\r\n} { if {$m1 == 2} {incr m1} exp_continue } -re {^ 0x[a-f0-9]+ : stm_write_cmd[^\[]+\[systemtap_test_module1\]\r\n} { if {$m1 == 3} {incr module1} exp_continue } -re {^ 0x[a-f0-9]+ : [a-z_]+[^\[]+\[kernel\]\r\n} { if {$module1 == 1} {incr kernel} # we expect at least one [kernel] frame, maybe more. } eof { set eof_found 1; fail "early test shutdown (m1 eof)" } } if {! $eof_found} { exp_continue } } -re {.*--- yyy_func2 ---\r\nthe stack is 0x[a-f0-9]+ [^\r\n]+\r\n} { incr m2 expect { -timeout 5 -re {^ 0x[a-f0-9]+ : yyy_func2[^\[]+\[systemtap_test_module2\]\r\n} { if {$m2 == 1} {incr m2} exp_continue } -re {^ 0x[a-f0-9]+ : yyy_func1[^\[]+\[systemtap_test_module2\]\r\n} { if {$m2 == 2} {incr m2} exp_continue } -re {^ 0x[a-f0-9]+ : stm_write_cmd[^\[]+\[systemtap_test_module1\]\r\n} { if {$m2 == 3} {incr module1} exp_continue } -re {^ 0x[a-f0-9]+ : [a-z_]+[^\[]+\[kernel\]\r\n} { if {$module1 == 2} {incr kernel} # we expect at least one [kernel] frame, maybe more. } eof { set eof_found 1; fail "early test shutdown (m2 eof)" } } if {! $eof_found} { exp_continue } } #backtrace from yyy_func3 -re {.*backtrace from module\(\"systemtap_test_module2\"\)\.function\(\"yyy_func3@[^\r\n]+\r\n} { incr m3 expect { -timeout 5 -re {^ 0x[a-f0-9]+ : yyy_func3[^\[]+\[systemtap_test_module2\]\r\n} { if {$m3 == 1} {incr m3} exp_continue } -re {^ 0x[a-f0-9]+ : yyy_func2[^\[]+\[systemtap_test_module2\]\r\n} { if {$m3 == 2} {incr m3} exp_continue } -re {^ 0x[a-f0-9]+ : yyy_func1[^\[]+\[systemtap_test_module2\]\r\n} { if {$m3 == 3} {incr m3} exp_continue } -re {^ 0x[a-f0-9]+ : stm_write_cmd[^\[]+\[systemtap_test_module1\]\r\n} { if {$m3 == 4} {incr module1} exp_continue } -re {^ 0x[a-f0-9]+ : [a-z_]+[^\[]+\[kernel\]\r\n} { if {$module1 == 3} {incr kernel} # we expect at least one [kernel] frame, maybe more. } eof { set eof_found 1; fail "early test shutdown (m3 eof)" } } if {! $eof_found} { exp_continue } } -re {.*--- yyy_func3 ---\r\nthe stack is 0x[a-f0-9]+ [^\r\n]+\r\n} { incr m4 expect { -timeout 5 -re {^ 0x[a-f0-9]+ : yyy_func3[^\[]+\[systemtap_test_module2\]\r\n} { if {$m4 == 1} {incr m4} exp_continue } -re {^ 0x[a-f0-9]+ : yyy_func2[^\[]+\[systemtap_test_module2\]\r\n} { if {$m4 == 2} {incr m4} exp_continue } -re {^ 0x[a-f0-9]+ : yyy_func1[^\[]+\[systemtap_test_module2\]\r\n} { if {$m4 == 3} {incr m4} exp_continue } -re {^ 0x[a-f0-9]+ : stm_write_cmd[^\[]+\[systemtap_test_module1\]\r\n} { if {$m4 == 4} {incr module1} exp_continue } -re {^ 0x[a-f0-9]+ : [a-z_]+[^\[]+\[kernel\]\r\n} { if {$module1 == 4} {incr kernel} # we expect at least one [kernel] frame, maybe more. } eof { set eof_found 1; fail "early test shutdown (m4 eof)" } } if {! $eof_found} { exp_continue } } #backtrace from yyy_func4 -re {.*backtrace from module\(\"systemtap_test_module2\"\)\.function\(\"yyy_func4@[^\r\n]+\r\n} { incr m5 expect { -timeout 5 -re {^ 0x[a-f0-9]+ : yyy_func4[^\[]+\[systemtap_test_module2\]\r\n} { if {$m5 == 1} {incr m5} exp_continue } -re {^ 0x[a-f0-9]+ : yyy_func3[^\[]+\[systemtap_test_module2\]\r\n} { if {$m5 == 2} {incr m5} exp_continue } -re {^ 0x[a-f0-9]+ : yyy_func2[^\[]+\[systemtap_test_module2\]\r\n} { if {$m5 == 3} {incr m5} exp_continue } -re {^ 0x[a-f0-9]+ : yyy_func1[^\[]+\[systemtap_test_module2\]\r\n} { if {$m5 == 4} {incr m5} exp_continue } -re {^ 0x[a-f0-9]+ : stm_write_cmd[^\[]+\[systemtap_test_module1\]\r\n} { if {$m5 == 5} {incr module1} exp_continue } -re {^ 0x[a-f0-9]+ : [a-z_]+[^\[]+\[kernel\]\r\n} { if {$module1 == 5} {incr kernel} # we expect at least one [kernel] frame, maybe more. } eof { set eof_found 1; fail "early test shutdown (m5 eof)" } } if {! $eof_found} { exp_continue } } -re {.*--- yyy_func4 ---\r\nthe stack is 0x[a-f0-9]+ [^\r\n]+\r\n} { incr m6 expect { -timeout 5 -re {^ 0x[a-f0-9]+ : yyy_func4[^\[]+\[systemtap_test_module2\]\r\n} { if {$m6 == 1} {incr m6} exp_continue } -re {^ 0x[a-f0-9]+ : yyy_func3[^\[]+\[systemtap_test_module2\]\r\n} { if {$m6 == 2} {incr m6} exp_continue } -re {^ 0x[a-f0-9]+ : yyy_func2[^\[]+\[systemtap_test_module2\]\r\n} { if {$m6 == 3} {incr m6} exp_continue } -re {^ 0x[a-f0-9]+ : yyy_func1[^\[]+\[systemtap_test_module2\]\r\n} { if {$m6 == 4} {incr m6} exp_continue } -re {^ 0x[a-f0-9]+ : stm_write_cmd[^\[]+\[systemtap_test_module1\]\r\n} { if {$m6 == 5} {incr module1} exp_continue } -re {^ 0x[a-f0-9]+ : [a-z_]+[^\[]+\[kernel\]\r\n} { if {$module1 == 6} {incr kernel} # we expect at least one [kernel] frame, maybe more. } eof { set eof_found 1; fail "early test shutdown (m6 eof)" } } if {! $eof_found} { exp_continue } } eof { # good backtrace.stp called exit(). incr script_exit; } } exec kill -INT -[exp_pid] if {$m1 == 3} { pass "backtrace of yyy_func2" } else { fail "backtrace of yyy_func2 ($m1)" } if {$m2 == 3} { pass "print_syms of yyy_func2" } else { fail "print_syms of yyy_func2 ($m2)" } if {$m3 == 4} { pass "backtrace of yyy_func3" } else { fail "backtrace of yyy_func3 ($m3)" } if {$m4 == 4} { pass "print_syms of yyy_func3" } else { fail "print_syms of yyy_func3 ($m4)" } if {$m5 == 5} { pass "backtrace of yyy_func4" } else { fail "backtrace of yyy_func4 ($m5)" } if {$m6 == 5} { pass "print_syms of yyy_func4" } else { fail "print_syms of yyy_func4 ($m6)" } if {$module1 == 6} { pass "print_syms found systemtap_test_module1" } else { fail "print_syms didn't find systemtap_test_module1 ($module1)" } if {$kernel >= 6} { pass "print_syms found \[kernel\]" } else { fail "print_syms didn't find \[kernel\] ($kernel)" } if {$script_exit == 1} { pass "backtrace.stp called exit" } else { fail "backtrace.stp didn't call exit ($script_exit)" } catch { close } wait systemtap-2.3/testsuite/systemtap.context/context.exp000066400000000000000000000040571217430427200233660ustar00rootroot00000000000000set testlist {backtrace args pid num_args} if {![installtest_p]} { foreach test $testlist { untested $test } return } set build_dir "" proc cleanup_modules {} { global build_dir catch { exec kill -INT -[exp_pid] } foreach n {1 2} { as_root [list /bin/rm -f /lib/modules/$::uname/kernel/systemtap_test_module$n.ko] as_root [list /sbin/rmmod systemtap_test_module$n] } if {$build_dir != ""} { catch { exec rm -rf $build_dir } } } proc build_modules {} { global build_dir global srcdir subdir # Create the build directory and populate it if {[catch {exec mktemp -d staptestXXXXXX} build_dir]} { verbose -log "Failed to create temporary directory: $build_dir" return 0 } foreach f [glob $srcdir/$subdir/systemtap_test_module*.c] { exec cp $f $build_dir/ } # Build the modules foreach n {2 1} { exec cp -p $srcdir/$subdir/makefile$n $build_dir/Makefile if {[catch {exec make -C $build_dir clean} res]} { verbose -log "$res" return 0 } catch {exec make -C $build_dir} res if {![file exists $build_dir/systemtap_test_module$n.ko]} { verbose -log "$res" return 0 } set res [as_root [list cp $build_dir/systemtap_test_module$n.ko /lib/modules/$::uname/kernel]] if { $res != 0 } { verbose -log "$res" return 0 } } # Install the modules foreach n {2 1} { set res [as_root [list /sbin/insmod $build_dir/systemtap_test_module$n.ko]] if {$res != 0} { verbose -log "$res" return 0 } } return 1 } # first build the modules # NB: We cannot "cd" on behalf the whole dejagnu process, especially # without going back to the build tree, and especially not to the # source tree expecting to be able to write there. # # cd $srcdir/$subdir set uname [exec /bin/uname -r] if {[build_modules] == 0} { verbose -log "BUILD FAILED" foreach test $testlist { fail "$test - could not build modules" } return } foreach test $testlist { send_log "sourcing: $srcdir/$subdir/$test.tcl\n" source $srcdir/$subdir/$test.tcl } cleanup_modules systemtap-2.3/testsuite/systemtap.context/fib.c000066400000000000000000000006421217430427200220640ustar00rootroot00000000000000#include #include long fib(int x) { if (x == 0 || x == 1) return 1; else return fib(x - 1) + fib(x - 2); } int main(int argc, char **argv) { int x = 0; long result = 0; if (argc != 2) { printf("0\n"); return 1; } x = atoi(argv[1]); if (x < 0) { printf("0\n"); return 1; } result = fib(x); printf("%ld\n", result); return 0; } systemtap-2.3/testsuite/systemtap.context/fib.exp000066400000000000000000000034101217430427200224320ustar00rootroot00000000000000# Tests backtrace in the classic Fibonacci program set test "fib" # Only run on make installcheck and utrace present. if {! [installtest_p]} { untested "$test"; return } if {! [utrace_p]} { untested "$test"; return } if {! [uretprobes_p]} { untested "$test"; return } set testpath "$srcdir/$subdir" set testsrc "$testpath/fib.c" set testexe "[pwd]/$test" # We want debug info and no optimization (is that totally necessary?) set testflags "additional_flags=-g additional_flags=-O0" set teststp "$testpath/$test.stp" # When possible explicitly set 64 bit mode if kernel is 64 bit. switch -regexp $::tcl_platform(machine) { {^(x86_64|ppc64|s390x)$} { set testflags "$testflags additional_flags=-m64" } } set res [target_compile $testsrc $testexe executable $testflags] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile $testsrc" return } spawn stap -c "$testexe 10" $teststp set fibcalls 0 set maincalls 0 expect { -timeout 120 -re {^fib[^\r\n]*[\r\n]} { incr fibcalls; exp_continue } -re {^main[^\r\n]*[\r\n]} { incr maincalls; exp_continue } -re {^[^\r\n]*[\r\n]} {exp_continue} timeout { fail "$test (timeout)" } eof { } } wait if {$fibcalls == 18 && $maincalls == 2} { pass "$test ($fibcalls $maincalls)" } { fail "$test ($fibcalls $maincalls)" } spawn stap -c "$testexe 10" -- $teststp --entry set fibcalls 0 set maincalls 0 expect { -timeout 120 -re {^fib[^\r\n]*[\r\n]} { incr fibcalls; exp_continue } -re {^main[^\r\n]*[\r\n]} { incr maincalls; exp_continue } -re {^[^\r\n]*[\r\n]} {exp_continue} timeout { fail "$test (timeout)" } eof { } } wait if {$fibcalls == 55 && $maincalls == 10} { pass "$test ($fibcalls $maincalls)" } { fail "$test ($fibcalls $maincalls)" } systemtap-2.3/testsuite/systemtap.context/fib.stp000066400000000000000000000006351217430427200224520ustar00rootroot00000000000000global depth = 0 global max_depth = 0 probe process("fib").function("fib").call { depth++ if (depth > max_depth) { max_depth = depth %( $# > 0 %? print_ubacktrace_brief(); printf("\n") %) } } probe process("fib").function("fib").return { %( $# == 0 %? if (depth == max_depth) { print_ubacktrace_brief() printf("\n") } %) depth-- } systemtap-2.3/testsuite/systemtap.context/makefile1000066400000000000000000000003701217430427200227370ustar00rootroot00000000000000obj-m := systemtap_test_module1.o KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules clean: rm -f *.mod.c systemtap_test_module1.ko *.o .*.cmd Modules.symvers rm -rf .tmp_versions systemtap-2.3/testsuite/systemtap.context/makefile2000066400000000000000000000003701217430427200227400ustar00rootroot00000000000000obj-m := systemtap_test_module2.o KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules clean: rm -f *.mod.c systemtap_test_module2.ko *.o .*.cmd Modules.symvers rm -rf .tmp_versions systemtap-2.3/testsuite/systemtap.context/num_args.stp000066400000000000000000000041471217430427200235270ustar00rootroot00000000000000%( arch == "i386" %? global ir = "eax", lr = "eax" %) %( arch == "x86_64" %? global ir = "eax", lr = "rax" %) %( arch == "powerpc" %? global ir = "r3", lr = "r3" %) %( arch == "s390" %? global ir = "r2", lr = "r2" %) %( arch == "arm" %? global ir = "r0", lr = "r0" %) probe module("systemtap-test-module2").function("yyy_int") { printf("yyy_int %d %d %d\n", int_arg(1), int_arg(2), int_arg(3)) } probe module("systemtap-test-module2").function("yyy_int").return { printf("yyy_int returns %d\n", register(ir)) } probe module("systemtap-test-module2").function("yyy_uint") { printf("yyy_uint %d %d %d\n", uint_arg(1), uint_arg(2), uint_arg(3)) } probe module("systemtap-test-module2").function("yyy_uint").return { printf("yyy_uint returns %d\n", u_register(ir)) } probe module("systemtap-test-module2").function("yyy_long") { printf("yyy_long %d %d %d\n", long_arg(1), long_arg(2), long_arg(3)) } probe module("systemtap_test-module2").function("yyy_long").return { printf("yyy_long returns %d\n", register(lr)) } probe module("systemtap-test_module2").function("yyy_int64") { # On i386, kernel is built with -mregparm=3. The first arg occupies the # first two registers. The 2nd arg is not split between the 3rd register # and the stack, but rather passed entirely on the stack. printf("yyy_int64 %d %d %d\n", %( arch == "i386" %? s64_arg(1), s64_arg(4), s64_arg(6) %: s64_arg(1), s64_arg(2), s64_arg(3) %) ) } probe module("systemtap_test_module2").function("yyy_int64").return { printf("yyy_int64 returns %d\n", register(ir)) } probe module("systemtap_test_module2").function("yyy_char") { printf("yyy_char %1b %1b %1b\n", int_arg(1), int_arg(2), int_arg(3)) } probe module("systemtap_test_module2").function("yyy_char").return { printf("yyy_char returns %1b\n", register(ir)) } probe module("systemtap_test_module2").function("yyy_str") { printf("yyy_str %s-%s-%s\n", kernel_string(pointer_arg(1)), kernel_string(pointer_arg(2)), kernel_string(pointer_arg(3))) } probe module("systemtap_test_module2").function("yyy_str").return { printf("yyy_str returns %s\n", kernel_string(register(lr))) } probe begin { printf("READY\n") } systemtap-2.3/testsuite/systemtap.context/num_args.tcl000066400000000000000000000033041217430427200234750ustar00rootroot00000000000000set tag "numeric" eval spawn stap $srcdir/$subdir/num_args.stp expect { -timeout 120 "READY" { exec echo 1 > /proc/stap_test_cmd expect { -timeout 5 "yyy_int -1 200 300\r\nyyy_int returns 499\r\n" { pass "integer function arguments -- $tag" } timeout {fail "integer function arguments -- $tag"} } exec echo 2 > /proc/stap_test_cmd expect { -timeout 5 "yyy_uint 4294967295 200 300\r\nyyy_uint returns 499\r\n" { pass "unsigned function arguments -- $tag" } timeout {fail "unsigned function arguments -- $tag"} } exec echo 3 > /proc/stap_test_cmd expect { -timeout 5 "yyy_long -1 200 300\r\nyyy_long returns 499\r\n" { pass "long function arguments -- $tag" } timeout {fail "long function arguments -- $tag"} } exec echo 4 > /proc/stap_test_cmd expect { -timeout 5 "yyy_int64 -1 200 300\r\nyyy_int64 returns 499\r\n" { pass "int64 function arguments -- $tag" } timeout {fail "int64 function arguments -- $tag"} } exec echo 5 > /proc/stap_test_cmd expect { -timeout 5 "yyy_char a b c\r\nyyy_char returns Q\r\n" { pass "char function arguments -- $tag" } timeout {fail "char function arguments -- $tag"} } exec echo 6 > /proc/stap_test_cmd expect { -timeout 5 "yyy_str Hello-System-Tap\r\nyyy_str returns XYZZY\r\n" { pass "string function arguments -- $tag" } timeout {fail "string function arguments -- $tag"} } } -re "semantic error:" { fail "function arguments -- $tag: compilation failed" } timeout {fail "all function arguments tests - timeout"} eof {fail "function arguments -- $tag: unexpected timeout"} } exec kill -INT -[exp_pid] catch close wait systemtap-2.3/testsuite/systemtap.context/pid.stp000066400000000000000000000006021217430427200224600ustar00rootroot00000000000000probe module("systemtap_test_module2").function("yyy_int") { printf("execname: %s\n", execname()) printf("pexecname: %s\n", pexecname()) printf("pid: %d\n", pid()) printf("ppid: %d\n", ppid()) printf("tid: %d\n", tid()) printf("uid: %d\n", uid()) printf("euid: %d\n", euid()) printf("gid: %d\n", gid()) printf("egid: %d\n", egid()) exit() } probe begin { printf("READY\n") } systemtap-2.3/testsuite/systemtap.context/pid.tcl000066400000000000000000000014551217430427200224430ustar00rootroot00000000000000set tests [list execname pexecname pid ppid tid uid euid gid egid] spawn stap $srcdir/$subdir/pid.stp #exp_internal 1 expect { -timeout 120 "READY" { set pid [exec echo 1 > /proc/stap_test_cmd &] set ppid {[0-9]*} set uid [exec id -ru] set gid [exec id -rg] set euid [exec id -u] set egid [exec id -g] set results [list "execname: echo\r\n" "pexecname: expect\r\n" "pid: $pid\r\n" "ppid: $ppid\r\n" "tid: $pid\r\n" "uid: $uid\r\n" "euid: $euid\r\n" "gid: $gid\r\n" "egid: $egid\r\n"] set i 0 foreach t $tests { expect { -timeout 5 -re [lindex $results $i] { pass $t } timeout {fail "$t - timeout"} eof {fail "$t - unexpected EOF"} } incr i } } timeout {fail "all pid tests - timeout"} eof {fail "all pid tests - unexpected EOF"} } catch {close} wait systemtap-2.3/testsuite/systemtap.context/symbols.exp000066400000000000000000000005771217430427200233750ustar00rootroot00000000000000set test "symbols" if {![installtest_p]} { untested $test; return } spawn stap -g $srcdir/$subdir/symbols.stp set ok 0 expect { -timeout 120 -re { 0x[a-f0-9]+[^\r]*\r} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } #FIXME does not handle case of hanging symbols.stp correctly wait if {$ok == 11} { pass "$test ($ok)" } { fail "$test ($ok)" } systemtap-2.3/testsuite/systemtap.context/symbols.stp000077500000000000000000000005421217430427200234020ustar00rootroot00000000000000#! stap probe begin { # a spectrum of figures for 32-bit x86 print_syms ("0x0 0x80000000 0xc0000000 0xe0000000 0xf0000000 0xffffffff") # for x86_64 print_syms ("0xffffffff00000000 0xffffffff80000000 0xffffffff80120000") print_syms ("0xffffffff88000000 0xffffffffffffffff") # ... for a total of 11 lines, which symbols.exp counts exit () } systemtap-2.3/testsuite/systemtap.context/systemtap_test_module1.c000066400000000000000000000046561217430427200260530ustar00rootroot00000000000000/* -*- linux-c -*- * Systemtap Test Module 1 * Copyright (C) 2007 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. */ #include #include #include #include #include /* The purpose of this module is to provide a bunch of functions that */ /* do nothing important, and then call them in different contexts. */ /* We use a /proc file to trigger function calls from user context. */ /* Then systemtap scripts set probes on the functions and run tests */ /* to see if the expected output is received. This is better than using */ /* the kernel because kernel internals frequently change. */ /** These functions are in module 2 **/ /* They are there to prevent compiler optimization from */ /* optimizing away functions. */ int yyy_func1 (int); int yyy_int (int,int,int); unsigned yyy_uint (unsigned,unsigned,unsigned); long yyy_long (long,long,long); int64_t yyy_int64 (int64_t,int64_t,int64_t); char yyy_char(char, char, char); char *yyy_str(char *, char *, char *); /************ Below are the functions to create this module ************/ static struct proc_dir_entry *stm_ctl = NULL; static ssize_t stm_write_cmd (struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char type; if (get_user(type, (char __user *)buf)) return -EFAULT; switch (type) { case '0': yyy_func1(1234); break; case '1': yyy_int(-1, 200, 300); break; case '2': yyy_uint((unsigned)-1, 200, 300); break; case '3': yyy_long(-1L, 200L, 300L); break; case '4': yyy_int64(-1, 200, 300); break; case '5': yyy_char('a', 'b', 'c'); break; case '6': yyy_str("Hello", "System", "Tap"); break; default: printk ("systemtap_test_module1: invalid command type %d\n", (int)type); return -EINVAL; } return count; } static struct file_operations stm_fops_cmd = { .owner = THIS_MODULE, .write = stm_write_cmd, }; int init_module(void) { stm_ctl = proc_create ("stap_test_cmd", 0666, NULL, &stm_fops_cmd); if (stm_ctl == NULL) return -1; return 0; } void cleanup_module(void) { if (stm_ctl) remove_proc_entry ("stap_test_cmd", NULL); } MODULE_DESCRIPTION("systemtap backtrace test module1"); MODULE_LICENSE("GPL"); systemtap-2.3/testsuite/systemtap.context/systemtap_test_module2.c000066400000000000000000000042211217430427200260400ustar00rootroot00000000000000/* -*- linux-c -*- * Systemtap Test Module 2 * Copyright (C) 2007 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. */ #include #include #include /* The purpose of this module is to provide a bunch of functions that */ /* do nothing important, and then call them in different contexts. */ /* We use a /proc file to trigger function calls from user context. */ /* Then systemtap scripts set probes on the functions and run tests */ /* to see if the expected output is received. */ /** Here are all the functions we will probe **/ /* some nested functions to test backtraces */ int noinline yyy_func4 (int foo) { asm (""); return foo + 1; } int noinline yyy_func3 (int foo) { foo = yyy_func4(foo); asm (""); return foo + 1; } int noinline yyy_func2 (int foo) { foo = yyy_func3(foo); asm (""); return foo + 1; } int noinline yyy_func1 (int foo) { foo = yyy_func2(foo); asm (""); return foo + 1; } EXPORT_SYMBOL(yyy_func1); /* 1. int argument testing */ int noinline yyy_int(int a, int b, int c) { asm (""); return a+b+c; } /* 2. uint argument testing */ unsigned noinline yyy_uint(unsigned a, unsigned b, unsigned c) { asm (""); return a+b+c; } /* 3. long argument testing */ long noinline yyy_long(long a, long b, long c) { asm (""); return a+b+c; } /* 4. int64_t argument testing */ int noinline yyy_int64(int64_t a, int64_t b, int64_t c) { asm (""); return a+b+c; } /* 5. char argument testing */ char noinline yyy_char(char a, char b, char c) { asm (""); return 'Q'; } /* 5. string argument testing */ char * noinline yyy_str(char *a, char *b, char *c) { asm (""); return "XYZZY"; } EXPORT_SYMBOL(yyy_int); EXPORT_SYMBOL(yyy_uint); EXPORT_SYMBOL(yyy_long); EXPORT_SYMBOL(yyy_int64); EXPORT_SYMBOL(yyy_char); EXPORT_SYMBOL(yyy_str); MODULE_DESCRIPTION("systemtap backtrace test module2"); MODULE_LICENSE("GPL"); systemtap-2.3/testsuite/systemtap.context/uprobe_backtrace.stp000066400000000000000000000011171217430427200252010ustar00rootroot00000000000000probe process("uprobe_uaddr").function("main").call { print_ubacktrace() printf("\n") } probe process("uprobe_uaddr").function("main").return { print_ubacktrace() printf("\n") } probe process("uprobe_uaddr").function("func").call { print_ubacktrace() printf("\n") } probe process("uprobe_uaddr").function("func").return { print_ubacktrace() printf("\n") } probe process("uprobe_uaddr").function("func2").call { print_ubacktrace() printf("\n") } probe process("uprobe_uaddr").function("func2").return { print_ubacktrace() printf("\n") } systemtap-2.3/testsuite/systemtap.context/uprobe_stmt_num.c000066400000000000000000000004531217430427200245460ustar00rootroot00000000000000static int func2 (int x, int y) { return x + y; } static int func (int arg) { int x = 16; int y = arg - x; int z = func2(x, y); return x + y + z; } int main (int argc, char *argv[], char *envp[]) { // Note: Passing to srand to force evaluation of func(). srand(func(42)); return 0; } systemtap-2.3/testsuite/systemtap.context/uprobe_stmt_num.exp000066400000000000000000000050271217430427200251220ustar00rootroot00000000000000# Tests whether we can put statement probes on all lines of a function, # even without debuginfo around (in guru mode currently). PR10454. set test "uprobe_stmt_num" # Only run on make installcheck and uprobes present. if {! [installtest_p]} { untested "$test"; return } if {! [uprobes_p]} { untested "$test"; return } set testpath "$srcdir/$subdir" set testsrc "$testpath/$test.c" set testexe "[pwd]/$test" # We want debug info and no optimization (every line counts). set testflags "additional_flags=-g additional_flags=-O0" set teststp "$testpath/$test.stp" set res [target_compile $testsrc $testexe executable $testflags] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile $testsrc" return } set cmd [concat stap -wc $testexe $teststp] send_log "cmd: $cmd\n" catch {eval exec $cmd} output send_log "cmd output: $output\n" # There should be at least 6 address lines: function entry, 4 actual # source lines and function exit. Be sure to ignore any non-numeric # lines (since we only want to save the output addresses). set output_lines {} foreach line [split $output "\n"] { if {[regexp {^0x[0-9]+} $line]} { lappend output_lines "$line" } } set lines [llength $output_lines] if { $lines >= 6 } { pass "$test-run-one" } else { fail "$test-run-one ($lines)" } # Expect the same output for next runs set ::result_string $output # Sanity check, just run again... stap_run3 $test-run-two -w $testpath/$test.stp -c $testexe # create a script based on the given statements, # probe all of them individually. set fp [open $test-run-statements.stp "w"] foreach line $output_lines { puts $fp "probe process(\"uprobe_stmt_num\").statement($line)" puts $fp "{" puts $fp " printf(\"0x%x\\n\", uaddr());" puts $fp "}" } close $fp stap_run3 $test-run-statements -w $test-run-statements.stp -c $testexe # Now strip away the line info and try again (with -g). set strip_cmd [list "objcopy" "-R" ".debug_line"] lappend strip_cmd "$testexe" send_log "Executing: $strip_cmd\n" eval exec $strip_cmd stap_run3 $test-run-statements-nolines -w -g $test-run-statements.stp -c $testexe # XXX Last test still fails. PR10454. setup_kfail 10454 "*-*-*" # Now strip away all debuginfo. Since the script doesn't need any it # should still work. set strip_cmd [list "strip" "-g"] lappend strip_cmd "$testexe" send_log "Executing: $strip_cmd\n" eval exec $strip_cmd stap_run3 $test-run-statements-nodebuginfo -w -g $test-run-statements.stp -c $testexe # cleanup eval exec rm $testexe $test-run-statements.stp systemtap-2.3/testsuite/systemtap.context/uprobe_stmt_num.stp000066400000000000000000000001501217430427200251240ustar00rootroot00000000000000probe process("uprobe_stmt_num").statement("func@uprobe_stmt_num.c:*") { printf("0x%x\n", uaddr()); } systemtap-2.3/testsuite/systemtap.context/uprobe_uaddr.exp000066400000000000000000000033101217430427200243440ustar00rootroot00000000000000# Tests uaddr in function call and return probes. For a call probe we # expect the address to be in the function; for a return probe it # should be in the function's caller. set test "uprobe_uaddr" # Only run on make installcheck and uprobes present. if {! [installtest_p]} { untested "$test"; return } if {! [uretprobes_p]} { untested "$test"; return } set testpath "$srcdir/$subdir" set testsrc "$testpath/uprobe_stmt_num.c" set testexe "[pwd]/$test" # We want debug info and no optimization (every line counts). set testflags "additional_flags=-g additional_flags=-O0" set teststp "$testpath/$test.stp" set res [target_compile $testsrc $testexe executable $testflags] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile $testsrc" return } set cmd [concat stap -c $testexe $teststp] send_log "cmd: $cmd\n" catch {eval exec $cmd} output send_log "cmd output:\n $output\n" # Only save the address lines. set output_lines {} foreach line [split $output "\n"] { if {[regexp {0x[0-9]+} $line]} { lappend output_lines "$line" } } set lines [llength $output_lines] if { $lines == 6 } { pass "$test" } else { fail "$test ($lines)" } set result_funcs [list "main+*" "func+*" "func2+*" "func+*" "main+*"] set lnr 0 foreach expected $result_funcs output $output_lines { if {$expected != ""} { if [string match $expected $output] { pass "$test match line $lnr $expected" } else { fail "$test match line $lnr $expected $output" } incr lnr; } else { break; } } if [string match "main *" [lindex $output_lines 5]] { fail "$test return from main" } else { pass "$test return from main" } systemtap-2.3/testsuite/systemtap.context/uprobe_uaddr.stp000066400000000000000000000010301217430427200243530ustar00rootroot00000000000000probe process("uprobe_uaddr").function("main").call { println(usymdata(uaddr())) } probe process("uprobe_uaddr").function("main").return { println(usymdata(uaddr())) } probe process("uprobe_uaddr").function("func").call { println(usymdata(uaddr())) } probe process("uprobe_uaddr").function("func").return { println(usymdata(uaddr())) } probe process("uprobe_uaddr").function("func2").call { println(usymdata(uaddr())) } probe process("uprobe_uaddr").function("func2").return { println(usymdata(uaddr())) } systemtap-2.3/testsuite/systemtap.context/uprobe_uaddr_mark.c000066400000000000000000000001421217430427200250040ustar00rootroot00000000000000#include "sys/sdt.h" int main () { STAP_PROBE(testsuite, uprobe_uaddr_mark); return 0; } systemtap-2.3/testsuite/systemtap.context/uprobe_uaddr_mark.exp000066400000000000000000000013461217430427200253650ustar00rootroot00000000000000# Tests that uaddr matches the statement address of an SDT mark, # to show whether we're getting REG_IP munging right. set test "uprobe_uaddr_mark" set ::result_string {success} # Only run on make installcheck and uprobes present. if {! [installtest_p]} { untested "$test"; return } if {! [uprobes_p]} { untested "$test"; return } set testpath "$srcdir/$subdir" set testsrc "$testpath/$test.c" set testexe "[pwd]/$test" set testflags [sdt_includes] set teststp "$testpath/$test.stp" set res [target_compile $testsrc $testexe executable $testflags] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile $testsrc" return } stap_run3 $test $teststp -c $testexe catch {exec rm -f $test.exe} systemtap-2.3/testsuite/systemtap.context/uprobe_uaddr_mark.stp000066400000000000000000000005011217430427200253670ustar00rootroot00000000000000probe process("uprobe_uaddr_mark").mark("uprobe_uaddr_mark") { // Check that uaddr() is the same address as the pp() statement. statement = sprintf(".statement(%#x)", uaddr()) if (isinstr(pp(), statement)) println("success") else printf("failure: %#x doesn't match %s\n", uaddr(), pp()) } systemtap-2.3/testsuite/systemtap.context/usymbols.c000066400000000000000000000023761217430427200232070ustar00rootroot00000000000000/* usymbol test case * Copyright (C) 2008, Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. * * Uses signal to tranfer user space addresses into the kernel where a * probe on sigaction will extract them and produce the symbols. To * poke into the executable we get the sa_handler from the main executable, * and then the library through calling signal. * * FIXME. We call into the library to get the right symbol. If we * register the handler from the main executable. We need to handle * @plt symbols (setting a handler in the main executable that is in a * shared library will have the @plt address, not the address inside * the shared library). */ #include typedef void (*sighandler_t)(int); // function from our library int lib_main (void); void main_handler (int signum) { /* dummy handler, just used for the address... */ } int main (int argc, char *argv[], char *envp[]) { // Use SIGFPE since we never expect that to be triggered. signal(SIGFPE, main_handler); lib_main(); return 0; } systemtap-2.3/testsuite/systemtap.context/usymbols.exp000066400000000000000000000102171217430427200235520ustar00rootroot00000000000000set test "./usymbols" set testpath "$srcdir/$subdir" set testsrc "$testpath/usymbols.c" set testsrclib "$testpath/usymbols_lib.c" set testlibdir "[pwd]" set testflags "additional_flags=-g additional_flags=-O" # Only run on make installcheck and utrace present. if {! [installtest_p]} { untested "$test"; return } if {! [utrace_p]} { untested "$test"; return } if {! [uprobes_p]} { untested "$test"; return } # We need the execname() trick to work around (the workaround of) # PR6964 otherwise we get also the rt_sigactions of stapio. Get # the handler (comes from the executable or the library). # # We have to use @cast() on act_uaddr since syscall wrappers on # ppc64/s390x systems turn the 'struct sigaction' into a 'long int'. set testscript { probe syscall.rt_sigaction { if (pid() == target() && execname() == "%s") { // Note user address. handler = user_long(&@cast(act_uaddr, "struct sigaction")->sa_handler); try { printf("handler: %%s (%%s)\n", usymname(handler), umodname(handler)); } catch { printf("handler: %%s (%%s)\n", usymname(handler), ""); } } } probe syscall.rt_sigaction32 ? { if (pid() == target() && execname() == "%s") { // Note user address. handler = user_long(@defined(@cast(0, "compat_sigaction")->sa_handler) ? &@cast(act_uaddr, "compat_sigaction")->sa_handler : &@cast(act_uaddr, "sigaction32")->sa_handler); try { printf("handler: %%s (%%s)\n", usymname(handler), umodname(handler)); } catch { printf("handler: %%s (%%s)\n", usymname(handler), ""); } } } } for {set i 0} {$i < [all_compile_flags]} {incr i} { set extra_flag [all_compile_flag $i] set extra_name [all_compile_flag_name $i] verbose "testing usymbols $extra_name" set testexename "usymbols" set testlibname "usymbols" set maintestflags "$testflags additional_flags=-L$testlibdir additional_flags=-Wl,-rpath,$testlibdir" set testlibflags "testflags additional_flags=-fPIC additional_flags=-shared" set testexename "${testexename}-${extra_name}" set testlibname "${testlibname}-${extra_name}" set maintestflags "$maintestflags additional_flags=-l$testlibname $extra_flag" set testlibflags "$testlibflags $extra_flag" # Compile our test program and library. set testso "$testlibdir/lib${testlibname}.so" set res [target_compile $testsrclib $testso executable $testlibflags] if { $res != "" } { verbose "target_compile for $testso failed: $res" 2 fail "unable to compile usymbols_lib.c $extra_name" continue } set testexe "[pwd]/${testexename}" set res [target_compile $testsrc $testexe executable $maintestflags] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "unable to compile usymbols.c $extra_name" continue } # Originally the output string used 'pwd' to get the full path to # the testexename/testlibname. However, if the test directory has # a long path, the start of the path gets truncated in systemtap # output, so the test was failing. Now we just check for a path # ending in the correct filename. set output "handler: main_handler (.+/${testexename}) handler: lib_handler (.+/lib${testlibname}.so)" # Used to need to run stap with both the exe and the libraries # used as -d args. Now use --ldd to pick up both exe and the # library we just linked in. set script [format $testscript $testexename $testexename] send_log "script: $script\n" set cmd [concat stap -w -d $testexe --ldd -c $testexe -e {$script}] send_log "cmd: $cmd\n" catch {eval exec $cmd} res send_log "cmd output: $res\n" set n 0 set m [llength [split $output "\n"]] set expected [split $output "\n"] set nfails 0 foreach line [split $res "\n"] { if {![regexp [lindex $expected $n] $line]} { fail "usymbols $extra_name" send_log "line [expr $n + 1]: expected \"[lindex $expected $n]\", " send_log "Got \"$line\"\n" incr nfails } incr n } if { $n != $m } { fail "usymbols $extra_name" send_log "Got \"$n\" lines, expected \"$m\" lines\n" } elseif { $nfails == 0 } { pass "usymbols $extra_name" exec rm -f $testexe $testso } } systemtap-2.3/testsuite/systemtap.context/usymbols_lib.c000066400000000000000000000015231217430427200240260ustar00rootroot00000000000000/* usymbol test case - library helper * Copyright (C) 2008, Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. * * Uses signal to tranfer user space addresses into the kernel where a * probe on sigaction will extract them and produce the symbols. To * poke into the executable we get the sa_handler set through signal * from this library. */ #include typedef void (*sighandler_t)(int); void lib_handler (int signum) { /* dummy handler, just used for the address... */ } void lib_main () { // Use SIGFPE since we never expect that to be triggered. signal(SIGFPE, lib_handler); } systemtap-2.3/testsuite/systemtap.examples/000077500000000000000000000000001217430427200213105ustar00rootroot00000000000000systemtap-2.3/testsuite/systemtap.examples/README000066400000000000000000000130701217430427200221710ustar00rootroot00000000000000This text describes contribution procedures for adding scripts to systemtap.examples directory. Please read before submitting SystemTap examples. Discussions take place on the mailing list. - general The script should do something that normal users of SystemTap might like to do, such as show which processes have system calls that time out or show which memory accesses cause page faults. Scripts that check that some aspect of SystemTap operates correctly, but would never be used by a regular user should go in one of the other testsuite directories. - copyright You must designate the appropriate copyright holder for your contribution. The copyright holder is assumed to agree with the general licensing terms (GPLv2+). - coding style Abide by the general formatting of the code for SystemTap. The code base generally follows the GNU standards in usermode code and the Linux kernel standards in runtime code. - Try to keep the lines shorter than 80 characters long. - Make use of SystemTap functions to factor out common idioms in code. - Use tapset probe points rather than raw function names. - No probes by file and line number are allowed in examples. - Avoid using guru mode (-g) in the examples. - Minimize use of globals variables: All associative arrays must be global in SystemTap. Variables used only for the duration of a probe should be local. - Make the file executable and use the following line at the beginning of the script to select the proper interpreter: #! /usr/bin/env stap - Describe the example Each example script has a description in a .meta file that provide an easy-to-parse format that describes various aspect of the example script. The .meta file has the same base name as the example script. The .meta file is parsed to generate a web page listing all the available examples; the webpage is available at: http://sourceware.org/systemtap/examples/. The .meta file also describes how to run the compiled example script for testing. This ensures that the example is frequently run to verify it works on a wide range of platforms. The meta file contains the following elements. Each element (key and value) are on one line. If a key can have a list of values, the list elements are separated by spaces. title: Descriptive title for the script (required) name: the file name for the script, e.g. iotime.stp (required) version: versioning if any fixes and developed can be identified (required) author: name of author(s), "anonymous" if unknown (required) exclusivearch: Stated if the script can only run on some arches this concept borrowed from rpm, matches types for rpm: x86 i386 x86_64 ppc ppc64, s390 (optional) requires: Some scripts may require software to be available. In some cases may need version numbering, e.g. kernel >= 2.6 Can have multiple "requires:" tags. (optional) keywords: List of likely words to categorize the script (required) keywords are separated by spaces. autofs backtrace callgraph cpu device disk file filesystem format function futex interrupt io kvm limits locking memory monitoring nanosleep network nfs numa process profiling qemu scheduler scsi security signals simple slab socket statistics syscall tcp thread time trace tracepoint traffic tty utilization virtualization watchdog watchpoint subsystem: List what part of the kernel the instrumentation probes (required) any none audit cpu blockio file filesystem locking memory numa network process scheduler syscall or user-space (probes are in the user-space) application: when user-space probing becomes available (optional) a script might probe a particular application this tag indicates the applicaton status: describes the state of development for the script (required) proposed just an idea experimental an implemented idea, but use at own risk alpha beta production should be safe to use exit: how long does the script run? (required) fixed exits in a fixed amount of time user-controlled exits with "cntrl-c" event-ended exits with some arbitrary event output: what kind of output does the script generate? (required) trace histogram graph sorted-list batch timed on-exit scope: How much of the processes on the machine does the script watch? (required) system-wide, process or per-socket arg_[0-9]+: Describe what the arguments into the script are. (optional) description: A text description what the script does. (required) test_support: How to check that the example is applicable. Run by 'sh -c COMMAND'. (e.g. stap -l needed.probe) test_check: How to check that the example compiles. Run by 'sh -c COMMAND'. (e.g. stap -p4 iotime.stp) test_installcheck: How to check that the example runs. Run by 'sh -c COMMAND'. (e.g. stap iotime.stp -c "sleep 1") - Review, revision, and submission of the example script When you have a SystemTap script that should be included as an example, submit it to the SystemTap mailing list, systemtap@sourceware.org for review. Even if the script is not ready for submission as an example, feel free to ask questions or discuss the work-in-progress script with other people working with SystemTap. systemtap-2.3/testsuite/systemtap.examples/check.exp000066400000000000000000000061351217430427200231100ustar00rootroot00000000000000# check.exp # # This script searches the systemtap.examples directory for .meta files # The .meta files contain information categorizing the script. The # .meta files are composed of lines of tags. Each tag is followed by a # value. #open the file and read in all the lines of data in FILE #return a string with the data proc get_meta_data { FILE } { set meta_data "" catch { set fl [open "$FILE" RDONLY] set meta_data [read -nonewline $fl] close $fl } return $meta_data } #extract value for TAG from string META_DATA #if there is no matching tag return "" proc extract_tag { META_DATA TAG } { set taglines "" set value "" set expr "^$TAG: \[^\r\n\]*" regexp -line -all $expr $META_DATA taglines set expr "^$TAG: " regsub -line $expr $taglines "" value verbose -log "meta taglines '$taglines' tag '$TAG' value '$value'" return $value } proc run_command { test action command } { #FIXME tcl says that single quotes not dealt with if { $command != "" } then { verbose -log "attempting command $command" set res [catch {exec sh -c $command 2>@1} value] verbose -log "OUT $value" verbose -log "RC $res" if { $res != 0 } { # allow failure for support if { $action != "support" } { fail "$test $action" } return $res } else { pass "$test $action" return $res } } else { untested "$test $action" return 0 } } set src_examples [fullpath $srcdir/systemtap.examples] set meta_files [lsort [exec find $src_examples -path "*.meta"]] set curdir [pwd] verbose -log "SAVED PWD=$curdir" foreach file $meta_files { cd $curdir verbose -log "PRETEST PWD=[pwd]" set dir [file dirname $file] set test [regsub {.*/testsuite/} $file ""] set test [regsub {.meta} $test ""] set meta_data [get_meta_data $file] set test_support [extract_tag "$meta_data" "test_support"] # Do this after get_meta_data, as $file/$srcdir may be relative, # and become invalid after cd $dir. cd $dir verbose -log "TEST PWD=[pwd]" set command $test_support set supported_p 1 if { $command != "" } { # need to test support set res [run_command "$test" "support" $command] if { $res != 0 } { set supported_p 0 } } set build_p 1 if { $supported_p == 1 } { set test_check [extract_tag "$meta_data" "test_check"] set command $test_check set res [run_command "$test" "build" $command] if { $res != 0 } { set build_p 0 } } else { untested "$test build" continue } set test_installcheck [extract_tag "$meta_data" "test_installcheck"] # The pass/fail logic too simple and fails for some examples # FIXME would like to be able to run more complicated test code if {[info procs installtest_p] != "" && [installtest_p] && $test_installcheck != "" } then { if { $supported_p == 1 && $build_p == 1} { set command $test_installcheck run_command "$test" "run" $command } else { untested "$test run" } } } # get back to starting point cd $curdir verbose -log "RESTORED PWD=[pwd]" systemtap-2.3/testsuite/systemtap.examples/examples-index-gen.pl000077500000000000000000000176701217430427200253550ustar00rootroot00000000000000#! /usr/bin/perl # Generates index files from examples .meta file info. # Copyright (C) 2008-2011 Red Hat Inc. # # This file is part of systemtap, and is free software. You can # redistribute it and/or modify it under the terms of the GNU General # Public License (GPL); either version 2, or (at your option) any # later version. use strict; use warnings; use Cwd 'abs_path'; use File::Copy; use File::Find; use File::Path; use Text::Wrap; use HTML::Entities; my $inputdir; if ($#ARGV >= 0) { $inputdir = $ARGV[0]; } else { $inputdir = "."; } $inputdir = abs_path($inputdir); my $outputdir; if ($#ARGV >= 1) { $outputdir = $ARGV[1]; } else { $outputdir = $inputdir; } $outputdir = abs_path($outputdir); my %scripts = (); print "Parsing .meta files in $inputdir...\n"; find(\&parse_meta_files, $inputdir); my $meta; my $keyword; my %keywords; # Adds a formatted meta entry to a given file handle as text. sub add_meta_txt(*;$) { my($file,$meta) = @_; print $file "$scripts{$meta}{name} - $scripts{$meta}{title}\n"; # Don't output these, the description mentions all these in general. #print $file "output: $scripts{$meta}{output}, "; #print $file "exits: $scripts{$meta}{exit}, "; #print $file "status: $scripts{$meta}{status}\n"; print $file "keywords: $scripts{$meta}{keywords}\n"; $Text::Wrap::columns = 72; my $description = wrap(' ', ' ', $scripts{$meta}{description}); print $file "\n$description\n"; $Text::Wrap::separator = " \\\n"; my $usage = wrap('', ' ', $scripts{$meta}{test_installcheck}); print $file "\n # $usage\n"; $Text::Wrap::separator = "\n"; print $file "\n\n"; } # Adds a formatted meta entry to a given file handle as text. sub add_meta_html(*;$) { my($file,$meta) = @_; my $name = $scripts{$meta}{name}; print $file "$name "; print $file "- $scripts{$meta}{title}
\n"; # Don't output these, the description mentions all these in general. #print $file "output: $scripts{$meta}{output}, "; #print $file "exits: $scripts{$meta}{exit}, "; #print $file "status: $scripts{$meta}{status}
\n"; print $file "keywords: "; foreach $keyword (split(/ /, $scripts{$meta}{keywords})) { print $file '' . (uc $keyword) . " "; } print $file "
\n"; print $file "

".encode_entities($scripts{$meta}{description}); $Text::Wrap::separator = " \\\n"; my $usage = wrap('', '', $scripts{$meta}{test_installcheck}); $Text::Wrap::separator = "\n"; my $usage = encode_entities($usage); print $file "

# $usage
"; print $file "

\n"; } my $HEADER = "SYSTEMTAP EXAMPLES INDEX\n" . "(see also keyword-index.txt)\n\n"; my $header_tmpl = "$inputdir/html/html_header.tmpl"; open(TEMPLATE, "<$header_tmpl") || die "couldn't open $header_tmpl, $!"; my $HTMLHEADER = do { local $/;