Skip to content

christophebedard/instrument-attribute-gcc-plugin

Repository files navigation

instrument-attribute-gcc-plugin

gcc plugin providing an instrument_function attribute and other gcc flags to specify which functions should be instrumented.

What it does

When enabling function instrumentation (-finstrument-functions), the built-in flags (-finstrument-functions-exclude-file-list=file,file,…, -finstrument-functions-exclude-function-list=sym,sym,…) and attribute (no_instrument_function) only allow you to exclude functions from being instrumented.

This plugin allows you to instrument individual functions, by:

  • adding the instrument_function attribute to a function
  • giving a list of paths to files with function definitions (-fplugin-arg-instrument_attribute-include-file-list=file,file,…)
  • giving a list of function names (-fplugin-arg-instrument_attribute-include-function-list=sym,sym,…)

For example, you might want to use this when you want to instrument only select functions and avoid instrumenting everything, since it adds a measurable overhead.

Of course, you will have to keep in mind that not all functions were instrumented when interpreting the data. For example, the self-time of a function may be misleading if only a portion of the functions it calls are instrumented.

Build the plugin

This has been tested with gcc 7.4.0, 7.5.0, 8.4.0, 9.3.0, and 10.2.0, but it probably works with other versions as well.

Download plugin headers. The exact package name depends on the gcc major version (e.g. gcc-9-plugin-dev for 9.3.0).

$ sudo apt-get install gcc-9-plugin-dev

Then clone and build.

$ git clone https://github.com/christophebedard/instrument-attribute-gcc-plugin.git
$ cd instrument-attribute-gcc-plugin/
$ make

Use the plugin

To use this plugin when building your own application with gcc, add the instrument_function attribute to the function(s) you want to instrument. For example, to instrument main() and instrumented_function(), but not NOT_instrumented_function():

void __attribute__((instrument_function)) instrumented_function()
{
  // This is instrumented
}

void NOT_instrumented_function()
{
  // This is NOT instrumented
}

int __attribute__((instrument_function)) main()
{
  // This is instrumented
  instrumented_function();
  NOT_instrumented_function();
  return 0;
}

Then, to build, simply enable -finstrument-functions and set the path to the plugin with -fplugin=path/to/instrument_attribute.so. Assuming the file above is named test.c:

$ gcc -fplugin=./instrument_attribute.so -finstrument-functions test.c -o test

Similar to gcc's built-in flags, you can also instrument functions by giving a list of file paths and/or by giving a list of names.

-fplugin-arg-instrument_attribute-include-file-list=file,file,…
-fplugin-arg-instrument_attribute-include-function-list=sym,sym,…

These matches are done on substrings. If the given file value is a substring of a file's path, its functions will be instrumented; if the given sym value is a substring of a function's user-visible name, it will be instrumented.

Verbose mode and debugging

You can use the VERBOSE environment variable, i.e. VERBOSE=1. It will print the functions for which instrumentation is enabled.

$ VERBOSE=1 gcc -Itest/e2e/include \
    -fplugin=./instrument_attribute.so -finstrument-functions \
    -fplugin-arg-instrument_attribute-include-file-list=test/e2e/src/some_,test/e2e/include/other/other_file.h \
    -fplugin-arg-instrument_attribute-include-function-list=instrumented_with_function_list,myawesomelib_,random_other_function_name \
    -c test/e2e/src/main.c -o test/e2e/obj/main.o
Plugin: instrument_function attribute
  instrumented function: (test/e2e/include/other/other_file.h:23) other_file_instrumented_with_file_list
  instrumented function: (test/e2e/src/main.c:28) instrumented_function
  instrumented function: (test/e2e/src/main.c:38) instrumented_with_function_list
  instrumented function: (test/e2e/src/main.c:43) main

You can also use the -fplugin-arg-instrument_attribute-debug flag to enable debugging to get much more information and figure out how functions were instrumented. Enabling debugging will also enable verbose mode.

$ gcc -Itest/e2e/include -MMD -MP \
    -fplugin=./instrument_attribute.so -finstrument-functions \
    -fplugin-arg-instrument_attribute-debug \
    -fplugin-arg-instrument_attribute-include-file-list=test/e2e/src/some_,test/e2e/include/other/other_file.h \
    -fplugin-arg-instrument_attribute-include-function-list=instrumented_with_function_list,myawesomelib_,random_other_function_name \
    -c test/e2e/src/main.c -o test/e2e/obj/main.o
Plugin parameter:
  include-file-list: test/e2e/src/some_,test/e2e/include/other/other_file.h
    list of size 2: test/e2e/src/some_, test/e2e/include/other/other_file.h, 
Plugin parameter:
  include-function-list: instrumented_with_function_list,myawesomelib_,random_other_function_name
    list of size 3: instrumented_with_function_list, myawesomelib_, random_other_function_name, 
Plugin: instrument_function attribute
    checking file: test/e2e/include/other/other_file.h
      function instrumented from file list: test/e2e/include/other/other_file.h (other_file_instrumented_with_file_list)
  instrumented function: (test/e2e/include/other/other_file.h:23) other_file_instrumented_with_file_list
    function instrumented from attribute: instrumented_function
  instrumented function: (test/e2e/src/main.c:28) instrumented_function
    checking file: test/e2e/src/main.c
    checking function: not_instrumented_function
  NOT instrumented function: (test/e2e/src/main.c:33) not_instrumented_function
    checking file: test/e2e/src/main.c
    checking function: instrumented_with_function_list
      function instrumented from function name list: instrumented_with_function_list
  instrumented function: (test/e2e/src/main.c:38) instrumented_with_function_list
    function instrumented from attribute: main
  instrumented function: (test/e2e/src/main.c:43) main

Tracing example with LTTng

Install LTTng (this only requires userspace tracing).

$ sudo apt-get install lttng-tools liblttng-ust-dev babeltrace

Start a session daemon if it's not already running.

$ lttng-sessiond --daemon

Build the plugin, then build your application using the plugin (see above).

Then, create an LTTng session.

$ lttng create test --output=./my-test-trace/

Enable the func_entry/func_exit events.

$ lttng enable-event -c testchan -u lttng_ust_cyg_profile_fast:func_entry
$ lttng enable-event -c testchan -u lttng_ust_cyg_profile_fast:func_exit

Start tracing.

$ lttng start

Run your application, making sure to preload the profiling library (note: the path to the shared library might be different on your system).

$ LD_PRELOAD=/usr/lib/x86_64-linux-gnu/liblttng-ust-cyg-profile-fast.so ./your/application

Stop tracing.

$ lttng stop
$ lttng destroy

Use babeltrace to view the output.

$ sudo apt-get install babeltrace
$ babeltrace my-test-trace/

Process the trace data however you want (suggestion: Trace Compass).

Contributing

See CONTRIBUTING.md.

About

gcc plugin providing an instrument_function attribute and other flags to allow-list functions to be instrumented

Topics

Resources

License

Unknown and 2 other licenses found

Licenses found

Unknown
LICENSE
LGPL-3.0
license-lgpl-v3.txt
MIT
license-mit.txt

Stars

Watchers

Forks