refactor: fix definition of time_t and off_t in Newlib#5132
Open
dybucc wants to merge 2 commits into
Open
Conversation
Contributor
Author
|
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.
Contributor
Author
|
CI actually passes. There seems to be an issue with a glob import that is not used, but this has not |
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.
de697e2 to
0e027c7
Compare
Collaborator
|
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. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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