newlib: fix definition of time_t and off_t#5132
Conversation
|
CI seems to be failing for reasons unrelated to the changes introduced in the patch. A rerun should |
time_t in Newlibtime_t and off_t in Newlib
7152f77 to
e821035
Compare
This comment has been minimized.
This comment has been minimized.
|
CI actually passes. There seems to be an issue with a glob import that is not used, but this has not |
de697e2 to
0e027c7
Compare
This comment has been minimized.
This comment has been minimized.
0e027c7 to
6abed2e
Compare
This comment has been minimized.
This comment has been minimized.
|
I couldn't remember what the possible env+os combinations were for these platforms, here's a quick list. |
There was a problem hiding this comment.
I'm having some difficulty extracting a simplified goal from the top post. Is this the net delta on targets we currently support?
- On armv7-rtems,
time_tchanges from i32 to i64 - On armv7-rtems,
off_tchanges from i64 toc_long, which should be i64->i32 - On armv7-vita,
off_tchanges fromc_inttoc_long. I think there is no change here?
If this sounds accurate, ping the target maintainer (see https://doc.rust-lang.org/rustc/platform-support/armv7-rtems-eabihf.html) for confirmation. This is generally a good idea when tricky things like this change on less popular targets, there may be config or other nuance that doesn't show up in the source code.
Also please don't call this a refactor, that term usually means cleaning up code without changing behavior - if the user experience changes somehow then it's kind of misleading. (Applies to some of your other PRs as well).
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's mostly intended to be set by espidf build tooling, but it would be good to at least mention it. A PR would be welcome in the crate-level docs, after #5179 adds some structure.
It would also be great to know whether the libc crate considers horizon to be the OS for both the Nintendo Switch and the Nintendo 3DS targets, or only for the Nintendo 3DS target.
aarch64-nintendo-switch-freestanding does not appear to set a target_env, so I would assume the latter.
|
@rustbot author for clarification |
|
Reminder, once the PR becomes ready for a review, use |
time_t and off_t in Newlibtime_t and off_t
|
The changes here are required to fit the definitions upstream of The changes for file offset types are concerned with either
I'll open a PR soon with the documentation for ESP-IDF. @rustbot ready |
6abed2e to
c2b0970
Compare
This comment has been minimized.
This comment has been minimized.
|
Hey @thesummer! I was wondering if I could get confirmation on these changes on the RTEMS target you maintain? |
|
Hey @nikarh @pheki @zetanumbers! I was wondering if I could get confirmation on these changes on the Sony PS Vita target you maintain? |
There was a problem hiding this comment.
Thanks for asking!
Just need a change as the Vita uses 32-bit time_t.
Keeping it on the top-level comment for easy reference, here are the sources I could find (somewhat redundant with the finds in the root PR comment but in vitasdk's fork):
off_t
time_t
--enable-newlib-long-time_tis set in CMakeLists.txt- In configure:
- In configure.in:
_TIME_T_is settime_tis set
| if #[cfg(any( | ||
| target_os = "espidf", | ||
| target_os = "vita", | ||
| target_os = "rtems", | ||
| target_arch = "aarch64" | ||
| ))] { |
There was a problem hiding this comment.
For vita, this one seems correct, as by looking at the definitions it seems to be defined as a long. There should also be no change in behavior as both c_int and c_long are aliases to i32 in this platform.
Sources in the top level review comment.
| } else { | ||
| pub type time_t = i64; |
There was a problem hiding this comment.
This one looks wrong for the vita, which uses 32-bit time, as --enable-newlib-long-time_t is set when building newlib in vitasdk (currently the only supported SDK).
The correct definition would be c_long (effectively i32).
Sources in the top-level comment.
Indeed libc doesn't match every source, but with every change I need to figure out a succinct description of what (1) is changing to look more similar to source without affecting users, vs. (2) is a behavior change of some form. IOW I'm interested in the intent more than the problem list, to make sure I'm on the same page as PR authors. To help with that, are the summary bullet points at #5132 (review) accurate? |
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 either one of a signed 64 bit integer or a C `long`. The former is only present when `_off_t` (note the starting underscore) is defined under `machine/_types.h`. `off_t` is defined as a `c_long` in all other cases. There's some special casing for Cygwin, but that is unimportant in the `libc` crate because the Cygwin module is not a child module of the newlib module. Except in `vita`, espressif's platforms, devkitA64 for `aarch64`, and RTEMS, this type is always defined under `machine/_types.h`. Otherwise, it's defined as a `c_long` under `sys/_types.h`. More details can be found in the accompanying PR.
c2b0970 to
3388aa7
Compare
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
Description
This PR adresses bit-width representation issues under the newlib target environment concerned with both the
time_tandoff_ttypes.In newlib,
time_tis conditionally defined as being ac_longlongunder thehorizonandespidftarget operating systems. Otherwise, it always defaults to using a 32-bit signed integer.off_tis always defined as a 64-bit signed integer except inespidfand invita, where they are defined asc_longandc_int, respectively.This is possibly incorrect. The newlib upstream repo maintained by Cygwin defines
time_tconditionally as being either one of ac_longor 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_tto theconfigurebuild script, or if the host system is known to havec_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 onhorizon. Support forespidfwith 32-bittime_tis likely provided for compatibility purposes following the analogous compatibility shims espressif has set in place in their upstream repos [1] [2].Upstream also defines
off_tin an ever so slightly different way to the declaration in thelibccrate. The definition in the "official" repo maintained by the Cygwin developers will always provide a 64-bit value. The forks forvita, espressif'sesp-32, devkitA64 (and by extensionhorizonin the Nintendo Switch but not in the Nintendo 3DS,) and RTEMS, don't define this type in themachine/_types.hheader file. This header file is the one where the first definition for the type appears, and is the one that takes priority if it exists. A macro checks that insys/_types.h, and will otherwise define the type in terms of ac_long. This only happens in the afore mentioned platforms, where the definition ofoff_tis removed frommachine/_types.h. Currently, the exposed type is not completely wrong, but is quite defintely wrong invita.This patch changes the
time_tdefinition to fit a 64-bit signed integer unless compiling for the afore mentioned environment (the one fortime_t) with the existingcfg(espidf_time32)enabled. Note this option is "documented" as being meant for end users of thelibccrate to enable, but no information on it is provided anywhere in all of thelibccrate. It seems like the only users of thatcfgare the projects in the esp-rs org. Some of the other targets using newlib have been verified to also follow this definition fortime_t(sources below.) Among those checked are the ones for which we have custom modules at the end of thenewlib/mod.rsmodule. Notably, no architecture-specific definitions were found foraarch64.A simple test has been ran in all platforms except
vitaandaarch64(which here means the Nintendo Switch with devkitPro's devkitA64) for bothtime_tandoff_t. The former used a two-element array oftime_tvalues and ensured that a write through an FFI routine (liketime) only overwrote one of the values and not both. The latter required a bit more intricate testing, as no C standard library routine takes a mutable pointer to anoff_t. All of the affected platforms required emulation and to some extent, supported embedding a virtual file system to the compiled binary. This was used to embed files with different sizes and use stream seeking operations with values foroff_tboth larger and smaller than 32 bits.Testing was not possible in
vitabecause the emulator did not support the type of homebrew package that the Rust toolchain forvitabuilds. Inhorizonfor the Nintendo Switch underaarch64with devkitA64, testing was neither possible for the same reason as invita.It would also be great to know whether the
libccrate considershorizonto be the OS for both the Nintendo Switch and the Nintendo 3DS targets, or only for the Nintendo 3DS target. It just so happens that thenewlibmodule has submodules for all three of them with a note that mentions testing only with devkitARM. Usingcfg's for different architecures may not be the right choice, as there could be other systems whose ISA matchedaarch64with changes to their newlib fork that differ from those in devkitA64 (or any other devkitPro SDK, for that matter.)Sources
Cygwin's, espressif's and the Vita SDK's newlib forks showing conditional definition of the
time_ttype and theoff_ttype. Note Vita SDK's fork contains definitions relative to multiple target systems, but the one underinclude/syshas taken priority. The definition underinclude/vita/sys#includes the former to define itsoff_ttype.Sources on devkitARM could not be found online, but they can be found under the installed toolchain's directory in
devkitARM/by runningripgrepwith the following command.Newlib sources documenting the
configurebuild script non-default option for using ac_longfor theirtime_tdefinition.Cygwin upstream codesearch showing the definition of
_off_t, which defines__off_t, and eventuallyoff_t. Note how this is defined inmachine/_types.h(as ani64,) and later that is checked insys/_types.h(falling back to ac_long.)espressif's
esp-32fork of newlib,vita's and RTEMS' showing how they don't have a definition in terms ani64undermachine/_types.h.Checklist
libc-test/semverhave been updated*LASTor*MAXare included (see #3131)cd libc-test && cargo test --target mytarget); especially relevant for platforms that may not be checked in CI