Coder Social home page Coder Social logo

namhyung / uftrace Goto Github PK

View Code? Open in Web Editor NEW
2.9K 86.0 419.0 8.08 MB

Function graph tracer for C/C++/Rust/Python

Home Page: https://uftrace.github.io/slide/

License: GNU General Public License v2.0

Makefile 1.59% C 74.40% Assembly 1.39% Shell 0.49% C++ 0.38% Batchfile 0.01% Python 20.91% Dockerfile 0.19% Lua 0.27% HTML 0.06% JavaScript 0.29%
function tracer tracing trace

uftrace's Introduction

Nightly test Discord

uftrace

Packaging status

uftrace is a function call graph tracer for C, C++, Rust and Python programs.

It hooks into the entry and exit of each function, recording timestamps as well as the function's arguments and return values. uftrace is capable of tracing both user and kernel functions, as well as library functions and system events providing an integrated execution flow in a single timeline.

Initially, uftrace only supported function tracing with compiler support. However, it now allows users to trace function calls without recompilation by analyzing instructions in each function prologue and dynamically and selectively patching those instructions.

Users can also write and run scripts for each function entry and exit using python/luajit APIs to create custom tools for their specific purposes.

uftrace offers various filters to reduce the amount of trace data and provides visualization using Chrome trace viewer and flame graph or call-graph diagrams for graphviz and mermaid, allowing for a big picture view of the execution flow.

It was heavily inspired by the ftrace framework of the Linux kernel and the name uftrace stems from the combination of user and ftrace.

It can record data from:

  • User space C/C++/Rust functions, by either dynamically patching functions using -P., or else selective NOP patching using code compiled with -pg, -finstrument-functions or -fpatchable-function-entry=N.
  • C/C++/Rust Library functions (through PLT hooking)
  • Python functions (using Python's trace/profile infrastructure)
  • Kernel functions (using the ftrace framework in Linux kernel)
  • Kernel trace events (using event tracing framework in Linux kernel)
  • Task creation, termination and scheduling events (using Linux perf_event)
  • User space events in the target binary or libraries (using SystemTap SDT ABI)
  • PMU counter values for given functions (using Linux perf_event)

With the recorded data, uftrace can:

  • Show colored and nested function call graphs.
  • Show arguments and return values symbolically using libc function prototypes and DWARF debug information.
  • Apply filters to minimize the amount of trace data in both record and replay time.
  • Extract metadata from traces. (e.g. system information on which the trace was taken)
  • Generate symbol tables and memory maps of the traced program and library functions.
  • Generate task relationship trees (parent and children) of nested programs in traces.

It supports many commands and filters such as filtering by function call duration for analysis of program execution and performance.

uftrace-live-demo

Features

uftrace traces each function in the executable and shows time durations.

Usually, for this to be possible, the program needs to be compiled with -pg or -fpatchable-function-entry=5 (=2 is enough on aarch64). With full dynamic tracing (-P.|--patch=.), uftrace works on all executables (as long they are not stripped, or symbol information is available from a separate file).

uftrace hooks into the PLT in the given executable file to trace library calls and with (-l|--nest-libcall), it also hooks into the procedure linkage tables (PLTs) of shared libraries. The depth can be limited using -D<num>, where 1 is flat call tracing.

Using (-a|--auto-args), uftrace automatically records arguments and return values of known functions. Without extra debug information, this includes the API functions of standard (C language or system) libraries. This can be combined with -P. or -l: For example, -la traces nested library calls, even in stripped executables.

In addition, -a implies --srcline, so it records the source line location info, and this info can be shown by uftrace replay --srcline and in uftrace tui. Users can directly open the editor at the source location as shown in https://uftrace.github.io/slide/#120.

If debug information for the program (gcc -g) is available, --auto-args works even on functions inside the compiled the user programs.

In case argument information is not available, argument specifications like (-A udev_new@arg1/s) can be passed on the command line or an options file.

Example:

$ uftrace record -la -A udev_new@arg1/s lsusb >/dev/null
$ uftrace replay -f+module
or simply:
$ uftrace -la -A udev_new@arg1/s -f+module lsusb  # -f+module adds the module name
# DURATION     TID        MODULE NAME   FUNCTION
 306.339 us [ 23561]            lsusb | setlocale(LC_TYPE, "") = "en_US.UTF-8";
   1.163 us [ 23561]            lsusb | getopt_long(1, 0x7fff7175f6a8, "D:vtP:p:s:d:Vh") = -1;
            [ 23561]            lsusb | udev_new("POSIXLY_CORRECT") {
   0.406 us [ 23561] libudev.so.1.7.2 |   malloc(16) = 0x55e07277a7b0;
   2.620 us [ 23561]            lsusb | } /* udev_new */
            [ 23561]            lsusb | udev_hwdb_new() {
   0.427 us [ 23561] libudev.so.1.7.2 |   calloc(1, 200) = 0x55e07277a7d0;
   5.829 us [ 23561] libudev.so.1.7.2 |   fopen64("/etc/systemd/hwdb/hwdb.bin", "re") = 0;

Furthermore, it can show detailed execution flow at function level, and report which functions had the longest execution time. It also shows information about the execution environment.

You can set up filters to exclude or include specific functions when tracing. In addition, function arguments and return values can be saved and shown later.

It supports multi-process and/or multi-threaded applications. With root privileges and if the kernel was built with CONFIG_FUNCTION_GRAPH_TRACER=y, kernel functions can be traced as well.

How to build and install uftrace

On Linux distros, misc/install-deps.sh can be used to install required software(s) for building uftrace. Those are for optional and advanced features, but are highly recommended.

$ sudo misc/install-deps.sh

Once you installed required software(s) on your system, it can be built and installed like following:

$ ./configure
$ make
$ sudo make install

For details about installation and dependencies, please refer to INSTALL.md

How to use uftrace

These are the commands supported by uftrace:

  • record : runs a program and saves the trace data
  • replay : shows program execution in the trace data
  • report : shows performance statistics in the trace data
  • live : does record and replay in a row (default)
  • info : shows system and program info in the trace data
  • dump : shows low-level trace data
  • recv : saves the trace data from network
  • graph : shows function call graph in the trace data
  • script : runs a script for recorded trace data
  • tui : show text user interface for graph and report

You can use -h or --help option to see available commands and options.

$ uftrace
uftrace -- function (graph) tracer for userspace

 usage: uftrace [COMMAND] [OPTION...] [<program>]

 COMMAND:
   record          Run a program and saves the trace data
   replay          Show program execution in the trace data
   report          Show performance statistics in the trace data
   live            Do record and replay in a row (default)
   info            Show system and program info in the trace data
   dump            Show low-level trace data
   recv            Save the trace data from network
   graph           Show function call graph in the trace data
   script          Run a script for recorded trace data
   tui             Show text user interface for graph and report

Try `uftrace --help' or `man uftrace [COMMAND]' for more information.

If omitted, it defaults to the live command which is almost same as running record and replay subcommand in a row (but does not record the trace info to files).

For recording, the executable needs to be compiled with the -pg (or -finstrument-functions) option which generates profiling code (calling mcount or __cyg_profile_func_enter/exit) for each function.

Note that, there's an experimental support for dynamic tracing on x86_64 and AArch64(ARM64) which doesn't require such (re-)compilations. Also, recent compilers have some options to help uftrace to reduce tracing overhead with similar way (although it still needs recompilation of your program). Please see dynamic tracing section for more details.

$ uftrace tests/t-abc
# DURATION    TID     FUNCTION
  16.134 us [ 1892] | __monstartup();
 223.736 us [ 1892] | __cxa_atexit();
            [ 1892] | main() {
            [ 1892] |   a() {
            [ 1892] |     b() {
            [ 1892] |       c() {
   2.579 us [ 1892] |         getpid();
   3.739 us [ 1892] |       } /* c */
   4.376 us [ 1892] |     } /* b */
   4.962 us [ 1892] |   } /* a */
   5.769 us [ 1892] | } /* main */

For more analysis, you'd be better recording it first so that it can run analysis commands like replay, report, graph, dump and/or info multiple times.

$ uftrace record tests/t-abc

It'll create uftrace.data directory that contains trace data files. Other analysis commands expect the directory exists in the current directory, but one can use another using -d option.

The replay command shows execution information like above. As you can see, t-abc is a very simple program merely calls a, b and c functions. In the c function it called getpid() which is a library function implemented in the C library (glibc) on normal systems - the same goes to __cxa_atexit().

Users can use various filter options to limit functions it records/prints. The depth filter (-D option) is to omit functions under the given call depth. The time filter (-t option) is to omit functions running less than the given time. And the function filters (-F and -N options) are to show/hide functions under the given function.

The -k option enables to trace kernel functions as well (needs root access). With the classic hello world program, the output would look like below (Note, I changed it to use fprintf() with stderr rather than the plain printf() to make it invoke system call directly):

$ sudo uftrace -k tests/t-hello
Hello world
# DURATION    TID     FUNCTION
   1.365 us [21901] | __monstartup();
   0.951 us [21901] | __cxa_atexit();
            [21901] | main() {
            [21901] |   fprintf() {
   3.569 us [21901] |     __do_page_fault();
  10.127 us [21901] |     sys_write();
  20.103 us [21901] |   } /* fprintf */
  21.286 us [21901] | } /* main */

You can see the page fault handler and the system call handler for write() were called inside the fprintf() call.

Also, it can record and show function arguments and return value with -A and -R options respectively. The following example records first argument and return value of 'fib' (Fibonacci number) function.

$ uftrace record -A fib@arg1 -R fib@retval tests/t-fibonacci 5

$ uftrace replay
# DURATION    TID     FUNCTION
   2.853 us [22080] | __monstartup();
   2.194 us [22080] | __cxa_atexit();
            [22080] | main() {
   2.706 us [22080] |   atoi();
            [22080] |   fib(5) {
            [22080] |     fib(4) {
            [22080] |       fib(3) {
   7.473 us [22080] |         fib(2) = 1;
   0.419 us [22080] |         fib(1) = 1;
  11.452 us [22080] |       } = 2; /* fib */
   0.460 us [22080] |       fib(2) = 1;
  13.823 us [22080] |     } = 3; /* fib */
            [22080] |     fib(3) {
   0.424 us [22080] |       fib(2) = 1;
   0.437 us [22080] |       fib(1) = 1;
   2.860 us [22080] |     } = 2; /* fib */
  19.600 us [22080] |   } = 5; /* fib */
  25.024 us [22080] | } /* main */

The report command lets you know which function spends the longest time including its children (total time).

$ uftrace report
  Total time   Self time       Calls  Function
  ==========  ==========  ==========  ====================================
   25.024 us    2.718 us           1  main
   19.600 us   19.600 us           9  fib
    2.853 us    2.853 us           1  __monstartup
    2.706 us    2.706 us           1  atoi
    2.194 us    2.194 us           1  __cxa_atexit

The graph command shows function call graph of given function. In the above example, function graph of function 'main' looks like below:

$ uftrace graph  main
# Function Call Graph for 'main' (session: 073f1e84aa8b09d3)
=============== BACKTRACE ===============
 backtrace #0: hit 1, time  25.024 us
   [0] main (0x40066b)

========== FUNCTION CALL GRAPH ==========
  25.024 us : (1) main
   2.706 us :  +-(1) atoi
            :  |
  19.600 us :  +-(1) fib
  16.683 us :    (2) fib
  12.773 us :    (4) fib
   7.892 us :    (2) fib

The dump command shows raw output of each trace record. You can see the result in the Chrome browser, once the data is processed with uftrace dump --chrome. Below is a trace of clang (LLVM) compiling a small C++ template metaprogram.

uftrace-chrome-dump

It also supports flame-graph output as well. The data can be processed with uftrace dump --flame-graph and passed to flamegraph.pl. Below is a flame graph result of gcc compiling a simple C program.

uftrace-flame-graph-dump

The info command shows system and program information when recorded.

$ uftrace info
# system information
# ==================
# program version     : uftrace v0.8.1
# recorded on         : Tue May 24 11:21:59 2016
# cmdline             : uftrace record tests/t-abc
# cpu info            : Intel(R) Core(TM) i7-3930K CPU @ 3.20GHz
# number of cpus      : 12 / 12 (online / possible)
# memory info         : 20.1 / 23.5 GB (free / total)
# system load         : 0.00 / 0.06 / 0.06 (1 / 5 / 15 min)
# kernel version      : Linux 4.5.4-1-ARCH
# hostname            : sejong
# distro              : "Arch Linux"
#
# process information
# ===================
# number of tasks     : 1
# task list           : 5098
# exe image           : /home/namhyung/project/uftrace/tests/t-abc
# build id            : a3c50d25f7dd98dab68e94ef0f215edb06e98434
# exit status         : exited with code: 0
# elapsed time        : 0.003219479 sec
# cpu time            : 0.000 / 0.003 sec (sys / user)
# context switch      : 1 / 1 (voluntary / involuntary)
# max rss             : 3072 KB
# page fault          : 0 / 172 (major / minor)
# disk iops           : 0 / 24 (read / write)

The script command allows user to run a custom script on a data recorded. The supported script types are Python 3, Python 2.7 and Lua 5.1 as of now.

The tui command is for interactive text-based user interface using ncurses. It provides basic functionality of graph, report and info commands as of now.

Limitations

  • It can trace a C/C++/Rust/Python application on Linux and Android.
  • It cannot trace an already running process yet.
  • It was not designed for system-wide tracing in mind.
  • It mainly supports x86_64, AArch64 architectures. It also works on x86 (32-bit), ARM (v6 and v7) but some features like dynamic tracing and automatic argument fetching might not work well.

License

The uftrace program is released under GPL v2. See COPYING file for details.

uftrace's People

Contributors

ansbal avatar apatchydev avatar bernhardkaindl avatar binkoni avatar chokyuwon avatar claudiajkang avatar clementguidi avatar danieltimlee avatar dridi avatar ekyooo avatar fistki avatar gichoel avatar gy741 avatar henrychoi7 avatar honggyukim avatar hqsz avatar jonghyun-an avatar kangtegong avatar mirusu400 avatar namhyung avatar paranlee avatar parkhanbum avatar qpakzk avatar rls1004 avatar shpark avatar sypark9646 avatar taeguk avatar taeung avatar thepaul avatar yihong0618 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

uftrace's Issues

Fedora packaging FTBFS

I have a problem building the Fedora package from source on current master branch. Building with

./configure && make

works fine.

Spec file is here [1]. But that is not really important. Just the fact that the build system adds its own set of GCC switches (mostly security related) and has its own set of paths where binaries and libraries will be put.

Relevant build output:

<snip/>
+ cd uftrace-0.6.2
+ export 'CFLAGS=-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1'
+ CFLAGS='-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1'
+ export 'LDFLAGS=-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld'
+ LDFLAGS='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld'
+ ./configure --prefix=/usr --libdir=/usr/lib64/uftrace
+ /usr/bin/make -O -j2 V=1
  GEN      version.h
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-recv.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-recv.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-dump.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-dump.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-report.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-report.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-replay.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-replay.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-info.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-info.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-live.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-live.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE -DINSTALL_LIB_PATH='"/usr/lib64/uftrace"'  -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-record.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-record.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-graph.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-graph.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/rbtree.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/rbtree.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/session.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/session.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/pager.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/pager.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/data-file.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/data-file.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/filter.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/filter.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/debug.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/debug.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE -Wno-unused-value  -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/demangle.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/demangle.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/fstack.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/fstack.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/kernel.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/kernel.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/utils.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/utils.c
gcc -O2 -g -D_GNU_SOURCE -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/cpuinfo.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/cpuinfo.c
gcc -O2 -g -D_GNU_SOURCE -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/regs.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/regs.c
ld -r -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/uftrace.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/cpuinfo.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/regs.o
  FLAGS:   * new build flags or cross compiler
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/symbol.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/symbol.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/mcount.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/mcount.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/dynamic.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/dynamic.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/record.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/record.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/plthook.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/plthook.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/symbol.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/symbol.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/debug.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/debug.c
gcc -c -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -I /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/include   -D_GNU_SOURCE -std=gnu99 /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/event-parse.c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/event-parse.o
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/rbtree.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/rbtree.c
gcc -c -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -I /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/include   -D_GNU_SOURCE -std=gnu99 /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/event-plugin.c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/event-plugin.o
gcc -c -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -I /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/include   -D_GNU_SOURCE -std=gnu99 /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/trace-seq.c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/trace-seq.o
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/filter.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/filter.c
gcc -c -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -I /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/include   -D_GNU_SOURCE -std=gnu99 /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/parse-filter.c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/parse-filter.o
gcc -c -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -I /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/include   -D_GNU_SOURCE -std=gnu99 /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/parse-utils.c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/parse-utils.o
gcc -c -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -I /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/include   -D_GNU_SOURCE -std=gnu99 /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/kbuffer-parse.c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/kbuffer-parse.o
rm -f /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/libtraceevent.a; ar rcs /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/libtraceevent.a /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/event-parse.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/event-plugin.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/trace-seq.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/parse-filter.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/parse-utils.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/kbuffer-parse.o
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/demangle.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/demangle.c
gcc -fPIC -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/mcount.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/mcount.S
gcc -fPIC -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/fentry.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/fentry.S
gcc -fPIC -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/xray.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/xray.S
gcc -fPIC -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/plthook.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/plthook.S
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/utils.c
gcc -O2 -g -D_GNU_SOURCE -fPIC -fvisibility=hidden -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/mcount-dynamic.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/mcount-dynamic.c
gcc -O2 -g -D_GNU_SOURCE -fPIC -fvisibility=hidden -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/mcount-support.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/mcount-support.c
gcc -O2 -g -D_GNU_SOURCE -fPIC -fvisibility=hidden -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/regs.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/regs.c
ld -r -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/mcount-entry.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/mcount.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/fentry.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/xray.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/plthook.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/mcount-dynamic.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/mcount-support.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/regs.op
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -DDISABLE_MCOUNT_FILTER -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/mcount-fast.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/mcount.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -DDISABLE_MCOUNT_FILTER -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/dynamic-fast.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/dynamic.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -DDISABLE_MCOUNT_FILTER -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/record-fast.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/record.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -DDISABLE_MCOUNT_FILTER -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/plthook-fast.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/plthook.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -DSINGLE_THREAD -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/dynamic-single.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/dynamic.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -DSINGLE_THREAD -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/record-single.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/record.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -DSINGLE_THREAD -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/mcount-single.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/mcount.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -DSINGLE_THREAD -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/plthook-single.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/plthook.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -DDISABLE_MCOUNT_FILTER -DSINGLE_THREAD -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/dynamic-fast-single.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/dynamic.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -DDISABLE_MCOUNT_FILTER -DSINGLE_THREAD -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/mcount-fast-single.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/mcount.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -DDISABLE_MCOUNT_FILTER -DSINGLE_THREAD -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/record-fast-single.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/record.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/mcount-nop.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/mcount-nop.c
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -fPIC -fvisibility=hidden -DDISABLE_MCOUNT_FILTER -DSINGLE_THREAD -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/plthook-fast-single.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/plthook.c
gcc -shared -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/libmcount.so /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/mcount.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/dynamic.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/record.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/plthook.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/symbol.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/debug.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/rbtree.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/filter.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/demangle.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/mcount-entry.op -lelf -lrt -ldl -pthread -Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -lstdc++  
gcc -shared -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/libmcount-fast.so /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/mcount-fast.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/dynamic-fast.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/record-fast.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/plthook-fast.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/symbol.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/debug.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/rbtree.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/filter.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/demangle.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/mcount-entry.op -lelf -lrt -ldl -pthread -Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -lstdc++  
gcc -shared -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/libmcount-single.so /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/mcount-single.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/dynamic-single.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/record-single.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/plthook-single.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/symbol.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/debug.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/rbtree.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/filter.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/demangle.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/mcount-entry.op -lelf -lrt -ldl -pthread -Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -lstdc++  
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -c -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/uftrace.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/uftrace.c
gcc -shared -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/libmcount-nop.so /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/mcount-nop.op -lelf -lrt -ldl -pthread -Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -lstdc++  
gcc -shared -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/libmcount-fast-single.so /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/mcount-fast-single.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/dynamic-fast-single.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/record-fast-single.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libmcount/plthook-fast-single.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/symbol.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/debug.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/rbtree.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/filter.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/demangle.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils.op /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/mcount-entry.op -lelf -lrt -ldl -pthread -Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -lstdc++  
gcc -O2 -g -D_GNU_SOURCE -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1  -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2 -iquote /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64 -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers -DHAVE_CXA_DEMANGLE   -o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/uftrace /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/uftrace.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-recv.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-dump.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-report.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-replay.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-info.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-record.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-live.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/cmd-graph.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/session.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/rbtree.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/data-file.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/pager.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/demangle.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/filter.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/debug.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/fstack.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/kernel.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/symbol.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/utils/utils.o /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/uftrace.o -lelf -lrt -ldl -pthread -Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -lstdc++ -L/home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent -ltraceevent -ldl 
/usr/bin/ld: /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/uftrace.o: relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/uftrace.o: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
Makefile:203: recipe for target '/home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/uftrace' failed
make: *** [/home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/uftrace] Error 1
error: Bad exit status from /var/tmp/rpm-tmp.KVHUAf (%build)
<snip/>

It seems that uftrace binary objects are build without -fPIC enabled but a library (libtraceevent) that is linked is.

$ ls /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/libtraceevent.a 
/home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/libtraceevent.a
$ ar -x /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/libtraceevent/libtraceevent.a 
$ readelf --relocs trace-seq.o|egrep '(GOT|PLT|JU?MP_SLOT)'
000000000011  002100000004 R_X86_64_PLT32    0000000000000000 realloc - 4
00000000005c  002300000004 R_X86_64_PLT32    0000000000000000 fwrite - 4
00000000008f  002500000004 R_X86_64_PLT32    0000000000000000 malloc - 4
000000000104  002300000004 R_X86_64_PLT32    0000000000000000 fwrite - 4
000000000151  002800000004 R_X86_64_PLT32    0000000000000000 free - 4
00000000018c  002300000004 R_X86_64_PLT32    0000000000000000 fwrite - 4
000000000276  002a00000004 R_X86_64_PLT32    0000000000000000 __vsnprintf_chk - 4
0000000002e3  002300000004 R_X86_64_PLT32    0000000000000000 fwrite - 4
0000000002f4  002b00000004 R_X86_64_PLT32    0000000000000000 __stack_chk_fail - 4
00000000034e  002a00000004 R_X86_64_PLT32    0000000000000000 __vsnprintf_chk - 4
0000000003af  002300000004 R_X86_64_PLT32    0000000000000000 fwrite - 4
0000000003fc  002e00000004 R_X86_64_PLT32    0000000000000000 strlen - 4
00000000045c  002f00000004 R_X86_64_PLT32    0000000000000000 memcpy - 4
0000000004b1  002300000004 R_X86_64_PLT32    0000000000000000 fwrite - 4
0000000004da  002300000004 R_X86_64_PLT32    0000000000000000 fwrite - 4
0000000005af  002300000004 R_X86_64_PLT32    0000000000000000 fwrite - 4
0000000005d8  002300000004 R_X86_64_PLT32    0000000000000000 fwrite - 4
000000000641  002300000004 R_X86_64_PLT32    0000000000000000 fwrite - 4
000000000688  003300000004 R_X86_64_PLT32    0000000000000000 puts - 4
0000000006d9  003300000004 R_X86_64_PLT32    0000000000000000 puts - 4
0000000006fd  002300000004 R_X86_64_PLT32    0000000000000000 fwrite - 4
0000000006b3  003400000004 R_X86_64_PLT32    0000000000000000 __printf_chk - 4

But when I test uftrace.o

$ readelf --relocs /home/bkircher/rpmbuild/BUILD/uftrace-0.6.2/arch/x86_64/uftrace.o|egrep '(GOT|PLT|JU?MP_SLOT)' 
exit 1

Sorry, if this is a problem with the spec file and not a problem with uftrace. I am just a bit lost.

[1] https://bugzilla.redhat.com/show_bug.cgi?id=1398922

more issues in kernel function support

@namhyung I've tested some features for kernel function tracing and have some comments as follows:

  1. time filter for kernel functions in record command doesn't filter-out kernel functions that spent less time than threshold. (maybe already aware of it)
  2. 'trace' trigger is not working for kernel functions
  3. graph command result seems to include kernel functions out of main function by default and --kernel-skip-out option is not working with graph command. This is tested when kernel function is given as last argument. (e.g. __do_page_fault)

Please have a look at it.

Making -f elapsed or timestamp as default when -r is given

As commited in b12ffd5, users have to use -r/--time-range option as follows:

  $ uftrace replay -f elapsed -r +8us~
  #  ELAPSED    FUNCTION
     8.174 us |         getpid();
     9.585 us |       } /* c */
     9.845 us |     } /* b */
    10.022 us |   } /* a */
    10.191 us | } /* main */

