From 57e6ede01fbad9faeeb462b2feab6f712cf3b121 Mon Sep 17 00:00:00 2001 From: Christophe Bedard Date: Tue, 8 Oct 2024 08:00:12 -0700 Subject: [PATCH] Allow enabling syscalls through `ros2 trace` or the Trace action (#137) Signed-off-by: Christophe Bedard --- README.md | 4 +- lttngpy/src/lttngpy/_lttngpy_pybind11.cpp | 15 +++++ lttngpy/src/lttngpy/event.cpp | 21 ++++++- lttngpy/src/lttngpy/event.hpp | 10 ++++ .../test/test_ros2trace/test_trace.py | 58 ++++++++++++++++++- .../test_trace_action.py | 10 ++++ tracetools_launch/tracetools_launch/action.py | 15 +++++ .../tracetools_trace/test_lttng_tracing.py | 6 ++ .../tracetools_trace/tools/args.py | 4 ++ .../tracetools_trace/tools/lttng_impl.py | 45 +++++++++----- tracetools_trace/tracetools_trace/trace.py | 23 ++++++-- 11 files changed, 187 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index db363f81..167d14eb 100644 --- a/README.md +++ b/README.md @@ -170,7 +170,7 @@ $ ros2 trace stop session_name # Stop tracing after starting or resuming Run each command with `-h` for more information. -You must [install the kernel tracer](#building) if you want to enable kernel events (using the `-k`/`--kernel-events` option). +You must [install the kernel tracer](#building) if you want to enable [kernel](https://lttng.org/docs/v2.13/#doc-tracing-the-linux-kernel) events (using the `-k`/`--kernel-events` option) or syscalls (using the `--syscalls` option). If you have installed the kernel tracer, use kernel tracing, and still encounter an error here, make sure to [add your user to the `tracing` group](#tracing). ### Launch file trace action @@ -185,7 +185,7 @@ $ ros2 launch tracetools_launch example.launch.py The `Trace` action will also set the `LD_PRELOAD` environment to preload [LTTng's userspace tracing helper(s)](https://lttng.org/docs/v2.13/#doc-prebuilt-ust-helpers) if the corresponding event(s) are enabled. For more information, see [this example launch file](./tracetools_launch/launch/example.launch.py) and the [`Trace` action](./tracetools_launch/tracetools_launch/action.py). -You must [install the kernel tracer](#building) if you want to enable kernel events (`events_kernel` in Python, `events-kernel` in XML or YAML). +You must [install the kernel tracer](#building) if you want to enable [kernel](https://lttng.org/docs/v2.13/#doc-tracing-the-linux-kernel) events (`events_kernel` in Python, `events-kernel` in XML or YAML) or syscalls (`syscalls` in Python, XML, or YAML). If you have installed the kernel tracer, use kernel tracing, and still encounter an error here, make sure to [add your user to the `tracing` group](#tracing). ## Design diff --git a/lttngpy/src/lttngpy/_lttngpy_pybind11.cpp b/lttngpy/src/lttngpy/_lttngpy_pybind11.cpp index 8777fa84..cccf294b 100644 --- a/lttngpy/src/lttngpy/_lttngpy_pybind11.cpp +++ b/lttngpy/src/lttngpy/_lttngpy_pybind11.cpp @@ -130,6 +130,16 @@ PYBIND11_MODULE(_lttngpy_pybind11, m) { py::arg("output")); // Event + py::enum_(m, "lttng_event_type") + .value("LTTNG_EVENT_ALL", LTTNG_EVENT_ALL) + .value("LTTNG_EVENT_TRACEPOINT", LTTNG_EVENT_TRACEPOINT) + .value("LTTNG_EVENT_PROBE", LTTNG_EVENT_PROBE) + .value("LTTNG_EVENT_FUNCTION", LTTNG_EVENT_FUNCTION) + .value("LTTNG_EVENT_FUNCTION_ENTRY", LTTNG_EVENT_FUNCTION_ENTRY) + .value("LTTNG_EVENT_NOOP", LTTNG_EVENT_NOOP) + .value("LTTNG_EVENT_SYSCALL", LTTNG_EVENT_SYSCALL) + .value("LTTNG_EVENT_USERSPACE_PROBE", LTTNG_EVENT_USERSPACE_PROBE) + .export_values(); py::enum_(m, "lttng_event_output") .value("LTTNG_EVENT_SPLICE", LTTNG_EVENT_SPLICE) .value("LTTNG_EVENT_MMAP", LTTNG_EVENT_MMAP) @@ -141,6 +151,7 @@ PYBIND11_MODULE(_lttngpy_pybind11, m) { py::kw_only(), py::arg("session_name"), py::arg("domain_type"), + py::arg("event_type"), py::arg("channel_name"), py::arg("events")); m.def( @@ -149,6 +160,10 @@ PYBIND11_MODULE(_lttngpy_pybind11, m) { "Get tracepoints.", py::kw_only(), py::arg("domain_type")); + m.def( + "get_syscalls", + <tngpy::get_syscalls, + "Get syscalls."); m.def( "add_contexts", <tngpy::add_contexts, diff --git a/lttngpy/src/lttngpy/event.cpp b/lttngpy/src/lttngpy/event.cpp index dac98a56..4b1bd689 100644 --- a/lttngpy/src/lttngpy/event.cpp +++ b/lttngpy/src/lttngpy/event.cpp @@ -35,6 +35,7 @@ namespace lttngpy int enable_events( const std::string & session_name, const enum lttng_domain_type domain_type, + const enum lttng_event_type event_type, const std::string & channel_name, const std::set & events) { @@ -59,7 +60,7 @@ int enable_events( break; } event_name.copy(event->name, LTTNG_SYMBOL_NAME_LEN); - event->type = LTTNG_EVENT_TRACEPOINT; + event->type = event_type; ret = lttng_enable_event(handle, event, channel_name.c_str()); lttng_event_destroy(event); @@ -101,6 +102,24 @@ std::variant> get_tracepoints(const enum lttng_domain return tracepoints_var; } +std::variant> get_syscalls() +{ + struct lttng_event * events = nullptr; + int ret = lttng_list_syscalls(&events); + std::variant> syscalls_var = ret; + if (0 <= ret) { + std::set syscalls = {}; + const int num_events = ret; + for (int i = 0; i < num_events; i++) { + syscalls.insert(events[i].name); + } + syscalls_var = syscalls; + } + + std::free(events); + return syscalls_var; +} + int _fill_in_event_context( const std::string & context_field, const enum lttng_domain_type domain_type, diff --git a/lttngpy/src/lttngpy/event.hpp b/lttngpy/src/lttngpy/event.hpp index 82e7f100..127c2bc8 100644 --- a/lttngpy/src/lttngpy/event.hpp +++ b/lttngpy/src/lttngpy/event.hpp @@ -30,6 +30,7 @@ namespace lttngpy * * \param session_name the session name * \param domain_type the domain type + * \param event_type the event type * \param channel_name the channel name * \param events the set of event names * \return 0 on success, else a negative LTTng error code @@ -37,6 +38,7 @@ namespace lttngpy int enable_events( const std::string & session_name, const enum lttng_domain_type domain_type, + const enum lttng_event_type event_type, const std::string & channel_name, const std::set & events); @@ -49,6 +51,14 @@ int enable_events( */ std::variant> get_tracepoints(const enum lttng_domain_type domain_type); +/** + * Get syscalls. + * + * \return the set of syscalls, else a negative LTTng error code (e.g., if kernel tracer is not + * available) + */ +std::variant> get_syscalls(); + /** * Add contexts. * diff --git a/test_ros2trace/test/test_ros2trace/test_trace.py b/test_ros2trace/test/test_ros2trace/test_trace.py index 0de1cab2..bf48b68a 100644 --- a/test_ros2trace/test/test_ros2trace/test_trace.py +++ b/test_ros2trace/test/test_ros2trace/test_trace.py @@ -26,6 +26,7 @@ from launch import LaunchService from launch_ros.actions import Node from lttngpy import impl as lttngpy +from tracetools_read import get_event_name from tracetools_test.mark_process import get_corresponding_trace_test_events from tracetools_test.mark_process import get_trace_test_id from tracetools_test.mark_process import TRACE_TEST_ID_ENV_VAR @@ -51,6 +52,24 @@ def are_tracepoints_included() -> bool: return 0 == process.returncode +def skip_if_no_kernel_tracing(func): + """Skip test if kernel tracing for kernel tracepoints or syscalls is not available.""" + def wrapper(*args, **kwargs): + kernel_tracepoints = lttngpy.get_tracepoints(domain_type=lttngpy.LTTNG_DOMAIN_KERNEL) + syscalls = lttngpy.get_syscalls() + error = ', '.join( + f'{name}: {lttngpy.lttng_strerror(error_code)}' for name, error_code in ( + ('kernel tracepoints', kernel_tracepoints), + ('syscalls', syscalls), + ) + if isinstance(error_code, int) + ) + if error: + raise unittest.SkipTest(f'kernel tracer is required: {error}') + return func(*args, **kwargs) + return wrapper + + @unittest.skipIf(not is_lttng_installed(minimum_version='2.9.0'), 'LTTng is required') class TestROS2TraceCLI(unittest.TestCase): @@ -94,6 +113,7 @@ def assertTraceContains( self, trace_dir: str, *, + expected_event_name: List[str] = [], expected_field_value: List[Tuple[str, str]] = [], expected_field: List[str] = [], ) -> int: @@ -108,6 +128,11 @@ def assertTraceContains( 0, f'no matching trace test events found in trace from events: {events_all}', ) + for event_name in expected_event_name: + self.assertTrue( + any(event_name == get_event_name(event) for event in events), + f'{event_name} not found in events: {events}', + ) for field_value in expected_field_value: self.assertTrue( any(field_value in event.items() for event in events), @@ -309,6 +334,37 @@ def test_default_tracing(self) -> None: shutil.rmtree(tmpdir) + @skip_if_no_kernel_tracing + def test_kernel_tracing(self) -> None: + tmpdir = self.create_test_tmpdir('test_kernel_tracing') + session_name = 'test_kernel_tracing' + + process = self.run_trace_command_start( + [ + '--path', tmpdir, + '--ust', TRACE_TEST_ID_TP_NAME, + '--kernel', 'sched_switch', + '--syscall', 'openat', + '--session-name', session_name, + ], + wait_for_start=True, + ) + self.run_nodes() + ret = self.run_trace_command_stop(process) + self.assertEqual(0, ret) + trace_dir = os.path.join(tmpdir, session_name) + self.assertTraceContains( + trace_dir, + expected_event_name=[ + 'sched_switch', + 'syscall_entry_openat', + 'syscall_exit_openat', + ], + ) + self.assertTracingSessionNotExist(session_name) + + shutil.rmtree(tmpdir) + def test_env_var_ros_trace_dir(self) -> None: tmpdir = self.create_test_tmpdir('test_env_var_ros_trace_dir') session_name = 'test_env_var_ros_trace_dir' @@ -398,7 +454,7 @@ def test_no_events(self) -> None: # Enabling no events should result in an error ret = self.run_trace_command( - ['--path', tmpdir, '--ust', '--kernel', '--session-name', session_name], + ['--path', tmpdir, '--ust', '--kernel', '--syscall', '--session-name', session_name], ) self.assertEqual(1, ret) self.assertTraceNotExist(os.path.join(tmpdir, session_name)) diff --git a/test_tracetools_launch/test/test_tracetools_launch/test_trace_action.py b/test_tracetools_launch/test/test_tracetools_launch/test_trace_action.py index 6428318f..571d4408 100644 --- a/test_tracetools_launch/test/test_tracetools_launch/test_trace_action.py +++ b/test_tracetools_launch/test/test_tracetools_launch/test_trace_action.py @@ -102,6 +102,7 @@ def test_action(self) -> None: session_name='my-session-name', base_path=tmpdir, events_kernel=[], + syscalls=[], events_ust=[ 'ros2:*', '*', @@ -126,6 +127,7 @@ def test_action_frontend_xml(self) -> None: base-path="{}" append-trace="true" events-kernel="" + syscalls="" events-ust="ros2:* *" subbuffer-size-ust="524288" subbuffer-size-kernel="1048576" @@ -154,6 +156,7 @@ def test_action_frontend_yaml(self) -> None: base-path: {} append-trace: true events-kernel: "" + syscalls: "" events-ust: ros2:* * subbuffer-size-ust: 524288 subbuffer-size-kernel: 1048576 @@ -176,6 +179,7 @@ def test_action_context_per_domain(self) -> None: session_name='my-session-name', base_path=tmpdir, events_kernel=[], + syscalls=[], events_ust=[ 'ros2:*', '*', @@ -193,6 +197,7 @@ def test_action_context_per_domain(self) -> None: session_name='my-session-name', base_path=tmpdir, events_kernel=[], + syscalls=[], events_ust=[ 'ros2:*', '*', @@ -234,6 +239,7 @@ def test_action_substitutions(self) -> None: session_name=LaunchConfiguration(session_name_arg.name), base_path=TextSubstitution(text=tmpdir), events_kernel=[], + syscalls=[], events_ust=[ EnvironmentVariable(name='TestTraceAction__event_ust'), TextSubstitution(text='*'), @@ -270,6 +276,7 @@ def test_action_ld_preload(self) -> None: session_name='my-session-name', base_path=tmpdir, events_kernel=[], + syscalls=[], events_ust=[ 'lttng_ust_cyg_profile_fast:*', 'lttng_ust_libc:*', @@ -323,6 +330,7 @@ def test_append_timestamp(self) -> None: append_timestamp=True, base_path=tmpdir, events_kernel=[], + syscalls=[], events_ust=[ 'ros2:*', '*', @@ -348,6 +356,7 @@ def test_append_trace(self) -> None: base_path=tmpdir, append_trace=False, events_kernel=[], + syscalls=[], events_ust=[ 'ros2:*', '*', @@ -367,6 +376,7 @@ def test_append_trace(self) -> None: base_path=tmpdir, append_trace=True, events_kernel=[], + syscalls=[], events_ust=[ 'ros2:*', '*', diff --git a/tracetools_launch/tracetools_launch/action.py b/tracetools_launch/tracetools_launch/action.py index c1d5d14d..ffc38ecb 100644 --- a/tracetools_launch/tracetools_launch/action.py +++ b/tracetools_launch/tracetools_launch/action.py @@ -112,6 +112,7 @@ def __init__( append_trace: bool = False, events_ust: Iterable[SomeSubstitutionsType] = names.DEFAULT_EVENTS_ROS, events_kernel: Iterable[SomeSubstitutionsType] = [], + syscalls: Iterable[SomeSubstitutionsType] = [], context_fields: Union[Iterable[SomeSubstitutionsType], Dict[str, Iterable[SomeSubstitutionsType]]] = names.DEFAULT_CONTEXT, @@ -140,6 +141,7 @@ def __init__( otherwise an error is reported :param events_ust: the list of ROS UST events to enable :param events_kernel: the list of kernel events to enable + :param syscalls: the list of syscalls to enable :param context_fields: the names of context fields to enable if it's a list or a set, the context fields are enabled for both kernel and userspace; if it's a dictionary: { domain type string -> context fields list } @@ -160,6 +162,7 @@ def __init__( self._trace_directory = None self._events_ust = [normalize_to_list_of_substitutions(x) for x in events_ust] self._events_kernel = [normalize_to_list_of_substitutions(x) for x in events_kernel] + self._syscalls = [normalize_to_list_of_substitutions(x) for x in syscalls] self._context_fields = \ { domain: [normalize_to_list_of_substitutions(field) for field in fields] @@ -195,6 +198,10 @@ def events_ust(self): def events_kernel(self): return self._events_kernel + @property + def syscalls(self): + return self._syscalls + @property def context_fields(self): return self._context_fields @@ -295,6 +302,10 @@ def parse(cls, entity: Entity, parser: Parser): if events_kernel is not None: kwargs['events_kernel'] = cls._parse_cmdline(events_kernel, parser) \ if events_kernel else [] + syscalls = entity.get_attr('syscalls', optional=True) + if syscalls is not None: + kwargs['syscalls'] = cls._parse_cmdline(syscalls, parser) \ + if syscalls else [] context_fields = entity.get_attr('context-fields', optional=True) if context_fields is not None: kwargs['context_fields'] = cls._parse_cmdline(context_fields, parser) \ @@ -374,6 +385,7 @@ def _perform_substitutions(self, context: LaunchContext) -> None: if self._base_path else path.get_tracing_directory() self._events_ust = [perform_substitutions(context, x) for x in self._events_ust] self._events_kernel = [perform_substitutions(context, x) for x in self._events_kernel] + self._syscalls = [perform_substitutions(context, x) for x in self._syscalls] self._context_fields = \ { domain: [perform_substitutions(context, field) for field in fields] @@ -418,6 +430,7 @@ def _setup(self) -> bool: append_trace=self._append_trace, ros_events=self._events_ust, kernel_events=self._events_kernel, + syscalls=self._syscalls, context_fields=self._context_fields, subbuffer_size_ust=self._subbuffer_size_ust, subbuffer_size_kernel=self._subbuffer_size_kernel, @@ -427,6 +440,7 @@ def _setup(self) -> bool: self._logger.info(f'Writing tracing session to: {self._trace_directory}') self._logger.debug(f'UST events: {self._events_ust}') self._logger.debug(f'Kernel events: {self._events_kernel}') + self._logger.debug(f'Syscalls: {self._syscalls}') self._logger.debug(f'Context fields: {self._context_fields}') self._logger.debug(f'LD_PRELOAD: {self._ld_preload_actions}') self._logger.debug(f'UST subbuffer size: {self._subbuffer_size_ust}') @@ -454,6 +468,7 @@ def __repr__(self): f'trace_directory={self._trace_directory}, ' f'events_ust={self._events_ust}, ' f'events_kernel={self._events_kernel}, ' + f'syscalls={self._syscalls}, ' f'context_fields={self._context_fields}, ' f'ld_preload_actions={self._ld_preload_actions}, ' f'subbuffer_size_ust={self._subbuffer_size_ust}, ' diff --git a/tracetools_trace/test/tracetools_trace/test_lttng_tracing.py b/tracetools_trace/test/tracetools_trace/test_lttng_tracing.py index 312fd793..11d3ee1d 100644 --- a/tracetools_trace/test/tracetools_trace/test_lttng_tracing.py +++ b/tracetools_trace/test/tracetools_trace/test_lttng_tracing.py @@ -74,6 +74,12 @@ def test_no_kernel_tracer(self): base_path='/tmp', kernel_events=['sched_switch'], ) + with self.assertRaises(RuntimeError): + setup( + session_name='test-session', + base_path='/tmp', + syscalls=['open'], + ) def test_get_lttng_home(self): from tracetools_trace.tools.lttng_impl import get_lttng_home diff --git a/tracetools_trace/tracetools_trace/tools/args.py b/tracetools_trace/tracetools_trace/tools/args.py index c27074c1..edfae986 100644 --- a/tracetools_trace/tracetools_trace/tools/args.py +++ b/tracetools_trace/tracetools_trace/tools/args.py @@ -63,6 +63,10 @@ def _add_arguments_configure(parser: argparse.ArgumentParser) -> None: default=[], help='the kernel events to enable (default: no kernel events)') events_kernel_arg.completer = ArgCompleter(names.EVENTS_KERNEL) # type: ignore + parser.add_argument( + '--syscall', nargs='*', dest='syscalls', metavar='SYSCALL', + default=[], + help='the syscalls to enable (default: no syscalls)') context_arg = parser.add_argument( # type: ignore '-c', '--context', nargs='*', dest='context_fields', metavar='CONTEXT', default=names.DEFAULT_CONTEXT, diff --git a/tracetools_trace/tracetools_trace/tools/lttng_impl.py b/tracetools_trace/tracetools_trace/tools/lttng_impl.py index 63b2246f..6b9c4702 100644 --- a/tracetools_trace/tracetools_trace/tools/lttng_impl.py +++ b/tracetools_trace/tracetools_trace/tools/lttng_impl.py @@ -151,6 +151,7 @@ def setup( append_trace: bool = False, ros_events: Union[List[str], Set[str]] = DEFAULT_EVENTS_ROS, kernel_events: Union[List[str], Set[str]] = [], + syscalls: Union[List[str], Set[str]] = [], context_fields: Union[List[str], Set[str], Dict[str, List[str]]] = DEFAULT_CONTEXT, channel_name_ust: str = 'ros2', channel_name_kernel: str = 'kchan', @@ -175,6 +176,8 @@ def setup( an error is reported :param ros_events: list of ROS events to enable :param kernel_events: list of kernel events to enable + :param syscalls: list of syscalls to enable + these will be part of the kernel channel :param context_fields: the names of context fields to enable if it's a list or a set, the context fields are enabled for both kernel and userspace; if it's a dictionary: { domain type string -> context fields list } @@ -212,14 +215,14 @@ def setup( if is_session_daemon_not_alive(): raise RuntimeError('failed to start lttng session daemon') - # Make sure the kernel tracer is available if there are kernel events + # Make sure the kernel tracer is available if there are kernel events, including syscalls # Do this after spawning a session daemon, otherwise we can't detect the kernel tracer - if 0 < len(kernel_events) and not is_kernel_tracer_available(): + if 0 < (len(kernel_events) + len(syscalls)) and not is_kernel_tracer_available(): raise RuntimeError( 'kernel tracer is not available:\n' - ' cannot use kernel events:\n' - " 'ros2 trace' command: cannot use '-k' option\n" - " 'Trace' action: cannot set 'events_kernel'/'events-kernel' list\n" + ' cannot use kernel events or syscalls:\n' + " 'ros2 trace' command: cannot use '-k' or '--syscall' options\n" + " 'Trace' action: cannot set 'events_kernel'/'events-kernel' or 'syscalls' lists\n" ' install the kernel tracer, e.g., on Ubuntu, install lttng-modules-dkms\n' ' see: https://github.com/ros2/ros2_tracing#building' ) @@ -229,11 +232,13 @@ def setup( ros_events = set(ros_events) if not isinstance(kernel_events, set): kernel_events = set(kernel_events) + if not isinstance(syscalls, set): + syscalls = set(syscalls) if isinstance(context_fields, list): context_fields = set(context_fields) - ust_enabled = ros_events is not None and len(ros_events) > 0 - kernel_enabled = kernel_events is not None and len(kernel_events) > 0 + ust_enabled = bool(ros_events) + kernel_enabled = bool(kernel_events) or bool(syscalls) if not (ust_enabled or kernel_enabled): raise RuntimeError('no events enabled') @@ -271,6 +276,7 @@ def setup( _enable_events( session_name=session_name, domain_type=domain_type, + event_type=lttngpy.LTTNG_EVENT_TRACEPOINT, channel_name=channel_name, events=ros_events, ) @@ -302,12 +308,22 @@ def setup( # mmap channel output instead of splice output=lttngpy.LTTNG_EVENT_MMAP, ) - _enable_events( - session_name=session_name, - domain_type=domain_type, - channel_name=channel_name, - events=kernel_events, - ) + if kernel_events: + _enable_events( + session_name=session_name, + domain_type=domain_type, + event_type=lttngpy.LTTNG_EVENT_TRACEPOINT, + channel_name=channel_name, + events=kernel_events, + ) + if syscalls: + _enable_events( + session_name=session_name, + domain_type=domain_type, + event_type=lttngpy.LTTNG_EVENT_SYSCALL, + channel_name=channel_name, + events=syscalls, + ) _add_contexts( session_name=session_name, domain_type=domain_type, @@ -443,9 +459,10 @@ def _enable_events(**kwargs) -> None: if result < 0: session_name = kwargs['session_name'] channel_name = kwargs['channel_name'] + events = kwargs['events'] error = lttngpy.lttng_strerror(result) raise RuntimeError( - f"failed to enable event for channel '{channel_name}' " + f"failed to enable event(s) {events} for channel '{channel_name}' " f"in tracing session '{session_name}': {error}" ) diff --git a/tracetools_trace/tracetools_trace/trace.py b/tracetools_trace/tracetools_trace/trace.py index 725e27b8..0efa6741 100644 --- a/tracetools_trace/tracetools_trace/trace.py +++ b/tracetools_trace/tracetools_trace/trace.py @@ -40,23 +40,28 @@ def _display_info( *, ros_events: List[str], kernel_events: List[str], + syscalls: List[str], context_fields: List[str], display_list: bool, ) -> None: - ust_enabled = len(ros_events) > 0 - kernel_enabled = len(kernel_events) > 0 - if ust_enabled: - print(f'UST tracing enabled ({len(ros_events)} events)') + if ros_events: + print(f'userspace tracing enabled ({len(ros_events)} events)') if display_list: print_names_list(ros_events) else: - print('UST tracing disabled') - if kernel_enabled: + print('userspace tracing disabled') + if kernel_events: print(f'kernel tracing enabled ({len(kernel_events)} events)') if display_list: print_names_list(kernel_events) else: print('kernel tracing disabled') + if syscalls: + print(f'syscall tracing enabled ({len(syscalls)} syscalls)') + if display_list: + print_names_list(syscalls) + else: + print('syscalls tracing disabled') if len(context_fields) > 0: print(f'context ({len(context_fields)} fields)') if display_list: @@ -82,6 +87,7 @@ def init( append_trace: bool, ros_events: List[str], kernel_events: List[str], + syscalls: List[str], context_fields: List[str], display_list: bool, interactive: bool, @@ -101,6 +107,7 @@ def init( an error is reported :param ros_events: list of ROS events to enable :param kernel_events: list of kernel events to enable + :param syscalls: list of syscalls to enable :param context_fields: list of context fields to enable :param display_list: whether to display list(s) of enabled events and context names :param interactive: whether to require user interaction to start tracing @@ -109,6 +116,7 @@ def init( _display_info( ros_events=ros_events, kernel_events=kernel_events, + syscalls=syscalls, context_fields=context_fields, display_list=display_list, ) @@ -126,6 +134,7 @@ def init( append_trace=append_trace, ros_events=ros_events, kernel_events=kernel_events, + syscalls=syscalls, context_fields=context_fields, ) if trace_directory is None: @@ -213,6 +222,7 @@ def work() -> int: append_trace=args.append_trace, ros_events=args.events_ust, kernel_events=args.events_kernel, + syscalls=args.syscalls, context_fields=args.context_fields, display_list=args.list, interactive=True, @@ -241,6 +251,7 @@ def work() -> int: append_trace=args.append_trace, ros_events=args.events_ust, kernel_events=args.events_kernel, + syscalls=args.syscalls, context_fields=args.context_fields, display_list=args.list, interactive=False,