Skip to content

refactor: fix definition of time_t and off_t in Newlib#5132

Draft
dybucc wants to merge 2 commits into
rust-lang:mainfrom
dybucc:newlib-fix-time_t
Draft

refactor: fix definition of time_t and off_t in Newlib#5132
dybucc wants to merge 2 commits into
rust-lang:mainfrom
dybucc:newlib-fix-time_t

Conversation

@dybucc
Copy link
Copy Markdown
Contributor

@dybucc dybucc commented Jun 1, 2026

Description

This PR adresses bit-width representation issues under the newlib target environment concerned with
both the time_t and off_t types.

In newlib, time_t is conditionally defined as being a c_longlong under the horizon and
espidf target operating systems. Otherwise, it always defaults to using a 32-bit signed integer.
The off_t is always defined as a 64-bti signed integer except in espidf and in vita, where
they are defined as c_long and c_int, respectively.

This is possibly incorrect. The newlib upstream repo maintained by Cygwin defines time_t
conditionally as being either one of a c_long or a signed integer type with at least 64 bits
precision. The definition will always default to the latter unless one issues
--enable-newlib-long-time_t to the configure build script, or if the host system is known to
have c_longs larger than 32 bits. In much the same vein, the espressif upstream repo for their
fork of newlib uses the exact same definition, and so does the devkitARM shipped for development on
horizon. Support for espidf with 32-bit time_t is likely provided for compatibility purposes
following the analogous compatibility shims espressif has set in place in their upstream repos [1]
[2].

The upstream repo also includes definitions for the off_t type that depend mostly on whether the
target machine is running under the Cygwin environment and is not following the LP64 model. This
definition remains the same across all forks from espressif and the VitaSDK. The specifics of the
type's bit-width are left to the C implementation's discretion in most cases, as the type is only
defined as being a c_longlong in the afore mentioned case (Cygwin + non-LP64.) Indeed, one could
infer from this that the type is likely to be 64-bits wide as a consequence of running under the
LP64 model and having a fallback definition in terms of a c_long. That, though, could not be the
case. The conditionally compiled code in charge of those typedefs may evaluate that the system is
not running under Cygwin and still provide a c_long-relative definition. According to the GNU
docs, the preprocessor will short-circuit expressions involving logical operators to #if in much
the same way as in "runtime" C. Even though the likelihood of there being systems other than Windows
that follow LLP64 is not large, this does mean we are always exposing a 64-bit definition, when
off_t could be 32 bits wide.

This patch changes the definition to fit a 64-bit signed integer time_t unless compiling for the
afore mentioned environment with the existing cfg(espidf_time32) enabled. Note this option is
"documented" as being meant for end users of the libc crate to enable, but no information on it is
provided anywhere in all of the libc crate. It seems like the only users of that cfg are the
projects in the esp-rs org. Some of the other targets using newlib have been verified to also follow
this definition for time_t (sources below.) Among those checked are the ones for which we have
custom modules at the end of the newlib/mod.rs module. Notably, no architecture-specific
definitions were found for aarch64.

This patch also changes the definition of off_t to be unconditionally be a c_long, for the above
mentioned reasons.

Changes introduced in this patch have not yet been tested in horizon (for the time_t change) nor
in vita (for the off_t change.) For that reason, the PR is currently open as a draft, pending
testing on horizon. The PR has been opened anyway to the last three days' worth of work.

The test consisted simply of checking the size_of::<T>() for T = libc::time_t and
T = libc::off_t through the QEMU emulator with esp-32 as the target. These bitwidths were
compared with their values usptream, and they seem to fit correctly.

Sources

Checklist

  • Relevant tests in libc-test/semver have been updated
  • No placeholder or unstable values like *LAST or *MAX are
    included (see #3131)
  • Tested locally (cd libc-test && cargo test --target mytarget);
    especially relevant for platforms that may not be checked in CI

@dybucc
Copy link
Copy Markdown
Contributor Author

dybucc commented Jun 2, 2026

CI seems to be failing for reasons unrelated to the chagnes introduced in the patch. A rerun should
do it.

@dybucc dybucc changed the title refactor: fix definition of time_t in Newlib refactor: fix definition of time_t and off_t in Newlib Jun 3, 2026
dybucc added 2 commits June 4, 2026 09:04
At present, the newlib module uses a faulty definition of the `time_t`
type that falls back to a 32-bti signed integer if the target does not
match either one of the `horizon` operating system or the espressif
ESP-IDF with the 32-bit compatibility shim for `time_t` values.

In all current upstream repos forking newlib, the definition follows a
default where `time_t` is defined as a 64-bit type. It only falls back
to a 32-bit type if a non-default build-time option is issues to the
`configure` script, or otherwise if the host machine is detected to
support `c_long`s larger than 32 bits.
The newlib definition is shown to be always a `c_long` when not running
under any one of Cygwin and a machine not following the LP64 memory
model abstraction.

This seems to hold across all targets currently supported in the `libc`
crate. The exceptions that were being made for `espidf` and `vita` did
not seem correct. The definitions in their corresponding forks fit
exactly those of the upstream newlib repo maintained by the Cygwin
developers.

More details can be found in the accompanying PR.
@dybucc dybucc force-pushed the newlib-fix-time_t branch from b6f56e5 to 915701c Compare June 4, 2026 07:04
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.

1 participant