riscv32gc-unknown-linux-gnu: `timex` uses the 32-bit `c_long` layout (144 bytes), glibc's riscv32 `struct timex` is 208 bytes
メンテナーはふだん 1 日以内に返信
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 76/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- rust
調査の方向性
src/unix/linux_like/linux/gnu/b32/mod.rsと、issueで説明されているbuild.rsのターゲット設定を読みます。riscv32向けのglibcのbits/timex.hとtimexのレイアウトを比較し、その後、riscv32のレイアウトを確認して、i686とarmv7が現在のサイズを維持していることを確かめます。timexがriscv32でglibcの208バイトのレイアウトと一致し、末尾を越えて書き込まない状態になれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Target: riscv32gc-unknown-linux-gnu (glibc; 64-bit time_t is this target's only ABI)
Versions: libc 0.2.186, 0.2.191 and 1.0.0-alpha.5 (the declarations quoted below are unchanged on main); glibc 2.44; rustc 1.98.1.
src/unix/linux_like/linux/gnu/b32/mod.rs declares timex twice: the c_longlong layout under #[cfg(gnu_time_bits64)] (0.2.191 lines 191-227) and the c_long layout under #[cfg(not(gnu_time_bits64))] (lines 229-262). The build script never sets gnu_time_bits64 on riscv32, because its time_t is 64-bit already (build.rs:329-345):
// 32-bit arches with 64-bit time_t by default. rv32 is 64-only, `x86_64` covers the x32 arch,
// `!(linux|windows|hurd)` covers vxworks and future platforms.
let gnu32_already_time64 = target_arch == "riscv32"
|| target_arch == "x86_64"
|| !matches!(target_os.as_str(), "linux" | "windows" | "hurd");
let gnu = target_env == "gnu";
let gnu32_time64 = gnu && target_ptr_width == "32" && (gnu32_timebits == "64" || time64);
if gnu32_time64 && !gnu32_already_time64 {
so riscv32 gets the time32 layout, with 32-bit long fields:
#[cfg(not(gnu_time_bits64))]
pub struct timex {
pub modes: c_uint,
pub offset: c_long,
pub freq: c_long,
pub maxerror: c_long,
pub esterror: c_long,
pub status: c_int,
pub constant: c_long,
pub precision: c_long,
pub tolerance: c_long,
pub time: crate::timeval,
...
glibc's riscv32 struct timex takes the long long layout whenever __TIMESIZE == 64 && __WORDSIZE == 32 (glibc 2.44, bits/timex.h:26-36; riscv32's bits/timesize.h defines __TIMESIZE as 64):
struct timex
{
# if defined __USE_TIME64_REDIRECTS || (__TIMESIZE == 64 && __WORDSIZE == 32)
unsigned int modes; /* mode selector */
int :32; /* pad */
long long offset; /* time offset (usec) */
long long freq; /* frequency offset (scaled ppm) */
long long maxerror; /* maximum error (usec) */
long long esterror; /* estimated error (usec) */
int status; /* clock command/status */
int :32; /* pad */
Layouts, measured
libc timex |
glibc struct timex |
|
|---|---|---|
| size | 144 | 208 |
offset of freq |
8 | 16 |
offset of status |
20 | 40 |
offset of time |
40 | 72 |
offset of tai |
92 | 160 |
The libc column: const assertions under cargo check --target riscv32gc-unknown-linux-gnu, the same on 0.2.186, 0.2.191 and 1.0.0-alpha.5. The glibc column: _Static_asserts compiled by riscv32-unknown-linux-gnu-gcc 16.2.1 against glibc 2.44's headers.
At run time (qemu-riscv32 10.2.3, glibc 2.44, libc 0.2.191): adjtimex() with modes = 0, called on a libc::timex at the head of a canary-filled 256-byte buffer, changes the 20 bytes at offsets 144-163 (glibc's errcnt, stbcnt and tai): it writes past the end of the Rust struct. And status reads 0x0 (the upper half of glibc's freq) while glibc's status holds 0x40, STA_UNSYNC, so an unsynchronized clock reads as synchronized.
Minimal example (no dependency but libc):
#![no_std]
const _: [(); 208] = [(); core::mem::size_of::<libc::timex>()];
cargo check --target riscv32gc-unknown-linux-gnu fails with expected an array with a size of 208, found one with a size of 144.
A possible fix: give riscv32 the c_longlong layout too, #[cfg(any(gnu_time_bits64, target_arch = "riscv32"))] on the first declaration and #[cfg(not(any(gnu_time_bits64, target_arch = "riscv32")))] on the second. With that change on 0.2.191: riscv32 208 bytes, adjtimex() changes nothing past the struct, status reads 0x40; i686 and armv7 keep their 128 bytes.
Related: the time64 tracking issue #5507.
- 主要言語
- Rust
- スター
- 2.6k
- フォーク
- 1.3k
- 平均マージ
- 2日 8時間
- マージ済み PR(30日)
- 27
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
rust-lang/libc のほかの issue
-
Expose `open_how` on Android対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
rust-lang/libc#5673 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
RTEMS: `dirfd` is not declared対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
rust-lang/libc#5655 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
C-bug O-macos
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
rust-lang/libc#5650 · コメント 16 件 ·
メンテナーはふだん 1 日以内に返信
-
C-API-request
難易度 2/5 1〜3時間 初心者へのやさしさ 67/100
メンテナーはふだん 1 日以内に返信
-
libc-test: some semver files are never checked対応中かも @Deepak-negi11 が 26 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 67/100
rust-lang/libc#5622 · コメント 1 件 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信
似ている issue
-
binding:python bug
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
メンテナーはふだん 1 日以内に返信
-
enhancement
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
coollabsio/orbit#72 ·
メンテナーはふだん 1 日以内に返信
-
enhancement
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
-
bug order-flow studies ui
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
userFRM/egui-charts#2417 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 2 日以内に返信