1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
//! The Twizzler Runtime API is the core interface definition for Twizzler programs, including
//! startup, execution, and libstd support. It defines a set of traits that, when all implemented,
//! form the full interface that Rust's libstd expects from a Twizzler runtime.
//!
//! From a high level, a Twizzler program links against Rust's libstd and a particular runtime that
//! will support libstd. That runtime must implement the minimum set of interfaces required by the
//! [Runtime] trait. Libstd then invokes the runtime functions when needed (e.g. allocating memory,
//! exiting a thread, etc.). Other libraries may invoke runtime functions directly as well
//! (bypassing libstd), but note that doing so may not play nicely with libstd's view of the world.
//!
//! # What does it look like to use the runtime?
//!
//! When a program (including libstd) wishes to use the runtime, it invokes this library's
//! [get_runtime] function, which will return a reference (a &'static dyn reference) to a type that
//! implements the Runtime trait. From there, runtime functions can be called: ```
//! let runtime = get_runtime();
//! runtime.get_monotonic()
//! ```
//! Note that this function is only exposed if the runtime feature is enabled.
//!
//! # So who is providing that type that implements [Runtime]?
//!
//! Another library! Right now, Twizzler defines two runtimes: a "minimal" runtime, and a
//! "reference" runtime. Those are not implemented in this crate. The minimal runtime is implemented
//! as part of the twizzler-abi crate, as it's the most "baremetal" runtime. The reference runtime
//! is implemented as a standalone set of crates. Of course, other runtimes can be implemented, as
//! long as they implement the required interface in this crate, libstd will work.
//!
//! ## Okay but how does get_runtime work?
//!
//! Well, [get_runtime] is just a wrapper around calling an extern "C" function,
//! [__twz_get_runtime]. This symbol is external, so not defined in this crate. A crate that
//! implements [Runtime] then defines [__twz_get_runtime], allowing link-time swapping of runtimes. The twizzler-abi crate defines this symbol with (weak linkage)[https://en.wikipedia.org/wiki/Weak_symbol], causing it to be linked
//! only if another (strong) definition is not present. Thus, a program can link to a specific
//! runtime, but it can also be loaded by a dynamic linker and have its runtime selected at load
//! time.

#![no_std]
#![feature(unboxed_closures)]
#![feature(naked_functions)]
#![feature(c_size_t)]
#![feature(linkage)]
#![feature(core_intrinsics)]
#![feature(error_in_core)]

use core::fmt::{Display, LowerHex, UpperHex};
#[cfg_attr(feature = "kernel", allow(unused_imports))]
use core::{
    alloc::GlobalAlloc,
    ffi::CStr,
    num::NonZeroUsize,
    panic::RefUnwindSafe,
    ptr::NonNull,
    sync::atomic::{AtomicU32, AtomicUsize, Ordering},
    time::Duration,
};

#[cfg(feature = "rt0")]
pub mod rt0;

#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
/// An object ID, represented as a transparent wrapper type. Any value where the upper 64 bits are
/// zero is invalid.
pub struct ObjID(u128);

impl ObjID {
    /// Create a new ObjID out of a 128 bit value.
    pub const fn new(id: u128) -> Self {
        Self(id)
    }

    /// Split an object ID into upper and lower values, useful for syscalls.
    pub fn split(&self) -> (u64, u64) {
        ((self.0 >> 64) as u64, (self.0 & 0xffffffffffffffff) as u64)
    }

    /// Build a new ObjID out of a high part and a low part.
    pub fn new_from_parts(hi: u64, lo: u64) -> Self {
        ObjID::new(((hi as u128) << 64) | (lo as u128))
    }

    pub fn as_u128(&self) -> u128 {
        self.0
    }
}

impl core::convert::AsRef<ObjID> for ObjID {
    fn as_ref(&self) -> &ObjID {
        self
    }
}

impl From<u128> for ObjID {
    fn from(id: u128) -> Self {
        Self::new(id)
    }
}

impl LowerHex for ObjID {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "{:x}", self.0)
    }
}

impl UpperHex for ObjID {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "{:X}", self.0)
    }
}

impl core::fmt::Display for ObjID {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "ObjID({:x})", self.0)
    }
}

impl core::fmt::Debug for ObjID {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "ObjID({:x})", self.0)
    }
}