But I think it'd be better to make -f elapsed or -f timestamp as default depending on RANGE stlye. For example, the above example can be simplified as follows:

  $ uftrace replay -r +8us~
  #  ELAPSED    FUNCTION
     8.174 us |         getpid();
     9.585 us |       } /* c */
     9.845 us |     } /* b */
    10.022 us |   } /* a */
    10.191 us | } /* main */

(implicit) argument display problem

Hi @namhyung ,

I've found some problem with the below example:

#include <vector>

int foo(int a)
{
  return a + 1;
}

std::vector<int> bar(int a)
{
  std::vector<int> v;
  v.push_back(a);
  return v;
}

int main()
{
  foo(10);
  bar(10);
}

After compiling it with g++, I run it with the below command:

$ g++ -pg test.cc
$ uftrace -D 2 -A foo@arg1 -A bar@arg1,arg2 ./a.out
# DURATION    TID     FUNCTION
   2.077 us [149041] | __cxa_atexit();
            [149041] | main() {
   0.803 us [149041] |   foo(10);
   9.520 us [149041] |   bar(0x7ffcea799440, 10);
   3.640 us [149041] |   std::vector::~vector();
  15.797 us [149041] | } /* main */

The strange thing is that bar accepts only one argument but the given parameter is shown at the second argument, i.e. arg2.

Because of this, argument printing is not properly done in some cases.
Is there anyway to handle this case?

PLT hook segfault about GCC 7

There is no this problem of uftrace built by gcc 5.4.1.
But when building uftrace by gcc 7.0.1, I found the segmentation fault about PLT hook like below.

# normal tracing

$ uftrace tests/t-abc
WARN: invalid task file
child terminated by signal: 11: Segmentation fault
# DURATION    TID     FUNCTION

But if using --no-libcall, the segmentation fault didn't appear.

$ uftrace --no-libcall t-abc
# DURATION    TID     FUNCTION
            [ 5133] | main() {
            [ 5133] |   a() {
            [ 5133] |     b() {
   0.982 us [ 5133] |       c();
   1.854 us [ 5133] |     } /* b */
   2.170 us [ 5133] |   } /* a */
   2.792 us [ 5133] | } /* main */

If checking core file, you can see libmcount/plthook.c:429

Reading symbols from t-abc...(no debugging symbols found)...done.
[New LWP 5249]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `t-abc'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007ff5a1b8a322 in plthook_entry (ret_addr=0x7ffd79fb0378, child_idx=1, 
    module_id=140692961395048, regs=0x7ffd79fb0338)
    at /home/taeung/git/uftrace/libmcount/plthook.c:429
429		struct ftrace_trigger tr = {

Clang X-ray dynamic tracing support

Clang/LLVM 4.0 provides a dynamic tracing feature called X-ray. It's similar to gcc -mfentry -mnop-mcount but it also supports the exit path (like -finstrument-functions). In the end, it's more powerful and safe, but generates more bloated code - and it seems that the xray library is linked statically to the executable.

I pushed the code into review/xray-support-v1 branch. Anyone can play with the clang 4, please test! The usage is same as the dynamic patch (-P option):

$ clang -fxray-instrument -fxray-instruction-threshold=1 -o abc-xray  tests/s-abc.c

$ uftrace -P main abc-xray
# DURATION    TID     FUNCTION
            [11093] | main() {
   1.659 us [11093] |   getpid();
   5.963 us [11093] | } /* main */

child terminated by signal: 11: Segmentation fault

Hi Namhyung !

I found a error in the situation as below.
(I tested on the latest master branch.)

$ cat hello.c
#include <stdio.h>

void main()
{
	printf("hello\n");
}
$ gcc -pg -o hello hello.c
$ uftrace record hello 
child terminated by signal: 11: Segmentation fault

I a bit looked into the situation debugging uftrace.
And I found several things as below.
First, segment fault happened in libmcount-fast.so

$ tail -f /var/log/kern.log
... (omitted) ...

Feb  8 22:50:55 taeung-ThinkPad-X1-Carbon-3rd kernel: [427108.691576] hello[1245]: segfault at 7ffd3e049fd8 ip 00007ff209b03e0f sp 00007ffd3e049fe0 error 6 in libmcount-fast.so[7ff209aff000+15000]
...

And after poll() at cmd-record.c, POLLHUP was returned so read_record_mmap() didn't work even once.

$ cat cmd-record.c
...
1481         while (!uftrace_done) {
1482                 struct pollfd pollfd = {
1483                         .fd = pfd[0],
1484                         .events = POLLIN,
1485                 };
1486                 int ret;
1487 
1488                 ret = poll(&pollfd, 1, 1000);
1489                 if (ret < 0 && errno == EINTR)
1490                         continue;
1491                 if (ret < 0)
1492                         pr_err("error during poll");
1493 
1494                 if (pollfd.revents & POLLIN)
1495                         read_record_mmap(pfd[0], opts->dirname, opts->bufsize);
1496 
1497                 if (pollfd.revents & (POLLERR | POLLHUP))
1498                         break;
1499         }
...

So the uftrace.data has not task.txt as below but we can know info as below

$ ls uftrace.data
hello.sym  info

$ cat uftrace.data/info 
Ftrace!�(��c���exename:/home/taeung/workspace/perf-test/test_hello
build_id:d456fe41bf063dc8db3135b8d8d58723ad3dd23c
exit_status:139
cmdline:/home/taeung/git/uftrace/uftrace record test_hello 
cpuinfo:lines=2
cpuinfo:nr_cpus=4 / 4 (online/possible)
cpuinfo:desc=Intel(R) Core(TM) i7-5500U CPU @ 2.40GHz
meminfo:1.6 / 7.4 GB (free / total)
osinfo:lines=3
osinfo:kernel=Linux 4.5.0-rc4+
osinfo:hostname=taeung-ThinkPad-X1-Carbon-3rd
osinfo:distro="Ubuntu 16.04 LTS"
usageinfo:lines=6
usageinfo:systime=0.004000
usageinfo:usrtime=0.000000
usageinfo:ctxsw=3 / 1 (voluntary / involuntary)
usageinfo:maxrss=10736
usageinfo:pagefault=0 / 2214 (major / minor)
usageinfo:iops=0 / 0 (read / write)
loadinfo:0.31 / 0.30 / 0.27

And output of runtest.py

Test case             pg             finstrument-fu
--------------------: O0 O1 O2 O3 Os O0 O1 O2 O3 Os
001 basic           : OK OK OK OK OK OK OK OK OK OK
...
016 alloca          : OK OK OK OK OK OK NG NG NG NG
...
052 nested_func     : OK OK OK OK OK NG NG NG NG NG
...
058 arg_int         : OK OK OK OK OK SK SK SK SK SK
059 arg_str         : OK OK OK OK OK SK SK SK SK SK
060 arg_fmt         : OK OK OK OK OK SK SK SK SK SK
061 arg_plt         : OK OK OK OK OK OK OK OK OK OK
062 arg_char        : OK OK OK OK OK SK SK SK SK SK
063 retval          : OK OK OK OK OK SK SK SK SK SK
064 trigger_trace   : OK OK OK OK OK OK OK OK OK OK
065 arg_order       : OK OK OK OK OK SK SK SK SK SK
066 no_demangle     : OK OK OK OK OK OK OK OK OK OK
067 report_diff     : OK OK OK OK OK OK OK OK OK OK
068 filter_time_A   : OK OK OK OK OK SK SK SK SK SK
...
079 replay_kernel_D : SK SK SK SK SK SK SK SK SK SK
080 replay_kernel_D2: SK SK SK SK SK SK SK SK SK SK
081 kernel_depth    : SK SK SK SK SK SK SK SK SK SK
...
103 dump_kernel     : SK SK SK SK SK SK SK SK SK SK
104 graph_kernel    : SK SK SK SK SK SK SK SK SK SK
...
124 exception       : NG SG SG SG SG OK OK OK OK OK
125 report_range    : OK OK OK OK OK OK OK OK OK OK
...

Don't libmcount-fast.so handle the error ?
I don't find out the root cause..

Discussion: Handling several types of arguments when recording with arguments of all functions

To find out first arguments of all functions, we can run uftrace -A .@arg1 ./a.out.
And then we can see as below.

$ uftrace -A .@arg1 ./a.out
# DURATION    TID     FUNCTION
   1.348 us [ 1178] | __monstartup(0x400820);
   0.720 us [ 1178] | __cxa_atexit(0x7fea2fa47cc0);
            [ 1178] | main(1) {
   6.120 us [ 1178] |   fgets(0x7ffd453e0f70);

...(omitted)...

But if we do, we can only see just addresses.
It isn't readable to human being.. 😟

So if we run uftrace -A .@arg1/s ./a.out, the segment fault occurs as below.

$ uftrace -A .@arg1/s ./a.out
child terminated by signal: 11: Segmentation fault
# DURATION    TID     FUNCTION
   1.053 us [ 1263] | __monstartup("1<ED>I<89><D1>^H<89><E2>H<83><E4><F0>PTL<8D>^Ez^E");
   0.443 us [ 1263] | __cxa_atexit("H<83><EC>^H<E8><87><E5><FF><FF><E8>"�");

Sure, it is wrong to use -A .@arg1/s because all first arguments of all functions aren't string type.

By the way, you see core dump file,
(As you know, the reason of above problem is that all first arguments of all functions aren't string type format.)

$ gdb ./a.out ./core
GNU gdb (Ubuntu 7.11-0ubuntu1) 7.11
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./a.out...(no debugging symbols found)...done.
[New LWP 32399]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  save_to_argbuf (argbuf=argbuf@entry=0x7f4c9b951010, args_spec=0x1803120, 
    ctx=ctx@entry=0x7ffdb9714c40) at /home/taeung/git/uftrace/libmcount/record.c:264

warning: Source file is more recent than executable.
264						dst[i] = str[i];
(gdb) list
259					 * registers (on x86) depends on the internal
260					 * implementation.  Do it manually.
261					 */
262					len = 0;
263					for (i = 0; i < max_size - total_size; i++) {
264						dst[i] = str[i];
265						if (!str[i])
266							break;
267						len++;
268					}
(gdb) bt
#0  save_to_argbuf (argbuf=argbuf@entry=0x7f4c9b951010, args_spec=0x1803120, 
    ctx=ctx@entry=0x7ffdb9714c40) at /home/taeung/git/uftrace/libmcount/record.c:264
#1  0x00007f4c9b644be0 in save_argument (mtdp=<optimized out>, rstack=0x1806280, 
    args_spec=<optimized out>, regs=<optimized out>)
    at /home/taeung/git/uftrace/libmcount/record.c:306
#2  0x00007f4c9b643401 in mcount_entry_filter_record (mtdp=mtdp@entry=0x7f4c9ba53748, 
    rstack=rstack@entry=0x1806280, tr=tr@entry=0x7ffdb9714cc0, regs=regs@entry=0x7ffdb9714d38)
    at /home/taeung/git/uftrace/libmcount/mcount.c:372
#3  0x00007f4c9b643574 in mcount_entry (parent_loc=0x7ffdb9714dc8, child=4197217, 
    regs=0x7ffdb9714d38) at /home/taeung/git/uftrace/libmcount/mcount.c:531
#4  0x00007f4c9b6505d1 in mcount () from /usr/local/lib/libmcount.so
#5  0x0000000000400b6a in main ()
(gdb) quit

In this case, IMHO if first arguments of some functions are actually string type, we can show it as string value
but if first arguments of other functions isn't actually string type, we can print just a address instead. 😄

What do you think about it?
How do you handle several type of arguments of functions ?
Do you have a plan to automatize detecting type of argument (formats : such as i,u,x,c,s,f) ?

For example,
Enable user to run just e.g. uftrace -A .@arg1/auto to see value of arguments whatever they are string, integer, float or etc.

What do you think about it, too ?

odd result from uftrace replay --kernel on ARM32

Hi, @namhyung

I think that the result of uftrace with any example on arm32 is very similar to a result with the same example on x86_64, basically.

Log from uftrace ./hello on x86_64:

$ uftrace ./hello
Hello world
# DURATION    TID     FUNCTION
   1.124 us [23238] | __monstartup();
   0.667 us [23238] | __cxa_atexit();
            [23238] | main() {
   7.538 us [23238] |   printf();
   8.301 us [23238] | } /* main */

Log from uftrace ./hello on arm32:

$ uftrace ./hello -kernel
Hello world
# DURATION    TID     FUNCTION
  17.700 us [ 2337] | __cxa_atexit();
            [ 2337] | main() {
  73.500 us [ 2337] |   printf();
  89.600 us [ 2337] | } /* main */

The results are very similar to each other. By the way, using --kernel option, they show quite different results as below.

Log from uftrace --kernel ./hello on x86_64:

$ uftrace --kernel ./hello
Hello world
# DURATION    TID     FUNCTION
   1.040 us [23246] | __monstartup();
   0.650 us [23246] | __cxa_atexit();
            [23246] | main() {
            [23246] |   printf() {
            [23246] |     sys_newfstat() {
   0.974 us [23246] |       smp_irq_work_interrupt();
   4.759 us [23246] |     } /* sys_newfstat */
   3.685 us [23246] |     sys_mmap();
   3.773 us [23246] |     __do_page_fault();
   1.861 us [23246] |     smp_irq_work_interrupt();
  22.089 us [23246] |   } /* printf */
  22.880 us [23246] | } /* main */

Log from uftrace --kernel ./hello on arm32:

$ uftrace --kernel ./hello        
Hello world
# DURATION    TID     FUNCTION
   4.900 us [ 2342] | __cxa_atexit();
            [ 2342] | sys_clock_gettime() {
  20.800 us [ 2342] |   gic_handle_irq();
  45.600 us [ 2342] | } /* __cxa_atexit */
   5.000 us [ 2342] | main();
            [ 2342] | sys_clock_gettime() {
            [ 2342] |   printf() {
   4.900 us [ 2342] |   } /* sys_clock_gettime */
  15.600 us [ 2342] |   sys_fstat64();
  42.900 us [ 2342] |   sys_mmap_pgoff();
  48.500 us [ 2342] |   do_page_fault();
            [ 2342] |   sys_clock_gettime() {
   7.700 us [ 2342] |   } /* printf */
 176.200 us [ 2342] | } /* sys_clock_gettime */
  20.700 us [ 2342] | gic_handle_irq();
   8.200 us [ 2342] | sys_clock_gettime();

I think there is something wrong in arm32, but I don't know whether it is a bug or not. Could you please let me know how do I fix it? And I left some related-questions.

  1. Why they are different entry point? Both of them have a similar hello.sym file.
  2. I think uftrace report on arm shows odd result, too. IMHO, It seems that sys_clock_gettime() returns wrong result in record phase. So I was thinking the problems comes from arch_timer in armv7. By the way, date command returns correct result on my machine.

uftrace report on arm: It shows that __cxa_atexit spent most of the time in application.

$uftrace report
  Total time   Self time       Calls  Function
  ==========  ==========  ==========  ====================================
   37.600 us   19.700 us           1  __cxa_atexit
    8.000 us    8.000 us           2  sys_clock_gettime
    6.500 us    6.500 us           1  printf
    6.300 us    6.300 us           1  main

new 'read' trigger action

This 'read' trigger support reading some data when executing given function(s). It could be some global variable, process stat (like rusage) or system-wide info. I don't want to make it too general as it could be handled with proposed scripting support. So I'll focus on a couple of specific usage only. Currently I plan to have rusage support (for memory/RSS info) but it could be extended if needed.

I wrote a PoC code using "read=rusage" trigger like below:

$ uftrace  -T a@read=rusage  tests/t-abc
# DURATION    TID     FUNCTION
            [20028] | main() {
            [20028] |   a() {
            [20028] |     /* read:rusage (rss = 3092KB) */
            [20028] |     b() {
            [20028] |       c() {
   1.448 us [20028] |         getpid();
  10.270 us [20028] |       } /* c */
  11.250 us [20028] |     } /* b */
  18.380 us [20028] |   } /* a */
  19.537 us [20028] | } /* main */

As you can see when it enters to the function "a", it reads the rusage info, save it and display it as an event (comment). Maybe I can also make it read the same at the function exit, but I'd like to hear some feedback before doing that.

The code was pushed to review/trigger-read-v1.

-mfentry segfault on GCC 7

Hello,

When building uftrace by gcc 7, I found the segmentation fault at libmcount/mcount.c:515.
It is similar to #91

gcc : 7.0.1
git-branch : master

  • dynamic tracing test environment
$ gcc -dumpversion
7.0.1

$ git status | head -1
On branch master

$ sudo make clean && sudo make install

  • Segmentation fault at libmcount/mcount.c:515.
    (This situation is same whatever target problem(abc.dyn) is built by e.g. gcc 5,6,7)
$ gcc -pg -mfentry -mnop-mcount -o abc.dyn tests/s-abc.c

$ uftrace -P . abc.dyn
child terminated by signal: 11: Segmentation fault
# DURATION    TID     FUNCTION
   0.668 us [ 8281] | __monstartup();
   0.500 us [ 8281] | __cxa_atexit();
  • Check core file with gdb
$ gdb abc.dyn core
...
Reading symbols from abc.dyn...(no debugging symbols found)...done.
[New LWP 8281]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `abc.dyn'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007fb4135f05c2 in mcount_entry (parent_loc=0x7fffaaef5948, child=4195955, 
    regs=0x7fffaaef5910) at /home/taeung/git/uftrace/libmcount/mcount.c:515
