Skip to content

Fix the semihosting file open modes for update and append - #4312

Merged
bugadani merged 1 commit into
probe-rs:masterfrom
MaxFreedomPollard:fix-semihosting-file-modes
Sep 6, 2026
Merged

bugadani merged 1 commit into
probe-rs:masterfrom
MaxFreedomPollard:fix-semihosting-file-modes

Conversation

@MaxFreedomPollard

Copy link
Copy Markdown
Contributor

open_file in probe-rs-tools/src/bin/probe-rs/rpc/utils/semihosting.rs maps the ARM semihosting SYS_OPEN mode strings onto File::options(). Three of the six rows do not do what C fopen does, so a target that opens a file for update or for appending gets the wrong file.

Line 196, "r+" | "r+b", sets truncate(true). fopen opens r+ for update and leaves the contents alone, so a target that reopened a file to patch part of it found the file empty.

Line 199, "a" | "ab", sets write(true) and never append(true), so the writes land at offset 0 and overwrite the start of the file. Writing ab to a file holding 0123456789 produced ab23456789 instead of 0123456789ab.

Line 200, "a+" | "a+b", sets read(true).write(false).create(true). create needs write or append access, so File::options().open() returns InvalidInput with "creating or truncating a file requires write or append access" and a+ never opens a file at all. That is the same std rule #3960 ran into for r, which fixed r only.

The fix is truncate(false) for r+, and append(true) for a and a+. w and w+ were already right.

The tests call open_file directly, so they need no probe and no target. They cover the five distinct behaviours of the mode table. Against the mode table on master, r and w pass and the other three fail:

test rpc::utils::semihosting::test::read_does_not_truncate ... ok
test rpc::utils::semihosting::test::write_truncates ... ok
test rpc::utils::semihosting::test::read_update_does_not_truncate ... FAILED
test rpc::utils::semihosting::test::append_writes_to_the_end ... FAILED
test rpc::utils::semihosting::test::append_update_writes_to_the_end ... FAILED

---- read_update_does_not_truncate ----
  left: []
 right: [48, 49, 50, 51, 52, 53, 54, 55, 56, 57]

---- append_writes_to_the_end ----
  left: [97, 98, 50, 51, 52, 53, 54, 55, 56, 57]
 right: [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98]

---- append_update_writes_to_the_end ----
mode a+ failed to open the file

With the change, on macOS 26.2 arm64 with rustc 1.95.0:

cargo test -p probe-rs-tools --bin probe-rs semihosting:: gives test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 150 filtered out.

cargo fmt --all -- --check reports no diff.

cargo clippy -p probe-rs-tools --all-features --all-targets --locked -- -D warnings -A clippy::collapsible_match finishes clean. The allow covers util/cargo.rs:86, which the clippy in my toolchain also rejects on master, before this change.

Must

Nice to have

  • You add a description of your work to this PR.
  • You added proper docs (in code, rustdoc and README.md) for your newly added features and code.

`open_file` in probe-rs-tools/src/bin/probe-rs/rpc/utils/semihosting.rs
mapped the ARM semihosting SYS_OPEN mode strings onto `File::options()`
with three mistakes:

- `r+` and `r+b` set `truncate(true)`. C `fopen` opens `r+` for update
  without truncating, so a target that opened an existing file to update
  it found the file empty.
- `a` and `ab` set `write(true)` but never `append(true)`, so writes
  landed at offset 0 and overwrote the start of the file instead of
  appending to it.
- `a+` and `a+b` set `read(true).write(false).create(true)`. `create`
  needs write or append access, so `File::options().open()` always
  returned `InvalidInput` and the open never succeeded.

Use `truncate(false)` for `r+`, and `append(true)` for `a` and `a+`.
Add tests over `open_file` for the five distinct behaviours of the mode
table: `r` and `r+` keep the contents, `w` truncates, `a` and `a+`
append.
@bugadani
bugadani added this pull request to the merge queue Sep 6, 2026
Merged via the queue into probe-rs:master with commit 615bf5e Sep 6, 2026
19 of 21 checks passed
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