#[repr(C)]
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
/// Auxillary information provided to a new program on runtime entry.
pub enum AuxEntry {
    /// Ends the aux array.
    Null,
    /// A pointer to this program's program headers, and the number of them. See the ELF
    /// specification for more info.
    ProgramHeaders(u64, usize),
    /// A pointer to the env var array.
    Environment(u64),
    /// A pointer to the arguments array.
    Arguments(usize, u64),
    /// The object ID of the executable.
    ExecId(ObjID),
    /// Initial runtime information. The value is runtime-specific.
    RuntimeInfo(usize, u64),
}

/// Full runtime trait, composed of smaller traits
pub trait Runtime:
    ThreadRuntime
    + ObjectRuntime
    + CoreRuntime
    + RustFsRuntime
    + RustProcessRuntime
    + RustStdioRuntime
    + DebugRuntime
    + RustTimeRuntime
{
    // todo: get random
}

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
/// Arguments that std expects to pass to spawn.
pub struct ThreadSpawnArgs {
    /// The initial stack size
    pub stack_size: usize,
    /// The entry point
    pub start: usize,
    /// The argument to the entry point
    pub arg: usize,
}

/// Possible errors on spawn.
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
pub enum SpawnError {
    /// An error that is not classified.
    Other,
    /// One of the arguments in spawn args was invalid.
    InvalidArgument,
    /// An object used as a handle was not found.
    ObjectNotFound,
    /// An object used as a handle may not be accessed by the caller.
    PermissionDenied,
    /// Failed to spawn thread in-kernel.
    KernelError,
}

impl Display for SpawnError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            SpawnError::Other => write!(f, "unknown error"),
            SpawnError::InvalidArgument => write!(f, "invalid argument"),
            SpawnError::ObjectNotFound => write!(f, "object not found"),
            SpawnError::PermissionDenied => write!(f, "permission denied"),
            SpawnError::KernelError => write!(f, "kernel error"),
        }
    }
}

impl core::error::Error for SpawnError {}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
/// An ABI-defined argument passed to __tls_get_addr.
pub struct TlsIndex {
    /// The ID of the module.
    pub mod_id: usize,
    /// The offset into that module's TLS region.
    pub offset: usize,
}

/// All the thread-related runtime functions.
pub trait ThreadRuntime {
    /// Essentially number of threads on this system
    fn available_parallelism(&self) -> NonZeroUsize;

    /// Wait for futex (see: Linux)
    fn futex_wait(&self, futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool;
    /// Wake one for futex (see: Linux)
    fn futex_wake(&self, futex: &AtomicU32) -> bool;
    /// Wake all for futex (see: Linux)
    fn futex_wake_all(&self, futex: &AtomicU32);

    /// Spawn a thread, returning an internal ID that uniquely identifies a thread in the runtime.
    fn spawn(&self, args: ThreadSpawnArgs) -> Result<u32, SpawnError>;

    /// Yield calling thread
    fn yield_now(&self);

    /// Set the name of calling thread
    fn set_name(&self, name: &CStr);

    /// Sleep calling thread
    fn sleep(&self, duration: Duration);

    /// Wait for the specified thread to terminate, or optionally time out.
    fn join(&self, id: u32, timeout: Option<Duration>) -> Result<(), JoinError>;

    /// Implements the __tls_get_addr functionality. If the runtime feature is enabled, this crate
    /// defines the extern "C" function __tls_get_addr as a wrapper around calling this function
    /// after getting the runtime from [get_runtime]. If the provided index is invalid, return
    /// None.
    fn tls_get_addr(&self, tls_index: &TlsIndex) -> Option<*const u8>;
}

/// All the object related runtime functions.
pub trait ObjectRuntime {
    /// Map an object to an [ObjectHandle]. The handle may reference the same internal mapping as
    /// other calls to this function.
    fn map_object(&self, id: ObjID, flags: MapFlags) -> Result<ObjectHandle, MapError>;
    /// Called on drop of an object handle.
    fn release_handle(&self, handle: &mut ObjectHandle);