515		struct ftrace_trigger tr = {

basic support for FlameGraph

While dumping to chrome tracing format is extremely useful, some people prefer or accustom to the FlameGraph. So it'd be better to support both format as they also has subtle differences.

Add dump subcommand --flame-graph option to collapse function call stacks (like graph does) and feed it to the flamegraph.pl script. This just uses invocation count for now but it might support to use duration as an option.

The code was pushed to review/flame-graph branch:

$ uftrace dump --flame-graph -d node-1ms.data | flamegraph.pl > flamegraph-node-1ms.svg

Below is the generated svg file.
flamegraph of uftrace node -t 1ms

Getting source line number with --symbol-with-addr option

Sometimes it'd be better to see information of source line numbers to understand the exact locations of the functions during replay, report, and graph commands. To clearly address this issue, we may have to support libdwarf but I think we can go to a simpler way by just showing address with each symbol.

So why don't we add an option named --symbol-with-addr to show address with symbol. For example, the replay output looks like this.

$ uftrace replay --symbol-with-addr
# DURATION    TID     FUNCTION
   0.587 us [12264] | <400a90> __cxa_atexit();
            [12264] | <400e15> main() {
  30.911 us [12264] |   <400dd7> __static_initialization_and_destruction_0();
  31.037 us [12264] | } /* <400e15> main */
            [12264] | <400ca2> main() {
   0.627 us [12264] |   <400e4e> std::vector::vector();
   0.030 us [12264] |   <400ed8> __gnu_cxx::__normal_iterator::__normal_iterator();
   7.651 us [12264] |   <400ef6> std::vector::push_back();
    ...

In this case, we can see the source line number by using addr2line with the address above. If we want to see the location of std::vector::push_back, we can find it as follows.

$ addr2line -e a.out 400ef6
/usr/include/c++/4.8/bits/stl_vector.h:901

Tracing chromium web browser

Hi,

I've tried to trace chromium project using uftrace to understand how web browser works.
To make the work easier, I think it'd be better to run it as headless mode that is developed for better automatic test and scripting. It's also chrome browser without UI so it'd be better work with uftrace.
https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md

I first modified the build script to add -finstrument-functions option as below:

diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 50ee2a6a40da..2f8b732684d6 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -133,9 +133,9 @@ config("default_include_dirs") {

 config("compiler") {
   asmflags = []
-  cflags = []
-  cflags_c = []
-  cflags_cc = []
+  cflags = [ "-finstrument-functions" ]
+  cflags_c = [ "-finstrument-functions" ]
+  cflags_cc = [ "-finstrument-functions" ]
   cflags_objc = []
   cflags_objcc = []
   ldflags = []

After build is completed, it works fine.

$ ./headless_shell https://www.google.com
[1227/140319:INFO:fake_audio_manager.cc(23)] FakeAudioManager
[1227/140323:INFO:fake_audio_manager.cc(27)] ~FakeAudioManager

In order to make the environment simpler, I used --no-sandbox option and it also works fine.
http://www.chromium.org/developers/design-documents/sandbox

$ ./headless_shell --no-sandbox https://www.google.com
[1227/140735:INFO:fake_audio_manager.cc(23)] FakeAudioManager
[1227/140739:INFO:fake_audio_manager.cc(27)] ~FakeAudioManager

But I found segfault when I run it with uftrace as below:

$ uftrace record --no-pager -D 1 ./headless_shell --no-sandbox https://www.google.com
[1227/134556:INFO:fake_audio_manager.cc(23)] FakeAudioManager
child terminated by signal: 11: Segmentation fault

The replay output shows some results but it also shows broken data as follows:

$ uftrace replay
# DURATION    TID     FUNCTION
   2.507 us [13715] | std::basic_ios::init();
   0.337 us [13715] | std::basic_ios::init();
   0.279 us [13715] | std::basic_ios::init();
   0.259 us [13715] | std::basic_ios::init();
   0.569 us [13715] | GoogleInitializer::GoogleInitializer();
   0.156 us [13715] | LowLevelAlloc::Arena::Arena();
   0.057 us [13715] | LowLevelAlloc::Arena::Arena();
   0.066 us [13715] | LowLevelAlloc::Arena::Arena();
 103.942 us [13715] | _GLOBAL__N_1::SpinLock_InitHelper::SpinLock_InitHelper();
    ...
   0.027 us [13715] | SkColorSetARGBInline();
   0.694 us [13715] | google::protobuf::internal::_GLOBAL__N_1::InitDetector::InitDetector();
  15.767 us [13744] | cfree();
  40.113 us [13744] | cfree();
                    |   /* inverted time: broken data? */
  15.767 us [13744] | cfree();
  40.113 us [13744] | cfree();

The below shows the core dump backtrace, so please have a look at it:

$ gdb ./headless_shell core
  ...
Reading symbols from ./headless_shell...done.
[New LWP 13744]
[New LWP 13742]
[New LWP 13746]
[New LWP 13715]
[New LWP 13745]
[New LWP 13734]
[New LWP 13725]
[New LWP 13733]
[New LWP 13741]
[New LWP 13740]
[New LWP 13739]
[New LWP 13737]
[New LWP 13743]
[New LWP 13738]
[New LWP 13736]
[New LWP 13735]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `/home/honggyu/work.hdd/chromium/src/out/Debug.53/head'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007ff3b30d084c in record_ret_stack (mtdp=mtdp@entry=0x7ff3a83e8670, type=type@entry=FTRACE_ENTRY, mrstack=mrstack@entry=0x160ef8a36020)
    at /home/honggyu/src/uftrace/git/uftrace/libmcount/record.c:356
356             struct mcount_shmem_buffer *curr_buf = shmem->buffer[shmem->curr];
(gdb) bt
#0  0x00007ff3b30d084c in record_ret_stack (mtdp=mtdp@entry=0x7ff3a83e8670, type=type@entry=FTRACE_ENTRY, mrstack=mrstack@entry=0x160ef8a36020)
    at /home/honggyu/src/uftrace/git/uftrace/libmcount/record.c:356
#1  0x00007ff3b30d0f35 in record_trace_data (mtdp=mtdp@entry=0x7ff3a83e8670, mrstack=mrstack@entry=0x160ef8a36020, retval=retval@entry=0x0)
    at /home/honggyu/src/uftrace/git/uftrace/libmcount/record.c:483
#2  0x00007ff3b30cef46 in mcount_exit_filter_record (mtdp=0x7ff3a83e8670, rstack=0x160ef8a36020, retval=0x0) at /home/honggyu/src/uftrace/git/uftrace/libmcount/mcount.c:384
#3  0x00007ff3b30cf22c in cygprof_exit (parent=<optimized out>, child=<optimized out>) at /home/honggyu/src/uftrace/git/uftrace/libmcount/mcount.c:621
#4  __cyg_profile_func_exit (child=0x20000, parent=0xffffffff) at /home/honggyu/src/uftrace/git/uftrace/libmcount/mcount.c:902
#5  0x000000000047a245 in tcmalloc::ThreadCache::DestroyThreadCache (ptr=0x160eec575440)
#6  0x00007ff3b0972f82 in __nptl_deallocate_tsd () at pthread_create.c:158
#7  0x00007ff3b0973195 in start_thread (arg=0x7ff3a83e8700) at pthread_create.c:325
#8  0x00007ff3b06a047d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

refactoring build process

This patchset fixes and cleans up the uftrace build. Currently it runs feature-checking code during make (if it's not run before) but it seems there's some race that misses existing dependency (usually libstdc++).

Main idea is moving featuring-checking into configure script. The tricky part is calling the configure inside make (if it's not called before) and then build uftrace with a recursive make (with new feature-checking result). It seems it doesn't work correctly in some (older) systems. It's not a problem if users run the configure script manually before make though. But I'd like to not require running configure before make if possible.

The code is pushed to review/build-update-v1. It'd be really great if anyone can try it and can confirm it doesn't break. @thepaul could you please take a look at it?

specifying argument and retval in shared libraries

There's some problems when displaying function arguments and return values in shared libraries. If t-arg is compiled from s-arg.c, and libabc_test_lib.so is compiled from s-lib.c, the problem can be reproduced as follows:

$ ldd t-arg
        linux-vdso.so.1 =>  (0x00007ffe81724000)
        libabc_test_lib.so (0x00007f6d9c98a000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6d9c5aa000)
        /lib64/ld-linux-x86-64.so.2 (0x0000556c6968b000)

$ uftrace -A .*@arg1 -R .*@retval t-arg
# DURATION    TID     FUNCTION
   2.576 us [38912] | __cxa_atexit();
            [38912] | main(1) {
            [38912] |   foo(1) {
            [38912] |     lib_a() {
            [38912] |       lib_a() {
            [38912] |         lib_b() {
   1.236 us [38912] |           lib_c();
   3.182 us [38912] |         } /* lib_b */
   4.626 us [38912] |       } /* lib_a */
   6.376 us [38912] |     } /* lib_a */
   7.578 us [38912] |   } = 2057; /* foo */
   9.543 us [38912] | } = 0; /* main */

As you can see above, lib_a(), lib_b(), lib_c() do not show function arguments and return values here.

Skip symbol loading for record command

Sometimes symbol loading takes too much time when target binary is really big. (e.g. chrome)
It'd be a lot better to save time when I only run record command without symbol related options such as -F, -N, -T, -A, and -R. In most cases, I prefer to use only time-filter option(-t) so please skip symbol loading as default.

dynamic tracing support (on x86_64)

Linux kernel has dynamic tracing feature using gcc's -mfentry and replacing them to nop during build stage. The resulting binary has only a small performance overhead when not used for tracing. Now recent gcc provides -mnop-mcount option to do that automatically so uftrace can also make use of it. I added -P/--patch option to selectively enable functions at runtime like kernel does. Maybe it can be extended to selectively disable functions later.

The code is pushed onto review/dynamic-trace-v1 branch.

$ gcc -o abc -pg -mfentry -mnop-mcount tests/s-abc.c

$ uftrace abc
uftrace: /home/namhyung/project/uftrace/cmd-record.c:1305:check_binary
  ERROR: Can't find 'mcount' symbol in the 'abc'.
         It seems not to be compiled with -pg or -finstrument-functions flag
         which generates traceable code.  Please check your binary file.

$ uftrace --force abc
# DURATION    TID     FUNCTION
   1.698 us [19993] | __monstartup();
   1.350 us [19993] | __cxa_atexit();
   0.805 us [19993] | getpid();

$ uftrace --force -P a abc
# DURATION    TID     FUNCTION
   1.685 us [20000] | __monstartup();
   0.845 us [20000] | __cxa_atexit();
            [20000] | a() {
   0.615 us [20000] |   getpid();
   1.380 us [20000] | } /* a */

$ uftrace --force -P . abc
# DURATION    TID     FUNCTION
   1.754 us [20010] | __monstartup();
   0.966 us [20010] | __cxa_atexit();
            [20010] | main() {
            [20010] |   a() {
            [20010] |     b() {
            [20010] |       c() {
   0.727 us [20010] |         getpid();
   1.597 us [20010] |       } /* c */
   1.997 us [20010] |     } /* b */
   2.325 us [20010] |   } /* a */
   2.702 us [20010] | } /* main */

Problem with recorded data when tracing chrome browser

As I mentioned in #42 , the recorded data is somehow broken. Please see the details below.
record command doesn't crash the target program now.

$ uftrace record --no-pager -t 30us ./headless_shell --no-sandbox https://www.google.com
[1229/143623:INFO:fake_audio_manager.cc(23)] FakeAudioManager
[1229/143637:INFO:fake_audio_manager.cc(27)] ~FakeAudioManager

But it seems to be the recorded data is a bit strange.

$ uftrace replay
# DURATION    TID     FUNCTION
            [ 4311] | _GLOBAL__N_1::SpinLock_InitHelper::SpinLock_InitHelper() {
            [ 4311] |   NumCPUs() {
  94.906 us [ 4311] |     InitializeSystemInfo();
  95.309 us [ 4311] |   } /* NumCPUs */
  95.510 us [ 4311] | } /* _GLOBAL__N_1::SpinLock_InitHelper::SpinLock_InitHelper */
            [ 4311] | LoggerRegisterHelperChildProcessMsg_Shutdown::LoggerRegisterHelperChildProcessMsg_Shutdown() {
  50.057 us [ 4311] |   content::RegisterIPCLogger();
  50.280 us [ 4311] | } /* LoggerRegisterHelperChildProcessMsg_Shutdown::LoggerRegisterHelperChildProcessMsg_Shutdown */
            [ 4311] | LoggerRegisterHelperChildProcessMsg_SetProcessBackgrounded::LoggerRegisterHelperChildProcessMsg_SetProcessBackgrounded() {
            [ 4311] |   content::RegisterIPCLogger() {
    ...
  53.002 us [ 4311] |                 tcmalloc::ThreadCache::ReleaseToCentralCache();
   1.497 ms [ 4311] |               } /* tcmalloc::ThreadCache::Scavenge */
   1.498 ms [ 4311] |             } /* tcmalloc::ThreadCache::Deallocate */
   1.500 ms [ 4311] |           } /* _GLOBAL__N_1::do_free_with_callback */
   1.500 ms [ 4311] |         } /* _GLOBAL__N_1::do_free */
   4.712 ms [ 4311] |       } /* MallocBlock::ProcessFreeQueue */
   4.712 ms [ 4311] |     } /* DanglingWriteChecker */
   4.712 ms [ 4311] |   } /* _GLOBAL__N_1::google_destruct_module_debugallocation */
   4.712 ms [ 4311] | } /* GoogleInitializer::~GoogleInitializer */

uftrace stopped tracing with remaining functions
===============================================
task: 4315
[14] <80bdfa0>
[13] <80bdf20>
[12] <21c80b0>
[11] <0>
[10] <0>
[9] <0>
[8] <0>
[7] <0>
[6] <0>
[5] <0>
[4] <0>
[3] <0>
[2] <0>
[1] <0>
[0] <0>

task: 4317
[1] base::Thread::ThreadMain
[0] base::_GLOBAL__N_1::ThreadFunc

$ uftrace replay --tid 4315
# DURATION    TID     FUNCTION
  34.665 us [ 4315] |                         base::CloseSuperfluousFds();

uftrace stopped tracing with remaining functions
===============================================
task: 4315
[14] <80bdfa0>
[13] <80bdf20>
[12] <21c80b0>
[11] <0>
[10] <0>
[9] <0>
[8] <0>
[7] <0>
[6] <0>
[5] <0>
[4] <0>
[3] <0>
[2] <0>
[1] <0>
[0] <0>

And uftrace graph crashes as follows:

$ uftrace graph
Segmentation fault (core dumped)

$ gdb `which uftrace`
    ...
(gdb) r graph
Starting program: /home/honggyu/usr/bin/uftrace graph
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x0000000000407549 in build_graph (func=0x42b438 "main", handle=0x7fffffffdc60, opts=0x7fffffffde20) at /home/honggyu/src/uftrace/git/uftrace/cmd-graph.c:448
448                     sym = find_symtabs(&tg->graph->sess->symtabs, frs->addr);
(gdb) bt
#0  0x0000000000407549 in build_graph (func=0x42b438 "main", handle=0x7fffffffdc60, opts=0x7fffffffde20) at /home/honggyu/src/uftrace/git/uftrace/cmd-graph.c:448
#1  command_graph (argc=argc@entry=2, argv=argv@entry=0x7fffffffdff8, opts=opts@entry=0x7fffffffde20) at /home/honggyu/src/uftrace/git/uftrace/cmd-graph.c:525
#2  0x0000000000403d26 in main (argc=2, argv=0x7fffffffdff8) at /home/honggyu/src/uftrace/git/uftrace/uftrace.c:804
(gdb) p tg->graph->sess
Cannot access memory at address 0x10
(gdb) q
A debugging session is active.

Disable pager for record command

It'd be better to disable pager when uftrace record is executed without replay or live. Sometimes if I want to stop the recording, pressing Ctrl-C does not give beautiful user-experience due to pager.

$ uftrace record -t 30us ./headless_shell --no-sandbox https://www.google.com
^C
:...skipping...
:...skipping...
:...skipping...
:...skipping...
:...skipping...


$ 

I think record command should not change the original behavior of target program.

Implicit fallthrough warning on GCC 7.x

@namhyung

I found warning messages about -Wimplicit-fallthrough on gcc-7.0.1,
on current master branch.

The reason is like below.
https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
It looks like gcc 7 has added a default warning about fall-through.

But there isn't the warning option in gcc 6:
https://gcc.gnu.org/onlinedocs/gcc-6.3.0/gcc/Warning-Options.html

Is it needed to handle this warning message on gcc-7.x?
If you want to handle it, what about this ?

Currently the warning messages occur when building ufrace by gcc-7.0.1 like below.

$ gcc -dumpversion
7.0.1

$  git status | head -1
On branch master

$ sudo make clean && sudo make install
...
/home/taeung/git/uftrace/utils/utils.c: In function ‘parse_min’:
/home/taeung/git/uftrace/utils/utils.c:288:12: warning: this statement may fall through [-Wimplicit-fallthrough=]
    decimal *= 10;
    ~~~~~~~~^~~~~
/home/taeung/git/uftrace/utils/utils.c:289:3: note: here
   case 3:
   ^~~~
  CC       arch/x86_64/cpuinfo.o
  CC       arch/x86_64/regs.o
  LINK     arch/x86_64/uftrace.o
  FLAGS:   * new build flags or cross compiler
  CC FPIC  libtraceevent/event-parse.o
/home/taeung/git/uftrace/libtraceevent/event-parse.c: In function ‘process_arg_token’:
/home/taeung/git/uftrace/libtraceevent/event-parse.c:2914:6: warning: this statement may fall through [-Wimplicit-fallthrough=]
   if (strcmp(token, "(") == 0) {
      ^
/home/taeung/git/uftrace/libtraceevent/event-parse.c:2919:2: note: here
  case EVENT_OP:
  ^~~~
  CC FPIC  libtraceevent/event-plugin.o
  CC FPIC  libtraceevent/trace-seq.o
  CC FPIC  libtraceevent/parse-filter.o
/home/taeung/git/uftrace/libtraceevent/parse-filter.c: In function ‘pevent_filter_clear_trivial’:
/home/taeung/git/uftrace/libtraceevent/parse-filter.c:1625:7: warning: this statement may fall through [-Wimplicit-fallthrough=]
    if (filter_type->filter->boolean.value)
       ^
/home/taeung/git/uftrace/libtraceevent/parse-filter.c:1627:3: note: here
   case FILTER_TRIVIAL_TRUE:
   ^~~~
  CC FPIC  libtraceevent/parse-utils.o
  CC FPIC  libtraceevent/kbuffer-parse.o
  LINK     libtraceevent/libtraceevent.a
  LINK     uftrace
  CC FPIC  libmcount/mcount.op
  CC FPIC  libmcount/dynamic.op
  CC FPIC  libmcount/record.op
  CC FPIC  libmcount/plthook.op
  CC FPIC  symbol.op
  CC FPIC  debug.op
  CC FPIC  rbtree.op
  CC FPIC  filter.op
  CC FPIC  demangle.op
  CC FPIC  utils.op
/home/taeung/git/uftrace/utils/utils.c: In function ‘parse_min’:
/home/taeung/git/uftrace/utils/utils.c:288:12: warning: this statement may fall through [-Wimplicit-fallthrough=]
    decimal *= 10;
    ~~~~~~~~^~~~~
/home/taeung/git/uftrace/utils/utils.c:289:3: note: here
   case 3:
   ^~~~
...

I have two way to handle it.

  1. Add -Wno-implicit-fallthrough for gcc-7.0.1 into Makefile to just ignore this warning.
diff --git a/Makefile b/Makefile
index ee09adf..42d289f 100644
--- a/Makefile
+++ b/Makefile
@@ -67,6 +67,11 @@ COMMON_LDFLAGS := -lelf -lrt -ldl -pthread $(LDFLAGS)
 
 COMMON_CFLAGS += -W -Wall -Wno-unused-parameter -Wno-missing-field-initializers
 
+OVER_GCC_VER7 := $(shell echo `gcc -dumpversion | cut -f1 -d.` \>= 7 | bc)
+ifeq ($(OVER_GCC_VER7),1)
+  COMMON_CFLAGS += -Wno-implicit-fallthrough
+endif
+
 #
 # Note that the plain CFLAGS and LDFLAGS can be changed
 # by config/Makefile later but *_*FLAGS can not.

Or,
2) Add /* fall through */ into the switch statements to avoid this warning.

diff --git a/libtraceevent/event-parse.c b/libtraceevent/event-parse.c
index 324a384..a38e43a 100644
--- a/libtraceevent/event-parse.c
+++ b/libtraceevent/event-parse.c
@@ -2905,6 +2905,7 @@ process_arg_token(struct event_format *event, struct print_arg *arg,
                 break;
 
         case EVENT_DQUOTE:
+                /* fall through */
         case EVENT_SQUOTE:
                 arg->type = PRINT_ATOM;
                 arg->atom.atom = token;
@@ -2916,6 +2917,7 @@ process_arg_token(struct event_format *event, struct print_arg *arg,
                         type = process_paren(event, arg, &token);
                         break;
                 }
+                /* fall through */
         case EVENT_OP:
                 /* handle single ops */
                 arg->type = PRINT_OP;
diff --git a/libtraceevent/parse-filter.c b/libtraceevent/parse-filter.c
index 21c92fb..185774a 100644
--- a/libtraceevent/parse-filter.c
+++ b/libtraceevent/parse-filter.c
@@ -1624,9 +1624,11 @@ int pevent_filter_clear_trivial(struct event_filter *filter,
                 case FILTER_TRIVIAL_FALSE:
                         if (filter_type->filter->boolean.value)
                                 continue;
+                        /* fall through */
                 case FILTER_TRIVIAL_TRUE:
                         if (!filter_type->filter->boolean.value)
                                 continue;
+                        /* fall through */
                 default:
                         break;
                 }
diff --git a/utils/utils.c b/utils/utils.c
index 046cb1d..ce8ce46 100644
--- a/utils/utils.c
+++ b/utils/utils.c
@@ -286,6 +286,7 @@ static uint64_t parse_min(uint64_t min, uint64_t decimal, int decimal_places)
                         break;
                 case 2:
                         decimal *= 10;
+                        /* fall through */
                 case 3:
                         decimal *= 10;
                         nsec += decimal * NSEC_PER_MSEC;

What do you think about the above handling ?

d8 launch failed

Hi,

I've found a problem when running d8 with current master uftrace.

$ uftrace -vv -t 100ms d8 -e ''
symbol: check trace functions in d8
uftrace: creating 10 thread(s) for recording
uftrace: using libmcount.so library for tracing
uftrace: start writer thread 0
uftrace: start writer thread 1
uftrace: start writer thread 2
uftrace: start writer thread 3
uftrace: start writer thread 4
uftrace: start writer thread 5
uftrace: start writer thread 6
uftrace: start writer thread 7
uftrace: start writer thread 8
uftrace: start writer thread 9
mcount: initializing mcount library
symbol: loading dynamic symbols from /home/honggyu/work/v8/git/v8/out/x64.debug/d8
mcount: opening executable image: /home/honggyu/work/v8/git/v8/out/x64.debug/d8

And it doesn't have any response. I've found the commit(9479ec2) that affects this problem as follows:
Please have a look at it!

Skip filtered function from other task when replay

Currently uftrace replay merges ENTRY and EXIT records if the functions is a leaf or all functions between them are filtered out (and then it'll look like a leaf). But it only checks functions from same task and didn't merge when there's another record of other task even if it's filtered out (so won't be shown). This can be easily seen when kernel tracing is enabled.

A Simpler example is the multi-thread test case (t-thread).

$ uftrace record tests/t-thread

$ uftrace replay
# DURATION    TID     FUNCTION
            [20053] | main() {
  81.953 us [20053] |   pthread_create();
  53.108 us [20053] |   pthread_create();
 188.065 us [20053] |   pthread_create();
 184.846 us [20053] |   pthread_create();
            [20053] |   pthread_join() {
            [20057] | foo() {
            [20057] |   a() {
            [20057] |     b() {
   5.735 us [20057] |       c();
   7.308 us [20057] |     } /* b */
   8.081 us [20057] |   } /* a */
   9.212 us [20057] | } /* foo */
            [20056] | foo() {
            [20056] |   a() {
            [20056] |     b() {
   0.211 us [20056] |       c();
   1.069 us [20056] |     } /* b */
   1.480 us [20056] |   } /* a */
   2.086 us [20056] | } /* foo */
            [20055] | foo() {
            [20055] |   a() {
            [20055] |     b() {
   0.335 us [20055] |       c();
   1.623 us [20055] |     } /* b */
   2.551 us [20055] |   } /* a */
   3.944 us [20055] | } /* foo */
            [20058] | foo() {
            [20058] |   a() {
            [20058] |     b() {
   0.193 us [20058] |       c();
   1.387 us [20058] |     } /* b */
   1.886 us [20058] |   } /* a */
   2.562 us [20058] | } /* foo */
 779.561 us [20053] |   } /* pthread_join */
   1.136 us [20053] |   pthread_join();
   0.702 us [20053] |   pthread_join();
   0.650 us [20053] |   pthread_join();
   1.309 ms [20053] | } /* main */

When I set function filter on "main" function, it only shows the main thread but pthread_join() cannot be merged since there are many functions (not displayed though) from other tasks.

$ uftrace replay -F main
# DURATION    TID     FUNCTION
            [20053] | main() {
  81.953 us [20053] |   pthread_create();
  53.108 us [20053] |   pthread_create();
 188.065 us [20053] |   pthread_create();
 184.846 us [20053] |   pthread_create();
            [20053] |   pthread_join() {
 779.561 us [20053] |   } /* pthread_join */
   1.136 us [20053] |   pthread_join();
   0.702 us [20053] |   pthread_join();
   0.650 us [20053] |   pthread_join();
   1.309 ms [20053] | } /* main */

With this patchset, it can skip those filtered functions and can merge pthread_join().

$ uftrace replay -F main
# DURATION    TID     FUNCTION
            [20053] | main() {
  81.953 us [20053] |   pthread_create();
  53.108 us [20053] |   pthread_create();
 188.065 us [20053] |   pthread_create();
 184.846 us [20053] |   pthread_create();
 779.561 us [20053] |   pthread_join();
   1.136 us [20053] |   pthread_join();
   0.702 us [20053] |   pthread_join();
   0.650 us [20053] |   pthread_join();
   1.309 ms [20053] | } /* main */

I pushed the code to the review/replay-skip branch.

Warning In fstack.c: next_time variable didn’t be initilaized at read_user_stack function calling

In fstack.c file, uint64_t next_time; variable didn't be initialized.
I think, if(next_i < 0 || tmp->time < next_time) is short-circuit evaluation.
So, when this loop isn't first loop, this variable is substituted in this way.
next_time = tmp->time;

However, if next_time variable didn't be initialized in first loop, this Warining message is displayed.

So I hope to initialize this variable.
As initial value doesn't care, Can I this variable initilize 0 or UINT64_MAX ?

compilation warnings

@namhyung @thepaul I see a lot of compilation warnings during build in my environment. I use Ubuntu 14.04 and the compiler info is as follows:

$ gcc --version
gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4

Please see the warnings below:

$ make
  ...
  CC FPIC  libtraceevent/event-parse.o
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/event-parse.c: In function ‘event_read_fields’:
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/event-parse.c:1550:37: warning: signed and unsigned type in conditional expression [-Wsign-compare]
            event->pevent->long_size :
                                     ^
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/event-parse.c: In function ‘pevent_find_event_by_name’:
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/event-parse.c:3324:21: warning: ‘event’ may be used uninitialized in this function [-Wmaybe-uninitialized]
  pevent->last_event = event;
                     ^
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/event-parse.c: In function ‘pevent_data_lat_fmt’:
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/event-parse.c:4549:20: warning: ‘migrate_disable’ may be used uninitialized in this function [-Wmaybe-uninitialized]
    trace_seq_printf(s, "%d", migrate_disable);
                    ^
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/event-parse.c:4556:20: warning: ‘lock_depth’ may be used uninitialized in this function [-Wmaybe-uninitialized]
    trace_seq_printf(s, "%d", lock_depth);
                    ^
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/event-parse.c: In function ‘pevent_event_info’:
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/event-parse.c:4453:18: warning: ‘len_arg’ may be used uninitialized in this function [-Wmaybe-uninitialized]
     print_str_arg(&p, data, size, event,
                  ^
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/event-parse.c:4248:6: note: ‘len_arg’ was declared here
  int len_arg;
      ^
  CC FPIC  libtraceevent/event-plugin.o
  CC FPIC  libtraceevent/trace-seq.o
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/trace-seq.c: In function ‘trace_seq_puts’:
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/trace-seq.c:201:13: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  while (len > ((s->buffer_size - 1) - s->len))
             ^
  CC FPIC  libtraceevent/parse-filter.o
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/parse-filter.c: In function ‘show_error’:
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/parse-filter.c:56:28: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for (i = 1; i < len && i < index; i++)
                            ^
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/parse-filter.c: In function ‘arg_to_str’:
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/parse-filter.c:2318:11: warning: ignoring return value of ‘asprintf’, declared with attribute warn_unused_result [-Wunused-result]
   asprintf(&str, arg->boolean.value ? "TRUE" : "FALSE");
           ^
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/parse-filter.c: In function ‘op_to_str’:
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/parse-filter.c:2111:13: warning: ignoring return value of ‘asprintf’, declared with attribute warn_unused_result [-Wunused-result]
     asprintf(&str, val ? "TRUE" : "FALSE");
             ^
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/parse-filter.c:2129:11: warning: ignoring return value of ‘asprintf’, declared with attribute warn_unused_result [-Wunused-result]
   asprintf(&str, "(%s) %s (%s)", left, op, right);
           ^
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/parse-filter.c:2145:12: warning: ignoring return value of ‘asprintf’, declared with attribute warn_unused_result [-Wunused-result]
    asprintf(&str, right_val ? "FALSE" : "TRUE");
            ^
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/parse-filter.c:2148:11: warning: ignoring return value of ‘asprintf’, declared with attribute warn_unused_result [-Wunused-result]
   asprintf(&str, "%s(%s)", op, right);
           ^
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/parse-filter.c: In function ‘num_to_str’:
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/parse-filter.c:2266:11: warning: ignoring return value of ‘asprintf’, declared with attribute warn_unused_result [-Wunused-result]
   asprintf(&str, "%s %s %s", lstr, op, rstr);
           ^
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/parse-filter.c: In function ‘str_to_str’:
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/parse-filter.c:2301:11: warning: ignoring return value of ‘asprintf’, declared with attribute warn_unused_result [-Wunused-result]
   asprintf(&str, "%s %s \"%s\"",
           ^
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/parse-filter.c: In function ‘val_to_str’:
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/parse-filter.c:2164:10: warning: ignoring return value of ‘asprintf’, declared with attribute warn_unused_result [-Wunused-result]
  asprintf(&str, "%lld", arg->value.val);
          ^
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/parse-filter.c: In function ‘exp_to_str’:
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/parse-filter.c:2222:10: warning: ignoring return value of ‘asprintf’, declared with attribute warn_unused_result [-Wunused-result]
  asprintf(&str, "%s %s %s", lstr, op, rstr);
          ^
  CC FPIC  libtraceevent/parse-utils.o
  CC FPIC  libtraceevent/kbuffer-parse.o
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/kbuffer-parse.c: In function ‘kbuffer_read_at_offset’:
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/kbuffer-parse.c:619:13: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  if (offset < kbuf->start)
             ^
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/kbuffer-parse.c:628:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  while (kbuf->curr < offset) {
                    ^
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/kbuffer-parse.c: In function ‘__old_next_event’:
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/kbuffer-parse.c:339:27: warning: ‘length’ may be used uninitialized in this function [-Wmaybe-uninitialized]
  kbuf->next = kbuf->index + length;
                           ^
/home/honggyu/src/uftrace/git/uftrace/libtraceevent/kbuffer-parse.c:297:15: note: ‘length’ was declared here
  unsigned int length;
               ^

ARM aarch64 support

This is a preliminary support for 64-bit ARM (aarch64) systems. The gcc generates calls to _mcount with -pg option on aarch64 and PLT hook is implmented to support tracing library calls. I think basic functionality is ok but there are some problems on displaying function arguments.

$ uname -a
Linux linaro-developer 4.9.6 #14 SMP Thu Apr 20 00:09:36 KST 2017 aarch64 GNU/Linux

$ uftrace -V
uftrace v0.6.2-153-g81c6

$ uftrace tests/t-abc
# DURATION    TID     FUNCTION
 221.488 us [ 8275] | __cxa_atexit();
            [ 8275] | main() {
            [ 8275] |   a() {
            [ 8275] |     b() {
            [ 8275] |       c() {
   7.024 us [ 8275] |         getpid();
 117.280 us [ 8275] |       } /* c */
 174.672 us [ 8275] |     } /* b */
 188.624 us [ 8275] |   } /* a */
 245.248 us [ 8275] | } /* main */

The problem is that gcc generates code that overwrites the value of x0 register before entering to the "_mcount" so uftrace cannot read the correct value of the first argument. Also floating-point arguments are not accessed for now (due to a compile error).

I only tested it on a qemu environment with gcc 6.3 (from Linaro). Currently it passes all unit tests and ~75% of runtime tests. The code is available on the review/aarch64-support-v1 branch.

Confusing the option name by the case-sensitive letter

I think the option name may confused at the letter 'd' or 'D'.

In case of 'd', it uses to specify the directory name, while 'D' uses to configure a certain level of depth.

As I know, many programmers prefer to use shortcut key for simplicity. However, uftrace provides two features with the same letter, even if they can be distinguished by case-sensitive. It would be confusing to users compared to using different letters.

For example, du command that is widely used in linux to get disk usage, it uses 'd' for level of depth. In addition, most of application uses 'o' letter to specify the directory name for output data.

So, I think uftrace needs to modify the name of option to make it clearer. It would be more familiar with users.

What do you think about?

SDT event support

Add basic support for event tracing. The event tracing is usable when there are available events on the system. Currently systemtap SDT can be used, and it's already added to many programs and libraries on Ubuntu systems at least. It doesn't save and show event's arguments yet but it'll be added soon.

The code was pushed to review/sdt-support-v1 branch.

An SDT event can be defined using STAP_PROBE* macro like following. I defined "uftrace:event1" event (note that an event has PROVIDER:EVENT format) with a single argument of "n". The code will add a NOP insn at the point of the event. For more information, please see SDT implementation page.

The uftrace will replace the NOP insn to an invalid op so that it can generate an illegal opcode exception which sends SIGILL signal to the current task. And then it registers a signal handler for SIGILL to process the event information and continue to proceed with the next instruction.

  $ cat tests/s-sdt.c
  #include <stdio.h>
  #include <stdlib.h>
  #include <sys/sdt.h>        // <-- include the SDT header

  void foo(int n)
  {
    STAP_PROBE1(uftrace, event1, n);    // <-- defined here
    printf("n = %d\n", n);
  }

  int main(int argc, char *argv[])
  {
    int n = 1;

    if (argc > 1)
      n = atoi(argv[1]);

    foo(n);
    return 0;
  }

The test case enables all events under the name of "uftrace" like below. I plan to add (regex or glob) pattern matching.

  $ uftrace -E uftrace:*  tests/t-sdt
  # DURATION    TID     FUNCTION
     9.392 us [28141] | __monstartup();
    12.912 us [28141] | __cxa_atexit();
              [28141] | main() {
              [28141] |   foo() {
              [28141] |     /* uftrace:event1 */      // <--  here
     2.405 us [28141] |     printf();
     2.896 us [28141] |   } /* foo */
     3.017 us [28141] | } /* main */

Add MIPS support

Currently "arch" folder only contains x86_64 and arm subfolders.
It would be great to add MIPS support too.

Stuck when --tid option is given more than twice

--tid option is to show only specified thread output but if --tid option is used twice, uftrace stucks and does not finish.

$ uftrace replay --tid 17490 -D 1
# DURATION    TID     FUNCTION
            [17490] | base::_GLOBAL__N_1::ThreadFunc() {

uftrace stopped tracing with remaining functions
================================================
task: 17490
[5] base::MessagePumpDefault::Run
[4] base::MessageLoop::RunHandler
[3] base::RunLoop::Run
[2] base::Thread::Run
[1] base::Thread::ThreadMain
[0] base::_GLOBAL__N_1::ThreadFunc

$ uftrace replay --tid 17471 -D 1
# DURATION    TID     FUNCTION
  16.943 ms [17471] | _GLOBAL__N_1::SpinLock_InitHelper::SpinLock_InitHelper();
  26.989 ms [17471] | LoggerRegisterHelperChildProcessMsg_Shutdown::LoggerRegisterHelperChildProcessMsg_Shutdown();
  60.363 us [17471] | LoggerRegisterHelperChildProcessMsg_GetChildNonPersistentHistogramData::LoggerRegisterHelperChildProcessMsg_GetChildNonPersistentHistogramData();
  32.766 us [17471] | LoggerRegisterHelperAccessibilityMsg_SetFocus::LoggerRegisterHelperAccessibilityMsg_SetFocus();
  58.275 us [17471] | LoggerRegisterHelperAccessibilityHostMsg_LocationChanges::LoggerRegisterHelperAccessibilityHostMsg_LocationChanges();
    ...
  56.909 us [17471] | SkRTConf::SkRTConf();
  56.835  s [17471] | main();
  74.205 us [17471] | SkRTConfRegistry::~SkRTConfRegistry();
   3.217 ms [17471] | GoogleInitializer::~GoogleInitializer();

Here is the problematic example:

$ uftrace replay --tid 17490 --tid 17471 -D 1
  ( ... does not finish ... )

I know that the correct usage of --tid is as follows:

--tid=TID[,TID,...]
      Only print functions called by the given threads.  To see the list of threads in the data file, you can use uftrace report --threads or uftrace info.

But it's better to prevent using --tid option is used more than twice.

Display time according to --time-range option

Good morning, Namhyung 😄

I found a problem. Is it a problem ? or I did wrong usage for it ? 😟
I tested on current master branch (58639c)

$ uftrace ./a.out
# DURATION    TID     FUNCTION
   0.834 us [16683] | __monstartup();
   0.419 us [16683] | __cxa_atexit();
            [16683] | main() {
   5.181 us [16683] |   fgets();
            [16683] |   get_values_from() {
   0.576 us [16683] |     strdup();

... (It hasn't any problems)

But if using -r or --time-range with + prefix, it isn't work with a warning message as below.

$ uftrace -r +1us ./a.out
invalid time range: +1us (ignoring...)
# DURATION    TID     FUNCTION
   0.635 us [16628] | __monstartup();
   0.404 us [16628] | __cxa_atexit();
            [16628] | main() {
   4.102 us [16628] |   fgets();
            [16628] |   get_values_from() {
   0.561 us [16628] |     strdup();
...

Should we fix it ? and
Add test scripts for time-range such as t053_filter_time.py ? 😄

More filtering options for report, dump and graph

Currently replay subcommand can filter the data using function name, tid and/or depth. But other subcommands like report, dump and graph didn't have that options. As it keeps fstack (func_stack) when it reads the data, it can reuse the fstack for other subcommands to do those kind of filtering as well.

The code was pushed to review/filter-update branch.

Some examples:

$ uftrace replay -d abc.data
# DURATION    TID     FUNCTION
            [15938] | main() {
            [15938] |   a() {
            [15938] |     b() {
            [15938] |       c() {
   1.622 us [15938] |         getpid();
   5.139 us [15938] |       } /* c */
   5.925 us [15938] |     } /* b */
   6.414 us [15938] |   } /* a */
   6.974 us [15938] | } /* main */

$ uftrace replay -d abc.data -F b
# DURATION    TID     FUNCTION
            [15938] | b() {
            [15938] |   c() {
   1.622 us [15938] |     getpid();
   5.139 us [15938] |   } /* c */
   5.925 us [15938] | } /* b */

$ uftrace report -d abc.data -F b
  Total time   Self time       Calls  Function
  ==========  ==========  ==========  ====================================
    5.925 us    0.786 us           1  b
    5.139 us    3.517 us           1  c
    1.622 us    1.622 us           1  getpid

$ uftrace dump -d abc.data -F b
ftrace file header: magic         = 4674726163652100
ftrace file header: version       = 4
ftrace file header: header size   = 40
ftrace file header: endian        = 1 (little)
ftrace file header: class         = 2 (64 bit)
ftrace file header: features      = 0x3
ftrace file header: info          = 0x3ff

reading 15938.dat
241325.123513472  15938: [entry] b(400674) depth: 2
241325.123513646  15938: [entry] c(400636) depth: 3
241325.123514272  15938: [entry] getpid(400490) depth: 4
241325.123515894  15938: [exit ] getpid(400490) depth: 4
241325.123518785  15938: [exit ] c(400636) depth: 3
241325.123519397  15938: [exit ] b(400674) depth: 2

REAME.md update is needed

The current limitation is out-dated so needs to be updated.

Limitations

  • It can only trace a native C/C++ application compiled with -pg option.
  • It cannot trace already running process.
  • It cannot be used for system-wide tracing.
  • It only supports x86_64 and ARM (v6,7) for now.

Functions defined in dynamically loaded shared libraries are not named

Given a function that was defined in a .so, that was dlopen-ed, where the main program and the .so are both built with -pg, the dumped json does not contain the names of the functions defined in the .so, and what seem to be addresses of the functions are output instead.

The issue seems to boil down to the fact that the filenames and offsets of the shared libraries is only checked when the traced program starts, which means that shared libraries linked with -l are handled properly, but if the program dynamically loads a .so, which is the case if the main program loads a binary plugin at run-time.

A workaround for the issue is:
uftrace record main_program, waiting until the program loads all of its dynamic dependencies, then overwriting the processes map with cat /proc/pidof main_program/maps > /path/to/working_dir/uftrace.data/sid-xxxxxxxxxxxxxxxx.map.

However, if the .sos are used one after the other, like load a.so, use it, unload a.so, load b.so use it and so on, there may not be a point where all functions are loaded at one time, in fact, it may even be possible that b.so's memory space overlap a.so's now unmapped memory space, making the task even harder.

It should also be noted that dlopen is not the only way by which functions can be loaded at run-time, think mmap with mprotect.

For my use-case, simply waiting a bit before checking the maps would solve the issue, but in general, it might be necessary to hook mmap or dlopen and store the address->file mapping information frequently. If there are other mechanisms to load functions, it might be necessary to inspect the program every time an unknown function is called, however the performance penalty for doing so might be prohibitive.

Handle the gcc bug of `finstrument-functions dual instrumentation problem` ?

Because of the old version gcc(e.g. 5.3.1) bug of finstrument-functions dual instrumentation problem like below,

$ objdump -d t-openclose --start-address=0x400626 --stop-address=0x400690

t-openclose:     file format elf64-x86-64


Disassembly of section .text:

0000000000400626 <main>:
  400626:	53                   	push   %rbx
  400627:	48 8b 74 24 08       	mov    0x8(%rsp),%rsi
  40062c:	bf 26 06 40 00       	mov    $0x400626,%edi
  400631:	e8 da fe ff ff       	callq  400510 <__cyg_profile_func_enter@plt>
  400636:	48 8b 74 24 08       	mov    0x8(%rsp),%rsi
  40063b:	bf 00 05 40 00       	mov    $0x400500,%edi
  400640:	e8 cb fe ff ff       	callq  400510 <__cyg_profile_func_enter@plt>
  400645:	be 00 00 00 00       	mov    $0x0,%esi
  40064a:	bf 14 07 40 00       	mov    $0x400714,%edi
  40064f:	b8 00 00 00 00       	mov    $0x0,%eax
  400654:	e8 a7 fe ff ff       	callq  400500 <open@plt>
  400659:	89 c3                	mov    %eax,%ebx
  40065b:	48 8b 74 24 08       	mov    0x8(%rsp),%rsi
  400660:	bf 00 05 40 00       	mov    $0x400500,%edi
  400665:	e8 86 fe ff ff       	callq  4004f0 <__cyg_profile_func_exit@plt>
  40066a:	89 df                	mov    %ebx,%edi
  40066c:	e8 5f fe ff ff       	callq  4004d0 <close@plt>
  400671:	48 8b 74 24 08       	mov    0x8(%rsp),%rsi
  400676:	bf 26 06 40 00       	mov    $0x400626,%edi
  40067b:	e8 70 fe ff ff       	callq  4004f0 <__cyg_profile_func_exit@plt>
  400680:	b8 00 00 00 00       	mov    $0x0,%eax
  400685:	5b                   	pop    %rbx
  400686:	c3                   	retq   
  400687:	66 0f 1f 84 00 00 00 	nopw   0x0(%rax,%rax,1)
  40068e:	00 00 

Problem Situation:

The below bug occurs in gcc 5.3.1.

$ gcc --version | head -1
gcc (Ubuntu 5.3.1-14ubuntu2) 5.3.1 20160413

Duplicated open() like below.

$ gcc -o t-openclose -finstrument-functions -O1 s-openclose.c 

taeung ~/git/uftrace/tests 
:> uftrace ./t-openclose 
# DURATION    TID     FUNCTION
            [ 3113] | main() {
            [ 3113] |   open() {
   3.464 us [ 3113] |     open();
   6.041 us [ 3113] |   } /* open */
   1.388 us [ 3113] |   close();
   8.068 us [ 3113] | } /* main */

No matter Situation:

But in gcc 7.0.1, there isn't the bug anymore.

$ ~/recent/bin/gcc --version | head -1
gcc (GCC) 7.0.1 20170405 (experimental)
$ ~/recent/bin/gcc -o t-openclose -finstrument-functions -O1 s-openclose.c
$ uftrace ./t-openclose 
# DURATION    TID     FUNCTION
            [ 3136] | main() {
   3.595 us [ 3136] |   open();
   1.009 us [ 3136] |   close();
   7.201 us [ 3136] | } /* main */

And @namhyung ,
I guess you already know the gcc bug of finstrument-functions dual instrumentation problem.
I wonder where is the source code you handle this bug ?
And would you mind, if I dig and resolve the bug ?

Thanks,
Taeung

V8 functions are not traced in headless chrome shell

Headless chrome is now traced

  • execution record
$ uftrace record -t 1ms ./headless_shell --no-sandbox https://www.google.com
[0105/134130:WARNING:host_discardable_shared_memory_manager.cc(132)] Less than 64MB of free space in temporary directory for shared memory files: 7
[0105/134130:INFO:fake_audio_manager.cc(23)] FakeAudioManager
[0105/134144:INFO:fake_audio_manager.cc(27)] ~FakeAudioManager
  • function execution replay
$ uftrace replay
# DURATION    TID     FUNCTION
            [14989] | main() {
            [14989] |   HeadlessShell::HeadlessShell() {
            [14989] |     headless::HeadlessDevToolsClient::Create() {
   5.826 ms [14989] |       headless::HeadlessDevToolsClientImpl::HeadlessDevToolsClientImpl();
   5.874 ms [14989] |     } /* headless::HeadlessDevToolsClient::Create */
   5.881 ms [14989] |   } /* HeadlessShell::HeadlessShell */
            [14989] |   headless::HeadlessBrowserMain() {
            [14989] |     headless::_GLOBAL__N_1::RunContentMain() {
            [14989] |       content::ContentMain() {
            [14989] |         content::ContentMainRunnerImpl::Initialize() {
            [14989] |           base::i18n::InitializeICU() {
            [14989] |             icu_56::TimeZone::createDefault() {
    ...
  • call graph
$ uftrace graph
    ...
  49.745  s : (1) main
   5.881 ms :  +-(1) HeadlessShell::HeadlessShell
   5.874 ms :  | (1) headless::HeadlessDevToolsClient::Create
   5.826 ms :  | (1) headless::HeadlessDevToolsClientImpl::HeadlessDevToolsClientImpl
            :  |
  49.735  s :  +-(1) headless::HeadlessBrowserMain
  49.735  s :  | (1) headless::_GLOBAL__N_1::RunContentMain
  49.735  s :  | (1) content::ContentMain
  19.160 ms :  |  +-(1) content::ContentMainRunnerImpl::Initialize
   1.097 ms :  |  |  +-(1) base::i18n::InitializeICU
    ...
   1.053 ms :  |  |  | (1) icu_56::TimeZone::detectHostTimeZone
            :  |  |  |
   3.642 ms :  |  |  +-(1) gin::V8Initializer::LoadV8Snapshot
   3.494 ms :  |  |  | (1) gin::_GLOBAL__N_1::OpenFileIfNecessary
   3.470 ms :  |  |  | (1) gin::_GLOBAL__N_1::OpenV8File
    ...
  • summary report
$ uftrace report
  Total time   Self time       Calls  Function
  ==========  ==========  ==========  ====================================
    3.055  m    1.613 ms          14  base::_GLOBAL__N_1::ThreadFunc
    2.022  m  119.933 us          10  base::RunLoop::Run
    2.022  m   17.478 us          10  base::MessageLoop::RunHandler
    2.008  m    4.569 ms           9  base::Thread::ThreadMain
    2.008  m   12.324 us           9  base::Thread::Run
    ...
   56.108  s   63.371 ms         258  event_base_loop
   55.599  s   55.599  s         231  epoll_dispatch
   49.745  s    1.233 ms           1  main
   49.735  s  557.884 us           1  headless::HeadlessBrowserMain
    ...

However, I don't find V8 code execution trace from the above trace. So I've asked why V8 is not executed in headless chrome dev mailing list as follows:
https://groups.google.com/a/chromium.org/forum/#!topic/headless-dev/pMuQN1Y0rjE

I found V8 execution log by running the below command:

$ ./headless_shell --trace-startup=* --trace-startup-duration=10 --remote-debugging-port=9222 http://www.independent.co.uk
[0105/141004:WARNING:host_discardable_shared_memory_manager.cc(132)] Less than 64MB of free space in temporary directory for shared memory files: 5
[0105/141004:INFO:fake_audio_manager.cc(23)] FakeAudioManager
[0105/141005:ERROR:socket_posix.cc(125)] bind() returned an error, errno=98: Address already in use
[0105/141005:ERROR:devtools_http_handler.cc(228)] Cannot start http server for devtools. Stop devtools.
[0105/141017:INFO:browser_main_loop.cc(293)] Completed startup tracing to chrometrace.log
^C

It generates chrometrace.log, which is the original json log file for chrome trace viewer and I can find V8 execution record here.

I retried the above command with uftrace again with --no-sandbox but still didn't get V8 execution record from uftrace record as follows.

$ uftrace record -t 10ms ./headless_shell --no-sandbox --trace-startup=* --trace-startup-duration=10 --remote-debugging-port=9222 http://www.independent.co.uk
    ...

And I executed the same command with some v8 functions pinned regardless of time filter setting but it crashes as follows:

$ uftrace record -t 10ms -T v8::internal::Parser::ParseLazy.*@trace ./headless_shell --no-sandbox --trace-startup=* --trace-startup-duration=10 --remote-debugging-port=9222 http://www.independent.co.uk
[0105/140147:WARNING:host_discardable_shared_memory_manager.cc(132)] Less than 64MB of free space in temporary directory for shared memory files: 6
[0105/140148:INFO:fake_audio_manager.cc(23)] FakeAudioManager
[0105/140200:WARNING:trace_log.cc(1039)] The following threads haven't finished flush in time. If this happens stably for some thread, please call TraceLog::GetInstance()->SetCurrentThreadBlocksMessageLoop() from the thread to avoid its trace events from being lost.
[0105/140200:WARNING:trace_log.cc(1047)] Thread: CrRendererMain
[0105/140201:INFO:browser_main_loop.cc(293)] Completed startup tracing to chrometrace.log
Received signal 7 BUS_ADRERR 7f7111d26000
#0 0x7f711bdfa805 backtrace
#1 0x000007fa5e59

execve() is not added to filter in utils/fstack.c

Hi,
I wrote a short program and compiled in two versions, e.g. with execl() and with execve() - see listing of b.cpp and a.cpp.
It appeared, that uftrace can show the trace of functions from a.out (g++ -Wall -pg a.cpp) only when b.cpp is compiled in version with execl() (g++ -Wall -pg b.cpp -o b.out -lpthread)
uftrace was used as follows: uftrace b.out.

I noticed, that execve() is not added to fixup_syms[] in utils/fstack.c but this did not solve my problem.
Even though, after my change in debug prints I can see "filter: filter match: execve" I do not see traces from a.out.

Could you comment, why execve() is not added to filter and why I cannot see a.out functions in uftrace record?

uftrace patch

diff --git a/utils/fstack.c b/utils/fstack.c
index c73917f..4feb30b 100644
--- a/utils/fstack.c
+++ b/utils/fstack.c
@@ -282,7 +282,7 @@ static int setup_fstack_filters(struct ftrace_file_handle *handle,
 }
 
 static const char *fixup_syms[] = {
-       "execl", "execlp", "execle", "execv", "execvp", "execvpe",
+       "execl", "execlp", "execle", "execv", "execve", "execvp", "execvpe",
        "setjmp", "_setjmp", "sigsetjmp", "__sigsetjmp",
        "longjmp", "siglongjmp", "__longjmp_chk",
        "fork", "vfork", "daemon",

uftrace -vv b.out (with execl)

symbol: check trace functions in ./b.out
uftrace: creating 1 thread(s) for recording
uftrace: start writer thread 0
uftrace: using libmcount.so library for tracing
mcount: initializing mcount library
symbol: loading dynamic symbols from /home/rlukasik/b.out
mcount: opening executable image: /home/rlukasik/b.out
mcount: found GOT at 0x602000 (PLT resolver: 0x7f1be68d5870)
mcount: overwrite [11] mcount: 0x7f1be66b3cb0
mcount: mcount setup done
uftrace: MSG SESSION: 27414: /home/rlukasik/b.out (8cffbd5c7348b526)
mcount: preparing shmem buffers
uftrace: MSG START: /uftrace-8cffbd5c7348b526-27414-000
uftrace: MSG TASK : 27414/27414
main()
Great success
mcount: preparing shmem buffers
uftrace: MSG START: /uftrace-8cffbd5c7348b526-27417-000
uftrace: MSG TASK : 27414/27417
dispather_monitor_thread_entry
uftrace: MSG FORK1: 27414/-1
mcount: releasing all shmem buffers for task 27418
mcount: preparing shmem buffers
uftrace: MSG START: /uftrace-8cffbd5c7348b526-27418-000
uftrace: MSG FORK2: 27414/27418
dispatcher_exec
mcount: initializing mcount library
symbol: loading dynamic symbols from /home/rlukasik/a.out
mcount: opening executable image: /home/rlukasik/a.out
mcount: found GOT at 0x601000 (PLT resolver: 0x7f3ffe68f870)
mcount: overwrite [6] mcount: 0x7f3ffe46dcb0
mcount: mcount setup done
uftrace: MSG SESSION: 27418: /home/rlukasik/a.out (9cae909fe80cca00)
mcount: preparing shmem buffers
uftrace: MSG START: /uftrace-9cae909fe80cca00-27418-000
uftrace: MSG TASK : 27418/27418
a.out
uftrace: MSG  END : /uftrace-9cae909fe80cca00-27418-000
mcount: shmem_finish: tid: 27418 seqnum = 0 curr = 0, nr_buf = 2 max_buf = 2
mcount: releasing all shmem buffers for task 27418
mcount: shmem_finish: tid: 27417 seqnum = 0 curr = 0, nr_buf = 2 max_buf = 2
mcount: releasing all shmem buffers for task 27417
uftrace: MSG  END : /uftrace-8cffbd5c7348b526-27417-000
mcount: shmem_finish: tid: 27414 seqnum = 0 curr = 0, nr_buf = 2 max_buf = 2
mcount: releasing all shmem buffers for task 27414
uftrace: MSG  END : /uftrace-8cffbd5c7348b526-27414-000
uftrace: all process/thread exited
uftrace: child terminated with exit code: 0
uftrace: reading /tmp/uftrace-live-ndcHUa/task.txt file
session: new task: tid = 27414
session: new task: tid = 27417
session: new task: tid = 27418
uftrace: stop writer thread 0
uftrace: flushing /uftrace-8cffbd5c7348b526-27414-000
uftrace: flushing /uftrace-8cffbd5c7348b526-27417-000
uftrace: flushing /uftrace-9cae909fe80cca00-27418-000
uftrace: unlink for session: 8cffbd5c7348b526
uftrace: unlink for session: 9cae909fe80cca00
uftrace: unlink for session: 8cffbd5c7348b526
symbol: loading symbols from ./b.out
symbol: loading dynamic symbols from ./b.out
symbol: saving symbols to /tmp/uftrace-live-ndcHUa/b.out.sym
symbol: unload symbol tables
uftrace: live-record finished.. 
uftrace: start live-replaying...
uftrace: reading /tmp/uftrace-live-ndcHUa/task.txt file
session: new session: pid = 27414, session = 8cffbd5c7348b526
symbol: loading symbols from /tmp/uftrace-live-ndcHUa/b.out.sym: offset = 400000
session: task session: tid = 27414, session = 8cffbd5c7348b526
session: new task: tid = 27414, session = 8cffbd5c7348b526
session: task session: tid = 27417, session = 8cffbd5c7348b526
session: new task: tid = 27417, session = 8cffbd5c7348b526
session: task session: tid = 27418, session = 8cffbd5c7348b526
session: new task: tid = 27418, session = 8cffbd5c7348b526
session: new session: pid = 27418, session = 9cae909fe80cca00
symbol: loading symbols from /home/rlukasik/a.out
symbol: loading dynamic symbols from /home/rlukasik/a.out
session: task session: tid = 27418, session = 9cae909fe80cca00
fstack: opening /tmp/uftrace-live-ndcHUa/27414.dat
fstack: opening /tmp/uftrace-live-ndcHUa/27417.dat
fstack: opening /tmp/uftrace-live-ndcHUa/27418.dat
filter: add filter for execl
filter: add filter for fork
# DURATION    TID     FUNCTION
fstack: ENTRY: [27414] stack: 0, depth: 0, disp: 0, I: 0, O: 0, D: 1024, flags = 0 
            [27414] | _GLOBAL__sub_I_main() {
fstack: ENTRY: [27414] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
            [27414] |   __static_initialization_and_destruction_0() {
fstack: ENTRY: [27414] stack: 2, depth: 2, disp: 2, I: 0, O: 0, D: 1022, flags = 0 
 122.787 us [27414] |     std::ios_base::Init::Init();
fstack: EXIT : [27414] stack: 2, depth: 1022, disp: 2, I: 0, O: 0, D: 1021, flags = 0
 126.232 us [27414] |   } /* __static_initialization_and_destruction_0 */
fstack: EXIT : [27414] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
 126.534 us [27414] | } /* _GLOBAL__sub_I_main */
fstack: EXIT : [27414] stack: 0, depth: 1024, disp: 0, I: 0, O: 0, D: 1023, flags = 0
fstack: ENTRY: [27414] stack: 0, depth: 0, disp: 0, I: 0, O: 0, D: 1024, flags = 0 
            [27414] | main() {
fstack: ENTRY: [27414] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
   9.038 us [27414] |   std::operator <<();
fstack: EXIT : [27414] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27414] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
  67.883 us [27414] |   std::basic_ostream::operator <<();
fstack: EXIT : [27414] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27414] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
  32.191 us [27414] |   pthread_create();
fstack: EXIT : [27414] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27414] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
   1.041 us [27414] |   std::operator <<();
fstack: EXIT : [27414] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27414] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
  51.797 us [27414] |   std::basic_ostream::operator <<();
fstack: EXIT : [27414] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27414] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
            [27414] |   pthread_join() {
fstack: ENTRY: [27417] stack: 0, depth: 0, disp: 0, I: 0, O: 0, D: 1024, flags = 0 
            [27417] | dispather_monitor_thread_entry() {
fstack: ENTRY: [27417] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
   1.180 us [27417] |   std::operator <<();
fstack: EXIT : [27417] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27417] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
  46.969 us [27417] |   std::basic_ostream::operator <<();
fstack: EXIT : [27417] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27417] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
   2.340 us [27417] |   fflush();
fstack: EXIT : [27417] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27417] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
filter: filter match: fork
 157.368 us [27417] |   fork();
fstack: EXIT : [27417] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27417] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
            [27417] |   dispatcher_monitor() {
fstack: ENTRY: [27417] stack: 2, depth: 2, disp: 2, I: 0, O: 0, D: 1022, flags = 0 
            [27417] |     waitpid() {
            [27418] | } /* fork */
fstack: EXIT : [27418] stack: 1, depth: 1024, disp: 0, I: 0, O: 0, D: 1024, flags = 0
fstack: ENTRY: [27418] stack: 1, depth: 1, disp: 0, I: 0, O: 0, D: 1024, flags = 0 
            [27418] | dispatcher_exec() {
fstack: ENTRY: [27418] stack: 2, depth: 2, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
  18.083 us [27418] |   std::operator <<();
fstack: EXIT : [27418] stack: 2, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27418] stack: 2, depth: 2, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
  21.914 us [27418] |   std::basic_ostream::operator <<();
fstack: EXIT : [27418] stack: 2, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27418] stack: 2, depth: 2, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
filter: filter match: execl
            [27418] |   execl() {
fstack: ENTRY: [27418] stack: 0, depth: 0, disp: 0, I: 0, O: 0, D: 1022, flags = 0 
            [27418] | _GLOBAL__sub_I_main() {
fstack: ENTRY: [27418] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1021, flags = 0 
            [27418] |   __static_initialization_and_destruction_0() {
fstack: ENTRY: [27418] stack: 2, depth: 2, disp: 2, I: 0, O: 0, D: 1020, flags = 0 
 182.925 us [27418] |     std::ios_base::Init::Init();
fstack: EXIT : [27418] stack: 2, depth: 1020, disp: 2, I: 0, O: 0, D: 1019, flags = 0
 187.411 us [27418] |   } /* __static_initialization_and_destruction_0 */
fstack: EXIT : [27418] stack: 1, depth: 1021, disp: 1, I: 0, O: 0, D: 1020, flags = 0
 187.710 us [27418] | } /* _GLOBAL__sub_I_main */
fstack: EXIT : [27418] stack: 0, depth: 1022, disp: 0, I: 0, O: 0, D: 1021, flags = 0
fstack: ENTRY: [27418] stack: 0, depth: 0, disp: 0, I: 0, O: 0, D: 1022, flags = 0 
            [27418] | main() {
fstack: ENTRY: [27418] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1021, flags = 0 
  16.067 us [27418] |   std::operator <<();

uftrace -vv b.out (with execve)

symbol: check trace functions in ./b.out
uftrace: creating 1 thread(s) for recording
uftrace: start writer thread 0
uftrace: using libmcount.so library for tracing
mcount: initializing mcount library
symbol: loading dynamic symbols from /home/rlukasik/b.out
mcount: opening executable image: /home/rlukasik/b.out
mcount: found GOT at 0x602000 (PLT resolver: 0x7f27f7d60870)
mcount: overwrite [11] mcount: 0x7f27f7b3ecb0
mcount: mcount setup done
uftrace: MSG SESSION: 27399: /home/rlukasik/b.out (628a8e93ec92bbd6)
mcount: preparing shmem buffers
uftrace: MSG START: /uftrace-628a8e93ec92bbd6-27399-000
uftrace: MSG TASK : 27399/27399
main()
Great success
mcount: preparing shmem buffers
uftrace: MSG START: /uftrace-628a8e93ec92bbd6-27402-000
uftrace: MSG TASK : 27399/27402
dispather_monitor_thread_entry
uftrace: MSG FORK1: 27399/-1
mcount: releasing all shmem buffers for task 27403
mcount: preparing shmem buffers
uftrace: MSG START: /uftrace-628a8e93ec92bbd6-27403-000
uftrace: MSG FORK2: 27399/27403
dispatcher_exec
a.out
mcount: shmem_finish: tid: 27402 seqnum = 0 curr = 0, nr_buf = 2 max_buf = 2
mcount: releasing all shmem buffers for task 27402
uftrace: MSG  END : /uftrace-628a8e93ec92bbd6-27402-000
mcount: shmem_finish: tid: 27399 seqnum = 0 curr = 0, nr_buf = 2 max_buf = 2
mcount: releasing all shmem buffers for task 27399
uftrace: MSG  END : /uftrace-628a8e93ec92bbd6-27399-000
uftrace: all process/thread exited
uftrace: child terminated with exit code: 0
uftrace: reading /tmp/uftrace-live-bxnzUh/task.txt file
session: new task: tid = 27399
session: new task: tid = 27402
session: new task: tid = 27403
uftrace: stop writer thread 0
uftrace: flushing /uftrace-628a8e93ec92bbd6-27403-000
uftrace: unlink for session: 628a8e93ec92bbd6
symbol: loading symbols from ./b.out
symbol: loading dynamic symbols from ./b.out
symbol: saving symbols to /tmp/uftrace-live-bxnzUh/b.out.sym
symbol: unload symbol tables
uftrace: live-record finished.. 
uftrace: start live-replaying...
uftrace: reading /tmp/uftrace-live-bxnzUh/task.txt file
session: new session: pid = 27399, session = 628a8e93ec92bbd6
symbol: loading symbols from /tmp/uftrace-live-bxnzUh/b.out.sym: offset = 400000
session: task session: tid = 27399, session = 628a8e93ec92bbd6
session: new task: tid = 27399, session = 628a8e93ec92bbd6
session: task session: tid = 27402, session = 628a8e93ec92bbd6
session: new task: tid = 27402, session = 628a8e93ec92bbd6
session: task session: tid = 27403, session = 628a8e93ec92bbd6
session: new task: tid = 27403, session = 628a8e93ec92bbd6
fstack: opening /tmp/uftrace-live-bxnzUh/27399.dat
fstack: opening /tmp/uftrace-live-bxnzUh/27402.dat
fstack: opening /tmp/uftrace-live-bxnzUh/27403.dat
filter: add filter for execve
filter: add filter for fork
# DURATION    TID     FUNCTION
fstack: ENTRY: [27399] stack: 0, depth: 0, disp: 0, I: 0, O: 0, D: 1024, flags = 0 
            [27399] | _GLOBAL__sub_I_main() {
fstack: ENTRY: [27399] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
            [27399] |   __static_initialization_and_destruction_0() {
fstack: ENTRY: [27399] stack: 2, depth: 2, disp: 2, I: 0, O: 0, D: 1022, flags = 0 
 112.638 us [27399] |     std::ios_base::Init::Init();
fstack: EXIT : [27399] stack: 2, depth: 1022, disp: 2, I: 0, O: 0, D: 1021, flags = 0
 116.223 us [27399] |   } /* __static_initialization_and_destruction_0 */
fstack: EXIT : [27399] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
 116.713 us [27399] | } /* _GLOBAL__sub_I_main */
fstack: EXIT : [27399] stack: 0, depth: 1024, disp: 0, I: 0, O: 0, D: 1023, flags = 0
fstack: ENTRY: [27399] stack: 0, depth: 0, disp: 0, I: 0, O: 0, D: 1024, flags = 0 
            [27399] | main() {
fstack: ENTRY: [27399] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
  14.480 us [27399] |   std::operator <<();
fstack: EXIT : [27399] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27399] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
   9.620 us [27399] |   std::basic_ostream::operator <<();
fstack: EXIT : [27399] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27399] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
  26.550 us [27399] |   pthread_create();
fstack: EXIT : [27399] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27399] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
   0.845 us [27399] |   std::operator <<();
fstack: EXIT : [27399] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27399] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
   1.490 us [27399] |   std::basic_ostream::operator <<();
fstack: EXIT : [27399] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27399] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
            [27399] |   pthread_join() {
fstack: ENTRY: [27402] stack: 0, depth: 0, disp: 0, I: 0, O: 0, D: 1024, flags = 0 
            [27402] | dispather_monitor_thread_entry() {
fstack: ENTRY: [27402] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
   3.039 us [27402] |   std::operator <<();
fstack: EXIT : [27402] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27402] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
   3.755 us [27402] |   std::basic_ostream::operator <<();
fstack: EXIT : [27402] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27402] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
   2.753 us [27402] |   fflush();
fstack: EXIT : [27402] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27402] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
filter: filter match: fork
 314.505 us [27402] |   fork();
fstack: EXIT : [27402] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27402] stack: 1, depth: 1, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
            [27402] |   dispatcher_monitor() {
fstack: ENTRY: [27402] stack: 2, depth: 2, disp: 2, I: 0, O: 0, D: 1022, flags = 0 
            [27402] |     waitpid() {
            [27403] | } /* fork */
fstack: EXIT : [27403] stack: 1, depth: 1024, disp: 0, I: 0, O: 0, D: 1024, flags = 0
fstack: ENTRY: [27403] stack: 1, depth: 1, disp: 0, I: 0, O: 0, D: 1024, flags = 0 
            [27403] | dispatcher_exec() {
fstack: ENTRY: [27403] stack: 2, depth: 2, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
  17.744 us [27403] |   std::operator <<();
fstack: EXIT : [27403] stack: 2, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27403] stack: 2, depth: 2, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
  73.801 us [27403] |   std::basic_ostream::operator <<();
fstack: EXIT : [27403] stack: 2, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
fstack: ENTRY: [27403] stack: 2, depth: 2, disp: 1, I: 0, O: 0, D: 1023, flags = 0 
filter: filter match: execve
            [27403] |   execve() {
   1.005  s [27402] |     } /* waitpid */
fstack: EXIT : [27402] stack: 2, depth: 1022, disp: 2, I: 0, O: 0, D: 1021, flags = 0
   1.005  s [27402] |   } /* dispatcher_monitor */
fstack: EXIT : [27402] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
   1.005  s [27402] | } /* dispather_monitor_thread_entry */
fstack: EXIT : [27402] stack: 0, depth: 1024, disp: 0, I: 0, O: 0, D: 1023, flags = 0
   1.008  s [27399] |   } /* pthread_join */
fstack: EXIT : [27399] stack: 1, depth: 1023, disp: 1, I: 0, O: 0, D: 1022, flags = 0
   1.008  s [27399] | } /* main */
fstack: EXIT : [27399] stack: 0, depth: 1024, disp: 0, I: 0, O: 0, D: 1023, flags = 0
fstack: ENTRY: [27399] stack: 0, depth: 0, disp: 0, I: 0, O: 0, D: 1024, flags = 0 
   8.769 us [27399] | std::ios_base::Init::~Init();
fstack: EXIT : [27399] stack: 0, depth: 1024, disp: 0, I: 0, O: 0, D: 1023, flags = 0
symbol: unload symbol tables

file: b.cpp

#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <sys/wait.h>
#include <errno.h>
#include <cstdio>


static bool dispatcher_exec()
{
    std::cout << "dispatcher_exec" << std::endl;
    //return execl("/home/rlukasik/a.out", "/home/rlukasik/a.out", (char* const*)NULL);
    return execve("/home/rlukasik/a.out", NULL, NULL);
}

static void dispatcher_monitor(pid_t pid)
{
    int status;

    while (waitpid(pid, &status, 0) == -1)
    {
        if(errno != EINTR && errno != ECHILD)
        {
            break;
        }
    }
}
    
static void* dispather_monitor_thread_entry(void* arg)
{
    std::cout << "dispather_monitor_thread_entry" << std::endl;
    pid_t pid;
    (void) arg;

    fflush(NULL);
    pid = fork();

    if(pid == (pid_t)(-1))
    {
        std::cout << "fork() failed!" << std::endl;
        return (NULL);
    }
    else if(pid == 0)
        (void)dispatcher_exec();
    else
        dispatcher_monitor(pid);

    return (NULL);
}

int main()
{
    std::cout << "main()" << std::endl;

    pthread_t thread;

    if(pthread_create(&thread, NULL, dispather_monitor_thread_entry, NULL) != 0)
    {
        std::cout << "pthread_create() failed!" << std::endl;
    }
    else
        std::cout << "Great success" << std::endl;

    pthread_join(thread, NULL);
    return 0;
}

file a.cpp

#include <iostream>
#include <unistd.h>

int main()
{
    std::cout << "a.out" << std::endl;
    sleep(1);

    return 0;
}

Chromium is not properly traced with -t 30us

As I mentioned in issue #41, headless chrome doesn't work properly when I run it with -t 30us.
There are 2 different problematic cases.

Case 1. the target program goes zombie process and does not finish.

$ uftrace record --no-pager -t 30us ./headless_shell --no-sandbox https://www.google.com
[1228/162649:INFO:fake_audio_manager.cc(23)] FakeAudioManager
[1228/162649:ERROR:child_process_launcher.cc(528)] Failed to launch child process
[1228/162650:WARNING:message_queue.cc(38)] Leaking 1 ports in unreceived messages
[1228/162650:WARNING:message_queue.cc(38)] Leaking 2 ports in unreceived messages
[1228/162650:WARNING:message_queue.cc(38)] Leaking 1 ports in unreceived messages

Case 2. the target program crashes and shows StackTrace messages.

$ uftrace record --no-pager -t 30us ./headless_shell --no-sandbox https://www.google.com
[1228/162441:INFO:fake_audio_manager.cc(23)] FakeAudioManager
Received signal 11 <unknown> 000000000000
#0 0x000007fa5e59 base::debug::StackTrace::StackTrace()
#1 0x000007fa597f base::debug::(anonymous namespace)::StackDumpSignalHandler()
#2 0x7f55de8fd340 <unknown>
#3 0x7f55e1050f66 record_ret_stack
#4 0x7f55e10512c1 record_trace_data
#5 0x7f55e104fc86 mcount_exit_filter_record
#6 0x7f55e105082c __cyg_profile_func_exit
#7 0x000000440a22 (anonymous namespace)::TCFree()
#8 0x00000043ee12 ShimFree
#9 0x7f55e10510f2 clear_shmem_buffer
#10 0x7f55e104fb6d atfork_child_handler
#11 0x7f55de5e9147 __libc_fork
#12 0x00000a96cea0 sandbox::Credentials::ForkAndDropCapabilitiesInChild()
#13 0x0000021ccfa5 content::Zygote::ForkWithRealPid()
#14 0x0000021ce4fa content::Zygote::ReadArgsAndFork()
#15 0x0000021cb8dd content::Zygote::HandleForkRequest()
#16 0x0000021cad41 content::Zygote::HandleRequestFromBrowser()
#17 0x0000021ca2fe content::Zygote::ProcessRequests()
#18 0x0000021da26b content::ZygoteMain()
#19 0x000007ab2b9a content::RunZygote()
#20 0x000007ab33b0 content::RunNamedProcessTypeMain()
#21 0x000007ab64d4 content::ContentMainRunnerImpl::Run()
#22 0x000007ab20bd content::ContentMain()
#23 0x000007e66744 headless::(anonymous namespace)::RunContentMain()
#24 0x000007e6650f headless::RunChildProcessIfNeeded()
#25 0x000000428d31 main
#26 0x7f55de549ec5 __libc_start_main
#27 0x000000428bf5 <unknown>
  r8: cdcdcdcdcdcdcdcd  r9: 0000000000000001 r10: 0000000030bc87ce r11: 00007f55de6afc70
 r12: 0013104eb6c5658e r13: 00007f55e145e790 r14: 0000000000000001 r15: 0000000000000000
  di: 000000000001fff0  si: 0000000000000000  bp: 00007f55e145e790  bx: 0000000000000000
  dx: 000023cca89573e0  ax: 000023cca8947d90  cx: 0000000000000000  sp: 00007ffc9c3cac10
  ip: 00007f55e1050f66 efl: 0000000000010213 cgf: 0000000000000033 erf: 0000000000000000
 trp: 000000000000000d msk: 0000000000010000 cr2: 0000000010d34a18
[end of stack trace]
[1228/162441:ERROR:zygote_communication_linux.cc(144)] Did not receive ping from zygote child
[1228/162441:FATAL:zygote_communication_linux.cc(145)] Check failed: false.
#0 0x000007fa5e59 base::debug::StackTrace::StackTrace()
#1 0x000008001f30 logging::LogMessage::~LogMessage()
#2 0x0000021c6183 content::ZygoteCommunication::ForkRequest()
#3 0x00000132b060 content::(anonymous namespace)::LaunchOnLauncherThread()
#4 0x0000013345ee _ZNK4base8internal15RunnableAdapterIPFvRKNS_8CallbackIFvPN7content19ZygoteCommunicationENS_7ProcessEiELNS0_8CopyModeE1EEENS3_13BrowserThread2IDEiPNS3_32SandboxedProcessLauncherDelegateEN4mojo3edk20ScopedPlatformHandleEP
NS_11CommandLineEEE3RunIJSB_RKSD_RKiRKSF_SI_RKSK_EEEvDpOT_
#5 0x000001334219 _ZN4base8internal12InvokeHelperILb0EvE8MakeItSoIRKNS0_15RunnableAdapterIPFvRKNS_8CallbackIFvPN7content19ZygoteCommunicationENS_7ProcessEiELNS0_8CopyModeE1EEENS6_13BrowserThread2IDEiPNS6_32SandboxedProcessLauncherDelegat
eEN4mojo3edk20ScopedPlatformHandleEPNS_11CommandLineEEEEJSE_RKSG_RKiRKSI_SL_RKSN_EEEvOT_DpOT0_
#6 0x0000013340ee _ZN4base8internal7InvokerINS0_9BindStateINS0_15RunnableAdapterIPFvRKNS_8CallbackIFvPN7content19ZygoteCommunicationENS_7ProcessEiELNS0_8CopyModeE1EEENS5_13BrowserThread2IDEiPNS5_32SandboxedProcessLauncherDelegateEN4mojo3
edk20ScopedPlatformHandleEPNS_11CommandLineEEEEJRSB_RSF_RiRSH_NS0_13PassedWrapperISK_EERSM_EEEFvvEE7RunImplIRKSP_RKSt5tupleIJSB_SF_iSH_SV_SM_EEJLm0ELm1ELm2ELm3ELm4ELm5EEEEvOT_OT0_NS_13IndexSequenceIJXspT1_EEEE
#7 0x00000133360f _ZN4base8internal7InvokerINS0_9BindStateINS0_15RunnableAdapterIPFvRKNS_8CallbackIFvPN7content19ZygoteCommunicationENS_7ProcessEiELNS0_8CopyModeE1EEENS5_13BrowserThread2IDEiPNS5_32SandboxedProcessLauncherDelegateEN4mojo3
edk20ScopedPlatformHandleEPNS_11CommandLineEEEEJRSB_RSF_RiRSH_NS0_13PassedWrapperISK_EERSM_EEEFvvEE3RunEPNS0_13BindStateBaseE
#8 0x000000523e6c base::Callback<>::Run()
#9 0x000008205670 base::debug::TaskAnnotator::RunTask()
#10 0x0000080201cf base::MessageLoop::RunTask()
#11 0x00000802058e base::MessageLoop::DeferOrRunPendingTask()
#12 0x0000080208ad base::MessageLoop::DoWork()
#13 0x00000803e4d6 base::MessagePumpDefault::Run()
#14 0x00000801fb20 base::MessageLoop::RunHandler()
#15 0x0000080cf382 base::RunLoop::Run()
#16 0x00000814d9d8 base::Thread::Run()
#17 0x000001258ca6 content::BrowserThreadImpl::ProcessLauncherThreadRun()
#18 0x0000012592fd content::BrowserThreadImpl::Run()
#19 0x00000814dd7e base::Thread::ThreadMain()
#20 0x0000081345ba base::(anonymous namespace)::ThreadFunc()
#21 0x7fd8bf944182 start_thread
#22 0x7fd8bf67147d clone

[0100/000000:FATAL:zygote_linux.cc(515)] Check failed: len > 0 (0 vs. 0)
#0 0x000007fa5e59 base::debug::StackTrace::StackTrace()
#1 0x000008001f30 logging::LogMessage::~LogMessage()
#2 0x0000021cd3f0 content::Zygote::ForkWithRealPid()
#3 0x0000021ce4fa content::Zygote::ReadArgsAndFork()
#4 0x0000021cb8dd content::Zygote::HandleForkRequest()
#5 0x0000021cad41 content::Zygote::HandleRequestFromBrowser()
#6 0x0000021ca2fe content::Zygote::ProcessRequests()
#7 0x0000021da26b content::ZygoteMain()
#8 0x000007ab2b9a content::RunZygote()
#9 0x000007ab33b0 content::RunNamedProcessTypeMain()
#10 0x000007ab64d4 content::ContentMainRunnerImpl::Run()
#11 0x000007ab20bd content::ContentMain()
#12 0x000007e66744 headless::(anonymous namespace)::RunContentMain()
#13 0x000007e6650f headless::RunChildProcessIfNeeded()
#14 0x000000428d31 main
#15 0x7f55de549ec5 __libc_start_main
#16 0x000000428bf5 <unknown>

Received signal 6
#0 0x000007fa5e59 base::debug::StackTrace::StackTrace()
#1 0x000007fa597f base::debug::(anonymous namespace)::StackDumpSignalHandler()
#2 0x7f55de8fd340 <unknown>
#3 0x7f55de55ecc9 gsignal
#4 0x7f55de5620d8 abort
#5 0x000007fa4819 base::debug::(anonymous namespace)::DebugBreak()
#6 0x000007fa47db base::debug::BreakDebugger()
#7 0x00000800227e logging::LogMessage::~LogMessage()
#8 0x0000021cd3f0 content::Zygote::ForkWithRealPid()
#9 0x0000021ce4fa content::Zygote::ReadArgsAndFork()
#10 0x0000021cb8dd content::Zygote::HandleForkRequest()
#11 0x0000021cad41 content::Zygote::HandleRequestFromBrowser()
#12 0x0000021ca2fe content::Zygote::ProcessRequests()
#13 0x0000021da26b content::ZygoteMain()
#14 0x000007ab2b9a content::RunZygote()
#15 0x000007ab33b0 content::RunNamedProcessTypeMain()
#16 0x000007ab64d4 content::ContentMainRunnerImpl::Run()
#17 0x000007ab20bd content::ContentMain()
#18 0x000007e66744 headless::(anonymous namespace)::RunContentMain()
#19 0x000007e6650f headless::RunChildProcessIfNeeded()
#20 0x000000428d31 main
#21 0x7f55de549ec5 __libc_start_main
#22 0x000000428bf5 <unknown>
  r8: 0000000000000030  r9: 0000000000000001 r10: 0000000000000008 r11: 0000000000000206
 r12: 0000000000428bcc r13: 00007ffc9c3d53b0 r14: 0000000000000000 r15: 0000000000000000
  di: 0000000000005d99  si: 0000000000005d99  bp: 00007ffc9c3ca8b0  bx: 00007ffc9c3d2f20
  dx: 0000000000000006  ax: 0000000000000000  cx: 00007f55de55ecc9  sp: 00007ffc9c3ca778
  ip: 00007f55de55ecc9 efl: 0000000000000206 cgf: 0000000000000033 erf: 0000000000000007
 trp: 000000000000000e msk: 0000000000010000 cr2: 0000000010d34a18
[end of stack trace]
child terminated by signal: 6: Aborted
^C

Please have a look at it!

Assertion error: Assertion `sess' failed when reading multithreaded data

I don't know if it's me, a bug or just lack of documentation, but I get this message when trying to 'uftrace report' on data from a multithreaded application (compiled with -lpthread):

uftrace: /home/me/sources/uftrace/utils/session.c:198: add_session_ref: Assertion sess' failed.`

This is my task.txt file. It appears to have no way to identify the session for tid 9461. Shouldn't the SESS argument be the pid instead of the tid?

[me@me multithread]$ cat uftrace.data/task.txt 
SESS timestamp=2525026.536462738 tid=9460 sid=c979e932a604f4f8 exename="/home/me/sources/test/multithread/multithread"
TASK timestamp=2525026.536514704 tid=9460 pid=9457
TASK timestamp=2525026.536579834 tid=9461 pid=9457

I can work on a fix if need be.

kernel event tracing support

The linux kernel provides event tracing though tracefs. As we use ftrace infrastructure for function tracing, event tracing can be supported same way. Allow -E option can have events contain "@kernel" mark for kernel event tracing. The event information will be saved in "kernel_header" file in the data directory.

Following example shows scheduler events during sleep 1 second.

  $ sudo uftrace -k -E sched:*@kernel --force /usr/bin/sleep 1
  # DURATION    TID     FUNCTION
  ...
     3.529 us [23463] | bindtextdomain();
     2.021 us [23463] | textdomain();
     1.419 us [23463] | __cxa_atexit();
              [23463] | getopt_long() {
              [23463] |   __do_page_fault() {
              [23463] |     /* [sched:sched_waking] comm=uftrace pid=23464 prio=120 target_cpu=003 *  /
              [23463] |     /* [sched:sched_wake_idle_without_ipi] cpu=3 */
              [23463] |     /* [sched:sched_wakeup] comm=uftrace pid=23464 prio=120 target_cpu=003 *  /
    25.903 us [23463] |   } /* __do_page_fault */
     1.478 us [23463] |   smp_irq_work_interrupt();
    32.931 us [23463] | } /* getopt_long */
     0.775 us [23463] | getopt_long();
     1.929 us [23463] | __errno_location();
     1.202 us [23463] | newlocale();
     4.695 us [23463] | strtod_l();
     0.203 us [23463] | __errno_location();
              [23463] | nanosleep() {
              [23463] |   sys_nanosleep() {
     1.560 us [23463] |     smp_irq_work_interrupt();
              [23463] |     /* [sched:sched_stat_runtime] comm=sleep pid=23463 runtime=341360 [ns] vruntime=2911893876206 [ns] */
              [23463] |     /* [sched:sched_switch] prev_comm=sleep prev_pid=23463 prev_prio=120 prev_state=S ==> next_comm=swapper/2 next_pid=0 next_prio=120 */
     1.000  s [23463] |   } /* sys_nanosleep */
     1.000  s [23463] | } /* nanosleep */
    12.491 us [23463] | __fpending();
     3.210 us [23463] | fileno();
     2.337 us [23463] | __freading();
     0.346 us [23463] | __freading();
     4.188 us [23463] | fflush();
              [23463] | fclose() {
              [23463] |   sys_close() {
     3.812 us [23463] |     smp_irq_work_interrupt();
    14.803 us [23463] |   } /* sys_close */
    27.770 us [23463] | } /* fclose */
  ...

Pushed the code to review/kernel-event-v1 branch.

support scheduler event using perf syscall

The Linux perf event system (from kernel v4.3) provides a way to trace scheduler context switch event without root privilege. Using these events, one can know the program behavior more precisely IMHO. Currently it only traces sched in/out events, but other events like page fault can be added easily if needed. For now these sched events are always enabled if system supports.

Following example shows a result of the t-sleep test program:

$ uftrace record -d sleep.data tests/t-sleep

$ uftrace replay -d sleep.data
# DURATION    TID     FUNCTION
            [19307] | main() {
            [19307] |   foo() {
            [19307] |     mem_alloc() {
   1.526 us [19307] |       malloc();
   6.130 us [19307] |     } /* mem_alloc */
            [19307] |     bar() {
            [19307] |       usleep() {
            [19307] |         /* perf_event: sched-out */
   2.118 ms [19307] |         /* perf_event: sched-in */
   2.135 ms [19307] |       } /* usleep */
   2.137 ms [19307] |     } /* bar */
            [19307] |     mem_free() {
   3.700 us [19307] |       free();
   4.655 us [19307] |     } /* mem_free */
   2.149 ms [19307] |   } /* foo */
   2.150 ms [19307] | } /* main */

$ uftrace report -d sleep.data
  Total time   Self time       Calls  Function
  ==========  ==========  ==========  ====================================
    2.150 ms    0.486 us           1  main
    2.149 ms    1.121 us           1  foo
    2.137 ms    2.218 us           1  bar
    2.135 ms   16.918 us           1  usleep
    6.130 us    4.604 us           1  mem_alloc
    4.655 us    0.955 us           1  mem_free
    3.700 us    3.700 us           1  free
    1.526 us    1.526 us           1  malloc

This is another example with two threads:

$ uftrace foobar
# DURATION    TID     FUNCTION
   1.185 us [19369] | __monstartup();
   1.117 us [19369] | __cxa_atexit();
            [19369] | main() {
            [19369] |   foo() {
   0.135 us [19369] |     bar();
   0.732 us [19369] |   } /* foo */
  76.508 us [19369] |   pthread_create();
            [19369] |   pthread_join() {
            [19369] |     /* perf_event: sched-out */
            [19373] | /* perf_event: sched-in */
            [19373] | foo() {
   0.203 us [19373] |   bar();
   1.656 us [19373] | } /* foo */
 267.295 us [19369] |     /* perf_event: sched-in */
 283.937 us [19369] |   } /* pthread_join */
 363.592 us [19369] | } /* main */

Pushed the code to review/sched-event-v1.

can not find symbol in mcount support (on ARM)

I ran the ./runtest.py on machine. Most of test cases are passed but I got the error on two test cases as below:

root@kesl:~/uftrace/tests# ./runtest.py 076
Test case pg finstrument-fu
--------------------: O0 O1 O2 O3 Os O0 O1 O2 O3 Os
uftrace: /root/uftrace/arch/arm/mcount-support.c:263:mcount_arch_parent_location
ERROR: cannot find symbol for b6efd631
uftrace: /root/uftrace/arch/arm/mcount-support.c:263:mcount_arch_parent_location
ERROR: cannot find symbol for b6f2b65f
uftrace: /root/uftrace/arch/arm/mcount-support.c:263:mcount_arch_parent_location
ERROR: cannot find symbol for b6f1565f
uftrace: /root/uftrace/arch/arm/mcount-support.c:263:mcount_arch_parent_location
ERROR: cannot find symbol for b6f4665f
uftrace: /root/uftrace/arch/arm/mcount-support.c:263:mcount_arch_parent_location
ERROR: cannot find symbol for b6f7a65d
076 lib_replay_F : NG NG NG NG NG NG NG NG NG NG

root@kesl:~/uftrace/tests# ./runtest.py 077
Test case pg finstrument-fu
--------------------: O0 O1 O2 O3 Os O0 O1 O2 O3 Os
uftrace: /root/uftrace/arch/arm/mcount-support.c:263:mcount_arch_parent_location
ERROR: cannot find symbol for b6ef6631
uftrace: /root/uftrace/arch/arm/mcount-support.c:263:mcount_arch_parent_location
ERROR: cannot find symbol for b6f2165f
uftrace: /root/uftrace/arch/arm/mcount-support.c:263:mcount_arch_parent_location
ERROR: cannot find symbol for b6f2665f
uftrace: /root/uftrace/arch/arm/mcount-support.c:263:mcount_arch_parent_location
ERROR: cannot find symbol for b6fba65f
uftrace: /root/uftrace/arch/arm/mcount-support.c:263:mcount_arch_parent_location
ERROR: cannot find symbol for b6f5b65d
077 lib_replay_T : NG NG NG NG NG NG NG NG NG NG

I am not sure whether the error is my configuration problem or a bug.
Could you let me know what the problem is?

(Incompatible) kernel option change

After a discussion with @honggyukim I decided to change some kernel options:

Now --kernel-full (-K) option does 4 things:

  • set kernel depth to max when record
  • set number of writer threads to same as cpus (unless --num-thread option is given) when record
  • set internal timeout to 10us for checking kernel buffer when record
  • show kernel functions outside of fuser functions when replay (inverse of --kernel-skip-out)

This is not good. I'd like to keep kernel tracing option more simple. While the -k (or --kernel) option does the thing, I think I need to break the -K option too.

  1. setting kernel depth to max is not practical for most cases IMHO and it produces many LOST records. I recommend users to use a much lower kernel depth (default is 1 but you may want 2 or 3) unless you're a kernel developer.
  2. default number of writer thread when tracing kernel should be determined depending on how much data it'll generate. So I think it should consider the kernel depth limit rather than the value of this option.
  3. The timeout of 10us seems so small and I'm afraid it may hurts the performance.
  4. I guess that most users of uftrace focus on their code and how the kernel affect it during the execution. So I think it'd be better hiding kernel functions outside of user functions by default.

Now I'm thinking that the --kernel-full option should do a single job. The item 1 above can be done with --kernel-depth option and I think it'll be used more frequently than others. So the short option -K now goes to the --kernel-depth instead of --kernel-full so it'll require an integer argument. The item 2 will not require any changes of command line options. The item 3 should be gone IMHO. The last, item 4 is what --kernel-full will do from now on.

Once it merges the code in review/kernel-option-change branch (c45b247):

## simple kernel tracing
$ sudo uftrace -k hello

## increase kernel-depth to 2
$ sudo uftrace -k -K2 hello

## show all kernel functions (including outside of user functions)
$ sudo uftrace -k --kernel-full hello

--time-range option seems to be not working

Additionally I tested --time-range option and I think it seems to be not working.
(Same environment : on current master branch; 58639c)

I think there are problems not only about #66 but also when using TIME~TIME
I checked --time-range usage as below.

$ uftrace --help | grep range
  -r, --time-range=TIME~TIME Show output within the TIME range only

But it seems to be not working as below

$ uftrace -r 1us~2us ./a.out
invalid timestamp string
invalid timestamp string
# DURATION    TID     FUNCTION

And if we check TIME STAMP as below,

$ uftrace -f time ./a.out
#     TIMESTAMP       FUNCTION
   174103.519727780 | __monstartup();
   174103.519731523 | __cxa_atexit();
   174103.519733068 | main() {
   174103.519733166 |   fgets();
   174103.519738659 |   get_values_from() {
   174103.519738847 |     strdup();
   174103.519739937 |     strsep();
   174103.519740778 |     atoi();
   174103.519741701 |     atoi();
   174103.519742074 |   } /* get_values_from */
...

and if using --time-range option, the case not work, too.

$ uftrace -r 174103.519738659~174103.519742074 ./old < input.txt 
# DURATION    TID     FUNCTION

But time stamp values are always changed each time uftrace work.
How to use --time-range ?
Is wrong my usage for it ? 😟

need modification in tutorial

When I read a tutorial of function-depth filter part, I was difficult to understand from your assumption.

I'm attaching the original text as below and marking the bold the part of your assumption that I was confused.

========== text from tutorial ==========
The next is function-depth filter. You can use -D or --depth to limit function call depth to be recorded. Below is apply depth-2 filter on the uftrace itself when replay the hello world program. To make it clearer, I named the binary built with the compiler instrumentation as "uftrace-pg" and assume the trace data is in hello.data. The "--" in the command line is to tell the option parser that it's the end of the option. For simplicity, I omitted the output of replaying hello world from the uftrace-pg:
$ uftrace -D 2 -- uftrace-pg replay -d hello.data
========== text from tutorial ==========

The confusion came from how to create hello.data. Even if uftrace can record the trace data to specific directory and you discussed at the front of tutorial, there is no kindly guideline to store tracing data to specific directory.

When I was executed "uftrace record hello -d hello.data" at the first time, because I followed replay command in the example. After I executed the command, only “uftrace.data” was created. The reason made me confused. Anyway, I found the way to store data with directory name. There are two ways to use “uftrace -d hello.data record hello” or “uftrace record -d hello.data hello”.

The command “uftrace record hello -d hello.data” is no effect to directory’s name, Is it your intention? or is the problem in parsing the argument in uftrace?

Anyway, the goal of the paragraph is to show feature of function-depth tracing, isn’t it? If so, it would be better to use a simpler example for user like me (newbie) instead of uftrace-pg and hello.data. You know, the newbie like me, expects examples in the tutorial will run without modification.

PLT hook segfault from <__fentry__@plt> on GCC7

This problem is similar to #92 and #91 .
But this only -pg -mfentry case is like below.

  • Target program
$ cat  hello.c
#include <stdio.h>

void main()
{
	printf("hello\n");
}
  • Failed only -pg -mfentry case (with uftrace built by GCC7)
    (Sure, normal tracing and dynamic tracing are fine)
$ gcc -o hello -pg -mfentry hello.c

$ uftrace ./hello
child terminated by signal: 11: Segmentation fault
# DURATION    TID     FUNCTION
   1.741 us [14660] | __monstartup();
   1.519 us [14660] | __cxa_atexit();

  • With --no-libcall, there isn't segfault.
uftrace --no-libcall ./hello
hello
# DURATION    TID     FUNCTION
   2.212 us [15019] | main();

This problem is related to the 16-byte stack alignment required from GCC7 because of movaps.

$ gdb ./hello core
...
Core was generated by `./hello'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007fa62271d612 in plthook_entry (ret_addr=0x7fff69e186f0, child_idx=4, 
    module_id=140351523635560, regs=0x7fff69e186b0)
    at /home/taeung/git/uftrace/libmcount/plthook.c:429
429		struct ftrace_trigger tr = {
(gdb) disas
Dump of assembler code for function plthook_entry:
   0x00007fa62271d5f0 <+0>:	push   %r15
   0x00007fa62271d5f2 <+2>:	push   %r14
   0x00007fa62271d5f4 <+4>:	push   %r13
   0x00007fa62271d5f6 <+6>:	push   %r12
   0x00007fa62271d5f8 <+8>:	push   %rbp
   0x00007fa62271d5f9 <+9>:	push   %rbx
   0x00007fa62271d5fa <+10>:	pxor   %xmm0,%xmm0
   0x00007fa62271d5fe <+14>:	sub    $0x58,%rsp
   0x00007fa62271d602 <+18>:	lea    0x217318(%rip),%rax        # 0x7fa622934921 <mcount_setup_done>
   0x00007fa62271d609 <+25>:	movq   $0x0,0x40(%rsp)
=> 0x00007fa62271d612 <+34>:	movaps %xmm0,0x20(%rsp)
   0x00007fa62271d617 <+39>:	movzbl (%rax),%r13d
...
(gdb) p $rsp
$1 = (void *) 0x7fff69e18618

AYK, you can check "rsp % 16 != 0" (i.e. 0x7fff69e18618 % 16 = 0x8).

And I checked all values of rsp%16 at the very beginning of plt_hooker() each time it is called with GDB.

(gdb) set follow-fork-mode child
(gdb) b plt_hooker
Function "plt_hooker" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (plt_hooker) pending.
(gdb) r --no-pager ./hello
...
(gdb) bt
#0  0x00007ffff7bca3a4 in plt_hooker () from /usr/local/lib/libmcount-fast.so
#1  0x0000000000400539 in _start ()
(gdb) p $rsp
$1 = (void *) 0x7fffffffddf8
(gdb) c
Continuing.
...
(gdb) bt
#0  0x00007ffff7bca3a4 in plt_hooker () from /usr/local/lib/libmcount-fast.so
#1  0x0000000000400571 in __gmon_start__ ()
#2  0x00000000004004a5 in _init ()
#3  0x0000000200000001 in ?? ()
#4  0x0000000000400681 in __libc_csu_init ()
#5  0x00007ffff780f7bf in __libc_start_main (main=0x400637 <main>, argc=1, 
    argv=0x7fffffffde28, init=0x400650 <__libc_csu_init>, fini=<optimized out>, 
    rtld_fini=<optimized out>, stack_end=0x7fffffffde18) at ../csu/libc-start.c:247
#6  0x0000000000400539 in _start ()
(gdb) p $rsp
$2 = (void *) 0x7fffffffdcd8
(gdb) c
Continuing.
...
(gdb) p $rsp
$3 = (void *) 0x7fffffffdce8
(gdb) c
Continuing.
...
(gdb) bt
#0  0x00007ffff7bca3a4 in plt_hooker () from /usr/local/lib/libmcount-fast.so
#1  0x000000000040063c in main ()
(gdb) p $rsp
$4 = (void *) 0x7fffffffdd30
(gdb) c
Continuing.

Thread 2.1 "hello" received signal SIGSEGV, Segmentation fault.
0x00007ffff7bbf612 in plthook_entry (ret_addr=0x7fffffffdd40, child_idx=4, 
    module_id=140737354129768, regs=0x7fffffffdd00)
    at /home/taeung/git/uftrace/libmcount/plthook.c:429
429		struct ftrace_trigger tr = {
  1. <__libc_start_main@plt> case from _start()
    0x7fffffffddf8 % 16 = 0x8

  2. <__monstartup@plt> case from gmon_start()
    0x7fffffffdcd8 % 16 = 0x8

  3. <__cxa_atexit@plt> case from _init()
    0x7fffffffdce8 % 16 = 0x8

  4. <__fentry__@plt> case from main()
    0x7fffffffdd30 % 16 = 0x0

I thought plt_hooker() adjusts rsp for (rsp % 16 == 0) because of the 16-byte alignment,
but <__fentry__@plt> case is already "rsp % 16 == 0" before plt_hooker() is called.
So we need to add some if-else statement into arch/x86_64/plthook.S ?
Or, my investigation way is wrong ?

Segmentation fault CentOS 7 + devtoolset-6

Hi,

I try to run uftrace in CentOS 7 and I get a segmentation fault that I failed to track down where it occurs. To reproduce it:


$ scl enable devtoolset-6 bash
$ uftrace a.out
uftrace: /uftrace/cmd-live.c:63:sigsegv_handler
Segmentation fault
uftrace: /uftrace/cmd-live.c:27:cleanup_tempdir
 ERROR: cannot open temp dir: File name too long
uftrace: /uftrace/cmd-live.c:27:cleanup_tempdir
 ERROR: cannot open temp dir: File name too long
WARN: invalid task file
 DURATION    TID     FUNCTION
  1. a.out is a oneliner printf("hello world\n")
  2. tried different gcc version with the same result
  3. under gdb, backtrace says "No stack"
  4. if devtoolset-6 is not enabled, the segmentation fault does not occur and the program runs just fine.

The points 3 and 4 make me think that the problem may be related to dynamically linked libraries. It is as if it crashes during process initialization.

I'm confused about this problem. Do you have any ideas?

uftrace rev-id: 985e206

Thanks for this awesome tool!

ERROR: invalid task file: No such file or directory

Hi,

I've run uftrace record with my executable and after its run there's:

dan@octa ~> ls -la uftrace.data/
total 9,1M
-rw-r--r-- 1 dan dan  873 Dez 16 17:13 info
-rw-rw-r-- 1 dan dan 9,1M Dez 16 17:13 VisPER-5.1.003-dev_linux-64.sym

And info contains:

dan@octa ~> cat uftrace.data/info 
Ftrace!(cexename:/home/dan/intes/builds/trunk/profile/visper/bin/VisPER-5.1.003-dev_linux-64
build_id:34395e2328a726069098d6aa75de2fff20d2eca0
exit_status:0
cmdline:uftrace record /home/dan/intes/builds/trunk/profile/visper/bin/VisPER-5.1.003-dev_linux-64 --mem 8000 /home/dan/intes/dms/5.1/vis.DMS1 
cpuinfo:lines=2
cpuinfo:nr_cpus=16 / 16 (online/possible)
cpuinfo:desc=Intel(R) Core(TM) i7-5960X CPU @ 3.00GHz
meminfo:13.1 / 31.3 GB (free / total)
osinfo:lines=3
osinfo:kernel=Linux 4.4.0-34-generic
osinfo:hostname=octa
osinfo:distro="Ubuntu 16.04.1 LTS"
usageinfo:lines=6
usageinfo:systime=108.524000
usageinfo:usrtime=504.436000
usageinfo:ctxsw=43496 / 3448 (voluntary / involuntary)
usageinfo:maxrss=13648052
usageinfo:pagefault=13 / 17769547 (major / minor)
usageinfo:iops=15506976 / 144392 (read / write)
loadinfo:0.86 / 0.94 / 0.63

But now calling uftrace report gives me:

dan@octa ~> uftrace report
uftrace: /home/dan/builds/uftrace/utils/data-file.c:307:open_data_file
 ERROR: invalid task file: No such file or directory

The used uftrace version:

dan@octa ~> uftrace --version
uftrace v0.6-147-g726c

Any ideas?

Greetings,
Daniel

Exception catched in function still throw out causing the program terminating

void test()
{    
    try {
    ┊   throw exception();
    }   
    catch (exception& e)
    {   
    ┊   cout << "exception catched" << endl;
    }                                                                                                                                                                        
    return;
}       
        
int main()
{       
    test();
    return 0;
}

I have a file like above, expected the exception can be catched, when I run without uftrace, it did. but failed running with uftrace. The exception can not be catched running with uftrace

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.