Merge "Change visibility of alloc share/unshare functions to pub(crate)" into main
diff --git a/vmbase/src/bionic.rs b/vmbase/src/bionic.rs
index 2ce0e83..29fa0ff 100644
--- a/vmbase/src/bionic.rs
+++ b/vmbase/src/bionic.rs
@@ -22,6 +22,7 @@
 use core::str;
 
 use crate::console;
+use crate::cstr;
 use crate::eprintln;
 use crate::read_sysreg;
 
@@ -79,6 +80,11 @@
     unsafe { ERRNO = value };
 }
 
+fn get_errno() -> c_int {
+    // SAFETY: vmbase is currently single-threaded.
+    unsafe { ERRNO }
+}
+
 /// Reports a fatal error detected by Bionic.
 ///
 /// # Safety
@@ -154,142 +160,168 @@
 
 #[no_mangle]
 extern "C" fn strerror(n: c_int) -> *mut c_char {
-    // Messages taken from errno(1).
-    let s = match n {
-        0 => "Success",
-        1 => "Operation not permitted",
-        2 => "No such file or directory",
-        3 => "No such process",
-        4 => "Interrupted system call",
-        5 => "Input/output error",
-        6 => "No such device or address",
-        7 => "Argument list too long",
-        8 => "Exec format error",
-        9 => "Bad file descriptor",
-        10 => "No child processes",
-        11 => "Resource temporarily unavailable",
-        12 => "Cannot allocate memory",
-        13 => "Permission denied",
-        14 => "Bad address",
-        15 => "Block device required",
-        16 => "Device or resource busy",
-        17 => "File exists",
-        18 => "Invalid cross-device link",
-        19 => "No such device",
-        20 => "Not a directory",
-        21 => "Is a directory",
-        22 => "Invalid argument",
-        23 => "Too many open files in system",
-        24 => "Too many open files",
-        25 => "Inappropriate ioctl for device",
-        26 => "Text file busy",
-        27 => "File too large",
-        28 => "No space left on device",
-        29 => "Illegal seek",
-        30 => "Read-only file system",
-        31 => "Too many links",
-        32 => "Broken pipe",
-        33 => "Numerical argument out of domain",
-        34 => "Numerical result out of range",
-        35 => "Resource deadlock avoided",
-        36 => "File name too long",
-        37 => "No locks available",
-        38 => "Function not implemented",
-        39 => "Directory not empty",
-        40 => "Too many levels of symbolic links",
-        42 => "No message of desired type",
-        43 => "Identifier removed",
-        44 => "Channel number out of range",
-        45 => "Level 2 not synchronized",
-        46 => "Level 3 halted",
-        47 => "Level 3 reset",
-        48 => "Link number out of range",
-        49 => "Protocol driver not attached",
-        50 => "No CSI structure available",
-        51 => "Level 2 halted",
-        52 => "Invalid exchange",
-        53 => "Invalid request descriptor",
-        54 => "Exchange full",
-        55 => "No anode",
-        56 => "Invalid request code",
-        57 => "Invalid slot",
-        59 => "Bad font file format",
-        60 => "Device not a stream",
-        61 => "No data available",
-        62 => "Timer expired",
-        63 => "Out of streams resources",
-        64 => "Machine is not on the network",
-        65 => "Package not installed",
-        66 => "Object is remote",
-        67 => "Link has been severed",
-        68 => "Advertise error",
-        69 => "Srmount error",
-        70 => "Communication error on send",
-        71 => "Protocol error",
-        72 => "Multihop attempted",
-        73 => "RFS specific error",
-        74 => "Bad message",
-        75 => "Value too large for defined data type",
-        76 => "Name not unique on network",
-        77 => "File descriptor in bad state",
-        78 => "Remote address changed",
-        79 => "Can not access a needed shared library",
-        80 => "Accessing a corrupted shared library",
-        81 => ".lib section in a.out corrupted",
-        82 => "Attempting to link in too many shared libraries",
-        83 => "Cannot exec a shared library directly",
-        84 => "Invalid or incomplete multibyte or wide character",
-        85 => "Interrupted system call should be restarted",
-        86 => "Streams pipe error",
-        87 => "Too many users",
-        88 => "Socket operation on non-socket",
-        89 => "Destination address required",
-        90 => "Message too long",
-        91 => "Protocol wrong type for socket",
-        92 => "Protocol not available",
-        93 => "Protocol not supported",
-        94 => "Socket type not supported",
-        95 => "Operation not supported",
-        96 => "Protocol family not supported",
-        97 => "Address family not supported by protocol",
-        98 => "Address already in use",
-        99 => "Cannot assign requested address",
-        100 => "Network is down",
-        101 => "Network is unreachable",
-        102 => "Network dropped connection on reset",
-        103 => "Software caused connection abort",
-        104 => "Connection reset by peer",
-        105 => "No buffer space available",
-        106 => "Transport endpoint is already connected",
-        107 => "Transport endpoint is not connected",
-        108 => "Cannot send after transport endpoint shutdown",
-        109 => "Too many references: cannot splice",
-        110 => "Connection timed out",
-        111 => "Connection refused",
-        112 => "Host is down",
-        113 => "No route to host",
-        114 => "Operation already in progress",
-        115 => "Operation now in progress",
-        116 => "Stale file handle",
-        117 => "Structure needs cleaning",
-        118 => "Not a XENIX named type file",
-        119 => "No XENIX semaphores available",
-        120 => "Is a named type file",
-        121 => "Remote I/O error",
-        122 => "Disk quota exceeded",
-        123 => "No medium found",
-        124 => "Wrong medium type",
-        125 => "Operation canceled",
-        126 => "Required key not available",
-        127 => "Key has expired",
-        128 => "Key has been revoked",
-        129 => "Key was rejected by service",
-        130 => "Owner died",
-        131 => "State not recoverable",
-        132 => "Operation not possible due to RF-kill",
-        133 => "Memory page has hardware error",
-        _ => "Unknown errno value",
+    cstr_error(n).as_ptr().cast_mut().cast()
+}
+
+#[no_mangle]
+extern "C" fn perror(s: *const c_char) {
+    let prefix = if s.is_null() {
+        None
+    } else {
+        // SAFETY: Just like libc, we need to assume that `s` is a valid NULL-terminated string.
+        let c_str = unsafe { CStr::from_ptr(s) };
+        // TODO(Rust 1.71): if c_str.is_empty() {
+        if c_str.to_bytes().is_empty() {
+            None
+        } else {
+            Some(c_str.to_str().unwrap())
+        }
     };
 
-    s.as_ptr().cast_mut().cast()
+    let error = cstr_error(get_errno()).to_str().unwrap();
+
+    if let Some(prefix) = prefix {
+        eprintln!("{prefix}: {error}");
+    } else {
+        eprintln!("{error}");
+    }
+}
+
+fn cstr_error(n: c_int) -> &'static CStr {
+    // Messages taken from errno(1).
+    match n {
+        0 => cstr!("Success"),
+        1 => cstr!("Operation not permitted"),
+        2 => cstr!("No such file or directory"),
+        3 => cstr!("No such process"),
+        4 => cstr!("Interrupted system call"),
+        5 => cstr!("Input/output error"),
+        6 => cstr!("No such device or address"),
+        7 => cstr!("Argument list too long"),
+        8 => cstr!("Exec format error"),
+        9 => cstr!("Bad file descriptor"),
+        10 => cstr!("No child processes"),
+        11 => cstr!("Resource temporarily unavailable"),
+        12 => cstr!("Cannot allocate memory"),
+        13 => cstr!("Permission denied"),
+        14 => cstr!("Bad address"),
+        15 => cstr!("Block device required"),
+        16 => cstr!("Device or resource busy"),
+        17 => cstr!("File exists"),
+        18 => cstr!("Invalid cross-device link"),
+        19 => cstr!("No such device"),
+        20 => cstr!("Not a directory"),
+        21 => cstr!("Is a directory"),
+        22 => cstr!("Invalid argument"),
+        23 => cstr!("Too many open files in system"),
+        24 => cstr!("Too many open files"),
+        25 => cstr!("Inappropriate ioctl for device"),
+        26 => cstr!("Text file busy"),
+        27 => cstr!("File too large"),
+        28 => cstr!("No space left on device"),
+        29 => cstr!("Illegal seek"),
+        30 => cstr!("Read-only file system"),
+        31 => cstr!("Too many links"),
+        32 => cstr!("Broken pipe"),
+        33 => cstr!("Numerical argument out of domain"),
+        34 => cstr!("Numerical result out of range"),
+        35 => cstr!("Resource deadlock avoided"),
+        36 => cstr!("File name too long"),
+        37 => cstr!("No locks available"),
+        38 => cstr!("Function not implemented"),
+        39 => cstr!("Directory not empty"),
+        40 => cstr!("Too many levels of symbolic links"),
+        42 => cstr!("No message of desired type"),
+        43 => cstr!("Identifier removed"),
+        44 => cstr!("Channel number out of range"),
+        45 => cstr!("Level 2 not synchronized"),
+        46 => cstr!("Level 3 halted"),
+        47 => cstr!("Level 3 reset"),
+        48 => cstr!("Link number out of range"),
+        49 => cstr!("Protocol driver not attached"),
+        50 => cstr!("No CSI structure available"),
+        51 => cstr!("Level 2 halted"),
+        52 => cstr!("Invalid exchange"),
+        53 => cstr!("Invalid request descriptor"),
+        54 => cstr!("Exchange full"),
+        55 => cstr!("No anode"),
+        56 => cstr!("Invalid request code"),
+        57 => cstr!("Invalid slot"),
+        59 => cstr!("Bad font file format"),
+        60 => cstr!("Device not a stream"),
+        61 => cstr!("No data available"),
+        62 => cstr!("Timer expired"),
+        63 => cstr!("Out of streams resources"),
+        64 => cstr!("Machine is not on the network"),
+        65 => cstr!("Package not installed"),
+        66 => cstr!("Object is remote"),
+        67 => cstr!("Link has been severed"),
+        68 => cstr!("Advertise error"),
+        69 => cstr!("Srmount error"),
+        70 => cstr!("Communication error on send"),
+        71 => cstr!("Protocol error"),
+        72 => cstr!("Multihop attempted"),
+        73 => cstr!("RFS specific error"),
+        74 => cstr!("Bad message"),
+        75 => cstr!("Value too large for defined data type"),
+        76 => cstr!("Name not unique on network"),
+        77 => cstr!("File descriptor in bad state"),
+        78 => cstr!("Remote address changed"),
+        79 => cstr!("Can not access a needed shared library"),
+        80 => cstr!("Accessing a corrupted shared library"),
+        81 => cstr!(".lib section in a.out corrupted"),
+        82 => cstr!("Attempting to link in too many shared libraries"),
+        83 => cstr!("Cannot exec a shared library directly"),
+        84 => cstr!("Invalid or incomplete multibyte or wide character"),
+        85 => cstr!("Interrupted system call should be restarted"),
+        86 => cstr!("Streams pipe error"),
+        87 => cstr!("Too many users"),
+        88 => cstr!("Socket operation on non-socket"),
+        89 => cstr!("Destination address required"),
+        90 => cstr!("Message too long"),
+        91 => cstr!("Protocol wrong type for socket"),
+        92 => cstr!("Protocol not available"),
+        93 => cstr!("Protocol not supported"),
+        94 => cstr!("Socket type not supported"),
+        95 => cstr!("Operation not supported"),
+        96 => cstr!("Protocol family not supported"),
+        97 => cstr!("Address family not supported by protocol"),
+        98 => cstr!("Address already in use"),
+        99 => cstr!("Cannot assign requested address"),
+        100 => cstr!("Network is down"),
+        101 => cstr!("Network is unreachable"),
+        102 => cstr!("Network dropped connection on reset"),
+        103 => cstr!("Software caused connection abort"),
+        104 => cstr!("Connection reset by peer"),
+        105 => cstr!("No buffer space available"),
+        106 => cstr!("Transport endpoint is already connected"),
+        107 => cstr!("Transport endpoint is not connected"),
+        108 => cstr!("Cannot send after transport endpoint shutdown"),
+        109 => cstr!("Too many references: cannot splice"),
+        110 => cstr!("Connection timed out"),
+        111 => cstr!("Connection refused"),
+        112 => cstr!("Host is down"),
+        113 => cstr!("No route to host"),
+        114 => cstr!("Operation already in progress"),
+        115 => cstr!("Operation now in progress"),
+        116 => cstr!("Stale file handle"),
+        117 => cstr!("Structure needs cleaning"),
+        118 => cstr!("Not a XENIX named type file"),
+        119 => cstr!("No XENIX semaphores available"),
+        120 => cstr!("Is a named type file"),
+        121 => cstr!("Remote I/O error"),
+        122 => cstr!("Disk quota exceeded"),
+        123 => cstr!("No medium found"),
+        124 => cstr!("Wrong medium type"),
+        125 => cstr!("Operation canceled"),
+        126 => cstr!("Required key not available"),
+        127 => cstr!("Key has expired"),
+        128 => cstr!("Key has been revoked"),
+        129 => cstr!("Key was rejected by service"),
+        130 => cstr!("Owner died"),
+        131 => cstr!("State not recoverable"),
+        132 => cstr!("Operation not possible due to RF-kill"),
+        133 => cstr!("Memory page has hardware error"),
+        _ => cstr!("Unknown errno value"),
+    }
 }
diff --git a/vmbase/src/memory/shared.rs b/vmbase/src/memory/shared.rs
index 8d5f457..68f9ebd 100644
--- a/vmbase/src/memory/shared.rs
+++ b/vmbase/src/memory/shared.rs
@@ -27,6 +27,7 @@
 use alloc::vec::Vec;
 use buddy_system_allocator::{FrameAllocator, LockedFrameAllocator};
 use core::alloc::Layout;
+use core::cmp::max;
 use core::mem::size_of;
 use core::num::NonZeroUsize;
 use core::ops::Range;
@@ -354,6 +355,11 @@
 }
 
 fn try_shared_alloc(layout: Layout) -> Option<NonNull<u8>> {
+    // Adjusts the layout size to the max of the next power of two and the alignment,
+    // as this is the actual size of the memory allocated in `alloc_aligned()`.
+    let size = max(layout.size().next_power_of_two(), layout.align());
+    let layout = Layout::from_size_align(size, layout.align()).unwrap();
+
     let mut shared_pool = SHARED_POOL.get().unwrap().lock();
 
     if let Some(buffer) = shared_pool.alloc_aligned(layout) {