    /// Map two objects in sequence, useful for executable loading. The default implementation makes
    /// no guarantees about ordering.
    fn map_two_objects(
        &self,
        in_id_a: ObjID,
        in_flags_a: MapFlags,
        in_id_b: ObjID,
        in_flags_b: MapFlags,
    ) -> Result<(ObjectHandle, ObjectHandle), MapError> {
        let map_and_check = |rev: bool| {
            let (id_a, flags_a) = if rev {
                (in_id_b, in_flags_b)
            } else {
                (in_id_a, in_flags_a)
            };

            let (id_b, flags_b) = if !rev {
                (in_id_b, in_flags_b)
            } else {
                (in_id_a, in_flags_a)
            };

            let a = self.map_object(id_a, flags_a)?;
            let b = self.map_object(id_b, flags_b)?;
            let a_addr = a.start as usize;
            let b_addr = b.start as usize;

            if rev && a_addr > b_addr {
                Ok((b, a))
            } else if !rev && b_addr > a_addr {
                Ok((a, b))
            } else {
                Err(MapError::InternalError)
            }
        };

        map_and_check(false).or_else(|_| map_and_check(true))
    }
}

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
/// Possible errors of join.
pub enum JoinError {
    /// The internal-thread-ID does not exist.
    LookupError,
    /// Join timed out.
    Timeout,
}

impl Display for JoinError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            JoinError::LookupError => write!(f, "lookup error"),
            JoinError::Timeout => write!(f, "operation timed out"),
        }
    }
}

impl core::error::Error for JoinError {}

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
/// Possible errors of mapping an object.
pub enum MapError {
    /// Error is unclassified.
    Other,
    /// An internal runtime error occurred.
    InternalError,
    /// Ran out of resources when trying to map the object.
    OutOfResources,
    /// The specified object does not exist.
    NoSuchObject,
    /// Access is disallowed.
    PermissionDenied,
    /// An argument to map is invalid.
    InvalidArgument,
}

impl Display for MapError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            MapError::Other => write!(f, "unknown error"),
            MapError::InternalError => write!(f, "internal error"),
            MapError::OutOfResources => write!(f, "out of resources"),
            MapError::NoSuchObject => write!(f, "no such object"),
            MapError::PermissionDenied => write!(f, "permission denied"),
            MapError::InvalidArgument => write!(f, "invalid argument"),
        }
    }
}

impl core::error::Error for MapError {}

bitflags::bitflags! {
    /// Mapping protections for mapping objects into the address space.
    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
    pub struct MapFlags: u32 {
        /// Read allowed.
        const READ = 1;
        /// Write allowed.
        const WRITE = 2;
        /// Exec allowed.
        const EXEC = 4;
    }
}

#[cfg_attr(feature = "kernel", allow(dead_code))]
/// A handle to an internal object. This has similar semantics to Arc, but since this crate
/// must be #[no_std], we need to implement refcounting ourselves.
pub struct ObjectHandle {
    /// Pointer to refcounter.
    pub internal_refs: Option<NonNull<InternalHandleRefs>>,
    /// The ID of the object.
    pub id: ObjID,
    /// The flags of this handle.
    pub flags: MapFlags,
    /// A pointer to the object's start (null-page, not base).
    pub start: *mut u8,
    /// A pointer to the object's metadata.
    pub meta: *mut u8,
}

impl core::fmt::Debug for ObjectHandle {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_struct("ObjectHandle")
            .field("id", &self.id)
            .field("flags", &self.flags)
            .field("start", &self.start)
            .field("meta", &self.meta)
            .finish()
    }
}

unsafe impl Send for ObjectHandle {}
unsafe impl Sync for ObjectHandle {}

pub struct InternalHandleRefs {
    count: AtomicUsize,
}

impl Default for InternalHandleRefs {
    fn default() -> Self {
        Self {
            count: AtomicUsize::new(1),
        }
    }
}

impl ObjectHandle {
    pub fn new(
        internal_refs: Option<NonNull<InternalHandleRefs>>,
        id: ObjID,
        flags: MapFlags,
        start: *mut u8,
        meta: *mut u8,
    ) -> Self {
        Self {
            internal_refs,
            id,
            flags,
            start,
            meta,
        }
    }
}

impl Clone for ObjectHandle {
    fn clone(&self) -> Self {
        let Some(ref refs) = self.internal_refs else {
            panic!("cannot clone an unsafe object handle");
        };
        let rc = unsafe { refs.as_ref() };
        // This use of Relaxed ordering is justified by https://doc.rust-lang.org/nomicon/arc-mutex/arc-clone.html.
        let old_count = rc.count.fetch_add(1, Ordering::Relaxed);
        // The above link also justifies the following behavior. If our count gets this high, we
        // have probably run into a problem somewhere.
        if old_count >= isize::MAX as usize {
            get_runtime().abort();
        }
        Self {
            internal_refs: self.internal_refs,
            id: self.id,
            flags: self.flags,
            start: self.start,
            meta: self.meta,
        }
    }
}

