newlib: give RTEMS its own socket address types#5307
Conversation
RTEMS's networking is rtems-libbsd, a port of the FreeBSD stack, so every socket address on RTEMS begins with a one-byte length followed by a one-byte family, and sockaddr_storage is 128 bytes. The definitions RTEMS was picking up came from src/unix/newlib/arm/mod.rs, which has neither. The first cfg_if in src/unix/newlib/mod.rs selects espidf, horizon and vita by target_os and only then falls through to target_arch, so armv7-rtems-eabihf lands in arm/mod.rs; a second cfg_if then glob-imports mod rtems on top. The length byte comes from libbsd, not from newlib, so the definitions belong in the rtems module the way the other three OSes have their own -- not in the arch module, where they would silently change any other newlib arm target. Measured with arm-rtems6-gcc 13.3 against the RTEMS 6 headers for BSP xilinx_zynq_a9_qemu, and cross-checked at runtime in QEMU: offsetof(struct sockaddr_in, sin_len) = 0 offsetof(struct sockaddr_in, sin_family) = 1 sizeof(struct sockaddr_storage) = 128 offsetof(struct sockaddr_storage, ss_family) = 1 sizeof(struct sockaddr_un) = 106 AF_INET6 = 28 and getsockname() on a socket bound to 0.0.0.0:5064 returns 16 bytes starting 10 02 00 00, i.e. ss_len=16 then ss_family=2. Consequence today: std reads the family at offset 0, sees the length, matches neither AF_INET nor AF_INET6, and every address-returning call -- local_addr, peer_addr, accept, recv_from, lookup_host -- fails with InvalidInput and no OS error. TcpListener::bind succeeds and TcpListener::accept cannot work. aarch64/mod.rs already carries the correct shape; it is cited here as evidence of the layout, not as the model for the location.
Same cause as the previous commit: RTEMS was taking the else arm of every cfg_if in the newlib module, which carries newlib-generic (devkitPro/Cygwin) values, while RTEMS 6 with rtems-libbsd uses FreeBSD's. Every value below was measured by arm-rtems6-gcc against the RTEMS 6 headers for BSP xilinx_zynq_a9_qemu. 305 of the 349 constants the newlib modules declare are integer constants the RTEMS headers also define; 27 of those 305 disagreed. After this commit, 0 disagree. POLLOUT 0x10 -> 0x4 POLLHUP 0x4 -> 0x10 MSG_DONTWAIT 4 -> 0x80 MSG_DONTROUTE 0 -> 0x4 MSG_WAITALL 0 -> 0x40 MSG_NOSIGNAL 0 -> 0x20000 FIONBIO 1 -> 0x8004667e TCP_NODELAY 8193 -> 1 TCP_MAXSEG 8194 -> 2 IP_TTL 8 -> 4 IP_ADD_MEMBERSHIP 11 -> 12 IP_DROP_MEMBERSHIP 12 -> 13 O_CLOEXEC 0x80000 -> 0x40000 SOCK_CLOEXEC O_CLOEXEC -> 0x10000000 FD_SETSIZE 1024 -> 256 NCCS 32 -> 20 TRY_AGAIN 4 -> 2 NO_DATA 2 -> 4 NO_ADDRESS 2 -> NO_DATA AI_NUMERICSERV 0 -> 8 AI_ADDRCONFIG 0 -> 0x400 NI_NUMERICSERV 0 -> 8 NI_DGRAM 0 -> 0x10 EAI_FAMILY -303 -> 5 EAI_MEMORY -304 -> 6 EAI_NONAME -305 -> 8 EAI_SOCKTYPE -307 -> 10 MSG_NOSIGNAL, TCP_NODELAY, POLLOUT/POLLHUP and IP_ADD_MEMBERSHIP are the ones that break working programs rather than merely reporting the wrong number. NCCS changes the size of struct termios. That struct is still wrong on RTEMS for a second reason -- it is missing c_ispeed and c_ospeed -- which is left for a separate change.
|
@rustbot label stable-nominated |
|
This is not in a reviewable state. Handwrite all comments, PR descriptions, commit messages, and anything else where you're communicating with humans, and ensure you are following the guidelines at https://github.com/rust-lang/libc/blob/main/CONTRIBUTING.md#submitting-a-pull-request. @rustbot author |
|
Reminder, once the PR becomes ready for a review, use |
Thanks, I'll rewrite the description and commit messages to follow the contributing guidelines. |
On
armv7-rtems-eabihfeverylibcsocket address struct is missing the BSDlength byte, and 27 socket/file constants have the wrong value. The result:
TcpListener::bindsucceeds butlocal_addr()fails withInvalidInput,and every
accept/peer_addr/recv_fromfails the same way —stdcannotparse an address RTEMS returns. Networking is unusable on the target.
Two commits: the address structs (
sockaddr,sockaddr_in,sockaddr_in6,sockaddr_un,sockaddr_storage), then the constants (AF_INET6,PF_INET6,SOL_SOCKET,FIONBIO,POLL*,MSG_*,O_CLOEXEC,SOCK_CLOEXEC,NCCS,FD_SETSIZE,TCP_NODELAY,TCP_MAXSEG,IP_TTL,IP_{ADD,DROP}_MEMBERSHIP,h_errno,AI_*,NI_*,EAI_*).Why
newlib/rtems/, notnewlib/arm/RTEMS's network stack is
rtems-libbsd, imported from FreeBSD, so its socketaddresses carry a leading one-byte length. The length byte comes from the OS,
not the architecture — plain newlib on arm has no such stack and no length
byte.
src/unix/newlib/mod.rsalready selects bytarget_osfirst (espidf,horizon, vita) before falling through to
target_arch, and already glob-importsmod rtemsfortarget_os = "rtems", so this follows the layout that is there.newlib/arm's copies become#[cfg(not(target_os = "rtems"))], so nonon-RTEMS target changes.
newlib/aarch64/mod.rs:22already hassin_len— correct shape, wrongplace: it silently changes plain
aarch64-none-newlibtoo. This PR does notrepeat that.
sa_family_t = u8is correct for RTEMS and is left alone; onelength byte plus one family byte is exactly the BSD layout.
Evidence
From the toolchain headers a shim compile actually resolves (
arm-rtems6-gcc -M):sys/socket.h:246hasAF_INET6 28;libcsays 23._SS_MAXSIZEis 128,where
newlib/arm/mod.rs:27declaredsockaddr_storageas 28 bytes.In the guest,
getsocknameon0.0.0.0:5064returns10 02 00 00 …—ss_len = 16,ss_family = 2.std'ssocket_addr_from_creads offset 0,gets 16, matches neither
AF_INETnorAF_INET6, and returnsInvalidInputwithraw_os_error() == None— no syscall failed.Same binary and image,
libcthe only variable:Scope measured by compiling, for
armv7-rtems-eabihf, a generated file ofconst _: () = assert!(libc::NAME == <value from arm-rtems6-gcc>);, socfgresolution is the compiler's and not a script's:
sockaddr*layout facts wrongarmis the only reachable RTEMS outlier:aarch64has the right shape but nosockaddr_storage;powerpc(devkitPPC) documents having no sockaddr;espidf/vitaalready carry length bytes;horizonis not BSD-derived.Verification
armv7-rtems-eabihf;cargo +nightly fmt --all -- --checkclean.riscv32imc-esp-espidfbuilds, unchanged.armv7-sony-vita-newlibeabihfandarmv6k-nintendo-3dsfail identically before and after (pre-existingE0573atsrc/unix/mod.rs:936).2faafecb, gcc 13.3.0, newlib1b3dcfd, BSPxilinx_zynq_a9_qemuunderqemu-system-arm.Must reach 0.2 to unblock anyone:
library/std/Cargo.tomldepends onlibc 0.2.x, so amain-only fix never reaches thestdthat-Zbuild-stdcompiles.
@rustbot label stable-nominated
Not in this PR
time_t,dev_t,ino_t,rlim_t,clock_tare 8bytes on RTEMS and declared 4;
clockid_tis signed and declared unsigned.Separate PR (newlib: correct RTEMS scalar type widths #5308), because it overlaps the open newlib: fix definition of
time_tandoff_t#5132. Both PRsadd to
src/unix/newlib/rtems/mod.rs; whichever lands second needs a one-hunkcontext rebase there.
fcntl(F_DUPFD)fails on anrtems-libbsdsocket, soTcpStream::try_clonecannot work there. Not a
libcdefect —rtems-libbsdinstallsrtems_bsd_sysgen_open_erroras.open_hon every socket, whichduplicate_iop(cpukit/libcsupport/src/fcntl.c) calls. Reported separately.