Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support the x86_64 x32 ABI #1384

Closed
hvdijk opened this issue Feb 6, 2021 · 4 comments
Closed

Support the x86_64 x32 ABI #1384

hvdijk opened this issue Feb 6, 2021 · 4 comments

Comments

@hvdijk
Copy link

hvdijk commented Feb 6, 2021

When trying to build for x86_64-unknown-linux-gnux32, a lot of errors are shown (the first ones not related to x32). It would be nice to see support for this. The problem is that many places use libc::c_long, which for x86_64-unknown-linux-gnux32 is i32, where the actual types to use are i64 for compatibility with x86_64-unknown-linux-gnu.

I am just reporting this as an issue for the moment: I had taken a stab at fixing this myself, but quickly found I don't really know Rust well enough yet. If someone else doesn't get it working first, I will try again when I have some more time to learn the language properly.

$ cargo build --target=x86_64-unknown-linux-gnux32
    Updating crates.io index
   Compiling libc v0.2.85
   Compiling bitflags v1.2.1
   Compiling cfg-if v1.0.0
   Compiling nix v0.19.0 (/home/harald/rust-nix)
error[E0308]: mismatched types
  --> src/mqueue.rs:47:29
   |
47 |             (*p).mq_flags = mq_flags;
   |                             ^^^^^^^^
   |                             |
   |                             expected `i64`, found `i32`
   |                             help: you can convert an `i32` to an `i64`: `mq_flags.into()`

error[E0308]: mismatched types
  --> src/mqueue.rs:48:30
   |
48 |             (*p).mq_maxmsg = mq_maxmsg;
   |                              ^^^^^^^^^
   |                              |
   |                              expected `i64`, found `i32`
   |                              help: you can convert an `i32` to an `i64`: `mq_maxmsg.into()`

error[E0308]: mismatched types
  --> src/mqueue.rs:49:31
   |
49 |             (*p).mq_msgsize = mq_msgsize;
   |                               ^^^^^^^^^^
   |                               |
   |                               expected `i64`, found `i32`
   |                               help: you can convert an `i32` to an `i64`: `mq_msgsize.into()`

error[E0308]: mismatched types
  --> src/mqueue.rs:50:31
   |
50 |             (*p).mq_curmsgs = mq_curmsgs;
   |                               ^^^^^^^^^^
   |                               |
   |                               expected `i64`, found `i32`
   |                               help: you can convert an `i32` to an `i64`: `mq_curmsgs.into()`

error[E0308]: mismatched types
  --> src/mqueue.rs:56:9
   |
55 |     pub fn flags(&self) -> c_long {
   |                            ------ expected `i32` because of return type
56 |         self.mq_attr.mq_flags
   |         ^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `i64`
   |
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
   |
56 |         self.mq_attr.mq_flags.try_into().unwrap()
   |

error[E0308]: mismatched types
   --> src/mqueue.rs:154:31
    |
154 | ...                   oldattr.mq_attr.mq_maxmsg,
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `i64`
    |
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
154 |                               oldattr.mq_attr.mq_maxmsg.try_into().unwrap(),
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
   --> src/mqueue.rs:155:31
    |
155 | ...                   oldattr.mq_attr.mq_msgsize,
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `i64`
    |
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
155 |                               oldattr.mq_attr.mq_msgsize.try_into().unwrap(),
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
   --> src/mqueue.rs:156:31
    |
156 | ...                   oldattr.mq_attr.mq_curmsgs);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `i64`
    |
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
156 |                               oldattr.mq_attr.mq_curmsgs.try_into().unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
   --> src/mqueue.rs:166:31
    |
166 | ...                   oldattr.mq_attr.mq_maxmsg,
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `i64`
    |
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
166 |                               oldattr.mq_attr.mq_maxmsg.try_into().unwrap(),
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
   --> src/mqueue.rs:167:31
    |
167 | ...                   oldattr.mq_attr.mq_msgsize,
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `i64`
    |
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
167 |                               oldattr.mq_attr.mq_msgsize.try_into().unwrap(),
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
   --> src/mqueue.rs:168:31
    |
168 | ...                   oldattr.mq_attr.mq_curmsgs);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `i64`
    |
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
168 |                               oldattr.mq_attr.mq_curmsgs.try_into().unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
   --> src/sys/statfs.rs:102:16
    |
102 |         FsType(self.0.f_type)
    |                ^^^^^^^^^^^^^ expected `i32`, found `i64`
    |
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
102 |         FsType(self.0.f_type.try_into().unwrap())
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
   --> src/sys/statfs.rs:142:9
    |
141 |     pub fn optimal_transfer_size(&self) -> libc::c_long {
    |                                            ------------ expected `i32` because of return type
142 |         self.0.f_bsize
    |         ^^^^^^^^^^^^^^ expected `i32`, found `i64`
    |
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
142 |         self.0.f_bsize.try_into().unwrap()
    |

error[E0308]: mismatched types
   --> src/sys/statfs.rs:181:9
    |
180 |     pub fn block_size(&self) -> libc::c_long {
    |                                 ------------ expected `i32` because of return type
181 |         self.0.f_bsize
    |         ^^^^^^^^^^^^^^ expected `i32`, found `i64`
    |
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
181 |         self.0.f_bsize.try_into().unwrap()
    |

error[E0308]: mismatched types
   --> src/sys/statfs.rs:223:9
    |
222 |     pub fn maximum_name_length(&self) -> libc::c_long {
    |                                          ------------ expected `i32` because of return type
223 |         self.0.f_namelen
    |         ^^^^^^^^^^^^^^^^ expected `i32`, found `i64`
    |
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
223 |         self.0.f_namelen.try_into().unwrap()
    |

error[E0308]: mismatched types
   --> src/sys/statfs.rs:267:9
    |
266 |     pub fn blocks(&self) -> libc::c_ulong {
    |                             ------------- expected `u32` because of return type
267 |         self.0.f_blocks
    |         ^^^^^^^^^^^^^^^ expected `u32`, found `u64`
    |
help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
    |
267 |         self.0.f_blocks.try_into().unwrap()
    |

error[E0308]: mismatched types
   --> src/sys/statfs.rs:305:9
    |
304 |     pub fn blocks_free(&self) -> libc::c_ulong {
    |                                  ------------- expected `u32` because of return type
305 |         self.0.f_bfree
    |         ^^^^^^^^^^^^^^ expected `u32`, found `u64`
    |
help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
    |
305 |         self.0.f_bfree.try_into().unwrap()
    |

error[E0308]: mismatched types
   --> src/sys/statfs.rs:343:9
    |
342 |     pub fn blocks_available(&self) -> libc::c_ulong {
    |                                       ------------- expected `u32` because of return type
343 |         self.0.f_bavail
    |         ^^^^^^^^^^^^^^^ expected `u32`, found `u64`
    |
help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
    |
343 |         self.0.f_bavail.try_into().unwrap()
    |

error[E0308]: mismatched types
   --> src/sys/statfs.rs:381:9
    |
380 |     pub fn files(&self) -> libc::c_ulong {
    |                            ------------- expected `u32` because of return type
381 |         self.0.f_files
    |         ^^^^^^^^^^^^^^ expected `u32`, found `u64`
    |
help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
    |
381 |         self.0.f_files.try_into().unwrap()
    |

error[E0308]: mismatched types
   --> src/sys/statfs.rs:419:9
    |
418 |     pub fn files_free(&self) -> libc::c_ulong {
    |                                 ------------- expected `u32` because of return type
419 |         self.0.f_ffree
    |         ^^^^^^^^^^^^^^ expected `u32`, found `u64`
    |
help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
    |
419 |         self.0.f_ffree.try_into().unwrap()
    |

error[E0308]: mismatched types
  --> src/sys/sysinfo.rs:39:24
   |
39 |         self.scale_mem(self.0.totalswap)
   |                        ^^^^^^^^^^^^^^^^ expected `u32`, found `u64`
   |
help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
   |
39 |         self.scale_mem(self.0.totalswap.try_into().unwrap())
   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
  --> src/sys/sysinfo.rs:44:24
   |
44 |         self.scale_mem(self.0.freeswap)
   |                        ^^^^^^^^^^^^^^^ expected `u32`, found `u64`
   |
help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
   |
44 |         self.scale_mem(self.0.freeswap.try_into().unwrap())
   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
  --> src/sys/sysinfo.rs:49:24
   |
49 |         self.scale_mem(self.0.totalram)
   |                        ^^^^^^^^^^^^^^^ expected `u32`, found `u64`
   |
help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
   |
49 |         self.scale_mem(self.0.totalram.try_into().unwrap())
   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
  --> src/sys/sysinfo.rs:58:24
   |
58 |         self.scale_mem(self.0.freeram)
   |                        ^^^^^^^^^^^^^^ expected `u32`, found `u64`
   |
help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
   |
58 |         self.scale_mem(self.0.freeram.try_into().unwrap())
   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
  --> src/sys/time.rs:76:22
   |
76 |             tv_nsec: duration.subsec_nanos() as c_long
   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i64`, found `i32`

error[E0308]: mismatched types
   --> src/sys/time.rs:151:37
    |
151 | ...                   tv_nsec: nanos as c_long })
    |                                ^^^^^^^^^^^^^^^ expected `i64`, found `i32`

error[E0308]: mismatched types
   --> src/sys/time.rs:192:9
    |
191 |     pub fn tv_nsec(&self) -> c_long {
    |                              ------ expected `i32` because of return type
192 |         self.0.tv_nsec
    |         ^^^^^^^^^^^^^^ expected `i32`, found `i64`
    |
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
192 |         self.0.tv_nsec.try_into().unwrap()
    |

error: aborting due to 27 previous errors

For more information about this error, try `rustc --explain E0308`.
error: could not compile `nix`

To learn more, run the command again with --verbose.
@hvdijk
Copy link
Author

hvdijk commented Feb 6, 2021

Ah, I searched for issues, but not PRs. There is an open PR for this, #1366, which shows a test failure on CI but is likely to be a good starting point.

@hvdijk
Copy link
Author

hvdijk commented Feb 7, 2021

Actually, aside from needing some more updates to the test code, that PR already looks good. The test failure that was displayed for CI previously was not related to x32. As I cannot update someone else's PR (nor should I be able to), I will put in a comment here the additional patch I needed to get tests to pass, with the exception of sys::test_socket::test_vsock which fails for unrelated reasons the same way as on x86_64-unknown-linux-gnu. @nabijaczleweli, does this look like something you could add to your PR, or would you want me to submit this independently somehow?

diff --git a/test/sys/test_ptrace.rs b/test/sys/test_ptrace.rs
index 38cf408b..5be99c1b 100644
--- a/test/sys/test_ptrace.rs
+++ b/test/sys/test_ptrace.rs
@@ -150,11 +150,11 @@ fn test_ptrace_syscall() {
             // set this option to recognize syscall-stops
             ptrace::setoptions(child, ptrace::Options::PTRACE_O_TRACESYSGOOD).unwrap();
 
-            #[cfg(target_pointer_width = "64")]
-            let get_syscall_id = || ptrace::getregs(child).unwrap().orig_rax as i64;
+            #[cfg(target_arch = "x86_64")]
+            let get_syscall_id = || ptrace::getregs(child).unwrap().orig_rax as libc::c_long;
 
-            #[cfg(target_pointer_width = "32")]
-            let get_syscall_id = || ptrace::getregs(child).unwrap().orig_eax as i32;
+            #[cfg(target_arch = "x86")]
+            let get_syscall_id = || ptrace::getregs(child).unwrap().orig_eax as libc::c_long;
 
             // kill entry
             ptrace::syscall(child, None).unwrap();
diff --git a/test/test_mq.rs b/test/test_mq.rs
index ecee2009..1667a35b 100644
--- a/test/test_mq.rs
+++ b/test/test_mq.rs
@@ -1,17 +1,15 @@
-use libc::c_long;
-
 use std::ffi::CString;
 use std::str;
 
 use nix::errno::Errno::*;
 use nix::Error::Sys;
-use nix::mqueue::{mq_open, mq_close, mq_send, mq_receive};
+use nix::mqueue::{mq_open, mq_close, mq_send, mq_receive, mq_attr_member_t};
 use nix::mqueue::{MqAttr, MQ_OFlag};
 use nix::sys::stat::Mode;
 
 #[test]
 fn test_mq_send_and_receive() {
-    const MSG_SIZE: c_long =  32;
+    const MSG_SIZE: mq_attr_member_t = 32;
     let attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
     let mq_name= &CString::new(b"/a_nix_test_queue".as_ref()).unwrap();
 
@@ -43,7 +41,7 @@ fn test_mq_send_and_receive() {
 #[cfg(not(any(target_os = "netbsd")))]
 fn test_mq_getattr() {
     use nix::mqueue::mq_getattr;
-    const MSG_SIZE: c_long =  32;
+    const MSG_SIZE: mq_attr_member_t = 32;
     let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
     let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
     let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
@@ -66,7 +64,7 @@ fn test_mq_getattr() {
 #[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
 fn test_mq_setattr() {
     use nix::mqueue::{mq_getattr, mq_setattr};
-    const MSG_SIZE: c_long =  32;
+    const MSG_SIZE: mq_attr_member_t = 32;
     let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
     let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
     let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
@@ -87,7 +85,7 @@ fn test_mq_setattr() {
     // O_NONBLOCK can be set (see tests below)
     assert_ne!(new_attr_get, new_attr);
 
-    let new_attr_non_blocking =  MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as c_long, 10, MSG_SIZE, 0);
+    let new_attr_non_blocking =  MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as mq_attr_member_t, 10, MSG_SIZE, 0);
     mq_setattr(mqd, &new_attr_non_blocking).unwrap();
     let new_attr_get = mq_getattr(mqd).unwrap();
 
@@ -103,7 +101,7 @@ fn test_mq_setattr() {
 #[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
 fn test_mq_set_nonblocking() {
     use nix::mqueue::{mq_getattr, mq_set_nonblock, mq_remove_nonblock};
-    const MSG_SIZE: c_long =  32;
+    const MSG_SIZE: mq_attr_member_t = 32;
     let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
     let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
     let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
@@ -116,7 +114,7 @@ fn test_mq_set_nonblocking() {
     let mqd = r.unwrap();
     mq_set_nonblock(mqd).unwrap();
     let new_attr = mq_getattr(mqd);
-    assert_eq!(new_attr.unwrap().flags(), MQ_OFlag::O_NONBLOCK.bits() as c_long);
+    assert_eq!(new_attr.unwrap().flags(), MQ_OFlag::O_NONBLOCK.bits() as mq_attr_member_t);
     mq_remove_nonblock(mqd).unwrap();
     let new_attr = mq_getattr(mqd);
     assert_eq!(new_attr.unwrap().flags(), 0);
@@ -127,7 +125,7 @@ fn test_mq_set_nonblocking() {
 #[cfg(not(any(target_os = "netbsd")))]
 fn test_mq_unlink() {
     use nix::mqueue::mq_unlink;
-    const MSG_SIZE: c_long =  32;
+    const MSG_SIZE: mq_attr_member_t = 32;
     let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
     let mq_name_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap();
     let mq_name_not_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap();

There was also a problem in caps that prevented getting to the point where tests run; I have submitted a PR for that.

@nabijaczleweli
Copy link
Contributor

I've added (a derivative of) your patch to #1366, thanks!

@asomers
Copy link
Member

asomers commented Aug 9, 2021

Closing this issue, as it was fixed by #1366

@asomers asomers closed this as completed Aug 9, 2021
SteveLauC added a commit to SteveLauC/nix that referenced this issue Nov 21, 2022
SteveLauC added a commit to SteveLauC/nix that referenced this issue Nov 29, 2022
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

No branches or pull requests

3 participants