impl Drop for ObjectHandle {
    fn drop(&mut self) {
        let Some(ref refs) = self.internal_refs else {
            return;
        };
        // This use of Release ordering is justified by https://doc.rust-lang.org/nomicon/arc-mutex/arc-clone.html.
        let rc = unsafe { refs.as_ref() };
        if rc.count.fetch_sub(1, Ordering::Release) != 1 {
            return;
        }
        // This fence is needed to prevent reordering of the use and deletion
        // of the data.
        core::sync::atomic::fence(Ordering::Acquire);
        let runtime = get_runtime();
        runtime.release_handle(self);
    }
}

/// Definitions of core runtime features.
pub trait CoreRuntime {
    /// Returns a reference to an allocator to use for default (global) allocations.
    fn default_allocator(&self) -> &'static dyn GlobalAlloc;

    /// Called by libstd before calling main.
    fn pre_main_hook(&self) {}

    /// Called by libstd after returning from main.
    fn post_main_hook(&self) {}

    /// Exit the calling thread. This is allowed to cause a full exit of the entire program and all
    /// threads.
    fn exit(&self, code: i32) -> !;

    /// Thread abort. This is allowed to cause a full exit of the entire program and all threads.
    fn abort(&self) -> !;

    /// Called by rt0 code to start the runtime. Once the runtime has initialized, it should call
    /// the provided entry function. The pointer arg is a pointer to an array of [AuxEntry] that
    /// terminates with an [AuxEntry::Null].
    fn runtime_entry(
        &self,
        arg: *const AuxEntry,
        std_entry: unsafe extern "C" fn(BasicAux) -> BasicReturn,
    ) -> !;
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
/// Arguments passed by the runtime to libstd.
pub struct BasicAux {
    /// The number of arguments.
    pub argc: usize,
    /// A null-terminated list of null-terminated strings, forming arguments to the program.
    pub args: *const *const i8,
    /// The environment pointer, also a null-terminated list of null-terminated strings.
    pub env: *const *const i8,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
/// Return value returned by std from LibStdEntry
pub struct BasicReturn {
    /// Exit code. 0 is success, non-zero is application-defined.
    pub code: i32,
}

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
/// Possible errors returned by the FsRuntime
pub enum FsError {
    /// Error is unclassified.
    Other,
    /// Path provided isn't a valid u128 integer
    InvalidPath,
    /// Couldn't find the file descriptor
    LookupError,
    /// Seek is beyond maximum file size or before 0
    SeekError,
}

impl Display for FsError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            FsError::Other => write!(f, "unknown error"),
            FsError::InvalidPath => write!(f, "Path is invalid"),
            FsError::LookupError => write!(f, "Couldn't find file descriptor"),
            FsError::SeekError => write!(f, "Couldn't seek to this position"),
        }
    }
}

impl core::error::Error for FsError {}

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
/// Enum of the possible ways to seek within a object
pub enum SeekFrom {
    /// Sets to the offset in bytes
    Start(u64),
    /// Sets to the offset relative to the end of the file
    End(i64),
    /// Sets the offset relative to the position of the cursor
    Current(i64),
}

/// A identifier for a Twizzler object that allows File-like IO
/// The data backing RawFd holds the position of the file cursor and a reference to the object that
/// stores the file's data.
pub type RawFd = u32;

/// Runtime that implements STD's FS support. Currently being implemented.
pub trait RustFsRuntime {
    /// Takes in a u128 integer as CStr and emits a File Descriptor that allows File-Like IO on a
    /// Twizzler Object. Note that the object must already exist to be opened.
    fn open(&self, path: &CStr) -> Result<RawFd, FsError>;

    /// Reads bytes from the source twizzler Object into the specified buffer, returns how many
    /// bytes were read.
    fn read(&self, fd: RawFd, buf: &mut [u8]) -> Result<usize, FsError>;

    /// Writes bytes from the source twizzler Object into the specified buffer, returns how many
    /// bytes were written.
    fn write(&self, fd: RawFd, buf: &[u8]) -> Result<usize, FsError>;

    /// Cleans the data associated with the RawFd allowing reuse. Note that this doesn't
    /// close/unmap the backing object.
    fn close(&self, fd: RawFd) -> Result<(), FsError>;

    /// Moves the cursor to a specified offset within the backed object.
    fn seek(&self, fd: RawFd, pos: SeekFrom) -> Result<usize, FsError>;
}

/// Runtime that implements std's process and command support. Currently unimplemented.
pub trait RustProcessRuntime: RustStdioRuntime {}

/// The type of a callback to an IO Read call (see: [RustStdioRuntime]).
pub type IoReadDynCallback<'a, R> = &'a mut (dyn (FnMut(&dyn IoRead) -> R));

/// The type of a callback to an IO Write call (see: [RustStdioRuntime]).
pub type IoWriteDynCallback<'a, R> = &'a (dyn (Fn(&dyn IoWrite) -> R));

/// The type of a callback to an IO Write call (see: [RustStdioRuntime]).
pub type IoWritePanicDynCallback<'a, R> = &'a (dyn (Fn(&dyn IoWrite) -> R) + RefUnwindSafe);

/// Runtime that implements stdio.
pub trait RustStdioRuntime {
    /// Execute a closure with an implementer of [IoWrite] that can be used for panic output.
    fn with_panic_output(&self, cb: IoWritePanicDynCallback<'_, ()>);

    /// Execute a closure with an implementer of [IoRead] that can be used for stdin.
    fn with_stdin(
        &self,
        cb: IoReadDynCallback<'_, Result<usize, ReadError>>,
    ) -> Result<usize, ReadError>;

    /// Execute a closure with an implementer of [IoWrite] that can be used for stdout.
    fn with_stdout(
        &self,
        cb: IoWriteDynCallback<'_, Result<usize, WriteError>>,
    ) -> Result<usize, WriteError>;

    /// Execute a closure with an implementer of [IoWrite] that can be used for stderr.
    fn with_stderr(
        &self,
        cb: IoWriteDynCallback<'_, Result<usize, WriteError>>,
    ) -> Result<usize, WriteError>;
}

/// Possible errors from read.
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub enum ReadError {
    /// Unclassified error
    Other,
    /// IO Error
    IoError,
    /// Permission denied
    PermissionDenied,
    /// No such IO mechanism.
    NoIo,
}

impl Display for ReadError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            ReadError::Other => write!(f, "unknown error"),
            ReadError::IoError => write!(f, "I/O error"),
            ReadError::PermissionDenied => write!(f, "permission denied"),
            ReadError::NoIo => write!(f, "no such I/O mechanism"),
        }
    }
}

impl core::error::Error for ReadError {}

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub enum WriteError {
    /// Unclassified error
    Other,
    /// IO Error
    IoError,
    /// Permission denied
    PermissionDenied,
    /// No such IO mechanism.
    NoIo,
}

impl Display for WriteError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            WriteError::Other => write!(f, "unknown error"),
            WriteError::IoError => write!(f, "I/O error"),
            WriteError::PermissionDenied => write!(f, "permission denied"),
            WriteError::NoIo => write!(f, "no such I/O mechanism"),
        }
    }
}

impl core::error::Error for WriteError {}

/// Trait for stdin
pub trait IoRead {
    /// Read data into buf, returning the number of bytes read.
    fn read(&self, buf: &mut [u8]) -> Result<usize, ReadError>;
}

/// Trait for stdout/stderr
pub trait IoWrite {
    /// Write data from buf, returning the number of bytes written.
    fn write(&self, buf: &[u8]) -> Result<usize, WriteError>;
    /// Flush any buffered internal data. This function is allowed to be a no-op.
    fn flush(&self) -> Result<(), WriteError>;
}

/// Runtime trait for libstd's time support
pub trait RustTimeRuntime {
    /// Get a monotonic timestamp.
    fn get_monotonic(&self) -> Duration;
    /// Get a system time timestamp.
    fn get_system_time(&self) -> Duration;
    /// Is the monotonic timestamp monotonic or not?
    fn actual_monotonicity(&self) -> Monotonicity;
}

/// Possible types of monotonicity.
pub enum Monotonicity {
    /// Not monotonic at all.
    NonMonotonic,
    /// Weakly monotonic (function may increase or stay the same).
    Weak,
    /// Strictly monotonic (function always increases).
    Strict,
}

/// An abstract representation of a library, useful for debugging and backtracing.
pub struct Library {
    /// The ID of this library.
    pub id: LibraryId,
    /// How this library is mapped.
    pub mapping: ObjectHandle,
    /// Actual range of addresses that comprise the library binary data.
    pub range: AddrRange,
    /// Information for dl_iterate_phdr
    pub dl_info: Option<DlPhdrInfo>,
}

impl AsRef<Library> for Library {
    fn as_ref(&self) -> &Library {
        self
    }
}

impl Library {
    pub fn name(&self) -> Option<&CStr> {
        unsafe { Some(CStr::from_ptr(self.dl_info?.name as *const i8)) }
    }
}

#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
/// Internal library ID type.
pub struct LibraryId(pub usize);

/// The runtime must ensure that the addresses are constant for the whole life of the library type,
/// and that all threads may see the type.
unsafe impl Send for Library {}

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
pub type ElfAddr = usize;
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
pub type ElfHalf = u32;

#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct DlPhdrInfo {
    pub addr: ElfAddr,
    pub name: *const u8,
    pub phdr_start: *const u8,
    pub phdr_num: ElfHalf,
    pub _adds: core::ffi::c_longlong,
    pub _subs: core::ffi::c_longlong,
    pub modid: core::ffi::c_size_t,
    pub tls_data: *const core::ffi::c_void,
}

/// Functions for the debug support part of libstd (e.g. unwinding, backtracing).
pub trait DebugRuntime {
    /// Gets a handle to a library given the ID.
    fn get_library(&self, id: LibraryId) -> Option<Library>;
    /// Returns the ID of the main executable, if there is one.
    fn get_exeid(&self) -> Option<LibraryId>;
    /// Get a segment of a library, if the segment index exists. All segment IDs are indexes, so
    /// they range from [0, N).
    fn get_library_segment(&self, lib: &Library, seg: usize) -> Option<AddrRange>;
    /// Get the full mapping of the underlying library.
    fn get_full_mapping(&self, lib: &Library) -> Option<ObjectHandle>;
    /// Handler for calls to the dl_iterate_phdr call.
    fn iterate_phdr(&self, f: &mut dyn FnMut(DlPhdrInfo) -> core::ffi::c_int) -> core::ffi::c_int;
    /// Get the library ID immediately following the given one.
    fn next_library_id(&self, id: LibraryId) -> Option<LibraryId> {
        Some(LibraryId(id.0 + 1))
    }
}

#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq)]
/// An address range.
pub struct AddrRange {
    /// Starting virtual address.
    pub start: usize,
    /// Length of the range.
    pub len: usize,
}

extern "rust-call" {
    /// Called by get_runtime to actually get the runtime.
    #[linkage = "extern_weak"]
    fn __twz_get_runtime(_a: ()) -> &'static (dyn Runtime + Sync);
}

/// Wrapper around call to __twz_get_runtime.
pub fn get_runtime() -> &'static (dyn Runtime + Sync) {
    unsafe { __twz_get_runtime(()) }
}

#[cfg(feature = "kernel")]
pub mod __imp {
    #[linkage = "weak"]
    #[no_mangle]
    pub unsafe extern "C" fn __twz_get_runtime() {
        core::intrinsics::abort();
    }
}

/// Public definition of __tls_get_addr, a function that gets automatically called by the compiler
/// when needed for TLS pointer resolution.
#[cfg(feature = "rustc-dep-of-std")]
#[no_mangle]
pub unsafe extern "C" fn __tls_get_addr(arg: usize) -> *const u8 {
    // Just call the runtime.
    let runtime = crate::get_runtime();
    let index = (arg as *const crate::TlsIndex)
        .as_ref()
        .expect("null pointer passed to __tls_get_addr");
    runtime
        .tls_get_addr(index)
        .expect("index passed to __tls_get_addr is invalid")
}

/// Public definition of dl_iterate_phdr, used by libunwind for learning where loaded objects
/// (executables, libraries, ...) are.
#[cfg(feature = "rustc-dep-of-std")]
#[no_mangle]
pub unsafe extern "C" fn dl_iterate_phdr(
    callback: extern "C" fn(
        ptr: *const DlPhdrInfo,
        sz: core::ffi::c_size_t,
        data: *mut core::ffi::c_void,
    ) -> core::ffi::c_int,
    data: *mut core::ffi::c_void,
) -> core::ffi::c_int {
    let runtime = crate::get_runtime();
    runtime.iterate_phdr(&mut |info| callback(&info, core::mem::size_of::<DlPhdrInfo>(), data))
}