Skip to content

fix: avoid attr_value_t conversion of new_command result during module init - #387

Merged
Wenzel merged 1 commit into
intel:mainfrom
Wenzel:fix/init-tsffs-command-registration
Sep 11, 2026
Merged

Wenzel merged 1 commit into
intel:mainfrom
Wenzel:fix/init-tsffs-command-registration

Conversation

@Wenzel

@Wenzel Wenzel commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Problem

Loading the tsffs module crashes with a SIGSEGV on newer Simics Base versions, before any target is even set up. load-module tsffs alone is enough to reproduce it — no model required.

Segmentation fault (SIGSEGV) in thread ("simics-scriptbr")
#3  VT_effective_log_level
#4  VT_log_message64
#5  VT_log_error
#6  simics::api::logging::log_error
#7  _simics_module_init
#8  load_module_common.part.0
#9  SIM_load_module

Root cause

Two independent issues compound here.

1. The trigger. init() registers the init-tsffs CLI command by handing a bare new_command(...) call to run_python. SIM_run_python converts the value of a trailing expression to an attr_value_t. Newer Simics Base versions return a CliCommand object from new_command rather than None, and that object has no attr_value_t representation:

SimExc_Type: Failed converting return value from SIM_run_python()
to attr_value_t: unsupported Python object type(_run_python)

The command itself registers fine — I confirmed this by wrapping new_command and observing it return normally. Only the marshalling of the return value fails. #[simics_exception] then promotes the pending exception into an Err.

2. The segfault that hides it. The error path is itself unsound:

let tsffs = Tsffs::create()?;   // *mut ConfClass
...
.map_err(|e| { error!(tsffs, "{e}"); e })

simics::log! casts its object argument with $obj as *mut ConfObject. ConfClass and ConfObject are distinct opaque types, so this raw pointer cast compiles silently, and VT_log_error goes on to read a conf_class_t as a conf_object_t. That is the crash in VT_effective_log_level, and it swallows the actual error message.

Fix

Bind the result of new_command to a variable so the snippet is a statement rather than an expression. Nothing is returned, so no conversion is attempted.

Drop the error! call that passed a ConfClass where a ConfObject was required. The remaining .expect() surfaces any genuine failure without dereferencing an invalid pointer.

Verification

Rebuilt with cargo simics-build -r and loaded the resulting module:

simics> load-module tsffs
simics> init-tsffs
TSFFS initialized. Configure and use it as @tsffs.
simics> @print(tsffs)
<the tsffs 'tsffs'>

Previously this sequence segfaulted at load-module.

Note for maintainers

The unchecked $obj as *mut simics::ConfObject cast in the log! / error! macros in simulator-bindings makes passing a ConfClass a silent, guaranteed segfault. Constraining that parameter to AsConfObject / *mut ConfObject would have turned this into a compile error rather than a crash in module init. Might be worth a separate issue there.

Module initialization registers the `init-tsffs` CLI command by passing a
`new_command(...)` call to `run_python`. `SIM_run_python` converts the value
of a trailing expression to an `attr_value_t`. Newer Simics Base versions
return a `CliCommand` object from `new_command` instead of `None`, and that
object has no `attr_value_t` representation, so the conversion raises
`SimExc_Type`. The command is registered successfully; only the marshalling
of the return value fails.

`#[simics_exception]` turns that pending exception into an `Err`, which the
error path then mishandles:

    let tsffs = Tsffs::create()?;   // *mut ConfClass
    ...
    .map_err(|e| { error!(tsffs, "{e}"); e })

`simics::log!` casts its object argument with `$obj as *mut ConfObject`.
`ConfClass` and `ConfObject` are distinct opaque types, so this raw pointer
cast compiles silently and `VT_log_error` reads a `conf_class_t` as a
`conf_object_t`. The result is a SIGSEGV inside `VT_effective_log_level`
while loading the module, which hides the real error entirely:

    intel#3  VT_effective_log_level
    intel#4  VT_log_message64
    intel#5  VT_log_error
    intel#6  simics::api::logging::log_error
    intel#7  _simics_module_init

Bind the result of `new_command` to a variable so the snippet is a statement
rather than an expression. No value is returned, so no conversion is
attempted. Drop the `error!` call that passed a `ConfClass` where a
`ConfObject` was required; the remaining `.expect()` reports any genuine
failure without dereferencing an invalid pointer.

Verified by loading the rebuilt module: `load-module tsffs` followed by
`init-tsffs` now succeeds and creates the `tsffs` object.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The focused fix addresses both documented crash causes and is covered by existing module-loading integration paths.

Pull request overview

Fixes a module-load crash on newer Simics versions.

Changes:

  • Prevents new_command results from being marshalled to attr_value_t.
  • Removes unsafe error logging with a ConfClass pointer.
File summaries
File Description
src/lib.rs Safely registers init-tsffs during module initialization.
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 0
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@Wenzel
Wenzel merged commit fc8733a into intel:main Sep 11, 2026
24 checks passed
@Wenzel
Wenzel deleted the fix/init-tsffs-command-registration branch September 11, 2026 02:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants