Skip to content

Commit

Permalink
Auto merge of #28543 - gandro:netbsd, r=alexcrichton
Browse files Browse the repository at this point in the history
These changes introduce the ability to cross-compile working binaries for NetBSD/amd64. Previous support added in PR #26682 shared all its code with the OpenBSD implementation, and was therefore never functional (e.g. linking against non-existing symbols and using wrong type definitions). Nonetheless, the previous patches were a great starting point and made my work significantly easier. 😃 

Because there are no stage0 snapshots for NetBSD (yet), I used a cross-compiler for NetBSD 7.0 RC3 and only tested some toy programs (threading and channels, stack guards, a small TCP/IP echo server and some other platform dependent bits). If someone could point me to documentation on how to generate a stage0 snapshot from a cross-compiler I'm happy to run the full test suite.

A few other notes regarding Rust on NetBSD/amd64:
- To preserve binary compatibility, NetBSD introduces new symbols for system call wrappers on breaking ABI changes and keeps the old (legacy) symbols around, see [this documentation](https://www.netbsd.org/docs/internals/en/chap-processes.html#syscalls_master) for some details. I went ahead and modified the `libc` and `std` crate to use the current (renamed) symbols instead of the legacy ones where I found them, but I might have missed some. Notably using the `sigaction` symbol (deprecated in 1998) instead of `__sigaction14` even triggers SIGSYS (bad syscall) on my amd64 setup. I also changed the type definitions to use the most recent version.
- NetBSD's gdb doesn't really support position independent executables, so you might want to turn that off for debugging, see [NetBSD Problem Report #48250](https://gnats.netbsd.org/48250).
- For binaries invoked using a relative path, NetBSD supports `$ORIGIN` only for short `rpath`s (~64 chars or so, I'm told). If running an executable fails with `execname not specified in AUX vector: No such file or directory`, consider invoking the binary using its full absolute path.
  • Loading branch information
bors committed Sep 22, 2015
2 parents 2a6f6f2 + 428bb16 commit 9c1aaeb
Show file tree
Hide file tree
Showing 9 changed files with 603 additions and 68 deletions.
1 change: 1 addition & 0 deletions mk/cfg/x86_64-unknown-netbsd.mk
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# x86_64-unknown-netbsd configuration
CROSS_PREFIX_x86_64-unknown-netbsd=x86_64-unknown-netbsd-
CC_x86_64-unknown-netbsd=$(CC)
CXX_x86_64-unknown-netbsd=$(CXX)
CPP_x86_64-unknown-netbsd=$(CPP)
Expand Down
538 changes: 488 additions & 50 deletions src/liblibc/lib.rs

Large diffs are not rendered by default.

13 changes: 7 additions & 6 deletions src/libstd/os/netbsd/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! NetBSD/OpenBSD-specific raw type definitions
//! NetBSD-specific raw type definitions

#![stable(feature = "raw_ext", since = "1.1.0")]

Expand All @@ -17,7 +17,7 @@ use os::unix::raw::{uid_t, gid_t};

#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = i64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u32;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = i32;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type fflags_t = u32;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type mode_t = u32;
Expand Down Expand Up @@ -55,6 +55,10 @@ pub struct stat {
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_ctime_nsec: c_long,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_birthtime: time_t,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_birthtime_nsec: c_long,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_size: off_t,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_blocks: blkcnt_t,
Expand All @@ -64,8 +68,5 @@ pub struct stat {
pub st_flags: fflags_t,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_gen: u32,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_birthtime: time_t,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_birthtime_nsec: c_long,
st_spare: [u32; 2],
}
12 changes: 9 additions & 3 deletions src/libstd/sys/unix/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,10 @@ pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 70;
target_os = "dragonfly"))]
pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 71;
#[cfg(any(target_os = "bitrig",
target_os = "netbsd",
target_os = "openbsd"))]
pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 101;
#[cfg(target_os = "netbsd")]
pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 48;
#[cfg(target_os = "android")]
pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 0x0048;

Expand Down Expand Up @@ -131,26 +132,31 @@ extern {

pub fn raise(signum: libc::c_int) -> libc::c_int;

#[cfg_attr(target_os = "netbsd", link_name = "__sigaction14")]
pub fn sigaction(signum: libc::c_int,
act: *const sigaction,
oldact: *mut sigaction) -> libc::c_int;

#[cfg_attr(target_os = "netbsd", link_name = "__sigaltstack14")]
pub fn sigaltstack(ss: *const sigaltstack,
oss: *mut sigaltstack) -> libc::c_int;

#[cfg(not(target_os = "android"))]
#[cfg_attr(target_os = "netbsd", link_name = "__sigemptyset14")]
pub fn sigemptyset(set: *mut sigset_t) -> libc::c_int;

pub fn pthread_sigmask(how: libc::c_int, set: *const sigset_t,
oldset: *mut sigset_t) -> libc::c_int;

#[cfg(not(target_os = "ios"))]
#[cfg_attr(target_os = "netbsd", link_name = "__getpwuid_r50")]
pub fn getpwuid_r(uid: libc::uid_t,
pwd: *mut passwd,
buf: *mut libc::c_char,
buflen: libc::size_t,
result: *mut *mut passwd) -> libc::c_int;

#[cfg_attr(target_os = "netbsd", link_name = "__utimes50")]
pub fn utimes(filename: *const libc::c_char,
times: *const libc::timeval) -> libc::c_int;
pub fn gai_strerror(errcode: libc::c_int) -> *const libc::c_char;
Expand Down Expand Up @@ -347,12 +353,12 @@ mod signal_os {
#[cfg(any(target_os = "macos",
target_os = "ios"))]
pub type sigset_t = u32;
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
#[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))]
#[repr(C)]
pub struct sigset_t {
bits: [u32; 4],
}
#[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))]
#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
pub type sigset_t = libc::c_uint;

// This structure has more fields, but we're not all that interested in
Expand Down
7 changes: 6 additions & 1 deletion src/libstd/sys/unix/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,12 @@ pub fn current_exe() -> io::Result<PathBuf> {
::fs::read_link("/proc/curproc/file")
}

#[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))]
#[cfg(target_os = "netbsd")]
pub fn current_exe() -> io::Result<PathBuf> {
::fs::read_link("/proc/curproc/exe")
}

#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
pub fn current_exe() -> io::Result<PathBuf> {
use sync::StaticMutex;
static LOCK: StaticMutex = StaticMutex::new();
Expand Down
1 change: 1 addition & 0 deletions src/libstd/sys/unix/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ mod tests {

#[cfg(not(target_os = "android"))]
extern {
#[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")]
fn sigaddset(set: *mut c::sigset_t, signum: libc::c_int) -> libc::c_int;
}

Expand Down
66 changes: 65 additions & 1 deletion src/libstd/sys/unix/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ extern {
pub fn pthread_cond_signal(cond: *mut pthread_cond_t) -> libc::c_int;
pub fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> libc::c_int;
pub fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> libc::c_int;
#[cfg_attr(target_os = "netbsd", link_name = "__gettimeofday50")]
pub fn gettimeofday(tp: *mut libc::timeval,
tz: *mut libc::c_void) -> libc::c_int;

Expand All @@ -55,7 +56,6 @@ extern {
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
target_os = "netbsd",
target_os = "openbsd"))]
mod os {
use libc;
Expand Down Expand Up @@ -249,3 +249,67 @@ mod os {
};
pub const PTHREAD_MUTEX_RECURSIVE: libc::c_int = 1;
}

#[cfg(target_os = "netbsd")]
mod os {
use libc;

// size of the type minus width of the magic and alignment field
#[cfg(target_arch = "x86_64")]
const __PTHREAD_MUTEX_SIZE__: usize = 48 - 4 - 8;

#[cfg(target_arch = "x86_64")]
const __PTHREAD_MUTEXATTR_SIZE__: usize = 16 - 8; // no magic field

#[cfg(target_arch = "x86_64")]
const __PTHREAD_COND_SIZE__: usize = 40 - 4 - 8;

#[cfg(target_arch = "x86_64")]
const __PTHREAD_RWLOCK_SIZE__: usize = 64 - 4 - 8;

const _PTHREAD_MUTEX_MAGIC_INIT: libc::c_uint = 0x33330003;
const _PTHREAD_COND_MAGIC_INIT: libc::c_uint = 0x55550005;
const _PTHREAD_RWLOCK_MAGIC_INIT: libc::c_uint = 0x99990009;

#[repr(C)]
pub struct pthread_mutex_t {
__magic: libc::c_uint,
__opaque: [u8; __PTHREAD_MUTEX_SIZE__],
__align: libc::c_longlong,
}
#[repr(C)]
pub struct pthread_mutexattr_t {
__opaque: [u8; __PTHREAD_MUTEXATTR_SIZE__],
__align: libc::c_longlong,
}
#[repr(C)]
pub struct pthread_cond_t {
__magic: libc::c_uint,
__opaque: [u8; __PTHREAD_COND_SIZE__],
__align: libc::c_longlong,
}
#[repr(C)]
pub struct pthread_rwlock_t {
__magic: libc::c_uint,
__opaque: [u8; __PTHREAD_RWLOCK_SIZE__],
__align: libc::c_longlong,
}

pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
__magic: _PTHREAD_MUTEX_MAGIC_INIT,
__opaque: [0; __PTHREAD_MUTEX_SIZE__],
__align: 0,
};
pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
__magic: _PTHREAD_COND_MAGIC_INIT,
__opaque: [0; __PTHREAD_COND_SIZE__],
__align: 0,
};
pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
__magic: _PTHREAD_RWLOCK_MAGIC_INIT,
__opaque: [0; __PTHREAD_RWLOCK_SIZE__],
__align: 0,
};

pub const PTHREAD_MUTEX_RECURSIVE: libc::c_int = 2;
}
31 changes: 24 additions & 7 deletions src/libstd/sys/unix/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ impl Thread {
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
target_os = "netbsd",
target_os = "openbsd"))]
pub fn set_name(name: &str) {
extern {
Expand All @@ -126,6 +125,21 @@ impl Thread {
}
}

#[cfg(target_os = "netbsd")]
pub fn set_name(name: &str) {
extern {
fn pthread_setname_np(thread: libc::pthread_t,
name: *const libc::c_char,
arg: *mut libc::c_void) -> libc::c_int;
}
let cname = CString::new(&b"%s"[..]).unwrap();
let carg = CString::new(name).unwrap();
unsafe {
pthread_setname_np(pthread_self(), cname.as_ptr(),
carg.as_ptr() as *mut libc::c_void);
}
}

pub fn sleep(dur: Duration) {
let mut ts = libc::timespec {
tv_sec: dur.as_secs() as libc::time_t,
Expand Down Expand Up @@ -191,13 +205,12 @@ pub mod guard {

#[cfg(any(target_os = "macos",
target_os = "bitrig",
target_os = "netbsd",
target_os = "openbsd"))]
unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
current().map(|s| s as *mut libc::c_void)
}

#[cfg(any(target_os = "linux", target_os = "android"))]
#[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd"))]
unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
use super::pthread_attr_init;

Expand Down Expand Up @@ -263,7 +276,7 @@ pub mod guard {
pthread_get_stacksize_np(pthread_self())) as usize)
}

#[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "bitrig"))]
#[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
pub unsafe fn current() -> Option<usize> {
#[repr(C)]
struct stack_t {
Expand All @@ -290,7 +303,7 @@ pub mod guard {
})
}

#[cfg(any(target_os = "linux", target_os = "android"))]
#[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd"))]
pub unsafe fn current() -> Option<usize> {
use super::pthread_attr_init;

Expand All @@ -307,13 +320,17 @@ pub mod guard {
let mut size = 0;
assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0);

ret = Some(stackaddr as usize + guardsize as usize);
ret = if cfg!(target_os = "netbsd") {
Some(stackaddr as usize)
} else {
Some(stackaddr as usize + guardsize as usize)
};
}
assert_eq!(pthread_attr_destroy(&mut attr), 0);
ret
}

#[cfg(any(target_os = "linux", target_os = "android"))]
#[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd"))]
extern {
fn pthread_getattr_np(native: libc::pthread_t,
attr: *mut libc::pthread_attr_t) -> libc::c_int;
Expand Down
2 changes: 2 additions & 0 deletions src/libstd/sys/unix/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ mod inner {
#[link(name = "rt")]
extern {}


extern {
#[cfg_attr(target_os = "netbsd", link_name = "__clock_gettime50")]
fn clock_gettime(clk_id: libc::c_int, tp: *mut libc::timespec) -> libc::c_int;
}

Expand Down

0 comments on commit 9c1aaeb

Please sign in to comment.